Can anyone tell me how to implement an FIR filter using c programming language.
To combine multiple filters:
Start with an unit impulse (a signal with a 1 in the first position and 0 everywhere else). Apply the first filter. Apply the second filter. Continue until all filters are applied. The result shows how the combined filters convolve the unit impulse (provided the array is long enough that no data was lost), so the values in it are the coefficients for one filter that is the composition of the other filters.
Here is sample code:
#include <stdio.h>
#include <string.h>
#define NumberOf(a) (sizeof (a) / sizeof *(a))
/* Convolve Signal with Filter.
Signal must contain OutputLength + FilterLength - 1 elements. Conversely,
if there are N elements in Signal, OutputLength may be at most
N+1-FilterLength.
*/
static void convolve(
float *Signal,
float *Filter, size_t FilterLength,
float *Output, size_t OutputLength)
{
for (size_t i = 0; i < OutputLength; ++i)
{
double sum = 0;
for (size_t j = 0; j < FilterLength; ++j)
sum += Signal[i+j] * Filter[FilterLength - 1 - j];
Output[i] = sum;
}
}
int main(void)
{
// Define a length for buffers that is long enough for this demonstration.
#define LongEnough 128
// Define some sample filters.
float Filter0[] = { 1, 2, -1 };
float Filter1[] = { 1, 5, 7, 5, 1 };
size_t Filter0Length = NumberOf(Filter0);
size_t Filter1Length = NumberOf(Filter1);
// Define a unit impulse positioned so it captures all of the filters.
size_t UnitImpulsePosition = Filter0Length - 1 + Filter1Length - 1;
float UnitImpulse[LongEnough];
memset(UnitImpulse, 0, sizeof UnitImpulse);
UnitImpulse[UnitImpulsePosition] = 1;
// Calculate a filter that is Filter0 and Filter1 combined.
float CombinedFilter[LongEnough];
// Set N to number of inputs that must be used.
size_t N = UnitImpulsePosition + 1 + Filter0Length - 1 + Filter1Length - 1;
// Subtract to find number of outputs of first convolution, then convolve.
N -= Filter0Length - 1;
convolve(UnitImpulse, Filter0, Filter0Length, CombinedFilter, N);
// Subtract to find number of outputs of second convolution, then convolve.
N -= Filter1Length - 1;
convolve(CombinedFilter, Filter1, Filter1Length, CombinedFilter, N);
// Remember size of resulting filter.
size_t CombinedFilterLength = N;
// Display filter.
for (size_t i = 0; i < CombinedFilterLength; ++i)
printf("CombinedFilter[%zu] = %g.\n", i, CombinedFilter[i]);
// Define two identical signals.
float Buffer0[LongEnough];
float Buffer1[LongEnough];
for (size_t i = 0; i < LongEnough; ++i)
{
Buffer0[i] = i;
Buffer1[i] = i;
}
// Convolve Buffer0 by using the two filters separately.
// Start with buffer length.
N = LongEnough;
// Subtract to find number of outputs of first convolution, then convolve.
N -= Filter0Length - 1;
convolve(Buffer0, Filter0, Filter0Length, Buffer0, N);
// Subtract to find number of outputs of second convolution, then convolve.
N -= Filter1Length - 1;
convolve(Buffer0, Filter1, Filter1Length, Buffer0, N);
// Remember the length of the result.
size_t ResultLength = N;
// Convolve Buffer1 with the combined filter.
convolve(Buffer1, CombinedFilter, CombinedFilterLength, Buffer1, ResultLength);
// Show the contents of Buffer0 and Buffer1, and their differences.
for (size_t i = 0; i < ResultLength; ++i)
{
printf("Buffer0[%zu] = %g. Buffer1[%zu] = %g. Difference = %g.\n",
i, Buffer0[i], i, Buffer1[i], Buffer0[i] - Buffer1[i]);
}
return 0;
}
I found this code snippet did not work for me (Visual Studio 2005).
I did eventually find convolution questions having a great answer:
1d linear convolution in ANSI C code?
For those who don't know - the convolution is exactly the same operation as FIR filtering - the "kernel" is the FIR Filter impulse response and the signal is the input signal.
I hope this helps some poor sap who was looking for FIR code :-)
Designing an FIR filter is NOT a simple topic, but implementing an already-designed filter (assuming you already have the FIR coefficients) isn't too bad. The algorithm is called convolution. Here's a naive implementation...
void convolve (double *p_coeffs, int p_coeffs_n,
double *p_in, double *p_out, int n)
{
int i, j, k;
double tmp;
for (k = 0; k < n; k++) // position in output
{
tmp = 0;
for (i = 0; i < p_coeffs_n; i++) // position in coefficients array
{
j = k - i; // position in input
if (j >= 0) // bounds check for input buffer
{
tmp += p_coeffs [k] * p_in [j];
}
}
p_out [i] = tmp;
}
}
Basically, the convolution does a moving weighted average of the input signal. The weights are the filter coefficients, which are assumed to sum to 1.0. If the weights sum to something other than 1.0, you get some amplification/attenuation as well as filtering.
BTW - it's possible this function has the coefficients array backwards - I haven't double-checked and it's a while since I thought about these things.
For how you calculate the FIR coefficients for a particular filter, there's a fair amount of mathematics behind that - you really need a good book on digital signal processing. This one is available free for a PDF, but I'm not sure how good it is. I have Rorabaugh and Orfandis, both published in the mid nineties but these things don't really get obsolete.