AEC3 回声消除内核 · 估计回声再减掉

AEC3 是 WebRTC 的回声消除引擎。它分两级:自适应线性滤波器建模声学路径、从远端参考预测回声并减掉;残余回声抑制器再把线性滤波没除净的部分压下去。这一章讲清这两级、延迟估计、以及 AEC3 为什么是 WebRTC 音频的明珠。

作者 David更新于 第 73 篇(共 112 篇)

AEC3 回声消除内核 · 估计回声再减掉

回声问题讲清了,现在看 WebRTC 怎么消——AEC3(Acoustic Echo Canceller v3,modules/audio_processing/aec3/)。它是 APM 的明珠,用两级把回声消得干干净净。这一章拆它的核心思路(不逐行啃 DSP,而是抓住“它凭什么能消”)。

核心思路:预测回声,减掉它

AEC3 的总思路一句话:

AEC3 知道扬声器播了什么(远端参考),就用一个“模型”预测出“这段声音经声学路径漏回麦克风会是什么样”(即回声),然后从麦克风采的音里把这个预测的回声减掉**——剩下的就是干净的近端语音。** 这就是“必须同时知道播了什么和采了什么”的用处:有了远端参考(播的),预测出回声;有了近端(采的),减掉回声。

难点当然是那个“模型”——它得准确刻画看不见、还在变的声学路径。AEC3 用自适应滤波来实时逼近这条路径,并分两级处理。

第一级:自适应线性滤波

AEC3 的第一级是一个自适应线性滤波器:

线性滤波器在线学习扬声器到麦克风的声学路径(建模成一组滤波系数),用它对远端参考做滤波,得到“预测的回声”,从近端减掉。它靠观测“减完还剩多少”来持续调整系数,越学越准。 这是经典的自适应滤波(类似 NLMS 等算法):

  • 它维护一组系数,代表当前估计的声学路径(冲激响应)。
  • 每一帧,用这组系数滤波远端参考 → 预测回声 → 从近端减掉 → 得到“残差”。
  • 用残差反馈调整系数:残差里若还有回声成分,说明系数不准,就微调——路径一变(你动了手机),它就重新收敛到新路径。

线性滤波能消掉回声的线性、可预测部分——通常是回声的大头。但它有局限:扬声器 / 放大器的非线性失真、路径突变的瞬间,它消不干净,会留下残余回声。所以要有第二级。

第二级:残余回声抑制

第一级减完还剩的残余回声,交给第二级——残余回声抑制器:

抑制器在频域工作:估计“每个频段还剩多少残余回声”,据此衰减那些残余回声占主导的频段——像一个智能的、随回声动态调整的均衡器。 它不像线性滤波那样“精确相减”,而是“按比例压制”:某个频段残余回声多,就把这个频段整体压低。代价是可能连带压掉一点近端语音(那个频段的人声也被削),所以要精细——这里就要用上双讲检测:双讲时手下留情(别压太狠,保住近端语音),单讲时放心压(反正没有近端语音要保)。

两级配合:线性滤波精确消掉大部分(可预测的)回声,残余抑制兜底压掉剩下的(非线性、难预测的)回声。一“减”一“压”,把回声消到听不见,同时尽量保住近端语音。这个“精确 + 兜底”的两级架构,是现代回声消除的标准范式,AEC3 把它打磨到了很高水准。

关键辅助:延迟估计

还有一个隐藏的关键:AEC3 得知道远端参考和近端回声之间的延迟——扬声器播出的声音,过多久才漏回麦克风?这个延迟(含音频硬件缓冲 + 声学传播)因设备而异、可能几十到几百毫秒,且会变。AEC3 有专门的延迟估计,把远端参考和近端对齐——不对齐,滤波器就“预测”错时刻的回声,消不掉。延迟估计错了,回声消除全盘失效,所以它是 AEC3 稳健性的基石。

一张 AEC3 流程图

图表加载中…

小结与下一章

AEC3 消回声的思路:用远端参考预测回声、从近端减掉。两级:① 自适应线性滤波——在线学习声学路径、预测并精确相减(消可预测的大头),路径变了持续重收敛;② 残余回声抑制——频域衰减线性没除净的残余(非线性部分),配合双讲检测避免误伤近端语音。延迟估计把远近端对齐,是基石。一减一压,回声消到听不见。

回声消掉了,链条还有增益和降噪。下一章看自动增益 AGC。👉 自动增益控制。

参考资料

  • [1] libwebrtc 源码.modules/audio_processing/aec3/(echo_canceller3.cc、adaptive_fir_filter.h、residual_echo_estimator.h、echo_path_delay_estimator.h)。
  • [2] 自适应滤波(NLMS)与残余回声抑制 —— AEC 的信号处理基础。
  • [3] 关联回声问题、APM 总览。

本页目录