| 43 |
43 |
m_binFrom(0),
|
| 44 |
44 |
m_binTo(0),
|
| 45 |
45 |
m_bins(0),
|
| 46 |
|
m_history(0)
|
|
46 |
m_history(0),
|
|
47 |
m_prevpeak(0),
|
|
48 |
m_prevprop(0)
|
| 47 |
49 |
{
|
| 48 |
50 |
}
|
| 49 |
51 |
|
| ... | ... | |
| 270 |
272 |
}
|
| 271 |
273 |
}
|
| 272 |
274 |
|
|
275 |
double
|
|
276 |
CepstrumPitchTracker::calculatePeakProportion(const double *data, double abstot, int n)
|
|
277 |
{
|
|
278 |
double aroundPeak = data[n];
|
|
279 |
double peakProportion = 0.0;
|
|
280 |
|
|
281 |
int i = n - 1;
|
|
282 |
while (i > 0 && data[i] <= data[i+1]) {
|
|
283 |
aroundPeak += fabs(data[i]);
|
|
284 |
--i;
|
|
285 |
}
|
|
286 |
i = n + 1;
|
|
287 |
while (i < m_bins && data[i] <= data[i-1]) {
|
|
288 |
aroundPeak += fabs(data[i]);
|
|
289 |
++i;
|
|
290 |
}
|
|
291 |
peakProportion = aroundPeak / abstot;
|
|
292 |
|
|
293 |
return peakProportion;
|
|
294 |
}
|
|
295 |
|
|
296 |
bool
|
|
297 |
CepstrumPitchTracker::acceptPeak(int n, double peakProportion)
|
|
298 |
{
|
|
299 |
bool accept = false;
|
|
300 |
|
|
301 |
if (abs(n - m_prevpeak) < 10) { //!!! should depend on bin count
|
|
302 |
accept = true;
|
|
303 |
} else if (peakProportion > m_prevprop * 2) {
|
|
304 |
accept = true;
|
|
305 |
}
|
|
306 |
|
|
307 |
return accept;
|
|
308 |
}
|
|
309 |
|
| 273 |
310 |
CepstrumPitchTracker::FeatureSet
|
| 274 |
311 |
CepstrumPitchTracker::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
|
| 275 |
312 |
{
|
| ... | ... | |
| 307 |
344 |
filter(rawcep, data);
|
| 308 |
345 |
delete[] rawcep;
|
| 309 |
346 |
|
|
347 |
double abstot = 0.0;
|
|
348 |
|
|
349 |
for (int i = 0; i < n; ++i) {
|
|
350 |
abstot += fabs(data[i]);
|
|
351 |
}
|
|
352 |
|
| 310 |
353 |
double maxval = 0.0;
|
| 311 |
|
int maxbin = 0;
|
| 312 |
|
double abstot = 0.0;
|
|
354 |
int maxbin = -1;
|
| 313 |
355 |
|
| 314 |
356 |
for (int i = 0; i < n; ++i) {
|
| 315 |
357 |
if (data[i] > maxval) {
|
| 316 |
358 |
maxval = data[i];
|
| 317 |
359 |
maxbin = i;
|
| 318 |
360 |
}
|
| 319 |
|
abstot += fabs(data[i]);
|
| 320 |
361 |
}
|
| 321 |
362 |
|
| 322 |
|
double aroundPeak = 0.0;
|
| 323 |
|
double peakProportion = 0.0;
|
| 324 |
|
if (maxval > 0.0) {
|
| 325 |
|
aroundPeak += fabs(maxval);
|
| 326 |
|
int i = maxbin - 1;
|
| 327 |
|
while (i > 0 && data[i] <= data[i+1]) {
|
| 328 |
|
aroundPeak += fabs(data[i]);
|
| 329 |
|
--i;
|
|
363 |
bool accepted = false;
|
|
364 |
|
|
365 |
if (maxbin >= 0) {
|
|
366 |
double pp = calculatePeakProportion(data, abstot, maxbin);
|
|
367 |
if (acceptPeak(maxbin, pp)) {
|
|
368 |
accepted = true;
|
|
369 |
} else {
|
|
370 |
// try a secondary peak
|
|
371 |
maxval = 0.0;
|
|
372 |
int secondbin = 0;
|
|
373 |
for (int i = 1; i < n-1; ++i) {
|
|
374 |
if (i != maxbin &&
|
|
375 |
data[i] > data[i-1] &&
|
|
376 |
data[i] > data[i+1] &&
|
|
377 |
data[i] > maxval) {
|
|
378 |
maxval = data[i];
|
|
379 |
secondbin = i;
|
|
380 |
}
|
|
381 |
}
|
|
382 |
double spp = calculatePeakProportion(data, abstot, secondbin);
|
|
383 |
if (acceptPeak(secondbin, spp)) {
|
|
384 |
maxbin = secondbin;
|
|
385 |
pp = spp;
|
|
386 |
accepted = true;
|
|
387 |
}
|
| 330 |
388 |
}
|
| 331 |
|
i = maxbin + 1;
|
| 332 |
|
while (i < n && data[i] <= data[i-1]) {
|
| 333 |
|
aroundPeak += fabs(data[i]);
|
| 334 |
|
++i;
|
|
389 |
if (accepted) {
|
|
390 |
m_prevpeak = maxbin;
|
|
391 |
m_prevprop = pp;
|
| 335 |
392 |
}
|
| 336 |
393 |
}
|
| 337 |
|
peakProportion = aroundPeak / abstot;
|
| 338 |
|
|
|
394 |
|
| 339 |
395 |
// std::cerr << "peakProportion = " << peakProportion << std::endl;
|
| 340 |
396 |
// std::cerr << "peak = " << m_inputSampleRate / (maxbin + m_binFrom) << std::endl;
|
| 341 |
397 |
// std::cerr << "bins = " << m_bins << std::endl;
|
| 342 |
398 |
|
| 343 |
|
if (peakProportion >= (0.00006 * m_bins)) {
|
|
399 |
// if (peakProportion >= (0.00006 * m_bins)) {
|
|
400 |
if (accepted) {
|
| 344 |
401 |
Feature f;
|
| 345 |
402 |
f.hasTimestamp = true;
|
| 346 |
403 |
f.timestamp = timestamp;
|