[SCM] calf/master: Merge branch 'master' of file:///home/kfoltman/calf into saturators

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


Add LR and RL modes to Vintage Delay (idea by Louigi Verona).
Add GUI XML for the two new plugins.
Add first version of Markus' saturation and enhancer plugins.
Add Tom Szilagyi's distortion code from TAP plugins (thanks Tom!)
Call get_param_count once and store the result for later.
Implement LADISH level 1.
Add/update copyright notices.
Separate session manager interface code into separate classes.
Enable dlopen support checking in libtool options.
Create links to proper directories, not the ones in $DISTDIR.
Send /quit to out-of-process GUI on cleanup, remove unnecessary printf.
Remove another instance of false advertising of GTK+ GUI when not enabled.
Put presets in separate files.
Do not generate GTK+ GUI related RDF if it is disabled.
Make out-of-process GUI the default one for LV2.
More decoupling and cleanups.
Add missing aftertouch support to LV2 and DSSI wrappers.
Fix compile problem when DSSI is disabled.
Only link main_win.cpp into JACK host, as it is never used in the plugin GUIs.
Build system fix.
Build system enhancements.
Fix a recent heap corruption bug in DSSI wrapper that affected Organ.
More dependency trimming.
More reference cleanups.
Make JACK host more independent of changes in plugin code.
Remove more unnecessary includes.
Fix compilation with !USE_LASH_0_6.
Fix waveform graph in Calf Organ.
Add missing overrides of MIDI-related virtual methods.
More cleanups.
Unbreak assertion in plugins.
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 e36e347410920e1bf6473639db32b46e469a7615
Merge: 973428663d484e92e6e0d30af56940f8e5b783f4 da582087b18e3d0c82e895f1d8ff29c301db20aa
Author: Krzysztof <wdev at foltman.com>
Date:   Tue May 4 23:54:33 2010 +0100

    Merge branch 'master' of file:///home/kfoltman/calf into saturators
    
    Conflicts:
    	gui/gui-saturator.xml
    	src/calf/modulelist.h
    	src/modules_dsp.cpp

diff --combined src/calf/metadata.h
index 63788fe,85d8984..23f1597
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@@ -257,34 -257,6 +257,34 @@@ struct pulsator_metadata: public plugin
      PLUGIN_NAME_ID_LABEL("pulsator", "pulsator", "Pulsator")
  };
  
 +/// 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
@@@ -456,6 -428,26 +456,26 @@@ struct wavetable_metadata: public plugi
      PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable")
  };
      
+ /// 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 Enhancer - metadata
+ struct enhancer_metadata: public plugin_metadata<enhancer_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("enhancer", "enhancer", "Enhancer")
+ };
+ 
  };
  
  #endif
diff --combined src/calf/modules.h
index 3e4d256,7c0e9f5..f8a6221
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@@ -122,13 -122,13 +122,13 @@@ class vintage_delay_audio_module: publi
  public:    
      // 1MB of delay memory per channel... uh, RAM is cheap
      enum { MAX_DELAY = 262144, ADDR_MASK = MAX_DELAY - 1 };
+     enum { MIXMODE_STEREO, MIXMODE_PINGPONG, MIXMODE_LR, MIXMODE_RL }; 
      float buffers[2][MAX_DELAY];
      int bufptr, deltime_l, deltime_r, mixmode, medium, old_medium;
      /// number of table entries written (value is only important when it is less than MAX_DELAY, which means that the buffer hasn't been totally filled yet)
      int age;
      
-     gain_smoothing amt_left, amt_right, fb_left, fb_right;
-     float dry;
+     gain_smoothing amt_left, amt_right, fb_left, fb_right, dry;
      
      dsp::biquad_d2<float> biquad_left[2], biquad_right[2];
      
@@@ -602,47 -602,39 +602,7 @@@ public
      bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
  };
  
