shithub: leaf

Download patch

ref: a3ed8625546600dec04297ea012fd597cac20e76
parent: 77f3ac50b351c86af9a608e402428cc73b0cd726
author: spiricom <jeff@snyderphonics.com>
date: Sun Jun 7 21:53:33 EDT 2020

added float tTalkbox

--- a/leaf/Inc/leaf-effects.h
+++ b/leaf/Inc/leaf-effects.h
@@ -1,8 +1,7 @@
 /*==============================================================================
  
  leaf-effects.h
- Created: 20 Jan 2017 12:01:54pm
- Author:  Michael R Mulshine
+
  
  ==============================================================================*/
 
@@ -21,14 +20,8 @@
 #include "leaf-analysis.h"
 #include "leaf-envelopes.h"
     
-    /*!
-     * @internal
-     * Header.
-     * @include basic-oscillators.h
-     * @example basic-oscillators.c
-     * An example.
-     */
-    
+
+
     //==============================================================================
     
     /* tTalkbox */
@@ -37,7 +30,7 @@
     typedef struct _tTalkbox
     {
         float param[NUM_TALKBOX_PARAM];
-        
+
         int bufsize;
         float* car0;
         float* car1;
@@ -44,16 +37,16 @@
         float* window;
         float* buf0;
         float* buf1;
-        
+        float* k;
         float warpFactor;
         int32_t warpOn;
-
+        int freeze;
         float emphasis;
         int32_t K, N, O, pos;
         float wet, dry, FX;
         float d0, d1, d2, d3, d4;
         float u0, u1, u2, u3, u4;
-        
+        float G;
         double* dl;
         double* Rt;
 
@@ -68,16 +61,69 @@
     void    tTalkbox_freeFromPool   (tTalkbox* const, tMempool* const);
     
     float   tTalkbox_tick           (tTalkbox* const, float synth, float voice);
+    float 	tTalkbox_tickFrozen		(tTalkbox* const voc, float synth, float voice);
     void    tTalkbox_update         (tTalkbox* const);
     void    tTalkbox_suspend        (tTalkbox* const);
     void    tTalkbox_lpcDurbin      (float *r, int p, float *k, float *g);
-    void 	tTalkbox_lpc			(float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn);
+    void 	tTalkbox_lpc			(float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G);
     void    tTalkbox_setQuality     (tTalkbox* const, float quality);
-    void 	tTalkbox_setWarpFactor		(tTalkbox* const voc, float warp);
+    void 	tTalkbox_setWarpFactor	(tTalkbox* const voc, float warp);
     void 	tTalkbox_setWarpOn		(tTalkbox* const voc, float warpOn);
+    void 	tTalkbox_setFreeze		(tTalkbox* const voc, float freeze);
     void 	tTalkbox_warpedAutocorrelate	(float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda);
     //==============================================================================
     
+
+    ///////
+
+    typedef struct _tTalkboxFloat
+      {
+          float param[NUM_TALKBOX_PARAM];
+
+          int bufsize;
+          float* car0;
+          float* car1;
+          float* window;
+          float* buf0;
+          float* buf1;
+          float* k;
+          float warpFactor;
+          int32_t warpOn;
+          int freeze;
+          float emphasis;
+          int32_t K, N, O, pos;
+          float wet, dry, FX;
+          float d0, d1, d2, d3, d4;
+          float u0, u1, u2, u3, u4;
+          float G;
+          float* dl;
+          float* Rt;
+
+
+      } _tTalkboxFloat;
+
+      typedef _tTalkboxFloat* tTalkboxFloat;
+
+      void    tTalkboxFloat_init           (tTalkboxFloat* const, int bufsize);
+      void    tTalkboxFloat_free           (tTalkboxFloat* const);
+      void    tTalkboxFloat_initToPool     (tTalkboxFloat* const, int bufsize, tMempool* const);
+      void    tTalkboxFloat_freeFromPool   (tTalkboxFloat* const, tMempool* const);
+
+      float   tTalkboxFloat_tick           (tTalkboxFloat* const, float synth, float voice);
+      float 	tTalkboxFloat_tickFrozen		(tTalkboxFloat* const voc, float synth, float voice);
+      void    tTalkboxFloat_update         (tTalkboxFloat* const);
+      void    tTalkboxFloat_suspend        (tTalkboxFloat* const);
+      void    tTalkboxFloat_lpcDurbin      (float *r, int p, float *k, float *g);
+      void 	tTalkboxFloat_lpc			(float *buf, float *car, float* dl, float* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G);
+      void    tTalkboxFloat_setQuality     (tTalkboxFloat* const, float quality);
+      void 	tTalkboxFloat_setWarpFactor	(tTalkboxFloat* const voc, float warp);
+      void 	tTalkboxFloat_setWarpOn		(tTalkboxFloat* const voc, float warpOn);
+      void 	tTalkboxFloat_setFreeze		(tTalkboxFloat* const voc, float freeze);
+      void 	tTalkboxFloat_warpedAutocorrelate	(float * x, float* dl, float* Rt, unsigned int L, float * R, unsigned int P, float lambda);
+      //==============================================================================
+
+
+
     /* tVocoder */
 #define NUM_VOCODER_PARAM 8
 #define NBANDS 16
@@ -132,7 +178,7 @@
 	void    tRosenbergGlottalPulse_freeFromPool   (tRosenbergGlottalPulse* const, tMempool* const);
 
 	float   tRosenbergGlottalPulse_tick           (tRosenbergGlottalPulse* const);
-
+	float   tRosenbergGlottalPulse_tickHQ           (tRosenbergGlottalPulse* const gp);
 	void   tRosenbergGlottalPulse_setFreq           (tRosenbergGlottalPulse* const, float freq);
 
 	void   tRosenbergGlottalPulse_setOpenLength           (tRosenbergGlottalPulse* const, float openLength);
@@ -284,7 +330,7 @@
         float radius;
         
         float inputPeriod;
-        
+        int shiftOn;
         int numVoices;
     } _tAutotune;
     
--- a/leaf/Inc/leaf-math.h
+++ b/leaf/Inc/leaf-math.h
@@ -204,6 +204,8 @@
 
     float fastdbtoa(float db);
 
+    float fasterdbtoa(float db);
+
     float maximum (float num1, float num2);
 
     float minimum (float num1, float num2);
--- a/leaf/Inc/leaf-physical.h
+++ b/leaf/Inc/leaf-physical.h
@@ -228,7 +228,55 @@
     void    tLivingString_setLevStrength        (tLivingString* const, float levStrength);
     void    tLivingString_setLevMode            (tLivingString* const, int levMode);
     
+
+
+        // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+    /* Complex Living String */
+    typedef struct _tComplexLivingString {
+        float freq, waveLengthInSamples;        // the frequency of the whole string, determining delay length
+        float pickPos;    // the pick position, dividing the string, in ratio
+        float prepPos;    // preparation position, in ratio
+        int prepLower;
+        float prepIndex;    // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj)
+        float dampFreq;    // frequency for the bridge LP filter, in Hz
+        float decay; // amplitude damping factor for the string (only active in mode 0)
+        float levMode;
+        float curr;
+        tLinearDelay delLF,delUF, delMF, delMB, delUB,delLB;    // delay for lower/upper/forward/backward part of the waveguide model
+        tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL;
+        tHighpass DCblockerL, DCblockerU;
+        tFeedbackLeveler fbLevU, fbLevL;
+        tExpSmooth wlSmooth, pickPosSmooth, prepPosSmooth;
+    } _tComplexLivingString;
+
+    typedef _tComplexLivingString* tComplexLivingString;
+
+    void    tComplexLivingString_init                  (tComplexLivingString* const, float freq, float pickPos, float prepPos, float prepIndex,
+                                                 float dampFreq, float decay, float targetLev, float levSmoothFactor,
+                                                 float levStrength, int levMode);
+    void    tComplexLivingString_free                  (tComplexLivingString* const);
+    void    tComplexLivingString_initToPool            (tComplexLivingString* const, float freq, float pickPos, float prepPos, float prepIndex,
+                                                 float dampFreq, float decay, float targetLev, float levSmoothFactor,
+                                                 float levStrength, int levMode, tMempool* const);
+    void    tComplexLivingString_freeFromPool          (tComplexLivingString* const, tMempool* const);
+
+    float   tComplexLivingString_tick                  (tComplexLivingString* const, float input);
+    float   tComplexLivingString_sample                (tComplexLivingString* const);
+    void    tComplexLivingString_setFreq               (tComplexLivingString* const, float freq);
+    void    tComplexLivingString_setWaveLength         (tComplexLivingString* const, float waveLength); // in samples
+    void    tComplexLivingString_setPickPos            (tComplexLivingString* const, float pickPos);
+    void    tComplexLivingString_setPrepPos            (tComplexLivingString* const, float prepPos);
+    void    tComplexLivingString_setPrepIndex          (tComplexLivingString* const, float prepIndex);
+    void    tComplexLivingString_setDampFreq           (tComplexLivingString* const, float dampFreq);
+    void    tComplexLivingString_setDecay              (tComplexLivingString* const, float decay); // should be near 1.0
+    void    tComplexLivingString_setTargetLev          (tComplexLivingString* const, float targetLev);
+    void    tComplexLivingString_setLevSmoothFactor    (tComplexLivingString* const, float levSmoothFactor);
+    void    tComplexLivingString_setLevStrength        (tComplexLivingString* const, float levStrength);
+    void    tComplexLivingString_setLevMode            (tComplexLivingString* const, int levMode);
     // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+    
     
     //Reed Table - borrowed from STK
     typedef struct _tReedTable {
--- a/leaf/Inc/leaf-sampling.h
+++ b/leaf/Inc/leaf-sampling.h
@@ -69,6 +69,7 @@
     void  tBuffer_record                (tBuffer* const);
     void  tBuffer_stop                  (tBuffer* const);
     int   tBuffer_getRecordPosition     (tBuffer* const);
+    void   tBuffer_setRecordPosition     (tBuffer* const, int pos);
     
     void  tBuffer_setRecordMode         (tBuffer* const, RecordMode mode);
     
@@ -76,6 +77,8 @@
     
     uint32_t tBuffer_getBufferLength    (tBuffer* const);
     uint32_t tBuffer_getRecordedLength  (tBuffer* const sb);
+    void 	tBuffer_setRecordedLength	(tBuffer* const sb, int length);
+    int 	tBuffer_isActive			(tBuffer* const sb);
     
     //==============================================================================
     
--- a/leaf/Src/leaf-analysis.c
+++ b/leaf/Src/leaf-analysis.c
@@ -62,8 +62,10 @@
     //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?
     //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff;  // too expensive
     
+#ifdef NO_DENORMAL_CHECK
+#else
     if( e->y < VSF)   e->y = 0.0f;
-    
+#endif
     return e->y;
 }
 
