3. 降噪算法基础回顾:经典谱减法、维纳滤波、自适应滤波(LMS/NLMS)原理与适用场景

各位同学,欢迎来到第三章。在咱们真正上手高通平台之前,我觉得有必要把降噪算法的基础再过一遍。你可能会说:“这些算法我都学过啊。” 嗯,我理解。但实际部署的时候,你会发现书本上的知识和芯片上的表现,有时候是两码事。

这一章,我们聚焦三个最经典的降噪算法:谱减法、维纳滤波、自适应滤波(LMS/NLMS)。我会结合我在高通平台上踩过的坑,帮你理清它们的原理和适用场景。

核心观点:没有最好的算法,只有最合适的场景。选错算法,再强的DSP也救不了你。
三种经典降噪算法核心逻辑对比 谱减法 噪声估计 → 幅度谱相减 维纳滤波 MMSE准则 → 频域滤波器 自适应滤波(LMS/NLMS) 梯度下降 → 时域系数更新 适用:稳态噪声 局限:音乐噪声 适用:平稳噪声 局限:需要先验知识 适用:非平稳/回声 局限:收敛速度/稳定性 高通Hexagon DSP关注点:MIPS预算、内存带宽、定点精度、实时性

3.1 谱减法:最直观的“切噪声”

谱减法的思路非常直接:带噪语音的幅度谱 - 噪声幅度谱 = 干净语音幅度谱。说白了,就是假设噪声是加性的,我们只要知道噪声长什么样,把它减掉就行了。

我个人习惯把谱减法比作“用橡皮擦擦掉背景”。你拿一张带噪的图,知道背景是什么颜色,直接擦掉。但问题在于——你永远无法精确知道每一帧的噪声。我们通常用无声段来估计噪声,然后假设它短时间内不变。

我的经验:谱减法在高通平台上实现时,最头疼的是“音乐噪声”(Musical Noise)。就是那种听起来像流水一样的残留噪声。我曾经在一个车载项目里,因为谱减法参数没调好,被客户投诉“声音像在水里说话”。后来我加了过减因子和频谱平滑,才压下去。

核心公式:

|Ŝ(ω)|² = |Y(ω)|² - α · |N̂(ω)|²

其中:
  Y(ω)  = 带噪语音频谱
  N̂(ω) = 估计的噪声频谱
  α     = 过减因子(α > 1 可减少音乐噪声)

适用场景:

  • 稳态噪声:风扇声、空调声、发动机怠速声。这类噪声频谱变化慢,容易估计。
  • 低信噪比环境:谱减法在 SNR 低于 0dB 时效果会急剧下降。
  • 对延迟敏感的应用:谱减法延迟低,适合实时通信。
避坑指南:我曾经在 Hexagon DSP 上实现谱减法时,发现定点化后的噪声估计偏差很大。原因是噪声更新时的平滑因子用了太小的小数,导致精度丢失。建议用 Q15 格式,并注意溢出保护。

3.2 维纳滤波:最小均方误差下的最优解

维纳滤波的思路比谱减法更“数学”。它不直接减幅度谱,而是设计一个滤波器,让输出信号与干净信号的均方误差最小。你想想看,这其实是在找一个最优的“折中方案”。

我记得第一次在里看到维纳滤波的推导时,被那一堆自相关矩阵搞得头晕。但实际用起来,它的核心就是一句话:根据信噪比动态调整滤波器的增益。信噪比高的频段,增益接近1;信噪比低的频段,增益压低。

核心公式:

H(ω) = Pₛ(ω) / (Pₛ(ω) + Pₙ(ω))

其中:
  Pₛ(ω) = 干净语音的功率谱
  Pₙ(ω) = 噪声的功率谱
  H(ω)  = 维纳滤波器的频域响应

你看,这个公式很优雅。但问题来了——我们不知道 Pₛ(ω)。实际中,我们用 Pᵧ(ω) - Pₙ(ω) 来近似,或者用决策导向法(Decision-Directed)来估计先验信噪比。

