[SCM] calf/master: Merge branch 'master' into saturators

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:39:49 UTC 2013


+ EQ-12: fix labels
+ EQ-8: correct overrides for input and output VU meters
+ Equalizers: convert lists of per-band parameters using macros (ugly, but effective)
+ EQ-8, EQ-12: reduce copypasta by using a class template
+ EQ-8: use label overrides to cover up the cover up of GStreamer bug ;)
+ GUI: make 'text' attribute for labels higher-priority than 'param' attribute
+ Compatibility: workaround for GStreamer crash bug in Ubuntu 9.10 (thanks to Stefan Kost for diagnosing the problem and suggesting the workaround)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
X-Git-Refname: refs/heads/master
X-Git-Reftype: branch
X-Git-Oldrev: d6a3c1a63a147948535a50da009275278ad5e6a3
X-Git-Newrev: 34569260c452f0fa4c543155ebba174a42a343dc

The following commit has been merged in the master branch:
commit 77c43617be727add27997d1e5cbd90d1378dd436
Merge: d10b50b3ea6d5dbb8989ee380cfa5479bf3209d9 5882b0684b10f778d220f6f02f929e20477aab06
Author: Markus Schmidt <schmidt at boomshop.net>
Date:   Mon Nov 16 09:45:14 2009 +0100

    Merge branch 'master' into saturators

diff --combined src/calf/metadata.h
index ad35275,a992590..4dd2275
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@@ -92,6 -92,12 +92,12 @@@ public
      PLUGIN_NAME_ID_LABEL("multichorus", "multichorus", "Multi Chorus")
  };
  
+ enum CalfEqMode {
+     MODE12DB,
+     MODE24DB,
+     MODE36DB
+ };
+ 
  /// Monosynth - metadata
  struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
  {
@@@ -211,6 -217,7 +217,7 @@@ struct equalizer8band_metadata: public 
             param_p3_active, param_p3_level, param_p3_freq, param_p3_q,
             param_p4_active, param_p4_level, param_p4_freq, param_p4_q,
             param_count };
+     enum { PeakBands = 4, first_graph_param = param_hp_active, last_graph_param = param_p4_q };
      PLUGIN_NAME_ID_LABEL("equalizer8band", "equalizer8band", "Equalizer 8 Band")
  };
  /// Markus's 12-band EQ - metadata
@@@ -232,37 -239,10 +239,38 @@@ struct equalizer12band_metadata: publi
             param_p7_active, param_p7_level, param_p7_freq, param_p7_q,
             param_p8_active, param_p8_level, param_p8_freq, param_p8_q,
             param_count };
+     enum { PeakBands = 8, first_graph_param = param_hp_active, last_graph_param = param_p8_q };
      PLUGIN_NAME_ID_LABEL("equalizer12band", "equalizer12band", "Equalizer 12 Band")
  };
  
 +/// Markus's Saturator - metadata
 +struct saturator_metadata: public plugin_metadata<saturator_metadata>
 +{
 +    enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true };
 +    enum { param_bypass, param_level_in, param_level_out, param_mix, param_meter_in,
 +           param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive,
 +           param_lp_pre_freq, param_hp_pre_freq, param_lp_post_freq, param_hp_post_freq,
 +           param_p_freq, param_p_level, param_p_q, param_count };
 +    PLUGIN_NAME_ID_LABEL("saturator", "saturator", "Saturator")
 +};
 +/// Markus's Exciter - metadata
 +struct exciter_metadata: public plugin_metadata<exciter_metadata>
 +{
 +    enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true };
 +    enum { param_bypass, param_level_in, param_level_out, param_amount, param_meter_in,
 +           param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive,
 +           param_freq, param_listen, param_count };
 +    PLUGIN_NAME_ID_LABEL("exciter", "exciter", "Exciter")
 +};
 +/// Markus's Bass Enhancer - metadata
 +struct bassenhancer_metadata: public plugin_metadata<bassenhancer_metadata>
 +{
 +    enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true };
 +    enum { param_bypass, param_level_in, param_level_out, param_amount, param_meter_in,
 +           param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive,
 +           param_freq, param_listen, param_count };
 +    PLUGIN_NAME_ID_LABEL("bassenhancer", "bassenhancer", "Bass Enhancer")
 +};
  /// Organ - enums for parameter IDs etc. (this mess is caused by organ split between plugin and generic class - which was
  /// a bad design decision and should be sorted out some day) XXXKF @todo
  struct organ_enums
diff --combined src/calf/modules.h
index 000505f,6c9008a..b46ddf3
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@@ -37,7 -37,7 +37,7 @@@ namespace calf_plugins 
  using namespace dsp;
  
  struct ladspa_plugin_info;
-     
+ 
  #if 0
  class amp_audio_module: public null_audio_module
  {
@@@ -1038,120 -1038,28 +1038,28 @@@ public
      int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
  };
  
- /// Equalizer 12 Band by Markus Schmidt (based on Krzysztof's filters)
- class equalizer12band_audio_module: public audio_module<equalizer12band_metadata>, public frequency_response_line_graph  {
- private:
-     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[8], p_freq_old[8], p_q_old[8];
-     float hp_mode_old1, hp_freq_old1, hp_active_old1;
-     float lp_mode_old1, lp_freq_old1, lp_active_old1;
-     float ls_level_old1, ls_freq_old1, ls_active_old1;
-     float hs_level_old1, hs_freq_old1, hs_active_old1;
-     float p_level_old1[8], p_freq_old1[8], p_q_old1[8], p_active_old1[8];
-     enum CalfEqModes {
-         MODE12DB,
-         MODE24DB,
-         MODE36DB
-     };
-     CalfEqModes eq_mode, eq_mode_old1[2];
-     uint32_t clip_inL, clip_outL, clip_inR, clip_outR;
-     float meter_inL, meter_outL, meter_inR, meter_outR;
-     biquad_d2<float> hpL[3], hpR[3], lpL[3], lpR[3];
-     biquad_d2<float> lsL, lsR, hsL, hsR;
-     biquad_d2<float> pL[8], pR[8];
+ /// Equalizer N Band by Markus Schmidt (based on Krzysztof's filters)
+ template<class BaseClass>
+ class equalizerNband_audio_module: public audio_module<BaseClass>, public frequency_response_line_graph {
  public:
-     typedef std::complex<double> cfloat;
-     float *ins[in_count];
-     float *outs[out_count];
-     float *params[param_count];
-     uint32_t srate;
-     bool is_active;
-     volatile int last_generation, last_calculated_generation;
-     equalizer12band_audio_module();
-     void activate();
-     void deactivate();
-     void params_changed();
-     float freq_gain(int index, double freq, uint32_t sr)
-     {
-         float ret = 1.f;
-         if(*params[param_hp_active] > 0.f) {
-             switch((int)*params[param_hp_mode]) {
-                 case MODE12DB:
-                     ret *= hpL[0].freq_gain(freq, sr);
-                     ret *= hpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE24DB:
-                     ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr);
-                     ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE36DB:
-                     ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr);
-                     ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr);
-                     break;
-             }
-         }
-         if(*params[param_lp_active] > 0.f) {
-             switch((int)*params[param_lp_mode]) {
-                 case MODE12DB:
-                     ret *= lpL[0].freq_gain(freq, sr);
-                     ret *= lpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE24DB:
-                     ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr);
-                     ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE36DB:
-                     ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr);
-                     ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr);
-                     break;
-             }
-         }
-         ret *= (*params[param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1;
-         ret *= (*params[param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p1_active] > 0.f) ? pL[0].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p2_active] > 0.f) ? pL[1].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p3_active] > 0.f) ? pL[2].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p4_active] > 0.f) ? pL[3].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p5_active] > 0.f) ? pL[4].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p6_active] > 0.f) ? pL[5].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p7_active] > 0.f) ? pL[6].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p8_active] > 0.f) ? pL[7].freq_gain(freq, sr) : 1;
-         return ret;
-     }
-     void set_sample_rate(uint32_t 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);
-     bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context);
-     int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
- };
- 
- /// Equalizer 8 Band by Markus Schmidt (based on Krzysztof's filters)
- class equalizer8band_audio_module: public audio_module<equalizer8band_metadata>, public frequency_response_line_graph  {
+     typedef audio_module<BaseClass> AM;
+     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[4], p_freq_old[4], p_q_old[4];
-     float hp_mode_old1, hp_freq_old1, hp_active_old1;
-     float lp_mode_old1, lp_freq_old1, lp_active_old1;
-     float ls_level_old1, ls_freq_old1, ls_active_old1;
-     float hs_level_old1, hs_freq_old1, hs_active_old1;
-     float p_level_old1[4], p_freq_old1[4], p_q_old1[4], p_active_old1[4];
-     enum CalfEqModes {
-         MODE12DB,
-         MODE24DB,
-         MODE36DB
-     };
-     CalfEqModes eq_mode, eq_mode_old1[2];
+     float p_level_old[PeakBands], p_freq_old[PeakBands], p_q_old[PeakBands];
+     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;
-     biquad_d2<float> hpL[3], hpR[3], lpL[3], lpR[3];
+     biquad_d2<float> hp[3][2], lp[3][2];
      biquad_d2<float> lsL, lsR, hsL, hsR;
-     biquad_d2<float> pL[4], pR[4];
+     biquad_d2<float> pL[PeakBands], pR[PeakBands];
  public:
      typedef std::complex<double> cfloat;
      float *ins[in_count];
@@@ -1160,60 -1068,24 +1068,24 @@@
      uint32_t srate;
      bool is_active;
      volatile int last_generation, last_calculated_generation;
-     equalizer8band_audio_module();
+     equalizerNband_audio_module();
      void activate();
      void deactivate();
      void params_changed();
-     float freq_gain(int index, double freq, uint32_t sr)
+     float freq_gain(int index, double freq, uint32_t sr);
+     void set_sample_rate(uint32_t sr)
      {
-         float ret = 1.f;
-         if(*params[param_hp_active] > 0.f) {
-             switch((int)*params[param_hp_mode]) {
-                 case MODE12DB:
-                     ret *= hpL[0].freq_gain(freq, sr);
-                     ret *= hpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE24DB:
-                     ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr);
-                     ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE36DB:
-                     ret *= hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr) * hpL[0].freq_gain(freq, sr);
-                     ret *= hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr) * hpR[0].freq_gain(freq, sr);
-                     break;
-             }
-         }
-         if(*params[param_lp_active] > 0.f) {
-             switch((int)*params[param_lp_mode]) {
-                 case MODE12DB:
-                     ret *= lpL[0].freq_gain(freq, sr);
-                     ret *= lpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE24DB:
-                     ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr);
-                     ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr);
-                     break;
-                 case MODE36DB:
-                     ret *= lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr) * lpL[0].freq_gain(freq, sr);
-                     ret *= lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr) * lpR[0].freq_gain(freq, sr);
-                     break;
-             }
-         }
-         ret *= (*params[param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1;
-         ret *= (*params[param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p1_active] > 0.f) ? pL[0].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p2_active] > 0.f) ? pL[1].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p3_active] > 0.f) ? pL[2].freq_gain(freq, sr) : 1;
-         ret *= (*params[param_p4_active] > 0.f) ? pL[3].freq_gain(freq, sr) : 1;
-         return ret;
+         srate = sr;
      }
