Butterworth Low Pass Filter C / C++ Implementation

The code below defines a butterworth 6th order low pass filter with center freq. 0.1 * sampling frequency.
The processor code uses double precision but you can easily convert it to ‘float’ floating point arithmetic as needed.
One application of this type of Butterworth low pass filter is anti-aliasing.
It’s necessary to use a low pass filter whenever you want to reduce the sample rate, for example from 10kHz sampling rate down to 5kHz. Butterworth 6th order has a sharp transfer function and few ripples.

void ButterworthLowpassFilter0100SixthOrder(const double src[], double dest[], int size)
{ 	
	const int NZEROS = 6;
	const int NPOLES = 6;
	const double GAIN = 2.936532839e+03;

	double xv[NZEROS+1] = {0.0}, yv[NPOLES+1] = {0.0};

    for (int i = 0; i < size; i++)
  	{ 
		xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; 
        xv[6] = src[i] / GAIN;
        yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; 
        yv[6] =   (xv[0] + xv[6]) + 6.0 * (xv[1] + xv[5]) + 15.0 * (xv[2] + xv[4])
                     + 20.0 * xv[3]
                     + ( -0.0837564796 * yv[0]) + (  0.7052741145 * yv[1])
                     + ( -2.5294949058 * yv[2]) + (  4.9654152288 * yv[3])
                     + ( -5.6586671659 * yv[4]) + (  3.5794347983 * yv[5]);
        dest[i] = yv[6];
    }
}

The same Butterworth 6th order low pass filter again with a cut off frequency of 0.05 * sample rate:

// Defines a butterworth low pass filter with center freq. 0.05 * sampling frequency
// Note: this processor only works with 'double'
// this filter is used as anti-aliasing filter from 20kHz sampling rate down to 5kHz
void ButterworthLowpassFilter0050SixthOrder(const double src[], double dest[], int size)
{ 	
	const int NZEROS = 6;
	const int NPOLES = 6;
	const double GAIN = 1.165969038e+05;

	double xv[NZEROS+1] = {0.0}, yv[NPOLES+1] = {0.0};

    for (int i = 0; i < size; i++)
  	{ 
		xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; 
        xv[6] = src[i] / GAIN;
        yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; 
        yv[6] =   (xv[0] + xv[6]) + 6.0 * (xv[1] + xv[5]) + 15.0 * (xv[2] + xv[4])
                     + 20.0 * xv[3]
                     + ( -0.2951724313 * yv[0]) + (  2.1290387500 * yv[1])
                     + ( -6.4411118810 * yv[2]) + ( 10.4690788930 * yv[3])
                     + ( -9.6495177287 * yv[4]) + (  4.7871354989 * yv[5]);
        dest[i] = yv[6];
    }
} 

This time the Butterworth 6th order low pass filter was parameterized with a cut off frequency of 0.08 * sample rate:

// Defines a butterworth lowpass filter with center freq. 0.08 * sampling frequency
// Note: this processor only works with 'double'
// this filter is used as anti-aliasing filter from 10kHz sampling rate down to 4kHz
void ButterworthLowpassFilter0080SixthOrder(const double src[], double dest[], int size)
{ 	
	const int NZEROS = 6;
	const int NPOLES = 6;
	const double GAIN = 9.339780497e+03;

	double xv[NZEROS+1] = {0.0}, yv[NPOLES+1] = {0.0};

    for (int i = 0; i < size; i++)
  	{ 
		xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; 
        xv[6] = src[i] / GAIN;
        yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; 
        yv[6] =   (xv[0] + xv[6]) + 6.0 * (xv[1] + xv[5]) + 15.0 * (xv[2] + xv[4])
                     + 20.0 * xv[3]
                     + ( -0.1396600417 * yv[0]) + (  1.1086708553 * yv[1])
                     + ( -3.7230194289 * yv[2]) + (  6.7850160254 * yv[3])
                     + ( -7.0995038188 * yv[4]) + (  4.0616439992 * yv[5]);
        dest[i] = yv[6];
    }
} 

The last variant of this filter uses a cut off frequency of 0.04 * sample rate. For example if sample rate is 10 kHz, the cut off would be at 400 Hz.

void ButterworthLowpassFilter0040SixthOrder(const double src[], double dest[], int size)
{ 	
	const int NZEROS = 6;
	const int NPOLES = 6;
	const double GAIN = 4.004448900e+05;
	double xv[NZEROS+1] = {0.0}, yv[NPOLES+1] = {0.0};

    for (int i = 0; i < size; i++)
  	{ 
		xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; 
        xv[6] = src[i] / GAIN;
        yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; 
        yv[6] =   (xv[0] + xv[6]) + 6.0 * (xv[1] + xv[5]) + 15.0 * (xv[2] + xv[4])
                     + 20.0 * xv[3]
                     + ( -0.3774523864 * yv[0]) + (  2.6310551285 * yv[1])
                     + ( -7.6754745482 * yv[2]) + ( 11.9993158160 * yv[3])
                     + (-10.6070421840 * yv[4]) + (  5.0294383514 * yv[5]);
        dest[i] = yv[6];
    }
}

Hope this helps!