From 4b92af788b901f7b92ef3c4a8de79d338b833ac6 Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sun, 12 Sep 2010 00:24:45 +0100 Subject: [PATCH] Fix handling of very short notes in Monosynth. (cherry picked from commit 5965d9922a0753e2dce4f743a23b9512be01a7ac) --- .../calf/src/calf/modules_synths.h | 4 ++ plugins/ladspa_effect/calf/src/monosynth.cpp | 55 +++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/plugins/ladspa_effect/calf/src/calf/modules_synths.h b/plugins/ladspa_effect/calf/src/calf/modules_synths.h index 8cd1c0ba4..ee4ae42e1 100644 --- a/plugins/ladspa_effect/calf/src/calf/modules_synths.h +++ b/plugins/ladspa_effect/calf/src/calf/modules_synths.h @@ -88,6 +88,8 @@ public: int32_t last_stretch1; /// Next note to play on the next calculate_step int queue_note_on; + /// Whether the queued note has been already released + bool queue_note_on_and_off; /// Velocity of the next note to play float queue_vel; /// Integer value for modwheel (0-16383, read from CC1 - MSBs and CC33 - LSBs) @@ -122,6 +124,8 @@ public: static void precalculate_waves(progress_report_iface *reporter); void set_sample_rate(uint32_t sr); void delayed_note_on(); + /// Release a note (physically), called from note-off handler or when note-off has been scheduled after note-on (very short queued note) + void end_note(); /// Handle MIDI Note On message (does not immediately trigger a note, as it must start on /// boundary of step_size samples). void note_on(int note, int vel); diff --git a/plugins/ladspa_effect/calf/src/monosynth.cpp b/plugins/ladspa_effect/calf/src/monosynth.cpp index d5c77c16f..2f2b731ad 100644 --- a/plugins/ladspa_effect/calf/src/monosynth.cpp +++ b/plugins/ladspa_effect/calf/src/monosynth.cpp @@ -76,6 +76,7 @@ void monosynth_audio_module::activate() { stack.clear(); last_pwshift1 = last_pwshift2 = 0; last_stretch1 = 65536; + queue_note_on_and_off = false; } waveform_family *monosynth_audio_module::waves; @@ -433,6 +434,12 @@ void monosynth_audio_module::delayed_note_on() queue_note_on = -1; float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, envelope1.value, envelope2.value, 0.5+0.5*lfo1.last, 0.5+0.5*lfo2.last}; calculate_modmatrix(moddest, moddest_count, modsrc); + + if (queue_note_on_and_off) + { + end_note(); + queue_note_on_and_off = false; + } } void monosynth_audio_module::set_sample_rate(uint32_t sr) { @@ -629,6 +636,7 @@ void monosynth_audio_module::apply_fadeout() void monosynth_audio_module::note_on(int note, int vel) { queue_note_on = note; + queue_note_on_and_off = false; last_key = note; queue_vel = vel / 127.f; stack.push(note); @@ -637,29 +645,40 @@ void monosynth_audio_module::note_on(int note, int vel) void monosynth_audio_module::note_off(int note, int vel) { stack.pop(note); + if (note == queue_note_on) + { + queue_note_on_and_off = true; + return; + } // If releasing the currently played note, try to get another one from note stack. if (note == last_key) { - if (stack.count()) - { - last_key = note = stack.nth(stack.count() - 1); - start_freq = freq; - target_freq = freq = dsp::note_to_hz(note); - porta_time = 0; - set_frequency(); - if (!(legato & 1)) { - envelope1.note_on(); - envelope2.note_on(); - stopping = false; - running = true; - } - return; - } - gate = false; - envelope1.note_off(); - envelope2.note_off(); + end_note(); } } +void monosynth_audio_module::end_note() +{ + if (stack.count()) + { + int note; + last_key = note = stack.nth(stack.count() - 1); + start_freq = freq; + target_freq = freq = dsp::note_to_hz(note); + porta_time = 0; + set_frequency(); + if (!(legato & 1)) { + envelope1.note_on(); + envelope2.note_on(); + stopping = false; + running = true; + } + return; + } + gate = false; + envelope1.note_off(); + envelope2.note_off(); +} + void monosynth_audio_module::channel_pressure(int value) { inertia_pressure.set_inertia(value * (1.0 / 127.0));