shithub: leaf

Download patch

ref: 19a991d12e072f63f39deaa24ae083d6ca417b71
parent: 6e322e9033baed4027c8b3184c41fbc8df18b186
author: spiricom <jeff@snyderphonics.com>
date: Thu Dec 26 18:39:09 EST 2019

fixed wavefolder and added samplereducer

binary files a/.DS_Store b/.DS_Store differ
binary files a/LEAF/.DS_Store b/LEAF/.DS_Store differ
binary files a/LEAF/Inc/.DS_Store b/LEAF/Inc/.DS_Store differ
--- a/LEAF/Inc/leaf-distortion.h
+++ b/LEAF/Inc/leaf-distortion.h
@@ -25,23 +25,23 @@
     
     typedef struct _tLockhartWavefolder
     {
-        float Ln1;
-        float Fn1;
+        double Ln1;
+        double Fn1;
         float xn1;
-        
-        float RL;
-        float R;
-        float VT;
-        float Is;
 
-        float a;
-        float b;
-        float d;
+        double RL;
+        double R;
+        double VT;
+        double Is;
 
+        double a;
+        double b;
+        double d;
+
         // Antialiasing error threshold
-        float thresh;
-        float half_a;
-        float longthing;
+        double thresh;
+        double half_a;
+        double longthing;
 
     } _tLockhartWavefolder;
     
@@ -54,6 +54,27 @@
     
     //==============================================================================
     
+
+
+    typedef struct _tSampleReducer
+    {
+        float invRatio;
+        float hold;
+        uint32_t count;
+    } _tSampleReducer;
+
+    typedef _tSampleReducer* tSampleReducer;
+
+    void    tSampleReducer_init    (tSampleReducer* const);
+    void    tSampleReducer_free    (tSampleReducer* const);
+
+    float   tSampleReducer_tick    (tSampleReducer* const, float input);
+
+    // sampling ratio
+    void    tSampleReducer_setRatio (tSampleReducer* const, float ratio);
+
+    //==============================================================================
+
     typedef struct _tCrusher
     {
         float srr;
@@ -63,6 +84,7 @@
         uint32_t  op; //which bitwise operation (0-7)
         
         float gain;
+        tSampleReducer sReducer;
         
     } _tCrusher;
     
@@ -85,7 +107,9 @@
     // sampling ratio
     void    tCrusher_setSamplingRatio (tCrusher* const, float ratio);
     
+
     //==============================================================================
+
     
     typedef struct _tOversampler
     {
binary files a/LEAF/Src/.DS_Store b/LEAF/Src/.DS_Store differ
--- a/LEAF/Src/leaf-distortion.c
+++ b/LEAF/Src/leaf-distortion.c
@@ -16,11 +16,17 @@
 #include "../Inc/leaf-distortion.h"
 #include "../Inc/leaf-tables.h"
 
+
 #endif
 
 //============================================================================================================
 // WAVEFOLDER
 //============================================================================================================
+
+
+//from the paper: Virtual Analog Model of the Lockhart Wavefolder
+//by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao
+
 void tLockhartWavefolder_init(tLockhartWavefolder* const wf)
 {
     _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder));
@@ -37,9 +43,10 @@
     w->a = 2.0*w->RL/w->R;
     w->b = (w->R+2.0*w->RL)/(w->VT*w->R);
     w->d = (w->RL*w->Is)/w->VT;
-    w->half_a = 0.5f * w->a;
+    w->half_a = 0.5 * w->a;
     w->longthing = (0.5*w->VT/w->b);
 
+
     // Antialiasing error threshold
     w->thresh = 10e-10;
 }
