// ----------------------------------------------------------------------- // // Copyright (C) 2003-2013 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 #include #include #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 (); } } } // -----------------------------------------------------------------------