Here’s a tool that plots frequency response from filter coefficients.
The coefficients fields are tolerant of input format. Most characters that don’t look like numbers are treated as separators. So, you can enter coefficients separated by spaces or commas, or on different lines, separated by returns. That makes it easier to copy and paste coefficients from online filter calculators. They also ignore numbers that are followed by “=” or “ =”, so that “a0 = 0.1234” is seen as “0.1234”. Click the chart to accept coefficient changes, or change one of the controls.
Important: This tool does not assume that the filter coefficients are normalized to y0. So, in most cases you’ll need to insert a “1” as the first pole coefficient, the b0 term.
If there are no pole coefficients, it’s an FIR filter—all zeros.
Again, the convention of this website is that coefficients corresponding to zeros (left side of a direct form I) are the a coefficients, and poles the b coefficients. It’s usually easy to see because most IIR filter calculators normalize the output. So, if you are missing a0, it probably means that a and b are swapped with respect to this site’s convention—just paste them in the opposite coefficients fields (and remember to use a 1 for the missing coefficient). Also, negative signs at the summation for the feedback terms (b) are not rolled into the coefficients.
Hey Nigel
first, I really very much like your articles. They also inspired me using Flotr2 too.
I just copy&pasted results generated with your Pole-Zero placement v2 app to here, thinking that I would see identical amplitude responses, which I don’t. Please try
Pole-Zero placement v2:
entries from top to bottom: 0.88, 0.08, 0.895, 0.185
poles at 0.8523531817931953 ± 0.2188471007050722i
zeros at 0.748047588424602 ± 0.49137542210832796i
a0 = 0.2282997765604545
a1 = -0.3415581945878469
a2 = 0.07262795524876171
b1 = -1.7047063635863906
b2 = 0.6786118930259678
copy&pasted into left field
a0 = 0.2282997765604545
a1 = -0.3415581945878469
a2 = 0.07262795524876171
and right field
1.0
b1 = -1.7047063635863906
b2 = 0.6786118930259678
keep up the good work
olli
Thanks, Olli! At a glance, it looks like a problem with the coefficients generation of the Pole-Zero placement widget. I’ll dig into it as soon at I get a chance, much appreciated…
OK, try it now.
great 🙂
btw, since we are at it, I’ve seen that you’re generating the x points for the log plot using
(Math.pow(base, value) – 1) / (base – 1) * (max – min) + min;
where value goes from 0 to 1.
if equidistant points in the log plot are the goal, the equation would be , e.g. for base 10,
Math.pow(10, Math.log10(max/min)*xi ) * min
you may compare for min,max = 0.1,10 and value = 0.5
not that it would matter 🙂
cheers again
olli
Thanks, Olli. I did catch that I wasn’t doing it quite right, as I grabbed some things from other ancient bits on this site. I “fixed” it, which broke it altogether; short on time, I put it back together and posted for now. (I don’t think it mattered, though; I started off doing my own log scaling as in the past, but discovered flotr2 has log option, and switched to that.)
Looking further, I see I was doing it as you suggested for my Pole-Zero Placement V2 widget all along…really need to rewrite some of these things with common code for the website…btw, I found that base 2 works out better, not surprising for binary computers, and avoids 1.0 turning into 0.999…
Nice. I think it needs a “calculate” button since I could edit the coefficients and nothing would happen until I played with the controls directly below the graph.
One thing that would be really nice is an additional function similar to the test function in the IIR filter designer from http://www.iowahills.com/ for the 2 biquad forms and fixed point with variable register widths and number of fractional bits. In my case I need to design a bass and treble filter (low/high shelf filters which that the Iowahills software does not design) for a form 2 biquad implemented in Verilog (FPGA) that uses fixed point arithmetic and I currently have no idea how big I need to make the register sizes.
Click the chart (see instructions below the coefficient fields).
Yes, fixed point is a problem, and you’ll find the issues mainly at the low frequency end for the direct forms. The feedback coefficients are the most sensitive, since…the error feeds back. Go to the biquad calculator, and make a lowpass filter of, say 100 Hz at 44.1 kHz—not at all an unusual audio filter. Copy the coefficients into the grapher here, and start deleting digits off the the end of the b coefficients. By the time you get down to five significant decimal digits, the response is diverging quite a bit (change the fifth and see how much the chart changes). And consider that 5 digits (99999) correspond more than 16 binary digits.
I’d love to do a truly complete filter designer…time…
Sorry, I usually do better than that at reading instructions… One thing I forgot in my last message was that it would be nice to have some smaller range options or an auto option. The shelf filters for bass and treble don’t show much of a curve even with 60dB. Thanks for the tip with editing the coefficients to reduce the precision. As for avoiding register overflow, I’ll probably write a program for testing that.
Hey Nigel, just playing with this one and I noticed that your graph shows the ‘pass’ area for the virtual signal as peaking at ~-18dB where I know that the pass area for the following coefficients is, sampling at 48K, 0dB from 10Hz to ~1400Hz where the start of the downward slope slowly increases till it is ~-3dB at 2400Hz and ~-30dB at 10Khz; the shape your plot has seems right enough but why is it starting at ~-18dB instead of 0dB ?
low pass fs=48K, fc=~0.05*fs, Q=0.7071; encoded to S1.31 then returned to floating point;
a{ 0.000554271228611469
0.00110854236409068
0.000554271228611469}
and
b{ [1]
-1.77863007877022
0.800800926983356}
Hi Rob,
You don’t say how you calculated your coefficients, but the a coefficients are scaled by 0.1, which is to say -20 dB. Your fc is actually ~0.025*fc. Put that in Biquad calculator v2 and you’ll see.
Ah, and then I discover my comedy of errors… I made a couple of ‘whopper-like’ mistakes before my final error, which was to make the initial comment here.
The second last mistake I made was taking the coefficients generated by my third last mistake and shifting the decimal point one extra spot; ie; 1.234567E-03 != 0.0001234567 I guess I was hazy yesterday after I found the test boxes above do not grok ‘#.####E-#’ and manually shifted each decimal point in the ‘a’ coefs quite poorly 🙂
Hi Nigel.
You mention that if there are no poles then it’s FIR. Does this mean that your grapher will correctly graph FIR filters?
Yes, it works fine for FIR filters.
Nigel hi,
Thanks for this article, I’m becoming addicted to this web site…
I’ve always wondered how professional plug-in EQ’s actually calculate their ‘Frequency Response’ curve, I guess they use this (or similar) methodology? Or maybe they use a more efficient way?
Also, if the discussed plug-in EQ has for example 10 bands and the user ‘drags and drops’ a single band, using the mouse, what would be a good way to calculate the FR graph ?
The immediate methodology would be to hold a loop of 10 bands, which receive the biquads of each band in series and the output FR curve line would be the output of this loop. But that is highly none efficient…
Helpful tool, but it took me some time to understand, that “a” and “b” have oposite meaning to most literature (typically stands b for zeros, a for poles, see https://en.wikipedia.org/wiki/Digital_biquad_filter). And a “recalculate” button would be helpfull.
The classic DSP texts are split on this, and there is also no convention on whether subtractions are rolled into the sign bit, so you have to pay attention. See here. But note that I labeled the fields as to whether they were pole or zero coefficients.