Sample rate (Hz)
Fc (Hz)
Q
Gain (dB)

Something useful: a biquad filter coefficient calculator. Set the filter Type, the Sample rate (or 1.0 for “normalized” frequency), and cutoff of center frequency Fc. You can adjust Q for lowpass, highpass, bandpass, notch, and peak filters (use 0.7071–which is 1 divided by the square root of 2–for Butterworth lowpass and highpass), and Gain for peak and shelving filters. View the frequency response with a linear or log scale. You can copy and past the resulting coefficients into your programs.
More info on biquads in previous posts, here and here.
Note that there is an improved version of this calculator here.
Hey Nigel…I guess all that competitive math with you in grade school paid off! LOL
Looks like some cool stuff here.
I think you have your a and b coefficients labeling swapped in the coefficient output window.
Thanks for visiting!
Actually, I prefer the a’s in the numerator (of the zdomain transfer function), and b’s in the denominator—some folks go the other way. (I did an informal survey of the DSP texts on my book shelf when this sort of discussion came up some years back, and the a’sontop were most popular, but some fine authors choose the other way as well.)
Folks also disagree on the sign of the denominator coefficients (I use a minus sign at the summation for the denominator/feedback coefficients, others negate the coefficients and use all adds.) If you start from the z transform, the a’s on top and minuses for the denominator coefficients are most natural; if you start at the block diagram of a direct form II biquad, then you’ll tend towards the other convention.
In any case, I’m consistent—check my other articles on biquads and the bilinear transform. But thanks for bringing this up—it reminds me why I need to post some sample code as well.
Nigel, I’ve really enjoyed your articles and have learned a lot. I have a simple biquad filter working fine and I’d like to cascade it. After cascading it appears I’m getting pretty much the same response as not cascading. I’ve defined variables “current_sample” and “filtered_sample” so current_sample is the output of the ADC and filtered_sample is then the value after filtering. Below is the simple biquad code. My thoughts were initially that I could simply run the BiQuad filter section again changing only the “y” values. I’m not sure it’s that easy and kindly ask your help.
—————————————————————————————————
// Lowpass fc=20, 2000 samples/sec, Q=.707
a0 = 0.0009446914586925257;
a1 = 0.0018893829173850513;
a2 = 0.0009446914586925257;
b1 = 1.911196288237583;
b2 = 0.914975054072353;
b1=b1*1;
b2=b2*1;
current_sample = SampleADCfloat();
/* BiQuad filter */
x[2]=x[1];
x[1]=x[0];
x[0]=current_sample;
y[2]=y[1];
y[1]=y[0];
filtered_sample= a0*x[0] + a1*x[1] + a2*x[2] + b1*y[1] + b2*y[2];
y[0]=filtered_sample;
/* Cascade? */
y[2]=y[1];
y[1]=y[0];
filtered_sample= a0*x[0] + a1*x[1] + a2*x[2] + b1*y[1] + b2*y[2];
y[0]=filtered_sample;
.repeat above?
.repeat above?
.repeat above?
Hi Paul,
I see some problems with your code, but since you’re using floating point, I’d go with transposed direct form II anyway, which requires just two saved states per biquad:
http://www.earlevel.com/main/2003/02/28/biquads/
I’m sure you can figure it out from there, but for those who need a head start: Looking at the diagram there (let’s call the top delay state z1, and the lower one z2), you’ll see that the output is
output = input * a0 + z1;
Now for the new z1 and z2:
z1 = input * a1 + z2 – b1 * output;
z2 = input * a2 – b2 * output;
To cascade, you’d repeat the above, preceded with “input = output;”, and another a new set of delay states (z11, z22). Also note that you’ll need to adjust your filter settings—cascading two filters that are each 3dB at 10 kHz yields a filter with a different 3dB point and shape (it’s now 6dB at 10 kHz). So depending on the exact filter shape you want, you may want to use different frequency and Q setting for each section, or just adjust the Q.
Thank you Nigel! I’ll give this a try.
Thanks for being so nice, I definately fit the “need a little head start” category since I’ve never worked with filters like this. Just understanding that the “z” values end up as intermediate values in the calculations is a jump start. As soon as I have time I should start a beginner’s course or read a book that starts with the simple terminology.
Thanks again!
Hey, Nigel, nice js app! Very handy!
Calculation of a1 for low shelf seems incorrect though (a1 > 2.0 when all coefficients should have magnitude <= 2). It is probably irrelevant, but anyway I am using the app with Chrome running in Ubuntu.
Glad it’s helpful to you, Adriano! Remember, the shelves have gain, so you’ll see the a coefficients go over 2 for the boost case. BTW, the high and low shelves are from Udo Zölzer’s Digital Audio Signal Processing.
Nigel
Nigel, you are absolutely right. I mistook b’s for a’s and applied the stability triangle rule for the nonrecursive coefficients instead of the recursive ones. Sorry for that.
Hi Nigel!
I just wanted to thank you for your excellent articles. It seems everything I need is right here! Thanks!
Fredrik C
Dear Nigel,
Is it possible to explain how to add the SLOPE for shelfing filters?
(In the formulas)
Hi Gábor,
I did some work on slope, late last year, including Q (it’s useful to allow a dip before the shelf transition, as some vintage analog equalizers). It was educational, but at a certain point I realized that the only real purpose would be to develop a highquality EQ, and for that I’d want to make other changes as well—and for what, with so many highquality EQ plugins available. So I stopped—it wasn’t something I wanted for myself, and it wasn’t what I wanted to do here in this blog. I might get back to it at another time, but there were so many other things I want to get done first…
But the basic thing was working out the polezero motion in the sdomain, relating to the controls. From there it’s just the bilinear transform. Sorry, I know that’s not very useful information.
Nigel
Nigel, it would be interesting to highlight that the Q definition implicit in your designer reference the 3 dB points, not the halfgain ones. “One problem with this definition is that complementary equalizers with the same defined bandwidth, boost/cut frequency, and opposite boost/cut gains, do not cancel each other to result in a flat 0 dB overall response.” For instance, a 18 dB peaking EQ do not perfectly cancel two cascaded +9 dB with same frequency and Q. Please refer to the paper where the above quote was extracted for a thorough discussion [1].
Gábor, please refer to [2] for a second order shelving filters with adjustable slopes.
[1] BristowJohnson, R., “The Equivalence of Various Methods of Computing Biquad Coefficients for Audio Parametric Equalizers” URL: http://thesounddesign.com/MIO/EQCoefficients.pdf
[2] BristowJohnson, R., “Cookbook formulae for audio EQ biquad filter coefficients” URL: http://www.musicdsp.org/files/AudioEQCookbook.txt
Thanks for your comments, Adriano.
True, but that doesn’t mean it’s “wrong”, simple an alternate definition. You can’t cascade two lowpass filters of the same Q and frequency and get a steeper slope with the same frequency and Q specs either (two biquads set to 1 kHz and 0.707Q do not produce a fourthorder 1 kHz filter as defined by 3 dB), yet that’s the standard definition.
Yes, the variable slope is interesting, but it’s not of the form that’s usually used for audio, and will not sound good at higher Q. It produces both a dip near unit and a peak at the shelf height, while the usual shape for both analog consoles and their digital equivalents is to have the dip at unity by no bump at the shelf gain level.
Also, note that the rbj shelves are not symmetrical—cut and boost behave differently. The transfer function must be inverted for negative gain, to preserve the same shape on both sides of unity.
Nigel, referencing 3 dB points is indeed pretty standard and surely not “wrong”. In some cases it may even be actually perceptually preferable to use the 3 dB reference points (e.g., MID EQ in mixing consoles), so that the perceptually the bandwidth increases with gain magnitude. I believe it nevertheless relevant to point out that halflogarithmgain (vs halflineargain points) reference points must be used in order to have the perfectcancelling property in the magnitude frequency response.
The RBJ formulas for shelves given in [2] actually do have gain symmetry, i.e., cascading a shelf with gain +G with another with gain G produce unity frequency response. Cascading a shelf with gain +G with two others with gain G/2 , however, does not produce unity frequency response. Therefore, we have here a weaker perfect cancelling property for shelves than for halfgain peaking EQs.
Regarding shelves variable slopes, the most useful S range is within 0.33 and 1.0 (slower than firstorder to fastest monotonic second order). For faster than 12 dB/oct slopes, higher order shelves must be employed, such as in [3].
[3] Holters, M. and Zölzer, U., “PARAMETRIC HIGHERORDER SHELVING FILTERS”, in Proc. of 14th European Signal Processing Conference (EUSIPCO 2006), Florence, Italy, September 48, 2006. URL: http://www.researchgate.net/publication/239734982_Parametric_higherorder_shelving_filters/file/3deec51c2ae3d17210.pdf
Hi Adriano,
Yes, you are correct about rbj’s shelves being symmetrical. I took a look only at the transfer function before, and did not notice that he was calculating his coefficients based on the midpoint of the shelf, not the corner frequency. I think that audio engineers are more familiar with the corner frequency definition, as that’s how hardware EQs work (at least the ones that I’m familiar with). Out of curiosity, I did a quick check with some of my EQ plugins, and the old “Q” equalizers from Waves (“The world’s very first paragraphic EQ”, they claim) appear to use that definition, though their newer ones (REQ, etc.) use corner frequency, as do the others that I have (the old Motu PEQ, and newer Oxfordclone MW Equalizer, for instance).
Yes, with S of 1 or less, slope control is useful for audio. I won’t implement it without a more general Q solution, though. I did take a stab at a general solution, with Q less than 0.7071 reducing the slope, and causing a dip with steeper initial slope when greater than 0.7071. I was successful in general, but need to work out the polezero motion so that behaves closer to what I’ve seen for seen for similar EQs, since there doesn’t appear to be an obvious engineeringdriven definition. (But maybe there is—I need to play with it in the sdomain and see.)
Nigel
Nigel, I believe it would be interesting to conclude this thread by presenting the formula to convert between both Q definitions. Let G be the peaking filter absolute gain, let Q_lin be the halfpower (3 dB), aka full width at half maximum (FWHM), referenced quality factor and Q_log be the halflogarithmgain (G/2 with G in decibels), then the two quantites are related by the following ratio: Q_lin / Q_log = 10^(G/40).
Finally, another interesting (and thorough) reference on the subject is [4], in which it is possible to see that the 3 dB actually references the bandpass from which the peaking filter is derived and that is why for G < 6 dB the 3 dB actually does not reference the sign(G)*(G3) dB points.
[4] Miller, R., ""Why DSP Boxes Set the Same Way Differ"" in RaneNote 167, 2007 Rane Corporation, URL: http://www.rane.com/note167.html
Thanks for the helpful comments, Adriano.
Below I present very accurate approximations in Ruby code for converting between corner (LPF/HPF 3 dB) [5] and midpoint (G/2 in dB) witt S = 1 [2] high/lowshelves cutoff specifications.
[5] http://www.earlevel.com/main/2011/01/02/biquadformulas/