Mercurial > hg > vamp-simple-cepstrum
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 } |