2. 降噪滤波器基础
各位同学,咱们今天聊聊降噪算法的几个老前辈。说实话,我在做DSP移植的头三年,跟这几位打交道的时间比跟家人还多。它们虽然年纪不小,但直到今天,很多商用产品里依然能看到它们的身影。
为什么?因为简单、有效、实时性好。你想想看,在资源受限的嵌入式平台上,有时候一个几百行的谱减法,比一个几万行的深度学习模型更管用。这不是说深度学习不好,而是说——选对工具比选贵的工具更重要。
谱减法:最直观的降噪思路
谱减法的思路特别朴素:既然噪声是叠加在语音上的,那我先估算出噪声的频谱,然后从带噪信号的频谱里把它减掉,不就干净了吗?
我刚开始做语音降噪时,第一个实现的就是谱减法。代码写起来快,跑起来也快。但有个坑——减过头了就会出现「音乐噪声」,听起来像水烧开时的咕噜声,特别刺耳。
核心公式:
|S(ω)|² = |Y(ω)|² - α · |N(ω)|²
其中 α 是过减因子,一般取 1.0~2.5。α 越大,降噪越狠,但音乐噪声也越明显。
谱减法的流程其实就三步:
- 噪声估计——用前几帧的静音段估算噪声谱
- 谱相减——按公式做减法,负值置零或取半波整流
- 相位还原——保留原始相位,用减完的幅度谱做IFFT
这里有个细节:相位为什么不处理?因为人耳对相位不敏感,保留原始相位能省掉大量计算。我在一个Cortex-M4的项目里,就靠这个技巧把处理延迟从15ms压到了8ms。
避坑指南:我曾经在一个对讲机项目里直接用标准谱减法,结果对方反馈「声音像在水里说话」。后来发现是噪声估计更新太慢,导致非平稳噪声没被减掉。解决办法是把噪声估计的更新周期从1秒缩短到200ms,同时加了一个VAD(语音活动检测)来防止语音段污染噪声估计。
维纳滤波:从统计角度做降噪
维纳滤波跟谱减法不同。它不直接做减法,而是算一个增益函数,对每个频点做加权。说白了,信噪比高的频点多保留,信噪比低的频点压下去。
我个人习惯把维纳滤波理解成「智能音量旋钮」——每个频点都有一个独立的旋钮,旋钮的位置由当前信噪比决定。
| 对比项 | 谱减法 | 维纳滤波 |
|---|---|---|
| 数学基础 | 确定性相减 | 最小均方误差估计 |
| 输出质量 | 可能有音乐噪声 | 更平滑,噪声残留少 |
| 计算量 | 低(一次FFT+减法) | 中等(需计算功率谱密度) |
| 实时性 | 优秀 | 良好 |
| 适用场景 | 平稳噪声、资源受限 | 需要更高语音质量 |
维纳滤波的增益函数长这样:
H(ω) = Ps(ω) / (Ps(ω) + Pn(ω))
其中 Ps 是语音功率谱,Pn 是噪声功率谱。当 Pn 远大于 Ps 时,H 趋近于 0,该频点被抑制;反之则趋近于 1,保留原样。
嗯,这里要注意:实际实现时,Ps 和 Pn 都是估计值,估计不准就会导致语音失真。我在一个车载免提项目里,试过用维纳滤波做后处理,结果发现风噪场景下语音变得「闷闷的」。后来加了一个先验信噪比平滑,才把这个问题解决。
自适应滤波:动态跟踪噪声变化
自适应滤波跟前面两种算法最大的区别是——它能自己调整参数。你不需要提前知道噪声的统计特性,算法会通过误差信号自动更新滤波器系数。
最经典的是LMS(最小均方)算法,更新公式简单到令人发指:
w(n+1) = w(n) + μ · e(n) · x(n)
μ 是步长因子,e(n) 是误差信号,x(n) 是输入信号。就这么一行,就能实现自适应噪声对消。
我在一个助听器芯片的移植项目中,用LMS做自适应反馈抑制。当时芯片的RAM只有32KB,我硬是把滤波器阶数压到了64阶,步长用定点Q15格式实现,最终跑在16kHz采样率下,延迟不到3ms。
经验之谈:自适应滤波的步长选择是个技术活。步长太大,收敛快但稳态误差大;步长太小,收敛慢且跟不上噪声变化。我一般用归一化LMS(NLMS),把步长除以输入信号的功率,这样对输入幅度变化不敏感。具体实现时,分母加一个小常数防止除零。
算法复杂度与实时性要求
做DSP移植,最怕的就是算法跑不起来。咱们得算一笔账:
假设采样率16kHz,帧长256点,帧移128点(50%重叠)。每帧的处理时间必须小于帧移对应的时间——也就是128/16000 = 8ms。如果处理时间超过8ms,就会出现丢帧或卡顿。
三种算法的典型计算量对比如下:
| 算法 | 每帧乘加次数 | 典型延迟 | 适合平台 |
|---|---|---|---|
| 谱减法 | ~2K | 1-3ms | MCU、低端DSP |
| 维纳滤波 | ~5K | 2-5ms | 中端DSP、ARM |
| 自适应滤波(LMS) | ~N·M | 3-10ms | DSP、FPGA |
N是滤波器阶数,M是每帧采样点数。64阶LMS在256点帧长下,每帧大约需要16K次乘加——比谱减法多了8倍。
所以我的建议是:先评估硬件资源,再选算法。如果主频只有几十MHz,RAM不到64KB,老老实实用谱减法。如果有个300MHz以上的DSP,再考虑维纳滤波或自适应滤波。
三种算法的知识体系
下面这张图是我自己整理的,把三种算法的核心逻辑和适用场景串在了一起。你看完应该能快速建立起整体认知。
从这张图你能看到,三种算法虽然思路不同,但都依赖FFT和帧处理。这也是为什么我在后续章节会花大量篇幅讲FFT的DSP优化——它是所有降噪算法的基石。
好了,这一章的内容就到这里。三种算法各有千秋,没有绝对的好坏。关键是你得清楚自己的应用场景——是追求极低延迟?还是追求最佳语音质量?还是需要动态适应噪声环境?想清楚这个,选算法就不难了。