轉自:http://www.voidcn.com/article/p-snamarwr-p.htmlphp
高級Linux聲音體系(英語:Advanced LinuxSound Architecture,縮寫爲ALSA)是Linux內核中,爲聲卡提供的驅動組件,以替代原先的OSS(開放聲音系統)。 一部分的目的是支持聲卡的自動配置,以及完美的處理系統中的多個聲音設備,這些目的大多都已達到。另外一個聲音框架JACK使用ALSA提供低延遲的專業級音頻編輯和混音能力。html
Jaroslav Kysela過去是這個項目的領導者,這個項目開始於爲1998年Gravis Ultrasound所開發的驅動,它一直做爲一個單獨的軟件包開發,直到2002年他被引進入Linux內核的開發版本 (2.5.4-2.5.5)。從2.6版本開始ALSA成爲Linux內核中默認的標準音頻驅動程序集,OSS則被標記爲廢棄。編程
ALSA是一個徹底開放源代碼的音頻驅動程序集,除了像OSS那樣提供了一組內核驅動程序模塊以外,ALSA還專門爲簡化應用程序的編寫提供了相應的函數庫,與OSS提供的基於ioctl的原始編程接口相比,ALSA函數庫使用起來要更加方便一些。利用該函數庫,開發人員能夠方便快捷的開發出本身的應用程序,細節則留給函數庫內部處理。固然ALSA也提供了相似於OSS的系統接口,不過ALSA的開發者建議應用程序開發者使用音頻函數庫而不是驅動程序的API。app
ALSA體系主要分爲三層,按照調用關係依次是,app、alsa-lib、kerneldriver。框架
Kernel driver 層,爲內核驅動代碼,主要在內核源碼中的sound目錄下,負責對硬件進行控制與操做。驅動建立的設備文件,在文件系統中的/dev/snd/目錄下。注意,應用層使用alsa-API中打開的設備文件,並非/dev/snd/目錄下的文件,而是alsa-lib對設備的再一次封裝的產物,叫作plugins,如plughw:0,0 ,後面詳細解釋。函數
alsa驅動的設備文件結構: 字符設備
# ls /dev/snd/ -lh
total 0
crw-rw---- 1 root root 116, 0 Aug 21 16:01 controlC0
crw-rw---- 1 root root 116, 24 Aug 21 16:01 pcmC0D0c
crw-rw---- 1 root root 116, 16 Aug 21 16:01 pcmC0D0p
crw-rw---- 1 root root 116, 25 Aug 21 16:01 pcmC0D1c
crw-rw---- 1 root root 116, 17 Aug 21 16:01 pcmC0D1p
crw-rw---- 1 root root 116, 26 Aug 21 16:01 pcmC0D2c
crw-rw---- 1 root root 116, 33 Aug 21 16:01 timer
controlC0 用於聲卡的控制,例如通道選擇,混音,麥克風的控制等
pcmC0D0c 用於錄音的pcm設備
pcmC0D0p 用於播放的pcm設備
timer 定時器
C0D0表明的是聲卡0中的設備0,pcmC0D0c最後一個c表明capture,pcmC0D0p最後一個p表明playback,這些都是alsa-driver中的命名規則。spa
Alsa-lib層,爲不一樣的驅動提供統一的接口alsa API,簡化了開發人員對於驅動層的調用開發。主要有以下接口開放源代碼
網址:https://www.alsa-project.org/alsa-doc/alsa-lib/插件
The currently designed interfaces are listed below:線程
Information Interface (/proc/asound)
Control Interface (/dev/snd/controlCX)
Mixer Interface (/dev/snd/mixerCXDX)
PCM Interface (/dev/snd/pcmCXDX)
Raw MIDI Interface (/dev/snd/midiCXDX)
Sequencer Interface (/dev/snd/seq)
Timer Interface (/dev/snd/timer)
咱們在應用中,主要使用的是 PCM 接口。如Snd_pcm_open()函數。
除了Alsa-API接口之外,alsa-lib還能夠經過配置文件,開放其附加功能,如採樣率轉換、軟件混音等。
咱們就是利用alsa-lib的附加功能實現咱們的重採樣功能,修改的地方主要包括alsa-lib的配置和APP調用兩方面。下一章對如何利用alsa-lib的配置文件開放其採樣率轉換功能進行描述。
asound.conf配置文件,是alsa-lib的默認配置文件,路徑在 /etc/,能夠用來配置alsa庫的一些附加功能。這個文件不是alsa庫運行時所必須的,沒有它alsa庫也能夠正常運行。
關於asound.conf的配置,能夠參考如下文檔:
http://www.alsa-project.org/main/index.php/Asoundrc
先闡述一些重要的名詞:
Card:聲卡,直接對應硬件,ID從0開始計數。
Device:設備,在一個card上,能夠有多個device,每一個device能夠獨立被打開和使用,ID從0開始計數。
Plugin:插件,前文說過,應用層調用alsa庫時,操做的並非驅動層建立的設備文件,而是這個plugins,plugin是alsa庫對音頻處理設備的抽象,hw plugin爲硬件設備抽象出的plugin,是最基礎的模塊,不須要對alsa-lib進行配置便可使用,咱們常見的plughw:0,0含義就是類型爲hw的plugin,編號聲卡0上面的設備0。除了hw類型的plugin外,還有一些純軟件實現的模塊,能夠用來進行音頻處理,例如,能夠實現音頻採樣率轉換的rate plugin,能夠用來混音的dmix plugin等等。
Slave:從屬設備,能夠把幾個plugin鏈接起來,sink端的設備就是source端設備的slave。
須要使用這些附加的plugin,就要對配置文件(asound.conf)進行配置,這個配置是實時生效的,因此咱們沒必要修改文件系統中的文件,而是在運行咱們的應用程序以前,將本身的配置文件拷貝到/etc/下,對默認的配置文件進行覆蓋就好了。
具體如何配置,書寫格式,請參看Asoundrc文檔。
如下就是個人配置,
pcm_slave.sl2 {
pcm"plughw:0,1"
rate48000
}
pcm.rate_convert {
typerate
slavesl2
}
這個配置的含義是,
下面一段:建立一個使用pcm API接口的設備,叫作rate_convert,它的類型是rate(能夠實現採樣率轉換的plugin),它有一個slave叫作sl2;
上面一段:定義一個使用pcm接口的slave,叫作sl2,他其實是plughw:0,1這個設備的別名,即等同於plughw:0,1(對應我用於播放的AIC3104芯片),這個設備須要的採樣率是48KHz。
經過這個配置,就能夠在app中,使用pcm API打開rate_convert這個設備,並把解碼後的8K採樣率的PCM數據,直接使用snd_pcm_writei寫入設備,rate_convert這個設備就能夠自動將PCM數據重採樣至48KHz,而後自動傳遞給plughw:0,1進行播放。
在看Asoundrc的文檔中,一直不明白,爲何在配置文件中,只有輸出的採樣率配置,而沒有輸入的採樣率配置,要重採樣,alsa-lib總得知道把啥轉換成48K吧,
在實踐中發現,能夠經過APP調用alsa-API中的snd_pcm_hw_params_set_rate_near()函數將數據源的採樣率爲8K傳遞給alsa-lib。下面一章對app調用alsa-API進行說明。
在app調用這塊兒,其餘的通用調用流程在這裏就不累述了,使用個項目原來的那套代碼就行,只有三塊兒須要修改和注意:
一、使用snd_pcm_open()打開的設備文件rate_convert(不需再打開plughw:0,1了),PCM數據的原始採樣率,用snd_pcm_hw_params_set_rate_near()對rate_convert進行配置。
二、重要的參數Period_size,即播放週期大小,單位爲Byte,需使用snd_pcm_hw_params_set_period_size_near()進行配置,若是period_size配的不對,或者不配置,會發生underRun,播放聲音斷斷續續。
8K pcm, 配置sample_rate爲8000,配置period_size爲256
48K pcm, 配置sample_rate爲48000,配置period_size爲1024
三、配置負責playback的AIC3104的採樣率爲48K
在研究alsa-lib的調用時,還有一些沒有搞明白的地方,這裏記錄下來,未來你們有時間能夠研究研究。
一、個人設備上音頻輸入輸出分開使用了兩塊AIC3104,這樣重採樣後G711的自編自解就不成問題,由於輸入的AIC3104設爲8K,輸出的AIC3104設爲48K播放重採樣後的數據,若是系統中只使用一塊AIC3104,就必須對輸入的PCM數據也進行一次重採樣,這裏沒有進行研究。
二、多設備綁定,假如咱們系統中有多個playback設備,如今的作法是啓兩個線程,分別寫入數據,若是可使用alsa-lib的slave配置將多個設備進行綁定,例如一個rate plugin綁定兩個 hw plugin,而後只需向這一個rate plugin寫入數據便可,不會遇到兩個播放線程同步的問題,我試了一下,只能綁定一個slave,再多綁一個,第一個slave就會沒有播放聲音。
三、混音功能,這個混音功能看似是很是強大的,它能夠把多個不一樣採樣率的通道,混合成一路統一採樣率的數據進行播放,若是咱們之後能夠進行多路解碼,或者要實現視頻會議中MCU的功能,那勢必要用到這個功能,在這裏尚未進行深究。