[SCM] calf/master: + MultiChorus: first attempt at filtered chorus (nothing too innovative, alas)

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:38:49 UTC 2013


The following commit has been merged in the master branch:
commit 840c825affd3870173de681d91dded484e1841db
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Sun Jan 11 22:03:39 2009 +0000

    + MultiChorus: first attempt at filtered chorus (nothing too innovative, alas)

diff --git a/gui/gui-multichorus.xml b/gui/gui-multichorus.xml
index 0e7e8dd..f3068f5 100644
--- a/gui/gui-multichorus.xml
+++ b/gui/gui-multichorus.xml
@@ -62,4 +62,23 @@
             </frame>
         </hbox>
     </if>
+    <frame label="LFO" attach-x="0" attach-y="3" shrink-y="1">
+        <hbox>
+            <vbox border="10">
+                <label param="freq" />
+                <knob param="freq" />
+                <value param="freq" />
+            </vbox>
+            <vbox border="10">
+                <label param="freq2" />
+                <knob param="freq2" />
+                <value param="freq2" />
+            </vbox>
+            <vbox border="10">
+                <label param="q" />
+                <knob param="q" />
+                <value param="q" />
+            </vbox>
+        </hbox>
+    </frame>
 </table>
diff --git a/src/calf/biquad.h b/src/calf/biquad.h
index f98bcc1..aa81c8a 100644
--- a/src/calf/biquad.h
+++ b/src/calf/biquad.h
@@ -47,6 +47,7 @@ class biquad_coeffs
 public:
     // filter coefficients
     Coeff a0, a1, a2, b1, b2;
+    typedef std::complex<double> cfloat;
 
     biquad_coeffs()
     {
@@ -310,7 +311,16 @@ public:
         freq *= 2.0 * M_PI / sr;
         cfloat z = 1.0 / exp(cfloat(0.0, freq));
         
-        return std::abs((cfloat(a0) + double(a1) * z + double(a2) * z*z) / (cfloat(1.0) + double(b1) * z + double(b2) * z*z));
+        return std::abs(h_z(z));
+    }
+    
+    /// Return H(z) the filter's gain at frequency freq
+    /// @param freq   Frequency to look up
+    /// @param sr     Filter sample rate (used to convert frequency to angular frequency)
+    cfloat h_z(const cfloat &z)
+    {
+        
+        return (cfloat(a0) + double(a1) * z + double(a2) * z*z) / (cfloat(1.0) + double(b1) * z + double(b2) * z*z);
     }
     
 };
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index b340218..1b1273e 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -77,7 +77,7 @@ public:
 struct multichorus_metadata: public plugin_metadata<multichorus_metadata>
 {
 public:    
-    enum { par_delay, par_depth, par_rate, par_stereo, par_voices, par_vphase, par_amount, par_dryamount, param_count };
+    enum { par_delay, par_depth, par_rate, par_stereo, par_voices, par_vphase, par_amount, par_dryamount, par_freq, par_freq2, par_q, param_count };
     enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false, require_midi = false };
     PLUGIN_NAME_ID_LABEL("multichorus", "multichorus", "Multi Chorus")
 };
diff --git a/src/calf/modules.h b/src/calf/modules.h
index 16f6e7f..3cc35bb 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -626,6 +626,74 @@ public:
     virtual void control_change(int ctl, int val);
 };
 
+/// Compose two filters in series
+template<class F1, class F2>
+class filter_compose {
+public:
+    typedef std::complex<float> cfloat;
+    F1 f1;
+    F2 f2;
+public:
+    float process(float value) {
+        return f2.process(f1.process(value));
+    }
+    
+    cfloat h_z(const cfloat &z) {
+        return f1.h_z(z) * f2.h_z(z);
+    }
+    
+    /// Return the filter's gain at frequency freq
+    /// @param freq   Frequency to look up
+    /// @param sr     Filter sample rate (used to convert frequency to angular frequency)
+    float freq_gain(float freq, float sr)
+    {
+        typedef std::complex<double> cfloat;
+        freq *= 2.0 * M_PI / sr;
+        cfloat z = 1.0 / exp(cfloat(0.0, freq));
+        
+        return std::abs(h_z(z));
+    }
+    
+    void sanitize() {
+        f1.sanitize();
+        f2.sanitize();
+    }
+};
+
+/// Compose two filters in parallel
+template<class F1, class F2>
+class filter_sum {
+public:
+    typedef std::complex<double> cfloat;
+    F1 f1;
+    F2 f2;
+public:
+    float process(float value) {
+        return f2.process(value) + f1.process(value);
+    }
+    
+    inline cfloat h_z(const cfloat &z) {
+        return f1.h_z(z) + f2.h_z(z);
+    }
+    
+    /// Return the filter's gain at frequency freq
+    /// @param freq   Frequency to look up
+    /// @param sr     Filter sample rate (used to convert frequency to angular frequency)
+    float freq_gain(float freq, float sr)
+    {
+        typedef std::complex<double> cfloat;
+        freq *= 2.0 * M_PI / sr;
+        cfloat z = 1.0 / exp(cfloat(0.0, freq));
+        
+        return std::abs(h_z(z));
+    }
+    
+    void sanitize() {
+        f1.sanitize();
+        f2.sanitize();
+    }
+};
+
 /// A multitap stereo chorus thing - processing
 class multichorus_audio_module: public audio_module<multichorus_metadata>, public line_graph_iface
 {
@@ -634,8 +702,9 @@ public:
     float *outs[out_count];
     float *params[param_count];
     uint32_t srate;
-    dsp::multichorus<float, sine_multi_lfo<float, 8>, 4096> left, right;
+    dsp::multichorus<float, sine_multi_lfo<float, 8>, filter_sum<dsp::biquad_d2<>, dsp::biquad_d2<> >, 4096> left, right;
     float last_r_phase;
+    float cutoff;
     bool is_active;
     
 public:    
@@ -667,6 +736,10 @@ public:
             right.lfo.phase += chorus_phase(r_phase * 4096);
             last_r_phase = r_phase;
         }
