biquad 0.3__py3-none-any.whl → 0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
biquad/__init__.py CHANGED
@@ -1,55 +1,55 @@
1
- __version__ = "0.3"
2
-
3
-
4
- from .allpass import allpass
5
- from .bandpass import bandpass
6
- from .biquad import biquad
7
- from .highpass import highpass
8
- from .highshelf import highshelf
9
- from .lowpass import lowpass
10
- from .lowshelf import lowshelf
11
- from .notch import notch
12
- from .peak import peak
13
-
14
-
15
- def filter(name, sr, **kwargs):
16
- """
17
- Create a filter instance of the specified filter name.
18
-
19
- Parameters
20
- ----------
21
- sr : int or float
22
- Sample rate in hertz.
23
- f : int or float, optional
24
- Persistent filter frequency parameter in hertz.
25
- q : int or float, optional
26
- Persistent filter quality parameter.
27
- """
28
-
29
- name = str(name).lower()
30
-
31
- if name in ['allpass', 'all', 'ap', 'apf']:
32
- return allpass(sr, **kwargs)
33
-
34
- if name in ['bandpass', 'band', 'bp', 'bpf']:
35
- return bandpass(sr, **kwargs)
36
-
37
- if name in ['highpass', 'high', 'hp', 'hpf']:
38
- return highpass(sr, **kwargs)
39
-
40
- if name in ['highshelf', 'hs', 'hsf']:
41
- return highshelf(sr, **kwargs)
42
-
43
- if name in ['lowpass', 'low', 'lp', 'lpf']:
44
- return lowpass(sr, **kwargs)
45
-
46
- if name in ['lowshelf', 'ls', 'lsf']:
47
- return lowshelf(sr, **kwargs)
48
-
49
- if name in ['notch', 'nf']:
50
- return notch(sr, **kwargs)
51
-
52
- if name in ['peak', 'pf']:
53
- return peak(sr, **kwargs)
54
-
55
- return biquad(sr, **kwargs)
1
+ __version__ = "0.5"
2
+
3
+
4
+ from .allpass import allpass
5
+ from .bandpass import bandpass
6
+ from .biquad import biquad
7
+ from .highpass import highpass
8
+ from .highshelf import highshelf
9
+ from .lowpass import lowpass
10
+ from .lowshelf import lowshelf
11
+ from .notch import notch
12
+ from .peak import peak
13
+
14
+
15
+ def filter(name, sr, **kwargs):
16
+ """
17
+ Create a filter instance of the specified filter name.
18
+
19
+ Parameters
20
+ ----------
21
+ sr : int or float
22
+ Sample rate in hertz.
23
+ f : int or float, optional
24
+ Persistent filter frequency parameter in hertz.
25
+ q : int or float, optional
26
+ Persistent filter quality parameter.
27
+ """
28
+
29
+ name = str(name).lower()
30
+
31
+ if name in ['allpass', 'all', 'ap', 'apf']:
32
+ return allpass(sr, **kwargs)
33
+
34
+ if name in ['bandpass', 'band', 'bp', 'bpf']:
35
+ return bandpass(sr, **kwargs)
36
+
37
+ if name in ['highpass', 'high', 'hp', 'hpf']:
38
+ return highpass(sr, **kwargs)
39
+
40
+ if name in ['highshelf', 'hs', 'hsf']:
41
+ return highshelf(sr, **kwargs)
42
+
43
+ if name in ['lowpass', 'low', 'lp', 'lpf']:
44
+ return lowpass(sr, **kwargs)
45
+
46
+ if name in ['lowshelf', 'ls', 'lsf']:
47
+ return lowshelf(sr, **kwargs)
48
+
49
+ if name in ['notch', 'nf']:
50
+ return notch(sr, **kwargs)
51
+
52
+ if name in ['peak', 'pf']:
53
+ return peak(sr, **kwargs)
54
+
55
+ return biquad(sr, **kwargs)
biquad/allpass.py CHANGED
@@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
6
6
  Source: https://github.com/jurihock/biquad
