Sample rate (Hz) | |

Fc (Hz) | |

Q | |

Gain (dB) | |

Here’s an update of the biquad calculator. It adds one-pole highpass and lowpass filters, and frequency, Q, and gain sliders. The sliders cover the range of typical audio settings, and are valuable for getting a quick feel for how the filters respond. But for precise settings and a wider range of parameters, type settings into the edit fields. (For this reason, the connection between sliders and edit fields are one-way—sliders update the edit fields, but changing the fields does not change the sliders positions accordingly.)

Review the biquad direct forms here; direct form I is best for fixed point processors, while direct for II transposed is best for floating point implementations.

I can’t see the sliders, I have extra text boxes instead – Firefox 20 for Ubuntu Canonical 1.0

Freescale SGTL5000 is a pain in the neck. Freescale representatives tell me that their PEQ uses IIR Biquad digital filter and 20 bit number is all fractions with one sign bit and 19 bits after the decimal point so only able to represent -1 to 0.99997; Then they tell me to find a 3rd party tool and their help is vacuous thereafter.

Your Biquad Calculator V2 seems pretty cool but keeps giving me figures above 0.99997 and/or below -1

Please help me.

To the slider issue, Firefox doesn’t support HTML 5 “range” (slider) controls before release 23. I make no attempt to support anything that’s not HTML 5 compliant, at this point. It’s not worth the effort.

OK, it looks like you’re saying that at the filter settings you want (low frequency, apparently), the 20-bit fixed point coefficients don’t have sufficient resolution. This is always an issue with direct form biquads, as the poles are very sensitive to quantization at the angles of zero and pi. There are other filter forms that work better in that area. The state variable form is quite good for low frequencies.

Excellent work. This page and the whole website is useful.

Great web site! However, I was also stumped on why b0 was missing until I read the comments section from your old calculator. Maybe it’ll help if there’s big bold disclaimer at the beginning letting folks know your a are for numerator and b are for denominator and that could be different from what others are using?

Good point—maybe I’ll add a reference to the typical filter forms…

Nigel,

I left an early message about coefficient scaling, and here are the coefficients in question. I am using a high shelf filter.

a0 = 2.1711322014279757

a1 = -4.073744433313715

a2 = 1.9182767385279291

b1 = -1.8153410827045682

b2 = 0.8310055893467576

I am trying to scale these to be between +-2 as my processor requires numbers in that range. 2 of the above are outside that.

Thanks

The most convenient method depends on the processor, but the way that this is usually handled is to halve the particular coefficient, then multiply-accumulate it twice:

mac -x0,y1,a

mac -x0,y1,a

Similarly, you could quarter the coefficient and repeat it four times. Those are simply the sort of tradeoffs that you have with fixed-point processors.

I had been succesful in just scaling down a0,a1,a2 using a constant factor, in your case you may just divide all of them by (-a1/2) so a1=-2.0 and all others scale down accordingly.

b1 and b2 remain the same.

It will result in the output being scaled down accordingly, in this case slightly more than 6 dB.

Thanks for the response Nigel.

Unfortunately, I do not have the ability to multiply and accumulate. I am trying to use a biquad on a Blutetooth chip and all I have access to is the coefficients – I cannot program anything else. Their structure is fixed in silicon. If it is not possible to scale them and still keep the b0 coefficient as unity, I will have to adjust the parameters (like gain, etc) until they are are all under 2 for magnitude.

Mike

Just discovered this website.. very helpful! .. thanks a lot!

Luca

P.S.:

Only the gain slider doesn’t work for me (Firefox 29 on Mac OSx)

Hi Luca—I’m glad you like the site, thanks for saying so!

Note that the gain slider affects only peak and shelf filters. Notice that the gain field is disabled for others (try to change it). In most browsers, you’ll see that the gain field is dimmed for the other filters, but for some reason Firefox does not dim the field when disabled. Also, under Safari and Opera, the sliders update in real time as they move, not just upon release of the mouse button, making the experience a lot better than in Firefox or Chrome at this time.

Nigel

PS—Sliders updating on drag should now work on all browsers.

