annotate dsp/tempotracking/TempoTrack.cpp @ 241:a98dd8ec96f8

* Move dsp/maths to maths ; bring PCA and HMM across from Soundbite
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 09 Jan 2008 10:31:29 +0000
parents dbc354a00714
children 200677638f5b
rev   line source
c@225 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@225 2
c@225 3 /*
c@225 4 QM DSP Library
c@225 5
c@225 6 Centre for Digital Music, Queen Mary, University of London.
c@225 7 This file copyright 2005-2006 Christian Landone.
c@225 8 All rights reserved.
c@225 9 */
c@225 10
c@225 11 #include "TempoTrack.h"
c@225 12
c@241 13 #include "maths/MathAliases.h"
c@241 14 #include "maths/MathUtilities.h"
c@225 15
c@231 16 #include <iostream>
c@231 17
c@225 18
c@225 19 //////////////////////////////////////////////////////////////////////
c@225 20 // Construction/Destruction
c@225 21 //////////////////////////////////////////////////////////////////////
c@225 22
c@225 23 TempoTrack::TempoTrack( TTParams Params )
c@225 24 {
c@225 25 m_tempoScratch = NULL;
c@225 26 m_rawDFFrame = NULL;
c@225 27 m_smoothDFFrame = NULL;
c@225 28 m_frameACF = NULL;
c@225 29
c@225 30 m_dataLength = 0;
c@225 31 m_winLength = 0;
c@225 32 m_lagLength = 0;
c@225 33
c@225 34 m_rayparam = 0;
c@225 35 m_sigma = 0;
c@225 36 m_DFWVNnorm = 0;
c@225 37
c@225 38 initialise( Params );
c@225 39 }
c@225 40
c@225 41 TempoTrack::~TempoTrack()
c@225 42 {
c@225 43 deInitialise();
c@225 44 }
c@225 45
c@225 46 void TempoTrack::initialise( TTParams Params )
c@225 47 {
c@225 48 m_winLength = Params.winLength;
c@225 49 m_lagLength = Params.lagLength;
c@225 50
c@225 51 m_rayparam = 43.0;
c@225 52 m_sigma = sqrt(3.9017);
c@225 53 m_DFWVNnorm = exp( ( log( 2.0 ) / m_rayparam ) * ( m_winLength + 2 ) );
c@225 54
c@225 55 m_rawDFFrame = new double[ m_winLength ];
c@225 56 m_smoothDFFrame = new double[ m_winLength ];
c@225 57 m_frameACF = new double[ m_winLength ];
c@225 58 m_tempoScratch = new double[ m_lagLength ];
c@225 59
c@225 60 unsigned int winPre = Params.WinT.pre;
c@225 61 unsigned int winPost = Params.WinT.post;
c@225 62
c@225 63 m_DFFramer.configure( m_winLength, m_lagLength );
c@225 64
c@225 65 m_DFPParams.length = m_winLength;
c@225 66 m_DFPParams.AlphaNormParam = Params.alpha;
c@225 67 m_DFPParams.LPOrd = Params.LPOrd;
c@225 68 m_DFPParams.LPACoeffs = Params.LPACoeffs;
c@225 69 m_DFPParams.LPBCoeffs = Params.LPBCoeffs;
c@225 70 m_DFPParams.winPre = Params.WinT.pre;
c@225 71 m_DFPParams.winPost = Params.WinT.post;
c@225 72 m_DFPParams.isMedianPositive = true;
c@225 73
c@225 74 m_DFConditioning = new DFProcess( m_DFPParams );
c@225 75
c@225 76 }
c@225 77
c@225 78 void TempoTrack::deInitialise()
c@225 79 {
c@225 80 delete [] m_rawDFFrame;
c@225 81
c@225 82 delete [] m_smoothDFFrame;
c@225 83
c@225 84 delete [] m_frameACF;
c@225 85
c@225 86 delete [] m_tempoScratch;
c@225 87
c@225 88 delete m_DFConditioning;
c@225 89 }
c@225 90
c@225 91 void TempoTrack::createCombFilter(double* Filter, unsigned int winLength, unsigned int TSig, double beatLag)
c@225 92 {
c@225 93 unsigned int i;
c@225 94
c@225 95 if( beatLag == 0 )
c@225 96 {
c@225 97 for( i = 0; i < winLength; i++ )
c@225 98 {
c@225 99 Filter[ i ] = ( ( i + 1 ) / pow( m_rayparam, 2.0) ) * exp( ( -pow(( i + 1 ),2.0 ) / ( 2.0 * pow( m_rayparam, 2.0))));
c@225 100 }
c@225 101 }
c@225 102 else
c@225 103 {
c@225 104 m_sigma = beatLag/8;
c@225 105 for( i = 0; i < winLength; i++ )
c@225 106 {
c@225 107 double dlag = (double)(i+1) - beatLag;
c@225 108 Filter[ i ] = exp(-0.5 * pow(( dlag / m_sigma), 2.0) ) / (sqrt( 2 * PI) * m_sigma);
c@225 109 }
c@225 110 }
c@225 111 }
c@225 112
c@225 113 double TempoTrack::tempoMM(double* ACF, double* weight, int tsig)
c@225 114 {
c@225 115
c@225 116 double period = 0;
c@225 117 double maxValRCF = 0.0;
c@225 118 unsigned int maxIndexRCF = 0;
c@225 119
c@225 120 double* pdPeaks;
c@225 121
c@225 122 unsigned int maxIndexTemp;
c@225 123 double maxValTemp;
c@225 124 unsigned int count;
c@225 125
c@225 126 unsigned int numelem;
c@225 127 int i, a, b;
c@225 128
c@225 129 for( i = 0; i < m_lagLength; i++ )
c@225 130 m_tempoScratch[ i ] = 0.0;
c@225 131
c@225 132 if( tsig == 0 )
c@225 133 {
c@225 134 //if time sig is unknown, use metrically unbiased version of Filterbank
c@225 135 numelem = 4;
c@225 136 }
c@225 137 else
c@225 138 {
c@225 139 numelem = tsig;
c@225 140 }
c@225 141
c@225 142 for(i=1;i<m_lagLength-1;i++)
c@225 143 {
c@225 144 //first and last output values are left intentionally as zero
c@225 145 for (a=1;a<=numelem;a++)
c@225 146 {
c@225 147 for(b=(1-a);b<a;b++)
c@225 148 {
c@225 149 if( tsig == 0 )
c@225 150 {
c@225 151 m_tempoScratch[i] += ACF[a*(i+1)+b-1] * (1.0 / (2.0 * (double)a-1)) * weight[i];
c@225 152 }
c@225 153 else
c@225 154 {
c@225 155 m_tempoScratch[i] += ACF[a*(i+1)+b-1] * 1 * weight[i];
c@225 156 }
c@225 157 }
c@225 158 }
c@225 159 }
c@225 160
c@225 161
c@225 162 //NOW FIND MAX INDEX OF ACFOUT
c@225 163 for( i = 0; i < m_lagLength; i++)
c@225 164 {
c@225 165 if( m_tempoScratch[ i ] > maxValRCF)
c@225 166 {
c@225 167 maxValRCF = m_tempoScratch[ i ];
c@225 168 maxIndexRCF = i;
c@225 169 }
c@225 170 }
c@231 171
c@231 172 double locked = 5168.f / maxIndexRCF;
c@231 173 if (locked >= 30 && locked <= 180) {
c@231 174 m_lockedTempo = locked;
c@231 175 }
c@231 176
c@225 177 if( tsig == 0 )
c@225 178 tsig = 4;
c@225 179
c@225 180
c@225 181 if( tsig == 4 )
c@225 182 {
c@225 183 pdPeaks = new double[ 4 ];
c@225 184 for( i = 0; i < 4; i++ ){ pdPeaks[ i ] = 0.0;}
c@225 185
c@225 186 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1;
c@225 187
c@225 188 maxIndexTemp = 0;
c@225 189 maxValTemp = 0.0;
c@225 190 count = 0;
c@225 191
c@225 192 for( i = (2 * maxIndexRCF + 1) - 1; i < (2 * maxIndexRCF + 1) + 2; i++ )
c@225 193 {
c@225 194 if( ACF[ i ] > maxValTemp )
c@225 195 {
c@225 196 maxValTemp = ACF[ i ];
c@225 197 maxIndexTemp = count;
c@225 198 }
c@225 199 count++;
c@225 200 }
c@225 201 pdPeaks[ 1 ] = (double)( maxIndexTemp + 1 + ( (2 * maxIndexRCF + 1 ) - 2 ) + 1 )/2;
c@225 202
c@225 203 maxIndexTemp = 0;
c@225 204 maxValTemp = 0.0;
c@225 205 count = 0;
c@225 206
c@225 207 for( i = (3 * maxIndexRCF + 2 ) - 2; i < (3 * maxIndexRCF + 2 ) + 3; i++ )
c@225 208 {
c@225 209 if( ACF[ i ] > maxValTemp )
c@225 210 {
c@225 211 maxValTemp = ACF[ i ];
c@225 212 maxIndexTemp = count;
c@225 213 }
c@225 214 count++;
c@225 215 }
c@225 216 pdPeaks[ 2 ] = (double)( maxIndexTemp + 1 + ( (3 * maxIndexRCF + 2) - 4 ) + 1 )/3;
c@225 217
c@225 218 maxIndexTemp = 0;
c@225 219 maxValTemp = 0.0;
c@225 220 count = 0;
c@225 221
c@225 222 for( i = ( 4 * maxIndexRCF + 3) - 3; i < ( 4 * maxIndexRCF + 3) + 4; i++ )
c@225 223 {
c@225 224 if( ACF[ i ] > maxValTemp )
c@225 225 {
c@225 226 maxValTemp = ACF[ i ];
c@225 227 maxIndexTemp = count;
c@225 228 }
c@225 229 count++;
c@225 230 }
c@225 231 pdPeaks[ 3 ] = (double)( maxIndexTemp + 1 + ( (4 * maxIndexRCF + 3) - 9 ) + 1 )/4 ;
c@225 232
c@225 233
c@225 234 period = MathUtilities::mean( pdPeaks, 4 );
c@225 235 }
c@225 236 else
c@225 237 {
c@225 238 pdPeaks = new double[ 3 ];
c@225 239 for( i = 0; i < 3; i++ ){ pdPeaks[ i ] = 0.0;}
c@225 240
c@225 241 pdPeaks[ 0 ] = ( double )maxIndexRCF + 1;
c@225 242
c@225 243 maxIndexTemp = 0;
c@225 244 maxValTemp = 0.0;
c@225 245 count = 0;
c@225 246
c@225 247 for( i = (2 * maxIndexRCF + 1) - 1; i < (2 * maxIndexRCF + 1) + 2; i++ )
c@225 248 {
c@225 249 if( ACF[ i ] > maxValTemp )
c@225 250 {
c@225 251 maxValTemp = ACF[ i ];
c@225 252 maxIndexTemp = count;
c@225 253 }
c@225 254 count++;
c@225 255 }
c@225 256 pdPeaks[ 1 ] = (double)( maxIndexTemp + 1 + ( (2 * maxIndexRCF + 1 ) - 2 ) + 1 )/2;
c@225 257
c@225 258 maxIndexTemp = 0;
c@225 259 maxValTemp = 0.0;
c@225 260 count = 0;
c@225 261
c@225 262 for( i = (3 * maxIndexRCF + 2 ) - 2; i < (3 * maxIndexRCF + 2 ) + 3; i++ )
c@225 263 {
c@225 264 if( ACF[ i ] > maxValTemp )
c@225 265 {
c@225 266 maxValTemp = ACF[ i ];
c@225 267 maxIndexTemp = count;
c@225 268 }
c@225 269 count++;
c@225 270 }
c@225 271 pdPeaks[ 2 ] = (double)( maxIndexTemp + 1 + ( (3 * maxIndexRCF + 2) - 4 ) + 1 )/3;
c@225 272
c@225 273
c@225 274 period = MathUtilities::mean( pdPeaks, 3 );
c@225 275 }
c@225 276
c@225 277 delete [] pdPeaks;
c@225 278
c@225 279 return period;
c@225 280 }
c@225 281
c@225 282 void TempoTrack::stepDetect( double* periodP, double* periodG, int currentIdx, int* flag )
c@225 283 {
c@225 284 double stepthresh = 1 * 3.9017;
c@225 285
c@225 286 if( *flag )
c@225 287 {
c@225 288 if(abs(periodG[ currentIdx ] - periodP[ currentIdx ]) > stepthresh)
c@225 289 {
c@225 290 // do nuffin'
c@225 291 }
c@225 292 }
c@225 293 else
c@225 294 {
c@225 295 if(fabs(periodG[ currentIdx ]-periodP[ currentIdx ]) > stepthresh)
c@225 296 {
c@225 297 *flag = 3;
c@225 298 }
c@225 299 }
c@225 300 }
c@225 301
c@225 302 void TempoTrack::constDetect( double* periodP, int currentIdx, int* flag )
c@225 303 {
c@225 304 double constthresh = 2 * 3.9017;
c@225 305
c@225 306 if( fabs( 2 * periodP[ currentIdx ] - periodP[ currentIdx - 1] - periodP[ currentIdx - 2] ) < constthresh)
c@225 307 {
c@225 308 *flag = 1;
c@225 309 }
c@225 310 else
c@225 311 {
c@225 312 *flag = 0;
c@225 313 }
c@225 314 }
c@225 315
c@225 316 int TempoTrack::findMeter(double *ACF, unsigned int len, double period)
c@225 317 {
c@225 318 int i;
c@225 319 int p = (int)MathUtilities::round( period );
c@225 320 int tsig;
c@225 321
c@225 322 double Energy_3 = 0.0;
c@225 323 double Energy_4 = 0.0;
c@225 324
c@225 325 double temp3A = 0.0;
c@225 326 double temp3B = 0.0;
c@225 327 double temp4A = 0.0;
c@225 328 double temp4B = 0.0;
c@225 329
c@225 330 double* dbf = new double[ len ]; int t = 0;
c@225 331 for( unsigned int u = 0; u < len; u++ ){ dbf[ u ] = 0.0; }
c@225 332
c@225 333 if( (double)len < 6 * p + 2 )
c@225 334 {
c@225 335 for( i = ( 3 * p - 2 ); i < ( 3 * p + 2 ) + 1; i++ )
c@225 336 {
c@225 337 temp3A += ACF[ i ];
c@225 338 dbf[ t++ ] = ACF[ i ];
c@225 339 }
c@225 340
c@225 341 for( i = ( 4 * p - 2 ); i < ( 4 * p + 2 ) + 1; i++ )
c@225 342 {
c@225 343 temp4A += ACF[ i ];
c@225 344 }
c@225 345
c@225 346 Energy_3 = temp3A;
c@225 347 Energy_4 = temp4A;
c@225 348 }
c@225 349 else
c@225 350 {
c@225 351 for( i = ( 3 * p - 2 ); i < ( 3 * p + 2 ) + 1; i++ )
c@225 352 {
c@225 353 temp3A += ACF[ i ];
c@225 354 }
c@225 355
c@225 356 for( i = ( 4 * p - 2 ); i < ( 4 * p + 2 ) + 1; i++ )
c@225 357 {
c@225 358 temp4A += ACF[ i ];
c@225 359 }
c@225 360
c@225 361 for( i = ( 6 * p - 2 ); i < ( 6 * p + 2 ) + 1; i++ )
c@225 362 {
c@225 363 temp3B += ACF[ i ];
c@225 364 }
c@225 365
c@225 366 for( i = ( 2 * p - 2 ); i < ( 2 * p + 2 ) + 1; i++ )
c@225 367 {
c@225 368 temp4B += ACF[ i ];
c@225 369 }
c@225 370
c@225 371 Energy_3 = temp3A + temp3B;
c@225 372 Energy_4 = temp4A + temp4B;
c@225 373 }
c@225 374
c@225 375 if (Energy_3 > Energy_4)
c@225 376 {
c@225 377 tsig = 3;
c@225 378 }
c@225 379 else
c@225 380 {
c@225 381 tsig = 4;
c@225 382 }
c@225 383
c@225 384
c@225 385 return tsig;
c@225 386 }
c@225 387
c@225 388 void TempoTrack::createPhaseExtractor(double *Filter, unsigned int winLength, double period, unsigned int fsp, unsigned int lastBeat)
c@225 389 {
c@225 390 int p = (int)MathUtilities::round( period );
c@225 391 int predictedOffset = 0;
c@225 392
c@225 393 double* phaseScratch = new double[ p*2 ];
c@225 394
c@225 395
c@225 396 if( lastBeat != 0 )
c@225 397 {
c@225 398 lastBeat = (int)MathUtilities::round((double)lastBeat );///(double)winLength);
c@225 399
c@225 400 predictedOffset = lastBeat + p - fsp;
c@225 401
c@225 402 if (predictedOffset < 0)
c@225 403 {
c@225 404 lastBeat = 0;
c@225 405 }
c@225 406 }
c@225 407
c@225 408 if( lastBeat != 0 )
c@225 409 {
c@225 410 int mu = p;
c@225 411 double sigma = (double)p/4;
c@225 412 double PhaseMin = 0.0;
c@225 413 double PhaseMax = 0.0;
c@225 414 unsigned int scratchLength = p*2;
c@225 415 double temp = 0.0;
c@225 416
c@225 417 for( int i = 0; i < scratchLength; i++ )
c@225 418 {
c@225 419 phaseScratch[ i ] = exp( -0.5 * pow( ( i - mu ) / sigma, 2 ) ) / ( sqrt( 2*PI ) *sigma );
c@225 420 }
c@225 421
c@225 422 MathUtilities::getFrameMinMax( phaseScratch, scratchLength, &PhaseMin, &PhaseMax );
c@225 423
c@225 424 for(int i = 0; i < scratchLength; i ++)
c@225 425 {
c@225 426 temp = phaseScratch[ i ];
c@225 427 phaseScratch[ i ] = (temp - PhaseMin)/PhaseMax;
c@225 428 }
c@225 429
c@225 430 unsigned int index = 0;
c@225 431 for(int i = p - ( predictedOffset - 1); i < p + ( p - predictedOffset) + 1; i++)
c@225 432 {
c@225 433 Filter[ index++ ] = phaseScratch[ i ];
c@225 434 }
c@225 435 }
c@225 436 else
c@225 437 {
c@225 438 for( int i = 0; i < p; i ++)
c@225 439 {
c@225 440 Filter[ i ] = 1;
c@225 441 }
c@225 442 }
c@225 443
c@225 444 delete [] phaseScratch;
c@225 445 }
c@225 446
c@225 447 int TempoTrack::phaseMM(double *DF, double *weighting, unsigned int winLength, double period)
c@225 448 {
c@225 449 int alignment = 0;
c@225 450 int p = (int)MathUtilities::round( period );
c@225 451
c@225 452 double temp = 0.0;
c@225 453
c@225 454 double* y = new double[ winLength ];
c@225 455 double* align = new double[ p ];
c@225 456
c@225 457 for( int i = 0; i < winLength; i++ )
c@225 458 {
c@225 459 y[ i ] = (double)( -i + winLength )/(double)winLength;
c@225 460 }
c@225 461
c@225 462 for( int o = 0; o < p; o++ )
c@225 463 {
c@225 464 temp = 0.0;
c@225 465 for(int i = 1 + (o - 1); i< winLength; i += (p + 1))
c@225 466 {
c@225 467 temp = temp + DF[ i ] * y[ i ];
c@225 468 }
c@225 469 align[ o ] = temp * weighting[ o ];
c@225 470 }
c@225 471
c@225 472
c@225 473 double valTemp = 0.0;
c@225 474 for(int i = 0; i < p; i++)
c@225 475 {
c@225 476 if( align[ i ] > valTemp )
c@225 477 {
c@225 478 valTemp = align[ i ];
c@225 479 alignment = i;
c@225 480 }
c@225 481 }
c@225 482
c@225 483 delete [] y;
c@225 484 delete [] align;
c@225 485
c@225 486 return alignment;
c@225 487 }
c@225 488
c@225 489 int TempoTrack::beatPredict(unsigned int FSP0, double alignment, double period, unsigned int step )
c@225 490 {
c@225 491 int beat = 0;
c@225 492
c@225 493 int p = (int)MathUtilities::round( period );
c@225 494 int align = (int)MathUtilities::round( alignment );
c@225 495 int FSP = (int)MathUtilities::round( FSP0 );
c@225 496
c@225 497 int FEP = FSP + ( step );
c@225 498
c@225 499 beat = FSP + align;
c@225 500
c@225 501 m_beats.push_back( beat );
c@225 502
c@225 503 while( beat + p < FEP )
c@225 504 {
c@225 505 beat += p;
c@225 506
c@225 507 m_beats.push_back( beat );
c@225 508 }
c@225 509
c@225 510 return beat;
c@225 511 }
c@225 512
c@225 513 vector<int> TempoTrack::process(double *DF, unsigned int length)
c@225 514 {
c@225 515 m_dataLength = length;
c@225 516
c@225 517 double period = 0.0;
c@225 518 int stepFlag = 0;
c@225 519 int constFlag = 0;
c@225 520 int FSP = 0;
c@225 521 int tsig = 0;
c@225 522 int lastBeat = 0;
c@225 523
c@225 524
c@225 525 double* RW = new double[ m_lagLength ];
c@225 526 for( unsigned int clear = 0; clear < m_lagLength; clear++){ RW[ clear ] = 0.0;}
c@225 527
c@225 528 double* GW = new double[ m_lagLength ];
c@225 529 for(unsigned int clear = 0; clear < m_lagLength; clear++){ GW[ clear ] = 0.0;}
c@225 530
c@225 531 double* PW = new double[ m_lagLength ];
c@225 532 for(unsigned int clear = 0; clear < m_lagLength; clear++){ PW[ clear ] = 0.0;}
c@225 533
c@225 534 m_DFFramer.setSource( DF, m_dataLength );
c@225 535
c@225 536 unsigned int TTFrames = m_DFFramer.getMaxNoFrames();
c@225 537
c@225 538 double* periodP = new double[ TTFrames ];
c@225 539 for(unsigned int clear = 0; clear < TTFrames; clear++){ periodP[ clear ] = 0.0;}
c@225 540
c@225 541 double* periodG = new double[ TTFrames ];
c@225 542 for(unsigned int clear = 0; clear < TTFrames; clear++){ periodG[ clear ] = 0.0;}
c@225 543
c@225 544 double* alignment = new double[ TTFrames ];
c@225 545 for(unsigned int clear = 0; clear < TTFrames; clear++){ alignment[ clear ] = 0.0;}
c@225 546
c@225 547 m_beats.clear();
c@225 548
c@225 549 createCombFilter( RW, m_lagLength, 0, 0 );
c@225 550
c@225 551 int TTLoopIndex = 0;
c@225 552
c@225 553 for( unsigned int i = 0; i < TTFrames; i++ )
c@225 554 {
c@225 555 m_DFFramer.getFrame( m_rawDFFrame );
c@225 556
c@225 557 m_DFConditioning->process( m_rawDFFrame, m_smoothDFFrame );
c@225 558
c@225 559 m_correlator.doAutoUnBiased( m_smoothDFFrame, m_frameACF, m_winLength );
c@225 560
c@225 561 periodP[ TTLoopIndex ] = tempoMM( m_frameACF, RW, 0 );
c@225 562
c@225 563 if( GW[ 0 ] != 0 )
c@225 564 {
c@225 565 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig );
c@225 566 }
c@225 567 else
c@225 568 {
c@225 569 periodG[ TTLoopIndex ] = 0.0;
c@225 570 }
c@225 571
c@225 572 stepDetect( periodP, periodG, TTLoopIndex, &stepFlag );
c@225 573
c@225 574 if( stepFlag == 1)
c@225 575 {
c@225 576 constDetect( periodP, TTLoopIndex, &constFlag );
c@225 577 stepFlag = 0;
c@225 578 }
c@225 579 else
c@225 580 {
c@225 581 stepFlag -= 1;
c@225 582 }
c@225 583
c@225 584 if( stepFlag < 0 )
c@225 585 {
c@225 586 stepFlag = 0;
c@225 587 }
c@225 588
c@225 589 if( constFlag != 0)
c@225 590 {
c@225 591 tsig = findMeter( m_frameACF, m_winLength, periodP[ TTLoopIndex ] );
c@225 592
c@225 593 createCombFilter( GW, m_lagLength, tsig, periodP[ TTLoopIndex ] );
c@225 594
c@225 595 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig );
c@225 596
c@225 597 period = periodG[ TTLoopIndex ];
c@225 598
c@225 599 createPhaseExtractor( PW, m_winLength, period, FSP, 0 );
c@225 600
c@225 601 constFlag = 0;
c@225 602
c@225 603 }
c@225 604 else
c@225 605 {
c@225 606 if( GW[ 0 ] != 0 )
c@225 607 {
c@225 608 period = periodG[ TTLoopIndex ];
c@225 609 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat );
c@225 610
c@225 611 }
c@225 612 else
c@225 613 {
c@225 614 period = periodP[ TTLoopIndex ];
c@225 615 createPhaseExtractor( PW, m_winLength, period, FSP, 0 );
c@225 616 }
c@225 617 }
c@225 618
c@225 619 alignment[ TTLoopIndex ] = phaseMM( m_rawDFFrame, PW, m_winLength, period );
c@225 620
c@225 621 lastBeat = beatPredict(FSP, alignment[ TTLoopIndex ], period, m_lagLength );
c@225 622
c@225 623 FSP += (m_lagLength);
c@225 624
c@225 625 TTLoopIndex++;
c@225 626 }
c@225 627
c@225 628
c@225 629 delete [] periodP;
c@225 630 delete [] periodG;
c@225 631 delete [] alignment;
c@225 632
c@225 633 delete [] RW;
c@225 634 delete [] GW;
c@225 635 delete [] PW;
c@225 636
c@225 637 return m_beats;
c@225 638 }
c@225 639
c@225 640
c@225 641
c@225 642
c@225 643
c@231 644 vector<int> TempoTrack::process( vector <double> DF,
c@231 645 vector <double> *tempoReturn )
c@225 646 {
c@225 647 m_dataLength = DF.size();
c@225 648
c@231 649 m_lockedTempo = 0.0;
c@231 650
c@225 651 double period = 0.0;
c@225 652 int stepFlag = 0;
c@225 653 int constFlag = 0;
c@225 654 int FSP = 0;
c@225 655 int tsig = 0;
c@225 656 int lastBeat = 0;
c@225 657
c@225 658 vector <double> causalDF;
c@225 659
c@225 660 causalDF = DF;
c@225 661
c@225 662 //Prepare Causal Extension DFData
c@225 663 unsigned int DFCLength = m_dataLength + m_winLength;
c@225 664
c@225 665 for( unsigned int j = 0; j < m_winLength; j++ )
c@225 666 {
c@225 667 causalDF.push_back( 0 );
c@225 668 }
c@225 669
c@225 670
c@225 671 double* RW = new double[ m_lagLength ];
c@225 672 for( unsigned int clear = 0; clear < m_lagLength; clear++){ RW[ clear ] = 0.0;}
c@225 673
c@225 674 double* GW = new double[ m_lagLength ];
c@225 675 for(unsigned int clear = 0; clear < m_lagLength; clear++){ GW[ clear ] = 0.0;}
c@225 676
c@225 677 double* PW = new double[ m_lagLength ];
c@225 678 for(unsigned clear = 0; clear < m_lagLength; clear++){ PW[ clear ] = 0.0;}
c@225 679
c@225 680 m_DFFramer.setSource( &causalDF[0], m_dataLength );
c@225 681
c@225 682 unsigned int TTFrames = m_DFFramer.getMaxNoFrames();
c@225 683
c@225 684 double* periodP = new double[ TTFrames ];
c@225 685 for(unsigned clear = 0; clear < TTFrames; clear++){ periodP[ clear ] = 0.0;}
c@225 686
c@225 687 double* periodG = new double[ TTFrames ];
c@225 688 for(unsigned clear = 0; clear < TTFrames; clear++){ periodG[ clear ] = 0.0;}
c@225 689
c@225 690 double* alignment = new double[ TTFrames ];
c@225 691 for(unsigned clear = 0; clear < TTFrames; clear++){ alignment[ clear ] = 0.0;}
c@225 692
c@225 693 m_beats.clear();
c@225 694
c@225 695 createCombFilter( RW, m_lagLength, 0, 0 );
c@225 696
c@225 697 int TTLoopIndex = 0;
c@225 698
c@225 699 for( unsigned int i = 0; i < TTFrames; i++ )
c@225 700 {
c@225 701 m_DFFramer.getFrame( m_rawDFFrame );
c@225 702
c@225 703 m_DFConditioning->process( m_rawDFFrame, m_smoothDFFrame );
c@225 704
c@225 705 m_correlator.doAutoUnBiased( m_smoothDFFrame, m_frameACF, m_winLength );
c@225 706
c@225 707 periodP[ TTLoopIndex ] = tempoMM( m_frameACF, RW, 0 );
c@225 708
c@225 709 if( GW[ 0 ] != 0 )
c@225 710 {
c@225 711 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig );
c@225 712 }
c@225 713 else
c@225 714 {
c@225 715 periodG[ TTLoopIndex ] = 0.0;
c@225 716 }
c@225 717
c@225 718 stepDetect( periodP, periodG, TTLoopIndex, &stepFlag );
c@225 719
c@225 720 if( stepFlag == 1)
c@225 721 {
c@225 722 constDetect( periodP, TTLoopIndex, &constFlag );
c@225 723 stepFlag = 0;
c@225 724 }
c@225 725 else
c@225 726 {
c@225 727 stepFlag -= 1;
c@225 728 }
c@225 729
c@225 730 if( stepFlag < 0 )
c@225 731 {
c@225 732 stepFlag = 0;
c@225 733 }
c@225 734
c@225 735 if( constFlag != 0)
c@225 736 {
c@225 737 tsig = findMeter( m_frameACF, m_winLength, periodP[ TTLoopIndex ] );
c@225 738
c@225 739 createCombFilter( GW, m_lagLength, tsig, periodP[ TTLoopIndex ] );
c@225 740
c@225 741 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig );
c@225 742
c@225 743 period = periodG[ TTLoopIndex ];
c@225 744
c@225 745 createPhaseExtractor( PW, m_winLength, period, FSP, 0 );
c@225 746
c@225 747 constFlag = 0;
c@225 748
c@225 749 }
c@225 750 else
c@225 751 {
c@225 752 if( GW[ 0 ] != 0 )
c@225 753 {
c@225 754 period = periodG[ TTLoopIndex ];
c@225 755 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat );
c@225 756
c@225 757 }
c@225 758 else
c@225 759 {
c@225 760 period = periodP[ TTLoopIndex ];
c@225 761 createPhaseExtractor( PW, m_winLength, period, FSP, 0 );
c@225 762 }
c@225 763 }
c@225 764
c@225 765 alignment[ TTLoopIndex ] = phaseMM( m_rawDFFrame, PW, m_winLength, period );
c@225 766
c@225 767 lastBeat = beatPredict(FSP, alignment[ TTLoopIndex ], period, m_lagLength );
c@225 768
c@225 769 FSP += (m_lagLength);
c@225 770
c@231 771 if (tempoReturn) tempoReturn->push_back(m_lockedTempo);
c@231 772
c@225 773 TTLoopIndex++;
c@225 774 }
c@225 775
c@225 776
c@225 777 delete [] periodP;
c@225 778 delete [] periodG;
c@225 779 delete [] alignment;
c@225 780
c@225 781 delete [] RW;
c@225 782 delete [] GW;
c@225 783 delete [] PW;
c@225 784
c@225 785 return m_beats;
c@225 786 }