Linux 驱动之 ALSA(八)Alsa Plugin
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