7
7
  """
8
8
 
9
- from .biquad import biquad, __df1__
9
+ from .biquad import biquad, __df1__, __gain__, __resize__
10
10
 
11
11
  import numba
12
12
  import numpy
@@ -17,7 +17,7 @@ class allpass(biquad):
17
17
  Allpass filter (APF).
18
18
  """
19
19
 
20
- def __init__(self, sr, *, f=None, q=1):
20
+ def __init__(self, sr, f=None, g=0, q=1):
21
21
  """
22
22
  Create a new filter instance.
23
23
 
@@ -27,15 +27,17 @@ class allpass(biquad):
27
27
  Sample rate in hertz.
28
28
  f : int or float, optional
29
29
  Persistent filter frequency parameter in hertz.
30
+ g : int or float, optional
31
+ Persistent filter gain parameter in decibel.
30
32
  q : int or float, optional
31
33
  Persistent filter quality parameter.
32
34
  """
33
35
 
34
- super().__init__(sr=sr, f=f, q=q)
36
+ super().__init__(sr=sr, f=f, g=g, q=q)
35
37
 
36
- self.__call__(0, 1) # warmup numba
38
+ self.__call__(0) # warmup numba
37
39
 
38
- def __call__(self, x, f=None, q=None):
40
+ def __call__(self, x, f=None, g=None, q=None):
39
41
  """
40
42
  Process single or multiple contiguous signal values at once.
41
43
 
@@ -45,6 +47,8 @@ class allpass(biquad):
45
47
  Filter input data.
46
48
  f : scalar or array like, optional
47
49
  Instantaneous filter frequency parameter in hertz.
50
+ g : scalar or array like, optional
51
+ Instantaneous filter gain parameter in decibel.
48
52
  q : scalar or array like, optional
49
53
  Instantaneous filter quality parameter.
50
54
 
@@ -62,21 +66,23 @@ class allpass(biquad):
62
66
  x = numpy.atleast_1d(x)
63
67
  y = numpy.zeros(x.shape, x.dtype)
64
68
 
65
- f = numpy.atleast_1d(self.f if f is None else f)
66
- q = numpy.atleast_1d(self.q if q is None else q)
67
-
68
- f = numpy.resize(f, x.shape)
69
- q = numpy.resize(q, x.shape)
69
+ f = __resize__(self.f if f is None else f, x.shape)
70
+ g = __resize__(self.g if g is None else __gain__(g), x.shape)
71
+ q = __resize__(self.q if q is None else q, x.shape)
70
72
 
71
73
  sr = self.sr
72
74
 
73
- self.__filter__(ba, xy, x, y, f, q, sr)
75
+ self.__filter__(ba, xy, x, y, f, g, q, sr)
76
+
77
+ self.f = f[-1]
78
+ self.g = g[-1]
79
+ self.q = q[-1]
74
80
 
75
81
  return y[0] if scalar else y
76
82
 
77
83
  @staticmethod
78
84
  @numba.jit(nopython=True, fastmath=True)
79
- def __filter__(ba, xy, x, y, f, q, sr):
85
+ def __filter__(ba, xy, x, y, f, g, q, sr):
80
86
 
81
87
  rs = 2 * numpy.pi / sr
82
88
 
@@ -87,18 +93,18 @@ class allpass(biquad):
87
93
  cosw = numpy.cos(w)
88
94
  sinw = numpy.sin(w)
89
95
 
90
- c = -(2 * cosw)
91
- p = sinw / (2 * q[i])
96
+ alpha = sinw / (+2 * q[i])
97
+ beta = cosw * (-2)
92
98
 
93
99
  # update b
94
- ba[0, 0] = 1 - p
95
- ba[0, 1] = c
96
- ba[0, 2] = 1 + p
100
+ ba[0, 0] = 1 - alpha
101
+ ba[0, 1] = beta
102
+ ba[0, 2] = 1 + alpha
97
103
 
98
104
  # update a
99
- ba[1, 0] = 1 + p
100
- ba[1, 1] = c
101
- ba[1, 2] = 1 - p
105
+ ba[1, 0] = 1 + alpha
106
+ ba[1, 1] = beta
107
+ ba[1, 2] = 1 - alpha
102
108
 
103
109
  # update y
104
- __df1__(ba, xy, x, y, i)
110
+ __df1__(g[i], ba, xy, x, y, i)
biquad/bandpass.py CHANGED
@@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
6
6
  Source: https://github.com/jurihock/biquad
7
7
  """
