Mercurial > hg > qm-dsp
comparison dsp/tempotracking/TempoTrack.cpp @ 47:38bf09927942
* Build fixes for gcc 4.3.2
* _Maybe_, but probably not, fix crash in tempo tracker... let's see how
we get on
author | cannam |
---|---|
date | Mon, 10 Nov 2008 14:01:55 +0000 |
parents | 4f1870dbab2c |
children | 09aba2ccd94a |
comparison
equal
deleted
inserted
replaced
46:4f1870dbab2c | 47:38bf09927942 |
---|---|
14 #include "maths/MathUtilities.h" | 14 #include "maths/MathUtilities.h" |
15 | 15 |
16 #include <iostream> | 16 #include <iostream> |
17 | 17 |
18 #include <cassert> | 18 #include <cassert> |
19 | |
20 //#define DEBUG_TEMPO_TRACK 1 | |
19 | 21 |
20 | 22 |
21 #define RAY43VAL | 23 #define RAY43VAL |
22 | 24 |
23 ////////////////////////////////////////////////////////////////////// | 25 ////////////////////////////////////////////////////////////////////// |
162 else | 164 else |
163 { | 165 { |
164 numelem = tsig; | 166 numelem = tsig; |
165 } | 167 } |
166 | 168 |
169 #ifdef DEBUG_TEMPO_TRACK | |
167 std::cerr << "tempoMM: m_winLength = " << m_winLength << ", m_lagLength = " << m_lagLength << ", numelem = " << numelem << std::endl; | 170 std::cerr << "tempoMM: m_winLength = " << m_winLength << ", m_lagLength = " << m_lagLength << ", numelem = " << numelem << std::endl; |
171 #endif | |
168 | 172 |
169 for(i=1;i<m_lagLength-1;i++) | 173 for(i=1;i<m_lagLength-1;i++) |
170 { | 174 { |
171 //first and last output values are left intentionally as zero | 175 //first and last output values are left intentionally as zero |
172 for (a=1;a<=numelem;a++) | 176 for (a=1;a<=numelem;a++) |
310 double locked = 5168.f / maxIndexRCF; | 314 double locked = 5168.f / maxIndexRCF; |
311 if (locked >= 30 && locked <= 180) { | 315 if (locked >= 30 && locked <= 180) { |
312 m_lockedTempo = locked; | 316 m_lockedTempo = locked; |
313 } | 317 } |
314 | 318 |
319 #ifdef DEBUG_TEMPO_TRACK | |
320 std::cerr << "tempoMM: locked tempo = " << m_lockedTempo << std::endl; | |
321 #endif | |
322 | |
315 if( tsig == 0 ) | 323 if( tsig == 0 ) |
316 tsig = 4; | 324 tsig = 4; |
317 | 325 |
318 | 326 |
327 #ifdef DEBUG_TEMPO_TRACK | |
319 std::cerr << "tempoMM: maxIndexRCF = " << maxIndexRCF << std::endl; | 328 std::cerr << "tempoMM: maxIndexRCF = " << maxIndexRCF << std::endl; |
329 #endif | |
320 | 330 |
321 if( tsig == 4 ) | 331 if( tsig == 4 ) |
322 { | 332 { |
333 #ifdef DEBUG_TEMPO_TRACK | |
334 std::cerr << "tsig == 4" << std::endl; | |
335 #endif | |
336 | |
323 pdPeaks = new double[ 4 ]; | 337 pdPeaks = new double[ 4 ]; |
324 for( i = 0; i < 4; i++ ){ pdPeaks[ i ] = 0.0;} | 338 for( i = 0; i < 4; i++ ){ pdPeaks[ i ] = 0.0;} |
325 | 339 |
326 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1; | 340 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1; |
327 | 341 |
372 | 386 |
373 | 387 |
374 period = MathUtilities::mean( pdPeaks, 4 ); | 388 period = MathUtilities::mean( pdPeaks, 4 ); |
375 } | 389 } |
376 else | 390 else |
377 { | 391 { |
392 #ifdef DEBUG_TEMPO_TRACK | |
393 std::cerr << "tsig != 4" << std::endl; | |
394 #endif | |
395 | |
378 pdPeaks = new double[ 3 ]; | 396 pdPeaks = new double[ 3 ]; |
379 for( i = 0; i < 3; i++ ){ pdPeaks[ i ] = 0.0;} | 397 for( i = 0; i < 3; i++ ){ pdPeaks[ i ] = 0.0;} |
380 | 398 |
381 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1; | 399 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1; |
382 | 400 |
528 void TempoTrack::createPhaseExtractor(double *Filter, unsigned int winLength, double period, unsigned int fsp, unsigned int lastBeat) | 546 void TempoTrack::createPhaseExtractor(double *Filter, unsigned int winLength, double period, unsigned int fsp, unsigned int lastBeat) |
529 { | 547 { |
530 int p = (int)MathUtilities::round( period ); | 548 int p = (int)MathUtilities::round( period ); |
531 int predictedOffset = 0; | 549 int predictedOffset = 0; |
532 | 550 |
551 #ifdef DEBUG_TEMPO_TRACK | |
533 std::cerr << "TempoTrack::createPhaseExtractor: period = " << period << ", p = " << p << std::endl; | 552 std::cerr << "TempoTrack::createPhaseExtractor: period = " << period << ", p = " << p << std::endl; |
534 | 553 #endif |
535 assert(p < 10000); | 554 |
536 | 555 if (p > 10000) { |
537 double* phaseScratch = new double[ p*2 ]; | 556 std::cerr << "TempoTrack::createPhaseExtractor: WARNING! Highly implausible period value " << p << "!" << std::endl; |
557 period = 5168 / 120; | |
558 } | |
559 | |
560 double* phaseScratch = new double[ p*2 + 2 ]; | |
561 for (int i = 0; i < p*2 + 2; ++i) phaseScratch[i] = 0.0; | |
538 | 562 |
539 | 563 |
540 if( lastBeat != 0 ) | 564 if( lastBeat != 0 ) |
541 { | 565 { |
542 lastBeat = (int)MathUtilities::round((double)lastBeat );///(double)winLength); | 566 lastBeat = (int)MathUtilities::round((double)lastBeat );///(double)winLength); |
543 | 567 |
544 predictedOffset = lastBeat + p - fsp; | 568 predictedOffset = lastBeat + p - fsp; |
545 | 569 |
546 if (predictedOffset < 0) | 570 if (predictedOffset < 0) |
547 { | 571 { |
548 lastBeat = 0; | 572 lastBeat = 0; |
549 } | 573 } |
550 } | 574 } |
551 | 575 |
552 if( lastBeat != 0 ) | 576 if( lastBeat != 0 ) |
553 { | 577 { |
554 int mu = p; | 578 int mu = p; |
569 { | 593 { |
570 temp = phaseScratch[ i ]; | 594 temp = phaseScratch[ i ]; |
571 phaseScratch[ i ] = (temp - PhaseMin)/PhaseMax; | 595 phaseScratch[ i ] = (temp - PhaseMin)/PhaseMax; |
572 } | 596 } |
573 | 597 |
598 #ifdef DEBUG_TEMPO_TRACK | |
574 std::cerr << "predictedOffset = " << predictedOffset << std::endl; | 599 std::cerr << "predictedOffset = " << predictedOffset << std::endl; |
600 #endif | |
575 | 601 |
576 unsigned int index = 0; | 602 unsigned int index = 0; |
577 for(int i = p - ( predictedOffset - 1); i < p + ( p - predictedOffset) + 1; i++) | 603 for (int i = p - ( predictedOffset - 1); i < p + ( p - predictedOffset) + 1; i++) |
578 { | 604 { |
579 std::cerr << "assigning to filter index " << index << " (size = " << p*2 << ")" << std::endl; | 605 #ifdef DEBUG_TEMPO_TRACK |
606 std::cerr << "assigning to filter index " << index << " (size = " << p*2 << ")" << " value " << phaseScratch[i] << " from scratch index " << i << std::endl; | |
607 #endif | |
580 Filter[ index++ ] = phaseScratch[ i ]; | 608 Filter[ index++ ] = phaseScratch[ i ]; |
581 } | 609 } |
582 } | 610 } |
583 else | 611 else |
584 { | 612 { |
656 } | 684 } |
657 | 685 |
658 return beat; | 686 return beat; |
659 } | 687 } |
660 | 688 |
661 vector<int> TempoTrack::process(double *DF, unsigned int length) | 689 |
662 { | 690 |
663 m_dataLength = length; | 691 vector<int> TempoTrack::process( vector <double> DF, |
664 | 692 vector <double> *tempoReturn ) |
693 { | |
694 m_dataLength = DF.size(); | |
695 | |
696 m_lockedTempo = 0.0; | |
697 | |
665 double period = 0.0; | 698 double period = 0.0; |
666 int stepFlag = 0; | 699 int stepFlag = 0; |
667 int constFlag = 0; | 700 int constFlag = 0; |
668 int FSP = 0; | 701 int FSP = 0; |
669 int tsig = 0; | 702 int tsig = 0; |
670 int lastBeat = 0; | 703 int lastBeat = 0; |
671 | 704 |
705 vector <double> causalDF; | |
706 | |
707 causalDF = DF; | |
708 | |
709 //Prepare Causal Extension DFData | |
710 unsigned int DFCLength = m_dataLength + m_winLength; | |
711 | |
712 for( unsigned int j = 0; j < m_winLength; j++ ) | |
713 { | |
714 causalDF.push_back( 0 ); | |
715 } | |
716 | |
672 | 717 |
673 double* RW = new double[ m_lagLength ]; | 718 double* RW = new double[ m_lagLength ]; |
674 for( unsigned int clear = 0; clear < m_lagLength; clear++){ RW[ clear ] = 0.0;} | 719 for( unsigned int clear = 0; clear < m_lagLength; clear++){ RW[ clear ] = 0.0;} |
675 | 720 |
676 double* GW = new double[ m_lagLength ]; | 721 double* GW = new double[ m_lagLength ]; |
677 for(unsigned int clear = 0; clear < m_lagLength; clear++){ GW[ clear ] = 0.0;} | 722 for(unsigned int clear = 0; clear < m_lagLength; clear++){ GW[ clear ] = 0.0;} |
678 | 723 |
679 double* PW = new double[ m_lagLength ]; | 724 double* PW = new double[ m_lagLength ]; |
680 for(unsigned int clear = 0; clear < m_lagLength; clear++){ PW[ clear ] = 0.0;} | 725 for(unsigned clear = 0; clear < m_lagLength; clear++){ PW[ clear ] = 0.0;} |
681 | 726 |
682 m_DFFramer.setSource( DF, m_dataLength ); | 727 m_DFFramer.setSource( &causalDF[0], m_dataLength ); |
683 | 728 |
684 unsigned int TTFrames = m_DFFramer.getMaxNoFrames(); | 729 unsigned int TTFrames = m_DFFramer.getMaxNoFrames(); |
730 | |
731 #ifdef DEBUG_TEMPO_TRACK | |
732 std::cerr << "TTFrames = " << TTFrames << std::endl; | |
733 #endif | |
685 | 734 |
686 double* periodP = new double[ TTFrames ]; | 735 double* periodP = new double[ TTFrames ]; |
687 for(unsigned int clear = 0; clear < TTFrames; clear++){ periodP[ clear ] = 0.0;} | 736 for(unsigned clear = 0; clear < TTFrames; clear++){ periodP[ clear ] = 0.0;} |
688 | 737 |
689 double* periodG = new double[ TTFrames ]; | 738 double* periodG = new double[ TTFrames ]; |
690 for(unsigned int clear = 0; clear < TTFrames; clear++){ periodG[ clear ] = 0.0;} | 739 for(unsigned clear = 0; clear < TTFrames; clear++){ periodG[ clear ] = 0.0;} |
691 | 740 |
692 double* alignment = new double[ TTFrames ]; | 741 double* alignment = new double[ TTFrames ]; |
693 for(unsigned int clear = 0; clear < TTFrames; clear++){ alignment[ clear ] = 0.0;} | 742 for(unsigned clear = 0; clear < TTFrames; clear++){ alignment[ clear ] = 0.0;} |
694 | 743 |
695 m_beats.clear(); | 744 m_beats.clear(); |
696 | 745 |
697 createCombFilter( RW, m_lagLength, 0, 0 ); | 746 createCombFilter( RW, m_lagLength, 0, 0 ); |
698 | 747 |
742 | 791 |
743 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); | 792 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); |
744 | 793 |
745 period = periodG[ TTLoopIndex ]; | 794 period = periodG[ TTLoopIndex ]; |
746 | 795 |
747 // am temporarily changing the last input parameter to lastBeat instead of '0' | 796 #ifdef DEBUG_TEMPO_TRACK |
748 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat ); | 797 std::cerr << "TempoTrack::process: constFlag == " << constFlag << ", TTLoopIndex = " << TTLoopIndex << ", period from periodG = " << period << std::endl; |
798 #endif | |
799 | |
800 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); | |
749 | 801 |
750 constFlag = 0; | 802 constFlag = 0; |
751 | 803 |
752 } | 804 } |
753 else | 805 else |
754 { | 806 { |
755 if( GW[ 0 ] != 0 ) | 807 if( GW[ 0 ] != 0 ) |
756 { | 808 { |
757 period = periodG[ TTLoopIndex ]; | 809 period = periodG[ TTLoopIndex ]; |
758 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat ); | 810 |
759 | 811 #ifdef DEBUG_TEMPO_TRACK |
760 } | 812 std::cerr << "TempoTrack::process: GW[0] == " << GW[0] << ", TTLoopIndex = " << TTLoopIndex << ", period from periodG = " << period << std::endl; |
761 else | 813 #endif |
762 { | |
763 period = periodP[ TTLoopIndex ]; | |
764 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); | |
765 } | |
766 } | |
767 | |
768 alignment[ TTLoopIndex ] = phaseMM( m_rawDFFrame, PW, m_winLength, period ); | |
769 | |
770 lastBeat = beatPredict(FSP, alignment[ TTLoopIndex ], period, m_lagLength ); | |
771 | |
772 FSP += (m_lagLength); | |
773 | |
774 TTLoopIndex++; | |
775 } | |
776 | |
777 | |
778 delete [] periodP; | |
779 delete [] periodG; | |
780 delete [] alignment; | |
781 | |
782 delete [] RW; | |
783 delete [] GW; | |
784 delete [] PW; | |
785 | |
786 return m_beats; | |
787 } | |
788 | |
789 | |
790 | |
791 | |
792 | |
793 vector<int> TempoTrack::process( vector <double> DF, | |
794 vector <double> *tempoReturn ) | |
795 { | |
796 m_dataLength = DF.size(); | |
797 | |
798 m_lockedTempo = 0.0; | |
799 | |
800 double period = 0.0; | |
801 int stepFlag = 0; | |
802 int constFlag = 0; | |
803 int FSP = 0; | |
804 int tsig = 0; | |
805 int lastBeat = 0; | |
806 | |
807 vector <double> causalDF; | |
808 | |
809 causalDF = DF; | |
810 | |
811 //Prepare Causal Extension DFData | |
812 unsigned int DFCLength = m_dataLength + m_winLength; | |
813 | |
814 for( unsigned int j = 0; j < m_winLength; j++ ) | |
815 { | |
816 causalDF.push_back( 0 ); | |
817 } | |
818 | |
819 | |
820 double* RW = new double[ m_lagLength ]; | |
821 for( unsigned int clear = 0; clear < m_lagLength; clear++){ RW[ clear ] = 0.0;} | |
822 | |
823 double* GW = new double[ m_lagLength ]; | |
824 for(unsigned int clear = 0; clear < m_lagLength; clear++){ GW[ clear ] = 0.0;} | |
825 | |
826 double* PW = new double[ m_lagLength ]; | |
827 for(unsigned clear = 0; clear < m_lagLength; clear++){ PW[ clear ] = 0.0;} | |
828 | |
829 m_DFFramer.setSource( &causalDF[0], m_dataLength ); | |
830 | |
831 unsigned int TTFrames = m_DFFramer.getMaxNoFrames(); | |
832 | |
833 double* periodP = new double[ TTFrames ]; | |
834 for(unsigned clear = 0; clear < TTFrames; clear++){ periodP[ clear ] = 0.0;} | |
835 | |
836 double* periodG = new double[ TTFrames ]; | |
837 for(unsigned clear = 0; clear < TTFrames; clear++){ periodG[ clear ] = 0.0;} | |
838 | |
839 double* alignment = new double[ TTFrames ]; | |
840 for(unsigned clear = 0; clear < TTFrames; clear++){ alignment[ clear ] = 0.0;} | |
841 | |
842 m_beats.clear(); | |
843 | |
844 createCombFilter( RW, m_lagLength, 0, 0 ); | |
845 | |
846 int TTLoopIndex = 0; | |
847 | |
848 for( unsigned int i = 0; i < TTFrames; i++ ) | |
849 { | |
850 m_DFFramer.getFrame( m_rawDFFrame ); | |
851 | |
852 m_DFConditioning->process( m_rawDFFrame, m_smoothDFFrame ); | |
853 | |
854 m_correlator.doAutoUnBiased( m_smoothDFFrame, m_frameACF, m_winLength ); | |
855 | |
856 periodP[ TTLoopIndex ] = tempoMM( m_frameACF, RW, 0 ); | |
857 | |
858 if( GW[ 0 ] != 0 ) | |
859 { | |
860 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); | |
861 } | |
862 else | |
863 { | |
864 periodG[ TTLoopIndex ] = 0.0; | |
865 } | |
866 | |
867 stepDetect( periodP, periodG, TTLoopIndex, &stepFlag ); | |
868 | |
869 if( stepFlag == 1) | |
870 { | |
871 constDetect( periodP, TTLoopIndex, &constFlag ); | |
872 stepFlag = 0; | |
873 } | |
874 else | |
875 { | |
876 stepFlag -= 1; | |
877 } | |
878 | |
879 if( stepFlag < 0 ) | |
880 { | |
881 stepFlag = 0; | |
882 } | |
883 | |
884 if( constFlag != 0) | |
885 { | |
886 tsig = findMeter( m_frameACF, m_winLength, periodP[ TTLoopIndex ] ); | |
887 | |
888 createCombFilter( GW, m_lagLength, tsig, periodP[ TTLoopIndex ] ); | |
889 | |
890 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); | |
891 | |
892 period = periodG[ TTLoopIndex ]; | |
893 | |
894 std::cerr << "TempoTrack::process(2): constFlag == " << constFlag << ", TTLoopIndex = " << TTLoopIndex << ", period from periodG = " << period << std::endl; | |
895 | |
896 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); | |
897 | |
898 constFlag = 0; | |
899 | |
900 } | |
901 else | |
902 { | |
903 if( GW[ 0 ] != 0 ) | |
904 { | |
905 period = periodG[ TTLoopIndex ]; | |
906 | |
907 std::cerr << "TempoTrack::process(2): GW[0] == " << GW[0] << ", TTLoopIndex = " << TTLoopIndex << ", period from periodG = " << period << std::endl; | |
908 | 814 |
909 if (period > 10000) { | 815 if (period > 10000) { |
910 std::cerr << "WARNING! Highly implausible period value!" << std::endl; | 816 std::cerr << "TempoTrack::process: WARNING! Highly implausible period value " << period << "!" << std::endl; |
911 std::cerr << "periodG contains (of " << TTFrames << " frames): " << std::endl; | 817 std::cerr << "periodG contains (of " << TTFrames << " frames): " << std::endl; |
912 for (int i = 0; i < TTLoopIndex + 3 && i < TTFrames; ++i) { | 818 for (int i = 0; i < TTLoopIndex + 3 && i < TTFrames; ++i) { |
913 std::cerr << i << " -> " << periodG[i] << std::endl; | 819 std::cerr << i << " -> " << periodG[i] << std::endl; |
914 } | 820 } |
915 std::cerr << "periodP contains (of " << TTFrames << " frames): " << std::endl; | 821 std::cerr << "periodP contains (of " << TTFrames << " frames): " << std::endl; |
916 for (int i = 0; i < TTLoopIndex + 3 && i < TTFrames; ++i) { | 822 for (int i = 0; i < TTLoopIndex + 3 && i < TTFrames; ++i) { |
917 std::cerr << i << " -> " << periodP[i] << std::endl; | 823 std::cerr << i << " -> " << periodP[i] << std::endl; |
918 } | 824 } |
825 period = 5168 / 120; | |
919 } | 826 } |
920 | 827 |
921 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat ); | 828 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat ); |
922 | 829 |
923 } | 830 } |
924 else | 831 else |
925 { | 832 { |
926 period = periodP[ TTLoopIndex ]; | 833 period = periodP[ TTLoopIndex ]; |
927 | 834 |
928 std::cerr << "TempoTrack::process(2): GW[0] == " << GW[0] << ", TTLoopIndex = " << TTLoopIndex << ", period from periodP = " << period << std::endl; | 835 #ifdef DEBUG_TEMPO_TRACK |
836 std::cerr << "TempoTrack::process: GW[0] == " << GW[0] << ", TTLoopIndex = " << TTLoopIndex << ", period from periodP = " << period << std::endl; | |
837 #endif | |
929 | 838 |
930 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); | 839 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); |
931 } | 840 } |
932 } | 841 } |
933 | 842 |