Infinite Impulse Response Filter (iirfilt)

The iirfilt_crcf object and family implement the infinite impulse response (IIR) filters. Also known as recursive filters, IIR filters allow a portion of the output to be fed back into the input, thus creating an impulse response which is non-zero for an infinite amount of time. Formally, the output signal \(y[n]\) may be written in terms of the input signal \(x[n]\) as

(13)\[y[n] = \frac{1}{a_0} \left( \sum_{j=0}^{n_b-1}{ b_j x[n-j] } - \sum_{k=1}^{n_a-1}{ a_k y[n-k] } \right)\]

where \(\vec{b} = [b_0,b_1,\ldots,b_{n_b-1}]^T\) are the feed-forward parameters and \(\vec{a} = [a_0,a_1,\ldots,a_{n_a-1}]^T\) are the feed-back parameters of length \(n_b\) and \(n_a\), respectively. The \(z\)-transform of the transfer function is therefore

(14)\[H(z) = \frac{Y(z)}{X(z)} = \frac{\sum\limits_{j=0}^{n_b-1}{b_j z^{-j}}} {\sum\limits_{k=0}^{n_a-1}{a_k z^{-k}}} = \frac{ b_0 + b_1 z^{-1} + \cdots + b_{n_b-1} z^{n_b-1}} { a_0 + a_1 z^{-1} + \cdots + a_{n_a-1} z^{n_a-1}}\]

Typically the coefficients in \(H(z)\) are normalized such that \(a_0=1\).

For larger order filters (even as small as \(n\approx 8\)) the filter can become unstable due to finite machine precision. It is often therefore useful to express \(H(z)\) in terms of second-order sections. For a filter of order \(n\), these sections are denoted by the two \((L+r)\times 3\) matrices \(\vec{B}\) and \(\vec{A}\) where \(r=n \mod 2\) (0 for odd \(n\), 1 for even \(n\)) and \(L=(n-r)/2\).

(15)\[H_d(z) = \left[ \frac{B_{r,0} + B_{r,1}z^{-1}} {1 + A_{r,1}z^{-1}} \right]^r \prod_{k=1}^{L} {\left[ \frac{B_{k,0} + B_{k,1}z^{-1} + B_{k,2}z^{-2}} {1 + A_{k,1}z^{-1} + A_{k,2}z^{-2}} \right]}\]

Notice that \(H(z)\) is now a series of cascaded second-order IIR filters. The sos form is practical when filters are designed from analog prototypes where the poles and zeros are known. liquid implements second-order sections efficiently with the internal iirfiltsos_crcf family of objects. For a cascaded second-order section IIR filter, use create_sos().

Examples

Listed below is a basic example of the interface in which a low-pass filter is applied to a signal to remove a high-frequency component.

#include <stdio.h>
#include <math.h>
#include <complex.h>
#include "liquid.h"

int main(int argc, char*argv[])
{
    // create filter object from prototype
    iirfilt_crcf q = iirfilt_crcf_create_prototype(
        LIQUID_IIRDES_ELLIP,
        LIQUID_IIRDES_LOWPASS,
        LIQUID_IIRDES_SOS,
        7,      // filter order
        0.1f,   // fc, cutoff frequency
        0.0f,   // f0, center frequency for bandpass
        0.1f,   // Ap, pass-band ripple [dB]
        40.0f); // As, stop-band suppression [dB]

    printf(" x-real x-imag y-real y-imag\n");
    unsigned int i;
    for (i=0; i<120; i++) {
        // input (two tones)
        float complex x = i >= 80 ? 0 :
            1.0f*cexpf(_Complex_I*2*M_PI*0.057f*i) +
            0.5f*cexpf(_Complex_I*2*M_PI*0.392f*i);

        // compute filtered output
        float complex y;
        iirfilt_crcf_execute(q, x, &y);
        printf("%12.8f %12.8f %12.8f %12.8f\n",
            crealf(x), cimagf(x), crealf(y), cimagf(y));
    }

    // destroy filter object
    iirfilt_crcf_destroy(q);
    return 0;
}

The output of this example is plotted below in Figure 5, below:

../_images/iirfilt-0.png

Figure 5 iirfilt_crcf (infinite impulse response filter) demonstration

You can create a filter from a given set of filter coefficients as well, viz.

#include <liquid/liquid.h>

int main() {
    // options
    unsigned int order=4;   // filter order

    unsigned int n = order+1;
    float b[n], a[n];

    // ... initialize filter coefficients ...

    // create filter object
    iirfilt_crcf q = iirfilt_crcf_create(b,n,a,n);

    float complex x;    // input sample
    float complex y;    // output sample

    // execute filter (repeat as necessary)
    iirfilt_crcf_execute(q,x,&y);

    // destroy filter object
    iirfilt_crcf_destroy(q);
}

