Mercurial > hg > qm-dsp
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; |