Mercurial > hg > btrack
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() |