diff --git a/esfm.c b/esfm.c index 54af9cc..2779270 100644 --- a/esfm.c +++ b/esfm.c @@ -374,7 +374,6 @@ ESFM_envelope_calc(esfm_slot *slot) bool reset = 0; bool key_on; bool key_on_signal; - uint16 delay_counter_compare; key_on = *slot->in.key_on; if (!slot->chip->native_mode) @@ -421,19 +420,42 @@ ESFM_envelope_calc(esfm_slot *slot) { slot->in.eg_delay_run = 1; slot->in.eg_delay_counter = 0; + slot->in.eg_delay_transitioned_01 = 0; + slot->in.eg_delay_transitioned_01_gate = 0; + slot->in.eg_delay_transitioned_10 = 0; + slot->in.eg_delay_transitioned_10_gate = 0; + slot->in.eg_delay_counter_compare = 0; + if (slot->env_delay > 0) + { + slot->in.eg_delay_counter_compare = 256 << slot->env_delay; + } } else if (!key_on) { slot->in.eg_delay_run = 0; } - delay_counter_compare = 0; - if (slot->env_delay > 0) + // TODO: is this really how the chip behaves? Can it only transition the envelope delay once? Am I implementing this in a sane way? I feel like this is a roundabout hack. + if ((slot->in.eg_delay_transitioned_10 && !slot->in.eg_delay_transitioned_10_gate) || + (slot->in.eg_delay_transitioned_01 && !slot->in.eg_delay_transitioned_01_gate) + ) { - delay_counter_compare = 256 << slot->env_delay; + slot->in.eg_delay_counter_compare = 0; + if (slot->env_delay > 0) + { + slot->in.eg_delay_counter_compare = 256 << slot->env_delay; + } + if (slot->in.eg_delay_transitioned_10) + { + slot->in.eg_delay_transitioned_10_gate = 1; + } + if (slot->in.eg_delay_transitioned_01) + { + slot->in.eg_delay_transitioned_01_gate = 1; + } } - if (key_on && ((slot->in.eg_delay_counter >= delay_counter_compare) || !slot->chip->native_mode)) + if (key_on && ((slot->in.eg_delay_counter >= slot->in.eg_delay_counter_compare) || !slot->chip->native_mode)) { key_on_signal = 1; } else { @@ -443,7 +465,7 @@ ESFM_envelope_calc(esfm_slot *slot) if (key_on && slot->in.eg_state == EG_RELEASE) { - if ((slot->in.eg_delay_counter >= delay_counter_compare) || !slot->chip->native_mode) + if ((slot->in.eg_delay_counter >= slot->in.eg_delay_counter_compare) || !slot->chip->native_mode) { reset = 1; reg_rate = slot->attack_rate; diff --git a/esfm.h b/esfm.h index d5c734b..f410558 100644 --- a/esfm.h +++ b/esfm.h @@ -174,7 +174,12 @@ typedef struct _esfm_slot_internal uint2 eg_state; flag eg_delay_run; + flag eg_delay_transitioned_10; + flag eg_delay_transitioned_10_gate; + flag eg_delay_transitioned_01; + flag eg_delay_transitioned_01_gate; uint16 eg_delay_counter; + uint16 eg_delay_counter_compare; } esfm_slot_internal; diff --git a/esfm_registers.c b/esfm_registers.c index 789c68e..d87a594 100644 --- a/esfm_registers.c +++ b/esfm_registers.c @@ -365,6 +365,14 @@ ESFM_slot_write (esfm_slot *slot, uint8_t register_idx, uint8_t data) ESFM_slot_update_keyscale(slot); break; case 0x05: + if (slot->env_delay < (data >> 5)) + { + slot->in.eg_delay_transitioned_01 = 1; + } + else if (slot->env_delay > (data >> 5)) + { + slot->in.eg_delay_transitioned_10 = 1; + } slot->env_delay = data >> 5; slot->emu_key_on = (data >> 5) & 0x01; slot->block = (data >> 2) & 0x07;