降噪算法基础:经典降噪算法概述

各位同学,咱们今天聊聊降噪算法的几个老前辈。说实话,我在做DSP移植的头三年,跟这几位打交道的时间比跟家人还多。它们虽然年纪不小,但直到今天,很多商用产品里依然能看到它们的身影。

为什么?因为简单、有效、实时性好。你想想看,在资源受限的嵌入式平台上,有时候一个几百行的谱减法,比一个几万行的深度学习模型更管用。这不是说深度学习不好,而是说——选对工具比选贵的工具更重要。

谱减法:最直观的降噪思路

谱减法的思路特别朴素:既然噪声是叠加在语音上的,那我先估算出噪声的频谱,然后从带噪信号的频谱里把它减掉,不就干净了吗?

我刚开始做语音降噪时,第一个实现的就是谱减法。代码写起来快,跑起来也快。但有个坑——减过头了就会出现「音乐噪声」,听起来像水烧开时的咕噜声,特别刺耳。

核心公式:

|S(ω)|² = |Y(ω)|² - α · |N(ω)|²

其中 α 是过减因子,一般取 1.0~2.5。α 越大,降噪越狠,但音乐噪声也越明显。

谱减法的流程其实就三步:

  1. 噪声估计——用前几帧的静音段估算噪声谱
  2. 谱相减——按公式做减法,负值置零或取半波整流
  3. 相位还原——保留原始相位,用减完的幅度谱做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,再考虑维纳滤波或自适应滤波。

三种算法的知识体系

下面这张图是我自己整理的,把三种算法的核心逻辑和适用场景串在了一起。你看完应该能快速建立起整体认知。

经典降噪算法知识体系 谱减法 核心:|S|² = |Y|² - α|N|² 优点:计算量小,实现简单 缺点:音乐噪声明显 适用:平稳噪声、资源受限 维纳滤波 核心:H = Ps / (Ps + Pn) 优点:语音质量好,噪声平滑 缺点:需准确估计功率谱 适用:需要高语音质量场景 自适应滤波 核心:w(n+1)=w(n)+μ·e·x 优点:动态跟踪噪声变化 缺点:计算量大,收敛问题 适用:非平稳噪声、回声消除 共同基础:FFT + 帧处理 + 重叠保留法 实时性要求:处理时间 < 帧移时间(如8ms@16kHz) 选型建议:先评估硬件资源,再选算法 说明

从这张图你能看到,三种算法虽然思路不同,但都依赖FFT和帧处理。这也是为什么我在后续章节会花大量篇幅讲FFT的DSP优化——它是所有降噪算法的基石。

好了,这一章的内容就到这里。三种算法各有千秋,没有绝对的好坏。关键是你得清楚自己的应用场景——是追求极低延迟?还是追求最佳语音质量?还是需要动态适应噪声环境?想清楚这个,选算法就不难了。