Finite Impulse Response Filter (firfilt)

Finite impulse response (FIR) filters are implemented in liquid with the firfilt family of objects.

Operation

FIR filters (also known as non-recursive filters) operate on discrete-time samples, computing the output \(y\) as the convolution of the input \(\vec{x}\) with the filter coefficients \(\vec{h}\) as

(12)\[y(n) = \sum_{k=0}^{N-1}{ h(k) x(N-k-1) }\]

where \(\vec{h} = [h(0),h(1),\ldots,h(N-1)]\) is the filter impulse response. Notice that the output sample in the above equation is simply the vector dot product (see [dotprod](/doc/dotprod)) of the filter coefficients \(\vec{h}\) with the time-reversed sequence \(\vec{x}\).

../_images/firfilt-0.png

Figure 2 firfilt_crcf (finite impulse response filter) demonstration

An example of the firfilt object can be seen in Figure 2 in which a low-pass filter is applied to a signal to remove a high-frequency component.

Examples

An example of the firfilt interface is provided in the listing, below:

#include <liquid/liquid.h>

int main() {
    // options
    unsigned int h_len=21;  // filter order
    float h[h_len];         // filter coefficients

    // ... initialize filter coefficients ...

    // create filter object
    firfilt_crcf q = firfilt_crcf_create(h,h_len);

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

    // execute filter (repeat as necessary)
    {
        firfilt_crcf_push(q, x);    // push input sample
        firfilt_crcf_execute(q,&y); // compute output
    }

    // destroy filter object
    firfilt_crcf_destroy(q);
}

Interface

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

create()

Create a finite impulse response filter (firfilt) object by directly specifying the filter coefficients in an array

firfilt_rrrf = firfilt_rrrf_create(float * _h, unsigned int _n);
  • float * _h: filter coefficients

  • unsigned int _n: number of filter coefficients

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create(float * _h, unsigned int _n);
  • float * _h: filter coefficients

  • unsigned int _n: number of filter coefficients

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create(float complex * _h, unsigned int _n);
  • float complex * _h: filter coefficients

  • unsigned int _n: number of filter coefficients

  • returns new firfilt_cccf object

create_kaiser()

Create object using Kaiser-Bessel windowed sinc method

firfilt_rrrf = firfilt_rrrf_create_kaiser(unsigned int _n, float _fc, float _as, float _mu);
  • unsigned int _n: filter length

  • float _fc: filter normalized cut-off frequency

  • float _as: filter stop-band attenuation

  • float _mu: fractional sample offset

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create_kaiser(unsigned int _n, float _fc, float _as, float _mu);
  • unsigned int _n: filter length

  • float _fc: filter normalized cut-off frequency

  • float _as: filter stop-band attenuation

  • float _mu: fractional sample offset

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create_kaiser(unsigned int _n, float _fc, float _as, float _mu);
  • unsigned int _n: filter length

  • float _fc: filter normalized cut-off frequency

  • float _as: filter stop-band attenuation

  • float _mu: fractional sample offset

  • returns new firfilt_cccf object

create_rnyquist()

Create object from square-root Nyquist prototype. The filter length will be (2 k m + 1 ) samples long with a delay of ( k m + 1 ) samples.

firfilt_rrrf = firfilt_rrrf_create_rnyquist(int _type, unsigned int _k, unsigned int _m, float _beta, float _mu);
  • int _type: filter type (e.g. LIQUID_FIRFILT_RRC)

  • unsigned int _k: nominal samples per symbol

  • unsigned int _m: filter delay

  • float _beta: rolloff factor, 0 < beta <= 1

  • float _mu: fractional sample offset

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create_rnyquist(int _type, unsigned int _k, unsigned int _m, float _beta, float _mu);
  • int _type: filter type (e.g. LIQUID_FIRFILT_RRC)

  • unsigned int _k: nominal samples per symbol

  • unsigned int _m: filter delay

  • float _beta: rolloff factor, 0 < beta <= 1

  • float _mu: fractional sample offset

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create_rnyquist(int _type, unsigned int _k, unsigned int _m, float _beta, float _mu);
  • int _type: filter type (e.g. LIQUID_FIRFILT_RRC)

  • unsigned int _k: nominal samples per symbol

  • unsigned int _m: filter delay

  • float _beta: rolloff factor, 0 < beta <= 1

  • float _mu: fractional sample offset

  • returns new firfilt_cccf object

