shithub: leaf

Download patch

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)