[SCM] calf/master: + Organ: new waveforms, ability to select waveforms for each drawbar + Phaser: new effect, up to 12 1st order allpass stages

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


The following commit has been merged in the master branch:
commit 6673230192d416d8a5acce42524f9096c8854b1b
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Sun Mar 23 23:14:17 2008 +0000

    + Organ: new waveforms, ability to select waveforms for each drawbar
    + Phaser: new effect, up to 12 1st order allpass stages
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@135 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index fad34aa..26ed93c 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -41,18 +41,12 @@ public:
     virtual ~audio_effect() {}
 };
 
-/**
- * Base class for chorus and flanger. Wouldn't be needed if it wasn't
- * for odd behaviour of GCC when deriving templates from template
- * base classes (not seeing fields from base classes!).
- */
-class chorus_base: public audio_effect
+class modulation_effect: public audio_effect
 {
 protected:
-    int sample_rate, min_delay_samples, mod_depth_samples;
-    float rate, wet, dry, min_delay, mod_depth, odsr;
+    int sample_rate;
+    float rate, wet, dry, odsr;
     gain_smoothing gs_wet, gs_dry;
-    sine_table<int, 4096, 65536> sine;
 public:
     fixed_point<unsigned int, 20> phase, dphase;
     float get_rate() {
@@ -74,8 +68,133 @@ public:
     }
     void set_dry(float dry) {
         this->dry = dry;
-        gs_dry.set_inertia(wet);
+        gs_dry.set_inertia(dry);
+    }
+    void reset_phase(float req_phase)
+    {
+        phase = req_phase * 4096.0;
+    }
+    void inc_phase(float req_phase)
+    {
+        phase += fixed_point<unsigned int, 20>(req_phase * 4096.0);
+    }
+    void setup(int sample_rate)
+    {
+        this->sample_rate = sample_rate;
+        this->odsr = 1.0 / sample_rate;
+        phase = 0;
+        set_rate(get_rate());
+    }
+};
+
+/**
+ * A monophonic phaser. If you want stereo, combine two :)
+ * Also, gave up on using template args for signal type.
+ */
+template<int MaxStages>
+class simple_phaser: public modulation_effect
+{
+protected:
+    float base_frq, mod_depth, resonance, fb;
+    float state;
+    int cnt, stages;
+    dsp::onepole<float, float> stage1;
+    float x1[MaxStages], y1[MaxStages];
+public:
+    float get_base_frq() {
+        return base_frq;
+    }
+    void set_base_frq(float _base_frq) {
+        base_frq = _base_frq;
+    }
+    int get_stages() {
+        return stages;
+    }
+    void set_stages(int _stages) {
+        if (_stages > stages)
+        {
+            for (int i = stages; i < _stages; i++)
+            {
+                x1[i] = x1[stages-1];
+                y1[i] = y1[stages-1];
+            }
+        }
+        stages = _stages;
+    }
+    float get_mod_depth() {
+        return mod_depth;
+    }
+    void set_mod_depth(float _mod_depth) {
+        mod_depth = _mod_depth;
+    }
+    float get_fb() {
+        return fb;
+    }
+    void set_fb(float fb) {
+        this->fb = fb;
+    }
+    virtual void setup(int sample_rate) {
+        modulation_effect::setup(sample_rate);
+        reset();
+    }
+    void reset()
+    {
+        cnt = 0;
+        state = 0;
+        for (int i = 0; i < MaxStages; i++)
+            x1[i] = y1[i] = 0;
+        control_step();
+    }
+    inline void control_step()
+    {
+        cnt = 0;
+        int v = phase.get() + 0x40000000;
+        int sign = v >> 31;
+        v ^= sign;
+        // triangle wave, range from 0 to INT_MAX
+        double vf = (double)((v >> 16) * (1.0 / 16384.0) - 1);
+        
+        float freq = base_frq * pow(2.0, vf * mod_depth / 1200.0);
+        freq = dsp::clip<float>(freq, 10.0, 0.49 * sample_rate);
+        stage1.set_ap_w(freq * (M_PI / 2.0) * odsr);
+        phase += dphase * 16;
+    }
+    void process(float *buf_out, float *buf_in, int nsamples) {
+        for (int i=0; i<nsamples; i++) {
+            cnt++;
+            if (cnt == 16)
+                control_step();
+            float in = *buf_in++;
+            float fd = in + state * fb;
+            for (int j = 0; j < stages; j++)
+                fd = stage1.process_ap(fd, x1[j], y1[j]);
+            state = fd;
+            
+            float sdry = in * gs_dry.get();
+            float swet = fd * gs_wet.get();
+            *buf_out++ = sdry + swet;
+        }
+        for (int i = 0; i < stages; i++)
+        {
+            dsp::sanitize(x1[i]);
+            dsp::sanitize(y1[i]);
+        }
     }
+};
+
+/**
+ * Base class for chorus and flanger. Wouldn't be needed if it wasn't
+ * for odd behaviour of GCC when deriving templates from template
+ * base classes (not seeing fields from base classes!).
+ */
+class chorus_base: public modulation_effect
+{
+protected:
+    int sample_rate, 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;
     }