@@ -887,7 +889,10 @@
     tEnvPD_initToPool(&p->env, p->windowSize, p->hopSize, p->frameSize, mp);
     
     tSNAC_initToPool(&p->snac, DEFOVERLAP, mp);
-    
+
+    p->history = 0.0f;
+    p->alpha = 1.0f;
+    p->tolerance = 1.0f;
     p->timeConstant = DEFTIMECONSTANT;
     p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
     p->fidelityThreshold = 0.95;
@@ -928,7 +933,10 @@
         tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
         float fidelity = tSNAC_getFidelity(&p->snac);
         // Fidelity threshold recommended by Katja Vetters is 0.95 for most instruments/voices http://www.katjaas.nl/helmholtz/helmholtz.html
-        if (fidelity > p->fidelityThreshold) p->period = tSNAC_getPeriod(&p->snac);
+        if (fidelity > p->fidelityThreshold)
+        {
+        	p->period = tSNAC_getPeriod(&p->snac);
+        }
         
         p->curBlock++;
         if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
@@ -935,7 +943,6 @@
         p->lastBlock++;
         if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
     }
-    
     return p->period;
 }
 
--- a/leaf/Src/leaf-effects.c
+++ b/leaf/Src/leaf-effects.c
@@ -25,6 +25,13 @@
 //============================================================================================================
 
 //LPC vocoder adapted from MDA's excellent open source talkbox plugin code
+
+#define ORD_MAX           34 // Was 100.
+// order is defined by the set_quality function.
+// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24.
+// -JS
+
+
 void tTalkbox_init(tTalkbox* const voc, int bufsize)
 {
     tTalkbox_initToPool(voc, bufsize, &leaf.mempool);
@@ -47,7 +54,8 @@
     v->warpFactor = 0.0f;
     v->warpOn = 0;
     v->bufsize = bufsize;
-    
+    v->freeze = 0;
+    v->G = 0.0f;
     v->car0 =   (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
     v->car1 =   (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
     v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
@@ -56,7 +64,9 @@
     
     v->dl = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);
     v->Rt = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);
-    
+
+    v->k = (float*) mpool_alloc(sizeof(float) * ORD_MAX, m);
+
     tTalkbox_update(voc);
     tTalkbox_suspend(voc);
 }
@@ -74,7 +84,7 @@
     
     mpool_free((char*)v->dl, m);
     mpool_free((char*)v->Rt, m);
-    
+    mpool_free((char*)v->k, m);
     mpool_free((char*)v, m);
 }
 
@@ -132,8 +142,6 @@
 //wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0);
 void tTalkbox_warpedAutocorrelate(float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda)
 {
-//    double dl[L];
-//    double Rt[L];
     double r1,r2,r1t;
     R[0]=0;
     Rt[0]=0;
@@ -140,30 +148,30 @@
     r1=0;
     r2=0;
     r1t=0;
-    for(int32_t k=0; k<L;k++)
+    for(uint32_t m=0; m<L;m++)
     {
-                    Rt[0] += (double)(x[k]) * (double)(x[k]);
+                    Rt[0] += (double)(x[m]) * (double)(x[m]);
 
-                    dl[k]= r1 - (double)(lambda) * (double)(x[k]-r2);
-                    r1 = x[k];
-                    r2 = dl[k];
+                    dl[m]= r1 - (double)(lambda) * (double)(x[m]-r2);
+                    r1 = x[m];
+                    r2 = dl[m];
     }
-    for(int32_t i=1; i<=P; i++)
+    for(uint32_t i=1; i<=P; i++)
     {
             Rt[i]=0;
             r1=0;
             r2=0;
-            for(unsigned int k=0; k<L;k++)
+            for(unsigned int m=0; m<L;m++)
             {
-                    Rt[i] += (double) (dl[k]) * (double)(x[k]);
+                    Rt[i] += (double) (dl[m]) * (double)(x[m]);
 
-                    r1t = dl[k];
-                    dl[k]= r1 - (double)(lambda) * (double)(r1t-r2);
+                    r1t = dl[m];
+                    dl[m]= r1 - (double)(lambda) * (double)(r1t-r2);
                     r1 = r1t;
-                    r2 = dl[k];
+                    r2 = dl[m];
             }
     }
-    for(int32_t i=0; i<=P; i++)
+    for(uint32_t i=0; i<=P; i++)
     {
             R[i]=(float)(Rt[i]);
     }
@@ -170,51 +178,137 @@
 
 }
 
-
-
-#define ORD_MAX           35 // Was 100.
-// order is defined by the set_quality function.
-// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24.
-// -JS
-void tTalkbox_lpc(float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn)
+void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
 {
-    float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;
-    int32_t i, j, nn=n;
-    
-    if (warpOn == 0)
+    int i, j;
+    float a[ORD_MAX], at[ORD_MAX], e=r[0];
+
+    for(i=0; i<=p; i++)
     {
-        for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
-        {
-            z[j] = r[j] = 0.0f;
-            for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
-        }
+    	a[i] = 0.0f; //probably don't need to clear at[] or k[]
     }
-    else
+	k[0] = 0.0f;
+    at[0] = 0.0f;
+    for(i=1; i<=p; i++)
     {
-        for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
+        k[i] = -r[i];
+
+        for(j=1; j<i; j++)
         {
-            z[j] = r[j] = 0.0f;
+            at[j] = a[j];
+            k[i] -= a[j] * r[i-j];
         }
-    	tTalkbox_warpedAutocorrelate(buf, dl, Rt, n, r, o, warp);
+        if(fabs(e) < 1.0e-20f) { e = 0.0f;  break; }
+        k[i] /= e;
+
+        a[i] = k[i];
+        for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
+
+        e *= 1.0f - k[i] * k[i];
     }
 
-    r[0] *= 1.001f;  //stability fix
+    if(e < 1.0e-20f) e = 0.0f;
+    *g = sqrtf(e);
+}
+
+float tTalkbox_tick(tTalkbox* const voc, float synth, float voice)
+{
+    _tTalkbox* v = *voc;
     
-    float min = 0.00001f;
-    if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; }
+    int32_t  p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
+    float e=v->emphasis, w, o, x, fx=v->FX;
+    float p, q, h0=0.3f, h1=0.77f;
     
-    tTalkbox_lpcDurbin(r, o, k, &G);  //calc reflection coeffs
+    o = voice;
+    x = synth;
     
-    //this is for stability to keep reflection coefficients inside the unit circle
-    //but in Harma's papers I've seen 0.998.  just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS
-    for(i=0; i<=o; i++)
+
+
+    p = v->d0 + h0 *  x; v->d0 = v->d1;  v->d1 = x  - h0 * p;
+    q = v->d2 + h1 * v->d4; v->d2 = v->d3;  v->d3 = v->d4 - h1 * q;
+    v->d4 = x;
+    x = p + q;
+    
+    if(v->K++)
     {
-        if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;
+        v->K = 0;
+        
+        v->car0[p0] = v->car1[p1] = x; //carrier input
+        
+        x = o - e;  e = o;  //6dB/oct pre-emphasis
+        
+        w = v->window[p0]; fx = v->buf0[p0] * w;  v->buf0[p0] = x * w;  //50% overlapping hanning windows
+        if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G);  p0 = 0; }
+        
+        w = 1.0f - w;  fx += v->buf1[p1] * w;  v->buf1[p1] = x * w;
+        if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G);  p1 = 0; }
     }
     
