Mercurial > hg > btrack
comparison src/OnsetDetectionFunction.cpp @ 117:ca2d83d29814 tip master
Merge branch 'release/1.0.5'
author | Adam Stark <adamstark.uk@gmail.com> |
---|---|
date | Fri, 18 Aug 2023 20:07:33 +0200 |
parents | 54c657d621dd |
children |
comparison
equal
deleted
inserted
replaced
96:c58f01834337 | 117:ca2d83d29814 |
---|---|
21 | 21 |
22 #include <math.h> | 22 #include <math.h> |
23 #include "OnsetDetectionFunction.h" | 23 #include "OnsetDetectionFunction.h" |
24 | 24 |
25 //======================================================================= | 25 //======================================================================= |
26 OnsetDetectionFunction::OnsetDetectionFunction (int hopSize_,int frameSize_) | 26 OnsetDetectionFunction::OnsetDetectionFunction (int hopSize_, int frameSize_) |
27 : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow) | 27 : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow) |
28 { | 28 { |
29 // indicate that we have not initialised yet | 29 // indicate that we have not initialised yet |
30 initialised = false; | 30 initialised = false; |
31 | 31 |
35 // initialise with arguments to constructor | 35 // initialise with arguments to constructor |
36 initialise (hopSize_, frameSize_, ComplexSpectralDifferenceHWR, HanningWindow); | 36 initialise (hopSize_, frameSize_, ComplexSpectralDifferenceHWR, HanningWindow); |
37 } | 37 } |
38 | 38 |
39 //======================================================================= | 39 //======================================================================= |
40 OnsetDetectionFunction::OnsetDetectionFunction(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_) | 40 OnsetDetectionFunction::OnsetDetectionFunction (int hopSize_, int frameSize_, int onsetDetectionFunctionType_, int windowType_) |
41 : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow) | 41 : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow) |
42 { | 42 { |
43 // indicate that we have not initialised yet | 43 // indicate that we have not initialised yet |
44 initialised = false; | 44 initialised = false; |
45 | 45 |
67 // pass the new frame and hop size to the main initialisation function | 67 // pass the new frame and hop size to the main initialisation function |
68 initialise (hopSize_, frameSize_, onsetDetectionFunctionType, windowType); | 68 initialise (hopSize_, frameSize_, onsetDetectionFunctionType, windowType); |
69 } | 69 } |
70 | 70 |
71 //======================================================================= | 71 //======================================================================= |
72 void OnsetDetectionFunction::initialise(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_) | 72 void OnsetDetectionFunction::initialise (int hopSize_, int frameSize_, int onsetDetectionFunctionType_, int windowType_) |
73 { | 73 { |
74 hopSize = hopSize_; // set hopsize | 74 hopSize = hopSize_; // set hopsize |
75 frameSize = frameSize_; // set framesize | 75 frameSize = frameSize_; // set framesize |
76 | 76 |
77 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type | 77 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type |
138 #endif | 138 #endif |
139 | 139 |
140 #ifdef USE_KISS_FFT | 140 #ifdef USE_KISS_FFT |
141 complexOut.resize (frameSize); | 141 complexOut.resize (frameSize); |
142 | 142 |
143 for (int i = 0; i < frameSize;i++) | 143 for (int i = 0; i < frameSize; i++) |
144 { | 144 { |
145 complexOut[i].resize(2); | 145 complexOut[i].resize(2); |
146 } | 146 } |
147 | 147 |
148 fftIn = new kiss_fft_cpx[frameSize]; | 148 fftIn = new kiss_fft_cpx[frameSize]; |
179 double OnsetDetectionFunction::calculateOnsetDetectionFunctionSample (double* buffer) | 179 double OnsetDetectionFunction::calculateOnsetDetectionFunctionSample (double* buffer) |
180 { | 180 { |
181 double odfSample; | 181 double odfSample; |
182 | 182 |
183 // shift audio samples back in frame by hop size | 183 // shift audio samples back in frame by hop size |
184 for (int i = 0; i < (frameSize-hopSize);i++) | 184 std::rotate (frame.begin(), frame.begin() + hopSize, frame.end()); |
185 { | |
186 frame[i] = frame[i+hopSize]; | |
187 } | |
188 | 185 |
189 // add new samples to frame from input buffer | 186 // add new samples to frame from input buffer |
190 int j = 0; | 187 int j = 0; |
191 for (int i = (frameSize-hopSize);i < frameSize;i++) | 188 for (int i = (frameSize - hopSize); i < frameSize; i++) |
192 { | 189 { |
193 frame[i] = buffer[j]; | 190 frame[i] = buffer[j]; |
194 j++; | 191 j++; |
195 } | 192 } |
196 | 193 |
267 | 264 |
268 | 265 |
269 //======================================================================= | 266 //======================================================================= |
270 void OnsetDetectionFunction::performFFT() | 267 void OnsetDetectionFunction::performFFT() |
271 { | 268 { |
272 int fsize2 = (frameSize/2); | 269 int fsize2 = (frameSize / 2); |
273 | 270 |
274 #ifdef USE_FFTW | 271 #ifdef USE_FFTW |
275 // window frame and copy to complex array, swapping the first and second half of the signal | 272 // window frame and copy to complex array, swapping the first and second half of the signal |
276 for (int i = 0;i < fsize2;i++) | 273 for (int i = 0; i < fsize2; i++) |
277 { | 274 { |
278 complexIn[i][0] = frame[i + fsize2] * window[i + fsize2]; | 275 complexIn[i][0] = frame[i + fsize2] * window[i + fsize2]; |
279 complexIn[i][1] = 0.0; | 276 complexIn[i][1] = 0.0; |
280 complexIn[i+fsize2][0] = frame[i] * window[i]; | 277 complexIn[i+fsize2][0] = frame[i] * window[i]; |
281 complexIn[i+fsize2][1] = 0.0; | 278 complexIn[i+fsize2][1] = 0.0; |
316 double sum; | 313 double sum; |
317 | 314 |
318 sum = 0; // initialise sum | 315 sum = 0; // initialise sum |
319 | 316 |
320 // sum the squares of the samples | 317 // sum the squares of the samples |
321 for (int i = 0;i < frameSize;i++) | 318 for (int i = 0; i < frameSize; i++) |
322 { | 319 { |
323 sum = sum + (frame[i] * frame[i]); | 320 sum = sum + (frame[i] * frame[i]); |
324 } | 321 } |
325 | 322 |
326 return sum; // return sum | 323 return sum; // return sum |
361 double sum; | 358 double sum; |
362 | 359 |
363 // perform the FFT | 360 // perform the FFT |
364 performFFT(); | 361 performFFT(); |
365 | 362 |
366 // compute first (N/2)+1 mag values | 363 // compute first (N / 2) + 1 mag values |
367 for (int i = 0;i < (frameSize/2)+1;i++) | 364 for (int i = 0; i < (frameSize / 2) + 1; i++) |
368 { | 365 { |
369 magSpec[i] = sqrt (pow (complexOut[i][0], 2) + pow (complexOut[i][1], 2)); | 366 magSpec[i] = sqrt (pow (complexOut[i][0], 2) + pow (complexOut[i][1], 2)); |
370 } | 367 } |
371 // mag spec symmetric above (N/2)+1 so copy previous values | 368 // mag spec symmetric above (N / 2) + 1 so copy previous values |
372 for (int i = (frameSize/2)+1; i < frameSize; i++) | 369 for (int i = (frameSize / 2) + 1; i < frameSize; i++) |
373 { | 370 { |
374 magSpec[i] = magSpec[frameSize-i]; | 371 magSpec[i] = magSpec[frameSize - i]; |
375 } | 372 } |
376 | 373 |
377 sum = 0; // initialise sum to zero | 374 sum = 0; // initialise sum to zero |
378 | 375 |
379 for (int i = 0; i < frameSize; i++) | 376 for (int i = 0; i < frameSize; i++) |
382 diff = magSpec[i] - prevMagSpec[i]; | 379 diff = magSpec[i] - prevMagSpec[i]; |
383 | 380 |
384 // ensure all difference values are positive | 381 // ensure all difference values are positive |
385 if (diff < 0) | 382 if (diff < 0) |
386 { | 383 { |
387 diff = diff*-1; | 384 diff = diff * -1; |
388 } | 385 } |
389 | 386 |
390 // add difference to sum | 387 // add difference to sum |
391 sum = sum + diff; | 388 sum = sum + diff; |
392 | 389 |
404 double sum; | 401 double sum; |
405 | 402 |
406 // perform the FFT | 403 // perform the FFT |
407 performFFT(); | 404 performFFT(); |
408 | 405 |
409 // compute first (N/2)+1 mag values | 406 // compute first (N / 2) + 1 mag values |
410 for (int i = 0;i < (frameSize/2) + 1; i++) | 407 for (int i = 0; i < (frameSize / 2) + 1; i++) |
411 { | 408 { |
412 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); | 409 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
413 } | 410 } |
414 // mag spec symmetric above (N/2)+1 so copy previous values | 411 // mag spec symmetric above (N / 2) + 1 so copy previous values |
415 for (int i = (frameSize/2)+1;i < frameSize;i++) | 412 for (int i = (frameSize / 2) + 1; i < frameSize; i++) |
416 { | 413 { |
417 magSpec[i] = magSpec[frameSize-i]; | 414 magSpec[i] = magSpec[frameSize - i]; |
418 } | 415 } |
419 | 416 |
420 sum = 0; // initialise sum to zero | 417 sum = 0; // initialise sum to zero |
421 | 418 |
422 for (int i = 0;i < frameSize;i++) | 419 for (int i = 0; i < frameSize; i++) |
423 { | 420 { |
424 // calculate difference | 421 // calculate difference |
425 diff = magSpec[i] - prevMagSpec[i]; | 422 diff = magSpec[i] - prevMagSpec[i]; |
426 | 423 |
427 // only add up positive differences | 424 // only add up positive differences |
449 performFFT(); | 446 performFFT(); |
450 | 447 |
451 sum = 0; // initialise sum to zero | 448 sum = 0; // initialise sum to zero |
452 | 449 |
453 // compute phase values from fft output and sum deviations | 450 // compute phase values from fft output and sum deviations |
454 for (int i = 0;i < frameSize;i++) | 451 for (int i = 0; i < frameSize; i++) |
455 { | 452 { |
456 // calculate phase value | 453 // calculate phase value |
457 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); | 454 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); |
458 | 455 |
459 // calculate magnitude value | 456 // calculate magnitude value |
461 | 458 |
462 | 459 |
463 // if bin is not just a low energy bin then examine phase deviation | 460 // if bin is not just a low energy bin then examine phase deviation |
464 if (magSpec[i] > 0.1) | 461 if (magSpec[i] > 0.1) |
465 { | 462 { |
466 dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; // phase deviation | 463 dev = phase[i] - (2 * prevPhase[i]) + prevPhase2[i]; // phase deviation |
467 pdev = princarg (dev); // wrap into [-pi,pi] range | 464 pdev = princarg (dev); // wrap into [-pi,pi] range |
468 | 465 |
469 // make all values positive | 466 // make all values positive |
470 if (pdev < 0) | 467 if (pdev < 0) |
471 { | 468 { |
472 pdev = pdev*-1; | 469 pdev = pdev * -1; |
473 } | 470 } |
474 | 471 |
475 // add to sum | 472 // add to sum |
476 sum = sum + pdev; | 473 sum = sum + pdev; |
477 } | 474 } |
495 performFFT(); | 492 performFFT(); |
496 | 493 |
497 sum = 0; // initialise sum to zero | 494 sum = 0; // initialise sum to zero |
498 | 495 |
499 // compute phase values from fft output and sum deviations | 496 // compute phase values from fft output and sum deviations |
500 for (int i = 0;i < frameSize;i++) | 497 for (int i = 0; i < frameSize; i++) |
501 { | 498 { |
502 // calculate phase value | 499 // calculate phase value |
503 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); | 500 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); |
504 | 501 |
505 // calculate magnitude value | 502 // calculate magnitude value |
535 performFFT(); | 532 performFFT(); |
536 | 533 |
537 sum = 0; // initialise sum to zero | 534 sum = 0; // initialise sum to zero |
538 | 535 |
539 // compute phase values from fft output and sum deviations | 536 // compute phase values from fft output and sum deviations |
540 for (int i = 0;i < frameSize;i++) | 537 for (int i = 0; i < frameSize; i++) |
541 { | 538 { |
542 // calculate phase value | 539 // calculate phase value |
543 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); | 540 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); |
544 | 541 |
545 // calculate magnitude value | 542 // calculate magnitude value |
586 { | 583 { |
587 // calculate magnitude value | 584 // calculate magnitude value |
588 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); | 585 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
589 | 586 |
590 | 587 |
591 sum = sum + (magSpec[i] * ((double) (i+1))); | 588 sum = sum + (magSpec[i] * ((double) (i + 1))); |
592 | 589 |
593 // store values for next calculation | 590 // store values for next calculation |
594 prevMagSpec[i] = magSpec[i]; | 591 prevMagSpec[i] = magSpec[i]; |
595 } | 592 } |
596 | 593 |
607 performFFT(); | 604 performFFT(); |
608 | 605 |
609 sum = 0; // initialise sum to zero | 606 sum = 0; // initialise sum to zero |
610 | 607 |
611 // compute phase values from fft output and sum deviations | 608 // compute phase values from fft output and sum deviations |
612 for (int i = 0;i < frameSize;i++) | 609 for (int i = 0; i < frameSize; i++) |
613 { | 610 { |
614 // calculate magnitude value | 611 // calculate magnitude value |
615 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); | 612 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
616 | 613 |
617 // calculate difference | 614 // calculate difference |
620 if (mag_diff < 0) | 617 if (mag_diff < 0) |
621 { | 618 { |
622 mag_diff = -mag_diff; | 619 mag_diff = -mag_diff; |
623 } | 620 } |
624 | 621 |
625 sum = sum + (mag_diff * ((double) (i+1))); | 622 sum = sum + (mag_diff * ((double) (i + 1))); |
626 | 623 |
627 // store values for next calculation | 624 // store values for next calculation |
628 prevMagSpec[i] = magSpec[i]; | 625 prevMagSpec[i] = magSpec[i]; |
629 } | 626 } |
630 | 627 |
641 performFFT(); | 638 performFFT(); |
642 | 639 |
643 sum = 0; // initialise sum to zero | 640 sum = 0; // initialise sum to zero |
644 | 641 |
645 // compute phase values from fft output and sum deviations | 642 // compute phase values from fft output and sum deviations |
646 for (int i = 0;i < frameSize;i++) | 643 for (int i = 0; i < frameSize; i++) |
647 { | 644 { |
648 // calculate magnitude value | 645 // calculate magnitude value |
649 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); | 646 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
650 | 647 |
651 // calculate difference | 648 // calculate difference |
652 mag_diff = magSpec[i] - prevMagSpec[i]; | 649 mag_diff = magSpec[i] - prevMagSpec[i]; |
653 | 650 |
654 if (mag_diff > 0) | 651 if (mag_diff > 0) |
655 { | 652 { |
656 sum = sum + (mag_diff * ((double) (i+1))); | 653 sum = sum + (mag_diff * ((double) (i + 1))); |
657 } | 654 } |
658 | 655 |
659 // store values for next calculation | 656 // store values for next calculation |
660 prevMagSpec[i] = magSpec[i]; | 657 prevMagSpec[i] = magSpec[i]; |
661 } | 658 } |
671 //======================================================================= | 668 //======================================================================= |
672 void OnsetDetectionFunction::calculateHanningWindow() | 669 void OnsetDetectionFunction::calculateHanningWindow() |
673 { | 670 { |
674 double N; // variable to store framesize minus 1 | 671 double N; // variable to store framesize minus 1 |
675 | 672 |
676 N = (double) (frameSize-1); // framesize minus 1 | 673 N = (double) (frameSize - 1); // framesize minus 1 |
677 | 674 |
678 // Hanning window calculation | 675 // Hanning window calculation |
679 for (int n = 0; n < frameSize; n++) | 676 for (int n = 0; n < frameSize; n++) |
680 { | 677 { |
681 window[n] = 0.5 * (1 - cos (2 * pi * (n / N))); | 678 window[n] = 0.5 * (1 - cos (2 * pi * (n / N))); |
686 void OnsetDetectionFunction::calclulateHammingWindow() | 683 void OnsetDetectionFunction::calclulateHammingWindow() |
687 { | 684 { |
688 double N; // variable to store framesize minus 1 | 685 double N; // variable to store framesize minus 1 |
689 double n_val; // double version of index 'n' | 686 double n_val; // double version of index 'n' |
690 | 687 |
691 N = (double) (frameSize-1); // framesize minus 1 | 688 N = (double) (frameSize - 1); // framesize minus 1 |
692 n_val = 0; | 689 n_val = 0; |
693 | 690 |
694 // Hamming window calculation | 691 // Hamming window calculation |
695 for (int n = 0;n < frameSize;n++) | 692 for (int n = 0; n < frameSize; n++) |
696 { | 693 { |
697 window[n] = 0.54 - (0.46 * cos (2 * pi * (n_val/N))); | 694 window[n] = 0.54 - (0.46 * cos (2 * pi * (n_val / N))); |
698 n_val = n_val+1; | 695 n_val = n_val+1; |
699 } | 696 } |
700 } | 697 } |
701 | 698 |
702 //======================================================================= | 699 //======================================================================= |
703 void OnsetDetectionFunction::calculateBlackmanWindow() | 700 void OnsetDetectionFunction::calculateBlackmanWindow() |
704 { | 701 { |
705 double N; // variable to store framesize minus 1 | 702 double N; // variable to store framesize minus 1 |
706 double n_val; // double version of index 'n' | 703 double n_val; // double version of index 'n' |
707 | 704 |
708 N = (double) (frameSize-1); // framesize minus 1 | 705 N = (double) (frameSize - 1); // framesize minus 1 |
709 n_val = 0; | 706 n_val = 0; |
710 | 707 |
711 // Blackman window calculation | 708 // Blackman window calculation |
712 for (int n = 0;n < frameSize;n++) | 709 for (int n = 0; n < frameSize; n++) |
713 { | 710 { |
714 window[n] = 0.42 - (0.5*cos(2*pi*(n_val/N))) + (0.08*cos(4*pi*(n_val/N))); | 711 window[n] = 0.42 - (0.5 * cos (2 * pi * (n_val / N))) + (0.08 * cos (4 * pi * (n_val / N))); |
715 n_val = n_val+1; | 712 n_val = n_val + 1; |
716 } | 713 } |
717 } | 714 } |
718 | 715 |
719 //======================================================================= | 716 //======================================================================= |
720 void OnsetDetectionFunction::calculateTukeyWindow() | 717 void OnsetDetectionFunction::calculateTukeyWindow() |
723 double n_val; // double version of index 'n' | 720 double n_val; // double version of index 'n' |
724 double alpha; // alpha [default value = 0.5]; | 721 double alpha; // alpha [default value = 0.5]; |
725 | 722 |
726 alpha = 0.5; | 723 alpha = 0.5; |
727 | 724 |
728 N = (double) (frameSize-1); // framesize minus 1 | 725 N = (double) (frameSize - 1); // framesize minus 1 |
729 | 726 |
730 // Tukey window calculation | 727 // Tukey window calculation |
731 | 728 |
732 n_val = (double) (-1*((frameSize/2)))+1; | 729 n_val = (double) (-1 * ((frameSize / 2))) + 1; |
733 | 730 |
734 for (int n = 0;n < frameSize;n++) // left taper | 731 for (int n = 0; n < frameSize; n++) // left taper |
735 { | 732 { |
736 if ((n_val >= 0) && (n_val <= (alpha*(N/2)))) | 733 if ((n_val >= 0) && (n_val <= (alpha * (N / 2)))) |
737 { | 734 { |
738 window[n] = 1.0; | 735 window[n] = 1.0; |
739 } | 736 } |
740 else if ((n_val <= 0) && (n_val >= (-1*alpha*(N/2)))) | 737 else if ((n_val <= 0) && (n_val >= (-1 * alpha * (N / 2)))) |
741 { | 738 { |
742 window[n] = 1.0; | 739 window[n] = 1.0; |
743 } | 740 } |
744 else | 741 else |
745 { | 742 { |
746 window[n] = 0.5*(1+cos(pi*(((2*n_val)/(alpha*N))-1))); | 743 window[n] = 0.5 * (1 + cos (pi * (((2 * n_val) / (alpha * N)) - 1))); |
747 } | 744 } |
748 | 745 |
749 n_val = n_val+1; | 746 n_val = n_val + 1; |
750 } | 747 } |
751 | 748 |
752 } | 749 } |
753 | 750 |
754 //======================================================================= | 751 //======================================================================= |
755 void OnsetDetectionFunction::calculateRectangularWindow() | 752 void OnsetDetectionFunction::calculateRectangularWindow() |
756 { | 753 { |
757 // Rectangular window calculation | 754 // Rectangular window calculation |
758 for (int n = 0;n < frameSize;n++) | 755 for (int n = 0; n < frameSize; n++) |
759 { | 756 { |
760 window[n] = 1.0; | 757 window[n] = 1.0; |
761 } | 758 } |
762 } | 759 } |
763 | 760 |