Aha. Bet you thought that “When off-the-shelf won’t do: the step-by-step birth of a custom digital filter, Part 2” wrapped up our custom digital filter discussion. But it still had one trick left up its sleeve.
Someone in the team speculated on whether we could build some sort of audio response equalizer into the system. I’d recently done a super multi-band stereo octave equalizer running on the Digital Filter Block, together with application code that ensured that the frequency response would actually be a curve that went through the user defined ‘slider’ positions. It was a lovely thing! – let me know if you’d like me to write about it. Trouble is, it needed all of the coefficient memory of the DFB (and some of the cycles too), and we just used that for our custom decimation filters.
What I really needed was an equalizer, or at least some sort of tone control, that needed precisely zero extra filtering resource. OK, nothing like a challenge! All I needed was a method. And, a short while later…
The transfer function of the one of the biquads in the cascade (it happens to be the final one, in the cascade order I finally settled on) is the product of a 1st order lowpass piece (from the original 7th order lowpass filter) and a 1st order allpass piece (from the 3rd order phase equalizer). The allpass piece has a flat magnitude response because the magnitude responses of the numerator and denominator functions are identical (only the phase responses differ; this is characteristic of all true allpass filters). If we change either the numerator or the denominator coefficients , changing the locations of the zero or the pole, then the magnitude response will change.
And, guess what? When the pole and zero of that particular allpass portion are moved apart in frequency, so that the magnitudes of the numerator and denominator no longer cancel out, you can achieve either a boost or a cut in high frequencies with respect to low ones. This is sometimes also called a shelving response and in our particular case, it occurs in a frequency range that’s a really good match for an old-school audio treble control!
It turns out that we need to do the boost and cut modifications in slightly different ways, to ensure a nice symmetry in the treble results, with respect to a constant bass level. For boost (an upward shelf response) , the adjustment is done in the numerator coefficients, by decreasing the zero frequency. In this case the denominator coefficients are unchanged.
For a matching cut response (a downward shelf), the adjustment is done in the denominator coefficients, by decreasing the pole frequency. Because the overall gain of the biquad function is affected by both sets of coefficients, we also have to apply some scaling to the numerator coefficients, to keep the low frequency gain constant.
Figure 1 shows the resultant filter magnitude response when the response is adjusted between a boost of 9 dB and a cut of 9 dB in 3 dB steps. The change in gain at 1 kHz is minimal, and most of the gain change is available by the time you get to 10 kHz.
Adjusting the coefficients of the allpass section away from the design value is clearly going to have an effect on the linearity of the phase response – but so does having a classic boost/cut treble control in the first place!
Obviously the filter is not so good at filtering out high frequencies if you turn the treble control knob up to max – but a separately-implemented tone control circuit would also suffer from this. And yes, I know, I haven’t done a bass control. That will probably take some extra thinkage. But, just remember, when you need to raise the tone of your signal a little bit, you might not need any extra processing power.
I hope you get a good… response from your colleagues, when you suggest this! / Kendall