comparison SimpleCepstrum.cpp @ 24:0a3c1ecff644

Add rather simplistic cubic interpolation for peak values in a cepstrum output (not yet for pitch tracker). Only gains us 1dp
author Chris Cannam
date Thu, 05 Jul 2012 20:50:56 +0100
parents 7786d595d2f2
children 44bb93cae288
comparison
equal deleted inserted replaced
23:1ae8041ae31b 24:0a3c1ecff644
255 255
256 OutputDescriptor d; 256 OutputDescriptor d;
257 257
258 d.identifier = "raw_cepstral_peak"; 258 d.identifier = "raw_cepstral_peak";
259 d.name = "Frequency corresponding to raw cepstral peak"; 259 d.name = "Frequency corresponding to raw cepstral peak";
260 d.description = "Return the frequency whose period corresponds to the quefrency with the maximum value within the specified range of the cepstrum"; 260 d.description = "Return the frequency whose period corresponds to the quefrency with the maximum bin value within the specified range of the cepstrum";
261 d.unit = "Hz"; 261 d.unit = "Hz";
262 d.hasFixedBinCount = true; 262 d.hasFixedBinCount = true;
263 d.binCount = 1; 263 d.binCount = 1;
264 d.hasKnownExtents = true; 264 d.hasKnownExtents = true;
265 d.minValue = m_fmin; 265 d.minValue = m_fmin;
268 d.sampleType = OutputDescriptor::OneSamplePerStep; 268 d.sampleType = OutputDescriptor::OneSamplePerStep;
269 d.hasDuration = false; 269 d.hasDuration = false;
270 m_pkOutput = n++; 270 m_pkOutput = n++;
271 outputs.push_back(d); 271 outputs.push_back(d);
272 272
273 d.identifier = "interpolated_peak";
274 d.name = "Interpolated peak frequency";
275 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";
276 m_ipkOutput = n++;
277 outputs.push_back(d);
278
273 d.identifier = "variance"; 279 d.identifier = "variance";
274 d.name = "Variance of cepstral bins in range"; 280 d.name = "Variance of cepstral bins in range";
275 d.unit = ""; 281 d.unit = "";
276 d.description = "Return the variance of bin values within the specified range of the cepstrum"; 282 d.description = "Return the variance of bin values within the specified range of the cepstrum";
277 d.hasKnownExtents = false; 283 d.hasKnownExtents = false;
443 } 449 }
444 mean /= m_histlen; 450 mean /= m_histlen;
445 result[i] = mean; 451 result[i] = mean;
446 } 452 }
447 } 453 }
454
455 double
456 SimpleCepstrum::cubicInterpolate(const double y[4], double x)
457 {
458 double a0 = y[3] - y[2] - y[0] + y[1];
459 double a1 = y[0] - y[1] - a0;
460 double a2 = y[2] - y[0];
461 double a3 = y[1];
462 return
463 a0 * x * x * x +
464 a1 * x * x +
465 a2 * x +
466 a3;
467 }
468
469 double
470 SimpleCepstrum::findInterpolatedPeak(const double *in, int maxbin)
471 {
472 if (maxbin < 2 || maxbin > m_bins - 3) {
473 return maxbin;
474 }
475
476 double maxval = 0.0;
477 double maxidx = maxbin;
478
479 const int divisions = 10;
480 double y[4];
481
482 y[0] = in[maxbin-1];
483 y[1] = in[maxbin];
484 y[2] = in[maxbin+1];
485 y[3] = in[maxbin+2];
486 for (int i = 0; i < divisions; ++i) {
487 double probe = double(i) / double(divisions);
488 double value = cubicInterpolate(y, probe);
489 if (value > maxval) {
490 maxval = value;
491 maxidx = maxbin + probe;
492 }
493 }
494
495 y[3] = y[2];
496 y[2] = y[1];
497 y[1] = y[0];
498 y[0] = in[maxbin-2];
499 for (int i = 0; i < divisions; ++i) {
500 double probe = double(i) / double(divisions);
501 double value = cubicInterpolate(y, probe);
502 if (value > maxval) {
503 maxval = value;
504 maxidx = maxbin - 1 + probe;
505 }
506 }
507
508 /*
509 std::cerr << "centre = " << maxbin << ": ["
510 << in[maxbin-2] << ","
511 << in[maxbin-1] << ","
512 << in[maxbin] << ","
513 << in[maxbin+1] << ","
514 << in[maxbin+2] << "] -> " << maxidx << std::endl;
515 */
516
517 return maxidx;
518 }
448 519
449 void 520 void
450 SimpleCepstrum::addStatisticalOutputs(FeatureSet &fs, const double *data) 521 SimpleCepstrum::addStatisticalOutputs(FeatureSet &fs, const double *data)
451 { 522 {
452 int n = m_bins; 523 int n = m_bins;
471 nextPeakVal = data[i]; 542 nextPeakVal = data[i];
472 } 543 }
473 } 544 }
474 545
475 Feature rf; 546 Feature rf;
547 Feature irf;
476 if (maxval > 0.0) { 548 if (maxval > 0.0) {
477 rf.values.push_back(m_inputSampleRate / (maxbin + m_binFrom)); 549 rf.values.push_back(m_inputSampleRate / (maxbin + m_binFrom));
550 double cimax = findInterpolatedPeak(data, maxbin);
551 irf.values.push_back(m_inputSampleRate / (cimax + m_binFrom));
478 } else { 552 } else {
479 rf.values.push_back(0); 553 rf.values.push_back(0);
554 irf.values.push_back(0);
480 } 555 }
481 fs[m_pkOutput].push_back(rf); 556 fs[m_pkOutput].push_back(rf);
557 fs[m_ipkOutput].push_back(irf);
482 558
483 double total = 0; 559 double total = 0;
484 for (int i = 0; i < n; ++i) { 560 for (int i = 0; i < n; ++i) {
485 total += data[i]; 561 total += data[i];
486 } 562 }