ref: 20f08ffb1a3e4430e3c3af804e34ebe3d4fab125
parent: 376abf2e92f5f3d6dcb5a0c6a3ac0ff13d555d28
author: spiricom <jeff@snyderphonics.com>
date: Wed May 6 12:45:48 EDT 2020
added vocoder warping and glottal pulse model
binary files a/.DS_Store b/.DS_Store differ
binary files a/LEAF/.DS_Store b/LEAF/.DS_Store differ
--- a/LEAF/Inc/leaf-analysis.h
+++ b/LEAF/Inc/leaf-analysis.h
@@ -239,10 +239,6 @@
float fidelityThreshold;
- float history;
- float alpha;
- float tolerance;
-
} _tPeriodDetection;
typedef _tPeriodDetection* tPeriodDetection;
@@ -257,8 +253,6 @@
void tPeriodDetection_setHopSize (tPeriodDetection* const, int hs);
void tPeriodDetection_setWindowSize (tPeriodDetection* const, int ws);
void tPeriodDetection_setFidelityThreshold(tPeriodDetection* const, float threshold);
- void tPeriodDetection_setAlpha (tPeriodDetection* const, float alpha);
- void tPeriodDetection_setTolerance (tPeriodDetection* const, float tolerance);
//==============================================================================
--- a/LEAF/Inc/leaf-effects.h
+++ b/LEAF/Inc/leaf-effects.h
@@ -45,11 +45,15 @@
float* buf0;
float* buf1;
+ float warpFactor;
+ int32_t warpOn;
+
float emphasis;
int32_t K, N, O, pos;
float wet, dry, FX;
float d0, d1, d2, d3, d4;
float u0, u1, u2, u3, u4;
+
} _tTalkbox;
@@ -64,9 +68,11 @@
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, int32_t n, int32_t o);
+ void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o, float warp, int warpOn);
void tTalkbox_setQuality (tTalkbox* const, float quality);
-
+ void tTalkbox_setWarpFactor (tTalkbox* const voc, float warp);
+ void tTalkbox_setWarpOn (tTalkbox* const voc, float warpOn);
+ void tTalkbox_warpedAutocorrelate (float * x, unsigned int L, float * R, unsigned int P, float lambda);
//==============================================================================
/* tVocoder */
@@ -101,6 +107,34 @@
//==============================================================================
+ // tRosenbergGlottalPulse
+
+ typedef struct _tRosenbergGlottalPulse
+ {
+
+ float phase;
+ float openLength;
+ float pulseLength;
+ float freq;
+ float inc;
+
+
+ } _tRosenbergGlottalPulse;
+
+ typedef _tRosenbergGlottalPulse* tRosenbergGlottalPulse;
+
+ void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const);
+ void tRosenbergGlottalPulse_free (tRosenbergGlottalPulse* const);
+ void tRosenbergGlottalPulse_initToPool (tRosenbergGlottalPulse* const, tMempool* const);
+ void tRosenbergGlottalPulse_freeFromPool (tRosenbergGlottalPulse* const, tMempool* const);
+
+ float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const);
+
+ float tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const, float freq);
+
+ float tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const, float openLength);
+
+ float tRosenbergGlottalPulse_setPulseLength (tRosenbergGlottalPulse* const, float pulseLength);
//==============================================================================
@@ -264,8 +298,6 @@
void tAutotune_setHopSize (tAutotune* const, int hs);
void tAutotune_setWindowSize (tAutotune* const, int ws);
void tAutotune_setFidelityThreshold (tAutotune* const, float threshold);
- void tAutotune_setAlpha (tAutotune* const, float alpha);
- void tAutotune_setTolerance (tAutotune* const, float tolerance);
float tAutotune_getInputPeriod (tAutotune* const);
float tAutotune_getInputFreq (tAutotune* const);
--- a/LEAF/Inc/leaf-math.h
+++ b/LEAF/Inc/leaf-math.h
@@ -37,8 +37,9 @@
#define SQRT8 2.82842712475f
#define WSCALE 1.30612244898f
#define PI (3.14159265358979f)
-#define TWO_PI (2 * PI)
-
+#define TWO_PI (6.28318530717958f)
+#define HALF_PI (1.570796326794897f)
+
#define VSF 1.0e-38f
#define MAX_DELAY 8192
--- a/LEAF/Src/leaf-analysis.c
+++ b/LEAF/Src/leaf-analysis.c
@@ -1,11 +1,11 @@
/*==============================================================================
-
- leaf-analysis.c
- Created: 30 Nov 2018 11:56:49am
- Author: airship
-
- ==============================================================================*/
+ leaf-analysis.c
+ Created: 30 Nov 2018 11:56:49am
+ Author: airship
+
+==============================================================================*/
+
#if _WIN32 || _WIN64
#include "..\Inc\leaf-analysis.h"
@@ -504,7 +504,7 @@
s->fidelity = 0.;
s->minrms = DEFMINRMS;
s->framesize = SNAC_FRAME_SIZE;
-
+
s->inputbuf = (float*) mpool_calloc(sizeof(float) * SNAC_FRAME_SIZE, m);
s->processbuf = (float*) mpool_calloc(sizeof(float) * (SNAC_FRAME_SIZE * 2), m);
s->spectrumbuf = (float*) mpool_calloc(sizeof(float) * (SNAC_FRAME_SIZE / 2), m);
@@ -873,10 +873,6 @@
p->timeConstant = DEFTIMECONSTANT;
p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
p->fidelityThreshold = 0.95;
-
- p->history = 0.0f;
- p->alpha = 1.0f;
- p->tolerance = 1.0f;
}
void tPeriodDetection_freeFromPool (tPeriodDetection* const pd, tMempool* const mp)
@@ -914,15 +910,7 @@
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)
- {
- float detected = tSNAC_getPeriod(&p->snac);
- p->history = detected * p->alpha + (p->history * (1 - p->alpha));
- float delta = 0.0f;
- if (detected > p->history) delta = (detected / p->history) - 1.0f;
- else delta = (p->history / detected) - 1.0f;
- if (delta < p->tolerance) p->period = detected;
- }
+ if (fidelity > p->fidelityThreshold) p->period = tSNAC_getPeriod(&p->snac);
p->curBlock++;
if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
@@ -955,17 +943,4 @@
{
_tPeriodDetection* p = *pd;
p->fidelityThreshold = threshold;
-}
-
-void tPeriodDetection_setAlpha (tPeriodDetection* pd, float alpha)
-{
- _tPeriodDetection* p = *pd;
- p->alpha = LEAF_clip(0.0f, alpha, 1.0f);
-}
-
-void tPeriodDetection_setTolerance (tPeriodDetection* pd, float tolerance)
-{
- _tPeriodDetection* p = *pd;
- if (tolerance < 0.0f) p->tolerance = 0.0f;
- else p->tolerance = tolerance;
}
--- a/LEAF/Src/leaf-effects.c
+++ b/LEAF/Src/leaf-effects.c
@@ -24,6 +24,7 @@
// TALKBOX
//============================================================================================================
+//LPC vocoder adapted from MDA's excellent open source talkbox plugin code
void tTalkbox_init(tTalkbox* const voc, int bufsize)
{
@@ -33,7 +34,8 @@
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->car0 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
@@ -68,7 +70,8 @@
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->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
@@ -103,7 +106,7 @@
if(fs < 8000.0f) fs = 8000.0f;
if(fs > 96000.0f) fs = 96000.0f;
- int32_t n = (int32_t)(0.01633f * fs);
+ 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);
@@ -144,18 +147,77 @@
}
}
+// 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 tTalkbox_warpedAutocorrelate(float * x, 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;
+ r1=0;
+ r2=0;
+ r1t=0;
+ for(int32_t k=0; k<L;k++)
+ {
+ Rt[0] += (double)(x[k]) * (double)(x[k]);
-#define ORD_MAX 100 // Was 50. Increasing this gets rid of glitchiness, lowering it breaks it; not sure how it affects performance
-void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o)
+ dl[k]= r1 - (double)(lambda) * (double)(x[k]-r2);
+ r1 = x[k];
+ r2 = dl[k];
+ }
+ for(int32_t i=1; i<=P; i++)
+ {
+ Rt[i]=0;
+ r1=0;
+ r2=0;
+ for(unsigned int k=0; k<L;k++)
+ {
+ Rt[i] += (double) (dl[k]) * (double)(x[k]);
+
+ r1t = dl[k];
+ dl[k]= r1 - (double)(lambda) * (double)(r1t-r2);
+ r1 = r1t;
+ r2 = dl[k];
+ }
+ }
+ for(int32_t i=0; i<=P; i++)
+ {
+ R[i]=(float)(Rt[i]);
+ }
+
+}
+
+
+
+#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, int32_t n, int32_t o, float warp, int warpOn)
{
float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;
int32_t i, j, nn=n;
- for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
+ if (warpOn == 0)
{
- z[j] = r[j] = 0.0f;
- for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
+ 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, n, r, o, warp);
+ }
+
r[0] *= 1.001f; //stability fix
float min = 0.00001f;
@@ -163,6 +225,8 @@
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.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;
@@ -186,8 +250,8 @@
int i, j;
float a[ORD_MAX], at[ORD_MAX], e=r[0];
- for(i=0; i<=p; i++) a[i] = at[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[] or k[]
+ at[0] = 0.0f;
for(i=1; i<=p; i++)
{
k[i] = -r[i];
@@ -198,7 +262,7 @@
k[i] -= a[j] * r[i-j];
}
if(fabs(e) < 1.0e-20f) { e = 0.0f; break; }
- k[i] /= e; // This might be costing us
+ k[i] /= e;
a[i] = k[i];
for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
@@ -215,14 +279,14 @@
_tTalkbox* v = *voc;
int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
- float e=v->emphasis, w, o, x, dr, fx=v->FX;
+ float e=v->emphasis, w, o, x, fx=v->FX;
float p, q, h0=0.3f, h1=0.77f;
o = voice;
x = synth;
- dr = o;
-
+
+
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;
@@ -237,10 +301,10 @@
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->N, v->O); p0 = 0; }
+ if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O, v->warpFactor, v->warpOn); 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->N, v->O); p1 = 0; }
+ if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O, v->warpFactor, v->warpOn); p1 = 0; }
}
p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p;
@@ -254,7 +318,7 @@
v->pos = p0;
v->FX = fx;
-
+
return o;
}
@@ -264,9 +328,27 @@
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_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;
+}
+
+
//============================================================================================================
// VOCODER
//============================================================================================================
@@ -479,6 +561,89 @@
v->kval = 0;
}
+
+
+/// Glottal Pulse (Rosenberg model)
+
+void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const gp)
+{
+ tRosenbergGlottalPulse_initToPool(gp, &leaf.mempool);
+}
+void tRosenbergGlottalPulse_free (tRosenbergGlottalPulse* const gp)
+{
+ tRosenbergGlottalPulse_freeFromPool(gp, &leaf.mempool);
+}
+void tRosenbergGlottalPulse_initToPool (tRosenbergGlottalPulse* const gp, tMempool* const mp)
+{
+
+ _tMempool* m = *mp;
+ _tRosenbergGlottalPulse* g = *gp = (_tRosenbergGlottalPulse*) mpool_alloc(sizeof(_tRosenbergGlottalPulse), m);
+
+ g->phase = 0.0f;
+ g->openLength = 0.0f;
+ g->pulseLength = 0.0f;
+ g->freq = 0.0f;
+ g->inc = 0.0f;
+
+
+}
+void tRosenbergGlottalPulse_freeFromPool (tRosenbergGlottalPulse* const gp, tMempool* const mp)
+{
+ _tMempool* m = *mp;
+ _tRosenbergGlottalPulse* g = *gp;
+ mpool_free(g, m);
+}
+
+float tRosenbergGlottalPulse_tick (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->pulseLength-g->openLength));
+ }
+
+ else
+ {
+ output = 0.0f;
+ }
+ return output;
+}
+
+float tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const gp, float freq)
+{
+ _tRosenbergGlottalPulse* g = *gp;
+ g->freq = freq;
+ g->inc = freq * leaf.invSampleRate;
+}
+
+float tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const gp, float openLength)
+{
+ _tRosenbergGlottalPulse* g = *gp;
+ g->openLength = openLength;
+}
+
+float tRosenbergGlottalPulse_setPulseLength (tRosenbergGlottalPulse* const gp, float pulseLength)
+{
+ _tRosenbergGlottalPulse* g = *gp;
+ g->pulseLength = pulseLength;
+}
+
+
+
+
//============================================================================================================
// SOLAD
//============================================================================================================
@@ -517,12 +682,12 @@
void tSOLAD_initToPool (tSOLAD* const wp, tMempool* const mp)
{
_tMempool* m = *mp;
-
+
_tSOLAD* w = *wp = (_tSOLAD*) mpool_calloc(sizeof(_tSOLAD), m);
w->pitchfactor = 1.;
w->delaybuf = (float*) mpool_calloc(sizeof(float) * (LOOPSIZE+16), m);
-
+
solad_init(w);
}
@@ -900,9 +1065,9 @@
void tPitchShift_initToPool (tPitchShift* const psr, tPeriodDetection* const pd, float* out, int bufSize, tMempool* const mp)
{
_tMempool* m = *mp;
-
+
_tPitchShift* ps = *psr = (_tPitchShift*) mpool_calloc(sizeof(_tPitchShift), m);
-
+
_tPeriodDetection* p = *pd;
ps->p = pd;
@@ -1078,7 +1243,7 @@
tRetune_setTimeConstant(rt, DEFTIMECONSTANT);
r->inputPeriod = 0.0f;
-
+
r->ps = (tPitchShift*) mpool_calloc(sizeof(tPitchShift) * r->numVoices, m);
r->pitchFactor = (float*) mpool_calloc(sizeof(float) * r->numVoices, m);
r->tickOutput = (float*) mpool_calloc(sizeof(float) * r->numVoices, m);
@@ -1088,7 +1253,7 @@
}
tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp);
-
+
for (int i = 0; i < r->numVoices; ++i)
{
tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp);
@@ -1259,7 +1424,7 @@
}
tPeriodDetection_initToPool(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize, mp);
-
+
for (int i = 0; i < r->numVoices; ++i)
{
tPitchShift_initToPool(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize, mp);
@@ -1293,15 +1458,15 @@
float tempPeriod = tPeriodDetection_tick(&r->pd, sample);
if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS
- {
- r->inputPeriod = tempPeriod;
- }
-
- for (int v = 0; v < r->numVoices; ++v)
- {
- r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]);
- }
-
+ {
+ r->inputPeriod = tempPeriod;
+ }
+
+ for (int v = 0; v < r->numVoices; ++v)
+ {
+ r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]);
+ }
+
return r->tickOutput;
}
@@ -1376,22 +1541,10 @@
void tAutotune_setFidelityThreshold(tAutotune* const rt, float threshold)
{
_tAutotune* r = *rt;
-
+
tPeriodDetection_setFidelityThreshold(&r->pd, threshold);
}
-void tAutotune_setAlpha (tAutotune* rt, float alpha)
-{
- _tAutotune* r = *rt;
- tPeriodDetection_setAlpha(&r->pd, alpha);
-}
-
-void tAutotune_setTolerance (tAutotune* rt, float tolerance)
-{
- _tAutotune* r = *rt;
- tPeriodDetection_setTolerance(&r->pd, tolerance);
-}
-
float tAutotune_getInputPeriod(tAutotune* const rt)
{
_tAutotune* r = *rt;
@@ -1425,7 +1578,7 @@
fs->fsmooth = (float*) leaf_calloc(sizeof(float) * fs->ford);
fs->ftvec = (float*) leaf_calloc(sizeof(float) * fs->ford);
fs->fbuff = (float*) leaf_calloc(sizeof(float*) * fs->ford);
-
+
fs->falph = powf(0.001f, 40.0f * leaf.invSampleRate);
fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f*leaf.sampleRate))-0.1916f);
fs->fhp = 0.0f;
@@ -1435,11 +1588,11 @@
fs->fmutealph = powf(0.001f, 0.5f * leaf.invSampleRate);
fs->cbi = 0;
fs->intensity = 1.0f;
- fs->invIntensity = 1.0f;
- tHighpass_init(&fs->hp, 10.0f);
- tHighpass_init(&fs->hp2, 10.0f);
- tFeedbackLeveler_init(&fs->fbl1, 0.99f, 0.005f, 0.125f, 0);
- tFeedbackLeveler_init(&fs->fbl2, 0.99f, 0.005f, 0.125f, 0);
+ fs->invIntensity = 1.0f;
+ tHighpass_init(&fs->hp, 10.0f);
+ tHighpass_init(&fs->hp2, 10.0f);
+ tFeedbackLeveler_init(&fs->fbl1, 0.99f, 0.005f, 0.125f, 0);
+ tFeedbackLeveler_init(&fs->fbl2, 0.99f, 0.005f, 0.125f, 0);
}
void tFormantShifter_free(tFormantShifter* const fsr)
@@ -1457,8 +1610,8 @@
leaf_free(fs->fbuff);
tHighpass_free(&fs->hp);
tHighpass_free(&fs->hp2);
- tFeedbackLeveler_free(&fs->fbl1);
- tFeedbackLeveler_free(&fs->fbl2);
+ tFeedbackLeveler_free(&fs->fbl1);
+ tFeedbackLeveler_free(&fs->fbl2);
leaf_free(fs);
}
@@ -1478,8 +1631,8 @@
fs->ftvec = (float*) mpool_calloc(sizeof(float) * fs->ford, m);
fs->fbuff = (float*) mpool_calloc(sizeof(float*) * fs->ford, m);
+
-
fs->falph = powf(0.001f, 10.0f * leaf.invSampleRate);
fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f*leaf.sampleRate))-0.1916f);
fs->fhp = 0.0f;
@@ -1528,9 +1681,9 @@
in = tFeedbackLeveler_tick(&fs->fbl1, in);
in = tHighpass_tick(&fs->hp, in * fs->intensity);
-
+
float fa, fb, fc, foma, falph, ford, flamb, tf, fk;
-
+
ford = fs->ford;
falph = fs->falph;
foma = (1.0f - falph);
@@ -1556,7 +1709,7 @@
fb = fc - tf*fa;
fa = fa - tf*fc;
}
-
+
//return fa * 0.1f;
return fa;
}
@@ -1567,7 +1720,7 @@
float fa, fb, fc, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
ford = fs->ford;
-
+
flpa = fs->flpa;
flamb = fs->flamb;
tf = fs->shiftFactor * (1.0f+flamb)/(1.0f-flamb);
@@ -1654,7 +1807,7 @@
// ...and we're done messing with formants
//tf = tFeedbackLeveler_tick(&fs->fbl2, tf);
tf = tHighpass_tick(&fs->hp2, tanhf(tf));
-
+
return tf * fs->invIntensity;
}
@@ -1668,21 +1821,21 @@
void tFormantShifter_setIntensity(tFormantShifter* const fsr, float intensity)
{
_tFormantShifter* fs = *fsr;
-
-
-
+
+
+
fs->intensity = LEAF_clip(1.0f, intensity, 100.0f);
-
- // tFeedbackLeveler_setTargetLevel(&fs->fbl1, fs->intensity);
+
+ // tFeedbackLeveler_setTargetLevel(&fs->fbl1, fs->intensity);
//tFeedbackLeveler_setTargetLevel(&fs->fbl2, fs->intensity);
//make sure you don't divide by zero, doofies
if (fs->intensity != 0.0f)
{
- fs->invIntensity = 1.0f/fs->intensity;
+ fs->invIntensity = 1.0f/fs->intensity;
}
else
{
- fs->invIntensity = 1.0f;
+ fs->invIntensity = 1.0f;
}
-
+
}