文章

一种二阶滤波器的设计方式

参考DAFX_Digtial_Audio_Effects这本书,一个二阶滤波器的设计为:

公式

 b0b1b2a1a2
Lowpass$\frac{K^2Q}{K^2Q+K+Q}$$\frac{2K^2Q}{K^2Q+K+Q}$$\frac{K^2Q}{K^2Q+K+Q}$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$\frac{K^2Q-K+Q}{K^2Q+K+Q}$
Highpass$\frac{Q}{K^2Q+K+Q}$$-\frac{2Q}{K^2Q+K+Q}$$\frac{Q}{K^2Q+K+Q}$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$\frac{K^2Q-K+Q}{K^2Q+K+Q}$
Bandpass$\frac{K}{K^2Q+K+Q}$$0$$-\frac{K}{K^2Q+K+Q}$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$\frac{K^2Q-K+Q}{K^2Q+K+Q}$
Bandreject$\frac{Q(1+K^2)}{K^2Q+K+Q}$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$\frac{Q(1+K^2)}{K^2Q+K+Q}$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$\frac{K^2Q-K+Q}{K^2Q+K+Q}$
Allpass$\frac{K^2Q-K+Q}{K^2Q+K+Q}$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$1$$\frac{2Q(K^2-1)}{K^2Q+K+Q}$$\frac{K^2Q-K+Q}{K^2Q+K+Q}$

$K=tan(\pi fc/fs) \qquad fc为中心频率,fs为采样率$

对于低通滤波器和高通滤波器,当$Q=\frac{1}{\sqrt{2}}$,滤波器最大平坦到截至频率,对于较低的Q,有着较大的通带衰减,对于较高的Q,在Fc的地方幅度会上升。

对于带通和带阻滤波器,Q与带宽有关,$Q=\frac{f_c}{f_b}$,与带宽是反相关的。

这里会在设定的中心频率和带宽之间-3dB的增益。

matlab代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function [b,a] = Lowpass(K, Q)

b0=K^2*Q/(K^2*Q+K+Q);
b1=2*K^2*Q/(K^2*Q+K+Q);
b2=K^2*Q/(K^2*Q+K+Q);

a0=1;
a1=2*Q*(K^2-1)/(K^2*Q+K+Q);
a2=(K^2*Q-K+Q)/(K^2*Q+K+Q);

b=[b0,b1,b2];
a=[a0,a1,a2];
end


function [b,a] = Highpass(K, Q)

b0=Q/(K^2*Q+K+Q);
b1=-2*Q/(K^2*Q+K+Q);
b2=Q/(K^2*Q+K+Q);

a0=1;
a1=2*Q*(K^2-1)/(K^2*Q+K+Q);
a2=(K^2*Q-K+Q)/(K^2*Q+K+Q);

b=[b0,b1,b2];
a=[a0,a1,a2];

end


function [b,a] = Bandpass(K, Q)

b0=K/(K^2*Q+K+Q);
b1=0;
b2=-K/(K^2*Q+K+Q);

a0=1;
a1=2*Q*(K^2-1)/(K^2*Q+K+Q);
a2=(K^2*Q-K+Q)/(K^2*Q+K+Q);

b=[b0,b1,b2];
a=[a0,a1,a2];

end


function [b,a] = Bandreject(K, Q)

b0=(Q*(1+K^2))/(K^2*Q+K+Q);
b1=(2*Q*(K^2-1))/(K^2*Q+K+Q);
b2=(Q*(1+K^2))/(K^2*Q+K+Q);

a0=1;
a1=2*Q*(K^2-1)/(K^2*Q+K+Q);
a2=(K^2*Q-K+Q)/(K^2*Q+K+Q);

b=[b0,b1,b2];
a=[a0,a1,a2];

end

