Content-Length: 1142467 | pFad | http://github.com/adafruit/circuitpython/commit/05a50b8fd8f9146b0fe9dea28e55182c9acb4f5b

5B Initial replacement of old `Biquad` with `BlockBiquad` · adafruit/circuitpython@05a50b8 · GitHub
Skip to content

Commit 05a50b8

Browse files
committed
Initial replacement of old Biquad with BlockBiquad
1 parent 25216c8 commit 05a50b8

30 files changed

+1352
-1527
lines changed

ports/unix/variants/coverage/mpconfigvariant.mk

-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ SRC_BITMAP := \
6262
shared-bindings/synthio/LFO.c \
6363
shared-bindings/synthio/Note.c \
6464
shared-bindings/synthio/Biquad.c \
65-
shared-bindings/synthio/BlockBiquad.c \
6665
shared-bindings/synthio/Synthesizer.c \
6766
shared-bindings/traceback/__init__.c \
6867
shared-bindings/util.c \
@@ -105,7 +104,6 @@ SRC_BITMAP := \
105104
shared-module/synthio/LFO.c \
106105
shared-module/synthio/Note.c \
107106
shared-module/synthio/Biquad.c \
108-
shared-module/synthio/BlockBiquad.c \
109107
shared-module/synthio/Synthesizer.c \
110108
shared-bindings/vectorio/Circle.c \
111109
shared-module/vectorio/Circle.c \

py/circuitpy_defns.mk

-1
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,6 @@ SRC_SHARED_MODULE_ALL = \
727727
supervisor/__init__.c \
728728
supervisor/StatusBar.c \
729729
synthio/Biquad.c \
730-
synthio/BlockBiquad.c \
731730
synthio/LFO.c \
732731
synthio/Math.c \
733732
synthio/MidiTrack.c \

