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