4、ALSA架构与高通适配:核心概念与实战工具

好,我们进入第四章。这一章我打算聊聊ALSA——高级Linux声音架构。说实话,很多做车载音频的工程师,一听到ALSA就头大。觉得它太底层、太复杂。但我想说,你如果搞懂了ALSA,高通平台上的音频开发,你就掌握了主动权。

我个人习惯把ALSA比作一个“音频设备管理器”。它帮你把硬件抽象成几个简单的概念,然后用一套统一的接口去操作。今天我们就把它拆开来看。

4.1 ALSA核心概念:Card、Device、PCM、Control

ALSA的核心概念其实就四个:Card、Device、PCM、Control。我一个个讲。

4.1.1 Card(声卡)

Card就是一张“逻辑声卡”。在嵌入式平台,比如高通8155、8295上,通常只有一个Card,代表整个音频子系统。但有些平台会有多个Card,比如一个给内部扬声器,一个给蓝牙。

你可以用 cat /proc/asound/cards 查看当前系统有哪些Card。我见过一个项目,客户非要搞两个Card,结果路由配置搞得一团糟。所以我的建议是:能用一张Card搞定,就别分两张

4.1.2 Device(设备)

每个Card下面可以有多个Device。Device代表一个独立的音频数据流通道。比如,Device 0可能是播放,Device 1可能是录音。

在高通平台上,Device的编号和DMA(直接内存访问)通道是绑定的。我记得有一次调试,发现录音没声音,查了半天,原来是Device编号和硬件DMA通道没对上。嗯,这里要注意:Device编号不是随便写的,必须和硬件设计一致

4.1.3 PCM(脉冲编码调制)

PCM是音频数据的“载体”。你播放的每一段音乐,录制的每一句语音,最终都要通过PCM设备来读写。PCM设备有采样率、位深、通道数等属性。

你可以用 aplay -larecord -l 查看PCM设备列表。我刚开始做车载时,总搞不清PCM设备和Device的关系。说白了,Device是硬件通道,PCM是软件接口。你通过PCM接口去读写Device。

4.1.4 Control(控制)

Control是ALSA里最灵活、也最容易让人迷惑的部分。它用来控制音频路径上的各种“开关”和“旋钮”。比如:

  • 音量调节(Master Volume、PCM Volume)
  • 音频路由(把播放数据送到扬声器还是耳机)
  • 混音器(Mixer)设置

你可以用 amixer controls 列出所有Control。我曾经在一个项目中,因为一个Control的名字写错了(大小写问题),导致音频路由死活切不过去。所以,Control的名字是大小写敏感的,千万别搞错

核心总结:

  • Card = 逻辑声卡
  • Device = 硬件数据通道
  • PCM = 软件读写接口
  • Control = 控制开关和旋钮

4.2 高通平台ALSA驱动适配要点

高通平台的ALSA驱动,和标准Linux内核的ALSA驱动有些不同。它基于ASoC(ALSA System on Chip)架构,并且加入了高通自己的音频框架——比如 q6asmq6afe 等。

我总结几个适配要点:

4.2.1 DAI Link的配置

DAI Link是CPU(处理器)和Codec(编解码器)之间的数字音频接口。在高通平台上,DAI Link通常通过 q6afe 驱动来配置。你需要确保:

  • DAI Link的格式(I2S、TDM、PDM)和硬件一致
  • 时钟(BCLK、LRCLK)的极性正确
  • 采样率和位深匹配

我遇到过一个问题:扬声器播放声音有“嘶嘶”的杂音。查了半天,发现是BCLK的极性配置反了。嗯,这种问题用示波器一看就明白,但如果你没有示波器,那就只能靠经验了。

4.2.2 Machine Driver的编写

Machine Driver是连接CPU DAI和Codec DAI的“胶水代码”。高通平台通常使用 snd_soc_card 结构体来定义。你需要在这个结构体里指定:

  • Card的名字
  • DAI Link的列表
  • 辅助设备(如时钟、电源)

