Biquad filter of the C language and MATLAB design

Handling CSDN self https://blog.csdn.net/u013213111/article/details/90529164

Reference:
biquad filter

Examples herein, and code in Github

First, what is the biquad filter? The wiki is to say: the second, recursive, linear, comprising two poles and two zeros, "biquad" name from its transfer function is the ratio of two quadratic polynomials.

In signal processing, a digital biquad filter is a second order recursive linear filter, containing two poles and two zeros. "Biquad" is an abbreviation of "biquadratic", which refers to the fact that in the Z domain, its transfer function is the ratio of two quadratic functions: H(z)=(b₀+b₁z⁻¹+b₂z⁻²)/(a₀+a₁z⁻¹+a₂z⁻²) The coefficients are often normalized such that a₀ = 1: H(z)=(b₀+b₁z⁻¹+b₂z⁻²)/(1+a₁z⁻¹+a₂z⁻²) High-order IIR filters can be highly sensitive to quantization of their coefficients, and can easily become unstable.

Normalized transfer function written like this:
H (Z) = (+ b₀ + b₁z⁻¹ b₂z⁻²) / (. 1 + + a₁z⁻¹ a₂z⁻²)

With the MATLAB Filter Designer to design a: 400Hz bandpass IIR, Sections 4 needed to implement the filter structure is given by default Direct-Form II.
Here Insert Picture Description
Select the Analysis menu bar Filter Coeffients can see the filter coefficients:
Here Insert Picture Description
Numerator, molecules, that is, the transfer function of the item b are, from top to bottom as b₀, b₁ and b₂.
Denominator, the denominator, that is a transfer function in terms of, from top to bottom as a₀, a₁ and a₂, wherein a₀ is always 1.
Gain, gain.

An array to store the filter coefficients:

//8-order IIR filter with 4 sections
const int sections = 4;

//nominator
const float b[4][3] = {
    { 1, -1.984454421, 1 },
    { 1, -1.999405318, 1 },
    { 1, -1.993167556, 1 },
    { 1, -1.998644244, 1 }
};

//denominator
const float a[4][3] = {
    { 1, -1.984532740, 0.9884094716 },
    { 1, -1.988571923, 0.9909378613 },
    { 1, -1.991214225, 0.9962624248 },
    { 1, -1.995917854, 0.9977478940 }
};

const float gain[4] = { 0.583805364, 0.583805364, 0.170388576, 0.170388576 };

In Direct-Form II example to write implementation code, the calculation is:
Y [n-] = b₀w [n-] + b₁w [. 1-n-] + b₂w [2-n-]
where w [n] = x [n ] -a₁w [n-1] -a₂w [ n-2]
code is as follows:
an array to the intermediate state quantity storing filter w [n-1] and w [n-2]:

float w[sections][2]; //filter states

Before filter calculation, initialized filter:

for (int i = 0; i < sections; i++) {
        w[i][0] = 0; //w[n-1]
        w[i][1] = 0; //w[n-2]
}

Calculation started: pcmIn[i]the original input signal, the input section 1, section 1 is output as the input section 2, and so on, because the filter is composed of four Sections, therefore cycle 4 times.
Note that the output is multiplied by gain.

y[0] = pcmIn[i];
        for (j = 0; j < sections; j++) {
            tmp[j] = y[j] - a[j][1] * w[j][0] - a[j][2] * w[j][1]; //calculate w[n]
            y[j+1] = tmp[j] + b[j][1] * w[j][0] + b[j][2] * w[j][1]; //calculate the j-th section filter output y[n]
            w[j][1] = w[j][0]; //move w[n-1] -> w[n-2]
            w[j][0] = tmp[j]; //move w[n] -> w[n-1]
            y[j+1] = gain[j] * y[j+1]; //multiply with gain
        }
            
out = y[j];

If you need to get output such as PCM16, then clipped out again, that's all.

Guess you like

Origin www.cnblogs.com/lyrich/p/10987875.html