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:
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
);
}
};