comparison dsp/tempotracking/TempoTrack.cpp @ 505:930b5b0f707d

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