From 55db6b79475b85eac094cd003e9ddb11bcd07372 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Mon, 20 Nov 2023 09:50:03 -0600 Subject: [PATCH] Added `SYNTHIO_WAVEFORM_SIZE` definition, renamed 'loop_...' to 'waveform_loop_...', added 'ring_waveform_loop_...` parameters, and updated docstrings. --- shared-bindings/synthio/Note.c | 99 +++++++++++++++++++++--------- shared-bindings/synthio/Note.h | 18 ++++-- shared-bindings/synthio/__init__.h | 2 + shared-module/synthio/Note.c | 38 +++++++++--- shared-module/synthio/Note.h | 4 +- shared-module/synthio/__init__.c | 24 +++++--- 6 files changed, 131 insertions(+), 54 deletions(-) diff --git a/shared-bindings/synthio/Note.c b/shared-bindings/synthio/Note.c index 60e7c67e1c..f0a18b13a6 100644 --- a/shared-bindings/synthio/Note.c +++ b/shared-bindings/synthio/Note.c @@ -40,13 +40,15 @@ static const mp_arg_t note_properties[] = { { MP_QSTR_amplitude, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1) } }, { MP_QSTR_bend, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0) } }, { MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, + { MP_QSTR_waveform_loop_start, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_waveform_loop_end, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } }, { MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, { MP_QSTR_filter, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, { MP_QSTR_ring_frequency, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, { MP_QSTR_ring_bend, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, { MP_QSTR_ring_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, - { MP_QSTR_loop_start, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, - { MP_QSTR_loop_end, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_ring_waveform_loop_start, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_ring_waveform_loop_end, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } }, }; //| class Note: //| def __init__( @@ -55,6 +57,8 @@ static const mp_arg_t note_properties[] = { //| frequency: float, //| panning: BlockInput = 0.0, //| waveform: Optional[ReadableBuffer] = None, +//| waveform_loop_start: int = 0, +//| waveform_loop_end: int = 0, //| envelope: Optional[Envelope] = None, //| amplitude: BlockInput = 0.0, //| bend: BlockInput = 0.0, @@ -62,8 +66,8 @@ static const mp_arg_t note_properties[] = { //| ring_frequency: float = 0.0, //| ring_bend: float = 0.0, //| ring_waveform: Optional[ReadableBuffer] = 0.0, -//| loop_start: int = 0, -//| loop_end: int = 0, +//| ring_waveform_loop_start: int = 0, +//| ring_waveform_loop_end: int = 0, //| ) -> None: //| """Construct a Note object, with a frequency in Hz, and optional panning, waveform, envelope, tremolo (volume change) and bend (frequency change). //| @@ -214,6 +218,43 @@ MP_PROPERTY_GETSET(synthio_note_waveform_obj, (mp_obj_t)&synthio_note_get_waveform_obj, (mp_obj_t)&synthio_note_set_waveform_obj); +//| waveform_loop_start: int +//| """The index of where to begin looping waveform data. Must be greater than or equal to 0 and less than the total size of the waveform data.""" +STATIC mp_obj_t synthio_note_get_waveform_loop_start(mp_obj_t self_in) { + synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(common_hal_synthio_note_get_waveform_loop_start(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_waveform_loop_start_obj, synthio_note_get_waveform_loop_start); + +STATIC mp_obj_t synthio_note_set_waveform_loop_start(mp_obj_t self_in, mp_obj_t arg) { + synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_synthio_note_set_waveform_loop_start(self, mp_obj_get_int(arg)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_waveform_loop_start_obj, synthio_note_set_waveform_loop_start); +MP_PROPERTY_GETSET(synthio_note_waveform_loop_start_obj, + (mp_obj_t)&synthio_note_get_waveform_loop_start_obj, + (mp_obj_t)&synthio_note_set_waveform_loop_start_obj); + +//| waveform_loop_end: int +//| """The index of where to end looping waveform data. Must be greater than 0 or ``waveform_loop_start`` and less than or equal to the total size of the waveform data. If the value of the index does not match these parameters, the loop will occur at the end of the waveform.""" +//| +STATIC mp_obj_t synthio_note_get_waveform_loop_end(mp_obj_t self_in) { + synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(common_hal_synthio_note_get_waveform_loop_end(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_waveform_loop_end_obj, synthio_note_get_waveform_loop_end); + +STATIC mp_obj_t synthio_note_set_waveform_loop_end(mp_obj_t self_in, mp_obj_t arg) { + synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_synthio_note_set_waveform_loop_end(self, mp_obj_get_int(arg)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_waveform_loop_end_obj, synthio_note_set_waveform_loop_end); +MP_PROPERTY_GETSET(synthio_note_waveform_loop_end_obj, + (mp_obj_t)&synthio_note_get_waveform_loop_end_obj, + (mp_obj_t)&synthio_note_set_waveform_loop_end_obj); + //| envelope: Envelope //| """The envelope of this note""" @@ -300,42 +341,42 @@ MP_PROPERTY_GETSET(synthio_note_ring_waveform_obj, (mp_obj_t)&synthio_note_get_ring_waveform_obj, (mp_obj_t)&synthio_note_set_ring_waveform_obj); -//| loop_start: int -//| """The index of where to begin looping waveform data. Must be greater than 0 and less than the total size of the waveform data.""" -STATIC mp_obj_t synthio_note_get_loop_start(mp_obj_t self_in) { +//| ring_waveform_loop_start: int +//| """The index of where to begin looping waveform data. Must be greater than or equal to 0 and less than the total size of the waveform data.""" +STATIC mp_obj_t synthio_note_get_ring_waveform_loop_start(mp_obj_t self_in) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_synthio_note_get_loop_start(self)); + return mp_obj_new_int(common_hal_synthio_note_get_ring_waveform_loop_start(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_loop_start_obj, synthio_note_get_loop_start); +MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_ring_waveform_loop_start_obj, synthio_note_get_ring_waveform_loop_start); -STATIC mp_obj_t synthio_note_set_loop_start(mp_obj_t self_in, mp_obj_t arg) { +STATIC mp_obj_t synthio_note_set_ring_waveform_loop_start(mp_obj_t self_in, mp_obj_t arg) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_synthio_note_set_loop_start(self, mp_obj_get_int(arg)); + common_hal_synthio_note_set_ring_waveform_loop_start(self, mp_obj_get_int(arg)); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_loop_start_obj, synthio_note_set_loop_start); -MP_PROPERTY_GETSET(synthio_note_loop_start_obj, - (mp_obj_t)&synthio_note_get_loop_start_obj, - (mp_obj_t)&synthio_note_set_loop_start_obj); +MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_ring_waveform_loop_start_obj, synthio_note_set_ring_waveform_loop_start); +MP_PROPERTY_GETSET(synthio_note_ring_waveform_loop_start_obj, + (mp_obj_t)&synthio_note_get_ring_waveform_loop_start_obj, + (mp_obj_t)&synthio_note_set_ring_waveform_loop_start_obj); -//| loop_end: int -//| """The index of where to end looping waveform data. Must be greater than 0 or ``loop_start`` and less than the total size of the waveform data.""" +//| ring_waveform_loop_end: int +//| """The index of where to end looping waveform data. Must be greater than 0 or ``waveform_loop_start`` and less than or equal to the total size of the waveform data. If the value of the index does not match these parameters, the loop will occur at the end of the waveform.""" //| -STATIC mp_obj_t synthio_note_get_loop_end(mp_obj_t self_in) { +STATIC mp_obj_t synthio_note_get_ring_waveform_loop_end(mp_obj_t self_in) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_synthio_note_get_loop_end(self)); + return mp_obj_new_int(common_hal_synthio_note_get_ring_waveform_loop_end(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_loop_end_obj, synthio_note_get_loop_end); +MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_ring_waveform_loop_end_obj, synthio_note_get_ring_waveform_loop_end); -STATIC mp_obj_t synthio_note_set_loop_end(mp_obj_t self_in, mp_obj_t arg) { +STATIC mp_obj_t synthio_note_set_ring_waveform_loop_end(mp_obj_t self_in, mp_obj_t arg) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_synthio_note_set_loop_end(self, mp_obj_get_int(arg)); + common_hal_synthio_note_set_ring_waveform_loop_end(self, mp_obj_get_int(arg)); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_loop_end_obj, synthio_note_set_loop_end); -MP_PROPERTY_GETSET(synthio_note_loop_end_obj, - (mp_obj_t)&synthio_note_get_loop_end_obj, - (mp_obj_t)&synthio_note_set_loop_end_obj); +MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_ring_waveform_loop_end_obj, synthio_note_set_ring_waveform_loop_end); +MP_PROPERTY_GETSET(synthio_note_ring_waveform_loop_end_obj, + (mp_obj_t)&synthio_note_get_ring_waveform_loop_end_obj, + (mp_obj_t)&synthio_note_set_ring_waveform_loop_end_obj); @@ -349,14 +390,16 @@ STATIC const mp_rom_map_elem_t synthio_note_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_filter), MP_ROM_PTR(&synthio_note_filter_obj) }, { MP_ROM_QSTR(MP_QSTR_panning), MP_ROM_PTR(&synthio_note_panning_obj) }, { MP_ROM_QSTR(MP_QSTR_waveform), MP_ROM_PTR(&synthio_note_waveform_obj) }, + { MP_ROM_QSTR(MP_QSTR_waveform_loop_start), MP_ROM_PTR(&synthio_note_waveform_loop_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_waveform_loop_end), MP_ROM_PTR(&synthio_note_waveform_loop_end_obj) }, { MP_ROM_QSTR(MP_QSTR_envelope), MP_ROM_PTR(&synthio_note_envelope_obj) }, { MP_ROM_QSTR(MP_QSTR_amplitude), MP_ROM_PTR(&synthio_note_amplitude_obj) }, { MP_ROM_QSTR(MP_QSTR_bend), MP_ROM_PTR(&synthio_note_bend_obj) }, { MP_ROM_QSTR(MP_QSTR_ring_frequency), MP_ROM_PTR(&synthio_note_ring_frequency_obj) }, { MP_ROM_QSTR(MP_QSTR_ring_bend), MP_ROM_PTR(&synthio_note_ring_bend_obj) }, { MP_ROM_QSTR(MP_QSTR_ring_waveform), MP_ROM_PTR(&synthio_note_ring_waveform_obj) }, - { MP_ROM_QSTR(MP_QSTR_loop_start), MP_ROM_PTR(&synthio_note_loop_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_loop_end), MP_ROM_PTR(&synthio_note_loop_end_obj) }, + { MP_ROM_QSTR(MP_QSTR_ring_waveform_loop_start), MP_ROM_PTR(&synthio_note_ring_waveform_loop_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_ring_waveform_loop_end), MP_ROM_PTR(&synthio_note_ring_waveform_loop_end_obj) }, }; STATIC MP_DEFINE_CONST_DICT(synthio_note_locals_dict, synthio_note_locals_dict_table); diff --git a/shared-bindings/synthio/Note.h b/shared-bindings/synthio/Note.h index 89529c7c57..150f8ee549 100644 --- a/shared-bindings/synthio/Note.h +++ b/shared-bindings/synthio/Note.h @@ -24,6 +24,12 @@ void common_hal_synthio_note_set_bend(synthio_note_obj_t *self, mp_obj_t value); mp_obj_t common_hal_synthio_note_get_waveform_obj(synthio_note_obj_t *self); void common_hal_synthio_note_set_waveform(synthio_note_obj_t *self, mp_obj_t value); +mp_int_t common_hal_synthio_note_get_waveform_loop_start(synthio_note_obj_t *self); +void common_hal_synthio_note_set_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in); + +mp_int_t common_hal_synthio_note_get_waveform_loop_end(synthio_note_obj_t *self); +void common_hal_synthio_note_set_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in); + mp_float_t common_hal_synthio_note_get_ring_frequency(synthio_note_obj_t *self); void common_hal_synthio_note_set_ring_frequency(synthio_note_obj_t *self, mp_float_t value); @@ -33,11 +39,11 @@ void common_hal_synthio_note_set_ring_bend(synthio_note_obj_t *self, mp_obj_t va mp_obj_t common_hal_synthio_note_get_ring_waveform_obj(synthio_note_obj_t *self); void common_hal_synthio_note_set_ring_waveform(synthio_note_obj_t *self, mp_obj_t value); +mp_int_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self); +void common_hal_synthio_note_set_ring_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in); + +mp_int_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self); +void common_hal_synthio_note_set_ring_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in); + mp_obj_t common_hal_synthio_note_get_envelope_obj(synthio_note_obj_t *self); void common_hal_synthio_note_set_envelope(synthio_note_obj_t *self, mp_obj_t value); - -mp_int_t common_hal_synthio_note_get_loop_start(synthio_note_obj_t *self); -void common_hal_synthio_note_set_loop_start(synthio_note_obj_t *self, mp_int_t value_in); - -mp_int_t common_hal_synthio_note_get_loop_end(synthio_note_obj_t *self); -void common_hal_synthio_note_set_loop_end(synthio_note_obj_t *self, mp_int_t value_in); diff --git a/shared-bindings/synthio/__init__.h b/shared-bindings/synthio/__init__.h index 4a44277e85..e77e77ecc6 100644 --- a/shared-bindings/synthio/__init__.h +++ b/shared-bindings/synthio/__init__.h @@ -29,6 +29,8 @@ #include "py/objnamedtuple.h" #include "py/enum.h" +#define SYNTHIO_WAVEFORM_SIZE 16384 + typedef enum { SYNTHIO_ENVELOPE_STATE_ATTACK, SYNTHIO_ENVELOPE_STATE_DECAY, SYNTHIO_ENVELOPE_STATE_SUSTAIN, SYNTHIO_ENVELOPE_STATE_RELEASE diff --git a/shared-module/synthio/Note.c b/shared-module/synthio/Note.c index 22bd74cd3c..065ca388ac 100644 --- a/shared-module/synthio/Note.c +++ b/shared-module/synthio/Note.c @@ -120,6 +120,24 @@ void common_hal_synthio_note_set_waveform(synthio_note_obj_t *self, mp_obj_t wav self->waveform_obj = waveform_in; } +mp_int_t common_hal_synthio_note_get_waveform_loop_start(synthio_note_obj_t *self) { + return self->waveform_loop_start; +} + +void common_hal_synthio_note_set_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in) { + mp_int_t val = mp_arg_validate_int_range(value_in, 0, SYNTHIO_WAVEFORM_SIZE - 1, MP_QSTR_waveform_loop_start); + self->waveform_loop_start = val; +} + +mp_int_t common_hal_synthio_note_get_waveform_loop_end(synthio_note_obj_t *self) { + return self->waveform_loop_end; +} + +void common_hal_synthio_note_set_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in) { + mp_int_t val = mp_arg_validate_int_range(value_in, 1, SYNTHIO_WAVEFORM_SIZE, MP_QSTR_waveform_loop_end); + self->waveform_loop_end = val; +} + mp_obj_t common_hal_synthio_note_get_ring_waveform_obj(synthio_note_obj_t *self) { return self->ring_waveform_obj; } @@ -135,22 +153,22 @@ void common_hal_synthio_note_set_ring_waveform(synthio_note_obj_t *self, mp_obj_ self->ring_waveform_obj = ring_waveform_in; } -mp_int_t common_hal_synthio_note_get_loop_start(synthio_note_obj_t *self) { - return self->loop_start; +mp_int_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self) { + return self->ring_waveform_loop_start; } -void common_hal_synthio_note_set_loop_start(synthio_note_obj_t *self, mp_int_t value_in) { - mp_int_t val = mp_arg_validate_int_range(value_in, 0, 32767, MP_QSTR_loop_start); - self->loop_start = val; +void common_hal_synthio_note_set_ring_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in) { + mp_int_t val = mp_arg_validate_int_range(value_in, 0, SYNTHIO_WAVEFORM_SIZE - 1, MP_QSTR_ring_waveform_loop_start); + self->ring_waveform_loop_start = val; } -mp_int_t common_hal_synthio_note_get_loop_end(synthio_note_obj_t *self) { - return self->loop_end; +mp_int_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self) { + return self->ring_waveform_loop_end; } -void common_hal_synthio_note_set_loop_end(synthio_note_obj_t *self, mp_int_t value_in) { - mp_int_t val = mp_arg_validate_int_range(value_in, 0, 32767, MP_QSTR_loop_end); - self->loop_end = val; +void common_hal_synthio_note_set_ring_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in) { + mp_int_t val = mp_arg_validate_int_range(value_in, 1, SYNTHIO_WAVEFORM_SIZE, MP_QSTR_ring_waveform_loop_end); + self->ring_waveform_loop_end = val; } void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate) { diff --git a/shared-module/synthio/Note.h b/shared-module/synthio/Note.h index 106b4a5bd2..c9faa60cac 100644 --- a/shared-module/synthio/Note.h +++ b/shared-module/synthio/Note.h @@ -48,10 +48,10 @@ typedef struct synthio_note_obj { int32_t ring_frequency_scaled, ring_frequency_bent; mp_buffer_info_t waveform_buf; + uint32_t waveform_loop_start, waveform_loop_end; mp_buffer_info_t ring_waveform_buf; + uint32_t ring_waveform_loop_start, ring_waveform_loop_end; synthio_envelope_definition_t envelope_def; - - uint32_t loop_start, loop_end; } synthio_note_obj_t; void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate); diff --git a/shared-module/synthio/__init__.c b/shared-module/synthio/__init__.c index 1158fc0840..06477e26ac 100644 --- a/shared-module/synthio/__init__.c +++ b/shared-module/synthio/__init__.c @@ -185,6 +185,7 @@ static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou uint32_t ring_dds_rate = 0; const int16_t *ring_waveform = NULL; + uint32_t ring_waveform_start = 0; uint32_t ring_waveform_length = 0; if (mp_obj_is_small_int(note_obj)) { @@ -203,18 +204,24 @@ static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou if (note->waveform_buf.buf) { waveform = note->waveform_buf.buf; waveform_length = note->waveform_buf.len; - if (note->loop_start > 0 && note->loop_start < waveform_length) { - waveform_start = note->loop_start; + if (note->waveform_loop_start > 0 && note->waveform_loop_start < waveform_length) { + waveform_start = note->waveform_loop_start; } - if (note->loop_end > waveform_start && note->loop_end < waveform_length) { - waveform_length = note->loop_end; + if (note->waveform_loop_end > waveform_start && note->waveform_loop_end < waveform_length) { + waveform_length = note->waveform_loop_end; } } dds_rate = synthio_frequency_convert_scaled_to_dds((uint64_t)frequency_scaled * (waveform_length - waveform_start), sample_rate); if (note->ring_frequency_scaled != 0 && note->ring_waveform_buf.buf) { ring_waveform = note->ring_waveform_buf.buf; ring_waveform_length = note->ring_waveform_buf.len; - ring_dds_rate = synthio_frequency_convert_scaled_to_dds((uint64_t)note->ring_frequency_bent * ring_waveform_length, sample_rate); + if (note->ring_waveform_loop_start > 0 && note->ring_waveform_loop_start < ring_waveform_length) { + ring_waveform_start = note->waveform_loop_start; + } + if (note->ring_waveform_loop_end > ring_waveform_start && note->ring_waveform_loop_end < ring_waveform_length) { + ring_waveform_length = note->ring_waveform_loop_end; + } + ring_dds_rate = synthio_frequency_convert_scaled_to_dds((uint64_t)note->ring_frequency_bent * (ring_waveform_length - ring_waveform_start), sample_rate); uint32_t lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT; if (ring_dds_rate > lim / sizeof(int16_t)) { ring_dds_rate = 0; // can't ring at that frequency @@ -257,18 +264,19 @@ static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou // now modulate by ring and accumulate accum = synth->ring_accum[chan]; + offset = ring_waveform_start << SYNTHIO_FREQUENCY_SHIFT; lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT; // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided if (accum > lim) { - accum %= lim; + accum = accum % lim + offset; } for (uint16_t i = 0; i < dur; i++) { accum += ring_dds_rate; // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed if (accum > lim) { - accum -= lim; + accum = accum - lim + offset; } int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT; int16_t wi = (ring_waveform[idx] * out_buffer32[i]) / 32768; @@ -442,7 +450,7 @@ STATIC void parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what, mp void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj) { *bufinfo_waveform = ((mp_buffer_info_t) { .buf = (void *)square_wave, .len = 2 }); - parse_common(bufinfo_waveform, waveform_obj, MP_QSTR_waveform, 16384); + parse_common(bufinfo_waveform, waveform_obj, MP_QSTR_waveform, SYNTHIO_WAVEFORM_SIZE); } STATIC int find_channel_with_note(synthio_synth_t *synth, mp_obj_t note) {