Finite Impulse Reseponse Decimator (firdecim)

The firdecim object family implements a basic decimator with an integer output-to-input resampling ratio \(D\). For example, an input signal sampled at 96 MHz is decimated by a factor \(D=25\) results in an output signal with a sample rate 3.84 MHz. It is essentially just a firfilt object which operates on a block of samples at a time. An example of the firdecimator can be seen in [fig-filter-firdecim-crcf].

../_images/firdecim-0.png

Figure 1 firdecim_crcf example with \(D=4\), compensating for filter delay.

Filter Delay

The delay of the decimator will depend upon the filter coefficients themselves. Normally, an FIR filter has symmetric coefficients and has a length \(2Mm+1\) in which case the output delay is \(Mm\) samples, where \(M\) is the decimation rate and \(m\) is the filter semi-length. But if the filter coefficients are _not_ symmetric or if the filter length follows a different length, the delay will be something different. Unfortunately the decimator cannot compensate for this automatically since it doesn’t know the filter response. The delay could even be a fraction of a sample.

If the filter does have a length \(2Mm+1\) then the output delay will be \(m\) samples; this is one of the reasons designing a filter of this length is convenient. If this is the case, you can then just ignore the first \(m\) output samples (e.g. after decimation), and then flush \(m\) blocks of \(M\) samples each through the filter to compensate for that delay.

Example

An example of the firdecim interface is listed below.

#include <liquid/liquid.h>

int main() {
    // options
    unsigned int M = 4;         // decimation factor
    unsigned int h_len = 21;    // filter length

    // design filter and create decimator object
    float h[h_len];             // filter coefficients
    firdecim_crcf q = firdecim_crcf_create(M,h,h_len);

    // generate input signal and decimate
    float complex x[M];         // input samples
    float complex y;            // output sample

    // run decimator (repeat as necessary)
    {
        firdecim_crcf_execute(q, x, &y);
    }

    // destroy decimator object
    firdecim_crcf_destroy(q);
}

Interface

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

create()

Create decimator from external coefficients

firdecim_rrrf = firdecim_rrrf_create(unsigned int _M, float * _h, unsigned int _h_len);
  • unsigned int _M: decimation factor

  • float * _h: filter coefficients

  • unsigned int _h_len: filter length

  • returns new firdecim_rrrf object

firdecim_crcf = firdecim_crcf_create(unsigned int _M, float * _h, unsigned int _h_len);
  • unsigned int _M: decimation factor

  • float * _h: filter coefficients

  • unsigned int _h_len: filter length

  • returns new firdecim_crcf object

firdecim_cccf = firdecim_cccf_create(unsigned int _M, float complex * _h, unsigned int _h_len);
  • unsigned int _M: decimation factor

  • float complex * _h: filter coefficients

  • unsigned int _h_len: filter length

  • returns new firdecim_cccf object

create_kaiser()

Create decimator from filter prototype prototype (Kaiser-Bessel windowed-sinc function)

firdecim_rrrf = firdecim_rrrf_create_kaiser(unsigned int _M, unsigned int _m, float _as);
  • unsigned int _M: decimation factor

  • unsigned int _m: filter delay

  • float _as: stop-band attenuation

  • returns new firdecim_rrrf object

firdecim_crcf = firdecim_crcf_create_kaiser(unsigned int _M, unsigned int _m, float _as);
  • unsigned int _M: decimation factor

  • unsigned int _m: filter delay

  • float _as: stop-band attenuation

  • returns new firdecim_crcf object

firdecim_cccf = firdecim_cccf_create_kaiser(unsigned int _M, unsigned int _m, float _as);
  • unsigned int _M: decimation factor

  • unsigned int _m: filter delay

  • float _as: stop-band attenuation

  • returns new firdecim_cccf object

create_prototype()

Create decimator object from filter prototype

firdecim_rrrf = firdecim_rrrf_create_prototype(int _type, unsigned int _M, unsigned int _m, float _beta, float _dt);
  • int _type: filter type (e.g. LIQUID_FIRFILT_RCOS)

  • unsigned int _M: interpolation factor

  • unsigned int _m: filter delay (symbols)

  • float _beta: excess bandwidth factor

  • float _dt: fractional sample delay

  • returns new firdecim_rrrf object

firdecim_crcf = firdecim_crcf_create_prototype(int _type, unsigned int _M, unsigned int _m, float _beta, float _dt);
  • int _type: filter type (e.g. LIQUID_FIRFILT_RCOS)

  • unsigned int _M: interpolation factor

  • unsigned int _m: filter delay (symbols)

  • float _beta: excess bandwidth factor

  • float _dt: fractional sample delay

  • returns new firdecim_crcf object

firdecim_cccf = firdecim_cccf_create_prototype(int _type, unsigned int _M, unsigned int _m, float _beta, float _dt);
  • int _type: filter type (e.g. LIQUID_FIRFILT_RCOS)

  • unsigned int _M: interpolation factor

  • unsigned int _m: filter delay (symbols)

  • float _beta: excess bandwidth factor

  • float _dt: fractional sample delay

  • returns new firdecim_cccf object

copy()

Copy object including all internal objects and state

firdecim_rrrf = firdecim_rrrf_copy(firdecim_rrrf _q);
  • firdecim_rrrf _q:

  • returns new firdecim_rrrf object

firdecim_crcf = firdecim_crcf_copy(firdecim_crcf _q);
  • firdecim_crcf _q:

  • returns new firdecim_crcf object

