Mercurial > hg > vamp-simple-cepstrum
changeset 40:d6acf12f0a8e
Switch from cubic to much simpler & faster parabolic interpolator
author | Chris Cannam |
---|---|
date | Fri, 20 Jul 2012 22:12:16 +0100 |
parents | 59701cbc4b93 |
children | 0475318170c8 |
files | SimpleCepstrum.cpp |
diffstat | 1 files changed, 14 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/SimpleCepstrum.cpp Thu Jul 19 17:51:57 2012 +0100 +++ b/SimpleCepstrum.cpp Fri Jul 20 22:12:16 2012 +0100 @@ -280,7 +280,7 @@ d.identifier = "interpolated_peak"; d.name = "Interpolated peak frequency"; - d.description = "Return the frequency whose period corresponds to the quefrency with the maximum bin value within the specified range of the cepstrum, using cubic interpolation to estimate the peak quefrency to finer than single bin resolution"; + d.description = "Return the frequency whose period corresponds to the quefrency with the maximum bin value within the specified range of the cepstrum, using parabolic interpolation to estimate the peak quefrency to finer than single bin resolution"; m_ipkOutput = n++; outputs.push_back(d); @@ -461,68 +461,29 @@ } double -SimpleCepstrum::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 SimpleCepstrum::findInterpolatedPeak(const double *in, int maxbin) { - if (maxbin < 2 || maxbin > m_bins - 3) { + // after jos, + // https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html + + if (maxbin < 1 || maxbin > m_bins - 2) { return maxbin; } - double maxval = 0.0; - double maxidx = maxbin; + double alpha = in[maxbin-1]; + double beta = in[maxbin]; + double gamma = in[maxbin+1]; - const int divisions = 10; - double y[4]; + double denom = (alpha - 2*beta + gamma); - 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; - } + if (denom == 0) { + // flat + return maxbin; } - 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; - } - } + double p = ((alpha - gamma) / denom) / 2.0; -/* - std::cerr << "centre = " << maxbin << ": [" - << in[maxbin-2] << "," - << in[maxbin-1] << "," - << in[maxbin] << "," - << in[maxbin+1] << "," - << in[maxbin+2] << "] -> " << maxidx << std::endl; -*/ - - return maxidx; + return double(maxbin) + p; } void