rnnoise的主要函数rnnoise_process_frame中首先是对输入的信号做biquad滤波。
biquad Filter
双二阶滤波器,wiki介绍在这里
它是一种IIR filter
双二阶滤波器系数a1,a2,b0,b1,b2公式如下
一般运算使用如下公式:
rnnoise源码中的双二阶计算函数是上述公式的实现,但是加入了调节参数mem。该参数从训练模型中获取
函数源码如下
/**
* @param y 为输出信号
* @param mem为调节参数,该参数从训练模型中获取
* @param x为输入信号
* @param b biquad系数b值
* @param a biquad系数a值
* @param N x信号数组长度
**/
static void biquad(float *y, float mem[2], const float *x, const float *b, const float *a, int N) {
int i;
for (i=0;i<N;i++) {
float xi, yi;
xi = x[i];
yi = x[i] + mem[0];
mem[0] = mem[1] + (b[0]*(double)xi - a[0]*(double)yi);
mem[1] = (b[1]*(double)xi - a[1]*(double)yi);
y[i] = yi;
}
}
biquad滤波器的作用
通过配置合适的系数a和b,可以让biquad滤波器过滤掉信号中的高频噪音信号。那么如何获取系数a和b的值呢?
rnnoise中biquad系数a值与b值
从rnnoise源码中可以看到,这个系数是在源码中hard code的。如下图。
笔者实验发现,如果修改了这个值,滤波效果会显著使源信号失真。可能这个值是成熟的经验值。所以我们就沿用这个准备好的系数。
这里的mem系数是什么作用呢?
为了验证这个系数的作用,笔者做了个实验。
首先模拟了一个信号,如下
将mem值设置为{0,0},然后执行biquad滤波。可以看到波形基本没变。(这里提一下啊,如果a和b值不恰当,这里波形会严重变样),只是部分点y值略有不同
现在将mem调整为{0.5,0}
将mem调整为{0,0.5}
将mem调整为{-0.5,0}
将mem调整为{0,-0.5}
将mem调整为{0.5,-0.5}
从这个实验看出
- 第一个值和第二个值作用似乎一样,
- 符号对信号正向偏移和负向便宜有作用