-     void set_sample_rate(uint32_t 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);
      bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context);
      int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
  };
  
+ typedef equalizerNband_audio_module<equalizer8band_metadata> equalizer8band_audio_module;
+ typedef equalizerNband_audio_module<equalizer12band_metadata> equalizer12band_audio_module;
+ 
  /// Equalizer 5 Band by Markus Schmidt (based on Krzysztof's filters)
  class equalizer5band_audio_module: public audio_module<equalizer5band_metadata>, public frequency_response_line_graph  {
  private:
@@@ -1256,115 -1128,6 +1128,115 @@@ public
      int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
  };
  
 +class distortion_audio_module {
 +private:
 +    float blend_old, drive_old;
 +    float meter;
 +    float rdrive, rbdr, kpa, kpb, kna, knb, ap, an, imr, kc, srct, sq, pwrq;
 +    float prev_med, prev_out;
 +public:
 +    uint32_t srate;
 +    bool is_active;
 +    distortion_audio_module();
 +    void activate();
 +    void deactivate();
 +    void set_params(float blend, float drive);
 +    void set_sample_rate(uint32_t sr);
 +    float process(float in);
 +    float get_distortion_level();
 +    static inline float
 +    // NOTICE!! These routines are implemented for testing purposes only!
 +    // They're taken from TAP Plugins and will act as a placeholder until
 +    // Krzysztof's distrotion routine is ready!
 +    M(float x) {
 +
 +        if ((x > 0.000000001f) || (x < -0.000000001f))
 +            return x;
 +        else
 +            return 0.0f;
 +    }
 +
 +    static inline float
 +    D(float x) {
 +
 +        if (x > 0.000000001f)
 +            return sqrt(x);
 +        else if (x < -0.000000001f)
 +            return sqrt(-x);
 +        else
 +            return 0.0f;
 +    }
 +};
 +
 +/// Saturator by Markus Schmidt (based on Krzysztof's filters and 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];
 +    distortion_audio_module dist[2];
 +public:
 +    float *ins[in_count];
 +    float *outs[out_count];
 +    float *params[param_count];
 +    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 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];
 +    distortion_audio_module dist[2];
 +public:
 +    float *ins[in_count];
 +    float *outs[out_count];
 +    float *params[param_count];
 +    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 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];
 +    distortion_audio_module dist[2];
 +public:
 +    float *ins[in_count];
 +    float *outs[out_count];
 +    float *params[param_count];
 +    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 audio_module<filterclavier_metadata>, 
diff --combined src/modules.cpp
index e3b747f,fec7c53..14f27d8
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@@ -31,7 -31,7 +31,7 @@@
  using namespace dsp;
  using namespace calf_plugins;
  
- const char *calf_plugins::calf_copyright_info = "(C) 2001-2008 Krzysztof Foltman, license: LGPL";
+ const char *calf_plugins::calf_copyright_info = "(C) 2001-2009 Krzysztof Foltman, Thor Harald Johanssen, Markus Schmidt and others; license: LGPL";
  
  ////////////////////////////////////////////////////////////////////////////
  
