comparison TempogramPlugin.cpp @ 21:12b952286959

* Debugging 1Hz freeze using vamp-plugin-tester
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Mon, 18 Aug 2014 15:22:44 +0100
parents de7213b35755
children 99380ba63be6
comparison
equal deleted inserted replaced
20:de7213b35755 21:12b952286959
326 OutputList list; 326 OutputList list;
327 327
328 // See OutputDescriptor documentation for the possibilities here. 328 // See OutputDescriptor documentation for the possibilities here.
329 // Every plugin must have at least one output. 329 // Every plugin must have at least one output.
330 330
331 OutputDescriptor d1;
332 float d_sampleRate; 331 float d_sampleRate;
333 float tempogramInputSampleRate = (float)m_inputSampleRate/m_inputStepSize; 332 float tempogramInputSampleRate = (float)m_inputSampleRate/m_inputStepSize;
334 333
334 OutputDescriptor d3;
335 d3.identifier = "cyclicTempogram";
336 d3.name = "Cyclic Tempogram";
337 d3.description = "Cyclic Tempogram";
338 d3.unit = "";
339 d3.hasFixedBinCount = true;
340 d3.binCount = m_cyclicTempogramOctaveDivider > 0 && !isnan(m_cyclicTempogramOctaveDivider) ? m_cyclicTempogramOctaveDivider : 0;
341 d3.hasKnownExtents = false;
342 d3.isQuantized = false;
343 d3.sampleType = OutputDescriptor::FixedSampleRate;
344 d_sampleRate = tempogramInputSampleRate/m_tempogramHopSize;
345 d3.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0;
346 d3.hasDuration = false;
347 list.push_back(d3);
348
349 OutputDescriptor d1;
335 d1.identifier = "tempogram"; 350 d1.identifier = "tempogram";
336 d1.name = "Tempogram"; 351 d1.name = "Tempogram";
337 d1.description = "Tempogram"; 352 d1.description = "Tempogram";
338 d1.unit = "BPM"; 353 d1.unit = "BPM";
339 d1.hasFixedBinCount = true; 354 d1.hasFixedBinCount = true;
363 d_sampleRate = tempogramInputSampleRate; 378 d_sampleRate = tempogramInputSampleRate;
364 d2.sampleRate = d_sampleRate > 0 && !isnan(d_sampleRate) ? d_sampleRate : 0; 379 d2.sampleRate = d_sampleRate > 0 && !isnan(d_sampleRate) ? d_sampleRate : 0;
365 d2.hasDuration = false; 380 d2.hasDuration = false;
366 list.push_back(d2); 381 list.push_back(d2);
367 382
368 OutputDescriptor d3;
369 d3.identifier = "cyclicTempogram";
370 d3.name = "Cyclic Tempogram";
371 d3.description = "Cyclic Tempogram";
372 d3.unit = "";
373 d3.hasFixedBinCount = true;
374 d3.binCount = m_cyclicTempogramOctaveDivider > 0 && !isnan(m_cyclicTempogramOctaveDivider) ? m_cyclicTempogramOctaveDivider : 0;
375 d3.hasKnownExtents = false;
376 d3.isQuantized = false;
377 d3.sampleType = OutputDescriptor::FixedSampleRate;
378 d_sampleRate = tempogramInputSampleRate/m_tempogramHopSize;
379 d3.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0;
380 d3.hasDuration = false;
381 list.push_back(d3);
382
383 return list; 383 return list;
384 } 384 }
385 385
386 void TempogramPlugin::checkParameterValues(){ 386 bool TempogramPlugin::handleParameterValues(){
387
388 if (m_tempogramHopSize <= 0) return false;
389 if (m_tempogramLog2FftLength <= 0) return false;
387 390
388 if (m_tempogramFftLength < m_tempogramWindowLength){ 391 if (m_tempogramFftLength < m_tempogramWindowLength){
389 m_tempogramFftLength = m_tempogramWindowLength; 392 m_tempogramFftLength = m_tempogramWindowLength;
390 } 393 }
391 if (m_tempogramMinBPM > m_tempogramMaxBPM){ 394 if (m_tempogramMinBPM > m_tempogramMaxBPM){
392 m_tempogramMinBPM = 30; 395 m_tempogramMinBPM = 30;
393 m_tempogramMaxBPM = 480; 396 m_tempogramMaxBPM = 480;
394 } 397 }
395 398
396 float tempogramInputSampleRate = (float)m_inputSampleRate/m_inputStepSize; 399 float tempogramInputSampleRate = (float)m_inputSampleRate/m_inputStepSize;
397 m_tempogramMinBin = (unsigned int)(max(floor(((m_tempogramMinBPM/60)/tempogramInputSampleRate)*m_tempogramFftLength), (float)0.0)); 400 m_tempogramMinBin = (max(floor(((m_tempogramMinBPM/60)/tempogramInputSampleRate)*m_tempogramFftLength), (float)0.0));
398 m_tempogramMaxBin = (unsigned int)(min(ceil(((m_tempogramMaxBPM/60)/tempogramInputSampleRate)*m_tempogramFftLength), (float)m_tempogramFftLength/2)); 401 m_tempogramMaxBin = (min(ceil(((m_tempogramMaxBPM/60)/tempogramInputSampleRate)*m_tempogramFftLength), (float)m_tempogramFftLength/2));
399 402
400 if (m_tempogramMinBPM > m_cyclicTempogramMinBPM) m_cyclicTempogramMinBPM = m_tempogramMinBPM; 403 if (m_tempogramMinBPM > m_cyclicTempogramMinBPM) m_cyclicTempogramMinBPM = m_tempogramMinBPM;
401 float cyclicTempogramMaxBPM = 480; 404 float cyclicTempogramMaxBPM = 480;
402 if (m_tempogramMaxBPM < cyclicTempogramMaxBPM) cyclicTempogramMaxBPM = m_tempogramMaxBPM; 405 if (m_tempogramMaxBPM < cyclicTempogramMaxBPM) cyclicTempogramMaxBPM = m_tempogramMaxBPM;
403 406
404 m_cyclicTempogramNumberOfOctaves = floor(log2(cyclicTempogramMaxBPM/m_cyclicTempogramMinBPM)); 407 m_cyclicTempogramNumberOfOctaves = floor(log2(cyclicTempogramMaxBPM/m_cyclicTempogramMinBPM));
405 int numberOfBinsInFirstOctave = bpmToBin(m_cyclicTempogramMinBPM); 408 int numberOfBinsInFirstOctave = bpmToBin(m_cyclicTempogramMinBPM);
406 if (m_cyclicTempogramOctaveDivider > numberOfBinsInFirstOctave) m_cyclicTempogramOctaveDivider = numberOfBinsInFirstOctave; 409 if (m_cyclicTempogramOctaveDivider > numberOfBinsInFirstOctave) m_cyclicTempogramOctaveDivider = numberOfBinsInFirstOctave;
407 410
411 return true;
408 } 412 }
409 413
410 bool 414 bool
411 TempogramPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) 415 TempogramPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
412 { 416 {
416 // Real initialisation work goes here! 420 // Real initialisation work goes here!
417 m_inputBlockSize = blockSize; 421 m_inputBlockSize = blockSize;
418 m_inputStepSize = stepSize; 422 m_inputStepSize = stepSize;
419 423
420 m_spectrogram = SpectrogramTransposed(m_inputBlockSize/2.0f + 1); 424 m_spectrogram = SpectrogramTransposed(m_inputBlockSize/2.0f + 1);
421 checkParameterValues(); 425 if (!handleParameterValues()) return false;
422 //cout << m_cyclicTempogramOctaveDivider << endl; 426 //cout << m_cyclicTempogramOctaveDivider << endl;
423 427
424 return true; 428 return true;
425 } 429 }
426 430
428 TempogramPlugin::reset() 432 TempogramPlugin::reset()
429 { 433 {
430 // Clear buffers, reset stored values, etc 434 // Clear buffers, reset stored values, etc
431 m_spectrogram.clear(); 435 m_spectrogram.clear();
432 m_spectrogram = SpectrogramTransposed(m_inputBlockSize/2.0f + 1); 436 m_spectrogram = SpectrogramTransposed(m_inputBlockSize/2.0f + 1);
433 checkParameterValues(); 437 handleParameterValues();
434 } 438 }
435 439
436 TempogramPlugin::FeatureSet 440 TempogramPlugin::FeatureSet
437 TempogramPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp) 441 TempogramPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
438 { 442 {
443 //cerr << "Here" << endl;
444
439 size_t n = m_inputBlockSize/2 + 1; 445 size_t n = m_inputBlockSize/2 + 1;
440 446
441 FeatureSet featureSet; 447 FeatureSet featureSet;
442 Feature feature; 448 Feature feature;
443 449
447 for (int i = 0; i < (int)n; i++){ 453 for (int i = 0; i < (int)n; i++){
448 float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]); 454 float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]);
449 magnitude = magnitude > m_noveltyCurveMinDB ? magnitude : m_noveltyCurveMinDB; 455 magnitude = magnitude > m_noveltyCurveMinDB ? magnitude : m_noveltyCurveMinDB;
450 m_spectrogram[i].push_back(magnitude); 456 m_spectrogram[i].push_back(magnitude);
451 } 457 }
452 458
453 return featureSet; 459 return featureSet;
454 } 460 }
455 461
456 vector<unsigned int> TempogramPlugin::calculateTempogramNearestNeighbourLogBins() const 462 vector<unsigned int> TempogramPlugin::calculateTempogramNearestNeighbourLogBins() const
457 { 463 {
480 else if(bin > m_tempogramFftLength/2.0f) bin = m_tempogramFftLength; 486 else if(bin > m_tempogramFftLength/2.0f) bin = m_tempogramFftLength;
481 487
482 return bin; 488 return bin;
483 } 489 }
484 490
491 float TempogramPlugin::binToBPM(const int &bin) const
492 {
493 float sampleRate = m_inputSampleRate/m_inputStepSize;
494
495 return (bin*sampleRate/m_tempogramFftLength)*60;
496 }
497
485 TempogramPlugin::FeatureSet 498 TempogramPlugin::FeatureSet
486 TempogramPlugin::getRemainingFeatures() 499 TempogramPlugin::getRemainingFeatures()
487 { 500 {
488 501
489 float * hannWindow = new float[m_tempogramWindowLength]; 502 float * hannWindow = new float[m_tempogramWindowLength];
495 508
496 //initialise novelty curve processor 509 //initialise novelty curve processor
497 size_t numberOfBlocks = m_spectrogram[0].size(); 510 size_t numberOfBlocks = m_spectrogram[0].size();
498 //cerr << numberOfBlocks << endl; 511 //cerr << numberOfBlocks << endl;
499 NoveltyCurveProcessor nc(m_inputSampleRate, m_inputBlockSize, numberOfBlocks, m_noveltyCurveCompressionConstant); 512 NoveltyCurveProcessor nc(m_inputSampleRate, m_inputBlockSize, numberOfBlocks, m_noveltyCurveCompressionConstant);
500 vector<float> noveltyCurve = nc.spectrogramToNoveltyCurve(m_spectrogram); //calculate novelty curve from magnitude data 513 vector<float> noveltyCurve = nc.spectrogramToNoveltyCurve(m_spectrogram); //calculate novelty curvefrom magnitude data
501 //if(noveltyCurve.size() > 50) for (int i = 0; i < 50; i++) cerr << noveltyCurve[i] << endl; 514 //if(noveltyCurve.size() > 50) for (int i = 0; i < 50; i++) cerr << noveltyCurve[i] << endl;
502 515
503 //push novelty curve data to featureset 1 and set timestamps 516 //push novelty curve data to featureset 1 and set timestamps
504 for (int i = 0; i < (int)numberOfBlocks; i++){ 517 for (int i = 0; i < (int)numberOfBlocks; i++){
505 Feature noveltyCurveFeature; 518 Feature noveltyCurveFeature;
506 noveltyCurveFeature.values.push_back(noveltyCurve[i]); 519 noveltyCurveFeature.values.push_back(noveltyCurve[i]);
507 noveltyCurveFeature.hasTimestamp = false; 520 noveltyCurveFeature.hasTimestamp = false;
508 featureSet[1].push_back(noveltyCurveFeature); 521 featureSet[2].push_back(noveltyCurveFeature);
522 assert(!isnan(noveltyCurveFeature.values.back()));
509 } 523 }
510 524
511 //window function for spectrogram 525 //window function for spectrogram
512 WindowFunction::hanning(hannWindow, m_tempogramWindowLength); 526 WindowFunction::hanning(hannWindow, m_tempogramWindowLength);
513 527
525 Feature tempogramFeature; 539 Feature tempogramFeature;
526 540
527 assert(tempogram[block].size() == (m_tempogramFftLength/2 + 1)); 541 assert(tempogram[block].size() == (m_tempogramFftLength/2 + 1));
528 for(int k = m_tempogramMinBin; k < (int)m_tempogramMaxBin; k++){ 542 for(int k = m_tempogramMinBin; k < (int)m_tempogramMaxBin; k++){
529 tempogramFeature.values.push_back(tempogram[block][k]); 543 tempogramFeature.values.push_back(tempogram[block][k]);
544 assert(!isnan(tempogramFeature.values.back()));
530 } 545 }
531 tempogramFeature.hasTimestamp = false; 546 tempogramFeature.hasTimestamp = false;
532 featureSet[0].push_back(tempogramFeature); 547 featureSet[1].push_back(tempogramFeature);
533 } 548 }
534 549
535 //Calculate cyclic tempogram 550 //Calculate cyclic tempogram
536 vector<unsigned int> logBins = calculateTempogramNearestNeighbourLogBins(); 551 vector<unsigned int> logBins = calculateTempogramNearestNeighbourLogBins();
537 552
540 for (int block = 0; block < tempogramLength; block++){ 555 for (int block = 0; block < tempogramLength; block++){
541 Feature cyclicTempogramFeature; 556 Feature cyclicTempogramFeature;
542 557
543 for (int i = 0; i < (int)m_cyclicTempogramOctaveDivider; i++){ 558 for (int i = 0; i < (int)m_cyclicTempogramOctaveDivider; i++){
544 float sum = 0; 559 float sum = 0;
560
561 //mcerr << floor(binToBPM(logBins[i]) + 0.5) << " " << floor(binToBPM(logBins[i + m_cyclicTempogramOctaveDivider]) + 0.5) << endl;
562
545 for (int j = 0; j < (int)m_cyclicTempogramNumberOfOctaves; j++){ 563 for (int j = 0; j < (int)m_cyclicTempogramNumberOfOctaves; j++){
546 sum += tempogram[block][logBins[i+j*m_cyclicTempogramOctaveDivider]]; 564 sum += tempogram[block][logBins[i+j*m_cyclicTempogramOctaveDivider]];
547 } 565 }
548 cyclicTempogramFeature.values.push_back(sum/m_cyclicTempogramNumberOfOctaves); 566 cyclicTempogramFeature.values.push_back(sum/m_cyclicTempogramNumberOfOctaves);
567 assert(!isnan(cyclicTempogramFeature.values.back()));
549 } 568 }
550 569
551 cyclicTempogramFeature.hasTimestamp = false; 570 cyclicTempogramFeature.hasTimestamp = false;
552 featureSet[2].push_back(cyclicTempogramFeature); 571 featureSet[0].push_back(cyclicTempogramFeature);
553 } 572 }
554 573
555 return featureSet; 574 return featureSet;
556 } 575 }