第一章:抗噪基础——噪声来源与性能评估

各位同行,欢迎来到《语音交互系统抗噪性能调优手册》的第一章。

做语音抗噪这么多年,我最大的感触是:很多人一上来就调算法,却连噪声从哪来的都没搞清楚。这就像医生看病,连病因都没查明白就开药方,能治好才怪。

所以这一章,我们先打好基础。我会带你梳理噪声的三大来源,讲清楚几个核心指标,最后给出一套基线测试方法。嗯,这些都是我踩过坑之后总结出来的经验。

1.1 噪声来源分类

语音交互系统里的噪声,说白了就三类:环境噪声、结构噪声、电噪声。我分别说一下。

1.1.1 环境噪声

这是最常见的,也是大家最先想到的。比如马路上汽车喇叭声、咖啡馆里的人声嘈杂、办公室的空调声、家里的电视声……这些都属于环境噪声。

我个人习惯把环境噪声分成两类:

  • 稳态噪声:像空调、风扇这种,频谱相对稳定,处理起来其实不难。
  • 非稳态噪声:像关门声、突然的说话声、狗叫声,这种突发性的噪声最难搞。我在项目中遇到过最头疼的就是会议室里突然有人咳嗽,算法直接懵了。

1.1.2 结构噪声

这个很多人会忽略。结构噪声是指设备本身或与设备接触的物体产生的振动噪声。

举个例子:你把手机放在桌子上,对方说话时,声音通过桌面传导到麦克风,这就是结构噪声。还有设备内部的马达振动、按键声、触摸屏的反馈声……

避坑指南:我曾经做过一个智能音箱项目,测试时发现底噪特别大,查了半天才发现是音箱底部的橡胶垫太硬,和桌面产生了共振。换了个软垫,底噪直接降了5dB。所以结构噪声往往藏在细节里。

1.1.3 电噪声

电噪声来自电路本身。比如电源纹波、数字电路开关噪声、ADC量化噪声等。

你想想看,麦克风采集到的信号,经过放大器、ADC、数字信号处理……每一步都会引入电噪声。尤其是低端硬件,电噪声可能比环境噪声还大。

我记得有一次调试一个车载语音系统,发现信噪比始终上不去。后来用示波器一测,发现电源纹波高达50mV,直接耦合到了音频信号里。换了LDO之后,问题就解决了。

1.2 抗噪性能核心指标

搞清楚了噪声来源,接下来就要知道怎么衡量抗噪效果。我常用的指标有三个:SNR、STOI、PESQ。它们各有侧重。

指标 全称 衡量什么 我的使用场景
SNR 信噪比 信号与噪声的能量比 快速评估,调参时看趋势
STOI 短时客观可懂度 语音的可懂度 评估人耳能不能听懂
PESQ 感知语音质量评估 语音的听觉质量 最终验收,贴近主观感受

1.2.1 SNR(信噪比)

SNR是最基础的指标。公式很简单:SNR = 10 * log10(信号能量 / 噪声能量),单位是dB。

但这里有个坑:SNR高不代表语音质量好。为什么?因为SNR只算能量比,不关心噪声的频谱分布。比如一个算法把噪声能量压低了,但同时也把语音的高频细节削没了,SNR可能还是高的,但听起来就是闷闷的。

所以我一般把SNR当作快速筛选指标。调参时先看SNR有没有提升,有的话再往下看STOI和PESQ。

1.2.2 STOI(短时客观可懂度)

STOI衡量的是语音的可懂度——说白了就是你能不能听清对方在说什么。它的取值范围是0到1,越接近1越好。

STOI对语音的时频结构比较敏感。如果算法把语音的某些频段破坏了,STOI会明显下降。我在项目中遇到过一种情况:SNR提升了3dB,但STOI反而下降了0.05。后来发现是降噪算法把清辅音(比如/s/、/sh/)给误杀了,导致可懂度变差。

小技巧:STOI对噪声类型比较敏感。对于非稳态噪声,STOI的下降会比SNR更明显。所以如果你处理的是突发噪声,建议优先看STOI。

