IIR filter software implementation (Matlab+C++)

Write an IIR filter using C++

We first need to design an IIR filter in MATLAB and generate a header file that reflects the frequency response characteristics of the IIR filter


theoretical support

IIR filtering is called a recursive filter, and it is a filter with feedback. When the order is large, multiple second-order section filters are generally used in series, which can improve the stability of the system.

A second-order nodal coefficient law is shown in the figure:

The difference equation for the Kth second-order section can be written

The cascade structure of N second-order sections is shown in the following figure:

According to the second-order nodal diagram, the output of the previous stage is regarded as the input of the latter stage, and the function of IIR digital filtering can be realized by software.


 

Generate header files using Matlab

First open the Filter Design & Analysis Tool in MATLAB

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Here we first design a low-pass filter

Fs represents the sampling frequency, the sampling frequency must be greater than twice the highest frequency of the original signal,

Otherwise spectral aliasing will occur.

Fpass is the passband frequency, Fstop is the stopband cutoff frequency

After these parameters are set, click Design Filter

 

What is generated is a second-order section filter combination, with a total of 31 orders, that is, a combination of multiple second-order filters

Then generate the C Header File in the Target option

 Numerator is the name of the numerator coefficient array, Numerator length is the length of the numerator coefficient array,

 Denominator is the denominator.


Analyze the generated header file

The following is an example of a low-pass filter with Fpass as 10K and Fstop as 12K

Before using the header file, it is necessary to convert the data type of Matlab to the data type supported by C++ according to the situation. Here we use the double type

 

Before analyzing the header file, look at the first section of filtering parameters provided by Matlab

Take the data of the first second-order section as an example:

  • Numerator: 1  2  1
  • Denominator: 1  -0.55930961405944157  0.92579835996619642
  • Gain:0.34162218647668868

Numerator is the coefficient of the numerator, b0, b1, b2 respectively

Denominator is the coefficient of the denominator, a0, a1, a2 respectively.

Gain is the gain of each section. In order to stabilize each section, this item can stabilize the signal size.

 

Then compare the header file, the following is an interception of the main part of the header file:

#define MWSPT_NSEC 41
int NL[MWSPT_NSEC] = { 1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,
3,1,3,1,2,1 };
double NUM[MWSPT_NSEC][3] = {
  {
     0.3416221864767,                 0,                 0 
  },
  {
                   1,                 2,                 1 
  },
  {
     0.3180955154747,                 0,                 0 
  },
  {
                   1,                 2,                 1 
  },......
MWSPT_NSEC is the filter order, the specific number of sections is in the comments at the beginning of the header file
NL[MWSPT_NSEC] This array defines the number of useful data in each row of the NUM[MWSPT_NSEC][3] array (it is optional)

In the NUM[MWSPT_NSEC][3] array (numerator parameters), the first item of the odd row is the gain item, and the even row has 3 coefficients, which are b0, b1, and b2 respectively.

From this, we can find the law, define K as the current order, and p as the first pointer of the array, then, the gain term of each section is (p+6*K), and the first coefficient is (p+3+ 6*K),

The second coefficient is (p+3+6*K+1) and the third coefficient is (p+3+6*K+2).


C++ programming implementation

In the process of software design, the delay variable of each second-order section is only summed, and is directly assigned as an intermediate variable in the process. This is because the delay variable of the next input data n+1 is the sum of the previous input data. Designing in this way can save register space.

In order to improve the processing speed, the program needs to use pointers for parameter transfer, and pay special attention to the transfer method of the first address of the two-dimensional array as &a[0][0]->double* a.

 

filter function

double iir(double *a, double *b,double* w, double xin, int N_IIR)

{

    int k;

double temp = xin;

 

for (k = 0; k<N_IIR; k++)

{

   

    *(w+k*3) = temp - *(a + 3+6 * k  + 1) *(*(w + k * 3+1)) - *(a + 3 + 6 * k + 2) *(*(w + k * 3+2));

         //Here temp is the input of the second-order section and the output of the previous second-order section

         temp = *(b + 3 + 6 * k )* (*(w + k * 3)) + *(b + 3 + 6 * k + 1) * (*(w + k * 3+1)) + *(b + 3+6 * k + 2)* (*(w + k * 3+2));

//Here temp is the output of the second-order section and the input of the next second-order section

 

        

         *(w + k * 3 + 2) = *(w + k * 3 + 1);

         *(w + k * 3 + 1) = *(w + k * 3);

        

         temp = temp*(*(b + 6 * k));//Amplification, stable signal

}

return temp;

}


practical testing

Test a low-pass filter with Fpass of 10K and Fstop of 12K

Input three signals with frequencies of 2K, 11K, and 20K in the program. In theory, 2k is completely passed, 11k is partially attenuated, and 20K is completely filtered out.

The upper picture is the original signal, and the lower picture is the filtered signal.

The actual test found that it meets the design requirements, and the signal is basically completely attenuated in the transition band.

Test C++ program
 void main()
{
    const int N = 100;
    int i,j;
    double xn[N];
    double w[20][3];
    double yn[N];

    for (i = 0; i < 20; i++)//初始化
    {
        for (j = 0; j < 3; j++)
            w[i][j] = 0;
    }

    for (i = 0; i < N; i++)
    {
        xn[i] = sin(2 * 3.1416 * 20 / 50 * i)+ sin(2 * 3.1416 * 2 / 50 * i)+ sin(2 * 3.1416 * 11 / 50 * i);

        yn [i] = iir (& DEN [ 0 ] [ 0 ], & NUM [ 0 ] [ 0 ], & w [ 0 ] [ 0 ], xn [i], 20 );
    
    }

    ofstream SaveFile_a("xn.txt");
    for (i = 0; i<N; i++)
        SaveFile_a << " " << xn[i] << endl;
    SaveFile_a.close();

    ofstream SaveFile_b("yn.txt");
    for (i = 0; i<N; i++)
        SaveFile_b << " " << yn[i] << endl;
    SaveFile_a.close();
}

Matlab program for analysis
xn1=fopen('xn.txt','r');
[xn,count]=fscanf(xn1,'%f');
fclose(xn1);

N = length(xn);% Find the number of sampling points
xn_f = fft(xn);% Fourier transform the signal
xn_f=abs(xn_f(1:N/2));
f = 50000/N*(0:N/2-1);

subplot(211);
stem(f,abs(xn_f));
xlabel('Frequency / (s)');ylabel('Amplitude');

title( ' Original signal spectrum ' );
grid;

yn1 = fopen ( ' yn.txt ' , ' r ' );
[in, count] = fscanf (in1, ' % f ' );
fclose(yn1);

yn_f = fft(yn);% Fourier transform the signal
yn_f = abs (yn_f ( 1 : N / 2 ));
subplot(212);
stem (f, abs (in_f));
xlabel('Frequency / (s)');ylabel('Amplitude');
title( ' Filtered signal spectrum ' );
grid;

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325360897&siteId=291194637