# C implementation of LP filter

I have the following code, which I am told is a low-pass Butterworth filter. How do I derive the frequency response and phase for this? I only have experience in analog electronics and so cannot relate this to a real filter response. I'm not sure why everything is scaled up by 2^ 16 - it must be to do with maintaining adequate resolution during the calculations?

#define FILTER_TC(FC, FS) ((411775 * FC) / FS)'


where TC = (2^16) * 2pi * Fc * Fs, with Fc the cut-off frequency in Hz, and Fs the sample frequency in Hz.

#define FILTER_LP(FILTER_OUT, FILTER_IN, FC, FS) \
(FILTER_OUT += ((signed long)FILTER_TC(FC, FS) * \
((signed long)FILTER_IN - (signed long)(FILTER_OUT)) >> 16)'


Thank you for any help with this.

jmv

You can figure out the filter's transfer function by rewriting the body of the preprocessor macro a bit. Let FILTER_TC(FC, FS) (which really just defines the cutoff frequency of the filter) be equal to k in the below expression.

#define FILTER_LP(FILTER_OUT, FILTER_IN, FC, FS) \
FILTER_OUT = FILTER_OUT + ((signed long) k * ((signed long) FILTER_IN - (signed long) FILTER_OUT)) >> 16)


In the above, I just expanded the += operator to be a bit less terse. By inspection, we can write the discrete-time difference equation:

$$y[n] = y[n-1] + k(x[n] - y[n-1]) \\ y[n] = (1-k)y[n-1] + k x[n]$$

where $y[n]$ and $x[n]$ are equal to FILTER_OUT and FILTER_IN at time index $n$, respectively. This maps to a $z$-domain transfer function of:

$$H(z) = \frac{Y(z)}{X(z)} = \frac{k}{1 - (1-k)z^{-1}}$$

This is a lowpass filter, although it is not a Butterworth filter. Its frequency response is plotted below for k = 0.25.

In the above frequency response plot, the blue trace shows the magnitude response and the green trace corresponds to the phase response. It shows that the example you gave isn't a particularly good lowpass filter, even for a first-order filter. You could do better with respect to high-frequency attenuation by using a correct Butterworth structure, for example.

The bit manipulations and explicit casts to signed long types are used because the filter is implemented using fixed-point arithmetic. This is a scheme by which you use integers to represent real numbers using a fixed quantization level. Fixed-point implementations of DSP algorithms were almost ubiquitous in the past, but floating-point processing is becoming more and more common. I would expect to find fixed-point implementations primarily in low-power or embedded contexts today.