我个人习惯把Machine Driver写得尽量简洁。不要在里面加太多业务逻辑,否则后期维护会很痛苦。

4.2.3 音频路由的配置

高通平台的音频路由,是通过 tinymix 工具来配置的。你需要定义好各个音频路径的Control。比如:

  • 播放路径:PCM0 -> Mixer -> DAC -> Speaker
  • 录音路径:MIC -> ADC -> Mixer -> PCM1

我曾经在一个项目中,因为漏配了一个Mixer的Control,导致录音只有左声道有声音。所以,音频路由的配置一定要完整,不能漏掉任何一个节点

警告:高通平台的音频驱动,很多Control是“虚拟”的,它们不直接对应硬件寄存器,而是通过DSP(数字信号处理器)来间接控制。所以,不要试图用 amixer 去直接读写硬件寄存器,那会出问题的。

4.3 tinymix / tinyplay / tinycap 工具实战

好了,理论讲完了,我们来点实战。高通平台推荐使用 tinymixtinyplaytinycap 这套工具,而不是标准的 amixeraplayarecord。为什么?因为 tiny* 工具更轻量,而且对高通平台的支持更好。

4.3.1 tinymix:音频路由的“遥控器”

tinymix 用来查看和设置Control。基本用法:

# 列出所有Control
tinymix

# 查看某个Control的当前值
tinymix "PCM Playback Volume"

# 设置某个Control的值
tinymix "PCM Playback Volume" 80

我建议你先把所有Control列出来,然后一个一个试。比如,你想让扬声器出声,就找到“Speaker Switch”或“Speaker Volume”这样的Control,把它打开。

小技巧:你可以用 tinymix -D 0 指定Card编号。如果系统有多个Card,别忘了指定。

4.3.2 tinyplay:播放音频文件

tinyplay 用来播放WAV文件。基本用法:

# 播放一个WAV文件
tinyplay test.wav

# 指定PCM设备播放
tinyplay -D 0 -d 0 test.wav

这里 -D 0 是Card 0,-d 0 是Device 0。我刚开始用的时候,总忘记指定Device,结果播放没声音。后来我养成了习惯:每次都用 -D-d 明确指定

4.3.3 tinycap:录制音频文件

tinycap 用来录制WAV文件。基本用法:

# 录制5秒的音频
tinycap -D 0 -d 1 -r 48000 -b 16 -c 2 -t 5 record.wav

参数说明:

  • -r:采样率,48000 Hz
  • -b:位深,16 bit
  • -c:通道数,2(立体声)
  • -t:录制时长,5秒

我记得有一次调试车载麦克风阵列,用 tinycap 录制后发现只有左声道有数据。后来发现是Control里把“MIC1”和“MIC2”的路由搞反了。用 tinymix 调整一下就好了。

实战流程:

  1. tinymix 列出所有Control,找到音频路由相关的开关和音量。
  2. 设置好路由,比如把播放数据送到扬声器。
  3. tinyplay 播放一个测试音频,确认扬声器有声音。
  4. tinycap 录制一段音频,确认麦克风能正常工作。

4.4 避坑指南

最后,我分享几个我踩过的坑:

  • Control名字别写错:大小写、空格、下划线,一个都不能错。我曾经因为“Volume”写成了“Volum”,结果调试了一整天。
  • PCM设备编号别搞混:播放和录音的PCM设备编号可能不同。用 tinyplay -ltinycap -l 先确认一下。
  • 音频路由要完整:从PCM到DAC,中间可能经过多个Mixer和Switch。漏掉任何一个,声音都出不来。
  • 采样率要匹配:播放的音频文件采样率,必须和PCM设备支持的采样率一致。否则会有“吱吱”的杂音。

好了,这一章就到这里。ALSA其实没那么可怕,你只要理解了Card、Device、PCM、Control这四个概念,再配合 tinymixtinyplaytinycap 这三个工具,大部分音频问题都能搞定。下一章,我们聊聊高通平台上的音频路由配置,那才是真正考验功力的时候。