|
5 | 5 | // SPDX-License-Identifier: MIT
|
6 | 6 | #include "shared-bindings/audiofilters/Filter.h"
|
7 | 7 |
|
| 8 | +#include "shared-module/synthio/BlockBiquad.h" |
8 | 9 | #include <stdint.h>
|
9 | 10 | #include "py/runtime.h"
|
10 | 11 |
|
@@ -68,65 +69,62 @@ void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self) {
|
68 | 69 | }
|
69 | 70 | self->buffer[0] = NULL;
|
70 | 71 | self->buffer[1] = NULL;
|
| 72 | + self->filter = mp_const_none; |
71 | 73 | self->filter_buffer = NULL;
|
72 | 74 | self->filter_states = NULL;
|
73 | 75 | }
|
74 | 76 |
|
75 |
| -void reset_filter_states(audiofilters_filter_obj_t *self) { |
76 |
| - self->filter_states_len = 0; |
77 |
| - self->filter_states = NULL; |
78 |
| - |
| 77 | +void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, mp_obj_t filter_in) { |
| 78 | + size_t n_items; |
79 | 79 | mp_obj_t *items;
|
80 |
| - if (mp_obj_is_type(self->filter, (const mp_obj_type_t *)&synthio_biquad_type_obj)) { |
81 |
| - self->filter_states_len = 1; |
82 |
| - items = self->filter; |
83 |
| - } else if (mp_obj_is_tuple_compatible(self->filter)) { |
84 |
| - mp_obj_tuple_get(self->filter, &self->filter_states_len, &items); |
85 |
| - } |
86 |
| - |
87 |
| - if (!self->filter_states_len) { |
88 |
| - return; |
89 |
| - } |
90 |
| - |
91 |
| - self->filter_states = m_malloc(self->filter_states_len * sizeof(biquad_filter_state)); |
92 |
| - |
93 |
| - if (mp_obj_is_type(items, (const mp_obj_type_t *)&synthio_biquad_type_obj)) { |
94 |
| - synthio_biquad_filter_assign(&self->filter_states[0], items); |
95 |
| - } else { |
96 |
| - for (size_t i = 0; i < self->filter_states_len; i++) { |
97 |
| - synthio_biquad_filter_assign(&self->filter_states[i], items[i]); |
| 80 | + mp_obj_t *filter_objs; |
| 81 | + |
| 82 | + if (filter_in == mp_const_none) { |
| 83 | + n_items = 0; |
| 84 | + filter_objs = NULL; |
| 85 | + } else if (MP_OBJ_TYPE_HAS_SLOT(mp_obj_get_type(filter_in), iter)) { |
| 86 | + // convert object to tuple if it wasn't before |
| 87 | + filter_in = MP_OBJ_TYPE_GET_SLOT(&mp_type_tuple, make_new)( |
| 88 | + &mp_type_tuple, 1, 0, &filter_in); |
| 89 | + mp_obj_tuple_get(filter_in, &n_items, &items); |
| 90 | + for (size_t i = 0; i < n_items; i++) { |
| 91 | + if (!synthio_is_any_biquad(items[i])) { |
| 92 | + mp_raise_TypeError_varg( |
| 93 | + MP_ERROR_TEXT("%q in %q must be of type %q, not %q"), |
| 94 | + MP_QSTR_object, |
| 95 | + MP_QSTR_filter, |
| 96 | + MP_QSTR_AnyBiquad, |
| 97 | + mp_obj_get_type(items[i])->name); |
| 98 | + } |
98 | 99 | }
|
99 |
| - } |
100 |
| -} |
101 |
| - |
102 |
| -mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self) { |
103 |
| - if (mp_obj_is_type(self->filter, (const mp_obj_type_t *)&synthio_biquad_type_obj) || mp_obj_is_tuple_compatible(self->filter)) { |
104 |
| - return self->filter; |
| 100 | + filter_objs = items; |
105 | 101 | } else {
|
106 |
| - return mp_const_none; |
| 102 | + n_items = 1; |
| 103 | + if (!synthio_is_any_biquad(filter_in)) { |
| 104 | + mp_raise_TypeError_varg( |
| 105 | + MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), |
| 106 | + MP_QSTR_filter, MP_QSTR_AnyBiquad, MP_QSTR_iterable, mp_obj_get_type(filter_in)->name); |
| 107 | + } |
| 108 | + filter_objs = &self->filter; |
107 | 109 | }
|
108 |
| -} |
109 |
| - |
110 |
| -void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, mp_obj_t arg) { |
111 |
| - if (arg == mp_const_none || mp_obj_is_type(arg, (const mp_obj_type_t *)&synthio_biquad_type_obj)) { |
112 |
| - self->filter = arg; |
113 |
| - } else if (mp_obj_is_tuple_compatible(arg) || mp_obj_is_type(arg, &mp_type_list)) { |
114 |
| - size_t tuple_len; |
115 |
| - mp_obj_t *tuple_items = NULL; |
116 | 110 |
|
117 |
| - mp_obj_get_array(arg, &tuple_len, &tuple_items); |
| 111 | + // everything has been checked, so we can do the following without fear |
118 | 112 |
|
119 |
| - mp_obj_t *biquad_objects[tuple_len]; |
120 |
| - for (size_t i = 0; i < tuple_len; i++) { |
121 |
| - biquad_objects[i] = mp_arg_validate_type_in(tuple_items[i], (const mp_obj_type_t *)&synthio_biquad_type_obj, MP_QSTR_filter); |
122 |
| - } |
| 113 | + self->filter = filter_in; |
| 114 | + self->filter_objs = filter_objs; |
| 115 | + self->filter_states = m_renew(biquad_filter_state, |
| 116 | + self->filter_states, |
| 117 | + self->filter_states_len, |
| 118 | + n_items); |
| 119 | + self->filter_states_len = n_items; |
123 | 120 |
|
124 |
| - self->filter = mp_obj_new_tuple(tuple_len, (const mp_obj_t *)biquad_objects); |
125 |
| - } else { |
126 |
| - mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be a %q object, %q, or %q"), MP_QSTR_filter, MP_QSTR_Biquad, MP_QSTR_tuple, MP_QSTR_None); |
| 121 | + for (size_t i = 0; i < n_items; i++) { |
| 122 | + synthio_biquad_filter_assign(&self->filter_states[i], items[i]); |
127 | 123 | }
|
| 124 | +} |
128 | 125 |
|
129 |
| - reset_filter_states(self); |
| 126 | +mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self) { |
| 127 | + return self->filter; |
130 | 128 | }
|
131 | 129 |
|
132 | 130 | mp_obj_t common_hal_audiofilters_filter_get_mix(audiofilters_filter_obj_t *self) {
|
@@ -187,6 +185,9 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
187 | 185 | channel = 0;
|
188 | 186 | }
|
189 | 187 |
|
| 188 | + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required |
| 189 | + mp_float_t mix = MIN(1.0, MAX(synthio_block_slot_get(&self->mix), 0.0)); |
| 190 | + |
190 | 191 | // Switch our buffers to the other buffer
|
191 | 192 | self->last_buf_idx = !self->last_buf_idx;
|
192 | 193 |
|
@@ -276,6 +277,10 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
276 | 277 |
|
277 | 278 | // Process biquad filters
|
278 | 279 | for (uint8_t j = 0; j < self->filter_states_len; j++) {
|
| 280 | + mp_obj_t filter_obj = self->filter_objs[j]; |
| 281 | + if (mp_obj_is_type(filter_obj, &synthio_block_biquad_type_obj)) { |
| 282 | + common_hal_synthio_block_biquad_tick(filter_obj, &self->filter_states[j]); |
| 283 | + } |
279 | 284 | synthio_biquad_filter_samples(&self->filter_states[j], self->filter_buffer, n_samples);
|
280 | 285 | }
|
281 | 286 |
|
|
0 commit comments