[SCM] calf/master: + Added bandlimited osc classes + Internal cleanups/bugfixes

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:36:42 UTC 2013


The following commit has been merged in the master branch:
commit 1edb70baea586dd02adef7260426ef13e8003bb2
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Sat Dec 8 12:14:13 2007 +0000

    + Added bandlimited osc classes
    + Internal cleanups/bugfixes
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@8 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index 7f98730..e49e1f3 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,3 +1,3 @@
 calfdir = $(includedir)/calf
 
-calf_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h jackhost.h modules.h modules_dev.h onepole.h primitives.h wave.h
+calf_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h delay.h fft.h fixed_point.h giface.h inertia.h jackhost.h modules.h modules_dev.h onepole.h osc.h primitives.h wave.h
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index 2da56d4..8844693 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -31,30 +31,6 @@ namespace dsp {
 #endif
 
 /**
- * typical precalculated sine table
- */
-template<class T, int N, int Multiplier>
-class sine_table
-{
-public:
-    static bool initialized;
-    static T data[N+1];
-    sine_table() {
-        if (initialized)
-            return;
-        initialized = true;
-        for (int i=0; i<N+1; i++)
-            data[i] = (T)(Multiplier*sin(i*2*M_PI*(1.0/N)));
-    }
-};
-
-template<class T, int N, int Multiplier>
-bool sine_table<T,N,Multiplier>::initialized = false;
-
-template<class T, int N, int Multiplier>
-T sine_table<T,N,Multiplier>::data[N+1];
-
-/**
  * Audio effect base class. Not really useful until it gets more developed.
  */
 class audio_effect
diff --git a/src/calf/fft.h b/src/calf/fft.h
new file mode 100644
index 0000000..f8b79cf
--- /dev/null
+++ b/src/calf/fft.h
@@ -0,0 +1,103 @@
+/* Calf DSP Library
+ * FFT class
+ *
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CALF_FFT_H
+#define __CALF_FFT_H
+
+#include <complex>
+
+namespace dsp {
+
+/// FFT routine copied from my old OneSignal library, modified to 
+/// match Calf's style. It's not fast at all, just a straightforward
+/// implementation.
+template<class T, int O>
+class fft
+{
+    typedef typename std::complex<T> complex;
+    int scramble[1<<O];
+    complex sines[1<<O];
+public:
+    fft()
+    {
+        int N=1<<O;
+        for (int i=0; i<N; i++)
+        {
+            int v=0;
+            for (int j=0; j<O; j++)
+                if (i&(1<<j))
+                    v+=(N>>(j+1));
+            scramble[i]=v;
+            sines[i]=complex(cos(2*PI*i/N),sin(2*PI*i/N));
+        }
+    }
+    void calculate(complex *input, complex *output, bool inverse)
+    {
+        int N=1<<O;
+        int N1=N-1;
+        int i;
+        // Scramble the input data
+        if (inverse)
+        {
+            float mf=1.0/N;
+            for (i=0; i<N; i++)
+            {
+                complex &c=input[scramble[i]];
+                output[i]=mf*complex(c.imag(),c.real());
+            }
+        }
+        else
+            for (i=0; i<N; i++)
+                output[i]=input[scramble[i]];
+
+        // O butterfiles
+        for (i=0; i<O; i++)
+        {
+            int PO=1<<i, PNO=1<<(O-i-1);
+            int j,k;
+            for (j=0; j<PNO; j++)
+            {
+                int base=j<<(i+1);
+                for (k=0; k<PO; k++)
+                {
+                    int B1=base+k;
+                    int B2=base+k+(1<<i);
+                    complex r1=output[B1];
+                    complex r2=output[B2];
+                    output[B1]=r1+r2*sines[(B1<<(O-i-1))&N1];
+                    output[B2]=r1+r2*sines[(B2<<(O-i-1))&N1];
+                }
+            }
+        }
+        if (inverse)
+        {
+            for (i=0; i<N; i++)
+            {
+                const complex &c=output[i];
+                output[i]=complex(c.imag(),c.real());
+            }
+        }
+    }
+};
+
+};
+
+#endif
diff --git a/src/calf/jackhost.h b/src/calf/jackhost.h
index d10ab9a..4f696ee 100644
--- a/src/calf/jackhost.h
+++ b/src/calf/jackhost.h
@@ -148,6 +148,7 @@ public:
     
     virtual void init_module() {
         module.set_sample_rate(sample_rate);
+        module.activate();
         module.params_changed();
     }
     
diff --git a/src/calf/modules_dev.h b/src/calf/modules_dev.h
index da2a2ea..337ad19 100644
--- a/src/calf/modules_dev.h
+++ b/src/calf/modules_dev.h
@@ -27,32 +27,12 @@
 #include "biquad.h"
 #include "audio_fx.h"
 #include "inertia.h"
+#include "osc.h"
 
 namespace synth {
 
 using namespace dsp;
-    
-/// Very simple, non-bandlimited saw oscillator. Should not be used for anything
-/// else than testing/prototyping.
-struct simple_oscillator
-{
-    uint32_t phase, phasedelta;
-    void reset()
-    {
-        phase = 0;
-    }
-    void set_freq(float freq, float sr)
-    {
-        phasedelta = (int)(freq * 65536.0 * 256.0 * 16.0 / sr) << 4;
-    }
-    inline float get()
-    {
-        float value = (phase >> 16 ) / 65535.0 - 0.5;
-        phase += phasedelta;
-        return value;
-    }
-};
-    
+        
 /// Monosynth-in-making. Parameters may change at any point, so don't make songs with it!
 class monosynth_audio_module
 {
@@ -65,7 +45,9 @@ public:
     float *outs[out_count];
     float *params[param_count];
     uint32_t srate, crate;
-    simple_oscillator osc1, osc2;
+    dsp::sine_table<float, 2048, 1> waveform_sine;
+    waveform_family<11> waves_saw;
+    waveform_oscillator<11> osc1, osc2;
     bool running;
     int last_key;
     
@@ -92,6 +74,7 @@ public:
                 float freq = 440 * pow(2.0, (last_key - 69) / 12.0);
                 osc1.set_freq(freq*0.995, srate);
                 osc2.set_freq(freq*1.005, srate);
+                osc2.waveform = osc1.waveform = waves_saw.get_level(osc1.phasedelta);
                 if (!running)
                 {
                     osc1.reset();
@@ -121,6 +104,11 @@ public:
         output_pos = 0;
         filter.reset();
         filter2.reset();
+        float data[2048];
+        for (int i = 0 ; i < 2048; i++)
+            data[i] = (float)(-1.f + i / 1024.f);
+        bandlimiter<11> bl;
+        waves_saw.make(bl, data);
     }
     void deactivate() {
     }
diff --git a/src/calf/osc.h b/src/calf/osc.h
new file mode 100644
index 0000000..6efc107
--- /dev/null
+++ b/src/calf/osc.h
@@ -0,0 +1,141 @@
+/* Calf DSP Library
+ * Oscillators
+ *
+ * Copyright (C) 2001-2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CALF_OSC_H
+#define __CALF_OSC_H
+
+#include "fft.h"
+#include <map>
+
+namespace synth
+{
+
+/// Very simple, non-bandlimited saw oscillator. Should not be used for anything
+/// else than testing/prototyping.
+struct simple_oscillator
+{
+    uint32_t phase, phasedelta;
+    void reset()
+    {
+        phase = 0;
+    }
+    void set_freq(float freq, float sr)
+    {
+        phasedelta = (int)(freq * 65536.0 * 256.0 * 16.0 / sr) << 4;
+    }
+    inline float get()
+    {
+        float value = (phase >> 16 ) / 65535.0 - 0.5;
+        phase += phasedelta;
+        return value;
+    }
+};
+
+template<int SIZE_BITS>
+struct bandlimiter
+{
+    enum { SIZE = 1 << SIZE_BITS };
+    static dsp::fft<float, SIZE_BITS> fft;
+    
+    std::complex<float> spectrum[SIZE];
+    
+    void compute_spectrum(float input[SIZE])
+    {
+        std::complex<float> data[SIZE];
+        for (int i = 0; i < SIZE; i++)
+            data[i] = input[i];
+        fft.calculate(data, spectrum, false);
+    }
+    
+    /// remove DC offset of the spectrum (it usually does more harm than good!)
+    void remove_dc()
+    {
+        spectrum[0] = 0.f;
+    }
+    
+    /// very basic bandlimiting (brickwall filter)
+    /// might need to be improved much in future!
+    void make_waveform(float output[SIZE], int cutoff)
+    {
+        std::complex<float> new_spec[SIZE], iffted[SIZE];
+        for (int i = 0; i < cutoff; i++)
+            new_spec[i] = spectrum[i];        
+        for (int i = cutoff; i < SIZE; i++)
+            new_spec[i] = 0.f;
+        fft.calculate(new_spec, iffted, true);
+        for (int i = 0; i < SIZE; i++)
+            output[i] = iffted[i].real();
+    }
+};
+
+template<int SIZE_BITS>
+dsp::fft<float, SIZE_BITS> bandlimiter<SIZE_BITS>::fft;
+
+/// Set of bandlimited wavetables
+template<int SIZE_BITS>
+struct waveform_family: public map<uint32_t, float *>
+{
+    enum { SIZE = 1 << SIZE_BITS };
+    using map<uint32_t, float *>::iterator;
+    using map<uint32_t, float *>::end;
+    using map<uint32_t, float *>::lower_bound;
+    
+    void make(bandlimiter<SIZE_BITS> &bl, float input[SIZE])
+    {
+        bl.compute_spectrum(input);
+        bl.remove_dc();
+        
+        uint32_t multiple = 1, base = 1 << (32 - SIZE_BITS);
+        while(multiple < SIZE / 2) {
+            float *wf = new float[SIZE];
+            bl.make_waveform(wf, (1 << SIZE_BITS) / multiple);
+            (*this)[base * multiple] = wf;
+            multiple = multiple << 1;
+        }
+    }
+    
+    inline float *get_level(uint32_t phase_delta)
+    {
+        iterator i = upper_bound(phase_delta);
+        if (i == end())
+            return NULL;
+        // printf("Level = %08x\n", i->first);
+        return i->second;
+    }
+};
+
+template<int SIZE_BITS>
+struct waveform_oscillator: public simple_oscillator
+{
+    enum { SIZE = 1 << SIZE_BITS, MASK = SIZE - 1 };
+    float *waveform;
+    inline float get()
+    {
+        uint32_t wpos = phase >> (32 - SIZE_BITS);
+        float value = lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SIZE - 1)) * (1.0f / SIZE));
+        phase += phasedelta;
+        return value;
+    }
+};
+
+};
+
+#endif
diff --git a/src/calf/primitives.h b/src/calf/primitives.h
index 9969a4b..5af0800 100644
--- a/src/calf/primitives.h
+++ b/src/calf/primitives.h
@@ -373,6 +373,30 @@ inline float fract16(unsigned int value)
     return (value & 0xFFFF) * (1.0 / 65536.0);
 }
 
+/**
+ * typical precalculated sine table
+ */
+template<class T, int N, int Multiplier>
+class sine_table
+{
+public:
+    static bool initialized;
+    static T data[N+1];
+    sine_table() {
+        if (initialized)
+            return;
+        initialized = true;
+        for (int i=0; i<N+1; i++)
+            data[i] = (T)(Multiplier*sin(i*2*M_PI*(1.0/N)));
+    }
+};
+
+template<class T, int N, int Multiplier>
+bool sine_table<T,N,Multiplier>::initialized = false;
+
+template<class T, int N, int Multiplier>
+T sine_table<T,N,Multiplier>::data[N+1];
+
 };
 
 #endif
diff --git a/src/modules.cpp b/src/modules.cpp
index 08c649a..4a0fc24 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -109,9 +109,9 @@ const char *monosynth_audio_module::param_names[] = {"Out L", "Out R", "Cutoff",
 
 parameter_properties monosynth_audio_module::param_props[] = {
     { 33,        10,16000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL },
-    { 3,        0.7,    4, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL },
-    { 6000,       0,10800, 1.01, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL },
-    { 2000,      10,20000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL },
+    { 2,        0.7,    4, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL },
+    { 8000,       0,10800, 1.01, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL },
+    { 350,      10,20000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL },
 };
 
 static synth::ladspa_info monosynth_info = { 0x8480, "Monosynth", "Calf Monosynth", "Krzysztof Foltman", copyright, "SynthesizerPlugin" };

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list