[SCM] calf/master: Replace allpass vibrato in Calf Organ with a simulation of scanner vibrato.

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


The following commit has been merged in the master branch:
commit d1ef2162983bdf24459be71cfd6065416d6aadad
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Sun Jan 16 15:18:54 2011 +0000

    Replace allpass vibrato in Calf Organ with a simulation of scanner vibrato.
    
    This is unfinished: I should add the way to switch to the old mode and to
    choose between scanner topologies (C1/C2/C3/full).

diff --git a/src/calf/organ.h b/src/calf/organ.h
index ac41599..969bd6d 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -174,6 +174,7 @@ public:
     void perc_reset();
 };
 
+/// A simple (and bad) simulation of scanner vibrato based on a series of modulated allpass filters
 class organ_vibrato
 {
 protected:
@@ -186,6 +187,30 @@ public:
     void process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate);
 };
 
+/// A more sophisticated simulation of scanner vibrato. Simulates a line box
+/// and an interpolating scanner. The line box is a series of 18 2nd order
+/// lowpass filters with cutoff frequency ~4kHz, with loss compensation.
+/// The interpolating scanner uses linear interpolation to "slide" between
+/// selected outputs of the line box.
+///
+/// @note
+/// This is a true CPU hog, and it should be optimised some day.
+/// @note
+/// The line box is mono. 36 lowpass filters might be an overkill.
+/// @note 
+/// See also: http://www.jhaible.de/interpolating_scanner_and_scanvib/jh_interpolating_scanner_and_scanvib.html
+/// (though it's a very loose adaptation of that version)
+class scanner_vibrato
+{
+protected:
+    enum { ScannerSize = 18 };
+    float lfo_phase;
+    dsp::biquad_d2<float> scanner[ScannerSize];
+public:
+    void reset();
+    void process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate);
+};
+
 class organ_voice: public dsp::voice, public organ_voice_base {
 protected:    
     enum { Channels = 2, BlockSize = 64, EnvCount = organ_parameters::EnvCount, FilterCount = organ_parameters::FilterCount };
@@ -197,7 +222,7 @@ protected:
     dsp::biquad_d1<float> filterL[2], filterR[2];
     adsr envs[EnvCount];
     dsp::inertia<dsp::linear_ramp> expression;
-    organ_vibrato vibrato;
+    scanner_vibrato vibrato;
     float velocity;
     bool perc_released;
     /// The envelopes have ended and the voice is in final fadeout stage
@@ -260,7 +285,7 @@ public:
 struct drawbar_organ: public dsp::basic_synth, public calf_plugins::organ_enums {
     organ_parameters *parameters;
     percussion_voice percussion;
-    organ_vibrato global_vibrato;
+    scanner_vibrato global_vibrato;
     two_band_eq eq_l, eq_r;
     
      drawbar_organ(organ_parameters *_parameters)
diff --git a/src/metadata.cpp b/src/metadata.cpp
index e6d5d36..b83e43c 100644
--- a/src/metadata.cpp
+++ b/src/metadata.cpp
@@ -987,8 +987,8 @@ CALF_PORT_PROPS(organ) = {
     { 0,  0, organ_enums::ampctl_count - 1,
                               0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg3_amp_ctl", "EG3 To Amp"},
 
-    { 6.6,     0.01,   80,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "vib_rate", "Vib Rate" },
-    { 0.5,        0,    1,    0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_amt", "Vib Mod Amt" },
+    { 6.6,     0.01,  240,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "vib_rate", "Vib Rate" },
+    { 1.0,        0,    1,    0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_amt", "Vib Mod Amt" },
     { 0.5,        0,    1,    0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_wet", "Vib Wet" },
     { 180,        0,  360,    0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vib_phase", "Vib Stereo" },
     { organ_enums::lfomode_global,        0,  organ_enums::lfomode_count - 1,    0, PF_ENUM | PF_CTL_COMBO, organ_vibrato_mode_names, "vib_mode", "Vib Mode" },
diff --git a/src/organ.cpp b/src/organ.cpp
index 3435607..e592e4f 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -611,6 +611,76 @@ void organ_vibrato::process(organ_parameters *parameters, float (*data)[2], unsi
     }
 }
 
+void scanner_vibrato::reset()
+{
+    for (int i = 0; i < ScannerSize; i++)
+        scanner[i].reset();
+    lfo_phase = 0.f;
+}
+
+void scanner_vibrato::process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate)
+{
+    if (!len)
+        return;
+    
+    // I bet the original components of the line box had some tolerance,
+    // hence two different values of cutoff frequency
+    scanner[0].set_lp_rbj(4000, 0.707, sample_rate);
+    scanner[1].set_lp_rbj(4200, 0.707, sample_rate);
+    for (int t = 2; t < ScannerSize; t ++)
+    {
+        scanner[t].copy_coeffs(scanner[t & 1]);
+    }
+    
+    float lfo_phase2 = lfo_phase + parameters->lfo_phase * (1.0 / 360.0);
+    if (lfo_phase2 >= 1.0)
+        lfo_phase2 -= 1.0;
+    float vib_wet = parameters->lfo_wet;
+    float dphase = parameters->lfo_rate / sample_rate;
+    static const int v1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8 };
+    static const int v2[] = { 0, 1, 2, 4, 6, 8, 9, 10, 12 };
+    static const int v3[] = { 0, 1, 3, 6, 11, 12, 15, 17, 18, 18, 18 };
+    const int *vib = v1;
+    static int sums[9];
+    float vibamt = 8 * parameters->lfo_amt;
+    for (unsigned int i = 0; i < len; i++)
+    {
+        float line[ScannerSize + 1];
+        float v0 = (data[i][0] + data[i][1]) * 0.5;
+        
+        line[0] = v0;
+        for (int t = 0; t < ScannerSize; t++)
+            line[t + 1] = scanner[t].process(line[t]) * 1.06;
+        
+        float lfo1 = lfo_phase < 0.5 ? 2 * lfo_phase : 2 - 2 * lfo_phase;
+        float lfo2 = lfo_phase2 < 0.5 ? 2 * lfo_phase2 : 2 - 2 * lfo_phase2;
+        
+        float pos = vibamt * lfo1;
+        int ipos = (int)pos;
+        float vl = lerp(line[vib[ipos]], line[vib[ipos + 1]], pos - ipos);
+        
+        pos = vibamt * lfo2;
+        ipos = (int)pos;
+        float vr = lerp(line[vib[ipos]], line[vib[ipos + 1]], pos - ipos);
+        
+        for (int t = 0; t < 9; t++)
+            sums[t] += fabs(line[vib[t]]);
+
+        lfo_phase += dphase;
+        if (lfo_phase >= 1.0)
+            lfo_phase -= 1.0;
+        lfo_phase2 += dphase;
+        if (lfo_phase2 >= 1.0)
+            lfo_phase2 -= 1.0;
+        
+        data[i][0] += (vl - v0) * vib_wet;
+        data[i][1] += (vr - v0) * vib_wet;
+    }
+    for (int t = 0; t < ScannerSize; t++)
+    {
+        scanner[t].sanitize();
+    }
+}
 //////////////////////////////////////////////////////////////////////////////////////////////////////
 
 void organ_voice::update_pitch()

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list