C语言代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
void Lowpass(double K, double Q, double *b, double *a)
{
    if ((b == NULL) || (a == NULL))
    {
        return;
    }
    double T = K * K * Q + K + Q;

    b[0] = K * K * Q / T;
    b[1] = 2 * K * K * Q / T;
    b[2] = K * K * Q / T;

    a[0] = 1;
    a[1] = 2 * Q * (K * K - 1) / T;
    a[2] = (K * K * Q - K + Q) / T;
}

void Highpass(double K, double Q, double *b, double *a)
{
    if ((b == NULL) || (a == NULL))
    {
        return;
    }
    double T = K * K * Q + K + Q;

    b[0] = Q / T;
    b[1] = -2 * Q / T;
    b[2] = Q / T;

    a[0] = 1;
    a[1] = 2 * Q * (K * K - 1) / T;
    a[2] = (K * K * Q - K + Q) / T;
}

void Bandpass(double K, double Q, double *b, double *a)
{
    if ((b == NULL) || (a == NULL))
    {
        return;
    }
    double T = K * K * Q + K + Q;

    b[0] = K / T;
    b[1] = 0;
    b[2] = -K / T;

    a[0] = 1;
    a[1] = 2 * Q * (K * K - 1) / T;
    a[2] = (K * K * Q - K + Q) / T;
}

void Bandreject(double K, double Q, double *b, double *a)
{
    if ((b == NULL) || (a == NULL))
    {
        return;
    }
    double T = K * K * Q + K + Q;

    b[0] = Q * (1 + K * K) / T;
    b[1] = 2 * Q * (K * 2 - 1) / T;
    b[2] = Q * (1 + K * K) / T;

    a[0] = 1;
    a[1] = 2 * Q * (K * K - 1) / T;
    a[2] = (K * K * Q - K + Q) / T;
}

二阶滤波器的使用

二阶滤波器可以分为直接I型和直接II型

直接I型为:

\[y[n]=b_0x[n]+b_1x[n-1]+b_2x[n-2]-a_1y[n-1]-a_2y[n-2]\]

针对b参数加入G参数,设置\(b=G*b^{'}\):

\[y[n]=G*(b_0^{'}x[n]+b_1^{'}x[n-1]+b_2^{'}x[n-2])-a_1y[n-1]-a_2y[n-2]\]

直接II型为:

\[y[n]=b_0w[n]+b_1w[n-1]+b_2w[n-2]\] \[w[n]=x[n]-a_1w[n-1]-a_2w[n-2]\]

定点计算建议使用I型,浮点计算建议使用II型。

C语言参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void DirectI_Filter(int *x, int *y, int len, double *b, double *a)
{
    if ((x == NULL) || (y == NULL) || (b == NULL) || (a == NULL))
    {
        return;
    }
    static double hisx[3] = {0};
    static double hisy[3] = {0};
    double sum;
    int i;
    for (i = 0; i < len; i++)
    {
        hisx[0] = x[i];
        sum = b[0] * hisx[0] + b[1] * hisx[1] + b[2] * hisx[2];
        sum = sum - a[1] * hisy[1] - a[2] * hisy[2];
        hisy[0] = sum;

        hisx[2] = hisx[1];
        hisx[1] = hisx[0];
        hisy[2] = hisy[1];
        hisy[1] = hisy[0];

        y[i] = hisy[0];
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void DirectII_Filter(int *x, int *y, int len, double *b, double *a)
{
    if ((x == NULL) || (y == NULL) || (b == NULL) || (a == NULL))
    {
        return;
    }
    static double hisw[3] = {0};
    int i;
    for (i = 0; i < len; i++)
    {
        hisw[0] = x[i] - a[1] * hisw[1] - a[2] * hisw[2];
        y[i] = b[0] * hisw[0] + b[1] * hisw[1] + b[2] * hisw[2];

        hisw[2] = hisw[1];
        hisw[1] = hisw[0];
    }
}

参考链接:

Digital biquad filter

本文由作者按照 CC BY 4.0 进行授权