@@ -55,28 +62,26 @@
 {
     double thresh, w, expw, p, r, s, err;
     // Error threshold
-    thresh = 10e-6;
+    thresh = 10e-10;
     // Initial guess (use previous value)
     w = ln;
     
     // Haley's method (Sec. 4.2 of the paper)
-    for(int i=0; i<100; i+=1) {
+    for(int i=0; i<1000; i+=1) {
         
         expw = exp(w);
         
         p = w*expw - x;
         r = (w+1.0)*expw;
-        s = (w+2.0)/(2.0*(w+1.0));        err = (p/(r-(p*s)));
+        s = (w+2.0)/(2.0*(w+1.0));
+        err = (p/(r-(p*s)));
         
         if (fabs(err)<thresh) {
-            break;
+        	break;
         }
-        if (isnan(err))
-        {
-            break;
-        }
         
         w = w - err;
+
     }
     return w;
 }
@@ -86,11 +91,9 @@
     _tLockhartWavefolder* w = *wf;
     
     float out = 0.0f;
-    // Constants
-
     
     // Compute Antiderivative
-    int l = (samp > 0) - (samp < 0);
+    int l = (samp > 0.0f) - (samp < 0.0f);
     double u = w->d*exp(l*w->b*samp);
     double Ln = tLockhartWavefolderLambert(u,w->Ln1);
     double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp;
@@ -99,14 +102,10 @@
     if (fabs(samp-w->xn1)<w->thresh) {
         
         // Compute Averaged Wavefolder Output
-        double xn = 0.5*(samp+w->xn1);
+        float xn = 0.5f*(samp+w->xn1);
         u = w->d*exp(l*w->b*xn);
         Ln = tLockhartWavefolderLambert(u,w->Ln1);
         out = (float) (l*w->VT*Ln - w->a*xn);
-        if (isnan(out))
-        {
-            ;
-        }
 
     }
     else {
@@ -113,10 +112,6 @@
         
         // Apply AA Form
         out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
-        if (isnan(out))
-        {
-            ;
-        }
     }
     
     // Update States
@@ -140,7 +135,7 @@
     c->div = SCALAR;
     c->rnd = 0.25f;
     c->srr = 0.25f;
-    
+    tSampleReducer_init(&c->sReducer);
     c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
 }
 
@@ -147,7 +142,7 @@
 void    tCrusher_free    (tCrusher* const cr)
 {
     _tCrusher* c = *cr;
-    
+    tSampleReducer_free(&c->sReducer);
     leaf_free(c);
 }
 
@@ -169,7 +164,7 @@
     
     sample = LEAF_round(sample, c->rnd);
     
-    sample = LEAF_reduct(sample, c->srr);
+    sample = tSampleReducer_tick(&c->sReducer, sample);
     
     return sample * c->gain;
     
@@ -204,9 +199,56 @@
 {
     _tCrusher* c = *cr;
     c->srr = ratio;
+    tSampleReducer_setRatio(&c->sReducer, ratio);
+
 }
 
+//============================================================================================================
+// Sample-Rate reducer
+//============================================================================================================
 
+
+void tSampleReducer_init(tSampleReducer* const sr)
+{
+	_tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer));
+
+
+
+	s->invRatio = 1.0f;
+	s->hold = 0.0f;
+	s->count = 0;
+
+}
+
+void    tSampleReducer_free    (tSampleReducer* const sr)
+{
+	_tSampleReducer* s = *sr;
+
+    leaf_free(s);
+}
+
+float tSampleReducer_tick(tSampleReducer* const sr, float input)
+{
+	_tSampleReducer* s = *sr;
+    if (s->count > s->invRatio)
+    {
+        s->hold = input;
+        s->count = 0;
+    }
+
+    s->count++;
+    return s->hold;
+}
+
+
+void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio)
+{
+	 _tSampleReducer* s = *sr;
+	if ((ratio <= 1.0f) && (ratio >= 0.0f))
+	s->invRatio = 1.0f / ratio;
+
+}
+
 //============================================================================================================
 // Oversampler
 //============================================================================================================
@@ -411,7 +453,7 @@
     output = acc0;
     
     /* Processing is complete.
-     Now copy the last numTaps - 1 samples to the satrt of the state buffer.
+     Now copy the last numTaps - 1 samples to the start of the state buffer.
      This prepares the state buffer for the next function call. */
     
     /* Points to the start of the state buffer */
--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -165,23 +165,6 @@
     return shaperOut;
 }
 
-// reduce sample resolution
-float hold = 0.f;
-int reduct_count = 0;
-
-
-float LEAF_reduct (float input, float ratio)
-{
-    reduct_count++;
-    if (reduct_count > 1.f / ratio)
-    {
-        hold = input;
-        reduct_count = 0;
-    }
-    
-    return hold;
-}
-
 // round input to nearest rnd
 float LEAF_round (float input, float rnd)
 {
@@ -270,12 +253,12 @@
 float LEAF_tanh(float x)
 {
     
-    if( x < -3 )
-        return -1;
-    else if( x > 3 )
-        return 1;
+    if( x < -3.0f )
+        return -1.0f;
+    else if( x > 3.0f )
+        return 1.0f;
     else
-        return x * ( 27 + x * x ) / ( 27 + 9 * x * x );
+        return x * ( 27.0f + x * x ) / ( 27.0f + 9.0f * x * x );
 }