webrtc代码走读(二十四)-QOS系列16-音频QOS-3A算法
WebRTC音频前处理3A算法摘要:AEC(回声消除)、AGC(自动增益控制)和ANS(噪声抑制)共同保障音频质量。AEC通过分析参考信号消除回声;AGC动态调整音量保持舒适听感;ANS识别并抑制环境噪声。源码实现上,AEC3模块处理回声路径估计与双讲检测,AGC通过数字增益平滑调整音量,ANS则在频域过滤噪声。这些算法通过AudioProcessing类统一调度,按帧实时处理音频数据,最终输出清
音频的QoS可以分:音频前处理3A算法、NetEQ两大类。

1、AEC(回声消除)
“别让对方听到自己的声音反弹”
1.1 作用:
视频通话时,如果你开着扬声器,对方的声音会从扬声器播放出来,然后被你的麦克风重新录下来,再传回给对方——对方就会听到自己的回声,非常影响体验。AEC的作用就是把这个回声干掉。
通俗原理:
WebRTC的AEC(源码在modules/audio_processing/aec3/目录)就像一个“回声侦探”:
- 它会拿到两个信号:一个是“即将从你的扬声器播放的声音”(参考信号,比如对方说的话),另一个是“你的麦克风实际录到的声音”(包含你的说话声+环境噪音+回声)。
- 它会分析“参考信号”的特征(比如频率、波形),然后在麦克风信号里找到“长得像参考信号”的部分(这就是回声)。
- 最后把这部分“回声”从麦克风信号里减掉,剩下的就是“你的声音+少量噪音”,传给对方。
1.2 源码关键:
- 核心文件:
aec3.cc(AEC3入口)、echo_path_estimator.cc(回声路径估计)、double_talk_detector.cc(双讲检测)。 - 核心逻辑:
Aec3::Process函数接收麦克风信号(capture)和参考信号(render),通过回声路径估计器生成“预测回声”,从麦克风信号中减去后,再用残留回声抑制器处理剩余杂音。 - 双讲处理:
double_talk_detector.cc通过比较本地语音和回声的能量,判断“是否两边同时说话”,避免误删本地声音。
2、AGC(自动增益控制)
“不管你大声小声,对方听着都舒服”
2.1 作用:
有的人说话离麦克风近,声音特别大;有的人离得远,声音特别小;还有人说话忽大忽小。AGC的作用就是自动调整音量,让传给对方的声音大小保持在一个合适的范围,不会刺耳也不会听不清。
通俗原理:
WebRTC的AGC(源码在modules/audio_processing/gain_control/)就像一个“自动音量旋钮”:
- 它会先“听”一下当前麦克风的声音有多大(比如用
level_estimator.cc计算音量)。 - 如果声音太小(比如低于目标值-18dB,这个值可以配置),就把音量调大(增加增益);如果声音太大(快到刺耳的程度),就把音量调小(降低增益)。
- 为了避免音量突然跳变(比如突然从小声变大声吓一跳),它会慢慢调整(比如每次只调一点点,源码里的
gain_applier.cc负责平滑处理)。
2.2 源码关键:
- 核心文件:
gain_control_impl.cc(AGC入口)、digital_agc.cc(数字增益计算)、gain_applier.cc(平滑增益)。 - 核心逻辑:
GainControlImpl::Process函数接收原始音频,digital_agc.cc中的LevelEstimator计算当前音量,ComputeGain函数根据目标音量计算需要的增益,最后由gain_applier.cc平滑应用增益,避免突变。 - 模式选择:支持“数字增益”(最常用,
kAdaptiveDigital)、“模拟增益”(需硬件支持)等,通过set_mode配置。
3、ANS(噪声抑制)
“过滤杂音,只留人声”
3.1 作用:
你在咖啡厅、办公室打电话时,背景里的空调声、键盘声、别人的说话声会被麦克风录进去,对方听着很吵。ANS的作用就是把这些噪音过滤掉,让对方更清晰地听到你的声音。
通俗原理:
WebRTC的ANS(源码在modules/audio_processing/noise_suppression/)就像一个“噪音过滤器”:
- 它会先“学习”环境噪音的特征(比如空调声是持续的、频率固定的),在你没说话的时候(通过
voice_activity_detector.cc判断“是否在说话”),悄悄记录噪音的“样子”。 - 当你说话时,它会把麦克风信号里“长得像噪音”的部分减弱(比如用
ns_core.cc里的算法,在频率域里把噪音对应的频段音量降低),而“长得像人声”的部分尽量保留。 - 你可以配置过滤强度(源码里的
Level),比如“轻度过滤”(保留更多环境音,适合音乐场景)或“深度过滤”(几乎只剩人声,适合嘈杂环境)。
3.2 源码关键:
- 核心文件:
noise_suppression_impl.cc(ANS入口)、ns_core.cc(降噪核心)、voice_activity_detector.cc(语音检测)。 - 核心逻辑:
NoiseSuppressionImpl::Process函数接收带噪音的信号,ns_core.cc先将信号转成频域(FFT),UpdateNoiseEstimate估计噪声频谱,Suppress函数对每个频率点计算抑制增益(噪音频段增益低,人声频段增益高),最后转回时域输出。
4、WebRTC中3A算法的完整调用流程
WebRTC把3A算法包装成了一个“音频处理管道”,通过AudioProcessing类统一调度,调用流程分三步:初始化配置、实时处理、销毁资源。
阶段1:初始化音频处理器(配置3A参数)
#include "webrtc/modules/audio_processing/include/audio_processing.h"
// 1. 创建音频处理器实例(内部自动初始化3A模块)
webrtc::AudioProcessing* apm = webrtc::AudioProcessing::Create();
if (!apm) { /* 初始化失败处理 */ }
// 2. 配置AEC(回声消除)
webrtc::EchoCancellation* aec = apm->echo_cancellation();
aec->Enable(true); // 开启AEC
aec->set_suppression_level(webrtc::EchoCancellation::kHighSuppression); // 高抑制强度
// 3. 配置AGC(自动增益控制)
webrtc::GainControl* agc = apm->gain_control();
agc->Enable(true); // 开启AGC
agc->set_mode(webrtc::GainControl::kAdaptiveDigital); // 数字增益模式(最常用)
agc->set_target_level_dbfs(-18); // 目标音量(默认-18dBFS)
// 4. 配置ANS(噪声抑制)
webrtc::NoiseSuppression* ans = apm->noise_suppression();
ans->Enable(true); // 开启ANS
ans->set_level(webrtc::NoiseSuppression::kHigh); // 高降噪强度
阶段2:实时处理音频帧(3A算法实际工作)
实时通信中,音频按“帧”处理(通常10ms一帧,16kHz采样率下每帧160个样本):
const int sample_rate = 16000; // 采样率16kHz
const size_t frame_size = 160; // 每帧160样本(10ms)
int16_t mic_frame[frame_size]; // 麦克风采集的原始信号(含回声、噪音)
int16_t render_frame[frame_size]; // 扬声器参考信号(对方的声音)
while (通话进行中) {
// 1. 读取麦克风和扬声器数据(实际由设备驱动提供)
read_microphone(mic_frame, frame_size); // 从麦克风获取数据
read_speaker(render_frame, frame_size); // 获取即将播放的对方声音
// 2. 处理参考信号(供AEC学习回声特征)
webrtc::AudioFrame render_audio;
render_audio.UpdateFrame(0, render_frame, frame_size, sample_rate,
webrtc::AudioFrame::kNormalSpeech,
webrtc::AudioFrame::kVadActive);
apm->ProcessReverseStream(&render_audio); // 传给AEC作为参考
// 3. 处理麦克风信号(依次应用AEC→AGC→ANS)
webrtc::AudioFrame mic_audio;
mic_audio.UpdateFrame(0, mic_frame, frame_size, sample_rate,
webrtc::AudioFrame::kNormalSpeech,
webrtc::AudioFrame::kVadActive);
apm->ProcessStream(&mic_audio); // 核心处理:3A算法在此生效
// 4. 处理后的信号可直接发送给对方
send_to_remote(mic_audio.data(), frame_size);
}
流程说明:
ProcessReverseStream:将扬声器信号存入AEC的缓存,用于后续回声预测。ProcessStream:按顺序调用3A算法——先AEC消除回声,再AGC调整音量,最后ANS过滤噪声,输出“干净”的声音。
阶段3:销毁资源
delete apm; // 自动释放AEC、AGC、ANS等所有子模块资源
以下是3A算法(AEC、AGC、ANS)与WebRTC音频处理流程图中模块的对应表
| 流程图模块 | 对应3A算法 | 核心源码目录/文件 | 关键功能(通俗解释) |
|---|---|---|---|
| AEC模块 | 声学回声消除(AEC) | aec3/aec3.cc aec3/echo_path_estimator.cc aec3/double_talk_detector.cc |
1. 用Render信号(扬声器即将播放的参考信号,如对方声音,供 AEC 识别 “回声特征”)作为“回声模板”,在Capture信号(麦克风采集的原始信号,含人声 + 回声 + 噪音)中识别并减去回声; 2. 双讲检测避免误删本地人声 |
| AGC模块 | 自动增益控制(AGC) | gain_control/gain_control_impl.cc gain_control/digital_agc.cc gain_control/gain_applier.cc |
1. 检测AEC处理后的信号音量; 2. 自动放大/缩小音量至目标值(如-18dBFS); 3. 平滑调整避免音量突变 |
| ANS模块 | 声学噪声抑制(ANS) | noise_suppression/noise_suppression_impl.cc noise_suppression/ns_core.cc noise_suppression/voice_activity_detector.cc |
1. 学习环境噪音特征(如空调声); 2. 减弱信号中“像噪音”的频段,保留人声; 3. 语音检测辅助判断何时更新噪声模型 |
| VAD模块(辅助) | 静音检测(依赖3A) | modules/audio_processing/voice_activity_detection/ |
1. 判断处理后的信号是否含人声; 2. 无语音时触发静音,减少无效传输(省带宽) |
补充说明:
-
流程顺序的必要性:
流程图中AEC→AGC→ANS的顺序是固定的:- 必须先消回声(AEC),否则AGC会放大回声,ANS可能误把回声当噪音处理;
- AGC在中间调整音量,避免后续ANS因音量过小而误判;
- ANS最后降噪,确保输出信号的纯净度。
-
Render信号的特殊作用:
仅AEC需要Render信号(用于回声比对),其他模块(AGC、ANS)只处理麦克风信号(Capture) -
VAD的辅助性:
VAD不直接参与“信号优化”,但依赖3A处理后的信号判断“是否有语音”,是提升传输效率的辅助模块。
总结:3A算法的核心价值
在实时语音/视频通话中,3A算法是“体验的基石”:
- 没有AEC,对方会听到自己的回声,通话变成“回音室”;
- 没有AGC,对方要么听不清,要么被突然的大声吓一跳;
- 没有ANS,嘈杂环境下的通话会变成“听噪音猜人话”。
WebRTC通过AudioProcessing类将复杂的3A算法封装成简单接口,开发者无需深入信号处理细节,只需按流程调用,就能快速实现高质量的实时音频通信——这也是WebRTC被广泛用于视频会议、语音聊天工具的重要原因。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)