firdecim_cccf = firdecim_cccf_copy(firdecim_cccf _q);
  • firdecim_cccf _q:

  • returns new firdecim_cccf object

destroy()

Destroy decimator object, freeing all internal memory

int = firdecim_rrrf_destroy(firdecim_rrrf _q);
  • firdecim_rrrf _q:

  • returns standard error code

int = firdecim_crcf_destroy(firdecim_crcf _q);
  • firdecim_crcf _q:

  • returns standard error code

int = firdecim_cccf_destroy(firdecim_cccf _q);
  • firdecim_cccf _q:

  • returns standard error code

print()

Print decimator object properties to stdout

int = firdecim_rrrf_print(firdecim_rrrf _q);
  • firdecim_rrrf _q:

  • returns standard error code

int = firdecim_crcf_print(firdecim_crcf _q);
  • firdecim_crcf _q:

  • returns standard error code

int = firdecim_cccf_print(firdecim_cccf _q);
  • firdecim_cccf _q:

  • returns standard error code

reset()

Reset decimator object internal state

int = firdecim_rrrf_reset(firdecim_rrrf _q);
  • firdecim_rrrf _q:

  • returns standard error code

int = firdecim_crcf_reset(firdecim_crcf _q);
  • firdecim_crcf _q:

  • returns standard error code

int = firdecim_cccf_reset(firdecim_cccf _q);
  • firdecim_cccf _q:

  • returns standard error code

get_decim_rate()

Get decimation rate

unsigned int = firdecim_rrrf_get_decim_rate(firdecim_rrrf _q);
  • firdecim_rrrf _q:

  • returns something good

unsigned int = firdecim_crcf_get_decim_rate(firdecim_crcf _q);
  • firdecim_crcf _q:

  • returns something good

unsigned int = firdecim_cccf_get_decim_rate(firdecim_cccf _q);
  • firdecim_cccf _q:

  • returns something good

set_scale()

Set output scaling for decimator

int = firdecim_rrrf_set_scale(firdecim_rrrf _q, float _scale);
  • firdecim_rrrf _q: decimator object

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

  • returns standard error code

int = firdecim_crcf_set_scale(firdecim_crcf _q, float _scale);
  • firdecim_crcf _q: decimator object

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

  • returns standard error code

int = firdecim_cccf_set_scale(firdecim_cccf _q, float complex _scale);
  • firdecim_cccf _q: decimator object

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

  • returns standard error code

get_scale()

Get output scaling for decimator

int = firdecim_rrrf_get_scale(firdecim_rrrf _q, float * _scale);
  • firdecim_rrrf _q: decimator object

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

  • returns standard error code

int = firdecim_crcf_get_scale(firdecim_crcf _q, float * _scale);
  • firdecim_crcf _q: decimator object

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

  • returns standard error code

int = firdecim_cccf_get_scale(firdecim_cccf _q, float complex * _scale);
  • firdecim_cccf _q: decimator object

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

  • returns standard error code

freqresp()

Compute complex frequency response (H) of decimator on prototype filter coefficients at a specific frequency (f_c)

int = firdecim_rrrf_freqresp(firdecim_rrrf _q, float _fc, liquid_float_complex * _H);
  • firdecim_rrrf _q: decimator object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

int = firdecim_crcf_freqresp(firdecim_crcf _q, float _fc, liquid_float_complex * _H);
  • firdecim_crcf _q: decimator object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

int = firdecim_cccf_freqresp(firdecim_cccf _q, float _fc, liquid_float_complex * _H);
  • firdecim_cccf _q: decimator object

  • float _fc: normalized frequency for evaluation

  • liquid_float_complex * _H: pointer to output complex frequency response

  • returns standard error code

execute()

Execute decimator on _M input samples

int = firdecim_rrrf_execute(firdecim_rrrf _q, float * _x, float * _y);
  • firdecim_rrrf _q: decimator object

  • float * _x: input samples

  • float * _y: output sample pointer

  • returns standard error code

int = firdecim_crcf_execute(firdecim_crcf _q, float complex * _x, float complex * _y);
  • firdecim_crcf _q: decimator object

  • float complex * _x: input samples

  • float complex * _y: output sample pointer

  • returns standard error code

int = firdecim_cccf_execute(firdecim_cccf _q, float complex * _x, float complex * _y);
  • firdecim_cccf _q: decimator object

  • float complex * _x: input samples

  • float complex * _y: output sample pointer

  • returns standard error code

execute_block()

Execute decimator on block of _n*_M input samples

int = firdecim_rrrf_execute_block(firdecim_rrrf _q, float * _x, unsigned int _n, float * _y);
  • firdecim_rrrf _q: decimator object

  • float * _x: input array

  • unsigned int _n: number of _output_ samples

  • float * _y: output array,

  • returns standard error code

int = firdecim_crcf_execute_block(firdecim_crcf _q, float complex * _x, unsigned int _n, float complex * _y);
  • firdecim_crcf _q: decimator object

  • float complex * _x: input array

  • unsigned int _n: number of _output_ samples

  • float complex * _y: output array,

  • returns standard error code

int = firdecim_cccf_execute_block(firdecim_cccf _q, float complex * _x, unsigned int _n, float complex * _y);
  • firdecim_cccf _q: decimator object

  • float complex * _x: input array

  • unsigned int _n: number of _output_ samples

  • float complex * _y: output array,

  • returns standard error code