+    p = v->u0 + h0 * fx; v->u0 = v->u1;  v->u1 = fx - h0 * p;
+    q = v->u2 + h1 * v->u4; v->u2 = v->u3;  v->u3 = v->u4 - h1 * q;
+    v->u4 = fx;
+    x = p + q;
+    
+    o = x;
+    
+    v->emphasis = e;
+    v->pos = p0;
+    v->FX = fx;
+    
+
+    return o;
+}
+
+
+void tTalkbox_lpc(float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G)
+{
+    float z[ORD_MAX], r[ORD_MAX], x;
+    int32_t i, j, nn=n;
+
+
+	if (warpOn == 0)
+	{
+		for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
+		{
+			z[j] = r[j] = 0.0f;
+			for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
+		}
+	}
+	else
+	{
+		for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
+		{
+			z[j] = r[j] = 0.0f;
+		}
+		tTalkbox_warpedAutocorrelate(buf, dl, Rt, n, r, o, warp);
+	}
+
+	r[0] *= 1.001f;  //stability fix
+
+	float min = 0.000001f;
+	if (!freeze)
+	{
+		if(r[0] < min)
+		{
+			for(i=0; i<n; i++)
+			{
+				buf[i] = 0.0f;
+				return;
+			}
+		}
+
+		tTalkbox_lpcDurbin(r, o, k, G);  //calc reflection coeffs
+
+		//this is for stability to keep reflection coefficients inside the unit circle
+		//in mda's code it's .995 but in Harma's papers I've seen 0.998.  just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS
+		for(i=0; i<=o; i++)
+		{
+			if(k[i] > 0.998f) k[i] = 0.998f; else if(k[i] < -0.998f) k[i] = -.998f;
+		}
+    }
     for(i=0; i<n; i++)
     {
-        x = G * car[i];
+        x = G[0] * car[i];
         for(j=o; j>0; j--)  //lattice filter
         {
             x -= k[j] * z[j-1];
@@ -224,18 +318,213 @@
     }
 }
 
+void tTalkbox_setQuality(tTalkbox* const voc, float quality)
+{
+    _tTalkbox* v = *voc;
+    v->param[3] = quality;
+    v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
+    if (v->O >= ORD_MAX)
+    {
+    	v->O = ORD_MAX-1;
+    }
+}
 
-void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
+void tTalkbox_setWarpFactor(tTalkbox* const voc, float warpFactor)
 {
+    _tTalkbox* v = *voc;
+
+    v->warpFactor = warpFactor;
+}
+
+void tTalkbox_setWarpOn(tTalkbox* const voc, float warpOn)
+{
+    _tTalkbox* v = *voc;
+
+    v->warpOn = warpOn;
+}
+
+void tTalkbox_setFreeze(tTalkbox* const voc, float freeze)
+{
+    _tTalkbox* v = *voc;
+
+    v->freeze = freeze;
+}
+
+
+
+////
+
+// LPC vocoder adapted from MDA's excellent open source talkbox plugin code
+// order is defined by the set_quality function.
+// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24.
+
+//the "float" version has no double calculations for faster computation on single-precision FPUs
+
+// -JS
+
+
+void tTalkboxFloat_init(tTalkboxFloat* const voc, int bufsize)
+{
+    tTalkboxFloat_initToPool(voc, bufsize, &leaf.mempool);
+}
+
+void tTalkboFloat_free(tTalkboxFloat* const voc)
+{
+    tTalkboxFloat_freeFromPool(voc, &leaf.mempool);
+}
+
+void    tTalkboxFloat_initToPool     (tTalkboxFloat* const voc, int bufsize, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tTalkboxFloat* v = *voc = (_tTalkboxFloat*) mpool_alloc(sizeof(_tTalkboxFloat), m);
+
+    v->param[0] = 0.5f;  //wet
+    v->param[1] = 0.0f;  //dry
+    v->param[2] = 0; // Swap
+    v->param[3] = 1.0f;  //quality
+    v->warpFactor = 0.0f;
+    v->warpOn = 0;
+    v->bufsize = bufsize;
+    v->freeze = 0;
+    v->G = 0.0f;
+    v->car0 =   (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+    v->car1 =   (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+    v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+    v->buf0 =   (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+    v->buf1 =   (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+
+    v->dl = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+    v->Rt = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
+
+    v->k = (float*) mpool_alloc(sizeof(float) * ORD_MAX, m);
+
+    tTalkboxFloat_update(voc);
+    tTalkboxFloat_suspend(voc);
+}
+
+void    tTalkboxFloat_freeFromPool   (tTalkboxFloat* const voc, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tTalkboxFloat* v = *voc;
+
+    mpool_free((char*)v->buf1, m);
+    mpool_free((char*)v->buf0, m);
+    mpool_free((char*)v->window, m);
+    mpool_free((char*)v->car1, m);
+    mpool_free((char*)v->car0, m);
+
+    mpool_free((char*)v->dl, m);
+    mpool_free((char*)v->Rt, m);
+    mpool_free((char*)v->k, m);
+    mpool_free((char*)v, m);
+}
+
+void tTalkboxFloat_update(tTalkboxFloat* const voc) ///update internal parameters...
+{
+    _tTalkboxFloat* v = *voc;
+
+    float fs = leaf.sampleRate;
+    if(fs <  8000.0f) fs =  8000.0f;
+    if(fs > 96000.0f) fs = 96000.0f;
+
+    int32_t n = (int32_t)(0.01633f * fs); //this sets the window time to 16ms if the buffer is large enough. Buffer needs to be at least 784 samples at 48000
+    if(n > v->bufsize) n = v->bufsize;
+
+    //O = (VstInt32)(0.0005f * fs);
+    v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs);
+
+    if(n != v->N) //recalc hanning window
+    {
+        v->N = n;
+        float dp = TWO_PI / v->N;
+        float p = 0.0f;
+        for(n=0; n<v->N; n++)
+        {
+            v->window[n] = 0.5f - 0.5f * cosf(p);
+            p += dp;
+        }
+    }
+    v->wet = 0.5f * v->param[0] * v->param[0];
+    v->dry = 2.0f * v->param[1] * v->param[1];
+}
+
+void tTalkboxFloat_suspend(tTalkboxFloat* const voc) ///clear any buffers...
+{
+    _tTalkboxFloat* v = *voc;
+
+    v->pos = v->K = 0;
+    v->emphasis = 0.0f;
+    v->FX = 0;
+
+    v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f;
+    v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f;
+
+    for (int32_t i = 0; i < v->bufsize; i++)
+    {
+        v->buf0[i] = 0;
+        v->buf1[i] = 0;
+        v->car0[i] = 0;
+        v->car1[i] = 0;
+    }
+}
+
+// warped autocorrelation adapted from ten.enegatum@liam's post on music-dsp 2004-04-07 09:37:51
+//find the order-P autocorrelation array, R, for the sequence x of length L and warping of lambda
+//wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0);
+void tTalkboxFloat_warpedAutocorrelate(float * x, float* dl, float* Rt, unsigned int L, float * R, unsigned int P, float lambda)
+{
+    float r1,r2,r1t;
+    R[0]=0;
+    Rt[0]=0;
+    r1=0;
+    r2=0;
+    r1t=0;
+    for(uint32_t m=0; m<L;m++)
+    {
+                    Rt[0] += (x[m]) * (x[m]);
+
+                    dl[m]= r1 - lambda * (x[m]-r2);
+                    r1 = x[m];
+                    r2 = dl[m];
+    }
+    for(uint32_t i=1; i<=P; i++)
+    {
+            Rt[i]=0;
+            r1=0;
+            r2=0;
+            for(unsigned int m=0; m<L;m++)
+            {
+                    Rt[i] +=  (dl[m]) * (x[m]);
+
+                    r1t = dl[m];
+                    dl[m]= r1 - lambda * (r1t-r2);
+                    r1 = r1t;
+                    r2 = dl[m];
+            }
+    }
+    for(uint32_t i=0; i<=P; i++)
+    {
+            R[i]=Rt[i];
+    }
+
+}
+
+void tTalkboxFloat_lpcDurbin(float *r, int p, float *k, float *g)
+{
     int i, j;
     float a[ORD_MAX], at[ORD_MAX], e=r[0];
-    
-    for(i=0; i<=p; i++) a[i] = 0.0f; //probably don't need to clear at[] or k[]
+
+    for(i=0; i<=p; i++)
+    {
+    	a[i] = 0.0f; //probably don't need to clear at[]
+
+    }
+	k[0] = 0.0f;
     at[0] = 0.0f;
     for(i=1; i<=p; i++)
     {
         k[i] = -r[i];
-        
+
         for(j=1; j<i; j++)
         {
             at[j] = a[j];
@@ -243,69 +532,127 @@
         }
         if(fabs(e) < 1.0e-20f) { e = 0.0f;  break; }
         k[i] /= e;
-        
+
         a[i] = k[i];
         for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
-        
+
         e *= 1.0f - k[i] * k[i];
     }
-    
+
     if(e < 1.0e-20f) e = 0.0f;
     *g = sqrtf(e);
 }
 
-float tTalkbox_tick(tTalkbox* const voc, float synth, float voice)
+float tTalkboxFloat_tick(tTalkboxFloat* const voc, float synth, float voice)
 {
-    _tTalkbox* v = *voc;
-    
+    _tTalkboxFloat* v = *voc;
+
     int32_t  p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
     float e=v->emphasis, w, o, x, fx=v->FX;
     float p, q, h0=0.3f, h1=0.77f;
-    
+
     o = voice;
     x = synth;
-    
 
 
+
     p = v->d0 + h0 *  x; v->d0 = v->d1;  v->d1 = x  - h0 * p;
     q = v->d2 + h1 * v->d4; v->d2 = v->d3;  v->d3 = v->d4 - h1 * q;
     v->d4 = x;
     x = p + q;
-    
+
     if(v->K++)
     {
         v->K = 0;
-        
+
         v->car0[p0] = v->car1[p1] = x; //carrier input
-        
+
         x = o - e;  e = o;  //6dB/oct pre-emphasis
-        
+
         w = v->window[p0]; fx = v->buf0[p0] * w;  v->buf0[p0] = x * w;  //50% overlapping hanning windows
-        if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn);  p0 = 0; }
-        
+        if(++p0 >= v->N) { tTalkboxFloat_lpc(v->buf0, v->car0, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G);  p0 = 0; }
+
         w = 1.0f - w;  fx += v->buf1[p1] * w;  v->buf1[p1] = x * w;
-        if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn);  p1 = 0; }
+        if(++p1 >= v->N) { tTalkboxFloat_lpc(v->buf1, v->car1, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G);  p1 = 0; }
     }
-    
+
     p = v->u0 + h0 * fx; v->u0 = v->u1;  v->u1 = fx - h0 * p;
     q = v->u2 + h1 * v->u4; v->u2 = v->u3;  v->u3 = v->u4 - h1 * q;
     v->u4 = fx;
     x = p + q;
-    
+
     o = x;
-    
+
     v->emphasis = e;
     v->pos = p0;
     v->FX = fx;
-    
 
+
     return o;
 }
 
