日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ALSA声卡12_从零编写之添加音量控制_学习笔记

發布時間:2023/12/10 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ALSA声卡12_从零编写之添加音量控制_学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、設置音量時應用程序的調用過程

(1)strace分析: amixer cset numid=1 30?(設置音量)
/dev/snd/controlC0
open
SNDRV_CTL_IOCTL_CARD_INFO
SNDRV_CTL_IOCTL_PVERSION
SNDRV_CTL_IOCTL_ELEM_INFO
SNDRV_CTL_IOCTL_ELEM_READ
SNDRV_CTL_IOCTL_ELEM_WRITE?: snd_ctl_elem_write_user

(2)應用程序調用SNDRV_CTL_IOCTL_ELEM_WRITE時,驅動程序調用snd_ctl_elem_write_user函數,這個函數從用戶空間把一些參數拷貝進來,然后調用函數snd_ctl_elem_write

(3)函數snd_ctl_elem_write

找到一個snd_kcontrol結構體,然后調用snd_control結構體的put函數。


(4)這個snd_kcontrol結構體是誰提供的

ASOC驅動程序分為3大塊(machine,codec,platform),應該在codec這一塊來提供的,因為它跟聲卡密切相關。去調節音量的時候肯定要調整它



2、寫程序(uda1341.c(codec))

(1)結構體snd_kcontrol_new

static const struct?snd_kcontrol_new?uda1341_vol_control =?
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,?//表示snd_kcontrol結構體用于哪一類設備(表示進行參數設置)
? ? .name = "Master Playback Volume", ?//音量控制,每個聲卡驅動程序的snd_kcontrol各不相同,為什么應用程序都可以調整它的音量,對于某些常用的屬性,它們都有固定的名字。應用程序根據名字找到它的snd_kcontrol項,調用里面的put函數。
.info = uda1341_info_vol, ?//獲得一些信息,如音量范圍是多少
.get ?= uda1341_get_vol,//獲得當前的音量值
.put ?= uda1341_put_vol,?//設置音量
};


(2)?獲得音量信息,比如最小值最大值

/*
?* 獲得音量信息,比如最小值最大值
?*/

int uda1341_info_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;//音量值的類型是整數
uinfo->count = 2;//聲道數是雙聲道的
uinfo->value.integer.min = 0;//最小整數,
uinfo->value.integer.max = 63;//最大整數,
return 0;
}

因為uda1341的音量控制是6位的(0表示最大音量,63表示最小音量),而應用程序中0表示最小音量,值越大表示音量越大


(3)獲得當前音量值

/*
?* 獲得當前音量值
?*/

int uda1341_get_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);


? ? ucontrol->value.integer.value[1] = \ ?//這里?\ ?表示ucontrol->value.integer.value[0] 等于ucontrol->value.integer.value[1] ,因為是雙聲道
ucontrol->value.integer.value[0] = 63 - snd_soc_read(codec, UDA1341_DATA00);//讀寄存器DAT00的值,因為驅動程序的值和應用程序的值大小是相反的,uda1341不支持寄存器的讀操作,要想得到一個寄存器的值,是去讀某個cache(這個cache保存的是設置寄存器的值)
return 0;
}

(4)?設置當前音量值

/*
?* 設置當前音量值
?*/

int uda1341_put_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int val;


val = 63 - ucontrol->value.integer.value[0];//應用程序傳進來的值寫到寄存器里面要反轉


? ? snd_soc_write(codec, UDA1341_DATA00, val);//把值val寫到寄存器DATA00中去
? ??
return 0;
}

3、結構體snd_kcontrol_new和內核部分的連接

(1)probe函數

static int uda1341_soc_probe(struct snd_soc_codec *codec)
{
? ? int ret;
? ? uda1341_init_regs(codec);
? ??
ret = snd_soc_add_codec_controls(codec, &uda1341_vol_control, 1);
? ? return ret;
}


4、測試


amixer ?controls查看控制項

amixer cget numid=1表示查看當前音量

amixer cset numid=1 30設置音量



5、Input Mux

因為不同的板子的麥克風通道不同(在uda1341),用同一驅動,想錄音時應用程序應該設置input mux選項。



表明它能選擇哪個麥克風通道,當前是哪一個麥克風通道,設置哪一個麥克風通道


值uda134x_mixer_enum[2]是數組的第2項


6、

讓板子使用內核自帶的驅動程序


查看設備節點和控制項(input mux在倒數第二項)


查看控制項第11項的值(當前值是0)


若選擇第1個通道(模擬通道)最后1個參數表明第幾個通道



轉載于:https://www.cnblogs.com/alan666/p/8311864.html

總結

以上是生活随笔為你收集整理的ALSA声卡12_从零编写之添加音量控制_学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。