BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

commit 4f7beafcd3a4065179b88f5138b0a3716832a98d
parent 710c3b78bbc1cd49e0cd19149e28b512c8538c2f
Author: Matt Demanett <matt@demanett.net>
Date:   Tue,  9 Jun 2020 23:39:22 -0400

Bug fixes in Multimode filter; fix (L)VCF to not add sample delay due to their internal serial fixed highpass filters.

Diffstat:
Msrc/LVCF.cpp | 2+-
Msrc/VCF.cpp | 2+-
Msrc/dsp/filters/multimode.cpp | 47+++++++++++++++++++++++++++--------------------
Msrc/dsp/filters/multimode.hpp | 24++++++++++++++++++------
4 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/src/LVCF.cpp b/src/LVCF.cpp @@ -30,7 +30,7 @@ void LVCF::Engine::setParams( void LVCF::Engine::sampleRateChange(int modulationSteps) { _sampleRate = APP->engine->getSampleRate(); _frequencySL.setParams(_sampleRate, 100.0f / (float)modulationSteps, frequencyToSemitone(maxFrequency - minFrequency)); - _finalHP.setParams(_sampleRate, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw); + _finalHP.setParams(_sampleRate, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw, MultimodeFilter::LINEAR_BANDWIDTH_MODE, MultimodeFilter::MINIMUM_DELAY_MODE); } void LVCF::Engine::reset() { diff --git a/src/VCF.cpp b/src/VCF.cpp @@ -52,7 +52,7 @@ void VCF::Engine::setParams( void VCF::Engine::sampleRateChange(int modulationSteps) { _sampleRate = APP->engine->getSampleRate(); _frequencySL.setParams(_sampleRate, 100.0f / (float)modulationSteps, frequencyToSemitone(maxFrequency - minFrequency)); - _finalHP.setParams(_sampleRate, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw); + _finalHP.setParams(_sampleRate, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw, MultimodeFilter::LINEAR_BANDWIDTH_MODE, MultimodeFilter::MINIMUM_DELAY_MODE); for (int i = 0; i < nFilters; ++i) { _gainSLs[i].setParams(_sampleRate, 50.0f, 1.0f); } diff --git a/src/dsp/filters/multimode.cpp b/src/dsp/filters/multimode.cpp @@ -26,11 +26,12 @@ void Biquad4::reset() { _y[0] = _y[1] = _y[2] = 0.0; } -void Biquad4::setN(int n) { - assert(n <= 4); - for (; n < 4; ++n) { - setParams(n, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); +void Biquad4::setN(int n, bool minDelay) { + assert(n > 0 && n <= 4); + for (int i = n; i < 4; ++i) { + setParams(i, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); } + _outputIndex = minDelay ? n - 1 : 3; } float Biquad4::next(float sample) { @@ -47,7 +48,7 @@ float Biquad4::next(float sample) { _y[2] = _y[1]; _y[1] = _y[0]; _y[0] = ((_a0 * _x[0]) + (_a1 * _x[1]) + (_a2 * _x[2])) - ((_b1 * _y[1]) + (_b2 * _y[2])); - return _y[0][3]; + return _y[0][_outputIndex]; } template<> void BiquadBank<MultimodeTypes::T, 4>::setParams(int i, MultimodeTypes::T a0, MultimodeTypes::T a1, MultimodeTypes::T a2, MultimodeTypes::T b0, MultimodeTypes::T b1, MultimodeTypes::T b2) { @@ -59,10 +60,8 @@ template<> void BiquadBank<MultimodeTypes::T, 4>::reset() { _biquads->reset(); } -template<> void BiquadBank<MultimodeTypes::T, 4>::setN(int n) { - for (; n < 4; ++n) { - _biquads->setParams(n, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); - } +template<> void BiquadBank<MultimodeTypes::T, 4>::setN(int n, bool minDelay) { + _biquads->setN(n, minDelay); } template<> float BiquadBank<MultimodeTypes::T, 4>::next(float sample) { @@ -81,12 +80,16 @@ template<> void BiquadBank<MultimodeTypes::T, 16>::reset() { _biquads[3].reset(); } -template<> void BiquadBank<MultimodeTypes::T, 16>::setN(int n) { - for (int i = n, nn = n + (4 - n % 4); i < nn; ++i) { - _biquads[i / 4].setParams(i % 4, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); +template<> void BiquadBank<MultimodeTypes::T, 16>::setN(int n, bool minDelay) { + assert(n > 0 && n <= 16); + for (int i = 0, nn = n / 4; i < nn; ++i) { + _biquads[i].setN(4, false); + } + if (n % 4 != 0) { + _biquads[n / 4].setN(n % 4, minDelay); } for (int i = 0; i < 4; ++i) { - _biquads[i].disable(4 * i > n); + _biquads[i].disable(4 * i >= n); } } @@ -110,7 +113,7 @@ template<typename T, int N> void BiquadBank<T, N>::reset() { } } -template<typename T, int N> void BiquadBank<T, N>::setN(int n) { +template<typename T, int N> void BiquadBank<T, N>::setN(int n, bool _minDelay) { assert(n <= N); _n = n; for (; n < N; ++n) { @@ -153,7 +156,8 @@ template<int N> void MultimodeDesigner<N>::setParams( Mode mode, float frequency, float qbw, - BandwidthMode bwm + BandwidthMode bwm, + DelayMode dm ) { assert(N >= minPoles && N <= maxPoles); assert(poles >= minPoles && poles <= N); @@ -162,7 +166,7 @@ template<int N> void MultimodeDesigner<N>::setParams( assert(qbw >= minQbw && qbw <= maxQbw); bool repole = _type != type || _mode != mode || _nPoles != poles || (type == CHEBYSHEV_TYPE && (mode == LOWPASS_MODE || mode == HIGHPASS_MODE) && _qbw != qbw); - bool redesign = repole || _frequency != frequency || _qbw != qbw || _sampleRate != sampleRate || _bandwidthMode != bwm; + bool redesign = repole || _frequency != frequency || _qbw != qbw || _sampleRate != sampleRate || _bandwidthMode != bwm || _delayMode != dm; _sampleRate = sampleRate; _half2PiST = M_PI * (1.0f / sampleRate); _type = type; @@ -171,6 +175,7 @@ template<int N> void MultimodeDesigner<N>::setParams( _frequency = frequency; _qbw = qbw; _bandwidthMode = bwm; + _delayMode = dm; if (repole) { switch (_type) { @@ -224,7 +229,7 @@ template<int N> void MultimodeDesigner<N>::setParams( case LOWPASS_MODE: case HIGHPASS_MODE: { _nBiquads = _nPoles / 2 + _nPoles % 2; - biquads.setN(_nBiquads); + biquads.setN(_nBiquads, _delayMode == MINIMUM_DELAY_MODE); // T iq = (1.0 / std::sqrt(2.0)) - 0.65 * _qbw; T iq = (T)0.8 - (T)0.6 * _qbw; @@ -284,7 +289,7 @@ template<int N> void MultimodeDesigner<N>::setParams( case BANDPASS_MODE: case BANDREJECT_MODE: { _nBiquads = ((_nPoles / 2) * 2) + (_nPoles % 2); - biquads.setN(_nBiquads); + biquads.setN(_nBiquads, _delayMode == MINIMUM_DELAY_MODE); T wdl = 0.0; T wdh = 0.0; @@ -445,7 +450,8 @@ template<int N> void MultimodeBase<N>::design( Mode mode, float frequency, float qbw, - BandwidthMode bwm + BandwidthMode bwm, + DelayMode dm ) { _designer.setParams( _biquads, @@ -456,7 +462,8 @@ template<int N> void MultimodeBase<N>::design( mode, frequency, qbw, - bwm + bwm, + dm ); } diff --git a/src/dsp/filters/multimode.hpp b/src/dsp/filters/multimode.hpp @@ -22,10 +22,11 @@ namespace dsp { float_4 _x[3] {}; float_4 _y[3] {}; bool _disable = false; + int _outputIndex = 3; void setParams(int i, float a0, float a1, float a2, float b0, float b1, float b2); void reset(); - void setN(int n); + void setN(int n, bool minDelay = false); inline void disable(bool disable) { _disable = disable; } float next(float sample); }; @@ -42,7 +43,7 @@ struct BiquadBank : Filter { void setParams(int i, T a0, T a1, T a2, T b0, T b1, T b2); void reset(); - void setN(int n); + void setN(int n, bool minDelay = false); float next(float sample) override; }; @@ -70,6 +71,12 @@ struct MultimodeTypes { PITCH_BANDWIDTH_MODE }; + enum DelayMode { + UNKNOWN_DELAY_MODE, + FIXED_DELAY_MODE, + MINIMUM_DELAY_MODE + }; + static constexpr int minPoles = 1; static constexpr int maxPoles = 16; static constexpr int modPoles = 1; @@ -113,6 +120,7 @@ struct MultimodeDesigner : MultimodeTypes { float _frequency = -1.0f; float _qbw = -1.0f; BandwidthMode _bandwidthMode = UNKNOWN_BANDWIDTH_MODE; + DelayMode _delayMode = UNKNOWN_DELAY_MODE; Pole _poles[maxPoles / 2]; int _nBiquads = 0; @@ -125,7 +133,8 @@ struct MultimodeDesigner : MultimodeTypes { Mode mode, float frequency, float qbw, - BandwidthMode bwm = PITCH_BANDWIDTH_MODE + BandwidthMode bwm = PITCH_BANDWIDTH_MODE, + DelayMode dm = FIXED_DELAY_MODE ); }; @@ -142,7 +151,8 @@ struct MultimodeBase : MultimodeTypes, Filter { Mode mode, float frequency, float qbw, - BandwidthMode bwm = PITCH_BANDWIDTH_MODE + BandwidthMode bwm = PITCH_BANDWIDTH_MODE, + DelayMode dm = FIXED_DELAY_MODE ); float next(float sample) override; void reset(); @@ -156,7 +166,8 @@ struct MultimodeFilter : MultimodeBase<16> { Mode mode, float frequency, float qbw, - BandwidthMode bwm = PITCH_BANDWIDTH_MODE + BandwidthMode bwm = PITCH_BANDWIDTH_MODE, + DelayMode dm = FIXED_DELAY_MODE ) { design( sampleRate, @@ -165,7 +176,8 @@ struct MultimodeFilter : MultimodeBase<16> { mode, frequency, qbw, - bwm + bwm, + dm ); } };