-void tTalkbox_setQuality(tTalkbox* const voc, float quality)
+
+void tTalkboxFloat_lpc(float *buf, float *car, float* dl, float* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G)
 {
-    _tTalkbox* v = *voc;
-    
+    float z[ORD_MAX], r[ORD_MAX], x;
+    int32_t i, j, nn=n;
+
+
+	if (warpOn == 0)
+	{
+		for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
+		{
+			z[j] = r[j] = 0.0f;
+			for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
+		}
+	}
+	else
+	{
+		for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
+		{
+			z[j] = r[j] = 0.0f;
+		}
+		tTalkboxFloat_warpedAutocorrelate(buf, dl, Rt, n, r, o, warp);
+	}
+
+	r[0] *= 1.001f;  //stability fix
+
+	float min = 0.000001f;
+	if (!freeze)
+	{
+		if(r[0] < min)
+		{
+			for(i=0; i<n; i++)
+			{
+				buf[i] = 0.0f;
+				return;
+			}
+		}
+
+		tTalkbox_lpcDurbin(r, o, k, G);  //calc reflection coeffs
+
+		//this is for stability to keep reflection coefficients inside the unit circle
+		//but in Harma's papers I've seen 0.998.  just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS
+		for(i=0; i<=o; i++)
+		{
+			if(k[i] > 0.998f) k[i] = 0.998f; else if(k[i] < -0.998f) k[i] = -.998f;
+		}
+    }
+    for(i=0; i<n; i++)
+    {
+        x = G[0] * car[i];
+        for(j=o; j>0; j--)  //lattice filter
+        {
+            x -= k[j] * z[j-1];
+            z[j] = z[j-1] + k[j] * x;
+        }
+        buf[i] = z[0] = x;  //output buf[] will be windowed elsewhere
+    }
+}
+
+void tTalkboxFloat_setQuality(tTalkboxFloat* const voc, float quality)
+{
+    _tTalkboxFloat* v = *voc;
     v->param[3] = quality;
     v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
     if (v->O >= ORD_MAX)
@@ -314,21 +661,28 @@
     }
 }
 
-void tTalkbox_setWarpFactor(tTalkbox* const voc, float warpFactor)
+void tTalkboxFloat_setWarpFactor(tTalkboxFloat* const voc, float warpFactor)
 {
-    _tTalkbox* v = *voc;
+    _tTalkboxFloat* v = *voc;
 
     v->warpFactor = warpFactor;
 }
 
-void tTalkbox_setWarpOn(tTalkbox* const voc, float warpOn)
+void tTalkboxFloat_setWarpOn(tTalkboxFloat* const voc, float warpOn)
 {
-    _tTalkbox* v = *voc;
+    _tTalkboxFloat* v = *voc;
 
     v->warpOn = warpOn;
 }
 
+void tTalkboxFloat_setFreeze(tTalkboxFloat* const voc, float freeze)
+{
+    _tTalkboxFloat* v = *voc;
 
+    v->freeze = freeze;
+}
+
+
 //============================================================================================================
 // VOCODER
 //============================================================================================================
@@ -374,7 +728,7 @@
     
     float tpofs = 6.2831853f * leaf.invSampleRate;
     
-    float rr, th, re;
+    float rr, th;
     
     float sh;
     
@@ -389,7 +743,7 @@
     if(v->param[7]<0.5f)
     {
         v->nbnd=8;
-        re=0.003f;
+
         v->f[1][2] = 3000.0f;
         v->f[2][2] = 2200.0f;
         v->f[3][2] = 1500.0f;
@@ -401,7 +755,7 @@
     else
     {
         v->nbnd=16;
-        re=0.0015f;
+
         v->f[ 1][2] = 5000.0f; //+1000
         v->f[ 2][2] = 4000.0f; //+750
         v->f[ 3][2] = 3250.0f; //+500
@@ -588,6 +942,35 @@
     return output;
 }
 
+
+float   tRosenbergGlottalPulse_tickHQ           (tRosenbergGlottalPulse* const gp)
+{
+    _tRosenbergGlottalPulse* g = *gp;
+
+    float output = 0.0f;
+
+    // Phasor increment
+    g->phase += g->inc;
+    while (g->phase >= 1.0f) g->phase -= 1.0f;
+    while (g->phase < 0.0f) g->phase += 1.0f;
+
+    if (g->phase < g->openLength)
+    {
+        output = 0.5f*(1.0f-cosf(PI * g->phase));
+    }
+
+    else if (g->phase < g->pulseLength)
+    {
+        output = cosf(HALF_PI * (g->phase-g->openLength)* g->invPulseLengthMinusOpenLength);
+    }
+
+    else
+    {
+        output = 0.0f;
+    }
+    return output;
+}
+
 void   tRosenbergGlottalPulse_setFreq           (tRosenbergGlottalPulse* const gp, float freq)
 {
     _tRosenbergGlottalPulse* g = *gp;
@@ -999,7 +1382,7 @@
 
 void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize)
 {
-    tPitchShift_freeFromPool(psr, &leaf.mempool);
+    tPitchShift_initToPool(psr, pd, out, bufSize, &leaf.mempool);
 }
 
 void tPitchShift_free(tPitchShift* const psr)
@@ -1386,6 +1769,7 @@
     }
     
     r->inputPeriod = 0.0f;
+    r->shiftOn = 0;
 }
 
 void    tAutotune_freeFromPool      (tAutotune* const rt, tMempool* const mp)
--- a/leaf/Src/leaf-math.c
+++ b/leaf/Src/leaf-math.c
@@ -109,7 +109,7 @@
 
 // alternative implementation for abs()
 // REQUIRES: 32 bit floats
