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 {