Really helpful! Thanks! The coordinates work great in the CMSIS library for ARM. A couple questions, though: 1) The gain slider seems to have no effect either on the graph or the output. The output seems to have 0 gain (which is really what I wanted) despite saying 6db in the slider.

2) If I wanted to implement two stages of biquad, would I just use the same coefficients again? I don’t see anywhere a way to calculate biquad coefficients beyond the first stage.

Thanks again for such a useful page!

1) Try a newer browser—it’s an html5 feature, so it won’t work in old browsers, and I know that previous versions of Firefox didn’t have them working right either.

2) No, because the corner will have a 6 dB rolloff instead of 3 dB, for a Butterworth (Q = 0.7071) lowpass. Do a search on cascading biquads, or factoring higher order filters into biquads. Basically, for a fourth-order Butterworth lowpass made from biquads, the Q settings will be different for each section in order to form the intended corner. But, if your application is not so picking about the definition of the corner, then maybe identical settings are fine.

Can you be more specific on how you get up the co-efficents in CMSIS, I am trying and it seems the A and B terms are reversed. ARM says {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, …}

seems b10 would be a0

seems b11 would be a1

seems b12 would be a2

seems a11 would be b1

seems a12 would be b2

???

You are correct—as I said, there is no standard for A and B, but the dead giveaway is that in a normalized filter, it’s easy to tell which are which. (The output index-0 coefficient is normalized to 1, and is left out—in my case b0, in their’s a0.)

This is a great tool. Would it be possible to add group delay calculation to this, please?

So useful. Any plans for butterworth filters?

Easy—just use 0.7071 (1 divided by the square root of 2) for Q! The calculator defaults to that setting when it opens.

Thanks for the response. I mean higher order Butterworth filters to get those really sharp corners.

You can convert a higher-order Butterworth prototype with the inverse z transform. Higher orders are increasingly more sensitive to numerical errors, though, so you’d have to evaluate numerical properties for a given filter setting, at a given numerical precision (64-bit floating point, for instance). To avoid that, you can cascade multiple lower-order filters, such as first and second order. You can find a helpful table in wikipedia by searching for “Butterworth filter”. For instance, it lists (s^2 + 0.7654s + 1)(s^2 + 1.8478s + 1) for fourth-order. That means that you need one biquad with a Q of 1/0.7654, followed by another with Q 1/1.8478.

Hi Nigel,

Thanks for sharing your work. One thing I don’t understand is the definition of Q, which seems to vary with the type of filter. The specs I get from control engineers define notch (and bandpass) filters in terms of a sample frequency, notch center frequency, and bandwidth, defined as the difference between -3dB frequencies. For example, fs = 200, fc = 3.3, bw = 1, all in Hz. Can you explain how to computer Q for a Butterworth filter with these specs?

Joe

Joe, there are definitely different interpretations for Q, especially for bandpass, peak, and shelving filters. And note that many of the classic analog EQs deviate from engineering-type definitions. Refer to Robert Bristow-Johnson’s well-know biquad reference, “Cookbook formulae for audio EQ biquad filter coefficients” for comments on bandpass. (Note that despite different formulas, most of his filters are mathematically identical with mine, with the same approach but different factoring; I think the main exception is our shelving implementations.)

Is there any workaround so that I could use the following settings:

Sample Rate: 12kHz

FC: 7kHz

with the peak filter?

7kHz is more than half the sample rate of 12kHz—it’s above the highest frequency you could play back. (Of course, you could say that setting an Fc of 5kHz would be the same as 7kHz, since the response is mirrored around half the sample rate.)

Thank you for a very useful and informative page.

However the one pole hp does not seem to behave like a normal one pole hp filter…

Glad you like it, Roger. The hp works correctly, but it’s simply a one-pole (no zero). That makes it of limited value, and is only here for illustration and completeness. I included it because I commented on it in the one-pole article. But for a DC blocker, for instance, a better solution is to subtract the one-pole lp from its input.

Overall fantastic tool to study filters!

