[SCM] calf/master: + Added inertia and timer (once_per_n) classes + Added adjustable inertia to filter plugin + Removed dependency on NAS (in currently used code, at least) + Namespace cleanups

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 d9b2878815d313677c05956762ce2d1891b2f97c
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Sun Dec 2 01:05:07 2007 +0000

    + Added inertia and timer (once_per_n) classes
    + Added adjustable inertia to filter plugin
    + Removed dependency on NAS (in currently used code, at least)
    + Namespace cleanups
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@4 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/configure.in b/configure.in
index 9cad532..f65ab9b 100644
--- a/configure.in
+++ b/configure.in
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([calf],[0.0.3],[wdev at foltman.com])
+AC_INIT([calf],[0.0.4],[wdev at foltman.com])
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADER([config.h])
 
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index c167bb5..2508e0f 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,3 +1,3 @@
 calfdir = $(includedir)/calf
 
-calf_HEADERS = audio_fx.h biquad.h buffer.h delay.h fixed_point.h giface.h modules.h onepole.h primitives.h
+calf_HEADERS = audio_fx.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h modules.h onepole.h primitives.h wave.h
diff --git a/src/calf/buffer.h b/src/calf/buffer.h
index 44ad22e..18cf101 100644
--- a/src/calf/buffer.h
+++ b/src/calf/buffer.h
@@ -21,9 +21,6 @@
 #ifndef __BUFFER_H
 #define __BUFFER_H
 
-#include <typeinfo>
-#include <audio/wave.h>
-
 namespace dsp {
 
 /// decrease by N if >= N (useful for circular buffers)
@@ -235,21 +232,6 @@ template<int N, class T = float>
 class stereo_auto_buffer: public auto_buffer<N, stereo_sample<T> > {
 };
 
-template<class T>
-bool load_wave(dsp::dynamic_buffer<T> &dest, const char *file_name) {
-    WaveInfo *file = WaveOpenFileForReading(file_name);
-    typedef dsp::sample_traits<T> st;
-    if (file->channels == st::channels && file->bitsPerSample == st::bps) {
-        dest.resize(file->numSamples);
-        WaveReadFile((char *)dest.data(), dest.size()*sizeof(T), file);
-        WaveCloseFile(file);
-        return true;
-    }
-    WaveCloseFile(file);
-    fprintf(stderr, "Sorry, need a %d channels and %d bps, got %d channels and %d bps\n", st::channels, st::bps, file->channels, file->bitsPerSample);
-    return false;
-}
-
 };
 
 #endif
