shithub: leaf

Download patch

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