[SCM] calf/master: Cleanups/bugfixes in Monosynth.

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:40:18 UTC 2013


The following commit has been merged in the master branch:
commit 404e1a0861e9b7a79f3b0175f40b427c06945adc
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Tue May 25 00:05:24 2010 +0100

    Cleanups/bugfixes in Monosynth.

diff --git a/src/calf/envelope.h b/src/calf/envelope.h
index 94f87ed..302e4c0 100644
--- a/src/calf/envelope.h
+++ b/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/src/calf/inertia.h b/src/calf/inertia.h
index aca1fbf..d6bbd29 100644
--- a/src/calf/inertia.h
+++ b/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/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 3b7ca83..8cd1c0b 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -45,14 +45,22 @@ public:
     static dsp::waveform_family<MONOSYNTH_WAVE_BITS> *waves;
     dsp::waveform_oscillator<MONOSYNTH_WAVE_BITS> osc1, osc2;
     dsp::triangle_lfo lfo1, lfo2;
-    bool running, stopping, gate, force_fadeout;
+    dsp::biquad_d1_lerp<float> 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<float> phaseshifter;
-    dsp::biquad_d1_lerp<float> filter;
-    dsp::biquad_d1_lerp<float> 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<dsp::exponential_ramp> 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/src/monosynth.cpp b/src/monosynth.cpp
index a2d1248..5120eab 100644
--- a/src/monosynth.cpp
+++ b/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<float>(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;
 }
 

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list