However, looks like lowshelf ans highshelf responses are not precise – or am I missing something? As far as I know, with this type of filter, the Fc (center frequency) is a point of half the magnitude swing of the filter, however, it’s not the case on this plot.

If You set Fc at 1391 Hz (so it is right at the corresponding vertical grid line), and apply – 6 dB gain, You clearly see that it’s shifted in frequency – so that 1391 Hz is not at -3 dB.

What is wrong in my assumptions?

… and it’s worth mentioning I meant using log scale for better clarity

Hi Oleg—thanks, and good points. First, the Fc definition of shelves depends on the implementation. Digital Performer’s Master Works EQs behave exactly as mine do. At a glance, Waves’ REQ works that way too. But their (very old) Q seems to use mid-point (as do rbj’s cookbook shelves). But I don’t think mid is the norm—I think it’s corner for analog EQs, and most modern digital EQs emulate them. Lastly, it make sense logically, as the pole-zero angles remain constant at the frequency for any gain value—the same as if you were mixing a lowpass filter with variable gain with the direct signal (ignoring phase issues). The only advantage to picking the middle is that you can get by with a single equation.

But I don’t see the shift you mention. For instance, set Fc to 1391.3 Hz, and set Gain to any multiple of 10, plus 3—positive or negative, high or low shelf (-43, -33, -23…); you’ll see the plot cross at 3 dB closer to unity (-40, -30, -20).

Thank You for Explanations… Now clear …

Thanks for the site.

It would be great if one could form a URL that would be for a certain filter: EG

http://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/?type=peak&q=10&fc=1000&fs=44100

That way one could send filters to other people, etc..

Thanks again,

–Tom

Nice idea, Tom, thanks—I’ll consider that.

Great site to have stumbled across! Loads of good reading and well written explanations, as I tread slowly to some understanding of audio DSP!

I have some working biquads based on the RBJ cookbook and am now trying to produce visuals/graphs of frequency response like the ones shown on this calculator, and like the ones you get in VST EQ plugins etc. Any chance of a head start in what I should be plotting and a few lines of code to show me how it was achieved here? I think I should be plotting 20Log|H(z)| as y axis data but I can’t get it to work.

Yours hopefully

Mark

Hi Mark…There is more than one way to do it, but a fairly simple one if you are starting from pole/zero coordinates is to walk around the unit circle (from 0 to pi is sufficient, since the other half is symmetrical) and for each point, take the products of the lengths of the vectors drawn from each zero to that point, divided by the product of the lengths of vectors from the poles (two of each for a biquad).

Of course you get there directly from coefficients with some manipulation…looking at my Java code on this webpage, that’s what I’m doing. I’m reluctant to google and put up a link to somewhere else here, but I have no control over the link becoming obsolete later, but just do a search on magnitude response of a biquad. Remember that my “a” coefficients are on top of the transfer function, possible reverse of what you might find elsewhere.

Nigel

Hi Nigel

Thanks for your reply. I have been trying with the 2nd approach i.e working from the coefficients using RBJ’s comments and manipulations from here :

https://groups.google.com/forum/#!topic/comp.dsp/jA-o05autEQ

but I am going wrong somewhere. I will carry on trying though, as I do get something vaguely resembling the curves I expect but I know they’re not right!

As well as your a’s and b’s being swapped I also noticed in one article that you comment that your implementations for low & high shelf are more symmetric for boost/gain than RBJ’s so I am trying them now.

Great site to read/learn from so far but I still have some way to go! 🙂

Mark

Hi Mark,

OK, it’s looks like you’re doing the same thing I’m doing—take a look at the source of this page. It depends on the browser, but for Safari, for instance, right click on the page and Inspect Element (maybe this needs the developer menu enabled?), and look at biquad2.js. Look for the look that calculates phi. It seems the only change is swap a for b, the signs look the same at a glance.

As far as the shelves…I recall looking again, and concluding that Robert’s shelves and mine (after Zölzer) behaved the same. Robert added a Q control, but it’s not a musically desirable one. I did some work on a more desirable Q control (one that doesn’t peak on the shelf), but didn’t completely work out the control details. I decided I probably needed to make a tool that let me play around in the s domain to figure out the interaction I wanted—left for when I have more time, or actually need such a shelf.

