Added SYNTHIO_WAVEFORM_SIZE definition, renamed 'loop_...' to 'waveform_loop_...', added 'ring_waveform_loop_...` parameters, and updated docstrings.

This commit is contained in:
dcooperdalrymple 2023-11-20 09:50:03 -06:00
parent 785ef5abd2
commit 55db6b7947
6 changed files with 131 additions and 54 deletions

View File

@ -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_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_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, 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_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_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_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_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_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_ring_waveform_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_end, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } },
}; };
//| class Note: //| class Note:
//| def __init__( //| def __init__(
@ -55,6 +57,8 @@ static const mp_arg_t note_properties[] = {
//| frequency: float, //| frequency: float,
//| panning: BlockInput = 0.0, //| panning: BlockInput = 0.0,
//| waveform: Optional[ReadableBuffer] = None, //| waveform: Optional[ReadableBuffer] = None,
//| waveform_loop_start: int = 0,
//| waveform_loop_end: int = 0,
//| envelope: Optional[Envelope] = None, //| envelope: Optional[Envelope] = None,
//| amplitude: BlockInput = 0.0, //| amplitude: BlockInput = 0.0,
//| bend: BlockInput = 0.0, //| bend: BlockInput = 0.0,
@ -62,8 +66,8 @@ static const mp_arg_t note_properties[] = {
//| ring_frequency: float = 0.0, //| ring_frequency: float = 0.0,
//| ring_bend: float = 0.0, //| ring_bend: float = 0.0,
//| ring_waveform: Optional[ReadableBuffer] = 0.0, //| ring_waveform: Optional[ReadableBuffer] = 0.0,
//| loop_start: int = 0, //| ring_waveform_loop_start: int = 0,
//| loop_end: int = 0, //| ring_waveform_loop_end: int = 0,
//| ) -> None: //| ) -> None:
//| """Construct a Note object, with a frequency in Hz, and optional panning, waveform, envelope, tremolo (volume change) and bend (frequency change). //| """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_get_waveform_obj,
(mp_obj_t)&synthio_note_set_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 //| envelope: Envelope
//| """The envelope of this note""" //| """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_get_ring_waveform_obj,
(mp_obj_t)&synthio_note_set_ring_waveform_obj); (mp_obj_t)&synthio_note_set_ring_waveform_obj);
//| loop_start: int //| ring_waveform_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.""" //| """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_loop_start(mp_obj_t self_in) { 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); 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); 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; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_loop_start_obj, synthio_note_set_loop_start); 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_loop_start_obj, MP_PROPERTY_GETSET(synthio_note_ring_waveform_loop_start_obj,
(mp_obj_t)&synthio_note_get_loop_start_obj, (mp_obj_t)&synthio_note_get_ring_waveform_loop_start_obj,
(mp_obj_t)&synthio_note_set_loop_start_obj); (mp_obj_t)&synthio_note_set_ring_waveform_loop_start_obj);
//| loop_end: int //| ring_waveform_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.""" //| """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); 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); 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; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_loop_end_obj, synthio_note_set_loop_end); 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_loop_end_obj, MP_PROPERTY_GETSET(synthio_note_ring_waveform_loop_end_obj,
(mp_obj_t)&synthio_note_get_loop_end_obj, (mp_obj_t)&synthio_note_get_ring_waveform_loop_end_obj,
(mp_obj_t)&synthio_note_set_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_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_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), 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_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_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_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_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_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_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_ring_waveform_loop_start), MP_ROM_PTR(&synthio_note_ring_waveform_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_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); STATIC MP_DEFINE_CONST_DICT(synthio_note_locals_dict, synthio_note_locals_dict_table);

View File

@ -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); 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); 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); 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); 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); 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); 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); 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); 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);

View File

