Alsa-lib層,爲不同的驅動提供統一的接口alsa API,簡化了開發人員對於驅動層的調用開發。接口定義地址:
https://www.alsa-project.org/alsa-doc/alsa-lib/
關於asound.conf的配置,可以參考官網解釋:
https://www.alsa-project.org/main/index.php/Asoundrc
詳細的插件講解,官網網址:
https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html
1. 什麼是asound.conf
asound.conf配置文件,是alsa-lib的默認配置文件,路徑在 /etc/,可以用來配置alsa庫的一些附加功能。這個文件不是alsa庫運行時所必須的,沒有它alsa庫也可以正常運行。asound.conf允許對聲卡或者設備進行更高級的控制,提供訪問alsa-lib中的pcm插件方法,允許你做更多的複雜的控制,比如可以把聲卡組合成一個或者多聲卡訪問多個I/O。
ps:在usr/local/shar/alsa/中有一個文件叫---alsa.conf,asound.conf 這個文件在調用snd_pcm_open這個api函數時,會被加載同時解析。
2. 什麼是插件(plugins)?
在ALSA中,PCM插件擴展了PCM設備的功能和特性。插件可以自動處理諸如:命名設備、採樣率轉換、通道間的採樣複製、寫入文件、爲多個輸入/輸出連接聲卡/設備(不同步採樣)、使用多通道聲卡/設備等工作。
3. Plugin: hw
此插件直接與ALSA內核驅動程序通信,它是一種沒有任何轉換的原始通信。
pcm.name {
type hw # Kernel PCM
card INT/STR # Card name (string) or number (integer)
[device INT] # Device number (default 0)
[subdevice INT] # Subdevice number (default -1: first available)
[sync_ptr_ioctl BOOL] # Use SYNC_PTR ioctl rather than the direct mmap access for control structures
[nonblock BOOL] # Force non-blocking open mode
[format STR] # Restrict only to the given format
[channels INT] # Restrict only to the given channels
[rate INT] # Restrict only to the given rate
[chmap MAP] # Override channel maps; MAP is a string array
}
nonblock選項指定設備是否以非阻塞方式打開。注意此選項並不會更改讀/寫訪問的阻塞行爲。隻影響打開設備時的阻塞行爲。如果想保持與舊ALSA版本的兼容性,請關閉此選項。
下面是一個例子:
pcm.!default {
type hw
card 0
}
ctl.!default {
type hw
card 0
}
名字爲default的聲卡,指向card0,也就是hw:0,0,測試命令:aplay -D default test.wav
hw後面跟的數字是聲卡號和設備號,可以用如下命令查看硬件支持聲卡數:
cat /proc/asound/cards 或者 ls /dev/dns. (pcm0c (capture), pcm0p (playback))
4. Slave 定義
在ALSA中,PCM插件擴展了PCM設備的功能和特性。插件可以自動處理諸如:命名設備、採樣率轉換、通道間的採樣複製、寫入文件、爲多個輸入/輸出連接聲卡/設備(不同步採樣)、使用多通道聲卡/設備等工作。要使用它們,開發者需要創建一個虛擬從屬設備(slave device)。
pcm_slave.NAME {
pcm STR # PCM name
# or
pcm { } # PCM definition
format STR # Format or "unchanged"
channels INT # Count of channels or "unchanged" string
rate INT # Rate in Hz or "unchanged" string
period_time INT # Period time in us or "unchanged" string
buffer_time INT # Buffer time in us or "unchanged" string
}
一個最簡單的slave用例:
pcm_slave.sltest {
pcm "hw:1,0"
}
在slave設備配置中加入採樣率轉換:
pcm_slave.sl2 {
pcm "hw:1,0"
rate 48000
}
pcm.rate_convert {
type rate
slave sl2
}
調用這個接口,44.1k的採樣頻率的音頻將會轉換爲48khz輸出。
可以用aplay命令測試創建的虛擬設備:
aplay -D rate_convert test.wav
上圖的slave配置的另一種方式,兩種方式等同:
pcm.rate_convert {
type rate
slave {
pcm "hw:1,0"
rate 48000
}
}
上面的用例用到了 Plugin: Rate
4.Plugin: Rate
這個插件可以轉換採樣率,但是輸入輸出格式必須爲線型。
pcm.name {
type rate # Rate PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
rate INT # Slave rate
[format STR] # Slave format
}
converter STR # optional
# or
converter [ STR1 STR2 ... ] # optional
# Converter type, default is taken from
# defaults.pcm.rate_converter
# or
converter { # optional
name STR # Convertor type
xxx yyy # optional convertor-specific configuration
}
}
5. Plugin: Route & Volume
此插件可以轉換聲道數和應用聲音。轉換聲音這個我沒有很明白,官網也沒有給出具體的用例。
pcm.name {
type route # Route & Volume conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format
[channels INT] # Slave channels
}
ttable { # Transfer table (bi-dimensional compound of cchannels * schannels numbers)
CCHANNEL {
SCHANNEL REAL # route value (0.0 - 1.0)
}
}
}
6. Automatic conversion plugin
這個插件可以轉換channels、rate和format,可以理解爲是rate和Route & Volume的集合體。
pcm.name {
type plug # Automatic conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format (default nearest) or "unchanged"
[channels INT] # Slave channels (default nearest) or "unchanged"
[rate INT] # Slave rate (default nearest) or "unchanged"
}
route_policy STR # route policy for automatic ttable generation
# STR can be 'default', 'average', 'copy', 'duplicate'
# average: result is average of input channels
# copy: only first channels are copied to destination
# duplicate: duplicate first set of channels
# default: copy policy, except for mono capture - sum
ttable { # Transfer table (bi-dimensional compound of cchannels * schannels numbers)
CCHANNEL {
SCHANNEL REAL # route value (0.0 - 1.0)
}
}
rate_converter STR # type of rate converter
# or
rate_converter [ STR1 STR2 ... ]
# type of rate converter
# default value is taken from defaults.pcm.rate_converter
}
看一下小例子:
pcm.nfbtout {
type plug
slave {
pcm "hw:1,0"
rate 8000
channels 2
}
}
7. Plugin: dmix
有了一個本地的alsa插件,叫做dmix(直接混合)插件。它允許軟件混合在一個易於使用的語法中,而不需要先安裝/理解一個新的應用程序。但是需要注意的一點:The resolution for 32-bit mixing is only 24-bit. The low significant byte is filled with zeros. The extra 8 bits are used for the saturation.
注意,dmix插件不是基於客戶機/服務器架構,而是直接寫入聲卡的dma緩衝區。一次可以運行的實例數量沒有限制。
pcm.name {
type dmix # Direct mix
ipc_key INT # unique IPC key
ipc_key_add_uid BOOL # add current uid to unique IPC key
ipc_perm INT # IPC permissions (octal, default 0600)
hw_ptr_alignment STR # Slave application and hw pointer alignment type
# STR can be one of the below strings :
# no
# roundup
# rounddown
# auto (default)
slave STR
# or
slave { # Slave definition
pcm STR # slave PCM name
# or
pcm { } # slave PCM definition
format STR # format definition
rate INT # rate definition
channels INT
period_time INT # in usec
# or
period_size INT # in bytes
buffer_time INT # in usec
# or
buffer_size INT # in bytes
periods INT # when buffer_size or buffer_time is not specified
}
bindings { # note: this is client independent!!!
N INT # maps slave channel to client channel N
}
slowptr BOOL # slow but more precise pointer updates
}
ipc_key必須是整數形式的唯一ipc key。對於每個不同的dmix定義,這個數字必須是唯一的,因爲共享內存是用這個key創建的。當ipc_key_add_uid設置爲true時,uid值將添加到ipc_key設置中。這樣可以避免同一個IPC密鑰與不同用戶同時發生衝突。
hw_ptr_alignment這個配置默認是auto,其他配置可以去上面貼的第三個網址中瞭解。
注意,dmix插件本身只支持單個配置。也就是說,它只支持固定rate(默認48000)、format(s16)、channels(2)和period_time (125000)。對於使用其它配置,開發者必須在從PCM定義中明確設置該值。
一個用例:
pcm.dmix_44 {
type dmix
ipc_key 321456 # any unique value
ipc_key_add_uid true
slave {
pcm "hw:0"
format S32_LE
rate 44100
}
}
可以利用這個配置的聲卡播放一個48k 的音頻:aplay -Dplug:dmix_44 foo_48k.wav
對於使用OSS仿真設備的dmix插件,必須將period和buffer sizes設置爲2的冪次方。例如:
pcm.dmixoss {
type dmix
ipc_key 321456 # any unique value
ipc_key_add_uid true
slave {
pcm "hw:0"
period_time 0
period_size 1024 # must be power of 2
buffer_size 8192 # ditto
}
}
period_time必須爲0,對於帶有多通道IO的聲卡,添加綁定也非常有用。(官網中的這句,我不是很明白),綁定的用例:
pcm.dmixoss {
...
bindings {
0 0 # map from 0 to 0
1 1 # map from 1 to 1
}
}
8. Plugin: dsnoop
此插件將一個capture流拆分爲多個。它的工作方式與dmix插件相反,從多個客戶端同時讀取共享捕獲緩衝區。以下參數的含義與dmix插件幾乎相同。
pcm.name {
type dsnoop # Direct snoop
ipc_key INT # unique IPC key
ipc_key_add_uid BOOL # add current uid to unique IPC key
ipc_perm INT # IPC permissions (octal, default 0600)
slave STR
# or
slave { # Slave definition
pcm STR # slave PCM name
# or
pcm { } # slave PCM definition
format STR # format definition
rate INT # rate definition
channels INT
period_time INT # in usec
# or
period_size INT # in bytes
buffer_time INT # in usec
# or
buffer_size INT # in bytes
periods INT # when buffer_size or buffer_time is not specified
}
bindings { # note: this is client independent!!!
N INT # maps slave channel to client channel N
}
slowptr BOOL # slow but more precise pointer updates
}