shared-bindings/audiofilters/Filter.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
//|
2525
//| def __init__(
2626
//| self,
27-
//| filter: Optional[synthio.AnyBiquad | Tuple[synthio.AnyBiquad]] = None,
27+
//| filter: Optional[synthio.Biquad | Tuple[synthio.Biquad]] = None,
2828
//| mix: synthio.BlockInput = 1.0,
2929
//| buffer_size: int = 512,
3030
//| sample_rate: int = 8000,
@@ -39,7 +39,7 @@
3939
//| The mix parameter allows you to change how much of the unchanged sample passes through to
4040
//| the output to how much of the effect audio you hear as the output.
4141
//|
42-
//| :param Optional[synthio.AnyBiquad|Tuple[synthio.AnyBiquad]] filter: A normalized biquad filter object or tuple of normalized biquad filter objects. The sample is processed sequentially by each filter to produce the output samples.
42+
//| :param Optional[synthio.Biquad|Tuple[synthio.Biquad]] filter: A normalized biquad filter object or tuple of normalized biquad filter objects. The sample is processed sequentially by each filter to produce the output samples.
4343
//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0).
4444
//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use
4545
//| :param int sample_rate: The sample rate to be used
@@ -127,7 +127,7 @@ static void check_for_deinit(audiofilters_filter_obj_t *self) {
127127
// Provided by context manager helper.
128128

129129

130-
//| filter: synthio.AnyBiquad | Tuple[synthio.AnyBiquad] | None
130+
//| filter: synthio.Biquad | Tuple[synthio.Biquad] | None
131131
//| """A normalized biquad filter object or tuple of normalized biquad filter objects. The sample is processed sequentially by each filter to produce the output samples."""
132132
//|
133133
static mp_obj_t audiofilters_filter_obj_get_filter(mp_obj_t self_in) {

shared-bindings/synthio/Biquad.c

+182-49
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,210 @@
11
// This file is part of the CircuitPython project: https://circuitpython.org
22
//
3-
// SPDX-FileCopyrightText: Copyright (c) 2021 Artyom Skrobov
3+
// SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries
44
//
55
// SPDX-License-Identifier: MIT
66

7-
#include <math.h>
8-
#include <string.h>
9-
107
#include "py/enum.h"
11-
#include "py/mperrno.h"
12-
#include "py/obj.h"
13-
#include "py/objnamedtuple.h"
8+
#include "py/objproperty.h"
149
#include "py/runtime.h"
10+
#include "shared-bindings/synthio/Biquad.h"
11+
#include "shared-bindings/util.h"
1512

16-
#include "shared-bindings/synthio/__init__.h"
17-
#include "shared-bindings/synthio/LFO.h"
18-
#include "shared-bindings/synthio/Math.h"
19-
#include "shared-bindings/synthio/MidiTrack.h"
20-
#include "shared-bindings/synthio/Note.h"
21-
#include "shared-bindings/synthio/Synthesizer.h"
22-
23-
#include "shared-module/synthio/LFO.h"
13+
//| class FilterMode:
14+
//| """The type of filter"""
15+
//|
16+
//| LOW_PASS: FilterMode
17+
//| """A low-pass filter"""
18+
//| HIGH_PASS: FilterMode
19+
//| """A high-pass filter"""
20+
//| BAND_PASS: FilterMode
21+
//| """A band-pass filter"""
22+
//| NOTCH: FilterMode
23+
//| """A notch filter"""
24+
//| LOW_SHELF: FilterMode
25+
//| """A low shelf filter"""
26+
//| HIGH_SHELF: FilterMode
27+
//| """A high shelf filter"""
28+
//| PEAKING_EQ: FilterMode
29+
//| """A peaking equalizer filter"""
30+
//|
31+
//|
2432

25-
#define default_attack_time (MICROPY_FLOAT_CONST(0.1))
26-
#define default_decay_time (MICROPY_FLOAT_CONST(0.05))
27-
#define default_release_time (MICROPY_FLOAT_CONST(0.2))
28-
#define default_attack_level (MICROPY_FLOAT_CONST(1.))
29-
#define default_sustain_level (MICROPY_FLOAT_CONST(0.8))
33+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, LOW_PASS, SYNTHIO_LOW_PASS);
34+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, HIGH_PASS, SYNTHIO_HIGH_PASS);
35+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, BAND_PASS, SYNTHIO_BAND_PASS);
36+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, NOTCH, SYNTHIO_NOTCH);
37+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, LOW_SHELF, SYNTHIO_LOW_SHELF);
38+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, HIGH_SHELF, SYNTHIO_HIGH_SHELF);
39+
MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, PEAKING_EQ, SYNTHIO_PEAKING_EQ);
3040

