diff options
Diffstat (limited to 'src')
35 files changed, 5297 insertions, 0 deletions
diff --git a/src/autowah.cc b/src/autowah.cc new file mode 100644 index 0000000..a18c8d3 --- /dev/null +++ b/src/autowah.cc @@ -0,0 +1,130 @@ +/* + Copyright (C) 2009 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <math.h> +#include <string.h> +#include "autowah.h" + + +void Ladspa_Autowah::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +#define G_RES 4.0f +#define F_MIN 300.0f +#define F_RAT 10 +#define B_MIN 0.03f +#define B_RAT 4 +#define T_MIN 0.05f +#define T_LOG 2 + + +void Ladspa_Autowah::active (bool act) +{ + if (! act) return; + + _wbase = F_MIN * 6.28f / _fsam; + _bbase = B_MIN; + _rfact = 64.0f / (_fsam * T_MIN); + _z1 = _z2 = 0; + _s1 = _s2 = 0; + _gx = _gy = 0; + _dr = 0; +} + + +void Ladspa_Autowah::runproc (SampleCount len, bool add) +{ + int i, k; + float *inp = _port [A_INP]; + float *out = _port [A_OUT]; + float z1, z2, s1, s2, gx, gy; + float ds1, ds2, dgx, dgy; + float gd, rf, md, fr, dr; + float b, p, t, w, x, y; + + gx = _gx; + gy = _gy; + t = _port [C_OPMIX][0]; + _gy = G_RES * t; + _gx = _gy + 1 - t; + dgx = (_gx - gx) / len; + dgy = (_gy - gy) / len; + + gd = 10 * powf (10.0f, 0.05f * _port [C_DRIVE][0]); + rf = 1.0f - _rfact / powf (10.0f, T_LOG * _port [C_DECAY][0]); + md = _port [C_RANGE][0]; + fr = _port [C_FREQ][0]; + + z1 = _z1; + z2 = _z2; + s1 = _s1; + s2 = _s2; + dr = _dr; + + while (len) + { + k = (len > 80) ? 64 : len; + + p = 0; + for (i = 0; i < k; i++) + { + x = inp [i]; + p += x * x; + } + p = gd * sqrtf (p / k); + + if (p > dr) dr += 0.1f *(p - dr); + if (dr > md) dr = md; + t = dr + fr; + dr = dr * rf + 1e-10f; + w = _wbase * (1 + (F_RAT - 1) * t * t); + b = w * _bbase * (1 + (B_RAT - 1) * t); + if (w > 0.7f) w = 0.7f; + + _s1 = -cosf (w); + _s2 = (1 - b) / (1 + b); + ds1 = (_s1 - s1) / k; + ds2 = (_s2 - s2) / k; + + for (i = 0; i < k; i++) + { + s1 += ds1; + s2 += ds2; + gx += dgx; + gy += dgy; + x = inp [i]; + y = x - s2 * z2; + out [i] = gx * x - gy * (z2 + s2 * y); + y -= s1 * z1; + z2 = z1 + s1 * y; + z1 = y + 1e-10f; + } + inp += k; + out += k; + len -= k; + } + + _z1 = z1; + _z2 = z2; + _dr = dr; +} + diff --git a/src/autowah.h b/src/autowah.h new file mode 100644 index 0000000..79a3d9c --- /dev/null +++ b/src/autowah.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2009 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __AUTOWAH_H +#define __AUTOWAH_H + + +#include "ladspaplugin.h" + + +class Ladspa_Autowah : public LadspaPlugin +{ +public: + + enum { A_INP, A_OUT, C_DRIVE, C_DECAY, C_RANGE, C_FREQ, C_OPMIX, NPORT }; + + Ladspa_Autowah (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Autowah (void) {} + +private: + + float *_port [NPORT]; + float _wbase; + float _bbase; + float _rfact; + float _z1, _z2; + float _s1, _s2; + float _gx, _gy; + float _dr; +}; + + +#endif diff --git a/src/autowah_lv2.cc b/src/autowah_lv2.cc new file mode 100644 index 0000000..29a64ee --- /dev/null +++ b/src/autowah_lv2.cc @@ -0,0 +1,56 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "autowah.h" +#include "plugin_lv2.h" + +extern "C" { + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Autowah(rate); +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/fomp/autowah", + instantiate, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} + +} // extern "C" diff --git a/src/blvco.cc b/src/blvco.cc new file mode 100644 index 0000000..328f4b0 --- /dev/null +++ b/src/blvco.cc @@ -0,0 +1,354 @@ +/* + Copyright (C) 2003 Fons Adriaensen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "blvco.h" +#include "exp2ap.h" + +extern float exp2ap (float x); + + +static float _pulse [] = +{ + 0.000000, 0.000366, 0.001458, 0.003117, 0.005028, 0.006756, 0.007806, 0.007704, + 0.006086, 0.002778, -0.002139, -0.008292, -0.015022, -0.021434, -0.026492, -0.029153, + -0.028511, -0.023957, -0.015297, -0.002869, 0.012417, 0.029105, 0.045302, 0.058853, + 0.067578, 0.069533, 0.063273, 0.048113, 0.024337, -0.006682, -0.042487, -0.079654, + -0.114036, -0.141088, -0.156243, -0.155364, -0.135210, -0.093843, -0.030932, 0.052092, + 0.152049, 0.264172, 0.382359, 0.499585, 0.608450, 0.701808, 0.773391, 0.818353, + 0.833670, 0.818353, 0.773391, 0.701808, 0.608450, 0.499585, 0.382359, 0.264172, + 0.152049, 0.052092, -0.030932, -0.093843, -0.135210, -0.155364, -0.156243, -0.141088, + -0.114036, -0.079654, -0.042487, -0.006682, 0.024337, 0.048113, 0.063273, 0.069533, + 0.067578, 0.058853, 0.045302, 0.029105, 0.012417, -0.002869, -0.015297, -0.023957, + -0.028511, -0.029153, -0.026492, -0.021434, -0.015022, -0.008292, -0.002139, 0.002778, + 0.006086, 0.007704, 0.007806, 0.006756, 0.005028, 0.003117, 0.001458, 0.000366, + 0.000000 +}; + + +static const float lg2midc = log2f(261.63f); + + +void Ladspa_VCO_pulse1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_VCO_pulse1::active (bool act) +{ + _p = 0.5; + _w = _y = _z = 0; + _j = 0; + memset (_f, 0, (FILLEN + NCOEFF) * sizeof (float)); +} + + +void Ladspa_VCO_pulse1::runproc (SampleCount len, bool add) +{ + int i, j, n; + float *outp, *freq, *expm, *linm; + float a, p, r, t, w, dw, y, z, *f; + + outp = _port[OUTP]; + freq = _port[FREQ] - 1; + expm = _port[EXPM] - 1; + linm = _port[LINM] - 1; + + p = _p; + w = _w; + y = _y; + z = _z; + j = _j; + + a = 0.2 + 0.8 * _port [FILT][0]; + do + { + n = (len > 24) ? 16 : len; + freq += n; + expm += n; + linm += n; + len -= n; + + t = (exp2ap (log2f(*freq) - lg2midc + _port[OCTN][0] + _port[TUNE][0] + *expm * _port[EXPG][0] + 8.03136) + + 1e3 * *linm * _port[LING][0]) / _fsam; + if (t < 1e-5) t = 1e-5; + if (t > 0.5) t = 0.5; + dw = (t - w) / n; + + while (n--) + { + w += dw; + p += w; + if (p >= 1.0) + { + p -= 1.0; + r = NPHASE * p / w; + i = (int) r; + r -= i; + f = _f + j; + while (i < NPHASE * NCOEFF) + { + *f++ += r * _pulse [i + 1 ] + (1 - r) * _pulse [i]; + i += NPHASE; + } + } + + y = _f [j]; + z += a * (y - z); + *outp++ = z; + if (++j == FILLEN) + { + j = 0; + memcpy (_f, _f + FILLEN, NCOEFF * sizeof (float)); + memset (_f + NCOEFF, 0, FILLEN * sizeof (float)); + } + } + } + while (len); + + _p = p; + _w = w; + _y = y; + _z = z; + _j = j; +} + + + +void Ladspa_VCO_saw1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_VCO_saw1::active (bool act) +{ + _p = 0.5; + _w = _x = _y = _z = _d = 0; + _j = 0; + memset (_f, 0, (FILLEN + NCOEFF) * sizeof (float)); +} + + +void Ladspa_VCO_saw1::runproc (SampleCount len, bool add) +{ + int i, j, n; + float *outp, *freq, *expm, *linm, *sync; + float a, d, p, r, t, w, dw, x, y, z, *f; + + outp = _port[OUTP]; + freq = _port[FREQ] - 1; + expm = _port[EXPM] - 1; + linm = _port[LINM] - 1; + sync = _port[SYNC]; + + p = _p; + w = _w; + x = _x; + y = _y; + z = _z; + d = _d; + j = _j; + + a = 0.2 + 0.8 * _port [FILT][0]; + do + { + n = (len > 24) ? 16 : len; + freq += n; + expm += n; + linm += n; + len -= n; + + t = (exp2ap (log2f(*freq) - lg2midc + _port[OCTN][0] + _port[TUNE][0] + *expm * _port[EXPG][0] + 8.03136 + d) + + 1e3 * *linm * _port[LING][0]) / _fsam; + if (t < 1e-5) t = 1e-5; + if (t > 0.5) t = 0.5; + dw = (t - w) / n; + + while (n--) + { + w += dw; + p += w; + if (p >= 1.0) + { + p -= 1.0; + r = NPHASE * p / w; + i = (int) r; + r -= i; + f = _f + j; + while (i < NPHASE * NCOEFF) + { + *f++ += r * _pulse [i + 1 ] + (1 - r) * _pulse [i]; + i += NPHASE; + } + } + + x += _f [j] - w * (0.01 * y + 0.2 * x + 1); + y += 6.3 * w * x; + z += a * (x - z); + *outp++ = z; + d += 0.01 * (y * *sync++ - d); + if (++j == FILLEN) + { + j = 0; + memcpy (_f, _f + FILLEN, NCOEFF * sizeof (float)); + memset (_f + NCOEFF, 0, FILLEN * sizeof (float)); + } + } + } + while (len); + + _p = p; + _w = w; + _x = x; + _y = y; + _z = z; + _d = d; + _j = j; +} + + + +void Ladspa_VCO_rec1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_VCO_rec1::active (bool act) +{ + _p = 0.0; + _x = _y = _z = _d = 0; + _w = 0; + _b = 0.5; + _j = _k = 0; + memset (_f, 0, (FILLEN + NCOEFF) * sizeof (float)); +} + + +void Ladspa_VCO_rec1::runproc (SampleCount len, bool add) +{ + int i, j, k, n; + float *outp, *freq, *expm, *linm, *wavm, *sync; + float a, b, db, d, p, r, t, w, dw, x, y, z, *f; + + outp = _port[OUTP]; + freq = _port[FREQ] - 1; + expm = _port[EXPM] - 1; + linm = _port[LINM] - 1; + wavm = _port[WAVM] - 1; + sync = _port[SYNC]; + + p = _p; + w = _w; + b = _b; + x = _x; + y = _y; + z = _z; + d = _d; + j = _j; + k = _k; + + a = 0.2 + 0.8 * _port [FILT][0]; + do + { + n = (len > 24) ? 16 : len; + freq += n; + expm += n; + linm += n; + wavm += n; + len -= n; + + t = (exp2ap (log2f(*freq) - lg2midc + _port[OCTN][0] + _port[TUNE][0] + *expm * _port[EXPG][0] + 8.03136 + d) + + 1e3 * *linm * _port[LING][0]) / _fsam; + if (t < 1e-5) t = 1e-5; + if (t > 0.5) t = 0.5; + dw = (t - w) / n; + t = 0.5 * (1.0 + _port [WAVE][0] + *wavm * _port [WMOD][0]); + if (t < 0.02) t = 0.02; + if (t > 0.98) t = 0.98; + db = (t - b) / n; + + while (n--) + { + w += dw; + b += db; + p += w; + t = k ? 1.0 : b; + while (p >= t) + { + if (k) + { + k = 0; + p -= 1.0; + r = NPHASE * p / w; + t = b; + i = (int) r; + r -= i; + f = _f + j; + while (i < NPHASE * NCOEFF) + { + *f++ += r * _pulse [i + 1 ] + (1 - r) * _pulse [i]; + i += NPHASE; + } + } + else + { + k = 1; + r = NPHASE * (p - t) / w; + t = 1.0; + i = (int) r; + r -= i; + f = _f + j; + while (i < NPHASE * NCOEFF) + { + *f++ -= r * _pulse [i + 1 ] + (1 - r) * _pulse [i]; + i += NPHASE; + } + } + } + x -= w * (0.01 * y + 0.2 * x); + x += _f [j]; + y += 6.3 * w * x; + z += a * (x - z); + *outp++ = z; + d += 0.01 * (y * *sync++ - d); + if (++j == FILLEN) + { + j = 0; + memcpy (_f, _f + FILLEN, NCOEFF * sizeof (float)); + memset (_f + NCOEFF, 0, FILLEN * sizeof (float)); + } + } + } + while (len); + + _p = p; + _w = w; + _b = b; + _x = x; + _y = y; + _z = z; + _d = d; + _j = j; + _k = k; +} diff --git a/src/blvco.h b/src/blvco.h new file mode 100644 index 0000000..c56a33e --- /dev/null +++ b/src/blvco.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2003 Fons Adriaensen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __VCOSAWPULSE_H +#define __VCOSAWPULSE_H + +#include "ladspaplugin.h" + + +class Ladspa_VCO_pulse1 : public LadspaPlugin +{ +public: + + enum { NPHASE = 8, NCOEFF = 12, FILLEN = 256 }; + enum { OUTP, FREQ, EXPM, LINM, OCTN, TUNE, EXPG, LING, FILT, NPORT }; + + Ladspa_VCO_pulse1 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_VCO_pulse1 (void) {} + +private: + + float *_port [NPORT]; + float _p, _w, _y, _z; + float _f [FILLEN + NCOEFF]; + int _j; +}; + + +class Ladspa_VCO_saw1 : public LadspaPlugin +{ +public: + + enum { NPHASE = 8, NCOEFF = 12, FILLEN = 256 }; + enum { OUTP, FREQ, EXPM, LINM, SYNC, OCTN, TUNE, EXPG, LING, FILT, NPORT }; + + Ladspa_VCO_saw1 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_VCO_saw1 (void) {} + +private: + + float *_port [NPORT]; + float _p, _w, _x, _y, _z, _d; + float _f [FILLEN + NCOEFF]; + int _j; +}; + + +class Ladspa_VCO_rec1 : public LadspaPlugin +{ +public: + + enum { NPHASE = 8, NCOEFF = 12, FILLEN = 256 }; + enum { OUTP, FREQ, EXPM, LINM, WAVM, SYNC, OCTN, TUNE, EXPG, LING, WAVE, WMOD, FILT, NPORT }; + + Ladspa_VCO_rec1 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_VCO_rec1 (void) {} + +private: + + float *_port [NPORT]; + float _p, _w, _b, _x, _y, _z, _d; + float _f [FILLEN + NCOEFF]; + int _j, _k; +}; + + +#endif diff --git a/src/blvco_lv2.cc b/src/blvco_lv2.cc new file mode 100644 index 0000000..1e539e6 --- /dev/null +++ b/src/blvco_lv2.cc @@ -0,0 +1,90 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "blvco.h" +#include "plugin_lv2.h" + +extern "C" { + +static LV2_Handle +instantiate1(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_VCO_pulse1(rate); +} + +static LV2_Handle +instantiate2(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_VCO_saw1(rate); +} + +static LV2_Handle +instantiate3(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_VCO_rec1(rate); +} + +static const LV2_Descriptor descriptors[3] = { + { "http://drobilla.net/plugins/fomp/pulse_vco", + instantiate1, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/saw_vco", + instantiate2, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/rec_vco", + instantiate3, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + if (index < 3) { + return &descriptors[index]; + } + return NULL; +} + +} // extern "C" diff --git a/src/cs_chorus.cc b/src/cs_chorus.cc new file mode 100644 index 0000000..5cb28c5 --- /dev/null +++ b/src/cs_chorus.cc @@ -0,0 +1,406 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <math.h> +#include <string.h> +#include "cs_chorus.h" + + + +Ladspa_CS_chorus1::Ladspa_CS_chorus1 (SampleRate fsam) : LadspaPlugin (fsam) +{ + _size = (unsigned long)(ceil (30 * fsam / 1000.0)) + 64; + _size = (_size >> 6) << 6; + _line = new float [_size + 1]; +} + + +Ladspa_CS_chorus1::~Ladspa_CS_chorus1 (void) +{ + delete[] _line; +} + + +void Ladspa_CS_chorus1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_CS_chorus1::active (bool act) +{ + unsigned int i; + + if (act) + { + _wi = _gi = 0; + _x1 = _x2 = 1; + _y1 = _y2 = 0; + memset (_line, 0, (_size + 1) * sizeof (float)); + for (i = 0; i < 3; i++) _ri [i] = _dr [i] = 0; + } +} + + +void Ladspa_CS_chorus1::runproc (SampleCount len, bool add) +{ + unsigned long i, k, wi; + int j; + float *p0, *p1; + float t, x, y; + p0 = _port [INPUT]; + p1 = _port [OUTPUT]; + + wi = _wi; + do + { + if (_gi == 0) + { + _gi = 64; + + t = 402.12f * _port [FREQ1][0] / _fsam; + x = _x1 - t * _y1; + y = _y1 + t * _x1; + t = sqrtf (x * x + y * y); + _x1 = x / t; + _y1 = y / t; + + t = 402.12f * _port [FREQ2][0] / _fsam; + x = _x2 - t * _y2; + y = _y2 + t * _x2; + t = sqrtf (x * x + y * y); + _x2 = x / t; + _y2 = y / t; + + x = _port [TMOD1][0] * _x1 + _port [TMOD2][0] * _x2; + y = _port [TMOD1][0] * _y1 + _port [TMOD2][0] * _y2; + + _dr [0] = x; + _dr [1] = -0.500f * x + 0.866f * y; + _dr [2] = -0.500f * x - 0.866f * y; + + for (j = 0; j < 3; j++) + { + t = _port [DELAY][0] + _dr [j]; + if (t < 0) t = 0; + if (t > 30) t = 30; + t *= _fsam / 1000.0f; + _dr [j] = (t - _ri [j]) / 64; + } + } + + k = (_gi < len) ? _gi : len; + _gi -= k; + len -= k; + + while (k--) + { + _line [++wi] = *p0++; + y = 0; + for (j = 0; j < 3; j++) + { + x = wi - _ri [j]; + _ri [j] += _dr [j]; + if (x < 0) x += _size; + i = (int)(floorf (x)); + x -= i; + y += (1 - x) * _line [i] + x * _line [i + 1]; + } + y *= 0.333f; + if (add) *p1++ += y * _gain; + else *p1++ = y; + + } + if (wi == _size) _line [wi = 0] = _line [_size]; + } + while (len); + + _wi = wi; +} + + + + +Ladspa_CS_chorus2::Ladspa_CS_chorus2 (SampleRate fsam) : LadspaPlugin (fsam) +{ + _size = (unsigned long)(ceil (30 * fsam / 500.0)) + 192; + _size = (_size >> 6) << 6; + _line = new float [_size + 1]; +} + + +Ladspa_CS_chorus2::~Ladspa_CS_chorus2 (void) +{ + delete[] _line; +} + + +void Ladspa_CS_chorus2::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_CS_chorus2::active (bool act) +{ + unsigned int i; + + if (act) + { + _wi = _gi = 0; + _x1 = _x2 = 1; + _y1 = _y2 = 0; + _a = _b = 0; + memset (_line, 0, (_size + 1) * sizeof (float)); + for (i = 0; i < 3; i++) _ri [i] = _dr [i] = 0; + } +} + + +void Ladspa_CS_chorus2::runproc (SampleCount len, bool add) +{ + unsigned long i, k, wi; + int j; + float *p0, *p1; + float a, b, t, x, y; + + p0 = _port [INPUT]; + p1 = _port [OUTPUT]; + + wi = _wi; + a = _a; + b = _b; + do + { + if (_gi == 0) + { + _gi = 64; + + t = 402.12f * _port [FREQ1][0] / _fsam; + x = _x1 - t * _y1; + y = _y1 + t * _x1; + t = sqrtf (x * x + y * y); + _x1 = x / t; + _y1 = y / t; + + t = 402.12f * _port [FREQ2][0] / _fsam; + x = _x2 - t * _y2; + y = _y2 + t * _x2; + t = sqrtf (x * x + y * y); + _x2 = x / t; + _y2 = y / t; + + x = _port [TMOD1][0] * _x1 + _port [TMOD2][0] * _x2; + y = _port [TMOD1][0] * _y1 + _port [TMOD2][0] * _y2; + + _dr [0] = x; + _dr [1] = -0.500f * x + 0.866f * y; + _dr [2] = -0.500f * x - 0.866f * y; + + for (j = 0; j < 3; j++) + { + t = _port [DELAY][0] + _dr [j]; + if (t < 0) t = 0; + if (t > 30) t = 30; + t *= _fsam / 500.0f; + _dr [j] = (t - _ri [j]) / 64; + } + } + + k = (_gi < len) ? _gi : len; + _gi -= k; + len -= k; + + while (k--) + { + x = *p0++ + 0.52f * a - 0.25f * b; + _line [++wi] = 0.5f * (x + b) + a; + b = a; + a = x; + x = 0.52f * a - 0.25f * b; + _line [++wi] = 0.5f * (x + b) + a; + b = a; + a = x; + + y = 0; + for (j = 0; j < 3; j++) + { + x = wi - _ri [j]; + _ri [j] += _dr [j]; + if (x < 0) x += _size; + i = (int)(floorf (x)); + x -= i; + y += (1 - x) * _line [i] + x * _line [i + 1]; + } + y *= 0.333f; + if (add) *p1++ += y * _gain; + else *p1++ = y; + + } + if (wi == _size) _line [wi = 0] = _line [_size]; + } + while (len); + + _wi = wi; + _a = a; + _b = b; +} + + + + +Ladspa_CS_chorus3::Ladspa_CS_chorus3 (SampleRate fsam) : LadspaPlugin (fsam) +{ + _size = (unsigned long)(ceil (30 * fsam / 500.0)) + 192; + _size = (_size >> 6) << 6; + _line = new float [_size + 1]; +} + + +Ladspa_CS_chorus3::~Ladspa_CS_chorus3 (void) +{ + delete[] _line; +} + + +void Ladspa_CS_chorus3::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_CS_chorus3::active (bool act) +{ + unsigned int i; + + if (act) + { + _wi = _gi = 0; + _x1 = _x2 = 1; + _y1 = _y2 = 0; + _a = _b = 0; + memset (_line, 0, (_size + 1) * sizeof (float)); + for (i = 0; i < 3; i++) _ri [i] = _dr [i] = 0; + } +} + + +void Ladspa_CS_chorus3::runproc (SampleCount len, bool add) +{ + unsigned long i, k, wi; + int j; + float *p0, *p1, *p2, *p3; + float a, b, t, x, y; + + p0 = _port [INPUT]; + p1 = _port [OUTPUT1]; + p2 = _port [OUTPUT2]; + p3 = _port [OUTPUT3]; + + wi = _wi; + a = _a; + b = _b; + do + { + if (_gi == 0) + { + _gi = 64; + + t = 402.12f * _port [FREQ1][0] / _fsam; + x = _x1 - t * _y1; + y = _y1 + t * _x1; + t = sqrtf (x * x + y * y); + _x1 = x / t; + _y1 = y / t; + + t = 402.12f * _port [FREQ2][0] / _fsam; + x = _x2 - t * _y2; + y = _y2 + t * _x2; + t = sqrtf (x * x + y * y); + _x2 = x / t; + _y2 = y / t; + + x = _port [TMOD1][0] * _x1 + _port [TMOD2][0] * _x2; + y = _port [TMOD1][0] * _y1 + _port [TMOD2][0] * _y2; + + _dr [0] = x; + _dr [1] = -0.500f * x + 0.866f * y; + _dr [2] = -0.500f * x - 0.866f * y; + + for (j = 0; j < 3; j++) + { + t = _port [DELAY][0] + _dr [j]; + if (t < 0) t = 0; + if (t > 30) t = 30; + t *= _fsam / 500.0f; + _dr [j] = (t - _ri [j]) / 64; + } + } + + k = (_gi < len) ? _gi : len; + _gi -= k; + len -= k; + + while (k--) + { + x = *p0++ + 0.52f * a - 0.25f * b; + _line [++wi] = 0.5f * (x + b) + a; + b = a; + a = x; + x = 0.52f * a - 0.25f * b; + _line [++wi] = 0.5f * (x + b) + a; + b = a; + a = x; + + x = wi - _ri [0]; + _ri [0] += _dr [0]; + if (x < 0) x += _size; + i = (int)(floorf (x)); + x -= i; + y = (1 - x) * _line [i] + x * _line [i + 1]; + if (add) *p1++ += y * _gain; + else *p1++ = y; + + x = wi - _ri [1]; + _ri [1] += _dr [1]; + if (x < 0) x += _size; + i = (int)(floorf (x)); + x -= i; + y = (1 - x) * _line [i] + x * _line [i + 1]; + if (add) *p2++ += y * _gain; + else *p2++ = y; + + x = wi - _ri [2]; + _ri [2] += _dr [2]; + if (x < 0) x += _size; + i = (int)(floorf (x)); + x -= i; + y = (1 - x) * _line [i] + x * _line [i + 1]; + if (add) *p3++ += y * _gain; + else *p3++ = y; + } + if (wi == _size) _line [wi = 0] = _line [_size]; + } + while (len); + + _wi = wi; + _a = a; + _b = b; +} + diff --git a/src/cs_chorus.h b/src/cs_chorus.h new file mode 100644 index 0000000..9228ffa --- /dev/null +++ b/src/cs_chorus.h @@ -0,0 +1,106 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __CS_CHORUS_H +#define __CS_CHORUS_H + +#include "ladspaplugin.h" + + +class Ladspa_CS_chorus1 : public LadspaPlugin +{ +public: + + enum { INPUT, OUTPUT, DELAY, FREQ1, TMOD1, FREQ2, TMOD2, NPORT }; + + Ladspa_CS_chorus1 (SampleRate fsam); + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_CS_chorus1 (void); + +private: + + float *_port [NPORT]; + unsigned long _size; + unsigned long _wi; + unsigned long _gi; + float _ri [3]; + float _dr [3]; + float _x1, _y1; + float _x2, _y2; + float *_line; +}; + + +class Ladspa_CS_chorus2 : public LadspaPlugin +{ +public: + + enum { INPUT, OUTPUT, DELAY, FREQ1, TMOD1, FREQ2, TMOD2, NPORT }; + + Ladspa_CS_chorus2 (SampleRate fsam); + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_CS_chorus2 (void); + +private: + + float *_port [NPORT]; + unsigned long _size; + unsigned long _wi; + unsigned long _gi; + float _ri [3]; + float _dr [3]; + float _x1, _y1; + float _x2, _y2; + float _a, _b; + float *_line; +}; + + +class Ladspa_CS_chorus3 : public LadspaPlugin +{ +public: + + enum { INPUT, OUTPUT1, OUTPUT2, OUTPUT3, DELAY, FREQ1, TMOD1, FREQ2, TMOD2, NPORT }; + + Ladspa_CS_chorus3 (SampleRate fsam); + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_CS_chorus3 (void); + +private: + + float *_port [NPORT]; + unsigned long _size; + unsigned long _wi; + unsigned long _gi; + float _ri [3]; + float _dr [3]; + float _x1, _y1; + float _x2, _y2; + float _a, _b; + float *_line; +}; + + +#endif diff --git a/src/cs_chorus_if.cc b/src/cs_chorus_if.cc new file mode 100644 index 0000000..4b5c270 --- /dev/null +++ b/src/cs_chorus_if.cc @@ -0,0 +1,247 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//----------------------------------------------------------------------------------- +// Common definitions + + +#include "cs_chorus.h" + +#define NMODS 3 +#define VERSION "0.4.0" + + +static const char* maker = "Fons Adriaensen <fons@kokkinizita.net>"; +static const char* copyr = "(C) 2003-2008 Fons Adriaensen - License: GPL2"; + + +static void pconnect (LADSPA_Handle H, PortIndex port, LADSPA_Data *data) +{ + ((LadspaPlugin *)H)->setport (port, data); +} + +static void activate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (true); +} + +static void runplugin (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, false); +} + +static void runadding (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, true); +} + +static void setadding (LADSPA_Handle H, LADSPA_Data gain) +{ + ((LadspaPlugin *)H)->setgain (gain); +} + +static void deactivate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (false); +} + +static void cleanup (LADSPA_Handle H) +{ + delete (LadspaPlugin *) H; +} + +//----------------------------------------------------------------------------------- +// Plugin definitions + + +static const char* name1 = "Chorus1 - Based on CSound orchestra by Sean Costello"; +static const char* label1 = "Chorus1"; + +static LADSPA_Handle instant1 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_CS_chorus1 (rate); +} + + +static const char* name2 = "Chorus2 - Based on CSound orchestra by Sean Costello"; +static const char* label2 = "Chorus2"; + +static LADSPA_Handle instant2 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_CS_chorus2 (rate); +} + + +static const char* name3 = "Triple chorus"; +static const char* label3 = "TripleChorus"; + +static LADSPA_Handle instant3 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_CS_chorus3 (rate); +} + + + +static const LADSPA_PortDescriptor pdesc12 [Ladspa_CS_chorus1::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const char * const pname12 [Ladspa_CS_chorus1::NPORT] = +{ + "Input", + "Output", + "Delay (ms)", + "Mod Frequency 1 (Hz)", + "Mod Amplitude 1 (ms)", + "Mod Frequency 2 (Hz)", + "Mod Amplitude 2 (ms)" +}; + +static const LADSPA_PortRangeHint phint12 [Ladspa_CS_chorus1::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, 0, 30 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_LOGARITHMIC, 0.003, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_LOGARITHMIC, 0.01, 30 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, 0, 3 } +}; + + +static const LADSPA_PortDescriptor pdesc3 [Ladspa_CS_chorus3::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const char * const pname3 [Ladspa_CS_chorus3::NPORT] = +{ + "Input", + "Output1", + "Output2", + "Output3", + "Delay (ms)", + "Mod Frequency 1 (Hz)", + "Mod Amplitude 1 (ms)", + "Mod Frequency 2 (Hz)", + "Mod Amplitude 2 (ms)" +}; + +static const LADSPA_PortRangeHint phint3 [Ladspa_CS_chorus3::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, 0, 30 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_LOGARITHMIC, 0.003, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_LOGARITHMIC, 0.01, 30 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, 0, 3 } +}; + + +static const LADSPA_Descriptor moddescr [NMODS] = +{ + { + 1944, + label1, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name1, + maker, + copyr, + Ladspa_CS_chorus1::NPORT, + pdesc12, + pname12, + phint12, + 0, + instant1, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + }, + { + 1945, + label2, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name2, + maker, + copyr, + Ladspa_CS_chorus1::NPORT, + pdesc12, + pname12, + phint12, + 0, + instant2, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + }, + { + 1951, + label3, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name3, + maker, + copyr, + Ladspa_CS_chorus3::NPORT, + pdesc3, + pname3, + phint3, + 0, + instant3, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + } +}; + +extern "C" const LADSPA_Descriptor *ladspa_descriptor (unsigned long i) +{ + if (i >= NMODS) return 0; + return moddescr + i; +} + +//----------------------------------------------------------------------------------- diff --git a/src/cs_chorus_lv2.cc b/src/cs_chorus_lv2.cc new file mode 100644 index 0000000..bb58b6c --- /dev/null +++ b/src/cs_chorus_lv2.cc @@ -0,0 +1,90 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "cs_chorus.h" +#include "plugin_lv2.h" + +extern "C" { + +static LV2_Handle +instantiate1(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_CS_chorus1(rate); +} + +static LV2_Handle +instantiate2(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_CS_chorus2(rate); +} + +static LV2_Handle +instantiate3(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_CS_chorus3(rate); +} + +static const LV2_Descriptor descriptors[3] = { + { "http://drobilla.net/plugins/fomp/cs_chorus1", + instantiate1, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/cs_chorus2", + instantiate2, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/triple_chorus", + instantiate3, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + if (index < 3) { + return &descriptors[index]; + } + return NULL; +} + +} // extern "C" diff --git a/src/cs_phaser.cc b/src/cs_phaser.cc new file mode 100644 index 0000000..099c90c --- /dev/null +++ b/src/cs_phaser.cc @@ -0,0 +1,191 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <stdio.h> +#include <math.h> +#include "cs_phaser.h" +#include "exp2ap.h" + + +void Ladspa_CS_phaser1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_CS_phaser1::active (bool act) +{ + if (act) + { + _w = _z = 0; + for (int i = 0; i < NSECT; i++) _c [i] = 0; + } +} + + +void Ladspa_CS_phaser1::runproc (SampleCount len, bool add) +{ + int i, k, ns; + float *p0, *p1, *p2, *p3, *p4; + float g0, gf, gi, gm; + float d, t, w, dw, x, z; + + p0 = _port [0]; + p1 = _port [1]; + p2 = _port [2] - 1; + p3 = _port [3] - 1; + p4 = _port [4] - 1; + + ns = (int)(floor (_port [6][0] + 0.5)); + g0 = exp2ap (0.1661f * _port [5][0]); + gf = _port [10][0]; + gm = _port [11][0]; + gi = 1 - fabs (gm); + + w = _w; + z = _z + 1e-10f; + + do + { + k = (len > 24) ? 16 : len; + p2 += k; + p3 += k; + p4 += k; + len -= k; + + t = (exp2ap (_port [8][0] * *p3 + _port [7][0] + *p2 + 9.683f) + _port [9][0] * *p4 * 1000.0f) / _fsam; + if (t < 0.0f) t = 0.0f; + if (t > 1.5f) t = 1.5f; + t = (sinf (t) - 1) / cosf (t) + 1; + dw = (t - w) / k; + + while (k--) + { + w += dw; + x = g0 * *p0++; + z = gf * z + x; + z = 4 * tanhf (0.25f * z); + for (i = 0; i < ns; i++) + { + t = _c [i]; + d = w * (2 * z - t); + t += d; + _c [i] = t + d; + z = t - z; + } + t = gm * z + gi * x; + if (add) *p1++ += t * _gain; + else *p1++ = t; + } + } + while (len); + + _w = w; + _z = z; +} + + + +void Ladspa_CS_phaser1lfo::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_CS_phaser1lfo::active (bool act) +{ + if (act) + { + _gi = 0; + _z = _w = _v = _p = 0; + for (int i = 0; i < NSECT; i++) _c [i] = 0; + } +} + + + + +void Ladspa_CS_phaser1lfo::runproc (SampleCount len, bool add) +{ + int i, k, ns; + float *p0, *p1; + float g0, gf, gi, gm; + float d, t, w, v, x, z; + + p0 = _port [0]; + p1 = _port [1]; + + ns = (int)(floor (_port [3][0] + 0.5)); + g0 = exp2ap (0.1661f * _port [2][0]); + gf = _port [8][0]; + gm = _port [9][0]; + gi = 1 - fabs (gm); + + z = _z + 1e-10f; + w = _w; + v = _v; + + do + { + if (_gi == 0) + { + _gi = DSUB; + _p += 2 * DSUB * _port [5][0] / _fsam; + if (_p > 1) _p -= 2; + x = 0.999f * _port [6][0]; + d = _p - x; + if (d < 0) t = 0.5f + d / (1 + x); + else t = 0.5f - d / (1 - x); + t = exp2ap (_port [7][0] * t + _port [4][0] + 9.683f) / _fsam; + if (t < 0.0f) t = 0.0f; + if (t > 1.5f) t = 1.5f; + t = (sinf (t) - 1) / cosf (t) + 1; + v = (t - w) / DSUB; + } + + k = (_gi < len) ? _gi : len; + _gi -= k; + len -= k; + while (k--) + { + x = g0 * *p0++; + z = gf * z + x; + z = 4 * tanhf (0.25f * z); + for (i = 0; i < ns; i++) + { + t = _c [i]; + d = w * (2 * z - t); + t += d; + _c [i] = t + d; + z = t - z; + } + t = gm * z + gi * x; + if (add) *p1++ += t * _gain; + else *p1++ = t; + w += v; + } + } + while (len); + + _z = z; + _w = w; + _v = v; +} + + diff --git a/src/cs_phaser.h b/src/cs_phaser.h new file mode 100644 index 0000000..d0e0f3c --- /dev/null +++ b/src/cs_phaser.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __CS_PHASER_H +#define __CS_PHASER_H + +#include "ladspaplugin.h" + + +class Ladspa_CS_phaser1 : public LadspaPlugin +{ +public: + + enum { NPORT = 12, NSECT = 30 }; + + Ladspa_CS_phaser1 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_CS_phaser1 (void) {} + +private: + + float *_port [NPORT]; + float _w, _z, _c [NSECT]; +}; + + +class Ladspa_CS_phaser1lfo : public LadspaPlugin +{ +public: + + enum { NPORT = 10, NSECT = 30 }; + + Ladspa_CS_phaser1lfo (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_CS_phaser1lfo (void) {} + +private: + + enum { DSUB = 32 }; + + float *_port [NPORT]; + float _z, _w, _v, _p, _c [NSECT]; + unsigned int _gi; +}; + +#endif diff --git a/src/cs_phaser_if.cc b/src/cs_phaser_if.cc new file mode 100644 index 0000000..d1ef98c --- /dev/null +++ b/src/cs_phaser_if.cc @@ -0,0 +1,236 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//----------------------------------------------------------------------------------- +// Common definitions + + +#include "cs_phaser.h" + +#define VERSION "0.4.0" +#define NMODS 2 + + +static const char* maker = "Fons Adriaensen <fons@kokkinizita.net>"; +static const char* copyr = "(C) 2003-2008 Fons Adriaensen - License: GPL2"; + + +static void pconnect (LADSPA_Handle H, unsigned long port, LADSPA_Data *data) +{ + ((LadspaPlugin *)H)->setport (port, data); +} + +static void activate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (true); +} + +static void runplugin (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, false); +} + +static void runadding (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, true); +} + +static void setadding (LADSPA_Handle H, LADSPA_Data gain) +{ + ((LadspaPlugin *)H)->setgain (gain); +} + +static void deactivate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (false); +} + +static void cleanup (LADSPA_Handle H) +{ + delete (LadspaPlugin *) H; +} + +//----------------------------------------------------------------------------------- + +static const char* name0 = "Phaser1 - Similar to CSound's phaser1 by Sean Costello"; +static const char* label0 = "Phaser1"; + +static LADSPA_Handle instant0 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_CS_phaser1 (rate); +} + + +static const LADSPA_PortDescriptor pdesc0 [Ladspa_CS_phaser1::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const char * const pname0 [Ladspa_CS_phaser1::NPORT] = +{ + "Input", + "Output", + "Frequency", + "Exp FM", + "Lin FM", + "Input gain (dB)", + "Sections", + "Frequency", + "Exp FM gain", + "Lin FM gain", + "Feedback gain", + "Output mix" +}; + +static const LADSPA_PortRangeHint phint0 [Ladspa_CS_phaser1::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -40, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_INTEGER, 1, Ladspa_CS_phaser1::NSECT }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -6, 6 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -1, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -1, 1 }, +}; + + +//----------------------------------------------------------------------------------- + +static const char* name1 = "Phaser1 with LFO"; +static const char* label1 = "Phaser1+LFO"; + +static LADSPA_Handle instant1 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_CS_phaser1lfo (rate); +} + + +static const LADSPA_PortDescriptor pdesc1 [Ladspa_CS_phaser1lfo::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const char * const pname1 [Ladspa_CS_phaser1lfo::NPORT] = +{ + "Input", + "Output", + "Input gain (dB)", + "Sections", + "Frequency", + "LFO frequency (Hz)", + "LFO waveform", + "Modulation gain", + "Feedback gain", + "Output mix" +}; + +static const LADSPA_PortRangeHint phint1 [Ladspa_CS_phaser1lfo::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -40, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_INTEGER, 1, Ladspa_CS_phaser1lfo::NSECT }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -6, 6 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_LOGARITHMIC, 0.01, 30 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -1, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -1, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -1, 1 }, +}; + + +//----------------------------------------------------------------------------------- + +static const LADSPA_Descriptor moddescr [NMODS] = +{ + { + 1946, + label0, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name0, + maker, + copyr, + Ladspa_CS_phaser1::NPORT, + pdesc0, + pname0, + phint0, + 0, + instant0, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + }, + { + 1947, + label1, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name1, + maker, + copyr, + Ladspa_CS_phaser1lfo::NPORT, + pdesc1, + pname1, + phint1, + 0, + instant1, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + } +}; + +extern "C" const LADSPA_Descriptor *ladspa_descriptor (unsigned long i) +{ + if (i >= NMODS) return 0; + return moddescr + i; +} + +//----------------------------------------------------------------------------------- diff --git a/src/cs_phaser_lv2.cc b/src/cs_phaser_lv2.cc new file mode 100644 index 0000000..576d4a2 --- /dev/null +++ b/src/cs_phaser_lv2.cc @@ -0,0 +1,73 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "cs_phaser.h" +#include "plugin_lv2.h" + +extern "C" { + +static LV2_Handle +instantiate1(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_CS_phaser1(rate); +} + +static LV2_Handle +instantiate2(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_CS_phaser1lfo(rate); +} + +static const LV2_Descriptor descriptors[3] = { + { "http://drobilla.net/plugins/fomp/cs_phaser1", + instantiate1, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/cs_phaser1_lfo", + instantiate2, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + if (index < 2) { + return &descriptors[index]; + } + return NULL; +} + +} // extern "C" diff --git a/src/exp2ap.h b/src/exp2ap.h new file mode 100644 index 0000000..2485539 --- /dev/null +++ b/src/exp2ap.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <math.h> + +static inline float exp2ap (float x) +{ + const int i = (int)(floorf (x)); + x -= i; + return ldexpf (1 + x * (0.6930f + x * (0.2416f + x * (0.0517f + x * 0.0137f))), i); +} + + diff --git a/src/filters.cc b/src/filters.cc new file mode 100644 index 0000000..8c93696 --- /dev/null +++ b/src/filters.cc @@ -0,0 +1,113 @@ +/* + Copyright (C) 2004-2009 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <string.h> +#include "filters.h" +#include "exp2ap.h" + + +void Ladspa_Paramfilt::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_Paramfilt::active (bool act) +{ + int j; + + if (! act) return; + _fade = 0; + _gain = 1; + for (j = 0; j < NSECT; j++) _sect [j].init (); +} + + +void Ladspa_Paramfilt::runproc (SampleCount len, bool add) +{ + int i, j, k; + float *aip = _port [AIP]; + float *aop = _port [AOP]; + float *p, sig [48]; + float t, g, d; + float fgain; + float sfreq [NSECT]; + float sband [NSECT]; + float sgain [NSECT]; + + fgain = exp2ap (0.1661 * _port [GAIN][0]); + for (j = 0; j < NSECT; j++) + { + t = _port [SECT + 4 * j + Paramsect::FREQ][0] / _fsam; + if (t < 0.0002) t = 0.0002; + if (t > 0.4998) t = 0.4998; + sfreq [j] = t; + sband [j] = _port [SECT + 4 * j + Paramsect::BAND][0]; + if (_port [SECT + 4 * j + Paramsect::SECT][0] > 0) sgain [j] = exp2ap (0.1661 * _port [SECT + 4 * j + Paramsect::GAIN][0]); + else sgain [j] = 1.0; + } + + while (len) + { + k = (len > 48) ? 32 : len; + + t = fgain; + g = _gain; + if (t > 1.25 * g) t = 1.25 * g; + else if (t < 0.80 * g) t = 0.80 * g; + _gain = t; + d = (t - g) / k; + for (i = 0; i < k; i++) + { + g += d; + sig [i] = g * aip [i]; + } + + for (j = 0; j < NSECT; j++) _sect [j].proc (k, sig, sfreq [j], sband [j], sgain [j]); + + j = _fade; + g = j / 16.0; + p = 0; + if (_port [FILT][0] > 0) + { + if (j == 16) p = sig; + else ++j; + } + else + { + if (j == 0) p = aip; + else --j; + } + _fade = j; + if (p) memcpy (aop, p, k * sizeof (float)); + else + { + d = (j / 16.0 - g) / k; + for (i = 0; i < k; i++) + { + g += d; + aop [i] = g * sig [i] + (1 - g) * aip [i]; + } + } + aip += k; + aop += k; + len -= k; + } +} + diff --git a/src/filters.h b/src/filters.h new file mode 100644 index 0000000..3000870 --- /dev/null +++ b/src/filters.h @@ -0,0 +1,130 @@ +/* + Copyright (C) 2004-2009 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __FILTERS_H +#define __FILTERS_H + +#include <math.h> +#include "ladspaplugin.h" + + +class Paramsect +{ +public: + + enum { SECT, FREQ, BAND, GAIN }; + + void init (void) + { + _f = 0.25f; + _b = _g = 1.0f; + _a = _s1 = _s2 = _z1 = _z2 = 0.0f; + } + + void proc (int k, float *sig, float f, float b, float g) + { + float s1, s2, d1, d2, a, da, x, y; + bool u2 = false; + + s1 = _s1; + s2 = _s2; + a = _a; + d1 = 0; + d2 = 0; + da = 0; + + if (f != _f) + { + if (f < 0.5f * _f) f = 0.5f * _f; + else if (f > 2.0f * _f) f = 2.0f * _f; + _f = f; + _s1 = -cosf (6.283185f * f); + d1 = (_s1 - s1) / k; + u2 = true; + } + + if (g != _g) + { + if (g < 0.5f * _g) g = 0.5f * _g; + else if (g > 2.0f * _g) g = 2.0f * _g; + _g = g; + _a = 0.5f * (g - 1.0f); + da = (_a - a) / k; + u2 = true; + } + + if (b != _b) + { + if (b < 0.5f * _b) b = 0.5f * _b; + else if (b > 2.0f * _b) b = 2.0f * _b; + _b = b; + u2 = true; + } + + if (u2) + { + b *= 7 * f / sqrtf (g); + _s2 = (1 - b) / (1 + b); + d2 = (_s2 - s2) / k; + } + + while (k--) + { + s1 += d1; + s2 += d2; + a += da; + x = *sig; + y = x - s2 * _z2; + *sig++ -= a * (_z2 + s2 * y - x); + y -= s1 * _z1; + _z2 = _z1 + s1 * y; + _z1 = y + 1e-10f; + } + } + +private: + + float _f, _b, _g; + float _s1, _s2, _a; + float _z1, _z2; +}; + + +class Ladspa_Paramfilt : public LadspaPlugin +{ +public: + + enum { AIP, AOP, FILT, GAIN, SECT, NSECT = 4, NPORT = 20 }; + + Ladspa_Paramfilt (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Paramfilt (void) {} + +private: + + float *_port [NPORT]; + float _gain; + int _fade; + Paramsect _sect [NSECT]; +}; + + +#endif diff --git a/src/filters_lv2.cc b/src/filters_lv2.cc new file mode 100644 index 0000000..0696c38 --- /dev/null +++ b/src/filters_lv2.cc @@ -0,0 +1,56 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "filters.h" +#include "plugin_lv2.h" + +extern "C" { + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Paramfilt(rate); +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/fomp/parametric1", + instantiate, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} + +} // extern "C" diff --git a/src/ladspaplugin.h b/src/ladspaplugin.h new file mode 100644 index 0000000..61d1210 --- /dev/null +++ b/src/ladspaplugin.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __LADSPAPLUGIN_H +#define __LADSPAPLUGIN_H + +#include <lv2/lv2plug.in/ns/lv2core/lv2.h> + + +/* This class name is now a misnomer but I have left it as-is to minimize + fragmentation. The following typedefs serve the same purpose, so the + plugins can be built with the correct LV2 type (e.g. uint32_t instead of + unsigned long) without 'hard' switching the DSP code to the new type. This + way, it should be straightforward to make the same code build as both LADSPA + and LV2 plugins, should the packages merge. ~ David Robillard, Aug. 2012 */ + +typedef double SampleRate; +typedef uint32_t SampleCount; +typedef uint32_t PortIndex; +typedef void PortData; + +class LadspaPlugin +{ +public: + + LadspaPlugin (SampleRate fsam) : _gain (1.0), _fsam (fsam) {} + + virtual void setport (PortIndex port, PortData *data) = 0; + virtual void active (bool act) = 0; + virtual void runproc (SampleCount len, bool add) = 0; + virtual ~LadspaPlugin (void) {} + + void setgain (float gain) { _gain = gain; } + +protected: + + float _gain; + float _fsam; +}; + + + +#endif diff --git a/src/mvchpf24.cc b/src/mvchpf24.cc new file mode 100644 index 0000000..96d3097 --- /dev/null +++ b/src/mvchpf24.cc @@ -0,0 +1,126 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <stdio.h> +#include <math.h> +#include "mvchpf24.h" +#include "exp2ap.h" + + +static const float lg2midc = log2f(261.63f); + + +void Ladspa_Mvchpf1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_Mvchpf1::active (bool act) +{ + _c1 = _c2 = _c3 = _c4 = _x = 0; + _w = 1e5; +} + + +void Ladspa_Mvchpf1::runproc (SampleCount len, bool add) +{ + int k; + float *p0, *p1, *p2, *p3; + float c1, c2, c3, c4; + float g0, g1, d, w, dw, t, x, y; + + p0 = _port [AINP]; + p1 = _port [AOUT]; + p2 = _port [AFREQ] - 1; + p3 = _port [AFMOD] - 1; + g0 = exp2ap (0.1661f * _port [CINP][0]) / 4; + g1 = exp2ap (0.1661f * _port [COUT][0]) * 4; + if (add) g1 *= _gain; + + c1 = _c1; + c2 = _c2; + c3 = _c3; + c4 = _c4; + w = _w; + x = _x; + + do + { + k = (len > 24) ? 16 : len; + p2 += k; + p3 += k; + len -= k; + + t = _fsam / exp2ap (_port [CFMOD][0] * *p3 + *p2 + log2f(_port [CFREQ][0]) - lg2midc + 9.2f); + if (t < 2) t = 2; + dw = (t - w) / k; + + while (k--) + { + w += dw; + + x = y = *p0++ * g0 - 0.3f * x; + + d = x - c1 + 1e-10f; + t = d * d; + d *= (1 + t) / (w + t); + c1 += d; + x -= c1; + c1 += d; + + d = x - c2 + 1e-10f; + t = d * d; + d *= (1 + t) / (w + t); + c2 += d; + x -= c2; + c2 += d; + + d = x - c3 + 1e-10f; + t = d * d; + d *= (1 + t) / (w + t); + c3 += d; + x -= c3; + c3 += d; + + d = x - c4 + 1e-10f; + t = d * d; + d *= (1 + t) / (w + t); + c4 += d; + x -= c4; + c4 += d; + + if (add) *p1++ += g1 * x; + else *p1++ = g1 * x; + + x -= y; + } + } + while (len); + + _c1 = c1; + _c2 = c2; + _c3 = c3; + _c4 = c4; + _w = w; + _x = x; +} + + + diff --git a/src/mvchpf24.h b/src/mvchpf24.h new file mode 100644 index 0000000..3fbaee4 --- /dev/null +++ b/src/mvchpf24.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __MVCHPF24_H +#define __MVCHPF24_H + +#include "ladspaplugin.h" + + +class Ladspa_Mvchpf1 : public LadspaPlugin +{ +public: + + enum { AINP, AOUT, AFREQ, AFMOD, CINP, CFREQ, CFMOD, COUT, NPORT }; + + Ladspa_Mvchpf1 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Mvchpf1 (void) {} + +private: + + float *_port [NPORT]; + float _c1, _c2, _c3, _c4, _w, _x; + +}; + + +#endif diff --git a/src/mvchpf24_if.cc b/src/mvchpf24_if.cc new file mode 100644 index 0000000..337f6ae --- /dev/null +++ b/src/mvchpf24_if.cc @@ -0,0 +1,150 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//----------------------------------------------------------------------------------- +// Common definitions + + +#include "mvchpf24.h" + +#define NMODS 1 +#define VERSION "0.4.0" + + +static const char* maker = "Fons Adriaensen <fons@kokkinizita.net>"; +static const char* copyr = "(C) 2003-2008 Fons Adriaensen - License: GPL2"; + + +static void pconnect (LADSPA_Handle H, unsigned long port, LADSPA_Data *data) +{ + ((LadspaPlugin *)H)->setport (port, data); +} + +static void activate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (true); +} + +static void runplugin (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, false); +} + +static void runadding (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, true); +} + +static void setadding (LADSPA_Handle H, LADSPA_Data gain) +{ + ((LadspaPlugin *)H)->setgain (gain); +} + +static void deactivate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (false); +} + +static void cleanup (LADSPA_Handle H) +{ + delete (LadspaPlugin *) H; +} + +//----------------------------------------------------------------------------------- +// Plugin definitions + + +static const char* name1 = "Mvchpf-1 Digital implementation of the VC HP filter invented by R.A. Moog"; +static const char* label1 = "Mvchpf-1"; + + +static LADSPA_Handle instant1 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_Mvchpf1 (rate); +} + + +static const char * const pname1 [Ladspa_Mvchpf1::NPORT] = +{ + "Input", + "Output", + "Frequency", + "Exp FM", + "Input gain (dB)", + "Frequency", + "Exp FM gain", + "Output gain (dB)" +}; + +static const LADSPA_PortDescriptor pdesc1 [Ladspa_Mvchpf1::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const LADSPA_PortRangeHint phint1 [Ladspa_Mvchpf1::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -60, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -6, 6 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -15, 15 }, +}; + + +static const LADSPA_Descriptor moddescr [NMODS] = +{ + { + 1960, + label1, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name1, + maker, + copyr, + Ladspa_Mvchpf1::NPORT, + pdesc1, + pname1, + phint1, + 0, + instant1, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + } +}; + +extern "C" const LADSPA_Descriptor *ladspa_descriptor (unsigned long i) +{ + if (i >= NMODS) return 0; + return moddescr + i; +} + +//----------------------------------------------------------------------------------- diff --git a/src/mvchpf24_lv2.cc b/src/mvchpf24_lv2.cc new file mode 100644 index 0000000..c34fca3 --- /dev/null +++ b/src/mvchpf24_lv2.cc @@ -0,0 +1,87 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "mvchpf24.h" + +extern "C" { + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + ((LadspaPlugin*)instance)->setport(port, data); +} + +static void +activate(LV2_Handle instance) +{ + ((LadspaPlugin*)instance)->active(true); +} + +static void +run(LV2_Handle instance, uint32_t n_samples) +{ + ((LadspaPlugin*)instance)->runproc(n_samples, false); +} + +static void +deactivate(LV2_Handle instance) +{ + ((LadspaPlugin*)instance)->active(false); +} + +static void +cleanup(LV2_Handle instance) +{ + delete ((LadspaPlugin*)instance); +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Mvchpf1(rate); +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/fomp/mvchpf1", + instantiate, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} + +} // extern "C" diff --git a/src/mvclpf24.cc b/src/mvclpf24.cc new file mode 100644 index 0000000..357fd7c --- /dev/null +++ b/src/mvclpf24.cc @@ -0,0 +1,439 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include <stdio.h> +#include <math.h> +#include "mvclpf24.h" +#include "exp2ap.h" + + +static const float lg2midc = log2f(261.63f); + + +void Ladspa_Moogvcf1::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_Moogvcf1::active (bool act) +{ + _c1 = _c2 = _c3 = _c4 = _c5 = _w = _r = 0; +} + + +void Ladspa_Moogvcf1::runproc (SampleCount len, bool add) +{ + int k; + float *p0, *p1, *p2, *p3, *p4; + float c1, c2, c3, c4, c5; + float g0, g1, r, dr, w, dw, x, t; + + p0 = _port [A_INPUT]; + p1 = _port [A_OUTPUT]; + p2 = _port [A_FREQ] - 1; + p3 = _port [A_FMOD] - 1; + p4 = _port [A_RESO] - 1; + g0 = exp2ap (0.1661f * _port [C_IPGAIN][0]) / 4; + g1 = exp2ap (0.1661f * _port [C_OPGAIN][0]) * 4; + if (add) g1 *= _gain; + + c1 = _c1 + 1e-6f; + c2 = _c2; + c3 = _c3; + c4 = _c4; + c5 = _c5; + w = _w; + r = _r; + + do + { + k = (len > 24) ? 16 : len; + p2 += k; + p3 += k; + p4 += k; + len -= k; + + t = exp2ap (_port [C_FMODG][0] * *p3 + log2f(_port [C_FREQ][0]) - lg2midc + *p2 + 10.82f) / _fsam; + if (t < 0.8f) t *= 1 - 0.4f * t - 0.125f * t * t; + else + { + t *= 0.6f; + if (t > 0.92f) t = 0.92f; + } + dw = (t - w) / k; + + t = _port [C_RESOG][0] * *p4 + _port [C_RESO][0]; + if (r > 1) r = 1; + if (r < 0) r = 0; + dr = (t - r) / k; + + while (k--) + { + w += dw; + r += dr; + x = -4.2 * r * c5 + *p0++ * g0 + 1e-10f; + t = c1 / (1 + fabsf (c1)); + c1 += w * (x - t); + x = c1 / (1 + fabsf (c1)); + c2 += w * (x - c2); + c3 += w * (c2 - c3); + c4 += w * (c3 - c4); + if (add) *p1++ += g1 * c4; + else *p1++ = g1 * c4; + c5 += 0.5f * (c4 - c5); + } + } + while (len); + + _c1 = c1; + _c2 = c2; + _c3 = c3; + _c4 = c4; + _c5 = c5; + _w = w; + _r = r; +} + + + +void Ladspa_Moogvcf2::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_Moogvcf2::active (bool act) +{ + _c1 = _c2 = _c3 = _c4 = _c5 = _w = _r = 0; +} + + +void Ladspa_Moogvcf2::runproc (SampleCount len, bool add) +{ + int k; + float *p0, *p1, *p2, *p3, *p4; + float c1, c2, c3, c4, c5; + float g0, g1, r, dr, w, dw, x, t; + + p0 = _port [A_INPUT]; + p1 = _port [A_OUTPUT]; + p2 = _port [A_FREQ] - 1; + p3 = _port [A_FMOD] - 1; + p4 = _port [A_RESO] - 1; + g0 = exp2ap (0.1661f * _port [C_IPGAIN][0]) / 4; + g1 = exp2ap (0.1661f * _port [C_OPGAIN][0]) * 4; + if (add) g1 *= _gain; + + c1 = _c1 + 1e-6f; + c2 = _c2; + c3 = _c3; + c4 = _c4; + c5 = _c5; + w = _w; + r = _r; + + do + { + k = (len > 24) ? 16 : len; + p2 += k; + p3 += k; + p4 += k; + len -= k; + + t = exp2ap (_port [C_FMODG][0] * *p3 + log2f(_port [C_FREQ][0]) - lg2midc + *p2 + 10.71f) / _fsam; + if (t < 0.8f) t *= 1 - 0.4f * t - 0.125f * t * t; + else + { + t *= 0.6f; + if (t > 0.92f) t = 0.92f; + } + dw = (t - w) / k; + + t = _port [C_RESOG][0] * *p4 + _port [C_RESO][0]; + if (t > 1) t = 1; + if (t < 0) t = 0; + dr = (t - r) / k; + + while (k--) + { + w += dw; + r += dr; + + x = -4.5f * r * c5 + *p0++ * g0 + 1e-10f; +// x = tanhf (x); + x /= sqrtf (1 + x * x); + c1 += w * (x - c1) / (1 + c1 * c1); + c2 += w * (c1 - c2) / (1 + c2 * c2); + c3 += w * (c2 - c3) / (1 + c3 * c3); + c4 += w * (c3 - c4) / (1 + c4 * c4); + + if (add) *p1++ += g1 * (c4); + else *p1++ = g1 * (c4); + c5 += 0.5f * (c4 - c5); + } + } + while (len); + + _c1 = c1; + _c2 = c2; + _c3 = c3; + _c4 = c4; + _c5 = c5; + _w = w; + _r = r; +} + + + +void Ladspa_Moogvcf3::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_Moogvcf3::active (bool act) +{ + _c1 = _c2 = _c3 = _c4 = _c5 = _w = _r = 0; +} + + +void Ladspa_Moogvcf3::runproc (SampleCount len, bool add) +{ + int k; + float *p0, *p1, *p2, *p3, *p4; + float c1, c2, c3, c4, c5; + float g0, g1, r, dr, w, dw, x, t, d; + + p0 = _port [A_INPUT]; + p1 = _port [A_OUTPUT]; + p2 = _port [A_FREQ] - 1; + p3 = _port [A_FMOD] - 1; + p4 = _port [A_RESO] - 1; + g0 = exp2ap (0.1661f * _port [C_IPGAIN][0]) / 4; + g1 = exp2ap (0.1661f * _port [C_OPGAIN][0]) * 4; + if (add) g1 *= _gain; + + c1 = _c1; + c2 = _c2; + c3 = _c3; + c4 = _c4; + c5 = _c5; + w = _w; + r = _r; + + do + { + k = (len > 24) ? 16 : len; + p2 += k; + p3 += k; + p4 += k; + len -= k; + + t = exp2ap (_port [C_FMODG][0] * *p3 + log2f(_port [C_FREQ][0]) - lg2midc + *p2 + 9.70f) / _fsam; + if (t < 0.75f) t *= 1.005f - t * (0.624f - t * (0.65f - t * 0.54f)); + else + { + t *= 0.6748f; + if (t > 0.82f) t = 0.82f; + } + dw = (t - w) / k; + + t = _port [C_RESOG][0] * *p4 + _port [C_RESO][0]; + if (t > 1) t = 1; + if (t < 0) t = 0; + dr = (t - r) / k; + + while (k--) + { + w += dw; + r += dr; + + x = *p0 * g0 - (4.3f - 0.2f * w) * r * c5 + 1e-10f; +// x = tanhf (x); + x /= sqrtf (1 + x * x); + d = w * (x - c1) / (1 + c1 * c1); + x = c1 + 0.77f * d; + c1 = x + 0.23f * d; + d = w * (x - c2) / (1 + c2 * c2); + x = c2 + 0.77f * d; + c2 = x + 0.23f * d; + d = w * (x - c3) / (1 + c3 * c3); + x = c3 + 0.77f * d; + c3 = x + 0.23f * d; + d = w * (x - c4); + x = c4 + 0.77f * d; + c4 = x + 0.23f * d; + c5 += 0.85f * (c4 - c5); + + x = *p0++ * g0 -(4.3f - 0.2f * w) * r * c5; +// x = tanhf (x); + x /= sqrtf (1 + x * x); + d = w * (x - c1) / (1 + c1 * c1); + x = c1 + 0.77f * d; + c1 = x + 0.23f * d; + d = w * (x - c2) / (1 + c2 * c2); + x = c2 + 0.77f * d; + c2 = x + 0.23f * d; + d = w * (x - c3) / (1 + c3 * c3); + x = c3 + 0.77f * d; + c3 = x + 0.23f * d; + d = w * (x - c4); + x = c4 + 0.77f * d; + c4 = x + 0.23f * d; + c5 += 0.85f * (c4 - c5); + + if (add) *p1++ += g1 * c4; + else *p1++ = g1 * c4; + } + } + while (len); + + _c1 = c1; + _c2 = c2; + _c3 = c3; + _c4 = c4; + _c5 = c5; + _w = w; + _r = r; +} + + +void Ladspa_Moogvcf4::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_Moogvcf4::active (bool act) +{ + _c1 = _c2 = _c3 = _c4 = _c5 = _w = _r = 0; +} + + +void Ladspa_Moogvcf4::runproc (SampleCount len, bool add) +{ + int k, op; + float *p0, *p1, *p2, *p3, *p4; + float c1, c2, c3, c4, c5; + float g0, g1, r, dr, w, dw, x, t, d, y; + + p0 = _port [A_INPUT]; + p1 = _port [A_OUTPUT]; + p2 = _port [A_FREQ] - 1; + p3 = _port [A_FMOD] - 1; + p4 = _port [A_RESO] - 1; + g0 = exp2ap (0.1661f * _port [C_IPGAIN][0]) / 4; + g1 = exp2ap (0.1661f * _port [C_OPGAIN][0]) * 4; + op = (int)(floorf (_port [C_LPFILT][0] + 0.5)); + if (add) g1 *= _gain; + + c1 = _c1 + 1e-6f; + c2 = _c2; + c3 = _c3; + c4 = _c4; + c5 = _c5; + w = _w; + r = _r; + + do + { + k = (len > 24) ? 16 : len; + p2 += k; + p3 += k; + p4 += k; + len -= k; + + t = exp2ap (_port [C_FMODG][0] * *p3 + log2f(_port [C_FREQ][0]) - lg2midc + *p2 + 9.70f) / _fsam; + if (t < 0.75f) t *= 1.005f - t * (0.624f - t * (0.65f - t * 0.54f)); + else + { + t *= 0.6748f; + if (t > 0.82f) t = 0.82f; + } + dw = (t - w) / k; + + t = _port [C_RESOG][0] * *p4 + _port [C_RESO][0]; + if (t > 1) t = 1; + if (t < 0) t = 0; + dr = (t - r) / k; + + while (k--) + { + w += dw; + r += dr; + + x = *p0 * g0 - (4.3f - 0.2f * w) * r * c5 + 1e-10f; +// x = tanhf (x); + x /= sqrtf (1 + x * x); + d = w * (x - c1) / (1 + c1 * c1); + x = c1 + 0.77f * d; + c1 = x + 0.23f * d; + d = w * (x - c2) / (1 + c2 * c2); + x = c2 + 0.77f * d; + c2 = x + 0.23f * d; + d = w * (x - c3) / (1 + c3 * c3); + x = c3 + 0.77f * d; + c3 = x + 0.23f * d; + d = w * (x - c4); + x = c4 + 0.77f * d; + c4 = x + 0.23f * d; + c5 += 0.85f * (c4 - c5); + + x = y = *p0++ * g0 -(4.3f - 0.2f * w) * r * c5; +// x = tanhf (x); + x /= sqrtf (1 + x * x); + d = w * (x - c1) / (1 + c1 * c1); + x = c1 + 0.77f * d; + c1 = x + 0.23f * d; + d = w * (x - c2) / (1 + c2 * c2); + x = c2 + 0.77f * d; + c2 = x + 0.23f * d; + d = w * (x - c3) / (1 + c3 * c3); + x = c3 + 0.77f * d; + c3 = x + 0.23f * d; + d = w * (x - c4); + x = c4 + 0.77f * d; + c4 = x + 0.23f * d; + c5 += 0.85f * (c4 - c5); + + switch (op) + { + case 1: y = c1; break; + case 2: y = c2; break; + case 3: y = c3; break; + case 4: y = c4; break; + } + + if (add) *p1++ += g1 * y; + else *p1++ = g1 * y; + } + } + while (len); + + _c1 = c1; + _c2 = c2; + _c3 = c3; + _c4 = c4; + _c5 = c5; + _w = w; + _r = r; +} + + diff --git a/src/mvclpf24.h b/src/mvclpf24.h new file mode 100644 index 0000000..f1132d3 --- /dev/null +++ b/src/mvclpf24.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef __MOOGVCF_H +#define __MOOGVCF_H + +#include "ladspaplugin.h" + + +class Ladspa_Moogvcf1 : public LadspaPlugin +{ +public: + + enum { A_INPUT, A_OUTPUT, A_FREQ, A_FMOD, A_RESO, + C_IPGAIN, C_FREQ, C_FMODG, C_RESO, C_RESOG, C_OPGAIN, NPORT }; + + Ladspa_Moogvcf1 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Moogvcf1 (void) {} + +private: + + float *_port [NPORT]; + float _c1, _c2, _c3, _c4, _c5, _w, _r; + +}; + + +class Ladspa_Moogvcf2 : public LadspaPlugin +{ +public: + + enum { A_INPUT, A_OUTPUT, A_FREQ, A_FMOD, A_RESO, + C_IPGAIN, C_FREQ, C_FMODG, C_RESO, C_RESOG, C_OPGAIN, NPORT }; + + Ladspa_Moogvcf2 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Moogvcf2 (void) {} + +private: + + float *_port [NPORT]; + float _c1, _c2, _c3, _c4, _c5, _w, _r; + +}; + + +class Ladspa_Moogvcf3 : public LadspaPlugin +{ +public: + + enum { A_INPUT, A_OUTPUT, A_FREQ, A_FMOD, A_RESO, + C_IPGAIN, C_FREQ, C_FMODG, C_RESO, C_RESOG, C_OPGAIN, NPORT }; + + Ladspa_Moogvcf3 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Moogvcf3 (void) {} + +private: + + float *_port [NPORT]; + float _c1, _c2, _c3, _c4, _c5, _w, _r; + +}; + + +class Ladspa_Moogvcf4 : public LadspaPlugin +{ +public: + + enum { A_INPUT, A_OUTPUT, A_FREQ, A_FMOD, A_RESO, + C_IPGAIN, C_FREQ, C_FMODG, C_RESO, C_RESOG, + C_LPFILT, C_OPGAIN, NPORT, NLABEL = 5 }; + + Ladspa_Moogvcf4 (SampleRate fsam) : LadspaPlugin (fsam) {} + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_Moogvcf4 (void) {} + +private: + + float *_port [NPORT]; + float _c1, _c2, _c3, _c4, _c5, _w, _r; + +}; + +#endif diff --git a/src/mvclpf24_if.cc b/src/mvclpf24_if.cc new file mode 100644 index 0000000..301ae92 --- /dev/null +++ b/src/mvclpf24_if.cc @@ -0,0 +1,299 @@ +/* + Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//----------------------------------------------------------------------------------- +// Common definitions + + +#include "mvclpf24.h" + +#define NMODS 4 +#define VERSION "0.4.0" + + +static const char* maker = "Fons Adriaensen <fons@kokkinizita.net>"; +static const char* copyr = "(C) 2003-2008 Fons Adriaensen - License: GPL2"; + + +static void pconnect (LADSPA_Handle H, unsigned long port, LADSPA_Data *data) +{ + ((LadspaPlugin *)H)->setport (port, data); +} + +static void activate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (true); +} + +static void runplugin (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, false); +} + +static void runadding (LADSPA_Handle H, unsigned long k) +{ + ((LadspaPlugin *)H)->runproc (k, true); +} + +static void setadding (LADSPA_Handle H, LADSPA_Data gain) +{ + ((LadspaPlugin *)H)->setgain (gain); +} + +static void deactivate (LADSPA_Handle H) +{ + ((LadspaPlugin *)H)->active (false); +} + +static void cleanup (LADSPA_Handle H) +{ + delete (LadspaPlugin *) H; +} + +//----------------------------------------------------------------------------------- +// Plugin definitions + + +static const char* name1 = "Mvclpf-1 Digital implementation of the VC filter invented by R.A.Moog"; +static const char* label1 = "Mvclpf-1"; + +static LADSPA_Handle instant1 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_Moogvcf1 (rate); +} + +static const char* name2 = "Mvclpf-2 Digital implementation of the VC filter invented by R.A.Moog"; +static const char* label2 = "Mvclpf-2"; + +static LADSPA_Handle instant2 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_Moogvcf2 (rate); +} + +static const char* name3 = "Mvclpf-3 Digital implementation of the VC filter invented by R.A.Moog"; +static const char* label3 = "Mvclpf-3"; + +static LADSPA_Handle instant3 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_Moogvcf3 (rate); +} + +static const char* name4 = "Mvclpf-4 Digital implementation of the VC filter invented by R.A.Moog"; +static const char* label4 = "Mvclpf-4"; + +static LADSPA_Handle instant4 (const struct _LADSPA_Descriptor *desc, unsigned long rate) +{ + return new Ladspa_Moogvcf4 (rate); +} + + +static const char * const pname1 [Ladspa_Moogvcf1::NPORT] = +{ + "Input", + "Output", + "Frequency", + "Exp FM", + "Resonance", + "Input gain (dB)", + "Frequency", + "Exp FM gain", + "Resonance", + "Resonance gain", + "Output gain (dB)" +}; + +static const LADSPA_PortDescriptor pdesc1 [Ladspa_Moogvcf1::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const LADSPA_PortRangeHint phint1 [Ladspa_Moogvcf1::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -60, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -6, 6 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -15, 15 }, +}; + + +static const char * const pname4 [Ladspa_Moogvcf4::NPORT + Ladspa_Moogvcf4::NLABEL] = +{ + "Input", + "Output", + "Frequency", + "Exp FM", + "Resonance", + "Input gain (dB)", + "Frequency", + "Exp FM gain", + "Resonance", + "Resonance gain", + "Filter poles", + "Output gain (dB)", + "No lowpass", + " 6 dB/oct", + "12 dB/oct", + "18 dB/oct", + "24 dB/oct" +}; + +static const LADSPA_PortDescriptor pdesc4 [Ladspa_Moogvcf4::NPORT] = +{ + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL +}; + +static const LADSPA_PortRangeHint phint4 [Ladspa_Moogvcf4::NPORT] = +{ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -60, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -6, 6 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 10 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 1 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_INTEGER /*| LADSPA_HINT_SWITCHED*/, 0, 4 }, + { LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0, -15, 15 }, +}; + + +static const LADSPA_Descriptor moddescr [NMODS] = +{ + { + 1941, + label1, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name1, + maker, + copyr, + Ladspa_Moogvcf1::NPORT, + pdesc1, + pname1, + phint1, + 0, + instant1, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + }, + { + 1942, + label2, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name2, + maker, + copyr, + Ladspa_Moogvcf2::NPORT, + pdesc1, + pname1, + phint1, + 0, + instant2, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + }, + { + 1943, + label3, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name3, + maker, + copyr, + Ladspa_Moogvcf3::NPORT, + pdesc1, + pname1, + phint1, + 0, + instant3, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + }, + { + 1948, + label4, + LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, + name4, + maker, + copyr, + Ladspa_Moogvcf4::NPORT, + pdesc4, + pname4, + phint4, + 0, + instant4, + pconnect, + activate, + runplugin, + runadding, + setadding, + deactivate, + cleanup + } +}; + +extern "C" const LADSPA_Descriptor *ladspa_descriptor (unsigned long i) +{ + if (i >= NMODS) return 0; + return moddescr + i; +} + +//----------------------------------------------------------------------------------- diff --git a/src/mvclpf24_lv2.cc b/src/mvclpf24_lv2.cc new file mode 100644 index 0000000..dbd8b51 --- /dev/null +++ b/src/mvclpf24_lv2.cc @@ -0,0 +1,136 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "mvclpf24.h" + +extern "C" { + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + ((LadspaPlugin*)instance)->setport(port, data); +} + +static void +activate(LV2_Handle instance) +{ + ((LadspaPlugin*)instance)->active(true); +} + +static void +run(LV2_Handle instance, uint32_t n_samples) +{ + ((LadspaPlugin*)instance)->runproc(n_samples, false); +} + +static void +deactivate(LV2_Handle instance) +{ + ((LadspaPlugin*)instance)->active(false); +} + +static void +cleanup(LV2_Handle instance) +{ + delete ((LadspaPlugin*)instance); +} + +static LV2_Handle +instantiate1(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Moogvcf1(rate); +} + +static LV2_Handle +instantiate2(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Moogvcf2(rate); +} +static LV2_Handle +instantiate3(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Moogvcf3(rate); +} +static LV2_Handle +instantiate4(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_Moogvcf4(rate); +} + +static const LV2_Descriptor descriptors[4] = { + { "http://drobilla.net/plugins/fomp/mvclpf1", + instantiate1, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/mvclpf2", + instantiate2, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/mvclpf3", + instantiate3, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL }, + { "http://drobilla.net/plugins/fomp/mvclpf4", + instantiate4, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL } +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + if (index < 4) { + return &descriptors[index]; + } + return NULL; +} + +} // extern "C" diff --git a/src/pareq.cc b/src/pareq.cc new file mode 100644 index 0000000..4feb991 --- /dev/null +++ b/src/pareq.cc @@ -0,0 +1,199 @@ +// ---------------------------------------------------------------------- +// +// Copyright (C) 2010-2013 Fons Adriaensen <fons@linuxaudio.org> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// ---------------------------------------------------------------------- + + +#include <math.h> +#include <string.h> +#include "pareq.h" + + +Pareq::Pareq (void) : + _touch0 (0), + _touch1 (0), + _state (BYPASS), + _g0 (1), + _g1 (1), + _f0 (1e3f), + _f1 (1e3f) +{ + setfsamp (0.0f); +} + + +Pareq::~Pareq (void) +{ +} + + +void Pareq::setfsamp (float fsamp) +{ + _fsamp = fsamp; + reset (); +} + + +void Pareq::reset (void) +{ + memset (_z1, 0, sizeof (float) * MAXCH); + memset (_z2, 0, sizeof (float) * MAXCH); +} + + +void Pareq::prepare (int nsamp) +{ + bool upd = false; + float g, f; + + if (_touch1 != _touch0) + { + if (_g0 < 0.1f) _g0 = 0.1f; + if (_g0 > 10.0f) _g0 = 10.0f; + if (_f0 < 20.0f) _f0 = 20.0f; + if (_f0 > 20e3f) _f0 = 20e3f; + g = _g0; + f = _f0; + if (g != _g1) + { + upd = true; + if (g > 2 * _g1) _g1 *= 2; + else if (_g1 > 2 * g) _g1 /= 2; + else _g1 = g; + } + if (f != _f1) + { + upd = true; + if (f > 2 * _f1) _f1 *= 2; + else if (_f1 > 2 * f) _f1 /= 2; + else _f1 = f; + } + if (upd) + { + if ((_state == BYPASS) && (_g1 == 1)) + { + calcpar1 (0, _g1, _f1); + } + else + { + _state = SMOOTH; + calcpar1 (nsamp, _g1, _f1); + } + } + else + { + _touch1 = _touch0; + if (fabs (_g1 - 1) < 0.001f) + { + _state = BYPASS; + reset (); + } + else + { + _state = STATIC; + } + } + } +} + + +void Pareq::calcpar1 (int nsamp, float g, float f) +{ + float b, c1, c2, gg; + + f *= float (M_PI) / _fsamp; + b = 2 * f / sqrtf (g); + gg = 0.5f * (g - 1); + c1 = -cosf (2 * f); + c2 = (1 - b) / (1 + b); + if (nsamp) + { + _dc1 = (c1 - _c1) / nsamp + 1e-30f; + _dc2 = (c2 - _c2) / nsamp + 1e-30f; + _dgg = (gg - _gg) / nsamp + 1e-30f; + } + else + { + _c1 = c1; + _c2 = c2; + _gg = gg; + } +} + + +void Pareq::process1 (int nsamp, int nchan, float *data[]) +{ + int i, j; + float c1, c2, gg; + float x, y, z1, z2; + float *p; + + c1 = _c1; + c2 = _c2; + gg = _gg; + if (_state == SMOOTH) + { + for (i = 0; i < nchan; i++) + { + p = data [i]; + z1 = _z1 [i]; + z2 = _z2 [i]; + c1 = _c1; + c2 = _c2; + gg = _gg; + for (j = 0; j < nsamp; j++) + { + c1 += _dc1; + c2 += _dc2; + gg += _dgg; + x = *p; + y = x - c2 * z2; + *p++ = x - gg * (z2 + c2 * y - x); + y -= c1 * z1; + z2 = z1 + c1 * y; + z1 = y + 1e-20f; + } + _z1 [i] = z1; + _z2 [i] = z2; + } + _c1 = c1; + _c2 = c2; + _gg = gg; + } + else + { + for (i = 0; i < nchan; i++) + { + p = data [i]; + z1 = _z1 [i]; + z2 = _z2 [i]; + for (j = 0; j < nsamp; j++) + { + x = *p; + y = x - c2 * z2; + *p++ = x - gg * (z2 + c2 * y - x); + y -= c1 * z1; + z2 = z1 + c1 * y; + z1 = y + 1e-20f; + } + _z1 [i] = z1; + _z2 [i] = z2; + } + } +} + diff --git a/src/pareq.h b/src/pareq.h new file mode 100644 index 0000000..b2448be --- /dev/null +++ b/src/pareq.h @@ -0,0 +1,74 @@ +// ---------------------------------------------------------------------- +// +// Copyright (C) 2010-2013 Fons Adriaensen <fons@linuxaudio.org> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// ---------------------------------------------------------------------- + + +#ifndef __PAREQ_H +#define __PAREQ_H + + +#include <stdint.h> +#include <math.h> + + +class Pareq +{ +public: + + Pareq (void); + ~Pareq (void); + + void setfsamp (float fsamp); + void setparam (float f, float g) + { + _f0 = f; + _g0 = powf (10.0f, 0.05f * g); + _touch0++; + } + void reset (void); + void prepare (int nsamp); + void process (int nsamp, int nchan, float *data[]) + { + if (_state != BYPASS) process1 (nsamp, nchan, data); + } + +private: + + enum { BYPASS, STATIC, SMOOTH, MAXCH = 4 }; + + void calcpar1 (int nsamp, float g, float f); + void process1 (int nsamp, int nchan, float *data[]); + + volatile int16_t _touch0; + volatile int16_t _touch1; + int _state; + float _fsamp; + + float _g0, _g1; + float _f0, _f1; + float _c1, _dc1; + float _c2, _dc2; + float _gg, _dgg; + + float _z1 [MAXCH]; + float _z2 [MAXCH]; +}; + + +#endif diff --git a/src/plugin_lv2.h b/src/plugin_lv2.h new file mode 100644 index 0000000..4014b59 --- /dev/null +++ b/src/plugin_lv2.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2012 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "ladspaplugin.h" + +extern "C" { + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + ((LadspaPlugin*)instance)->setport(port, data); +} + +static void +activate(LV2_Handle instance) +{ + ((LadspaPlugin*)instance)->active(true); +} + +static void +run(LV2_Handle instance, uint32_t n_samples) +{ + ((LadspaPlugin*)instance)->runproc(n_samples, false); +} + +static void +deactivate(LV2_Handle instance) +{ + ((LadspaPlugin*)instance)->active(false); +} + +static void +cleanup(LV2_Handle instance) +{ + delete ((LadspaPlugin*)instance); +} + +} // extern "C" diff --git a/src/reverbs.cc b/src/reverbs.cc new file mode 100644 index 0000000..9e8e5af --- /dev/null +++ b/src/reverbs.cc @@ -0,0 +1,125 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2003-2014 Fons Adriaensen <fons@linuxaudio.org> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// ----------------------------------------------------------------------- + + +#include <stdio.h> +#include <math.h> +#include "reverbs.h" + + +void Ladspa_zita_reverb::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_zita_reverb::active (bool act) +{ + if (! act) + { + _zreverb->reset (); + _nprep = 0; + } +} + + +void Ladspa_zita_reverb::runproc (SampleCount frames, bool add) +{ + unsigned long k; + float *inp [2] = { _port [A_INPL], _port [A_INPR] }; + float *out [2] = { _port [A_OUTL], _port [A_OUTR] }; + + _zreverb->set_delay (_port [C_DELAY][0]); + _zreverb->set_xover (_port [C_XOVER][0]); + _zreverb->set_rtlow (_port [C_RTLOW][0]); + _zreverb->set_rtmid (_port [C_RTMID][0]); + _zreverb->set_fdamp (_port [C_FDAMP][0]); + _zreverb->set_eq1 (_port [C_FREQ1][0], _port [C_GAIN1][0]); + _zreverb->set_eq2 (_port [C_FREQ2][0], _port [C_GAIN2][0]); + _zreverb->set_opmix (_port [C_OPMIX][0]); + while (frames) + { + if (!_nprep) + { + _zreverb->prepare (FRAGM); + _nprep = FRAGM; + } + k = (_nprep < frames) ? _nprep : frames; + _zreverb->process (k, inp, out); + inp [0] += k; + inp [1] += k; + out [0] += k; + out [1] += k; + frames -= k; + _nprep -= k; + } +} + + + +void Ladspa_zita_reverb_amb::setport (PortIndex port, PortData *data) +{ + _port [port] = (float*)data; +} + + +void Ladspa_zita_reverb_amb::active (bool act) +{ + if (! act) + { + _zreverb->reset (); + _nprep = 0; + } +} + + +void Ladspa_zita_reverb_amb::runproc (SampleCount frames, bool add) +{ + unsigned long k; + float *inp [2] = { _port [A_INPL], _port [A_INPR] }; + float *out [4] = { _port [A_OUTW], _port [A_OUTX], _port [A_OUTY], _port [A_OUTZ] }; + + _zreverb->set_delay (_port [C_DELAY][0]); + _zreverb->set_xover (_port [C_XOVER][0]); + _zreverb->set_rtlow (_port [C_RTLOW][0]); + _zreverb->set_rtmid (_port [C_RTMID][0]); + _zreverb->set_fdamp (_port [C_FDAMP][0]); + _zreverb->set_eq1 (_port [C_FREQ1][0], _port [C_GAIN1][0]); + _zreverb->set_eq2 (_port [C_FREQ2][0], _port [C_GAIN2][0]); + _zreverb->set_rgxyz (_port [C_RGXYZ][0]); + while (frames) + { + if (!_nprep) + { + _zreverb->prepare (FRAGM); + _nprep = FRAGM; + } + k = (_nprep < frames) ? _nprep : frames; + _zreverb->process (k, inp, out); + inp [0] += k; + inp [1] += k; + out [0] += k; + out [1] += k; + out [2] += k; + out [3] += k; + frames -= k; + _nprep -= k; + } +} diff --git a/src/reverbs.h b/src/reverbs.h new file mode 100644 index 0000000..2650856 --- /dev/null +++ b/src/reverbs.h @@ -0,0 +1,134 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2003-2014 Fons Adriaensen <fons@linuxaudio.org> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// ----------------------------------------------------------------------- + + +#ifndef __REVERBS_H +#define __REVERBS_H + +#include "ladspaplugin.h" +#include "zreverb.h" + + +// ----------------------------------------------------------------------- + + +class Ladspa_zita_reverb : public LadspaPlugin +{ +public: + + enum + { + A_INPL, + A_INPR, + A_OUTL, + A_OUTR, + C_DELAY, + C_XOVER, + C_RTLOW, + C_RTMID, + C_FDAMP, + C_FREQ1, + C_GAIN1, + C_FREQ2, + C_GAIN2, + C_OPMIX, + NPORT + }; + + Ladspa_zita_reverb (SampleRate fsam) : LadspaPlugin (fsam) + { + _zreverb = new Zreverb (); + _zreverb->init (fsam, false); + _nprep = 0; + } + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_zita_reverb (void) + { + delete _zreverb; + } + +private: + + enum { FRAGM = 2048 }; + + float *_port [NPORT]; + Zreverb *_zreverb; + unsigned long _nprep; +}; + + +// ----------------------------------------------------------------------- + + +class Ladspa_zita_reverb_amb : public LadspaPlugin +{ +public: + + enum + { + A_INPL, + A_INPR, + A_OUTW, + A_OUTX, + A_OUTY, + A_OUTZ, + C_DELAY, + C_XOVER, + C_RTLOW, + C_RTMID, + C_FDAMP, + C_FREQ1, + C_GAIN1, + C_FREQ2, + C_GAIN2, + C_RGXYZ, + NPORT + }; + + Ladspa_zita_reverb_amb (unsigned long fsam) : LadspaPlugin (fsam) + { + _zreverb = new Zreverb (); + _zreverb->init (fsam, true); + _nprep = 0; + } + virtual void setport (PortIndex port, PortData *data); + virtual void active (bool act); + virtual void runproc (SampleCount len, bool add); + virtual ~Ladspa_zita_reverb_amb (void) + { + delete _zreverb; + } + +private: + + enum { FRAGM = 2048 }; + + float *_port [NPORT]; + Zreverb *_zreverb; + unsigned long _nprep; +}; + + +// ----------------------------------------------------------------------- + + +#endif diff --git a/src/reverbs_lv2.cc b/src/reverbs_lv2.cc new file mode 100644 index 0000000..e6eb9f0 --- /dev/null +++ b/src/reverbs_lv2.cc @@ -0,0 +1,73 @@ +/* + Copyright (C) 2014 David Robillard <d@drobilla.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stddef.h> + +#include "reverbs.h" +#include "plugin_lv2.h" + +extern "C" { + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_zita_reverb(rate); +} + +static LV2_Handle +instantiate_amb(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + return new Ladspa_zita_reverb_amb(rate); +} + +static const LV2_Descriptor descriptors[] = { + { + "http://drobilla.net/plugins/fomp/reverb", + instantiate, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL + } , { + "http://drobilla.net/plugins/fomp/reverb_amb", + instantiate_amb, + connect_port, + activate, + run, + deactivate, + cleanup, + NULL + } +}; + +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + return (index < 2) ? &descriptors[index] : NULL; +} + +} // extern "C" diff --git a/src/zreverb.cc b/src/zreverb.cc new file mode 100644 index 0000000..98055a2 --- /dev/null +++ b/src/zreverb.cc @@ -0,0 +1,425 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2003-2013 Fons Adriaensen <fons@linuxaudio.org> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// ----------------------------------------------------------------------- + + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "zreverb.h" + + +// ----------------------------------------------------------------------- + + +Diff1::Diff1 (void) : + _size (0), + _line (0) +{ +} + + +Diff1::~Diff1 (void) +{ + fini (); +} + + +void Diff1::init (int size, float c) +{ + _size = size; + _line = new float [size]; + _c = c; + reset (); +} + + +void Diff1::fini (void) +{ + delete[] _line; + _size = 0; + _line = 0; +} + + +void Diff1::reset (void) +{ + memset (_line, 0, _size * sizeof (float)); + _i = 0; +} + + +// ----------------------------------------------------------------------- + + +Delay::Delay (void) : + _size (0), + _line (0) +{ +} + + +Delay::~Delay (void) +{ + fini (); +} + + +void Delay::init (int size) +{ + _size = size; + _line = new float [size]; + reset (); +} + + +void Delay::fini (void) +{ + delete[] _line; + _size = 0; + _line = 0; +} + + +void Delay::reset (void) +{ + memset (_line, 0, _size * sizeof (float)); + _i = 0; +} + + +// ----------------------------------------------------------------------- + + +Vdelay::Vdelay (void) : + _size (0), + _line (0) +{ +} + + +Vdelay::~Vdelay (void) +{ + fini (); +} + + +void Vdelay::init (int size) +{ + _size = size; + _line = new float [size]; + reset (); +} + + +void Vdelay::fini (void) +{ + delete[] _line; + _size = 0; + _line = 0; +} + + +void Vdelay::reset (void) +{ + memset (_line, 0, _size * sizeof (float)); + _iwr = 0; + _ir0 = 0; + _ir1 = 0; +} + + +void Vdelay::set_delay (int del) +{ + _ir1 = _iwr - del; + if (_ir1 < 0) _ir1 += _size; +} + + +// ----------------------------------------------------------------------- + + +void Filt1::set_params (float del, float tmf, float tlo, float wlo, float thi, float chi) +{ + float g, t; + + _gmf = powf (0.001f, del / tmf); + _glo = powf (0.001f, del / tlo) / _gmf - 1.0f; + _wlo = wlo; + g = powf (0.001f, del / thi) / _gmf; + t = (1 - g * g) / (2 * g * g * chi); + _whi = (sqrtf (1 + 4 * t) - 1) / (2 * t); +} + + +// ----------------------------------------------------------------------- + + +float Zreverb::_tdiff1 [8] = +{ + 20346e-6f, + 24421e-6f, + 31604e-6f, + 27333e-6f, + 22904e-6f, + 29291e-6f, + 13458e-6f, + 19123e-6f +}; + + +float Zreverb::_tdelay [8] = +{ + 153129e-6f, + 210389e-6f, + 127837e-6f, + 256891e-6f, + 174713e-6f, + 192303e-6f, + 125000e-6f, + 219991e-6f +}; + + +Zreverb::Zreverb (void) +{ +} + + +Zreverb::~Zreverb (void) +{ + fini (); +} + + +void Zreverb::init (float fsamp, bool ambis) +{ + int i, k1, k2; + + _fsamp = fsamp; + _ambis = ambis; + _cntA1 = 1; + _cntA2 = 0; + _cntB1 = 1; + _cntB2 = 0; + _cntC1 = 1; + _cntC2 = 0; + + _ipdel = 0.04f; + _xover = 200.0f; + _rtlow = 3.0f; + _rtmid = 2.0f; + _fdamp = 3e3f; + _opmix = 1.0f; + _rgxyz = 0.0f; + + _g0 = _d0 = 0; + _g1 = _d1 = 0; + + _vdelay0.init ((int)(0.1f * _fsamp)); + _vdelay1.init ((int)(0.1f * _fsamp)); + for (i = 0; i < 8; i++) + { + k1 = (int)(floorf (_tdiff1 [i] * _fsamp + 0.5f)); + k2 = (int)(floorf (_tdelay [i] * _fsamp + 0.5f)); + _diff1 [i].init (k1, (i & 1) ? -0.6f : 0.6f); + _delay [i].init (k2 - k1); + } + + _pareq1.setfsamp (fsamp); + _pareq2.setfsamp (fsamp); +} + + +void Zreverb::fini (void) +{ +} + + +void Zreverb::reset (void) +{ + int i; + + _vdelay0.reset (); + _vdelay1.reset (); + for (i = 0; i < 8; i++) + { + _diff1 [i].reset (); + _filt1 [i].reset (); + _delay [i].reset (); + } +} + + +void Zreverb::prepare (int nfram) +{ + int a, b, c, i, k; + float t0, t1, wlo, chi; + + a = _cntA1; + b = _cntB1; + c = _cntC1; + _d0 = _d1 = 0; + + if (a != _cntA2) + { + if (_ipdel < 0.02f) _ipdel = 0.02f; + if (_ipdel > 0.10f) _ipdel = 0.10f; + k = (int)(floorf ((_ipdel - 0.02f) * _fsamp + 0.5f)); + _vdelay0.set_delay (k); + _vdelay1.set_delay (k); + _cntA2 = a; + } + + if (b != _cntB2) + { + if (_xover < 50.0f) _xover = 50.0f; + if (_xover > 1.0e3f) _xover = 1.0e3f; + if (_rtlow < 1.0f) _rtlow = 1.0f; + if (_rtlow > 8.0f) _rtlow = 8.0f; + if (_rtmid < 1.0f) _rtmid = 1.0f; + if (_rtmid > 8.0f) _rtmid = 8.0f; + if (_fdamp < 1.5e3f) _fdamp = 1.5e3f; + if (_fdamp > 24.0e3f) _fdamp = 24.0e3f; + wlo = 6.2832f * _xover / _fsamp; + if (_fdamp > 0.49f * _fsamp) chi = 2; + else chi = 1 - cosf (6.2832f * _fdamp / _fsamp); + for (i = 0; i < 8; i++) + { + _filt1 [i].set_params (_tdelay [i], _rtmid, _rtlow, wlo, 0.5f * _rtmid, chi); + } + _cntB2 = b; + } + + if (c != _cntC2) + { + if (_rtmid < 1.0f) _rtmid = 1.0f; + if (_rtmid > 8.0f) _rtmid = 8.0f; + if (_ambis) + { + if (_rgxyz < -9.0f) _rgxyz = -9.0f; + if (_rgxyz > 9.0f) _rgxyz = 9.0f; + t0 = 1.0f / sqrtf (_rtmid); + t1 = t0 * powf (10.0f, 0.05f * _rgxyz); + } + else + { + if (_opmix < 0.0f) _opmix = 0.0f; + if (_opmix > 1.0f) _opmix = 1.0f; + t0 = (1 - _opmix) * (1 + _opmix); + t1 = 0.7f * _opmix * (2 - _opmix) / sqrtf (_rtmid); + } + _d0 = (t0 - _g0) / nfram; + _d1 = (t1 - _g1) / nfram; + _cntC2 = c; + } + + _pareq1.prepare (nfram); + _pareq2.prepare (nfram); +} + + +void Zreverb::process (int nfram, float *inp [], float *out []) +{ + int i, n; + float *p0, *p1; + float *q0, *q1, *q2, *q3; + float t, g, x0, x1, x2, x3, x4, x5, x6, x7; + + g = sqrtf (0.125f); + + p0 = inp [0]; + p1 = inp [1]; + q0 = out [0]; + q1 = out [1]; + q2 = out [2]; + q3 = out [3]; + + for (i = 0; i < nfram; i++) + { + _vdelay0.write (p0 [i]); + _vdelay1.write (p1 [i]); + + t = 0.3f * _vdelay0.read1 (); + x0 = _diff1 [0].process (_delay [0].read () + t); + x1 = _diff1 [1].process (_delay [1].read () + t); + x2 = _diff1 [2].process (_delay [2].read () - t); + x3 = _diff1 [3].process (_delay [3].read () - t); + t = 0.3f * _vdelay1.read1 (); + x4 = _diff1 [4].process (_delay [4].read () + t); + x5 = _diff1 [5].process (_delay [5].read () + t); + x6 = _diff1 [6].process (_delay [6].read () - t); + x7 = _diff1 [7].process (_delay [7].read () - t); + + t = x0 - x1; x0 += x1; x1 = t; + t = x2 - x3; x2 += x3; x3 = t; + t = x4 - x5; x4 += x5; x5 = t; + t = x6 - x7; x6 += x7; x7 = t; + t = x0 - x2; x0 += x2; x2 = t; + t = x1 - x3; x1 += x3; x3 = t; + t = x4 - x6; x4 += x6; x6 = t; + t = x5 - x7; x5 += x7; x7 = t; + t = x0 - x4; x0 += x4; x4 = t; + t = x1 - x5; x1 += x5; x5 = t; + t = x2 - x6; x2 += x6; x6 = t; + t = x3 - x7; x3 += x7; x7 = t; + + if (_ambis) + { + _g0 += _d0; + _g1 += _d1; + q0 [i] = _g0 * x0; + q1 [i] = _g1 * x1; + q2 [i] = _g1 * x4; + q3 [i] = _g1 * x2; + } + else + { + _g1 += _d1; + q0 [i] = _g1 * (x1 + x2); + q1 [i] = _g1 * (x1 - x2); + } + + _delay [0].write (_filt1 [0].process (g * x0)); + _delay [1].write (_filt1 [1].process (g * x1)); + _delay [2].write (_filt1 [2].process (g * x2)); + _delay [3].write (_filt1 [3].process (g * x3)); + _delay [4].write (_filt1 [4].process (g * x4)); + _delay [5].write (_filt1 [5].process (g * x5)); + _delay [6].write (_filt1 [6].process (g * x6)); + _delay [7].write (_filt1 [7].process (g * x7)); + } + + n = _ambis ? 4 : 2; + _pareq1.process (nfram, n, out); + _pareq2.process (nfram, n, out); + if (!_ambis) + { + for (i = 0; i < nfram; i++) + { + _g0 += _d0; + q0 [i] += _g0 * _vdelay0.read0 (); + q1 [i] += _g0 * _vdelay1.read0 (); + } + } +} + + +// ----------------------------------------------------------------------- + diff --git a/src/zreverb.h b/src/zreverb.h new file mode 100644 index 0000000..2f9b905 --- /dev/null +++ b/src/zreverb.h @@ -0,0 +1,244 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2003-2013 Fons Adriaensen <fons@linuxaudio.org> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// ----------------------------------------------------------------------- + + +#ifndef __ZREVERB_H +#define __ZREVERB_H + +#include "pareq.h" + + +// ----------------------------------------------------------------------- + + +class Diff1 +{ +private: + + friend class Zreverb; + + Diff1 (void); + ~Diff1 (void); + + void init (int size, float c); + void fini (void); + void reset (void); + + float process (float x) + { + float z = _line [_i]; + x -= _c * z; + _line [_i] = x; + if (++_i == _size) _i = 0; + return z + _c * x; + } + + int _i; + float _c; + int _size; + float *_line; +}; + + +// ----------------------------------------------------------------------- + + +class Filt1 +{ +private: + + friend class Zreverb; + + Filt1 (void) : _slo (0), _shi (0) {} + ~Filt1 (void) {} + + void set_params (float del, float tmf, float tlo, float wlo, float thi, float chi); + + float process (float x) + { + _slo += _wlo * (x - _slo) + 1e-10f; + x += _glo * _slo; + _shi += _whi * (x - _shi); + return _gmf * _shi; + } + + void reset (void) + { + _slo = 0; + _shi = 0; + } + + float _gmf; + float _glo; + float _wlo; + float _whi; + float _slo; + float _shi; +}; + + + + +// ----------------------------------------------------------------------- + + +class Delay +{ +private: + + friend class Zreverb; + + Delay (void); + ~Delay (void); + + void init (int size); + void fini (void); + void reset (void); + + float read (void) + { + return _line [_i]; + } + + void write (float x) + { + _line [_i++] = x; + if (_i == _size) _i = 0; + } + + int _i; + int _size; + float *_line; +}; + + +// ----------------------------------------------------------------------- + + +class Vdelay +{ +private: + + friend class Zreverb; + + Vdelay (void); + ~Vdelay (void); + + void init (int size); + void fini (void); + void reset (void); + void set_delay (int del); + + void write (float x) + { + _line [_iwr++] = x; + if (_iwr == _size) _iwr = 0; + } + + float read0 (void) + { + float x = _line [_ir0++]; + if (_ir0 == _size) _ir0 = 0; + return x; + } + + float read1 (void) + { + float x = _line [_ir1++]; + if (_ir1 == _size) _ir1 = 0; + return x; + } + + int _iwr; + int _ir0; + int _ir1; + int _size; + float *_line; +}; + + +// ----------------------------------------------------------------------- + + +class Zreverb +{ +public: + + Zreverb (void); + ~Zreverb (void); + + void init (float fsamp, bool ambis); + void fini (void); + + void reset (void); + void prepare (int n); + void process (int n, float *inp [], float *out []); + + void set_delay (float v) { _ipdel = v; _cntA1++; } + void set_xover (float v) { _xover = v; _cntB1++; } + void set_rtlow (float v) { _rtlow = v; _cntB1++; } + void set_rtmid (float v) { _rtmid = v; _cntB1++; _cntC1++; } + void set_fdamp (float v) { _fdamp = v; _cntB1++; } + void set_opmix (float v) { _opmix = v; _cntC1++; } + void set_rgxyz (float v) { _rgxyz = v; _cntC1++; } + void set_eq1 (float f, float g) { _pareq1.setparam (f, g); } + void set_eq2 (float f, float g) { _pareq2.setparam (f, g); } + +private: + + + float _fsamp; + bool _ambis; + + Vdelay _vdelay0; + Vdelay _vdelay1; + Diff1 _diff1 [8]; + Filt1 _filt1 [8]; + Delay _delay [8]; + + volatile int _cntA1; + volatile int _cntB1; + volatile int _cntC1; + int _cntA2; + int _cntB2; + int _cntC2; + float _ipdel; + float _xover; + float _rtlow; + float _rtmid; + float _fdamp; + float _opmix; + float _rgxyz; + + float _g0, _d0; + float _g1, _d1; + + Pareq _pareq1; + Pareq _pareq2; + + static float _tdiff1 [8]; + static float _tdelay [8]; +}; + + +// ----------------------------------------------------------------------- + + +#endif |