8
8
 
9
- from .biquad import biquad, __df1__
9
+ from .biquad import biquad, __df1__, __gain__, __resize__
10
10
 
11
11
  import numba
12
12
  import numpy
@@ -17,7 +17,7 @@ class bandpass(biquad):
17
17
  Bandpass filter (BPF).
18
18
  """
19
19
 
20
- def __init__(self, sr, gain='skirt', *, f=None, q=0.7071):
20
+ def __init__(self, sr, f=None, g=0, q=0.7071, *, mode='peak'):
21
21
  """
22
22
  Create a new filter instance.
23
23
 
@@ -25,23 +25,25 @@ class bandpass(biquad):
25
25
  ----------
26
26
  sr : int or float
27
27
  Sample rate in hertz.
28
- gain : str, skirt or peak, optional
29
- Choice between constant skirt gain or constant 0 dB peak gain.
30
28
  f : int or float, optional
31
29
  Persistent filter frequency parameter in hertz.
30
+ g : int or float, optional
31
+ Persistent filter gain parameter in decibel.
32
32
  q : int or float, optional
33
33
  Persistent filter quality parameter.
34
+ mode : str, peak or skirt, optional
35
+ Choice between constant 0 dB peak gain or constant skirt gain.
34
36
  """
35
37
 
36
- super().__init__(sr=sr, f=f, q=q)
38
+ super().__init__(sr=sr, f=f, g=g, q=q)
37
39
 
38
- assert gain in ['skirt', 'peak']
40
+ assert mode in ['peak', 'skirt']
39
41
 
40
- self.gain = gain
42
+ self.mode = mode
41
43
 
42
- self.__call__(0, 1) # warmup numba
44
+ self.__call__(0) # warmup numba
43
45
 
44
- def __call__(self, x, f=None, q=None):
46
+ def __call__(self, x, f=None, g=None, q=None):
45
47
  """
46
48
  Process single or multiple contiguous signal values at once.
47
49
 
@@ -51,6 +53,8 @@ class bandpass(biquad):
51
53
  Filter input data.
52
54
  f : scalar or array like, optional
53
55
  Instantaneous filter frequency parameter in hertz.
56
+ g : scalar or array like, optional
57
+ Instantaneous filter gain parameter in decibel.
54
58
  q : scalar or array like, optional
55
59
  Instantaneous filter quality parameter.
56
60
 
@@ -68,25 +72,27 @@ class bandpass(biquad):
68
72
  x = numpy.atleast_1d(x)
69
73
  y = numpy.zeros(x.shape, x.dtype)
70
74
 
71
- f = numpy.atleast_1d(self.f if f is None else f)
72
- q = numpy.atleast_1d(self.q if q is None else q)
73
-
74
- f = numpy.resize(f, x.shape)
75
- q = numpy.resize(q, x.shape)
75
+ f = __resize__(self.f if f is None else f, x.shape)
76
+ g = __resize__(self.g if g is None else __gain__(g), x.shape)
77
+ q = __resize__(self.q if q is None else q, x.shape)
76
78
 
77
79
  sr = self.sr
78
- gain = self.gain
80
+ mode = self.mode
81
+
82
+ self.__filter__(ba, xy, x, y, f, g, q, sr, mode)
79
83
 
80
- self.__filter__(ba, xy, x, y, f, q, sr, gain)
84
+ self.f = f[-1]
85
+ self.g = g[-1]
86
+ self.q = q[-1]
81
87
 
82
88
  return y[0] if scalar else y
83
89
 
