11from math import cos , sin , sqrt , tau
2-
32from audio_filters .iir_filter import IIRFilter
43
54"""
98Alternatively 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