1.2.3 PESQ(感知语音质量评估)

PESQ是ITU-T P.862标准定义的指标,它模拟人耳的听觉感知,给出一个-0.5到4.5的分数。分数越高,语音质量越好。

PESQ是我做最终验收时必看的指标。因为它最贴近主观听感。但PESQ也有缺点:计算量大,而且对非线性处理(比如噪声抑制)的评估不太准确。

我记得有一次,一个降噪算法在PESQ上得了4.2分,但实际听感却很差,有严重的音乐噪声。后来查资料才知道,PESQ对音乐噪声不敏感。所以不要迷信单一指标,最好三个指标结合起来看。

1.3 调优前的基线测试方法

在开始调优之前,一定要先做基线测试。不然你都不知道自己调得是好是坏。我一般按以下步骤来:

1.3.1 准备测试数据

测试数据要覆盖各种噪声场景。我建议至少准备以下类型:

  • 纯净语音:至少20条,男女各半,内容覆盖不同音素
  • 噪声数据:至少5种噪声(白噪声、粉红噪声、咖啡馆噪声、马路噪声、办公室噪声)
  • 混合数据:将纯净语音和噪声按不同SNR(0dB、5dB、10dB、15dB)混合

我个人习惯用NOISEX-92数据库里的噪声,再加上自己录的一些真实场景噪声。

1.3.2 搭建测试流程

测试流程要标准化,不然结果没法对比。我一般用Python写一个测试脚本:

import numpy as np
import soundfile as sf
from pystoi import stoi
from pesq import pesq

def baseline_test(clean_file, noisy_file, fs=16000):
    # 读取音频
    clean, _ = sf.read(clean_file)
    noisy, _ = sf.read(noisy_file)
    
    # 计算SNR
    signal_power = np.mean(clean ** 2)
    noise_power = np.mean((noisy - clean) ** 2)
    snr = 10 * np.log10(signal_power / noise_power)
    
    # 计算STOI
    stoi_score = stoi(clean, noisy, fs, extended=False)
    
    # 计算PESQ
    pesq_score = pesq(fs, clean, noisy, 'nb')
    
    return snr, stoi_score, pesq_score

# 示例:测试一条数据
snr, stoi_score, pesq_score = baseline_test('clean.wav', 'noisy.wav')
print(f'SNR: {snr:.2f} dB, STOI: {stoi_score:.3f}, PESQ: {pesq_score:.2f}')

1.3.3 记录基线数据

把所有测试结果记录到一个表格里,作为后续调优的参考。我一般用CSV格式:

噪声类型 输入SNR (dB) 输入STOI 输入PESQ
白噪声 0 0.45 1.23
白噪声 5 0.62 1.89
咖啡馆噪声 0 0.38 1.05
咖啡馆噪声 5 0.55 1.67
重要提醒:基线测试一定要用相同的测试数据相同的测试流程。我见过有人换了测试数据,结果调优效果看起来很好,其实只是数据不同导致的。所以测试流程一定要固定下来。

1.3.4 分析基线结果

拿到基线数据后,不要急着调优。先分析一下:

  • 哪个噪声场景最差?是白噪声还是非稳态噪声?
  • 哪个指标最差?是SNR低,还是STOI低?
  • 有没有明显的异常值?比如某条数据PESQ特别低,可能是录音有问题。

我曾经遇到过一个项目,基线测试发现所有数据在0dB SNR下STOI都低于0.3。这说明原始信号的可懂度已经非常差了,单纯靠降噪算法很难提升。后来我们改用了麦克风阵列,才解决了问题。所以基线测试也能帮你判断硬件是否需要升级

好了,第一章的内容就到这里。总结一下:

  • 噪声来源要搞清楚,环境、结构、电路,一个都不能漏
  • 三个指标各有侧重,SNR看能量,STOI看可懂度,PESQ看质量
  • 基线测试是调优的起点,一定要标准化、可复现

下一章,我会讲传统降噪算法,包括谱减法、维纳滤波、自适应滤波这些经典方法。到时候我会结合项目经验,告诉你哪些方法好用,哪些是坑。

咱们下章见。