[SCM] calf/master: More source code reorganisation to speed up partial builds

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:40:10 UTC 2013


The following commit has been merged in the master branch:
commit eeaa1655be0cb2f64db6a0d17b53d6b14fa7daff
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Fri May 7 22:40:28 2010 +0100

    More source code reorganisation to speed up partial builds
    
    * Update/correct copyright notices
    * Break up plugin code into separate header/cpp files for each group
      (distortion, EQ, modulation fx, everything else)
    * Make reverb a class, not a class template, un-inline some methods

diff --git a/src/Makefile.am b/src/Makefile.am
index 858b5de..40f5c47 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,7 +52,7 @@ calfbenchmark_CXXFLAGS = $(AM_CXXFLAGS) -DTEST_OSC
 calfbenchmark_LDADD += libcalfgui.la
 endif
 
-calf_la_SOURCES = audio_fx.cpp modules.cpp modules_dsp.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp plugin.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp modmatrix.cpp 
+calf_la_SOURCES = audio_fx.cpp modules.cpp modules_dist.cpp modules_dsp.cpp modules_eq.cpp modules_mod.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp plugin.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp modmatrix.cpp 
 calf_la_LIBADD ?= $(FLUIDSYNTH_DEPS_LIBS)
 if USE_DEBUG
 calf_la_LDFLAGS = -rpath $(ladspadir) -avoid-version -module -lexpat -disable-static $(FLUIDSYNTH_DEPS_LIBS)
diff --git a/src/audio_fx.cpp b/src/audio_fx.cpp
index 389ca57..54d6b77 100644
--- a/src/audio_fx.cpp
+++ b/src/audio_fx.cpp
@@ -1,6 +1,7 @@
-/* Calf DSP Library utility application.
+/* Calf DSP Library
  * Reusable audio effect classes - implementation.
- * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,7 +20,9 @@
  */
 
 #include <calf/audio_fx.h>
+#include <calf/giface.h>
 
+using namespace calf_plugins;
 using namespace dsp;
 
 simple_phaser::simple_phaser(int _max_stages, float *x1vals, float *y1vals)
@@ -231,6 +234,113 @@ float biquad_filter_module::freq_gain(int subindex, float freq, float srate) con
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+void reverb::update_times()
+{
+    switch(type)
+    {
+    case 0:
+        tl[0] =  397 << 16, tr[0] =  383 << 16;
+        tl[1] =  457 << 16, tr[1] =  429 << 16;
+        tl[2] =  549 << 16, tr[2] =  631 << 16;
+        tl[3] =  649 << 16, tr[3] =  756 << 16;
+        tl[4] =  773 << 16, tr[4] =  803 << 16;
+        tl[5] =  877 << 16, tr[5] =  901 << 16;
+        break;
+    case 1:
+        tl[0] =  697 << 16, tr[0] =  783 << 16;
+        tl[1] =  957 << 16, tr[1] =  929 << 16;
+        tl[2] =  649 << 16, tr[2] =  531 << 16;
+        tl[3] = 1049 << 16, tr[3] = 1177 << 16;
+        tl[4] =  473 << 16, tr[4] =  501 << 16;
+        tl[5] =  587 << 16, tr[5] =  681 << 16;
+        break;
+    case 2:
+    default:
+        tl[0] =  697 << 16, tr[0] =  783 << 16;
+        tl[1] =  957 << 16, tr[1] =  929 << 16;
+        tl[2] =  649 << 16, tr[2] =  531 << 16;
+        tl[3] = 1249 << 16, tr[3] = 1377 << 16;
+        tl[4] = 1573 << 16, tr[4] = 1671 << 16;
+        tl[5] = 1877 << 16, tr[5] = 1781 << 16;
+        break;
+    case 3:
+        tl[0] = 1097 << 16, tr[0] = 1087 << 16;
+        tl[1] = 1057 << 16, tr[1] = 1031 << 16;
+        tl[2] = 1049 << 16, tr[2] = 1039 << 16;
+        tl[3] = 1083 << 16, tr[3] = 1055 << 16;
+        tl[4] = 1075 << 16, tr[4] = 1099 << 16;
+        tl[5] = 1003 << 16, tr[5] = 1073 << 16;
+        break;
+    case 4:
+        tl[0] =  197 << 16, tr[0] =  133 << 16;
+        tl[1] =  357 << 16, tr[1] =  229 << 16;
+        tl[2] =  549 << 16, tr[2] =  431 << 16;
+        tl[3] =  949 << 16, tr[3] = 1277 << 16;
+        tl[4] = 1173 << 16, tr[4] = 1671 << 16;
+        tl[5] = 1477 << 16, tr[5] = 1881 << 16;
+        break;
+    case 5:
+        tl[0] =  197 << 16, tr[0] =  133 << 16;
+        tl[1] =  257 << 16, tr[1] =  179 << 16;
+        tl[2] =  549 << 16, tr[2] =  431 << 16;
+        tl[3] =  619 << 16, tr[3] =  497 << 16;
+        tl[4] = 1173 << 16, tr[4] = 1371 << 16;
+        tl[5] = 1577 << 16, tr[5] = 1881 << 16;
+        break;
+    }
+    
+    float fDec=1000 + 2400.f * diffusion;
+    for (int i = 0 ; i < 6; i++) {
+        ldec[i]=exp(-float(tl[i] >> 16) / fDec), 
+        rdec[i]=exp(-float(tr[i] >> 16) / fDec);
+    }
+}
+
+void reverb::reset()
+{
+    apL1.reset();apR1.reset();
+    apL2.reset();apR2.reset();
+    apL3.reset();apR3.reset();
+    apL4.reset();apR4.reset();
+    apL5.reset();apR5.reset();
+    apL6.reset();apR6.reset();
+    lp_left.reset();lp_right.reset();
+    old_left = 0; old_right = 0;
+}
+
+void reverb::process(float &left, float &right)
+{
+    unsigned int ipart = phase.ipart();
+    
+    // the interpolated LFO might be an overkill here
+    int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]) >> 2;
+    phase += dphase;
+    
+    left += old_right;
+    left = apL1.process_allpass_comb_lerp16(left, tl[0] - 45*lfo, ldec[0]);
+    left = apL2.process_allpass_comb_lerp16(left, tl[1] + 47*lfo, ldec[1]);
+    float out_left = left;
+    left = apL3.process_allpass_comb_lerp16(left, tl[2] + 54*lfo, ldec[2]);
+    left = apL4.process_allpass_comb_lerp16(left, tl[3] - 69*lfo, ldec[3]);
+    left = apL5.process_allpass_comb_lerp16(left, tl[4] + 69*lfo, ldec[4]);
+    left = apL6.process_allpass_comb_lerp16(left, tl[5] - 46*lfo, ldec[5]);
+    old_left = lp_left.process(left * fb);
+    sanitize(old_left);
+
+    right += old_left;
+    right = apR1.process_allpass_comb_lerp16(right, tr[0] - 45*lfo, rdec[0]);
+    right = apR2.process_allpass_comb_lerp16(right, tr[1] + 47*lfo, rdec[1]);
+    float out_right = right;
+    right = apR3.process_allpass_comb_lerp16(right, tr[2] + 54*lfo, rdec[2]);
+    right = apR4.process_allpass_comb_lerp16(right, tr[3] - 69*lfo, rdec[3]);
+    right = apR5.process_allpass_comb_lerp16(right, tr[4] + 69*lfo, rdec[4]);
+    right = apR6.process_allpass_comb_lerp16(right, tr[5] - 46*lfo, rdec[5]);
+    old_right = lp_right.process(right * fb);
+    sanitize(old_right);
+    
+    left = out_left, right = out_right;
+}
+
 /// Distortion Module by Tom Szilagyi
 ///
 /// This module provides a blendable saturation stage
@@ -305,3 +415,118 @@ float tap_distortion::get_distortion_level()
 {
     return meter;
 }
+
+////////////////////////////////////////////////////////////////////////////////
+
+simple_lfo::simple_lfo()
+{
+    is_active       = false;
+    phase = 0.f;
+}
+
+void simple_lfo::activate()
+{
+    is_active = true;
+    phase = 0.f;
+}
+
+void simple_lfo::deactivate()
+{
+    is_active = false;
+}
+
+float simple_lfo::get_value()
+{
+    return get_value_from_phase(phase, offset) * amount;
+}
+
+float simple_lfo::get_value_from_phase(float ph, float off) const
+{
+    float val = 0.f;
+    float phs = ph + off;
+    if (phs >= 1.0)
+        phs = fmod(phs, 1.f);
+    switch (mode) {
+        default:
+        case 0:
+            // sine
+            val = sin((phs * 360.f) * M_PI / 180);
+            break;
+        case 1:
+            // triangle
+            if(phs > 0.75)
+                val = (phs - 0.75) * 4 - 1;
+            else if(phs > 0.5)
+                val = (phs - 0.5) * 4 * -1;
+            else if(phs > 0.25)
+                val = 1 - (phs - 0.25) * 4;
+            else
+                val = phs * 4;
+            break;
+        case 2:
+            // square
+            val = (phs < 0.5) ? -1 : +1;
+            break;
+        case 3:
+            // saw up
+                val = phs * 2.f - 1;
+            break;
+        case 4:
+            // saw down
+            val = 1 - phs * 2.f;
+            break;
+    }
+    return val;
+}
+
+void simple_lfo::advance(uint32_t count)
+{
+    //this function walks from 0.f to 1.f and starts all over again
+    phase += count * freq * (1.0 / srate);
+    if (phase >= 1.0)
+        phase = fmod(phase, 1.f);
+}
+
+void simple_lfo::set_phase(float ph)
+{
+    //set the phase from outsinde
+    phase = fabs(ph);
+    if (phase >= 1.0)
+        phase = fmod(phase, 1.f);
+}
+
+void simple_lfo::set_params(float f, int m, float o, uint32_t sr, float a)
+{
+    // freq: a value in Hz
+    // mode: sine=0, triangle=1, square=2, saw_up=3, saw_down=4
+    // offset: value between 0.f and 1.f to offset the lfo in time
+    freq = f;
+    mode = m;
+    offset = o;
+    srate = sr;
+    amount = a;
+}
+
+bool simple_lfo::get_graph(float *data, int points, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    for (int i = 0; i < points; i++) {
+        float ph = (float)i / (float)points;
+        data[i] = get_value_from_phase(ph, offset) * amount;
+    }
+    return true;
+}
+
+bool simple_lfo::get_dot(float &x, float &y, int &size, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    float phs = phase + offset;
+    if (phs >= 1.0)
+        phs = fmod(phs, 1.f);
+    x = phase;
+    y = get_value_from_phase(phase, offset) * amount;
+    return true;
+}
+
diff --git a/src/benchmark.cpp b/src/benchmark.cpp
index bdc61b3..28071c4 100644
--- a/src/benchmark.cpp
+++ b/src/benchmark.cpp
@@ -24,6 +24,8 @@
 #include <calf/giface.h>
 #include <calf/modules.h>
 #include <calf/modules_dev.h>
+#include <calf/modules_eq.h>
+#include <calf/modules_mod.h>
 #else
 #include <config.h>
 #endif
@@ -377,7 +379,7 @@ void reverbir_calc()
     
     for (int t = 1; t < 38; t++)
     {
-        dsp::reverb<float> rvb;
+        dsp::reverb rvb;
         
         memset(data, 0, sizeof(data));
         data[0][0] = 1;
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index a67bc2d..6c2900f 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -5,6 +5,8 @@ noinst_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h custom_ctl.h \
     lv2_contexts.h lv2_data_access.h lv2_event.h lv2_external_ui.h \
     lv2_progress.h lv2_polymorphic_port.h lv2_string_port.h lv2_ui.h \
     lv2_uri_map.h lv2-midiport.h lv2helpers.h lv2wrap.h \
-    main_win.h metadata.h modmatrix.h modules.h modules_dev.h modules_synths.h modulelist.h \
+    main_win.h metadata.h modmatrix.h \
+    modules.h modules_dev.h modules_dist.h modules_eq.h modules_mod.h modules_synths.h \
+    modulelist.h \
     multichorus.h onepole.h organ.h osc.h osctl.h osctlnet.h osctl_glib.h preset.h \
     preset_gui.h primitives.h session_mgr.h synth.h utils.h vumeter.h wave.h waveshaping.h
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index 28215e7..b9e5012 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -1,7 +1,7 @@
 /* Calf DSP Library
  * Reusable audio effect classes.
  *
- * Copyright (C) 2001-2007 Krzysztof Foltman
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,8 +18,8 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  * Boston, MA  02110-1301  USA
  */
-#ifndef __CALF_AUDIOFX_H
-#define __CALF_AUDIOFX_H
+#ifndef CALF_AUDIOFX_H
+#define CALF_AUDIOFX_H
 
 #include "biquad.h"
 #include "delay.h"
@@ -28,6 +28,10 @@
 #include "onepole.h"
 #include <complex>
 
+namespace calf_plugins {
+    struct cairo_iface;
+};
+
 namespace dsp {
 #if 0
 }; to keep editor happy
@@ -336,15 +340,14 @@ public:
  * Just started implementing it, so there is no control over many
  * parameters.
  */
-template<class T>
 class reverb: public audio_effect
 {
-    simple_delay<2048, T> apL1, apL2, apL3, apL4, apL5, apL6;
-    simple_delay<2048, T> apR1, apR2, apR3, apR4, apR5, apR6;
+    simple_delay<2048, float> apL1, apL2, apL3, apL4, apL5, apL6;
+    simple_delay<2048, float> apR1, apR2, apR3, apR4, apR5, apR6;
     fixed_point<unsigned int, 25> phase, dphase;
     sine_table<int, 128, 10000> sine;
-    onepole<T> lp_left, lp_right;
-    T old_left, old_right;
+    onepole<float> lp_left, lp_right;
+    float old_left, old_right;
     int type;
     float time, fb, cutoff, diffusion;
     int tl[6], tr[6];
@@ -369,67 +372,7 @@ public:
         dphase = 0.5*128/sr;
         update_times();
     }
-    void update_times()
-    {
-        switch(type)
-        {
-        case 0:
-            tl[0] =  397 << 16, tr[0] =  383 << 16;
-            tl[1] =  457 << 16, tr[1] =  429 << 16;
-            tl[2] =  549 << 16, tr[2] =  631 << 16;
-            tl[3] =  649 << 16, tr[3] =  756 << 16;
-            tl[4] =  773 << 16, tr[4] =  803 << 16;
-            tl[5] =  877 << 16, tr[5] =  901 << 16;
-            break;
-        case 1:
-            tl[0] =  697 << 16, tr[0] =  783 << 16;
-            tl[1] =  957 << 16, tr[1] =  929 << 16;
-            tl[2] =  649 << 16, tr[2] =  531 << 16;
-            tl[3] = 1049 << 16, tr[3] = 1177 << 16;
-            tl[4] =  473 << 16, tr[4] =  501 << 16;
-            tl[5] =  587 << 16, tr[5] =  681 << 16;
-            break;
-        case 2:
-        default:
-            tl[0] =  697 << 16, tr[0] =  783 << 16;
-            tl[1] =  957 << 16, tr[1] =  929 << 16;
-            tl[2] =  649 << 16, tr[2] =  531 << 16;
-            tl[3] = 1249 << 16, tr[3] = 1377 << 16;
-            tl[4] = 1573 << 16, tr[4] = 1671 << 16;
-            tl[5] = 1877 << 16, tr[5] = 1781 << 16;
-            break;
-        case 3:
-            tl[0] = 1097 << 16, tr[0] = 1087 << 16;
-            tl[1] = 1057 << 16, tr[1] = 1031 << 16;
-            tl[2] = 1049 << 16, tr[2] = 1039 << 16;
-            tl[3] = 1083 << 16, tr[3] = 1055 << 16;
-            tl[4] = 1075 << 16, tr[4] = 1099 << 16;
-            tl[5] = 1003 << 16, tr[5] = 1073 << 16;
-            break;
-        case 4:
-            tl[0] =  197 << 16, tr[0] =  133 << 16;
-            tl[1] =  357 << 16, tr[1] =  229 << 16;
-            tl[2] =  549 << 16, tr[2] =  431 << 16;
-            tl[3] =  949 << 16, tr[3] = 1277 << 16;
-            tl[4] = 1173 << 16, tr[4] = 1671 << 16;
-            tl[5] = 1477 << 16, tr[5] = 1881 << 16;
-            break;
-        case 5:
-            tl[0] =  197 << 16, tr[0] =  133 << 16;
-            tl[1] =  257 << 16, tr[1] =  179 << 16;
-            tl[2] =  549 << 16, tr[2] =  431 << 16;
-            tl[3] =  619 << 16, tr[3] =  497 << 16;
-            tl[4] = 1173 << 16, tr[4] = 1371 << 16;
-            tl[5] = 1577 << 16, tr[5] = 1881 << 16;
-            break;
-        }
-        
-        float fDec=1000 + 2400.f * diffusion;
-        for (int i = 0 ; i < 6; i++) {
-            ldec[i]=exp(-float(tl[i] >> 16) / fDec), 
-            rdec[i]=exp(-float(tr[i] >> 16) / fDec);
-        }
-    }
+    void update_times();
     float get_time() const {
         return time;
     }
@@ -473,49 +416,8 @@ public:
         lp_left.set_lp(cutoff,sr);
         lp_right.set_lp(cutoff,sr);
     }
-    void reset()
-    {
-        apL1.reset();apR1.reset();
-        apL2.reset();apR2.reset();
-        apL3.reset();apR3.reset();
-        apL4.reset();apR4.reset();
-        apL5.reset();apR5.reset();
-        apL6.reset();apR6.reset();
-        lp_left.reset();lp_right.reset();
-        old_left = 0; old_right = 0;
-    }
-    void process(T &left, T &right)
-    {
-        unsigned int ipart = phase.ipart();
-        
-        // the interpolated LFO might be an overkill here
-        int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]) >> 2;
-        phase += dphase;
-        
-        left += old_right;
-        left = apL1.process_allpass_comb_lerp16(left, tl[0] - 45*lfo, ldec[0]);
-        left = apL2.process_allpass_comb_lerp16(left, tl[1] + 47*lfo, ldec[1]);
-        float out_left = left;
-        left = apL3.process_allpass_comb_lerp16(left, tl[2] + 54*lfo, ldec[2]);
-        left = apL4.process_allpass_comb_lerp16(left, tl[3] - 69*lfo, ldec[3]);
-        left = apL5.process_allpass_comb_lerp16(left, tl[4] + 69*lfo, ldec[4]);
-        left = apL6.process_allpass_comb_lerp16(left, tl[5] - 46*lfo, ldec[5]);
-        old_left = lp_left.process(left * fb);
-        sanitize(old_left);
-
-        right += old_left;
-        right = apR1.process_allpass_comb_lerp16(right, tr[0] - 45*lfo, rdec[0]);
-        right = apR2.process_allpass_comb_lerp16(right, tr[1] + 47*lfo, rdec[1]);
-        float out_right = right;
-        right = apR3.process_allpass_comb_lerp16(right, tr[2] + 54*lfo, rdec[2]);
-        right = apR4.process_allpass_comb_lerp16(right, tr[3] - 69*lfo, rdec[3]);
-        right = apR5.process_allpass_comb_lerp16(right, tr[4] + 69*lfo, rdec[4]);
-        right = apR6.process_allpass_comb_lerp16(right, tr[5] - 46*lfo, rdec[5]);
-        old_right = lp_right.process(right * fb);
-        sanitize(old_right);
-        
-        left = out_left, right = out_right;
-    }
+    void reset();
+    void process(float &left, float &right);
     void extra_sanitize()
     {
         lp_left.sanitize();
@@ -641,6 +543,28 @@ public:
     }
 };
 