84
90
  @staticmethod
85
91
  @numba.jit(nopython=True, fastmath=True)
86
- def __filter__(ba, xy, x, y, f, q, sr, gain):
92
+ def __filter__(ba, xy, x, y, f, g, q, sr, mode):
87
93
 
88
94
  rs = 2 * numpy.pi / sr
89
- skirt = gain == 'skirt'
95
+ skirt = mode == 'skirt'
90
96
 
91
97
  for i in range(x.size):
92
98
 
@@ -95,19 +101,19 @@ class bandpass(biquad):
95
101
  cosw = numpy.cos(w)
96
102
  sinw = numpy.sin(w)
97
103
 
98
- c = -(2 * cosw)
99
- p = sinw / (2 * q[i])
100
- g = sinw / 2 if skirt else p
104
+ alpha = sinw / (+2 * q[i])
105
+ beta = cosw * (-2)
106
+ gamma = sinw / (+2) if skirt else alpha
101
107
 
102
108
  # update b
103
- ba[0, 0] = +g
109
+ ba[0, 0] = +gamma
104
110
  ba[0, 1] = 0
105
- ba[0, 2] = -g
111
+ ba[0, 2] = -gamma
106
112
 
107
113
  # update a
108
- ba[1, 0] = 1 + p
109
- ba[1, 1] = c
110
- ba[1, 2] = 1 - p
114
+ ba[1, 0] = 1 + alpha
115
+ ba[1, 1] = beta
116
+ ba[1, 2] = 1 - alpha
111
117
 
112
118
  # update y
113
- __df1__(ba, xy, x, y, i)
119
+ __df1__(g[i], ba, xy, x, y, i)
biquad/biquad.py CHANGED
@@ -6,17 +6,15 @@ SPDX-License-Identifier: MIT
6
6
  Source: https://github.com/jurihock/biquad
7
7
  """
8
8
 
9
- from .plot import plot
10
-
11
9
  import numba
12
10
  import numpy
13
11
 
14
12
 
15
13
  @numba.jit(nopython=True, fastmath=True)
16
- def __df1__(ba, xy, x, y, i):
14
+ def __df1__(g, ba, xy, x, y, i):
17
15
  """
18
- Computes filter output y[i] based on filter input x[i]
19
- as well as specified filter coeffs ba and delay line xy,
16
+ Compute filter output y[i] based on filter input x[i]
17
+ as well as specified filter gain g, coeffs ba and delay line xy,
20
18
  according to the Direct Form 1.
21
19
  """
22
20
 
@@ -31,37 +29,67 @@ def __df1__(ba, xy, x, y, i):
31
29
  # update x
32
30
  xy[0, 0] = x[i]
33
31
 
32
+ # compute intermediate results b*x and a*y
33
+ bx = ba[0, 0] * xy[0, 0] + ba[0, 1] * xy[0, 1] + ba[0, 2] * xy[0, 2]
34
+ ay = ba[1, 1] * xy[1, 1] + ba[1, 2] * xy[1, 2]
35
+
34
36
  # update y
35
- xy[1, 0] = (ba[0, 0] * xy[0, 0] + \
36
- ba[0, 1] * xy[0, 1] + \
37
- ba[0, 2] * xy[0, 2] - \
38
- ba[1, 1] * xy[1, 1] - \
39
- ba[1, 2] * xy[1, 2]) / ba[1, 0]
37
+ xy[1, 0] = (bx * g - ay) / ba[1, 0]
40
38
 
41
39
  # return y
42
40
  y[i] = xy[1, 0]
43
41
 
44
42
 
45
- class biquad:
43
+ def __gain__(x, divisor=20):
46
44
  """
47
- Biquad filter base class.
45
+ Convert the specified decibel gain to the linear gain.
48
46
  """
49
47
 
50
- ba = numpy.array([[1, 0, 0], [1, 0, 0]], float)
48
+ if numpy.isscalar(x):
49
+
50
+ y = x / divisor
51
+ y = 10 ** y
52
+
53
+ else:
54
+
55
+ y = numpy.atleast_1d(x) / divisor
56
+ numpy.power(10, y, out=y)
57
+
58
+ return y
59
+
60
+
61
+ def __resize__(x, shape):
51
62
  """
