PCM (digital audio) plugins
PCM plugins extends functionality and features of PCM devices. The plugins take care about various sample conversions, sample copying among channels and so on.
Plugin: hw
This plugin communicates directly with the ALSA kernel driver. It is a raw communication without any conversions. The emulation of mmap access can be optionally enabled, but expect worse latency in the case.
The nonblock option specifies whether the device is opened in a non-blocking manner. Note that the blocking behavior for read/write access won't be changed by this option. This influences only on the blocking behavior at opening the device. If you would like to keep the compatibility with the older ALSA stuff, turn this option off.
1 | pcm.name { |
Example:
1 | pcm.!default{ |
给hw:0,1设备重命名为default
Test:
1 | aplay -D default test.wav |
Slave definition
The slave plugin can be specified directly with a string or the definition can be entered inside a compound configuration node. Some restrictions can be also specified (like static rate or count of channels).
1 | pcm_slave.NAME { |
Example:
1 | pcm_slave.slave_rate44100Hz { |
The equivalent configuration (in one compound):
1 | pcm.rate44100Hz { |
将hw:0,0声卡的采样频率转换为44100hz。
Test:
1 | aplay -D rate44100Hz test.wav |
Plugin: Rate
This plugin converts a stream rate. The input and output formats must be linear.
1 | pcm.name { |
Plugin: Route & Volume
This plugin converts channels and applies volume during the conversion. The format and rate must match for both of them.
SCHANNEL can be a channel name instead of a number (e g FL, LFE). If so, a matching channel map will be selected for the slave.
1 | pcm.name { |
Automatic conversion plugin
This plugin converts channels, rate and format on request.
1 | pcm.name { |
Example:
1 | pcm.nfbtout { |
Plugin: Multiple streams to One
This plugin converts multiple streams to one.
1 | pcm.name { |
For example, to bind two PCM streams with two-channel stereo (hw:0,0 and hw:0,1) as one 4-channel stereo PCM stream, define like this:
1 | pcm.quad { |
Note that the resultant pcm "quad" is not in the interleaved format but in the "complex" format. Hence, it's not accessible by applications which can handle only the interleaved (or the non-interleaved) format. In such a case, wrap this PCM with route or plug plugin.
1 | pcm.quad2 { |
Plugin: dmix
This plugin provides direct mixing of multiple streams. 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.
1 | pcm.name { |
ipc_key必须是整数形式的唯一ipc key。对于每个不同的dmix定义,这个数字必须是唯一的,因为共享内存是用这个key创建的。当ipc_key_add_uid设置为true时,uid值将添加到ipc_key设置中。这样可以避免同一个IPC密钥与不同用户同时发生冲突。
hw_ptr_alignment这个配置默认是auto
An example configuration for setting 44100 Hz, S32_LE
format as the slave PCM of "hw:0" is like below:
1 | pcm.dmix_44 { |
Test:
1 | aplay -Dplug:dmix_44 foo_48k.wav |
Plugin: dsnoop
此插件将一个capture流拆分为多个。它的工作方式与dmix插件相反,从多个客户端同时读取共享捕获缓冲区。以下参数的含义与dmix插件几乎相同。
1 | pcm.name { |
Open流程
下面以dsnoop插件为例梳理下alsa-lib使用插件的流程,详细如下:
原图
- 解析配置文件并生成配置树
- 打开实际设备,通过mmap映射驱动中的控制信息和buffer
Read流程
以下是read流程,write流程不再列出来了。
原图
- memcopy驱动DMA buffer中的数据
- hw_ptr数据指针的sync
可以看到alsa plug支持多进程,可以多个进程打开同一个slave声卡,多进程间通过信号量同步。 如果要自己创建一个声卡,同时让创建的声卡支持plugin,那么最好不要使用appl_ptr和依赖appl_ptr的api。
参考文献
https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html
https://alsa.opensrc.org/ALSA_plugins