@@ -91,14 +210,6 @@ public:
         // 128 because it's then multiplied by (hopefully) a value of 32768..-32767
         this->mod_depth_samples = (int)(mod_depth * 32.0 * sample_rate);
     }
-    void reset_phase(float req_phase)
-    {
-        phase = req_phase * 4096.0;
-    }
-    void inc_phase(float req_phase)
-    {
-        phase += fixed_point<unsigned int, 20>(req_phase * 4096.0);
-    }
 };
 
 /**
@@ -123,11 +234,8 @@ public:
         delay.reset();
     }
     virtual void setup(int sample_rate) {
-        this->sample_rate = sample_rate;
-        this->odsr = 1.0 / sample_rate;
+        modulation_effect::setup(sample_rate);
         delay.reset();
-        phase = 0;
-        set_rate(get_rate());
         set_min_delay(get_min_delay());
         set_mod_depth(get_mod_depth());
     }
diff --git a/src/calf/modules.h b/src/calf/modules.h
index 720c020..524cbaa 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -146,6 +146,80 @@ public:
     static const char *get_label() { return "Flanger"; }
 };
 
+class phaser_audio_module: public null_audio_module
+{
+public:
+    enum { par_freq, par_depth, par_rate, par_fb, par_stages, par_stereo, par_reset, par_amount, param_count };
+    enum { in_count = 2, out_count = 2, support_midi = false, rt_capable = true };
+    static const char *port_names[];
+    float *ins[in_count]; 
+    float *outs[out_count];
+    float *params[param_count];
+    uint32_t srate;
+    bool clear_reset;
+    float last_r_phase;
+    dsp::simple_phaser<12> left, right;
+    static parameter_properties param_props[];
+    void set_sample_rate(uint32_t sr) {
+        srate = sr;
+        left.setup(sr);
+        right.setup(sr);
+    }
+    void params_changed() {
+        float dry = 1.0;
+        float wet = *params[par_amount];
+        float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]);
+        float base_frq = *params[par_freq];
+        float mod_depth = *params[par_depth];
+        float fb = *params[par_fb];
+        int stages = (int)*params[par_stages];
+        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_base_frq(base_frq); right.set_base_frq(base_frq);
+        left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth);
+        left.set_fb(fb); right.set_fb(fb);
+        left.set_stages(stages); right.set_stages(stages);
+        float r_phase = *params[par_stereo] * (1.f / 360.f);
+        clear_reset = false;
+        if (*params[par_reset] >= 0.5) {
+            clear_reset = true;
+            left.reset_phase(0.f);
+            right.reset_phase(r_phase);
+        } else {
+            if (fabs(r_phase - last_r_phase) > 0.0001f) {
+                right.phase = left.phase;
+                right.inc_phase(r_phase);
+                last_r_phase = r_phase;
+            }
+        }
+    }
+    void params_reset()
+    {
+        if (clear_reset) {
+            *params[par_reset] = 0.f;
+            clear_reset = false;
+        }
+    }
+    void activate() {
+        left.reset();
+        right.reset();
+        last_r_phase = *params[par_stereo] * (1.f / 360.f);
+        left.reset_phase(0.f);
+        right.reset_phase(last_r_phase);
+    }
+    void deactivate() {
+    }
+    uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+        left.process(outs[0] + offset, ins[0] + offset, nsamples);
+        right.process(outs[1] + offset, ins[1] + offset, nsamples);
+        return outputs_mask; // XXXKF allow some delay after input going blank
+    }
+    static const char *get_name() { return "phaser"; }
+    static const char *get_id() { return "phaser"; }
+    static const char *get_label() { return "Phaser"; }
+};
+
 class reverb_audio_module: public null_audio_module
 {
 public:    
diff --git a/src/calf/onepole.h b/src/calf/onepole.h
index 3b794fb..790b318 100644
--- a/src/calf/onepole.h
+++ b/src/calf/onepole.h
@@ -37,6 +37,7 @@ public:
     T x1, y1;
     Coeff a0, a1, b1;
     
+    /// Set coefficients for a lowpass filter
     void set_lp(float fc, float sr)
     {
         //   x   x
@@ -47,6 +48,7 @@ public:
 		b1 = (x-1)*q;
     }
     
+    /// Set coefficients for an allpass filter
     void set_ap(float fc, float sr)
     {
         // x-1  x+1
@@ -57,6 +59,19 @@ public:
         a1 = 1;
     }
     
+    /// Set coefficients for an allpass filter, using omega instead of fc and sr
+    /// omega = (PI / 2) * fc / sr
+    void set_ap_w(float w)
+    {
+        // x-1  x+1
+        // x+1  x-1
+		Coeff x = tan (w);
+		Coeff q = 1/(1+x);
+		b1 = a0 = (x-1)*q;
+        a1 = 1;
+    }
+    
+    /// Set coefficients for a highpass filter
     void set_hp(float fc, float sr)
     {
         //   x   -x
@@ -68,6 +83,7 @@ public:
 		b1 = (x-1)*q;
     }
     
+    /// Process one sample
     inline T process(T in)
     {
         T out = in * a0 + x1 * a1 - y1 * b1;
@@ -76,6 +92,7 @@ public:
         return out;
     }
     
+    /// Process one sample, assuming it's a lowpass filter (optimized special case)
     inline T process_lp(T in)
     {
         T out = (in + x1) * a0 - y1 * b1;
@@ -84,6 +101,7 @@ public:
         return out;
     }
 
+    /// Process one sample, assuming it's a highpass filter (optimized special case)
     inline T process_hp(T in)
     {
         T out = (in - x1) * a0 - y1 * b1;
@@ -92,6 +110,7 @@ public:
         return out;
     }
     
+    /// Process one sample, assuming it's an allpass filter (optimized special case)
     inline T process_ap(T in)
     {
         T out = (in - y1) * a0 + x1;
@@ -100,6 +119,15 @@ public:
         return out;
     }
     
+    /// Process one sample using external state variables
+    inline T process_ap(T in, float &x1, float &y1)
+    {
+        T out = (in - y1) * a0 + x1;
+        x1 = in;
+        y1 = out;
+        return out;
+    }
+    
     inline void sanitize() 
     {
         dsp::sanitize(x1);
@@ -111,6 +139,14 @@ public:
         dsp::zero(x1);
         dsp::zero(y1);
     }
+    
+    template<class U>
+    inline void copy_coeffs(const onepole<U> &src)
+    {
+        a0 = src.a0;
+        a1 = src.a1;
+        b1 = src.b1;
+    }
 };
 
 };
diff --git a/src/calf/organ.h b/src/calf/organ.h
index 594de2d..5cc0296 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -49,7 +49,7 @@ struct organ_parameters {
 class organ_voice_base
 {
 protected:
-    enum { wave_sine, wave_pulse, wave_stretchsine, wave_count };
+    enum { wave_sine, wave_pulse, wave_sinepl1, wave_sinepl2, wave_sinepl3, wave_saw, wave_sqr, wave_ssaw, wave_ssqr, wave_count };
     static waveform_family<ORGAN_WAVE_BITS> waves[wave_count];
     // dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
     dsp::fixed_point<int, 20> phase, dphase;
diff --git a/src/calf/osc.h b/src/calf/osc.h
index 4f89a6f..b124d55 100644
--- a/src/calf/osc.h
+++ b/src/calf/osc.h
@@ -65,6 +65,14 @@ struct bandlimiter
         fft.calculate(data, spectrum, false);
     }
     
+    void compute_waveform(float output[SIZE])
+    {
+        std::complex<float> data[SIZE];
+        fft.calculate(spectrum, data, true);
+        for (int i = 0; i < SIZE; i++)
+            output[i] = data[i].real();
+    }
+    
     /// remove DC offset of the spectrum (it usually does more harm than good!)
     void remove_dc()
     {
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index b62ee6b..0ba0ad2 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -60,6 +60,8 @@ jack_host_base *synth::create_jack_host(const char *effect_name)
         return new jack_host<organ_audio_module>();
     else if (!strcasecmp(effect_name, "rotaryspeaker"))
         return new jack_host<rotary_speaker_audio_module>();
+    else if (!strcasecmp(effect_name, "phaser"))
+        return new jack_host<phaser_audio_module>();
 #ifdef ENABLE_EXPERIMENTAL
 #endif
     else
@@ -191,10 +193,9 @@ void host_session::open()
         jack_host_base *jh = create_jack_host(plugin_names[i].c_str());
         if (!jh) {
 #ifdef ENABLE_EXPERIMENTAL
-            throw audio_exception("Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth, organ, rotaryspeaker\n");
 #else
-            throw audio_exception("Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth\n");
 #endif
+            throw audio_exception("Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth, organ, rotaryspeaker, phaser\n");
         }
         jh->open(&client);
         
diff --git a/src/modules.cpp b/src/modules.cpp
index 18dea2d..5e6907c 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -67,6 +67,25 @@ ALL_WRAPPERS(flanger)
 
 ////////////////////////////////////////////////////////////////////////////
 
+const char *phaser_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
+
+parameter_properties phaser_audio_module::param_props[] = {
+    { 1000,      20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "base_freq", "Center Freq" },
+    { 4000,       0, 10800,  0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, 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.25,   -0.99, 0.99,  0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "feedback", "Feedback" },
+    { 6,          1, 12,   12, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "stages", "# Stages" },
+    { 180,        0, 360,  10, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" },
+    { 0,          0, 1,     2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" },
+    { 1,          0, 2,     0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "amount", "Amount" },
+};
+
+static synth::ladspa_info phaser_info = { 0x847d, "phaser", "Calf Phaser", "Krzysztof Foltman", copyright, "PhaserPlugin" };
+
+ALL_WRAPPERS(phaser)
+
+////////////////////////////////////////////////////////////////////////////
+
 const char *reverb_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
 
 const char *reverb_room_sizes[] = { "Small", "Medium", "Large", "Tunnel-like" };
@@ -172,6 +191,7 @@ const LV2_Descriptor *lv2_descriptor(uint32_t index)
         case 4: return &::lv2_monosynth.descriptor;
         case 5: return &::lv2_organ.descriptor;
         case 6: return &::lv2_rotary_speaker.descriptor;
+        case 7: return &::lv2_phaser.descriptor;
 #ifdef ENABLE_EXPERIMENTAL
 #endif
         default: return NULL;
@@ -192,6 +212,7 @@ const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
         case 2: return &::ladspa_reverb.descriptor;
         case 3: return &::ladspa_vintage_delay.descriptor;
         case 4: return &::ladspa_rotary_speaker.descriptor;
+        case 5: return &::ladspa_phaser.descriptor;
 #ifdef ENABLE_EXPERIMENTAL
 #endif
         default: return NULL;
@@ -213,6 +234,7 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long Index)
         case 4: return &::ladspa_vintage_delay.dssi_descriptor;
         case 5: return &::ladspa_organ.dssi_descriptor;
         case 6: return &::ladspa_rotary_speaker.dssi_descriptor;
+        case 7: return &::ladspa_phaser.dssi_descriptor;
 #ifdef ENABLE_EXPERIMENTAL
 #endif
         default: return NULL;
@@ -259,4 +281,5 @@ void synth::get_all_plugins(std::vector<giface_plugin_info> &plugins)
     plugins.push_back(create_plugin_info<vintage_delay_audio_module>(vintage_delay_info));
     plugins.push_back(create_plugin_info<organ_audio_module>(organ_info));
     plugins.push_back(create_plugin_info<rotary_speaker_audio_module>(rotary_speaker_info));
+    plugins.push_back(create_plugin_info<phaser_audio_module>(phaser_info));
 }
diff --git a/src/organ.cpp b/src/organ.cpp
index 08f88d1..5ff5685 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -62,60 +62,69 @@ const char *organ_audio_module::get_gui_xml()
                 "<value param=\"master\"/>"
             "</vbox>"
         "</hbox>"
-        "<table rows=\"5\" cols=\"9\">"
+        "<table rows=\"6\" cols=\"9\">"
             "<label  attach-x=\"0\" attach-y=\"0\" param=\"h1\"/>"
             "<vscale attach-x=\"0\" attach-y=\"1\" param=\"h1\"/>"
             "<value  attach-x=\"0\" attach-y=\"2\" param=\"h1\"/>"
             "<knob   attach-x=\"0\" attach-y=\"3\" param=\"f1\"/>"
             "<value  attach-x=\"0\" attach-y=\"4\" param=\"f1\"/>"
+            "<combo  attach-x=\"0\" attach-y=\"5\" param=\"w1\"/>"
     
             "<label  attach-x=\"1\" attach-y=\"0\" param=\"h3\"/>"
             "<vscale attach-x=\"1\" attach-y=\"1\" param=\"h3\"/>"
             "<value  attach-x=\"1\" attach-y=\"2\" param=\"h3\"/>"
             "<knob   attach-x=\"1\" attach-y=\"3\" param=\"f2\"/>"
             "<value  attach-x=\"1\" attach-y=\"4\" param=\"f2\"/>"
+            "<combo  attach-x=\"1\" attach-y=\"5\" param=\"w2\"/>"
     
             "<label  attach-x=\"2\" attach-y=\"0\" param=\"h2\"/>"
             "<vscale attach-x=\"2\" attach-y=\"1\" param=\"h2\"/>"
             "<value  attach-x=\"2\" attach-y=\"2\" param=\"h2\"/>"
             "<knob   attach-x=\"2\" attach-y=\"3\" param=\"f3\"/>"
             "<value  attach-x=\"2\" attach-y=\"4\" param=\"f3\"/>"
+            "<combo  attach-x=\"2\" attach-y=\"5\" param=\"w3\"/>"
     
             "<label  attach-x=\"3\" attach-y=\"0\" param=\"h4\"/>"
             "<vscale attach-x=\"3\" attach-y=\"1\" param=\"h4\"/>"
             "<value  attach-x=\"3\" attach-y=\"2\" param=\"h4\"/>"
             "<knob   attach-x=\"3\" attach-y=\"3\" param=\"f4\"/>"
             "<value  attach-x=\"3\" attach-y=\"4\" param=\"f4\"/>"
+            "<combo  attach-x=\"3\" attach-y=\"5\" param=\"w4\"/>"
 
             "<label  attach-x=\"4\" attach-y=\"0\" param=\"h6\"/>"
             "<vscale attach-x=\"4\" attach-y=\"1\" param=\"h6\"/>"
             "<value  attach-x=\"4\" attach-y=\"2\" param=\"h6\"/>"
             "<knob   attach-x=\"4\" attach-y=\"3\" param=\"f5\"/>"
             "<value  attach-x=\"4\" attach-y=\"4\" param=\"f5\"/>"
+            "<combo  attach-x=\"4\" attach-y=\"5\" param=\"w5\"/>"
     
             "<label  attach-x=\"5\" attach-y=\"0\" param=\"h8\"/>"
             "<vscale attach-x=\"5\" attach-y=\"1\" param=\"h8\"/>"
             "<value  attach-x=\"5\" attach-y=\"2\" param=\"h8\"/>"
             "<knob   attach-x=\"5\" attach-y=\"3\" param=\"f6\"/>"
             "<value  attach-x=\"5\" attach-y=\"4\" param=\"f6\"/>"
+            "<combo  attach-x=\"5\" attach-y=\"5\" param=\"w6\"/>"
 
             "<label  attach-x=\"6\" attach-y=\"0\" param=\"h10\"/>"
             "<vscale attach-x=\"6\" attach-y=\"1\" param=\"h10\"/>"
             "<value  attach-x=\"6\" attach-y=\"2\" param=\"h10\"/>"
             "<knob   attach-x=\"6\" attach-y=\"3\" param=\"f7\"/>"
             "<value  attach-x=\"6\" attach-y=\"4\" param=\"f7\"/>"
+            "<combo  attach-x=\"6\" attach-y=\"5\" param=\"w7\"/>"
 
             "<label  attach-x=\"7\" attach-y=\"0\" param=\"h12\"/>"
             "<vscale attach-x=\"7\" attach-y=\"1\" param=\"h12\"/>"
             "<value  attach-x=\"7\" attach-y=\"2\" param=\"h12\"/>"
             "<knob   attach-x=\"7\" attach-y=\"3\" param=\"f8\"/>"
             "<value  attach-x=\"7\" attach-y=\"4\" param=\"f8\"/>"
+            "<combo  attach-x=\"7\" attach-y=\"5\" param=\"w8\"/>"
 
             "<label  attach-x=\"8\" attach-y=\"0\" param=\"h16\"/>"
             "<vscale attach-x=\"8\" attach-y=\"1\" param=\"h16\"/>"
             "<value  attach-x=\"8\" attach-y=\"2\" param=\"h16\"/>"
             "<knob   attach-x=\"8\" attach-y=\"3\" param=\"f9\"/>"
             "<value  attach-x=\"8\" attach-y=\"4\" param=\"f9\"/>"
+            "<combo  attach-x=\"8\" attach-y=\"5\" param=\"w9\"/>"
         "</table>"
     "</vbox>"
     ;
@@ -125,6 +134,8 @@ const char *organ_audio_module::port_names[] = {"Out L", "Out R"};
 
 const char *organ_percussion_harmonic_names[] = { "2nd", "3rd" };
 
+const char *organ_wave_names[] = { "Sin", "Pls", "S+1", "S+2", "S+3", "Saw", "Sqr", "SSaw", "SSqr" };
+
 parameter_properties organ_audio_module::param_props[] = {
     { 8,       0,  8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h1", "16'" },
     { 8,       0,  8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h3", "5 1/3'" },
@@ -136,25 +147,25 @@ parameter_properties organ_audio_module::param_props[] = {
     { 0,       0,  8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h12", "1 1/3'" },
     { 8,       0,  8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h16", "1'" },
 
-    { 1,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f1", "Freq 1" },
-    { 3,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f2", "Freq 2" },
-    { 2,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f3", "Freq 3" },
-    { 4,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f4", "Freq 4" },
-    { 6,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f5", "Freq 5" },
-    { 8,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f6", "Freq 6" },
-    { 10,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f7", "Freq 7" },
-    { 12,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f8", "Freq 8" },
-    { 16,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f9", "Freq 9" },
-
-    { 2,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w1", "Wave 1" },
-    { 2,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w2", "Wave 2" },
-    { 1,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w3", "Wave 3" },
-    { 1,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w4", "Wave 4" },
-    { 0,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w5", "Wave 5" },
-    { 0,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w6", "Wave 6" },
-    { 0,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w7", "Wave 7" },
-    { 0,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w8", "Wave 8" },
-    { 0,       0,  8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w9", "Wave 9" },
+    { 1,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f1", "Freq 1" },
+    { 3,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f2", "Freq 2" },
+    { 2,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f3", "Freq 3" },
+    { 4,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f4", "Freq 4" },
+    { 6,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f5", "Freq 5" },
+    { 8,       1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f6", "Freq 6" },
+    { 10,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f7", "Freq 7" },
+    { 12,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f8", "Freq 8" },
+    { 16,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f9", "Freq 9" },
+
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w1", "Wave 1" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w2", "Wave 2" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w3", "Wave 3" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w4", "Wave 4" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w5", "Wave 5" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w6", "Wave 6" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w7", "Wave 7" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w8", "Wave 8" },
+    { 0,       0,  8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w9", "Wave 9" },
 
     { 1,         0,  1, 2, PF_BOOL | PF_CTL_TOGGLE, NULL, "foldover", "Foldover" },
     { 200,         10,  3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_decay", "Perc. decay" },
@@ -194,7 +205,43 @@ organ_voice_base::organ_voice_base(organ_parameters *_parameters)
         normalize_waveform(tmp, ORGAN_WAVE_SIZE);
         waves[wave_pulse].make(bl, tmp);
         for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = i < (ORGAN_WAVE_SIZE / 2) ? sin(i * 2 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
+        waves[wave_sinepl1].make(bl, tmp);
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = i < (ORGAN_WAVE_SIZE / 3) ? sin(i * 3 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
+        waves[wave_sinepl2].make(bl, tmp);
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
             tmp[i] = i < (ORGAN_WAVE_SIZE / 4) ? sin(i * 4 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
-        waves[wave_stretchsine].make(bl, tmp);
+        waves[wave_sinepl3].make(bl, tmp);
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = (i < (ORGAN_WAVE_SIZE / 2)) ? 1 : -1;
+        normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+        waves[wave_sqr].make(bl, tmp);
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = -1 + (i * 2.0 / ORGAN_WAVE_SIZE);
+        normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+        waves[wave_saw].make(bl, tmp);
+        
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = (i < (ORGAN_WAVE_SIZE / 2)) ? 1 : -1;
+        bl.compute_spectrum(tmp);
+        for (int i = 1; i <= ORGAN_WAVE_SIZE / 2; i++) {
+            bl.spectrum[i] *= 1.0 / sqrt(i);
+            bl.spectrum[ORGAN_WAVE_SIZE - i] *= 1.0 / sqrt(i);
+        }
+        bl.compute_waveform(tmp);
+        normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+        waves[wave_ssqr].make(bl, tmp);
+        
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = -1 + (i * 2.0 / ORGAN_WAVE_SIZE);
+        bl.compute_spectrum(tmp);
+        for (int i = 1; i <= ORGAN_WAVE_SIZE / 2; i++) {
+            bl.spectrum[i] *= 1.0 / sqrt(i);
+            bl.spectrum[ORGAN_WAVE_SIZE - i] *= 1.0 / sqrt(i);
+        }
+        bl.compute_waveform(tmp);
+        normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+        waves[wave_ssaw].make(bl, tmp);
     }
 }

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list