一、聲卡
1、聲卡是audio interface,它含有hardware buffer,而這個hardware buffer是在聲卡里面,不是內存。聲卡的緩存是環狀的,則ALSA中是將數據分成連續的片段然后傳到按單元片段傳輸。
2、當我們通過麥克風講話的聲音搜集到聲卡里之后,將內存從聲卡設備文件中讀取聲音數據的過程就是錄音過程;把內存中的聲音數據寫入到聲卡的設備文件中可以實現音頻文件。
3、我們在/dev/snd/目錄下用ls命令就可以看到相關的聲卡設備。
4、模/數(ADC)轉換器將模擬電壓轉換成離散的樣本值。聲音以固定的時間間隔被采樣,采樣的速率稱為采樣率。把樣本輸出到數/模(DAC)轉換器,比如擴音器,最后轉換成原來的模擬信號。
二、相關設備文件介紹
1、/dev/dsp
用於數字采樣(sampling)和數字錄音(recording)的設備文件,向該設備寫數據時使用聲卡上的D/A轉換器進行放音,而向該設備讀數據時使用聲卡上的A/D轉換器進行錄音。
聲卡使用DSP(數字信號處理器)來實現模擬信號和數字信號之間的轉換(有D/A和A/D轉換)。聲卡中的DSP設備在以只讀方式打開/dev/dsp時,使用A/D轉換器變成數字采樣后的樣本,通過read系統調用從聲卡讀取數據進行聲音的輸入;以只寫方式打開/dev/dsp時,數字信號經過D/A轉換器變成模擬信號,通過write進行聲音的輸出。以讀寫的方式打開 /dev/dsp可同時進行聲音的輸入和輸出。
2、/dev/sequencer合成器
3、/dev/mixer混音器
三、使用
1、在打開聲卡之后可通過ioctl函數來設置聲卡參數,函數如下所示:
int ioctl(int fd, int request, ...);
//參數fd是打開的文件的描述符,它是在設備打開時獲得的;如果設備比較復雜,那么對它的控制請求相應地也會有很多種。
//參數request是命令,它的目的就是用來區分不同的控制請求;通常說來,在對設備進行控制時還需要有其它參數,這要根據不同的控制請求才能確定,並且可能是與硬件設備直接相關的。
//第三個參數是完成命令的操作需要的參數或返回的結果。它的意義取決於命令參數,可以是單個數,或是指向復雜的數據結構的指針。(由於ioctl函數面向所有設備文件,不同的設備又是千差萬別,所以,第三個參數的意義、函數的返回值、錯誤代碼等等都取決於command。並且,不同的設備,即使是相同的command也有不同的含義,需要的參數和返回值、錯誤代碼等也不同。)
//ioctl函數中相關的命令如下:
SOUND_PCM_WRITE_BITS:設置聲卡的量化位數,8或者16,有些聲卡不支持16位;
SOUND_PCM_READ_BITS:獲取當前聲卡的量化位數;
SOUND_PCM_WRITE_CHANNELS:設置聲卡的聲道數目,1或者2,1為單聲道,2為立體聲;
SOUND_PCM_READ_CHANNELS:獲取當前聲卡的聲道數;
SOUND_PCM_WRITE_RATE:設置聲卡的采樣頻率,8K,16K等等;
SOUND_PCM_READ_RATE:獲取聲卡的采樣頻率
(1)聲卡讀取數據和向聲卡寫入數據時,具有特定的格式,默認為8位無符號數據、單聲道、8KHz采樣率,可通過ioctl系統調用來改變格式,可調節運行在Linux內核中的聲卡驅動程序中緩沖區的大小,進而達到放音和錄音想要的效果。例如:
//緩沖區大小設置
int setting = 0xnnnnssss;
int result = ioctl(handle, SNDCTL_DSP_SETFRAGMENT, &setting);
//參數setting實際上由兩部分組成,其低16位標明緩沖區的尺寸,相應的計算公式為buffer_size = 2^ssss;
//若參數setting低16位的值為16,那么相應的緩沖區的大小會被設置為65536字節。參數setting的高16位則用來標明分片(fragment)的最大序號,它的取值范圍從2一直到0x7FFF,其中0x7FFF表示沒有任何限制。
//設置聲卡聲道數目
int channels = 0; //0=mono 1=stereo
int result = ioctl(handle, SNDCTL_DSP_STEREO, &channels);
//設置采樣格式
int format = AFMT_U8;
int result = ioctl(handle, SNDCTL_DSP_SETFMT, &format);
//設置采樣頻率
int rate = 22050;
int result = ioctl(handle, SNDCTL_DSP_SPEED, &rate);
//調用ioctl時將第二個參數的值設置為SNDCTL_DSP_SPEED,同時在第三個參數中指定采樣頻率的數值。
//在 Linux下進行音頻編程時最常用到的幾種采樣頻率是11025Hz、16000Hz、22050Hz、32000Hz和44100Hz。
2、直接使用系統調用控制聲卡的是tinyalsa庫,位於目錄/external/tinyalsa下,編譯生成庫文件libtinyalsa.so(只涉及兩個文件mixer.c,pcm.c),編譯生成工具 tinycap,tinymix,tinypcminfo,tinyplay,可用於直接控制音頻通道,進行錄音播音測試。tinyalsa中使用:
pcm_open()來打開聲卡;
pcm_write()來播放音樂;
pcm_read()來錄音。
3、config 的配置很重要,tinyalsa直接從wav文件把channels,rate,等讀出來並配置進聲卡。
//轉換成config
config.channels = channels; //聲道數目
config.rate = rate; //采樣頻率
config.period_size = 1024; //周期
config.period_count = 4; //count
if (bits == 32)
config.format = PCM_FORMAT_S32_LE; //
else if (bits == 16)
config.format = PCM_FORMAT_S16_LE;
config.start_threshold = 0;
config.stop_threshold = 0;
config.silence_threshold = 0;
//
pcm = pcm_open(card, device, PCM_IN, &config);
if (!pcm || !pcm_is_ready(pcm)) {
printf("Unable to open PCM device (%s)\n",pcm_get_error(pcm));
return 0;
}
四、
1、spdif接口支持rawdata和pcmdata模式。
當音頻channel設置成channels=4的時候,spdif會相應設置成rawdata模式。當音頻channel設置成channels=2或者1的時候,spdif會設置成pcmdata模式。spdif是一個獨立的音頻驅動,接口支持alsalib中的標准接口。
2、Hdmiaudio支持rawdata和pcmdata模式。
當音頻channel設置成channels=4的時候,hdmiaudio會相應設置成rawdata模式。當音頻channel設置成channels=2或者1的時候,hdmiaudio會設置成pcmdata模式。Hdmiaudio是一個獨立的音頻驅動,接口支持alsalib中的標准接口。
