[SCM] calf/master: + MultiChorus: new effect added (incomplete)

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:37:47 UTC 2013


The following commit has been merged in the master branch:
commit 6a173e85df3d7603712c1eccd386257f712c2c18
Author: Krzysztof Foltman <kfoltman at ubuntu.(none)>
Date:   Mon Oct 27 22:43:11 2008 +0000

    + MultiChorus: new effect added (incomplete)

diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index 334ae1a..9050b5d 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -5,5 +5,5 @@ calf_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h custom_ctl.h \
     delay.h envelope.h fft.h fixed_point.h giface.h gui.h inertia.h \
     jackhost.h lv2_event.h lv2_ui.h lv2_uri_map.h lv2-midiport.h lv2helpers.h lv2wrap.h \
     main_win.h modules.h modules_dev.h modules_small.h modules_synths.h modulelist.h \
-    onepole.h organ.h osc.h osctl.h osctlnet.h plugininfo.h preset.h \
+    multichorus.h onepole.h organ.h osc.h osctl.h osctlnet.h plugininfo.h preset.h \
     preset_gui.h primitives.h synth.h utils.h wave.h
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index bd269d6..1bcf4ae 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -202,11 +202,10 @@ public:
 class chorus_base: public modulation_effect
 {
 protected:
-    int sample_rate, min_delay_samples, mod_depth_samples;
+    int min_delay_samples, mod_depth_samples;
     float min_delay, mod_depth;
     sine_table<int, 4096, 65536> sine;
 public:
-    fixed_point<unsigned int, 20> phase, dphase;
     float get_min_delay() {
         return min_delay;
     }
diff --git a/src/calf/fixed_point.h b/src/calf/fixed_point.h
index 46aaf46..de5f289 100644
--- a/src/calf/fixed_point.h
+++ b/src/calf/fixed_point.h
@@ -60,6 +60,14 @@ public:
         value = (T)(v*one());
     }
     
+    /// Makes an instance from a representation value (ie. same type of value as is used for internal storage and get/set)
+    static inline fixed_point from_base(const T &v) 
+    {
+        fixed_point result;
+        result.value = v;
+        return result;
+    }
+    
     inline T one() {
         return (T)(1) << FracBits;
     }
diff --git a/src/calf/modulelist.h b/src/calf/modulelist.h
index 09a226c..5f7f559 100644
--- a/src/calf/modulelist.h
+++ b/src/calf/modulelist.h
@@ -7,7 +7,7 @@
     PER_MODULE_ITEM(organ, true, "organ")
     PER_MODULE_ITEM(rotary_speaker, false, "rotaryspeaker")
     PER_MODULE_ITEM(phaser, false, "phaser")
-    PER_MODULE_ITEM(subsaw, false, "subsaw")
+    PER_MODULE_ITEM(multichorus, false, "multichorus")
 #undef PER_MODULE_ITEM
 #endif
 #ifdef PER_SMALL_MODULE_ITEM
diff --git a/src/calf/modules.h b/src/calf/modules.h
index f6e3a53..1563abf 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -25,6 +25,7 @@
 #include "biquad.h"
 #include "inertia.h"
 #include "audio_fx.h"
+#include "multichorus.h"
 #include "giface.h"
 
 namespace synth {
@@ -776,94 +777,56 @@ public:
     static const char *get_label() { return "Rotary Speaker"; }
 };
 
-class subsaw
-{
-public:
-    dsp::onepole<float> antidc, amp;
-    float last, state, last_amp;
-    bool cnt;
-public:
-    void set_sample_rate(uint32_t sr)
-    {
-        antidc.set_hp(10.0, sr);
-        amp.set_lp(10.0, sr);
-        state = 0;
-        last = 0.f;
-        last_amp = 0.f;
-        cnt = false;
-    }
-    inline float process(float value)
-    {
-        if (last >= 0.f && value < 0.f) // && 0 == (cnt = !cnt))
-        {
-            if (amp.y1 < state)
-                amp.y1 = state;
-            state = 0;
-        }
-        else
-        {
-            state += fabs(value);
-            last_amp = amp.process(0);
-        }
-        
-        last = value;
-        return antidc.process_hp(0.25f * state);
-    }
-};
-
-// A sub-osc thingy 
-class subsaw_audio_module: public null_audio_module
+// A multitap stereo chorus thing
+class multichorus_audio_module: public null_audio_module
 {
 public:    
-    enum { par_cutoff, param_count };
+    enum { par_delay, par_depth, par_rate, par_stereo, par_amount, param_count };
     enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false };
     float *ins[in_count]; 
     float *outs[out_count];
     float *params[param_count];
     static const char *port_names[];