+        left.post.f1.set_bp_rbj(*params[par_freq], *params[par_q], srate);
+        left.post.f2.set_bp_rbj(*params[par_freq2], *params[par_q], srate);
+        right.post.f1.copy_coeffs(left.post.f1);
+        right.post.f2.copy_coeffs(left.post.f2);
     }
     uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
         left.process(outs[0] + offset, ins[0] + offset, numsamples);
diff --git a/src/calf/multichorus.h b/src/calf/multichorus.h
index fcd96da..f4ab7ce 100644
--- a/src/calf/multichorus.h
+++ b/src/calf/multichorus.h
@@ -86,13 +86,15 @@ public:
  * Multi-tap chorus without feedback.
  * Perhaps MaxDelay should be a bit longer!
  */
-template<class T, class MultiLfo, int MaxDelay=4096>
+template<class T, class MultiLfo, class Postprocessor, int MaxDelay=4096>
 class multichorus: public chorus_base
 {
 protected:
     simple_delay<MaxDelay,T> delay;
 public:    
     MultiLfo lfo;
+    Postprocessor post;
+public:
     multichorus() {
         rate = 0.63f;
         dry = 0.5f;
@@ -140,17 +142,20 @@ public:
             {
                 int lfo_output = lfo.get_value(v);
                 // 3 = log2(32 >> 2) + 1 because the LFO value is in range of [-65535, 65535] (17 bits)
-                int v = mds + (mdepth * lfo_output >> (3 + 1));
-                int ifv = v >> 16;
+                int dv = mds + (mdepth * lfo_output >> (3 + 1));
+                int ifv = dv >> 16;
                 T fd; // signal from delay's output
-                delay.get_interp(fd, ifv, (v & 0xFFFF)*(1.0/65536.0));
+                delay.get_interp(fd, ifv, (dv & 0xFFFF)*(1.0/65536.0));
                 out += fd;
             }
+            // apply the post filter
+            out = post.process(out);
             T sdry = in * gs_dry.get();
             T swet = out * gs_wet.get() * scale;
             *buf_out++ = sdry + swet;
             lfo.step();
         }
+        post.sanitize();
     }
     float freq_gain(float freq, float sr)
     {
@@ -167,12 +172,13 @@ public:
         {
             int lfo_output = lfo.get_value(v);
             // 3 = log2(32 >> 2) + 1 because the LFO value is in range of [-65535, 65535] (17 bits)
-            int v = mds + (mdepth * lfo_output >> (3 + 1));
-            int fldp = v >> 16;
+            int dv = mds + (mdepth * lfo_output >> (3 + 1));
+            int fldp = dv >> 16;
             cfloat zn = std::pow(z, fldp); // z^-N
-            h += zn + (zn * z - zn) * cfloat(v / 65536.0 - fldp);
+            h += zn + (zn * z - zn) * cfloat(dv / 65536.0 - fldp);
         }
-        // simulate a lerped comb filter - H(z) = 1 / (1 + fb * (lerp(z^-N, z^-(N+1), fracpos))), N = int(pos), fracpos = pos - int(pos)
+        // apply the post filter
+        h *= post.h_z(z);
         // mix with dry signal
         float v = std::abs(cfloat(gs_dry.get_last()) + cfloat(scale * gs_wet.get_last()) * h);
         return v;
diff --git a/src/modules.cpp b/src/modules.cpp
index bd490b6..feef0bc 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -167,6 +167,9 @@ CALF_PORT_PROPS(multichorus) = {
     { 64,         0, 360,  91, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vphase", "Inter-voice phase" },
     { 2,          0,   4,   0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" },
     { 1.0,        0,   4,     0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" },
+    { 100,       10,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq", "Center Frq 1" },
+    { 5000,      10,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Center Frq 2" },
+    { 0.125,  0.125,   8,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "q", "Q" },
 };
 
 CALF_PLUGIN_INFO(multichorus) = { 0x8501, "MultiChorus", "Calf MultiChorus", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "ChorusPlugin" };
diff --git a/src/modules_dsp.cpp b/src/modules_dsp.cpp
index 2447b88..cdec24f 100644
--- a/src/modules_dsp.cpp
+++ b/src/modules_dsp.cpp
@@ -293,9 +293,14 @@ bool multichorus_audio_module::get_graph(int index, int subindex, float *data, i
 {
     if (!is_active)
         return false;
-    if (index == par_delay && subindex < 2) 
+    if (index == par_delay && subindex < 3) 
     {
-        set_channel_color(context, subindex);
+        if (subindex < 2)
+            set_channel_color(context, subindex);
+        else {
+            context->set_source_rgba(0, 1, 0);
+            context->set_line_width(1.0);
+        }
         return ::get_graph(*this, subindex, data, points);
     }
     if (index == par_rate && !subindex) {
@@ -342,6 +347,8 @@ bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos,
 
 float multichorus_audio_module::freq_gain(int subindex, float freq, float srate)
 {
+    if (subindex == 2)
+        return *params[par_amount] * left.post.freq_gain(freq, srate);
     return (subindex ? right : left).freq_gain(freq, srate);                
 }
 

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list