Skip to content

Commit 454be7e

Browse files
Fix: updated filter code
1 parent c0ad5bb commit 454be7e

1 file changed

Lines changed: 28 additions & 123 deletions

File tree

audio_filters/butterworth_filter.py

Lines changed: 28 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from math import cos, sin, sqrt, tau
2-
32
from audio_filters.iir_filter import IIRFilter
43

54
"""
@@ -9,28 +8,21 @@
98
Alternatively you can use scipy.signal.butter, which should yield the same results.
109
"""
1110

12-
13-
def make_lowpass(
14-
frequency: int,
15-
samplerate: int,
16-
q_factor: float = 1 / sqrt(2),
17-
) -> IIRFilter:
18-
"""
19-
Creates a low-pass filter
20-
21-
>>> filter = make_lowpass(1000, 48000)
22-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
23-
[1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.004277569313094809,
24-
0.008555138626189618, 0.004277569313094809]
25-
"""
11+
def _precompute(frequency: int, samplerate: int, q_factor: float):
12+
"""Helper to compute common values for filter design."""
2613
w0 = tau * frequency / samplerate
2714
_sin = sin(w0)
2815
_cos = cos(w0)
2916
alpha = _sin / (2 * q_factor)
17+
return _sin, _cos, alpha
18+
19+
20+
def make_lowpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
21+
"""Creates a low-pass filter."""
22+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
3023