create_firdespm()

Create object from Parks-McClellan algorithm prototype

firfilt_rrrf = firfilt_rrrf_create_firdespm(unsigned int _h_len, float _fc, float _as);
  • unsigned int _h_len: filter length

  • float _fc: cutoff frequency

  • float _as: stop-band attenuation

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create_firdespm(unsigned int _h_len, float _fc, float _as);
  • unsigned int _h_len: filter length

  • float _fc: cutoff frequency

  • float _as: stop-band attenuation

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create_firdespm(unsigned int _h_len, float _fc, float _as);
  • unsigned int _h_len: filter length

  • float _fc: cutoff frequency

  • float _as: stop-band attenuation

  • returns new firfilt_cccf object

create_rect()

Create rectangular filter prototype; that is ( vec{h} = { 1, 1, 1, ldots 1 } )

firfilt_rrrf = firfilt_rrrf_create_rect(unsigned int _n);
  • unsigned int _n: length of filter

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create_rect(unsigned int _n);
  • unsigned int _n: length of filter

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create_rect(unsigned int _n);
  • unsigned int _n: length of filter

  • returns new firfilt_cccf object

create_dc_blocker()

Create DC blocking filter from prototype

firfilt_rrrf = firfilt_rrrf_create_dc_blocker(unsigned int _m, float _as);
  • unsigned int _m: prototype filter semi-length such that filter length is 2*m+1

  • float _as: prototype filter stop-band attenuation

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create_dc_blocker(unsigned int _m, float _as);
  • unsigned int _m: prototype filter semi-length such that filter length is 2*m+1

  • float _as: prototype filter stop-band attenuation

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create_dc_blocker(unsigned int _m, float _as);
  • unsigned int _m: prototype filter semi-length such that filter length is 2*m+1

  • float _as: prototype filter stop-band attenuation

  • returns new firfilt_cccf object

create_notch()

Create notch filter from prototype

firfilt_rrrf = firfilt_rrrf_create_notch(unsigned int _m, float _as, float _f0);
  • unsigned int _m: prototype filter semi-length such that filter length is 2*m+1

  • float _as: prototype filter stop-band attenuation

  • float _f0: center frequency for notch, _fc in

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_create_notch(unsigned int _m, float _as, float _f0);
  • unsigned int _m: prototype filter semi-length such that filter length is 2*m+1

  • float _as: prototype filter stop-band attenuation

  • float _f0: center frequency for notch, _fc in

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_create_notch(unsigned int _m, float _as, float _f0);
  • unsigned int _m: prototype filter semi-length such that filter length is 2*m+1

  • float _as: prototype filter stop-band attenuation

  • float _f0: center frequency for notch, _fc in

  • returns new firfilt_cccf object

recreate()

Re-create filter object of potentially a different length with different coefficients. If the length of the filter does not change, not memory reallocation is invoked.

firfilt_rrrf = firfilt_rrrf_recreate(firfilt_rrrf _q, float * _h, unsigned int _n);
  • firfilt_rrrf _q: original filter object

  • float * _h: pointer to filter coefficients

  • unsigned int _n: filter length

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_recreate(firfilt_crcf _q, float * _h, unsigned int _n);
  • firfilt_crcf _q: original filter object

  • float * _h: pointer to filter coefficients

  • unsigned int _n: filter length

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_recreate(firfilt_cccf _q, float complex * _h, unsigned int _n);
  • firfilt_cccf _q: original filter object

  • float complex * _h: pointer to filter coefficients

  • unsigned int _n: filter length

  • returns new firfilt_cccf object

copy()

Copy object including all internal objects and state

firfilt_rrrf = firfilt_rrrf_copy(firfilt_rrrf _q);
  • firfilt_rrrf _q:

  • returns new firfilt_rrrf object

firfilt_crcf = firfilt_crcf_copy(firfilt_crcf _q);
  • firfilt_crcf _q:

  • returns new firfilt_crcf object

