frequency filtering

related to digital signal processing

digital filters are tools used to attenuate or remove frequencies or change phase relationships between frequencies. it is an effect on the amplitude of frequency partials.


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 can 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;