Mercurial > hg > pyin
changeset 136:7cbf40306c10 vamp-fft-revision
Add state to YinUtil, prepare to use the Vamp FFT (but don't actually use it yet)
author | Chris Cannam |
---|---|
date | Fri, 19 Aug 2016 12:00:13 +0100 |
parents | 2c73618b4067 |
children | 109c3a2ad930 |
files | LocalCandidatePYIN.cpp LocalCandidatePYIN.h Yin.cpp Yin.h YinUtil.cpp YinUtil.h |
diffstat | 6 files changed, 91 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/LocalCandidatePYIN.cpp Fri Aug 19 11:31:57 2016 +0100 +++ b/LocalCandidatePYIN.cpp Fri Aug 19 12:00:13 2016 +0100 @@ -48,12 +48,14 @@ m_preciseTime(0.0f), m_pitchProb(0), m_timestamp(0), - m_nCandidate(13) + m_nCandidate(13), + m_yinUtil(0) { } LocalCandidatePYIN::~LocalCandidatePYIN() { + delete m_yinUtil; } string @@ -268,6 +270,8 @@ m_channels = channels; m_stepSize = stepSize; m_blockSize = blockSize; + + m_yinUtil = new YinUtil(m_blockSize/2); reset(); @@ -297,20 +301,19 @@ size_t yinBufferSize = m_blockSize/2; double* yinBuffer = new double[yinBufferSize]; - if (!m_preciseTime) YinUtil::fastDifference(dInputBuffers, yinBuffer, yinBufferSize); - else YinUtil::slowDifference(dInputBuffers, yinBuffer, yinBufferSize); + if (!m_preciseTime) m_yinUtil->fastDifference(dInputBuffers, yinBuffer); + else m_yinUtil->slowDifference(dInputBuffers, yinBuffer); delete [] dInputBuffers; - YinUtil::cumulativeDifference(yinBuffer, yinBufferSize); + m_yinUtil->cumulativeDifference(yinBuffer); float minFrequency = 60; float maxFrequency = 900; - vector<double> peakProbability = YinUtil::yinProb(yinBuffer, - m_threshDistr, - yinBufferSize, - m_inputSampleRate/maxFrequency, - m_inputSampleRate/minFrequency); + vector<double> peakProbability = m_yinUtil->yinProb(yinBuffer, + m_threshDistr, + m_inputSampleRate/maxFrequency, + m_inputSampleRate/minFrequency); vector<pair<double, double> > tempPitchProb; for (size_t iBuf = 0; iBuf < yinBufferSize; ++iBuf) @@ -319,7 +322,7 @@ { double currentF0 = m_inputSampleRate * (1.0 / - YinUtil::parabolicInterpolation(yinBuffer, iBuf, yinBufferSize)); + m_yinUtil->parabolicInterpolation(yinBuffer, iBuf)); double tempPitch = 12 * std::log(currentF0/440)/std::log(2.) + 69; tempPitchProb.push_back(pair<double, double>(tempPitch, peakProbability[iBuf])); }
--- a/LocalCandidatePYIN.h Fri Aug 19 11:31:57 2016 +0100 +++ b/LocalCandidatePYIN.h Fri Aug 19 12:00:13 2016 +0100 @@ -18,6 +18,8 @@ #include "Yin.h" +class YinUtil; + class LocalCandidatePYIN : public Vamp::Plugin { public: @@ -70,6 +72,8 @@ vector<vector<pair<double, double> > > m_pitchProb; vector<Vamp::RealTime> m_timestamp; size_t m_nCandidate; + + YinUtil *m_yinUtil; }; #endif
--- a/Yin.cpp Fri Aug 19 11:31:57 2016 +0100 +++ b/Yin.cpp Fri Aug 19 12:00:13 2016 +0100 @@ -31,7 +31,8 @@ m_thresh(thresh), m_threshDistr(2), m_yinBufferSize(frameSize/2), - m_fast(fast) + m_fast(fast), + m_yinUtil(new YinUtil(m_yinBufferSize)) { if (frameSize & (frameSize-1)) { // throw "N must be a power of two"; @@ -40,6 +41,7 @@ Yin::~Yin() { + delete m_yinUtil; } Yin::YinOutput @@ -48,13 +50,13 @@ double* yinBuffer = new double[m_yinBufferSize]; // calculate aperiodicity function for all periods - if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize); - else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize); + if (m_fast) m_yinUtil->fastDifference(in, yinBuffer); + else m_yinUtil->slowDifference(in, yinBuffer); - YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize); + m_yinUtil->cumulativeDifference(yinBuffer); int tau = 0; - tau = YinUtil::absoluteThreshold(yinBuffer, m_yinBufferSize, m_thresh); + tau = m_yinUtil->absoluteThreshold(yinBuffer, m_thresh); double interpolatedTau; double aperiodicity; @@ -62,13 +64,13 @@ if (tau!=0) { - interpolatedTau = YinUtil::parabolicInterpolation(yinBuffer, abs(tau), m_yinBufferSize); + interpolatedTau = m_yinUtil->parabolicInterpolation(yinBuffer, abs(tau)); f0 = m_inputSampleRate * (1.0 / interpolatedTau); } else { interpolatedTau = 0; f0 = 0; } - double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); + double rms = std::sqrt(m_yinUtil->sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); aperiodicity = yinBuffer[abs(tau)]; // std::cerr << aperiodicity << std::endl; if (tau < 0) f0 = -f0; @@ -89,12 +91,12 @@ double* yinBuffer = new double[m_yinBufferSize]; // calculate aperiodicity function for all periods - if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize); - else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize); + if (m_fast) m_yinUtil->fastDifference(in, yinBuffer); + else m_yinUtil->slowDifference(in, yinBuffer); - YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize); + m_yinUtil->cumulativeDifference(yinBuffer); - vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize); + vector<double> peakProbability = m_yinUtil->yinProb(yinBuffer, m_threshDistr); // calculate overall "probability" from peak probability double probSum = 0; @@ -102,7 +104,7 @@ { probSum += peakProbability[iBin]; } - double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); + double rms = std::sqrt(m_yinUtil->sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); Yin::YinOutput yo(0,0,rms); for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf) { @@ -111,7 +113,7 @@ { double currentF0 = m_inputSampleRate * (1.0 / - YinUtil::parabolicInterpolation(yinBuffer, iBuf, m_yinBufferSize)); + m_yinUtil->parabolicInterpolation(yinBuffer, iBuf)); yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf])); } }
--- a/Yin.h Fri Aug 19 11:31:57 2016 +0100 +++ b/Yin.h Fri Aug 19 12:00:13 2016 +0100 @@ -26,6 +26,8 @@ using std::vector; using std::pair; +class YinUtil; + class Yin { public: @@ -64,6 +66,7 @@ mutable size_t m_yinBufferSize; mutable bool m_fast; // mutable bool m_removeUnvoiced; + YinUtil *m_yinUtil; }; #endif
--- a/YinUtil.cpp Fri Aug 19 11:31:57 2016 +0100 +++ b/YinUtil.cpp Fri Aug 19 12:00:13 2016 +0100 @@ -21,17 +21,27 @@ #include <boost/math/distributions.hpp> +YinUtil::YinUtil(size_t yinBufferSize) : + m_yinBufferSize(yinBufferSize), + m_fft(yinBufferSize * 2) +{ +} + +YinUtil::~YinUtil() +{ +} + void -YinUtil::slowDifference(const double *in, double *yinBuffer, const size_t yinBufferSize) +YinUtil::slowDifference(const double *in, double *yinBuffer) { yinBuffer[0] = 0; double delta ; int startPoint = 0; int endPoint = 0; - for (int i = 1; i < yinBufferSize; ++i) { + for (int i = 1; i < m_yinBufferSize; ++i) { yinBuffer[i] = 0; - startPoint = yinBufferSize/2 - i/2; - endPoint = startPoint + yinBufferSize; + startPoint = m_yinBufferSize/2 - i/2; + endPoint = startPoint + m_yinBufferSize; for (int j = startPoint; j < endPoint; ++j) { delta = in[i+j] - in[j]; yinBuffer[i] += delta * delta; @@ -40,14 +50,14 @@ } void -YinUtil::fastDifference(const double *in, double *yinBuffer, const size_t yinBufferSize) +YinUtil::fastDifference(const double *in, double *yinBuffer) { // DECLARE AND INITIALISE // initialisation of most of the arrays here was done in a separate function, // with all the arrays as members of the class... moved them back here. - size_t frameSize = 2 * yinBufferSize; + size_t frameSize = 2 * m_yinBufferSize; double *audioTransformedReal = new double[frameSize]; double *audioTransformedImag = new double[frameSize]; @@ -57,9 +67,9 @@ double *kernelTransformedImag = new double[frameSize]; double *yinStyleACFReal = new double[frameSize]; double *yinStyleACFImag = new double[frameSize]; - double *powerTerms = new double[yinBufferSize]; + double *powerTerms = new double[m_yinBufferSize]; - for (size_t j = 0; j < yinBufferSize; ++j) + for (size_t j = 0; j < m_yinBufferSize; ++j) { yinBuffer[j] = 0.; // set to zero powerTerms[j] = 0.; // set to zero @@ -80,13 +90,13 @@ // POWER TERM CALCULATION // ... for the power terms in equation (7) in the Yin paper powerTerms[0] = 0.0; - for (size_t j = 0; j < yinBufferSize; ++j) { + for (size_t j = 0; j < m_yinBufferSize; ++j) { powerTerms[0] += in[j] * in[j]; } // now iteratively calculate all others (saves a few multiplications) - for (size_t tau = 1; tau < yinBufferSize; ++tau) { - powerTerms[tau] = powerTerms[tau-1] - in[tau-1] * in[tau-1] + in[tau+yinBufferSize] * in[tau+yinBufferSize]; + for (size_t tau = 1; tau < m_yinBufferSize; ++tau) { + powerTerms[tau] = powerTerms[tau-1] - in[tau-1] * in[tau-1] + in[tau+m_yinBufferSize] * in[tau+m_yinBufferSize]; } // YIN-STYLE AUTOCORRELATION via FFT @@ -94,8 +104,8 @@ Vamp::FFT::forward(frameSize, in, nullImag, audioTransformedReal, audioTransformedImag); // 2. half of the data, disguised as a convolution kernel - for (size_t j = 0; j < yinBufferSize; ++j) { - kernel[j] = in[yinBufferSize-1-j]; + for (size_t j = 0; j < m_yinBufferSize; ++j) { + kernel[j] = in[m_yinBufferSize-1-j]; } Vamp::FFT::forward(frameSize, kernel, nullImag, kernelTransformedReal, kernelTransformedImag); @@ -108,9 +118,9 @@ // CALCULATION OF difference function // ... according to (7) in the Yin paper. - for (size_t j = 0; j < yinBufferSize; ++j) { + for (size_t j = 0; j < m_yinBufferSize; ++j) { // taking only the real part - yinBuffer[j] = powerTerms[0] + powerTerms[j] - 2 * audioTransformedReal[j+yinBufferSize-1]; + yinBuffer[j] = powerTerms[0] + powerTerms[j] - 2 * audioTransformedReal[j+m_yinBufferSize-1]; } delete [] audioTransformedReal; delete [] audioTransformedImag; @@ -124,7 +134,7 @@ } void -YinUtil::cumulativeDifference(double *yinBuffer, const size_t yinBufferSize) +YinUtil::cumulativeDifference(double *yinBuffer) { size_t tau; @@ -132,7 +142,7 @@ double runningSum = 0; - for (tau = 1; tau < yinBufferSize; ++tau) { + for (tau = 1; tau < m_yinBufferSize; ++tau) { runningSum += yinBuffer[tau]; if (runningSum == 0) { @@ -144,7 +154,7 @@ } int -YinUtil::absoluteThreshold(const double *yinBuffer, const size_t yinBufferSize, const double thresh) +YinUtil::absoluteThreshold(const double *yinBuffer, const double thresh) { size_t tau; size_t minTau = 0; @@ -152,11 +162,11 @@ // using Joren Six's "loop construct" from TarsosDSP tau = 2; - while (tau < yinBufferSize) + while (tau < m_yinBufferSize) { if (yinBuffer[tau] < thresh) { - while (tau+1 < yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau]) + while (tau+1 < m_yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau]) { ++tau; } @@ -187,20 +197,20 @@ static float single20[100] = {0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,1.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000}; std::vector<double> -YinUtil::yinProb(const double *yinBuffer, const size_t prior, const size_t yinBufferSize, const size_t minTau0, const size_t maxTau0) +YinUtil::yinProb(const double *yinBuffer, const size_t prior, const size_t minTau0, const size_t maxTau0) { size_t minTau = 2; - size_t maxTau = yinBufferSize; + size_t maxTau = m_yinBufferSize; // adapt period range, if necessary if (minTau0 > 0 && minTau0 < maxTau0) minTau = minTau0; - if (maxTau0 > 0 && maxTau0 < yinBufferSize && maxTau0 > minTau) maxTau = maxTau0; + if (maxTau0 > 0 && maxTau0 < m_yinBufferSize && maxTau0 > minTau) maxTau = maxTau0; double minWeight = 0.01; size_t tau; std::vector<float> thresholds; std::vector<float> distribution; - std::vector<double> peakProb = std::vector<double>(yinBufferSize); + std::vector<double> peakProb = std::vector<double>(m_yinBufferSize); size_t nThreshold = 100; int nThresholdInt = nThreshold; @@ -303,7 +313,7 @@ if (peakProb[minInd] > 1) { std::cerr << "WARNING: yin has prob > 1 ??? I'm returning all zeros instead." << std::endl; - return(std::vector<double>(yinBufferSize)); + return(std::vector<double>(m_yinBufferSize)); } double nonPeakProb = 1; @@ -324,16 +334,16 @@ } double -YinUtil::parabolicInterpolation(const double *yinBuffer, const size_t tau, const size_t yinBufferSize) +YinUtil::parabolicInterpolation(const double *yinBuffer, const size_t tau) { // this is taken almost literally from Joren Six's Java implementation - if (tau == yinBufferSize) // not valid anyway. + if (tau == m_yinBufferSize) // not valid anyway. { return static_cast<double>(tau); } double betterTau = 0.0; - if (tau > 0 && tau < yinBufferSize-1) { + if (tau > 0 && tau < m_yinBufferSize-1) { float s0, s1, s2; s0 = yinBuffer[tau-1]; s1 = yinBuffer[tau];
--- a/YinUtil.h Fri Aug 19 11:31:57 2016 +0100 +++ b/YinUtil.h Fri Aug 19 12:00:13 2016 +0100 @@ -14,29 +14,35 @@ #ifndef _YINUTIL_H_ #define _YINUTIL_H_ -#include "vamp-sdk/FFT.h" -#include "MeanFilter.h" - #include <cmath> #include <iostream> #include <vector> #include <exception> +#include "vamp-sdk/FFT.h" + using std::vector; class YinUtil { public: - static double sumSquare(const double *in, const size_t startInd, const size_t endInd); - static void difference(const double *in, double *yinBuffer, const size_t yinBufferSize); - static void fastDifference(const double *in, double *yinBuffer, const size_t yinBufferSize); - static void slowDifference(const double *in, double *yinBuffer, const size_t yinBufferSize); - static void cumulativeDifference(double *yinBuffer, const size_t yinBufferSize); - static int absoluteThreshold(const double *yinBuffer, const size_t yinBufferSize, const double thresh); - static vector<double> yinProb(const double *yinBuffer, const size_t prior, const size_t yinBufferSize, size_t minTau = 0, size_t maxTau = 0); - static double parabolicInterpolation(const double *yinBuffer, const size_t tau, - const size_t yinBufferSize); + YinUtil(size_t yinBufferSize); + ~YinUtil(); + + double sumSquare(const double *in, const size_t startInd, const size_t endInd); + void difference(const double *in, double *yinBuffer); + void fastDifference(const double *in, double *yinBuffer); + void slowDifference(const double *in, double *yinBuffer); + void cumulativeDifference(double *yinBuffer); + int absoluteThreshold(const double *yinBuffer, const double thresh); + vector<double> yinProb(const double *yinBuffer, const size_t prior, + size_t minTau = 0, size_t maxTau = 0); + double parabolicInterpolation(const double *yinBuffer, const size_t tau); + +private: + const size_t m_yinBufferSize; + Vamp::FFTReal m_fft; }; #endif