Mercurial > hg > vamp-simple-cepstrum
comparison SimpleCepstrum.cpp @ 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 | fcb6562b43f7 |
comparison
equal
deleted
inserted
replaced
39:59701cbc4b93 | 40:d6acf12f0a8e |
---|---|
278 m_pkOutput = n++; | 278 m_pkOutput = n++; |
279 outputs.push_back(d); | 279 outputs.push_back(d); |
280 | 280 |
281 d.identifier = "interpolated_peak"; | 281 d.identifier = "interpolated_peak"; |
282 d.name = "Interpolated peak frequency"; | 282 d.name = "Interpolated peak frequency"; |
283 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"; | 283 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"; |
284 m_ipkOutput = n++; | 284 m_ipkOutput = n++; |
285 outputs.push_back(d); | 285 outputs.push_back(d); |
286 | 286 |
287 d.identifier = "variance"; | 287 d.identifier = "variance"; |
288 d.name = "Variance of cepstral bins in range"; | 288 d.name = "Variance of cepstral bins in range"; |
459 result[i] = mean; | 459 result[i] = mean; |
460 } | 460 } |
461 } | 461 } |
462 | 462 |
463 double | 463 double |
464 SimpleCepstrum::cubicInterpolate(const double y[4], double x) | |
465 { | |
466 double a0 = y[3] - y[2] - y[0] + y[1]; | |
467 double a1 = y[0] - y[1] - a0; | |
468 double a2 = y[2] - y[0]; | |
469 double a3 = y[1]; | |
470 return | |
471 a0 * x * x * x + | |
472 a1 * x * x + | |
473 a2 * x + | |
474 a3; | |
475 } | |
476 | |
477 double | |
478 SimpleCepstrum::findInterpolatedPeak(const double *in, int maxbin) | 464 SimpleCepstrum::findInterpolatedPeak(const double *in, int maxbin) |
479 { | 465 { |
480 if (maxbin < 2 || maxbin > m_bins - 3) { | 466 // after jos, |
467 // https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html | |
468 | |
469 if (maxbin < 1 || maxbin > m_bins - 2) { | |
481 return maxbin; | 470 return maxbin; |
482 } | 471 } |
483 | 472 |
484 double maxval = 0.0; | 473 double alpha = in[maxbin-1]; |
485 double maxidx = maxbin; | 474 double beta = in[maxbin]; |
486 | 475 double gamma = in[maxbin+1]; |
487 const int divisions = 10; | 476 |
488 double y[4]; | 477 double denom = (alpha - 2*beta + gamma); |
489 | 478 |
490 y[0] = in[maxbin-1]; | 479 if (denom == 0) { |
491 y[1] = in[maxbin]; | 480 // flat |
492 y[2] = in[maxbin+1]; | 481 return maxbin; |
493 y[3] = in[maxbin+2]; | 482 } |
494 for (int i = 0; i < divisions; ++i) { | 483 |
495 double probe = double(i) / double(divisions); | 484 double p = ((alpha - gamma) / denom) / 2.0; |
496 double value = cubicInterpolate(y, probe); | 485 |
497 if (value > maxval) { | 486 return double(maxbin) + p; |
498 maxval = value; | |
499 maxidx = maxbin + probe; | |
500 } | |
501 } | |
502 | |
503 y[3] = y[2]; | |
504 y[2] = y[1]; | |
505 y[1] = y[0]; | |
506 y[0] = in[maxbin-2]; | |
507 for (int i = 0; i < divisions; ++i) { | |
508 double probe = double(i) / double(divisions); | |
509 double value = cubicInterpolate(y, probe); | |
510 if (value > maxval) { | |
511 maxval = value; | |
512 maxidx = maxbin - 1 + probe; | |
513 } | |
514 } | |
515 | |
516 /* | |
517 std::cerr << "centre = " << maxbin << ": [" | |
518 << in[maxbin-2] << "," | |
519 << in[maxbin-1] << "," | |
520 << in[maxbin] << "," | |
521 << in[maxbin+1] << "," | |
522 << in[maxbin+2] << "] -> " << maxidx << std::endl; | |
523 */ | |
524 | |
525 return maxidx; | |
526 } | 487 } |
527 | 488 |
528 void | 489 void |
529 SimpleCepstrum::addStatisticalOutputs(FeatureSet &fs, const double *data) | 490 SimpleCepstrum::addStatisticalOutputs(FeatureSet &fs, const double *data) |
530 { | 491 { |