comparison dsp/tempotracking/TempoTrack.cpp @ 39:200677638f5b

* Updated tempo tracking code from Matthew Davies
author cannam
date Fri, 01 Feb 2008 16:45:14 +0000
parents 2e3f5d2d62c1
children 4f1870dbab2c
comparison
equal deleted inserted replaced
38:3dff6e3e2121 39:200677638f5b
14 #include "maths/MathUtilities.h" 14 #include "maths/MathUtilities.h"
15 15
16 #include <iostream> 16 #include <iostream>
17 17
18 18
19 #define RAY43VAL
20
19 ////////////////////////////////////////////////////////////////////// 21 //////////////////////////////////////////////////////////////////////
20 // Construction/Destruction 22 // Construction/Destruction
21 ////////////////////////////////////////////////////////////////////// 23 //////////////////////////////////////////////////////////////////////
22 24
23 TempoTrack::TempoTrack( TTParams Params ) 25 TempoTrack::TempoTrack( TTParams Params )
24 { 26 {
25 m_tempoScratch = NULL; 27 m_tempoScratch = NULL;
26 m_rawDFFrame = NULL; 28 m_rawDFFrame = NULL;
27 m_smoothDFFrame = NULL; 29 m_smoothDFFrame = NULL;
28 m_frameACF = NULL; 30 m_frameACF = NULL;
31 m_smoothRCF = NULL;
29 32
30 m_dataLength = 0; 33 m_dataLength = 0;
31 m_winLength = 0; 34 m_winLength = 0;
32 m_lagLength = 0; 35 m_lagLength = 0;
33 36
54 57
55 m_rawDFFrame = new double[ m_winLength ]; 58 m_rawDFFrame = new double[ m_winLength ];
56 m_smoothDFFrame = new double[ m_winLength ]; 59 m_smoothDFFrame = new double[ m_winLength ];
57 m_frameACF = new double[ m_winLength ]; 60 m_frameACF = new double[ m_winLength ];
58 m_tempoScratch = new double[ m_lagLength ]; 61 m_tempoScratch = new double[ m_lagLength ];
62 m_smoothRCF = new double[ m_lagLength ];
63
59 64
60 unsigned int winPre = Params.WinT.pre; 65 unsigned int winPre = Params.WinT.pre;
61 unsigned int winPost = Params.WinT.post; 66 unsigned int winPost = Params.WinT.post;
62 67
63 m_DFFramer.configure( m_winLength, m_lagLength ); 68 m_DFFramer.configure( m_winLength, m_lagLength );
71 m_DFPParams.winPost = Params.WinT.post; 76 m_DFPParams.winPost = Params.WinT.post;
72 m_DFPParams.isMedianPositive = true; 77 m_DFPParams.isMedianPositive = true;
73 78
74 m_DFConditioning = new DFProcess( m_DFPParams ); 79 m_DFConditioning = new DFProcess( m_DFPParams );
75 80
81
82 // these are parameters for smoothing m_tempoScratch
83 m_RCFPParams.length = m_lagLength;
84 m_RCFPParams.AlphaNormParam = Params.alpha;
85 m_RCFPParams.LPOrd = Params.LPOrd;
86 m_RCFPParams.LPACoeffs = Params.LPACoeffs;
87 m_RCFPParams.LPBCoeffs = Params.LPBCoeffs;
88 m_RCFPParams.winPre = Params.WinT.pre;
89 m_RCFPParams.winPost = Params.WinT.post;
90 m_RCFPParams.isMedianPositive = true;
91
92 m_RCFConditioning = new DFProcess( m_RCFPParams );
93
76 } 94 }
77 95
78 void TempoTrack::deInitialise() 96 void TempoTrack::deInitialise()
79 { 97 {
80 delete [] m_rawDFFrame; 98 delete [] m_rawDFFrame;
81 99
82 delete [] m_smoothDFFrame; 100 delete [] m_smoothDFFrame;
101
102 delete [] m_smoothRCF;
83 103
84 delete [] m_frameACF; 104 delete [] m_frameACF;
85 105
86 delete [] m_tempoScratch; 106 delete [] m_tempoScratch;
87 107
88 delete m_DFConditioning; 108 delete m_DFConditioning;
109
110 delete m_RCFConditioning;
111
89 } 112 }
90 113
91 void TempoTrack::createCombFilter(double* Filter, unsigned int winLength, unsigned int TSig, double beatLag) 114 void TempoTrack::createCombFilter(double* Filter, unsigned int winLength, unsigned int TSig, double beatLag)
92 { 115 {
93 unsigned int i; 116 unsigned int i;
99 Filter[ i ] = ( ( i + 1 ) / pow( m_rayparam, 2.0) ) * exp( ( -pow(( i + 1 ),2.0 ) / ( 2.0 * pow( m_rayparam, 2.0)))); 122 Filter[ i ] = ( ( i + 1 ) / pow( m_rayparam, 2.0) ) * exp( ( -pow(( i + 1 ),2.0 ) / ( 2.0 * pow( m_rayparam, 2.0))));
100 } 123 }
101 } 124 }
102 else 125 else
103 { 126 {
104 m_sigma = beatLag/8; 127 m_sigma = beatLag/4;
105 for( i = 0; i < winLength; i++ ) 128 for( i = 0; i < winLength; i++ )
106 { 129 {
107 double dlag = (double)(i+1) - beatLag; 130 double dlag = (double)(i+1) - beatLag;
108 Filter[ i ] = exp(-0.5 * pow(( dlag / m_sigma), 2.0) ) / (sqrt( 2 * PI) * m_sigma); 131 Filter[ i ] = exp(-0.5 * pow(( dlag / m_sigma), 2.0) ) / (sqrt( 2 * PI) * m_sigma);
109 } 132 }
121 144
122 unsigned int maxIndexTemp; 145 unsigned int maxIndexTemp;
123 double maxValTemp; 146 double maxValTemp;
124 unsigned int count; 147 unsigned int count;
125 148
126 unsigned int numelem; 149 unsigned int numelem,i,j;
127 int i, a, b; 150 int a, b;
128 151
129 for( i = 0; i < m_lagLength; i++ ) 152 for( i = 0; i < m_lagLength; i++ )
130 m_tempoScratch[ i ] = 0.0; 153 m_tempoScratch[ i ] = 0.0;
131 154
132 if( tsig == 0 ) 155 if( tsig == 0 )
157 } 180 }
158 } 181 }
159 } 182 }
160 183
161 184
162 //NOW FIND MAX INDEX OF ACFOUT 185 //////////////////////////////////////////////////
163 for( i = 0; i < m_lagLength; i++) 186 // MODIFIED BEAT PERIOD EXTRACTION //////////////
164 { 187 /////////////////////////////////////////////////
165 if( m_tempoScratch[ i ] > maxValRCF) 188
166 { 189 // find smoothed version of RCF ( as applied to Detection Function)
167 maxValRCF = m_tempoScratch[ i ]; 190 m_RCFConditioning->process( m_tempoScratch, m_smoothRCF);
168 maxIndexRCF = i; 191
169 } 192 if (tsig != 0) // i.e. in context dependent state
170 } 193 {
194 // NOW FIND MAX INDEX OF ACFOUT
195 for( i = 0; i < m_lagLength; i++)
196 {
197 if( m_tempoScratch[ i ] > maxValRCF)
198 {
199 maxValRCF = m_tempoScratch[ i ];
200 maxIndexRCF = i;
201 }
202 }
203 }
204 else // using rayleigh weighting
205 {
206 vector <vector<double> > rcfMat;
207
208 double sumRcf = 0.;
209
210 double maxVal = 0.;
211 // now find the two values which minimise rcfMat
212 double minVal = 0.;
213 int p_i = 1; // periodicity for row i;
214 int p_j = 1; //periodicity for column j;
215
216
217 for ( i=0; i<m_lagLength; i++)
218 {
219 m_tempoScratch[i] =m_smoothRCF[i];
220 }
221
222 // normalise m_tempoScratch so that it sums to zero.
223 for ( i=0; i<m_lagLength; i++)
224 {
225 sumRcf += m_tempoScratch[i];
226 }
227
228 for( i=0; i<m_lagLength; i++)
229 {
230 m_tempoScratch[i] /= sumRcf;
231 }
232
233 // create a matrix to store m_tempoScratchValues modified by log2 ratio
234 for ( i=0; i<m_lagLength; i++)
235 {
236 rcfMat.push_back ( vector<double>() ); // adds a new row...
237 }
238
239 for (i=0; i<m_lagLength; i++)
240 {
241 for (j=0; j<m_lagLength; j++)
242 {
243 rcfMat[i].push_back (0.);
244 }
245 }
246
247 // the 'i' and 'j' indices deliberately start from '1' and not '0'
248 for ( i=1; i<m_lagLength; i++)
249 {
250 for (j=1; j<m_lagLength; j++)
251 {
252 double log2PeriodRatio = log( static_cast<double>(i)/static_cast<double>(j) ) / log(2.0);
253 rcfMat[i][j] = ( abs(1.0-abs(log2PeriodRatio)) );
254 rcfMat[i][j] += ( 0.01*( 1./(m_tempoScratch[i]+m_tempoScratch[j]) ) );
255 }
256 }
257
258 // set diagonal equal to maximum value in rcfMat
259 // we don't want to pick one strong middle peak - we need a combination of two peaks.
260
261 for ( i=1; i<m_lagLength; i++)
262 {
263 for (j=1; j<m_lagLength; j++)
264 {
265 if (rcfMat[i][j] > maxVal)
266 {
267 maxVal = rcfMat[i][j];
268 }
269 }
270 }
271
272 for ( i=1; i<m_lagLength; i++)
273 {
274 rcfMat[i][i] = maxVal;
275 }
276
277 // now find the row and column number which minimise rcfMat
278 minVal = maxVal;
279
280 for ( i=1; i<m_lagLength; i++)
281 {
282 for ( j=1; j<m_lagLength; j++)
283 {
284 if (rcfMat[i][j] < minVal)
285 {
286 minVal = rcfMat[i][j];
287 p_i = i;
288 p_j = j;
289 }
290 }
291 }
292
293
294 // initially choose p_j (arbitrary) - saves on an else statement
295 int beatPeriod = p_j;
296 if (m_tempoScratch[p_i] > m_tempoScratch[p_j])
297 {
298 beatPeriod = p_i;
299 }
300
301 // now write the output
302 maxIndexRCF = static_cast<int>(beatPeriod);
303
304 }
305
171 306
172 double locked = 5168.f / maxIndexRCF; 307 double locked = 5168.f / maxIndexRCF;
173 if (locked >= 30 && locked <= 180) { 308 if (locked >= 30 && locked <= 180) {
174 m_lockedTempo = locked; 309 m_lockedTempo = locked;
175 } 310 }
406 } 541 }
407 542
408 if( lastBeat != 0 ) 543 if( lastBeat != 0 )
409 { 544 {
410 int mu = p; 545 int mu = p;
411 double sigma = (double)p/4; 546 double sigma = (double)p/8;
412 double PhaseMin = 0.0; 547 double PhaseMin = 0.0;
413 double PhaseMax = 0.0; 548 double PhaseMax = 0.0;
414 unsigned int scratchLength = p*2; 549 unsigned int scratchLength = p*2;
415 double temp = 0.0; 550 double temp = 0.0;
416 551
455 double* align = new double[ p ]; 590 double* align = new double[ p ];
456 591
457 for( int i = 0; i < winLength; i++ ) 592 for( int i = 0; i < winLength; i++ )
458 { 593 {
459 y[ i ] = (double)( -i + winLength )/(double)winLength; 594 y[ i ] = (double)( -i + winLength )/(double)winLength;
595 y[ i ] = pow(y [i ],2.0); // raise to power 2.
460 } 596 }
461 597
462 for( int o = 0; o < p; o++ ) 598 for( int o = 0; o < p; o++ )
463 { 599 {
464 temp = 0.0; 600 temp = 0.0;
594 730
595 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig ); 731 periodG[ TTLoopIndex ] = tempoMM( m_frameACF, GW, tsig );
596 732
597 period = periodG[ TTLoopIndex ]; 733 period = periodG[ TTLoopIndex ];
598 734
599 createPhaseExtractor( PW, m_winLength, period, FSP, 0 ); 735 // am temporarily changing the last input parameter to lastBeat instead of '0'
736 createPhaseExtractor( PW, m_winLength, period, FSP, lastBeat );
600 737
601 constFlag = 0; 738 constFlag = 0;
602 739
603 } 740 }
604 else 741 else