diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-12-08 22:26:17 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-12-08 22:26:17 +0900 |
commit | fce86b22a2367f1be1f9aae5e1ba3d18d1371b74 (patch) | |
tree | 707fe84fef0569a152e632ce1e16407f9d19a3d2 /arts/modules/synth/synth_std_equalizer_impl.cpp | |
parent | 41fa1afc2c571b909acd0312e4eebb4a0b21e3c2 (diff) | |
download | tdemultimedia-fce86b22a2367f1be1f9aae5e1ba3d18d1371b74.tar.gz tdemultimedia-fce86b22a2367f1be1f9aae5e1ba3d18d1371b74.zip |
Renaming of files in preparation for code style tools.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'arts/modules/synth/synth_std_equalizer_impl.cpp')
-rw-r--r-- | arts/modules/synth/synth_std_equalizer_impl.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/arts/modules/synth/synth_std_equalizer_impl.cpp b/arts/modules/synth/synth_std_equalizer_impl.cpp new file mode 100644 index 00000000..be88a708 --- /dev/null +++ b/arts/modules/synth/synth_std_equalizer_impl.cpp @@ -0,0 +1,207 @@ +/* + + Copyright (C) 2000 Jeff Tranter + tranter@pobox.com + + (C) 1999 Stefan Westerfeld + stefan@space.twc.de + + (C) 1999 Martin Lorenz + lorenz@ch.tum.de + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#include <math.h> +#include "artsmodulessynth.h" +#include "stdsynthmodule.h" + +using namespace Arts; + +class Synth_STD_EQUALIZER_impl : virtual public Synth_STD_EQUALIZER_skel, + virtual public StdSynthModule +{ +protected: + float _low, _mid, _high, _frequency, _q; + float tlow, tmid, thigh, tfrequency; + float a1, a2, b0, b1, b2, x_0, x_1, x_2, y_1, y_2; + unsigned long all; + +public: + float low() { return _low; } + void low(float newLow) + { + if(newLow != _low) + { + _low = newLow; + calcParameters(); + high_changed(newLow); + } + } + + + float mid() { return _mid; } + void mid(float newMid) + { + if(newMid != _mid) + { + _mid = newMid; + calcParameters(); + mid_changed(newMid); + } + } + + float high() { return _high; } + void high(float newHigh) + { + if(newHigh != _high) + { + _high = newHigh; + calcParameters(); + high_changed(newHigh); + } + } + + + float frequency() { return _frequency; } + void frequency(float newFrequency) + { + if(newFrequency != _frequency) + { + _frequency = newFrequency; + calcParameters(); + frequency_changed(newFrequency); + } + } + + float q() { return _q; } + void q(float newQ) + { + if(newQ != _q) + { + _q = newQ; + calcParameters(); + q_changed(newQ); + } + } + + Synth_STD_EQUALIZER_impl() { + _low = _mid = _high = 0; _q = 0.5; + _frequency = 300; + } + + void calcParameters() + { + /* + + * _low, _mid, _high are in dB, transform them to tlow, tmid, + * thigh using: + * -6dB => 0.5 ; 0dB => 1 ; 6dB = 2.0 ; ... + */ + + tlow = exp(_low * 0.115524530093324); // exp(p[LOW]*ln(2)/6) + tmid = exp(_mid * 0.115524530093324); + thigh = exp(_high * 0.115524530093324); + + // _frequency is given in Hz, we need the w-value (and do clipping if + // it exceeds SR/2) + const float SAMPLING_RATE = 44100.0; + tfrequency = _frequency; + if (tfrequency > SAMPLING_RATE / 2.01) + tfrequency = SAMPLING_RATE / 2.01; + float w = 2 * M_PI * tfrequency / SAMPLING_RATE; + + // Calculations: + float t = 1/tan(w/2); + float tq = t/_q; + float t2 = t*t; + + float a0 = 1+tq+t2; + float a0r = 1/a0; + + // and now the real filter values: + a1 = (2 - 2 * t2) * a0r; + a2 = (1 - tq + t2) * a0r; + b0 = (tlow + tmid * tq + thigh * t2) * a0r; + b1 = (2 * tlow -2 * thigh * t2) * a0r; + b2 = (tlow - tmid * tq + thigh * t2) * a0r; + + // TODO: try if we need that here, or if we can change filter + // coefficients without setting the state to 0 + x_0 = x_1 = x_2 = y_1 = y_2 = 0.0; + all = 0; + } + + void streamInit() + { + calcParameters(); + } + + void calculateBlock(unsigned long samples) + { + all += samples; + + if (all > 1024) + { + /* The _problem_: (observed on a PII-350) + * + * I am not quite sure what happens here, but it seems to be like that: + * + * If an ordinary signal (a mp3 for instance) is sent through the + * equalizer, and then no more input is given (zeros as input), + * the y_1 and y_2 values oscillate for some time, coming closer and + * close to zero. + * + * But before the reach zero, they reach the smallest negative number + * (or smallest positive, or whatever), and stay there + * (because 0.005*smallest_negative will remain smallest_negative). + * + * Since then, the CPU usage for all operations on these floats + * increases, (since handling of smallest_negative seems to be a rare + * case). + * + * The _fix_: + * + * We observe the value of y_1. If it's very close to zero (may be as + * well smallest_positive/smallest_negative), we set it to zero, + * together with y_2. This shouldn't significantly influence + * correctness of the filter, but effectively solves the problem. + * + * If you don't believe me, try without this fix and tell me what + * happens on your computer. + */ + const float zero_lower =-0.00000001; + const float zero_upper = 0.00000001; + all = 0; + + if(zero_lower < y_1 && y_1 < zero_upper) + y_1 = y_2 = 0.0; + } + + unsigned long i; + float tmp; + for (i=0; i<samples; i++) + { + x_0 = invalue[i]; + tmp = x_0 * b0 + x_1 * b1 + x_2 * b2 - y_1 * a1 - y_2 * a2; + x_2 = x_1; x_1 = x_0; y_2 = y_1; y_1 = tmp; + outvalue[i] = tmp; + } + } + +}; + +REGISTER_IMPLEMENTATION(Synth_STD_EQUALIZER_impl); |