diff --git a/src/calf/inertia.h b/src/calf/inertia.h
new file mode 100644
index 0000000..8a70b40
--- /dev/null
+++ b/src/calf/inertia.h
@@ -0,0 +1,205 @@
+/* Calf DSP Library
+ * Basic "inertia" (parameter smoothing) classes.
+ * 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_INERTIA_H
+#define __CALF_INERTIA_H
+
+#include "primitives.h"
+
+namespace dsp {
+    
+/// Algorithm for a constant time linear ramp
+class linear_ramp
+{
+public:
+    int ramp_len;
+    float mul, delta;
+public:
+    linear_ramp(int _ramp_len) {
+        ramp_len = _ramp_len;
+        mul = (float)(1.0f / ramp_len);
+    }
+    inline void set_length(int _ramp_len) {
+        ramp_len = _ramp_len;
+        mul = (float)(1.0f / ramp_len);
+    }
+    inline int length()
+    {
+        return ramp_len;
+    }
+    inline void start_ramp(float start, float end)
+    {
+        delta = mul * (end - start);
+    }
+    inline float ramp(float value)
+    {
+        return value + delta;
+    }
+};
+    
+/// Algorithm for a constant time linear ramp
+class exponential_ramp
+{
+public:
+    int ramp_len;
+    float root, delta;
+public:
+    exponential_ramp(int _ramp_len) {
+        ramp_len = _ramp_len;
+        root = (float)(1.0f / ramp_len);
+    }
+    inline void set_length(int _ramp_len) {
+        ramp_len = _ramp_len;
+        root = (float)(1.0f / ramp_len);
+    }
+    inline int length()
+    {
+        return ramp_len;
+    }
+    inline void start_ramp(float start, float end)
+    {
+        delta = pow(end / start, root);
+    }
+    inline float ramp(float value)
+    {
+        return value * delta;
+    }
+};
+    
+/// Generic inertia using algorithm specified as template argument
+template<class Ramp>
+class inertia
+{
+public:
+    float old_value;
+    float value;
+    int count;
+    Ramp ramp;
+
+public:
+    inertia(const Ramp &_ramp, float init_value = 0.f)
+    : ramp(_ramp)
+    {
+        value = old_value = init_value;
+        count = 0;
+    }
+    /// Set value immediately (no inertia)
+    void set_now(float _value)
+    {
+        value = old_value = _value;
+        count = 0;
+    }
+    /// Set with inertia
+    void set_inertia(float source)
+    {
+        if (source != old_value) {
+            ramp.start_ramp(value, source);
+            count = ramp.length();
+            old_value = source;
+        }
+    }
+    /// Get smoothed value of given source value
+    inline float get(float source)
+    {
+        if (source != old_value) {
+            ramp.start_ramp(value, source);
+            count = ramp.length();
+            old_value = source;
+        }
+        if (!count)
+            return old_value;
+        value = ramp.ramp(value);
+        count--;
+        if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+            value = old_value;
+        return value;
+    }
+    /// Get smoothed value assuming no new input
+    inline float get()
+    {
+        if (!count)
+            return old_value;
+        value = ramp.ramp(value);
+        count--;
+        if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+            value = old_value;
+        return value;
+    }
+    /// Do one inertia step, without returning the new value and without changing inertia
+    inline void step()
+    {
+        if (count) {
+            value = ramp.ramp(value);
+            count--;
+            if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+                value = old_value;
+        }
+    }
+    /// Get last smoothed value, without affecting anything
+    inline float get_last() const
+    {
+        return value;
+    }
+    inline bool active()
+    {
+        return count > 0;
+    }
+};
+
+class once_per_n
+{
+public:
+    unsigned int frequency;
+    unsigned int left;
+public:
+    once_per_n(unsigned int _frequency)
+    : frequency(_frequency), left(_frequency)
+    {}
+    inline void start()
+    {
+        left = frequency;
+    }
+    /// Set timer to "elapsed" state (elapsed() will return true during next call)
+    inline void signal()
+    {
+        left = 0;
+    }
+    inline unsigned int get(unsigned int desired)
+    {
+        if (desired > left) {
+            desired = left;
+            left = 0;
+            return desired;
+        }
+        left -= desired;
+        return desired;
+    }
+    inline bool elapsed()
+    {
+        if (!left) {
+            left = frequency;
+            return true;
+        }
+        return false;
+    }
+};
+    
+}
+
+#endif
diff --git a/src/calf/modules.h b/src/calf/modules.h
index fe12ba1..7c355c4 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -24,8 +24,11 @@
 #include <assert.h>
 #include "biquad.h"
 #include "audio_fx.h"
+#include "inertia.h"
 
-using namespace synth;
+namespace synth {
+
+using namespace dsp;
 
 class amp_audio_module
 {
@@ -155,7 +158,7 @@ public:
 class filter_audio_module
 {
 public:    
-    enum { par_cutoff, par_resonance, par_mode, param_count };
+    enum { par_cutoff, par_resonance, par_mode, par_inertia, param_count };
     enum { in_count = 2, out_count = 2, rt_capable = true };
     float *ins[in_count]; 
     float *outs[out_count];
@@ -165,31 +168,59 @@ public:
     uint32_t srate;
     static parameter_properties param_props[];
     int order;
+    inertia<exponential_ramp> inertia_cutoff;
+    once_per_n timer;
     
-    void params_changed() {
-        float freq = *params[par_cutoff];
+    filter_audio_module()
+    : inertia_cutoff(exponential_ramp(128), 20)
+    , timer(128)
+    {
+    }
+    
+    void calculate_filter()
+    {
+        float freq = inertia_cutoff.get_last();
+        // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left);
         // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different
         float q = *params[par_resonance];
-        // XXXKF this is highly inefficient
+        // XXXKF this is highly inefficient and should be replaced as soon as I have fast f2i in primitives.h
         int mode = (int)*params[par_mode];
-        order = (mode < 3) ? mode + 1 : mode - 2;
         // printf("freq = %f q = %f mode = %d\n", freq, q, mode);
         if (mode < 3) {
             left[0].set_lp_rbj(freq, q, srate);
+            order = mode + 1;
         } else {
             left[0].set_hp_rbj(freq, q, srate);
+            order = mode - 2;
         }
+        // XXXKF this is highly inefficient and should be replaced as soon as I have fast f2i in primitives.h
+        int inertia = (int)*params[par_inertia];
+        if (inertia != inertia_cutoff.ramp.length())
+            inertia_cutoff.ramp.set_length(inertia);
+        
         right[0].copy_coeffs(left[0]);
         for (int i = 1; i < order; i++) {
             left[i].copy_coeffs(left[0]);
             right[i].copy_coeffs(left[0]);
         }
     }
+    void params_changed()
+    {
+        inertia_cutoff.set_inertia(*params[par_cutoff]);
+        calculate_filter();
+    }
+    void on_timer()
+    {
+        inertia_cutoff.step();
+        calculate_filter();
+    }
     void activate() {
         for (int i=0; i < order; i++) {
             left[i].reset();
             right[i].reset();
         }
+        timer = once_per_n(srate / 1000);
+        timer.start();
     }
     void deactivate() {
     }
@@ -248,18 +279,30 @@ public:
         return filter[order - 1].empty_d1() ? 0 : inmask;
     }
     uint32_t process(uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
-        if (outputs_mask & 1) {
-            outputs_mask &= ~1;
-            outputs_mask |= process_channel(left, ins[0], outs[0], numsamples, inputs_mask & 1);
-        }
-        if (outputs_mask & 2) {
-            outputs_mask &= ~2;
-            outputs_mask |= process_channel(right, ins[1], outs[1], numsamples, inputs_mask & 2);
+        uint32_t ostate = 0;
+        uint32_t offset = 0;
+        while(offset < numsamples) {
+            uint32_t numnow = numsamples - offset;
+            // if inertia's inactive, we can calculate the whole buffer at once
+            if (inertia_cutoff.active())
+                numnow = timer.get(numnow);
+            if (outputs_mask & 1) {
+                ostate |= process_channel(left, ins[0] + offset, outs[0] + offset, numnow, inputs_mask & 1);
+            }
+            if (outputs_mask & 2) {
+                ostate |= process_channel(right, ins[1] + offset, outs[1] + offset, numnow, inputs_mask & 2);
+            }
+            if (timer.elapsed()) {
+                on_timer();
+            }
+            offset += numnow;
         }
-        return outputs_mask;
+        return ostate;
     }
 };
 
 extern std::string get_builtin_modules_rdf();
 
+};
+
 #endif
diff --git a/src/calf/wave.h b/src/calf/wave.h
new file mode 100644
index 0000000..55a4806
--- /dev/null
+++ b/src/calf/wave.h
@@ -0,0 +1,42 @@
+/* Calf DSP Library
+ * Primitive interface to NAS WAV file operations.
+ * Not really useful for now, I've used it for testing previously.
+ *
+ * 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.
+ */
+
+#include <audio/wave.h>
+
+namespace dsp {
+
+template<class T>
+bool load_wave(dsp::dynamic_buffer<T> &dest, const char *file_name) {
+    WaveInfo *file = WaveOpenFileForReading(file_name);
+    typedef dsp::sample_traits<T> st;
+    if (file->channels == st::channels && file->bitsPerSample == st::bps) {
+        dest.resize(file->numSamples);
+        WaveReadFile((char *)dest.data(), dest.size()*sizeof(T), file);
+        WaveCloseFile(file);
+        return true;
+    }
+    WaveCloseFile(file);
+    fprintf(stderr, "Sorry, need a %d channels and %d bps, got %d channels and %d bps\n", st::channels, st::bps, file->channels, file->bitsPerSample);
+    return false;
+}
+
+}
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index c7d8f58..d01b6d3 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
     
     rdf += "<rdf:RDF xmlns:rdf=\"&rdf;\" xmlns:rdfs=\"&rdfs;\" xmlns:dc=\"&dc;\" xmlns:ladspa=\"&ladspa;\">\n";
 