-    dsp::biquad<float> filter_left, filter_right;
-    dsp::biquad<float> filter2_left, filter2_right;
-    dsp::biquad<float> filter3_left, filter3_right;
-    subsaw state_left, state_right;
     uint32_t srate;
+    dsp::multichorus<float, sine_multi_lfo<float, 6>, 2048> left, right;
+    
     static parameter_properties param_props[];
     static synth::ladspa_plugin_info plugin_info;
 public:    
-    subsaw_audio_module()
+    multichorus_audio_module()
     {
     }
     
     void params_changed()
     {
-        filter_left.set_bp_rbj(*params[par_cutoff], 2, srate);
-        filter_right.copy_coeffs(filter_left);
-        filter2_left.set_lp_rbj(*params[par_cutoff], 0.7, srate);
-        filter2_right.copy_coeffs(filter2_left);
+        // delicious copy-pasta from flanger module - it'd be better to keep it common or something
+        float dry = 1.0;
+        float wet = *params[par_amount];
+        float rate = *params[par_rate];
+        float min_delay = *params[par_delay] / 1000.0;
+        float mod_depth = *params[par_depth] / 1000.0;
+        left.set_dry(dry); right.set_dry(dry);
+        left.set_wet(wet); right.set_wet(wet);
+        left.set_rate(rate); right.set_rate(rate);
+        left.set_min_delay(min_delay); right.set_min_delay(min_delay);
+        left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth);
     }
     void activate() {
         params_changed();
     }
     void set_sample_rate(uint32_t sr) {
         srate = sr;
-        state_left.set_sample_rate(sr);
-        state_right.set_sample_rate(sr);
+        left.setup(sr);
+        right.setup(sr);
     }
     uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
-//        printf("sr=%d cutoff=%f res=%f mode=%f\n", srate, *params[par_cutoff], *params[par_resonance], *params[par_mode]);
-        uint32_t ostate = 3;
-        numsamples += offset;
-        filter3_left.set_lp_rbj(clip<double>(20000.0 * state_left.last_amp, 20.0, srate * 0.48), 3, srate);
-        filter3_right.set_lp_rbj(clip<double>(20000.0 * state_right.last_amp, 20.0, srate * 0.48), 3, srate);
-        while(offset < numsamples) {
-            outs[0][offset] = filter3_left.process_d1(state_left.process(filter2_left.process_d1(filter_left.process_d1(ins[0][offset]))));
-            outs[1][offset] = filter3_right.process_d1(state_right.process(filter2_right.process_d1(filter_right.process_d1(ins[1][offset]))));
-            offset ++;
-        }
-        return ostate;
+        left.process(outs[0] + offset, ins[0] + offset, numsamples);
+        right.process(outs[1] + offset, ins[1] + offset, numsamples);
+        return outputs_mask; // XXXKF allow some delay after input going blank
     }
-    static const char *get_id() { return "subsaw"; }
-    static const char *get_name() { return "subsaw"; }
-    static const char *get_label() { return "SubSaw"; }
+    static const char *get_id() { return "multichorus"; }
+    static const char *get_name() { return "multichorus"; }
+    static const char *get_label() { return "Multi Chorus"; }
 };
 
 extern std::string get_builtin_modules_rdf();
diff --git a/src/calf/multichorus.h b/src/calf/multichorus.h
index 42d64e5..8fccf1b 100644
--- a/src/calf/multichorus.h
+++ b/src/calf/multichorus.h
@@ -23,6 +23,108 @@
 
 #include "audio_fx.h"
 
