Skip to content

Commit 764c115

Browse files
audio_filters: clarify make_notch, document biquad notation, tighten set_coefficients guard
- Add a shared notation guide to butterworth_filter so the single-letter RBJ-cookbook names (w0/alpha/a0..a2/b0..b2) are self-explanatory across every filter instead of diverging in one function. - Comment make_notch's feed-forward/feed-back sections in plain English. - set_coefficients only fills the optional a_0 when exactly one coefficient is missing, so genuinely too-short inputs raise with their real length (new regression doctest).
1 parent 6e03d21 commit 764c115

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

‎audio_filters/butterworth_filter.py‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
Alternatively you can use scipy.signal.butter, which should yield the same results.
1010
1111
https://en.wikipedia.org/wiki/Butterworth_filter
12+
13+
Notation used throughout this module (from the RBJ Audio EQ Cookbook):
14+
w0 -- normalised angular frequency, ``2 * pi * frequency / samplerate``
15+
alpha -- bandwidth parameter, ``sin(w0) / (2 * q_factor)``
16+
b0..b2 -- feed-forward (numerator) coefficients of the biquad
17+
a0..a2 -- feed-back (denominator) coefficients of the biquad
18+
The a/b coefficient names match ``IIRFilter.set_coefficients`` and the standard
19+
biquad transfer function, so they are kept consistent across every filter here.
1220
"""
1321

1422

@@ -254,15 +262,19 @@ def make_notch(
254262
[1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 1.0,
255263
-1.9828897227476208, 1.0]
256264
"""
257-
w0 = tau * frequency / samplerate
265+
w0 = tau * frequency / samplerate # centre frequency, in radians/sample
258266
_sin = sin(w0)
259267
_cos = cos(w0)
260-
alpha = _sin / (2 * q_factor)
268+
alpha = _sin / (2 * q_factor) # controls how narrow the rejected band is
261269

270+
# Feed-forward: a pair of zeros placed exactly on the notch frequency, so
271+
# that frequency is fully cancelled while the rest of the spectrum passes.
262272
b0 = 1.0
263273
b1 = -2 * _cos
264274
b2 = 1.0
265275

276+
# Feed-back: matching poles just inside the unit circle keep the notch
277+
# narrow and the surrounding gain flat.
266278
a0 = 1 + alpha
267279
a1 = -2 * _cos
268280
a2 = 1 - alpha

‎audio_filters/iir_filter.py‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,19 @@ def set_coefficients(self, a_coeffs: list[float], b_coeffs: list[float]) -> None
6969
Traceback (most recent call last):
7070
...
7171
ValueError: Expected b_coeffs to have 3 elements for 2-order filter, got 2
72+
73+
A genuinely too-short ``a_coeffs`` is reported with its real length
74+
rather than after the optional ``a_0`` has been filled in:
75+
76+
>>> IIRFilter(2).set_coefficients([1.0], [1.0, 2.0, 3.0])
77+
Traceback (most recent call last):
78+
...
79+
ValueError: Expected a_coeffs to have 3 elements for 2-order filter, got 1
7280
"""
73-
if len(a_coeffs) < self.order + 1:
81+
if len(a_coeffs) == self.order:
82+
# The leading a_0 coefficient is optional; default it to 1.0.
83+
# Only a single missing coefficient is filled in this way, so that
84+
# genuinely too-short inputs are reported with their real length.
7485
a_coeffs = [1.0, *a_coeffs]
7586

7687
if len(a_coeffs) != self.order + 1:

0 commit comments

Comments
 (0)