From 4f56b7646e9c7107a4a0e9d1addf58d6df4d5a5d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 2 May 2023 14:14:50 -0500 Subject: [PATCH] synthio: slow ramp overall envelope back up .. and account releasing notes at their sustain level until they're done. this ameliorates the effect where multiple releasing notes don't seem to actually be releasing, but stay at a constant volume. --- shared-module/synthio/__init__.c | 30 ++++++++++++++++++++++++------ shared-module/synthio/__init__.h | 1 + 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/shared-module/synthio/__init__.c b/shared-module/synthio/__init__.c index 857f483780..19e9990b17 100644 --- a/shared-module/synthio/__init__.c +++ b/shared-module/synthio/__init__.c @@ -151,7 +151,12 @@ STATIC uint32_t synthio_synth_sum_envelope(synthio_synth_t *synth) { uint32_t result = 0; for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) { if (synth->span.note_obj[chan] != SYNTHIO_SILENCE) { - result += synth->envelope_state[chan].level; + synthio_envelope_state_t *state = &synth->envelope_state[chan]; + if (state->state == SYNTHIO_ENVELOPE_STATE_RELEASE) { + result += synth->envelope_definition.sustain_level; + } else { + result += state->level; + } } } return result; @@ -177,25 +182,38 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t int32_t sample_rate = synth->sample_rate; uint32_t total_envelope = synthio_synth_sum_envelope(synth); + if (total_envelope < synth->total_envelope) { + // total envelope is decreasing. Slowly let remaining notes get louder + // the time constant is arbitrary, on the order of 1s at 48kHz + total_envelope = synth->total_envelope = ( + total_envelope + synth->total_envelope * 255) / 256; + } else { + // total envelope is steady or increasing, so just store this as + // the high water mark + synth->total_envelope = total_envelope; + } if (total_envelope > 0) { uint16_t ovl_loudness = 0x7fffffff / MAX(0x8000, total_envelope); + for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) { - if (synth->span.note_obj[chan] == SYNTHIO_SILENCE) { + mp_obj_t note_obj = synth->span.note_obj[chan]; + if (note_obj == SYNTHIO_SILENCE) { synth->accum[chan] = 0; continue; } - // adjust loudness by envelope - uint16_t loudness = (ovl_loudness * synth->envelope_state[chan].level) >> 16; if (synth->envelope_state[chan].level == 0) { - // note is truly finished + // note is truly finished, but we only just noticed synth->span.note_obj[chan] = SYNTHIO_SILENCE; + continue; } + // adjust loudness by envelope + uint16_t loudness = (ovl_loudness * synth->envelope_state[chan].level) >> 16; + uint32_t dds_rate; const int16_t *waveform = synth->waveform; uint32_t waveform_length = synth->waveform_length; - mp_obj_t note_obj = synth->span.note_obj[chan]; if (mp_obj_is_small_int(note_obj)) { uint8_t note = mp_obj_get_int(note_obj); uint8_t octave = note / 12; diff --git a/shared-module/synthio/__init__.h b/shared-module/synthio/__init__.h index 42e4ee79d4..29520dfb5b 100644 --- a/shared-module/synthio/__init__.h +++ b/shared-module/synthio/__init__.h @@ -62,6 +62,7 @@ typedef struct { typedef struct synthio_synth { uint32_t sample_rate; + uint32_t total_envelope; int16_t *buffers[2]; const int16_t *waveform; uint16_t buffer_length;