Digital filters: the basic logic behind…
When building your schematic you often run into a situation when input of the module receives data periodically. It is rather obvious when the input is stream, but similar situation may occur even with green/ruby triggers, mouse events, midi etc. Such periodical stream of data is called Digital Signal (and it will be called that way further on). In such cases you often run into a situation, when you need the input to be “smoother” and not change so rapidly, or exact opposite – extract only the changes in the signal. Here digital filters come to the scene.
To understand a basic logic behind the filters let’s create a model situation:
You have a knob which outputs green signal and a module that operates on stream and receives this knob as an input (a simple “gain” module for this example). When you connect the knob to the module and turn it, you experience a zipping noise (green changes very slowly compared to sample-rate of the stream, so when the value is transformed to stream it changes is “steps”). You need to “smooth” the input from the knob.
Finite Impulse Response Filter (FIR)
One obvious way to do it is to create a module (or code block) which has one input and one output. And the module works in a way that output is 50%value of current input + 50% value of previous input. This obviously makes the change between current and previous value to be half as strong at the output – you basically average the values over time.
Now, how do we analyze what the filter actually does? The most common way, to analyze a filter is to analyze its impulse response. We feed the filter with input that is 1 on first sample and 0 on all others (There is a very handy primitive in FS that outputs impulse) and measure the output of the filter into the graph (the impulse response). This particular filter will output 0.5, 0.5, 0, 0, 0, … (In this case it is pretty obvious why – you can do the math yourself very easily). As you can see, the impulse response becomes zero after second sample – the impulse response is 2 samples long = Finite. In fact, you can see it is identical with the coefficients of the filter.
This is very handy property of FIR filters – you can measure an Impulse response of a device you want to mimic and feed the impulse response into FIR filter. The FIR filter will then simulate that device, as long as the device preforms only static filtering and non-modulating delays. Commonly this is used to implement guitar cabinet simulation and reverb simulation. FIR filter is also called Convolver, because it preforms convolution = directly applies an impulse response to a signal.
Another analysis we can do, is to convert the time-domain impulse response into frequency-domain using Discrete Fourier Transform (DFT – which is mainly implemented via FFT algorithm). This will show how the filter affects certain frequencies in the spectrum (how it changes amplitudes and phases). For this particular filter we can see, that it does not affect the low-frequencies (especially DC – holding constant value = frequency of zero Hz) and reduces the highest frequencies to zero.
In fact, you can use Inverse Fourier Transform to create impulse response with any desired amplitude/phase response (including linear phase) and feed it to FIR filter. How to do that is beyond this article, but there are several important properties to mention. First of all frequencies in DFT are scaled in linear fashion, however humans intuitively work in logarithmic scale. FIR filters therefore have exceptional razor-blade precision in high frequencies, but very poor resolution in low frequencies. To alter low frequency content more precisely, you need to increase the size of impulse response and CPU cost of FIR filter rises rapidly. Keep in mind that for 1000 samples long IR the filter has to do 1000 multiplications and 999 additions plus storing previous inputs. Even though there are FIR filter implementations that reduce the CPU load significantly (frequency domain convolvers) FIR filters are still the most CPU heavy filters out there.
- simple to design
- very flexible amplitude/phase response (suitable for device modeling and linear phase filtering)
- sharp cutoffs possible in high frequencies
- CPU heavy
- Low precision of amplitude response in low frequencies
- very hard to implement modulation/morphing in time
Infinite Impulse Response Filter (IIR)
Another obvious and similarly simple way to “smooth” the knob output is to make the output 50% current input + 50% previous output. This will result in similar reduction of “fast changes” and similarly preserves “holding values”, but there are some interesting properties to this type of topology. FIR filters only used inputs, to calculate the output – they used feed-forward topology. This filter uses also the output, so it introduces feed-backward.
Now, let’s do the same analysis as we did with FIR filter – let’s measure the impulse response and DFT of that impulse response. Clearly you can see, the impulse response goes like this: 0.5, 0.25, 0.125, 0.0625,.. The values get smaller and smaller, but never really reach zero – the impulse response is infinite. That’s in theory though – in reality the values get smaller and smaller until they are rounded to zero and impulse response ends. Similarly in real-life IIR filters, the impulse response decays and blends with the noise to a degree, that it disappears in it. Also notice, that unlike in FIR filter, where IR was identical with the coefficients, here the relationship is much more complex.
IIR filters are much superior to FIR filters in some situations. First of all because their impulse response is infinite, it is not hard to guess that even simple IIR filters can affect low frequency content with very high precision (frequency-wise). They are however much more sensitive to rounding error and not all combinations of coefficients do work (filters with 10 and more coefficients rarely work). Imagine for example the output would be 200% the previous output. The value would double each sample until it reaches clipping level (and potentially may damage the speakers and ears of a listener) or reach “infinity” and all math breaks at that point. You definitely need to be more careful when designing them. Also, because their impulse response decays to zero, they are very likely to introduce denormals – always add some denormal protection into the filter design.
The big advantage of IIR filter is, that you in fact need only a handful of coefficients to create complex amplitude/phase responses. It is a common practice to create a chain of simple filters to implement complicated responses. To calculate the right coefficients for an IIR filter is unfortunately high-end math (Z-tranform, least squares method, evolutionary algorithm,… just to mention few possible ways). As a designer you probably don’t want to become a mathematician just to be able to finish your project. Fortunately, mathematicians out there have done the work for you and published many most common filter-response-types. Many of which were implemented in flowstone too (RBJ Biquad Filters for example).
- lighter on CPU
- big variety of responses, even with simple filters
- easy to “parametrize” and modulate
- superior resolution in low frequencies
- many “ready to go” examples
- risk of instability
- high probability of denormals
- require complex mathematics to develop “from scratch”
- more sensitive to rounding errors