ref: 8f147944afaaa41bf53b2a1ed3884e07984c401c
parent: c3197de0732d863167944ca00c82f3e7165c8409
author: Matthew Wang <mjw7@princeton.edu>
date: Tue May 5 12:05:45 EDT 2020
trying some period detection hysteresis options
--- a/LEAF/Inc/leaf-analysis.h
+++ b/LEAF/Inc/leaf-analysis.h
@@ -239,6 +239,10 @@
float fidelityThreshold;
+ float history;
+ float alpha;
+ float tolerance;
+
} _tPeriodDetection;
typedef _tPeriodDetection* tPeriodDetection;
@@ -253,6 +257,8 @@
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
@@ -264,6 +264,8 @@
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/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,6 +873,10 @@
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)
@@ -910,7 +914,15 @@
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)
+ {
+ 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;
+ }
p->curBlock++;
if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
@@ -943,4 +955,17 @@
{
_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
@@ -254,7 +254,7 @@
v->pos = p0;
v->FX = fx;
-
+
return o;
}
@@ -517,12 +517,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 +900,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 +1078,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 +1088,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 +1259,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 +1293,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,10 +1376,22 @@
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;
@@ -1413,7 +1425,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;
@@ -1423,11 +1435,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)
@@ -1445,8 +1457,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);
}
@@ -1466,8 +1478,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;
@@ -1516,9 +1528,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);
@@ -1544,7 +1556,7 @@
fb = fc - tf*fa;
fa = fa - tf*fc;
}
-
+
//return fa * 0.1f;
return fa;
}
@@ -1555,7 +1567,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);
@@ -1642,7 +1654,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;
}
@@ -1656,21 +1668,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;
}
-
+
}
--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -262,11 +262,17 @@
float LEAF_clip(float min, float val, float max)
{
-
- if (val < min) {
- return min;
- } else if (val > max) {
- return max;
+ int tempmin = min;
+ int tempmax = max;
+ if (min > max)
+ {
+ tempmin = max;
+ tempmax = min;
+ }
+ if (val < tempmin) {
+ return tempmin;
+ } else if (val > tempmax) {
+ return tempmax;
} else {
return val;
}