Skip to main content
Computed

20 Hz high-pass

Rejects everything below the corner at 12 dB/octave and passes what is above it. Solved at 8 sample rates, with the poles, the real −3 dB point and the word length it stops working at.

Magnitude response at 48 kHz

Every vertex is 20·log₁₀|H(e)| evaluated on the unit circle — not a sketch of the filter's shape. The faint traces behind it are the same corner at every Q in the sweep below.

-18-12-60+6+12+18+241020501002005001k2k5k10k20k20 HzdBHz · 48 kHz

Gain at f0 (20 Hz)

−3.01 dB

exact at every sample rate — the bilinear transform maps this value, not just the frequency

Pole radius at 48 kHz

0.9981505

conjugate pair at ±0.11°, 0.00185 from the circle

−3 dB point

20.0 Hz

1.000× f0 at Q = 0.7071

16-bit fixed point

diverges

largest pole 1.0000000 in Q1.14

Coefficients, at every sample rate

The cookbook computes w₀ = 2πf₀/Fs, so the same filter is a different set of numbers at every rate. Rates whose Nyquist limit is at or below 20 Hz are absent because the filter does not exist there — equivalently, the f₀/Nyquist column never reaches 100%. That is why this table is 8 rows and a 20 Hz page is 8.

Sample rateb0b1b2a1a2Pole rf₀/Nyquist
8 kHz0.988954-1.9779080.988954-1.9777860.9780310.9889540.5%
16 kHz0.994462-1.9889240.994462-1.9888930.9889540.9944620.3%
22.1 kHz0.995978-1.9919570.995978-1.9919400.9919730.9959780.2%
32 kHz0.997227-1.9944540.997227-1.9944460.9944620.9972270.1%
44.1 kHz0.997987-1.9959740.997987-1.9959700.9959780.9979870.1%
48 kHz0.998151-1.9963010.998151-1.9962980.9963040.9981510.1%
96 kHz0.999075-1.9981500.999075-1.9981490.9981510.9990750.0%
192 kHz0.999537-1.9990750.999537-1.9990740.9990750.9995370.0%
const float b0 = 0.99815051f, b1 = -1.99630102f, b2 = 0.99815051f;
const float a1 = -1.99629760f, a2 = 0.99630444f;   // a0 == 1

What word length this filter survives

The fixed-point rows round all five coefficients to one shared scale, which is what a q15/q31 biquad section does with its post-shift.Pole radius is solved from the quadratic, not taken as √|a₂| — once rounding pushes the poles onto the real axis those two disagree, and the convenient one reports a comfortable margin on a filter that has already left the unit circle. Error is the worst deviation from float64 across frequencies where the response is within 40 dB of its own peak; below that it is measuring the −200 dB floor.

Word formatQ formatLargest pole√|a₂| saysStableWorst error in band
float640.99815050.9981505yesreference
float320.99815050.9981505yes0.0119 dB
32-bit fixedQ1.300.99815050.9981505yes0.0050 dB
24-bit fixedQ1.220.99815050.9981505yes1.3692 dB
16-bit fixedQ1.141.0000000 (real)0.9981367non/a — diverges

Read the two pole columns against each other on the 16-bit row.√|a₂| reports 0.9981367 — well inside the unit circle — while the larger real pole is actually at 1.0000000. The shortcut is the geometric mean of the two poles and is exact only while they are a conjugate pair. Evaluated rather than inferred, the quantised filter has +122 dB of gain near DC in that format — a filter that diverges, not one that is merely inaccurate.

What Q does at 20 Hz

f₀ does not move with Q — the −3 dB point does. They are the same frequency only at Q = 1/√2, which is why a Butterworth corner is the one people quote and why every other Q surprises somebody.

QAt f₀Peak−3 dBPole rGroup delay at f₀
0.5−6.02 dB0.00 dB @ 24.00 kHz31.1 Hz0.9973857.959 ms
0.7071−3.01 dB0.00 dB @ 23.23 kHz20.0 Hz0.99815111.253 ms
10.00 dB+1.25 dB @ 28 Hz17.1 Hz0.99869215.907 ms
2+6.02 dB+6.29 dB @ 21 Hz32.0 Hz0.99934631.735 ms
4+12.04 dB+12.10 dB @ 20 Hz23.6 Hz0.99967362.852 ms
10+20.00 dB+19.77 dB @ 20 Hz21.2 Hz0.999869147.620 ms

Questions this filter answers

What are the biquad coefficients for a 20 Hz high-pass filter at 48 kHz?

b0 = 0.998151, b1 = -1.996301, b2 = 0.998151, a1 = -1.996298, a2 = 0.996304, with a0 normalised to 1 — the RBJ Audio EQ Cookbook form at Q = 0.7071. Every other sample rate in the table above gives different numbers for the same filter, because w0 = 2πf0/Fs and every cosine and sine downstream of it moves.

Is a 20 Hz high-pass filter stable in 16-bit fixed point?

No. Rounding the five coefficients to a shared 1.14 scale pushes the poles onto the real axis and the larger one out to 1.0000000 — at or outside the unit circle, which is a filter that diverges rather than one that is merely inaccurate. Note that √|a2| still reads 0.9981367 here, comfortably inside the circle: the shortcut is the geometric mean of the two real poles and it does not see this. Use 24-bit (largest pole 0.9981505) or float32.

Where is the real −3 dB point of a 20 Hz high-pass filter?

20.0 Hz, which is 1.000× the 20 Hz corner. f0 and the −3 dB point are the same frequency only at Q = 1/√2; this page is designed at Q = 0.7071, and the Q sweep above shows the point moving from 31.1 Hz to 21.2 Hz across the sweep while f0 never moves.

How close to the unit circle are the poles of a 20 Hz high-pass filter?

0.9981505 at 48 kHz, as a conjugate pair at ±0.11°. Pole radius rises toward 1 as the corner frequency falls relative to the sample rate — the same filter at 192 kHz sits at 0.9995373 and at 8 kHz at 0.9889542. That distance is the whole story of the fixed-point table: a pole a few parts in 10⁵ from the circle has nowhere to be rounded to.

The neighbouring corners

One third-octave either side, and the same 20 Hz corner as every other filter type.

Method and limits. Coefficients follow the RBJ Audio EQ Cookbook, the bilinear transform of the analog prototype prewarped so the corner lands exactly on f0 — which is why −3.01 dB at 20 Hz holds at every sample rate in the table rather than only at low f0/Fs. Shelves fix the slope at S = 1, matching Web Audio's BiquadFilterNode, so Q is not read for those two types. Pole and zero radii are the roots of the quadratic, not sqrt(|a2|). The fixed-point rows model a single shared coefficient scale and no other quantisation: they say nothing about signal-path headroom, limit cycles or the accumulator width your implementation uses, all of which can make a filter that passes this table still misbehave. Nothing on this page is fetched or estimated — it is solved from the type and the frequency in the URL.