- 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;
-     }
- };
- 
 -/// Filterclavier --- MIDI controlled filter by Hans Baier
 -class filterclavier_audio_module: 
 -        public filter_module_with_inertia<biquad_filter_module, filterclavier_metadata>, 
 -        public frequency_response_line_graph
 -{        
 -    using audio_module<filterclavier_metadata>::ins;
 -    using audio_module<filterclavier_metadata>::outs;
 -    using audio_module<filterclavier_metadata>::params;
 -
 -    const float min_gain;
 -    const float max_gain;
 -    
 -    int last_note;
 -    int last_velocity;
 -        
 -public:    
 -    filterclavier_audio_module();
 -    void params_changed();
 -    void activate();
 -    void set_sample_rate(uint32_t sr);
 -    void deactivate();
 -  
 -    /// MIDI control
 -    virtual void note_on(int note, int vel);
 -    virtual void note_off(int note, int vel);
 -    
 -    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
 -    
 -private:
 -    void adjust_gain_according_to_filter_mode(int velocity);
 -};
 -
 -/// Saturator by Markus Schmidt (based on Krzysztof's filters and Tom Szilagyi's distortion algorithm)
 +/// Saturator by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
  class saturator_audio_module: public audio_module<saturator_metadata> {
  private:
      float hp_pre_freq_old, lp_pre_freq_old;
@@@ -652,11 -644,8 +612,11 @@@
      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];
+     tap_distortion dist[2];
  public:
 +    float *ins[in_count];
 +    float *outs[out_count];
 +    float *params[param_count];
      uint32_t srate;
      bool is_active;
      saturator_audio_module();
@@@ -667,43 -656,18 +627,40 @@@
      uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
  };
  
 -/// Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom Szilagyi's distortion algorithm)
 -class enhancer_audio_module: public audio_module<enhancer_metadata> {
 +/// Exciter by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
 +class exciter_audio_module: public audio_module<exciter_metadata> {
  private:
      float freq_old;
      uint32_t clip_in, clip_out;
      float meter_in, meter_out, meter_drive;
      biquad_d2<float> hp[2][4];
-     distortion_audio_module dist[2];
+     tap_distortion dist[2];
  public:
-     float *ins[in_count];
-     float *outs[out_count];
-     float *params[param_count];
      uint32_t srate;
      bool is_active;
 -    enhancer_audio_module();
 +    exciter_audio_module();
 +    void activate();
 +    void deactivate();
 +    void params_changed();
 +    void set_sample_rate(uint32_t sr);
 +    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
 +};
 +
 +/// Bass Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
 +class bassenhancer_audio_module: public audio_module<bassenhancer_metadata> {
 +private:
 +    float freq_old;
 +    uint32_t clip_in, clip_out;
 +    float meter_in, meter_out, meter_drive;
 +    biquad_d2<float> lp[2][4];
-     distortion_audio_module dist[2];
++    tap_distortion 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();
@@@ -711,40 -675,7 +668,38 @@@
      uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
  };
  
 +/// Filterclavier --- MIDI controlled filter by Hans Baier
 +class filterclavier_audio_module: 
 +        public filter_module_with_inertia<biquad_filter_module, filterclavier_metadata>, 
 +        public frequency_response_line_graph
 +{        
 +    using audio_module<filterclavier_metadata>::ins;
 +    using audio_module<filterclavier_metadata>::outs;
 +    using audio_module<filterclavier_metadata>::params;
 +
 +    const float min_gain;
 +    const float max_gain;
 +    
 +    int last_note;
 +    int last_velocity;
 +        
 +public:    
 +    filterclavier_audio_module();
 +    void params_changed();
 +    void activate();
 +    void set_sample_rate(uint32_t sr);
 +    void deactivate();
 +  
 +    /// MIDI control
 +    virtual void note_on(int note, int vel);
 +    virtual void note_off(int note, int vel);
 +    
 +    bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
 +    
 +private:
 +    void adjust_gain_according_to_filter_mode(int velocity);
 +};
  
- extern std::string get_builtin_modules_rdf();
- 
  };
  
  #include "modules_synths.h"
diff --combined src/modules.cpp
index b6d2899,fa14c53..9de7d03
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@@ -19,11 -19,6 +19,6 @@@
   * Boston, MA  02110-1301  USA
   */
  #include <config.h>