-float fastabsf(float f)
+inline float fastabsf(float f)
 {
     union
     {
@@ -130,7 +130,7 @@
     return x;
 }
 
-float fastexpf(float x) {
+inline float fastexpf(float x) {
     x = 1.0f + (x * 0.0009765625f);
     x *= x; x *= x; x *= x; x *= x;
     x *= x; x *= x; x *= x; x *= x;
@@ -145,7 +145,7 @@
     return x;
 }
 
-float fasterexpf(float x) {
+inline float fasterexpf(float x) {
     x = 1.0f + (x * 0.00390625f);
     x *= x; x *= x; x *= x; x *= x;
     x *= x; x *= x; x *= x; x *= x;
@@ -329,11 +329,16 @@
         tempmin = max;
         tempmax = min;
     }
-    if (val < tempmin) {
+    if (val < tempmin)
+    {
         return tempmin;
-    } else if (val > tempmax) {
+    }
+    else if (val > tempmax)
+    {
         return tempmax;
-    } else {
+    }
+    else
+    {
         return val;
     }
 }
@@ -696,6 +701,12 @@
 {
     //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
+}
+
+float fasterdbtoa(float db)
+{
+    //return powf(10.0f, db * 0.05f);
+    return fasterexpf(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
@@ -668,6 +668,252 @@
     return p->curr;
 }
 
+
+//////////---------------------------
+
+/* Complex Living String (has pick position and preparation position separated) */
+
+void    tComplexLivingString_init(tComplexLivingString* const pl, float freq, float pickPos, float prepPos, float prepIndex,
+                           float dampFreq, float decay, float targetLev, float levSmoothFactor,
+                           float levStrength, int levMode)
+{
+    tComplexLivingString_initToPool(pl, freq, pickPos, prepPos, prepIndex, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf.mempool);
+}
+
+void tComplexLivingString_free(tComplexLivingString* const pl)
+{
+    tComplexLivingString_freeFromPool(pl, &leaf.mempool);
+}
+
+void    tComplexLivingString_initToPool    (tComplexLivingString* const pl, float freq, float pickPos, float prepPos, float prepIndex,
+                                     float dampFreq, float decay, float targetLev, float levSmoothFactor,
+                                     float levStrength, int levMode, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tComplexLivingString* p = *pl = (_tComplexLivingString*) mpool_alloc(sizeof(_tComplexLivingString), m);
+
+    p->curr=0.0f;
+    tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
+    tComplexLivingString_setFreq(pl, freq);
+    p->freq = freq;
+    tExpSmooth_initToPool(&p->pickPosSmooth, pickPos, 0.01f, mp); // smoother for pick position
+    tExpSmooth_initToPool(&p->prepPosSmooth, prepPos, 0.01f, mp); // smoother for pick position
+
+    tComplexLivingString_setPickPos(pl, pickPos);
+    tComplexLivingString_setPrepPos(pl, prepPos);
+
+    p->prepPos=prepPos;
+    p->pickPos=pickPos;
+    tLinearDelay_initToPool(&p->delLF,p->waveLengthInSamples, 2400, mp);
+    tLinearDelay_initToPool(&p->delMF,p->waveLengthInSamples, 2400, mp);
+    tLinearDelay_initToPool(&p->delUF,p->waveLengthInSamples, 2400, mp);
+    tLinearDelay_initToPool(&p->delUB,p->waveLengthInSamples, 2400, mp);
+    tLinearDelay_initToPool(&p->delMB,p->waveLengthInSamples, 2400, mp);
+    tLinearDelay_initToPool(&p->delLB,p->waveLengthInSamples, 2400, mp);
+    tLinearDelay_clear(&p->delLF);
+    tLinearDelay_clear(&p->delMF);
+    tLinearDelay_clear(&p->delUF);
+    tLinearDelay_clear(&p->delUB);
+    tLinearDelay_clear(&p->delMB);
+    tLinearDelay_clear(&p->delLB);
+    p->dampFreq = dampFreq;
+    tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp);
+    tOnePole_initToPool(&p->nutFilter, dampFreq, mp);
+    tOnePole_initToPool(&p->prepFilterU, dampFreq, mp);
+    tOnePole_initToPool(&p->prepFilterL, dampFreq, mp);
+    tHighpass_initToPool(&p->DCblockerU,13, mp);
+    tHighpass_initToPool(&p->DCblockerL,13, mp);
+    p->decay=decay;
+    p->prepIndex = prepIndex;
+    tFeedbackLeveler_initToPool(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode, mp);
+    tFeedbackLeveler_initToPool(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode, mp);
+    p->levMode=levMode;
+}
+
+void    tComplexLivingString_freeFromPool  (tComplexLivingString* const pl, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tComplexLivingString* p = *pl;
+
+    tExpSmooth_freeFromPool(&p->wlSmooth, mp);
+    tExpSmooth_freeFromPool(&p->pickPosSmooth, mp);
+    tExpSmooth_freeFromPool(&p->prepPosSmooth, mp);
+    tLinearDelay_freeFromPool(&p->delLF, mp);
+    tLinearDelay_freeFromPool(&p->delMF, mp);
+    tLinearDelay_freeFromPool(&p->delUF, mp);
+    tLinearDelay_freeFromPool(&p->delUB, mp);
+    tLinearDelay_freeFromPool(&p->delMB, mp);
+    tLinearDelay_freeFromPool(&p->delLB, mp);
+    tOnePole_freeFromPool(&p->bridgeFilter, mp);
+    tOnePole_freeFromPool(&p->nutFilter, mp);
+    tOnePole_freeFromPool(&p->prepFilterU, mp);
+    tOnePole_freeFromPool(&p->prepFilterL, mp);
+    tHighpass_freeFromPool(&p->DCblockerU, mp);
+    tHighpass_freeFromPool(&p->DCblockerL, mp);
+    tFeedbackLeveler_freeFromPool(&p->fbLevU, mp);
+    tFeedbackLeveler_freeFromPool(&p->fbLevL, mp);
+
+    mpool_free((char*)p, m);
+}
+
+void     tComplexLivingString_setFreq(tComplexLivingString* const pl, float freq)
+{    // NOTE: It is faster to set wavelength in samples directly
+    _tComplexLivingString* p = *pl;
+    if (freq<20.0f) freq=20.0f;
+    else if (freq>10000.0f) freq=10000.0f;
+    p->waveLengthInSamples = leaf.sampleRate/freq;
+    tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+}
+
+void     tComplexLivingString_setWaveLength(tComplexLivingString* const pl, float waveLength)
+{
+    _tComplexLivingString* p = *pl;
+    if (waveLength<4.8f) waveLength=4.8f;
+    else if (waveLength>2400.0f) waveLength=2400.0f;
+    p->waveLengthInSamples = waveLength;
+    tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+}
+
+void     tComplexLivingString_setPickPos(tComplexLivingString* const pl, float pickPos)
+{    // between 0 and 1
+    _tComplexLivingString* p = *pl;
+    if (pickPos<0.5f) pickPos=0.5f;
+    else if (pickPos>1.f) pickPos=1.f;
+    p->pickPos = pickPos;
+    tExpSmooth_setDest(&p->pickPosSmooth, p->pickPos);
+}
+
+void     tComplexLivingString_setPrepPos(tComplexLivingString* const pl, float prepPos)
+{    // between 0 and 1
+    _tComplexLivingString* p = *pl;
+    if (prepPos<0.f) prepPos=0.f;
+    else if (prepPos>0.5f) prepPos=0.5f;
+    p->prepPos = prepPos;
+    tExpSmooth_setDest(&p->prepPosSmooth, p->prepPos);
+}
+
+void     tComplexLivingString_setPrepIndex(tComplexLivingString* const pl, float prepIndex)
+{    // between 0 and 1
+    _tComplexLivingString* p = *pl;
+    if (prepIndex<0.f) prepIndex=0.f;
+    else if (prepIndex>1.f) prepIndex=1.f;
+    p->prepIndex = prepIndex;
+}
+
+void     tComplexLivingString_setDampFreq(tComplexLivingString* const pl, float dampFreq)
+{
+    _tComplexLivingString* p = *pl;
+    tOnePole_setFreq(&p->bridgeFilter, dampFreq);
+    tOnePole_setFreq(&p->nutFilter, dampFreq);
+    tOnePole_setFreq(&p->prepFilterU, dampFreq);
+    tOnePole_setFreq(&p->prepFilterL, dampFreq);
+}
+
+void     tComplexLivingString_setDecay(tComplexLivingString* const pl, float decay)
+{
+    _tComplexLivingString* p = *pl;
+    p->decay=decay;
+}
+
+void     tComplexLivingString_setTargetLev(tComplexLivingString* const pl, float targetLev)
+{
+    _tComplexLivingString* p = *pl;
+    tFeedbackLeveler_setTargetLevel(&p->fbLevU, targetLev);
+    tFeedbackLeveler_setTargetLevel(&p->fbLevL, targetLev);
+}
+
+void     tComplexLivingString_setLevSmoothFactor(tComplexLivingString* const pl, float levSmoothFactor)
+{
+    _tComplexLivingString* p = *pl;
+    tFeedbackLeveler_setFactor(&p->fbLevU, levSmoothFactor);
+    tFeedbackLeveler_setFactor(&p->fbLevL, levSmoothFactor);
+}
+
+void     tComplexLivingString_setLevStrength(tComplexLivingString* const pl, float levStrength)
+{
+    _tComplexLivingString* p = *pl;
+    tFeedbackLeveler_setStrength(&p->fbLevU, levStrength);
+    tFeedbackLeveler_setStrength(&p->fbLevL, levStrength);
+}
+
+void     tComplexLivingString_setLevMode(tComplexLivingString* const pl, int levMode)
+{
+    _tComplexLivingString* p = *pl;
+    tFeedbackLeveler_setMode(&p->fbLevU, levMode);
+    tFeedbackLeveler_setMode(&p->fbLevL, levMode);
+    p->levMode=levMode;
+}
+
+float   tComplexLivingString_tick(tComplexLivingString* const pl, float input)
+{
+    _tComplexLivingString* p = *pl;
+
+    // from pickPos upwards=forwards
+    float fromLF=tLinearDelay_tickOut(&p->delLF);
+    float fromMF=tLinearDelay_tickOut(&p->delMF);
+    float fromUF=tLinearDelay_tickOut(&p->delUF);
+    float fromUB=tLinearDelay_tickOut(&p->delUB);
+    float fromMB=tLinearDelay_tickOut(&p->delMB);
+    float fromLB=tLinearDelay_tickOut(&p->delLB);
+
+    // into upper part of string, from bridge, going backwards
+    float fromBridge=-tFeedbackLeveler_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->bridgeFilter, fromUF)));
+    tLinearDelay_tickIn(&p->delUB, fromBridge);
+
+    // into pick position, take input and add it into the waveguide, going to come out of middle segment
+    tLinearDelay_tickIn(&p->delMB, fromUB+input);
+
+    // into lower part of string, from prepPos, going backwards
+    float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
+    float intoLower=p->prepIndex*fromLowerPrep+(1.0f - p->prepIndex)*fromMB;
+    tLinearDelay_tickIn(&p->delLB, intoLower);
+
+    // into lower part of string, from nut, going forwards toward prep position
+    float fromNut=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1.0f)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->nutFilter, fromLB)));
+    tLinearDelay_tickIn(&p->delLF, fromNut);
+
+    // into middle part of string, from prep going toward pick position
+    float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
+    float intoMiddle=p->prepIndex*fromUpperPrep+(1.0f - p->prepIndex)*fromLF;
+
+    //pick position, take input and add it into the waveguide, going to come out of middle segment
+    tLinearDelay_tickIn(&p->delMF, intoMiddle + input);
+
+    //take output of middle segment and put it into upper segment connecting to the bridge
+    tLinearDelay_tickIn(&p->delUF, fromMF);
+
+    // update all delay lengths
+    float pickP=tExpSmooth_tick(&p->pickPosSmooth);
+    float prepP=tExpSmooth_tick(&p->prepPosSmooth);
+    float wLen=tExpSmooth_tick(&p->wlSmooth);
+
+    float midLen = (pickP-prepP) * wLen; // the length between the pick and the prep;
+    float lowLen = prepP*wLen; // the length from prep to nut
+    float upLen = (1.0f-pickP)*wLen; // the length from pick to bridge
+
+
+    tLinearDelay_setDelay(&p->delLF, lowLen);
+    tLinearDelay_setDelay(&p->delLB, lowLen);
+
+    tLinearDelay_setDelay(&p->delMF, midLen);
+    tLinearDelay_setDelay(&p->delMB, midLen);
+
+    tLinearDelay_setDelay(&p->delUF, upLen);
+    tLinearDelay_setDelay(&p->delUB, upLen);
+
+    //update this to allow pickup position variation
+    p->curr = fromBridge;
+    return p->curr;
+}
+
+float   tComplexLivingString_sample(tComplexLivingString* const pl)
+{
+    _tComplexLivingString* p = *pl;
+    return p->curr;
+}
+
+
+
 ///Reed Table model
 //default values from STK are 0.6 offset and -0.8 slope
 
