ref: c4f8a19b78c9ed28aec07f0abbaa4764b22f8a44
parent: 96b6a59a61f0a4203e9c5720f378f45ad7d616fd
author: Jeffrey Snyder <jeffsnyder@jeffreys-mbp.mynetworksettings.com>
date: Thu Dec 15 12:24:58 EST 2022
optimized some things, such as compressor.
--- a/leaf/Inc/leaf-dynamics.h
+++ b/leaf/Inc/leaf-dynamics.h
@@ -64,7 +64,8 @@
float tauAttack, tauRelease;
float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain
-
+ float invR;
+ float inv4W;
float x_G[2], y_G[2], x_T[2], y_T[2];
int isActive;
--- a/leaf/Inc/leaf-filters.h
+++ b/leaf/Inc/leaf-filters.h
@@ -1072,6 +1072,7 @@
void tVZFilter_setResonance (tVZFilter* const vf, float res);
void tVZFilter_setFrequencyAndResonance (tVZFilter* const vf, float freq, float res);
void tVZFilter_setFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, float res, float gains);
+ void tVZFilter_setFastFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, float res, float gain);
void tVZFilter_setFrequencyAndBandwidthAndGain (tVZFilter* const vf, float freq, float BW, float gain);
void tVZFilter_setFrequencyAndResonanceAndMorph (tVZFilter* const vf, float freq, float res, float morph);
void tVZFilter_setMorphOnly (tVZFilter* const vf, float morph);
--- a/leaf/Inc/leaf-math.h
+++ b/leaf/Inc/leaf-math.h
@@ -217,6 +217,8 @@
float atodb(float a);
+ float fasteratodb(float a);
+
float dbtoa(float db);
float fastdbtoa(float db);
--- a/leaf/Inc/leaf-physical.h
+++ b/leaf/Inc/leaf-physical.h
@@ -351,6 +351,7 @@
float curr;
float Uout;
float Lout;
+ int maxLength;
tLinearDelay delayLineU;
tLinearDelay delayLineL;
tOnePole bridgeFilter;
@@ -357,20 +358,21 @@
tHighpass DCblocker;
tFeedbackLeveler fbLev;
tExpSmooth wlSmooth;
+ int oversampling;
float sampleRate;
} _tSimpleLivingString3;
typedef _tSimpleLivingString3* tSimpleLivingString3;
-void tSimpleLivingString3_init (tSimpleLivingString3* const, float freq, float dampFreq,
+void tSimpleLivingString3_init (tSimpleLivingString3* const, int oversampling, float freq, float dampFreq,
float decay, float targetLev, float levSmoothFactor,
float levStrength, int levMode, LEAF* const leaf);
-void tSimpleLivingString3_initToPool (tSimpleLivingString3* const, float freq, float dampFreq,
- float decay, float targetLev, float levSmoothFactor,
- float levStrength, int levMode, tMempool* const);
+void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, int oversampling, float freq, float dampFreq,
+ float decay, float targetLev, float levSmoothFactor,
+ float levStrength, int levMode, tMempool* const mp);
void tSimpleLivingString3_free (tSimpleLivingString3* const);
-float tSimpleLivingString3_pluck (tSimpleLivingString3* const pl, float input, float position);
+void tSimpleLivingString3_pluck (tSimpleLivingString3* const pl, float input, float position);
float tSimpleLivingString3_tick (tSimpleLivingString3* const, float input);
float tSimpleLivingString3_sample (tSimpleLivingString3* const);
void tSimpleLivingString3_setFreq (tSimpleLivingString3* const, float freq);
--- a/leaf/Src/leaf-dynamics.c
+++ b/leaf/Src/leaf-dynamics.c
@@ -64,8 +64,10 @@
c->y_T[0] = 0.0f, c->y_T[1] = 0.0f;
c->T = 0.0f; // Threshold
c->R = 0.5f; // compression Ratio
+ c->invR = 2.0f; //inverse of ratio
c->M = 3.0f; // decibel Make-up gain
- c->W = 1.0f; // decibel Width of knee transition
+ c->W = 1.5f; // decibel Width of knee transition
+ c->inv4W = 1.0f / (4.0f * c->W) ;
}
@@ -83,34 +85,33 @@
float slope, overshoot;
- float in_db = LEAF_clip(-90.0f, atodb(fabsf(in)), 0.0f);
+ float in_db = LEAF_clip(-90.0f, fasteratodb(fastabsf(in)), 0.0f);
float out_db = 0.0f;
c->y_T[1] = c->y_T[0];
- slope = 1.0f - (1.0f/c->R); // feed-forward topology;
+ slope = 1.0f - c->invR; // feed-forward topology;
overshoot = in_db - c->T;
- /*
- if (overshoot <= -(c->W * 0.5f))
+
+ if (overshoot <= -(c->W))
{
out_db = in_db;
c->isActive = 0;
}
-
- else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f)))
+ else if ((overshoot > -(c->W)) && (overshoot < (c->W)))
{
- float squareit = (overshoot + c->W*0.5f);
- out_db = in_db + slope * ((squareit * squareit) / (2.0f * c->W)); // .^ 2 ???
+ float squareit = (overshoot + c->W);
+ out_db = in_db + slope * ((squareit * squareit) * c->inv4W); // .^ 2 ???
c->isActive = 1;
}
- else if (overshoot >= (c->W * 0.5f))
+ else
{
out_db = in_db + slope * overshoot;
c->isActive = 1;
}
- */
+/* // simpler hard-knee version
if (overshoot <= 0.0f)
{
out_db = in_db;
@@ -121,26 +122,13 @@
out_db = in_db + slope * overshoot;
c->isActive = 1;
}
-
+ */
c->x_T[0] = out_db - in_db;
-
-
-
if (c->x_T[0] > c->y_T[1])
c->y_T[0] = c->tauAttack * c->y_T[1] + (1.0f-c->tauAttack) * c->x_T[0];
else
c->y_T[0] = c->tauRelease * c->y_T[1] + (1.0f-c->tauRelease) * c->x_T[0];
- if (isnan(c->y_T[0]))
- {
- out_db = 1.0f;
- }
-
float attenuation = fasterdbtoa(c->M - c->y_T[0]);
- if (isnan(attenuation))
- {
- out_db = 1.0f;
- }
- //float attenuation = 1.0f;
return attenuation * in;
}
@@ -158,10 +146,12 @@
_tCompressor* c = *comp;
c->T = thresh;
c->R = ratio;
- c->W = knee;
+ c->invR = 1.0f / ratio;
+ c->W = knee * 0.5f;
+ c->inv4W = 1.0f / (2.0f * knee);
c->M = makeup;
- c->tauAttack = expf(-1.0f/(0.001f * attack * c->sampleRate));
- c->tauRelease = expf(-1.0f/(0.001f * release * c->sampleRate));
+ c->tauAttack = fasterexpf(-1.0f/(0.001f * attack * c->sampleRate));
+ c->tauRelease = fasterexpf(-1.0f/(0.001f * release * c->sampleRate));
}
/* Feedback Leveler */
--- a/leaf/Src/leaf-filters.c
+++ b/leaf/Src/leaf-filters.c
@@ -1524,7 +1524,7 @@
int intVer = (int)cutoff;
float floatVer = cutoff - (float)intVer;
f->g = (__leaf_table_filtertan[intVer] * (1.0f - floatVer)) + (__leaf_table_filtertan[intVer+1] * floatVer);
-
+
switch( f->type )
{
case Bypass:
@@ -1697,6 +1697,18 @@
f->invG = 1.0f/f->G;
tVZFilter_calcCoeffs(vf);
}
+
+void tVZFilter_setFastFrequencyAndResonanceAndGain (tVZFilter* const vf, float freq, float res, float gain)
+{
+ _tVZFilter* f = *vf;
+ //f->fc = LEAF_clip(0.1f, freq, 0.4f * f->sampleRate);
+ f->Q = LEAF_clip(0.01f, res, 100.0f);
+ f->R2 = 1.0f / f->Q;
+ f->G = LEAF_clip(0.000001f, gain, 4000.0f);
+ f->invG = 1.0f/f->G;
+ tVZFilter_setFreqFast(vf, freq);
+}
+
void tVZFilter_setFrequencyAndBandwidthAndGain (tVZFilter* const vf, float freq, float BW, float gain)
{
_tVZFilter* f = *vf;
@@ -1707,6 +1719,7 @@
f->invG = 1.0f/f->G;
tVZFilter_calcCoeffs(vf);
}
+
void tVZFilter_setFrequencyAndResonanceAndMorph (tVZFilter* const vf, float freq, float res, float morph)
{
--- a/leaf/Src/leaf-math.c
+++ b/leaf/Src/leaf-math.c
@@ -810,11 +810,14 @@
{
return 20.0f*log10f(a);
}
+float fasteratodb(float a)
+{
+ return 20.0f*log10f_fast(a);
+}
float dbtoa(float db)
{
return powf(10.0f, db * 0.05f);
- //return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
}
--- a/leaf/Src/leaf-physical.c
+++ b/leaf/Src/leaf-physical.c
@@ -501,14 +501,14 @@
/* Simple Living String*/
-void tSimpleLivingString3_init(tSimpleLivingString3* const pl, float freq, float dampFreq,
+void tSimpleLivingString3_init(tSimpleLivingString3* const pl, int oversampling, float freq, float dampFreq,
float decay, float targetLev, float levSmoothFactor,
float levStrength, int levMode, LEAF* const leaf)
{
- tSimpleLivingString3_initToPool(pl, freq, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf->mempool);
+ tSimpleLivingString3_initToPool(pl, oversampling, freq, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf->mempool);
}
-void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, float freq, float dampFreq,
+void tSimpleLivingString3_initToPool (tSimpleLivingString3* const pl, int oversampling, float freq, float dampFreq,
float decay, float targetLev, float levSmoothFactor,
float levStrength, int levMode, tMempool* const mp)
{
@@ -516,12 +516,13 @@
_tSimpleLivingString3* p = *pl = (_tSimpleLivingString3*) mpool_alloc(sizeof(_tSimpleLivingString3), m);
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
-
- p->sampleRate = leaf->sampleRate;
+ p->oversampling = oversampling;
+ p->sampleRate = leaf->sampleRate * oversampling;
p->curr=0.0f;
+ p->maxLength = 2400 * oversampling;
tExpSmooth_initToPool(&p->wlSmooth, p->sampleRate/freq/2.0f, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
- tLinearDelay_initToPool(&p->delayLineU,p->waveLengthInSamples, 2400, mp);
- tLinearDelay_initToPool(&p->delayLineL,p->waveLengthInSamples, 2400, mp);
+ tLinearDelay_initToPool(&p->delayLineU,p->waveLengthInSamples, p->maxLength, mp);
+ tLinearDelay_initToPool(&p->delayLineL,p->waveLengthInSamples, p->maxLength, mp);
tSimpleLivingString3_setFreq(pl, freq);
tLinearDelay_setDelay(&p->delayLineU, p->waveLengthInSamples);
tLinearDelay_setDelay(&p->delayLineL, p->waveLengthInSamples);
@@ -554,10 +555,11 @@
void tSimpleLivingString3_setFreq(tSimpleLivingString3* const pl, float freq)
{
_tSimpleLivingString3* p = *pl;
-
- if (freq<20) freq=20;
- else if (freq>10000) freq=10000;
- p->waveLengthInSamples = (p->sampleRate/freq) * 0.5f;
+ p->freq = freq;
+ float waveLength = (p->sampleRate/freq);
+ if (waveLength<4.8) waveLength=4.8f;
+ else if (waveLength>p->maxLength*2) waveLength=p->maxLength*2;
+ p->waveLengthInSamples = waveLength * 0.5f;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -566,7 +568,7 @@
_tSimpleLivingString3* p = *pl;
if (waveLength<4.8) waveLength=4.8f;
- else if (waveLength>4800) waveLength=4800;
+ else if (waveLength>p->maxLength*2) waveLength=p->maxLength*2;
p->waveLengthInSamples = waveLength * 0.5f;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -608,7 +610,7 @@
p->levMode=levMode;
}
-float tSimpleLivingString3_pluck(tSimpleLivingString3* const pl, float input, float position)
+void tSimpleLivingString3_pluck(tSimpleLivingString3* const pl, float input, float position)
{
_tSimpleLivingString3* p = *pl;
int length = p->waveLengthInSamples;
@@ -636,7 +638,6 @@
int currentBufReadPointMod = currentBufReadPoint % p->delayLineU->maxDelay;
p->delayLineL->buff[currentBufWritePoint] = p->delayLineU->buff[currentBufReadPointMod];
}
-
}
float tSimpleLivingString3_tick(tSimpleLivingString3* const pl, float input)
@@ -644,8 +645,6 @@
_tSimpleLivingString3* p = *pl;
tLinearDelay_setDelay(&p->delayLineU, tExpSmooth_tick(&p->wlSmooth));
tLinearDelay_setDelay(&p->delayLineL, tExpSmooth_tick(&p->wlSmooth));
- //tLinearDelay_setDelay(&p->delayLineU, p->waveLengthInSamples);
- //tLinearDelay_setDelay(&p->delayLineL, p->waveLengthInSamples);
p->Uout = tOnePole_tick(&p->bridgeFilter,tLinearDelay_tickOut(&p->delayLineU));
p->Lout = tLinearDelay_tickOut(&p->delayLineL);