ref: b40f3a777e9dacbfc30351349a1c7d3a632f1d8e
parent: a7eedc627b937332dc96ae338b6373555a0cd2e5
author: spiricom <jeff@snyderphonics.com>
date: Mon May 18 08:22:19 EDT 2020
update envelopes and filters
binary files a/LEAF/.DS_Store b/LEAF/.DS_Store differ
--- a/LEAF/Inc/leaf-filters.h
+++ b/LEAF/Inc/leaf-filters.h
@@ -388,91 +388,92 @@
typedef enum VZFilterType
{
- Highpass = 0,
+ Highpass = 0,
Lowpass,
BandpassSkirt,
- BandpassPeak,
- BandReject,
+ BandpassPeak,
+ BandReject,
Bell,
- Lowshelf,
- Highshelf,
- Morph,
- Bypass,
- Allpass
+ Lowshelf,
+ Highshelf,
+ Morph,
+ Bypass,
+ Allpass
} VZFilterType;
-
- typedef struct _tVZFilter
- {
- VZFilterType type;
- // state:
- float s1, s2;
-
- // filter coefficients:
- float g; // embedded integrator gain
- float R2; // twice the damping coefficient (R2 == 2*R == 1/Q)
- float h; // factor for feedback (== 1/(1+2*R*g+g*g))
- float cL, cB, cH; // coefficients for low-, band-, and highpass signals
-
- // parameters:
- float fs; // sample-rate
- float fc; // characteristic frequency
- float G; // gain
- float invG; //1/gain
- float B; // bandwidth (in octaves)
- float m; // morph parameter (0...1)
-
- float sr; //local sampling rate of filter (may be different from leaf sr if oversampled)
- float inv_sr;
-
- } _tVZFilter;
-
- typedef _tVZFilter* tVZFilter;
-
- void tVZFilter_init (tVZFilter* const, VZFilterType type, float freq, float Q);
- void tVZFilter_free (tVZFilter* const);
- void tVZFilter_initToPool (tVZFilter* const, VZFilterType type, float freq, float Q, tMempool* const);
- void tVZFilter_freeFromPool (tVZFilter* const, tMempool* const);
- void tVZFilter_setSampleRate (tVZFilter* const, float sampleRate);
- float tVZFilter_tick (tVZFilter* const, float input);
- float tVZFilter_tickEfficient (tVZFilter* const vf, float in);
- void tVZFilter_calcCoeffs (tVZFilter* const);
- void tVZFilter_setBandwidth (tVZFilter* const, float bandWidth);
- void tVZFilter_setFreq (tVZFilter* const, float freq);
- void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw);
- void tVZFilter_setGain (tVZFilter* const, float gain);
- void tVZFilter_setType (tVZFilter* const, VZFilterType type);
- float tVZFilter_BandwidthToR (tVZFilter* const vf, float B);
-
-
-
-
- //diode ladder filter
- typedef struct _tDiodeFilter
- {
-
- float f;
- float r;
- float Vt;
- float n;
- float gamma;
- float zi;
- float g0inv;
- float g1inv;
- float g2inv;
- float s0, s1, s2, s3;
-
- } _tDiodeFilter;
-
- typedef _tDiodeFilter* tDiodeFilter;
-
- void tDiodeFilter_init (tDiodeFilter* const, float freq, float Q);
- void tDiodeFilter_free (tDiodeFilter* const);
- void tDiodeFilter_initToPool (tDiodeFilter* const, float freq, float Q, tMempool* const);
- void tDiodeFilter_freeFromPool (tDiodeFilter* const, tMempool* const);
-
- float tDiodeFilter_tick (tDiodeFilter* const, float input);
- void tDiodeFilter_setFreq (tDiodeFilter* const vf, float cutoff);
- void tDiodeFilter_setQ (tDiodeFilter* const vf, float resonance);
+
+
+ typedef struct _tVZFilter
+ {
+ VZFilterType type;
+ // state:
+ float s1, s2;
+
+ // filter coefficients:
+ float g; // embedded integrator gain
+ float R2; // twice the damping coefficient (R2 == 2*R == 1/Q)
+ float h; // factor for feedback (== 1/(1+2*R*g+g*g))
+ float cL, cB, cH; // coefficients for low-, band-, and highpass signals
+
+ // parameters:
+ float fs; // sample-rate
+ float fc; // characteristic frequency
+ float G; // gain
+ float invG; //1/gain
+ float B; // bandwidth (in octaves)
+ float m; // morph parameter (0...1)
+
+ float sr; //local sampling rate of filter (may be different from leaf sr if oversampled)
+ float inv_sr;
+
+ } _tVZFilter;
+
+ typedef _tVZFilter* tVZFilter;
+
+ void tVZFilter_init (tVZFilter* const, VZFilterType type, float freq, float Q);
+ void tVZFilter_free (tVZFilter* const);
+ void tVZFilter_initToPool (tVZFilter* const, VZFilterType type, float freq, float Q, tMempool* const);
+ void tVZFilter_freeFromPool (tVZFilter* const, tMempool* const);
+ void tVZFilter_setSampleRate (tVZFilter* const, float sampleRate);
+ float tVZFilter_tick (tVZFilter* const, float input);
+ float tVZFilter_tickEfficient (tVZFilter* const vf, float in);
+ void tVZFilter_calcCoeffs (tVZFilter* const);
+ void tVZFilter_setBandwidth (tVZFilter* const, float bandWidth);
+ void tVZFilter_setFreq (tVZFilter* const, float freq);
+ void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw);
+ void tVZFilter_setGain (tVZFilter* const, float gain);
+ void tVZFilter_setType (tVZFilter* const, VZFilterType type);
+ float tVZFilter_BandwidthToR (tVZFilter* const vf, float B);
+
+
+
+
+ //diode ladder filter
+ typedef struct _tDiodeFilter
+ {
+
+ float f;
+ float r;
+ float Vt;
+ float n;
+ float gamma;
+ float zi;
+ float g0inv;
+ float g1inv;
+ float g2inv;
+ float s0, s1, s2, s3;
+
+ } _tDiodeFilter;
+
+ typedef _tDiodeFilter* tDiodeFilter;
+
+ void tDiodeFilter_init (tDiodeFilter* const, float freq, float Q);
+ void tDiodeFilter_free (tDiodeFilter* const);
+ void tDiodeFilter_initToPool (tDiodeFilter* const, float freq, float Q, tMempool* const);
+ void tDiodeFilter_freeFromPool (tDiodeFilter* const, tMempool* const);
+
+ float tDiodeFilter_tick (tDiodeFilter* const, float input);
+ void tDiodeFilter_setFreq (tDiodeFilter* const vf, float cutoff);
+ void tDiodeFilter_setQ (tDiodeFilter* const vf, float resonance);
#ifdef __cplusplus
--- a/LEAF/Src/leaf-envelopes.c
+++ b/LEAF/Src/leaf-envelopes.c
@@ -533,7 +533,7 @@
_tRamp* ramp = *r = (_tRamp*) leaf_alloc(sizeof(_tRamp));
ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f);
- ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
+ ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
ramp->curr = 0.0f;
ramp->dest = 0.0f;
@@ -592,14 +592,14 @@
{
_tRamp* r = *ramp;
- if (time < r->minimum_time)
- {
- r->time = r->minimum_time;
- }
- else
- {
- r->time = time;
- }
+ if (time < r->minimum_time)
+ {
+ r->time = r->minimum_time;
+ }
+ else
+ {
+ r->time = time;
+ }
r->factor = (1.0f / r->time) * r->inv_sr_ms * (float)r->samples_per_tick;
r->inc = (r->dest - r->curr) * r->factor;
@@ -626,10 +626,10 @@
r->curr += r->inc;
if (((r->curr >= r->dest) && (r->inc > 0.0f)) || ((r->curr <= r->dest) && (r->inc < 0.0f)))
- {
- r->inc = 0.0f;
- r->curr=r->dest;
- }
+ {
+ r->inc = 0.0f;
+ r->curr=r->dest;
+ }
return r->curr;
}
@@ -647,7 +647,6 @@
r->factor = (1.0f / r->time) * r->inv_sr_ms * (float)r->samples_per_tick;
r->inc = (r->dest - r->curr) * r->factor;
}
-
--- a/LEAF/Src/leaf-filters.c
+++ b/LEAF/Src/leaf-filters.c
@@ -17,6 +17,7 @@
#include "../Inc/leaf-filters.h"
#include "../Inc/leaf-tables.h"
#include "../leaf.h"
+#include "tim.h"
#endif
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
@@ -1364,274 +1365,305 @@
return f->val[f->middlePosition];
}
-
/////
void tVZFilter_init (tVZFilter* const vf, VZFilterType type, float freq, float bandWidth)
{
- tVZFilter_initToPool(vf, type, freq, bandWidth, &leaf.mempool);
+ tVZFilter_initToPool(vf, type, freq, bandWidth, &leaf.mempool);
}
void tVZFilter_free (tVZFilter* const vf)
{
- tVZFilter_freeFromPool(vf, &leaf.mempool);
+ tVZFilter_freeFromPool(vf, &leaf.mempool);
}
void tVZFilter_initToPool (tVZFilter* const vf, VZFilterType type, float freq, float bandWidth, tMempool* const mp)
{
- _tMempool* m = *mp;
- _tVZFilter* f = *vf = (_tVZFilter*) mpool_alloc(sizeof(_tVZFilter), m);
- f->fc = freq;
- f->type = type;
- f->G = ONE_OVER_SQRT2;
- f->invG = 1.0f/ONE_OVER_SQRT2;
- f->B = bandWidth;
- f->m = 0.0f;
- f->s1 = 0.0f;
- f->s2 = 0.0f;
- f->sr = leaf.sampleRate;
- f->inv_sr = leaf.invSampleRate;
- tVZFilter_calcCoeffs(vf);
+ _tMempool* m = *mp;
+ _tVZFilter* f = *vf = (_tVZFilter*) mpool_alloc(sizeof(_tVZFilter), m);
+ f->fc = freq;
+ f->type = type;
+ f->G = ONE_OVER_SQRT2;
+ f->invG = 1.0f/ONE_OVER_SQRT2;
+ f->B = bandWidth;
+ f->m = 0.0f;
+ f->s1 = 0.0f;
+ f->s2 = 0.0f;
+ f->sr = leaf.sampleRate;
+ f->inv_sr = leaf.invSampleRate;
+ tVZFilter_calcCoeffs(vf);
}
void tVZFilter_freeFromPool (tVZFilter* const vf, tMempool* const mp)
{
- _tMempool* m = *mp;
- _tVZFilter* f = *vf = (_tVZFilter*) mpool_alloc(sizeof(_tVZFilter), m);
- mpool_free(f, m);
+ _tMempool* m = *mp;
+ _tVZFilter* f = *vf = (_tVZFilter*) mpool_alloc(sizeof(_tVZFilter), m);
+ mpool_free(f, m);
}
-void tVZFilter_setSampleRate (tVZFilter* const vf, float sampleRate)
+void tVZFilter_setSampleRate (tVZFilter* const vf, float sampleRate)
{
- _tVZFilter* f = *vf;
- f->sr = sampleRate;
- f->inv_sr = 1.0f/sampleRate;
+ _tVZFilter* f = *vf;
+ f->sr = sampleRate;
+ f->inv_sr = 1.0f/sampleRate;
}
-float tVZFilter_tick (tVZFilter* const vf, float in)
+float tVZFilter_tick (tVZFilter* const vf, float in)
{
- _tVZFilter* f = *vf;
+ _tVZFilter* f = *vf;
- float yL, yB, yH;
+ float yL, yB, yH;
- // compute highpass output via Eq. 5.1:
- yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
+ // compute highpass output via Eq. 5.1:
+ yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
- // compute bandpass output by applying 1st integrator to highpass output:
- yB = tanhf(f->g*yH) + f->s1;
- f->s1 = f->g*yH + yB; // state update in 1st integrator
+ // compute bandpass output by applying 1st integrator to highpass output:
+ yB = tanhf(f->g*yH) + f->s1;
+ f->s1 = f->g*yH + yB; // state update in 1st integrator
- // compute lowpass output by applying 2nd integrator to bandpass output:
- yL = tanhf(f->g*yB) + f->s2;
- f->s2 = f->g*yB + yL; // state update in 2nd integrator
+ // compute lowpass output by applying 2nd integrator to bandpass output:
+ yL = tanhf(f->g*yB) + f->s2;
+ f->s2 = f->g*yB + yL; // state update in 2nd integrator
- //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
- //
- //seems like that might look like this:
+ //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
+ //
+ //seems like that might look like this:
// y = tanh(g*x) + s; // output computation
// s = g*x + y; // state update
- //instead of this:
+ //instead of this:
// y = g*x + s; // output computation
// s = g*x + y; // state update
- return f->cL*yL + f->cB*yB + f->cH*yH;
+ return f->cL*yL + f->cB*yB + f->cH*yH;
}
-float tVZFilter_tickEfficient (tVZFilter* const vf, float in)
+float tVZFilter_tickEfficient (tVZFilter* const vf, float in)
{
- _tVZFilter* f = *vf;
+ _tVZFilter* f = *vf;
- float yL, yB, yH;
+ float yL, yB, yH;
- // compute highpass output via Eq. 5.1:
- yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
+ // compute highpass output via Eq. 5.1:
+ yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
- // compute bandpass output by applying 1st integrator to highpass output:
- yB = (f->g*yH) + f->s1;
- f->s1 = f->g*yH + yB; // state update in 1st integrator
+ // compute bandpass output by applying 1st integrator to highpass output:
+ yB = (f->g*yH) + f->s1;
+ f->s1 = f->g*yH + yB; // state update in 1st integrator
- // compute lowpass output by applying 2nd integrator to bandpass output:
- yL = (f->g*yB) + f->s2;
- f->s2 = f->g*yB + yL; // state update in 2nd integrator
+ // compute lowpass output by applying 2nd integrator to bandpass output:
+ yL = (f->g*yB) + f->s2;
+ f->s2 = f->g*yB + yL; // state update in 2nd integrator
- //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
- //
- //seems like that might look like this:
+ //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
+ //
+ //seems like that might look like this:
// y = tanh(g*x) + s; // output computation
// s = g*x + y; // state update
- //instead of this:
+ //instead of this:
// y = g*x + s; // output computation
// s = g*x + y; // state update
- return f->cL*yL + f->cB*yB + f->cH*yH;
+ return f->cL*yL + f->cB*yB + f->cH*yH;
}
+float tVZFilter_tickEfficientBP (tVZFilter* const vf, float in)
+{
+ _tVZFilter* f = *vf;
+ float yL, yB, yH;
+
+ // compute highpass output via Eq. 5.1:
+ yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
+
+ // compute bandpass output by applying 1st integrator to highpass output:
+ yB = (f->g*yH) + f->s1;
+ f->s1 = f->g*yH + yB; // state update in 1st integrator
+
+ // compute lowpass output by applying 2nd integrator to bandpass output:
+ yL = (f->g*yB) + f->s2;
+ f->s2 = f->g*yB + yL; // state update in 2nd integrator
+
+ //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
+ //
+ //seems like that might look like this:
+ // y = tanh(g*x) + s; // output computation
+ // s = g*x + y; // state update
+
+ //instead of this:
+ // y = g*x + s; // output computation
+ // s = g*x + y; // state update
+
+ return f->cL*yL + f->cB*yB + f->cH*yH;
+
+}
+
+
void tVZFilter_calcCoeffs (tVZFilter* const vf)
{
- _tVZFilter* f = *vf;
- f->g = tanf(PI * f->fc * f->inv_sr); // embedded integrator gain (Fig 3.11)
+ _tVZFilter* f = *vf;
+ f->g = tanf(PI * f->fc * f->inv_sr); // embedded integrator gain (Fig 3.11)
- switch( f->type )
- {
- case Bypass:
- {
- f->R2 = f->invG; // can we use an arbitrary value here, for example R2 = 1?
- f->cL = 1.0f;
- f->cB = f->R2;
- f->cH = 1.0f;
- }
- break;
- case Lowpass:
- {
- f->R2 = f->invG;
- f->cL = 1.0f; f->cB = 0.0f; f->cH = 0.0f;
- }
- break;
- case Highpass:
- {
- f->R2 = f->invG;
- f->cL = 0.0f; f->cB = 0.0f; f->cH = 1.0f;
- }
- break;
- case BandpassSkirt:
- {
- f->R2 = f->invG;
- f->cL = 0.0f; f->cB = 1.0f; f->cH = 0.0f;
- }
- break;
- case BandpassPeak:
- {
- f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
- f->cL = 0.0f; f->cB = f->R2; f->cH = 0.0f;
- }
- break;
- case BandReject:
- {
- f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
- f->cL = 1.0f; f->cB = 0.0f; f->cH = 1.0f;
- }
- break;
- case Bell:
- {
- float fl = f->fc*powf(2.0f, (-f->B)*0.5f); // lower bandedge frequency (in Hz)
- float wl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
- float r = f->g/wl;
- r *= r; // warped frequency ratio wu/wl == (wc/wl)^2 where wu is the
- // warped upper bandedge, wc the center
- f->R2 = 2.0f*sqrtf(((r*r+1.0f)/r-2.0f)/(4.0f*f->G));
- f->cL = 1.0f; f->cB = f->R2*f->G; f->cH = 1.0f;
- }
- break;
- case Lowshelf:
- {
- float A = sqrtf(f->G);
- f->g /= sqrtf(A); // scale SVF-cutoff frequency for shelvers
- f->R2 = 2*sinhf(f->B*logf(2.0f)*0.5f);
- f->cL = f->G; f->cB = f->R2*A; f->cH = 1.0f;
- }
- break;
- case Highshelf:
- {
- float A = sqrtf(f->G);
- f->g *= sqrtf(A); // scale SVF-cutoff frequency for shelvers
- f->R2 = 2.0f*sinhf(f->B*logf(2.0f)*0.5f);
- f->cL = 1.0f; f->cB = f->R2*A; f->cH = f->G;
- }
- break;
- case Allpass:
- {
- f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
- f->cL = 1.0f; f->cB = -f->R2; f->cH = 1.0f;
- }
- break;
+ switch( f->type )
+ {
+ case Bypass:
+ {
+ f->R2 = f->invG; // can we use an arbitrary value here, for example R2 = 1?
+ f->cL = 1.0f;
+ f->cB = f->R2;
+ f->cH = 1.0f;
+ }
+ break;
+ case Lowpass:
+ {
+ f->R2 = f->invG;
+ f->cL = 1.0f; f->cB = 0.0f; f->cH = 0.0f;
+ }
+ break;
+ case Highpass:
+ {
+ f->R2 = f->invG;
+ f->cL = 0.0f; f->cB = 0.0f; f->cH = 1.0f;
+ }
+ break;
+ case BandpassSkirt:
+ {
+ f->R2 = f->invG;
+ f->cL = 0.0f; f->cB = 1.0f; f->cH = 0.0f;
+ }
+ break;
+ case BandpassPeak:
+ {
+ f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
+ f->cL = 0.0f; f->cB = f->R2; f->cH = 0.0f;
+ }
+ break;
+ case BandReject:
+ {
+ f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
+ f->cL = 1.0f; f->cB = 0.0f; f->cH = 1.0f;
+ }
+ break;
+ case Bell:
+ {
+ float fl = f->fc*powf(2.0f, (-f->B)*0.5f); // lower bandedge frequency (in Hz)
+ float wl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
+ float r = f->g/wl;
+ r *= r; // warped frequency ratio wu/wl == (wc/wl)^2 where wu is the
+ // warped upper bandedge, wc the center
+ f->R2 = 2.0f*sqrtf(((r*r+1.0f)/r-2.0f)/(4.0f*f->G));
+ f->cL = 1.0f; f->cB = f->R2*f->G; f->cH = 1.0f;
+ }
+ break;
+ case Lowshelf:
+ {
+ float A = sqrtf(f->G);
+ f->g /= sqrtf(A); // scale SVF-cutoff frequency for shelvers
+ f->R2 = 2*sinhf(f->B*logf(2.0f)*0.5f);
+ f->cL = f->G; f->cB = f->R2*A; f->cH = 1.0f;
+ }
+ break;
+ case Highshelf:
+ {
+ float A = sqrtf(f->G);
+ f->g *= sqrtf(A); // scale SVF-cutoff frequency for shelvers
+ f->R2 = 2.0f*sinhf(f->B*logf(2.0f)*0.5f);
+ f->cL = 1.0f; f->cB = f->R2*A; f->cH = f->G;
+ }
+ break;
+ case Allpass:
+ {
+ f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
+ f->cL = 1.0f; f->cB = -f->R2; f->cH = 1.0f;
+ }
+ break;
- // experimental - maybe we must find better curves for cL, cB, cH:
- case Morph:
- {
- f->R2 = f->invG;
- float x = 2.0f*f->m-1.0f;
+ // experimental - maybe we must find better curves for cL, cB, cH:
+ case Morph:
+ {
+ f->R2 = f->invG;
+ float x = 2.0f*f->m-1.0f;
- f->cL = maximum(-x, 0.0f); /*cL *= cL;*/
- f->cH = minimum( x, 0.0f); /*cH *= cH;*/
- f->cB = 1.0f-x*x;
+ f->cL = maximum(-x, 0.0f); /*cL *= cL;*/
+ f->cH = minimum( x, 0.0f); /*cH *= cH;*/
+ f->cB = 1.0f-x*x;
- // bottom line: we need to test different versions for how they feel when tweaking the
- // morph parameter
+ // bottom line: we need to test different versions for how they feel when tweaking the
+ // morph parameter
- // this scaling ensures constant magnitude at the cutoff point (we divide the coefficients by
- // the magnitude response value at the cutoff frequency and scale back by the gain):
- float s = f->G * sqrtf((f->R2*f->R2) / (f->cL*f->cL + f->cB*f->cB + f->cH*f->cH - 2.0f*f->cL*f->cH));
- f->cL *= s; f->cB *= s; f->cH *= s;
- }
- break;
+ // this scaling ensures constant magnitude at the cutoff point (we divide the coefficients by
+ // the magnitude response value at the cutoff frequency and scale back by the gain):
+ float s = f->G * sqrtf((f->R2*f->R2) / (f->cL*f->cL + f->cB*f->cB + f->cH*f->cH - 2.0f*f->cL*f->cH));
+ f->cL *= s; f->cB *= s; f->cH *= s;
+ }
+ break;
- }
+ }
- f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
+ f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
}
-void tVZFilter_setBandwidth (tVZFilter* const vf, float B)
+void tVZFilter_setBandwidth (tVZFilter* const vf, float B)
{
- _tVZFilter* f = *vf;
- f->B = LEAF_clip(0.0f, B, 100.0f);
- tVZFilter_calcCoeffs(vf);
+ _tVZFilter* f = *vf;
+ f->B = LEAF_clip(0.0f, B, 100.0f);
+ tVZFilter_calcCoeffs(vf);
}
void tVZFilter_setFreq (tVZFilter* const vf, float freq)
{
- _tVZFilter* f = *vf;
- f->fc = LEAF_clip(0.0f, freq, 0.5f*leaf.sampleRate);
- tVZFilter_calcCoeffs(vf);
+ _tVZFilter* f = *vf;
+ f->fc = LEAF_clip(0.0f, freq, 0.5f*leaf.sampleRate);
+ tVZFilter_calcCoeffs(vf);
}
void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw)
{
- _tVZFilter* f = *vf;
- f->B = LEAF_clip(0.0f,bw, 100.0f);
- f->fc = LEAF_clip(0.0f, freq, 0.5f*leaf.sampleRate);
- tVZFilter_calcCoeffs(vf);
+ _tVZFilter* f = *vf;
+ f->B = LEAF_clip(0.0f,bw, 100.0f);
+ f->fc = LEAF_clip(0.0f, freq, 0.5f*leaf.sampleRate);
+ tVZFilter_calcCoeffs(vf);
}
-void tVZFilter_setGain (tVZFilter* const vf, float gain)
+void tVZFilter_setGain (tVZFilter* const vf, float gain)
{
- _tVZFilter* f = *vf;
- f->G = LEAF_clip(0.000001f, gain, 100.0f);
- f->invG = 1.0f/f->G;
- tVZFilter_calcCoeffs(vf);
+ _tVZFilter* f = *vf;
+ f->G = LEAF_clip(0.000001f, gain, 100.0f);
+ f->invG = 1.0f/f->G;
+ tVZFilter_calcCoeffs(vf);
}
-void tVZFilter_setMorph (tVZFilter* const vf, float morph)
+void tVZFilter_setMorph (tVZFilter* const vf, float morph)
{
- _tVZFilter* f = *vf;
- f->m = LEAF_clip(0.0f, morph, 1.0f);
- tVZFilter_calcCoeffs(vf);
+ _tVZFilter* f = *vf;
+ f->m = LEAF_clip(0.0f, morph, 1.0f);
+ tVZFilter_calcCoeffs(vf);
}
-void tVZFilter_setType (tVZFilter* const vf, VZFilterType type)
+void tVZFilter_setType (tVZFilter* const vf, VZFilterType type)
{
- _tVZFilter* f = *vf;
- f->type = type;
- tVZFilter_calcCoeffs(vf);
+ _tVZFilter* f = *vf;
+ f->type = type;
+ tVZFilter_calcCoeffs(vf);
}
float tVZFilter_BandwidthToR(tVZFilter* const vf, float B)
{
- _tVZFilter* f = *vf;
+ _tVZFilter* f = *vf;
float fl = f->fc*powf(2.0f, -B*0.5f); // lower bandedge frequency (in Hz)
float gl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies
- // unwarped: r = pow(2, -B/2) -> approximation for low
- // center-frequencies
+ // unwarped: r = pow(2, -B/2) -> approximation for low
+ // center-frequencies
return sqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
}
+
void tDiodeFilter_init (tDiodeFilter* const vf, float cutoff, float resonance)
{
tDiodeFilter_initToPool(vf, cutoff, resonance, &leaf.mempool);
@@ -1696,24 +1728,24 @@
// This formula gives the result for y3 thanks to MATLAB
float y3 = (f->s2 + f->s3 + t2*(f->s1 + f->s2 + f->s3 + t1*(f->s0 + f->s1 + f->s2 + f->s3 + t0*in)) + t1*(2.0f*f->s2 + 2.0f*f->s3))*t3 + f->s3 + 2.0f*f->s3*t1 + t2*(2.0f*f->s3 + 3.0f*f->s3*t1);
-// if (isnan(y3))
-// {
-// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-// }
+ if (isnan(y3))
+ {
+ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+ }
float tempy3denom = (t4 + t1*(2.0f*t4 + 4.0f) + t2*(t4 + t1*(t4 + f->r*t0 + 4.0f) + 3.0f) + 2.0f)*t3 + t4 + t1*(2.0f*t4 + 2.0f) + t2*(2.0f*t4 + t1*(3.0f*t4 + 3.0f) + 2.0f) + 1.0f;
-// if (isnan(tempy3denom))
-// {
-// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-// }
+ if (isnan(tempy3denom))
+ {
+ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+ }
if (tempy3denom == 0.0f)
{
tempy3denom = 0.000001f;
}
y3 = y3 / tempy3denom;
-// if (isnan(y3))
-// {
-// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-// }
+ if (isnan(y3))
+ {
+ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+ }
if (t1 == 0.0f)
{
t1 = 0.000001f;
@@ -1734,15 +1766,15 @@
// update state
f->s0 += 2.0f * (t0*xx + t1*(y1-y0));
-// if (isnan(f->s0))
-// {
-// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-// }
+ if (isnan(f->s0))
+ {
+ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+ }
-// if (isinf(f->s0))
-// {
-// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-// }
+ if (isinf(f->s0))
+ {
+ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+ }
f->s1 += 2.0f * (t2*(y2-y1) - t1*(y1-y0));
f->s2 += 2.0f * (t3*(y3-y2) - t2*(y2-y1));
f->s3 += 2.0f * (-t4*(y3) - t3*(y3-y2));