BIQUAD

← all examples · interactive version of jupyter/biquad.ipynb · analog front end
v_i
k2·s² + k1·s + k0
÷
s² + (w0/Q)·s + w0²
v_o
RESPONSE
Every one of these is the same denominator with a different numerator. The poles never move; only the zeros do.
POLES
ZEROS (NUMERATOR)
f0
Q
POLES
PEAK
DC / HF GAIN
OVERSHOOT
|H| and phase
Poles
Zeros
f0
Step / group delay

WHAT YOU ARE LOOKING AT

The notebook this comes from is not really about biquads. It is about not trusting your own algebra. It writes a signal flow graph down as three equations, hands them to sympy, and asks what transfer function falls out:

u1 = -w0*vo + vi*k0/w0
u2 = -w0/Q*vo + w0*u1/s + k1*vi + k2*s*vi
vo = u2/s

Do that by hand and you get

H(s) = (k2·s² + k1·s + k0) / (s² + (w0/Q)·s + w0²)

which is the standard biquad. There is no computer algebra in this page — that would mean shipping a CAS to a browser — so the derivation was done once by hand and then checked numerically against the three equations above at two hundred random points. They agree to fifteen digits.

What is worth having interactively is the other half: what that expression does. The denominator alone fixes the two poles, and therefore the ringing, the peaking and the settling. The numerator only places zeros, and that is the whole difference between a low-pass, a band-pass, a high-pass, a notch and an all-pass. Press the buttons and watch the poles stay exactly where they are.

THINGS WORTH TRYING

THE NOTEBOOK

Source: jupyter/biquad.ipynb, which uses sympy and sympy.physics.control to expand the flow graph. Its first cell does the same for a simpler single-integrator graph. For the discrete-time equivalent of all this, see the IIR example, where the same ideas live on the z-plane and the unit circle replaces the jω axis.