1010
1111
1212@njit (cache = True )
13- def gen_high_shelf (f0 , dbgain , qfactor , fs ):
14- """Generate high shelving filter coeficcients (digital).
15- f0: The center frequency where the gain in decibel is at half the maximum value.
16- Normalized to sampling frequency, i.e output will be filter from 0 to 2pi.
17- dbgain: gain at the top of the shelf in decibels
18- qfactor: determines shape of filter TODO: Document better
19- fs: sampling frequency
20-
21- TODO: Generate based on -3db
22- Based on: https://www.w3.org/2011/audio/audio-eq-cookbook.html
23- """
24- a = 10 ** (dbgain / 40.0 )
25- w0 = 2 * math .pi * (f0 / fs )
26- alpha = math .sin (w0 ) / (2 * qfactor )
27-
28- cosw0 = math .cos (w0 )
29- asquared = math .sqrt (a )
13+ def gen_shelf (f0 , dbgain , type , fs , qfactor = None , bandwidth = None , slope = None ):
14+ """Generate shelving filter coefficients (digital).
15+ * f0:
16+ The center frequency where the gain in decibel is at half the maximum value.
17+ Normalized to sampling frequency, i.e output will be filter from 0 to 2pi.
18+ * dbgain:
19+ gain at the top of the shelf in decibels
20+ * fs:
21+ sampling frequency
22+ * type:
23+ "high" for high shelf, "low" for low shelf
24+
25+ and one of the following:
26+ * qfactor:
27+ determines shape of filter TODO: Document better
28+ * bandwidth:
29+ bandwidth in octaves between midpoint (dbGain / 2) gain frequencies
30+ * slope:
31+ shelf slope. When slope=1, the shelf slope is as steep as it can be and
32+ remain monotonically increasing or decreasing gain with frequency.
33+ The shelf slope, in dB/octave, remains proportional to S for all other
34+ values for a fixed and
3035
31- b0 = a * ((a + 1 ) + (a - 1 ) * cosw0 + 2 * asquared * alpha )
32- b1 = - 2 * a * ((a - 1 ) + (a + 1 ) * cosw0 )
33- b2 = a * ((a + 1 ) + (a - 1 ) * cosw0 - 2 * asquared * alpha )
34- a0 = (a + 1 ) - (a - 1 ) * cosw0 + 2 * asquared * alpha
35- a1 = 2 * ((a - 1 ) - (a + 1 ) * cosw0 )
36- a2 = (a + 1 ) - (a - 1 ) * cosw0 - 2 * asquared * alpha
37- return [b0 , b1 , b2 ], [a0 , a1 , a2 ]
38-
39-
40- @njit (cache = True )
41- def gen_low_shelf (f0 , dbgain , qfactor , fs ):
42- """Generate low shelving filter coeficcients (digital).
43- f0: The center frequency where the gain in decibel is at half the maximum value.
44- Normalized to sampling frequency, i.e output will be filter from 0 to 2pi.
45- dbgain: gain at the top of the shelf in decibels
46- qfactor: determines shape of filter TODO: Document better
47- fs: sampling frequency
48-
49- TODO: Generate based on -3db
5036 Based on: https://www.w3.org/2011/audio/audio-eq-cookbook.html
5137 """
5238 a = 10 ** (dbgain / 40.0 )
5339 w0 = 2 * math .pi * (f0 / fs )
54- alpha = math .sin (w0 ) / (2 * qfactor )
40+
41+ if qfactor != None :
42+ alpha = math .sin (w0 ) / (2 * qfactor )
43+ elif bandwidth != None :
44+ alpha = math .sin (w0 ) * math .sinh ((math .log (2 ) / 2 ) * bandwidth * (w0 / math .sin (w0 )))
45+ elif slope != None :
46+ alpha = math .sin (w0 / 2 ) * math .sqrt ((a + 1 / a ) * (1 / slope - 1 ) + 2 )
47+ else :
48+ raise Exception ("Must specify one value for either qfactor, bandwidth, or slope" )
5549
5650 cosw0 = math .cos (w0 )
5751 asquared = math .sqrt (a )
5852
59- b0 = a * ((a + 1 ) - (a - 1 ) * cosw0 + 2 * asquared * alpha )
60- b1 = 2 * a * ((a - 1 ) - (a + 1 ) * cosw0 )
61- b2 = a * ((a + 1 ) - (a - 1 ) * cosw0 - 2 * asquared * alpha )
62- a0 = (a + 1 ) + (a - 1 ) * cosw0 + 2 * asquared * alpha
63- a1 = - 2 * ((a - 1 ) + (a + 1 ) * cosw0 )
64- a2 = (a + 1 ) + (a - 1 ) * cosw0 - 2 * asquared * alpha
53+ if type == "low" :
54+ b0 = a * ((a + 1 ) - (a - 1 ) * cosw0 + 2 * asquared * alpha )
55+ b1 = 2 * a * ((a - 1 ) - (a + 1 ) * cosw0 )
56+ b2 = a * ((a + 1 ) - (a - 1 ) * cosw0 - 2 * asquared * alpha )
57+ a0 = (a + 1 ) + (a - 1 ) * cosw0 + 2 * asquared * alpha
58+ a1 = - 2 * ((a - 1 ) + (a + 1 ) * cosw0 )
59+ a2 = (a + 1 ) + (a - 1 ) * cosw0 - 2 * asquared * alpha
60+ elif type == "high" :
61+ b0 = a * ((a + 1 ) + (a - 1 ) * cosw0 + 2 * asquared * alpha )
62+ b1 = - 2 * a * ((a - 1 ) + (a + 1 ) * cosw0 )
63+ b2 = a * ((a + 1 ) + (a - 1 ) * cosw0 - 2 * asquared * alpha )
64+ a0 = (a + 1 ) - (a - 1 ) * cosw0 + 2 * asquared * alpha
65+ a1 = 2 * ((a - 1 ) - (a + 1 ) * cosw0 )
66+ a2 = (a + 1 ) - (a - 1 ) * cosw0 - 2 * asquared * alpha
67+ else :
68+ raise Exception ("Must specify 'high' or 'low' for shelf type, instead got: " , type )
69+
6570 return [b0 , b1 , b2 ], [a0 , a1 , a2 ]
6671
6772
@@ -82,8 +87,14 @@ def __init__(self, fs, dBgain, mid_point, Q=1 / 2):
8287 # TODO:
8388 # We want to generate this based on time constant and 'X' value
8489 # currently we use the mid frequency and a gain to get the correct shape
85- # with eyeballed mid value. Q=1/2 seems to give the corret slope.
86- self .ataps , self .btaps = gen_high_shelf (mid_point , dBgain , Q , fs )
90+ # with eyeballed mid value. Q=1/2 seems to give the correct slope.
91+ self .ataps , self .btaps = gen_shelf (
92+ mid_point ,
93+ dBgain ,
94+ "high" ,
95+ fs ,
96+ qfactor = Q
97+ )
8798
8899 def get (self ):
89100 return self .btaps , self .ataps
0 commit comments