Digital IIR filters and the biquad cascade
Designing IIR filters in the five classical families (Butterworth, Chebyshev I and II, elliptic, Bessel) as a cascade of second-order sections: bilinear transform, stability from the poles, SOS coefficients and CMSIS-DSP export.
What the tool does
It designs a digital IIR filter from a specification (type, family, order, sample rate and cutoff) and returns the biquad coefficients, the frequency response (magnitude and phase), the pole-zero map and the CMSIS-DSP export. The computation runs in the browser on an own implementation, with no runtime dependencies: analogue prototype → LP→LP / LP→HP transformation → bilinear → SOS, using the Orfanidis algorithm for the elliptic’s Jacobi elliptic functions.
An order-N IIR filter is built as a cascade of second-order sections (SOS): it is the numerically robust form, because a single high-order section accumulates coefficient-quantization errors. Each section is a biquad:
From continuous to discrete: the bilinear transform
The analog prototype (Butterworth or Bessel) is mapped to the z-plane with the bilinear transform. To make the cutoff frequency match exactly, pre-warping is applied:
where T = 1/Fs. The bilinear transform preserves stability and compresses the frequency axis: the whole analog axis 0…∞ lands in 0…Fs/2 (Nyquist).
Stability: read it from the poles
The poles are the roots of each biquad’s denominator; the zeros those of the numerator. The bilinear transform sends the stable analog left half-plane to the inside of the unit circle. Therefore:
The tool computes the poles by solving z² + a₁z + a₂ = 0 for each section and flags whether even one leaves the unit circle.
The five approximations: which to choose
The families are the different ways of approximating the ideal “brick-wall” response. Each is a trade-off between transition steepness, ripple and phase linearity (time-domain fidelity). The tool covers all of them.
Butterworth — maximally flat magnitude
No passband ripple, asymptotic attenuation of 20·N dB/decade, the gentlest roll-off of the group.
When: clean passband, order not critical. A reasonable default with no tight requirements. Use cases: sensor conditioning, mild anti-aliasing, general smoothing.
Chebyshev I — passband ripple
Allows ripple Ap in the passband (parameter ε) in exchange for a steeper transition than Butterworth at the same order. Monotonic stopband.
where Tₙ is the Chebyshev polynomial. When: you need more selectivity and can tolerate some passband ripple. Use cases: channel filters, band separation where passband flatness is not essential.
Chebyshev II (inverse) — stopband ripple
Flat passband (like Butterworth), ripple in the stopband (parameter As). Steep transition, and the equiripple stopband guarantees a constant minimum rejection.
When: you want a clean passband but accept stopband ripple, with a guaranteed rejection floor. Use cases: anti-aliasing where passband flatness matters and a stopband floor is enough.
Elliptic / Cauer — the steepest
Ripple in both bands. For a given order it has the steepest transition of all: no other classical approximation beats it in selectivity for a given N. The price is the most non-linear phase (highly variable group delay near the cutoff) and more overshoot/ringing in time.
where Rₙ is the elliptic rational function (built on Jacobi elliptic functions) and ξ the selectivity factor linking passband and stopband ripple. Limiting cases (which frame its generality):
- stopband ripple → 0 degenerates into Chebyshev I
- passband ripple → 0 degenerates into Chebyshev II
- both → 0 degenerate into Butterworth
So the elliptic is the general form; the other three are its special cases. When: you need maximum steepness with the lowest order (and computational cost), and can tolerate ripple and non-linear phase. Use cases: aggressive anti-aliasing, narrow tone/band rejection, applications where only magnitude matters, not the waveform.
The group delay, measured
Saying the Bessel has “almost constant group delay” is true but says nothing about how much. Computed by finite differences on the phase, in samples, for the four order-4 filters with Fc = 100 Hz and fs = 1000 Hz:
| Family | 10 Hz | 50 Hz | 100 Hz | 150 Hz | In-band spread |
|---|---|---|---|---|---|
| Bessel | 4.93 | 5.04 | 4.49 | 2.63 | 12.4 % |
| Butterworth | 4.04 | 4.66 | 6.29 | 2.61 | 61.4 % |
| Chebyshev I | 4.33 | 5.94 | 13.59 | 1.40 | 213.7 % |
| Elliptic | 3.56 | 5.56 | 17.95 | 1.33 | 404.3 % |
The last column is the percentage spread of the delay between 10 and 100 Hz, and it lines the families up in a precise order: Bessel 12 %, Butterworth 61 %, Chebyshev I 214 %, elliptic 404 %. An edge crossing the elliptic comes out with its spectral components spread by a factor of four in transit time: that is exactly where the ringing comes from. If the signal is a pulse, an edge, a waveform to be measured in the time domain, that column matters more than the steepness.
Note also that the delay falls at 150 Hz for all of them: out of band the filter does not delay, it attenuates, and group delay loses practical meaning.
How much phase linearity survives in the digital domain
The Bessel’s linearity is a property of the analogue prototype, and the bilinear transform deforms it. By how much? It depends on where Fc sits relative to fs:
| f_c / f_s | In-band group-delay spread |
|---|---|
| 0.005 | 21.1 % |
| 0.010 | 21.0 % |
| 0.025 | 20.5 % |
| 0.050 | 18.6 % |
| 0.100 | 12.4 % |
| 0.200 | 26.7 % |
| 0.400 | 750.7 % |
Below fc/fs ≈ 0.1 the digital Bessel keeps the analogue behaviour: the 18–21 % spread is the order-4 prototype’s own, not damage from the transformation. Around 0.2 the bilinear starts to bite, and at fc/fs = 0.4 the spread reaches 750 %: the filter has lost any resemblance to a Bessel. So the practical rule is sharp — if you pick Bessel for the phase, you oversample: digital linear phase is bought with an fs at least ten times the useful band, or you move to a FIR, where it is exact by construction.
Bessel / Thomson — maximally linear phase
Near-constant group delay (linear phase): it preserves the time-domain waveform, no step overshoot. Very gentle roll-off. Note: the Bessel’s phase linearity is an analog property; the bilinear transform distorts it, so in the digital domain it is less sharp (for exact linear phase in digital use FIR filters).
When: time-domain fidelity (pulses, transients, waveforms) matters more than attenuation. Use cases: audio/instrumentation chains where overshoot is unacceptable, reconstruction of steep-edged signals.
The five families are not comparable at a fixed frequency
Before any comparison, one misunderstanding has to be cleared up, because it misleads almost everybody. The tool’s Fc field does not mean the same thing for the five families: each normalizes its prototype on a different edge, and the magnitude at Fc shows it immediately.
| Family | What f_c means | Magnitude at f_c |
|---|---|---|
| Butterworth | −3 dB edge | −3.01 dB |
| Chebyshev I | passband ripple edge | −1.00 dB |
| Chebyshev II | stopband edge | −40.00 dB |
| Elliptic | passband ripple edge | −1.00 dB |
| Bessel | delay normalization | −7.58 dB |
So the question “how much does it attenuate at 2·Fc?” has no comparable answer: you are measuring five filters whose origin sits in five different places. Comparing families at a fixed frequency leads, for instance, to concluding that Chebyshev II is phenomenal at order 2 — when in fact you are only reading back the value that was imposed on it by definition.
The two metrics that do compare
The first is the transition width: at what multiple of Fc the response reaches 40 dB of attenuation.
| Family | N = 2 | N = 4 | N = 6 | N = 8 |
|---|---|---|---|---|
| Bessel | × 4.05 | × 2.52 | × 1.91 | × 1.63 |
| Butterworth | × 4.05 | × 2.54 | × 1.95 | × 1.67 |
| Chebyshev I | × 4.04 | × 2.07 | × 1.48 | × 1.27 |
| Chebyshev II | × 1.00 | × 1.00 | × 1.00 | × 1.00 |
| Elliptic | × 3.69 | × 1.46 | × 1.09 | × 1.02 |
Read that way, the hierarchy is the expected one: the elliptic wins (1.02·Fc at order 8, essentially a wall), then Chebyshev I, then Butterworth and Bessel neck and neck. Chebyshev II reads 1.00 at every order because its Fc is the stopband edge: that row does not say it is the steepest, it says the question is ill-posed for that family.
The second is the stopband floor, that is the worst attenuation across the whole dark band:
| Family | N = 2 | N = 4 | N = 6 | N = 8 |
|---|---|---|---|---|
| Bessel | −14.9 dB | −29.0 dB | −43.0 dB | −56.9 dB |
| Butterworth | −14.1 dB | −28.0 dB | −41.9 dB | −55.9 dB |
| Chebyshev I | −13.4 dB | −38.3 dB | −63.3 dB | −88.4 dB |
| Chebyshev II | −40.0 dB | −40.0 dB | −40.0 dB | −40.0 dB |
| Elliptic | −13.8 dB | −40.0 dB | −40.0 dB | −40.0 dB |
Here the structural difference between the two halves of the table shows. Butterworth, Bessel and Chebyshev I have no stopband specification, so the floor drops with order — Chebyshev I reaches −88 dB at order 8. Chebyshev II and the elliptic have an equiripple stopband set by the Rs parameter: raising the order does not deepen the attenuation, it pins it at −40 dB and narrows the transition. These are two different design philosophies, and picking one at random is the most common way to waste order.
One boundary case deserves a note: the elliptic at order 2 does not reach 40 dB (it reads −13.8) because with two poles no solution satisfies 1 dB of ripple and 40 dB of stopband at once. That is not a calculation defect: it is the degree equation saying that specification needs at least order 4.
CMSIS-DSP export
Coefficients are exported for Arm’s arm_biquad_cascade_df2T_f32: 5 values per stage as {b0, b1, b2, a1, a2}, with a1 and a2 negated relative to the transfer function. CMSIS in fact implements:
The minus sign is already baked into the generated coefficients: copy the float32_t array straight into the firmware.
Validation and limits
The magnitude response of all five families (LP and HP) was compared against scipy.signal (butter, cheby1, cheby2, ellip, bessel → sosfreqz), with all poles inside the unit circle (automated tests included in the repository).
| Family | Point | Here | scipy (2 decimals) |
|---|---|---|---|
| Butterworth | 100 Hz | −3.010 dB | −3.01 dB |
| Butterworth | 200 Hz | −27.966 dB | −27.97 dB |
| Chebyshev I | 200 Hz | −38.269 dB | −38.27 dB |
| Chebyshev II | 200 Hz | −51.056 dB | −51.06 dB |
| Elliptic | 200 Hz | −40.881 dB | −40.88 dB |
| Bessel | 100 Hz | −7.578 dB | −7.58 dB |
The references are transcribed to two decimals, so a comparison against this table cannot say more than ±0.005 dB: the thousandths of a difference are the residue of that truncation, not an error in the design.
Where a closed form exists the reference is computed rather than transcribed, and the check becomes exact. For the bilinear Butterworth with prewarping
and at f = 2·f_c the ratio of the tangents is exactly √5, so the expected value is −10·log₁₀(1 + 5^N) = −27.965743 dB for N = 4 — the figure in the table. The generated biquad cascade matches the closed form to machine precision across the band and for every order 2–8: the test Butterworth contro la forma chiusa checks it with a 10⁻⁹ dB tolerance.
One caveat on method, if you want to redo the check: the dB has to be evaluated exactly at the frequency, not read off the nearest point of the response grid. At 512 points that read is 0.09 dB off at 200 Hz — twenty times the difference being looked for.
The elliptic uses the Orfanidis algorithm (Landen transformation for the Jacobi elliptic functions).
v0.2 limits: lowpass and highpass, even orders 2–8. Bandpass/bandstop coming. Cutoff Fc = passband edge (−3 dB for Butterworth; ripple edge for Chebyshev I and Elliptic; stopband edge for Chebyshev II; delay normalization for Bessel). Demonstrative tool: it does not replace the design and verification tools of a production DSP toolchain.
A similar project?
Acoustics, embedded, calculation tools: if you have a related use case, let’s talk.