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