Mercurial > hg > btrack
comparison src/BTrack.cpp @ 93:4aa362058011
Added Kiss FFT option
author | Adam Stark <adamstark.uk@gmail.com> |
---|---|
date | Sat, 18 Jun 2016 09:24:13 +0100 |
parents | a88d887bd281 |
children | 6a4dd7478954 |
comparison
equal
deleted
inserted
replaced
92:f6708e4c69f1 | 93:4aa362058011 |
---|---|
27 | 27 |
28 //======================================================================= | 28 //======================================================================= |
29 BTrack::BTrack() | 29 BTrack::BTrack() |
30 : odf (512, 1024, ComplexSpectralDifferenceHWR, HanningWindow) | 30 : odf (512, 1024, ComplexSpectralDifferenceHWR, HanningWindow) |
31 { | 31 { |
32 initialise(512, 1024); | 32 initialise (512, 1024); |
33 } | 33 } |
34 | 34 |
35 //======================================================================= | 35 //======================================================================= |
36 BTrack::BTrack (int hopSize_) | 36 BTrack::BTrack (int hopSize_) |
37 : odf(hopSize_, 2*hopSize_, ComplexSpectralDifferenceHWR, HanningWindow) | 37 : odf(hopSize_, 2*hopSize_, ComplexSpectralDifferenceHWR, HanningWindow) |
38 { | 38 { |
39 initialise(hopSize_, 2*hopSize_); | 39 initialise (hopSize_, 2*hopSize_); |
40 } | 40 } |
41 | 41 |
42 //======================================================================= | 42 //======================================================================= |
43 BTrack::BTrack (int hopSize_, int frameSize_) | 43 BTrack::BTrack (int hopSize_, int frameSize_) |
44 : odf (hopSize_, frameSize_, ComplexSpectralDifferenceHWR, HanningWindow) | 44 : odf (hopSize_, frameSize_, ComplexSpectralDifferenceHWR, HanningWindow) |
47 } | 47 } |
48 | 48 |
49 //======================================================================= | 49 //======================================================================= |
50 BTrack::~BTrack() | 50 BTrack::~BTrack() |
51 { | 51 { |
52 #ifdef USE_FFTW | |
52 // destroy fft plan | 53 // destroy fft plan |
53 fftw_destroy_plan (acfForwardFFT); | 54 fftw_destroy_plan (acfForwardFFT); |
54 fftw_destroy_plan (acfBackwardFFT); | 55 fftw_destroy_plan (acfBackwardFFT); |
55 fftw_free (complexIn); | 56 fftw_free (complexIn); |
56 fftw_free (complexOut); | 57 fftw_free (complexOut); |
58 #endif | |
59 | |
60 #ifdef USE_KISS_FFT | |
61 free (cfgForwards); | |
62 free (cfgBackwards); | |
63 delete [] fftIn; | |
64 delete [] fftOut; | |
65 #endif | |
57 } | 66 } |
58 | 67 |
59 //======================================================================= | 68 //======================================================================= |
60 double BTrack::getBeatTimeInSeconds (long frameNumber, int hopSize, int fs) | 69 double BTrack::getBeatTimeInSeconds (long frameNumber, int hopSize, int fs) |
61 { | 70 { |
135 | 144 |
136 | 145 |
137 // Set up FFT for calculating the auto-correlation function | 146 // Set up FFT for calculating the auto-correlation function |
138 FFTLengthForACFCalculation = 1024; | 147 FFTLengthForACFCalculation = 1024; |
139 | 148 |
149 #ifdef USE_FFTW | |
140 complexIn = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * FFTLengthForACFCalculation); // complex array to hold fft data | 150 complexIn = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * FFTLengthForACFCalculation); // complex array to hold fft data |
141 complexOut = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * FFTLengthForACFCalculation); // complex array to hold fft data | 151 complexOut = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * FFTLengthForACFCalculation); // complex array to hold fft data |
142 | 152 |
143 acfForwardFFT = fftw_plan_dft_1d (FFTLengthForACFCalculation, complexIn, complexOut, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation | 153 acfForwardFFT = fftw_plan_dft_1d (FFTLengthForACFCalculation, complexIn, complexOut, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation |
144 acfBackwardFFT = fftw_plan_dft_1d (FFTLengthForACFCalculation, complexOut, complexIn, FFTW_BACKWARD, FFTW_ESTIMATE); // FFT plan initialisation | 154 acfBackwardFFT = fftw_plan_dft_1d (FFTLengthForACFCalculation, complexOut, complexIn, FFTW_BACKWARD, FFTW_ESTIMATE); // FFT plan initialisation |
155 #endif | |
156 | |
157 #ifdef USE_KISS_FFT | |
158 fftIn = new kiss_fft_cpx[FFTLengthForACFCalculation]; | |
159 fftOut = new kiss_fft_cpx[FFTLengthForACFCalculation]; | |
160 cfgForwards = kiss_fft_alloc (FFTLengthForACFCalculation, 0, 0, 0); | |
161 cfgBackwards = kiss_fft_alloc (FFTLengthForACFCalculation, 1, 0, 0); | |
162 #endif | |
145 } | 163 } |
146 | 164 |
147 //======================================================================= | 165 //======================================================================= |
148 void BTrack::setHopSize (int hopSize_) | 166 void BTrack::setHopSize (int hopSize_) |
149 { | 167 { |
475 estimatedTempo = 60.0/((((double) hopSize) / 44100.0) * beatPeriod); | 493 estimatedTempo = 60.0/((((double) hopSize) / 44100.0) * beatPeriod); |
476 } | 494 } |
477 } | 495 } |
478 | 496 |
479 //======================================================================= | 497 //======================================================================= |
480 void BTrack::adaptiveThreshold (double*x, int N) | 498 void BTrack::adaptiveThreshold (double* x, int N) |
481 { | 499 { |
482 int i = 0; | 500 int i = 0; |
483 int k,t = 0; | 501 int k,t = 0; |
484 double x_thresh[N]; | 502 double x_thresh[N]; |
485 | 503 |
544 //======================================================================= | 562 //======================================================================= |
545 void BTrack::calculateBalancedACF (double* onsetDetectionFunction) | 563 void BTrack::calculateBalancedACF (double* onsetDetectionFunction) |
546 { | 564 { |
547 int onsetDetectionFunctionLength = 512; | 565 int onsetDetectionFunctionLength = 512; |
548 | 566 |
567 #ifdef USE_FFTW | |
549 // copy into complex array and zero pad | 568 // copy into complex array and zero pad |
550 for (int i = 0;i < FFTLengthForACFCalculation;i++) | 569 for (int i = 0;i < FFTLengthForACFCalculation;i++) |
551 { | 570 { |
552 if (i < onsetDetectionFunctionLength) | 571 if (i < onsetDetectionFunctionLength) |
553 { | 572 { |
572 } | 591 } |
573 | 592 |
574 // perform the ifft | 593 // perform the ifft |
575 fftw_execute (acfBackwardFFT); | 594 fftw_execute (acfBackwardFFT); |
576 | 595 |
596 #endif | |
597 | |
598 #ifdef USE_KISS_FFT | |
599 // copy into complex array and zero pad | |
600 for (int i = 0;i < FFTLengthForACFCalculation;i++) | |
601 { | |
602 if (i < onsetDetectionFunctionLength) | |
603 { | |
604 fftIn[i].r = onsetDetectionFunction[i]; | |
605 fftIn[i].i = 0.0; | |
606 } | |
607 else | |
608 { | |
609 fftIn[i].r = 0.0; | |
610 fftIn[i].i = 0.0; | |
611 } | |
612 } | |
613 | |
614 // execute kiss fft | |
615 kiss_fft (cfgForwards, fftIn, fftOut); | |
616 | |
617 // multiply by complex conjugate | |
618 for (int i = 0;i < FFTLengthForACFCalculation;i++) | |
619 { | |
620 fftOut[i].r = fftOut[i].r * fftOut[i].r + fftOut[i].i * fftOut[i].i; | |
621 fftOut[i].i = 0.0; | |
622 } | |
623 | |
624 // perform the ifft | |
625 kiss_fft (cfgBackwards, fftOut, fftIn); | |
626 | |
627 #endif | |
577 | 628 |
578 double lag = 512; | 629 double lag = 512; |
579 | 630 |
580 for (int i = 0; i < 512; i++) | 631 for (int i = 0; i < 512; i++) |
581 { | 632 { |
633 #ifdef USE_FFTW | |
582 // calculate absolute value of result | 634 // calculate absolute value of result |
583 double absValue = sqrt (complexIn[i][0]*complexIn[i][0] + complexIn[i][1]*complexIn[i][1]); | 635 double absValue = sqrt (complexIn[i][0]*complexIn[i][0] + complexIn[i][1]*complexIn[i][1]); |
636 #endif | |
584 | 637 |
638 #ifdef USE_KISS_FFT | |
639 // calculate absolute value of result | |
640 double absValue = sqrt (fftIn[i].r * fftIn[i].r + fftIn[i].i * fftIn[i].i); | |
641 #endif | |
585 // divide by inverse lad to deal with scale bias towards small lags | 642 // divide by inverse lad to deal with scale bias towards small lags |
586 acf[i] = absValue / lag; | 643 acf[i] = absValue / lag; |
587 | 644 |
588 // this division by 1024 is technically unnecessary but it ensures the algorithm produces | 645 // this division by 1024 is technically unnecessary but it ensures the algorithm produces |
589 // exactly the same ACF output as the old time domain implementation. The time difference is | 646 // exactly the same ACF output as the old time domain implementation. The time difference is |
617 return 0; | 674 return 0; |
618 } | 675 } |
619 } | 676 } |
620 | 677 |
621 //======================================================================= | 678 //======================================================================= |
622 void BTrack::normaliseArray(double* array, int N) | 679 void BTrack::normaliseArray (double* array, int N) |
623 { | 680 { |
624 double sum = 0; | 681 double sum = 0; |
625 | 682 |
626 for (int i = 0; i < N; i++) | 683 for (int i = 0; i < N; i++) |
627 { | 684 { |
652 | 709 |
653 double w1[winsize]; | 710 double w1[winsize]; |
654 double v = -2*beatPeriod; | 711 double v = -2*beatPeriod; |
655 double wcumscore; | 712 double wcumscore; |
656 | 713 |
657 | |
658 // create window | 714 // create window |
659 for (int i = 0; i < winsize; i++) | 715 for (int i = 0; i < winsize; i++) |
660 { | 716 { |
661 w1[i] = exp((-1*pow (tightness * log (-v / beatPeriod), 2)) / 2); | 717 w1[i] = exp((-1 * pow (tightness * log (-v / beatPeriod), 2)) / 2); |
662 v = v+1; | 718 v = v+1; |
663 } | 719 } |
664 | 720 |
665 // calculate new cumulative score value | 721 // calculate new cumulative score value |
666 max = 0; | 722 max = 0; |
674 max = wcumscore; | 730 max = wcumscore; |
675 } | 731 } |
676 n++; | 732 n++; |
677 } | 733 } |
678 | 734 |
679 | 735 latestCumulativeScoreValue = ((1 - alpha) * odfSample) + (alpha * max); |
680 latestCumulativeScoreValue = ((1-alpha)*odfSample) + (alpha*max); | |
681 | 736 |
682 cumulativeScore.addSampleToEnd (latestCumulativeScoreValue); | 737 cumulativeScore.addSampleToEnd (latestCumulativeScoreValue); |
683 } | 738 } |
684 | 739 |
685 //======================================================================= | 740 //======================================================================= |
686 void BTrack::predictBeat() | 741 void BTrack::predictBeat() |
687 { | 742 { |
688 int windowSize = (int) beatPeriod; | 743 int windowSize = (int) beatPeriod; |
689 double futureCumulativeScore[onsetDFBufferSize + windowSize]; | 744 double futureCumulativeScore[onsetDFBufferSize + windowSize]; |
690 double w2[windowSize]; | 745 double w2[windowSize]; |
746 | |
691 // copy cumscore to first part of fcumscore | 747 // copy cumscore to first part of fcumscore |
692 for (int i = 0;i < onsetDFBufferSize;i++) | 748 for (int i = 0;i < onsetDFBufferSize;i++) |
693 { | 749 { |
694 futureCumulativeScore[i] = cumulativeScore[i]; | 750 futureCumulativeScore[i] = cumulativeScore[i]; |
695 } | 751 } |
712 for (int i = 0;i < pastwinsize;i++) | 768 for (int i = 0;i < pastwinsize;i++) |
713 { | 769 { |
714 w1[i] = exp((-1*pow(tightness*log(-v/beatPeriod),2))/2); | 770 w1[i] = exp((-1*pow(tightness*log(-v/beatPeriod),2))/2); |
715 v = v+1; | 771 v = v+1; |
716 } | 772 } |
717 | |
718 | |
719 | 773 |
720 // calculate future cumulative score | 774 // calculate future cumulative score |
721 double max; | 775 double max; |
722 int n; | 776 int n; |
723 double wcumscore; | 777 double wcumscore; |
740 } | 794 } |
741 | 795 |
742 futureCumulativeScore[i] = max; | 796 futureCumulativeScore[i] = max; |
743 } | 797 } |
744 | 798 |
745 | |
746 // predict beat | 799 // predict beat |
747 max = 0; | 800 max = 0; |
748 n = 0; | 801 n = 0; |
749 | 802 |
750 for (int i = onsetDFBufferSize; i < (onsetDFBufferSize + windowSize); i++) | 803 for (int i = onsetDFBufferSize; i < (onsetDFBufferSize + windowSize); i++) |