52
- Biquad filter coefficient matrix of shape (2, 3):
53
- - ba[0] holds b coefficients
54
- - ba[1] holds a coefficients
63
+ Resize the specified value to the ndarray of desired shape.
55
64
  """
56
65
 
57
- xy = numpy.array([[0, 0, 0], [0, 0, 0]], float)
66
+ if numpy.isscalar(x):
67
+
68
+ y = numpy.full(shape, x)
69
+
70
+ else:
71
+
72
+ x = numpy.atleast_1d(x)
73
+ y = numpy.resize(x, shape)
74
+
75
+ return y
76
+
77
+
78
+ class biquad:
58
79
  """
59
- Biquad filter delay line matrix of shape (2, 3):
60
- - xy[0] holds input values
61
- - xy[0] holds output values
80
+ Biquad filter base class.
81
+
82
+ Parameters
83
+ ----------
84
+ ba : Biquad filter coefficient matrix of shape (2, 3) excl. gain factor:
85
+ - ba[0] holds b coefficients
86
+ - ba[1] holds a coefficients
87
+ xy : Biquad filter delay line matrix of shape (2, 3):
88
+ - xy[0] holds input values
89
+ - xy[1] holds output values
62
90
  """
63
91
 
64
- def __init__(self, sr, *, f=None, q=None):
92
+ def __init__(self, sr, f=None, g=None, q=None):
65
93
  """
66
94
  Create a new filter instance.
67
95
 
@@ -71,26 +99,34 @@ class biquad:
71
99
  Sample rate in hertz.
72
100
  f : int or float, optional
73
101
  Persistent filter frequency parameter in hertz.
102
+ g : int or float, optional
103
+ Persistent filter gain parameter in decibel.
74
104
  q : int or float, optional
75
105
  Persistent filter quality parameter.
76
106
  """
77
107
 
78
108
  assert (sr is not None) and (numpy.isscalar(sr) and numpy.isreal(sr))
79
109
  assert (f is None) or (numpy.isscalar(f) and numpy.isreal(f))
110
+ assert (g is None) or (numpy.isscalar(g) and numpy.isreal(g))
80
111
  assert (q is None) or (numpy.isscalar(q) and numpy.isreal(q))
81
112
 
82
113
  self.sr = sr
83
- self.f = f
84
- self.q = q
114
+ self.f = (sr / 4) if f is None else f
115
+ self.g = __gain__(0 if g is None else g)
116
+ self.q = 1 if q is None else q
117
+
118
+ self.ba = numpy.array([[1, 0, 0], [1, 0, 0]], float)
119
+ self.xy = numpy.array([[0, 0, 0], [0, 0, 0]], float)
85
120
 
86
121
  # warmup numba
122
+ g = self.g
87
123
  ba = self.ba
88
124
  xy = self.xy
89
- x = numpy.zeros(1, float)
90
- y = numpy.zeros(x.shape, x.dtype)
91
- __df1__(ba, xy, x, y, 0)
125
+ x = numpy.zeros(1, float)
126
+ y = numpy.zeros(x.shape, x.dtype)
127
+ __df1__(g, ba, xy, x, y, 0)
92
128
 
93
- def __call__(self, x, f=None, q=None):
129
+ def __call__(self, x, f=None, g=None, q=None):
94
130
  """
95
131
  Process single or multiple contiguous signal values at once.
96
132
 
@@ -100,6 +136,8 @@ class biquad:
100
136
  Filter input data.
101
137
  f : scalar or array like, optional
102
138
  Instantaneous filter frequency parameter in hertz.
139
+ g : scalar or array like, optional
140
+ Instantaneous filter gain parameter in decibel.
103
141
  q : scalar or array like, optional
104
142
  Instantaneous filter quality parameter.
105
143
 
