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