音频设备与混音 · ADM 与 AudioMixer
音频的两头是硬件:采集靠麦克风、播放靠扬声器。ADM 抽象各平台的音频设备,AudioMixer 把会议里多路远端音频混成一路播放。这一章讲清这两个「两头」组件,收尾第 7 部分。
音频设备与混音 · ADM 与 AudioMixer
音频管线的两头是硬件:发送侧的起点是麦克风采集,接收侧的终点是扬声器播放。抽象这些设备的是 ADM;而多人会议里,多路远端音频要混成一路才能播,靠 AudioMixer。这一章讲这两头,收尾第 7 部分。
ADM:音频设备的抽象
ADM(Audio Device Module,modules/audio_device/) 是各平台音频硬件的统一抽象:
ADM 把“各平台五花八门的音频 API”(Windows 的 WASAPI/Core Audio、macOS 的 CoreAudio、Android 的 AAudio/OpenSL、iOS 的 AudioUnit、Linux 的 ALSA/PulseAudio)收敛成统一接口——上层音频管线不关心底下是哪个平台。 它负责两件事:
- 采集(capture) —— 从麦克风读音频,喂给APM 处理、编码。
- 播放(render) —— 把NetEq 出的音频送到扬声器。
ADM 还有个关键角色:它的播放回调是驱动 NetEq GetAudio 的节拍源——声卡每隔固定时间(如 10ms)回调“给我下一段音频播”,这个回调就触发 NetEq 产出一段音频。所以 ADM 的播放时钟,是整个接收侧音频节奏的心跳。此外,有些平台的 ADM 能用硬件的回声消除 / 降噪,WebRTC 会视情况选择用平台的还是自带的 APM。ADM 是平台集成(第 12 部分)的重要一环。
AudioMixer:多路混成一路
多人会议里,你同时收到好几个人的音频(多条接收流)。但你只有一对扬声器——得把这几路混成一路再播。这是 AudioMixer(modules/audio_mixer/)的活:
**AudioMixer 把会议里多路远端音频**混合(相加)成一路,送去播放——就像调音台把多个声源合成一路输出。 混音不是简单相加了事,有讲究:
- 谁参与混音 —— 几十人的大会,不必把每个人都混进去(大多数人在静音)。AudioMixer 通常只混最响的几路(靠 VAD / 能量挑出“正在说话”的),忽略静音者——省 CPU、也让主讲更清晰。
- 防削顶 —— 多路相加可能超出幅度上限(削顶失真),混音要做限幅 / 归一。
- 每个接收流各有自己的 NetEq —— 混音前,每路先各自过 NetEq(各有各的抖动 / 丢包),出来对齐后再混。
在纯 P2P 两人通话里,AudioMixer 作用不大(就一路远端);它在多人会议(尤其本地混音的场景)才吃重。 大型会议更常用 SFU 转发多路让客户端各自混,或用 MCU 在服务器混——但客户端的 AudioMixer 始终是把“我收到的这几路”合成“我听到的一路”的最后一步。
小结与第 7 部分回顾
ADM(音频设备模块) 抽象各平台音频硬件(采集 + 播放),其播放回调是驱动 NetEq 的节拍心跳,也是平台集成一环。AudioMixer 把会议多路远端音频混成一路播放(只混最响几路、防削顶,各路先过各自 NetEq),多人会议才吃重。
第 7 部分「音频管线」到此完整:总览 → 编解码 Opus → ACM → NetEq(总览/缓冲延迟/六操作/丢包隐藏/时间伸缩) → APM(总览/回声问题/AEC3/AGC/NS+VAD) → 设备与混音。音频从麦克风到扬声器、以及它两颗明珠 NetEq 与 AEC3,已经拆透。
音视频都讲完了。还剩数据通道——传任意数据的那条路,底下是从零实现的 SCTP。第 8 部分进入 net/dcsctp/。👉 第 8 部分即将展开。
参考资料
- [1] libwebrtc 源码.
modules/audio_device/(ADM,各平台实现)、modules/audio_mixer/(AudioMixerImpl、frame_combiner.h)。 - [2] libwebrtc 源码.
modules/audio_device/g3doc/。 - [3] 关联NetEq(被 ADM 播放回调驱动)、平台集成第 12 部分。