?? linux音頻編程2.txt
字號:
SOUND_MIXER_SPEAKER PC喇叭
SOUND_MIXER_LINE 音頻線輸入
SOUND_MIXER_MIC 麥克風輸入
SOUND_MIXER_CD CD輸入
SOUND_MIXER_IMIX 回放音量
SOUND_MIXER_ALTPCM 從D/A 轉換器
SOUND_MIXER_RECLEV 錄音音量
SOUND_MIXER_IGAIN 輸入增益
SOUND_MIXER_OGAIN 輸出增益
SOUND_MIXER_LINE1 聲卡的第1輸入
SOUND_MIXER_LINE2 聲卡的第2輸入
SOUND_MIXER_LINE3 聲卡的第3輸入
表1 混音器命令
對 聲卡的輸入增益和輸出增益進行調節是混音器的一個主要作用,目前大部分聲卡采用的是8位或者16位的增益控制器,但作為程序員來講并不需要關心這些,因為 聲卡驅動程序會負責將它們變換成百分比的形式,也就是說無論是輸入增益還是輸出增益,其取值范圍都是從0到100。在進行混音器編程時,可以使用 SOUND_MIXER_READ宏來讀取混音通道的增益大小,例如在獲取麥克風的輸入增益時,可以使用如下的代碼:
int vol;
ioctl(fd, SOUND_MIXER_READ(SOUND_MIXER_MIC), &vol);
printf("Mic gain is at %d %%\n", vol);
對 于只有一個混音通道的單聲道設備來說,返回的增益大小保存在低位字節中。而對于支持多個混音通道的雙聲道設備來說,返回的增益大小實際上包括兩個部分,分 別代表左、右兩個聲道的值,其中低位字節保存左聲道的音量,而高位字節則保存右聲道的音量。下面的代碼可以從返回值中依次提取左右聲道的增益大小:
int left, right;
left = vol & 0xff;
right = (vol & 0xff00) >> 8;
printf("Left gain is %d %%, Right gain is %d %%\n", left, right);
類似地,如果想設置混音通道的增益大小,則可以通過SOUND_MIXER_WRITE宏來實現,此時遵循的原則與獲取增益值時的原則基本相同,例如下面的語句可以用來設置麥克風的輸入增益:
vol = (right << 8) + left;
ioctl(fd, SOUND_MIXER_WRITE(SOUND_MIXER_MIC), &vol);
在 編寫實用的音頻程序時,混音器是在涉及到兼容性時需要重點考慮的一個對象,這是因為不同的聲卡所提供的混音器資源是有所區別的。聲卡驅動程序提供了多個 ioctl系統調用來獲得混音器的信息,它們通常返回一個整型的位掩碼(bitmask),其中每一位分別代表一個特定的混音通道,如果相應的位為1,則 說明與之對應的混音通道是可用的。例如通過SOUND_MIXER_READ_DEVMASK返回的位掩碼,可以查詢出能夠被聲卡支持的每一個混音通道, 而通過SOUND_MIXER_READ_RECMAS返回的位掩碼,則可以查詢出能夠被當作錄音源的每一個通道。下面的代碼可以用來檢查CD輸入是否是 一個有效的混音通道:
ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask);
if (devmask & SOUND_MIXER_CD)
printf("The CD input is supported");
如果進一步還想知道其是否是一個有效的錄音源,則可以使用如下語句:
ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask);
if (recmask & SOUND_MIXER_CD)
printf("The CD input can be a recording source");
目 前大多數聲卡提供多個錄音源,通過SOUND_MIXER_READ_RECSRC可以查詢出當前正在使用的錄音源,同一時刻能夠使用幾個錄音源是由聲卡 硬件決定的。類似地,使用SOUND_MIXER_WRITE_RECSRC可以設置聲卡當前使用的錄音源,例如下面的代碼可以將CD輸入作為聲卡的錄音 源使用:
devmask = SOUND_MIXER_CD;
ioctl(fd, SOUND_MIXER_WRITE_DEVMASK, &devmask);
此外,所有的混音通道都有單聲道和雙聲道的區別,如果需要知道哪些混音通道提供了對立體聲的支持,可以通過SOUND_MIXER_READ_STEREODEVS來獲得。
4.3 音頻錄放框架
下面給出一個利用聲卡上的DSP設備進行聲音錄制和回放的基本框架,它的功能是先錄制幾秒種音頻數據,將其存放在內存緩沖區中,然后再進行回放,其所有的功能都是通過讀寫/dev/dsp設備文件來完成的:
/*
* sound.c
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
#define LENGTH 3 /* 存儲秒數 */
#define RATE 8000 /* 采樣頻率 */
#define SIZE 8 /* 量化位數 */
#define CHANNELS 1 /* 聲道數目 */
/* 用于保存數字音頻數據的內存緩沖區 */
unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];
int main()
{
int fd; /* 聲音設備的文件描述符 */
int arg; /* 用于ioctl調用的參數 */
int status; /* 系統調用的返回值 */
/* 打開聲音設備 */
fd = open("/dev/dsp", O_RDWR);
if (fd < 0) {
perror("open of /dev/dsp failed");
exit(1);
}
/* 設置采樣時的量化位數 */
arg = SIZE;
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_BITS ioctl failed");
if (arg != SIZE)
perror("unable to set sample size");
/* 設置采樣時的聲道數目 */
arg = CHANNELS;
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
if (arg != CHANNELS)
perror("unable to set number of channels");
/* 設置采樣時的采樣頻率 */
arg = RATE;
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_WRITE ioctl failed");
/* 循環,直到按下Control-C */
while (1) {
printf("Say something:\n");
status = read(fd, buf, sizeof(buf)); /* 錄音 */
if (status != sizeof(buf))
perror("read wrong number of bytes");
printf("You said:\n");
status = write(fd, buf, sizeof(buf)); /* 回放 */
if (status != sizeof(buf))
perror("wrote wrong number of bytes");
/* 在繼續錄音前等待回放結束 */
status = ioctl(fd, SOUND_PCM_SYNC, 0);
if (status == -1)
perror("SOUND_PCM_SYNC ioctl failed");
}
}
4.4 混音器框架
下面再給出一個對混音器進行編程的基本框架,利用它可以對各種混音通道的增益進行調節,其所有的功能都是通過讀寫/dev/mixer設備文件來完成的:
/*
* mixer.c
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/soundcard.h>
/* 用來存儲所有可用混音設備的名稱 */
const char *sound_device_names[] = SOUND_DEVICE_NAMES;
int fd; /* 混音設備所對應的文件描述符 */
int devmask, stereodevs; /* 混音器信息對應的位圖掩碼 */
char *name;
/* 顯示命令的使用方法及所有可用的混音設備 */
void usage()
{
int i;
fprintf(stderr, "usage: %s <device> <left-gain%%> <right-gain%%>\n"
" %s <device> <gain%%>\n\n"
"Where <device> is one of:\n", name, name);
for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++)
if ((1 << i) & devmask) /* 只顯示有效的混音設備 */
fprintf(stderr, "%s ", sound_device_names[i]);
fprintf(stderr, "\n");
exit(1);
}
int main(int argc, char *argv[])
{
int left, right, level; /* 增益設置 */
int status; /* 系統調用的返回值 */
int device; /* 選用的混音設備 */
char *dev; /* 混音設備的名稱 */
int i;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -