4. 硬件开发基础
座舱音频,是用户每天都会直接感知的功能。导航、电话、音乐、语音助手,哪个出问题都会被立刻投诉。8155 的音频子系统基于 ALSA 框架,但真正难的不是驱动,而是路由策略和音区管理。这一章,我把这些年踩过的坑和总结的方法都摊开来讲。
4.1 ALSA 框架在 8155 上的落地
ALSA 是 Linux 上的标准音频框架。8155 的硬件层面集成了多个 I2S 接口、TDM 总线和一个内部音频 DSP。驱动层暴露出来的,通常是多个 PCM 设备。
我个人习惯先通过 arecord -l 和 aplay -l 确认设备列表。在 8155 上,你可能会看到类似这样的输出:
**** List of PLAYBACK Hardware Devices ****
card 0: SA8155ADV [SA8155-ADV], device 0: MultiMedia0
card 0: SA8155ADV [SA8155-ADV], device 1: MultiMedia1
card 0: SA8155ADV [SA8155-ADV], device 2: Voice0
card 0: SA8155ADV [SA8155-ADV], device 3: Voice1
每个设备对应不同的用途。MultiMedia 用于音乐和导航,Voice 用于通话。为什么分开?因为底层路由和采样率不同。混在一起,调试起来会非常痛苦。
4.2 音频路由与策略:从硬件到场景
音频路由,说白了就是决定“声音从哪里来,到哪里去”。在 8155 上,路由控制主要通过 ALSA 的 amixer 或底层的 tinymix 完成。
举个例子,导航音要从左前门喇叭出来,同时音乐从全车喇叭出来。这需要配置 Mixer 的输入选择器和输出开关。
# 设置导航音路由到左前声道
tinymix "NAV_Playback_Channel" "Left"
tinymix "NAV_Volume" 80
# 设置音乐路由到全车
tinymix "MUSIC_Playback_Channel" "Stereo"
tinymix "MUSIC_Volume" 90
这里有个关键点:策略。你不能让所有音频都走同一个通道。我见过一个项目,导航和音乐混在一起,用户调音量时两个一起变,体验极差。
正确的做法是定义场景策略表:
| 场景 | 输入源 | 输出通道 | 优先级 | 音量策略 |
|---|---|---|---|---|
| 音乐播放 | MultiMedia0 | 全车喇叭 | 低 | 用户可调 |
| 导航播报 | MultiMedia1 | 左前门 | 中 | 音乐自动降低 |
| 蓝牙电话 | Voice0 | 全车喇叭+麦克风 | 高 | 音乐暂停 |
| 语音助手 | Voice1 | 前排麦克风+喇叭 | 高 | 导航暂停 |
这张表,就是音频策略的核心。每次场景切换,音频服务根据表里的规则,调用 tinymix 重新配置路由。
4.3 回声消除与降噪(AEC & ANC)
车载环境噪音大,回声问题尤其严重。8155 内部集成了硬件 AEC(回声消除)模块,但需要正确配置才能工作。
回声消除的原理,是让系统知道“喇叭正在播放什么”,然后从麦克风采集的信号中减去这部分。在 ALSA 层面,这通常通过一个 Loopback 设备实现。
# 启用 AEC 参考信号
tinymix "AEC_REFERENCE" "MultiMedia0"
tinymix "AEC_ENABLE" 1
降噪方面,8155 支持多麦克风阵列。我建议至少使用双麦方案:一个主麦采集人声,一个辅麦采集环境噪声。DSP 会做差分处理。
调试时,有几个参数需要重点关注:
- 收敛速度: 太快会导致声音断续,太慢则消除效果差。我一般从 50ms 开始调。
- 双讲表现: 两个人同时说话时,AEC 不能把对方的声音也消掉。这需要调整 NLP(非线性处理)的阈值。
- 风噪抑制: 开窗时,麦克风会录到风噪。8155 的 DSP 有专门的滤波器,记得在策略里开启。
4.4 多音区独立播放
这是座舱音频最复杂的功能。前排听音乐,后排看电影,互不干扰。8155 支持最多 4 个独立音区,每个音区有独立的音频通道和音量控制。
实现多音区,硬件上需要每个音区有独立的功放通道。软件上,需要为每个音区分配一个独立的 PCM 设备。
我画了一张架构图,帮你理解数据流:
代码层面,多音区的核心是音频策略服务。它监听系统事件(如“后排开始播放视频”),然后动态配置路由。
// 伪代码:多音区策略
void onVideoPlayStarted(int zone_id) {
if (zone_id == ZONE_REAR_LEFT) {
// 将音源3路由到音区3
tinymix_set("MIXER_SOURCE", "MultiMedia2");
tinymix_set("MIXER_DEST", "PCM_DEVICE_2");
tinymix_set("ZONE3_VOLUME", 70);
// 如果前排正在播放音乐,不做处理
// 如果前排正在导航,降低导航音量
}
}
4.5 性能与延迟考量
音频是实时性要求很高的场景。8155 的音频 DSP 可以分担大部分处理,但策略服务跑在 CPU 上。延迟主要来自三个地方:
- ALSA 缓冲区: 默认 1024 帧,约 23ms 延迟。对音乐够了,对语音助手偏大。我建议语音通道用 256 帧。
- 策略切换: tinymix 调用本身很快,但如果策略服务用 Java 写,GC 会导致抖动。关键路径建议用 C++ 或直接 ioctl。
- AEC 处理: 硬件 AEC 延迟约 10ms,软件实现可能到 30ms。能用硬件就用硬件。
嗯,这里要注意:延迟不是越低越好。太低的缓冲区会导致 underrun(数据没来得及填充)。你需要根据实际场景做平衡。
- 音乐通道:1024 帧,2 个周期
- 导航通道:512 帧,2 个周期
- 语音通道:256 帧,3 个周期
音频系统开发,说到底就是管理好“资源”和“策略”。硬件资源是固定的,但策略可以很灵活。把场景定义清楚,把路由配置做对,剩下的就是调优了。希望这一章的内容,能帮你少走一些弯路。