31-
static const mp_arg_t biquad_properties[] = {
32-
{ MP_QSTR_a1, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
33-
{ MP_QSTR_a2, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
34-
{ MP_QSTR_b0, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
35-
{ MP_QSTR_b1, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
36-
{ MP_QSTR_b2, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
41+
MAKE_ENUM_MAP(synthio_filter_mode) {
42+
MAKE_ENUM_MAP_ENTRY(mode, LOW_PASS),
43+
MAKE_ENUM_MAP_ENTRY(mode, HIGH_PASS),
44+
MAKE_ENUM_MAP_ENTRY(mode, BAND_PASS),
45+
MAKE_ENUM_MAP_ENTRY(mode, NOTCH),
46+
MAKE_ENUM_MAP_ENTRY(mode, LOW_SHELF),
47+
MAKE_ENUM_MAP_ENTRY(mode, HIGH_SHELF),
48+
MAKE_ENUM_MAP_ENTRY(mode, PEAKING_EQ),
3749
};
3850

51+
static MP_DEFINE_CONST_DICT(synthio_filter_mode_locals_dict, synthio_filter_mode_locals_table);
52+
53+
MAKE_PRINTER(synthio, synthio_filter_mode);
54+
55+
MAKE_ENUM_TYPE(synthio, FilterMode, synthio_filter_mode);
56+
57+
static synthio_filter_mode validate_synthio_filter_mode(mp_obj_t obj, qstr arg_name) {
58+
return cp_enum_value(&synthio_filter_mode_type, obj, arg_name);
59+
}
60+
3961
//| class Biquad:
40-
//| def __init__(self, b0: float, b1: float, b2: float, a1: float, a2: float) -> None:
41-
//| """Construct a normalized biquad filter object.
62+
//| def __init__(
63+
//| self,
64+
//| mode: FilterMode,
65+
//| frequency: BlockInput,
66+
//| Q: BlockInput = 0.7071067811865475,
67+
//| A: BlockInput = None,
68+
//| ) -> None:
69+
//| """Construct a biquad filter object with given settings.
4270
//|
43-
//| This implements the "direct form 1" biquad filter, where each coefficient
44-
//| has been pre-divided by a0.
71+
//| ``frequency`` gives the center frequency or corner frequency of the filter,
72+
//| depending on the mode.
4573
//|
46-
//| Biquad objects are usually constructed via one of the related methods on a `Synthesizer` object
47-
//| rather than directly from coefficients.
74+
//| ``Q`` gives the gain or sharpness of the filter.
4875
//|
49-
//| https://github.com/WebAudio/Audio-EQ-Cookbook/blob/main/Audio-EQ-Cookbook.txt
76+
//| ``A`` controls the gain of peaking and shelving filters according to the
77+
//| formula ``A = 10^(dBgain/40)``. For other filter types it is ignored.
5078
//|
51-
//| .. note:: This is deprecated in ``9.x.x`` and will be removed in ``10.0.0``. Use `BlockBiquad` objects instead.
52-
//| """
79+
//| Since ``frequency`` and ``Q`` are `BlockInput` objects, they can
80+
//| be varied dynamically. Internally, this is evaluated as "direct form 1"
81+
//| biquad filter.
5382
//|
83+
//| The internal filter state x[] and y[] is not updated when the filter
84+
//| coefficients change, and there is no theoretical justification for why
85+
//| this should result in a stable filter output. However, in practice,
86+
//| slowly varying the filter's characteristic frequency and sharpness
87+
//| appears to work as you'd expect."""
5488
//|
89+
90+
static const mp_arg_t biquad_properties[] = {
91+
{ MP_QSTR_mode, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL } },
92+
{ MP_QSTR_frequency, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL } },
93+
{ MP_QSTR_Q, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } },
94+
{ MP_QSTR_A, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE } },
95+
};
96+
5597
static mp_obj_t synthio_biquad_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
98+
enum { ARG_mode, ARG_frequency, ARG_Q };
99+
56100
mp_arg_val_t args[MP_ARRAY_SIZE(biquad_properties)];
57101
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(biquad_properties), biquad_properties, args);
58102

59-
for (size_t i = 0; i < MP_ARRAY_SIZE(biquad_properties); i++) {
60-
args[i].u_obj = mp_obj_new_float(mp_arg_validate_type_float(args[i].u_obj, biquad_properties[i].qst));
103+
if (args[ARG_Q].u_obj == MP_OBJ_NULL) {
104+
args[ARG_Q].u_obj = mp_obj_new_float(MICROPY_FLOAT_CONST(0.7071067811865475));
61105
}
62106

63-
MP_STATIC_ASSERT(sizeof(mp_arg_val_t) == sizeof(mp_obj_t));
64-
return namedtuple_make_new(type_in, MP_ARRAY_SIZE(args), 0, &args[0].u_obj);
107+
synthio_filter_mode mode = validate_synthio_filter_mode(args[ARG_mode].u_obj, MP_QSTR_mode);
108+
mp_obj_t result = common_hal_synthio_biquad_new(mode);
109+
properties_construct_helper(result, biquad_properties + 1, args + 1, MP_ARRAY_SIZE(biquad_properties) - 1);
110+
return result;
65111
}
66112

67-
const mp_obj_namedtuple_type_t synthio_biquad_type_obj = {
68-
NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_Biquad, synthio_biquad_make_new),
69-
.n_fields = 5,
70-
.fields = {
71-
MP_QSTR_a1,
72-
MP_QSTR_a2,
73-
MP_QSTR_b0,
74-
MP_QSTR_b1,
75-
MP_QSTR_b2,
76-
},
113+
//|
114+
//| mode: FilterMode
115+
//| """The mode of filter (read-only)"""
116+
static mp_obj_t synthio_biquad_get_mode(mp_obj_t self_in) {
117+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
118+
return cp_enum_find(&synthio_filter_mode_type, common_hal_synthio_biquad_get_mode(self));
119+
}
120+
MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_mode_obj, synthio_biquad_get_mode);
121+
122+
MP_PROPERTY_GETTER(synthio_biquad_mode_obj,
123+
(mp_obj_t)&synthio_biquad_get_mode_obj);
124+
125+
//|
126+
//| frequency: BlockInput
127+
//| """The central frequency (in Hz) of the filter"""
128+
static mp_obj_t synthio_biquad_get_frequency(mp_obj_t self_in) {
129+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
130+
return common_hal_synthio_biquad_get_frequency(self);
131+
}
132+
MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_frequency_obj, synthio_biquad_get_frequency);
133+
134+
static mp_obj_t synthio_biquad_set_frequency(mp_obj_t self_in, mp_obj_t arg) {
135+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
136+
common_hal_synthio_biquad_set_frequency(self, arg);
137+
return mp_const_none;
138+
}
139+
MP_DEFINE_CONST_FUN_OBJ_2(synthio_biquad_set_frequency_obj, synthio_biquad_set_frequency);
140+
MP_PROPERTY_GETSET(synthio_biquad_frequency_obj,
141+
(mp_obj_t)&synthio_biquad_get_frequency_obj,
142+
(mp_obj_t)&synthio_biquad_set_frequency_obj);
143+
144+
145+
//|
146+
//| Q: BlockInput
147+
//| """The sharpness (Q) of the filter"""
148+
//|
149+
static mp_obj_t synthio_biquad_get_Q(mp_obj_t self_in) {
150+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
151+
return common_hal_synthio_biquad_get_Q(self);
152+
}
153+
MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_Q_obj, synthio_biquad_get_Q);
154+
155+
static mp_obj_t synthio_biquad_set_Q(mp_obj_t self_in, mp_obj_t arg) {
156+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
157+
common_hal_synthio_biquad_set_Q(self, arg);
158+
return mp_const_none;
159+
}
160+
MP_DEFINE_CONST_FUN_OBJ_2(synthio_biquad_set_Q_obj, synthio_biquad_set_Q);
161+
MP_PROPERTY_GETSET(synthio_biquad_Q_obj,
162+
(mp_obj_t)&synthio_biquad_get_Q_obj,
163+
(mp_obj_t)&synthio_biquad_set_Q_obj);
164+
165+
//|
166+
//| A: BlockInput
167+
//| """The gain (A) of the filter
168+
//|
169+
//| This setting only has an effect for peaking and shelving EQ filters. It is related
170+
//| to the filter gain according to the formula ``A = 10^(dBgain/40)``.
171+
//| """
172+
//|
173+
//|
174+
static mp_obj_t synthio_biquad_get_A(mp_obj_t self_in) {
175+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
176+
return common_hal_synthio_biquad_get_A(self);
177+
}
178+
MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_A_obj, synthio_biquad_get_A);
179+
180+
static mp_obj_t synthio_biquad_set_A(mp_obj_t self_in, mp_obj_t arg) {
181+
synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in);
182+
common_hal_synthio_biquad_set_A(self, arg);
183+
return mp_const_none;
184+
}
185+
MP_DEFINE_CONST_FUN_OBJ_2(synthio_biquad_set_A_obj, synthio_biquad_set_A);
186+
MP_PROPERTY_GETSET(synthio_biquad_A_obj,
187+
(mp_obj_t)&synthio_biquad_get_A_obj,
188+
(mp_obj_t)&synthio_biquad_set_A_obj);
189+
190+
static const mp_rom_map_elem_t synthio_biquad_locals_dict_table[] = {
191+
{ MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&synthio_biquad_mode_obj) },
192+
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&synthio_biquad_frequency_obj) },
193+
{ MP_ROM_QSTR(MP_QSTR_Q), MP_ROM_PTR(&synthio_biquad_Q_obj) },
194+
{ MP_ROM_QSTR(MP_QSTR_A), MP_ROM_PTR(&synthio_biquad_A_obj) },
77195
};
196+
static MP_DEFINE_CONST_DICT(synthio_biquad_locals_dict, synthio_biquad_locals_dict_table);
197+
198+
static void biquad_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
199+
(void)kind;
200+
properties_print_helper(print, self_in, biquad_properties, MP_ARRAY_SIZE(biquad_properties));
201+
}
202+
203+
MP_DEFINE_CONST_OBJ_TYPE(
204+
synthio_biquad_type_obj,
205+
MP_QSTR_Biquad,
206+
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
207+
make_new, synthio_biquad_make_new,
208+
locals_dict, &synthio_biquad_locals_dict,
209+
print, biquad_print
210+
);

