[SCM] calf/master: + Organ: ruined perfectly good tonewheel organ wannabe by adding settable drawbar frequencies and more waveforms (including Farfisa-esque pulse), unfortunately there is no UI for setting waveforms yet + Monosynth: normalize -> normalize_waveform, made a global static function

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 9ec053dbaf498ac9630c98cfdb2b743134ce99f0
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Thu Mar 20 00:00:49 2008 +0000

    + Organ: ruined perfectly good tonewheel organ wannabe by adding settable drawbar frequencies and more waveforms (including Farfisa-esque pulse), unfortunately there is no UI for setting waveforms yet
    + Monosynth: normalize -> normalize_waveform, made a global static function
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@134 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 6998d97..4b4cf84 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -31,7 +31,7 @@
 
 namespace synth {
 
-#define MONOSYNTH_WAVE_SIZE 12
+#define MONOSYNTH_WAVE_BITS 12
     
 /// Monosynth-in-making. Parameters may change at any point, so don't make songs with it!
 /// It lacks inertia for parameters, even for those that really need it.
@@ -48,8 +48,8 @@ public:
     float *outs[out_count];
     float *params[param_count];
     uint32_t srate, crate;
-    static waveform_family<MONOSYNTH_WAVE_SIZE> waves[wave_count];
-    waveform_oscillator<MONOSYNTH_WAVE_SIZE> osc1, osc2;
+    static waveform_family<MONOSYNTH_WAVE_BITS> waves[wave_count];
+    waveform_oscillator<MONOSYNTH_WAVE_BITS> osc1, osc2;
     bool running, stopping, gate;
     int last_key;
     
@@ -196,7 +196,11 @@ public:
     using drawbar_organ::note_on;
     using drawbar_organ::note_off;
     using drawbar_organ::control_change;
-    enum { par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9, par_foldover,
+    enum { 
+        par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9, 
+        par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9, 
+        par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9, 
+        par_foldover,
         par_percdecay, par_perclevel, par_percharm, par_master, param_count };
     enum { in_count = 0, out_count = 2, support_midi = true, rt_capable = true };
     static const char *port_names[];
diff --git a/src/calf/organ.h b/src/calf/organ.h
index 9498c3b..594de2d 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -29,6 +29,8 @@ namespace synth
 
 struct organ_parameters {
     float drawbars[9];
+    float harmonics[9];
+    float waveforms[9];
     float foldover;
     float percussion_time;
     float percussion_level;
@@ -41,16 +43,24 @@ struct organ_parameters {
     inline int get_harmonic() { return dsp::fastf2i_drm(harmonic); }
 };
 
+#define ORGAN_WAVE_BITS 12
+#define ORGAN_WAVE_SIZE 4096
+
 class organ_voice_base
 {
 protected:
-    dsp::sine_table<float, 4096, 1> sine_wave;
+    enum { wave_sine, wave_pulse, wave_stretchsine, 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;
     int note;
     dsp::decay amp;
+    organ_parameters *parameters;
 
-    inline float sine(dsp::fixed_point<int, 20> ph) {
-        return ph.lerp_table_lookup_float(sine_wave.data);
+    organ_voice_base(organ_parameters *_parameters);
+    
+    inline float wave(float *data, dsp::fixed_point<int, 20> ph) {
+        return ph.lerp_table_lookup_float(data);
     }
 };
 
@@ -59,11 +69,10 @@ protected:
     bool released;
     int h4, h6, h8, h12, h16;
     dsp::fixed_point<int, 3> h10;
-    organ_parameters *parameters;
 
 public:
     organ_voice(organ_parameters *_parameters)
-    : parameters(_parameters) {
+    : organ_voice_base(_parameters) {
     }
 
     void reset() {
@@ -108,22 +117,45 @@ public:
         if (!amp.get_active())
             dsp::zero(buf[0], nsamples);
         else {
-            for (int i=0; i<nsamples; i++) {
-//                float osc = 0.2*sine(phase)+0.1*sine(4*phase)+0.08*sine(12*phase)+0.08*sine(16*phase);
-                float *drawbars = parameters->drawbars;
-                float osc = 
-                    drawbars[0]*sine(phase)+
-                    drawbars[1]*sine(3*phase)+
-                    drawbars[2]*sine(2*phase)+
-                    drawbars[3]*sine(h4*phase)+
-                    drawbars[4]*sine(h6*phase)+
-                    drawbars[5]*sine(h8*phase)+
-                    drawbars[6]*sine(h10*phase)+
-                    drawbars[7]*sine(h12*phase)+
-                    drawbars[8]*sine(h16*phase);
-                buf[0][i] += osc*amp.get();
-                if (released) amp.age_lin((1.0/44100.0)/0.03,0.0);
-                phase += dphase;
+            float tmp[256], *sig;
+            if (released)
+            {
+                sig = tmp;            
+                for (int i=0; i<nsamples; i++)
+                    tmp[i] = 0;
+            }
+            else
+                sig = buf[0];
+            dsp::fixed_point<int, 20> tphase, tdphase;
+            for (int h = 0; h < 9; h++)
+            {
+                float *data;
+                dsp::fixed_point<int, 24> hm = dsp::fixed_point<int, 24>(parameters->harmonics[h]);
+                int waveid = (int)parameters->waveforms[h];
+                if (waveid < 0 || waveid >= wave_count)
+                    waveid = 0;
+                do {
+                    data = waves[waveid].get_level((dphase * hm).get());
+                    if (data)
+                        break;
+                    hm.set(hm.get() >> 1);
+                } while(1);
+                tphase = phase * hm;
+                tdphase = dphase * hm;
+                float amp = parameters->drawbars[h];
+                for (int i=0; i<nsamples; i++) {
+    //                float osc = 0.2*sine(phase)+0.1*sine(4*phase)+0.08*sine(12*phase)+0.08*sine(16*phase);
+                    sig[i] += wave(data, tphase)*amp;
+                    tphase += tdphase;
+                }
+            }
+            phase += dphase * nsamples;
+            if (released)
+            {
+                for (int i=0; i<nsamples; i++) {
+                    buf[0][i] += tmp[i] * amp.get();
+                    amp.age_lin((1.0/44100.0)/0.03,0.0);
+                }
             }
         }
     }
@@ -138,13 +170,11 @@ public:
 /// Not a true voice, just something with similar-ish interface.
 class percussion_voice: public organ_voice_base {
 public:
-    organ_parameters *parameters;
     int sample_rate;
 
     percussion_voice(organ_parameters *_parameters)
+    : organ_voice_base(_parameters)
     {
-        parameters = _parameters;
-        note = -1;
     }
     void reset() {
         phase = 0;
@@ -171,8 +201,9 @@ public:
         float level = parameters->percussion_level * (8 * 9);
         // XXXKF the decay needs work!
         double age_const = parameters->perc_decay_const;
+        float *data = waves[wave_sine].begin()->second;
         for (int i = 0; i < nsamples; i++) {
-            float osc = level * sine(harmonic * phase);
+            float osc = level * wave(data, harmonic * phase);
             buf[i] += osc * amp.get();
             amp.age_exp(age_const, 1.0 / 32768.0);
             phase += dphase;
diff --git a/src/calf/osc.h b/src/calf/osc.h
index 6e85998..4f89a6f 100644
--- a/src/calf/osc.h
+++ b/src/calf/osc.h
@@ -138,6 +138,19 @@ struct waveform_oscillator: public simple_oscillator
     }
 };
 
+static inline void normalize_waveform(float *table, unsigned int size)
+{
+    float thismax = 0;
+    for (unsigned int i = 0; i < size; i++)
+        thismax = std::max(thismax, fabs(table[i]));
+    if (thismax < 0.000001f)
+        return;
+    for (unsigned int i = 0; i < size; i++)
+        table[i] /= thismax;
+}
+
+
+
 };
 
 #endif
diff --git a/src/monosynth.cpp b/src/monosynth.cpp
index 6f22eb8..e1eb66b 100644
--- a/src/monosynth.cpp
+++ b/src/monosynth.cpp
@@ -228,17 +228,6 @@ const char *monosynth_audio_module::get_gui_xml()
     return monosynth_gui_xml;
 }
 
-static void normalize(float *table, unsigned int size)
-{
-    float thismax = 0;
-    for (unsigned int i = 0; i < size; i++)
-        thismax = std::max(thismax, fabs(table[i]));
-    if (thismax < 0.000001f)
-        return;
-    for (unsigned int i = 0; i < size; i++)
-        table[i] /= thismax;
-}
-
 void monosynth_audio_module::activate() {
     running = false;
     output_pos = 0;
@@ -250,14 +239,14 @@ void monosynth_audio_module::activate() {
     stack.clear();
 }
 
-waveform_family<MONOSYNTH_WAVE_SIZE> monosynth_audio_module::waves[wave_count];
+waveform_family<MONOSYNTH_WAVE_BITS> monosynth_audio_module::waves[wave_count];
 
 void monosynth_audio_module::generate_waves()
 {
-    float data[1 << MONOSYNTH_WAVE_SIZE];
-    bandlimiter<MONOSYNTH_WAVE_SIZE> bl;
+    float data[1 << MONOSYNTH_WAVE_BITS];
+    bandlimiter<MONOSYNTH_WAVE_BITS> bl;
     
-    enum { S = 1 << MONOSYNTH_WAVE_SIZE, HS = S / 2, QS = S / 4, QS3 = 3 * QS };
+    enum { S = 1 << MONOSYNTH_WAVE_BITS, HS = S / 2, QS = S / 4, QS3 = 3 * QS };
     float iQS = 1.0 / QS;
 
     // yes these waves don't have really perfect 1/x spectrum because of aliasing
@@ -317,7 +306,7 @@ void monosynth_audio_module::generate_waves()
     for (int i = 0; i < S; i++) {
         data[i] = exp(-i * 1.0 / HS) * sin(i * PI / HS) * cos(2 * PI * i / HS);
     }
-    normalize(data, S);
+    normalize_waveform(data, S);
     waves[wave_test2].make(bl, data);
     for (int i = 0; i < S; i++) {
         //int ii = (i < HS) ? i : S - i;
@@ -347,12 +336,12 @@ void monosynth_audio_module::generate_waves()
     }
     waves[wave_test6].make(bl, data);
     for (int i = 0; i < S; i++) {
-        int j = i >> (MONOSYNTH_WAVE_SIZE - 11);
+        int j = i >> (MONOSYNTH_WAVE_BITS - 11);
         data[i] = (j ^ 0x1D0) * 1.0 / HS - 1;
     }
     waves[wave_test7].make(bl, data);
     for (int i = 0; i < S; i++) {
-        int j = i >> (MONOSYNTH_WAVE_SIZE - 11);
+        int j = i >> (MONOSYNTH_WAVE_BITS - 11);
         data[i] = -1 + 0.66 * (3 & ((j >> 8) ^ (j >> 10) ^ (j >> 6)));
     }
     waves[wave_test8].make(bl, data);
@@ -368,7 +357,7 @@ bool monosynth_audio_module::get_static_graph(int index, int subindex, float val
     if (index == par_wave1 || index == par_wave2) {
         if (subindex)
             return false;
-        enum { S = 1 << MONOSYNTH_WAVE_SIZE };
+        enum { S = 1 << MONOSYNTH_WAVE_BITS };
         int wave = dsp::clip(dsp::fastf2i_drm(value), 0, (int)wave_count - 1);
 
         float *waveform = waves[wave].get_level(0);
diff --git a/src/organ.cpp b/src/organ.cpp
index bee8941..08f88d1 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -62,42 +62,60 @@ const char *organ_audio_module::get_gui_xml()
                 "<value param=\"master\"/>"
             "</vbox>"
         "</hbox>"
-        "<table rows=\"3\" cols=\"9\">"
+        "<table rows=\"5\" 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\"/>"
     
             "<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\"/>"
     
             "<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\"/>"
     
             "<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\"/>"
 
             "<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\"/>"
     
             "<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\"/>"
 
             "<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\"/>"
 
             "<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\"/>"
 
             "<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\"/>"
         "</table>"
     "</vbox>"
     ;
@@ -118,6 +136,26 @@ 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,         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" },
     { 0.25,      0,  1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "perc_level", "Perc. level" },
@@ -135,3 +173,28 @@ const char *rotary_speaker_speed_names[] = { "Off", "Chorale", "Tremolo", "HoldP
 parameter_properties rotary_speaker_audio_module::param_props[] = {
     { 2,         0,  4, 1.01, PF_ENUM | PF_CTL_COMBO, rotary_speaker_speed_names, "vib_speed", "Speed Mode" },
 };
+
+waveform_family<ORGAN_WAVE_BITS> organ_voice_base::waves[organ_voice_base::wave_count];
+
+organ_voice_base::organ_voice_base(organ_parameters *_parameters)
+: parameters(_parameters)
+{
+    note = -1;
+    static bool inited = false;
+    if (!inited)
+    {
+        float tmp[ORGAN_WAVE_SIZE];
+        bandlimiter<ORGAN_WAVE_BITS> bl;
+        inited = true;
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = sin(i * 2 * M_PI / ORGAN_WAVE_SIZE);
+        waves[wave_sine].make(bl, tmp);
+        for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+            tmp[i] = (i < (ORGAN_WAVE_SIZE / 16)) ? 1 : 0;
+        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 / 4) ? sin(i * 4 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
+        waves[wave_stretchsine].make(bl, tmp);
+    }
+}

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list