aboutsummaryrefslogtreecommitdiffstats
path: root/src/pareq.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/pareq.cc')
-rw-r--r--src/pareq.cc199
1 files changed, 199 insertions, 0 deletions
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;
+ }
+ }
+}
+