基于ALSA庫實現音量調節
- ALSA庫實現音量調節
- 1、使用alsamixer工具查看音頻接口
- 2、完整代碼
- 2.1、snd_mixer_open
- 2.2、snd_mixer_attach、
- 2.3、snd_mixer_selem_register
- 2.4、snd_mixer_load
- 2.5、snd_mixer_first_elem/snd_mixer_elem_next
- 2.6、snd_mixer_selem_get_playback_volume_range/snd_mixer_selem_get_capture_volume_range
- 2.7、snd_mixer_selem_set_playback_volume_all
- 3、完整程序
- 4、注意細節
- 4.1、初始化順序
- 4.2、聲卡設備的選擇
- 4.3、元素查找
- 4.4、單雙通道音量設置
ALSA庫實現音量調節
1、使用alsamixer工具查看音頻接口
首先可以通過alsamixer工具圖形化查看聲卡的接口名,也可以使用該工具通過圖形嘗試調節音頻大小,能幫助你后面更好的實現從應用層去調節,直接輸入alsamixer
即可自動彈出圖形界面,如下圖,Speaker是我播放的元素名稱,上面的55是音量大小,通過鍵盤的上下鍵即可調節大小,這兩個參數在后面應用層時都會用到:
2、完整代碼
2.1、snd_mixer_open
- 打開并實例化一個空的混音器
2.2、snd_mixer_attach、
- 連接到選擇的聲卡控制設備
2.3、snd_mixer_selem_register
- 注冊混音器
int snd_mixer_selem_register(snd_mixer_t *mixer,struct snd_mixer_selem_regopt *options,snd_mixer_class_t **classp);
2.4、snd_mixer_load
- 加載混音器
2.5、snd_mixer_first_elem/snd_mixer_elem_next
- 找到混音器的第一個元素/查找下一個元素
2.6、snd_mixer_selem_get_playback_volume_range/snd_mixer_selem_get_capture_volume_range
- 獲取指定元素的音量范圍
int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,long *min,long *max);
int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,long *min,long *max);
2.7、snd_mixer_selem_set_playback_volume_all
- 一次性設置指定元素所有聲道的音量
3、完整程序
下面的函數實現音量的獲取和調節,通過ALSA庫的API接口,注冊一個混音器設備對象,使用該對象連接到想要控制的聲卡,然后開始查找該聲卡中的元素,找到想要控制的元素,然后對元素進行get和set,本函數實現對Speaker元素的調節控制揚聲器聲音大小,通過應用程序調節完音量后,可以使用alsamixer工具查看音量是否成功調節。
/* volume control init */
void volume_control_init(void)
{snd_mixer_t *mixer;snd_mixer_elem_t *elem;debug_msg(snd_mixer_open(&mixer,0),"opening mixer"); // 打開混音器設備debug_msg(snd_mixer_attach(mixer, "hw:1"),"attaching mixer"); // 連接到默認的聲卡debug_msg(snd_mixer_selem_register(mixer, NULL, NULL),"registering mixer"); // 載入聲卡配置debug_msg(snd_mixer_load(mixer),"load mixer");// 循環找到自己想要的elementelem = snd_mixer_first_elem(mixer);while(elem){// find element name(此處要找的就是上面看的speaker元素)if(strcmp("Speaker",snd_mixer_selem_get_name(elem)) == 0){printf("elem name : %s\n",snd_mixer_selem_get_name(elem));break;}elem = snd_mixer_elem_next(elem);}if(!elem){printf("snd_mixer_find_selem Error\n");snd_mixer_close(mixer);mixer = NULL;return;}long min, max;snd_mixer_selem_get_playback_volume_range(elem, &min, &max);printf("volume range: %ld -- %ld\n", min, max);long lVal, rVal;snd_mixer_handle_events(mixer); // 確保混音器狀態和應用程序狀態的同步snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &lVal);snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &rVal);printf("currnet volume: leftVal = %ld, rightVal = %ld\n", lVal, rVal);snd_mixer_selem_set_playback_volume_all(elem, 25);// 釋放資源snd_mixer_close(mixer);
}
4、注意細節
4.1、初始化順序
在初始化混音器設備時,需要先初始化好PCM聲卡設備,不然PCM初始化時會重置導致音頻設置失效
4.2、聲卡設備的選擇
程序中通過調用snd_mixer_attach
選擇聲卡設備,選擇時需要注意跟PCM選擇聲卡設備時不同,PCM初始化時選擇的是聲卡幾設備幾,比如聲卡1,設備0,那么PCM初始化打開設備時要傳入snd_pcm_open(&pb_handle, "plughw:1,0",SND_PCM_STREAM_PLAYBACK, 0)
,而mixer初始化時只需要選擇聲卡而不用詳細到設備,依然是聲卡1,設備0,那么mixer連接到聲卡時只需要傳入snd_mixer_attach(mixer, "hw:1")
。
4.3、元素查找
在mixer中,有很多的element(元素),也就是最開始通過圖形化看到的各種元素,在ALSA中好像沒有函數能夠直接查找到某個元素,只能通過snd_mixer_first_elem
找到第一個元素,然后通過snd_mixer_elem_next
開始查找下一個元素一直查下去,直到通過snd_mixer_selem_get_name
發現當前的元素是你想要調節的元素為止(你可以選擇將這種方式封裝起來成為一個能指定查找的函數)。
4.4、單雙通道音量設置
你可以通過snd_mixer_selem_is_playback_mono
查詢該聲卡是否是單通道(mono:單,stereo:雙),然后通過snd_mixer_selem_set_capture_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, volume)
的第2個參數來指定左右通道的音量,但是我沒什么時間深究,所以直接選擇snd_mixer_selem_set_capture_volume_all
來設置總音量。
同時需要注意一下音量的調節,雖然在alsamixer工具的圖形化中可以看到音量能從0調節到100,但是程序中使用snd_mixer_selem_get_playback_volume
獲取音量時會發現范圍在0-30,并且如果你使用amixer get 'DAC HPOUT Left'
get一下元素的值查看時就會發現limits的值也為0-30,因此在設置音量時也要注意設置的值不要超過這個范圍,不能以圖形化中的范圍去設置。
root@firefly:~/twoway# amixer get 'DAC HPOUT Left'
Simple mixer control 'DAC HPOUT Left',0Capabilities: volume volume-joinedPlayback channels: MonoCapture channels: MonoLimits: 0 - 30Mono: 30 [100%] [6.00dB]