firfilt_cccf = firfilt_cccf_copy(firfilt_cccf _q);
  • firfilt_cccf _q:

  • returns new firfilt_cccf object

destroy()

Destroy filter object and free all internal memory

int = firfilt_rrrf_destroy(firfilt_rrrf _q);
  • firfilt_rrrf _q:

  • returns standard error code

int = firfilt_crcf_destroy(firfilt_crcf _q);
  • firfilt_crcf _q:

  • returns standard error code

int = firfilt_cccf_destroy(firfilt_cccf _q);
  • firfilt_cccf _q:

  • returns standard error code

reset()

Reset filter object’s internal buffer

int = firfilt_rrrf_reset(firfilt_rrrf _q);
  • firfilt_rrrf _q:

  • returns standard error code

int = firfilt_crcf_reset(firfilt_crcf _q);
  • firfilt_crcf _q:

  • returns standard error code

int = firfilt_cccf_reset(firfilt_cccf _q);
  • firfilt_cccf _q:

  • returns standard error code

print()

Print filter object information to stdout

int = firfilt_rrrf_print(firfilt_rrrf _q);
  • firfilt_rrrf _q:

  • returns standard error code

int = firfilt_crcf_print(firfilt_crcf _q);
  • firfilt_crcf _q:

  • returns standard error code

int = firfilt_cccf_print(firfilt_cccf _q);
  • firfilt_cccf _q:

  • returns standard error code

set_scale()

Set output scaling for filter

int = firfilt_rrrf_set_scale(firfilt_rrrf _q, float _scale);
  • firfilt_rrrf _q: filter object

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

  • returns standard error code

int = firfilt_crcf_set_scale(firfilt_crcf _q, float _scale);
  • firfilt_crcf _q: filter object

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

  • returns standard error code

int = firfilt_cccf_set_scale(firfilt_cccf _q, float complex _scale);
  • firfilt_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 = firfilt_rrrf_get_scale(firfilt_rrrf _q, float * _scale);
  • firfilt_rrrf _q: filter object

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

  • returns standard error code

int = firfilt_crcf_get_scale(firfilt_crcf _q, float * _scale);
  • firfilt_crcf _q: filter object

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

  • returns standard error code

int = firfilt_cccf_get_scale(firfilt_cccf _q, float complex * _scale);
  • firfilt_cccf _q: filter object

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

  • returns standard error code

push()

Push sample into filter object’s internal buffer

int = firfilt_rrrf_push(firfilt_rrrf _q, float _x);
  • firfilt_rrrf _q: filter object

  • float _x: single input sample

  • returns standard error code

int = firfilt_crcf_push(firfilt_crcf _q, float complex _x);
  • firfilt_crcf _q: filter object

  • float complex _x: single input sample

  • returns standard error code

int = firfilt_cccf_push(firfilt_cccf _q, float complex _x);
  • firfilt_cccf _q: filter object

  • float complex _x: single input sample

  • returns standard error code

write()

Write block of samples into filter object’s internal buffer

int = firfilt_rrrf_write(firfilt_rrrf _q, float * _x, unsigned int _n);
  • firfilt_rrrf _q: filter object

  • float * _x: buffer of input samples

  • unsigned int _n: number of input samples

  • returns standard error code

int = firfilt_crcf_write(firfilt_crcf _q, float complex * _x, unsigned int _n);
  • firfilt_crcf _q: filter object

  • float complex * _x: buffer of input samples

  • unsigned int _n: number of input samples

  • returns standard error code

int = firfilt_cccf_write(firfilt_cccf _q, float complex * _x, unsigned int _n);
  • firfilt_cccf _q: filter object

  • float complex * _x: buffer of input samples

  • unsigned int _n: number of input samples

  • returns standard error code

execute()

Execute vector dot product on the filter’s internal buffer and coefficients

int = firfilt_rrrf_execute(firfilt_rrrf _q, float * _y);
  • firfilt_rrrf _q: filter object

  • float * _y: pointer to single output sample

  • returns standard error code

int = firfilt_crcf_execute(firfilt_crcf _q, float complex * _y);
  • firfilt_crcf _q: filter object

  • float complex * _y: pointer to single output sample

  • returns standard error code