shared-bindings/synthio/Biquad.c.bak

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2021 Artyom Skrobov
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include <math.h>
8+
#include <string.h>
9+
10+
#include "py/enum.h"
11+
#include "py/mperrno.h"
12+
#include "py/obj.h"
13+
#include "py/objnamedtuple.h"
14+
#include "py/runtime.h"
15+
16+
#include "shared-bindings/synthio/__init__.h"
17+
#include "shared-bindings/synthio/LFO.h"
18+
#include "shared-bindings/synthio/Math.h"
19+
#include "shared-bindings/synthio/MidiTrack.h"
20+
#include "shared-bindings/synthio/Note.h"
21+
#include "shared-bindings/synthio/Synthesizer.h"
22+
23+
#include "shared-module/synthio/LFO.h"
24+
25+
#define default_attack_time (MICROPY_FLOAT_CONST(0.1))
26+
#define default_decay_time (MICROPY_FLOAT_CONST(0.05))
27+
#define default_release_time (MICROPY_FLOAT_CONST(0.2))
28+
#define default_attack_level (MICROPY_FLOAT_CONST(1.))
29+
#define default_sustain_level (MICROPY_FLOAT_CONST(0.8))
30+
31+
static const mp_arg_t biquad_properties[] = {
32+
{ MP_QSTR_a1, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
33+
{ MP_QSTR_a2, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
34+
{ MP_QSTR_b0, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
35+
{ MP_QSTR_b1, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
36+
{ MP_QSTR_b2, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} },
37+
};
38+
39+
//| class Biquad:
40+
//| def __init__(self, b0: float, b1: float, b2: float, a1: float, a2: float) -> None:
41+
//| """Construct a normalized biquad filter object.
42+
//|
43+
//| This implements the "direct form 1" biquad filter, where each coefficient
44+
//| has been pre-divided by a0.
45+
//|
46+
//| Biquad objects are usually constructed via one of the related methods on a `Synthesizer` object
47+
//| rather than directly from coefficients.
48+
//|
49+
//| https://github.com/WebAudio/Audio-EQ-Cookbook/blob/main/Audio-EQ-Cookbook.txt
50+
//|
51+
//| .. note:: This is deprecated in ``9.x.x`` and will be removed in ``10.0.0``. Use `BlockBiquad` objects instead.
52+
//| """
53+
//|
54+
//|
55+
static mp_obj_t synthio_biquad_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
56+
mp_arg_val_t args[MP_ARRAY_SIZE(biquad_properties)];
57+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(biquad_properties), biquad_properties, args);
58+
59+
for (size_t i = 0; i < MP_ARRAY_SIZE(biquad_properties); i++) {
60+
args[i].u_obj = mp_obj_new_float(mp_arg_validate_type_float(args[i].u_obj, biquad_properties[i].qst));
61+
}
62+
63+
MP_STATIC_ASSERT(sizeof(mp_arg_val_t) == sizeof(mp_obj_t));
64+
return namedtuple_make_new(type_in, MP_ARRAY_SIZE(args), 0, &args[0].u_obj);
65+
}
66+
67+
const mp_obj_namedtuple_type_t synthio_biquad_type_obj = {
68+
NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_Biquad, synthio_biquad_make_new),
69+
.n_fields = 5,
70+
.fields = {
71+
MP_QSTR_a1,
72+
MP_QSTR_a2,
73+
MP_QSTR_b0,
74+
MP_QSTR_b1,
75+
MP_QSTR_b2,
76+
},
77+
};

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/adafruit/circuitpython/commit/05a50b8fd8f9146b0fe9dea28e55182c9acb4f5b

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy