ref: 8848fb89b3c7c196add6dca1fb58b5b0f4e0adc6
parent: f253eaf415bc6455db4d38dd4804d7136d874705
author: Matthew Wang <mjw7@princeton.edu>
date: Tue Nov 10 17:44:02 EST 2020
refining dual pitch detector
--- a/leaf/Inc/leaf-analysis.h
+++ b/leaf/Inc/leaf-analysis.h
@@ -17,6 +17,7 @@
#include "leaf-global.h"
#include "leaf-mempool.h"
+#include "leaf-distortion.h"
#include "leaf-math.h"
#include "leaf-filters.h"
#include "leaf-envelopes.h"
@@ -431,7 +432,7 @@
void tSNAC_initToPool (tSNAC* const, int overlaparg, tMempool* const);
void tSNAC_free (tSNAC* const);
- void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size);
+ void tSNAC_ioSamples (tSNAC *s, float *in, int size);
void tSNAC_setOverlap (tSNAC *s, int lap);
void tSNAC_setBias (tSNAC *s, float bias);
void tSNAC_setMinRMS (tSNAC *s, float rms);
@@ -539,12 +540,13 @@
typedef _tPeriodDetection* tPeriodDetection;
- void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize, LEAF* const leaf);
- void tPeriodDetection_initToPool (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize, tMempool* const);
+ void tPeriodDetection_init (tPeriodDetection* const, float* in, int bufSize, int frameSize, LEAF* const leaf);
+ void tPeriodDetection_initToPool (tPeriodDetection* const, float* in, int bufSize, int frameSize, tMempool* const);
void tPeriodDetection_free (tPeriodDetection* const);
float tPeriodDetection_tick (tPeriodDetection* const, float sample);
float tPeriodDetection_getPeriod (tPeriodDetection* const);
+ float tPeriodDetection_getFidelity (tPeriodDetection* pd);
void tPeriodDetection_setHopSize (tPeriodDetection* const, int hs);
void tPeriodDetection_setWindowSize (tPeriodDetection* const, int ws);
void tPeriodDetection_setFidelityThreshold(tPeriodDetection* const, float threshold);
@@ -862,7 +864,7 @@
#define ONSET_PERIODICITY 0.95f
#define MIN_PERIODICITY 0.9f
-#define DEFAULT_HYSTERESIS -40.0f
+#define DEFAULT_HYSTERESIS -200.0f
typedef struct _pitch_info
{
@@ -903,20 +905,22 @@
tMempool mempool;
- tPitchDetector _pd1;
+ tPeriodDetection _pd1;
tPitchDetector _pd2;
_pitch_info _current;
float _mean;
float _predicted_frequency;
int _first;
- int sub;
+ float highest, lowest;
+ float thresh;
+
} _tDualPitchDetector;
typedef _tDualPitchDetector* tDualPitchDetector;
- void tDualPitchDetector_init (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, LEAF* const leaf);
- void tDualPitchDetector_initToPool (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, tMempool* const mempool);
+ void tDualPitchDetector_init (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, float* inBuffer, int bufSize, LEAF* const leaf);
+ void tDualPitchDetector_initToPool (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, float* inBuffer, int bufSize, tMempool* const mempool);
void tDualPitchDetector_free (tDualPitchDetector* const detector);
int tDualPitchDetector_tick (tDualPitchDetector* const detector, float sample);
@@ -926,6 +930,7 @@
float tDualPitchDetector_predictFrequency (tDualPitchDetector* const detector);
void tDualPitchDetector_setHysteresis (tDualPitchDetector* const detector, float hysteresis);
+ void tDualPitchDetector_setPeriodicityThreshold (tDualPitchDetector* const detector, float thresh);
--- a/leaf/Inc/leaf-effects.h
+++ b/leaf/Inc/leaf-effects.h
@@ -652,6 +652,7 @@
tPitchShift* ps;
+ float* pdBuffer;
float* inBuffer;
float** outBuffers;
int bufSize;
--- 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"
@@ -92,7 +92,7 @@
_tMempool* m = *mp;
_tZeroCrossingCounter* z = *zc = (_tZeroCrossingCounter*) mpool_alloc(sizeof(_tZeroCrossingCounter), m);
z->mempool = m;
-
+
z->count = 0;
z->maxWindowSize = maxWindowSize;
z->currentWindowSize = maxWindowSize;
@@ -116,11 +116,11 @@
float tZeroCrossingCounter_tick (tZeroCrossingCounter* const zc, float input)
{
_tZeroCrossingCounter* z = *zc;
-
+
z->inBuffer[z->position] = input;
int futurePosition = ((z->position + 1) % z->currentWindowSize);
float output = 0.0f;
-
+
//add new value to count
if ((z->inBuffer[z->position] * z->inBuffer[z->prevPosition]) < 0.0f)
{
@@ -132,7 +132,7 @@
{
z->countBuffer[z->position] = 0;
}
-
+
//remove oldest value from count
if (z->countBuffer[futurePosition] > 0)
{
@@ -142,12 +142,12 @@
z->count = 0;
}
}
-
+
z->prevPosition = z->position;
z->position = futurePosition;
-
+
output = z->count * z->invCurrentWindowSize;
-
+
return output;
}
@@ -156,9 +156,9 @@
{
_tZeroCrossingCounter* z = *zc;
if (windowSize <= z->maxWindowSize)
- {
- z->currentWindowSize = windowSize;
- }
+ {
+ z->currentWindowSize = windowSize;
+ }
else
{
z->currentWindowSize = z->maxWindowSize;
@@ -257,7 +257,7 @@
for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
for (i = 0; i < npoints; i++)
- x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints;
+ x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints;
for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0;
x->x_f = 0;
@@ -320,7 +320,7 @@
x->x_result = x->x_sumbuf[0];
for (count = x->x_realperiod, sump = x->x_sumbuf;
count < x->x_npoints; count += x->x_realperiod, sump++)
- sump[0] = sump[1];
+ sump[0] = sump[1];
sump[0] = 0;
x->x_phase = x->x_realperiod - n;
}
@@ -494,7 +494,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);
@@ -520,7 +520,8 @@
/******************************************************************************/
-void tSNAC_ioSamples(tSNAC* const snac, float *in, float *out, int size)
+//void tSNAC_ioSamples(tSNAC* const snac, float *in, float *out, int size)
+void tSNAC_ioSamples(tSNAC* const snac, float *in, int size)
{
_tSNAC* s = *snac;
@@ -536,7 +537,8 @@
while(size--)
{
inputbuf[timeindex] = *in++;
- out[outindex++] = processbuf[timeindex++];
+// out[outindex++] = processbuf[timeindex++];
+ timeindex++;
timeindex &= mask;
}
s->timeindex = timeindex;
@@ -827,12 +829,12 @@
//===========================================================================
// PERIODDETECTION
//===========================================================================
-void tPeriodDetection_init (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize, LEAF* const leaf)
+void tPeriodDetection_init (tPeriodDetection* const pd, float* in, int bufSize, int frameSize, LEAF* const leaf)
{
- tPeriodDetection_initToPool(pd, in, out, bufSize, frameSize, &leaf->mempool);
+ tPeriodDetection_initToPool(pd, in, bufSize, frameSize, &leaf->mempool);
}
-void tPeriodDetection_initToPool (tPeriodDetection* const pd, float* in, float* out, int bufSize, int frameSize, tMempool* const mp)
+void tPeriodDetection_initToPool (tPeriodDetection* const pd, float* in, int bufSize, int frameSize, tMempool* const mp)
{
_tMempool* m = *mp;
_tPeriodDetection* p = *pd = (_tPeriodDetection*) mpool_calloc(sizeof(_tPeriodDetection), m);
@@ -840,7 +842,6 @@
LEAF* leaf = p->mempool->leaf;
p->inBuffer = in;
- p->outBuffer = out;
p->bufSize = bufSize;
p->frameSize = frameSize;
p->framesPerBuffer = p->bufSize / p->frameSize;
@@ -855,7 +856,7 @@
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;
@@ -895,13 +896,10 @@
tEnvPD_processBlock(&p->env, &(p->inBuffer[i]));
- tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
- float fidelity = tSNAC_getFidelity(&p->snac);
+ tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), p->frameSize);
+
// 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);
- }
+ p->period = tSNAC_getPeriod(&p->snac);
p->curBlock++;
if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
@@ -917,6 +915,12 @@
return p->period;
}
+float tPeriodDetection_getFidelity(tPeriodDetection* pd)
+{
+ _tPeriodDetection* p = *pd;
+ return tSNAC_getFidelity(&p->snac);
+}
+
void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
{
_tPeriodDetection* p = *pd;
@@ -959,7 +963,7 @@
_tMempool* m = *mp;
_tZeroCrossingInfo* z = *zc = (_tZeroCrossingInfo*) mpool_alloc(sizeof(_tZeroCrossingInfo), m);
z->mempool = m;
-
+
z->_leading_edge = INT_MIN;
z->_trailing_edge = INT_MIN;
z->_width = 0.0f;
@@ -1043,11 +1047,11 @@
z->_size = pow(2.0, ceil(log2((double)size)));
z->_mask = z->_size - 1;
-
z->_info = (tZeroCrossingInfo*) mpool_calloc(sizeof(tZeroCrossingInfo) * z->_size, m);
- for (unsigned i = 0; i < z->_size; i++)
- tZeroCrossingInfo_initToPool(&z->_info[i], mp);
+ for (unsigned i = 0; i < z->_size; i++)
+ tZeroCrossingInfo_initToPool(&z->_info[i], mp);
+
z->_pos = 0;
z->_prev = 0.0f;
@@ -1064,7 +1068,9 @@
_tZeroCrossingCollector* z = *zc;
for (unsigned i = 0; i < z->_size; i++)
- tZeroCrossingInfo_free(&z->_info[i]);
+
+ tZeroCrossingInfo_free(&z->_info[i]);
+
mpool_free((char*)z->_info, z->mempool);
mpool_free((char*)z, z->mempool);
}
@@ -1843,7 +1849,7 @@
{
if (info._period < collector->_first_period)
return 0;
-
+
float incoming_period = sub_collector_period_of(collector, info);
int multiple = fmaxf(1.0f, roundf( incoming_period / collector->_first_period));
return sub_collector_try_sub_harmonic(collector, fmin(collector->_range, multiple), info, incoming_period/multiple);
@@ -1982,8 +1988,8 @@
float period = tPeriodDetector_predictPeriod(&p->_pd);
if (period > 0.0f)
- return leaf->sampleRate / period;
- return 0.0f;
+ return leaf->sampleRate / period;
+ return 0.0f;
}
int tPitchDetector_indeterminate (tPitchDetector* const detector)
@@ -2023,7 +2029,7 @@
//=============================================================================
//_pitch_info result = bias(current, incoming, shift);
{
- float error = p->_current.frequency / 32.0f; // approx 1/2 semitone
+ float error = p->_current.frequency * 0.015625; // approx 1/4 semitone
float diff = fabsf(p->_current.frequency - incoming.frequency);
int done = 0;
@@ -2108,25 +2114,29 @@
static inline void compute_predicted_frequency(tDualPitchDetector* const detector);
-void tDualPitchDetector_init (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, LEAF* const leaf)
+void tDualPitchDetector_init (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, float* inBuffer, int bufSize, LEAF* const leaf)
{
- tDualPitchDetector_initToPool(detector, lowestFreq, highestFreq, &leaf->mempool);
+ tDualPitchDetector_initToPool(detector, lowestFreq, highestFreq, inBuffer, bufSize, &leaf->mempool);
}
-void tDualPitchDetector_initToPool (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, tMempool* const mempool)
+void tDualPitchDetector_initToPool (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, float* inBuffer, int bufSize, tMempool* const mempool)
{
_tMempool* m = *mempool;
_tDualPitchDetector* p = *detector = (_tDualPitchDetector*) mpool_alloc(sizeof(_tDualPitchDetector), m);
p->mempool = m;
- tPitchDetector_initToPool(&p->_pd1, lowestFreq*2.0f, highestFreq*2.0f, mempool);
- tPitchDetector_initToPool(&p->_pd2, lowestFreq*2.0f, highestFreq*2.0f, mempool);
+ tPeriodDetection_initToPool(&p->_pd1, inBuffer, bufSize, bufSize / 2, mempool);
+ tPitchDetector_initToPool(&p->_pd2, lowestFreq, highestFreq, mempool);
+
p->_current.frequency = 0.0f;
p->_current.periodicity = 0.0f;
p->_mean = lowestFreq + ((highestFreq - lowestFreq) / 2.0f);
p->_predicted_frequency = 0.0f;
p->_first = 1;
- p->sub = 0;
+ p->thresh = 0.98f;
+
+ p->lowest = lowestFreq;
+ p->highest = highestFreq;
}
void tDualPitchDetector_free (tDualPitchDetector* const detector)
@@ -2133,7 +2143,7 @@
{
_tDualPitchDetector* p = *detector;
- tPitchDetector_free(&p->_pd1);
+ tPeriodDetection_free(&p->_pd1);
tPitchDetector_free(&p->_pd2);
mpool_free((char*) p, p->mempool);
@@ -2142,65 +2152,84 @@
int tDualPitchDetector_tick (tDualPitchDetector* const detector, float sample)
{
_tDualPitchDetector* p = *detector;
+ LEAF* leaf = p->mempool->leaf;
- int pd1_ready;
- if (!(p->sub % 2))
+ tPeriodDetection_tick(&p->_pd1, sample);
+ int ready = tPitchDetector_tick(&p->_pd2, sample);
+
+ if (ready)
{
- pd1_ready = tPitchDetector_tick(&p->_pd2, sample);
- p->sub = 0;
- }
- else
- {
- pd1_ready = tPitchDetector_tick(&p->_pd1, sample);
- }
- p->sub++;
-
- if (pd1_ready)
- {
- int pd1_indeterminate = tPitchDetector_indeterminate(&p->_pd1);
int pd2_indeterminate = tPitchDetector_indeterminate(&p->_pd2);
int disagreement = 0;
- if (!pd1_indeterminate && !pd2_indeterminate)
+ float period = tPeriodDetection_getPeriod(&p->_pd1);
+ if (!pd2_indeterminate && period != 0.0f)
{
- _pitch_info _i1 = p->_pd1->_current;
+ _pitch_info _i1;
+ _i1.frequency = leaf->sampleRate / tPeriodDetection_getPeriod(&p->_pd1);
+ _i1.periodicity = tPeriodDetection_getFidelity(&p->_pd1);
_pitch_info _i2 = p->_pd2->_current;
- float pd1_diff = fabsf(_i1.frequency*0.5f - p->_mean);
- float pd2_diff = fabsf(_i2.frequency*0.5f - p->_mean);
- _pitch_info i1 = _i1;
- i1.frequency = i1.frequency*0.5f;
- _pitch_info i2 = _i2;
- i2.frequency = i2.frequency*0.5f;
-
- _pitch_info i = (pd1_diff < pd2_diff) ? i1 : i2;
- disagreement = fabsf(pd1_diff - pd2_diff) > 2.0f;
+ float pd1_diff = fabsf(_i1.frequency - p->_mean);
+ float pd2_diff = fabsf(_i2.frequency - p->_mean);
+
+ _pitch_info i;
+ disagreement = fabsf(_i1.frequency - _i2.frequency) > (p->_mean * 0.03125f);
+ // If they agree, we'll use bacf
+ if (!disagreement) i = _i2;
+ // A disagreement implies a change
+ // Start with smaller changes
+ else if (pd2_diff < p->_mean * 0.03125f) i = _i2;
+ else if (pd1_diff < p->_mean * 0.03125f) i = _i1;
+ // Now filter out lower fidelity stuff
+ else if (_i1.periodicity < p->thresh) return ready;
+ // Changing up (bacf tends to lead changes)
+ else if ((_i1.frequency > p->_mean && _i2.frequency > p->_mean) &&
+ (_i1.frequency < _i2.frequency) &&
+ (_i2.periodicity > p->thresh))
+ {
+ if (roundf(_i2.frequency / _i1.frequency) > 1) i = _i1;
+ else i = _i2;
+ }
+ // Changing down
+ else if ((_i1.frequency < p->_mean && _i2.frequency < p->_mean) &&
+ (_i1.frequency > _i2.frequency) &&
+ (_i2.periodicity > p->thresh))
+ {
+ if (roundf(_i1.frequency / _i2.frequency) > 1) i = _i1;
+ else i = _i2;
+ }
+ // A bit of handling for stuff out of bacf range, won't be as solid but better than nothing
+ else if (_i1.frequency > p->highest)
+ {
+ if (roundf(_i1.frequency / _i2.frequency) > 1) i = _i2;
+ else i = _i1;
+ }
+ else if (_i1.frequency < p->lowest)
+ {
+ if (roundf(_i2.frequency / _i1.frequency) > 1) i = _i2;
+ else i = _i1;
+ }
+ // Don't change if we met non of these, probably a bad read
+ else return ready;
- if (!disagreement) {
- if (p->_first)
- {
- p->_current = i;
- p->_mean = p->_current.frequency;
- p->_first = 0;
- p->_predicted_frequency = 0.0f;
- }
- else
- {
- p->_current = i;
- p->_mean = (0.2222222 * p->_current.frequency) + (0.7777778 * p->_mean);
- p->_predicted_frequency = 0.0f;
- }
+ if (p->_first)
+ {
+ p->_current = i;
+ p->_mean = p->_current.frequency;
+ p->_first = 0;
+ p->_predicted_frequency = 0.0f;
}
+ else
+ {
+ p->_current = i;
+ p->_mean = (0.2222222 * p->_current.frequency) + (0.7777778 * p->_mean);
+ p->_predicted_frequency = 0.0f;
+ }
+ return ready;
}
-
- if (pd1_indeterminate && pd2_indeterminate)
- {
- compute_predicted_frequency(detector);
- p->_current.frequency = 0.0f;
- p->_current.periodicity = 0.0f;
- }
}
-
- return pd1_ready;
+
+ return ready;
}
float tDualPitchDetector_getFrequency (tDualPitchDetector* const detector)
@@ -2226,31 +2255,36 @@
return p->_predicted_frequency;
}
-void tDualPitchDetector_setHysteresis (tDualPitchDetector* const detector, float hysteresis)
+void tDualPitchDetector_setHysteresis (tDualPitchDetector* const detector, float hysteresis)
{
_tDualPitchDetector* p = *detector;
- tPitchDetector_setHysteresis(&p->_pd1, hysteresis);
tPitchDetector_setHysteresis(&p->_pd2, hysteresis);
}
+void tDualPitchDetector_setPeriodicityThreshold (tDualPitchDetector* const detector, float thresh)
+{
+ _tDualPitchDetector* p = *detector;
+
+ p->thresh = thresh;
+}
+
static inline void compute_predicted_frequency(tDualPitchDetector* const detector)
{
_tDualPitchDetector* p = *detector;
- float f1 = tPitchDetector_predictFrequency(&p->_pd1);
- if (f1 > 0.0f)
+ float f1 = 1.0f / tPeriodDetection_getPeriod(&p->_pd1);
+ float f2 = tPitchDetector_predictFrequency(&p->_pd2);
+ if (f2 > 0.0f)
{
- float f2 = tPitchDetector_predictFrequency(&p->_pd2);
- if (f2 > 0.0f)
+ float error = f1 * 0.1f;
+ if (fabsf(f1 - f2) < error)
{
- float error = f1 * 0.1f;
- if (fabsf(f1 - f2) < error)
- {
- p->_predicted_frequency = f1;
- return;
- }
+ p->_predicted_frequency = f1;
+ return;
}
}
+
p->_predicted_frequency = 0.0f;
}
+
--- a/leaf/Src/leaf-effects.c
+++ b/leaf/Src/leaf-effects.c
@@ -1039,8 +1039,8 @@
w->period = INITPERIOD;
w->readlag = INITPERIOD;
w->blocksize = INITPERIOD;
-
- tAttackDetection_initToPool(&w->ad, INITPERIOD, 2, 2, mp);
+
+ tAttackDetection_initToPool(&w->ad, INITPERIOD, 5, 5, mp);
tHighpass_initToPool(&w->hp, 20.0f, mp);
}
@@ -1383,7 +1383,7 @@
ps->pd = *dpd;
ps->bufSize = bufSize;
- ps->pickiness = 0.95f;
+ ps->pickiness = 0.0f;
tSOLAD_initToPool(&ps->sola, pow(2.0, ceil(log2(ps->bufSize * 2.0))), mp);
tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
@@ -1468,7 +1468,7 @@
r->minInputFreq = minInputFreq;
r->maxInputFreq = maxInputFreq;
- tDualPitchDetector_initToPool(&r->dp, r->minInputFreq, r->maxInputFreq, mp);
+ tDualPitchDetector_initToPool(&r->dp, r->minInputFreq, r->maxInputFreq, r->inBuffer, r->bufSize, mp);
for (int i = 0; i < r->numVoices; ++i)
{
@@ -1589,6 +1589,7 @@
r->bufSize = bufSize;
r->numVoices = numVoices;
+ r->pdBuffer = (float*) mpool_alloc(sizeof(float) * 2048, m);
r->inBuffer = (float*) mpool_calloc(sizeof(float) * r->bufSize, m);
r->index = 0;
@@ -1600,7 +1601,7 @@
r->minInputFreq = minInputFreq;
r->maxInputFreq = maxInputFreq;
- tDualPitchDetector_initToPool(&r->dp, r->minInputFreq, r->maxInputFreq, mp);
+ tDualPitchDetector_initToPool(&r->dp, r->minInputFreq, r->maxInputFreq, r->pdBuffer, 2048, mp);
for (int i = 0; i < r->numVoices; ++i)
{
@@ -1623,6 +1624,7 @@
}
mpool_free((char*)r->shiftValues, r->mempool);
mpool_free((char*)r->ps, r->mempool);
+ mpool_free((char*)r->pdBuffer, r->mempool);
mpool_free((char*)r->inBuffer, r->mempool);
mpool_free((char*)r->outBuffers, r->mempool);
mpool_free((char*)r->output, r->mempool);
@@ -1666,10 +1668,7 @@
{
_tRetune* r = *rt;
- for (int i = 0; i < r->numVoices; ++i)
- {
- tPitchShift_setPickiness(&r->ps[i], p);
- }
+ tDualPitchDetector_setPeriodicityThreshold(&r->dp, p);
}
void tRetune_setNumVoices(tRetune* const rt, int numVoices)