annotate dsp/tempotracking/TempoTrack.cpp @ 16:2e3f5d2d62c1

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