comparison src/BTrack.cpp @ 100:6aea5918992d

More code style updates
author Adam Stark <adamstark.uk@gmail.com>
date Sun, 13 Aug 2017 11:00:31 +0100
parents 3b24b01fbe15
children 1fcc06afd9cb
comparison
equal deleted inserted replaced
99:b91eb3b6de86 100:6aea5918992d
82 long frameNum = (long) frameNumber; 82 long frameNum = (long) frameNumber;
83 83
84 return getBeatTimeInSeconds (frameNum, hopSize, fs); 84 return getBeatTimeInSeconds (frameNum, hopSize, fs);
85 } 85 }
86 86
87
88
89 //======================================================================= 87 //=======================================================================
90 void BTrack::initialise (int hopSize_, int frameSize_) 88 void BTrack::initialise (int hopSize_, int frameSize_)
91 { 89 {
92 // set vector sizes 90 // set vector sizes
93 resampledOnsetDF.resize (512); 91 resampledOnsetDF.resize (512);
106 // initialise parameters 104 // initialise parameters
107 tightness = 5; 105 tightness = 5;
108 alpha = 0.9; 106 alpha = 0.9;
109 tempo = 120; 107 tempo = 120;
110 estimatedTempo = 120.0; 108 estimatedTempo = 120.0;
111 tempoToLagFactor = 60.*44100./512.; 109 tempoToLagFactor = 60. * 44100. / 512.;
112 110
113 m0 = 10; 111 m0 = 10;
114 beatCounter = -1; 112 beatCounter = -1;
115 113
116 beatDueInFrame = false; 114 beatDueInFrame = false;
118 116
119 // create rayleigh weighting vector 117 // create rayleigh weighting vector
120 for (int n = 0; n < 128; n++) 118 for (int n = 0; n < 128; n++)
121 weightingVector[n] = ((double) n / pow (rayleighParameter, 2)) * exp((-1 * pow((double) - n, 2)) / (2 * pow (rayleighParameter, 2))); 119 weightingVector[n] = ((double) n / pow (rayleighParameter, 2)) * exp((-1 * pow((double) - n, 2)) / (2 * pow (rayleighParameter, 2)));
122 120
123 // initialise prev_delta 121 // initialise prevDelta
124 std::fill (prevDelta.begin(), prevDelta.end(), 1); 122 std::fill (prevDelta.begin(), prevDelta.end(), 1);
125 123
126 double t_mu = 41/2; 124 double t_mu = 41/2;
127 double m_sig; 125 double m_sig;
128 double x; 126 double x;
144 // initialise latest cumulative score value 142 // initialise latest cumulative score value
145 // in case it is requested before any processing takes place 143 // in case it is requested before any processing takes place
146 latestCumulativeScoreValue = 0; 144 latestCumulativeScoreValue = 0;
147 145
148 // initialise algorithm given the hopsize 146 // initialise algorithm given the hopsize
149 setHopSize(hopSize_); 147 setHopSize (hopSize_);
150 148
151 149
152 // Set up FFT for calculating the auto-correlation function 150 // Set up FFT for calculating the auto-correlation function
153 FFTLengthForACFCalculation = 1024; 151 FFTLengthForACFCalculation = 1024;
154 152
336 //======================================================================= 334 //=======================================================================
337 void BTrack::fixTempo (double tempo) 335 void BTrack::fixTempo (double tempo)
338 { 336 {
339 // firstly make sure tempo is between 80 and 160 bpm.. 337 // firstly make sure tempo is between 80 and 160 bpm..
340 while (tempo > 160) 338 while (tempo > 160)
341 { 339 tempo = tempo / 2;
342 tempo = tempo/2;
343 }
344 340
345 while (tempo < 80) 341 while (tempo < 80)
346 { 342 tempo = tempo * 2;
347 tempo = tempo * 2;
348 }
349 343
350 // convert tempo from bpm value to integer index of tempo probability 344 // convert tempo from bpm value to integer index of tempo probability
351 int tempo_index = (int) round((tempo - 80)/2); 345 int tempoIndex = (int) round((tempo - 80) / 2);
352 346
353 // now set previous fixed previous tempo observation values to zero 347 // now set previous fixed previous tempo observation values to zero
354 for (int i=0;i < 41;i++) 348 for (int i=0;i < 41;i++)
355 { 349 {
356 prevDeltaFixed[i] = 0; 350 prevDeltaFixed[i] = 0;
357 } 351 }
358 352
359 // set desired tempo index to 1 353 // set desired tempo index to 1
360 prevDeltaFixed[tempo_index] = 1; 354 prevDeltaFixed[tempoIndex] = 1;
361 355
362 // set the tempo fix flag 356 // set the tempo fix flag
363 tempoFixed = true; 357 tempoFixed = true;
364 } 358 }
365 359
398 392
399 //======================================================================= 393 //=======================================================================
400 void BTrack::calculateTempo() 394 void BTrack::calculateTempo()
401 { 395 {
402 // adaptive threshold on input 396 // adaptive threshold on input
403 adaptiveThreshold (resampledOnsetDF, 512); 397 adaptiveThreshold (resampledOnsetDF);
404 398
405 // calculate auto-correlation function of detection function 399 // calculate auto-correlation function of detection function
406 calculateBalancedACF (&resampledOnsetDF[0]); 400 calculateBalancedACF (resampledOnsetDF);
407 401
408 // calculate output of comb filterbank 402 // calculate output of comb filterbank
409 calculateOutputOfCombFilterBank(); 403 calculateOutputOfCombFilterBank();
410 404
411 // adaptive threshold on rcf 405 // adaptive threshold on rcf
412 adaptiveThreshold (combFilterBankOutput, 128); 406 adaptiveThreshold (combFilterBankOutput);
413 407
414
415 int t_index;
416 int t_index2;
417 // calculate tempo observation vector from beat period observation vector 408 // calculate tempo observation vector from beat period observation vector
418 for (int i = 0;i < 41;i++) 409 for (int i = 0; i < 41; i++)
419 { 410 {
420 t_index = (int) round (tempoToLagFactor / ((double) ((2*i)+80))); 411 int tempoIndex1 = (int) round (tempoToLagFactor / ((double) ((2*i)+80)));
421 t_index2 = (int) round (tempoToLagFactor / ((double) ((4*i)+160))); 412 int tempoIndex2 = (int) round (tempoToLagFactor / ((double) ((4*i)+160)));
422 413 tempoObservationVector[i] = combFilterBankOutput[tempoIndex1 - 1] + combFilterBankOutput[tempoIndex2 - 1];
423 414 }
424 tempoObservationVector[i] = combFilterBankOutput[t_index-1] + combFilterBankOutput[t_index2-1];
425 }
426
427
428 double maxval;
429 double maxind;
430 double curval;
431 415
432 // if tempo is fixed then always use a fixed set of tempi as the previous observation probability function 416 // if tempo is fixed then always use a fixed set of tempi as the previous observation probability function
433 if (tempoFixed) 417 if (tempoFixed)
434 { 418 {
435 for (int k = 0;k < 41;k++) 419 for (int k = 0; k < 41; k++)
436 { 420 prevDelta[k] = prevDeltaFixed[k];
437 prevDelta[k] = prevDeltaFixed[k]; 421 }
438 } 422
439 } 423 for (int j = 0; j < 41; j++)
440 424 {
441 for (int j=0;j < 41;j++) 425 double maxValue = -1;
442 { 426
443 maxval = -1; 427 for (int i = 0; i < 41; i++)
444 for (int i = 0;i < 41;i++) 428 {
445 { 429 double currentValue = prevDelta[i] * tempoTransitionMatrix[i][j];
446 curval = prevDelta[i] * tempoTransitionMatrix[i][j];
447 430
448 if (curval > maxval) 431 if (currentValue > maxValue)
449 { 432 maxValue = currentValue;
450 maxval = curval; 433 }
451 } 434
452 } 435 delta[j] = maxValue * tempoObservationVector[j];
453 436 }
454 delta[j] = maxval * tempoObservationVector[j]; 437
455 } 438 normaliseVector (delta);
456 439
457 440 double maxIndex = -1;
458 normaliseArray (delta); 441 double maxValue = -1;
459 442
460 maxind = -1; 443 for (int j = 0; j < 41; j++)
461 maxval = -1; 444 {
462 445 if (delta[j] > maxValue)
463 for (int j=0;j < 41;j++) 446 {
464 { 447 maxValue = delta[j];
465 if (delta[j] > maxval) 448 maxIndex = j;
466 {
467 maxval = delta[j];
468 maxind = j;
469 } 449 }
470 450
471 prevDelta[j] = delta[j]; 451 prevDelta[j] = delta[j];
472 } 452 }
473 453
474 beatPeriod = round ((60.0*44100.0)/(((2*maxind)+80)*((double) hopSize))); 454 beatPeriod = round ((60.0 * 44100.0) / (((2 * maxIndex) + 80) * ((double) hopSize)));
475 455
476 if (beatPeriod > 0) 456 if (beatPeriod > 0)
477 { 457 estimatedTempo = 60.0/((((double) hopSize) / 44100.0) * beatPeriod);
478 estimatedTempo = 60.0/((((double) hopSize) / 44100.0) * beatPeriod); 458 }
479 } 459
480 } 460 //=======================================================================
481 461 void BTrack::adaptiveThreshold (std::vector<double>& x)
482 //======================================================================= 462 {
483 void BTrack::adaptiveThreshold (std::vector<double>& x, int N) 463 int N = static_cast<int> (x.size());
484 { 464 double threshold[N];
485 int i = 0;
486 int k,t = 0;
487 double x_thresh[N];
488 465
489 int p_post = 7; 466 int p_post = 7;
490 int p_pre = 8; 467 int p_pre = 8;
491 468
492 t = std::min(N,p_post); // what is smaller, p_post of df size. This is to avoid accessing outside of arrays 469 int t = std::min (N, p_post); // what is smaller, p_post or df size. This is to avoid accessing outside of arrays
493 470
494 // find threshold for first 't' samples, where a full average cannot be computed yet 471 // find threshold for first 't' samples, where a full average cannot be computed yet
495 for (i = 0; i <= t; i++) 472 for (int i = 0; i <= t; i++)
496 { 473 {
497 k = std::min ((i + p_pre), N); 474 int k = std::min ((i + p_pre), N);
498 x_thresh[i] = calculateMeanOfArray (x, 1, k); 475 threshold[i] = calculateMeanOfVector (x, 1, k);
499 } 476 }
477
500 // find threshold for bulk of samples across a moving average from [i-p_pre,i+p_post] 478 // find threshold for bulk of samples across a moving average from [i-p_pre,i+p_post]
501 for (i = t + 1; i < N - p_post; i++) 479 for (int i = t + 1; i < N - p_post; i++)
502 { 480 {
503 x_thresh[i] = calculateMeanOfArray (x, i - p_pre, i + p_post); 481 threshold[i] = calculateMeanOfVector (x, i - p_pre, i + p_post);
504 } 482 }
483
505 // for last few samples calculate threshold, again, not enough samples to do as above 484 // for last few samples calculate threshold, again, not enough samples to do as above
506 for (i = N - p_post; i < N; i++) 485 for (int i = N - p_post; i < N; i++)
507 { 486 {
508 k = std::max ((i - p_post), 1); 487 int k = std::max ((i - p_post), 1);
509 x_thresh[i] = calculateMeanOfArray (x, k, N); 488 threshold[i] = calculateMeanOfVector (x, k, N);
510 } 489 }
511 490
512 // subtract the threshold from the detection function and check that it is not less than 0 491 // subtract the threshold from the detection function and check that it is not less than 0
513 for (i = 0; i < N; i++) 492 for (int i = 0; i < N; i++)
514 { 493 {
515 x[i] = x[i] - x_thresh[i]; 494 x[i] = x[i] - threshold[i];
495
516 if (x[i] < 0) 496 if (x[i] < 0)
517 { 497 x[i] = 0;
518 x[i] = 0;
519 }
520 } 498 }
521 } 499 }
522 500
523 //======================================================================= 501 //=======================================================================
524 void BTrack::calculateOutputOfCombFilterBank() 502 void BTrack::calculateOutputOfCombFilterBank()
525 { 503 {
526 int numelem; 504 std::fill (combFilterBankOutput.begin(), combFilterBankOutput.end(), 0.0);
527 505 int numCombElements = 4;
528 for (int i = 0;i < 128;i++)
529 {
530 combFilterBankOutput[i] = 0;
531 }
532
533 numelem = 4;
534 506
535 for (int i = 2; i <= 127; i++) // max beat period 507 for (int i = 2; i <= 127; i++) // max beat period
536 { 508 {
537 for (int a = 1; a <= numelem; a++) // number of comb elements 509 for (int a = 1; a <= numCombElements; a++) // number of comb elements
538 { 510 {
539 for (int b = 1-a; b <= a-1; b++) // general state using normalisation of comb elements 511 for (int b = 1 - a; b <= a - 1; b++) // general state using normalisation of comb elements
540 { 512 {
541 combFilterBankOutput[i-1] = combFilterBankOutput[i-1] + (acf[(a*i+b)-1]*weightingVector[i-1])/(2*a-1); // calculate value for comb filter row 513 combFilterBankOutput[i-1] = combFilterBankOutput[i-1] + (acf[(a*i+b)-1]*weightingVector[i-1])/(2*a-1); // calculate value for comb filter row
542 } 514 }
543 } 515 }
544 } 516 }
545 } 517 }
546 518
547 //======================================================================= 519 //=======================================================================
548 void BTrack::calculateBalancedACF (double* onsetDetectionFunction) 520 void BTrack::calculateBalancedACF (std::vector<double>& onsetDetectionFunction)
549 { 521 {
550 int onsetDetectionFunctionLength = 512; 522 int onsetDetectionFunctionLength = 512;
551 523
552 #ifdef USE_FFTW 524 #ifdef USE_FFTW
553 // copy into complex array and zero pad 525 // copy into complex array and zero pad
635 lag = lag - 1.; 607 lag = lag - 1.;
636 } 608 }
637 } 609 }
638 610
639 //======================================================================= 611 //=======================================================================
640 double BTrack::calculateMeanOfArray (std::vector<double>& array, int startIndex, int endIndex) 612 double BTrack::calculateMeanOfVector (std::vector<double>& vector, int startIndex, int endIndex)
641 { 613 {
642 int length = endIndex - startIndex; 614 int length = endIndex - startIndex;
643 double sum = std::accumulate (array.begin() + startIndex, array.begin() + endIndex, 0.0); 615 double sum = std::accumulate (vector.begin() + startIndex, vector.begin() + endIndex, 0.0);
644 616
645 if (length > 0) 617 if (length > 0)
646 return sum / static_cast<double> (length); // average and return 618 return sum / static_cast<double> (length); // average and return
647 else 619 else
648 return 0; 620 return 0;
649 } 621 }
650 622
651 //======================================================================= 623 //=======================================================================
652 void BTrack::normaliseArray (std::vector<double>& array) 624 void BTrack::normaliseVector (std::vector<double>& vector)
653 { 625 {
654 double sum = std::accumulate (array.begin(), array.end(), 0.0); 626 double sum = std::accumulate (vector.begin(), vector.end(), 0.0);
655 627
656 if (sum > 0) 628 if (sum > 0)
657 { 629 {
658 for (int i = 0; i < array.size(); i++) 630 for (int i = 0; i < vector.size(); i++)
659 array[i] = array[i] / sum; 631 vector[i] = vector[i] / sum;
660 } 632 }
661 } 633 }
662 634
663 //======================================================================= 635 //=======================================================================
664 void BTrack::updateCumulativeScore (double odfSample) 636 void BTrack::updateCumulativeScore (double onsetDetectionFunctionSample)
665 { 637 {
666 int start = onsetDFBufferSize - round (2. * beatPeriod); 638 int windowStart = onsetDFBufferSize - round (2. * beatPeriod);
667 int end = onsetDFBufferSize - round (beatPeriod / 2.); 639 int windowEnd = onsetDFBufferSize - round (beatPeriod / 2.);
668 int windowSize = end - start + 1; 640 int windowSize = windowEnd - windowStart + 1;
669 641
670 double w1[windowSize]; 642 double w1[windowSize];
671 double v = -2. * beatPeriod; 643 double v = -2. * beatPeriod;
672 double weightedCumulativeScore; 644 double weightedCumulativeScore;
673 645
680 } 652 }
681 653
682 // calculate new cumulative score value 654 // calculate new cumulative score value
683 double maxValue = 0; 655 double maxValue = 0;
684 int n = 0; 656 int n = 0;
685 for (int i = start; i <= end; i++) 657 for (int i = windowStart; i <= windowEnd; i++)
686 { 658 {
687 weightedCumulativeScore = cumulativeScore[i] * w1[n]; 659 weightedCumulativeScore = cumulativeScore[i] * w1[n];
688 660
689 if (weightedCumulativeScore > maxValue) 661 if (weightedCumulativeScore > maxValue)
690 maxValue = weightedCumulativeScore; 662 maxValue = weightedCumulativeScore;
691 663
692 n++; 664 n++;
693 } 665 }
694 666
695 latestCumulativeScoreValue = ((1 - alpha) * odfSample) + (alpha * maxValue); 667 latestCumulativeScoreValue = ((1 - alpha) * onsetDetectionFunctionSample) + (alpha * maxValue);
696 cumulativeScore.addSampleToEnd (latestCumulativeScoreValue); 668 cumulativeScore.addSampleToEnd (latestCumulativeScoreValue);
697 } 669 }
698 670
699 //======================================================================= 671 //=======================================================================
700 void BTrack::predictBeat() 672 void BTrack::predictBeat()