frequency filtering

related to digital signal processing

digital filters are tools used to attenuate or remove frequencies or change phase relationships between frequencies


filter variants

  • low-pass: low frequencies remain
  • high-pass: high frequencies remain
  • band-pass: a range of frequencies remains
  • band-reject: a range of frequencies is attenuated
  • all-pass: change phases
  • filter bank: multiple band-bass filters and multiple outputs. low-pass and high-pass can be used at the edges
  • equaliser: filter bank with output amplitudes modifiable and outputs recombined. other implementations possible

common filter types

  • windowed sinc

    • pro: extremely good frequency separation, custom frequency responses possible, inherent unity gain if impulse response is set up correctly
    • con: parameter changes require recreation of impulse response array
    • based on convolving the input samples with a centered sinc function array of limited length where the edges slowy fade to zero
    • the filters impulse response is a sinc function in the time domain and its frequency response is a rectangular function
    • the longer the impulse response kernel, the smaller the transition bandwidth
    • addition of kernels: adding another filter into the stop-band of another
    • convolution of kernels: adding another filter into the pass-band of another
    • take values of the sinc function, window it with a blackman window which performs well in this context, and use this array for convolution with an input signal
    • a high-pass filter can be created by spectrally inverting or spectrally reversing the impulse response
    • a band-pass filter can be created by convolution of low- and high-pass filter impulse responses
    • a band-reject filter can be created by summing low-pass and high-pass filter impulse responses
  • state-variable filter

    • pro: low/high/band/notch/peak/all at once via multiple outputs
    • con: ensuring unity gain and using multiple passes adds processing costs
    • related to the biquad filter
  • one-pole, one-zero, multi-pole

    • con: stop-band rises the higher the cutoff
  • biquad
  • moving average

    • con: almost useless for removing frequencies because it filters with large ripples in the frequency spectrum

    • pro: good for smoothing and anywhere where time domain shape matters more than frequencies. a centered moving average creates no shift between input and output signal

    • moving median and similar also possible


  • stopband: band where frequencies are attenuated most
  • passband: band where frequencies are kept
  • transition band: slope between stop and passband
  • cutoff: start of the transition band at the passband. band-pass or band-reject filter have two cutoff frequencies
  • q-factor: characterises a resonators bandwidth relative to its centre frequency
  • passes: filter output can be re-fed into the filter to possible increase the frequency separation
  • poles: number of coefficients to shape the filter response
  • difference equation: maps input samples to output samples in the case of fir filter implementations for example

tips for implementing digital filters

  • to make a windowed-sinc filter give seamless output when called frame-wise on continuous data, carryover data from the convolution must be kept between calls. convolution can be made seamless by writing input-length samples into output and the additional impulse-response-length samples that would occur into an additional carryover buffer that is written into the beginning of the output of the next call
  • to make multipass filters seamless you would need to keep a state value per pass
  • c code for seamless convolution and windowed-sinc filtering can be found in sph-sp
  • processing costs for windowed-sincs with frequently changing parameters can be reduced by reducing the resolution of changes. for example, only applying parameter changes for every 960 samples
  • band-pass filters can be optimised to become only low-pass or high-pass filters at the edges

exemplary one-pole filter implementations

x: input, y: output, alpha: cutoff as fraction of the sample rate


for i from 1 to n
  y[i] := alpha * (y[i-1] + x[i] - x[i-1])


for i from 1 to n
  y[i] := y[i-1] + alpha * (x[i] - y[i-1])

exemplary state-variable filter implementation in c

  • defines a routine for a fast filter that supports multiple filter types in one
  • only one output is taken but comments show how other filter results could be taken instead
  • state is to make subsequent call results for continuous data seamless
  • state must hold two elements and is allocated and owned by the caller
  • cutoff is as a fraction of the sample rate between 0 and 0.5
  • based on the state-variable filter described here:

    • http://www.cytomic.com/technical-papers
    • http://www.earlevel.com/main/2016/02/21/filters-for-synths-starting-out/
#include <math.h>
#include <inttypes.h>

void state_variable_filter(double* out, double* in, double in_count, double cutoff, double q_factor, double* state) {
  double a1;
  double a2;
  double g;
  double ic1eq;
  double ic2eq;
  uint32_t i;
  double k;
  double v0;
  double v1;
  double v2;
  ic1eq = state[0];
  ic2eq = state[1];
  g = tan(M_PI * cutoff);
  k = 2 - 2 * q_factor;
  a1 = 1 / (1 + g * (g + k));
  a2 = g * a1;
  for (i = 0; i < in_count; i = (1 + i)) {
    v0 = in[i];
    v1 = a1 * ic1eq + a2 * (v0 - ic2eq);
    v2 = ic2eq + (g * v1);
    ic1eq = 2 * v1 - ic1eq;
    ic2eq = 2 * v2 - ic2eq;
    // low-pass
    out[i] = v2;

    // instead of the low-pass result, other results could be written to out,
    // or multiple results if multiple output arrays are made available
    // high-pass
    //out[i] = v0 - k * v - v2;
    // band-pass
    //out[i] = v1;
    // band-reject
    //out[i] = v0 - k * v1;
    // peak
    //out[i] = 2 * v2 - v0 + k * v1;
    // all-pass
    //out[i] = v0 - 2 * k * v1;
  state[0] = ic1eq;
  state[1] = ic2eq;