Mercurial > hg > cepstral-pitchtracker
diff CepstrumPitchTracker.cpp @ 18:131b1c40be1a
Clumsily cut-n-paste interpolation into pitch tracker as well
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2012 21:54:50 +0100 |
parents | 088da53a2869 |
children | f9c4c4568fb0 |
line wrap: on
line diff
--- a/CepstrumPitchTracker.cpp Wed Jul 04 22:28:46 2012 +0100 +++ b/CepstrumPitchTracker.cpp Thu Jul 05 21:54:50 2012 +0100 @@ -220,7 +220,7 @@ m_blockSize(1024), m_fmin(50), m_fmax(1000), - m_vflen(3), + m_vflen(1), m_binFrom(0), m_binTo(0), m_bins(0) @@ -428,6 +428,71 @@ } } +double +CepstrumPitchTracker::cubicInterpolate(const double y[4], double x) +{ + double a0 = y[3] - y[2] - y[0] + y[1]; + double a1 = y[0] - y[1] - a0; + double a2 = y[2] - y[0]; + double a3 = y[1]; + return + a0 * x * x * x + + a1 * x * x + + a2 * x + + a3; +} + +double +CepstrumPitchTracker::findInterpolatedPeak(const double *in, int maxbin) +{ + if (maxbin < 2 || maxbin > m_bins - 3) { + return maxbin; + } + + double maxval = 0.0; + double maxidx = maxbin; + + const int divisions = 10; + double y[4]; + + y[0] = in[maxbin-1]; + y[1] = in[maxbin]; + y[2] = in[maxbin+1]; + y[3] = in[maxbin+2]; + for (int i = 0; i < divisions; ++i) { + double probe = double(i) / double(divisions); + double value = cubicInterpolate(y, probe); + if (value > maxval) { + maxval = value; + maxidx = maxbin + probe; + } + } + + y[3] = y[2]; + y[2] = y[1]; + y[1] = y[0]; + y[0] = in[maxbin-2]; + for (int i = 0; i < divisions; ++i) { + double probe = double(i) / double(divisions); + double value = cubicInterpolate(y, probe); + if (value > maxval) { + maxval = value; + maxidx = maxbin - 1 + probe; + } + } + +/* + std::cerr << "centre = " << maxbin << ": [" + << in[maxbin-2] << "," + << in[maxbin-1] << "," + << in[maxbin] << "," + << in[maxbin+1] << "," + << in[maxbin+2] << "] -> " << maxidx << std::endl; +*/ + + return maxidx; +} + CepstrumPitchTracker::FeatureSet CepstrumPitchTracker::process(const float *const *inputBuffers, RealTime timestamp) { @@ -496,7 +561,8 @@ } } - double peakfreq = m_inputSampleRate / (maxbin + m_binFrom); + double cimax = findInterpolatedPeak(data, maxbin); + double peakfreq = m_inputSampleRate / (cimax + m_binFrom); double confidence = 0.0; if (nextPeakVal != 0.0) {