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/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, gain=6, *, f=None, q=1):
21
- """
22
- Create a new filter instance.
23
-
24
- Parameters
25
- ----------
26
- sr : int or float
27
- Sample rate in hertz.
28
- gain : int or float, optional
29
- Filter peak gain value in decibel.
30
- f : int or float, optional
31
- Persistent filter frequency parameter in hertz.
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.gain = gain
39
- self.amp = 10 ** (gain / 40)
40
-
41
- self.__call__(0, 1) # warmup numba
42
-
43
- def __call__(self, x, f=None, q=None):
44
- """
45
- Process single or multiple contiguous signal values at once.
46
-
47
- Parameters
48
- ----------
49
- x : scalar or array like
50
- Filter input data.
51
- f : scalar or array like, optional
52
- Instantaneous filter frequency parameter in hertz.
53
- q : scalar or array like, optional
54
- Instantaneous filter quality parameter.
55
-
56
- Returns
57
- -------
58
- y : scalar or ndarray
59
- Filter output data of the same shape and dtype as the input x.
60
- """
61
-
62
- scalar = numpy.isscalar(x)
63
-
64
- ba = self.ba
65
- xy = self.xy
66
-
67
- x = numpy.atleast_1d(x)
68
- y = numpy.zeros(x.shape, x.dtype)
69
-
70
- f = numpy.atleast_1d(self.f if f is None else f)
71
- q = numpy.atleast_1d(self.q if q is None else q)
72
-
73
- f = numpy.resize(f, x.shape)
74
- q = numpy.resize(q, x.shape)
75
-
76
- sr = self.sr
77
- amp = self.amp
78
-
79
- self.__filter__(ba, xy, x, y, f, q, sr, amp)
80
-
81
- return y[0] if scalar else y
82
-
83
- @staticmethod
84
- @numba.jit(nopython=True, fastmath=True)
85
- def __filter__(ba, xy, x, y, f, q, sr, amp):
86
-
87
- sq = 2 * numpy.sqrt(amp)
88
- rs = 2 * numpy.pi / sr
89
-
90
- for i in range(x.size):
91
-
92
- w = f[i] * rs
93
-
94
- cosw = numpy.cos(w)
95
- sinw = numpy.sin(w)
96
-
97
- p = sq * sinw / (2 * q[i])
98
-
99
- pamp = amp + 1
100
- namp = amp - 1
101
-
102
- # update b
103
- ba[0, 0] = (pamp + namp * cosw + p) * amp
104
- ba[0, 1] = (namp + pamp * cosw) * amp * -2
105
- ba[0, 2] = (pamp + namp * cosw - p) * amp
106
-
107
- # update a
108
- ba[1, 0] = (pamp - namp * cosw + p)
109
- ba[1, 1] = (namp - pamp * cosw) * +2
110
- ba[1, 2] = (pamp - namp * cosw - p)
111
-
112
- # update y
113
- __df1__(ba, xy, x, y, i)
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, *, 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 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, 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 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 = 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 lowpass(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 lowpass(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)
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, gain=6, *, f=None, q=1):
21
- """
22
- Create a new filter instance.
23
-
24
- Parameters
25
- ----------
26
- sr : int or float
27
- Sample rate in hertz.
28
- gain : int or float, optional
29
- Filter peak gain value in decibel.
30
- f : int or float, optional
31
- Persistent filter frequency parameter in hertz.
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.gain = gain
39
- self.amp = 10 ** (gain / 40)
40
-
41
- self.__call__(0, 1) # warmup numba
42
-
43
- def __call__(self, x, f=None, q=None):
44
- """
45
- Process single or multiple contiguous signal values at once.
46
-
47
- Parameters
48
- ----------
49
- x : scalar or array like
50
- Filter input data.
51
- f : scalar or array like, optional
52
- Instantaneous filter frequency parameter in hertz.
53
- q : scalar or array like, optional
54
- Instantaneous filter quality parameter.
55
-
56
- Returns
57
- -------
58
- y : scalar or ndarray
59
- Filter output data of the same shape and dtype as the input x.
60
- """
61
-
62
- scalar = numpy.isscalar(x)
63
-
64
- ba = self.ba
65
- xy = self.xy
66
-
67
- x = numpy.atleast_1d(x)
68
- y = numpy.zeros(x.shape, x.dtype)
69
-
70
- f = numpy.atleast_1d(self.f if f is None else f)
71
- q = numpy.atleast_1d(self.q if q is None else q)
72
-
73
- f = numpy.resize(f, x.shape)
74
- q = numpy.resize(q, x.shape)
75
-
76
- sr = self.sr
77
- amp = self.amp
78
-
79
- self.__filter__(ba, xy, x, y, f, q, sr, amp)
80
-
81
- return y[0] if scalar else y
82
-
83
- @staticmethod
84
- @numba.jit(nopython=True, fastmath=True)
85
- def __filter__(ba, xy, x, y, f, q, sr, amp):
86
-
87
- sq = 2 * numpy.sqrt(amp)
88
- rs = 2 * numpy.pi / sr
89
-
90
- for i in range(x.size):
91
-
92
- w = f[i] * rs
93
-
94
- cosw = numpy.cos(w)
95
- sinw = numpy.sin(w)
96
-
97
- p = sq * sinw / (2 * q[i])
98
-
99
- pamp = amp + 1
100
- namp = amp - 1
101
-
102
- # update b
103
- ba[0, 0] = (pamp - namp * cosw + p) * amp
104
- ba[0, 1] = (namp - pamp * cosw) * amp * +2
105
- ba[0, 2] = (pamp - namp * cosw - p) * amp
106
-
107
- # update a
108
- ba[1, 0] = (pamp + namp * cosw + p)
109
- ba[1, 1] = (namp + pamp * cosw) * -2
110
- ba[1, 2] = (pamp + namp * cosw - p)
111
-
112
- # update y
113
- __df1__(ba, xy, x, y, i)
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, *, f=None, q=10):
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, 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 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 = 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 notch(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, 0] = 1
95
- ba[0, 1] = c
101
+ ba[0, 1] = beta
96
102
  ba[0, 2] = 1
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)