A biquad calculator

Sample rate (Hz)
Fc (Hz)
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.

This entry was posted in Biquads, Digital Audio, Filters, IIR Filters, Widgets. Bookmark the permalink.

13 Responses to A biquad calculator

  1. Anita Barteky-Bamford says:

    Hey Nigel…I guess all that competitive math with you in grade school paid off! LOL
    Looks like some cool stuff here.

  2. Erik says:

    I think you have your a and b coefficients labeling swapped in the coefficient output window.

    • Nigel Redmon says:

      Thanks for visiting!

      Actually, I prefer the a’s in the numerator (of the z-domain 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’s-on-top 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.

  3. Paul says:

    Nigel, I’ve really enjoyed your articles and have learned a lot. I have a simple bi-quad 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 bi-quad code. My thoughts were initially that I could simply run the Bi-Quad filter section again changing only the “y” values. I’m not sure it’s that easy and kindly ask your help.


    // Low-pass fc=20, 2000 samples/sec, Q=.707
    a0 = 0.0009446914586925257;
    a1 = 0.0018893829173850513;
    a2 = 0.0009446914586925257;
    b1 = -1.911196288237583;
    b2 = 0.914975054072353;


    current_sample = SampleADCfloat();

    /* Bi-Quad filter */
    filtered_sample= a0*x[0] + a1*x[1] + a2*x[2] + b1*y[1] + b2*y[2];

    /* Cascade? */
    filtered_sample= a0*x[0] + a1*x[1] + a2*x[2] + b1*y[1] + b2*y[2];

    .repeat above?
    .repeat above?
    .repeat above?

  4. Nigel Redmon says:

    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:


    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.

  5. Paul says:

    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!

  6. 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.

    • Nigel Redmon says:

      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.


  7. 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.

  8. Hi Nigel!

    I just wanted to thank you for your excellent articles. It seems everything I need is right here! Thanks!

    Fredrik C

  9. Gábor Kakuk says:

    Dear Nigel,

    Is it possible to explain how to add the SLOPE for shelfing filters?
    (In the formulas)

  10. Nigel Redmon says:

    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 high-quality EQ, and for that I’d want to make other changes as well—and for what, with so many high-quality EQ plug-ins 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 pole-zero motion in the s-domain, relating to the controls. From there it’s just the bilinear transform. Sorry, I know that’s not very useful information.


Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>