Skip to content

Commit 33fb771

Browse files
committed
synthio: Add filter argument to Synthesizer constructor
as step 1/n of adding FIR filtering
1 parent d3eda0a commit 33fb771

File tree

9 files changed

+34
-38
lines changed

9 files changed

+34
-38
lines changed

shared-bindings/synthio/MidiTrack.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,15 @@ STATIC mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_a
8888
mp_buffer_info_t bufinfo;
8989
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
9090

91-
mp_buffer_info_t bufinfo_waveform;
92-
synthio_synth_parse_waveform(&bufinfo_waveform, args[ARG_waveform].u_obj);
93-
9491
synthio_miditrack_obj_t *self = m_new_obj(synthio_miditrack_obj_t);
9592
self->base.type = &synthio_miditrack_type;
9693

9794
common_hal_synthio_miditrack_construct(self,
9895
(uint8_t *)bufinfo.buf, bufinfo.len,
9996
args[ARG_tempo].u_int,
10097
args[ARG_sample_rate].u_int,
101-
bufinfo_waveform.buf,
102-
bufinfo_waveform.len / 2,
98+
args[ARG_waveform].u_obj,
99+
mp_const_none,
103100
args[ARG_envelope].u_obj
104101
);
105102

shared-bindings/synthio/MidiTrack.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@
2727
#pragma once
2828

2929
#include "shared-module/synthio/MidiTrack.h"
30+
#include "py/obj.h"
3031

3132
extern const mp_obj_type_t synthio_miditrack_type;
3233

33-
void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self,
34-
const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, const int16_t *waveform, uint16_t waveform_len,
35-
mp_obj_t envelope);
34+
void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self, const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj);
3635

3736
void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self);
3837
bool common_hal_synthio_miditrack_deinited(synthio_miditrack_obj_t *self);

shared-bindings/synthio/Synthesizer.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,30 +59,29 @@
5959
//| :param int sample_rate: The desired playback sample rate; higher sample rate requires more memory
6060
//| :param int channel_count: The number of output channels (1=mono, 2=stereo)
6161
//| :param ReadableBuffer waveform: A single-cycle waveform. Default is a 50% duty cycle square wave. If specified, must be a ReadableBuffer of type 'h' (signed 16 bit)
62+
//| :param ReadableBuffer filter: Coefficients of an FIR filter to apply to notes with ``filter=True``. If specified, must be a ReadableBuffer of type 'h' (signed 16 bit)
6263
//| :param Optional[Envelope] envelope: An object that defines the loudness of a note over time. The default envelope, `None` provides no ramping, voices turn instantly on and off.
6364
//| """
6465
STATIC mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
65-
enum { ARG_sample_rate, ARG_channel_count, ARG_waveform, ARG_envelope };
66+
enum { ARG_sample_rate, ARG_channel_count, ARG_waveform, ARG_envelope, ARG_filter };
6667
static const mp_arg_t allowed_args[] = {
6768
{ MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 11025} },
6869
{ MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1} },
6970
{ MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
7071
{ MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
72+
{ MP_QSTR_filter, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } },
7173
};
7274
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
7375
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
7476

75-
mp_buffer_info_t bufinfo_waveform;
76-
synthio_synth_parse_waveform(&bufinfo_waveform, args[ARG_waveform].u_obj);
77-
7877
synthio_synthesizer_obj_t *self = m_new_obj(synthio_synthesizer_obj_t);
7978
self->base.type = &synthio_synthesizer_type;
8079

8180
common_hal_synthio_synthesizer_construct(self,
8281
args[ARG_sample_rate].u_int,
8382
args[ARG_channel_count].u_int,
84-
bufinfo_waveform.buf,
85-
bufinfo_waveform.len / 2,
83+
args[ARG_waveform].u_obj,
84+
args[ARG_filter].u_obj,
8685
args[ARG_envelope].u_obj);
8786

8887
return MP_OBJ_FROM_PTR(self);

shared-bindings/synthio/Synthesizer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
extern const mp_obj_type_t synthio_synthesizer_type;
3333

3434
void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self,
35-
uint32_t sample_rate, int channel_count, const int16_t *waveform, uint16_t waveform_length,
36-
mp_obj_t envelope);
35+
uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t filter_obj,
36+
mp_obj_t envelope_obj);
3737
void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self);
3838
bool common_hal_synthio_synthesizer_deinited(synthio_synthesizer_obj_t *self);
3939
uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self);

shared-bindings/synthio/__init__.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,6 @@ STATIC mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_ma
207207
}
208208
pyb_file_obj_t *file = MP_OBJ_TO_PTR(args[ARG_file].u_obj);
209209

210-
211-
mp_buffer_info_t bufinfo_waveform;
212-
synthio_synth_parse_waveform(&bufinfo_waveform, args[ARG_waveform].u_obj);
213-
214210
uint8_t chunk_header[14];
215211
f_rewind(&file->fp);
216212
UINT bytes_read;
@@ -250,7 +246,8 @@ STATIC mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_ma
250246
result->base.type = &synthio_miditrack_type;
251247

252248
common_hal_synthio_miditrack_construct(result, buffer, track_size,
253-
tempo, args[ARG_sample_rate].u_int, bufinfo_waveform.buf, bufinfo_waveform.len / 2,
249+
tempo, args[ARG_sample_rate].u_int, args[ARG_waveform].u_obj,
250+
mp_const_none,
254251
args[ARG_envelope].u_obj
255252
);
256253

