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 +55 -55
- biquad/allpass.py +27 -21
- biquad/bandpass.py +33 -27
- biquad/biquad.py +117 -35
- biquad/highpass.py +24 -18
- biquad/highshelf.py +115 -113
- biquad/lowpass.py +24 -18
- biquad/lowshelf.py +115 -113
- biquad/notch.py +25 -19
- biquad/peak.py +29 -29
- {biquad-0.3.dist-info → biquad-0.5.dist-info}/METADATA +103 -88
- biquad-0.5.dist-info/RECORD +15 -0
- {biquad-0.3.dist-info → biquad-0.5.dist-info}/WHEEL +1 -1
- {biquad-0.3.dist-info → biquad-0.5.dist-info/licenses}/LICENSE +21 -21
- biquad/plot.py +0 -96
- biquad-0.3.dist-info/RECORD +0 -16
- {biquad-0.3.dist-info → biquad-0.5.dist-info}/top_level.txt +0 -0
biquad/highshelf.py
CHANGED
|
@@ -1,113 +1,115 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Copyright (c) 2023 Juergen Hock
|
|
3
|
-
|
|
4
|
-
SPDX-License-Identifier: MIT
|
|
5
|
-
|
|
6
|
-
Source: https://github.com/jurihock/biquad
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from .biquad import biquad, __df1__
|
|
10
|
-
|
|
11
|
-
import numba
|
|
12
|
-
import numpy
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class highshelf(biquad):
|
|
16
|
-
"""
|
|
17
|
-
Highshelf filter (HSF).
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
def __init__(self, sr,
|
|
21
|
-
"""
|
|
22
|
-
Create a new filter instance.
|
|
23
|
-
|
|
24
|
-
Parameters
|
|
25
|
-
----------
|
|
26
|
-
sr : int or float
|
|
27
|
-
Sample rate in hertz.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Persistent filter
|
|
32
|
-
q : int or float, optional
|
|
33
|
-
Persistent filter quality parameter.
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
super().__init__(sr=sr, f=f, q=q)
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
self.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
ba[0,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
ba[1,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2023 Juergen Hock
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
Source: https://github.com/jurihock/biquad
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .biquad import biquad, __df1__, __gain__, __resize__
|
|
10
|
+
|
|
11
|
+
import numba
|
|
12
|
+
import numpy
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class highshelf(biquad):
|
|
16
|
+
"""
|
|
17
|
+
Highshelf filter (HSF).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, sr, f=None, g=6, q=1):
|
|
21
|
+
"""
|
|
22
|
+
Create a new filter instance.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
sr : int or float
|
|
27
|
+
Sample rate in hertz.
|
|
28
|
+
f : int or float, optional
|
|
29
|
+
Persistent filter frequency parameter in hertz.
|
|
30
|
+
g : int or float, optional
|
|
31
|
+
Persistent filter gain parameter in decibel.
|
|
32
|
+
q : int or float, optional
|
|
33
|
+
Persistent filter quality parameter.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
super().__init__(sr=sr, f=f, g=0, q=q)
|
|
37
|
+
|
|
38
|
+
self.g = __gain__(g, 40)
|
|
39
|
+
|
|
40
|
+
self.__call__(0) # warmup numba
|
|
41
|
+
|
|
42
|
+
def __call__(self, x, f=None, g=None, q=None):
|
|
43
|
+
"""
|
|
44
|
+
Process single or multiple contiguous signal values at once.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
x : scalar or array like
|
|
49
|
+
Filter input data.
|
|
50
|
+
f : scalar or array like, optional
|
|
51
|
+
Instantaneous filter frequency parameter in hertz.
|
|
52
|
+
g : scalar or array like, optional
|
|
53
|
+
Instantaneous filter gain parameter in decibel.
|
|
54
|
+
q : scalar or array like, optional
|
|
55
|
+
Instantaneous filter quality parameter.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
y : scalar or ndarray
|
|
60
|
+
Filter output data of the same shape and dtype as the input x.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
scalar = numpy.isscalar(x)
|
|
64
|
+
|
|
65
|
+
ba = self.ba
|
|
66
|
+
xy = self.xy
|
|
67
|
+
|
|
68
|
+
x = numpy.atleast_1d(x)
|
|
69
|
+
y = numpy.zeros(x.shape, x.dtype)
|
|
70
|
+
|
|
71
|
+
f = __resize__(self.f if f is None else f, x.shape)
|
|
72
|
+
g = __resize__(self.g if g is None else __gain__(g, 40), x.shape)
|
|
73
|
+
q = __resize__(self.q if q is None else q, x.shape)
|
|
74
|
+
|
|
75
|
+
sr = self.sr
|
|
76
|
+
|
|
77
|
+
self.__filter__(ba, xy, x, y, f, g, q, sr)
|
|
78
|
+
|
|
79
|
+
self.f = f[-1]
|
|
80
|
+
self.g = g[-1]
|
|
81
|
+
self.q = q[-1]
|
|
82
|
+
|
|
83
|
+
return y[0] if scalar else y
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
@numba.jit(nopython=True, fastmath=True)
|
|
87
|
+
def __filter__(ba, xy, x, y, f, g, q, sr):
|
|
88
|
+
|
|
89
|
+
rs = 2 * numpy.pi / sr
|
|
90
|
+
|
|
91
|
+
for i in range(x.size):
|
|
92
|
+
|
|
93
|
+
w = f[i] * rs
|
|
94
|
+
|
|
95
|
+
cosw = numpy.cos(w)
|
|
96
|
+
sinw = numpy.sin(w)
|
|
97
|
+
|
|
98
|
+
alpha = sinw / (2 * q[i])
|
|
99
|
+
alpha *= 2 * numpy.sqrt(g[i])
|
|
100
|
+
|
|
101
|
+
plus = g[i] + 1
|
|
102
|
+
minus = g[i] - 1
|
|
103
|
+
|
|
104
|
+
# update b
|
|
105
|
+
ba[0, 0] = (plus + minus * cosw + alpha)
|
|
106
|
+
ba[0, 1] = (minus + plus * cosw) * -2
|
|
107
|
+
ba[0, 2] = (plus + minus * cosw - alpha)
|
|
108
|
+
|
|
109
|
+
# update a
|
|
110
|
+
ba[1, 0] = (plus - minus * cosw + alpha)
|
|
111
|
+
ba[1, 1] = (minus - plus * cosw) * +2
|
|
112
|
+
ba[1, 2] = (plus - minus * cosw - alpha)
|
|
113
|
+
|
|
114
|
+
# update y
|
|
115
|
+
__df1__(g[i], ba, xy, x, y, i)
|
biquad/lowpass.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 lowpass(biquad):
|
|
|
17
17
|
Lowpass filter (LPF).
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
def __init__(self, sr,
|
|
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 lowpass(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
|
|
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 lowpass(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 lowpass(biquad):
|
|
|
62
66
|
x = numpy.atleast_1d(x)
|
|
63
67
|
y = numpy.zeros(x.shape, x.dtype)
|
|
64
68
|
|
|
65
|
-
f =
|
|
66
|
-
|
|
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 lowpass(biquad):
|
|
|
87
93
|
cosw = numpy.cos(w)
|
|
88
94
|
sinw = numpy.sin(w)
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
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 lowpass(biquad):
|
|
|
96
102
|
ba[0, 0] = ba[0, 2]
|
|
97
103
|
|
|
98
104
|
# update a
|
|
99
|
-
ba[1, 0] = 1 +
|
|
100
|
-
ba[1, 1] =
|
|
101
|
-
ba[1, 2] = 1 -
|
|
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/lowshelf.py
CHANGED
|
@@ -1,113 +1,115 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Copyright (c) 2023 Juergen Hock
|
|
3
|
-
|
|
4
|
-
SPDX-License-Identifier: MIT
|
|
5
|
-
|
|
6
|
-
Source: https://github.com/jurihock/biquad
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from .biquad import biquad, __df1__
|
|
10
|
-
|
|
11
|
-
import numba
|
|
12
|
-
import numpy
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class lowshelf(biquad):
|
|
16
|
-
"""
|
|
17
|
-
Lowshelf filter (LSF).
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
def __init__(self, sr,
|
|
21
|
-
"""
|
|
22
|
-
Create a new filter instance.
|
|
23
|
-
|
|
24
|
-
Parameters
|
|
25
|
-
----------
|
|
26
|
-
sr : int or float
|
|
27
|
-
Sample rate in hertz.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Persistent filter
|
|
32
|
-
q : int or float, optional
|
|
33
|
-
Persistent filter quality parameter.
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
super().__init__(sr=sr, f=f, q=q)
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
self.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
ba[0,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
ba[1,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2023 Juergen Hock
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
Source: https://github.com/jurihock/biquad
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .biquad import biquad, __df1__, __gain__, __resize__
|
|
10
|
+
|
|
11
|
+
import numba
|
|
12
|
+
import numpy
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class lowshelf(biquad):
|
|
16
|
+
"""
|
|
17
|
+
Lowshelf filter (LSF).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, sr, f=None, g=6, q=1):
|
|
21
|
+
"""
|
|
22
|
+
Create a new filter instance.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
sr : int or float
|
|
27
|
+
Sample rate in hertz.
|
|
28
|
+
f : int or float, optional
|
|
29
|
+
Persistent filter frequency parameter in hertz.
|
|
30
|
+
g : int or float, optional
|
|
31
|
+
Persistent filter gain parameter in decibel.
|
|
32
|
+
q : int or float, optional
|
|
33
|
+
Persistent filter quality parameter.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
super().__init__(sr=sr, f=f, g=0, q=q)
|
|
37
|
+
|
|
38
|
+
self.g = __gain__(g, 40)
|
|
39
|
+
|
|
40
|
+
self.__call__(0) # warmup numba
|
|
41
|
+
|
|
42
|
+
def __call__(self, x, f=None, g=None, q=None):
|
|
43
|
+
"""
|
|
44
|
+
Process single or multiple contiguous signal values at once.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
x : scalar or array like
|
|
49
|
+
Filter input data.
|
|
50
|
+
f : scalar or array like, optional
|
|
51
|
+
Instantaneous filter frequency parameter in hertz.
|
|
52
|
+
g : scalar or array like, optional
|
|
53
|
+
Instantaneous filter gain parameter in decibel.
|
|
54
|
+
q : scalar or array like, optional
|
|
55
|
+
Instantaneous filter quality parameter.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
y : scalar or ndarray
|
|
60
|
+
Filter output data of the same shape and dtype as the input x.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
scalar = numpy.isscalar(x)
|
|
64
|
+
|
|
65
|
+
ba = self.ba
|
|
66
|
+
xy = self.xy
|
|
67
|
+
|
|
68
|
+
x = numpy.atleast_1d(x)
|
|
69
|
+
y = numpy.zeros(x.shape, x.dtype)
|
|
70
|
+
|
|
71
|
+
f = __resize__(self.f if f is None else f, x.shape)
|
|
72
|
+
g = __resize__(self.g if g is None else __gain__(g, 40), x.shape)
|
|
73
|
+
q = __resize__(self.q if q is None else q, x.shape)
|
|
74
|
+
|
|
75
|
+
sr = self.sr
|
|
76
|
+
|
|
77
|
+
self.__filter__(ba, xy, x, y, f, g, q, sr)
|
|
78
|
+
|
|
79
|
+
self.f = f[-1]
|
|
80
|
+
self.g = g[-1]
|
|
81
|
+
self.q = q[-1]
|
|
82
|
+
|
|
83
|
+
return y[0] if scalar else y
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
@numba.jit(nopython=True, fastmath=True)
|
|
87
|
+
def __filter__(ba, xy, x, y, f, g, q, sr):
|
|
88
|
+
|
|
89
|
+
rs = 2 * numpy.pi / sr
|
|
90
|
+
|
|
91
|
+
for i in range(x.size):
|
|
92
|
+
|
|
93
|
+
w = f[i] * rs
|
|
94
|
+
|
|
95
|
+
cosw = numpy.cos(w)
|
|
96
|
+
sinw = numpy.sin(w)
|
|
97
|
+
|
|
98
|
+
alpha = sinw / (2 * q[i])
|
|
99
|
+
alpha *= 2 * numpy.sqrt(g[i])
|
|
100
|
+
|
|
101
|
+
plus = g[i] + 1
|
|
102
|
+
minus = g[i] - 1
|
|
103
|
+
|
|
104
|
+
# update b
|
|
105
|
+
ba[0, 0] = (plus - minus * cosw + alpha)
|
|
106
|
+
ba[0, 1] = (minus - plus * cosw) * +2
|
|
107
|
+
ba[0, 2] = (plus - minus * cosw - alpha)
|
|
108
|
+
|
|
109
|
+
# update a
|
|
110
|
+
ba[1, 0] = (plus + minus * cosw + alpha)
|
|
111
|
+
ba[1, 1] = (minus + plus * cosw) * -2
|
|
112
|
+
ba[1, 2] = (plus + minus * cosw - alpha)
|
|
113
|
+
|
|
114
|
+
# update y
|
|
115
|
+
__df1__(g[i], ba, xy, x, y, i)
|
biquad/notch.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 notch(biquad):
|
|
|
17
17
|
Notch filter.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
def __init__(self, sr,
|
|
20
|
+
def __init__(self, sr, f=None, g=0, q=10):
|
|
21
21
|
"""
|
|
22
22
|
Create a new filter instance.
|
|
23
23
|
|
|
@@ -27,15 +27,17 @@ class notch(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
|
|
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 notch(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 notch(biquad):
|
|
|
62
66
|
x = numpy.atleast_1d(x)
|
|
63
67
|
y = numpy.zeros(x.shape, x.dtype)
|
|
64
68
|
|
|
65
|
-
f =
|
|
66
|
-
|
|
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 notch(biquad):
|
|
|
87
93
|
cosw = numpy.cos(w)
|
|
88
94
|
sinw = numpy.sin(w)
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
alpha = sinw / (+2 * q[i])
|
|
97
|
+
beta = cosw * (-2)
|
|
92
98
|
|
|
93
99
|
# update b
|
|
94
100
|
ba[0, 0] = 1
|
|
95
|
-
ba[0, 1] =
|
|
101
|
+
ba[0, 1] = beta
|
|
96
102
|
ba[0, 2] = 1
|
|
97
103
|
|
|
98
104
|
# update a
|
|
99
|
-
ba[1, 0] = 1 +
|
|
100
|
-
ba[1, 1] =
|
|
101
|
-
ba[1, 2] = 1 -
|
|
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)
|