@@ -117,19 +155,27 @@ class biquad:
117
155
  x = numpy.atleast_1d(x)
118
156
  y = numpy.zeros(x.shape, x.dtype)
119
157
 
120
- self.__filter__(ba, xy, x, y)
158
+ f = __resize__(self.f if f is None else f, x.shape)
159
+ g = __resize__(self.g if g is None else __gain__(g), x.shape)
160
+ q = __resize__(self.q if q is None else q, x.shape)
161
+
162
+ self.__filter__(ba, xy, x, y, g)
163
+
164
+ self.f = f[-1]
165
+ self.g = g[-1]
166
+ self.q = q[-1]
121
167
 
122
168
  return y[0] if scalar else y
123
169
 
124
170
  @staticmethod
125
171
  @numba.jit(nopython=True, fastmath=True)
126
- def __filter__(ba, xy, x, y):
172
+ def __filter__(ba, xy, x, y, g):
127
173
 
128
174
  for i in range(x.size):
129
175
 
130
- __df1__(ba, xy, x, y, i)
176
+ __df1__(g[i], ba, xy, x, y, i)
131
177
 
132
- def response(self, norm=False, log=False):
178
+ def response(self, *, norm=False, log=False):
133
179
  """
134
180
  Returns frequency and phase response of the transfer function given by the ba coefficients.
135
181
 
@@ -154,6 +200,8 @@ class biquad:
154
200
 
155
201
  (b, a), sr = self.ba, self.sr
156
202
 
203
+ b *= self.g
204
+
157
205
  n = int(sr / 2)
158
206
 
159
207
  # compute frequencies from 0 to pi or sr/2 but excluding the Nyquist frequency
@@ -175,12 +223,46 @@ class biquad:
175
223
 
176
224
  return w, h
177
225
 
178
- def plot(self):
226
+ def plot(self, *, log=False):
179
227
  """
180
- Returns a filter response plotting wrapper to
181
- easily create the frequency or phase response plots.
228
+ Creates filter frequency and phase response plot.
229
+
230
+ Parameters
231
+ ----------
232
+ log : bool, optional
233
+ Option whether to express frequency values logarithmically.
182
234
  """
183
235
 
236
+ import matplotlib.pyplot as pyplot
237
+
184
238
  w, h = self.response()
185
239
 
186
- return plot(w, h)
240
+ with numpy.errstate(divide='ignore', invalid='ignore'):
241
+ habs = 20 * numpy.log10(numpy.abs(h))
242
+
243
+ harg = numpy.angle(h)
244
+
245
+ pyplot.plot(w, habs, color='b', alpha=0.9)
246
+ axis1 = pyplot.gca()
247
+ axis2 = axis1.twinx()
248
+ axis2.plot(w, harg, color='g', alpha=0.9)
249
+
250
+ axis1.set_xlabel('Hz')
251
+ axis1.set_ylabel('dB', color='b')
252
+ axis2.set_ylabel('rad', color='g')
253
+
254
+ habsmin = numpy.min(habs[numpy.isfinite(habs)])
255
+ habsmax = numpy.max(habs[numpy.isfinite(habs)])
256
+
257
+ habsmin = numpy.minimum(habsmin, -100)
258
+ habsmax = numpy.maximum(habsmax, +10)
259
+
260
+ hargmin = -numpy.pi
261
+ hargmax = +numpy.pi
262
+
263
+ axis1.set_ylim((habsmin * 1.1, habsmax * 1.1))
264
+ axis2.set_ylim((hargmin * 1.1, hargmax * 1.1))
265
+
266
+ if log: axis1.set_xscale('log')
267
+
268
+ return pyplot
biquad/highpass.py CHANGED
@@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
6
6
  Source: https://github.com/jurihock/biquad
7
7
  """
8
8
 
9
- from .biquad import biquad, __df1__
9
+ from .biquad import biquad, __df1__, __gain__, __resize__
10
10
 
11
11
  import numba
12
12
  import numpy
@@ -17,7 +17,7 @@ class highpass(biquad):
17
17
  Highpass filter (HPF).
