'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 |