Interface

Listed below is the full interface to the iirfilt family of objects.

create()

Create infinite impulse response filter from external coefficients. Note that the number of feed-forward and feed-back coefficients do not need to be equal, but they do need to be non-zero. Furthermore, the first feed-back coefficient (a_0) cannot be equal to zero, otherwise the filter will be invalid as this value is factored out from all coefficients. For stability reasons the number of coefficients should reasonably not exceed about 8 for single-precision floating-point.

iirfilt_rrrf = iirfilt_rrrf_create(float * _b, unsigned int _nb, float * _a, unsigned int _na);
  • float * _b: feed-forward coefficients (numerator)

  • unsigned int _nb: number of feed-forward coefficients

  • float * _a: feed-back coefficients (denominator)

  • unsigned int _na: number of feed-back coefficients

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create(float * _b, unsigned int _nb, float * _a, unsigned int _na);
  • float * _b: feed-forward coefficients (numerator)

  • unsigned int _nb: number of feed-forward coefficients

  • float * _a: feed-back coefficients (denominator)

  • unsigned int _na: number of feed-back coefficients

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create(float complex * _b, unsigned int _nb, float complex * _a, unsigned int _na);
  • float complex * _b: feed-forward coefficients (numerator)

  • unsigned int _nb: number of feed-forward coefficients

  • float complex * _a: feed-back coefficients (denominator)

  • unsigned int _na: number of feed-back coefficients

  • returns new iirfilt_cccf object

create_sos()

Create IIR filter using 2nd-order sections from external coefficients.

iirfilt_rrrf = iirfilt_rrrf_create_sos(float * _b, float * _a, unsigned int _nsos);
  • float * _b: feed-forward coefficients

  • float * _a: feed-back coefficients

  • unsigned int _nsos: number of second-order sections (sos)

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_sos(float * _b, float * _a, unsigned int _nsos);
  • float * _b: feed-forward coefficients

  • float * _a: feed-back coefficients

  • unsigned int _nsos: number of second-order sections (sos)

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_sos(float complex * _b, float complex * _a, unsigned int _nsos);
  • float complex * _b: feed-forward coefficients

  • float complex * _a: feed-back coefficients

  • unsigned int _nsos: number of second-order sections (sos)

  • returns new iirfilt_cccf object

create_prototype()

Create IIR filter from design template