+/// LFO module by Markus
+/// This module provides simple LFO's (sine=0, triangle=1, square=2, saw_up=3, saw_down=4)
+/// get_value() returns a value between -1 and 1
+class simple_lfo {
+private:
+    float phase, freq, offset, amount;
+    int mode;
+    uint32_t srate;
+    bool is_active;
+public:
+    simple_lfo();
+    void set_params(float f, int m, float o, uint32_t sr, float amount = 1.f);
+    float get_value();
+    void advance(uint32_t count);
+    void set_phase(float ph);
+    void activate();
+    void deactivate();
+    float get_value_from_phase(float ph, float off) const;
+    bool get_graph(float *data, int points, calf_plugins::cairo_iface *context) const;
+    bool get_dot(float &x, float &y, int &size, calf_plugins::cairo_iface *context) const;
+};
+
 #if 0
 { to keep editor happy
 #endif
diff --git a/src/calf/giface.h b/src/calf/giface.h
index cfee528..1340a0d 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -1,7 +1,7 @@
 /* Calf DSP Library
  * Common plugin interface definitions (shared between LADSPA/LV2/DSSI/standalone).
  *
- * Copyright (C) 2007 Krzysztof Foltman
+ * Copyright (C) 2007-2010 Krzysztof Foltman
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -671,6 +671,14 @@ static inline float dB_grid_inv(float pos)
     return pow(256.0, pos - 0.4);
 }
 
+/// Line graph interface implementation for frequency response graphs
+class frequency_response_line_graph: public line_graph_iface 
+{
+public:
+    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+    virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
+};
+
 /// set drawing color based on channel index (0 or 1)
 void set_channel_color(cairo_iface *context, int channel);
 
diff --git a/src/calf/modules.h b/src/calf/modules.h
index f66d4c2..7c1235f 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -1,7 +1,7 @@
-/* Calf DSP Library
- * Example audio modules
+/* Calf DSP plugin pack
+ * Assorted plugins
  *
- * Copyright (C) 2001-2007 Krzysztof Foltman
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,15 +18,14 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  * Boston, MA 02111-1307, USA.
  */
-#ifndef __CALF_MODULES_H
-#define __CALF_MODULES_H
+#ifndef CALF_MODULES_H
+#define CALF_MODULES_H
 
 #include <assert.h>
 #include <limits.h>
 #include "biquad.h"
 #include "inertia.h"
 #include "audio_fx.h"
-#include "multichorus.h"
 #include "giface.h"
 #include "metadata.h"
 #include "loudness.h"
@@ -34,78 +33,16 @@
 
 namespace calf_plugins {
 
-using namespace dsp;
-
 struct ladspa_plugin_info;
 
-class frequency_response_line_graph: public line_graph_iface 
-{
-public:
-    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
-    virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
-};
-
-class flanger_audio_module: public audio_module<flanger_metadata>, public frequency_response_line_graph
-{
-public:
-    dsp::simple_flanger<float, 2048> left, right;
-    uint32_t srate;
-    bool clear_reset;
-    float last_r_phase;
-    bool is_active;
-public:
-    flanger_audio_module() {
-        is_active = false;
-    }
-    void set_sample_rate(uint32_t sr);
-    void params_changed();
-    void params_reset();
-    void activate();
-    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
-    }
-    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
-    float freq_gain(int subindex, float freq, float srate) const;
-};
-
-class phaser_audio_module: public audio_module<phaser_metadata>, public frequency_response_line_graph
-{
-public:
-    enum { MaxStages = 12 };
-    uint32_t srate;
-    bool clear_reset;
-    float last_r_phase;
-    dsp::simple_phaser left, right;
-    float x1vals[2][MaxStages], y1vals[2][MaxStages];
-    bool is_active;
-public:
-    phaser_audio_module();
-    void params_changed();
-    void params_reset();
-    void activate();
-    void set_sample_rate(uint32_t sr);
-    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
-    }
-    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
-    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
-    float freq_gain(int subindex, float freq, float srate) const;
-};
-
 class reverb_audio_module: public audio_module<reverb_metadata>
 {
 public:    
-    dsp::reverb<float> reverb;
-    dsp::simple_delay<16384, stereo_sample<float> > pre_delay;
+    dsp::reverb reverb;
+    dsp::simple_delay<16384, dsp::stereo_sample<float> > pre_delay;
     dsp::onepole<float> left_lo, right_lo, left_hi, right_hi;
     uint32_t srate;
-    gain_smoothing amount, dryamount;
+    dsp::gain_smoothing amount, dryamount;
     int predelay_amt;
     float meter_wet, meter_out;
     uint32_t clip;
@@ -128,7 +65,7 @@ public:
     /// number of table entries written (value is only important when it is less than MAX_DELAY, which means that the buffer hasn't been totally filled yet)
     int age;
     
-    gain_smoothing amt_left, amt_right, fb_left, fb_right, dry;
+    dsp::gain_smoothing amt_left, amt_right, fb_left, fb_right, dry;
     
     dsp::biquad_d2<float> biquad_left[2], biquad_right[2];
     
@@ -144,52 +81,6 @@ public:
     uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
 };
 
