annotate dsp/tempotracking/TempoTrack.cpp @ 0:d7116e3183f8

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