qm-dsp
1.8
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 QM DSP Library 00005 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2005-2006 Christian Landone.and Matthew Davies. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "TempoTrack.h" 00017 00018 #include "maths/MathAliases.h" 00019 #include "maths/MathUtilities.h" 00020 00021 #include <iostream> 00022 00023 #include <cassert> 00024 00025 //#define DEBUG_TEMPO_TRACK 1 00026 00027 00028 #define RAY43VAL 00029 00031 // Construction/Destruction 00033 00034 TempoTrack::TempoTrack( TTParams Params ) 00035 { 00036 m_tempoScratch = NULL; 00037 m_rawDFFrame = NULL; 00038 m_smoothDFFrame = NULL; 00039 m_frameACF = NULL; 00040 m_smoothRCF = NULL; 00041 00042 m_dataLength = 0; 00043 m_winLength = 0; 00044 m_lagLength = 0; 00045 00046 m_rayparam = 0; 00047 m_sigma = 0; 00048 m_DFWVNnorm = 0; 00049 00050 initialise( Params ); 00051 } 00052 00053 TempoTrack::~TempoTrack() 00054 { 00055 deInitialise(); 00056 } 00057 00058 void TempoTrack::initialise( TTParams Params ) 00059 { 00060 m_winLength = Params.winLength; 00061 m_lagLength = Params.lagLength; 00062 00063 m_rayparam = 43.0; 00064 m_sigma = sqrt(3.9017); 00065 m_DFWVNnorm = exp( ( log( 2.0 ) / m_rayparam ) * ( m_winLength + 2 ) ); 00066 00067 m_rawDFFrame = new double[ m_winLength ]; 00068 m_smoothDFFrame = new double[ m_winLength ]; 00069 m_frameACF = new double[ m_winLength ]; 00070 m_tempoScratch = new double[ m_lagLength ]; 00071 m_smoothRCF = new double[ m_lagLength ]; 00072 00073 00074 unsigned int winPre = Params.WinT.pre; 00075 unsigned int winPost = Params.WinT.post; 00076 00077 m_DFFramer.configure( m_winLength, m_lagLength ); 00078 00079 m_DFPParams.length = m_winLength; 00080 m_DFPParams.AlphaNormParam = Params.alpha; 00081 m_DFPParams.LPOrd = Params.LPOrd; 00082 m_DFPParams.LPACoeffs = Params.LPACoeffs; 00083 m_DFPParams.LPBCoeffs = Params.LPBCoeffs; 00084 m_DFPParams.winPre = Params.WinT.pre; 00085 m_DFPParams.winPost = Params.WinT.post; 00086 m_DFPParams.isMedianPositive = true; 00087 00088 m_DFConditioning = new DFProcess( m_DFPParams ); 00089 00090 00091 // these are parameters for smoothing m_tempoScratch 00092 m_RCFPParams.length = m_lagLength; 00093 m_RCFPParams.AlphaNormParam = Params.alpha; 00094 m_RCFPParams.LPOrd = Params.LPOrd; 00095 m_RCFPParams.LPACoeffs = Params.LPACoeffs; 00096 m_RCFPParams.LPBCoeffs = Params.LPBCoeffs; 00097 m_RCFPParams.winPre = Params.WinT.pre; 00098 m_RCFPParams.winPost = Params.WinT.post; 00099 m_RCFPParams.isMedianPositive = true; 00100 00101 m_RCFConditioning = new DFProcess( m_RCFPParams ); 00102 00103 } 00104 00105 void TempoTrack::deInitialise() 00106 { 00107 delete [] m_rawDFFrame; 00108 00109 delete [] m_smoothDFFrame; 00110 00111 delete [] m_smoothRCF; 00112 00113 delete [] m_frameACF; 00114 00115 delete [] m_tempoScratch; 00116 00117 delete m_DFConditioning; 00118 00119 delete m_RCFConditioning; 00120 00121 } 00122 00123 void TempoTrack::createCombFilter(double* Filter, unsigned int winLength, unsigned int TSig, double beatLag) 00124 { 00125 unsigned int i; 00126 00127 if( beatLag == 0 ) 00128 { 00129 for( i = 0; i < winLength; i++ ) 00130 { 00131 Filter[ i ] = ( ( i + 1 ) / pow( m_rayparam, 2.0) ) * exp( ( -pow(( i + 1 ),2.0 ) / ( 2.0 * pow( m_rayparam, 2.0)))); 00132 } 00133 } 00134 else 00135 { 00136 m_sigma = beatLag/4; 00137 for( i = 0; i < winLength; i++ ) 00138 { 00139 double dlag = (double)(i+1) - beatLag; 00140 Filter[ i ] = exp(-0.5 * pow(( dlag / m_sigma), 2.0) ) / (sqrt( 2 * PI) * m_sigma); 00141 } 00142 } 00143 } 00144 00145 double TempoTrack::tempoMM(double* ACF, double* weight, int tsig) 00146 { 00147 00148 double period = 0; 00149 double maxValRCF = 0.0; 00150 unsigned int maxIndexRCF = 0; 00151 00152 double* pdPeaks; 00153 00154 unsigned int maxIndexTemp; 00155 double maxValTemp; 00156 unsigned int count; 00157 00158 unsigned int numelem,i,j; 00159 int a, b; 00160 00161 for( i = 0; i < m_lagLength; i++ ) 00162 m_tempoScratch[ i ] = 0.0; 00163 00164 if( tsig == 0 ) 00165 { 00166 //if time sig is unknown, use metrically unbiased version of Filterbank 00167 numelem = 4; 00168 } 00169 else 00170 { 00171 numelem = tsig; 00172 } 00173 00174 #ifdef DEBUG_TEMPO_TRACK 00175 std::cerr << "tempoMM: m_winLength = " << m_winLength << ", m_lagLength = " << m_lagLength << ", numelem = " << numelem << std::endl; 00176 #endif 00177 00178 for(i=1;i<m_lagLength-1;i++) 00179 { 00180 //first and last output values are left intentionally as zero 00181 for (a=1;a<=numelem;a++) 00182 { 00183 for(b=(1-a);b<a;b++) 00184 { 00185 if( tsig == 0 ) 00186 { 00187 m_tempoScratch[i] += ACF[a*(i+1)+b-1] * (1.0 / (2.0 * (double)a-1)) * weight[i]; 00188 } 00189 else 00190 { 00191 m_tempoScratch[i] += ACF[a*(i+1)+b-1] * 1 * weight[i]; 00192 } 00193 } 00194 } 00195 } 00196 00197 00199 // MODIFIED BEAT PERIOD EXTRACTION ////////////// 00201 00202 // find smoothed version of RCF ( as applied to Detection Function) 00203 m_RCFConditioning->process( m_tempoScratch, m_smoothRCF); 00204 00205 if (tsig != 0) // i.e. in context dependent state 00206 { 00207 // NOW FIND MAX INDEX OF ACFOUT 00208 for( i = 0; i < m_lagLength; i++) 00209 { 00210 if( m_tempoScratch[ i ] > maxValRCF) 00211 { 00212 maxValRCF = m_tempoScratch[ i ]; 00213 maxIndexRCF = i; 00214 } 00215 } 00216 } 00217 else // using rayleigh weighting 00218 { 00219 vector <vector<double> > rcfMat; 00220 00221 double sumRcf = 0.; 00222 00223 double maxVal = 0.; 00224 // now find the two values which minimise rcfMat 00225 double minVal = 0.; 00226 int p_i = 1; // periodicity for row i; 00227 int p_j = 1; //periodicity for column j; 00228 00229 00230 for ( i=0; i<m_lagLength; i++) 00231 { 00232 m_tempoScratch[i] =m_smoothRCF[i]; 00233 } 00234 00235 // normalise m_tempoScratch so that it sums to zero. 00236 for ( i=0; i<m_lagLength; i++) 00237 { 00238 sumRcf += m_tempoScratch[i]; 00239 } 00240 00241 for( i=0; i<m_lagLength; i++) 00242 { 00243 m_tempoScratch[i] /= sumRcf; 00244 } 00245 00246 // create a matrix to store m_tempoScratchValues modified by log2 ratio 00247 for ( i=0; i<m_lagLength; i++) 00248 { 00249 rcfMat.push_back ( vector<double>() ); // adds a new row... 00250 } 00251 00252 for (i=0; i<m_lagLength; i++) 00253 { 00254 for (j=0; j<m_lagLength; j++) 00255 { 00256 rcfMat[i].push_back (0.); 00257 } 00258 } 00259 00260 // the 'i' and 'j' indices deliberately start from '1' and not '0' 00261 for ( i=1; i<m_lagLength; i++) 00262 { 00263 for (j=1; j<m_lagLength; j++) 00264 { 00265 double log2PeriodRatio = log( static_cast<double>(i)/static_cast<double>(j) ) / log(2.0); 00266 rcfMat[i][j] = ( abs(1.0-abs(log2PeriodRatio)) ); 00267 rcfMat[i][j] += ( 0.01*( 1./(m_tempoScratch[i]+m_tempoScratch[j]) ) ); 00268 } 00269 } 00270 00271 // set diagonal equal to maximum value in rcfMat 00272 // we don't want to pick one strong middle peak - we need a combination of two peaks. 00273 00274 for ( i=1; i<m_lagLength; i++) 00275 { 00276 for (j=1; j<m_lagLength; j++) 00277 { 00278 if (rcfMat[i][j] > maxVal) 00279 { 00280 maxVal = rcfMat[i][j]; 00281 } 00282 } 00283 } 00284 00285 for ( i=1; i<m_lagLength; i++) 00286 { 00287 rcfMat[i][i] = maxVal; 00288 } 00289 00290 // now find the row and column number which minimise rcfMat 00291 minVal = maxVal; 00292 00293 for ( i=1; i<m_lagLength; i++) 00294 { 00295 for ( j=1; j<m_lagLength; j++) 00296 { 00297 if (rcfMat[i][j] < minVal) 00298 { 00299 minVal = rcfMat[i][j]; 00300 p_i = i; 00301 p_j = j; 00302 } 00303 } 00304 } 00305 00306 00307 // initially choose p_j (arbitrary) - saves on an else statement 00308 int beatPeriod = p_j; 00309 if (m_tempoScratch[p_i] > m_tempoScratch[p_j]) 00310 { 00311 beatPeriod = p_i; 00312 } 00313 00314 // now write the output 00315 maxIndexRCF = static_cast<int>(beatPeriod); 00316 } 00317 00318 00319 double locked = 5168.f / maxIndexRCF; 00320 if (locked >= 30 && locked <= 180) { 00321 m_lockedTempo = locked; 00322 } 00323 00324 #ifdef DEBUG_TEMPO_TRACK 00325 std::cerr << "tempoMM: locked tempo = " << m_lockedTempo << std::endl; 00326 #endif 00327 00328 if( tsig == 0 ) 00329 tsig = 4; 00330 00331 00332 #ifdef DEBUG_TEMPO_TRACK 00333 std::cerr << "tempoMM: maxIndexRCF = " << maxIndexRCF << std::endl; 00334 #endif 00335 00336 if( tsig == 4 ) 00337 { 00338 #ifdef DEBUG_TEMPO_TRACK 00339 std::cerr << "tsig == 4" << std::endl; 00340 #endif 00341 00342 pdPeaks = new double[ 4 ]; 00343 for( i = 0; i < 4; i++ ){ pdPeaks[ i ] = 0.0;} 00344 00345 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1; 00346 00347 maxIndexTemp = 0; 00348 maxValTemp = 0.0; 00349 count = 0; 00350 00351 for( i = (2 * maxIndexRCF + 1) - 1; i < (2 * maxIndexRCF + 1) + 2; i++ ) 00352 { 00353 if( ACF[ i ] > maxValTemp ) 00354 { 00355 maxValTemp = ACF[ i ]; 00356 maxIndexTemp = count; 00357 } 00358 count++; 00359 } 00360 pdPeaks[ 1 ] = (double)( maxIndexTemp + 1 + ( (2 * maxIndexRCF + 1 ) - 2 ) + 1 )/2; 00361 00362 maxIndexTemp = 0; 00363 maxValTemp = 0.0; 00364 count = 0; 00365 00366 for( i = (3 * maxIndexRCF + 2 ) - 2; i < (3 * maxIndexRCF + 2 ) + 3; i++ ) 00367 { 00368 if( ACF[ i ] > maxValTemp ) 00369 { 00370 maxValTemp = ACF[ i ]; 00371 maxIndexTemp = count; 00372 } 00373 count++; 00374 } 00375 pdPeaks[ 2 ] = (double)( maxIndexTemp + 1 + ( (3 * maxIndexRCF + 2) - 4 ) + 1 )/3; 00376 00377 maxIndexTemp = 0; 00378 maxValTemp = 0.0; 00379 count = 0; 00380 00381 for( i = ( 4 * maxIndexRCF + 3) - 3; i < ( 4 * maxIndexRCF + 3) + 4; i++ ) 00382 { 00383 if( ACF[ i ] > maxValTemp ) 00384 { 00385 maxValTemp = ACF[ i ]; 00386 maxIndexTemp = count; 00387 } 00388 count++; 00389 } 00390 pdPeaks[ 3 ] = (double)( maxIndexTemp + 1 + ( (4 * maxIndexRCF + 3) - 9 ) + 1 )/4 ; 00391 00392 00393 period = MathUtilities::mean( pdPeaks, 4 ); 00394 } 00395 else 00396 { 00397 #ifdef DEBUG_TEMPO_TRACK 00398 std::cerr << "tsig != 4" << std::endl; 00399 #endif 00400 00401 pdPeaks = new double[ 3 ]; 00402 for( i = 0; i < 3; i++ ){ pdPeaks[ i ] = 0.0;} 00403 00404 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1; 00405 00406 maxIndexTemp = 0; 00407 maxValTemp = 0.0; 00408 count = 0; 00409 00410 for( i = (2 * maxIndexRCF + 1) - 1; i < (2 * maxIndexRCF + 1) + 2; i++ ) 00411 { 00412 if( ACF[ i ] > maxValTemp ) 00413 { 00414 maxValTemp = ACF[ i ]; 00415 maxIndexTemp = count; 00416 } 00417 count++; 00418 } 00419 pdPeaks[ 1 ] = (double)( maxIndexTemp + 1 + ( (2 * maxIndexRCF + 1 ) - 2 ) + 1 )/2; 00420 00421 maxIndexTemp = 0; 00422 maxValTemp = 0.0; 00423 count = 0; 00424 00425 for( i = (3 * maxIndexRCF + 2 ) - 2; i < (3 * maxIndexRCF + 2 ) + 3; i++ ) 00426 { 00427 if( ACF[ i ] > maxValTemp ) 00428 { 00429 maxValTemp = ACF[ i ]; 00430 maxIndexTemp = count; 00431 } 00432 count++; 00433 } 00434 pdPeaks[ 2 ] = (double)( maxIndexTemp + 1 + ( (3 * maxIndexRCF + 2) - 4 ) + 1 )/3; 00435 00436 00437 period = MathUtilities::mean( pdPeaks, 3 ); 00438 } 00439 00440 delete [] pdPeaks; 00441 00442 return period; 00443 } 00444 00445 void TempoTrack::stepDetect( double* periodP, double* periodG, int currentIdx, int* flag ) 00446 { 00447 double stepthresh = 1 * 3.9017; 00448 00449 if( *flag ) 00450 { 00451 if(abs(periodG[ currentIdx ] - periodP[ currentIdx ]) > stepthresh) 00452 { 00453 // do nuffin' 00454 } 00455 } 00456 else 00457 { 00458 if(fabs(periodG[ currentIdx ]-periodP[ currentIdx ]) > stepthresh) 00459 { 00460 *flag = 3; 00461 } 00462 } 00463 } 00464 00465 void TempoTrack::constDetect( double* periodP, int currentIdx, int* flag ) 00466 { 00467 double constthresh = 2 * 3.9017; 00468 00469 if( fabs( 2 * periodP[ currentIdx ] - periodP[ currentIdx - 1] - periodP[ currentIdx - 2] ) < constthresh) 00470 { 00471 *flag = 1; 00472 } 00473 else 00474 { 00475 *flag = 0; 00476 } 00477 } 00478 00479 int TempoTrack::findMeter(double *ACF, unsigned int len, double period) 00480 { 00481 int i; 00482 int p = (int)MathUtilities::round( period ); 00483 int tsig; 00484 00485 double Energy_3 = 0.0; 00486 double Energy_4 = 0.0; 00487 00488 double temp3A = 0.0; 00489 double temp3B = 0.0; 00490 double temp4A = 0.0; 00491 double temp4B = 0.0; 00492 00493 double* dbf = new double[ len ]; int t = 0; 00494 for( unsigned int u = 0; u < len; u++ ){ dbf[ u ] = 0.0; } 00495 00496 if( (double)len < 6 * p + 2 ) 00497 { 00498 for( i = ( 3 * p - 2 ); i < ( 3 * p + 2 ) + 1; i++ ) 00499 { 00500 temp3A += ACF[ i ]; 00501 dbf[ t++ ] = ACF[ i ]; 00502 } 00503 00504 for( i = ( 4 * p - 2 ); i < ( 4 * p + 2 ) + 1; i++ ) 00505 { 00506 temp4A += ACF[ i ]; 00507 } 00508 00509 Energy_3 = temp3A; 00510 Energy_4 = temp4A; 00511 } 00512 else 00513 { 00514 for( i = ( 3 * p - 2 ); i < ( 3 * p + 2 ) + 1; i++ ) 00515 { 00516 temp3A += ACF[ i ]; 00517 } 00518 00519 for( i = ( 4 * p - 2 ); i < ( 4 * p + 2 ) + 1; i++ ) 00520 { 00521 temp4A += ACF[ i ]; 00522 } 00523 00524 for( i = ( 6 * p - 2 ); i < ( 6 * p + 2 ) + 1; i++ ) 00525 { 00526 temp3B += ACF[ i ]; 00527 } 00528 00529 for( i = ( 2 * p - 2 ); i < ( 2 * p + 2 ) + 1; i++ ) 00530 { 00531 temp4B += ACF[ i ]; 00532 } 00533 00534 Energy_3 = temp3A + temp3B; 00535 Energy_4 = temp4A + temp4B; 00536 } 00537 00538 if (Energy_3 > Energy_4) 00539 { 00540 tsig = 3; 00541 } 00542 else 00543 { 00544 tsig = 4; 00545 } 00546 00547 00548 return tsig; 00549 } 00550 00551 void TempoTrack::createPhaseExtractor(double *Filter, unsigned int winLength, double period, unsigned int fsp, unsigned int lastBeat) 00552 { 00553 int p = (int)MathUtilities::round( period ); 00554 int predictedOffset = 0; 00555 00556 #ifdef DEBUG_TEMPO_TRACK 00557 std::cerr << "TempoTrack::createPhaseExtractor: period = " << period << ", p = " << p << std::endl; 00558 #endif 00559 00560 if (p > 10000) { 00561 std::cerr << "TempoTrack::createPhaseExtractor: WARNING! Highly implausible period value " << p << "!" << std::endl; 00562 period = 5168 / 120; 00563 } 00564 00565 double* phaseScratch = new double[ p*2 + 2 ]; 00566 for (int i = 0; i < p*2 + 2; ++i) phaseScratch[i] = 0.0; 00567 00568 00569 if( lastBeat != 0 ) 00570 { 00571 lastBeat = (int)MathUtilities::round((double)lastBeat ); 00572 00573 predictedOffset = lastBeat + p - fsp; 00574 00575 if (predictedOffset < 0) 00576 { 00577 lastBeat = 0; 00578 } 00579 } 00580 00581 if( lastBeat != 0 ) 00582 { 00583 int mu = p; 00584 double sigma = (double)p/8; 00585 double PhaseMin = 0.0; 00586 double PhaseMax = 0.0; 00587 unsigned int scratchLength = p*2; 00588 double temp = 0.0; 00589 00590 for( int i = 0; i < scratchLength; i++ ) 00591 { 00592 phaseScratch[ i ] = exp( -0.5 * pow( ( i - mu ) / sigma, 2 ) ) / ( sqrt( 2*PI ) *sigma ); 00593 } 00594 00595 MathUtilities::getFrameMinMax( phaseScratch, scratchLength, &PhaseMin, &PhaseMax ); 00596 00597 for(int i = 0; i < scratchLength; i ++) 00598 { 00599 temp = phaseScratch[ i ]; 00600 phaseScratch[ i ] = (temp - PhaseMin)/PhaseMax; 00601 } 00602 00603 #ifdef DEBUG_TEMPO_TRACK 00604 std::cerr << "predictedOffset = " << predictedOffset << std::endl; 00605 #endif 00606 00607 unsigned int index = 0; 00608 for (int i = p - ( predictedOffset - 1); i < p + ( p - predictedOffset) + 1; i++) 00609 { 00610 #ifdef DEBUG_TEMPO_TRACK 00611 std::cerr << "assigning to filter index " << index << " (size = " << p*2 << ")" << " value " << phaseScratch[i] << " from scratch index " << i << std::endl; 00612 #endif 00613 Filter[ index++ ] = phaseScratch[ i ]; 00614 } 00615 } 00616 else 00617 { 00618 for( int i = 0; i < p; i ++) 00619 { 00620 Filter[ i ] = 1; 00621 } 00622 } 00623 00624 delete [] phaseScratch; 00625 } 00626 00627 int TempoTrack::phaseMM(double *DF, double *weighting, unsigned int winLength, double period) 00628 { 00629 int alignment = 0; 00630 int p = (int)MathUtilities::round( period ); 00631 00632 double temp = 0.0; 00633 00634 double* y = new double[ winLength ]; 00635 double* align = new double[ p ]; 00636 00637 for( int i = 0; i < winLength; i++ ) 00638 { 00639 y[ i ] = (double)( -i + winLength )/(double)winLength; 00640 y[ i ] = pow(y [i ],2.0); // raise to power 2. 00641 } 00642 00643 for( int o = 0; o < p; o++ ) 00644 { 00645 temp = 0.0; 00646 for(int i = 1 + (o - 1); i< winLength; i += (p + 1)) 00647 { 00648 temp = temp + DF[ i ] * y[ i ]; 00649 } 00650 align[ o ] = temp * weighting[ o ]; 00651 } 00652 00653 00654 double valTemp = 0.0; 00655 for(int i = 0; i < p; i++) 00656 { 00657 if( align[ i ] > valTemp ) 00658 { 00659 valTemp = align[ i ]; 00660 alignment = i; 00661 } 00662 } 00663 00664 delete [] y; 00665 delete [] align; 00666 00667 return alignment; 00668 } 00669 00670 int TempoTrack::beatPredict(unsigned int FSP0, double alignment, double period, unsigned int step ) 00671 { 00672 int beat = 0; 00673 00674 int p = (int)MathUtilities::round( period ); 00675 int align = (int)MathUtilities::round( alignment ); 00676 int FSP = (int)MathUtilities::round( FSP0 ); 00677 00678 int FEP = FSP + ( step ); 00679 00680 beat = FSP + align; 00681 00682 m_beats.push_back( beat ); 00683 00684 while( beat + p < FEP ) 00685 { 00686 beat += p; 00687 00688 m_beats.push_back( beat ); 00689 } 00690 00691 return beat; 00692 } 00693 00694 00695 00696 vector<int> TempoTrack::process( vector <double> DF, 00697 vector <double> *tempoReturn ) 00698 { 00699 m_dataLength = DF.size(); 00700 00701 m_lockedTempo = 0.0; 00702 00703 double period = 0.0; 00704 int stepFlag = 0; 00705 int constFlag = 0; 00706 int FSP = 0; 00707 int tsig = 0; 00708 int lastBeat = 0; 00709 00710 vector <double> causalDF; 00711 00712 causalDF = DF; 00713 00714 //Prepare Causal Extension DFData 00715 unsigned int DFCLength = m_dataLength + m_winLength; 00716 00717 for( unsigned int j = 0; j < m_winLength; j++ ) 00718 { 00719 causalDF.push_back( 0 ); 00720 } 00721 00722 00723 double* RW = new double[ m_lagLength ]; 00724 for( unsigned int clear = 0; clear < m_lagLength; clear++){ RW[ clear ] = 0.0;} 00725 00726 double* GW = new double[ m_lagLength ]; 00727 for(unsigned int clear = 0; clear < m_lagLength; clear++){ GW[ clear ] = 0.0;} 00728 00729 double* PW = new double[ m_lagLength ]; 00730 for(unsigned clear = 0; clear < m_lagLength; clear++){ PW[ clear ] = 0.0;} 00731 00732 m_DFFramer.setSource( &causalDF[0], m_dataLength ); 00733 00734 unsigned int TTFrames = m_DFFramer.getMaxNoFrames(); 00735 00736 #ifdef DEBUG_TEMPO_TRACK 00737 std::cerr << "TTFrames = " << TTFrames << std::endl; 00738 #endif 00739 00740 double* periodP = new double[ TTFrames ]; 00741 for(unsigned clear = 0; clear < TTFrames; clear++){ periodP[ clear ] = 0.0;} 00742 00743 double* periodG = new double[ TTFrames ]; 00744 for(unsigned clear = 0; clear < TTFrames; clear++){ periodG[ clear ] = 0.0;} 00745 00746 double* alignment = new double[ TTFrames ]; 00747 for(unsigned clear = 0; clear < TTFrames; clear++){ alignment[ clear ] = 0.0;} 00748 00749 m_beats.clear(); 00750 00751 createCombFilter( RW, m_lagLength, 0, 0 ); 00752 00753 int TTLoopIndex = 0; 00754 00755 for( unsigned int i = 0; i < TTFrames; i++ ) 00756 { 00757 m_DFFramer.getFrame( m_rawDFFrame ); 00758 00759 m_DFConditioning->process( m_rawDFFrame, m_smoothDFFrame ); 00760 00761 m_correlator.doAutoUnBiased( m_smoothDFFrame, m_frameACF, m_winLength ); 00762 00763 periodP[ TTLoopIndex ] = tempoMM( m_frameACF, RW, 0 ); 00764 00765 if( GW[ 0 ] != 0 ) 00766 { 00767 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); 00768 } 00769 else 00770 { 00771 periodG[ TTLoopIndex ] = 0.0; 00772 } 00773 00774 stepDetect( periodP, periodG, TTLoopIndex, &stepFlag ); 00775 00776 if( stepFlag == 1) 00777 { 00778 constDetect( periodP, TTLoopIndex, &constFlag ); 00779 stepFlag = 0; 00780 } 00781 else 00782 { 00783 stepFlag -= 1; 00784 } 00785 00786 if( stepFlag < 0 ) 00787 { 00788 stepFlag = 0; 00789 } 00790 00791 if( constFlag != 0) 00792 { 00793 tsig = findMeter( m_frameACF, m_winLength, periodP[ TTLoopIndex ] ); 00794 00795 createCombFilter( GW, m_lagLength, tsig, periodP[ TTLoopIndex ] ); 00796 00797 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); 00798 00799 period = periodG[ TTLoopIndex ]; 00800 00801 #ifdef DEBUG_TEMPO_TRACK 00802 std::cerr << "TempoTrack::process: constFlag == " << constFlag << ", TTLoopIndex = " << TTLoopIndex << ", period from periodG = " << period << std::endl; 00803 #endif 00804 00805 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); 00806 00807 constFlag = 0; 00808 00809 } 00810 else 00811 { 00812 if( GW[ 0 ] != 0 ) 00813 { 00814 period = periodG[ TTLoopIndex ]; 00815 00816 #ifdef DEBUG_TEMPO_TRACK 00817 std::cerr << "TempoTrack::process: GW[0] == " << GW[0] << ", TTLoopIndex = " << TTLoopIndex << ", period from periodG = " << period << std::endl; 00818 #endif 00819 00820 if (period > 10000) { 00821 std::cerr << "TempoTrack::process: WARNING! Highly implausible period value " << period << "!" << std::endl; 00822 std::cerr << "periodG contains (of " << TTFrames << " frames): " << std::endl; 00823 for (int i = 0; i < TTLoopIndex + 3 && i < TTFrames; ++i) { 00824 std::cerr << i << " -> " << periodG[i] << std::endl; 00825 } 00826 std::cerr << "periodP contains (of " << TTFrames << " frames): " << std::endl; 00827 for (int i = 0; i < TTLoopIndex + 3 && i < TTFrames; ++i) { 00828 std::cerr << i << " -> " << periodP[i] << std::endl; 00829 } 00830 period = 5168 / 120; 00831 } 00832 00833 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat ); 00834 00835 } 00836 else 00837 { 00838 period = periodP[ TTLoopIndex ]; 00839 00840 #ifdef DEBUG_TEMPO_TRACK 00841 std::cerr << "TempoTrack::process: GW[0] == " << GW[0] << ", TTLoopIndex = " << TTLoopIndex << ", period from periodP = " << period << std::endl; 00842 #endif 00843 00844 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); 00845 } 00846 } 00847 00848 alignment[ TTLoopIndex ] = phaseMM( m_rawDFFrame, PW, m_winLength, period ); 00849 00850 lastBeat = beatPredict(FSP, alignment[ TTLoopIndex ], period, m_lagLength ); 00851 00852 FSP += (m_lagLength); 00853 00854 if (tempoReturn) tempoReturn->push_back(m_lockedTempo); 00855 00856 TTLoopIndex++; 00857 } 00858 00859 00860 delete [] periodP; 00861 delete [] periodG; 00862 delete [] alignment; 00863 00864 delete [] RW; 00865 delete [] GW; 00866 delete [] PW; 00867 00868 return m_beats; 00869 }