语音算法里的平滑滤波器:从阶跃响应理解一阶和二阶滤波器的响应时间

在语音算法里,我们经常会对某些变量进行平滑处理,不要让变量变化得太突然,比如语音能量、噪声估计、增益曲线、VAD 判决概率、AGC 增益等,如果不进行平滑变量往往会抖得很厉害。

本文主要从阶跃响应的角度跟大家一起理解平滑滤波器的响应时间、相关参数和平滑效果。

本文和仿真代码同步发在个人博客网站 VoxWorking · 声学与音频知识平台,网站定期更新音频处理、语音处理和声学相关知识,欢迎大家浏览交流~

1. 阶跃响应是什么

假设某个控制参数原来是 0,突然变成 1。如果不做平滑,输出也会立刻从 0 跳到 1;如果加了平滑滤波器,输出不会马上到 1,而是慢慢靠近 1。这个从旧状态过渡到新状态的过程,就是阶跃响应。

在语音算法里,我们会关注某个被控变量平滑程度如何,多长时间能跟上变化,跟阶跃响应直接相关。

2. 一阶平滑滤波器

语音处理中最常见的一阶平滑形式是:

y[n] = alpha * y[n-1] + (1 - alpha) * x[n]

其中 x[n] 是当前输入,y[n] 是平滑后的输出,alpha 是平滑系数。

alpha 越接近 1,输出越平滑,但响应越慢;alpha 越小,输出越灵敏,但抖动也越明显。如果输入是一个从 0 跳到 1 的阶跃信号,那么一阶平滑滤波器的输出大致是指数上升,也表明了一阶平滑开始变化快,越接近目标越慢:

y[n] = 1 - alpha^n

常见的响应时间可以理解成:到达 63.2% / 90% / 95% 的响应时间。另外注意如果算法是按帧处理的,比如每帧 10 ms,那么响应时间还要乘以帧长,上式中的n是帧数n,几十帧的平滑过程,实际可能是几百毫秒。

基于上式我们可以计算响应时间与帧数之间的关系:

n = log(1 - target) / log(alpha)

假如 target = 0.9,表示到达最终值的 90%,那么则有 n90 = log(0.1) / log(alpha)

3. 不对称的攻击时间和释放时间

实际语音算法里,因为在变量上升段和下降段的平滑要求不一样,经常使用不对称的攻击时间和释放时间,也就是上升和下降用不同的平滑系数。比如:

if x[n] > y[n-1]:
    alpha = alpha_attack
else:
    alpha = alpha_release

y[n] = alpha * y[n-1] + (1 - alpha) * x[n]

其中 attack 可以理解为“跟上上升的速度”,release 可以理解为“跟上回落的速度”。可以理解成平滑在设计一种时间行为。

4. 二阶平滑滤波器

除了一阶平滑,二阶低通滤波器也经常用来做更强的平滑,比如一个二阶 IIR 低通滤波器可以写成:

y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2]
     - a1*y[n-1] - a2*y[n-2]

相比一阶滤波器,二阶滤波器有更强的频率选择性,可以更明显地压制快速抖动。

另外注意,对二阶低通来说,截止频率和响应时间关系很直接:截止频率越低,滤波越平滑,阶跃响应越慢;截止频率越高,响应越快,但对快速抖动的抑制也会变弱。工程上可以理解成二阶低通滤波器截止频率决定了滤波器的响应速度。

但二阶滤波器也可能会有以下问题:阶跃响应可能出现超调;参数设置不合适时可能有振铃;响应更平滑,但延迟也可能更明显;对系数量化和稳定性更敏感。它更适合用在需要更强平滑、并且能接受一定响应延迟的场景。

5. 小结

语音算法里的平滑滤波器,本质上是在控制参数的时间行为。一阶滤波器简单稳定,适合大多数控制量平滑。二阶滤波器可以提供更强的平滑能力,但也要注意超调、振铃和延迟。在做语音算法时,可以先考虑清楚“这个参数发生变化后,我希望它在多少毫秒内跟上?”,然后有这个响应时间反推平滑参数,这样更具有物理意义。平滑滤波器的关键是找到响应速度和稳定性之间的平衡。