- #include <assert.h>
- #include <memory.h>
- #if USE_JACK
- #include <jack/jack.h>
- #endif
  #include <calf/giface.h>
  #include <calf/metadata.h>
  #include <calf/audio_fx.h>
@@@ -146,6 -141,8 +141,8 @@@ CALF_PORT_NAMES(vintage_delay) = {"In L
  const char *vintage_delay_mixmodes[] = {
      "Stereo",
      "Ping-Pong",
+     "L then R",
+     "R then L",
  };
  
  const char *vintage_delay_fbmodes[] = {
@@@ -161,7 -158,7 +158,7 @@@ CALF_PORT_PROPS(vintage_delay) = 
      {  5,        1,    16,    1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_r", "Time R"},
      { 0.5,       0,    1,     0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "feedback", "Feedback" },
      { 0.25,      0,    4,   100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "amount", "Amount" },
-     { 1,         0,    1,     0, PF_ENUM | PF_CTL_COMBO, vintage_delay_mixmodes, "mix_mode", "Mix mode" },
+     { 1,         0,    3,     0, PF_ENUM | PF_CTL_COMBO, vintage_delay_mixmodes, "mix_mode", "Mix mode" },
      { 1,         0,    2,     0, PF_ENUM | PF_CTL_COMBO, vintage_delay_fbmodes, "medium", "Medium" },
      { 1.0,       0,    4,     0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" },
  };
@@@ -517,83 -514,6 +514,83 @@@ CALF_PLUGIN_INFO(pulsator) = { 0x8514, 
  
  ////////////////////////////////////////////////////////////////////////////
  
 +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,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Activation" },
 +    { 1,           0,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Master" },
 +    { 1,         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" },
 +    
 +    { 5,           0.1,         10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Saturation" },
 +    { 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) = { 0x8530, "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) = { 0x8531, "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) = { 0x8532, "BassEnhancer", "Calf Bass Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
 +
  ////////////////////////////////////////////////////////////////////////////
  
  CALF_PORT_NAMES(monosynth) = {
@@@ -967,6 -887,61 +964,61 @@@ CALF_PORT_PROPS(wavetable) = 
  
  ////////////////////////////////////////////////////////////////////////////
  
+ 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) = { 0x8519, "Saturator", "Calf Saturator", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
+ 
+ ////////////////////////////////////////////////////////////////////////////
+ 
+ CALF_PORT_NAMES(enhancer) = {"In L", "In R", "Out L", "Out R"};
+ 
+ CALF_PORT_PROPS(enhancer) = {
+     { 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(enhancer) = { 0x851A, "Enhancer", "Calf Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
+ 
+ ////////////////////////////////////////////////////////////////////////////
+ 
  calf_plugins::plugin_registry::plugin_registry()
  {
      #define PER_MODULE_ITEM(name, isSynth, jackname) plugins.push_back((new name##_metadata));
diff --combined src/modules_dsp.cpp
index cac8a60,ecc3095..a8a2c74
--- a/src/modules_dsp.cpp
+++ b/src/modules_dsp.cpp
@@@ -18,13 -18,8 +18,8 @@@
   * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
   * Boston, MA  02110-1301  USA
   */
- #include <config.h>
- #include <assert.h>
  #include <limits.h>
  #include <memory.h>
- #if USE_JACK
- #include <jack/jack.h>
- #endif
  #include <calf/giface.h>
  #include <calf/modules.h>
  #include <calf/modules_dev.h>
@@@ -303,18 -298,39 +298,39 @@@ void vintage_delay_audio_module::params
      float unit = 60.0 * srate / (*params[par_bpm] * *params[par_divide]);
      deltime_l = dsp::fastf2i_drm(unit * *params[par_time_l]);
      deltime_r = dsp::fastf2i_drm(unit * *params[par_time_r]);
-     amt_left.set_inertia(*params[par_amount]); amt_right.set_inertia(*params[par_amount]);
+     int deltime_fb = deltime_l + deltime_r;
      float fb = *params[par_feedback];
-     dry = *params[par_dryamount];
+     dry.set_inertia(*params[par_dryamount]);
      mixmode = dsp::fastf2i_drm(*params[par_mixmode]);
      medium = dsp::fastf2i_drm(*params[par_medium]);
-     if (mixmode == 0)
+     switch(mixmode)
      {
+     case MIXMODE_STEREO:
          fb_left.set_inertia(fb);
          fb_right.set_inertia(pow(fb, *params[par_time_r] / *params[par_time_l]));
-     } else {
+         amt_left.set_inertia(*params[par_amount]);
+         amt_right.set_inertia(*params[par_amount]);
+         break;
+     case MIXMODE_PINGPONG:
+         fb_left.set_inertia(fb);
+         fb_right.set_inertia(fb);
+         amt_left.set_inertia(*params[par_amount]);
+         amt_right.set_inertia(*params[par_amount]);
+         break;
+     case MIXMODE_LR:
+         fb_left.set_inertia(fb);
+         fb_right.set_inertia(fb);
+         amt_left.set_inertia(*params[par_amount]);                                          // L is straight 'amount'
+         amt_right.set_inertia(*params[par_amount] * pow(fb, 1.0 * deltime_r / deltime_fb)); // R is amount with feedback based dampening as if it ran through R/FB*100% of delay line's dampening
+         // deltime_l <<< deltime_r -> pow() = fb -> full delay line worth of dampening
+         // deltime_l >>> deltime_r -> pow() = 1 -> no dampening
+         break;
+     case MIXMODE_RL:
          fb_left.set_inertia(fb);
          fb_right.set_inertia(fb);
+         amt_left.set_inertia(*params[par_amount] * pow(fb, 1.0 * deltime_l / deltime_fb));
+         amt_right.set_inertia(*params[par_amount]);
+         break;
      }
      if (medium != old_medium)
          calc_filters();
@@@ -348,47 -364,86 +364,86 @@@ void vintage_delay_audio_module::calc_f
      biquad_right[1].copy_coeffs(biquad_left[1]);
  }
  
+ /// Single delay line with feedback at the same tap
+ static inline void delayline_impl(int age, int deltime, float dry_value, const float &delayed_value, float &out, float &del, gain_smoothing &amt, gain_smoothing &fb, float dry)
+ {
+     // if the buffer hasn't been cleared yet (after activation), pretend we've read zeros
+     if (age <= deltime) {
+         out = dry * dry_value;
+         amt.step();
+         fb.step();
+     }
+     else
+     {
+         float delayed = delayed_value; // avoid dereferencing the pointer in 'then' branch of the if()
+         dsp::sanitize(delayed);
+         out = dry * dry_value + delayed * amt.get();
+         del = dry_value + delayed * fb.get();
+     }
+ }
+ 
+ /// Single delay line with tap output
+ static inline void delayline2_impl(int age, int deltime, float dry_value, const float &delayed_value, const float &delayed_value_for_fb, float &out, float &del, gain_smoothing &amt, gain_smoothing &fb, float dry)
+ {
+     if (age <= deltime) {
+         out = dry * dry_value;
+         amt.step();
+         fb.step();
+     }
+     else
+     {
+         out = dry * dry_value + delayed_value * amt.get();
+         del = dry_value + delayed_value_for_fb * fb.get();
+         dsp::sanitize(out);
+         dsp::sanitize(del);
+     }
+ }
+ 
  uint32_t vintage_delay_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
  {
      uint32_t ostate = 3; // XXXKF optimize!
      uint32_t end = offset + numsamples;
-     int v = mixmode ? 1 : 0;
      int orig_bufptr = bufptr;
-     for(uint32_t i = offset; i < end; i++)
+     float out_left, out_right, del_left, del_right;
+     
+     switch(mixmode)
      {
-         float out_left, out_right, del_left, del_right;
-         // if the buffer hasn't been cleared yet (after activation), pretend we've read zeros
- 
-         if (deltime_l >= age) {
-             del_left = ins[0][i];
-             out_left = dry * del_left;
-             amt_left.step();
-             fb_left.step();
-         }
-         else
+         case MIXMODE_STEREO:
+         case MIXMODE_PINGPONG:
          {
-             float in_left = buffers[v][(bufptr - deltime_l) & ADDR_MASK];
-             dsp::sanitize(in_left);
-             out_left = dry * ins[0][i] + in_left * amt_left.get();
-             del_left = ins[0][i] + in_left * fb_left.get();
-         }
-         if (deltime_r >= age) {
-             del_right = ins[1][i];
-             out_right = dry * del_right;
-             amt_right.step();
-             fb_right.step();
+             int v = mixmode == MIXMODE_PINGPONG ? 1 : 0;
+             for(uint32_t i = offset; i < end; i++)
+             {                
+                 float cur_dry = dry.get();
+                 delayline_impl(age, deltime_l, ins[0][i], buffers[v][(bufptr - deltime_l) & ADDR_MASK], out_left, del_left, amt_left, fb_left, cur_dry);
+                 delayline_impl(age, deltime_r, ins[1][i], buffers[1 - v][(bufptr - deltime_r) & ADDR_MASK], out_right, del_right, amt_right, fb_right, cur_dry);
+                 
+                 age++;
+                 outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right;
+                 bufptr = (bufptr + 1) & (MAX_DELAY - 1);
+             }
          }
-         else
+         break;
+         
+         case MIXMODE_LR:
+         case MIXMODE_RL:
          {
-             float in_right = buffers[1 - v][(bufptr - deltime_r) & ADDR_MASK];
-             dsp::sanitize(in_right);
-             out_right = dry * ins[1][i] + in_right * amt_right.get();
-             del_right = ins[1][i] + in_right * fb_right.get();
+             int v = mixmode == MIXMODE_RL ? 1 : 0;
+             int deltime_fb = deltime_l + deltime_r;
+             int deltime_l_corr = mixmode == MIXMODE_RL ? deltime_fb : deltime_l;
+             int deltime_r_corr = mixmode == MIXMODE_LR ? deltime_fb : deltime_r;
+             
+             for(uint32_t i = offset; i < end; i++)
+             {
+                 float cur_dry = dry.get();
+                 delayline2_impl(age, deltime_l, ins[0][i], buffers[v][(bufptr - deltime_l_corr) & ADDR_MASK], buffers[v][(bufptr - deltime_fb) & ADDR_MASK], out_left, del_left, amt_left, fb_left, cur_dry);
+                 delayline2_impl(age, deltime_r, ins[1][i], buffers[1 - v][(bufptr - deltime_r_corr) & ADDR_MASK], buffers[1-v][(bufptr - deltime_fb) & ADDR_MASK], out_right, del_right, amt_right, fb_right, cur_dry);
+                 
+                 age++;
+                 outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right;
+                 bufptr = (bufptr + 1) & (MAX_DELAY - 1);
+             }
          }
-         
-         age++;
-         outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right;
-         bufptr = (bufptr + 1) & (MAX_DELAY - 1);
      }
      if (age >= MAX_DELAY)
          age = MAX_DELAY;
@@@ -2887,9 -2942,10 +2942,9 @@@ bool pulsator_audio_module::get_gridlin
      return false;
  }
  
 -
  /// Saturator Band by Markus Schmidt
  ///
- /// This module is based on Krzysztof's filters and Tom's distortion routine.
+ /// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
  /// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
  ///////////////////////////////////////////////////////////////////////////////////////////////
  
@@@ -3002,7 -3058,6 +3057,6 @@@ uint32_t saturator_audio_module::proces
          meter_in  = 0.f;
          meter_out = 0.f;
          meter_drive = 0.f;
- 
      } else {
          
          clip_in    -= std::min(clip_in,  numsamples);
@@@ -3010,57 -3065,49 +3064,57 @@@
          meter_in = 0.f;
          meter_out = 0.f;
          meter_drive = 0.f;
 -        
 +        float in_avg[2] = {0.f, 0.f};
 +        float out_avg[2] = {0.f, 0.f};
 +        float tube_avg = 0.f;
          // process
          while(offset < numsamples) {
              // cycle through samples
              float out[2], in[2] = {0.f, 0.f};
 -            float maxIn, maxOut, maxDrive = 0.f;
 +            float maxIn, maxOut = 0.f;
              int c = 0;
              
              if(in_count > 1 && out_count > 1) {
                  // stereo in/stereo out
                  // handle full stereo
                  in[0] = ins[0][offset];
 -                in[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];
 +            proc[0] = in[0] * *params[param_level_in];
 +            proc[1] = in[1] * *params[param_level_in];
              
              for (int i = 0; i < c; ++i) {
                  // all pre filters in chain
                  proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
                  proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
                  
 -                // saturate
 +                // get average for display purposes before...
 +                in_avg[i] += fabs(pow(proc[i], 2.f));
 +
 +                // ...saturate...
                  proc[i] = dist[i].process(proc[i]);
                  
 +                // ...and get average after...
 +                out_avg[i] += fabs(pow(proc[i], 2.f));
 +                
                  // tone control
                  proc[i] = p[i].process(proc[i]);
  
                  // all post filters in chain
                  proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
                  proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
 +                
 +                //subtract gain
 +                 proc[i] /= *params[param_level_in];
              }
              
              if(in_count > 1 && out_count > 1) {
@@@ -3071,6 -3118,7 +3125,6 @@@
                  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];
@@@ -3079,6 -3127,7 +3133,6 @@@
                  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
@@@ -3086,6 -3135,7 +3140,6 @@@
                  outs[0][offset] = out[0];
                  maxIn = fabs(in[0]);
                  maxOut = fabs(out[0]);
 -                maxDrive = dist[0].get_distortion_level();
              }
              
              if(maxIn > 1.f) {
@@@ -3101,14 -3151,13 +3155,14 @@@
              if(maxOut > meter_out) {
                  meter_out = maxOut;
              }
 -            if(maxDrive > meter_drive) {
 -                meter_drive = maxDrive;
 -            }
              
              // next sample
              ++offset;
          } // cycle trough samples
 +        
 +        tube_avg = (sqrt(std::max(out_avg[0], out_avg[1])) / numsamples) - (sqrt(std::max(in_avg[0], in_avg[1])) / numsamples);
 +        meter_drive = (5.0f * fabs(tube_avg) * (float(*params[param_blend]) + 30.0f));
 +        // printf("out:%.6f in: %.6f avg: %.6f drv: %.3f\n", sqrt(std::max(out_avg[0], out_avg[1])) / numsamples, sqrt(std::max(in_avg[0], in_avg[1])) / numsamples, tube_avg, meter_drive);
          // clean up
          lp[0][0].sanitize();
          lp[1][0].sanitize();
@@@ -3150,13 -3199,13 +3204,13 @@@
      return outputs_mask;
  }
  
 -/// Enhancer Band by Markus Schmidt
 +/// Exciter by Markus Schmidt
  ///
- /// This module is based on Krzysztof's filters and Tom's distortion routine.
- /// It sends the signal through a highpass, saturates it and sends it through a highpass again
+ /// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
+ /// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
  ///////////////////////////////////////////////////////////////////////////////////////////////
  
 -enhancer_audio_module::enhancer_audio_module()
 +exciter_audio_module::exciter_audio_module()
  {
      is_active = false;
      srate = 0;
@@@ -3167,18 -3216,18 +3221,19 @@@
      meter_drive = 0.f;
  }
  
 -void enhancer_audio_module::activate()
 +void exciter_audio_module::activate()
  {
      is_active = true;
      // set all filters
      params_changed();
  }
 -void enhancer_audio_module::deactivate()
++
 +void exciter_audio_module::deactivate()
  {
      is_active = false;
  }
  
 -void enhancer_audio_module::params_changed()
 +void exciter_audio_module::params_changed()
  {
      // set the params of all filters
      if(*params[param_freq] != freq_old) {
@@@ -3200,7 -3249,7 +3255,7 @@@
          dist[1].set_params(*params[param_blend], *params[param_drive]);
  }
  
 -void enhancer_audio_module::set_sample_rate(uint32_t sr)
 +void exciter_audio_module::set_sample_rate(uint32_t sr)
  {
      srate = sr;
      dist[0].set_sample_rate(sr);
@@@ -3208,7 -3257,7 +3263,7 @@@
          dist[1].set_sample_rate(sr);
  }
  
 -uint32_t enhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
 +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;
@@@ -3373,307 -3422,3 +3428,225 @@@
      return outputs_mask;
  }
  
 +/// Bass Enhancer by Markus Schmidt
 +///
 +/// This module is based on Krzysztof's filters and Tom's distortion routine.
 +/// It sends the signal through a lowpass, saturates it and sends it through a lowpass again
 +///////////////////////////////////////////////////////////////////////////////////////////////
 +
 +bassenhancer_audio_module::bassenhancer_audio_module()
 +{
 +    is_active = false;
 +    srate = 0;
 +    clip_in    = 0.f;
 +    clip_out   = 0.f;
 +    meter_in  = 0.f;
 +    meter_out = 0.f;
 +    meter_drive = 0.f;
 +}
 +
 +void bassenhancer_audio_module::activate()
 +{
 +    is_active = true;
 +    // set all filters
 +    params_changed();
 +}
 +void bassenhancer_audio_module::deactivate()
 +{
 +    is_active = false;
 +}
 +
 +void bassenhancer_audio_module::params_changed()
 +{
 +    // set the params of all filters
 +    if(*params[param_freq] != freq_old) {
 +        lp[0][0].set_lp_rbj(*params[param_freq], 0.707, (float)srate);
 +        lp[0][1].copy_coeffs(lp[0][0]);
 +        lp[0][2].copy_coeffs(lp[0][0]);
 +        lp[0][3].copy_coeffs(lp[0][0]);
 +        if(in_count > 1 && out_count > 1) {
 +            lp[1][0].copy_coeffs(lp[0][0]);
 +            lp[1][1].copy_coeffs(lp[0][0]);
 +            lp[1][2].copy_coeffs(lp[0][0]);
 +            lp[1][3].copy_coeffs(lp[0][0]);
 +        }
 +        freq_old = *params[param_freq];
 +    }
 +    // set distortion
 +    dist[0].set_params(*params[param_blend], *params[param_drive]);
 +    if(in_count > 1 && out_count > 1)
 +        dist[1].set_params(*params[param_blend], *params[param_drive]);
 +}
 +
 +void bassenhancer_audio_module::set_sample_rate(uint32_t sr)
 +{
 +    srate = sr;
 +    dist[0].set_sample_rate(sr);
 +    if(in_count > 1 && out_count > 1)
 +        dist[1].set_sample_rate(sr);
 +}
 +
 +uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
 +{
 +    bool bypass = *params[param_bypass] > 0.5f;
 +    numsamples += offset;
 +    if(bypass) {
 +        // everything bypassed
 +        while(offset < numsamples) {
 +            if(in_count > 1 && out_count > 1) {
 +                outs[0][offset] = ins[0][offset];
 +                outs[1][offset] = ins[1][offset];
 +            } else if(in_count > 1) {
 +                outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
 +            } else if(out_count > 1) {
 +                outs[0][offset] = ins[0][offset];
 +                outs[1][offset] = ins[0][offset];
 +            } else {
 +                outs[0][offset] = ins[0][offset];
 +            }
 +            ++offset;
 +        }
 +        // displays, too
 +        clip_in    = 0.f;
 +        clip_out   = 0.f;
 +        meter_in  = 0.f;
 +        meter_out = 0.f;
 +        meter_drive = 0.f;
 +    } else {
 +        
 +        clip_in    -= std::min(clip_in,  numsamples);
 +        clip_out   -= std::min(clip_out, numsamples);
 +        meter_in = 0.f;
 +        meter_out = 0.f;
 +        meter_drive = 0.f;
 +        
 +        // process
 +        while(offset < numsamples) {
 +            // cycle through samples
 +            float out[2], in[2] = {0.f, 0.f};
 +            float maxIn, maxOut, maxDrive = 0.f;
 +            int c = 0;
 +            
 +            if(in_count > 1 && out_count > 1) {
 +                // stereo in/stereo out
 +                // handle full stereo
 +                in[0] = ins[0][offset];
 +                in[0] *= *params[param_level_in];
 +                in[1] = ins[1][offset];
 +                in[1] *= *params[param_level_in];
 +                c = 2;
 +            } else {
 +                // in and/or out mono
 +                // handle mono
 +                in[0] = ins[0][offset];
 +                in[0] *= *params[param_level_in];
 +                in[1] = in[0];
 +                c = 1;
 +            }
 +            
 +            float proc[2];
 +            proc[0] = in[0];
 +            proc[1] = in[1];
 +            
 +            for (int i = 0; i < c; ++i) {
 +                // all pre filters in chain
 +                proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
 +                
 +                // saturate
 +                proc[i] = dist[i].process(proc[i]);
 +
 +                // all post filters in chain
 +                proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
 +            }
 +            
 +            if(in_count > 1 && out_count > 1) {
 +                // full stereo
 +                if(*params[param_listen] > 0.f)
 +                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
 +                else
 +                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
 +                outs[0][offset] = out[0];
 +                if(*params[param_listen] > 0.f)
 +                    out[1] = proc[1] * *params[param_amount] * *params[param_level_out];
 +                else
 +                    out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out];
 +                outs[1][offset] = out[1];
 +                maxIn = std::max(fabs(in[0]), fabs(in[1]));
 +                maxOut = std::max(fabs(out[0]), fabs(out[1]));
 +                maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount],
 +                                            dist[1].get_distortion_level() * *params[param_amount]);
 +            } else if(out_count > 1) {
 +                // mono -> pseudo stereo
 +                if(*params[param_listen] > 0.f)
 +                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
 +                else
 +                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
 +                outs[0][offset] = out[0];
 +                out[1] = out[0];
 +                outs[1][offset] = out[1];
 +                maxOut = fabs(out[0]);
 +                maxIn = fabs(in[0]);
 +                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
 +            } else {
 +                // stereo -> mono
 +                // or full mono
 +                if(*params[param_listen] > 0.f)
 +                    out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
 +                else
 +                    out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
 +                outs[0][offset] = out[0];
 +                maxIn = fabs(in[0]);
 +                maxOut = fabs(out[0]);
 +                maxDrive = dist[0].get_distortion_level() * *params[param_amount];
 +            }
 +            
 +            if(maxIn > 1.f) {
 +                clip_in  = srate >> 3;
 +            }
 +            if(maxOut > 1.f) {
 +                clip_out = srate >> 3;
 +            }
 +            // set up in / out meters
 +            if(maxIn > meter_in) {
 +                meter_in = maxIn;
 +            }
 +            if(maxOut > meter_out) {
 +                meter_out = maxOut;
 +            }
 +            if(maxDrive > meter_drive) {
 +                meter_drive = maxDrive;
 +            }
 +            
 +            // next sample
 +            ++offset;
 +        } // cycle trough samples
 +        // clean up
 +        lp[0][0].sanitize();
 +        lp[1][0].sanitize();
 +        lp[0][1].sanitize();
 +        lp[1][1].sanitize();
 +        lp[0][2].sanitize();
 +        lp[1][2].sanitize();
 +        lp[0][3].sanitize();
 +        lp[1][3].sanitize();
 +    }
 +    // draw meters
 +    if(params[param_clip_in] != NULL) {
 +        *params[param_clip_in] = clip_in;
 +    }
 +    if(params[param_clip_out] != NULL) {
 +        *params[param_clip_out] = clip_out;
 +    }
 +    
 +    if(params[param_meter_in] != NULL) {
 +        *params[param_meter_in] = meter_in;
 +    }
 +    if(params[param_meter_out] != NULL) {
 +        *params[param_meter_out] = meter_out;
 +    }
 +    if(params[param_meter_drive] != NULL) {
 +        *params[param_meter_drive] = meter_drive;
 +    }
 +    // whatever has to be returned x)
 +    return outputs_mask;
 +}
- 
- 
- /// Distortion Module by Tom Szilagyi
- ///
- /// 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