3. 单通道降噪:从谱减法到 MMSE 的进阶之路
各位好,欢迎来到第三章。
单通道降噪,说白了就是只靠一个麦克风,把噪声从语音里“拎”出来。这活儿听起来简单,做起来门道可多了。我刚开始做语音增强那会儿,觉得谱减法最直观,结果一跑出来全是“音乐噪声”,那叫一个头疼。今天咱们就把这几个经典算法——谱减法、维纳滤波、MMSE-STSA,还有噪声估计的MCRA和IMCRA,一个一个捋清楚。
3.1 谱减法:最朴素的“减法”思想
谱减法的核心思想,其实特别简单:
带噪语音的幅度谱 - 噪声的幅度谱 = 干净语音的幅度谱
嗯,就像做菜时把盐放多了,再舀出来一点。但问题是,你没法精确知道到底放了多少盐。
基本公式:
|Ŝ(ω)| = |Y(ω)| - |N̂(ω)|
其中 |Y(ω)| 是带噪语音幅度谱,|N̂(ω)| 是估计的噪声幅度谱。
我在项目中遇到过一个问题:当噪声估计不准时,减出来的结果会出现负值。怎么办?
常见的做法是加个“半波整流”:
if |Ŝ(ω)| < 0:
|Ŝ(ω)| = 0 # 或者保留一个很小的值
但这样会引入“音乐噪声”——听起来像背景里有水在滴答滴答。说白了,就是频谱上出现了孤立的尖峰。
我的经验:谱减法适合噪声平稳的场景,比如空调声、风扇声。对于非平稳噪声(比如键盘敲击声),效果就很差了。
3.2 维纳滤波:从统计角度出发
维纳滤波比谱减法聪明一点。它不再简单做减法,而是计算一个“增益函数”,对每个频点进行加权。
核心公式:
H(ω) = ξ(ω) / (1 + ξ(ω))
其中 ξ(ω) 是先验信噪比(prior SNR)。
你想想看,如果某个频点信噪比很高,H(ω) 就接近1,语音几乎不变;如果信噪比很低,H(ω) 就接近0,噪声被压下去。
我个人习惯用“决策导向”的方法来估计先验信噪比:
ξ(k, m) = α * (|Ŝ(k, m-1)|² / |N̂(k, m-1)|²) + (1-α) * max(γ(k, m)-1, 0)
其中 α 通常取 0.98,γ 是后验信噪比。
注意:维纳滤波假设语音和噪声都是平稳的,且不相关。实际中语音是非平稳的,所以效果会打折扣。我曾经在车载环境下测试,维纳滤波对风噪的处理就不太理想。
3.3 MMSE-STSA:最小均方误差的“最优解”
MMSE-STSA(Minimum Mean-Square Error Short-Time Spectral Amplitude)算法,说白了就是找一个“最优”的幅度谱估计,使得估计值和真实值之间的均方误差最小。
这个算法由 Ephraim 和 Malah 在1984年提出,至今仍是单通道降噪的标杆之一。
增益函数形式:
G(ξ, γ) = (√π/2) * √(ξ/(1+ξ)) * exp(-ν/2) * [(1+ν)I₀(ν/2) + νI₁(ν/2)]
其中 ν = ξ/(1+ξ) * γ,I₀ 和 I₁ 是修正贝塞尔函数。
嗯,这个公式看着挺吓人。但实际实现时,可以用查表法或者近似公式来加速。
我的建议:如果你追求音质,MMSE-STSA 比谱减法好很多,音乐噪声明显减少。但计算量也大,嵌入式设备上要小心。
3.4 噪声估计方法:MCRA 与 IMCRA
前面所有算法都依赖一个关键输入:噪声功率谱的估计。噪声估计不准,再好的降噪算法也是白搭。
3.4.1 MCRA(最小值控制递归平均)
MCRA 的核心思想是:
- 跟踪每个频点的功率谱最小值
- 根据当前功率与最小值的比值,判断当前帧是语音还是噪声
- 如果是噪声,就更新噪声估计
具体步骤:
1. 计算平滑功率谱:S(k, m) = α * S(k, m-1) + (1-α) * |Y(k, m)|²
2. 跟踪最小值:S_min(k, m) = min(S(k, m), S_min(k, m-1))
3. 计算比值:S(k, m) / S_min(k, m)
4. 如果比值小于阈值,判定为噪声帧,更新噪声估计
我在项目中遇到过一个问题:MCRA 对语音起始段的噪声估计有延迟。因为最小值跟踪需要时间,刚开始几帧噪声估计会偏高。
3.4.2 IMCRA(改进的 MCRA)
IMCRA 是 MCRA 的改进版,主要解决了两个问题:
- 语音存在概率的平滑性:IMCRA 用了两次平滑,避免噪声估计突变
- 最小值跟踪的偏差补偿:因为最小值总是偏小的,IMCRA 加了一个偏差补偿因子
核心改进点:
1. 第一次平滑:得到初步的语音存在概率
2. 第二次平滑:基于初步概率,对噪声估计进行更精细的更新
3. 偏差补偿:将最小值乘以一个补偿因子(通常 1.5~2.0)
避坑指南:我曾经在调试 IMCRA 时,发现补偿因子设太大,噪声估计偏高,导致语音被过度抑制。后来我根据实际场景动态调整补偿因子——安静环境用 1.5,嘈杂环境用 2.0。
3.5 算法对比与选择建议
| 算法 | 音质 | 计算量 | 适用场景 |
|---|---|---|---|
| 谱减法 | 较差(音乐噪声明显) | 低 | 平稳噪声、资源受限设备 |
| 维纳滤波 | 中等 | 中 | 平稳噪声、对延迟敏感的场景 |
| MMSE-STSA | 较好 | 高 | 非平稳噪声、追求音质的场景 |
| MCRA/IMCRA | (噪声估计用) | 中高 | 所有需要噪声估计的算法 |
我个人习惯是:MMSE-STSA + IMCRA 的组合,在大多数场景下都能取得不错的效果。当然,如果你在开发低功耗设备,谱减法 + MCRA 也是可以接受的。
最后说一句:没有万能的算法。实际项目中,我经常把几种算法串起来用——先用谱减法做粗降噪,再用维纳滤波做精细处理。效果往往比单一算法好。
好了,这一章的内容就到这里。下一章我们会聊自适应滤波和回声消除,那又是另一个有意思的话题了。