commit 44511fa374847cabbc238b8a7bbc0179719020ad
parent 5c3b6e6e097b18c033f36331bb85f3188a2baffa
Author: Jonathan Moore Liles <j.liles@unix.net>
Date: Tue, 15 Dec 2020 19:09:16 -0800
Revert "Revert "SVFilter: Use Value_Smoothing_Filter to smooth cutoff frequency changes.""
This reverts commit 36d9fbdc9c2c4806b7fd8a48b966bdcfce878c04.
The reason it didn't work the first time was accidentally passing buffer size where sample rate was intended.
Diffstat:
2 files changed, 30 insertions(+), 69 deletions(-)
diff --git a/src/DSP/SVFilter.cpp b/src/DSP/SVFilter.cpp
@@ -26,12 +26,6 @@
namespace zyn {
-enum FilterInterpolationType {
- INTERPOLATE_EXTREME = 0x01,
- INTERPOLATE_NON_ZERO,
- INTERPOLATE_NONE
-};
-
SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq,
unsigned char Fstages, unsigned int srate, int bufsize)
:Filter(srate, bufsize),
@@ -39,15 +33,15 @@ SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq,
stages(Fstages),
freq(Ffreq),
q(Fq),
- gain(1.0f),
- needsinterpolation(INTERPOLATE_NONE),
- firsttime(true)
+ gain(1.0f)
{
if(stages >= MAX_FILTER_STAGES)
stages = MAX_FILTER_STAGES;
outgain = 1.0f;
cleanup();
setfreq_and_q(Ffreq, Fq);
+ freq_smoothing.reset(Ffreq);
+ freq_smoothing.sample_rate(srate);
}
SVFilter::~SVFilter()
@@ -57,8 +51,6 @@ void SVFilter::cleanup()
{
for(int i = 0; i < MAX_FILTER_STAGES + 1; ++i)
st[i].low = st[i].high = st[i].band = st[i].notch = 0.0f;
- oldabovenq = false;
- abovenq = false;
}
SVFilter::response::response(float b0, float b1, float b2,
@@ -127,26 +119,8 @@ void SVFilter::setfreq(float frequency)
if(rap < 1.0f)
rap = 1.0f / rap;
- oldabovenq = abovenq;
- abovenq = frequency > (samplerate_f / 2 - 500.0f);
-
- bool nyquistthresh = (abovenq ^ oldabovenq);
-
- //if the frequency is changed fast, it needs interpolation
- if((rap > 3.0f) || nyquistthresh) { //(now, filter and coefficients backup)
- if(!firsttime)
- needsinterpolation = INTERPOLATE_EXTREME;
- ipar = par;
- } else if(rap != 1.0) {
- if (!firsttime)
- needsinterpolation = INTERPOLATE_NON_ZERO;
- ipar = par;
- } else {
- needsinterpolation = INTERPOLATE_NONE;
- }
freq = frequency;
computefiltercoefs();
- firsttime = false;
}
void SVFilter::setfreq_and_q(float frequency, float q_)
@@ -204,21 +178,6 @@ float *SVFilter::getfilteroutfortype(SVFilter::fstage &x) {
return out;
}
-void SVFilter::singlefilterout_with_par_interpolation(float *smp, fstage &x, parameters &par1, parameters &par2)
-{
- float *out = getfilteroutfortype(x);
- for(int i = 0; i < buffersize; ++i) {
- float p = i / buffersize_f;
- float f = par1.f + (par2.f - par1.f) * p;
- float q = par1.q + (par2.q - par1.q) * p;
- float q_sqrt = sqrtf(q);
- x.low = x.low + f * x.band;
- x.high = q_sqrt * smp[i] - x.low - q * x.band;
- x.band = f * x.high + x.band;
- x.notch = x.high + x.low;
- smp[i] = *out;
- }
-}
// simplifying the responses
// xl = xl*z(-1) + pf*xb*z(-1)
@@ -232,7 +191,7 @@ void SVFilter::singlefilterout_with_par_interpolation(float *smp, fstage &x, par
-void SVFilter::singlefilterout(float *smp, SVFilter::fstage &x, SVFilter::parameters &par)
+void SVFilter::singlefilterout(float *smp, SVFilter::fstage &x, SVFilter::parameters &par, int buffersize )
{
float *out = getfilteroutfortype(x);
for(int i = 0; i < buffersize; ++i) {
@@ -246,24 +205,28 @@ void SVFilter::singlefilterout(float *smp, SVFilter::fstage &x, SVFilter::parame
void SVFilter::filterout(float *smp)
{
- if (needsinterpolation == INTERPOLATE_EXTREME) {
- float ismp[buffersize];
- for(int i = 0; i < stages + 1; ++i)
- singlefilterout(smp, st[i], par);
- memcpy(ismp, smp, bufferbytes);
- for(int i = 0; i < stages + 1; ++i)
- singlefilterout(ismp, st[i], ipar);
- for(int i = 0; i < buffersize; ++i) {
- float x = i / buffersize_f;
- smp[i] = ismp[i] * (1.0f - x) + smp[i] * x;
- }
- } else if (needsinterpolation == INTERPOLATE_NON_ZERO) {
- for(int i = 0; i < stages + 1; ++i)
- singlefilterout_with_par_interpolation(smp, st[i], ipar, par);
- } else {
- for(int i = 0; i < stages + 1; ++i)
- singlefilterout(smp, st[i], par);
+ assert((buffersize % 8) == 0);
+
+ float freqbuf[buffersize];
+
+ if ( freq_smoothing.apply( freqbuf, buffersize, freq ) )
+ {
+ /* 8 sample chunks seems to work OK for AnalogFilter, so do that here too. */
+ for ( int i = 0; i < buffersize; i += 8 )
+ {
+ freq = freqbuf[i];
+ computefiltercoefs();
+
+ for(int j = 0; j < stages + 1; ++j)
+ singlefilterout(smp + i, st[j], par, 8 );
+ }
+
+ freq = freqbuf[buffersize - 1];
+ computefiltercoefs();
}
+ else
+ for(int i = 0; i < stages + 1; ++i)
+ singlefilterout(smp, st[i], par, buffersize );
for(int i = 0; i < buffersize; ++i)
smp[i] *= outgain;
diff --git a/src/DSP/SVFilter.h b/src/DSP/SVFilter.h
@@ -16,6 +16,7 @@
#include "../globals.h"
#include "Filter.h"
+#include "Value_Smoothing_Filter.h"
namespace zyn {
@@ -57,19 +58,16 @@ class SVFilter:public Filter
} par, ipar;
float *getfilteroutfortype(SVFilter::fstage &x);
- void singlefilterout(float *smp, fstage &x, parameters &par);
- void singlefilterout_with_par_interpolation(float *smp, fstage &x, parameters &par1, parameters &par2);
- void computefiltercoefs(void);
+ void singlefilterout(float *smp, fstage &x, parameters &par, int buffersize );
+
+ void computefiltercoefs(void);
int type; // The type of the filter (LPF1,HPF1,LPF2,HPF2...)
int stages; // how many times the filter is applied (0->1,1->2,etc.)
float freq; // Frequency given in Hz
float q; // Q factor (resonance or Q factor)
float gain; // the gain of the filter (if are shelf/peak) filters
- bool abovenq, //if the frequency is above the nyquist
- oldabovenq;
- int needsinterpolation;
- bool firsttime;
+ Value_Smoothing_Filter freq_smoothing;
};
}