--- a/leaf/Src/leaf-sampling.c
+++ b/leaf/Src/leaf-sampling.c
@@ -78,6 +78,7 @@
                 s->idx = 0;
             }
         }
+        s->recordedLength = s->idx;
     }
 }
 
@@ -110,7 +111,6 @@
 {
     _tBuffer* s = *sb;
     s->active = 0;
-    s->recordedLength = s->idx;
 }
 
 int   tBuffer_getRecordPosition(tBuffer* const sb)
@@ -119,6 +119,12 @@
     return s->idx;
 }
 
+void   tBuffer_setRecordPosition(tBuffer* const sb, int pos)
+{
+    _tBuffer* s = *sb;
+    s->idx = pos;
+}
+
 void  tBuffer_setRecordMode (tBuffer* const sb, RecordMode mode)
 {
     _tBuffer* s = *sb;
@@ -132,6 +138,7 @@
     {
         s->buff[i] = 0.f;
     }
+
 }
 
 uint32_t tBuffer_getBufferLength(tBuffer* const sb)
@@ -146,6 +153,18 @@
     return s->recordedLength;
 }
 
+void tBuffer_setRecordedLength(tBuffer* const sb, int length)
+{
+    _tBuffer* s = *sb;
+    s->recordedLength = length;
+}
+
+int tBuffer_isActive(tBuffer* const sb)
+{
+    _tBuffer* s = *sb;
+    return s->active;
+}
+
 //================================tSampler=====================================
 
 static void handleStartEndChange(tSampler* const sp);
@@ -224,8 +243,8 @@
     p->idx = 0.f;
 }
 
-volatile uint32_t errorState = 0;
 
+
 float tSampler_tick        (tSampler* const sp)
 {
     _tSampler* p = *sp;
@@ -429,10 +448,11 @@
         }
     }
     
-    float ticksToEnd = rev ? ((idx - start) * p->iinc) : ((end - idx) * p->iinc);
+
     if (p->mode == PlayNormal)
     {
-        if (ticksToEnd < (0.007f * leaf.sampleRate))
+    	float ticksToEnd = rev ? ((idx - start) * p->iinc) : ((end - idx) * p->iinc);
+    	if (ticksToEnd < (0.007f * leaf.sampleRate))
         {
             tRamp_setDest(&p->gain, 0.f);
             p->active = -1;
@@ -472,10 +492,7 @@
         }
     }
     
-    if (fabsf(sample-p->last) > 0.1f)
-    {
-        errorState = 1;
-    }
+
     
     p->last = sample;
     
--- a/leaf/Src/leaf-tables.c
+++ b/leaf/Src/leaf-tables.c
@@ -3489,7 +3489,7 @@
 8825f, 0.109358f, 0.110216f, 0.111384f, 0.112791f, 0.114326f, 0.115854f, 0.11724f, 0.118378f, 0.119201f, 0.119699f, 0.119919f, 0.119957f, 0.119941f, 0.120008f, 0.120281f, 0.120846f, 0.12174f, 0.12294f, 0.12437f, 0.125915f, 0.127438f, 0.128806f, 0.129914f, 0.130703f, 0.131166f, 0.131359f, 0.131381f, 0.131363f, 0.131442f, 0.131739f, 0.132338f, 0.133266f, 0.134498f, 0.13595f, 0.137504f, 0.139021f, 0.14037f, 0.141449f, 0.142202f, 0.142632f, 0.142797f, 0.142803f, 0.142784f, 0.142877f, 0.1432f, 0.143832f, 0.144796f, 0.146058f, 0.147533f, 0.149095f, 0.150605f, 0.151933f, 0.152981f, 0.153698f, 0.154094f, 0.154233f, 0.154224f, 0.154205f, 0.154312f, 0.154662f, 0.155328f, 0.156328f, 0.157622f, 0.159117f, 0.160686f, 0.162188f, 0.163494f, 0.16451f, 0.165192f, 0.165554f, 0.165666f, 0.165644f, 0.165626f, 0.165749f, 0.166126f, 0.166827f, 0.167863f, 0.169188f, 0.170703f, 0.172277f, 0.173771f, 0.175054f, 0.176038f, 0.176683f, 0.17701f, 0.177097f, 0.177062f, 0.177046f, 0.177186f, 0.177593f, 0.178329f, 0.179401f, 0.180756f, 0.18229f, 0.18387f, 0.185353f, 0.186612f, 0.187563f, 0.188171f, 0.188464f, 0.188526f, 0.188479f, 0.188467f, 0.188625f, 0.189061f, 0.189834f, 0.190942f, 0.192327f, 0.19388f, 0.195463f, 0.196934f, 0.198169f, 0.199085f, 0.199656f, 0.199915f, 0.199952f, 0.199895f, 0.199887f, 0.200065f, 0.200532f, 0.201342f, 0.202486f, 0.203901f, 0.205471f, 0.207057f, 0.208515f, 0.209724f, 0.210605f, 0.211138f, 0.211364f, 0.211377f, 0.211309f, 0.211307f, 0.211506f, 0.212005f, 0.212852f, 0.214033f, 0.215477f, 0.217065f, 0.218652f, 0.220096f, 0.221277f, 0.222122f, 0.222617f, 0.222809f, 0.222799f, 0.222722f, 0.222727f, 0.222948f, 0.22348f, 0.224365f, 0.225584f, 0.227056f, 0.22866f, 0.230248f, 0.231676f, 0.232828f, 0.233636f, 0.234092f, 0.234251f, 0.234218f, 0.234134f, 0.234147f, 0.234391f, 0.234957f, 0.235882f, 0.237137f, 0.238638f, 0.240257f, 0.241844f, 0.243255f, 0.244377f, 0.245148f, 0.245565f, 0.24569f, 0.245635f, 0.245544f, 0.245567f, 0.245836f, 0.246437f, 0.247401f, 0.248694f, 0.250223f, 0.251856f, 0.253441f, 0.254834f, 0.255925f, 0.256657f, 0.257034f, 0.257126f, 0.25705f, 0.256953f, 0.256987f, 0.257281f, 0.257919f, 0.258923f, 0.260253f, 0.261811f, 0.263457f, 0.265039f, 0.266412f, 0.267471f, 0.268163f, 0.2685f, 0.268559f, 0.268462f, 0.26836f, 0.268407f, 0.268729f, 0.269404f, 0.270449f, 0.271817f, 0.273402f, 0.275061f, 0.276637f, 0.27799f, 0.279014f, 0.279666f, 0.279963f, 0.279988f, 0.279871f, 0.279766f, 0.279827f, 0.280177f, 0.280891f, 0.281978f, 0.283383f, 0.284995f, 0.286666f, 0.288237f, 0.289567f, 0.290556f, 0.291166f, 0.291422f, 0.291414f, 0.291278f, 0.291171f, 0.291246f, 0.291627f, 0.292381f, 0.293511f, 0.294954f, 0.296592f, 0.298273f, 0.299837f, 0.301143f, 0.302096f, 0.302663f, 0.302878f, 0.302837f, 0.302682f, 0.302573f, 0.302666f, 0.303078f, 0.303873f, 0.305047f, 0.306528f, 0.308192f, 0.309883f, 0.311438f, 0.312718f, 0.313633f, 0.314156f, 0.314329f, 0.314256f, 0.314083f, 0.313975f, 0.314086f, 0.314531f, 0.315369f, 0.316586f, 0.318106f, 0.319796f, 0.321495f, 0.32304f, 0.324293f, 0.325168f, 0.325647f, 0.325777f, 0.325671f, 0.325481f, 0.325374f, 0.325505f, 0.325986f, 0.326867f, 0.328129f, 0.329688f, 0.331403f, 0.33311f, 0.334642f, 0.335867f, 0.336701f, 0.337133f, 0.337221f, 0.337082f, 0.336876f, 0.336772f, 0.336925f, 0.337442f, 0.338368f, 0.339677f, 0.341274f, 0.343014f, 0.344727f, 0.346246f, 0.34744f, 0.348232f, 0.348617f, 0.34866f, 0.348489f, 0.348267f, 0.348168f, 0.348344f, 0.348899f, 0.349872f, 0.351228f, 0.352864f, 0.354628f, 0.356346f, 0.357851f, 0.359012f, 0.35976f, 0.360096f, 0.360096f, 0.359892f, 0.359656f, 0.359562f, 0.359763f, 0.360359f, 0.36138f, 0.362783f, 0.364459f, 0.366247f, 0.367969f, 0.369457f, 0.370584f, 0.371285f, 0.371572f, 0.371526f, 0.371291f, 0.371041f, 0.370954f, 0.371182f, 0.37182f, 0.372891f, 0.374343f, 0.376058f, 0.37787f, 0.379594f, 0.381064f, 0.382155f, 0.382808f, 0.383043f, 0.382952f, 0.382685f, 0.382422f, 0.382344f, 0.382601f, 0.383282f, 0.384405f, 0.385908f, 0.387663f, 0.389497f, 0.391223f, 0.392672f, 0.393725f, 0.394328f, 0.394511f, 0.394373f, 0.394073f, 0.393799f, 0.393731f, 0.394019f, 0.394747f, 0.3
\ No newline at end of file
     },
     
