BogaudioModules

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

commit 8ebc14df5044e2320340912fc9a86115bb49f7cf
parent 34eacdfdaf8349db5c5ec56877f931739cfe9717
Author: Matt Demanett <matt@demanett.net>
Date:   Tue, 23 Jun 2020 23:21:57 -0400

Refactor MultimodeFilter interfaces; speed up FFB and PEQ*.

Diffstat:
Msrc/FFB.hpp | 4++--
Msrc/LVCF.hpp | 4++--
Msrc/VCF.hpp | 4++--
Msrc/dsp/filters/filter.hpp | 13++++++++-----
Msrc/dsp/filters/multimode.cpp | 35++++++++++++++++++++++++++++++++++-
Msrc/dsp/filters/multimode.hpp | 119+++++++++++++++++++++++++++++++++++--------------------------------------------
Msrc/parametric_eq.cpp | 4++--
Msrc/parametric_eq.hpp | 10++++++++--
8 files changed, 110 insertions(+), 83 deletions(-)

diff --git a/src/FFB.hpp b/src/FFB.hpp @@ -47,9 +47,9 @@ struct FFB : BGModule { }; struct Engine { - MultimodeFilter _lowPass; + MultimodeFilter8 _lowPass; FourPoleButtworthBandpassFilter _bandPasses[12]; - MultimodeFilter _highPass; + MultimodeFilter8 _highPass; Amplifier _amplifiers[14]; bogaudio::dsp::SlewLimiter _slews[14]; diff --git a/src/LVCF.hpp b/src/LVCF.hpp @@ -38,10 +38,10 @@ struct LVCF : BGModule { }; struct Engine { - MultimodeFilter _filter; + MultimodeFilter16 _filter; float _sampleRate; bogaudio::dsp::SlewLimiter _frequencySL; - MultimodeFilter _finalHP; + MultimodeFilter4 _finalHP; Engine() { sampleRateChange(); diff --git a/src/VCF.hpp b/src/VCF.hpp @@ -40,12 +40,12 @@ struct VCF : BGModule { static constexpr int maxPoles = 12; static constexpr int minPoles = 1; static constexpr int nFilters = maxPoles; - MultimodeFilter _filters[nFilters]; + MultimodeFilter16 _filters[nFilters]; float _gains[nFilters] {}; bogaudio::dsp::SlewLimiter _gainSLs[nFilters]; float _sampleRate; bogaudio::dsp::SlewLimiter _frequencySL; - MultimodeFilter _finalHP; + MultimodeFilter4 _finalHP; Engine() { sampleRateChange(); diff --git a/src/dsp/filters/filter.hpp b/src/dsp/filters/filter.hpp @@ -7,14 +7,17 @@ namespace bogaudio { namespace dsp { struct Filter { - Filter() {} virtual ~Filter() {} virtual float next(float sample) = 0; }; +struct ResetableFilter : Filter { + virtual void reset() = 0; +}; + template<typename T> -struct BiquadFilter : Filter { +struct BiquadFilter : ResetableFilter { T _a0 = 0.0; T _a1 = 0.0; T _a2 = 0.0; @@ -33,7 +36,7 @@ struct BiquadFilter : Filter { _b2 = b2 * ib0; } - void reset() { + void reset() override { _x[0] = _x[1] = _x[2] = 0.0; _y[0] = _y[1] = _y[2] = 0.0; } @@ -55,7 +58,7 @@ struct BiquadFilter : Filter { } }; -struct LowPassFilter : Filter { +struct LowPassFilter : ResetableFilter { float _sampleRate = 0.0f; float _cutoff = 0.0f; float _q = 0.0f; @@ -67,7 +70,7 @@ struct LowPassFilter : Filter { } void setParams(float sampleRate, float cutoff, float q = 0.001f); - void reset() { _biquad.reset(); } + void reset() override { _biquad.reset(); } float next(float sample) override { return _biquad.next(sample); } diff --git a/src/dsp/filters/multimode.cpp b/src/dsp/filters/multimode.cpp @@ -68,6 +68,36 @@ template<> float BiquadBank<MultimodeTypes::T, 4>::next(float sample) { return _biquads->next(sample); } + +template<> void BiquadBank<MultimodeTypes::T, 8>::setParams(int i, MultimodeTypes::T a0, MultimodeTypes::T a1, MultimodeTypes::T a2, MultimodeTypes::T b0, MultimodeTypes::T b1, MultimodeTypes::T b2) { + assert(i >= 0 && i < 8); + _biquads[i / 4].setParams(i % 4, a0, a1, a2, b0, b1, b2); +} + +template<> void BiquadBank<MultimodeTypes::T, 8>::reset() { + _biquads[0].reset(); + _biquads[1].reset(); +} + +template<> void BiquadBank<MultimodeTypes::T, 8>::setN(int n, bool minDelay) { + assert(n > 0 && n <= 8); + 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 < 2; ++i) { + _biquads[i].disable(4 * i >= n); + } +} + +template<> float BiquadBank<MultimodeTypes::T, 8>::next(float sample) { + sample = _biquads[0].next(sample); + return _biquads[1].next(sample); +} + + template<> void BiquadBank<MultimodeTypes::T, 16>::setParams(int i, MultimodeTypes::T a0, MultimodeTypes::T a1, MultimodeTypes::T a2, MultimodeTypes::T b0, MultimodeTypes::T b1, MultimodeTypes::T b2) { assert(i >= 0 && i < 16); _biquads[i / 4].setParams(i % 4, a0, a1, a2, b0, b1, b2); @@ -131,6 +161,7 @@ template<typename T, int N> float BiquadBank<T, N>::next(float sample) { #endif template struct BiquadBank<MultimodeTypes::T, 4>; +template struct BiquadBank<MultimodeTypes::T, 8>; template struct BiquadBank<MultimodeTypes::T, 16>; @@ -440,10 +471,11 @@ template<int N> void MultimodeDesigner<N>::setParams( } template struct MultimodeDesigner<4>; +template struct MultimodeDesigner<8>; template struct MultimodeDesigner<16>; -template<int N> void MultimodeBase<N>::design( +template<int N> void MultimodeBase<N>::setParams( float sampleRate, Type type, int poles, @@ -476,6 +508,7 @@ template<int N> void MultimodeBase<N>::reset() { } template struct MultimodeBase<4>; +template struct MultimodeBase<8>; template struct MultimodeBase<16>; } // namespace dsp diff --git a/src/dsp/filters/multimode.hpp b/src/dsp/filters/multimode.hpp @@ -33,7 +33,7 @@ namespace dsp { #endif template<typename T, int N> -struct BiquadBank : Filter { +struct BiquadBank : ResetableFilter { #ifdef RACK_SIMD Biquad4 _biquads[N / 4]; #else @@ -42,7 +42,7 @@ struct BiquadBank : Filter { #endif void setParams(int i, T a0, T a1, T a2, T b0, T b1, T b2); - void reset(); + void reset() override; void setN(int n, bool minDelay = false); float next(float sample) override; }; @@ -138,13 +138,8 @@ struct MultimodeDesigner : MultimodeTypes { ); }; -template<int N> -struct MultimodeBase : MultimodeTypes, Filter { - MultimodeDesigner<N> _designer; - BiquadBank<T, N> _biquads; - float _outGain = 1.0f; - - void design( +struct MultimodeFilter : MultimodeTypes, ResetableFilter { + virtual void setParams( float sampleRate, Type type, int poles, @@ -153,37 +148,16 @@ struct MultimodeBase : MultimodeTypes, Filter { float qbw, BandwidthMode bwm = PITCH_BANDWIDTH_MODE, DelayMode dm = FIXED_DELAY_MODE - ); - float next(float sample) override; - void reset(); + ) = 0; }; -struct MultimodeFilter : MultimodeBase<16> { - inline void setParams( - float sampleRate, - Type type, - int poles, - Mode mode, - float frequency, - float qbw, - BandwidthMode bwm = PITCH_BANDWIDTH_MODE, - DelayMode dm = FIXED_DELAY_MODE - ) { - design( - sampleRate, - type, - poles, - mode, - frequency, - qbw, - bwm, - dm - ); - } -}; +template<int N> +struct MultimodeBase : MultimodeFilter { + MultimodeDesigner<N> _designer; + BiquadBank<T, N> _biquads; + float _outGain = 1.0f; -struct FourPoleMultimodeFilter : MultimodeBase<4> { - inline void setParams( + void setParams( float sampleRate, Type type, int poles, @@ -192,90 +166,101 @@ struct FourPoleMultimodeFilter : MultimodeBase<4> { float qbw, BandwidthMode bwm = PITCH_BANDWIDTH_MODE, DelayMode dm = FIXED_DELAY_MODE - ) { - design( - sampleRate, - type, - poles, - mode, - frequency, - qbw, - bwm, - dm - ); - } + ) override; + float next(float sample) override; + void reset() override; }; -struct FourPoleButtworthLowpassFilter : MultimodeBase<4> { +typedef MultimodeBase<16> MultimodeFilter16; +typedef MultimodeBase<8> MultimodeFilter8; +typedef MultimodeBase<4> MultimodeFilter4; + +struct FourPoleButtworthLowpassFilter { + MultimodeFilter4 _filter; + inline void setParams( float sampleRate, float frequency, float q ) { - design( + _filter.setParams( sampleRate, - BUTTERWORTH_TYPE, + MultimodeFilter::BUTTERWORTH_TYPE, 4, - LOWPASS_MODE, + MultimodeFilter::LOWPASS_MODE, frequency, q ); } + inline float next(float sample) { return _filter.next(sample); } + inline void reset() { _filter.reset(); } }; -struct FourPoleButtworthHighpassFilter : MultimodeBase<4> { +struct FourPoleButtworthHighpassFilter { + MultimodeFilter4 _filter; + inline void setParams( float sampleRate, float frequency, float q ) { - design( + _filter.setParams( sampleRate, - BUTTERWORTH_TYPE, + MultimodeFilter::BUTTERWORTH_TYPE, 4, - HIGHPASS_MODE, + MultimodeFilter::HIGHPASS_MODE, frequency, q ); } + inline float next(float sample) { return _filter.next(sample); } + inline void reset() { _filter.reset(); } }; -struct TwoPoleButtworthBandpassFilter : MultimodeBase<4> { +struct TwoPoleButtworthBandpassFilter { + MultimodeFilter4 _filter; + inline void setParams( float sampleRate, float frequency, float bw, - BandwidthMode bwm = PITCH_BANDWIDTH_MODE + MultimodeFilter::BandwidthMode bwm = MultimodeFilter::PITCH_BANDWIDTH_MODE ) { - design( + _filter.setParams( sampleRate, - BUTTERWORTH_TYPE, + MultimodeFilter::BUTTERWORTH_TYPE, 2, - BANDPASS_MODE, + MultimodeFilter::BANDPASS_MODE, frequency, bw, bwm ); } + inline float next(float sample) { return _filter.next(sample); } + inline void reset() { _filter.reset(); } }; -struct FourPoleButtworthBandpassFilter : MultimodeBase<4> { +struct FourPoleButtworthBandpassFilter { + MultimodeFilter4 _filter; + inline void setParams( float sampleRate, float frequency, float bw, - BandwidthMode bwm = PITCH_BANDWIDTH_MODE + MultimodeFilter::BandwidthMode bwm = MultimodeFilter::PITCH_BANDWIDTH_MODE ) { - design( + _filter.setParams( sampleRate, - BUTTERWORTH_TYPE, + MultimodeFilter::BUTTERWORTH_TYPE, 4, - BANDPASS_MODE, + MultimodeFilter::BANDPASS_MODE, frequency, bw, bwm ); } + inline float next(float sample) { return _filter.next(sample); } + inline void reset() { _filter.reset(); } }; } // namespace dsp diff --git a/src/parametric_eq.cpp b/src/parametric_eq.cpp @@ -67,7 +67,7 @@ void PEQChannel::modulate() { } bw = MultimodeFilter::minQbw + bw * (MultimodeFilter::maxQbw - MultimodeFilter::minQbw); } - _filter.setParams( + _filter->setParams( _sampleRate, MultimodeFilter::BUTTERWORTH_TYPE, _poles, @@ -79,7 +79,7 @@ void PEQChannel::modulate() { } void PEQChannel::next(float sample) { - out = _amplifier.next(_filter.next(sample)); + out = _amplifier.next(_filter->next(sample)); rms = _rms.next(out / 5.0f); } diff --git a/src/parametric_eq.hpp b/src/parametric_eq.hpp @@ -19,7 +19,7 @@ struct PEQChannel { float _sampleRate; Amplifier _amplifier; bogaudio::dsp::SlewLimiter _levelSL; - MultimodeFilter _filter; + MultimodeFilter* _filter = NULL; bogaudio::dsp::SlewLimiter _frequencySL; bogaudio::dsp::SlewLimiter _bandwidthSL; RootMeanSquare _rms; @@ -42,6 +42,7 @@ struct PEQChannel { float rms = 0.0f; PEQChannel( + MultimodeFilter* filter, int polyChannel, Param& levelParam, Param& frequencyParam, @@ -54,7 +55,8 @@ struct PEQChannel { Input* bandwidthCvInput, float sampleRate = 1000.0f ) - : _c(polyChannel) + : _filter(filter) + , _c(polyChannel) , _levelParam(levelParam) , _frequencyParam(frequencyParam) , _frequencyCv1Param(frequencyCv1Param) @@ -69,6 +71,9 @@ struct PEQChannel { setFilterMode(MultimodeFilter::BANDPASS_MODE); _rms.setSensitivity(0.05f); } + virtual ~PEQChannel() { + delete _filter; + } void setSampleRate(float sampleRate); void setFilterMode(MultimodeFilter::Mode mode); @@ -106,6 +111,7 @@ struct PEQEngine { Input* bandwidthCvInput ) { _channels[i] = new PEQChannel( + i == 0 || i == _n - 1 ? (MultimodeFilter*)(new MultimodeFilter8()) : (MultimodeFilter*)(new MultimodeFilter4()), polyChannel, levelParam, frequencyParam,