-class rotary_speaker_audio_module: public audio_module<rotary_speaker_metadata>
-{
-public:
-    /// Current phases and phase deltas for bass and treble rotors
-    uint32_t phase_l, dphase_l, phase_h, dphase_h;
-    dsp::simple_delay<1024, float> delay;
-    dsp::biquad_d2<float> crossover1l, crossover1r, crossover2l, crossover2r;
-    dsp::simple_delay<8, float> phaseshift;
-    uint32_t srate;
-    int vibrato_mode;
-    /// Current CC1 (Modulation) value, normalized to [0, 1]
-    float mwhl_value;
-    /// Current CC64 (Hold) value, normalized to [0, 1]
-    float hold_value;
-    /// Current rotation speed for bass rotor - automatic mode
-    float aspeed_l;
-    /// Current rotation speed for treble rotor - automatic mode
-    float aspeed_h;
-    /// Desired speed (0=slow, 1=fast) - automatic mode
-    float dspeed;
-    /// Current rotation speed for bass rotor - manual mode
-    float maspeed_l;
-    /// Current rotation speed for treble rotor - manual mode
-    float maspeed_h;
-    
-    int meter_l, meter_h;
-    
-    rotary_speaker_audio_module();
-    void set_sample_rate(uint32_t sr);
-    void setup();
-    void activate();
-    void deactivate();
-    
-    void params_changed();
-    void set_vibrato();
-    /// Convert RPM speed to delta-phase
-    uint32_t rpm2dphase(float rpm);
-    /// Set delta-phase variables based on current calculated (and interpolated) RPM speed
-    void update_speed();
-    void update_speed_manual(float delta);
-    /// Increase or decrease aspeed towards raspeed, with required negative and positive rate
-    bool incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc);
-    uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-    virtual void control_change(int ctl, int val);
-};
-
 template<typename FilterClass, typename Metadata>
 class filter_module_with_inertia: public audio_module<Metadata>, public FilterClass
 {
@@ -200,15 +91,15 @@ public:
     using audio_module<Metadata>::outs;
     using audio_module<Metadata>::params;
     
-    inertia<exponential_ramp> inertia_cutoff, inertia_resonance, inertia_gain;
-    once_per_n timer;
+    dsp::inertia<dsp::exponential_ramp> inertia_cutoff, inertia_resonance, inertia_gain;
+    dsp::once_per_n timer;
     bool is_active;    
     mutable volatile int last_generation, last_calculated_generation;
     
     filter_module_with_inertia(float **ins, float **outs, float **params)
-    : inertia_cutoff(exponential_ramp(128), 20)
-    , inertia_resonance(exponential_ramp(128), 20)
-    , inertia_gain(exponential_ramp(128), 1.0)
+    : inertia_cutoff(dsp::exponential_ramp(128), 20)
+    , inertia_resonance(dsp::exponential_ramp(128), 20)
+    , inertia_gain(dsp::exponential_ramp(128), 1.0)
     , timer(128)
     {
         is_active = false;
@@ -252,7 +143,7 @@ public:
     {
         params_changed();
         FilterClass::filter_activate();
-        timer = once_per_n(FilterClass::srate / 1000);
+        timer = dsp::once_per_n(FilterClass::srate / 1000);
         timer.start();
         is_active = true;
     }
@@ -296,13 +187,13 @@ public:
 
 /// biquad filter module
 class filter_audio_module: 
-    public filter_module_with_inertia<biquad_filter_module, filter_metadata>, 
+    public filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>, 
     public frequency_response_line_graph
 {
     mutable float old_cutoff, old_resonance, old_mode;
 public:    
     filter_audio_module()
-    : filter_module_with_inertia<biquad_filter_module, filter_metadata>(ins, outs, params)
+    : filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>(ins, outs, params)
     {
         last_generation = 0;
     }
@@ -317,29 +208,6 @@ public:
     int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
 };
 
-/// A multitap stereo chorus thing - processing
-class multichorus_audio_module: public audio_module<multichorus_metadata>, public frequency_response_line_graph
-{
-public:
-    uint32_t srate;
-    dsp::multichorus<float, sine_multi_lfo<float, 8>, filter_sum<dsp::biquad_d2<>, dsp::biquad_d2<> >, 4096> left, right;
-    float last_r_phase;
-    float cutoff;
-    bool is_active;
-    
-public:    
-    multichorus_audio_module();
-    void params_changed();
-    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-    void activate();
-    void deactivate();
-    void set_sample_rate(uint32_t sr);
-    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
-    float freq_gain(int subindex, float freq, float srate) const;
-    bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
-    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
-};
-
 /// Not a true _audio_module style class, just pretends to be one!
 class gain_reduction_audio_module
 {
@@ -418,7 +286,7 @@ private:
     uint32_t clip_in, clip_out;
     float meter_in, meter_out;
     gain_reduction_audio_module compressor;
-    biquad_d2<float> f1L, f1R, f2L, f2R;
+    dsp::biquad_d2<float> f1L, f1R, f2L, f2R;
 public:
     typedef std::complex<double> cfloat;
     uint32_t srate;
@@ -478,7 +346,7 @@ private:
     float detected, clip_out;
     uint32_t clip_led;
     gain_reduction_audio_module compressor;
-    biquad_d2<float> hpL, hpR, lpL, lpR, pL, pR;
+    dsp::biquad_d2<float> hpL, hpR, lpL, lpR, pL, pR;
 public:
     uint32_t srate;
     bool is_active;
@@ -498,173 +366,9 @@ public:
     int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
 };
 
-/// Equalizer N Band by Markus Schmidt (based on Krzysztof's filters)
-template<class BaseClass, bool has_lphp>
-class equalizerNband_audio_module: public audio_module<BaseClass>, public frequency_response_line_graph {
-public:
-    typedef audio_module<BaseClass> AM;
-    using AM::ins;
-    using AM::outs;
-    using AM::params;
-    using AM::in_count;
-    using AM::out_count;
-    using AM::param_count;
-    using AM::PeakBands;
-private:
-    enum { graph_param_count = BaseClass::last_graph_param - BaseClass::first_graph_param + 1, params_per_band = AM::param_p2_active - AM::param_p1_active };
-    float hp_mode_old, hp_freq_old;
-    float lp_mode_old, lp_freq_old;
-    float ls_level_old, ls_freq_old;
-    float hs_level_old, hs_freq_old;
-    float p_level_old[PeakBands], p_freq_old[PeakBands], p_q_old[PeakBands];
-    mutable float old_params_for_graph[graph_param_count];
-    uint32_t clip_inL, clip_outL, clip_inR, clip_outR;
-    float meter_inL, meter_outL, meter_inR, meter_outR;
-    CalfEqMode hp_mode, lp_mode;
-    biquad_d2<float> hp[3][2], lp[3][2];
-    biquad_d2<float> lsL, lsR, hsL, hsR;
-    biquad_d2<float> pL[PeakBands], pR[PeakBands];
-    
-    inline void process_hplp(float &left, float &right);
-public:
-    typedef std::complex<double> cfloat;
-    uint32_t srate;
-    bool is_active;
-    mutable volatile int last_generation, last_calculated_generation;
-    equalizerNband_audio_module();
-    void activate();
-    void deactivate();
-
-    void params_changed();
-    float freq_gain(int index, double freq, uint32_t sr) const;
-    void set_sample_rate(uint32_t sr)
-    {
-        srate = sr;
-    }
-    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
-    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
-    int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
-};
-
-typedef equalizerNband_audio_module<equalizer5band_metadata, false> equalizer5band_audio_module;
-typedef equalizerNband_audio_module<equalizer8band_metadata, true> equalizer8band_audio_module;
-typedef equalizerNband_audio_module<equalizer12band_metadata, true> equalizer12band_audio_module;
-
-/// LFO by Markus
-class lfo_audio_module {
-private:
-    float phase, freq, offset, amount;
-    int mode;
-    uint32_t srate;
-    bool is_active;
-public:
-    lfo_audio_module();
-    void set_params(float f, int m, float o, uint32_t sr, float amount = 1.f);
-    float get_value();
-    void advance(uint32_t count);
-    void set_phase(float ph);
-    void activate();
-    void deactivate();
-    float get_value_from_phase(float ph, float off) const;
-    virtual bool get_graph(float *data, int points, cairo_iface *context) const;
-    virtual bool get_dot(float &x, float &y, int &size, cairo_iface *context) const;
-};
-
-/// Pulsator by Markus Schmidt
-class pulsator_audio_module: public audio_module<pulsator_metadata>, public frequency_response_line_graph  {
-private:
-    typedef pulsator_audio_module AM;
-    uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
-    float meter_inL, meter_inR, meter_outL, meter_outR;
-    float offset_old;
-    int mode_old;
-    bool clear_reset;
-    lfo_audio_module lfoL, lfoR;
-public:
-    uint32_t srate;
-    bool is_active;
-    pulsator_audio_module();
-    void activate();
-    void deactivate();
-    void params_changed();
-    void set_sample_rate(uint32_t sr);
-    void params_reset()
-    {
-        if (clear_reset) {
-            *params[param_reset] = 0.f;
-            clear_reset = false;
-        }
-    }
-    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
-    bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
-    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
-};
-
-/// Saturator by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
-class saturator_audio_module: public audio_module<saturator_metadata> {
-private:
-    float hp_pre_freq_old, lp_pre_freq_old;
-    float hp_post_freq_old, lp_post_freq_old;
-    float p_level_old, p_freq_old, p_q_old;
-    uint32_t clip_in, clip_out;
-    float meter_in, meter_out, meter_drive;
-    biquad_d2<float> lp[2][4], hp[2][4];
-    biquad_d2<float> p[2];
-    tap_distortion dist[2];
-public:
-    uint32_t srate;
-    bool is_active;
-    saturator_audio_module();
-    void activate();
-    void deactivate();
-    void params_changed();
-    void set_sample_rate(uint32_t sr);
-    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-};
-
-/// Exciter by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
-class exciter_audio_module: public audio_module<exciter_metadata> {
-private:
-    float freq_old;
-    uint32_t clip_in, clip_out;
-    float meter_in, meter_out, meter_drive;
-    biquad_d2<float> hp[2][4];
-    tap_distortion dist[2];
-public:
-    uint32_t srate;
-    bool is_active;
-    exciter_audio_module();
-    void activate();
-    void deactivate();
-    void params_changed();
-    void set_sample_rate(uint32_t sr);
-    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-};
-
-/// Bass Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
-class bassenhancer_audio_module: public audio_module<bassenhancer_metadata> {
-private:
-    float freq_old;
-    uint32_t clip_in, clip_out;
-    float meter_in, meter_out, meter_drive;
-    biquad_d2<float> lp[2][4];
-    tap_distortion dist[2];
-public:
-    uint32_t srate;
-    bool is_active;
-    bassenhancer_audio_module();
-    void activate();
-    void deactivate();
-    void params_changed();
-    void set_sample_rate(uint32_t sr);
-    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
-};
-
 /// Filterclavier --- MIDI controlled filter by Hans Baier
 class filterclavier_audio_module: 
-        public filter_module_with_inertia<biquad_filter_module, filterclavier_metadata>, 
+        public filter_module_with_inertia<dsp::biquad_filter_module, filterclavier_metadata>, 
         public frequency_response_line_graph
 {        
     using audio_module<filterclavier_metadata>::ins;
@@ -696,6 +400,4 @@ private:
 
 };
 
-#include "modules_synths.h"
-
 #endif
diff --git a/src/calf/modules_dist.h b/src/calf/modules_dist.h
new file mode 100644
index 0000000..6c49c37
--- /dev/null
+++ b/src/calf/modules_dist.h
@@ -0,0 +1,96 @@
+/* Calf DSP plugin pack
+ * Distortion related plugins
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
+ *
+ * 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., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef CALF_MODULES_DIST_H
+#define CALF_MODULES_DIST_H
+
+#include <assert.h>
+#include <limits.h>
+#include "biquad.h"
+#include "inertia.h"
+#include "audio_fx.h"
+#include "giface.h"
+#include "metadata.h"
+
+namespace calf_plugins {
+
+/// Saturator by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
+class saturator_audio_module: public audio_module<saturator_metadata> {
+private:
+    float hp_pre_freq_old, lp_pre_freq_old;
+    float hp_post_freq_old, lp_post_freq_old;
+    float p_level_old, p_freq_old, p_q_old;
+    uint32_t clip_in, clip_out;
+    float meter_in, meter_out, meter_drive;
+    dsp::biquad_d2<float> lp[2][4], hp[2][4];
+    dsp::biquad_d2<float> p[2];
+    dsp::tap_distortion dist[2];
+public:
+    uint32_t srate;
+    bool is_active;
+    saturator_audio_module();
+    void activate();
+    void deactivate();
+    void params_changed();
+    void set_sample_rate(uint32_t sr);
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+};
+
+/// Exciter by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
+class exciter_audio_module: public audio_module<exciter_metadata> {
+private:
+    float freq_old;
+    uint32_t clip_in, clip_out;
+    float meter_in, meter_out, meter_drive;
+    dsp::biquad_d2<float> hp[2][4];
+    dsp::tap_distortion dist[2];
+public:
+    uint32_t srate;
+    bool is_active;
+    exciter_audio_module();
+    void activate();
+    void deactivate();
+    void params_changed();
+    void set_sample_rate(uint32_t sr);
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+};
+
+/// Bass Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
+class bassenhancer_audio_module: public audio_module<bassenhancer_metadata> {
+private:
+    float freq_old;
+    uint32_t clip_in, clip_out;
+    float meter_in, meter_out, meter_drive;
+    dsp::biquad_d2<float> lp[2][4];
+    dsp::tap_distortion dist[2];
+public:
+    uint32_t srate;
+    bool is_active;
+    bassenhancer_audio_module();
+    void activate();
+    void deactivate();
+    void params_changed();
+    void set_sample_rate(uint32_t sr);
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+};
+
+};
+
+#endif
diff --git a/src/calf/modules_eq.h b/src/calf/modules_eq.h
new file mode 100644
index 0000000..14cad3c
--- /dev/null
+++ b/src/calf/modules_eq.h
@@ -0,0 +1,89 @@
+/* Calf DSP plugin pack
+ * Equalization related plugins
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
+ *
+ * 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., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef CALF_MODULES_EQ_H
+#define CALF_MODULES_EQ_H
+
+#include <assert.h>
+#include <limits.h>
+#include "biquad.h"
+#include "inertia.h"
+#include "audio_fx.h"
+#include "giface.h"
+#include "metadata.h"
+
+namespace calf_plugins {
+
+/// Equalizer N Band by Markus Schmidt (based on Krzysztof's filters)
+template<class BaseClass, bool has_lphp>
+class equalizerNband_audio_module: public audio_module<BaseClass>, public frequency_response_line_graph {
+public:
+    typedef audio_module<BaseClass> AM;
+    using AM::ins;
+    using AM::outs;
+    using AM::params;
+    using AM::in_count;
+    using AM::out_count;
+    using AM::param_count;
+    using AM::PeakBands;
+private:
+    enum { graph_param_count = BaseClass::last_graph_param - BaseClass::first_graph_param + 1, params_per_band = AM::param_p2_active - AM::param_p1_active };
+    float hp_mode_old, hp_freq_old;
+    float lp_mode_old, lp_freq_old;
+    float ls_level_old, ls_freq_old;
+    float hs_level_old, hs_freq_old;
+    float p_level_old[PeakBands], p_freq_old[PeakBands], p_q_old[PeakBands];
+    mutable float old_params_for_graph[graph_param_count];
+    uint32_t clip_inL, clip_outL, clip_inR, clip_outR;
+    float meter_inL, meter_outL, meter_inR, meter_outR;
+    CalfEqMode hp_mode, lp_mode;
+    dsp::biquad_d2<float> hp[3][2], lp[3][2];
+    dsp::biquad_d2<float> lsL, lsR, hsL, hsR;
+    dsp::biquad_d2<float> pL[PeakBands], pR[PeakBands];
+    
+    inline void process_hplp(float &left, float &right);
+public:
+    typedef std::complex<double> cfloat;
+    uint32_t srate;
+    bool is_active;
+    mutable volatile int last_generation, last_calculated_generation;
+    equalizerNband_audio_module();
+    void activate();
+    void deactivate();
+
+    void params_changed();
+    float freq_gain(int index, double freq, uint32_t sr) const;
+    void set_sample_rate(uint32_t sr)
+    {
+        srate = sr;
+    }
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
+    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+    int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
+};
+
+typedef equalizerNband_audio_module<equalizer5band_metadata, false> equalizer5band_audio_module;
+typedef equalizerNband_audio_module<equalizer8band_metadata, true> equalizer8band_audio_module;
+typedef equalizerNband_audio_module<equalizer12band_metadata, true> equalizer12band_audio_module;
+
+};
+
+#endif
diff --git a/src/calf/modules_mod.h b/src/calf/modules_mod.h
new file mode 100644
index 0000000..7824491
--- /dev/null
+++ b/src/calf/modules_mod.h
@@ -0,0 +1,190 @@
+/* Calf DSP plugin pack
+ * Modulation effect plugins
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
+ *
+ * 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., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef CALF_MODULES_MOD_H
+#define CALF_MODULES_MOD_H
+
+#include <assert.h>
+#include <limits.h>
+#include "biquad.h"
+#include "inertia.h"
+#include "audio_fx.h"
+#include "giface.h"
+#include "metadata.h"
+#include "multichorus.h"
+
+namespace calf_plugins {
+
+class flanger_audio_module: public audio_module<flanger_metadata>, public frequency_response_line_graph
+{
+public:
+    dsp::simple_flanger<float, 2048> left, right;
+    uint32_t srate;
+    bool clear_reset;
+    float last_r_phase;
+    bool is_active;
+public:
+    flanger_audio_module() {
+        is_active = false;
+    }
+    void set_sample_rate(uint32_t sr);
+    void params_changed();
+    void params_reset();
+    void activate();
+    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
+    }
+    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
+    float freq_gain(int subindex, float freq, float srate) const;
+};
+
+class phaser_audio_module: public audio_module<phaser_metadata>, public frequency_response_line_graph
+{
+public:
+    enum { MaxStages = 12 };
+    uint32_t srate;
+    bool clear_reset;
+    float last_r_phase;
+    dsp::simple_phaser left, right;
+    float x1vals[2][MaxStages], y1vals[2][MaxStages];
+    bool is_active;
+public:
+    phaser_audio_module();
+    void params_changed();
+    void params_reset();
+    void activate();
+    void set_sample_rate(uint32_t sr);
+    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
+    }
+    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
+    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+    float freq_gain(int subindex, float freq, float srate) const;
+};
+
+class rotary_speaker_audio_module: public audio_module<rotary_speaker_metadata>
+{
+public:
+    /// Current phases and phase deltas for bass and treble rotors
+    uint32_t phase_l, dphase_l, phase_h, dphase_h;
+    dsp::simple_delay<1024, float> delay;
+    dsp::biquad_d2<float> crossover1l, crossover1r, crossover2l, crossover2r;
+    dsp::simple_delay<8, float> phaseshift;
+    uint32_t srate;
+    int vibrato_mode;
+    /// Current CC1 (Modulation) value, normalized to [0, 1]
+    float mwhl_value;
+    /// Current CC64 (Hold) value, normalized to [0, 1]
+    float hold_value;
+    /// Current rotation speed for bass rotor - automatic mode
+    float aspeed_l;
+    /// Current rotation speed for treble rotor - automatic mode
+    float aspeed_h;
+    /// Desired speed (0=slow, 1=fast) - automatic mode
+    float dspeed;
+    /// Current rotation speed for bass rotor - manual mode
+    float maspeed_l;
+    /// Current rotation speed for treble rotor - manual mode
+    float maspeed_h;
+    
+    int meter_l, meter_h;
+    
+    rotary_speaker_audio_module();
+    void set_sample_rate(uint32_t sr);
+    void setup();
+    void activate();
+    void deactivate();
+    
+    void params_changed();
+    void set_vibrato();
+    /// Convert RPM speed to delta-phase
+    uint32_t rpm2dphase(float rpm);
+    /// Set delta-phase variables based on current calculated (and interpolated) RPM speed
+    void update_speed();
+    void update_speed_manual(float delta);
+    /// Increase or decrease aspeed towards raspeed, with required negative and positive rate
+    bool incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc);
+    uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+    virtual void control_change(int ctl, int val);
+};
+
+/// A multitap stereo chorus thing
+class multichorus_audio_module: public audio_module<multichorus_metadata>, public frequency_response_line_graph
+{
+public:
+    uint32_t srate;
+    dsp::multichorus<float, dsp::sine_multi_lfo<float, 8>, dsp::filter_sum<dsp::biquad_d2<>, dsp::biquad_d2<> >, 4096> left, right;
+    float last_r_phase;
+    float cutoff;
+    bool is_active;
+    
+public:    
+    multichorus_audio_module();
+    void params_changed();
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+    void activate();
+    void deactivate();
+    void set_sample_rate(uint32_t sr);
+    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
+    float freq_gain(int subindex, float freq, float srate) const;
+    bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
+    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+};
+
+/// Pulsator by Markus Schmidt
+class pulsator_audio_module: public audio_module<pulsator_metadata>, public frequency_response_line_graph  {
+private:
+    typedef pulsator_audio_module AM;
+    uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
+    float meter_inL, meter_inR, meter_outL, meter_outR;
+    float offset_old;
+    int mode_old;
+    bool clear_reset;
+    dsp::simple_lfo lfoL, lfoR;
+public:
+    uint32_t srate;
+    bool is_active;
+    pulsator_audio_module();
+    void activate();
+    void deactivate();
+    void params_changed();
+    void set_sample_rate(uint32_t sr);
+    void params_reset()
+    {
+        if (clear_reset) {
+            *params[param_reset] = 0.f;
+            clear_reset = false;
+        }
+    }
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
+    bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
+    bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+};
+
+};
+
+#endif
diff --git a/src/giface.cpp b/src/giface.cpp
index 9aa8934..8fe5037 100644
--- a/src/giface.cpp
+++ b/src/giface.cpp
@@ -1,7 +1,7 @@
 /* Calf DSP Library
- * Module wrapper methods.
+ * Implementation of various helpers for the plugin interface.
  *
- * Copyright (C) 2001-2007 Krzysztof Foltman
+ * Copyright (C) 2001-2010 Krzysztof Foltman
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,7 @@
  * Boston, MA  02110-1301  USA
  */
 #include <config.h>
+#include <limits.h>
 #include <calf/giface.h>
 #include <calf/osctlnet.h>
 #include <calf/utils.h>
@@ -291,6 +292,21 @@ void calf_plugins::set_channel_color(cairo_iface *context, int channel)
     context->set_line_width(1.5);
 }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{ 
+    return get_freq_gridline(subindex, pos, vertical, legend, context);
+}
+
+int frequency_response_line_graph::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
+{
+    subindex_graph = 0;
+    subindex_dot = 0;
+    subindex_gridline = generation ? INT_MAX : 0;
+    return 1;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////
 
 calf_plugins::plugin_registry &calf_plugins::plugin_registry::instance()
diff --git a/src/modules_dist.cpp b/src/modules_dist.cpp
new file mode 100644
index 0000000..aba40fc
--- /dev/null
+++ b/src/modules_dist.cpp
@@ -0,0 +1,738 @@
+/* Calf DSP plugin pack
+ * Distortion related plugins
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
+ *
+ * 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., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include <limits.h>
+#include <memory.h>
+#include <calf/giface.h>
+#include <calf/modules_dist.h>
+
+using namespace dsp;
+using namespace calf_plugins;
+
+#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
+
+/// Saturator Band by Markus Schmidt
+///
+/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
+/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+saturator_audio_module::saturator_audio_module()
+{
+    is_active = false;
+    srate = 0;
+    clip_in    = 0.f;
+    clip_out   = 0.f;
+    meter_in  = 0.f;
+    meter_out = 0.f;
+    meter_drive = 0.f;
+}
+
+void saturator_audio_module::activate()
+{
+    is_active = true;
+    // set all filters
+    params_changed();
+}
+void saturator_audio_module::deactivate()
+{
+    is_active = false;
+}
+
+void saturator_audio_module::params_changed()
+{
+    // set the params of all filters
+    if(*params[param_lp_pre_freq] != lp_pre_freq_old) {
+        lp[0][0].set_lp_rbj(*params[param_lp_pre_freq], 0.707, (float)srate);
+        if(in_count > 1 && out_count > 1)
+            lp[1][0].copy_coeffs(lp[0][0]);
+        lp[0][1].copy_coeffs(lp[0][0]);
+        if(in_count > 1 && out_count > 1)
+            lp[1][1].copy_coeffs(lp[0][0]);
+        lp_pre_freq_old = *params[param_lp_pre_freq];
+    }
+    if(*params[param_hp_pre_freq] != hp_pre_freq_old) {
+        hp[0][0].set_hp_rbj(*params[param_hp_pre_freq], 0.707, (float)srate);
+        if(in_count > 1 && out_count > 1)
+            hp[1][0].copy_coeffs(hp[0][0]);
+        hp[0][1].copy_coeffs(hp[0][0]);
+        if(in_count > 1 && out_count > 1)
+            hp[1][1].copy_coeffs(hp[0][0]);
+        hp_pre_freq_old = *params[param_hp_pre_freq];
+    }
+    if(*params[param_lp_post_freq] != lp_post_freq_old) {
+        lp[0][2].set_lp_rbj(*params[param_lp_post_freq], 0.707, (float)srate);
+        if(in_count > 1 && out_count > 1)
+            lp[1][2].copy_coeffs(lp[0][2]);
+        lp[0][3].copy_coeffs(lp[0][2]);
+        if(in_count > 1 && out_count > 1)
+            lp[1][3].copy_coeffs(lp[0][2]);
+        lp_post_freq_old = *params[param_lp_post_freq];
+    }
+    if(*params[param_hp_post_freq] != hp_post_freq_old) {
+        hp[0][2].set_hp_rbj(*params[param_hp_post_freq], 0.707, (float)srate);
+        if(in_count > 1 && out_count > 1)
+            hp[1][2].copy_coeffs(hp[0][2]);
+        hp[0][3].copy_coeffs(hp[0][2]);
+        if(in_count > 1 && out_count > 1)
+            hp[1][3].copy_coeffs(hp[0][2]);
+        hp_post_freq_old = *params[param_hp_post_freq];
+    }
+    if(*params[param_p_freq] != p_freq_old or *params[param_p_level] != p_level_old or *params[param_p_q] != p_q_old) {
+        p[0].set_peakeq_rbj((float)*params[param_p_freq], (float)*params[param_p_q], (float)*params[param_p_level], (float)srate);
+        if(in_count > 1 && out_count > 1)
+            p[1].copy_coeffs(p[0]);
+        p_freq_old = *params[param_p_freq];
+        p_level_old = *params[param_p_level];
+        p_q_old = *params[param_p_q];
+    }
+    // set distortion
+    dist[0].set_params(*params[param_blend], *params[param_drive]);
+    if(in_count > 1 && out_count > 1)
+        dist[1].set_params(*params[param_blend], *params[param_drive]);
+}
+
+void saturator_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    dist[0].set_sample_rate(sr);
+    if(in_count > 1 && out_count > 1)
+        dist[1].set_sample_rate(sr);
+}
+
+uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    bool bypass = *params[param_bypass] > 0.5f;
+    numsamples += offset;
+    if(bypass) {
+        // everything bypassed
+        while(offset < numsamples) {
+            if(in_count > 1 && out_count > 1) {
+                outs[0][offset] = ins[0][offset];
+                outs[1][offset] = ins[1][offset];
+            } else if(in_count > 1) {
+                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
+            } else if(out_count > 1) {
+                outs[0][offset] = ins[0][offset];
+                outs[1][offset] = ins[0][offset];
+            } else {
+                outs[0][offset] = ins[0][offset];
+            }
+            ++offset;
+        }
+        // displays, too
+        clip_in    = 0.f;
+        clip_out   = 0.f;
+        meter_in  = 0.f;
+        meter_out = 0.f;
+        meter_drive = 0.f;
+    } else {
+        
+        clip_in    -= std::min(clip_in,  numsamples);
+        clip_out   -= std::min(clip_out, numsamples);
+        meter_in = 0.f;
+        meter_out = 0.f;
+        meter_drive = 0.f;
+        float in_avg[2] = {0.f, 0.f};
+        float out_avg[2] = {0.f, 0.f};
+        float tube_avg = 0.f;
+        // process
+        while(offset < numsamples) {
+            // cycle through samples
+            float out[2], in[2] = {0.f, 0.f};
+            float maxIn, maxOut = 0.f;
+            int c = 0;
+            
+            if(in_count > 1 && out_count > 1) {
+                // stereo in/stereo out
+                // handle full stereo
+                in[0] = ins[0][offset];
+                in[1] = ins[1][offset];
+                c = 2;
+            } else {
+                // in and/or out mono
+                // handle mono
+                in[0] = ins[0][offset];
+                in[1] = in[0];
+                c = 1;
+            }
+            
+            float proc[2];
+            proc[0] = in[0] * *params[param_level_in];
+            proc[1] = in[1] * *params[param_level_in];
+            
+            for (int i = 0; i < c; ++i) {
+                // all pre filters in chain
+                proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
+                proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
+                
+                // get average for display purposes before...
+                in_avg[i] += fabs(pow(proc[i], 2.f));
+
+                // ...saturate...
+                proc[i] = dist[i].process(proc[i]);
+                
+                // ...and get average after...
+                out_avg[i] += fabs(pow(proc[i], 2.f));
+                
+                // tone control
+                proc[i] = p[i].process(proc[i]);
+
+                // all post filters in chain
+                proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
+                proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
+                
+                //subtract gain
+                 proc[i] /= *params[param_level_in];
+            }
+            
+            if(in_count > 1 && out_count > 1) {
+                // full stereo
+                out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                out[1] = ((proc[1] * *params[param_mix]) + in[1] * (1 - *params[param_mix])) * *params[param_level_out];
+                outs[1][offset] = out[1];
+                maxIn = std::max(fabs(in[0]), fabs(in[1]));
+                maxOut = std::max(fabs(out[0]), fabs(out[1]));
+            } else if(out_count > 1) {
+                // mono -> pseudo stereo
+                out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                out[1] = out[0];
+                outs[1][offset] = out[1];
+                maxOut = fabs(out[0]);
+                maxIn = fabs(in[0]);
+            } else {
+                // stereo -> mono
+                // or full mono
+                out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                maxIn = fabs(in[0]);
+                maxOut = fabs(out[0]);
+            }
+            
+            if(maxIn > 1.f) {
+                clip_in  = srate >> 3;
+            }
+            if(maxOut > 1.f) {
+                clip_out = srate >> 3;
+            }
+            // set up in / out meters
+            if(maxIn > meter_in) {
+                meter_in = maxIn;
+            }
+            if(maxOut > meter_out) {
+                meter_out = maxOut;
+            }
+            
+            // next sample
+            ++offset;
+        } // cycle trough samples
+        
+        tube_avg = (sqrt(std::max(out_avg[0], out_avg[1])) / numsamples) - (sqrt(std::max(in_avg[0], in_avg[1])) / numsamples);
+        meter_drive = (5.0f * fabs(tube_avg) * (float(*params[param_blend]) + 30.0f));
+        // printf("out:%.6f in: %.6f avg: %.6f drv: %.3f\n", sqrt(std::max(out_avg[0], out_avg[1])) / numsamples, sqrt(std::max(in_avg[0], in_avg[1])) / numsamples, tube_avg, meter_drive);
+        // clean up
+        lp[0][0].sanitize();
+        lp[1][0].sanitize();
+        lp[0][1].sanitize();
+        lp[1][1].sanitize();
+        lp[0][2].sanitize();
+        lp[1][2].sanitize();
+        lp[0][3].sanitize();
+        lp[1][3].sanitize();
+        hp[0][0].sanitize();
+        hp[1][0].sanitize();
+        hp[0][1].sanitize();
+        hp[1][1].sanitize();
+        hp[0][2].sanitize();
+        hp[1][2].sanitize();
+        hp[0][3].sanitize();
+        hp[1][3].sanitize();
+        p[0].sanitize();
+        p[1].sanitize();
+    }
+    // draw meters
+    if(params[param_clip_in] != NULL) {
+        *params[param_clip_in] = clip_in;
+    }
+    if(params[param_clip_out] != NULL) {
+        *params[param_clip_out] = clip_out;
+    }
+    
+    if(params[param_meter_in] != NULL) {
+        *params[param_meter_in] = meter_in;
+    }
+    if(params[param_meter_out] != NULL) {
+        *params[param_meter_out] = meter_out;
+    }
+    if(params[param_meter_drive] != NULL) {
+        *params[param_meter_drive] = meter_drive;
+    }
+    // whatever has to be returned x)
+    return outputs_mask;
+}
+
+/// Exciter by Markus Schmidt
+///
+/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
+/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+exciter_audio_module::exciter_audio_module()
+{
+    is_active = false;
+    srate = 0;
+    clip_in    = 0.f;
+    clip_out   = 0.f;
+    meter_in  = 0.f;
+    meter_out = 0.f;
+    meter_drive = 0.f;
+}
+
+void exciter_audio_module::activate()
+{
+    is_active = true;
+    // set all filters
+    params_changed();
+}
+
+void exciter_audio_module::deactivate()
+{
+    is_active = false;
+}
+
+void exciter_audio_module::params_changed()
+{
+    // set the params of all filters
+    if(*params[param_freq] != freq_old) {
+        hp[0][0].set_hp_rbj(*params[param_freq], 0.707, (float)srate);
+        hp[0][1].copy_coeffs(hp[0][0]);
+        hp[0][2].copy_coeffs(hp[0][0]);
+        hp[0][3].copy_coeffs(hp[0][0]);
+        if(in_count > 1 && out_count > 1) {
+            hp[1][0].copy_coeffs(hp[0][0]);
+            hp[1][1].copy_coeffs(hp[0][0]);
+            hp[1][2].copy_coeffs(hp[0][0]);
+            hp[1][3].copy_coeffs(hp[0][0]);
+        }
+        freq_old = *params[param_freq];
+    }
+    // set distortion
+    dist[0].set_params(*params[param_blend], *params[param_drive]);
+    if(in_count > 1 && out_count > 1)
+        dist[1].set_params(*params[param_blend], *params[param_drive]);
+}
+
+void exciter_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    dist[0].set_sample_rate(sr);
+    if(in_count > 1 && out_count > 1)
+        dist[1].set_sample_rate(sr);
+}
+
+uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    bool bypass = *params[param_bypass] > 0.5f;
+    numsamples += offset;
+    if(bypass) {
+        // everything bypassed
+        while(offset < numsamples) {
+            if(in_count > 1 && out_count > 1) {
+                outs[0][offset] = ins[0][offset];
+                outs[1][offset] = ins[1][offset];
+            } else if(in_count > 1) {
+                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
+            } else if(out_count > 1) {
+                outs[0][offset] = ins[0][offset];
+                outs[1][offset] = ins[0][offset];
+            } else {
+                outs[0][offset] = ins[0][offset];
+            }
+            ++offset;
+        }
+        // displays, too
+        clip_in    = 0.f;
+        clip_out   = 0.f;
+        meter_in  = 0.f;
+        meter_out = 0.f;
+        meter_drive = 0.f;
+    } else {
+        
+        clip_in    -= std::min(clip_in,  numsamples);
+        clip_out   -= std::min(clip_out, numsamples);
+        meter_in = 0.f;
+        meter_out = 0.f;
+        meter_drive = 0.f;
+        
+        // process
+        while(offset < numsamples) {
+            // cycle through samples
+            float out[2], in[2] = {0.f, 0.f};
+            float maxIn, maxOut, maxDrive = 0.f;
+            int c = 0;
+            
+            if(in_count > 1 && out_count > 1) {
+                // stereo in/stereo out
+                // handle full stereo
+                in[0] = ins[0][offset];
+                in[0] *= *params[param_level_in];
+                in[1] = ins[1][offset];
+                in[1] *= *params[param_level_in];
+                c = 2;
+            } else {
+                // in and/or out mono
+                // handle mono
+                in[0] = ins[0][offset];
+                in[0] *= *params[param_level_in];
+                in[1] = in[0];
+                c = 1;
+            }
+            
+            float proc[2];
+            proc[0] = in[0];
+            proc[1] = in[1];
+            
+            for (int i = 0; i < c; ++i) {
+                // all pre filters in chain
+                proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
+                
+                // saturate
+                proc[i] = dist[i].process(proc[i]);
+
+                // all post filters in chain
+                proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
+            }
+            
+            if(in_count > 1 && out_count > 1) {
+                // full stereo
+                if(*params[param_listen] > 0.f)
+                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                if(*params[param_listen] > 0.f)
+                    out[1] = proc[1] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out];
+                outs[1][offset] = out[1];
+                maxIn = std::max(fabs(in[0]), fabs(in[1]));
+                maxOut = std::max(fabs(out[0]), fabs(out[1]));
+                maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount],
+                                            dist[1].get_distortion_level() * *params[param_amount]);
+            } else if(out_count > 1) {
+                // mono -> pseudo stereo
+                if(*params[param_listen] > 0.f)
+                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                out[1] = out[0];
+                outs[1][offset] = out[1];
+                maxOut = fabs(out[0]);
+                maxIn = fabs(in[0]);
+                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
+            } else {
+                // stereo -> mono
+                // or full mono
+                if(*params[param_listen] > 0.f)
+                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                maxIn = fabs(in[0]);
+                maxOut = fabs(out[0]);
+                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
+            }
+            
+            if(maxIn > 1.f) {
+                clip_in  = srate >> 3;
+            }
+            if(maxOut > 1.f) {
+                clip_out = srate >> 3;
+            }
+            // set up in / out meters
+            if(maxIn > meter_in) {
+                meter_in = maxIn;
+            }
+            if(maxOut > meter_out) {
+                meter_out = maxOut;
+            }
+            if(maxDrive > meter_drive) {
+                meter_drive = maxDrive;
+            }
+            
+            // next sample
+            ++offset;
+        } // cycle trough samples
+        // clean up
+        hp[0][0].sanitize();
+        hp[1][0].sanitize();
+        hp[0][1].sanitize();
+        hp[1][1].sanitize();
+        hp[0][2].sanitize();
+        hp[1][2].sanitize();
+        hp[0][3].sanitize();
+        hp[1][3].sanitize();
+    }
+    // draw meters
+    if(params[param_clip_in] != NULL) {
+        *params[param_clip_in] = clip_in;
+    }
+    if(params[param_clip_out] != NULL) {
+        *params[param_clip_out] = clip_out;
+    }
+    
+    if(params[param_meter_in] != NULL) {
+        *params[param_meter_in] = meter_in;
+    }
+    if(params[param_meter_out] != NULL) {
+        *params[param_meter_out] = meter_out;
+    }
+    if(params[param_meter_drive] != NULL) {
+        *params[param_meter_drive] = meter_drive;
+    }
+    // whatever has to be returned x)
+    return outputs_mask;
+}
+
+/// Bass Enhancer by Markus Schmidt
+///
+/// This module is based on Krzysztof's filters and Tom's distortion routine.
+/// It sends the signal through a lowpass, saturates it and sends it through a lowpass again
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+bassenhancer_audio_module::bassenhancer_audio_module()
+{
+    is_active = false;
+    srate = 0;
+    clip_in    = 0.f;
+    clip_out   = 0.f;
+    meter_in  = 0.f;
+    meter_out = 0.f;
+    meter_drive = 0.f;
+}
+
+void bassenhancer_audio_module::activate()
+{
+    is_active = true;
+    // set all filters
+    params_changed();
+}
+void bassenhancer_audio_module::deactivate()
+{
+    is_active = false;
+}
+
+void bassenhancer_audio_module::params_changed()
+{
+    // set the params of all filters
+    if(*params[param_freq] != freq_old) {
+        lp[0][0].set_lp_rbj(*params[param_freq], 0.707, (float)srate);
+        lp[0][1].copy_coeffs(lp[0][0]);
+        lp[0][2].copy_coeffs(lp[0][0]);
+        lp[0][3].copy_coeffs(lp[0][0]);
+        if(in_count > 1 && out_count > 1) {
+            lp[1][0].copy_coeffs(lp[0][0]);
+            lp[1][1].copy_coeffs(lp[0][0]);
+            lp[1][2].copy_coeffs(lp[0][0]);
+            lp[1][3].copy_coeffs(lp[0][0]);
+        }
+        freq_old = *params[param_freq];
+    }
+    // set distortion
+    dist[0].set_params(*params[param_blend], *params[param_drive]);
+    if(in_count > 1 && out_count > 1)
+        dist[1].set_params(*params[param_blend], *params[param_drive]);
+}
+
+void bassenhancer_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    dist[0].set_sample_rate(sr);
+    if(in_count > 1 && out_count > 1)
+        dist[1].set_sample_rate(sr);
+}
+
+uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    bool bypass = *params[param_bypass] > 0.5f;
+    numsamples += offset;
+    if(bypass) {
+        // everything bypassed
+        while(offset < numsamples) {
+            if(in_count > 1 && out_count > 1) {
+                outs[0][offset] = ins[0][offset];
+                outs[1][offset] = ins[1][offset];
+            } else if(in_count > 1) {
+                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
+            } else if(out_count > 1) {
+                outs[0][offset] = ins[0][offset];
+                outs[1][offset] = ins[0][offset];
+            } else {
+                outs[0][offset] = ins[0][offset];
+            }
+            ++offset;
+        }
+        // displays, too
+        clip_in    = 0.f;
+        clip_out   = 0.f;
+        meter_in  = 0.f;
+        meter_out = 0.f;
+        meter_drive = 0.f;
+    } else {
+        
+        clip_in    -= std::min(clip_in,  numsamples);
+        clip_out   -= std::min(clip_out, numsamples);
+        meter_in = 0.f;
+        meter_out = 0.f;
+        meter_drive = 0.f;
+        
+        // process
+        while(offset < numsamples) {
+            // cycle through samples
+            float out[2], in[2] = {0.f, 0.f};
+            float maxIn, maxOut, maxDrive = 0.f;
+            int c = 0;
+            
+            if(in_count > 1 && out_count > 1) {
+                // stereo in/stereo out
+                // handle full stereo
+                in[0] = ins[0][offset];
+                in[0] *= *params[param_level_in];
+                in[1] = ins[1][offset];
+                in[1] *= *params[param_level_in];
+                c = 2;
+            } else {
+                // in and/or out mono
+                // handle mono
+                in[0] = ins[0][offset];
+                in[0] *= *params[param_level_in];
+                in[1] = in[0];
+                c = 1;
+            }
+            
+            float proc[2];
+            proc[0] = in[0];
+            proc[1] = in[1];
+            
+            for (int i = 0; i < c; ++i) {
+                // all pre filters in chain
+                proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
+                
+                // saturate
+                proc[i] = dist[i].process(proc[i]);
+
+                // all post filters in chain
+                proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
+            }
+            
+            if(in_count > 1 && out_count > 1) {
+                // full stereo
+                if(*params[param_listen] > 0.f)
+                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                if(*params[param_listen] > 0.f)
+                    out[1] = proc[1] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out];
+                outs[1][offset] = out[1];
+                maxIn = std::max(fabs(in[0]), fabs(in[1]));
+                maxOut = std::max(fabs(out[0]), fabs(out[1]));
+                maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount],
+                                            dist[1].get_distortion_level() * *params[param_amount]);
+            } else if(out_count > 1) {
+                // mono -> pseudo stereo
+                if(*params[param_listen] > 0.f)
+                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                out[1] = out[0];
+                outs[1][offset] = out[1];
+                maxOut = fabs(out[0]);
+                maxIn = fabs(in[0]);
+                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
+            } else {
+                // stereo -> mono
+                // or full mono
+                if(*params[param_listen] > 0.f)
+                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+                else
+                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+                outs[0][offset] = out[0];
+                maxIn = fabs(in[0]);
+                maxOut = fabs(out[0]);
+                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
+            }
+            
+            if(maxIn > 1.f) {
+                clip_in  = srate >> 3;
+            }
+            if(maxOut > 1.f) {
+                clip_out = srate >> 3;
+            }
+            // set up in / out meters
+            if(maxIn > meter_in) {
+                meter_in = maxIn;
+            }
+            if(maxOut > meter_out) {
+                meter_out = maxOut;
+            }
+            if(maxDrive > meter_drive) {
+                meter_drive = maxDrive;
+            }
+            
+            // next sample
+            ++offset;
+        } // cycle trough samples
+        // clean up
+        lp[0][0].sanitize();
+        lp[1][0].sanitize();
+        lp[0][1].sanitize();
+        lp[1][1].sanitize();
+        lp[0][2].sanitize();
+        lp[1][2].sanitize();
+        lp[0][3].sanitize();
+        lp[1][3].sanitize();
+    }
+    // draw meters
+    if(params[param_clip_in] != NULL) {
+        *params[param_clip_in] = clip_in;
+    }
+    if(params[param_clip_out] != NULL) {
+        *params[param_clip_out] = clip_out;
+    }
+    
+    if(params[param_meter_in] != NULL) {
+        *params[param_meter_in] = meter_in;
+    }
+    if(params[param_meter_out] != NULL) {
+        *params[param_meter_out] = meter_out;
+    }
+    if(params[param_meter_drive] != NULL) {
+        *params[param_meter_drive] = meter_drive;
+    }
+    // whatever has to be returned x)
+    return outputs_mask;
+}
diff --git a/src/modules_dsp.cpp b/src/modules_dsp.cpp
index a8a2c74..45e5d97 100644
--- a/src/modules_dsp.cpp
+++ b/src/modules_dsp.cpp
@@ -1,7 +1,7 @@
-/* Calf DSP Library
- * Example audio modules - DSP code
+/* Calf DSP plugin pack
+ * Assorted plugins
  *
- * Copyright (C) 2001-2008 Krzysztof Foltman
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -29,188 +29,6 @@ using namespace calf_plugins;
 
 #define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
 
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
-{ 
-    return get_freq_gridline(subindex, pos, vertical, legend, context);
-}
-
-int frequency_response_line_graph::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
-{
-    subindex_graph = 0;
-    subindex_dot = 0;
-    subindex_gridline = generation ? INT_MAX : 0;
-    return 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void flanger_audio_module::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);
-    is_active = true;
-}
-
-void flanger_audio_module::set_sample_rate(uint32_t sr) {
-    srate = sr;
-    left.setup(sr);
-    right.setup(sr);
-}
-
-void flanger_audio_module::deactivate() {
-    is_active = false;
-}
-
-bool flanger_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
-{
-    if (!is_active)
-        return false;
-    if (index == par_delay && subindex < 2) 
-    {
-        set_channel_color(context, subindex);
-        return ::get_graph(*this, subindex, data, points);
-    }
-    return false;
-}
-
-float flanger_audio_module::freq_gain(int subindex, float freq, float srate) const
-{
-    return (subindex ? right : left).freq_gain(freq, srate);                
-}
-
-void flanger_audio_module::params_changed()
-{
-    float dry = *params[par_dryamount];
-    float wet = *params[par_amount];
-    float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]);
-    float min_delay = *params[par_delay] / 1000.0;
-    float mod_depth = *params[par_depth] / 1000.0;
-    float fb = *params[par_fb];
-    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);
-    left.set_fb(fb); right.set_fb(fb);
-    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 flanger_audio_module::params_reset()
-{
-    if (clear_reset) {
-        *params[par_reset] = 0.f;
-        clear_reset = false;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-phaser_audio_module::phaser_audio_module()
-: left(MaxStages, x1vals[0], y1vals[0])
-, right(MaxStages, x1vals[1], y1vals[1])
-{
-    is_active = false;
-}
-
-void phaser_audio_module::set_sample_rate(uint32_t sr)
-{
-    srate = sr;
-    left.setup(sr);
-    right.setup(sr);
-}
-
-void phaser_audio_module::activate()
-{
-    is_active = true;
-    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 phaser_audio_module::deactivate()
-{
-    is_active = false;
-}
-
-bool phaser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
-{
-    if (!is_active)
-        return false;
-    if (subindex < 2) 
-    {
-        set_channel_color(context, subindex);
-        return ::get_graph(*this, subindex, data, points);
-    }
-    return false;
-}
-
-float phaser_audio_module::freq_gain(int subindex, float freq, float srate) const
-{
-    return (subindex ? right : left).freq_gain(freq, srate);                
-}
-
-bool phaser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
-{
-    return get_freq_gridline(subindex, pos, vertical, legend, context);
-}
-
-void phaser_audio_module::params_changed()
-{
-    float dry = *params[par_dryamount];
-    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 phaser_audio_module::params_reset()
-{
-    if (clear_reset) {
-        *params[par_reset] = 0.f;
-        clear_reset = false;
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 void reverb_audio_module::activate()
@@ -616,337 +434,6 @@ bool filterclavier_audio_module::get_graph(int index, int subindex, float *data,
     return false;
 }
 
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-rotary_speaker_audio_module::rotary_speaker_audio_module()
-{
-    mwhl_value = hold_value = 0.f;
-    phase_h = phase_l = 0.f;
-    aspeed_l = 1.f;
-    aspeed_h = 1.f;
-    dspeed = 0.f;
-}    
-
-void rotary_speaker_audio_module::set_sample_rate(uint32_t sr)
-{
-    srate = sr;
-    setup();
-}
-
-void rotary_speaker_audio_module::setup()
-{
-    crossover1l.set_lp_rbj(800.f, 0.7, (float)srate);
-    crossover1r.set_lp_rbj(800.f, 0.7, (float)srate);
-    crossover2l.set_hp_rbj(800.f, 0.7, (float)srate);
-    crossover2r.set_hp_rbj(800.f, 0.7, (float)srate);
-}
-
-void rotary_speaker_audio_module::activate()
-{
-    phase_h = phase_l = 0.f;
-    maspeed_h = maspeed_l = 0.f;
-    setup();
-}
-
-void rotary_speaker_audio_module::deactivate()
-{
-}
-
-void rotary_speaker_audio_module::control_change(int ctl, int val)
-{
-    if (vibrato_mode == 3 && ctl == 64)
-    {
-        hold_value = val / 127.f;
-        set_vibrato();
-        return;
-    }
-    if (vibrato_mode == 4 && ctl == 1)
-    {
-        mwhl_value = val / 127.f;
-        set_vibrato();
-        return;
-    }
-}
-
-void rotary_speaker_audio_module::params_changed()
-{
-    set_vibrato();
-}
-
-void rotary_speaker_audio_module::set_vibrato()
-{
-    vibrato_mode = fastf2i_drm(*params[par_speed]);
-    // manual vibrato - do not recalculate speeds as they're not used anyway
-    if (vibrato_mode == 5) 
-        return;
-    if (!vibrato_mode)
-        dspeed = -1;
-    else {
-        float speed = vibrato_mode - 1;
-        if (vibrato_mode == 3)
-            speed = hold_value;
-        if (vibrato_mode == 4)
-            speed = mwhl_value;
-        dspeed = (speed < 0.5f) ? 0 : 1;
-    }
-    update_speed();
-}
-
-/// Convert RPM speed to delta-phase
-uint32_t rotary_speaker_audio_module::rpm2dphase(float rpm)
-{
-    return (uint32_t)((rpm / (60.0 * srate)) * (1 << 30)) << 2;
-}
-
-/// Set delta-phase variables based on current calculated (and interpolated) RPM speed
-void rotary_speaker_audio_module::update_speed()
-{
-    float speed_h = aspeed_h >= 0 ? (48 + (400-48) * aspeed_h) : (48 * (1 + aspeed_h));
-    float speed_l = aspeed_l >= 0 ? 40 + (342-40) * aspeed_l : (40 * (1 + aspeed_l));
-    dphase_h = rpm2dphase(speed_h);
-    dphase_l = rpm2dphase(speed_l);
-}
-
-void rotary_speaker_audio_module::update_speed_manual(float delta)
-{
-    float ts = *params[par_treblespeed];
-    float bs = *params[par_bassspeed];
-    incr_towards(maspeed_h, ts, delta * 200, delta * 200);
-    incr_towards(maspeed_l, bs, delta * 200, delta * 200);
-    dphase_h = rpm2dphase(maspeed_h);
-    dphase_l = rpm2dphase(maspeed_l);
-}
-
-/// map a ramp [int] to a sinusoid-like function [0, 65536]
-static inline int pseudo_sine_scl(int counter)
-{
-    // premature optimization is a root of all evil; it can be done with integers only - but later :)
-    double v = counter * (1.0 / (65536.0 * 32768.0));
-    return (int) (32768 + 32768 * (v - v*v*v) * (1.0 / 0.3849));
-}
-
-/// Increase or decrease aspeed towards raspeed, with required negative and positive rate
-inline bool rotary_speaker_audio_module::incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc)
-{
-    if (aspeed < raspeed) {
-        aspeed = std::min(raspeed, aspeed + delta_acc);
-        return true;
-    }
-    else if (aspeed > raspeed) 
-    {
-        aspeed = std::max(raspeed, aspeed - delta_decc);
-        return true;
-    }        
-    return false;
-}
-
-uint32_t rotary_speaker_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    int shift = (int)(300000 * (*params[par_shift])), pdelta = (int)(300000 * (*params[par_spacing]));
-    int md = (int)(100 * (*params[par_moddepth]));
-    float mix = 0.5 * (1.0 - *params[par_micdistance]);
-    float mix2 = *params[par_reflection];
-    float mix3 = mix2 * mix2;
-    for (unsigned int i = 0; i < nsamples; i++) {
-        float in_l = ins[0][i + offset], in_r = ins[1][i + offset];
-        float in_mono = 0.5f * (in_l + in_r);
-        
-        int xl = pseudo_sine_scl(phase_l), yl = pseudo_sine_scl(phase_l + 0x40000000);
-        int xh = pseudo_sine_scl(phase_h), yh = pseudo_sine_scl(phase_h + 0x40000000);
-        // printf("%d %d %d\n", shift, pdelta, shift + pdelta + 20 * xl);
-        meter_l = xl;
-        meter_h = xh;
-        // float out_hi_l = in_mono - delay.get_interp_1616(shift + md * xh) + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) - delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh);
-        // float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - delay.get_interp_1616(shift + pdelta + md * xh) + delay.get_interp_1616(shift + pdelta + pdelta + md * yh);
-        float out_hi_l = in_mono + delay.get_interp_1616(shift + md * xh) - mix2 * delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) + mix3 * delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh);
-        float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - mix2 * delay.get_interp_1616(shift + pdelta + md * xh) + mix3 * delay.get_interp_1616(shift + pdelta + pdelta + md * yh);
-
-        float out_lo_l = in_mono + delay.get_interp_1616(shift + md * xl); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl);
-        float out_lo_r = in_mono + delay.get_interp_1616(shift + md * yl); // - delay.get_interp_1616(shift + pdelta + md * yl);
-        
-        out_hi_l = crossover2l.process(out_hi_l); // sanitize(out_hi_l);
-        out_hi_r = crossover2r.process(out_hi_r); // sanitize(out_hi_r);
-        out_lo_l = crossover1l.process(out_lo_l); // sanitize(out_lo_l);
-        out_lo_r = crossover1r.process(out_lo_r); // sanitize(out_lo_r);
-        
-        float out_l = out_hi_l + out_lo_l;
-        float out_r = out_hi_r + out_lo_r;
-        
-        float mic_l = out_l + mix * (out_r - out_l);
-        float mic_r = out_r + mix * (out_l - out_r);
-        
-        outs[0][i + offset] = mic_l * 0.5f;
-        outs[1][i + offset] = mic_r * 0.5f;
-        delay.put(in_mono);
-        phase_l += dphase_l;
-        phase_h += dphase_h;
-    }
-    crossover1l.sanitize();
-    crossover1r.sanitize();
-    crossover2l.sanitize();
-    crossover2r.sanitize();
-    float delta = nsamples * 1.0 / srate;
-    if (vibrato_mode == 5)
-        update_speed_manual(delta);
-    else
-    {
-        bool u1 = incr_towards(aspeed_l, dspeed, delta * 0.2, delta * 0.14);
-        bool u2 = incr_towards(aspeed_h, dspeed, delta, delta * 0.5);
-        if (u1 || u2)
-            set_vibrato();
-    }
-    if(params[par_meter_l] != NULL) {
-        *params[par_meter_l] = (float)meter_l / 65536.0;
-    }
-    if(params[par_meter_h] != NULL) {
-        *params[par_meter_h] = (float)meter_h / 65536.0;
-    }
-    return outputs_mask;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-multichorus_audio_module::multichorus_audio_module()
-{
-    is_active = false;
-    last_r_phase = -1;
-}
-
-void multichorus_audio_module::activate()
-{
-    is_active = true;
-    params_changed();
-}
-
-void multichorus_audio_module::deactivate()
-{
-    is_active = false;
-}
-
-void multichorus_audio_module::set_sample_rate(uint32_t sr) {
-    srate = sr;
-    left.setup(sr);
-    right.setup(sr);
-}
-
-bool multichorus_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
-{
-    if (!is_active)
-        return false;
-    int nvoices = (int)*params[par_voices];
-    if (index == par_delay && subindex < 3) 
-    {
-        if (subindex < 2)
-            set_channel_color(context, subindex);
-        else {
-            context->set_source_rgba(0.35, 0.4, 0.2);
-            context->set_line_width(1.0);
-        }
-        return ::get_graph(*this, subindex, data, points);
-    }
-    if (index == par_rate && subindex < nvoices) {
-        const sine_multi_lfo<float, 8> &lfo = left.lfo;
-        for (int i = 0; i < points; i++) {
-            float phase = i * 2 * M_PI / points;
-            // original -65536 to 65535 value
-            float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(phase) + 1)/ 8192.0) - 65536;
-            // scale to -1..1
-            data[i] = orig / 65536.0;
-        }
-        return true;
-    }
-    return false;
-}
-
-bool multichorus_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
-{
-    int voice = subindex >> 1;
-    int nvoices = (int)*params[par_voices];
-    if ((index != par_rate && index != par_depth) || voice >= nvoices)
-        return false;
-
-    float unit = (1 - *params[par_overlap]);
-    float scw = 1 + unit * (nvoices - 1);
-    set_channel_color(context, subindex);
-    const sine_multi_lfo<float, 8> &lfo = (subindex & 1 ? right : left).lfo;
-    if (index == par_rate)
-    {
-        x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
-        y = 0.95 * sin(x * 2 * M_PI);
-        y = (voice * unit + (y + 1) / 2) / scw * 2 - 1;
-    }
-    else
-    {
-        double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
-        x = 0.5 + 0.5 * sin(ph * 2 * M_PI);
-        y = subindex & 1 ? -0.75 : 0.75;
-        x = (voice * unit + x) / scw;
-    }
-    return true;
-}
-
-bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
-{
-    if (index == par_rate && !subindex)
-    {
-        pos = 0;
-        vertical = false;
-        return true;
-    }
-    if (index == par_delay)
-        return get_freq_gridline(subindex, pos, vertical, legend, context);
-    return false;
-}
-
-float multichorus_audio_module::freq_gain(int subindex, float freq, float srate) const
-{
-    if (subindex == 2)
-        return *params[par_amount] * left.post.freq_gain(freq, srate);
-    return (subindex ? right : left).freq_gain(freq, srate);                
-}
-
-void multichorus_audio_module::params_changed()
-{
-    // delicious copy-pasta from flanger module - it'd be better to keep it common or something
-    float dry = *params[par_dryamount];
-    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;
-    float overlap = *params[par_overlap];
-    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);
-    int voices = (int)*params[par_voices];
-    left.lfo.set_voices(voices); right.lfo.set_voices(voices);
-    left.lfo.set_overlap(overlap);right.lfo.set_overlap(overlap);
-    float vphase = *params[par_vphase] * (1.f / 360.f);
-    left.lfo.vphase = right.lfo.vphase = vphase * (4096 / std::max(voices - 1, 1));
-    float r_phase = *params[par_stereo] * (1.f / 360.f);
-    if (fabs(r_phase - last_r_phase) > 0.0001f) {
-        right.lfo.phase = left.lfo.phase;
-        right.lfo.phase += chorus_phase(r_phase * 4096);
-        last_r_phase = r_phase;
-    }
-    left.post.f1.set_bp_rbj(*params[par_freq], *params[par_q], srate);
-    left.post.f2.set_bp_rbj(*params[par_freq2], *params[par_q], srate);
-    right.post.f1.copy_coeffs(left.post.f1);
-    right.post.f2.copy_coeffs(left.post.f2);
-}
-
-uint32_t multichorus_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    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
-}
-
-
-
 /// Multibandcompressor by Markus Schmidt
 ///
 /// This module splits the signal in four different bands
@@ -2262,1391 +1749,3 @@ int gain_reduction_audio_module::get_changed_offsets(int generation, int &subind
     return last_generation;
 }
 
-/// Equalizer 12 Band by Markus Schmidt
-///
-/// This module is based on Krzysztof's filters. It provides a couple
-/// of different chained filters.
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-template<class BaseClass, bool has_lphp>
-equalizerNband_audio_module<BaseClass, has_lphp>::equalizerNband_audio_module()
-{
-    is_active = false;
-    srate = 0;
-    last_generation = 0;
-    clip_inL = clip_inR = clip_outL = clip_outR  = 0.f;
-    meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
-}
-
-template<class BaseClass, bool has_lphp>
-void equalizerNband_audio_module<BaseClass, has_lphp>::activate()
-{
-    is_active = true;
-    // set all filters
-    params_changed();
-}
-
-template<class BaseClass, bool has_lphp>
-void equalizerNband_audio_module<BaseClass, has_lphp>::deactivate()
-{
-    is_active = false;
-}
-
-static inline void copy_lphp(biquad_d2<float> filters[3][2])
-{
-    for (int i = 0; i < 3; i++)
-        for (int j = 0; j < 2; j++)
-            if (i || j)
-                filters[i][j].copy_coeffs(filters[0][0]);
-}
-
-template<class BaseClass, bool has_lphp>
-void equalizerNband_audio_module<BaseClass, has_lphp>::params_changed()
-{
-    // set the params of all filters
-    
-    // lp/hp first (if available)
-    if (has_lphp)
-    {
-        hp_mode = (CalfEqMode)(int)*params[AM::param_hp_mode];
-        lp_mode = (CalfEqMode)(int)*params[AM::param_lp_mode];
-
-        float hpfreq = *params[AM::param_hp_freq], lpfreq = *params[AM::param_lp_freq];
-        
-        if(hpfreq != hp_freq_old) {
-            hp[0][0].set_hp_rbj(hpfreq, 0.707, (float)srate, 1.0);
-            copy_lphp(hp);
-            hp_freq_old = hpfreq;
-        }
-        if(lpfreq != lp_freq_old) {
-            lp[0][0].set_lp_rbj(lpfreq, 0.707, (float)srate, 1.0);
-            copy_lphp(lp);
-            lp_freq_old = lpfreq;
-        }
-    }
-    
-    // then shelves
-    float hsfreq = *params[AM::param_hs_freq], hslevel = *params[AM::param_hs_level];
-    float lsfreq = *params[AM::param_ls_freq], lslevel = *params[AM::param_ls_level];
-    
-    if(lsfreq != ls_freq_old or lslevel != ls_level_old) {
-        lsL.set_lowshelf_rbj(lsfreq, 0.707, lslevel, (float)srate);
-        lsR.copy_coeffs(lsL);
-        ls_level_old = lslevel;
-        ls_freq_old = lsfreq;
-    }
-    if(hsfreq != hs_freq_old or hslevel != hs_level_old) {
-        hsL.set_highshelf_rbj(hsfreq, 0.707, hslevel, (float)srate);
-        hsR.copy_coeffs(hsL);
-        hs_level_old = hslevel;
-        hs_freq_old = hsfreq;
-    }
-    for (int i = 0; i < AM::PeakBands; i++)
-    {
-        int offset = i * params_per_band;
-        float freq = *params[AM::param_p1_freq + offset];
-        float level = *params[AM::param_p1_level + offset];
-        float q = *params[AM::param_p1_q + offset];
-        if(freq != p_freq_old[i] or level != p_level_old[i] or q != p_q_old[i]) {
-            pL[i].set_peakeq_rbj(freq, q, level, (float)srate);
-            pR[i].copy_coeffs(pL[i]);
-            p_freq_old[i] = freq;
-            p_level_old[i] = level;
-            p_q_old[i] = q;
-        }
-    }
-}
-
-template<class BaseClass, bool has_lphp>
-inline void equalizerNband_audio_module<BaseClass, has_lphp>::process_hplp(float &left, float &right)
-{
-    if (!has_lphp)
-        return;
-    if (*params[AM::param_lp_active] > 0.f)
-    {
-        switch(lp_mode)
-        {
-            case MODE12DB:
-                left = lp[0][0].process(left);
-                right = lp[0][1].process(right);
-                break;
-            case MODE24DB:
-                left = lp[1][0].process(lp[0][0].process(left));
-                right = lp[1][1].process(lp[0][1].process(right));
-                break;
-            case MODE36DB:
-                left = lp[2][0].process(lp[1][0].process(lp[0][0].process(left)));
-                right = lp[2][1].process(lp[1][1].process(lp[0][1].process(right)));
-                break;
-        }
-    }
-    if (*params[AM::param_hp_active] > 0.f)
-    {
-        switch(hp_mode)
-        {
-            case MODE12DB:
-                left = hp[0][0].process(left);
-                right = hp[0][1].process(right);
-                break;
-            case MODE24DB:
-                left = hp[1][0].process(hp[0][0].process(left));
-                right = hp[1][1].process(hp[0][1].process(right));
-                break;
-            case MODE36DB:
-                left = hp[2][0].process(hp[1][0].process(hp[0][0].process(left)));
-                right = hp[2][1].process(hp[1][1].process(hp[0][1].process(right)));
-                break;
-        }
-    }
-}
-
-template<class BaseClass, bool has_lphp>
-uint32_t equalizerNband_audio_module<BaseClass, has_lphp>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    bool bypass = *params[AM::param_bypass] > 0.f;
-    numsamples += offset;
-    if(bypass) {
-        // everything bypassed
-        while(offset < numsamples) {
-            outs[0][offset] = ins[0][offset];
-            outs[1][offset] = ins[1][offset];
-            ++offset;
-        }
-        // displays, too
-        clip_inL = clip_inR = clip_outL = clip_outR = 0.f;
-        meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
-    } else {
-        
-        clip_inL    -= std::min(clip_inL,  numsamples);
-        clip_inR    -= std::min(clip_inR,  numsamples);
-        clip_outL   -= std::min(clip_outL, numsamples);
-        clip_outR   -= std::min(clip_outR, numsamples);
-        meter_inL = 0.f;
-        meter_inR = 0.f;
-        meter_outL = 0.f;
-        meter_outR = 0.f;
-        
-        // process
-        while(offset < numsamples) {
-            // cycle through samples
-            float outL = 0.f;
-            float outR = 0.f;
-            float inL = ins[0][offset];
-            float inR = ins[1][offset];
-            // in level
-            inR *= *params[AM::param_level_in];
-            inL *= *params[AM::param_level_in];
-            
-            float procL = inL;
-            float procR = inR;
-            
-            // all filters in chain
-            process_hplp(procL, procR);
-            if(*params[AM::param_ls_active] > 0.f) {
-                procL = lsL.process(procL);
-                procR = lsR.process(procR);
-            }
-            if(*params[AM::param_hs_active] > 0.f) {
-                procL = hsL.process(procL);
-                procR = hsR.process(procR);
-            }
-            for (int i = 0; i < AM::PeakBands; i++)
-            {
-                if(*params[AM::param_p1_active + i * params_per_band] > 0.f) {
-                    procL = pL[i].process(procL);
-                    procR = pR[i].process(procR);
-                }
-            }
-            
-            outL = procL * *params[AM::param_level_out];
-            outR = procR * *params[AM::param_level_out];
-            
-            // send to output
-            outs[0][offset] = outL;
-            outs[1][offset] = outR;
-            
-            // clip LED's
-            if(inL > 1.f) {
-                clip_inL  = srate >> 3;
-            }
-            if(inR > 1.f) {
-                clip_inR  = srate >> 3;
-            }
-            if(outL > 1.f) {
-                clip_outL = srate >> 3;
-            }
-            if(outR > 1.f) {
-                clip_outR = srate >> 3;
-            }
-            // set up in / out meters
-            if(inL > meter_inL) {
-                meter_inL = inL;
-            }
-            if(inR > meter_inR) {
-                meter_inR = inR;
-            }
-            if(outL > meter_outL) {
-                meter_outL = outL;
-            }
-            if(outR > meter_outR) {
-                meter_outR = outR;
-            }
-            
-            // next sample
-            ++offset;
-        } // cycle trough samples
-        // clean up
-        for(int i = 0; i < 3; ++i) {
-            hp[i][0].sanitize();
-            hp[i][1].sanitize();
-            lp[i][0].sanitize();
-            lp[i][1].sanitize();
-        }
-        lsL.sanitize();
-        hsR.sanitize();
-        for(int i = 0; i < AM::PeakBands; ++i) {
-            pL[i].sanitize();
-            pR[i].sanitize();
-        }
-    }
-    // draw meters
-    SET_IF_CONNECTED(clip_inL)
-    SET_IF_CONNECTED(clip_inR)
-    SET_IF_CONNECTED(clip_outL)
-    SET_IF_CONNECTED(clip_outR)
-    SET_IF_CONNECTED(meter_inL)
-    SET_IF_CONNECTED(meter_inR)
-    SET_IF_CONNECTED(meter_outL)
-    SET_IF_CONNECTED(meter_outR)
-    // whatever has to be returned x)
-    return outputs_mask;
-}
-
-template<class BaseClass, bool has_lphp>
-bool equalizerNband_audio_module<BaseClass, has_lphp>::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
-{
-    if (!is_active)
-        return false;
-    if (index == AM::param_p1_freq && !subindex) {
-        context->set_line_width(1.5);
-        return ::get_graph(*this, subindex, data, points);
-    }
-    return false;
-}
-
-template<class BaseClass, bool has_lphp>
-bool equalizerNband_audio_module<BaseClass, has_lphp>::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
-{
-    if (!is_active) {
-        return false;
-    } else {
-        return get_freq_gridline(subindex, pos, vertical, legend, context);
-    }
-}
-
-template<class BaseClass, bool has_lphp>
-int equalizerNband_audio_module<BaseClass, has_lphp>::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
-{
-    if (!is_active) {
-        return false;
-    } else {
-        bool changed = false;
-        for (int i = 0; i < graph_param_count && !changed; i++)
-        {
-            if (*params[AM::first_graph_param + i] != old_params_for_graph[i])
-                changed = true;
-        }
-        if (changed)
-        {
-            for (int i = 0; i < graph_param_count; i++)
-                old_params_for_graph[i] = *params[AM::first_graph_param + i];
-            
-            last_generation++;
-            subindex_graph = 0;
-            subindex_dot = INT_MAX;
-            subindex_gridline = INT_MAX;
-        }
-        else {
-            subindex_graph = 0;
-            subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
-        }
-        if (generation == last_calculated_generation)
-            subindex_graph = INT_MAX;
-        return last_generation;
-    }
-    return false;
-}
-
-static inline float adjusted_lphp_gain(const float *const *params, int param_active, int param_mode, const biquad_d2<float> &filter, float freq, float srate)
-{
-    if(*params[param_active] > 0.f) {
-        float gain = filter.freq_gain(freq, srate);
-        switch((int)*params[param_mode]) {
-            case MODE12DB:
-                return gain;
-            case MODE24DB:
-                return gain * gain;
-            case MODE36DB:
-                return gain * gain * gain;
-        }
-    }
-    return 1;
-}
-
-template<class BaseClass, bool use_hplp>
-float equalizerNband_audio_module<BaseClass, use_hplp>::freq_gain(int index, double freq, uint32_t sr) const
-{
-    float ret = 1.f;
-    if (use_hplp)
-    {
-        ret *= adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)sr);
-        ret *= adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)sr);
-    }
-    ret *= (*params[AM::param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1;
-    ret *= (*params[AM::param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1;
-    for (int i = 0; i < PeakBands; i++)
-        ret *= (*params[AM::param_p1_active + i * params_per_band] > 0.f) ? pL[i].freq_gain(freq, (float)sr) : 1;
-    return ret;
-}
-
-template class equalizerNband_audio_module<equalizer5band_metadata, false>;
-template class equalizerNband_audio_module<equalizer8band_metadata, true>;
-template class equalizerNband_audio_module<equalizer12band_metadata, true>;
-
-/// LFO module by Markus
-/// This module provides simple LFO's (sine=0, triangle=1, square=2, saw_up=3, saw_down=4)
-/// get_value() returns a value between -1 and 1
-////////////////////////////////////////////////////////////////////////////////
-lfo_audio_module::lfo_audio_module()
-{
-    is_active       = false;
-    phase = 0.f;
-}
-
-void lfo_audio_module::activate()
-{
-    is_active = true;
-    phase = 0.f;
-}
-
-void lfo_audio_module::deactivate()
-{
-    is_active = false;
-}
-
-float lfo_audio_module::get_value()
-{
-    return get_value_from_phase(phase, offset) * amount;
-}
-
-float lfo_audio_module::get_value_from_phase(float ph, float off) const
-{
-    float val = 0.f;
-    float phs = ph + off;
-    if (phs >= 1.0)
-        phs = fmod(phs, 1.f);
-    switch (mode) {
-        default:
-        case 0:
-            // sine
-            val = sin((phs * 360.f) * M_PI / 180);
-            break;
-        case 1:
-            // triangle
-            if(phs > 0.75)
-                val = (phs - 0.75) * 4 - 1;
-            else if(phs > 0.5)
-                val = (phs - 0.5) * 4 * -1;
-            else if(phs > 0.25)
-                val = 1 - (phs - 0.25) * 4;
-            else
-                val = phs * 4;
-            break;
-        case 2:
-            // square
-            val = (phs < 0.5) ? -1 : +1;
-            break;
-        case 3:
-            // saw up
-                val = phs * 2.f - 1;
-            break;
-        case 4:
-            // saw down
-            val = 1 - phs * 2.f;
-            break;
-    }
-    return val;
-}
-
-void lfo_audio_module::advance(uint32_t count)
-{
-    //this function walks from 0.f to 1.f and starts all over again
-    phase += count * freq * (1.0 / srate);
-    if (phase >= 1.0)
-        phase = fmod(phase, 1.f);
-}
-
-void lfo_audio_module::set_phase(float ph)
-{
-    //set the phase from outsinde
-    phase = fabs(ph);
-    if (phase >= 1.0)
-        phase = fmod(phase, 1.f);
-}
-
-void lfo_audio_module::set_params(float f, int m, float o, uint32_t sr, float a)
-{
-    // freq: a value in Hz
-    // mode: sine=0, triangle=1, square=2, saw_up=3, saw_down=4
-    // offset: value between 0.f and 1.f to offset the lfo in time
-    freq = f;
-    mode = m;
-    offset = o;
-    srate = sr;
-    amount = a;
-}
-
-bool lfo_audio_module::get_graph(float *data, int points, cairo_iface *context) const
-{
-    if (!is_active)
-        return false;
-    for (int i = 0; i < points; i++) {
-        float ph = (float)i / (float)points;
-        data[i] = get_value_from_phase(ph, offset) * amount;
-    }
-    return true;
-}
-
-bool lfo_audio_module::get_dot(float &x, float &y, int &size, cairo_iface *context) const
-{
-    if (!is_active)
-        return false;
-    float phs = phase + offset;
-    if (phs >= 1.0)
-        phs = fmod(phs, 1.f);
-    x = phase;
-    y = get_value_from_phase(phase, offset) * amount;
-    return true;
-}
-
-/// Pulsator by Markus Schmidt
-///
-/// This module provides a couple
-/// of different LFO's for modulating the level of a signal.
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-pulsator_audio_module::pulsator_audio_module()
-{
-    is_active = false;
-    srate = 0;
-//    last_generation = 0;
-    clip_inL    = 0.f;
-    clip_inR    = 0.f;
-    clip_outL   = 0.f;
-    clip_outR   = 0.f;
-    meter_inL  = 0.f;
-    meter_inR  = 0.f;
-    meter_outL = 0.f;
-    meter_outR = 0.f;
-}
-
-void pulsator_audio_module::activate()
-{
-    is_active = true;
-    lfoL.activate();
-    lfoR.activate();
-    params_changed();
-}
-void pulsator_audio_module::deactivate()
-{
-    is_active = false;
-    lfoL.deactivate();
-    lfoR.deactivate();
-}
-
-void pulsator_audio_module::params_changed()
-{
-    lfoL.set_params(*params[param_freq], *params[param_mode], 0.f, srate, *params[param_amount]);
-    lfoR.set_params(*params[param_freq], *params[param_mode], *params[param_offset], srate, *params[param_amount]);
-    clear_reset = false;
-    if (*params[param_reset] >= 0.5) {
-        clear_reset = true;
-        lfoL.set_phase(0.f);
-        lfoR.set_phase(0.f);
-    }
-}
-
-void pulsator_audio_module::set_sample_rate(uint32_t sr)
-{
-    srate = sr;
-}
-
-uint32_t pulsator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    bool bypass = *params[param_bypass] > 0.5f;
-    uint32_t samples = numsamples + offset;
-    if(bypass) {
-        // everything bypassed
-        while(offset < samples) {
-            outs[0][offset] = ins[0][offset];
-            outs[1][offset] = ins[1][offset];
-            ++offset;
-        }
-        // displays, too
-        clip_inL    = 0.f;
-        clip_inR    = 0.f;
-        clip_outL   = 0.f;
-        clip_outR   = 0.f;
-        meter_inL  = 0.f;
-        meter_inR  = 0.f;
-        meter_outL = 0.f;
-        meter_outR = 0.f;
-        
-        // LFO's should go on
-        lfoL.advance(numsamples);
-        lfoR.advance(numsamples);
-        
-    } else {
-        
-        clip_inL    -= std::min(clip_inL,  numsamples);
-        clip_inR    -= std::min(clip_inR,  numsamples);
-        clip_outL   -= std::min(clip_outL, numsamples);
-        clip_outR   -= std::min(clip_outR, numsamples);
-        meter_inL = 0.f;
-        meter_inR = 0.f;
-        meter_outL = 0.f;
-        meter_outR = 0.f;
-        
-        // process
-        while(offset < samples) {
-            // cycle through samples
-            float outL = 0.f;
-            float outR = 0.f;
-            float inL = ins[0][offset];
-            float inR = ins[1][offset];
-            // in level
-            inR *= *params[param_level_in];
-            inL *= *params[param_level_in];
-            
-            if(*params[param_mono] > 0.5) {
-                inL = (inL + inR) * 0.5;
-                inR = inL;
-            }
-            float procL = inL;
-            float procR = inR;
-            
-            procL *= (lfoL.get_value() * 0.5 + *params[param_amount] / 2);
-            procR *= (lfoR.get_value() * 0.5 + *params[param_amount] / 2);
-            
-            outL = procL + inL * (1 - *params[param_amount]);
-            outR = procR + inR * (1 - *params[param_amount]);
-            
-            outL *=  *params[param_level_out];
-            outR *=  *params[param_level_out];
-            
-            // send to output
-            outs[0][offset] = outL;
-            outs[1][offset] = outR;
-            
-            // clip LED's
-            if(inL > 1.f) {
-                clip_inL  = srate >> 3;
-            }
-            if(inR > 1.f) {
-                clip_inR  = srate >> 3;
-            }
-            if(outL > 1.f) {
-                clip_outL = srate >> 3;
-            }
-            if(outR > 1.f) {
-                clip_outR = srate >> 3;
-            }
-            // set up in / out meters
-            if(inL > meter_inL) {
-                meter_inL = inL;
-            }
-            if(inR > meter_inR) {
-                meter_inR = inR;
-            }
-            if(outL > meter_outL) {
-                meter_outL = outL;
-            }
-            if(outR > meter_outR) {
-                meter_outR = outR;
-            }
-            
-            // next sample
-            ++offset;
-            
-            // advance lfo's
-            lfoL.advance(1);
-            lfoR.advance(1);
-        } // cycle trough samples
-    }
-    // draw meters
-    SET_IF_CONNECTED(clip_inL)
-    SET_IF_CONNECTED(clip_inR)
-    SET_IF_CONNECTED(clip_outL)
-    SET_IF_CONNECTED(clip_outR)
-    SET_IF_CONNECTED(meter_inL)
-    SET_IF_CONNECTED(meter_inR)
-    SET_IF_CONNECTED(meter_outL)
-    SET_IF_CONNECTED(meter_outR)
-    // whatever has to be returned x)
-    return outputs_mask;
-}
-
-bool pulsator_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
-{
-    if (!is_active) {
-        return false;
-    } else if(index == param_freq) {
-        if(subindex == 0) {
-            context->set_source_rgba(0.35, 0.4, 0.2, 1);
-            return lfoL.get_graph(data, points, context);
-        }
-        if(subindex == 1) {
-            context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
-            return lfoR.get_graph(data, points, context);
-        }
-    }
-    return false;
-}
-
-bool pulsator_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
-{
-    if (!is_active) {
-        return false;
-    } else if(index == param_freq) {
-        if(subindex == 0) {
-            context->set_source_rgba(0.35, 0.4, 0.2, 1);
-            return lfoL.get_dot(x, y, size, context);
-        }
-        if(subindex == 1) {
-            context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
-            return lfoR.get_dot(x, y, size, context);
-        }
-        return false;
-    }
-    return false;
-}
-
-bool pulsator_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
-{
-   if (index == param_freq && !subindex)
-    {
-        pos = 0;
-        vertical = false;
-        return true;
-    }
-    return false;
-}
-
-/// Saturator Band by Markus Schmidt
-///
-/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
-/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-saturator_audio_module::saturator_audio_module()
-{
-    is_active = false;
-    srate = 0;
-    clip_in    = 0.f;
-    clip_out   = 0.f;
-    meter_in  = 0.f;
-    meter_out = 0.f;
-    meter_drive = 0.f;
-}
-
-void saturator_audio_module::activate()
-{
-    is_active = true;
-    // set all filters
-    params_changed();
-}
-void saturator_audio_module::deactivate()
-{
-    is_active = false;
-}
-
-void saturator_audio_module::params_changed()
-{
-    // set the params of all filters
-    if(*params[param_lp_pre_freq] != lp_pre_freq_old) {
-        lp[0][0].set_lp_rbj(*params[param_lp_pre_freq], 0.707, (float)srate);
-        if(in_count > 1 && out_count > 1)
-            lp[1][0].copy_coeffs(lp[0][0]);
-        lp[0][1].copy_coeffs(lp[0][0]);
-        if(in_count > 1 && out_count > 1)
-            lp[1][1].copy_coeffs(lp[0][0]);
-        lp_pre_freq_old = *params[param_lp_pre_freq];
-    }
-    if(*params[param_hp_pre_freq] != hp_pre_freq_old) {
-        hp[0][0].set_hp_rbj(*params[param_hp_pre_freq], 0.707, (float)srate);
-        if(in_count > 1 && out_count > 1)
-            hp[1][0].copy_coeffs(hp[0][0]);
-        hp[0][1].copy_coeffs(hp[0][0]);
-        if(in_count > 1 && out_count > 1)
-            hp[1][1].copy_coeffs(hp[0][0]);
-        hp_pre_freq_old = *params[param_hp_pre_freq];
-    }
-    if(*params[param_lp_post_freq] != lp_post_freq_old) {
-        lp[0][2].set_lp_rbj(*params[param_lp_post_freq], 0.707, (float)srate);
-        if(in_count > 1 && out_count > 1)
-            lp[1][2].copy_coeffs(lp[0][2]);
-        lp[0][3].copy_coeffs(lp[0][2]);
-        if(in_count > 1 && out_count > 1)
-            lp[1][3].copy_coeffs(lp[0][2]);
-        lp_post_freq_old = *params[param_lp_post_freq];
-    }
-    if(*params[param_hp_post_freq] != hp_post_freq_old) {
-        hp[0][2].set_hp_rbj(*params[param_hp_post_freq], 0.707, (float)srate);
-        if(in_count > 1 && out_count > 1)
-            hp[1][2].copy_coeffs(hp[0][2]);
-        hp[0][3].copy_coeffs(hp[0][2]);
-        if(in_count > 1 && out_count > 1)
-            hp[1][3].copy_coeffs(hp[0][2]);
-        hp_post_freq_old = *params[param_hp_post_freq];
-    }
-    if(*params[param_p_freq] != p_freq_old or *params[param_p_level] != p_level_old or *params[param_p_q] != p_q_old) {
-        p[0].set_peakeq_rbj((float)*params[param_p_freq], (float)*params[param_p_q], (float)*params[param_p_level], (float)srate);
-        if(in_count > 1 && out_count > 1)
-            p[1].copy_coeffs(p[0]);
-        p_freq_old = *params[param_p_freq];
-        p_level_old = *params[param_p_level];
-        p_q_old = *params[param_p_q];
-    }
-    // set distortion
-    dist[0].set_params(*params[param_blend], *params[param_drive]);
-    if(in_count > 1 && out_count > 1)
-        dist[1].set_params(*params[param_blend], *params[param_drive]);
-}
-
-void saturator_audio_module::set_sample_rate(uint32_t sr)
-{
-    srate = sr;
-    dist[0].set_sample_rate(sr);
-    if(in_count > 1 && out_count > 1)
-        dist[1].set_sample_rate(sr);
-}
-
-uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    bool bypass = *params[param_bypass] > 0.5f;
-    numsamples += offset;
-    if(bypass) {
-        // everything bypassed
-        while(offset < numsamples) {
-            if(in_count > 1 && out_count > 1) {
-                outs[0][offset] = ins[0][offset];
-                outs[1][offset] = ins[1][offset];
-            } else if(in_count > 1) {
-                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
-            } else if(out_count > 1) {
-                outs[0][offset] = ins[0][offset];
-                outs[1][offset] = ins[0][offset];
-            } else {
-                outs[0][offset] = ins[0][offset];
-            }
-            ++offset;
-        }
-        // displays, too
-        clip_in    = 0.f;
-        clip_out   = 0.f;
-        meter_in  = 0.f;
-        meter_out = 0.f;
-        meter_drive = 0.f;
-    } else {
-        
-        clip_in    -= std::min(clip_in,  numsamples);
-        clip_out   -= std::min(clip_out, numsamples);
-        meter_in = 0.f;
-        meter_out = 0.f;
-        meter_drive = 0.f;
-        float in_avg[2] = {0.f, 0.f};
-        float out_avg[2] = {0.f, 0.f};
-        float tube_avg = 0.f;
-        // process
-        while(offset < numsamples) {
-            // cycle through samples
-            float out[2], in[2] = {0.f, 0.f};
-            float maxIn, maxOut = 0.f;
-            int c = 0;
-            
-            if(in_count > 1 && out_count > 1) {
-                // stereo in/stereo out
-                // handle full stereo
-                in[0] = ins[0][offset];
-                in[1] = ins[1][offset];
-                c = 2;
-            } else {
-                // in and/or out mono
-                // handle mono
-                in[0] = ins[0][offset];
-                in[1] = in[0];
-                c = 1;
-            }
-            
-            float proc[2];
-            proc[0] = in[0] * *params[param_level_in];
-            proc[1] = in[1] * *params[param_level_in];
-            
-            for (int i = 0; i < c; ++i) {
-                // all pre filters in chain
-                proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
-                proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
-                
-                // get average for display purposes before...
-                in_avg[i] += fabs(pow(proc[i], 2.f));
-
-                // ...saturate...
-                proc[i] = dist[i].process(proc[i]);
-                
-                // ...and get average after...
-                out_avg[i] += fabs(pow(proc[i], 2.f));
-                
-                // tone control
-                proc[i] = p[i].process(proc[i]);
-
-                // all post filters in chain
-                proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
-                proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
-                
-                //subtract gain
-                 proc[i] /= *params[param_level_in];
-            }
-            
-            if(in_count > 1 && out_count > 1) {
-                // full stereo
-                out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                out[1] = ((proc[1] * *params[param_mix]) + in[1] * (1 - *params[param_mix])) * *params[param_level_out];
-                outs[1][offset] = out[1];
-                maxIn = std::max(fabs(in[0]), fabs(in[1]));
-                maxOut = std::max(fabs(out[0]), fabs(out[1]));
-            } else if(out_count > 1) {
-                // mono -> pseudo stereo
-                out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                out[1] = out[0];
-                outs[1][offset] = out[1];
-                maxOut = fabs(out[0]);
-                maxIn = fabs(in[0]);
-            } else {
-                // stereo -> mono
-                // or full mono
-                out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                maxIn = fabs(in[0]);
-                maxOut = fabs(out[0]);
-            }
-            
-            if(maxIn > 1.f) {
-                clip_in  = srate >> 3;
-            }
-            if(maxOut > 1.f) {
-                clip_out = srate >> 3;
-            }
-            // set up in / out meters
-            if(maxIn > meter_in) {
-                meter_in = maxIn;
-            }
-            if(maxOut > meter_out) {
-                meter_out = maxOut;
-            }
-            
-            // next sample
-            ++offset;
-        } // cycle trough samples
-        
-        tube_avg = (sqrt(std::max(out_avg[0], out_avg[1])) / numsamples) - (sqrt(std::max(in_avg[0], in_avg[1])) / numsamples);
-        meter_drive = (5.0f * fabs(tube_avg) * (float(*params[param_blend]) + 30.0f));
-        // printf("out:%.6f in: %.6f avg: %.6f drv: %.3f\n", sqrt(std::max(out_avg[0], out_avg[1])) / numsamples, sqrt(std::max(in_avg[0], in_avg[1])) / numsamples, tube_avg, meter_drive);
-        // clean up
-        lp[0][0].sanitize();
-        lp[1][0].sanitize();
-        lp[0][1].sanitize();
-        lp[1][1].sanitize();
-        lp[0][2].sanitize();
-        lp[1][2].sanitize();
-        lp[0][3].sanitize();
-        lp[1][3].sanitize();
-        hp[0][0].sanitize();
-        hp[1][0].sanitize();
-        hp[0][1].sanitize();
-        hp[1][1].sanitize();
-        hp[0][2].sanitize();
-        hp[1][2].sanitize();
-        hp[0][3].sanitize();
-        hp[1][3].sanitize();
-        p[0].sanitize();
-        p[1].sanitize();
-    }
-    // draw meters
-    if(params[param_clip_in] != NULL) {
-        *params[param_clip_in] = clip_in;
-    }
-    if(params[param_clip_out] != NULL) {
-        *params[param_clip_out] = clip_out;
-    }
-    
-    if(params[param_meter_in] != NULL) {
-        *params[param_meter_in] = meter_in;
-    }
-    if(params[param_meter_out] != NULL) {
-        *params[param_meter_out] = meter_out;
-    }
-    if(params[param_meter_drive] != NULL) {
-        *params[param_meter_drive] = meter_drive;
-    }
-    // whatever has to be returned x)
-    return outputs_mask;
-}
-
-/// Exciter by Markus Schmidt
-///
-/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
-/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-exciter_audio_module::exciter_audio_module()
-{
-    is_active = false;
-    srate = 0;
-    clip_in    = 0.f;
-    clip_out   = 0.f;
-    meter_in  = 0.f;
-    meter_out = 0.f;
-    meter_drive = 0.f;
-}
-
-void exciter_audio_module::activate()
-{
-    is_active = true;
-    // set all filters
-    params_changed();
-}
-
-void exciter_audio_module::deactivate()
-{
-    is_active = false;
-}
-
-void exciter_audio_module::params_changed()
-{
-    // set the params of all filters
-    if(*params[param_freq] != freq_old) {
-        hp[0][0].set_hp_rbj(*params[param_freq], 0.707, (float)srate);
-        hp[0][1].copy_coeffs(hp[0][0]);
-        hp[0][2].copy_coeffs(hp[0][0]);
-        hp[0][3].copy_coeffs(hp[0][0]);
-        if(in_count > 1 && out_count > 1) {
-            hp[1][0].copy_coeffs(hp[0][0]);
-            hp[1][1].copy_coeffs(hp[0][0]);
-            hp[1][2].copy_coeffs(hp[0][0]);
-            hp[1][3].copy_coeffs(hp[0][0]);
-        }
-        freq_old = *params[param_freq];
-    }
-    // set distortion
-    dist[0].set_params(*params[param_blend], *params[param_drive]);
-    if(in_count > 1 && out_count > 1)
-        dist[1].set_params(*params[param_blend], *params[param_drive]);
-}
-
-void exciter_audio_module::set_sample_rate(uint32_t sr)
-{
-    srate = sr;
-    dist[0].set_sample_rate(sr);
-    if(in_count > 1 && out_count > 1)
-        dist[1].set_sample_rate(sr);
-}
-
-uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    bool bypass = *params[param_bypass] > 0.5f;
-    numsamples += offset;
-    if(bypass) {
-        // everything bypassed
-        while(offset < numsamples) {
-            if(in_count > 1 && out_count > 1) {
-                outs[0][offset] = ins[0][offset];
-                outs[1][offset] = ins[1][offset];
-            } else if(in_count > 1) {
-                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
-            } else if(out_count > 1) {
-                outs[0][offset] = ins[0][offset];
-                outs[1][offset] = ins[0][offset];
-            } else {
-                outs[0][offset] = ins[0][offset];
-            }
-            ++offset;
-        }
-        // displays, too
-        clip_in    = 0.f;
-        clip_out   = 0.f;
-        meter_in  = 0.f;
-        meter_out = 0.f;
-        meter_drive = 0.f;
-    } else {
-        
-        clip_in    -= std::min(clip_in,  numsamples);
-        clip_out   -= std::min(clip_out, numsamples);
-        meter_in = 0.f;
-        meter_out = 0.f;
-        meter_drive = 0.f;
-        
-        // process
-        while(offset < numsamples) {
-            // cycle through samples
-            float out[2], in[2] = {0.f, 0.f};
-            float maxIn, maxOut, maxDrive = 0.f;
-            int c = 0;
-            
-            if(in_count > 1 && out_count > 1) {
-                // stereo in/stereo out
-                // handle full stereo
-                in[0] = ins[0][offset];
-                in[0] *= *params[param_level_in];
-                in[1] = ins[1][offset];
-                in[1] *= *params[param_level_in];
-                c = 2;
-            } else {
-                // in and/or out mono
-                // handle mono
-                in[0] = ins[0][offset];
-                in[0] *= *params[param_level_in];
-                in[1] = in[0];
-                c = 1;
-            }
-            
-            float proc[2];
-            proc[0] = in[0];
-            proc[1] = in[1];
-            
-            for (int i = 0; i < c; ++i) {
-                // all pre filters in chain
-                proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
-                
-                // saturate
-                proc[i] = dist[i].process(proc[i]);
-
-                // all post filters in chain
-                proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
-            }
-            
-            if(in_count > 1 && out_count > 1) {
-                // full stereo
-                if(*params[param_listen] > 0.f)
-                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                if(*params[param_listen] > 0.f)
-                    out[1] = proc[1] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out];
-                outs[1][offset] = out[1];
-                maxIn = std::max(fabs(in[0]), fabs(in[1]));
-                maxOut = std::max(fabs(out[0]), fabs(out[1]));
-                maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount],
-                                            dist[1].get_distortion_level() * *params[param_amount]);
-            } else if(out_count > 1) {
-                // mono -> pseudo stereo
-                if(*params[param_listen] > 0.f)
-                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                out[1] = out[0];
-                outs[1][offset] = out[1];
-                maxOut = fabs(out[0]);
-                maxIn = fabs(in[0]);
-                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
-            } else {
-                // stereo -> mono
-                // or full mono
-                if(*params[param_listen] > 0.f)
-                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                maxIn = fabs(in[0]);
-                maxOut = fabs(out[0]);
-                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
-            }
-            
-            if(maxIn > 1.f) {
-                clip_in  = srate >> 3;
-            }
-            if(maxOut > 1.f) {
-                clip_out = srate >> 3;
-            }
-            // set up in / out meters
-            if(maxIn > meter_in) {
-                meter_in = maxIn;
-            }
-            if(maxOut > meter_out) {
-                meter_out = maxOut;
-            }
-            if(maxDrive > meter_drive) {
-                meter_drive = maxDrive;
-            }
-            
-            // next sample
-            ++offset;
-        } // cycle trough samples
-        // clean up
-        hp[0][0].sanitize();
-        hp[1][0].sanitize();
-        hp[0][1].sanitize();
-        hp[1][1].sanitize();
-        hp[0][2].sanitize();
-        hp[1][2].sanitize();
-        hp[0][3].sanitize();
-        hp[1][3].sanitize();
-    }
-    // draw meters
-    if(params[param_clip_in] != NULL) {
-        *params[param_clip_in] = clip_in;
-    }
-    if(params[param_clip_out] != NULL) {
-        *params[param_clip_out] = clip_out;
-    }
-    
-    if(params[param_meter_in] != NULL) {
-        *params[param_meter_in] = meter_in;
-    }
-    if(params[param_meter_out] != NULL) {
-        *params[param_meter_out] = meter_out;
-    }
-    if(params[param_meter_drive] != NULL) {
-        *params[param_meter_drive] = meter_drive;
-    }
-    // whatever has to be returned x)
-    return outputs_mask;
-}
-
-/// Bass Enhancer by Markus Schmidt
-///
-/// This module is based on Krzysztof's filters and Tom's distortion routine.
-/// It sends the signal through a lowpass, saturates it and sends it through a lowpass again
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-bassenhancer_audio_module::bassenhancer_audio_module()
-{
-    is_active = false;
-    srate = 0;
-    clip_in    = 0.f;
-    clip_out   = 0.f;
-    meter_in  = 0.f;
-    meter_out = 0.f;
-    meter_drive = 0.f;
-}
-
-void bassenhancer_audio_module::activate()
-{
-    is_active = true;
-    // set all filters
-    params_changed();
-}
-void bassenhancer_audio_module::deactivate()
-{
-    is_active = false;
-}
-
-void bassenhancer_audio_module::params_changed()
-{
-    // set the params of all filters
-    if(*params[param_freq] != freq_old) {
-        lp[0][0].set_lp_rbj(*params[param_freq], 0.707, (float)srate);
-        lp[0][1].copy_coeffs(lp[0][0]);
-        lp[0][2].copy_coeffs(lp[0][0]);
-        lp[0][3].copy_coeffs(lp[0][0]);
-        if(in_count > 1 && out_count > 1) {
-            lp[1][0].copy_coeffs(lp[0][0]);
-            lp[1][1].copy_coeffs(lp[0][0]);
-            lp[1][2].copy_coeffs(lp[0][0]);
-            lp[1][3].copy_coeffs(lp[0][0]);
-        }
-        freq_old = *params[param_freq];
-    }
-    // set distortion
-    dist[0].set_params(*params[param_blend], *params[param_drive]);
-    if(in_count > 1 && out_count > 1)
-        dist[1].set_params(*params[param_blend], *params[param_drive]);
-}
-
-void bassenhancer_audio_module::set_sample_rate(uint32_t sr)
-{
-    srate = sr;
-    dist[0].set_sample_rate(sr);
-    if(in_count > 1 && out_count > 1)
-        dist[1].set_sample_rate(sr);
-}
-
-uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
-{
-    bool bypass = *params[param_bypass] > 0.5f;
-    numsamples += offset;
-    if(bypass) {
-        // everything bypassed
-        while(offset < numsamples) {
-            if(in_count > 1 && out_count > 1) {
-                outs[0][offset] = ins[0][offset];
-                outs[1][offset] = ins[1][offset];
-            } else if(in_count > 1) {
-                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
-            } else if(out_count > 1) {
-                outs[0][offset] = ins[0][offset];
-                outs[1][offset] = ins[0][offset];
-            } else {
-                outs[0][offset] = ins[0][offset];
-            }
-            ++offset;
-        }
-        // displays, too
-        clip_in    = 0.f;
-        clip_out   = 0.f;
-        meter_in  = 0.f;
-        meter_out = 0.f;
-        meter_drive = 0.f;
-    } else {
-        
-        clip_in    -= std::min(clip_in,  numsamples);
-        clip_out   -= std::min(clip_out, numsamples);
-        meter_in = 0.f;
-        meter_out = 0.f;
-        meter_drive = 0.f;
-        
-        // process
-        while(offset < numsamples) {
-            // cycle through samples
-            float out[2], in[2] = {0.f, 0.f};
-            float maxIn, maxOut, maxDrive = 0.f;
-            int c = 0;
-            
-            if(in_count > 1 && out_count > 1) {
-                // stereo in/stereo out
-                // handle full stereo
-                in[0] = ins[0][offset];
-                in[0] *= *params[param_level_in];
-                in[1] = ins[1][offset];
-                in[1] *= *params[param_level_in];
-                c = 2;
-            } else {
-                // in and/or out mono
-                // handle mono
-                in[0] = ins[0][offset];
-                in[0] *= *params[param_level_in];
-                in[1] = in[0];
-                c = 1;
-            }
-            
-            float proc[2];
-            proc[0] = in[0];
-            proc[1] = in[1];
-            
-            for (int i = 0; i < c; ++i) {
-                // all pre filters in chain
-                proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
-                
-                // saturate
-                proc[i] = dist[i].process(proc[i]);
-
-                // all post filters in chain
-                proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
-            }
-            
-            if(in_count > 1 && out_count > 1) {
-                // full stereo
-                if(*params[param_listen] > 0.f)
-                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                if(*params[param_listen] > 0.f)
-                    out[1] = proc[1] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out];
-                outs[1][offset] = out[1];
-                maxIn = std::max(fabs(in[0]), fabs(in[1]));
-                maxOut = std::max(fabs(out[0]), fabs(out[1]));
-                maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount],
-                                            dist[1].get_distortion_level() * *params[param_amount]);
-            } else if(out_count > 1) {
-                // mono -> pseudo stereo
-                if(*params[param_listen] > 0.f)
-                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                out[1] = out[0];
-                outs[1][offset] = out[1];
-                maxOut = fabs(out[0]);
-                maxIn = fabs(in[0]);
-                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
-            } else {
-                // stereo -> mono
-                // or full mono
-                if(*params[param_listen] > 0.f)
-                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
-                else
-                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
-                outs[0][offset] = out[0];
-                maxIn = fabs(in[0]);
-                maxOut = fabs(out[0]);
-                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
-            }
-            
-            if(maxIn > 1.f) {
-                clip_in  = srate >> 3;
-            }
-            if(maxOut > 1.f) {
-                clip_out = srate >> 3;
-            }
-            // set up in / out meters
-            if(maxIn > meter_in) {
-                meter_in = maxIn;
-            }
-            if(maxOut > meter_out) {
-                meter_out = maxOut;
-            }
-            if(maxDrive > meter_drive) {
-                meter_drive = maxDrive;
-            }
-            
-            // next sample
-            ++offset;
-        } // cycle trough samples
-        // clean up
-        lp[0][0].sanitize();
-        lp[1][0].sanitize();
-        lp[0][1].sanitize();
-        lp[1][1].sanitize();
-        lp[0][2].sanitize();
-        lp[1][2].sanitize();
-        lp[0][3].sanitize();
-        lp[1][3].sanitize();
-    }
-    // draw meters
-    if(params[param_clip_in] != NULL) {
-        *params[param_clip_in] = clip_in;
-    }
-    if(params[param_clip_out] != NULL) {
-        *params[param_clip_out] = clip_out;
-    }
-    
-    if(params[param_meter_in] != NULL) {
-        *params[param_meter_in] = meter_in;
-    }
-    if(params[param_meter_out] != NULL) {
-        *params[param_meter_out] = meter_out;
-    }
-    if(params[param_meter_drive] != NULL) {
-        *params[param_meter_drive] = meter_drive;
-    }
-    // whatever has to be returned x)
-    return outputs_mask;
-}
diff --git a/src/modules_eq.cpp b/src/modules_eq.cpp
new file mode 100644
index 0000000..d4ea0bc
--- /dev/null
+++ b/src/modules_eq.cpp
@@ -0,0 +1,381 @@
+/* Calf DSP plugin pack
+ * Equalization related plugins
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
+ *
+ * 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., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include <limits.h>
+#include <memory.h>
+#include <calf/giface.h>
+#include <calf/modules_eq.h>
+
+using namespace dsp;
+using namespace calf_plugins;
+
+#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
+
+/// Equalizer 12 Band by Markus Schmidt
+///
+/// This module is based on Krzysztof's filters. It provides a couple
+/// of different chained filters.
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+template<class BaseClass, bool has_lphp>
+equalizerNband_audio_module<BaseClass, has_lphp>::equalizerNband_audio_module()
+{
+    is_active = false;
+    srate = 0;
+    last_generation = 0;
+    clip_inL = clip_inR = clip_outL = clip_outR  = 0.f;
+    meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
+}
+
+template<class BaseClass, bool has_lphp>
+void equalizerNband_audio_module<BaseClass, has_lphp>::activate()
+{
+    is_active = true;
+    // set all filters
+    params_changed();
+}
+
+template<class BaseClass, bool has_lphp>
+void equalizerNband_audio_module<BaseClass, has_lphp>::deactivate()
+{
+    is_active = false;
+}
+
+static inline void copy_lphp(biquad_d2<float> filters[3][2])
+{
+    for (int i = 0; i < 3; i++)
+        for (int j = 0; j < 2; j++)
+            if (i || j)
+                filters[i][j].copy_coeffs(filters[0][0]);
+}
+
+template<class BaseClass, bool has_lphp>
+void equalizerNband_audio_module<BaseClass, has_lphp>::params_changed()
+{
+    // set the params of all filters
+    
+    // lp/hp first (if available)
+    if (has_lphp)
+    {
+        hp_mode = (CalfEqMode)(int)*params[AM::param_hp_mode];
+        lp_mode = (CalfEqMode)(int)*params[AM::param_lp_mode];
+
+        float hpfreq = *params[AM::param_hp_freq], lpfreq = *params[AM::param_lp_freq];
+        
+        if(hpfreq != hp_freq_old) {
+            hp[0][0].set_hp_rbj(hpfreq, 0.707, (float)srate, 1.0);
+            copy_lphp(hp);
+            hp_freq_old = hpfreq;
+        }
+        if(lpfreq != lp_freq_old) {
+            lp[0][0].set_lp_rbj(lpfreq, 0.707, (float)srate, 1.0);
+            copy_lphp(lp);
+            lp_freq_old = lpfreq;
+        }
+    }
+    
+    // then shelves
+    float hsfreq = *params[AM::param_hs_freq], hslevel = *params[AM::param_hs_level];
+    float lsfreq = *params[AM::param_ls_freq], lslevel = *params[AM::param_ls_level];
+    
+    if(lsfreq != ls_freq_old or lslevel != ls_level_old) {
+        lsL.set_lowshelf_rbj(lsfreq, 0.707, lslevel, (float)srate);
+        lsR.copy_coeffs(lsL);
+        ls_level_old = lslevel;
+        ls_freq_old = lsfreq;
+    }
+    if(hsfreq != hs_freq_old or hslevel != hs_level_old) {
+        hsL.set_highshelf_rbj(hsfreq, 0.707, hslevel, (float)srate);
+        hsR.copy_coeffs(hsL);
+        hs_level_old = hslevel;
+        hs_freq_old = hsfreq;
+    }
+    for (int i = 0; i < AM::PeakBands; i++)
+    {
+        int offset = i * params_per_band;
+        float freq = *params[AM::param_p1_freq + offset];
+        float level = *params[AM::param_p1_level + offset];
+        float q = *params[AM::param_p1_q + offset];
+        if(freq != p_freq_old[i] or level != p_level_old[i] or q != p_q_old[i]) {
+            pL[i].set_peakeq_rbj(freq, q, level, (float)srate);
+            pR[i].copy_coeffs(pL[i]);
+            p_freq_old[i] = freq;
+            p_level_old[i] = level;
+            p_q_old[i] = q;
+        }
+    }
+}
+
+template<class BaseClass, bool has_lphp>
+inline void equalizerNband_audio_module<BaseClass, has_lphp>::process_hplp(float &left, float &right)
+{
+    if (!has_lphp)
+        return;
+    if (*params[AM::param_lp_active] > 0.f)
+    {
+        switch(lp_mode)
+        {
+            case MODE12DB:
+                left = lp[0][0].process(left);
+                right = lp[0][1].process(right);
+                break;
+            case MODE24DB:
+                left = lp[1][0].process(lp[0][0].process(left));
+                right = lp[1][1].process(lp[0][1].process(right));
+                break;
+            case MODE36DB:
+                left = lp[2][0].process(lp[1][0].process(lp[0][0].process(left)));
+                right = lp[2][1].process(lp[1][1].process(lp[0][1].process(right)));
+                break;
+        }
+    }
+    if (*params[AM::param_hp_active] > 0.f)
+    {
+        switch(hp_mode)
+        {
+            case MODE12DB:
+                left = hp[0][0].process(left);
+                right = hp[0][1].process(right);
+                break;
+            case MODE24DB:
+                left = hp[1][0].process(hp[0][0].process(left));
+                right = hp[1][1].process(hp[0][1].process(right));
+                break;
+            case MODE36DB:
+                left = hp[2][0].process(hp[1][0].process(hp[0][0].process(left)));
+                right = hp[2][1].process(hp[1][1].process(hp[0][1].process(right)));
+                break;
+        }
+    }
+}
+
+template<class BaseClass, bool has_lphp>
+uint32_t equalizerNband_audio_module<BaseClass, has_lphp>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    bool bypass = *params[AM::param_bypass] > 0.f;
+    numsamples += offset;
+    if(bypass) {
+        // everything bypassed
+        while(offset < numsamples) {
+            outs[0][offset] = ins[0][offset];
+            outs[1][offset] = ins[1][offset];
+            ++offset;
+        }
+        // displays, too
+        clip_inL = clip_inR = clip_outL = clip_outR = 0.f;
+        meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
+    } else {
+        
+        clip_inL    -= std::min(clip_inL,  numsamples);
+        clip_inR    -= std::min(clip_inR,  numsamples);
+        clip_outL   -= std::min(clip_outL, numsamples);
+        clip_outR   -= std::min(clip_outR, numsamples);
+        meter_inL = 0.f;
+        meter_inR = 0.f;
+        meter_outL = 0.f;
+        meter_outR = 0.f;
+        
+        // process
+        while(offset < numsamples) {
+            // cycle through samples
+            float outL = 0.f;
+            float outR = 0.f;
+            float inL = ins[0][offset];
+            float inR = ins[1][offset];
+            // in level
+            inR *= *params[AM::param_level_in];
+            inL *= *params[AM::param_level_in];
+            
+            float procL = inL;
+            float procR = inR;
+            
+            // all filters in chain
+            process_hplp(procL, procR);
+            if(*params[AM::param_ls_active] > 0.f) {
+                procL = lsL.process(procL);
+                procR = lsR.process(procR);
+            }
+            if(*params[AM::param_hs_active] > 0.f) {
+                procL = hsL.process(procL);
+                procR = hsR.process(procR);
+            }
+            for (int i = 0; i < AM::PeakBands; i++)
+            {
+                if(*params[AM::param_p1_active + i * params_per_band] > 0.f) {
+                    procL = pL[i].process(procL);
+                    procR = pR[i].process(procR);
+                }
+            }
+            
+            outL = procL * *params[AM::param_level_out];
+            outR = procR * *params[AM::param_level_out];
+            
+            // send to output
+            outs[0][offset] = outL;
+            outs[1][offset] = outR;
+            
+            // clip LED's
+            if(inL > 1.f) {
+                clip_inL  = srate >> 3;
+            }
+            if(inR > 1.f) {
+                clip_inR  = srate >> 3;
+            }
+            if(outL > 1.f) {
+                clip_outL = srate >> 3;
+            }
+            if(outR > 1.f) {
+                clip_outR = srate >> 3;
+            }
+            // set up in / out meters
+            if(inL > meter_inL) {
+                meter_inL = inL;
+            }
+            if(inR > meter_inR) {
+                meter_inR = inR;
+            }
+            if(outL > meter_outL) {
+                meter_outL = outL;
+            }
+            if(outR > meter_outR) {
+                meter_outR = outR;
+            }
+            
+            // next sample
+            ++offset;
+        } // cycle trough samples
+        // clean up
+        for(int i = 0; i < 3; ++i) {
+            hp[i][0].sanitize();
+            hp[i][1].sanitize();
+            lp[i][0].sanitize();
+            lp[i][1].sanitize();
+        }
+        lsL.sanitize();
+        hsR.sanitize();
+        for(int i = 0; i < AM::PeakBands; ++i) {
+            pL[i].sanitize();
+            pR[i].sanitize();
+        }
+    }
+    // draw meters
+    SET_IF_CONNECTED(clip_inL)
+    SET_IF_CONNECTED(clip_inR)
+    SET_IF_CONNECTED(clip_outL)
+    SET_IF_CONNECTED(clip_outR)
+    SET_IF_CONNECTED(meter_inL)
+    SET_IF_CONNECTED(meter_inR)
+    SET_IF_CONNECTED(meter_outL)
+    SET_IF_CONNECTED(meter_outR)
+    // whatever has to be returned x)
+    return outputs_mask;
+}
+
+template<class BaseClass, bool has_lphp>
+bool equalizerNband_audio_module<BaseClass, has_lphp>::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    if (index == AM::param_p1_freq && !subindex) {
+        context->set_line_width(1.5);
+        return ::get_graph(*this, subindex, data, points);
+    }
+    return false;
+}
+
+template<class BaseClass, bool has_lphp>
+bool equalizerNband_audio_module<BaseClass, has_lphp>::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{
+    if (!is_active) {
+        return false;
+    } else {
+        return get_freq_gridline(subindex, pos, vertical, legend, context);
+    }
+}
+
+template<class BaseClass, bool has_lphp>
+int equalizerNband_audio_module<BaseClass, has_lphp>::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
+{
+    if (!is_active) {
+        return false;
+    } else {
+        bool changed = false;
+        for (int i = 0; i < graph_param_count && !changed; i++)
+        {
+            if (*params[AM::first_graph_param + i] != old_params_for_graph[i])
+                changed = true;
+        }
+        if (changed)
+        {
+            for (int i = 0; i < graph_param_count; i++)
+                old_params_for_graph[i] = *params[AM::first_graph_param + i];
+            
+            last_generation++;
+            subindex_graph = 0;
+            subindex_dot = INT_MAX;
+            subindex_gridline = INT_MAX;
+        }
+        else {
+            subindex_graph = 0;
+            subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
+        }
+        if (generation == last_calculated_generation)
+            subindex_graph = INT_MAX;
+        return last_generation;
+    }
+    return false;
+}
+
+static inline float adjusted_lphp_gain(const float *const *params, int param_active, int param_mode, const biquad_d2<float> &filter, float freq, float srate)
+{
+    if(*params[param_active] > 0.f) {
+        float gain = filter.freq_gain(freq, srate);
+        switch((int)*params[param_mode]) {
+            case MODE12DB:
+                return gain;
+            case MODE24DB:
+                return gain * gain;
+            case MODE36DB:
+                return gain * gain * gain;
+        }
+    }
+    return 1;
+}
+
+template<class BaseClass, bool use_hplp>
+float equalizerNband_audio_module<BaseClass, use_hplp>::freq_gain(int index, double freq, uint32_t sr) const
+{
+    float ret = 1.f;
+    if (use_hplp)
+    {
+        ret *= adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)sr);
+        ret *= adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)sr);
+    }
+    ret *= (*params[AM::param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1;
+    ret *= (*params[AM::param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1;
+    for (int i = 0; i < PeakBands; i++)
+        ret *= (*params[AM::param_p1_active + i * params_per_band] > 0.f) ? pL[i].freq_gain(freq, (float)sr) : 1;
+    return ret;
+}
+
+template class equalizerNband_audio_module<equalizer5band_metadata, false>;
+template class equalizerNband_audio_module<equalizer8band_metadata, true>;
+template class equalizerNband_audio_module<equalizer12band_metadata, true>;
+
diff --git a/src/modules_mod.cpp b/src/modules_mod.cpp
new file mode 100644
index 0000000..f9716c2
--- /dev/null
+++ b/src/modules_mod.cpp
@@ -0,0 +1,736 @@
+/* Calf DSP plugin pack
+ * Modulation effect plugins
+ *
+ * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
+ *
+ * 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., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include <limits.h>
+#include <memory.h>
+#include <calf/giface.h>
+#include <calf/modules_mod.h>
+
+using namespace dsp;
+using namespace calf_plugins;
+
+#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void flanger_audio_module::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);
+    is_active = true;
+}
+
+void flanger_audio_module::set_sample_rate(uint32_t sr) {
+    srate = sr;
+    left.setup(sr);
+    right.setup(sr);
+}
+
+void flanger_audio_module::deactivate() {
+    is_active = false;
+}
+
+bool flanger_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    if (index == par_delay && subindex < 2) 
+    {
+        set_channel_color(context, subindex);
+        return ::get_graph(*this, subindex, data, points);
+    }
+    return false;
+}
+
+float flanger_audio_module::freq_gain(int subindex, float freq, float srate) const
+{
+    return (subindex ? right : left).freq_gain(freq, srate);                
+}
+
+void flanger_audio_module::params_changed()
+{
+    float dry = *params[par_dryamount];
+    float wet = *params[par_amount];
+    float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]);
+    float min_delay = *params[par_delay] / 1000.0;
+    float mod_depth = *params[par_depth] / 1000.0;
+    float fb = *params[par_fb];
+    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);
+    left.set_fb(fb); right.set_fb(fb);
+    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 flanger_audio_module::params_reset()
+{
+    if (clear_reset) {
+        *params[par_reset] = 0.f;
+        clear_reset = false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+phaser_audio_module::phaser_audio_module()
+: left(MaxStages, x1vals[0], y1vals[0])
+, right(MaxStages, x1vals[1], y1vals[1])
+{
+    is_active = false;
+}
+
+void phaser_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    left.setup(sr);
+    right.setup(sr);
+}
+
+void phaser_audio_module::activate()
+{
+    is_active = true;
+    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 phaser_audio_module::deactivate()
+{
+    is_active = false;
+}
+
+bool phaser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    if (subindex < 2) 
+    {
+        set_channel_color(context, subindex);
+        return ::get_graph(*this, subindex, data, points);
+    }
+    return false;
+}
+
+float phaser_audio_module::freq_gain(int subindex, float freq, float srate) const
+{
+    return (subindex ? right : left).freq_gain(freq, srate);                
+}
+
+bool phaser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{
+    return get_freq_gridline(subindex, pos, vertical, legend, context);
+}
+
+void phaser_audio_module::params_changed()
+{
+    float dry = *params[par_dryamount];
+    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 phaser_audio_module::params_reset()
+{
+    if (clear_reset) {
+        *params[par_reset] = 0.f;
+        clear_reset = false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+rotary_speaker_audio_module::rotary_speaker_audio_module()
+{
+    mwhl_value = hold_value = 0.f;
+    phase_h = phase_l = 0.f;
+    aspeed_l = 1.f;
+    aspeed_h = 1.f;
+    dspeed = 0.f;
+}    
+
+void rotary_speaker_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    setup();
+}
+
+void rotary_speaker_audio_module::setup()
+{
+    crossover1l.set_lp_rbj(800.f, 0.7, (float)srate);
+    crossover1r.set_lp_rbj(800.f, 0.7, (float)srate);
+    crossover2l.set_hp_rbj(800.f, 0.7, (float)srate);
+    crossover2r.set_hp_rbj(800.f, 0.7, (float)srate);
+}
+
+void rotary_speaker_audio_module::activate()
+{
+    phase_h = phase_l = 0.f;
+    maspeed_h = maspeed_l = 0.f;
+    setup();
+}
+
+void rotary_speaker_audio_module::deactivate()
+{
+}
+
+void rotary_speaker_audio_module::control_change(int ctl, int val)
+{
+    if (vibrato_mode == 3 && ctl == 64)
+    {
+        hold_value = val / 127.f;
+        set_vibrato();
+        return;
+    }
+    if (vibrato_mode == 4 && ctl == 1)
+    {
+        mwhl_value = val / 127.f;
+        set_vibrato();
+        return;
+    }
+}
+
+void rotary_speaker_audio_module::params_changed()
+{
+    set_vibrato();
+}
+
+void rotary_speaker_audio_module::set_vibrato()
+{
+    vibrato_mode = fastf2i_drm(*params[par_speed]);
+    // manual vibrato - do not recalculate speeds as they're not used anyway
+    if (vibrato_mode == 5) 
+        return;
+    if (!vibrato_mode)
+        dspeed = -1;
+    else {
+        float speed = vibrato_mode - 1;
+        if (vibrato_mode == 3)
+            speed = hold_value;
+        if (vibrato_mode == 4)
+            speed = mwhl_value;
+        dspeed = (speed < 0.5f) ? 0 : 1;
+    }
+    update_speed();
+}
+
+/// Convert RPM speed to delta-phase
+uint32_t rotary_speaker_audio_module::rpm2dphase(float rpm)
+{
+    return (uint32_t)((rpm / (60.0 * srate)) * (1 << 30)) << 2;
+}
+
+/// Set delta-phase variables based on current calculated (and interpolated) RPM speed
+void rotary_speaker_audio_module::update_speed()
+{
+    float speed_h = aspeed_h >= 0 ? (48 + (400-48) * aspeed_h) : (48 * (1 + aspeed_h));
+    float speed_l = aspeed_l >= 0 ? 40 + (342-40) * aspeed_l : (40 * (1 + aspeed_l));
+    dphase_h = rpm2dphase(speed_h);
+    dphase_l = rpm2dphase(speed_l);
+}
+
+void rotary_speaker_audio_module::update_speed_manual(float delta)
+{
+    float ts = *params[par_treblespeed];
+    float bs = *params[par_bassspeed];
+    incr_towards(maspeed_h, ts, delta * 200, delta * 200);
+    incr_towards(maspeed_l, bs, delta * 200, delta * 200);
+    dphase_h = rpm2dphase(maspeed_h);
+    dphase_l = rpm2dphase(maspeed_l);
+}
+
+/// map a ramp [int] to a sinusoid-like function [0, 65536]
+static inline int pseudo_sine_scl(int counter)
+{
+    // premature optimization is a root of all evil; it can be done with integers only - but later :)
+    double v = counter * (1.0 / (65536.0 * 32768.0));
+    return (int) (32768 + 32768 * (v - v*v*v) * (1.0 / 0.3849));
+}
+
+/// Increase or decrease aspeed towards raspeed, with required negative and positive rate
+inline bool rotary_speaker_audio_module::incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc)
+{
+    if (aspeed < raspeed) {
+        aspeed = std::min(raspeed, aspeed + delta_acc);
+        return true;
+    }
+    else if (aspeed > raspeed) 
+    {
+        aspeed = std::max(raspeed, aspeed - delta_decc);
+        return true;
+    }        
+    return false;
+}
+
+uint32_t rotary_speaker_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    int shift = (int)(300000 * (*params[par_shift])), pdelta = (int)(300000 * (*params[par_spacing]));
+    int md = (int)(100 * (*params[par_moddepth]));
+    float mix = 0.5 * (1.0 - *params[par_micdistance]);
+    float mix2 = *params[par_reflection];
+    float mix3 = mix2 * mix2;
+    for (unsigned int i = 0; i < nsamples; i++) {
+        float in_l = ins[0][i + offset], in_r = ins[1][i + offset];
+        float in_mono = 0.5f * (in_l + in_r);
+        
+        int xl = pseudo_sine_scl(phase_l), yl = pseudo_sine_scl(phase_l + 0x40000000);
+        int xh = pseudo_sine_scl(phase_h), yh = pseudo_sine_scl(phase_h + 0x40000000);
+        // printf("%d %d %d\n", shift, pdelta, shift + pdelta + 20 * xl);
+        meter_l = xl;
+        meter_h = xh;
+        // float out_hi_l = in_mono - delay.get_interp_1616(shift + md * xh) + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) - delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh);
+        // float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - delay.get_interp_1616(shift + pdelta + md * xh) + delay.get_interp_1616(shift + pdelta + pdelta + md * yh);
+        float out_hi_l = in_mono + delay.get_interp_1616(shift + md * xh) - mix2 * delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) + mix3 * delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh);
+        float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - mix2 * delay.get_interp_1616(shift + pdelta + md * xh) + mix3 * delay.get_interp_1616(shift + pdelta + pdelta + md * yh);
+
+        float out_lo_l = in_mono + delay.get_interp_1616(shift + md * xl); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl);
+        float out_lo_r = in_mono + delay.get_interp_1616(shift + md * yl); // - delay.get_interp_1616(shift + pdelta + md * yl);
+        
+        out_hi_l = crossover2l.process(out_hi_l); // sanitize(out_hi_l);
+        out_hi_r = crossover2r.process(out_hi_r); // sanitize(out_hi_r);
+        out_lo_l = crossover1l.process(out_lo_l); // sanitize(out_lo_l);
+        out_lo_r = crossover1r.process(out_lo_r); // sanitize(out_lo_r);
+        
+        float out_l = out_hi_l + out_lo_l;
+        float out_r = out_hi_r + out_lo_r;
+        
+        float mic_l = out_l + mix * (out_r - out_l);
+        float mic_r = out_r + mix * (out_l - out_r);
+        
+        outs[0][i + offset] = mic_l * 0.5f;
+        outs[1][i + offset] = mic_r * 0.5f;
+        delay.put(in_mono);
+        phase_l += dphase_l;
+        phase_h += dphase_h;
+    }
+    crossover1l.sanitize();
+    crossover1r.sanitize();
+    crossover2l.sanitize();
+    crossover2r.sanitize();
+    float delta = nsamples * 1.0 / srate;
+    if (vibrato_mode == 5)
+        update_speed_manual(delta);
+    else
+    {
+        bool u1 = incr_towards(aspeed_l, dspeed, delta * 0.2, delta * 0.14);
+        bool u2 = incr_towards(aspeed_h, dspeed, delta, delta * 0.5);
+        if (u1 || u2)
+            set_vibrato();
+    }
+    if(params[par_meter_l] != NULL) {
+        *params[par_meter_l] = (float)meter_l / 65536.0;
+    }
+    if(params[par_meter_h] != NULL) {
+        *params[par_meter_h] = (float)meter_h / 65536.0;
+    }
+    return outputs_mask;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+multichorus_audio_module::multichorus_audio_module()
+{
+    is_active = false;
+    last_r_phase = -1;
+}
+
+void multichorus_audio_module::activate()
+{
+    is_active = true;
+    params_changed();
+}
+
+void multichorus_audio_module::deactivate()
+{
+    is_active = false;
+}
+
+void multichorus_audio_module::set_sample_rate(uint32_t sr) {
+    srate = sr;
+    left.setup(sr);
+    right.setup(sr);
+}
+
+bool multichorus_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    int nvoices = (int)*params[par_voices];
+    if (index == par_delay && subindex < 3) 
+    {
+        if (subindex < 2)
+            set_channel_color(context, subindex);
+        else {
+            context->set_source_rgba(0.35, 0.4, 0.2);
+            context->set_line_width(1.0);
+        }
+        return ::get_graph(*this, subindex, data, points);
+    }
+    if (index == par_rate && subindex < nvoices) {
+        const sine_multi_lfo<float, 8> &lfo = left.lfo;
+        for (int i = 0; i < points; i++) {
+            float phase = i * 2 * M_PI / points;
+            // original -65536 to 65535 value
+            float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(phase) + 1)/ 8192.0) - 65536;
+            // scale to -1..1
+            data[i] = orig / 65536.0;
+        }
+        return true;
+    }
+    return false;
+}
+
+bool multichorus_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
+{
+    int voice = subindex >> 1;
+    int nvoices = (int)*params[par_voices];
+    if ((index != par_rate && index != par_depth) || voice >= nvoices)
+        return false;
+
+    float unit = (1 - *params[par_overlap]);
+    float scw = 1 + unit * (nvoices - 1);
+    set_channel_color(context, subindex);
+    const sine_multi_lfo<float, 8> &lfo = (subindex & 1 ? right : left).lfo;
+    if (index == par_rate)
+    {
+        x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
+        y = 0.95 * sin(x * 2 * M_PI);
+        y = (voice * unit + (y + 1) / 2) / scw * 2 - 1;
+    }
+    else
+    {
+        double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
+        x = 0.5 + 0.5 * sin(ph * 2 * M_PI);
+        y = subindex & 1 ? -0.75 : 0.75;
+        x = (voice * unit + x) / scw;
+    }
+    return true;
+}
+
+bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{
+    if (index == par_rate && !subindex)
+    {
+        pos = 0;
+        vertical = false;
+        return true;
+    }
+    if (index == par_delay)
+        return get_freq_gridline(subindex, pos, vertical, legend, context);
+    return false;
+}
+
+float multichorus_audio_module::freq_gain(int subindex, float freq, float srate) const
+{
+    if (subindex == 2)
+        return *params[par_amount] * left.post.freq_gain(freq, srate);
+    return (subindex ? right : left).freq_gain(freq, srate);                
+}
+
+void multichorus_audio_module::params_changed()
+{
+    // delicious copy-pasta from flanger module - it'd be better to keep it common or something
+    float dry = *params[par_dryamount];
+    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;
+    float overlap = *params[par_overlap];
+    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);
+    int voices = (int)*params[par_voices];
+    left.lfo.set_voices(voices); right.lfo.set_voices(voices);
+    left.lfo.set_overlap(overlap);right.lfo.set_overlap(overlap);
+    float vphase = *params[par_vphase] * (1.f / 360.f);
+    left.lfo.vphase = right.lfo.vphase = vphase * (4096 / std::max(voices - 1, 1));
+    float r_phase = *params[par_stereo] * (1.f / 360.f);
+    if (fabs(r_phase - last_r_phase) > 0.0001f) {
+        right.lfo.phase = left.lfo.phase;
+        right.lfo.phase += chorus_phase(r_phase * 4096);
+        last_r_phase = r_phase;
+    }
+    left.post.f1.set_bp_rbj(*params[par_freq], *params[par_q], srate);
+    left.post.f2.set_bp_rbj(*params[par_freq2], *params[par_q], srate);
+    right.post.f1.copy_coeffs(left.post.f1);
+    right.post.f2.copy_coeffs(left.post.f2);
+}
+
+uint32_t multichorus_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    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
+}
+
+/// Pulsator by Markus Schmidt
+///
+/// This module provides a couple
+/// of different LFO's for modulating the level of a signal.
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+pulsator_audio_module::pulsator_audio_module()
+{
+    is_active = false;
+    srate = 0;
+//    last_generation = 0;
+    clip_inL    = 0.f;
+    clip_inR    = 0.f;
+    clip_outL   = 0.f;
+    clip_outR   = 0.f;
+    meter_inL  = 0.f;
+    meter_inR  = 0.f;
+    meter_outL = 0.f;
+    meter_outR = 0.f;
+}
+
+void pulsator_audio_module::activate()
+{
+    is_active = true;
+    lfoL.activate();
+    lfoR.activate();
+    params_changed();
+}
+void pulsator_audio_module::deactivate()
+{
+    is_active = false;
+    lfoL.deactivate();
+    lfoR.deactivate();
+}
+
+void pulsator_audio_module::params_changed()
+{
+    lfoL.set_params(*params[param_freq], *params[param_mode], 0.f, srate, *params[param_amount]);
+    lfoR.set_params(*params[param_freq], *params[param_mode], *params[param_offset], srate, *params[param_amount]);
+    clear_reset = false;
+    if (*params[param_reset] >= 0.5) {
+        clear_reset = true;
+        lfoL.set_phase(0.f);
+        lfoR.set_phase(0.f);
+    }
+}
+
+void pulsator_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+}
+
+uint32_t pulsator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    bool bypass = *params[param_bypass] > 0.5f;
+    uint32_t samples = numsamples + offset;
+    if(bypass) {
+        // everything bypassed
+        while(offset < samples) {
+            outs[0][offset] = ins[0][offset];
+            outs[1][offset] = ins[1][offset];
+            ++offset;
+        }
+        // displays, too
+        clip_inL    = 0.f;
+        clip_inR    = 0.f;
+        clip_outL   = 0.f;
+        clip_outR   = 0.f;
+        meter_inL  = 0.f;
+        meter_inR  = 0.f;
+        meter_outL = 0.f;
+        meter_outR = 0.f;
+        
+        // LFO's should go on
+        lfoL.advance(numsamples);
+        lfoR.advance(numsamples);
+        
+    } else {
+        
+        clip_inL    -= std::min(clip_inL,  numsamples);
+        clip_inR    -= std::min(clip_inR,  numsamples);
+        clip_outL   -= std::min(clip_outL, numsamples);
+        clip_outR   -= std::min(clip_outR, numsamples);
+        meter_inL = 0.f;
+        meter_inR = 0.f;
+        meter_outL = 0.f;
+        meter_outR = 0.f;
+        
+        // process
+        while(offset < samples) {
+            // cycle through samples
+            float outL = 0.f;
+            float outR = 0.f;
+            float inL = ins[0][offset];
+            float inR = ins[1][offset];
+            // in level
+            inR *= *params[param_level_in];
+            inL *= *params[param_level_in];
+            
+            if(*params[param_mono] > 0.5) {
+                inL = (inL + inR) * 0.5;
+                inR = inL;
+            }
+            float procL = inL;
+            float procR = inR;
+            
+            procL *= (lfoL.get_value() * 0.5 + *params[param_amount] / 2);
+            procR *= (lfoR.get_value() * 0.5 + *params[param_amount] / 2);
+            
+            outL = procL + inL * (1 - *params[param_amount]);
+            outR = procR + inR * (1 - *params[param_amount]);
+            
+            outL *=  *params[param_level_out];
+            outR *=  *params[param_level_out];
+            
+            // send to output
+            outs[0][offset] = outL;
+            outs[1][offset] = outR;
+            
+            // clip LED's
+            if(inL > 1.f) {
+                clip_inL  = srate >> 3;
+            }
+            if(inR > 1.f) {
+                clip_inR  = srate >> 3;
+            }
+            if(outL > 1.f) {
+                clip_outL = srate >> 3;
+            }
+            if(outR > 1.f) {
+                clip_outR = srate >> 3;
+            }
+            // set up in / out meters
+            if(inL > meter_inL) {
+                meter_inL = inL;
+            }
+            if(inR > meter_inR) {
+                meter_inR = inR;
+            }
+            if(outL > meter_outL) {
+                meter_outL = outL;
+            }
+            if(outR > meter_outR) {
+                meter_outR = outR;
+            }
+            
+            // next sample
+            ++offset;
+            
+            // advance lfo's
+            lfoL.advance(1);
+            lfoR.advance(1);
+        } // cycle trough samples
+    }
+    // draw meters
+    SET_IF_CONNECTED(clip_inL)
+    SET_IF_CONNECTED(clip_inR)
+    SET_IF_CONNECTED(clip_outL)
+    SET_IF_CONNECTED(clip_outR)
+    SET_IF_CONNECTED(meter_inL)
+    SET_IF_CONNECTED(meter_inR)
+    SET_IF_CONNECTED(meter_outL)
+    SET_IF_CONNECTED(meter_outR)
+    // whatever has to be returned x)
+    return outputs_mask;
+}
+
+bool pulsator_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    if (!is_active) {
+        return false;
+    } else if(index == param_freq) {
+        if(subindex == 0) {
+            context->set_source_rgba(0.35, 0.4, 0.2, 1);
+            return lfoL.get_graph(data, points, context);
+        }
+        if(subindex == 1) {
+            context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
+            return lfoR.get_graph(data, points, context);
+        }
+    }
+    return false;
+}
+
+bool pulsator_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
+{
+    if (!is_active) {
+        return false;
+    } else if(index == param_freq) {
+        if(subindex == 0) {
+            context->set_source_rgba(0.35, 0.4, 0.2, 1);
+            return lfoL.get_dot(x, y, size, context);
+        }
+        if(subindex == 1) {
+            context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
+            return lfoR.get_dot(x, y, size, context);
+        }
+        return false;
+    }
+    return false;
+}
+
+bool pulsator_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{
+   if (index == param_freq && !subindex)
+    {
+        pos = 0;
+        vertical = false;
+        return true;
+    }
+    return false;
+}
diff --git a/src/plugin.cpp b/src/plugin.cpp
index 1f6a5c4..0905902 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -1,7 +1,7 @@
-/* Calf DSP Library
- * Example audio modules - LADSPA/DSSI/LV2 wrapper instantiation
+/* Calf DSP plugin pack
+ * LADSPA/DSSI/LV2 wrapper instantiation for all plugins
  *
- * Copyright (C) 2001-2008 Krzysztof Foltman
+ * Copyright (C) 2001-2010 Krzysztof Foltman
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,10 @@
 #include <calf/lv2wrap.h>
 #include <calf/modules.h>
 #include <calf/modules_dev.h>
+#include <calf/modules_dist.h>
+#include <calf/modules_eq.h>
+#include <calf/modules_mod.h>
+#include <calf/modules_synths.h>
 #include <calf/organ.h>
 
 using namespace calf_plugins;

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list