- 0.109358f, 0.110216f, 0.111384f, 0.112791f, 0.114326f, 0.115854f, 0.11724f, 0.118378f, 0.119201f, 0.119699f, 0.119919f, 0.119957f, 0.119941f, 0.120008f, 0.120281f, 0.120846f, 0.12174f, 0.12294f, 0.12437f, 0.125915f, 0.127438f, 0.128806f, 0.129914f, 0.130703f, 0.131166f, 0.131359f, 0.131381f, 0.131363f, 0.131442f, 0.131739f, 0.132338f, 0.133266f, 0.134498f, 0.13595f, 0.137504f, 0.139021f, 0.14037f, 0.141449f, 0.142202f, 0.142632f, 0.142797f, 0.142803f, 0.142784f, 0.142877f, 0.1432f, 0.143832f, 0.144796f, 0.146058f, 0.147533f, 0.149095f, 0.150605f, 0.151933f, 0.152981f, 0.153698f, 0.154094f, 0.154233f, 0.154224f, 0.154205f, 0.154312f, 0.154662f, 0.155328f, 0.156328f, 0.157622f, 0.159117f, 0.160686f, 0.162188f, 0.163494f, 0.16451f, 0.165192f, 0.165554f, 0.165666f, 0.165644f, 0.165626f, 0.165749f, 0.166126f, 0.166827f, 0.167863f, 0.169188f, 0.170703f, 0.172277f, 0.173771f, 0.175054f, 0.176038f, 0.176683f, 0.17701f, 0.177097f, 0.177062f, 0.177046f, 0.177186f, 0.177593f, 0.178329f, 0.179401f, 0.180756f, 0.18229f, 0.18387f, 0.185353f, 0.186612f, 0.187563f, 0.188171f, 0.188464f, 0.188526f, 0.188479f, 0.188467f, 0.188625f, 0.189061f, 0.189834f, 0.190942f, 0.192327f, 0.19388f, 0.195463f, 0.196934f, 0.198169f, 0.199085f, 0.199656f, 0.199915f, 0.199952f, 0.199895f, 0.199887f, 0.200065f, 0.200532f, 0.201342f, 0.202486f, 0.203901f, 0.205471f, 0.207057f, 0.208515f, 0.209724f, 0.210605f, 0.211138f, 0.211364f, 0.211377f, 0.211309f, 0.211307f, 0.211506f, 0.212005f, 0.212852f, 0.214033f, 0.215477f, 0.217065f, 0.218652f, 0.220096f, 0.221277f, 0.222122f, 0.222617f, 0.222809f, 0.222799f, 0.222722f, 0.222727f, 0.222948f, 0.22348f, 0.224365f, 0.225584f, 0.227056f, 0.22866f, 0.230248f, 0.231676f, 0.232828f, 0.233636f, 0.234092f, 0.234251f, 0.234218f, 0.234134f, 0.234147f, 0.234391f, 0.234957f, 0.235882f, 0.237137f, 0.238638f, 0.240257f, 0.241844f, 0.243255f, 0.244377f, 0.245148f, 0.245565f, 0.24569f, 0.245635f, 0.245544f, 0.245567f, 0.245836f, 0.246437f, 0.247401f, 0.248694f, 0.250223f, 0.251856f, 0.253441f, 0.254834f, 0.255925f, 0.256657f, 0.257034f, 0.257126f, 0.25705f, 0.256953f, 0.256987f, 0.257281f, 0.257919f, 0.258923f, 0.260253f, 0.261811f, 0.263457f, 0.265039f, 0.266412f, 0.267471f, 0.268163f, 0.2685f, 0.268559f, 0.268462f, 0.26836f, 0.268407f, 0.268729f, 0.269404f, 0.270449f, 0.271817f, 0.273402f, 0.275061f, 0.276637f, 0.27799f, 0.279014f, 0.279666f, 0.279963f, 0.279988f, 0.279871f, 0.279766f, 0.279827f, 0.280177f, 0.280891f, 0.281978f, 0.283383f, 0.284995f, 0.286666f, 0.288237f, 0.289567f, 0.290556f, 0.291166f, 0.291422f, 0.291414f, 0.291278f, 0.291171f, 0.291246f, 0.291627f, 0.292381f, 0.293511f, 0.294954f, 0.296592f, 0.298273f, 0.299837f, 0.301143f, 0.302096f, 0.302663f, 0.302878f, 0.302837f, 0.302682f, 0.302573f, 0.302666f, 0.303078f, 0.303873f, 0.305047f, 0.306528f, 0.308192f, 0.309883f, 0.311438f, 0.312718f, 0.313633f, 0.314156f, 0.314329f, 0.314256f, 0.314083f, 0.313975f, 0.314086f, 0.314531f, 0.315369f, 0.316586f, 0.318106f, 0.319796f, 0.321495f, 0.32304f, 0.324293f, 0.325168f, 0.325647f, 0.325777f, 0.325671f, 0.325481f, 0.325374f, 0.325505f, 0.325986f, 0.326867f, 0.328129f, 0.329688f, 0.331403f, 0.33311f, 0.334642f, 0.335867f, 0.336701f, 0.337133f, 0.337221f, 0.337082f, 0.336876f, 0.336772f, 0.336925f, 0.337442f, 0.338368f, 0.339677f, 0.341274f, 0.343014f, 0.344727f, 0.346246f, 0.34744f, 0.348232f, 0.348617f, 0.34866f, 0.348489f, 0.348267f, 0.348168f, 0.348344f, 0.348899f, 0.349872f, 0.351228f, 0.352864f, 0.354628f, 0.356346f, 0.357851f, 0.359012f, 0.35976f, 0.360096f, 0.360096f, 0.359892f, 0.359656f, 0.359562f, 0.359763f, 0.360359f, 0.36138f, 0.362783f, 0.364459f, 0.366247f, 0.367969f, 0.369457f, 0.370584f, 0.371285f, 0.371572f, 0.371526f, 0.371291f, 0.371041f, 0.370954f, 0.371182f, 0.37182f, 0.372891f, 0.374343f, 0.376058f, 0.37787f, 0.379594f, 0.381064f, 0.382155f, 0.382808f, 0.383043f, 0.382952f, 0.382685f, 0.382422f, 0.382344f, 0.382601f, 0.383282f, 0.384405f, 0.385908f, 0.387663f, 0.389497f, 0.391223f, 0.392672f, 0.393725f, 0.394328f, 0.394511f, 0.394373f, 0.394073f, 0.393799f, 0.393731f, 0.394019f, 0.394747f, 0.395923f
\ No newline at end of file
+ 0.109358f, 0.110216f, 0.111384f, 0.112791f, 0.114326f, 0.115854f, 0.11724f, 0.118378f, 0.119201f, 0.119699f, 0.119919f, 0.119957f, 0.119941f, 0.120008f, 0.120281f, 0.120846f, 0.12174f, 0.12294f, 0.12437f, 0.125915f, 0.127438f, 0.128806f, 0.129914f, 0.130703f, 0.131166f, 0.131359f, 0.131381f, 0.131363f, 0.131442f, 0.131739f, 0.132338f, 0.133266f, 0.134498f, 0.13595f, 0.137504f, 0.139021f, 0.14037f, 0.141449f, 0.142202f, 0.142632f, 0.142797f, 0.142803f, 0.142784f, 0.142877f, 0.1432f, 0.143832f, 0.144796f, 0.146058f, 0.147533f, 0.149095f, 0.150605f, 0.151933f, 0.152981f, 0.153698f, 0.154094f, 0.154233f, 0.154224f, 0.154205f, 0.154312f, 0.154662f, 0.155328f, 0.156328f, 0.157622f, 0.159117f, 0.160686f, 0.162188f, 0.163494f, 0.16451f, 0.165192f, 0.165554f, 0.165666f, 0.165644f, 0.165626f, 0.165749f, 0.166126f, 0.166827f, 0.167863f, 0.169188f, 0.170703f, 0.172277f, 0.173771f, 0.175054f, 0.176038f, 0.176683f, 0.17701f, 0.177097f, 0.177062f, 0.177046f, 0.177186f, 0.177593f, 0.178329f, 0.179401f, 0.180756f, 0.18229f, 0.18387f, 0.185353f, 0.186612f, 0.187563f, 0.188171f, 0.188464f, 0.188526f, 0.188479f, 0.188467f, 0.188625f, 0.189061f, 0.189834f, 0.190942f, 0.192327f, 0.19388f, 0.195463f, 0.196934f, 0.198169f, 0.199085f, 0.199656f, 0.199915f, 0.199952f, 0.199895f, 0.199887f, 0.200065f, 0.200532f, 0.201342f, 0.202486f, 0.203901f, 0.205471f, 0.207057f, 0.208515f, 0.209724f, 0.210605f, 0.211138f, 0.211364f, 0.211377f, 0.211309f, 0.211307f, 0.211506f, 0.212005f, 0.212852f, 0.214033f, 0.215477f, 0.217065f, 0.218652f, 0.220096f, 0.221277f, 0.222122f, 0.222617f, 0.222809f, 0.222799f, 0.222722f, 0.222727f, 0.222948f, 0.22348f, 0.224365f, 0.225584f, 0.227056f, 0.22866f, 0.230248f, 0.231676f, 0.232828f, 0.233636f, 0.234092f, 0.234251f, 0.234218f, 0.234134f, 0.234147f, 0.234391f, 0.234957f, 0.235882f, 0.237137f, 0.238638f, 0.240257f, 0.241844f, 0.243255f, 0.244377f, 0.245148f, 0.245565f, 0.24569f, 0.245635f, 0.245544f, 0.245567f, 0.245836f, 0.246437f, 0.247401f, 0.248694f, 0.250223f, 0.251856f, 0.253441f, 0.254834f, 0.255925f, 0.256657f, 0.257034f, 0.257126f, 0.25705f, 0.256953f, 0.256987f, 0.257281f, 0.257919f, 0.258923f, 0.260253f, 0.261811f, 0.263457f, 0.265039f, 0.266412f, 0.267471f, 0.268163f, 0.2685f, 0.268559f, 0.268462f, 0.26836f, 0.268407f, 0.268729f, 0.269404f, 0.270449f, 0.271817f, 0.273402f, 0.275061f, 0.276637f, 0.27799f, 0.279014f, 0.279666f, 0.279963f, 0.279988f, 0.279871f, 0.279766f, 0.279827f, 0.280177f, 0.280891f, 0.281978f, 0.283383f, 0.284995f, 0.286666f, 0.288237f, 0.289567f, 0.290556f, 0.291166f, 0.291422f, 0.291414f, 0.291278f, 0.291171f, 0.291246f, 0.291627f, 0.292381f, 0.293511f, 0.294954f, 0.296592f, 0.298273f, 0.299837f, 0.301143f, 0.302096f, 0.302663f, 0.302878f, 0.302837f, 0.302682f, 0.302573f, 0.302666f, 0.303078f, 0.303873f, 0.305047f, 0.306528f, 0.308192f, 0.309883f, 0.311438f, 0.312718f, 0.313633f, 0.314156f, 0.314329f, 0.314256f, 0.314083f, 0.313975f, 0.314086f, 0.314531f, 0.315369f, 0.316586f, 0.318106f, 0.319796f, 0.321495f, 0.32304f, 0.324293f, 0.325168f, 0.325647f, 0.325777f, 0.325671f, 0.325481f, 0.325374f, 0.325505f, 0.325986f, 0.326867f, 0.328129f, 0.329688f, 0.331403f, 0.33311f, 0.334642f, 0.335867f, 0.336701f, 0.337133f, 0.337221f, 0.337082f, 0.336876f, 0.336772f, 0.336925f, 0.337442f, 0.338368f, 0.339677f, 0.341274f, 0.343014f, 0.344727f, 0.346246f, 0.34744f, 0.348232f, 0.348617f, 0.34866f, 0.348489f, 0.348267f, 0.348168f, 0.348344f, 0.348899f, 0.349872f, 0.351228f, 0.352864f, 0.354628f, 0.356346f, 0.357851f, 0.359012f, 0.35976f, 0.360096f, 0.360096f, 0.359892f, 0.359656f, 0.359562f, 0.359763f, 0.360359f, 0.36138f, 0.362783f, 0.364459f, 0.366247f, 0.367969f, 0.369457f, 0.370584f, 0.371285f, 0.371572f, 0.371526f, 0.371291f, 0.371041f, 0.370954f, 0.371182f, 0.37182f, 0.372891f, 0.374343f, 0.376058f, 0.37787f, 0.379594f, 0.381064f, 0.382155f, 0.382808f, 0.383043f, 0.382952f, 0.382685f, 0.382422f, 0.382344f, 0.382601f, 0.383282f, 0.384405f, 0.385908f, 0.387663f, 0.389497f, 0.391223f, 0.392672f, 0.393725f, 0.394328f, 0.394511f, 0.394373f, 0.394073f, 0.393799f, 0.393731f, 0.394019f, 0.394747f, 0.395923f
\ No newline at end of file
 0.111384f, 0.112791f, 0.114326f, 0.115854f, 0.11724f, 0.118378f, 0.119201f, 0.119699f, 0.119919f, 0.119957f, 0.119941f, 0.120008f, 0.120281f, 0.120846f, 0.12174f, 0.12294f, 0.12437f, 0.125915f, 0.127438f, 0.128806f, 0.129914f, 0.130703f, 0.131166f, 0.131359f, 0.131381f, 0.131363f, 0.131442f, 0.131739f, 0.132338f, 0.133266f, 0.134498f, 0.13595f, 0.137504f, 0.139021f, 0.14037f, 0.141449f, 0.142202f, 0.142632f, 0.142797f, 0.142803f, 0.142784f, 0.142877f, 0.1432f, 0.143832f, 0.144796f, 0.146058f, 0.147533f, 0.149095f, 0.150605f, 0.151933f, 0.152981f, 0.153698f, 0.154094f, 0.154233f, 0.154224f, 0.154205f, 0.154312f, 0.154662f, 0.155328f, 0.156328f, 0.157622f, 0.159117f, 0.160686f, 0.162188f, 0.163494f, 0.16451f, 0.165192f, 0.165554f, 0.165666f, 0.165644f, 0.165626f, 0.165749f, 0.166126f, 0.166827f, 0.167863f, 0.169188f, 0.170703f, 0.172277f, 0.173771f, 0.175054f, 0.176038f, 0.176683f, 0.17701f, 0.177097f, 0.177062f, 0.177046f, 0.177186f, 0.177593f, 0.178329f, 0.179401f, 0.180756f, 0.18229f, 0.18387f, 0.185353f, 0.186612f, 0.187563f, 0.188171f, 0.188464f, 0.188526f, 0.188479f, 0.188467f, 0.188625f, 0.189061f, 0.189834f, 0.190942f, 0.192327f, 0.19388f, 0.195463f, 0.196934f, 0.198169f, 0.199085f, 0.199656f, 0.199915f, 0.199952f, 0.199895f, 0.199887f, 0.200065f, 0.200532f, 0.201342f, 0.202486f, 0.203901f, 0.205471f, 0.207057f, 0.208515f, 0.209724f, 0.210605f, 0.211138f, 0.211364f, 0.211377f, 0.211309f, 0.211307f, 0.211506f, 0.212005f, 0.212852f, 0.214033f, 0.215477f, 0.217065f, 0.218652f, 0.220096f, 0.221277f, 0.222122f, 0.222617f, 0.222809f, 0.222799f, 0.222722f, 0.222727f, 0.222948f, 0.22348f, 0.224365f, 0.225584f, 0.227056f, 0.22866f, 0.230248f, 0.231676f, 0.232828f, 0.233636f, 0.234092f, 0.234251f, 0.234218f, 0.234134f, 0.234147f, 0.234391f, 0.234957f, 0.235882f, 0.237137f, 0.238638f, 0.240257f, 0.241844f, 0.243255f, 0.244377f, 0.245148f, 0.245565f, 0.24569f, 0.245635f, 0.245544f, 0.245567f, 0.245836f, 0.246437f, 0.247401f, 0.248694f, 0.250223f, 0.251856f, 0.253441f, 0.254834f, 0.255925f, 0.256657f, 0.257034f, 0.257126f, 0.25705f, 0.256953f, 0.256987f, 0.257281f, 0.257919f, 0.258923f, 0.260253f, 0.261811f, 0.263457f, 0.265039f, 0.266412f, 0.267471f, 0.268163f, 0.2685f, 0.268559f, 0.268462f, 0.26836f, 0.268407f, 0.268729f, 0.269404f, 0.270449f, 0.271817f, 0.273402f, 0.275061f, 0.276637f, 0.27799f, 0.279014f, 0.279666f, 0.279963f, 0.279988f, 0.279871f, 0.279766f, 0.279827f, 0.280177f, 0.280891f, 0.281978f, 0.283383f, 0.284995f, 0.286666f, 0.288237f, 0.289567f, 0.290556f, 0.291166f, 0.291422f, 0.291414f, 0.291278f, 0.291171f, 0.291246f, 0.291627f, 0.292381f, 0.293511f, 0.294954f, 0.296592f, 0.298273f, 0.299837f, 0.301143f, 0.302096f, 0.302663f, 0.302878f, 0.302837f, 0.302682f, 0.302573f, 0.302666f, 0.303078f, 0.303873f, 0.305047f, 0.306528f, 0.308192f, 0.309883f, 0.311438f, 0.312718f, 0.313633f, 0.314156f, 0.314329f, 0.314256f, 0.314083f, 0.313975f, 0.314086f, 0.314531f, 0.315369f, 0.316586f, 0.318106f, 0.319796f, 0.321495f, 0.32304f, 0.324293f, 0.325168f, 0.325647f, 0.325777f, 0.325671f, 0.325481f, 0.325374f, 0.325505f, 0.325986f, 0.326867f, 0.328129f, 0.329688f, 0.331403f, 0.33311f, 0.334642f, 0.335867f, 0.336701f, 0.337133f, 0.337221f, 0.337082f, 0.336876f, 0.336772f, 0.336925f, 0.337442f, 0.338368f, 0.339677f, 0.341274f, 0.343014f, 0.344727f, 0.346246f, 0.34744f, 0.348232f, 0.348617f, 0.34866f, 0.348489f, 0.348267f, 0.348168f, 0.348344f, 0.348899f, 0.349872f, 0.351228f, 0.352864f, 0.354628f, 0.356346f, 0.357851f, 0.359012f, 0.35976f, 0.360096f, 0.360096f, 0.359892f, 0.359656f, 0.359562f, 0.359763f, 0.360359f, 0.36138f, 0.362783f, 0.364459f, 0.366247f, 0.367969f, 0.369457f, 0.370584f, 0.371285f, 0.371572f, 0.371526f, 0.371291f, 0.371041f, 0.370954f, 0.371182f, 0.37182f, 0.372891f, 0.374343f, 0.376058f, 0.37787f, 0.379594f, 0.381064f, 0.382155f, 0.382808f, 0.383043f, 0.382952f, 0.382685f, 0.382422f, 0.382344f, 0.382601f, 0.383282f, 0.384405f, 0.385908f, 0.387663f, 0.389497f, 0.391223f, 0.392672f, 0.393725f, 0.394328f, 0.394511f, 0.394373f, 0.394073f, 0.393799f, 0.393731f, 0.394019f, 0.394747f, 0.395923f, 0.397478f, 0.399273f,
\ No newline at end of file
     },