'How to make an IIR filter?

i'm trying to make IIR filter. I made FIR filter, but I feels IIR is more difficult than FIR.

I think IIR is similar with FIR, but it made me feels confused.

I think the filters are like this.

FIR : y(n) = b0(x[n]) + ... +bM-1(x[n-M+1])

IIR : y(n) = {b0(x[n]) + ... +bM-1(x[n-M+1])} - {a1(y[n-1]) + ... +aN(y[n-N}

in this case, how about a0? Is it just 1?

The part of y[n-1]..... is the problem. I confused how to make it.

Here is my code.

for (n = 0; n < length; n++) {
    coeffa = coeffs_A;
    coeffb = coeffs_B;
    inputp = &insamp[filterLength - 1 + n];
    acc = 0;
    bcc = 0;
    for (k = 0; k < filterLength; k++) {
        bcc += (*coeffb++) * (*inputp--);
    }
    for (k = 0; k < filterLength; k++) {
        acc += (*coeffa++) * (////////);
    }
    output[n] = bcc-acc;
}

In this case, filterLength is 7 and n is 80

////// is what i want to know.

Am I think wrong?



Solution 1:[1]

Typically IIR filters are implemented using direct form I or direct form II topologies. Each form requires memory states. These memory states keep the histories of the outputs and inputs in them. This makes it a lot simpler to implement the IIR filter. gtkiostream implements a direct form II approach and may be a helpful reference.

In addressing your question, I like the approach of directly estimating your filters from inputs and outputs, using the input and output buffers as memory states. As a coefficients always operate on outputs, use the outputs as the missing variable, something like this :

acc += (*coeffa++) * output[n-k];

Solution 2:[2]

I took your programm and rewrote it a bit to make it a MCVE and be easier readable:

#include  <stdio.h>
#define flen 3
#define slen  10

int main(void)
{

    int n,k;
    double a[flen] = {1,-0.5,0}, b[flen]={1,0,0};
    double input[slen]={0,0,1}; // 0s for flen-1 to avoid out of bounds
    double output[slen]={0};
    double acc, bcc;


    for (n = flen-1; n < slen; n++) {

        acc = 0;
        bcc = 0;
        for (k = 0; k < flen; k++) {
            bcc += b[k] * (input[n-k]);
        }
        for (k = 0; k < flen; k++) {
            acc += a[k] * (output[n-k]);
        }
        output[n] = bcc-acc;
        printf("%f\t%f\t%f\t%f\n",input[n],acc,bcc,output[n]);
    }



    return 0;
}

I am not entirely sure this is correct because I do not have the means to test with different filter settings against a filter design tool.

The impulse response for the given coefficents seems to be okay. But I haven't done anything in this topic for a few years now so I am not certain. The general idea should be okay I think.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Matt
Solution 2 Kami Kaze