对比维度 谱减法 维纳滤波
数学基础 幅度谱相减 MMSE 最优滤波
残留噪声 音乐噪声明显 残留噪声更自然
语音失真 较大 较小(参数调好时)
计算复杂度 低 中
高通平台适配 容易,MIPS 低 需要查表或近似计算
我的建议:如果你在 Hexagon DSP 上做维纳滤波,千万不要直接算除法。DSP 的除法指令很慢。我一般用查表法或者多项式近似来算 H(ω)。另外,先验信噪比的估计用 Decision-Directed 方法,效果比直接估计好很多。

3.3 自适应滤波(LMS/NLMS):动态追踪噪声

前面两种算法都假设噪声是平稳的。但现实世界哪有那么听话?你走在马路上,车声、风声、人声,噪声一直在变。这时候就需要自适应滤波了。

自适应滤波的核心思想是:让滤波器系数随着输入信号的变化而自动调整。最经典的就是 LMS(最小均方)算法。

LMS 算法步骤:

  1. 滤波输出:y(n) = wᵀ(n) · x(n)
  2. 误差计算:e(n) = d(n) - y(n)
  3. 系数更新:w(n+1) = w(n) + μ · e(n) · x(n)

其中 μ 是步长因子。步长越大,收敛越快,但稳态误差也越大。步长越小,越稳定,但收敛慢。这是个典型的“鱼和熊掌”问题。

NLMS(归一化 LMS) 是对 LMS 的改进。它把步长用输入信号的功率归一化,解决了 LMS 对输入信号幅度敏感的问题。

// NLMS 系数更新(伪代码)
for each sample n:
    y(n) = dot(w, x);           // 滤波输出
    e(n) = d(n) - y(n);         // 误差
    power = dot(x, x) + eps;    // 输入功率 + 防零除
    mu_normalized = mu / power; // 归一化步长
    w = w + mu_normalized * e(n) * x; // 更新系数
关键点:NLMS 的 mu 值通常取 0.1 ~ 0.5。mu 太大,滤波器会发散;mu 太小,收敛慢到让你怀疑人生。

适用场景:

  • 回声消除(AEC):自适应滤波是 AEC 的核心。我在高通平台做 AEC 时,用的就是 NLMS 的变种。
  • 主动降噪(ANC):需要实时追踪噪声路径的变化。
  • 非平稳噪声抑制:比如会议室里突然有人翻文件、咳嗽。
避坑指南:我曾经在一个项目里,LMS 滤波器在 Hexagon DSP 上跑着跑着就发散了。查了两天才发现是定点溢出。LMS 的系数更新涉及乘法累加,很容易超过 Q15 的范围。解决方案是:用 Q31 做内部累加,最后再截断回 Q15。或者直接用浮点模拟器先验证,再转定点。

3.4 三种算法的选择策略

好了,三种算法都讲完了。你可能会问:“那我到底该用哪个?” 嗯,这个问题没有标准答案。我根据在高通平台上的实战经验,给你一个选择参考:

场景 推荐算法 理由
稳态噪声(风扇、空调) 谱减法 简单、低延迟、MIPS 低
平稳噪声 + 高语音质量要求 维纳滤波 残留噪声更自然,语音失真小
非平稳噪声 / 回声消除 NLMS 自适应滤波 能动态追踪噪声变化
低功耗嵌入式平台 谱减法 / 简化维纳 计算量小,适合 Hexagon 小核
多麦克风阵列 自适应滤波 + 波束成形 空间信息 + 自适应能力
我的习惯:在实际项目中,我经常把谱减法和维纳滤波结合起来用。先用谱减法做粗降噪,再用维纳滤波做精细处理。这样既能控制音乐噪声,又能保证语音质量。当然,代价就是 MIPS 翻倍。在 Hexagon DSP 上,你需要仔细算好预算。