@@@ -222,8 -222,8 +222,8 @@@ CALF_PORT_PROPS(compressor) = 
      { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
      { 0,      0,  1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
      { 0,      0,  1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
-     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
-     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
+     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB-In" },
+     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB-Out" },
      { 0.125,      0.000976563, 1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" },
      { 2,      1, 20,  21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" },
      { 20,     0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" },
@@@ -261,8 -261,8 +261,8 @@@ CALF_PORT_PROPS(sidechaincompressor) = 
      { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
      { 0,      0,  1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
      { 0,      0,  1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
-     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
-     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
+     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB-In" },
+     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB-Out" },
      { 0.125,      0.000976563, 1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" },
      { 2,      1, 20,  21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" },
      { 20,     0.01, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" },
@@@ -273,13 -273,13 +273,13 @@@
      { 0,      0,  1,    0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_stereo_link_names, "stereo_link", "Stereo Link" },
      { 0, 0.03125, 1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Gain Reduction" },
      { 0,      0,  9,    0, PF_ENUM | PF_CTL_COMBO, sidechaincompressor_mode_names, "sc_mode", "Sidechain Mode" },
-     { 250,    10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "Freq" },
-     { 4500,   10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "Freq" },
-     { 1,      0.0625,  16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "Level" },
-     { 1,      0.0625,  16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "Level" },
+     { 250,    10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "F1 Freq" },
+     { 4500,   10,18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "F2 Freq" },
+     { 1,      0.0625,  16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "F1 Level" },
+     { 1,      0.0625,  16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "F2 Level" },
      { 0,      0,  1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" },
-     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f1_active", "active" },
-     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "active" },
+     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f1_active", "F1 Active" },
+     { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "F2 Active" },
  };
  
  CALF_PLUGIN_INFO(sidechaincompressor) = { 0x8502, "Sidechaincompressor", "Calf Sidechain Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
@@@ -298,74 -298,74 +298,74 @@@ CALF_PORT_PROPS(multibandcompressor) = 
      { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "Input R" },
      { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "Output L" },
      { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "Output R" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB-InL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
      
      { 100,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" },
      { 1000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" },
      { 6000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" },
      
-     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S" },
-     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S" },
-     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S" },
+     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S0" },
+     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S1" },
+     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S2" },
      
-     { 0.895025,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q" },
-     { 0.895025,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q" },
-     { 0.895025,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q" },
+     { 0.895025,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q0" },
+     { 0.895025,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q1" },
+     { 0.895025,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q2" },
      
      
-     { 0.0625,      0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold0", "Threshold" },
-     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio0", "Ratio" },
-     { 50,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack0", "Attack" },
-     { 100,         0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release0", "Release" },
-     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup0", "Makeup" },
-     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee0", "Knee" },
-     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection0", "Detection" },
-     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression0", "Gain Reduction" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output0", "Output" },
-     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass0", "Bypass" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute0", "Mute" },
+     { 0.0625,      0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold0", "Threshold 1" },
+     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio0", "Ratio 1" },
+     { 50,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack0", "Attack 1" },
+     { 100,         0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release0", "Release 1" },
+     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup0", "Makeup 1" },
+     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee0", "Knee 1" },
+     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection0", "Detection 1" },
+     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression0", "Gain Reduction 1" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output0", "Output 1" },
+     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass0", "Bypass 1" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute0", "Mute 1" },
      
      
-     { 0.03125,     0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold1", "Threshold" },
-     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio1", "Ratio" },
-     { 25,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack1", "Attack" },
-     { 50,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release1", "Release" },
-     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup1", "Makeup" },
-     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee1", "Knee" },
-     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection1", "Detection" },
-     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression1", "Gain Reduction" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output1", "Output" },
-     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass1", "Bypass" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute1", "Mute" },
+     { 0.03125,     0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold1", "Threshold 2" },
+     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio1", "Ratio 2" },
+     { 25,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack1", "Attack 2" },
+     { 50,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release1", "Release 2" },
+     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup1", "Makeup 2" },
+     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee1", "Knee 2" },
+     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection1", "Detection 2" },
+     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression1", "Gain Reduction 2" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output1", "Output 2" },
+     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass1", "Bypass 2" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute1", "Mute 2" },
      
      
-     { 0.015625,    0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold2", "Threshold" },
-     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio2", "Ratio" },
-     { 12.5,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack2", "Attack" },
-     { 25,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release2", "Release" },
-     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup2", "Makeup" },
-     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee2", "Knee" },
-     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection2", "Detection" },
-     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression2", "Gain Reduction" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output2", "Output" },
-     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass2", "Bypass" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute2", "Mute" },
+     { 0.015625,    0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold2", "Threshold 3" },
+     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio2", "Ratio 3" },
+     { 12.5,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack2", "Attack 3" },
+     { 25,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release2", "Release 3" },
+     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup2", "Makeup 3" },
+     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee2", "Knee 3" },
+     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection2", "Detection 3" },
+     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression2", "Gain Reduction 3" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output2", "Output 3" },
+     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass2", "Bypass 3" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute2", "Mute 3" },
      
      
-     { 0.0078125,   0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold3", "Threshold" },
-     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio3", "Ratio" },
-     { 6.25,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack3", "Attack" },
-     { 12.5,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release3", "Release" },
-     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup3", "Makeup" },
-     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee3", "Knee" },
-     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection3", "Detection" },
-     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression3", "Gain Reduction" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output3", "Output" },
-     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass3", "Bypass" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute3", "Mute" },
+     { 0.0078125,   0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold3", "Threshold 4" },
+     { 3,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio3", "Ratio 4" },
+     { 6.25,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack3", "Attack 4" },
+     { 12.5,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release3", "Release 4" },
+     { 2,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup3", "Makeup 4" },
+     { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee3", "Knee 4" },
+     { 1,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection3", "Detection 4" },
+     { 1,           0.03125,     1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression3", "Gain Reduction 4" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output3", "Output 4" },
+     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass3", "Bypass 4" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mute3", "Mute 4" },
  };
  
  CALF_PLUGIN_INFO(multibandcompressor) = { 0x8502, "Multibandcompressor", "Calf Multiband Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
@@@ -407,30 -407,30 +407,30 @@@ CALF_PORT_NAMES(equalizer5band) = {"In 
  
  CALF_PORT_PROPS(equalizer5band) = {
      { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
-     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
-     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
- 
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level" },
-     { 200,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq" },
+     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input Gain" },
+     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output Gain" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input Level" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output Level" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB-In" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB-Out" },
+ 
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "LS Active" },
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level L" },
+     { 200,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq L" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level" },
-     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "HS Active" },
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level H" },
+     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq H" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "active" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "F1 Active" },
      { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p1_level", "Level 1" },
      { 250,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p1_freq", "Freq 1" },
      { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p1_q", "Q 1" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "active" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "F2 Active" },
      { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p2_level", "Level 2" },
      { 1000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p2_freq", "Freq 2" },
      { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p2_q", "Q 2" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "active" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "F3 Active" },
      { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p3_level", "Level 3" },
      { 2500,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p3_freq", "Freq 3" },
      { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p3_q", "Q 3" },
@@@ -440,54 -440,48 +440,48 @@@ CALF_PLUGIN_INFO(equalizer5band) = { 0x
  
  //////////////////////////////////////////////////////////////////////////////
  
+ #define EQ_BAND_PARAMS(band, frequency) \
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p" #band "_active", "F" #band " Active" }, \
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p" #band "_level", "Level " #band }, \
+     { frequency,   10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p" #band "_freq", "Freq " #band }, \
+     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p" #band "_q", "Q " #band },
+ 
  CALF_PORT_NAMES(equalizer8band) = {"In L", "In R", "Out L", "Out R"};
- const char *rolloff_mode_names[] = {"12dB", "24dB", "36dB"};
+ const char *rolloff_mode_names[] = {"12dB/oct", "24dB/oct", "36dB/oct"};
  
  CALF_PORT_PROPS(equalizer8band) = {
      { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
-     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
-     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "L" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "R" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "L" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "R" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" },
- 
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "active" },
-     { 30,          10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "Freq" },
-     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "Mode" },
+     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input Gain" },
+     { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output Gain" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "Meter-InL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "Meter-InR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "Meter-OutL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "Meter-OutR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB-InL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
+ 
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "HP Active" },
+     { 30,          10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "HP Freq" },
+     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "HP Mode" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "active" },
-     { 18000,       10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "Freq" },
-     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "Mode" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "LP Active" },
+     { 18000,       10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "LP Freq" },
+     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "LP Mode" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level" },
-     { 200,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "LS Active" },
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "LS Level" },
+     { 200,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "LS Freq" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level" },
-     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "HS Active" },
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "HS Level" },
+     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "HS Freq" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p1_level", "Level 1" },
-     { 250,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p1_freq", "Freq 1" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p1_q", "Q 1" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p2_level", "Level 2" },
-     { 1000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p2_freq", "Freq 2" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p2_q", "Q 2" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p3_level", "Level 3" },
-     { 2500,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p3_freq", "Freq 3" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p3_q", "Q 3" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p4_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p4_level", "Level 4" },
-     { 5000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p4_freq", "Freq 4" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p4_q", "Q 4" },
+     EQ_BAND_PARAMS(1, 250)
+     EQ_BAND_PARAMS(2, 1000)
+     EQ_BAND_PARAMS(3, 2500)
+     EQ_BAND_PARAMS(4, 5000)
  };
  
  CALF_PLUGIN_INFO(equalizer8band) = { 0x8501, "Equalizer8Band", "Calf Equalizer 8 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
@@@ -500,146 -494,45 +494,122 @@@ CALF_PORT_PROPS(equalizer12band) = 
      { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
      { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
      { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "L" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "R" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "L" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "R" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" },
-     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" },
- 
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "active" },
-     { 30,          10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "Freq" },
-     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "Mode" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inL", "InL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_inR", "InR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outL", "OutL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_outR", "OutR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB-InL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
+     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
+ 
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hp_active", "HP Active" },
+     { 30,          10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_freq", "Freq HP" },
+     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "hp_mode", "Mode HP" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "active" },
-     { 18000,       10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "Freq" },
-     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "Mode" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "lp_active", "LP Active" },
+     { 18000,       10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_freq", "Freq LP" },
+     { 1,           0,           2,     0,  PF_ENUM | PF_CTL_COMBO, rolloff_mode_names, "lp_mode", "Mode LP" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level" },
-     { 200,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ls_active", "LS Active" },
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "ls_level", "Level LS" },
+     { 200,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ls_freq", "Freq LS" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level" },
-     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq" },
+     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "hs_active", "LS Active" },
+     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "hs_level", "Level HS" },
+     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hs_freq", "Freq HS" },
      
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p1_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p1_level", "Level 1" },
-     { 60,          10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "p1_freq", "Freq 1" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p1_q", "Q 1" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p2_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p2_level", "Level 2" },
-     { 120,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p2_freq", "Freq 2" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p2_q", "Q 2" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p3_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p3_level", "Level 3" },
-     { 250,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p3_freq", "Freq 3" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p3_q", "Q 3" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p4_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p4_level", "Level 4" },
-     { 500,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p4_freq", "Freq 4" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p4_q", "Q 4" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p5_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p5_level", "Level 5" },
-     { 1000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p5_freq", "Freq 5" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p5_q", "Q 5" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p6_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p6_level", "Level 6" },
-     { 2500,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p6_freq", "Freq 6" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p6_q", "Q 6" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p7_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p7_level", "Level 7" },
-     { 4000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p7_freq", "Freq 7" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p7_q", "Q 7" },
-     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "p8_active", "active" },
-     { 1,           0.015625,    64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p8_level", "Level 8" },
-     { 6000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p8_freq", "Freq 8" },
-     { 1,           0.1,         100,   1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p8_q", "Q 8" },
+     EQ_BAND_PARAMS(1, 60)
+     EQ_BAND_PARAMS(2, 120)
+     EQ_BAND_PARAMS(3, 250)
+     EQ_BAND_PARAMS(4, 500)
+     EQ_BAND_PARAMS(5, 1000)
+     EQ_BAND_PARAMS(6, 2500)
+     EQ_BAND_PARAMS(7, 4000)
+     EQ_BAND_PARAMS(8, 6000)
  };
  
  CALF_PLUGIN_INFO(equalizer12band) = { 0x8501, "Equalizer12Band", "Calf Equalizer 12 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
  
  ////////////////////////////////////////////////////////////////////////////
  
 +CALF_PORT_NAMES(saturator) = {"In L", "In R", "Out L", "Out R"};
 +
 +CALF_PORT_PROPS(saturator) = {
 +    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Gain" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Master" },
 +    { 0.5,         0,           1,     0,  PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "mix", "Mix" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
 +    
 +    { 2,           0.1,         10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Drive" },
 +    { 10,         -10,          10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_drive", "Drive" },
 +    
 +    { 20000,      10,           20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_pre_freq", "Lowpass" },
 +    { 10,         10,           20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_pre_freq", "Highpass" },
 +
 +    { 20000,      10,           20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_post_freq", "Lowpass" },
 +    { 10,         10,           20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_post_freq", "Highpass" },
 +    
 +    { 2000,       80,           8000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p_freq", "Tone" },
 +    { 1,          0.0625,       16,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p_level", "Amount" },
 +    { 1,          0.1,          10,    1,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p_q", "Gradient" },
 +};
 +
 +CALF_PLUGIN_INFO(saturator) = { 0x8502, "Saturator", "Calf Saturator", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
 +
 +////////////////////////////////////////////////////////////////////////////
 +
 +CALF_PORT_NAMES(exciter) = {"In L", "In R", "Out L", "Out R"};
 +
 +CALF_PORT_PROPS(exciter) = {
 +    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
 +    
 +    { 8.5,         0.1,         10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Harmonics" },
 +    { 0,          -10,          10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend harmonics" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_drive", "Harmonics level" },
 +    
 +    { 6000,       2000,         12000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" },
 +    { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" },
 +};
 +
 +CALF_PLUGIN_INFO(exciter) = { 0x8502, "Exciter", "Calf Exciter", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
 +
 +////////////////////////////////////////////////////////////////////////////
 +
 +CALF_PORT_NAMES(bassenhancer) = {"In L", "In R", "Out L", "Out R"};
 +
 +CALF_PORT_PROPS(bassenhancer) = {
 +    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_in", "Input" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_out", "Output" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
 +    
 +    { 8.5,         0.1,         10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Harmonics" },
 +    { 0,          -10,          10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend harmonics" },
 +    { 0,           0,           1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_drive", "Harmonics level" },
 +    
 +    { 120,        10,           250,   0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" },
 +    { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" },
 +};
 +
 +CALF_PLUGIN_INFO(bassenhancer) = { 0x8502, "BassEnhancer", "Calf Bass Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
 +
  ////////////////////////////////////////////////////////////////////////////
  
  CALF_PORT_NAMES(monosynth) = {
diff --combined src/modules_dsp.cpp
index 970ddda,352ea90..95105f3
--- a/src/modules_dsp.cpp
+++ b/src/modules_dsp.cpp
@@@ -32,87 -32,6 +32,6 @@@
  using namespace dsp;
  using namespace calf_plugins;
  
- /// convert amplitude value to normalized grid-ish value (0dB = 0.5, 30dB = 1.0, -30 dB = 0.0, -60dB = -0.5, -90dB = -1.0)
- static inline float dB_grid(float amp)
- {
-     return log(amp) * (1.0 / log(256.0)) + 0.4;
- }
- 
- template<class Fx>
- static bool get_graph(Fx &fx, int subindex, float *data, int points)
- {
-     for (int i = 0; i < points; i++)
-     {
-         typedef std::complex<double> cfloat;
-         double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
-         data[i] = dB_grid(fx.freq_gain(subindex, freq, fx.srate));
-     }
-     return true;
- }
- 
- /// convert normalized grid-ish value back to amplitude value
- static inline float dB_grid_inv(float pos)
- {
-     return pow(256.0, pos - 0.4);
- }
- 
- static void set_channel_color(cairo_iface *context, int channel)
- {
-     if (channel & 1)
-         context->set_source_rgba(0.35, 0.4, 0.2, 1);
-     else
-         context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
-     context->set_line_width(1.5);
- }
- 
- static bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true)
- {
-     if (subindex < 0 )
- 	return false;
-     if (use_frequencies)
-     {
-         if (subindex < 28)
-         {
-             vertical = true;
-             if (subindex == 9) legend = "100 Hz";
-             if (subindex == 18) legend = "1 kHz";
-             if (subindex == 27) legend = "10 kHz";
-             float freq = 100;
-             if (subindex < 9)
-                 freq = 10 * (subindex + 1);
-             else if (subindex < 18)
-                 freq = 100 * (subindex - 9 + 1);
-             else if (subindex < 27)
-                 freq = 1000 * (subindex - 18 + 1);
-             else
-                 freq = 10000 * (subindex - 27 + 1);
-             pos = log(freq / 20.0) / log(1000);
-             if (!legend.empty())
-                 context->set_source_rgba(0, 0, 0, 0.2);
-             else
-                 context->set_source_rgba(0, 0, 0, 0.1);
-             return true;
-         }
-         subindex -= 28;
-     }
-     if (subindex >= 32)
-         return false;
-     float gain = 16.0 / (1 << subindex);
-     pos = dB_grid(gain);
-     if (pos < -1)
-         return false;
-     if (subindex != 4)
-         context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2);
-     if (!(subindex & 1))
-     {
-         std::stringstream ss;
-         ss << (24 - 6 * subindex) << " dB";
-         legend = ss.str();
-     }
-     vertical = false;
-     return true;
- }
- 
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
@@@ -1811,556 -1730,114 +1730,114 @@@ int gain_reduction_audio_module::get_ch
  /// of different chained filters.
  ///////////////////////////////////////////////////////////////////////////////////////////////
  
- equalizer12band_audio_module::equalizer12band_audio_module()
+ template<class BaseClass>
+ equalizerNband_audio_module<BaseClass>::equalizerNband_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;
+     clip_inL = clip_inR = clip_outL = clip_outR  = 0.f;
+     meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
  }
  
- void equalizer12band_audio_module::activate()
+ template<class BaseClass>
+ void equalizerNband_audio_module<BaseClass>::activate()
  {
      is_active = true;
      // set all filters
      params_changed();
  }
- void equalizer12band_audio_module::deactivate()
+ 
+ template<class BaseClass>
+ void equalizerNband_audio_module<BaseClass>::deactivate()
  {
      is_active = false;
  }
  
- void equalizer12band_audio_module::params_changed()
+ static inline void copy_lphp(biquad_d2<float> filters[3][2])
  {
-     // set the params of all filters
-     if(*params[param_hp_freq] != hp_freq_old) {
-         hpL[0].set_hp_rbj(*params[param_hp_freq], 0.707, (float)srate, 1.0);
-         hpL[1].copy_coeffs(hpL[0]);
-         hpL[2].copy_coeffs(hpL[0]);
-         hpR[0].copy_coeffs(hpL[0]);
-         hpR[1].copy_coeffs(hpL[0]);
-         hpR[2].copy_coeffs(hpL[0]);
-         hp_freq_old = *params[param_hp_freq];
-     }
-     if(*params[param_lp_freq] != lp_freq_old) {
-         lpL[0].set_lp_rbj(*params[param_lp_freq], 0.707, (float)srate, 1.0);
-         lpL[1].copy_coeffs(lpL[0]);
-         lpL[2].copy_coeffs(lpL[0]);
-         lpR[0].copy_coeffs(lpL[0]);
-         lpR[1].copy_coeffs(lpL[0]);
-         lpR[2].copy_coeffs(lpL[0]);
-         lp_freq_old = *params[param_lp_freq];
-     }
-     if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) {
-         lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate);
-         lsR.copy_coeffs(lsL);
-         ls_level_old = *params[param_ls_level];
-         ls_freq_old = *params[param_ls_freq];
-     }
-     if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) {
-         hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate);
-         hsR.copy_coeffs(hsL);
-         hs_level_old = *params[param_hs_level];
-         hs_freq_old = *params[param_hs_freq];
-     }
-     if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) {
-         pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate);
-         pR[0].copy_coeffs(pL[0]);
-         p_freq_old[0] = *params[param_p1_freq];
-         p_level_old[0] = *params[param_p1_level];
-         p_q_old[0] = *params[param_p1_q];
-     }
-     if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) {
-         pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate);
-         pR[1].copy_coeffs(pL[1]);
-         p_freq_old[1] = *params[param_p2_freq];
-         p_level_old[1] = *params[param_p2_level];
-         p_q_old[1] = *params[param_p2_q];
-     }
-     if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) {
-         pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate);
-         pR[2].copy_coeffs(pL[2]);
-         p_freq_old[2] = *params[param_p3_freq];
-         p_level_old[2] = *params[param_p3_level];
-         p_q_old[2] = *params[param_p3_q];
-     }
-     if(*params[param_p4_freq] != p_freq_old[3] or *params[param_p4_level] != p_level_old[3] or *params[param_p4_q] != p_q_old[3]) {
-         pL[3].set_peakeq_rbj((float)*params[param_p4_freq], *params[param_p4_q], *params[param_p4_level], (float)srate);
-         pR[3].copy_coeffs(pL[3]);
-         p_freq_old[3] = *params[param_p4_freq];
-         p_level_old[3] = *params[param_p4_level];
-         p_q_old[3] = *params[param_p4_q];
-     }
-     if(*params[param_p5_freq] != p_freq_old[4] or *params[param_p5_level] != p_level_old[4] or *params[param_p5_q] != p_q_old[4]) {
-         pL[4].set_peakeq_rbj((float)*params[param_p5_freq], *params[param_p5_q], *params[param_p5_level], (float)srate);
-         pR[4].copy_coeffs(pL[4]);
-         p_freq_old[4] = *params[param_p5_freq];
-         p_level_old[4] = *params[param_p5_level];
-         p_q_old[4] = *params[param_p5_q];
-     }
-     if(*params[param_p6_freq] != p_freq_old[5] or *params[param_p6_level] != p_level_old[5] or *params[param_p6_q] != p_q_old[5]) {
-         pL[5].set_peakeq_rbj((float)*params[param_p6_freq], *params[param_p6_q], *params[param_p6_level], (float)srate);
-         pR[5].copy_coeffs(pL[5]);
-         p_freq_old[5] = *params[param_p6_freq];
-         p_level_old[5] = *params[param_p6_level];
-         p_q_old[5] = *params[param_p6_q];
-     }
-     if(*params[param_p7_freq] != p_freq_old[6] or *params[param_p7_level] != p_level_old[6] or *params[param_p7_q] != p_q_old[6]) {
-         pL[6].set_peakeq_rbj((float)*params[param_p7_freq], *params[param_p7_q], *params[param_p7_level], (float)srate);
-         pR[6].copy_coeffs(pL[6]);
-         p_freq_old[6] = *params[param_p7_freq];
-         p_level_old[6] = *params[param_p7_level];
-         p_q_old[6] = *params[param_p7_q];
-     }
-     if(*params[param_p8_freq] != p_freq_old[7] or *params[param_p8_level] != p_level_old[7] or *params[param_p8_q] != p_q_old[7]) {
-         pL[7].set_peakeq_rbj((float)*params[param_p8_freq], *params[param_p8_q], *params[param_p8_level], (float)srate);
-         pR[7].copy_coeffs(pL[7]);
-         p_freq_old[7] = *params[param_p8_freq];
-         p_level_old[7] = *params[param_p8_level];
-         p_q_old[7] = *params[param_p8_q];
-     }
- }
- 
- void equalizer12band_audio_module::set_sample_rate(uint32_t sr)
- {
-     srate = sr;
+     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]);
  }
  
- uint32_t equalizer12band_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) {
-             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;
-     } 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[param_level_in];
-             inL *= *params[param_level_in];
-             
-             float procL = inL;
-             float procR = inR;
-             
-             // all filters in chain
-             if(*params[param_hp_active] > 0.f) {
-                 switch((int)*params[param_hp_mode]) {
-                     case MODE12DB:
-                         procL = hpL[0].process(procL);
-                         procR = hpR[0].process(procR);
-                         break;
-                     case MODE24DB:
-                         procL = hpL[1].process(hpL[0].process(procL));
-                         procR = hpR[1].process(hpR[0].process(procR));
-                         break;
-                     case MODE36DB:
-                         procL = hpL[2].process(hpL[1].process(hpL[0].process(procL)));
-                         procR = hpR[2].process(hpR[1].process(hpR[0].process(procR)));
-                         break;
-                 }
-             }
-             if(*params[param_lp_active] > 0.f) {
-                 switch((int)*params[param_lp_mode]) {
-                     case MODE12DB:
-                         procL = lpL[0].process(procL);
-                         procR = lpR[0].process(procR);
-                         break;
-                     case MODE24DB:
-                         procL = lpL[1].process(lpL[0].process(procL));
-                         procR = lpR[1].process(lpR[0].process(procR));
-                         break;
-                     case MODE36DB:
-                         procL = lpL[2].process(lpL[1].process(lpL[0].process(procL)));
-                         procR = lpR[2].process(lpR[1].process(lpR[0].process(procR)));
-                         break;
-                 }
-             }
-             if(*params[param_ls_active] > 0.f) {
-                 procL = lsL.process(procL);
-                 procR = lsR.process(procR);
-             }
-             if(*params[param_hs_active] > 0.f) {
-                 procL = hsL.process(procL);
-                 procR = hsR.process(procR);
-             }
-             if(*params[param_p1_active] > 0.f) {
-                 procL = pL[0].process(procL);
-                 procR = pR[0].process(procR);
-             }
-             if(*params[param_p2_active] > 0.f) {
-                 procL = pL[1].process(procL);
-                 procR = pR[1].process(procR);
-             }
-             if(*params[param_p3_active] > 0.f) {
-                 procL = pL[2].process(procL);
-                 procR = pR[2].process(procR);
-             }
-             if(*params[param_p4_active] > 0.f) {
-                 procL = pL[3].process(procL);
-                 procR = pR[3].process(procR);
-             }
-             if(*params[param_p5_active] > 0.f) {
-                 procL = pL[4].process(procL);
-                 procR = pR[4].process(procR);
-             }
-             if(*params[param_p6_active] > 0.f) {
-                 procL = pL[5].process(procL);
-                 procR = pR[5].process(procR);
-             }
-             if(*params[param_p7_active] > 0.f) {
-                 procL = pL[6].process(procL);
-                 procR = pR[6].process(procR);
-             }
-             if(*params[param_p8_active] > 0.f) {
-                 procL = pL[7].process(procL);
-                 procR = pR[7].process(procR);
-             }
-             
-             outL = procL * *params[param_level_out];
-             outR = procR * *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;
-         } // cycle trough samples
-         // clean up
-         for(int i = 0; i < 3; ++i) {
-             hpL[i].sanitize();
-             hpR[i].sanitize();
-             lpL[i].sanitize();
-             lpR[i].sanitize();
-         }
-         lsL.sanitize();
-         hsR.sanitize();
-         for(int i = 0; i < 8; ++i) {
-             pL[i].sanitize();
-             pR[i].sanitize();
-         }
-     }
-     // draw meters
-     if(params[param_clip_inL] != NULL) {
-         *params[param_clip_inL] = clip_inL;
-     }
-     if(params[param_clip_inR] != NULL) {
-         *params[param_clip_inR] = clip_inR;
-     }
-     if(params[param_clip_outL] != NULL) {
-         *params[param_clip_outL] = clip_outL;
-     }
-     if(params[param_clip_outR] != NULL) {
-         *params[param_clip_outR] = clip_outR;
-     }
-     
-     if(params[param_meter_inL] != NULL) {
-         *params[param_meter_inL] = meter_inL;
-     }
-     if(params[param_meter_inR] != NULL) {
-         *params[param_meter_inR] = meter_inR;
-     }
-     if(params[param_meter_outL] != NULL) {
-         *params[param_meter_outL] = meter_outL;
-     }
-     if(params[param_meter_outR] != NULL) {
-         *params[param_meter_outR] = meter_outR;
-     }
-     // whatever has to be returned x)
-     return outputs_mask;
- }
- bool equalizer12band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
- {
-     if (!is_active)
-         return false;
-     if (index == param_p1_freq && !subindex) {
-         context->set_line_width(1.5);
-         return ::get_graph(*this, subindex, data, points);
-     }
-     return false;
- }
  
- bool equalizer12band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
+ template<class BaseClass>
+ void equalizerNband_audio_module<BaseClass>::params_changed()
  {
-     if (!is_active) {
-         return false;
-     } else {
-         return get_freq_gridline(subindex, pos, vertical, legend, context);
+     // set the params of all filters
+     
+     // lp/hp first
+     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;
      }
- }
- 
- int equalizer12band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
- {
-     if (!is_active) {
-         return false;
-     } else {
-         if (*params[param_hp_freq] != hp_freq_old1
-             or *params[param_hp_mode] != hp_mode_old1
-             or *params[param_lp_freq] != lp_freq_old1
-             or *params[param_lp_mode] != lp_mode_old1
-             
-             or *params[param_ls_freq] != ls_freq_old1
-             or *params[param_ls_level] != ls_level_old1
-             or *params[param_hs_freq] != hs_freq_old1
-             or *params[param_hs_level] != hs_level_old1
-             
-             or *params[param_p1_freq] != p_freq_old1[0]
-             or *params[param_p1_level] != p_level_old1[0]
-             or *params[param_p1_q] != p_q_old1[0]
-             
-             or *params[param_p2_freq] != p_freq_old1[1]
-             or *params[param_p2_level] != p_level_old1[1]
-             or *params[param_p2_q] != p_q_old1[1]
-                         
-             or *params[param_p3_freq] != p_freq_old1[2]
-             or *params[param_p3_level] != p_level_old1[2]
-             or *params[param_p3_q] != p_q_old1[2]
-             
-             or *params[param_p4_freq] != p_freq_old1[3]
-             or *params[param_p4_level] != p_level_old1[3]
-             or *params[param_p4_q] != p_q_old1[3]
-             
-             or *params[param_p5_freq] != p_freq_old1[4]
-             or *params[param_p5_level] != p_level_old1[4]
-             or *params[param_p5_q] != p_q_old1[4]
-             
-             or *params[param_p6_freq] != p_freq_old1[5]
-             or *params[param_p6_level] != p_level_old1[5]
-             or *params[param_p6_q] != p_q_old1[5]
-             
-             or *params[param_p7_freq] != p_freq_old1[6]
-             or *params[param_p7_level] != p_level_old1[6]
-             or *params[param_p7_q] != p_q_old1[6]
-             
-             or *params[param_p8_freq] != p_freq_old1[7]
-             or *params[param_p8_level] != p_level_old1[7]
-             or *params[param_p8_q] != p_q_old1[7])
-         {
-             
-             hp_freq_old1 = *params[param_hp_freq];
-             hp_mode_old1 = *params[param_hp_mode];
-             lp_freq_old1 = *params[param_lp_freq];
-             lp_mode_old1 = *params[param_lp_mode];
-             
-             ls_freq_old1 = *params[param_ls_freq];
-             ls_level_old1 = *params[param_ls_level];
-             hs_freq_old1 = *params[param_hs_freq];
-             hs_level_old1 = *params[param_hs_level];
-             
-             p_freq_old1[0] = *params[param_p1_freq];
-             p_level_old1[0] = *params[param_p1_level];
-             p_q_old1[0] = *params[param_p1_q];
-             
-             p_freq_old1[1] = *params[param_p2_freq];
-             p_level_old1[1] = *params[param_p2_level];
-             p_q_old1[1] = *params[param_p2_q];
-             
-             p_freq_old1[2] = *params[param_p3_freq];
-             p_level_old1[2] = *params[param_p3_level];
-             p_q_old1[2] = *params[param_p3_q];
-             
-             p_freq_old1[3] = *params[param_p4_freq];
-             p_level_old1[3] = *params[param_p4_level];
-             p_q_old1[3] = *params[param_p4_q];
-             
-             p_freq_old1[4] = *params[param_p5_freq];
-             p_level_old1[4] = *params[param_p5_level];
-             p_q_old1[4] = *params[param_p5_q];
-             
-             p_freq_old1[5] = *params[param_p6_freq];
-             p_level_old1[5] = *params[param_p6_level];
-             p_q_old1[5] = *params[param_p6_q];
-             
-             p_freq_old1[6] = *params[param_p7_freq];
-             p_level_old1[6] = *params[param_p7_level];
-             p_q_old1[6] = *params[param_p7_q];
-             
-             p_freq_old1[7] = *params[param_p8_freq];
-             p_level_old1[7] = *params[param_p8_level];
-             p_q_old1[7] = *params[param_p8_q];
-             
-             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;
+     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;
      }
-     return false;
- }
- 
- /// Equalizer 8 Band by Markus Schmidt
- ///
- /// This module is based on Krzysztof's filters. It provides a couple
- /// of different chained filters.
- ///////////////////////////////////////////////////////////////////////////////////////////////
- 
- equalizer8band_audio_module::equalizer8band_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 equalizer8band_audio_module::activate()
- {
-     is_active = true;
-     // set all filters
-     params_changed();
- }
- void equalizer8band_audio_module::deactivate()
- {
-     is_active = false;
- }
  
- void equalizer8band_audio_module::params_changed()
- {
-     // set the params of all filters
-     if(*params[param_hp_freq] != hp_freq_old) {
-         hpL[0].set_hp_rbj(*params[param_hp_freq], 0.707, (float)srate, 1.0);
-         hpL[1].copy_coeffs(hpL[0]);
-         hpL[2].copy_coeffs(hpL[0]);
-         hpR[0].copy_coeffs(hpL[0]);
-         hpR[1].copy_coeffs(hpL[0]);
-         hpR[2].copy_coeffs(hpL[0]);
-         hp_freq_old = *params[param_hp_freq];
-     }
-     if(*params[param_lp_freq] != lp_freq_old) {
-         lpL[0].set_lp_rbj(*params[param_lp_freq], 0.707, (float)srate, 1.0);
-         lpL[1].copy_coeffs(lpL[0]);
-         lpL[2].copy_coeffs(lpL[0]);
-         lpR[0].copy_coeffs(lpL[0]);
-         lpR[1].copy_coeffs(lpL[0]);
-         lpR[2].copy_coeffs(lpL[0]);
-         lp_freq_old = *params[param_lp_freq];
-     }
-     if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) {
-         lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate);
+     // 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 = *params[param_ls_level];
-         ls_freq_old = *params[param_ls_freq];
+         ls_level_old = lslevel;
+         ls_freq_old = lsfreq;
      }
-     if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) {
-         hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate);
+     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 = *params[param_hs_level];
-         hs_freq_old = *params[param_hs_freq];
+         hs_level_old = hslevel;
+         hs_freq_old = hsfreq;
      }
-     if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) {
-         pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate);
-         pR[0].copy_coeffs(pL[0]);
-         p_freq_old[0] = *params[param_p1_freq];
-         p_level_old[0] = *params[param_p1_level];
-         p_q_old[0] = *params[param_p1_q];
-     }
-     if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) {
-         pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate);
-         pR[1].copy_coeffs(pL[1]);
-         p_freq_old[1] = *params[param_p2_freq];
-         p_level_old[1] = *params[param_p2_level];
-         p_q_old[1] = *params[param_p2_q];
-     }
-     if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) {
-         pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate);
-         pR[2].copy_coeffs(pL[2]);
-         p_freq_old[2] = *params[param_p3_freq];
-         p_level_old[2] = *params[param_p3_level];
-         p_q_old[2] = *params[param_p3_q];
-     }
-     if(*params[param_p4_freq] != p_freq_old[3] or *params[param_p4_level] != p_level_old[3] or *params[param_p4_q] != p_q_old[3]) {
-         pL[3].set_peakeq_rbj((float)*params[param_p4_freq], *params[param_p4_q], *params[param_p4_level], (float)srate);
-         pR[3].copy_coeffs(pL[3]);
-         p_freq_old[3] = *params[param_p4_freq];
-         p_level_old[3] = *params[param_p4_level];
-         p_q_old[3] = *params[param_p4_q];
+     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;
+         }
      }
  }
  
- void equalizer8band_audio_module::set_sample_rate(uint32_t sr)
+ static void process_hplp(float &procL, float &procR, dsp::biquad_d2<float> filter[3][2], CalfEqMode mode)
  {
-     srate = sr;
+     switch(mode) {
+         case MODE12DB:
+             procL = filter[0][0].process(procL);
+             procR = filter[0][1].process(procR);
+             break;
+         case MODE24DB:
+             procL = filter[1][0].process(filter[0][0].process(procL));
+             procR = filter[1][1].process(filter[0][1].process(procR));
+             break;
+         case MODE36DB:
+             procL = filter[2][0].process(filter[1][0].process(filter[0][0].process(procL)));
+             procR = filter[2][1].process(filter[1][1].process(filter[0][1].process(procR)));
+             break;
+     }
  }
  
- uint32_t equalizer8band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+ #define SET_IF_CONNECTED(param) if (params[AM::param_##param] != NULL) *params[AM::param_##param] = param;
+ 
+ template<class BaseClass>
+ uint32_t equalizerNband_audio_module<BaseClass>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
  {
-     bool bypass = *params[param_bypass] > 0.5f;
+     bool bypass = *params[AM::param_bypass] > 0.f;
      numsamples += offset;
      if(bypass) {
          // everything bypassed
@@@ -2370,14 -1847,8 +1847,8 @@@
              ++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;
+         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);
@@@ -2388,6 -1859,8 +1859,8 @@@
          meter_inR = 0.f;
          meter_outL = 0.f;
          meter_outR = 0.f;
+         CalfEqMode hp_mode = (CalfEqMode)(int)*params[AM::param_hp_mode];
+         CalfEqMode lp_mode = (CalfEqMode)(int)*params[AM::param_lp_mode];
          
          // process
          while(offset < numsamples) {
@@@ -2397,72 -1870,37 +1870,37 @@@
              float inL = ins[0][offset];
              float inR = ins[1][offset];
              // in level
-             inR *= *params[param_level_in];
-             inL *= *params[param_level_in];
+             inR *= *params[AM::param_level_in];
+             inL *= *params[AM::param_level_in];
              
              float procL = inL;
              float procR = inR;
              
              // all filters in chain
-             if(*params[param_hp_active] > 0.f) {
-                 switch((int)*params[param_hp_mode]) {
-                     case MODE12DB:
-                         procL = hpL[0].process(procL);
-                         procR = hpR[0].process(procR);
-                         break;
-                     case MODE24DB:
-                         procL = hpL[1].process(hpL[0].process(procL));
-                         procR = hpR[1].process(hpR[0].process(procR));
-                         break;
-                     case MODE36DB:
-                         procL = hpL[2].process(hpL[1].process(hpL[0].process(procL)));
-                         procR = hpR[2].process(hpR[1].process(hpR[0].process(procR)));
-                         break;
-                 }
+             if(*params[AM::param_hp_active] > 0.f) {
+                 process_hplp(procL, procR, hp, hp_mode);
              }
-             if(*params[param_lp_active] > 0.f) {
-                 switch((int)*params[param_lp_mode]) {
-                     case MODE12DB:
-                         procL = lpL[0].process(procL);
-                         procR = lpR[0].process(procR);
-                         break;
-                     case MODE24DB:
-                         procL = lpL[1].process(lpL[0].process(procL));
-                         procR = lpR[1].process(lpR[0].process(procR));
-                         break;
-                     case MODE36DB:
-                         procL = lpL[2].process(lpL[1].process(lpL[0].process(procL)));
-                         procR = lpR[2].process(lpR[1].process(lpR[0].process(procR)));
-                         break;
-                 }
+             if(*params[AM::param_lp_active] > 0.f) {
+                 process_hplp(procL, procR, lp, lp_mode);
              }
-             if(*params[param_ls_active] > 0.f) {
+             if(*params[AM::param_ls_active] > 0.f) {
                  procL = lsL.process(procL);
                  procR = lsR.process(procR);
              }
-             if(*params[param_hs_active] > 0.f) {
+             if(*params[AM::param_hs_active] > 0.f) {
                  procL = hsL.process(procL);
                  procR = hsR.process(procR);
              }
-             if(*params[param_p1_active] > 0.f) {
-                 procL = pL[0].process(procL);
-                 procR = pR[0].process(procR);
-             }
-             if(*params[param_p2_active] > 0.f) {
-                 procL = pL[1].process(procL);
-                 procR = pR[1].process(procR);
-             }
-             if(*params[param_p3_active] > 0.f) {
-                 procL = pL[2].process(procL);
-                 procR = pR[2].process(procR);
-             }
-             if(*params[param_p4_active] > 0.f) {
-                 procL = pL[3].process(procL);
-                 procR = pR[3].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[param_level_out];
-             outR = procR * *params[param_level_out];
+             outL = procL * *params[AM::param_level_out];
+             outR = procR * *params[AM::param_level_out];
              
              // send to output
              outs[0][offset] = outL;
@@@ -2500,59 -1938,47 +1938,47 @@@
          } // cycle trough samples
          // clean up
          for(int i = 0; i < 3; ++i) {
-             hpL[i].sanitize();
-             hpR[i].sanitize();
-             lpL[i].sanitize();
-             lpR[i].sanitize();
+             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 < 4; ++i) {
+         for(int i = 0; i < AM::PeakBands; ++i) {
              pL[i].sanitize();
              pR[i].sanitize();
          }
      }
      // draw meters
-     if(params[param_clip_inL] != NULL) {
-         *params[param_clip_inL] = clip_inL;
-     }
-     if(params[param_clip_inR] != NULL) {
-         *params[param_clip_inR] = clip_inR;
-     }
-     if(params[param_clip_outL] != NULL) {
-         *params[param_clip_outL] = clip_outL;
-     }
-     if(params[param_clip_outR] != NULL) {
-         *params[param_clip_outR] = clip_outR;
-     }
-     
-     if(params[param_meter_inL] != NULL) {
-         *params[param_meter_inL] = meter_inL;
-     }
-     if(params[param_meter_inR] != NULL) {
-         *params[param_meter_inR] = meter_inR;
-     }
-     if(params[param_meter_outL] != NULL) {
-         *params[param_meter_outL] = meter_outL;
-     }
-     if(params[param_meter_outR] != NULL) {
-         *params[param_meter_outR] = meter_outR;
-     }
+     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 equalizer8band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
+ 
+ #undef SET_IF_CONNECTED
+ 
+ template<class BaseClass>
+ bool equalizerNband_audio_module<BaseClass>::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
  {
      if (!is_active)
          return false;
-     if (index == param_p1_freq && !subindex) {
+     if (index == AM::param_p1_freq && !subindex) {
          context->set_line_width(1.5);
          return ::get_graph(*this, subindex, data, points);
      }
      return false;
  }
  
- bool equalizer8band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
+ template<class BaseClass>
+ bool equalizerNband_audio_module<BaseClass>::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
  {
      if (!is_active) {
          return false;
@@@ -2561,63 -1987,22 +1987,22 @@@
      }
  }
  
- int equalizer8band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
+ template<class BaseClass>
+ int equalizerNband_audio_module<BaseClass>::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
  {
      if (!is_active) {
          return false;
      } else {
-         if (*params[param_hp_freq] != hp_freq_old1
-             or *params[param_hp_mode] != hp_mode_old1
-             or *params[param_lp_freq] != lp_freq_old1
-             or *params[param_lp_mode] != lp_mode_old1
-             
-             or *params[param_ls_freq] != ls_freq_old1
-             or *params[param_ls_level] != ls_level_old1
-             or *params[param_hs_freq] != hs_freq_old1
-             or *params[param_hs_level] != hs_level_old1
-             
-             or *params[param_p1_freq] != p_freq_old1[0]
-             or *params[param_p1_level] != p_level_old1[0]
-             or *params[param_p1_q] != p_q_old1[0]
-             
-             or *params[param_p2_freq] != p_freq_old1[1]
-             or *params[param_p2_level] != p_level_old1[1]
-             or *params[param_p2_q] != p_q_old1[1]
-                         
-             or *params[param_p3_freq] != p_freq_old1[2]
-             or *params[param_p3_level] != p_level_old1[2]
-             or *params[param_p3_q] != p_q_old1[2]
-             
-             or *params[param_p4_freq] != p_freq_old1[3]
-             or *params[param_p4_level] != p_level_old1[3]
-             or *params[param_p4_q] != p_q_old1[3])
+         bool changed = false;
+         for (int i = 0; i < graph_param_count && !changed; i++)
          {
-             
-             hp_freq_old1 = *params[param_hp_freq];
-             hp_mode_old1 = *params[param_hp_mode];
-             lp_freq_old1 = *params[param_lp_freq];
-             lp_mode_old1 = *params[param_lp_mode];
-             
-             ls_freq_old1 = *params[param_ls_freq];
-             ls_level_old1 = *params[param_ls_level];
-             hs_freq_old1 = *params[param_hs_freq];
-             hs_level_old1 = *params[param_hs_level];
-             
-             p_freq_old1[0] = *params[param_p1_freq];
-             p_level_old1[0] = *params[param_p1_level];
-             p_q_old1[0] = *params[param_p1_q];
-             
-             p_freq_old1[1] = *params[param_p2_freq];
-             p_level_old1[1] = *params[param_p2_level];
-             p_q_old1[1] = *params[param_p2_q];
-             
-             p_freq_old1[2] = *params[param_p3_freq];
-             p_level_old1[2] = *params[param_p3_level];
-             p_q_old1[2] = *params[param_p3_q];
-             
-             p_freq_old1[3] = *params[param_p4_freq];
-             p_level_old1[3] = *params[param_p4_level];
-             p_q_old1[3] = *params[param_p4_q];
+             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;
@@@ -2635,6 -2020,38 +2020,38 @@@
      return false;
  }
  
+ static inline float adjusted_lphp_gain(float **params, int param_active, int param_mode, 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>
+ float equalizerNband_audio_module<BaseClass>::freq_gain(int index, double freq, uint32_t sr)
+ {
+     float ret = 1.f;
+     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<equalizer8band_metadata>;
+ template class equalizerNband_audio_module<equalizer12band_metadata>;
+ 
  /// Equalizer 5 Band by Markus Schmidt
  ///
  /// This module is based on Krzysztof's filters. It provides a couple
@@@ -2893,787 -2310,3 +2310,787 @@@ int equalizer5band_audio_module::get_ch
      }
      return false;
  }
 +
 +/// Saturator Band by Markus Schmidt
 +///
 +/// This module is based on Krzysztof's filters and 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;
 +        
 +        // 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]));
 +                proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
 +                
 +                // saturate
 +                proc[i] = dist[i].process(proc[i]);
 +                
 +                // 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]));
 +            }
 +            
 +            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]));
 +                maxDrive = std::max(dist[0].get_distortion_level(), dist[1].get_distortion_level());
 +            } 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]);
 +                maxDrive = dist[0].get_distortion_level();
 +            } 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]);
 +                maxDrive = dist[0].get_distortion_level();
 +            }
 +            
 +            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();
 +        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 distortion routine.
 +/// It sends the signal through a highpass, saturates it and sends it through a highpass again
 +///////////////////////////////////////////////////////////////////////////////////////////////
 +
 +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 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;
 +}
 +
 +
 +/// Distortion Module by Krzysztof Foltman
 +///
 +/// This module provides a blendable saturation stage
 +///////////////////////////////////////////////////////////////////////////////////////////////
 +
 +distortion_audio_module::distortion_audio_module()
 +{
 +    is_active = false;
 +    srate = 0;
 +    meter = 0.f;
 +}
 +
 +void distortion_audio_module::activate()
 +{
 +    is_active = true;
 +    set_params(0.f, 0.f);
 +}
 +void distortion_audio_module::deactivate()
 +{
 +    is_active = false;
 +}
 +
 +void distortion_audio_module::set_params(float blend, float drive)
 +{
 +    // set distortion coeffs
 +    // NOTICE!! This routine is implemented for testing purposes only!
 +    // It is taken from TAP Plugins and will act as a placeholder until
 +    // Krzysztof's distrotion routine is ready!
 +    if ((drive_old != drive) || (blend_old != blend)) {
 +        rdrive = 12.0f / drive;
 +        rbdr = rdrive / (10.5f - blend) * 780.0f / 33.0f;
 +        kpa = D(2.0f * (rdrive*rdrive) - 1.0f) + 1.0f;
 +        kpb = (2.0f - kpa) / 2.0f;
 +        ap = ((rdrive*rdrive) - kpa + 1.0f) / 2.0f;
 +        kc = kpa / D(2.0f * D(2.0f * (rdrive*rdrive) - 1.0f) - 2.0f * rdrive*rdrive);
 +
 +        srct = (0.1f * srate) / (0.1f * srate + 1.0f);
 +        sq = kc*kc + 1.0f;
 +        knb = -1.0f * rbdr / D(sq);
 +        kna = 2.0f * kc * rbdr / D(sq);
 +        an = rbdr*rbdr / sq;
 +        imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f);
 +        pwrq = 2.0f / (imr + 1.0f);
 +        
 +        drive_old = drive;
 +        blend_old = blend;
 +    }
 +}
 +
 +void distortion_audio_module::set_sample_rate(uint32_t sr)
 +{
 +    srate = sr;
 +}
 +
 +float distortion_audio_module::process(float(in))
 +{
 +    // NOTICE!! This routine is implemented for testing purposes only!
 +    // It is taken from TAP Plugins and will act as a placeholder until
 +    // Krzysztof's distrotion routine is ready!
 +    meter = 0.f;
 +    float out = 0.f;
 +    float proc = in;
 +    float med;
 +    if (proc >= 0.0f) {
 +        med = (D(ap + proc * (kpa - proc)) + kpb) * pwrq;
 +    } else {
 +        med = (D(an - proc * (kna + proc)) + knb) * pwrq * -1.0f;
 +    }
 +    proc = srct * (med - prev_med + prev_out);
 +    prev_med = M(med);
 +    prev_out = M(proc);
 +    out = proc;
 +    meter = proc;
 +    return out;
 +}
 +
 +float distortion_audio_module::get_distortion_level()
 +{
 +    return meter;
 +}

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list