+namespace dsp {
+
+typedef fixed_point<unsigned int, 20> chorus_phase;
+
+template<class T, uint32_t Voices>
+class sine_multi_lfo
+{
+protected:
+    sine_table<int, 4096, 65536> sine;
+    enum { Multiplier = (65536 / Voices) << 16 };
+    
+public:
+    chorus_phase phase, dphase;
+
+public:
+    inline uint32_t get_voices() const
+    {
+        return Voices;
+    }
+    inline chorus_phase get_phase(uint32_t voice) const {
+        return phase + chorus_phase::from_base(Multiplier * voice);
+    }
+    inline void step() {
+        phase += dphase;
+    }
+    inline T get_scale() const {
+        return 1.0 / Voices;
+    }
+    void reset() {
+        phase = 0.f;
+    }
+};
+
+/**
+ * Multi-tap chorus without feedback.
+ * Perhaps MaxDelay should be a bit longer!
+ */
+template<class T, class MultiLfo, int MaxDelay=512>
+class multichorus: public chorus_base
+{
+protected:
+    simple_delay<MaxDelay,T> delay;
+    MultiLfo lfo;
+public:    
+    multichorus() {
+        rate = 0.63f;
+        dry = 0.5f;
+        wet = 0.5f;
+        min_delay = 0.005f;
+        mod_depth = 0.0025f;
+        setup(44100);
+    }
+    void reset() {
+        delay.reset();
+        lfo.reset();
+    }
+    void set_rate(float rate) {
+        chorus_base::set_rate(rate);
+        lfo.dphase = dphase;
+    }
+    virtual void setup(int sample_rate) {
+        printf("setting sample rate = %d\n", sample_rate);
+        modulation_effect::setup(sample_rate);
+        delay.reset();
+        lfo.reset();
+        set_min_delay(get_min_delay());
+        set_mod_depth(get_mod_depth());
+    }
+    template<class OutIter, class InIter>
+    void process(OutIter buf_out, InIter buf_in, int nsamples) {
+        int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
+        int mdepth = mod_depth_samples;
+        for (int i=0; i<nsamples; i++) {
+            phase += dphase;
+            
+            float in = *buf_in++;
+            
+            delay.put(in);
+            unsigned int nvoices = lfo.get_voices();
+            T out = 0.f;
+            // add up values from all voices, each voice tell its LFO phase and the buffer value is picked at that location
+            for (unsigned int v = 0; v < nvoices; v++)
+            {
+                chorus_phase phase = lfo.get_phase(v);
+                unsigned int ipart = phase.ipart();
+                int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]);
+                int v = mds + (mdepth * lfo >> 6);
+                int ifv = v >> 16;
+                T fd; // signal from delay's output
+                delay.get_interp(fd, ifv, (v & 0xFFFF)*(1.0/65536.0));
+                out += fd;
+            }
+            T sdry = in * gs_dry.get();
+            T swet = out * gs_wet.get() * lfo.get_scale();
+            *buf_out++ = sdry + swet;
+            lfo.step();
+        }
+    }
+};
+
+};
+
 #endif
 
 
diff --git a/src/modules.cpp b/src/modules.cpp
index ffce0c2..41125d8 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -163,13 +163,17 @@ synth::ladspa_plugin_info monosynth_audio_module::plugin_info = { 0x8480, "Monos
 
 ////////////////////////////////////////////////////////////////////////////
 
-const char *subsaw_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
+const char *multichorus_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
 
-parameter_properties subsaw_audio_module::param_props[] = {
-    { 2000,      10,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "cutoff", "Pre Cutoff" },
+parameter_properties multichorus_audio_module::param_props[] = {
+    { 0.1,      0.1, 10,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "min_delay", "Minimum delay" },
+    { 0.5,      0.1, 10,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "mod_depth", "Modulation depth" },
+    { 0.25,    0.01, 20,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "mod_rate", "Modulation rate" },
+    { 0,          0, 360,   9, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" },
+    { 1,          0, 2,     0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" },
 };
 
-synth::ladspa_plugin_info subsaw_audio_module::plugin_info = { 0x8500, "SubSaw", "Calf SubSaw", "Krzysztof Foltman", synth::calf_copyright_info, "UtilityPlugin" };
+synth::ladspa_plugin_info multichorus_audio_module::plugin_info = { 0x8501, "MultiChorus", "Calf MultiChorus", "Krzysztof Foltman", synth::calf_copyright_info, "ChorusPlugin" };
 
 ////////////////////////////////////////////////////////////////////////////
 

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list