For the other filters, the only difference between Robert’s and mine are factoring (sin/cos instead of tan).

Nigel

BTW, you can also do it with FFT. First, it should be obvious that you can plot the FFT (magnitude) of an FIR filter, since it’s equivalent to the impulse response—just zero pad it to the length you want. For a biquad (or higher order IIR), you can take the magnitude of an FFT of the numerator (a) coefficient, divided by the magnitude of an FFT of the denominator coefficients (b—but don’t forget to include b0=1.0, since we’ve normalized the coefficients), similarly padded. Anyway, I think that’s right, but check it in case I’m forgetting a detail.

Many thanks Nigel for taking time to help me!

I have looked at your biquads2.js script and it seems as I have a very similar approach, but my plots are just wrong for some reason. I am using plain java (actually “Processing” if you have ever used that as it’s great for visual and GUI things as well as being an easy IDE to use and code with for non-experts like me!), so some of the Javascript commands are unfamiliar. I will spend a few hours learning and see how it goes, as although the equations and maths used seem the same as yours, my plots are just wrong.

I will get there:) and once done will have a look at the FFT route. which is on my list of things to do anyway at some time.

Best regards

Mark

Got it! A few issues inc doing normalizing twice for coefficients and not properly using a log scale for plotting. Many thanks for all your help

Mark

It is a great site indeed, but there is something that i’ve stumbled on. For the bandpass filter, there is only one frequency instead of two. Then, i discovered that, the bandpass limits are F1=Fc/2 and F2=2*Fc, which means that F2=4*F1. Is there a solution to this problem? I think that the limits shouldn’t be calculated but instead, to be specified by the user.

Nigel

Great blog – it’s coming in very useful for my home project. I’m currently trying to do some pipe cleaning exercises, then plan to try and implement a H-infinity optimisation process to tune the gains according to some objective function.

However, I’m having a bit of difficulty getting off the ground with my Matlab simulation – I’ve implemented the biquad in Direct Form I and copied your filter coefficients from a highpass filter with fc=5kHz and Q=0.7071. My cut off is in roughly the right place, I’ve normalised with a gain of 2=6dB on the output and am using a discrete solver. However, my Bode has the wrong slope! Whilst your’s is around +25dB/decade, mine is around half of that. At the Nyquist/1000 breakpoint I still have -44.9dB.

I reckon I’ve implemented it correctly as per http://www.earlevel.com/main/2003/02/28/biquads/

But what could I have messed up to give me half the slope?! Thanks in advance…

Sorry, Kiran, this came in when I was away for the year end, and just realized I hadn’t answered. I don’t know, without seeing exactly what you’re doing, and don’t want to guess. I hope you’ve sorted it out by now.

No Problem – I actually went away and came back to the problem, so it’s just resurfaced… But the plot thickens. I’m sure I’m just doing something daft.

The coefficients from your calculator are:

a0 = 0.600716795914846;

a1 = -1.201433591829692;

a2 = 0.600716795914846;

b1 = -1.035121791879154;

b2 = 0.36774539178022964;

I’m using a normalising Gain of sqrt(2). I’ve set up a Simulink model (discrete) with a sample time of 44.1khz, and have drawn it in direct form I with the normalising gain stuck right on the output.

But then I use your equations to get the gains, as referenced in the source code. I expected them to come out with what your calculator gives me, but instead I get:

fc = 5000;

K = tand(pi*f/fc);

Q = 1/sqrt(2);

norm = 1 / (1 + K / Q + K * K);

a0 = 1 * norm;

a1 = -2 * a0;

a2 = a0;

b1 = 2 * (K * K – 1) * norm;

b2 = (1 – K / Q + K * K) * norm;

G = sqrt(2);

==>

a1 = -0.9908

a2 = 0.4954

b1 = -0.7175

b2 = 0.2641

G = 1.4142

So… the outputs and the gains appear different! The gradients of the slope are the same, but the coefficients from the calculator give me a Fc of around 2500Hz, whether when I use your equations and calculate, they look pretty much around 5kHz as requested.

