annotate dsp/tempotracking/TempoTrack.cpp @ 44:00603b8a940f

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