@ -29,6 +29,8 @@
#include "py/objnamedtuple.h" #include "py/objnamedtuple.h"
#include "py/enum.h" #include "py/enum.h"
#define SYNTHIO_WAVEFORM_SIZE 16384
typedef enum { typedef enum {
SYNTHIO_ENVELOPE_STATE_ATTACK, SYNTHIO_ENVELOPE_STATE_DECAY, SYNTHIO_ENVELOPE_STATE_ATTACK, SYNTHIO_ENVELOPE_STATE_DECAY,
SYNTHIO_ENVELOPE_STATE_SUSTAIN, SYNTHIO_ENVELOPE_STATE_RELEASE SYNTHIO_ENVELOPE_STATE_SUSTAIN, SYNTHIO_ENVELOPE_STATE_RELEASE

View File

@ -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; 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) { mp_obj_t common_hal_synthio_note_get_ring_waveform_obj(synthio_note_obj_t *self) {
return self->ring_waveform_obj; 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; self->ring_waveform_obj = ring_waveform_in;
} }
mp_int_t common_hal_synthio_note_get_loop_start(synthio_note_obj_t *self) { mp_int_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self) {
return self->loop_start; return self->ring_waveform_loop_start;
} }
void common_hal_synthio_note_set_loop_start(synthio_note_obj_t *self, mp_int_t value_in) { 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, 32767, MP_QSTR_loop_start); mp_int_t val = mp_arg_validate_int_range(value_in, 0, SYNTHIO_WAVEFORM_SIZE - 1, MP_QSTR_ring_waveform_loop_start);
self->loop_start = val; self->ring_waveform_loop_start = val;
} }
mp_int_t common_hal_synthio_note_get_loop_end(synthio_note_obj_t *self) { mp_int_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self) {
return self->loop_end; return self->ring_waveform_loop_end;
} }
void common_hal_synthio_note_set_loop_end(synthio_note_obj_t *self, mp_int_t value_in) { 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, 0, 32767, MP_QSTR_loop_end); mp_int_t val = mp_arg_validate_int_range(value_in, 1, SYNTHIO_WAVEFORM_SIZE, MP_QSTR_ring_waveform_loop_end);
self->loop_end = val; self->ring_waveform_loop_end = val;
} }
void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate) { void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate) {

View File

@ -48,10 +48,10 @@ typedef struct synthio_note_obj {
int32_t ring_frequency_scaled, ring_frequency_bent; int32_t ring_frequency_scaled, ring_frequency_bent;
mp_buffer_info_t waveform_buf; mp_buffer_info_t waveform_buf;
uint32_t waveform_loop_start, waveform_loop_end;
mp_buffer_info_t ring_waveform_buf; mp_buffer_info_t ring_waveform_buf;
uint32_t ring_waveform_loop_start, ring_waveform_loop_end;
synthio_envelope_definition_t envelope_def; synthio_envelope_definition_t envelope_def;
uint32_t loop_start, loop_end;
} synthio_note_obj_t; } synthio_note_obj_t;
void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate); void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate);

View File

@ -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; uint32_t ring_dds_rate = 0;
const int16_t *ring_waveform = NULL; const int16_t *ring_waveform = NULL;
uint32_t ring_waveform_start = 0;
uint32_t ring_waveform_length = 0; uint32_t ring_waveform_length = 0;
if (mp_obj_is_small_int(note_obj)) { 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) { if (note->waveform_buf.buf) {
waveform = note->waveform_buf.buf; waveform = note->waveform_buf.buf;
waveform_length = note->waveform_buf.len; waveform_length = note->waveform_buf.len;
if (note->loop_start > 0 && note->loop_start < waveform_length) { if (note->waveform_loop_start > 0 && note->waveform_loop_start < waveform_length) {
waveform_start = note->loop_start; waveform_start = note->waveform_loop_start;
} }
if (note->loop_end > waveform_start && note->loop_end < waveform_length) { if (note->waveform_loop_end > waveform_start && note->waveform_loop_end < waveform_length) {
waveform_length = note->loop_end; waveform_length = note->waveform_loop_end;
} }
} }
dds_rate = synthio_frequency_convert_scaled_to_dds((uint64_t)frequency_scaled * (waveform_length - waveform_start), sample_rate); 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) { if (note->ring_frequency_scaled != 0 && note->ring_waveform_buf.buf) {
ring_waveform = note->ring_waveform_buf.buf; ring_waveform = note->ring_waveform_buf.buf;
ring_waveform_length = note->ring_waveform_buf.len; 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; uint32_t lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT;
if (ring_dds_rate > lim / sizeof(int16_t)) { if (ring_dds_rate > lim / sizeof(int16_t)) {
ring_dds_rate = 0; // can't ring at that frequency 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 // now modulate by ring and accumulate
accum = synth->ring_accum[chan]; accum = synth->ring_accum[chan];
offset = ring_waveform_start << SYNTHIO_FREQUENCY_SHIFT;
lim = ring_waveform_length << 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 // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
if (accum > lim) { if (accum > lim) {
accum %= lim; accum = accum % lim + offset;
} }
for (uint16_t i = 0; i < dur; i++) { for (uint16_t i = 0; i < dur; i++) {
accum += ring_dds_rate; accum += ring_dds_rate;
// because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
if (accum > lim) { if (accum > lim) {
accum -= lim; accum = accum - lim + offset;
} }
int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT; int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT;
int16_t wi = (ring_waveform[idx] * out_buffer32[i]) / 32768; 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) { 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 }); *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) { STATIC int find_channel_with_note(synthio_synth_t *synth, mp_obj_t note) {