diff options
author | David Robillard <d@drobilla.net> | 2014-05-05 09:46:40 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2014-05-05 09:46:40 +0000 |
commit | b519cf2151fa3cff0a40646248c855f74c6b7baa (patch) | |
tree | 6cb62cce4ec82b7415d9eab1859253f2aa24d5ad | |
parent | ecc24d68b726c5822f009b8efd09c69c0d3305eb (diff) | |
download | fomp.lv2-b519cf2151fa3cff0a40646248c855f74c6b7baa.tar.gz fomp.lv2-b519cf2151fa3cff0a40646248c855f74c6b7baa.tar.bz2 fomp.lv2-b519cf2151fa3cff0a40646248c855f74c6b7baa.zip |
Add Zita reverb (stereo and ambisonic variant).
git-svn-id: http://svn.drobilla.net/lad/trunk/plugins/fomp.lv2@5395 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | fomp.lv2/autowah.ttl | 1 | ||||
-rw-r--r-- | fomp.lv2/manifest.ttl.in | 10 | ||||
-rw-r--r-- | fomp.lv2/parametric1.ttl | 1 | ||||
-rw-r--r-- | fomp.lv2/reverb.ttl | 136 | ||||
-rw-r--r-- | fomp.lv2/reverb_amb.ttl | 148 | ||||
-rw-r--r-- | src/pareq.cc | 199 | ||||
-rw-r--r-- | src/pareq.h | 75 | ||||
-rw-r--r-- | src/reverbs.cc | 125 | ||||
-rw-r--r-- | src/reverbs.h | 134 | ||||
-rw-r--r-- | src/reverbs_lv2.cc | 73 | ||||
-rw-r--r-- | src/zreverb.cc | 425 | ||||
-rw-r--r-- | src/zreverb.h | 244 | ||||
-rw-r--r-- | wscript | 5 |
14 files changed, 1578 insertions, 1 deletions
@@ -1,8 +1,9 @@ fomp (1.0.1) unstable; * Fix phaser plugin data and list phasers in manifest + * Add reverb and reverb_amb - -- David Robillard <d@drobilla.net> Thu, 20 Dec 2012 02:01:30 -0500 + -- David Robillard <d@drobilla.net> Mon, 05 May 2014 11:42:01 +0200 fomp (1.0.0) stable; diff --git a/fomp.lv2/autowah.ttl b/fomp.lv2/autowah.ttl index ec99fb3..9deede6 100644 --- a/fomp.lv2/autowah.ttl +++ b/fomp.lv2/autowah.ttl @@ -13,6 +13,7 @@ lv2:microVersion 0 ; lv2:minorVersion 0 ; lv2:optionalFeature lv2:hardRTCapable ; + lv2:project fomp: ; lv2:port [ a lv2:AudioPort , lv2:InputPort ; diff --git a/fomp.lv2/manifest.ttl.in b/fomp.lv2/manifest.ttl.in index 191a5a3..fa8730e 100644 --- a/fomp.lv2/manifest.ttl.in +++ b/fomp.lv2/manifest.ttl.in @@ -98,3 +98,13 @@ fomp:autowah a lv2:Plugin ; rdfs:seeAlso <autowah.ttl> ; lv2:binary <autowah@LIB_EXT@> . + +fomp:reverb + a lv2:Plugin ; + rdfs:seeAlso <reverb.ttl> ; + lv2:binary <reverbs@LIB_EXT@> . + +fomp:reverb_amb + a lv2:Plugin ; + rdfs:seeAlso <reverb_amb.ttl> ; + lv2:binary <reverbs@LIB_EXT@> . diff --git a/fomp.lv2/parametric1.ttl b/fomp.lv2/parametric1.ttl index 8118107..545c03d 100644 --- a/fomp.lv2/parametric1.ttl +++ b/fomp.lv2/parametric1.ttl @@ -11,6 +11,7 @@ fomp:parametric1 lv2:microVersion 0 ; lv2:minorVersion 0 ; lv2:optionalFeature lv2:hardRTCapable ; + lv2:project fomp: ; lv2:port [ a lv2:AudioPort , lv2:InputPort ; diff --git a/fomp.lv2/reverb.ttl b/fomp.lv2/reverb.ttl new file mode 100644 index 0000000..2824056 --- /dev/null +++ b/fomp.lv2/reverb.ttl @@ -0,0 +1,136 @@ +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + +fomp:reverb + a lv2:Plugin , + lv2:ReverbPlugin ; + doap:name "reverb" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:requiredFeature lv2:isLive ; + lv2:project fomp: ; + lv2:port [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "In L" ; + lv2:symbol "in_l" + ] , [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "In R" ; + lv2:symbol "in_r" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 2 ; + lv2:name "Out L" ; + lv2:symbol "out_l" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 3 ; + lv2:name "Out R" ; + lv2:symbol "out_r" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0.06 ; + lv2:index 4 ; + lv2:maximum 0.1 ; + lv2:minimum 0.02 ; + lv2:name "Delay" ; + lv2:symbol "delay" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 223.607 ; + lv2:index 5 ; + lv2:maximum 1000 ; + lv2:minimum 50 ; + lv2:name "Xover" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "xover" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 2.75 ; + lv2:index 6 ; + lv2:maximum 8 ; + lv2:minimum 1 ; + lv2:name "RT-low" ; + lv2:symbol "rt_low" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 2.75 ; + lv2:index 7 ; + lv2:maximum 8 ; + lv2:minimum 1 ; + lv2:name "RT-mid" ; + lv2:symbol "rt_mid" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 6000 ; + lv2:index 8 ; + lv2:maximum 24000 ; + lv2:minimum 1500 ; + lv2:name "Damping" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "damping" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 159.054 ; + lv2:index 9 ; + lv2:maximum 10000 ; + lv2:minimum 40 ; + lv2:name "F1-freq" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "f1_freq" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 10 ; + lv2:maximum 20 ; + lv2:minimum -20 ; + lv2:name "F1-gain" ; + lv2:symbol "f1_gain" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 2514.87 ; + lv2:index 11 ; + lv2:maximum 10000 ; + lv2:minimum 40 ; + lv2:name "F2-freq" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "f2_freq" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 12 ; + lv2:maximum 20 ; + lv2:minimum -20 ; + lv2:name "F2-gain" ; + lv2:symbol "f2_gain" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0.5 ; + lv2:index 13 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Output mix" ; + lv2:symbol "out_mix" + ] . diff --git a/fomp.lv2/reverb_amb.ttl b/fomp.lv2/reverb_amb.ttl new file mode 100644 index 0000000..0cbb562 --- /dev/null +++ b/fomp.lv2/reverb_amb.ttl @@ -0,0 +1,148 @@ +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + +fomp:reverb_amb + a lv2:Plugin , + lv2:ReverbPlugin ; + doap:name "reverb-amb" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:requiredFeature lv2:isLive ; + lv2:project fomp: ; + lv2:port [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "In L" ; + lv2:symbol "in_l" + ] , [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "In R" ; + lv2:symbol "in_r" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 2 ; + lv2:name "Out W" ; + lv2:symbol "out_w" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 3 ; + lv2:name "Out X" ; + lv2:symbol "out_x" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 4 ; + lv2:name "Out Y" ; + lv2:symbol "out_y" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 5 ; + lv2:name "Out Z" ; + lv2:symbol "out_z" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0.06 ; + lv2:index 6 ; + lv2:maximum 0.1 ; + lv2:minimum 0.02 ; + lv2:name "Delay" ; + lv2:symbol "delay" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 223.607 ; + lv2:index 7 ; + lv2:maximum 1000 ; + lv2:minimum 50 ; + lv2:name "Xover" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "xover" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 2.75 ; + lv2:index 8 ; + lv2:maximum 8 ; + lv2:minimum 1 ; + lv2:name "RT-low" ; + lv2:symbol "rt_low" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 2.75 ; + lv2:index 9 ; + lv2:maximum 8 ; + lv2:minimum 1 ; + lv2:name "RT-mid" ; + lv2:symbol "rt_mid" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 6000 ; + lv2:index 10 ; + lv2:maximum 24000 ; + lv2:minimum 1500 ; + lv2:name "Damping" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "damping" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 159.054 ; + lv2:index 11 ; + lv2:maximum 10000 ; + lv2:minimum 40 ; + lv2:name "F1-freq" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "fw_freq" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 12 ; + lv2:maximum 20 ; + lv2:minimum -20 ; + lv2:name "F1-gain" ; + lv2:symbol "fw_gain" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 2514.87 ; + lv2:index 13 ; + lv2:maximum 10000 ; + lv2:minimum 40 ; + lv2:name "F2-freq" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ; + lv2:symbol "f2_freq" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 14 ; + lv2:maximum 20 ; + lv2:minimum -20 ; + lv2:name "F2-gain" ; + lv2:symbol "f2_gain" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 15 ; + lv2:maximum 9 ; + lv2:minimum -9 ; + lv2:name "XYZ gain" ; + lv2:symbol "xyz_gain" + ] . 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..85ea7f9 --- /dev/null +++ b/src/pareq.h @@ -0,0 +1,75 @@ +// ---------------------------------------------------------------------- +// +// 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; + bool _bypass; + 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/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 @@ -81,3 +81,8 @@ def build(bld): build_plugin(bld, 'cxx', 'fomp.lv2', i, ['src/%s.cc' % i, 'src/%s_lv2.cc' % i]) + build_plugin(bld, 'cxx', 'fomp.lv2', 'reverbs', + ['src/reverbs.cc', + 'src/pareq.cc', + 'src/zreverb.cc', + 'src/reverbs_lv2.cc']) |