降噪处理之后人声像蒙了一层布,齿音和空气感消失,低频变得浑浊,这种发闷通常不是降噪算法本身不够好,而是两个参数没有配合到位:噪声剖面采样和阈值调整。噪声剖面代表当前环境中噪声的频谱形状与能量分布,阈值则决定哪些频率成分该被保留、哪些该被压制。如果剖面是在信噪比很低的静音段粗略抓取,或者阈值对所有频带一视同仁,降噪器就会把基频谐波和瞬态细节误判为噪声,造成可懂度下降和闷感。解决思路也很直接:让噪声估计跟上环境变化,让阈值具备频率感知和动态特性。

噪声剖面采样为何容易失真
很多降噪插件在初始化时会要求用户先录制一段纯噪声,例如空调声、电脑风扇声或房间底噪。这种静音段采样思路简单,但存在两个明显问题。第一,它只代表采样瞬间的噪声状态,实际录音中噪声往往不是完全平稳的,空调压缩机启停、室外车辆经过、键盘敲击等都会改变噪声谱。第二,静音段采样通常没有语音活动检测参与,如果用户开始采样时不小心录进了呼吸声或轻微动作声,噪声剖面就会混入伪噪声成分,后续降噪会把这些频率错误保留或错误压制。
改进方法之一是使用最小统计法。它的核心思想是在一个滑动时间窗口内,对每个频点持续记录幅值最小值,并把该最小值作为噪声底限。由于语音是间歇性的,长窗口内的最小值有较大概率代表纯噪声。公式可以写成 N(f,t)=min(|X(f,τ)|),其中 τ 属于 [t-W,t]。实际实现时还需要用语音存在概率修正,否则在连续说话较长时,最小值可能落到弱语音成分上,反而漏掉真正的噪声抬升。
另一种更稳健的做法是递归平均。它不直接保存一段窗口,而是根据每一帧的语音存在概率来决定噪声估计的更新速度。下面这个Python示例展示了一个简化的递归更新过程,speech_prob越接近1,噪声剖面就近似保持不动;越接近0,就越快地跟随当前幅值。
import numpy as np
def update_noise_profile(noise_old, magnitude, speech_prob, smooth=0.95):
# 动态更新系数:有语音时几乎不更新,无语音时快速跟踪噪声
alpha = smooth + (1 - smooth) * (1 - speech_prob)
noise_new = alpha * noise_old + (1 - alpha) * magnitude
return noise_new
递归平均配合最小统计,能够同时兼顾稳态底噪和非平稳噪声。它的好处是噪声剖面不会长期停留在开机时的状态,而是随着环境缓慢变化。当噪声剖面更接近真实底噪时,阈值计算才有可靠依据,这对改善降噪后发闷非常关键。
阈值调整要从固定门限转向动态增益
有了噪声剖面以后,下一步是决定每个频率成分去留的阈值。传统噪声门通常只设置一个全局dB阈值,低于阈值就静音,高于阈值就保留。这种方式在语音和噪声能量差异较大时有效,但在处理宽带噪声时会带来明显问题:语音的基频和低频谐波虽然能量较高,但在某些帧中可能只比噪声高几个dB,固定阈值一旦设置偏高,就会把这些谐波当作噪声切掉,听感立刻变闷。
更合理的做法是把阈值表示为一个与噪声剖面相关的动态量,而不是固定dB数。谱减法中的过减系数就是一个直观例子。对于每帧频谱,增益可以写成 G(f)=max(1-αN(f)/|X(f)|, G_min),其中 α 是过减系数,N(f) 是噪声幅度估计,|X(f)| 是当前帧幅度,G_min 是增益下限。当某频点信噪比低时,增益变小;信噪比高时,增益接近1。G_min 不建议设得太低,否则会产生音乐噪声和抽吸感。通过适当降低 α 并提高 G_min,可以保留更多中低频成分,减轻闷感。
还可以引入软阈值和多频带独立门限。软阈值不是直接截断,而是让低于阈值的成分按比例衰减。下面这段代码演示了频点级软门限增益计算,其中 ratio 控制阈值相对噪声幅度的倍数,floor_db 设置保底增益。
import numpy as np
def soft_gate_gain(magnitude, noise_mag, floor_db=-18.0, ratio=2.0):
floor_linear = 10 ** (floor_db / 20)
threshold = ratio * noise_mag + floor_linear
gain = np.ones_like(magnitude)
mask = magnitude < threshold
gain[mask] = np.maximum(floor_linear, magnitude[mask]) / np.maximum(threshold[mask], 1e-10)
return gain
多频带门限的意义在于,不同频段的噪声能量和语音贡献差异很大。低频噪声通常更强,但语音的基频也集中在低频;如果对低频使用和高频一样的阈值,很容易造成基频被误伤。实现时可以先对频谱做子带划分,例如按倍频程分成8到16个频带,每个频带根据该带内的噪声剖面和语音存在概率独立计算阈值,再做平滑合并。这样处理后人声厚度会被保留,高频空气感也不会被无差别削掉。
工程落地时的谐波保护与听感调优
即使噪声剖面和阈值都设计合理,实际听感仍可能出现发闷或抽吸,这时需要加入谐波保护。语音和乐器的听感很大程度上依赖谐波结构,如果基频和若干个谐波被降噪器分别处理,某些谐波被衰减、某些被保留,就会造成音色空洞和闷感。谐波保护的思路是先估计当前帧的基频,然后在基频整数倍频率附近放宽阈值,给谐波区域更高的增益下限。这样不仅能保护人声厚度,也能减少音乐类素材的损伤。
增益平滑同样不可忽略。如果每一帧的增益剧烈变化,降噪后的信号会出现类似噪声门的开合声,这种抽吸感会被耳朵误判为发闷或失真。工程上通常会用一阶平滑对增益做帧间滤波,attack时间设短一些,release时间设长一些。例如语音处理中attack约5到15毫秒,release约50到150毫秒,能兼顾响应速度与听感自然度。平滑后的增益再作用到复数谱或实数幅度上,可以减少相位断裂。
验证阶段建议先做A/B对比,用一段包含低频人声、齿音和房间底噪的素材进行降噪,重点听中低频是否还有支撑感、齿音是否清晰、结尾是否有抽吸。频谱分析上可以观察200到800赫兹区域的衰减程度,如果该区域整体被压低超过6个dB,说明阈值或过减系数仍然偏大。参数调优时先固定噪声剖面更新速度,再逐步降低全局过减系数,最后针对低频段手动提升增益下限。处理实时音频时还要注意延迟和计算量,递归平均配合子带阈值通常可以做到帧长为20毫秒以内的实时处理。
总体来看,降噪后发闷不是单一参数问题,而是噪声估计与阈值决策共同作用的结果。把静态剖面换成动态估计,把固定门限换成频率相关的软阈值,再加上谐波保护和增益平滑,通常能在不明显增加残留噪声的前提下恢复自然音色。关键还是要根据素材类型和听感反馈反复微调,而不是盲目追求降噪深度。