synthio: make sustain level relative to attack level

and re-vamp overall envelope calculation again.

Now, if you set a low overall attack level like 0.2 this avoids the
"diminishing volume" effect when many notes sound at once. You need
simply choose a maximum attack level that is appropriate for the max
number of voices that will actually be played.
This commit is contained in:
Jeff Epler 2023-05-04 07:22:02 -05:00
parent c06597c07a
commit 1701552dec
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
2 changed files with 8 additions and 8 deletions

View File

@ -79,8 +79,8 @@ static const mp_arg_t envelope_properties[] = {
//| :param float attack_time: The time in seconds it takes to ramp from 0 volume to attack_volume //| :param float attack_time: The time in seconds it takes to ramp from 0 volume to attack_volume
//| :param float decay_time: The time in seconds it takes to ramp from attack_volume to sustain_volume //| :param float decay_time: The time in seconds it takes to ramp from attack_volume to sustain_volume
//| :param float release_time: The time in seconds it takes to ramp from sustain_volume to release_volume. When a note is released before it has reached the sustain phase, the release is done with the same slope indicated by ``release_time`` and ``sustain_level`` //| :param float release_time: The time in seconds it takes to ramp from sustain_volume to release_volume. When a note is released before it has reached the sustain phase, the release is done with the same slope indicated by ``release_time`` and ``sustain_level``
//| :param float attack_level: The relative level, in the range ``0.0`` to ``1.0`` of the peak volume of the attack phase //| :param float attack_level: The level, in the range ``0.0`` to ``1.0`` of the peak volume of the attack phase
//| :param float sustain_level: The relative level, in the range ``0.0`` to ``1.0`` of the volume of the sustain phase //| :param float sustain_level: The level, in the range ``0.0`` to ``1.0`` of the volume of the sustain phase relative to the attack level
//| """ //| """
//| attack_time: float //| attack_time: float
//| """The time in seconds it takes to ramp from 0 volume to attack_volume""" //| """The time in seconds it takes to ramp from 0 volume to attack_volume"""
@ -92,10 +92,10 @@ static const mp_arg_t envelope_properties[] = {
//| """The time in seconds it takes to ramp from sustain_volume to release_volume. When a note is released before it has reached the sustain phase, the release is done with the same slope indicated by ``release_time`` and ``sustain_level``""" //| """The time in seconds it takes to ramp from sustain_volume to release_volume. When a note is released before it has reached the sustain phase, the release is done with the same slope indicated by ``release_time`` and ``sustain_level``"""
//| //|
//| attack_level: float //| attack_level: float
//| """The relative level, in the range ``0.0`` to ``1.0`` of the peak volume of the attack phase""" //| """The level, in the range ``0.0`` to ``1.0`` of the peak volume of the attack phase"""
//| //|
//| sustain_level: float //| sustain_level: float
//| """The relative level, in the range ``0.0`` to ``1.0`` of the volume of the sustain phase""" //| """The level, in the range ``0.0`` to ``1.0`` of the volume of the sustain phase relative to the attack level"""
//| //|
STATIC mp_obj_t synthio_envelope_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { STATIC mp_obj_t synthio_envelope_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {

View File

@ -77,7 +77,7 @@ void synthio_envelope_definition_set(synthio_envelope_definition_t *envelope, mp
mp_obj_tuple_get(obj, &len, &fields); mp_obj_tuple_get(obj, &len, &fields);
envelope->attack_level = (int)(32767 * mp_obj_get_float(fields[3])); envelope->attack_level = (int)(32767 * mp_obj_get_float(fields[3]));
envelope->sustain_level = (int)(32767 * mp_obj_get_float(fields[4])); envelope->sustain_level = (int)(32767 * mp_obj_get_float(fields[4]) * mp_obj_get_float(fields[3]));
envelope->attack_step = convert_time_to_rate( envelope->attack_step = convert_time_to_rate(
sample_rate, fields[0], envelope->attack_level); sample_rate, fields[0], envelope->attack_level);
@ -152,10 +152,10 @@ STATIC uint32_t synthio_synth_sum_envelope(synthio_synth_t *synth) {
for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) { for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) {
if (synth->span.note_obj[chan] != SYNTHIO_SILENCE) { if (synth->span.note_obj[chan] != SYNTHIO_SILENCE) {
synthio_envelope_state_t *state = &synth->envelope_state[chan]; synthio_envelope_state_t *state = &synth->envelope_state[chan];
if (state->state == SYNTHIO_ENVELOPE_STATE_RELEASE) { if (state->state == SYNTHIO_ENVELOPE_STATE_ATTACK) {
result += synth->envelope_definition.sustain_level;
} else {
result += state->level; result += state->level;
} else {
result += synth->envelope_definition.attack_level;
} }
} }
} }