diff --git a/plugins/ladspa_effect/calf/src/calf/envelope.h b/plugins/ladspa_effect/calf/src/calf/envelope.h index 94f87ed22..302e4c06c 100644 --- a/plugins/ladspa_effect/calf/src/calf/envelope.h +++ b/plugins/ladspa_effect/calf/src/calf/envelope.h @@ -207,6 +207,74 @@ public: } }; +/// Simple linear fade out for note tails +struct fadeout +{ + float value; + float step, step_orig; + bool done, undoing; + + fadeout(int steps = 256) + { + step_orig = (float)(1.f / steps); + value = 1.f; + reset(); + } + + /// Prepare fade out + void reset() + { + value = 1.f; + step = -step_orig; + done = false; + undoing = false; + } + + /// Fade back in with double speed (to prevent click on note restart) + void undo() + { + step = step_orig; + done = false; + undoing = true; + } + + /// Reset if fully faded out; fade back in if in the middle of fading out + void reset_soft() + { + if (value <= 0.f || value >= 1.f) + reset(); + else + undo(); + } + + void process(float *buffer, int len) + { + int i = 0; + if (!done) + { + for (; value > 0 && value <= 1.0 && i < len; i++) + { + buffer[i] *= value; + value += step; + } + if (value <= 0 || value > 1) + done = true; + } + if (done && value <= 0) + { + while (i < len) + buffer[i++] = 0.f; + } + if (done && undoing && value >= 1) + { + undoing = false; + done = false; + // prepare for the next fade-out + value = 1.f; + } + } +}; + }; #endif diff --git a/plugins/ladspa_effect/calf/src/calf/inertia.h b/plugins/ladspa_effect/calf/src/calf/inertia.h index aca1fbfec..d6bbd297a 100644 --- a/plugins/ladspa_effect/calf/src/calf/inertia.h +++ b/plugins/ladspa_effect/calf/src/calf/inertia.h @@ -245,7 +245,7 @@ public: } void set_sample_rate(int sr) { - ramp = linear_ramp(sr / 441); + ramp = linear_ramp(sr / 100); } // to change param, use set_inertia(value) // to read param, use get() diff --git a/plugins/ladspa_effect/calf/src/calf/modules_synths.h b/plugins/ladspa_effect/calf/src/calf/modules_synths.h index 3b7ca83a3..8cd1c0ba4 100644 --- a/plugins/ladspa_effect/calf/src/calf/modules_synths.h +++ b/plugins/ladspa_effect/calf/src/calf/modules_synths.h @@ -45,14 +45,22 @@ public: static dsp::waveform_family *waves; dsp::waveform_oscillator osc1, osc2; dsp::triangle_lfo lfo1, lfo2; - bool running, stopping, gate, force_fadeout; + dsp::biquad_d1_lerp filter, filter2; + /// The step code is producing non-zero values + bool running; + /// This is the last non-zero buffer (set on calculate_step after fadeout is complete, the next calculate_step will zero running) + bool stopping; + /// A key is kept pressed + bool gate; + /// All notes off fadeout + bool force_fadeout; + /// Last triggered note int last_key; + /// Output buffers, used to ensure updates are done every step_size regardless of process buffer size float buffer[step_size], buffer2[step_size]; + /// Read position within the buffers, on each '0' the buffers are being filled with new data by calculate_step uint32_t output_pos; - dsp::onepole phaseshifter; - dsp::biquad_d1_lerp filter; - dsp::biquad_d1_lerp filter2; /// Waveform number - OSC1 int wave1; /// Waveform number - OSC2 @@ -61,10 +69,15 @@ public: int prev_wave1; /// Last used waveform number - OSC2 int prev_wave2; - int filter_type, last_filter_type; + /// Filter type + int filter_type; + /// Filter type on the last calculate_step + int last_filter_type; float freq, start_freq, target_freq, cutoff, fgain, fgain_delta, separation; - float detune, xpose, xfade, ampctl, fltctl, queue_vel; - float odcr, porta_time, lfo_bend, lfo1_clock, lfo2_clock, modwheel_value; + float detune, xpose, xfade, ampctl, fltctl; + float odcr, porta_time, lfo_bend; + /// Modulation wheel position (0.f-1.f) + float modwheel_value; /// Delay counter for LFOs float lfo_clock; /// Last value of phase shift for pulse width emulation for OSC1 @@ -73,11 +86,23 @@ public: int32_t last_pwshift2; /// Last value of stretch for osc sync emulation for OSC1 int32_t last_stretch1; - int queue_note_on, stop_count, modwheel_value_int; + /// Next note to play on the next calculate_step + int queue_note_on; + /// Velocity of the next note to play + float queue_vel; + /// Integer value for modwheel (0-16383, read from CC1 - MSBs and CC33 - LSBs) + int modwheel_value_int; + /// Legato mode (bitmask) int legato; + /// Envelope Generators dsp::adsr envelope1, envelope2; dsp::keystack stack; + /// Smoothing for master volume dsp::gain_smoothing master; + /// Fadeout for buffer 1 + dsp::fadeout fadeout; + /// Fadeout for buffer 2 + dsp::fadeout fadeout2; /// Smoothed cutoff value dsp::inertia inertia_cutoff; /// Smoothed pitch bend value @@ -145,6 +170,8 @@ public: bool is_noisy(int param_no) const { return param_no != par_cutoff; } /// Calculate control signals and produce step_size samples of output. void calculate_step(); + /// Apply anti-click'n'pop fadeout (used at the end of the sound) + void apply_fadeout(); /// Main processing function uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask); }; diff --git a/plugins/ladspa_effect/calf/src/monosynth.cpp b/plugins/ladspa_effect/calf/src/monosynth.cpp index a2d124843..5120eab81 100644 --- a/plugins/ladspa_effect/calf/src/monosynth.cpp +++ b/plugins/ladspa_effect/calf/src/monosynth.cpp @@ -65,7 +65,6 @@ void monosynth_audio_module::activate() { running = false; output_pos = 0; queue_note_on = -1; - stop_count = 0; inertia_pitchbend.set_now(1.f); lfo_bend = 1.0; modwheel_value = 0.f; @@ -329,9 +328,8 @@ void monosynth_audio_module::calculate_buffer_stereo() for (uint32_t i = 0; i < step_size; i++) { float wave1 = buffer[i] * fgain; - float wave2 = phaseshifter.process_ap(wave1); buffer[i] = fgain * filter.process(wave1); - buffer2[i] = fgain * filter2.process(wave2); + buffer2[i] = fgain * filter2.process(wave1); fgain += fgain_delta; } } @@ -349,7 +347,8 @@ void monosynth_audio_module::lookup_waveforms() void monosynth_audio_module::delayed_note_on() { force_fadeout = false; - stop_count = 0; + fadeout.reset_soft(); + fadeout2.reset_soft(); porta_time = 0.f; start_freq = freq; target_freq = freq = 440 * pow(2.0, (queue_note_on - 69) / 12.0); @@ -358,9 +357,11 @@ void monosynth_audio_module::delayed_note_on() fltctl = 1.0 + (queue_vel - 1.0) * *params[par_vel2filter]; set_frequency(); lookup_waveforms(); + bool starting = false; if (!running) { + starting = true; if (legato >= 2) porta_time = -1.f; last_xfade = xfade; @@ -369,15 +370,9 @@ void monosynth_audio_module::delayed_note_on() filter.reset(); filter2.reset(); if (*params[par_lfo1trig] <= 0) - { lfo1.reset(); - lfo1_clock = 0.f; - } if (*params[par_lfo2trig] <= 0) - { lfo2.reset(); - lfo2_clock = 0.f; - } switch((int)*params[par_oscmode]) { case 1: @@ -401,22 +396,20 @@ void monosynth_audio_module::delayed_note_on() default: break; } - envelope1.note_on(); - envelope2.note_on(); running = true; } if (legato >= 2 && !gate) porta_time = -1.f; gate = true; stopping = false; - if (!(legato & 1) || (envelope1.released() && envelope2.released())) { + if (starting || !(legato & 1) || envelope1.released()) envelope1.note_on(); + if (starting || !(legato & 1) || envelope2.released()) envelope2.note_on(); - } envelope1.advance(); envelope2.advance(); queue_note_on = -1; - float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, 0, 0.5+0.5*lfo1.last, 0.5+0.5*lfo2.last}; + 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); } @@ -424,25 +417,25 @@ void monosynth_audio_module::set_sample_rate(uint32_t sr) { srate = sr; crate = sr / step_size; odcr = (float)(1.0 / crate); - phaseshifter.set_ap(1000.f, sr); fgain = 0.f; fgain_delta = 0.f; inertia_cutoff.ramp.set_length(crate / 30); // 1/30s inertia_pitchbend.ramp.set_length(crate / 30); // 1/30s + master.set_sample_rate(sr); } void monosynth_audio_module::calculate_step() { if (queue_note_on != -1) delayed_note_on(); - else if (stopping) + else + if (stopping || !running) { running = false; - dsp::zero(buffer, step_size); - if (is_stereo_filter()) - dsp::zero(buffer2, step_size); envelope1.advance(); envelope2.advance(); + lfo1.get(); + lfo2.get(); return; } lfo1.set_freq(*params[par_lforate], crate); @@ -543,9 +536,9 @@ void monosynth_audio_module::calculate_step() float e2a1 = *params[par_env1toamp]; float e2a2 = *params[par_env2toamp]; if (e2a1 > 0.f) - newfgain *= 1.0 - (1.0 - aenv1) * e2a1; + newfgain *= aenv1; if (e2a2 > 0.f) - newfgain *= 1.0 - (1.0 - aenv2) * e2a2; + newfgain *= aenv2; if (moddest[moddest_attenuation] != 0.f) newfgain *= dsp::clip(1 - moddest[moddest_attenuation] * moddest[moddest_attenuation], 0.f, 1.f); fgain_delta = (newfgain - fgain) * (1.0 / step_size); @@ -569,18 +562,42 @@ void monosynth_audio_module::calculate_step() calculate_buffer_stereo(); break; } - bool no_amp_env = *params[par_env1toamp] <= 0.f && *params[par_env2toamp] <= 0.f; - if ((envelope1.state == adsr::STOP && envelope2.state == adsr::STOP && !gate) || force_fadeout || (envelope1.state == adsr::RELEASE && no_amp_env) || (envelope2.state == adsr::RELEASE && no_amp_env)) + apply_fadeout(); +} + +void monosynth_audio_module::apply_fadeout() +{ + if (fadeout.undoing) { - enum { ramp = step_size * 4 }; - for (int i = 0; i < step_size; i++) - buffer[i] *= (ramp - i - stop_count) * (1.0f / ramp); + fadeout.process(buffer2, step_size); if (is_stereo_filter()) - for (int i = 0; i < step_size; i++) - buffer2[i] *= (ramp - i - stop_count) * (1.0f / ramp); - stop_count += step_size; - if (stop_count >= ramp) - stopping = true; + fadeout2.process(buffer2, step_size); + } + else + { + // stop the sound if the amplitude envelope is not running (if there's any) + bool aenv1_on = *params[par_env1toamp] > 0.f, aenv2_on = *params[par_env2toamp] > 0.f; + + bool do_fadeout = force_fadeout; + + // if there's no amplitude envelope at all, the fadeout starts at key release + if (!aenv1_on && !aenv2_on && !gate) + do_fadeout = true; + // if ENV1 modulates amplitude, the fadeout will start on ENV1 end too + if (aenv1_on && envelope1.state == adsr::STOP) + do_fadeout = true; + // if ENV2 modulates amplitude, the fadeout will start on ENV2 end too + if (aenv2_on && envelope2.state == adsr::STOP) + do_fadeout = true; + + if (do_fadeout || fadeout.undoing || fadeout2.undoing) + { + fadeout.process(buffer, step_size); + if (is_stereo_filter()) + fadeout2.process(buffer2, step_size); + if (fadeout.done) + stopping = true; + } } } @@ -695,38 +712,33 @@ void monosynth_audio_module::params_changed() uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) { - if (!running && queue_note_on == -1) { - for (uint32_t i = 0; i < nsamples / step_size; i++) - { - envelope1.advance(); - envelope2.advance(); - } - return 0; - } uint32_t op = offset; uint32_t op_end = offset + nsamples; + int had_data = 0; while(op < op_end) { - if (output_pos == 0) { - if (running || queue_note_on != -1) - calculate_step(); - else { - envelope1.advance(); - envelope2.advance(); - dsp::zero(buffer, step_size); - } - } + if (output_pos == 0) + calculate_step(); if(op < op_end) { uint32_t ip = output_pos; uint32_t len = std::min(step_size - output_pos, op_end - op); - if (is_stereo_filter()) - for(uint32_t i = 0 ; i < len; i++) { - float vol = master.get(); - outs[0][op + i] = buffer[ip + i] * vol, - outs[1][op + i] = buffer2[ip + i] * vol; - } - else - for(uint32_t i = 0 ; i < len; i++) - outs[0][op + i] = outs[1][op + i] = buffer[ip + i] * master.get(); + if (running) + { + had_data = 3; + if (is_stereo_filter()) + for(uint32_t i = 0 ; i < len; i++) { + float vol = master.get(); + outs[0][op + i] = buffer[ip + i] * vol; + outs[1][op + i] = buffer2[ip + i] * vol; + } + else + for(uint32_t i = 0 ; i < len; i++) + outs[0][op + i] = outs[1][op + i] = buffer[ip + i] * master.get(); + } + else + { + dsp::zero(&outs[0][op], len); + dsp::zero(&outs[1][op], len); + } op += len; output_pos += len; if (output_pos == step_size) @@ -734,6 +746,6 @@ uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uin } } - return 3; + return had_data; }