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