Building FX, Part IV - Low Pass Filters
This is the second in a series teaching the basics of how to build a filter in Reaktor. I will build some of the easiest filters possible, then expand on the concept to design a low pass filter with cutoff and Q controls.
It is very difficult to find resources on filters that do not assume advanced knowledge of math, electrical engineering, or digital signal processing. It is my hope to avoid this pitfall and create something more accessible. With that in mind, this tutorial will focus on the basic structure of filters, and familiarize the reader with some basic concepts before attempting anything too difficult.
THE MOST BASIC FILTERS
To begin with, let’s check out the world’s simplest FIR filter. It looks like this:
In case you’ve never encountered one before, the module marked ‘T’ is a Unit Delay module. it’s function is to delay the input by a single sample. So you can see that this structure simply averages the current and previous input samples.
Despite it’s simplicity, this filter has a fairly defined frequency response:
Now let’s talk about the term Finite Impulse Response and what it means. An ‘Impulse’ means a signal that is equal to 1 for a single sample period, then drops to 0 (IE the inputs to the macro are 1, 0, 0, 0, 0…). The ‘Impulse Response’ then, is the output of the filter in response to these inputs, in this case (0.5, 0.5, 0, 0, 0…). The filter drops to 0 in response to the impulse, fairly quickly, over a finite period time. Hence, the filter is said to have a Finite Impulse Response.
We can edit the filter to be an IIR filter like so:
All I have done is edit it so that the input to the Unit Delay is the output (y[n]) of the module rather than the input(x[n]). While this changes the frequency response of the structure quite visibly, it still acts as a low pass filter.
The Impulse Response of this filter will be 1, 0.5, 0.25, 0.125, 0.0625, etc, etc. The response will trend towards 0, but it will never actually reach it (in an ideal world; practically speaking, a digital system can only hold a certain range of values and will eventually reach 0 as well). Hence, this structure is referred to as an Infinite Impulse Response filter.
While these filters have the advantage of being extremely simple, they have the disadvantage of being mostly useless. Without knobs to control resonance and frequency cutoff points, they are only useful in situations that call for a static filter with their precise frequency response – not very useful.
THE BI-QUAD FILTER
Okay then, let’s look at a more useful filter design. We can start by recognizing that expanding the above structures is quite simple. Here’s an expanded FIR:
It may look like I’ve rearranged to order of things somewhat from our first FIR filter. However, notice that we can rewrite the first filter like so:
So in fact, the structure is practically identical. However, instead of simply multiplying each value by 0.5, each value is multiplied by a variable, marked b0, b1 and b2. These values are called filter coefficients. The values of b0, b1, and b2 will determine the frequency response of the filter.
The number of unit delays a filter has is equal to the order of the filter, so this is a 2nd order filter. It may also be referred to a two zero filter.
We can easily expand the IIR filter as well:
The IIR design is a 2nd order filter as well, also called a two pole filter.
A typical digital filter will contain both FIR and IIR elements. To achieve this effect, often an IIR filter is simply attached to the output of an FIR filter like so:
So, if you hear a filter referred to as a ‘two pole, two zero’, it means it has a 2nd order FIR section followed by a 2nd order IIR section (these are often referred to as Bi-Quad filters as well).
So you can see, the actual structure of a digital filter is pretty simple to grasp. Unfortunately, we still need to define the filter coefficients, which is where the math gets a lot more intense.
There are many known ways to calculate filter coefficients, each with their own advantages and disadvantages. Much of the math involved is far beyond the scope of this tutorial, and often beyond my ability to understand as well.
Fortunately, there are loads of resources available online detailing how to calculate filter coefficients – it is not necessary to derive them from scratch ourselves. One of the documents I found most useful as a beginner can be found here, by Robert Bristow-Johnson, a fairly well known name in the world of Digital Signal Processing. In the document, he details several types of digital filter, but each shares the same FIR/IIR structure – all that changes is the values of the coefficients.
For the sake of this tutorial, I’ll translate the low pass filter into Reaktor Primary modules. As long as you pay careful attention to the order of operations, doing all of this math in Reaktor is quite simple.
We’ll start with some preliminary calculations, as defined in the paper:
If you’re following very closely, you might have noticed I omitted something. The freq*2 / sampling rate should also be multiplied by π. As it turns out, the Sine modules in Reaktor Primary have some strange behavior – the value at the input is scaled by π.
So the multiplication by π is already taken care of for us automatically (as a note, the Sin module in Reaktor Core does not work this way, you can feed them both the same value and they will give different outputs). This can be pretty confusing, so it is important to take care when using the Sine/Cosine module. For this reason and others, I prefer to use Reaktor Core to program filters, however this tutorial is in Primary for the sake of accessibility.
Moving along, using the values we just calculated, Bristow-Johnson defines the low pass coefficients like so:
b0 = (1 – cos(w0))/2
b1 = 1 – cos(w0)
b2 = (1 – cos(w0))/2
a0 = 1 + alpha
a1 = -2*cos(w0)
a2 = 1 – alpha
This is easy enough to translate into Reaktor:
Again, I made a few changes to the text. Specifically, I multiplied both a1 and a2 by -1. This is because in the text, the values are subtracted in the final filter structure, yet in the simple examples I built, they are added. Basically, we’ll be adding a negative rather than subtracting a positive – in the end, the result is identical.
Towards the top of the document, Bristow-Johnson mentions this equation:
y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] – (a1/a0)*y[n-1] – (a2/a0)*y[n-2]
This is referred to as a difference equation. This may look complicated, but the reality is we have already defined every single variable in the equation, so it is a simple matter of plugging those variables into the proper place: x[n] is the input to our filter, x[n-1] is the input sent thru a single Unit Delay. y[n] is the filter output, y[n-1] is the filter output sent thru a single Unit Delay.
In fact, the FIR and IIR sections I built above mimic this equation almost precisely – the IIR section I built adds the y[n-1] and y[n-2] values, and Bristow-Johnson’s equation subtracts them (we already fixed this above!). The second difference is the use of the a0 coefficient, which is not used in the structures above. I created another simple macro to get rid of the a0 references:
Now it’s a simple matter of wiring everything together like so:
Now we have a low pass filter, which you can confirm by plugging the macro into the EzFFT Filter Analyzer I posted from the previous tutorial. Here’s what the frequency response should look like (cutoff set to 83, Q set to 1):
To change this into another filter type, you would simply replace the Coefficient macro with another macro. Bristow-Johnson details many filter types to choose from (some filter types require changes to the PreCalc macro as well, check the paper for details).
I hope you have found this tutorial to be useful. I have done my best to be as clear as possible, but if anything needs further explaining please feel free to ask, I’ll be happy to help! If there is sufficient interest in continuing filter tutorials, next time I would like to focus on some more math, particularly difference equations, how to create them, and how to translate them into Reaktor filters.
You can download a version of EzFFT Filter Analyzer with the new low pass filter included here. If you have any questions or suggestions, please feel free to post them in the comments. Thanks for reading!