3124
b0 = (1 - _cos) / 2
3225
b1 = 1 - _cos
33-
3426
a0 = 1 + alpha
3527
a1 = -2 * _cos
3628
a2 = 1 - alpha
@@ -40,27 +32,12 @@ def make_lowpass(
4032
return filt
4133

4234

43-
def make_highpass(
44-
frequency: int,
45-
samplerate: int,
46-
q_factor: float = 1 / sqrt(2),
47-
) -> IIRFilter:
48-
"""
49-
Creates a high-pass filter
50-
51-
>>> filter = make_highpass(1000, 48000)
52-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
53-
[1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.9957224306869052,
54-
-1.9914448613738105, 0.9957224306869052]
55-
"""
56-
w0 = tau * frequency / samplerate
57-
_sin = sin(w0)
58-
_cos = cos(w0)
59-
alpha = _sin / (2 * q_factor)
35+
def make_highpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
36+
"""Creates a high-pass filter."""
37+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
6038

6139
b0 = (1 + _cos) / 2
6240
b1 = -1 - _cos
63-
6441
a0 = 1 + alpha
6542
a1 = -2 * _cos
6643
a2 = 1 - alpha
@@ -70,28 +47,13 @@ def make_highpass(
7047
return filt
7148

7249

73-
def make_bandpass(
74-
frequency: int,
75-
samplerate: int,
76-
q_factor: float = 1 / sqrt(2),
77-
) -> IIRFilter:
78-
"""
79-
Creates a band-pass filter
80-
81-
>>> filter = make_bandpass(1000, 48000)
82-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
83-
[1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.06526309611002579,
84-
0, -0.06526309611002579]
85-
"""
86-
w0 = tau * frequency / samplerate
87-
_sin = sin(w0)
88-
_cos = cos(w0)
89-
alpha = _sin / (2 * q_factor)
50+
def make_bandpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
51+
"""Creates a band-pass filter."""
52+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
9053

9154
b0 = _sin / 2
9255
b1 = 0
9356
b2 = -b0
94-
9557
a0 = 1 + alpha
9658
a1 = -2 * _cos
9759
a2 = 1 - alpha
@@ -101,23 +63,9 @@ def make_bandpass(
10163
return filt
10264

10365

104-
def make_allpass(
105-
frequency: int,
106-
samplerate: int,
107-
q_factor: float = 1 / sqrt(2),
108-
) -> IIRFilter:
109-
"""
110-
Creates an all-pass filter
111-
112-
>>> filter = make_allpass(1000, 48000)
113-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
114-
[1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.9077040443587427,
115-
-1.9828897227476208, 1.0922959556412573]
116-
"""
117-
w0 = tau * frequency / samplerate
118-
_sin = sin(w0)
119-
_cos = cos(w0)
120-
alpha = _sin / (2 * q_factor)
66+
def make_allpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
67+
"""Creates an all-pass filter."""
68+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
12169

12270
b0 = 1 - alpha
12371
b1 = -2 * _cos
@@ -128,24 +76,9 @@ def make_allpass(
12876
return filt
12977

13078

131-
def make_peak(
132-
frequency: int,
133-
samplerate: int,
134-
gain_db: float,
135-
q_factor: float = 1 / sqrt(2),
136-
) -> IIRFilter:
137-
"""
138-
Creates a peak filter
139-
140-
>>> filter = make_peak(1000, 48000, 6)
141-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
142-
[1.0653405327119334, -1.9828897227476208, 0.9346594672880666, 1.1303715025601122,
143-
-1.9828897227476208, 0.8696284974398878]
144-
"""
145-
w0 = tau * frequency / samplerate
146-
_sin = sin(w0)
147-
_cos = cos(w0)
148-
alpha = _sin / (2 * q_factor)
79+
def make_peak(frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
80+
"""Creates a peak filter."""
81+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
14982
big_a = 10 ** (gain_db / 40)
15083

15184
b0 = 1 + alpha * big_a
@@ -160,25 +93,11 @@ def make_peak(
16093
return filt
16194

16295

163-
def make_lowshelf(
164-
frequency: int,
165-
samplerate: int,
166-
gain_db: float,
167-
q_factor: float = 1 / sqrt(2),
168-
) -> IIRFilter:
169-
"""
170-
Creates a low-shelf filter
171-
172-
>>> filter = make_lowshelf(1000, 48000, 6)
173-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
174-
[3.0409336710888786, -5.608870992220748, 2.602157875636628, 3.139954022810743,
175-
-5.591841778072785, 2.5201667380627257]
176-
"""
177-
w0 = tau * frequency / samplerate
178-
_sin = sin(w0)
179-
_cos = cos(w0)
180-
alpha = _sin / (2 * q_factor)
96+
def make_lowshelf(frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
97+
"""Creates a low-shelf filter."""
98+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
18199
big_a = 10 ** (gain_db / 40)
100+
182101
pmc = (big_a + 1) - (big_a - 1) * _cos
183102
ppmc = (big_a + 1) + (big_a - 1) * _cos
184103
mpc = (big_a - 1) - (big_a + 1) * _cos
@@ -197,25 +116,11 @@ def make_lowshelf(
197116
return filt
198117

199118

200-
def make_highshelf(
201-
frequency: int,
202-
samplerate: int,
203-
gain_db: float,
204-
q_factor: float = 1 / sqrt(2),
205-
) -> IIRFilter:
206-
"""
207-
Creates a high-shelf filter
208-
209-
>>> filter = make_highshelf(1000, 48000, 6)
210-
>>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE
211-
[2.2229172136088806, -3.9587208137297303, 1.7841414181566304, 4.295432981120543,
212-
-7.922740859457287, 3.6756456963725253]
213-
"""
214-
w0 = tau * frequency / samplerate
215-
_sin = sin(w0)
216-
_cos = cos(w0)
217-
alpha = _sin / (2 * q_factor)
119+
def make_highshelf(frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)) -> IIRFilter:
120+
"""Creates a high-shelf filter."""
121+
_sin, _cos, alpha = _precompute(frequency, samplerate, q_factor)
218122
big_a = 10 ** (gain_db / 40)
123+
219124
pmc = (big_a + 1) - (big_a - 1) * _cos
220125
ppmc = (big_a + 1) + (big_a - 1) * _cos
221126
mpc = (big_a - 1) - (big_a + 1) * _cos

0 commit comments

Comments
 (0)