iirfilt_rrrf = iirfilt_rrrf_create_prototype(liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _order, float _fc, float _f0, float _ap, float _as);
  • liquid_iirdes_filtertype _ftype: filter type (e.g. LIQUID_IIRDES_BUTTER)

  • liquid_iirdes_bandtype _btype: band type (e.g. LIQUID_IIRDES_BANDPASS)

  • liquid_iirdes_format _format: coefficients format (e.g. LIQUID_IIRDES_SOS)

  • unsigned int _order: filter order

  • float _fc: low-pass prototype cut-off frequency

  • float _f0: center frequency (band-pass

  • float _ap: pass-band ripple in dB

  • float _as: stop-band ripple in dB

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_prototype(liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _order, float _fc, float _f0, float _ap, float _as);
  • liquid_iirdes_filtertype _ftype: filter type (e.g. LIQUID_IIRDES_BUTTER)

  • liquid_iirdes_bandtype _btype: band type (e.g. LIQUID_IIRDES_BANDPASS)

  • liquid_iirdes_format _format: coefficients format (e.g. LIQUID_IIRDES_SOS)

  • unsigned int _order: filter order

  • float _fc: low-pass prototype cut-off frequency

  • float _f0: center frequency (band-pass

  • float _ap: pass-band ripple in dB

  • float _as: stop-band ripple in dB

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_prototype(liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _order, float _fc, float _f0, float _ap, float _as);
  • liquid_iirdes_filtertype _ftype: filter type (e.g. LIQUID_IIRDES_BUTTER)

  • liquid_iirdes_bandtype _btype: band type (e.g. LIQUID_IIRDES_BANDPASS)

  • liquid_iirdes_format _format: coefficients format (e.g. LIQUID_IIRDES_SOS)

  • unsigned int _order: filter order

  • float _fc: low-pass prototype cut-off frequency

  • float _f0: center frequency (band-pass

  • float _ap: pass-band ripple in dB

  • float _as: stop-band ripple in dB

  • returns new iirfilt_cccf object

create_lowpass()

Create simplified low-pass Butterworth IIR filter

iirfilt_rrrf = iirfilt_rrrf_create_lowpass(unsigned int _order, float _fc);
  • unsigned int _order: filter order

  • float _fc: low-pass prototype cut-off frequency

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_lowpass(unsigned int _order, float _fc);
  • unsigned int _order: filter order

  • float _fc: low-pass prototype cut-off frequency

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_lowpass(unsigned int _order, float _fc);
  • unsigned int _order: filter order

  • float _fc: low-pass prototype cut-off frequency

  • returns new iirfilt_cccf object

create_integrator()

Create 8th-order integrator filter

iirfilt_rrrf = iirfilt_rrrf_create_integrator();
  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_integrator();
  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_integrator();
  • returns new iirfilt_cccf object

create_differentiator()

Create 8th-order differentiator filter

iirfilt_rrrf = iirfilt_rrrf_create_differentiator();
  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_differentiator();
  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_differentiator();
  • returns new iirfilt_cccf object

create_dc_blocker()

Create simple first-order DC-blocking filter with transfer function ( H(z) = frac{1 - z^{-1}}{1 - (1-alpha)z^{-1}} )

iirfilt_rrrf = iirfilt_rrrf_create_dc_blocker(float _alpha);
  • float _alpha: normalized filter bandwidth

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_dc_blocker(float _alpha);
  • float _alpha: normalized filter bandwidth

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_dc_blocker(float _alpha);
  • float _alpha: normalized filter bandwidth

  • returns new iirfilt_cccf object

create_pll()

Create filter to operate as second-order integrating phase-locked loop (active lag design)

iirfilt_rrrf = iirfilt_rrrf_create_pll(float _w, float _zeta, float _K);
  • float _w: filter bandwidth

  • float _zeta: damping factor

  • float _K: loop gain

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_create_pll(float _w, float _zeta, float _K);
  • float _w: filter bandwidth

  • float _zeta: damping factor

  • float _K: loop gain

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_create_pll(float _w, float _zeta, float _K);
  • float _w: filter bandwidth

  • float _zeta: damping factor

  • float _K: loop gain

  • returns new iirfilt_cccf object

copy()

Copy object including all internal objects and state

iirfilt_rrrf = iirfilt_rrrf_copy(iirfilt_rrrf _q);
  • iirfilt_rrrf _q:

  • returns new iirfilt_rrrf object

iirfilt_crcf = iirfilt_crcf_copy(iirfilt_crcf _q);
  • iirfilt_crcf _q:

  • returns new iirfilt_crcf object

iirfilt_cccf = iirfilt_cccf_copy(iirfilt_cccf _q);
  • iirfilt_cccf _q:

  • returns new iirfilt_cccf object

destroy()

Destroy iirfilt object, freeing all internal memory

int = iirfilt_rrrf_destroy(iirfilt_rrrf _q);
  • iirfilt_rrrf _q:

  • returns standard error code

int = iirfilt_crcf_destroy(iirfilt_crcf _q);
  • iirfilt_crcf _q:

  • returns standard error code

int = iirfilt_cccf_destroy(iirfilt_cccf _q);
  • iirfilt_cccf _q:

  • returns standard error code

print()

Print iirfilt object properties to stdout

int = iirfilt_rrrf_print(iirfilt_rrrf _q);
  • iirfilt_rrrf _q:

  • returns standard error code

int = iirfilt_crcf_print(iirfilt_crcf _q);
  • iirfilt_crcf _q:

  • returns standard error code

int = iirfilt_cccf_print(iirfilt_cccf _q);
  • iirfilt_cccf _q:

  • returns standard error code

reset()

Reset iirfilt object internals

int = iirfilt_rrrf_reset(iirfilt_rrrf _q);
  • iirfilt_rrrf _q:

  • returns standard error code

int = iirfilt_crcf_reset(iirfilt_crcf _q);
  • iirfilt_crcf _q:

  • returns standard error code

int = iirfilt_cccf_reset(iirfilt_cccf _q);
  • iirfilt_cccf _q:

  • returns standard error code

set_scale()

Set output scaling for filter

int = iirfilt_rrrf_set_scale(iirfilt_rrrf _q, float _scale);
  • iirfilt_rrrf _q: filter object

  • float _scale: scaling factor to apply to each output sample

  • returns standard error code

int = iirfilt_crcf_set_scale(iirfilt_crcf _q, float _scale);
  • iirfilt_crcf _q: filter object

  • float _scale: scaling factor to apply to each output sample

  • returns standard error code

int = iirfilt_cccf_set_scale(iirfilt_cccf _q, float complex _scale);
  • iirfilt_cccf _q: filter object

  • float complex _scale: scaling factor to apply to each output sample

  • returns standard error code

get_scale()

Get output scaling for filter

int = iirfilt_rrrf_get_scale(iirfilt_rrrf _q, float * _scale);
  • iirfilt_rrrf _q: filter object

  • float * _scale: scaling factor applied to each output sample

  • returns standard error code

int = iirfilt_crcf_get_scale(iirfilt_crcf _q, float * _scale);
  • iirfilt_crcf _q: filter object

  • float * _scale: scaling factor applied to each output sample

  • returns standard error code

int = iirfilt_cccf_get_scale(iirfilt_cccf _q, float complex * _scale);
  • iirfilt_cccf _q: filter object

  • float complex * _scale: scaling factor applied to each output sample

  • returns standard error code

execute()

Compute filter output given a single input sample

int = iirfilt_rrrf_execute(iirfilt_rrrf _q, float _x, float * _y);
  • iirfilt_rrrf _q: iirfilt object

  • float _x: input sample

  • float * _y: output sample pointer

  • returns standard error code

int = iirfilt_crcf_execute(iirfilt_crcf _q, float complex _x, float complex * _y);
  • iirfilt_crcf _q: iirfilt object

  • float complex _x: input sample

  • float complex * _y: output sample pointer

  • returns standard error code

int = iirfilt_cccf_execute(iirfilt_cccf _q, float complex _x, float complex * _y);
  • iirfilt_cccf _q: iirfilt object

  • float complex _x: input sample

  • float complex * _y: output sample pointer

  • returns standard error code

execute_block()

Execute the filter on a block of input samples; in-place operation is permitted (the input and output buffers may be the same)

int = iirfilt_rrrf_execute_block(iirfilt_rrrf _q, float * _x, unsigned int _n, float * _y);
  • iirfilt_rrrf _q: filter object

  • float * _x: pointer to input array

  • unsigned int _n: number of input

  • float * _y: pointer to output array

  • returns standard error code

int = iirfilt_crcf_execute_block(iirfilt_crcf _q, float complex * _x, unsigned int _n, float complex * _y);
  • iirfilt_crcf _q: filter object

  • float complex * _x: pointer to input array

  • unsigned int _n: number of input

  • float complex * _y: pointer to output array

  • returns standard error code

int = iirfilt_cccf_execute_block(iirfilt_cccf _q, float complex * _x, unsigned int _n, float complex * _y);
  • iirfilt_cccf _q: filter object

  • float complex * _x: pointer to input array

  • unsigned int _n: number of input

  • float complex * _y: pointer to output array

  • returns standard error code

get_length()

Return number of coefficients for iirfilt object (maximum between the feed-forward and feed-back coefficients). Note that the filter length = filter order + 1

unsigned int = iirfilt_rrrf_get_length(iirfilt_rrrf _q);
  • iirfilt_rrrf _q:

  • returns something good

unsigned int = iirfilt_crcf_get_length(iirfilt_crcf _q);
  • iirfilt_crcf _q:

  • returns something good

unsigned int = iirfilt_cccf_get_length(iirfilt_cccf _q);
  • iirfilt_cccf _q:

  • returns something good

freqresponse()

Compute complex frequency response of filter object

int = iirfilt_rrrf_freqresponse(iirfilt_rrrf _q, float _fc, liquid_float_complex * _H);
  • iirfilt_rrrf _q: filter object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

int = iirfilt_crcf_freqresponse(iirfilt_crcf _q, float _fc, liquid_float_complex * _H);
  • iirfilt_crcf _q: filter object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

int = iirfilt_cccf_freqresponse(iirfilt_cccf _q, float _fc, liquid_float_complex * _H);
  • iirfilt_cccf _q: filter object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

get_psd()

Compute power spectral density response of filter object in dB

float = iirfilt_rrrf_get_psd(iirfilt_rrrf _q, float _fc);
  • iirfilt_rrrf _q: filter object

  • float _fc: normalized frequency for evaluation

  • returns something good

float = iirfilt_crcf_get_psd(iirfilt_crcf _q, float _fc);
  • iirfilt_crcf _q: filter object

  • float _fc: normalized frequency for evaluation

  • returns something good

float = iirfilt_cccf_get_psd(iirfilt_cccf _q, float _fc);
  • iirfilt_cccf _q: filter object

  • float _fc: normalized frequency for evaluation

  • returns something good

groupdelay()

Compute and return group delay of filter object

float = iirfilt_rrrf_groupdelay(iirfilt_rrrf _q, float _fc);
  • iirfilt_rrrf _q: filter object

  • float _fc: frequency to evaluate

  • returns something good

float = iirfilt_crcf_groupdelay(iirfilt_crcf _q, float _fc);
  • iirfilt_crcf _q: filter object

  • float _fc: frequency to evaluate

  • returns something good

float = iirfilt_cccf_groupdelay(iirfilt_cccf _q, float _fc);
  • iirfilt_cccf _q: filter object

  • float _fc: frequency to evaluate

  • returns something good