2019-06-17

related to digital signal processing

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

- algorithm for a state-variable filter on cytomic.com
- elementary filters on dsprelated.com
- first section on digital filters on dspguide.com
- guides on earlevel.com
- tomroelandts.com how to create a simple windowed-sinc low-pass filter and other guides
- wikipedia: fir filter, iir filter, low-pass filter, q-factor, sinc filter, state-variable filter

- 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

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

- 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

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

high-pass

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

low-pass

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

- 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;
}
```