int = firfilt_cccf_execute(firfilt_cccf _q, float complex * _y);
  • firfilt_cccf _q: filter object

  • float complex * _y: pointer to single output sample

  • returns standard error code

execute_one()

Execute filter on one sample, equivalent to push() and execute()

int = firfilt_rrrf_execute_one(firfilt_rrrf _q, float _x, float * _y);
  • firfilt_rrrf _q: filter object

  • float _x: single input sample

  • float * _y: pointer to single output sample

  • returns standard error code

int = firfilt_crcf_execute_one(firfilt_crcf _q, float complex _x, float complex * _y);
  • firfilt_crcf _q: filter object

  • float complex _x: single input sample

  • float complex * _y: pointer to single output sample

  • returns standard error code

int = firfilt_cccf_execute_one(firfilt_cccf _q, float complex _x, float complex * _y);
  • firfilt_cccf _q: filter object

  • float complex _x: single input sample

  • float complex * _y: pointer to single output sample

  • returns standard error code

execute_block()

Execute the filter on a block of input samples; in-place operation is permitted (_x and _y may point to the same place in memory)

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

  • float * _x: pointer to input array

  • unsigned int _n: number of input, output samples

  • float * _y: pointer to output array

  • returns standard error code

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

  • float complex * _x: pointer to input array

  • unsigned int _n: number of input, output samples

  • float complex * _y: pointer to output array

  • returns standard error code

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

  • float complex * _x: pointer to input array

  • unsigned int _n: number of input, output samples

  • float complex * _y: pointer to output array

  • returns standard error code

get_length()

Get length of filter object (number of internal coefficients)

unsigned int = firfilt_rrrf_get_length(firfilt_rrrf _q);
  • firfilt_rrrf _q:

  • returns something good

unsigned int = firfilt_crcf_get_length(firfilt_crcf _q);
  • firfilt_crcf _q:

  • returns something good

unsigned int = firfilt_cccf_get_length(firfilt_cccf _q);
  • firfilt_cccf _q:

  • returns something good

get_coefficients()

Get pointer to coefficients array

const float * = firfilt_rrrf_get_coefficients(firfilt_rrrf _q);
  • firfilt_rrrf _q:

  • returns something good

const float * = firfilt_crcf_get_coefficients(firfilt_crcf _q);
  • firfilt_crcf _q:

  • returns something good

const float complex * = firfilt_cccf_get_coefficients(firfilt_cccf _q);
  • firfilt_cccf _q:

  • returns something good

copy_coefficients()

Copy internal coefficients to external buffer

int = firfilt_rrrf_copy_coefficients(firfilt_rrrf _q, float * _h);
  • firfilt_rrrf _q: filter object

  • float * _h: pointer to output coefficients array

  • returns standard error code

int = firfilt_crcf_copy_coefficients(firfilt_crcf _q, float * _h);
  • firfilt_crcf _q: filter object

  • float * _h: pointer to output coefficients array

  • returns standard error code

int = firfilt_cccf_copy_coefficients(firfilt_cccf _q, float complex * _h);
  • firfilt_cccf _q: filter object

  • float complex * _h: pointer to output coefficients array

  • returns standard error code

freqresponse()

Compute complex frequency response of filter object

int = firfilt_rrrf_freqresponse(firfilt_rrrf _q, float _fc, liquid_float_complex * _H);
  • firfilt_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 = firfilt_crcf_freqresponse(firfilt_crcf _q, float _fc, liquid_float_complex * _H);
  • firfilt_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 = firfilt_cccf_freqresponse(firfilt_cccf _q, float _fc, liquid_float_complex * _H);
  • firfilt_cccf _q: filter object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

groupdelay()

Compute and return group delay of filter object

float = firfilt_rrrf_groupdelay(firfilt_rrrf _q, float _fc);
  • firfilt_rrrf _q: filter object

  • float _fc: frequency to evaluate

  • returns something good

float = firfilt_crcf_groupdelay(firfilt_crcf _q, float _fc);
  • firfilt_crcf _q: filter object

  • float _fc: frequency to evaluate

  • returns something good

float = firfilt_cccf_groupdelay(firfilt_cccf _q, float _fc);
  • firfilt_cccf _q: filter object

  • float _fc: frequency to evaluate

  • returns something good