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
},