2008年1月7日 星期一

實作 ALSA 主音量控制

Standard
OSS 已經成為歷史,今天的 ALSA 幾乎成為了所有 Linux 的音效驅動的標準規格。兩者相較之下,ALSA 新增了太多數不清的專業功能和特色,也難怪玩具般的 OSS 會敗陣下來。對研發人員來說,從 OSS 過渡到 ALSA 的困擾,就是聲音控制程式的 sourcecode 複雜度變高了。

以下是操弄 ALSA Library 的簡單範例:
#include <stdio.h>
#include <alsa/asoundlib.h>

int main(void)
{
int unmute, chn;
int al, ar;
snd_mixer_t *mixer;
snd_mixer_elem_t *master_element;

snd_mixer_open(&mixer, 0);
snd_mixer_attach(mixer, "default");
snd_mixer_selem_register(mixer, NULL, NULL);
snd_mixer_load(mixer);

/* 取得第一個 element,也就是 Master */
master_element = snd_mixer_first_elem(mixer);
/* 設定音量的範圍 0 ~ 100 */
snd_mixer_selem_set_playback_volume_range(master_element, 0, 100);

/* 取得 Master 是否靜音 */
snd_mixer_selem_get_playback_switch(master_element, 0, &unmute);
if (unmute)
printf("Master is Unmute.\n");
else
printf("Master is Mute.\n");

/* 取得左右聲道的音量 */
snd_mixer_selem_get_playback_volume(master_element, SND_MIXER_SCHN_FRONT_LEFT, &al);
snd_mixer_selem_get_playback_volume(master_element, SND_MIXER_SCHN_FRONT_RIGHT, &ar);
/* 兩聲道相加除以二求平均音量 */
printf("Master volume is %d\n", (al + ar) >> 1);

/* 設定 Master 音量 */
snd_mixer_selem_set_playback_volume(master_element, SND_MIXER_SCHN_FRONT_LEFT, 99);
snd_mixer_selem_set_playback_volume(master_element, SND_MIXER_SCHN_FRONT_RIGHT, 99);

/* 將 Master 切換為靜音 */
for (chn=0;chn<=SND_MIXER_SCHN_LAST;chn++) {
snd_mixer_selem_set_playback_switch(master_element, chn, 0);
}

/* 將 Master 切換為非靜音 */
for (chn=0;chn<=SND_MIXER_SCHN_LAST;chn++) {
snd_mixer_selem_set_playback_switch(master_element, chn, 1);
}
return 0;
}


比起 OSS 存取 /dev/mixer 的做法,ALSA 的確是複雜多了,但是仔細深入後會發現,這些複雜都是必要且有跡可循。