18
18
  """
19
19
 
20
- def __init__(self, sr, *, f=None, q=0.7071):
20
+ def __init__(self, sr, f=None, g=0, q=0.7071):
21
21
  """
22
22
  Create a new filter instance.
23
23
 
@@ -27,15 +27,17 @@ class highpass(biquad):
27
27
  Sample rate in hertz.
28
28
  f : int or float, optional
29
29
  Persistent filter frequency parameter in hertz.
30
+ g : int or float, optional
31
+ Persistent filter gain parameter in decibel.
30
32
  q : int or float, optional
31
33
  Persistent filter quality parameter.
32
34
  """
33
35
 
34
- super().__init__(sr=sr, f=f, q=q)
36
+ super().__init__(sr=sr, f=f, g=g, q=q)
35
37
 
36
- self.__call__(0, 1) # warmup numba
38
+ self.__call__(0) # warmup numba
37
39
 
38
- def __call__(self, x, f=None, q=None):
40
+ def __call__(self, x, f=None, g=None, q=None):
39
41
  """
40
42
  Process single or multiple contiguous signal values at once.
41
43
 
@@ -45,6 +47,8 @@ class highpass(biquad):
45
47
  Filter input data.
46
48
  f : scalar or array like, optional
47
49
  Instantaneous filter frequency parameter in hertz.
50
+ g : scalar or array like, optional
51
+ Instantaneous filter gain parameter in decibel.
48
52
  q : scalar or array like, optional
49
53
  Instantaneous filter quality parameter.
50
54
 
@@ -62,21 +66,23 @@ class highpass(biquad):
62
66
  x = numpy.atleast_1d(x)
63
67
  y = numpy.zeros(x.shape, x.dtype)
64
68
 
65
- f = numpy.atleast_1d(self.f if f is None else f)
66
- q = numpy.atleast_1d(self.q if q is None else q)
67
-
68
- f = numpy.resize(f, x.shape)
69
- q = numpy.resize(q, x.shape)
69
+ f = __resize__(self.f if f is None else f, x.shape)
70
+ g = __resize__(self.g if g is None else __gain__(g), x.shape)
71
+ q = __resize__(self.q if q is None else q, x.shape)
70
72
 
71
73
  sr = self.sr
72
74
 
73
- self.__filter__(ba, xy, x, y, f, q, sr)
75
+ self.__filter__(ba, xy, x, y, f, g, q, sr)
76
+
77
+ self.f = f[-1]
78
+ self.g = g[-1]
79
+ self.q = q[-1]
74
80
 
75
81
  return y[0] if scalar else y
76
82
 
77
83
  @staticmethod
78
84
  @numba.jit(nopython=True, fastmath=True)
79
- def __filter__(ba, xy, x, y, f, q, sr):
85
+ def __filter__(ba, xy, x, y, f, g, q, sr):
80
86
 
81
87
  rs = 2 * numpy.pi / sr
82
88
 
@@ -87,8 +93,8 @@ class highpass(biquad):
87
93
  cosw = numpy.cos(w)
88
94
  sinw = numpy.sin(w)
89
95
 
90
- c = -(2 * cosw)
91
- p = sinw / (2 * q[i])
96
+ alpha = sinw / (+2 * q[i])
97
+ beta = cosw * (-2)
92
98
 
93
99
  # update b
94
100
  ba[0, 1] = -(1 + cosw)
@@ -96,9 +102,9 @@ class highpass(biquad):
96
102
  ba[0, 0] = ba[0, 2]
97
103
 
98
104
  # update a
99
- ba[1, 0] = 1 + p
100
- ba[1, 1] = c
101
- ba[1, 2] = 1 - p
105
+ ba[1, 0] = 1 + alpha
106
+ ba[1, 1] = beta
107
+ ba[1, 2] = 1 - alpha
102
108
 
103
109
  # update y
104
- __df1__(ba, xy, x, y, i)
110
+ __df1__(g[i], ba, xy, x, y, i)