-    rdf += get_builtin_modules_rdf();
+    rdf += synth::get_builtin_modules_rdf();
     
     rdf += "</rdf:RDF>\n";
     
diff --git a/src/modules.cpp b/src/modules.cpp
index d1ef7a5..7365502 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -24,6 +24,8 @@
 #include <calf/giface.h>
 #include <calf/modules.h>
 
+using namespace synth;
+
 const char *copyright = "(C) 2001-2007 Krzysztof Foltman, license: LGPL";
 
 const char *amp_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Gain"};
@@ -68,7 +70,7 @@ synth::ladspa_wrapper<reverb_audio_module> reverb(reverb_info);
 
 ////////////////////////////////////////////////////////////////////////////
 
-const char *filter_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Cutoff", "Resonance", "Mode"};
+const char *filter_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Cutoff", "Resonance", "Mode", "Inertia"};
 
 const char *filter_choices[] = {
     "12dB/oct Lowpass",
@@ -83,6 +85,7 @@ parameter_properties filter_audio_module::param_props[] = {
     { 2000,      10,20000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL },
     { 0.707,  0.707,   20,  1.1, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL },
     { 0,          0,    5,    1, PF_ENUM | PF_CTL_COMBO, filter_choices },
+    { 20,         5,  100,    1, PF_INT | PF_SCALE_LOG | PF_CTL_KNOB, NULL},
 };
 
 static synth::ladspa_info filter_info = { 0x847f, "Filter", "Calf Filter", "Krzysztof Foltman", copyright, "FilterPlugin" };
@@ -96,22 +99,22 @@ extern "C" {
 const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
 {
     switch (Index) {
-        case 0: return &filter.descriptor;
-        case 1: return &flanger.descriptor;
-        case 2: return &reverb.descriptor;
+        case 0: return &::filter.descriptor;
+        case 1: return &::flanger.descriptor;
+        case 2: return &::reverb.descriptor;
         default: return NULL;
     }
 }
 
 };
 
-std::string get_builtin_modules_rdf()
+std::string synth::get_builtin_modules_rdf()
 {
     std::string rdf;
     
-    rdf += flanger.generate_rdf();
-    rdf += reverb.generate_rdf();
-    rdf += filter.generate_rdf();
+    rdf += ::flanger.generate_rdf();
+    rdf += ::reverb.generate_rdf();
+    rdf += ::filter.generate_rdf();
     
     return rdf;
 }

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list