shared-module/synthio/MidiTrack.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,13 @@ STATIC void start_parse(synthio_miditrack_obj_t *self) {
116116

117117
void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self,
118118
const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate,
119-
const int16_t *waveform, uint16_t waveform_length,
120-
mp_obj_t envelope) {
119+
mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj) {
121120

122121
self->tempo = tempo;
123122
self->track.buf = (void *)buffer;
124123
self->track.len = len;
125124

126-
synthio_synth_init(&self->synth, sample_rate, 1, waveform, waveform_length, envelope);
125+
synthio_synth_init(&self->synth, sample_rate, 1, waveform_obj, mp_const_none, envelope_obj);
127126

128127
start_parse(self);
129128
}

shared-module/synthio/Synthesizer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232

3333

3434
void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self,
35-
uint32_t sample_rate, int channel_count, const int16_t *waveform, uint16_t waveform_length,
36-
mp_obj_t envelope) {
35+
uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t filter_obj,
36+
mp_obj_t envelope_obj) {
3737

38-
synthio_synth_init(&self->synth, sample_rate, channel_count, waveform, waveform_length, envelope);
38+
synthio_synth_init(&self->synth, sample_rate, channel_count, waveform_obj, filter_obj, envelope_obj);
3939
}
4040

4141
void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self) {

shared-module/synthio/__init__.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,16 @@ mp_obj_t synthio_synth_envelope_get(synthio_synth_t *synth) {
373373
return synth->envelope_obj;
374374
}
375375

376-
void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, const int16_t *waveform, uint16_t waveform_length, mp_obj_t envelope_obj) {
376+
void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj) {
377377
mp_arg_validate_int_range(channel_count, 1, 2, MP_QSTR_channel_count);
378378
synth->buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count;
379379
synth->buffers[0] = m_malloc(synth->buffer_length, false);
380380
synth->buffers[1] = m_malloc(synth->buffer_length, false);
381381
synth->channel_count = channel_count;
382382
synth->other_channel = -1;
383-
synth->waveform = waveform;
384-
synth->waveform_length = waveform_length;
383+
synth->waveform_obj = waveform_obj;
384+
synthio_synth_parse_waveform(&synth->waveform_bufinfo, waveform_obj);
385+
synthio_synth_parse_filter(&synth->filter_bufinfo, filter_obj);
385386
synth->sample_rate = sample_rate;
386387
synthio_synth_envelope_set(synth, envelope_obj);
387388

@@ -402,21 +403,24 @@ void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_chan
402403
}
403404
}
404405

405-
STATIC bool parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what) {
406+
STATIC void parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what, mp_int_t max_len) {
406407
if (o != mp_const_none) {
407408
mp_get_buffer_raise(o, bufinfo, MP_BUFFER_READ);
408409
if (bufinfo->typecode != 'h') {
409410
mp_raise_ValueError_varg(translate("%q must be array of type 'h'"), what);
410411
}
411-
mp_arg_validate_length_range(bufinfo->len / 2, 2, 1024, what);
412-
return true;
412+
mp_arg_validate_length_range(bufinfo->len / 2, 2, max_len, what);
413413
}
414-
return false;
415414
}
416415

417416
void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj) {
418417
*bufinfo_waveform = ((mp_buffer_info_t) { .buf = (void *)square_wave, .len = 4 });
419-
parse_common(bufinfo_waveform, waveform_obj, MP_QSTR_waveform);
418+
parse_common(bufinfo_waveform, waveform_obj, MP_QSTR_waveform, 16384);
419+
}
420+
421+
void synthio_synth_parse_filter(mp_buffer_info_t *bufinfo_filter, mp_obj_t filter_obj) {
422+
*bufinfo_filter = ((mp_buffer_info_t) { .buf = NULL, .len = 0 });
423+
parse_common(bufinfo_filter, filter_obj, MP_QSTR_filter, 128);
420424
}
421425

422426
STATIC int find_channel_with_note(synthio_synth_t *synth, mp_obj_t note) {

shared-module/synthio/__init__.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ typedef struct synthio_synth {
7070
uint16_t last_buffer_length;
7171
uint8_t other_channel, buffer_index, other_buffer_index;
7272
uint16_t waveform_length;
73+
mp_buffer_info_t waveform_bufinfo, filter_bufinfo;
7374
synthio_envelope_definition_t global_envelope_definition;
74-
mp_obj_t envelope_obj;
75+
mp_obj_t waveform_obj, filter_obj, envelope_obj;
7576
synthio_midi_span_t span;
7677
uint32_t accum[CIRCUITPY_SYNTHIO_MAX_CHANNELS];
7778
uint32_t ring_accum[CIRCUITPY_SYNTHIO_MAX_CHANNELS];
@@ -91,12 +92,12 @@ typedef struct {
9192
void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t *buffer_length, uint8_t channel);
9293
void synthio_synth_deinit(synthio_synth_t *synth);
9394
bool synthio_synth_deinited(synthio_synth_t *synth);
94-
void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, const int16_t *waveform, uint16_t waveform_length,
95-
mp_obj_t envelope);
95+
void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope);
9696
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
9797
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing);
9898
void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel);
9999
void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj);
100+
void synthio_synth_parse_filter(mp_buffer_info_t *bufinfo_filter, mp_obj_t filter_obj);
100101
void synthio_synth_parse_envelope(uint16_t *envelope_sustain_index, mp_buffer_info_t *bufinfo_envelope, mp_obj_t envelope_obj, mp_obj_t envelope_hold_obj);
101102

102103
bool synthio_span_change_note(synthio_synth_t *synth, mp_obj_t old_note, mp_obj_t new_note);

0 commit comments

Comments
 (0)