Any ideas?!

I put the parameters in another biquad calculator on the web, and it came up with the same results as mine.

But I see “tand” in your code, instead of “tan”—isn’t that tangent in degrees in matlab? Or a typo?

It was tan in degrees in Matlab – plus I inverted my quotient… Thanks!

Aha – I’ve made an arithmetic error and matched the output from the two methods… However, the slope and values from the Highpass just above is a bit different to what I have for the two methods in Matlab – it’s as though your x-axis has the wrong scale?

I looked around and found this very nice filter widget with plotting. It gives the same coefficients as mine, and seems to plot them the same. Let me know if you see a discrepancy.

http://www.dspfilters.com/filterdemo/filterdemo.html

Will do – cool, thanks 😉

SOLVED! Was missing a time delay in my diagram… I have a long way to go.

Thanks for your help in starting the journey!

BR

I’d like to transpose the biquad designer from js (actually into C++).

I’d keep your copyright – but there is no license in the js file, and I’d like to play fair.

Also – if you ever feel a need to do something more, a Linkwitz Transform calculator would be really helpful.

In an answer above, you mention using a subtractive filter with input-lowpass. Under what circumstances is a subtractive approach a good one to use?

Thanks for a great site.

James

Please feel free to do so. My C++ filter code is the same (I translated it to js for the widget). The graphing code would be totally different, but the fft and magnitude calculations are pretty much the same in C or js.

As for subtracting, I assume you’re referring to my comment about a DC blocker? In general, subtracting (or adding) a filter’s output to the input signal will not give you the sum of magnitudes, due to phase shift induced by the filter around the cutoff. That’s especially evident in second-order and higher order filters. But it’s inconsequential in a DC blocker because it’s sub-audio.

Amazing: your calculator’s 5 numbers plug straight into the biquad filter module in SynthMaker, even that free v1.0.5 from Computer Music magazine! Can’t use 6 coefficients see, no “b0” pin! & my maths is the worst of anyone here! They plug right in & they work! Now I can make that bank of resonant (Q≈100) bandpass filters I need for the core of my audio to midi Vst plugin! I’m going to be rich… But don’t worry, I’m giving it all to my local donkey sanctuary!

Couple things…. I want to use this in ARM CMSIS biquad library and it seems the A and B terms are reversed? also would love a single pole bandpass option! 🙂 I need high, and low, and BP for a small audio app I am doing on an M3

See my comments about A and B elsewhere, but the gist is that I use A on top of the transfer function, as many classic texts do. But there is no standard, so it varies. Watch out for signs of the numerator coefficients too, as some folks roll the subtraction into an addition and sign flip. Sorry about that, it’s just the way it is.

And there is no one-pole bandpass. It requires a complex pole, and that means you’ll have a pair.

So I did learn the hard way about the +- of the coefficients … 🙂 Someone pointed out to me that the last 2 when used in the ARM CMSIS DSP libs, would need a sign change.

Example:

a0 = 0.9733553098104358

a1 = -1.9467106196208717

a2 = 0.9733553098104358

b1 = -1.9447880283614938

b2 = 0.9486332108802497

Becomes:

a0 = 0.9733553098104358

a1 = -1.9467106196208717

a2 = 0.9733553098104358

b1 = 1.9447880283614938

b2 = -0.9486332108802497

and it seems to work. If the signs were left alone the data output “ran away to infinity” 🙂

RichardS

Hello, I want draw this Q- Factor graph.

Could you please share code?

Thanks

You can view javascript from any site, depending on your browser (for instance, enable the Develop menu in Safari via Preferences/Advanced). But here’s a direct link.

Nigel thanks a lot for a useful tool, and a great site overall!

For anyone who wants to make a frequency response plot for the filter with calculated coefficients in MATLAB / Octave, here is how to use them with `freqz’ function to get a graph in Hz:

freqz([a0, a1, a2], [1, b1, b2], , 0, );

should be a power of 2, e.g. 512

`0′ is to get a graph with frequencies up to / 2 Hz