# Audio EQ Cookbook Stability

I'm implementing 6 cascaded biquad peaking filters to make a 6-band EQ. In the system I want to calculate the coefficients on the fly (it's just gain thats changing, center frequency and BW aren't). I am using single precision floating point data, and everything is based off the Audio EQ Cookbook that's posted here: Audio EQ Cookbook

Do I need to be concerned about stability? Or are the coefficients that come out guranteed to keep all poles inside the unit circle? If I do need to be worried about it, can I enforce bounds on the coefficients to force it to always be stable? If so, how would I go about figuring out what these bounds need to be?

• I'm pretty sure that each of those filters are stable, given initial parameters that lie within the given bounds. A $dB_{gain}$ or $Q$ that is infinite is not a good thing. Maybe that would push a pole onto the unit circle. I dunno exactly what would happen if some frequency parameter is specified as negative or greater than Nyquist. Maybe even $f_0=0$ might be a problem with some filters (like HPF), but I doubt it, however maybe I should look at it. Nov 29, 2023 at 22:21
• @robertbristow-johnson I did not expect to get a reply from the guy that wrote the thing! Thank you! I'll be sure to keep everything I'm asking within Nyquist, and with a reasonable Q. If you do ever look at it, I'd be very interested in what you find. Nov 29, 2023 at 22:40
• Looks like Hilmar covered it pretty well. When he mentions $a_1$ or $a_2$, Hilmar means those denominator coefficients normalized by $a_0$ in the cookbook. Nov 30, 2023 at 5:09

Do I need to be concerned about stability?

Yes, but not for the reasons you think (we'll get to this).

Or are the coefficients that come out guaranteed to keep all poles inside the unit circle?

Yes, the coefficients that come out of the cookbook are guaranteed to be stable unless you use non-sensical input. Your worst case will be the highest gain with the highest Q at the lowest frequency. Check that, just to make sure.

If I do need to be worried about it, can I enforce bounds on the coefficients to force it to always be stable?

yes

If so, how would I go about figuring out what these bounds need to be?

Using standard biquad coefficient notation, you want $$|a_2| < 1 \tag{1}$$ and $$|a_1| < 2\cdot \sqrt{|a_2|} \tag{2}$$. (note: I'm not sure the second one is necessary but it I'm pretty sure it's sufficient).

So unless you doing something very outlandish any filter you design with the cookbook will be perfectly stable. The more tricky part is making these filters time variant.

Updating a biquad "on the fly" can indeed cause large artifacts and in extreme cases instabilities. One of the more devious effects here is the impact of the coefficient changes to the state variables of the filter, which, in turn, depends a lot on the topology of the filter. Making a long story short: the safest choice is Direct Form I and the worst choices are Transposed Form I and Direct Form II.

If you update the coefficients in large steps you will get clicks or "zipper noise". One way to mitigate this is to put a single lowpass or smoothing filter on the gain itself. This way the gain doesn't change instantaneously but it ramps slowly over 100ms or so. This way the individual coefficient changes are small enough that they are not audible.

The downside here is that you have to compute the coefficients A LOT. It's a bit of an awkward calculation (my apologies to RBJ :-) ) and can chew up a LOT of CPU. It's much faster to interpolate the coefficients and/or the pole/zero locations directly (and/or using table lookups + interpolation). However, you will have to make sure that for whatever interpolation you use (linear, polynomial, spline, etc) every set of interpolated coefficients is still stable (per equations (1) and (2)). In that regard interpolating the poles (or zeros) is probably safest: if both your starting and your ending pole are inside the unit circle, so will be most reasonable interpolating paths. Getting the coefficients from the pole is cheap: $$a_1 = 2\cdot \Re\{p\}$$, $$a_2 = |p|^2$$

• Hil, I like DF1 because I worked a lot with it with the 56K and fixed-point. DF2 is bad with fixed-point arithmetic because the poles come before the zeros and the intermediate gain can be kinda wild before the zeros beat it back down. I think for time-variant filters that are used in musical application, I think the lattice might be the best form, but who knows. Coefficients can be efficiently calculated at a slower rate, like at $f_s/32$ or something and then let the coefficients slew on a per-sample basis. Nov 30, 2023 at 5:14
• In case of fixed center frequency and Q EQ, I've tried, with success, a polynomial based implementation which isn't as CPU intensive as what the original paper equations. What I mean is; changing coefficients are calculated by using few:th degree polynomial (which degree depends on accuracy needed). Two sets of polynomials are needed. One for 44.1kHz base sample rates and the other for 48kHz base sample rates. Nov 30, 2023 at 6:55