commit 11a8031753a4743f3a1e5a7510e6d7f79407f696
parent 9fd44013b620e423ce80beec2a3e7f6f0ec6f33f
Author: friedolino78 <34608315+friedolino78@users.noreply.github.com>
Date: Thu, 16 Sep 2021 22:09:47 +0200
fix of the AnalogFilter Punch (#136)
* fix of the AnalogFilter Punch
Co-authored-by: Friedolino <mkirchn@freenet.de>
Diffstat:
8 files changed, 57 insertions(+), 97 deletions(-)
diff --git a/src/DSP/AnalogFilter.cpp b/src/DSP/AnalogFilter.cpp
@@ -22,7 +22,6 @@
const float MAX_FREQ = 20000.0f;
-const float MAX_FREQ_CO = 1.0f / MAX_FREQ;
namespace zyn {
@@ -37,7 +36,8 @@ AnalogFilter::AnalogFilter(unsigned char Ftype,
freq(Ffreq),
q(Fq),
gain(1.0),
- recompute(true)
+ recompute(true),
+ freqbufsize(bufsize/8)
{
for(int i = 0; i < 3; ++i)
coeff.c[i] = coeff.d[i] = oldCoeff.c[i] = oldCoeff.d[i] = 0.0f;
@@ -47,8 +47,9 @@ AnalogFilter::AnalogFilter(unsigned char Ftype,
setfreq_and_q(Ffreq, Fq);
coeff.d[0] = 0; //this is not used
outgain = 1.0f;
- freq_smoothing.sample_rate(samplerate_f);
- freq_smoothing.reset( freq * MAX_FREQ_CO );
+ freq_smoothing.sample_rate(samplerate_f/8);
+ freq_smoothing.thresh(2.0f); // 2Hz
+ beforeFirstTick=true;
}
AnalogFilter::~AnalogFilter()
@@ -291,6 +292,11 @@ void AnalogFilter::setfreq(float frequency)
freq = frequency;
recompute = true;
}
+
+ if (beforeFirstTick) {
+ freq_smoothing.reset( freq );
+ beforeFirstTick=false;
+ }
}
void AnalogFilter::setfreq_and_q(float frequency, float q_)
@@ -350,18 +356,18 @@ inline void AnalogBiquadFilterB(const float coeff[5], float &src, float work[4])
src = work[2];
}
-void AnalogFilter::singlefilterout(float *smp, fstage &hist)
+void AnalogFilter::singlefilterout(float *smp, fstage &hist, float f, unsigned int bufsize)
{
assert((buffersize % 8) == 0);
if ( recompute )
{
- computefiltercoefs(freq,q);
+ computefiltercoefs(f,q);
recompute = false;
}
if(order == 1) { //First order filter
- for(int i = 0; i < buffersize; ++i) {
+ for(unsigned int i = 0; i < bufsize; ++i) {
float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1]
+ hist.y1 * coeff.d[1];
hist.y1 = y0;
@@ -371,7 +377,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist)
} else if(order == 2) {//Second order filter
const float coeff_[5] = {coeff.c[0], coeff.c[1], coeff.c[2], coeff.d[1], coeff.d[2]};
float work[4] = {hist.x1, hist.x2, hist.y1, hist.y2};
- for(int i = 0; i < buffersize; i+=8) {
+ for(unsigned int i = 0; i < bufsize; i+=8) {
AnalogBiquadFilterA(coeff_, smp[i + 0], work);
AnalogBiquadFilterB(coeff_, smp[i + 1], work);
AnalogBiquadFilterA(coeff_, smp[i + 2], work);
@@ -388,74 +394,25 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist)
}
}
-void AnalogFilter::singlefilterout_freqbuf(float *smp, fstage &hist,
- float *freqbuf)
-{
- assert((buffersize % 8) == 0);
-
- float frequency = -1.0f;
-
- for ( int i = 0; i < buffersize; i += 8 )
- {
- /* recompute coeffs for each 8 samples */
-
- const float f = ceilf(freqbuf[i] * MAX_FREQ);
-
- if ( fabsf( f - frequency ) >= 1.0f )
- {
- /* don't perform computation more often than necessary */
- computefiltercoefs(f,q);
- frequency = f;
- }
-
- if(order == 1) { //First order filter
- for ( int j = 0; j < 8; j++ )
- {
- float y0 = smp[i+j] * coeff.c[0] + hist.x1 * coeff.c[1]
- + hist.y1 * coeff.d[1];
- hist.y1 = y0;
- hist.x1 = smp[i+j];
- smp[i+j] = y0;
- }
- } else if(order == 2) {//Second order filter
-
- const float coeff_[5] = {coeff.c[0], coeff.c[1], coeff.c[2], coeff.d[1], coeff.d[2]};
- float work[4] = {hist.x1, hist.x2, hist.y1, hist.y2};
-
- AnalogBiquadFilterA(coeff_, smp[i + 0], work);
- AnalogBiquadFilterB(coeff_, smp[i + 1], work);
- AnalogBiquadFilterA(coeff_, smp[i + 2], work);
- AnalogBiquadFilterB(coeff_, smp[i + 3], work);
- AnalogBiquadFilterA(coeff_, smp[i + 4], work);
- AnalogBiquadFilterB(coeff_, smp[i + 5], work);
- AnalogBiquadFilterA(coeff_, smp[i + 6], work);
- AnalogBiquadFilterB(coeff_, smp[i + 7], work);
-
- hist.x1 = work[0];
- hist.x2 = work[1];
- hist.y1 = work[2];
- hist.y2 = work[3];
- }
- }
-
- recompute = true;
-}
-
void AnalogFilter::filterout(float *smp)
{
- float freqbuf[buffersize];
+ float freqbuf[freqbufsize];
- if ( freq_smoothing.apply( freqbuf, buffersize, freq * MAX_FREQ_CO ) )
+ if ( freq_smoothing.apply( freqbuf, freqbufsize, freq ) )
{
/* in transition, need to do fine grained interpolation */
for(int i = 0; i < stages + 1; ++i)
- singlefilterout_freqbuf(smp, history[i], freqbuf);
+ for(int j = 0; j < freqbufsize; ++j)
+ {
+ recompute = true;
+ singlefilterout(&smp[j*8], history[i], freqbuf[j], 8);
+ }
}
else
{
/* stable state, just use one coeff */
for(int i = 0; i < stages + 1; ++i)
- singlefilterout(smp, history[i]);
+ singlefilterout(smp, history[i], freq, buffersize);
}
for(int i = 0; i < buffersize; ++i)
diff --git a/src/DSP/AnalogFilter.h b/src/DSP/AnalogFilter.h
@@ -61,8 +61,7 @@ class AnalogFilter:public Filter
//old coeffs are used for interpolation when parameters change quickly
//Apply IIR filter to Samples, with coefficients, and past history
- void singlefilterout(float *smp, fstage &hist);// const Coeff &coeff);
- void singlefilterout_freqbuf(float *smp, fstage &hist, float *freqbuf);
+ void singlefilterout(float *smp, fstage &hist, float f, unsigned int bufsize);// const Coeff &coeff);
//Update coeff and order
void computefiltercoefs(float freq, float q);
@@ -74,7 +73,9 @@ class AnalogFilter:public Filter
bool recompute; // need to recompute coeff.
int order; //the order of the filter (number of poles)
+ int freqbufsize;
Value_Smoothing_Filter freq_smoothing; /* for smoothing freq modulations to avoid zipper effect */
+ bool beforeFirstTick; // reset the smoothing at first Tick
};
}
diff --git a/src/DSP/Value_Smoothing_Filter.cpp b/src/DSP/Value_Smoothing_Filter.cpp
@@ -64,7 +64,7 @@ Value_Smoothing_Filter::apply( sample_t * __restrict__ dst, nframes_t nframes, f
g2 += 1e-10f; /* denormal protection */
- if ( fabsf( gt - g2 ) < 0.0001f )
+ if ( fabsf( gt - g2 ) < t )
g2 = gt;
this->g1 = g1;
diff --git a/src/DSP/Value_Smoothing_Filter.h b/src/DSP/Value_Smoothing_Filter.h
@@ -25,7 +25,7 @@ typedef float sample_t;
class Value_Smoothing_Filter
{
- float w, g1, g2;
+ float w, g1, g2, t;
float _cutoff;
@@ -37,12 +37,14 @@ public:
{
g1 = g2 = 0;
_cutoff = 10.0f;
+ t = 0.0001f;
_reset_on_next_apply = false;
}
void reset_on_next_apply ( bool v ) { _reset_on_next_apply = v; }
void cutoff ( float v ) { _cutoff = v; }
+ void thresh ( float t_ ) { t = t_; }
void reset ( float v ) { g2 = g1 = v; }
diff --git a/src/Tests/AdNoteTest.cpp b/src/Tests/AdNoteTest.cpp
@@ -171,25 +171,25 @@ class AdNoteTest
#endif
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.1924f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.25552f, 0.0001f);
note->releasekey();
TS_ASSERT(!tr->hasNext());
w->add_watch("noteout/be4_mix");
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.4717f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.46883f, 0.0001f);
w->tick();
TS_ASSERT(tr->hasNext());
note->noteout(outL, outR);
sampleCount += synth->buffersize;
w->tick();
- TS_ASSERT_DELTA(outL[255], 0.0646f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.06695f, 0.0001f);
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.1183f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.11621f, 0.0001f);
w->tick();
note->noteout(outL, outR);
sampleCount += synth->buffersize;
diff --git a/src/Tests/PadNoteTest.cpp b/src/Tests/PadNoteTest.cpp
@@ -152,7 +152,7 @@ class PadNoteTest
#endif
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.3950, 0.0005f);
+ TS_ASSERT_DELTA(outL[255], -0.0555f, 0.0005f);
note->releasekey();
@@ -161,21 +161,21 @@ class PadNoteTest
w->add_watch("noteout");
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.2305f, 0.0005f);
+ TS_ASSERT_DELTA(outL[255], -0.0726f, 0.0005f);
w->tick();
TS_ASSERT(!tr->hasNext());
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.1164f, 0.0005f);
+ TS_ASSERT_DELTA(outL[255], -0.0516f, 0.0005f);
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.1079, 0.0005f);
+ TS_ASSERT_DELTA(outL[255], 0.0529f, 0.0005f);
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.0841f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.0525f, 0.0001f);
while(!note->finished()) {
note->noteout(outL, outR);
diff --git a/src/Tests/SubNoteTest.cpp b/src/Tests/SubNoteTest.cpp
@@ -117,7 +117,7 @@ class SubNoteTest
#endif
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.0010f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.0009f, 0.0001f);
note->releasekey();
@@ -126,12 +126,12 @@ class SubNoteTest
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.0114f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], 0.0026f, 0.0001f);
w->tick();
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.0014f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.0011f, 0.0001f);
w->tick();
TS_ASSERT(tr->hasNext());
@@ -141,7 +141,7 @@ class SubNoteTest
w->add_watch("noteout/amp_int");
note->noteout(outL, outR);
sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.0031f, 0.0001f);
+ TS_ASSERT_DELTA(outL[255], -0.0023f, 0.0001f);
w->tick();
note->noteout(outL, outR);
diff --git a/src/Tests/UnisonTest.cpp b/src/Tests/UnisonTest.cpp
@@ -116,21 +116,21 @@ class UnisonTest
sprng(0xbeef);
float data[][4] = {
- {0.125972,0.029887,0.000000,0.138013},
- {-0.095414,-0.083965,-0.000000,0.009048},
- {-0.077587,-0.001760,-0.021463,-0.013995},
- {0.041240,-0.008561,-0.000000,-0.099298},
- {-0.098969,-0.048030,-0.000052,-0.087053},
- {0.104913,-0.081452,-0.017700,0.000978},
- {0.041270,0.003788,0.006064,0.002436},
- {-0.030791,-0.036072,-0.007964,-0.015141},
- {0.009218,0.015333,-0.007500,0.083076},
- {0.058909,0.064450,-0.002517,0.041595},
- {-0.007731,-0.009040,-0.068033,-0.016573},
- {-0.047286,-0.002355,-0.049196,0.016222},
- {0.014014,-0.002635,0.006542,0.050710},
- {-0.054877,-0.027135,0.040211,0.031927},
- {-0.048367,0.022010,0.018224,0.032846},
+ {-0.034547,0.034349,-0.000000,0.138284},
+ {0.016801,-0.084991,0.000000,0.009240},
+ {0.020383,-0.002424,-0.012952,-0.014037},
+ {-0.041653,0.002287,0.000000,-0.098181},
+ {-0.009189,-0.049860,0.000268,-0.084941},
+ {0.056976,-0.084627,-0.018144,0.000666},
+ {-0.015588,0.003690,0.003994,0.002435},
+ {0.023178,-0.024961,0.004433,-0.015144},
+ {0.042007,-0.006559,-0.005887,0.083685},
+ {0.007638,0.057870,-0.014244,0.041457},
+ {-0.018006,-0.017846,-0.063624,-0.016378},
+ {0.004914,-0.001756,-0.046715,0.015975},
+ {0.004341,-0.014575,0.000560,0.050902},
+ {0.000470,-0.036961,0.038622,0.031383},
+ {-0.045796,0.000262,0.009858,0.031958},
};
int freq_spread[15];