Audio filter and equalizers ed

Problems with a naive equalizer ed

Task
You want to change the volume of an audio signal, but only within a certain frequency range. All other frequencies should stay untouched.

Naive idea ed

This already screams to be solved via Fast Fourier Transforms (FFT) - the signal (an array of real numbers) is transformed into the frequency domain, i.e. you get a new array of complex numbers, where each entry represents the intensity (and phase information) for a specific frequency inside the original signal.

It is then trivial to scale all entries inside the desired frequency range up or down and then transforming the signal back into its time domain.

Problem ed

Yes, this works perfectly when applied to the whole audio array at once (e.g. the whole 5 min song).

But what if you want a more flexible "live" audio effect. Then the signal comes in smaller chunks, let's say 1024 numbers at a time. If you simply try to apply the naive equalizer to each chunk separately, the result will have stutter, because each chunk still gives a smooth signal, but the end of one chunk might not fit to the start of the next.

There might be fixed using additional "smoothening" afterwards to make chunks fit together. But this further degrades the signal and and increases complexity.

Filter ed

Actually, we can do without expensive FFTs...

Basic idea ed

What happens, when taking the mean of neighbouring signal values? Smoothing! - For a low frequency signal, almost nothing changes. But a high frequency signal looses intensity by self-cancellation.

The most extreme cancellation happens for a sine wave at half the sampling rate, when one value is a high peak, and the next value is a low peak, etc.

Crappy low-pass filter
Instead of the mean, we can also take a weighted ("unfair") mean, i.e. when calling the input array \(x_i\) and the output \(y_i\), instead of\[ y_i = \frac{x_i + x_{i-1}}{2} = \frac{1}{2} x_i + \frac{1}{2} x_{i-1} \]we could define\[ y_i = \alpha x_i + (1 - \alpha) x_{i-1} \]with a mixing parameter \(\alpha \in [0,1]\). For \(\alpha=1\) nothing happens, the output is unchanged from the input. And for \(\alpha=\frac{1}{2}\), the previous smoothing happens.

Slightly better low-pass filter
To make things more fancy, we can reuse the previous output \(y_{i-1}\) value when calculating the new output:\[ y_i = \alpha x_i + (1-\alpha) y_{i-1} \]with \(\alpha = \frac{\omega \, \Delta t}{\omega \, \Delta t + 1}\) for the cut-off frequency \(\omega = 2 \pi f\) and the sampling rate \(\Delta t\).

Note, that this does not perfectly mute all frequencies above \(\omega\). Rather, there is a smooth transition around \(\omega\).

High-pass filter
Similarly, we can define a decent high-pass filter via\[ y_i = \alpha \left( y_{i-1} + x_i - x_{i-1} \right) \]and tuning the cut-off frequency \(f\) with \(\alpha = \frac{1}{\omega \, \Delta t + 1} \).

General IIR filter ed

By linearly mixing inputs and previous outputs, we can define\begin{align}y_i &= \beta_0 \, x_i + \beta_1 \, x_{i-1} + \beta_2 \, x_{i-2} + \dots - \alpha_1 \, y_{i-1} - \alpha_2 \, y_{i-2} - \dots \\&= \sum_{k=0}^{M} \beta_k \, x_{i-k} - \sum_{k=1}^{N} \, \alpha_k y_{i-k}\end{align}These are called IIR filters (Infinite Impulse Response).

If all \(\alpha_k = 0\), i.e. without feedback, we have FIR filters (Finite Impulse Response), because any output for an impulse input stops after \(M+1\) samples.

Transfer function
Very useful is the associated complex function\[ H(z) = \frac{\sum_k \beta_k \, z^{-k}}{1 + \sum_k \alpha_k \, z^{-k}} \]

A sine wave of frequency \(\omega\) passing through an IIR filter can not change its frequency. It can only scale its amplitude and shift its phase by a constant amount. Both changes can be read off from \(H(z)\) by inserting \(z = e^{i \omega \Delta t}\). The absolute value \(|H(z)|\) gives the amplitude scaling and the complex phase is the phase shift.

...maybe some proof...?

Biquad filters ed

Very useful is the subclass of filters with \(M=N=2\). They are very robust but already flexible enough for most cases.

Especially, a sequence of these can be used as a parametric equalizer. The usual components:

And for many other situations, there are also all-pass filters, that change phases without changing the amplitudes.

Categories: Blog, Audio programming