comparison src/BTrack.cpp @ 72:f4d9410f187e

flow: Merged <release> '1.0.0' to <master> ('master').
author Adam Stark <adamstark@users.noreply.github.com>
date Tue, 08 Jul 2014 12:32:27 +0100
parents b387d8327729
children 866024f9f95a
comparison
equal deleted inserted replaced
44:3049937d6ef1 72:f4d9410f187e
17 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */ 19 */
20 //======================================================================= 20 //=======================================================================
21 21
22 #include <iostream>
23 #include <cmath> 22 #include <cmath>
23 #include <algorithm>
24 #include "BTrack.h" 24 #include "BTrack.h"
25 #include "samplerate.h" 25 #include "samplerate.h"
26 using namespace std; 26
27 27 //=======================================================================
28 28 BTrack::BTrack() : odf(512,1024,ComplexSpectralDifferenceHWR,HanningWindow)
29 29 {
30 30 initialise(512, 1024);
31 //------------------------------------------------------------------------------- 31 }
32 // Constructor 32
33 BTrack :: BTrack() 33 //=======================================================================
34 BTrack::BTrack(int hopSize_) : odf(hopSize_,2*hopSize_,ComplexSpectralDifferenceHWR,HanningWindow)
34 { 35 {
35 float rayparam = 43; 36 initialise(hopSize_, 2*hopSize_);
36 float pi = 3.14159265; 37 }
38
39 //=======================================================================
40 BTrack::BTrack(int hopSize_,int frameSize_) : odf(hopSize_,frameSize_,ComplexSpectralDifferenceHWR,HanningWindow)
41 {
42 initialise(hopSize_, frameSize_);
43 }
44
45 //=======================================================================
46 double BTrack::getBeatTimeInSeconds(long frameNumber,int hopSize,int fs)
47 {
48 double hop = (double) hopSize;
49 double samplingFrequency = (double) fs;
50 double frameNum = (double) frameNumber;
51
52 return ((hop / samplingFrequency) * frameNum);
53 }
54
55 //=======================================================================
56 double BTrack::getBeatTimeInSeconds(int frameNumber,int hopSize,int fs)
57 {
58 long frameNum = (long) frameNumber;
59
60 return getBeatTimeInSeconds(frameNum, hopSize, fs);
61 }
62
63
64
65 //=======================================================================
66 void BTrack::initialise(int hopSize_, int frameSize_)
67 {
68 double rayparam = 43;
69 double pi = 3.14159265;
37 70
38 71
39 // initialise parameters 72 // initialise parameters
40 tightness = 5; 73 tightness = 5;
41 alpha = 0.9; 74 alpha = 0.9;
42 tempo = 120; 75 tempo = 120;
43 est_tempo = 120; 76 estimatedTempo = 120.0;
44 p_fact = 60.*44100./512.; 77 tempoToLagFactor = 60.*44100./512.;
45 78
46 m0 = 10; 79 m0 = 10;
47 beat = -1; 80 beatCounter = -1;
48 81
49 playbeat = 0; 82 beatDueInFrame = false;
50 83
51 84
52
53
54 // create rayleigh weighting vector 85 // create rayleigh weighting vector
55 for (int n = 0;n < 128;n++) 86 for (int n = 0;n < 128;n++)
56 { 87 {
57 wv[n] = ((float) n / pow(rayparam,2)) * exp((-1*pow((float)-n,2)) / (2*pow(rayparam,2))); 88 weightingVector[n] = ((double) n / pow(rayparam,2)) * exp((-1*pow((double)-n,2)) / (2*pow(rayparam,2)));
58 } 89 }
59 90
60 // initialise prev_delta 91 // initialise prev_delta
61 for (int i = 0;i < 41;i++) 92 for (int i = 0;i < 41;i++)
62 { 93 {
63 prev_delta[i] = 1; 94 prevDelta[i] = 1;
64 } 95 }
65 96
66 float t_mu = 41/2; 97 double t_mu = 41/2;
67 float m_sig; 98 double m_sig;
68 float x; 99 double x;
69 // create tempo transition matrix 100 // create tempo transition matrix
70 m_sig = 41/8; 101 m_sig = 41/8;
71 for (int i = 0;i < 41;i++) 102 for (int i = 0;i < 41;i++)
72 { 103 {
73 for (int j = 0;j < 41;j++) 104 for (int j = 0;j < 41;j++)
74 { 105 {
75 x = j+1; 106 x = j+1;
76 t_mu = i+1; 107 t_mu = i+1;
77 t_tmat[i][j] = (1 / (m_sig * sqrt(2*pi))) * exp( (-1*pow((x-t_mu),2)) / (2*pow(m_sig,2)) ); 108 tempoTransitionMatrix[i][j] = (1 / (m_sig * sqrt(2*pi))) * exp( (-1*pow((x-t_mu),2)) / (2*pow(m_sig,2)) );
78 } 109 }
79 } 110 }
80 111
81 // tempo is not fixed 112 // tempo is not fixed
82 tempofix = 0; 113 tempoFixed = false;
83 } 114
84 115 // initialise latest cumulative score value
85 //------------------------------------------------------------------------------- 116 // in case it is requested before any processing takes place
86 // Destructor 117 latestCumulativeScoreValue = 0;
87 BTrack :: ~BTrack() 118
119 // initialise algorithm given the hopsize
120 setHopSize(hopSize_);
121 }
122
123 //=======================================================================
124 void BTrack::setHopSize(int hopSize_)
88 { 125 {
89 126 hopSize = hopSize_;
90 } 127 onsetDFBufferSize = (512*512)/hopSize; // calculate df buffer size
91 128
92 //------------------------------------------------------------------------------- 129 beatPeriod = round(60/((((double) hopSize)/44100)*tempo));
93 // Initialise with frame size and set all frame sizes accordingly 130
94 void BTrack :: initialise(int fsize) 131 // set size of onset detection function buffer
95 { 132 onsetDF.resize(onsetDFBufferSize);
96 framesize = fsize; 133
97 dfbuffer_size = (512*512)/fsize; // calculate df buffer size 134 // set size of cumulative score buffer
98 135 cumulativeScore.resize(onsetDFBufferSize);
99 bperiod = round(60/((((float) fsize)/44100)*tempo));
100
101 dfbuffer = new float[dfbuffer_size]; // create df_buffer
102 cumscore = new float[dfbuffer_size]; // create cumscore
103
104 136
105 // initialise df_buffer to zeros 137 // initialise df_buffer to zeros
106 for (int i = 0;i < dfbuffer_size;i++) 138 for (int i = 0;i < onsetDFBufferSize;i++)
107 { 139 {
108 dfbuffer[i] = 0; 140 onsetDF[i] = 0;
109 cumscore[i] = 0; 141 cumulativeScore[i] = 0;
110 142
111 143
112 if ((i % ((int) round(bperiod))) == 0) 144 if ((i % ((int) round(beatPeriod))) == 0)
113 { 145 {
114 dfbuffer[i] = 1; 146 onsetDF[i] = 1;
115 } 147 }
116 } 148 }
117 } 149 }
118 150
119 //------------------------------------------------------------------------------- 151 //=======================================================================
120 // Add new sample to buffer and apply beat tracking 152 void BTrack::updateHopAndFrameSize(int hopSize_,int frameSize_)
121 void BTrack :: process(float df_sample) 153 {
122 { 154 // update the onset detection function object
155 odf.initialise(hopSize_, frameSize_);
156
157 // update the hop size being used by the beat tracker
158 setHopSize(hopSize_);
159 }
160
161 //=======================================================================
162 bool BTrack::beatDueInCurrentFrame()
163 {
164 return beatDueInFrame;
165 }
166
167 //=======================================================================
168 int BTrack::getHopSize()
169 {
170 return hopSize;
171 }
172
173 //=======================================================================
174 double BTrack::getLatestCumulativeScoreValue()
175 {
176 return latestCumulativeScoreValue;
177 }
178
179 //=======================================================================
180 void BTrack::processAudioFrame(double *frame)
181 {
182 // calculate the onset detection function sample for the frame
183 double sample = odf.calculateOnsetDetectionFunctionSample(frame);
184
185
186
187 // process the new onset detection function sample in the beat tracking algorithm
188 processOnsetDetectionFunctionSample(sample);
189 }
190
191 //=======================================================================
192 void BTrack::processOnsetDetectionFunctionSample(double newSample)
193 {
194 // we need to ensure that the onset
195 // detection function sample is positive
196 newSample = fabs(newSample);
197
198 // add a tiny constant to the sample to stop it from ever going
199 // to zero. this is to avoid problems further down the line
200 newSample = newSample + 0.0001;
201
123 m0--; 202 m0--;
124 beat--; 203 beatCounter--;
125 playbeat = 0; 204 beatDueInFrame = false;
126 205
127 // move all samples back one step 206 // move all samples back one step
128 for (int i=0;i < (dfbuffer_size-1);i++) 207 for (int i=0;i < (onsetDFBufferSize-1);i++)
129 { 208 {
130 dfbuffer[i] = dfbuffer[i+1]; 209 onsetDF[i] = onsetDF[i+1];
131 } 210 }
132 211
133 // add new sample at the end 212 // add new sample at the end
134 dfbuffer[dfbuffer_size-1] = df_sample; 213 onsetDF[onsetDFBufferSize-1] = newSample;
135 214
136 // update cumulative score 215 // update cumulative score
137 updatecumscore(df_sample); 216 updateCumulativeScore(newSample);
138 217
139 // if we are halfway between beats 218 // if we are halfway between beats
140 if (m0 == 0) 219 if (m0 == 0)
141 { 220 {
142 predictbeat(); 221 predictBeat();
143 } 222 }
144 223
145 // if we are at a beat 224 // if we are at a beat
146 if (beat == 0) 225 if (beatCounter == 0)
147 { 226 {
148 playbeat = 1; // indicate a beat should be output 227 beatDueInFrame = true; // indicate a beat should be output
149 228
150 // recalculate the tempo 229 // recalculate the tempo
151 dfconvert(); 230 resampleOnsetDetectionFunction();
152 calcTempo(); 231 calculateTempo();
153 } 232 }
154 } 233 }
155 234
156 //------------------------------------------------------------------------------- 235 //=======================================================================
157 // Set the tempo of the beat tracker 236 void BTrack::setTempo(double tempo)
158 void BTrack :: settempo(float tempo)
159 { 237 {
160 238
161 /////////// TEMPO INDICATION RESET ////////////////// 239 /////////// TEMPO INDICATION RESET //////////////////
162 240
163 // firstly make sure tempo is between 80 and 160 bpm.. 241 // firstly make sure tempo is between 80 and 160 bpm..
175 int tempo_index = (int) round((tempo - 80)/2); 253 int tempo_index = (int) round((tempo - 80)/2);
176 254
177 // now set previous tempo observations to zero 255 // now set previous tempo observations to zero
178 for (int i=0;i < 41;i++) 256 for (int i=0;i < 41;i++)
179 { 257 {
180 prev_delta[i] = 0; 258 prevDelta[i] = 0;
181 } 259 }
182 260
183 // set desired tempo index to 1 261 // set desired tempo index to 1
184 prev_delta[tempo_index] = 1; 262 prevDelta[tempo_index] = 1;
185 263
186 264
187 /////////// CUMULATIVE SCORE ARTIFICAL TEMPO UPDATE ////////////////// 265 /////////// CUMULATIVE SCORE ARTIFICAL TEMPO UPDATE //////////////////
188 266
189 // calculate new beat period 267 // calculate new beat period
190 int new_bperiod = (int) round(60/((((float) framesize)/44100)*tempo)); 268 int new_bperiod = (int) round(60/((((double) hopSize)/44100)*tempo));
191 269
192 int bcounter = 1; 270 int bcounter = 1;
193 // initialise df_buffer to zeros 271 // initialise df_buffer to zeros
194 for (int i = (dfbuffer_size-1);i >= 0;i--) 272 for (int i = (onsetDFBufferSize-1);i >= 0;i--)
195 { 273 {
196 if (bcounter == 1) 274 if (bcounter == 1)
197 { 275 {
198 cumscore[i] = 150; 276 cumulativeScore[i] = 150;
199 dfbuffer[i] = 150; 277 onsetDF[i] = 150;
200 } 278 }
201 else 279 else
202 { 280 {
203 cumscore[i] = 10; 281 cumulativeScore[i] = 10;
204 dfbuffer[i] = 10; 282 onsetDF[i] = 10;
205 } 283 }
206 284
207 bcounter++; 285 bcounter++;
208 286
209 if (bcounter > new_bperiod) 287 if (bcounter > new_bperiod)
213 } 291 }
214 292
215 /////////// INDICATE THAT THIS IS A BEAT ////////////////// 293 /////////// INDICATE THAT THIS IS A BEAT //////////////////
216 294
217 // beat is now 295 // beat is now
218 beat = 0; 296 beatCounter = 0;
219 297
220 // offbeat is half of new beat period away 298 // offbeat is half of new beat period away
221 m0 = (int) round(((float) new_bperiod)/2); 299 m0 = (int) round(((double) new_bperiod)/2);
222 } 300 }
223 301
224 302 //=======================================================================
225 //------------------------------------------------------------------------------- 303 void BTrack::fixTempo(double tempo)
226 // fix tempo to roughly around some value
227 void BTrack :: fixtempo(float tempo)
228 { 304 {
229 // firstly make sure tempo is between 80 and 160 bpm.. 305 // firstly make sure tempo is between 80 and 160 bpm..
230 while (tempo > 160) 306 while (tempo > 160)
231 { 307 {
232 tempo = tempo/2; 308 tempo = tempo/2;
241 int tempo_index = (int) round((tempo - 80)/2); 317 int tempo_index = (int) round((tempo - 80)/2);
242 318
243 // now set previous fixed previous tempo observation values to zero 319 // now set previous fixed previous tempo observation values to zero
244 for (int i=0;i < 41;i++) 320 for (int i=0;i < 41;i++)
245 { 321 {
246 prev_delta_fix[i] = 0; 322 prevDeltaFixed[i] = 0;
247 } 323 }
248 324
249 // set desired tempo index to 1 325 // set desired tempo index to 1
250 prev_delta_fix[tempo_index] = 1; 326 prevDeltaFixed[tempo_index] = 1;
251 327
252 // set the tempo fix flag 328 // set the tempo fix flag
253 tempofix = 1; 329 tempoFixed = true;
254 } 330 }
255 331
256 //------------------------------------------------------------------------------- 332 //=======================================================================
257 // do not fix the tempo anymore 333 void BTrack::doNotFixTempo()
258 void BTrack :: unfixtempo()
259 { 334 {
260 // set the tempo fix flag 335 // set the tempo fix flag
261 tempofix = 0; 336 tempoFixed = false;
262 } 337 }
263 338
264 //------------------------------------------------------------------------------- 339 //=======================================================================
265 // Convert detection function from N samples to 512 340 void BTrack::resampleOnsetDetectionFunction()
266 void BTrack :: dfconvert()
267 { 341 {
268 float output[512]; 342 float output[512];
269 343 float input[onsetDFBufferSize];
270 double src_ratio = 512.0/((double) dfbuffer_size); 344
271 int BUFFER_LEN = dfbuffer_size; 345 for (int i = 0;i < onsetDFBufferSize;i++)
346 {
347 input[i] = (float) onsetDF[i];
348 }
349
350 double src_ratio = 512.0/((double) onsetDFBufferSize);
351 int BUFFER_LEN = onsetDFBufferSize;
272 int output_len; 352 int output_len;
273 SRC_DATA src_data ; 353 SRC_DATA src_data ;
274 354
275 //output_len = (int) floor (((double) BUFFER_LEN) * src_ratio) ; 355 //output_len = (int) floor (((double) BUFFER_LEN) * src_ratio) ;
276 output_len = 512; 356 output_len = 512;
277 357
278 src_data.data_in = dfbuffer; 358 src_data.data_in = input;
279 src_data.input_frames = BUFFER_LEN; 359 src_data.input_frames = BUFFER_LEN;
280 360
281 src_data.src_ratio = src_ratio; 361 src_data.src_ratio = src_ratio;
282 362
283 src_data.data_out = output; 363 src_data.data_out = output;
285 365
286 src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1); 366 src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
287 367
288 for (int i = 0;i < output_len;i++) 368 for (int i = 0;i < output_len;i++)
289 { 369 {
290 df512[i] = src_data.data_out[i]; 370 resampledOnsetDF[i] = (double) src_data.data_out[i];
291 } 371 }
292 } 372 }
293 373
294 //------------------------------------------------------------------------------- 374 //=======================================================================
295 // To calculate the current tempo expressed as the beat period in detection function samples 375 void BTrack::calculateTempo()
296 void BTrack :: calcTempo()
297 { 376 {
298 // adaptive threshold on input 377 // adaptive threshold on input
299 adapt_thresh(df512,512); 378 adaptiveThreshold(resampledOnsetDF,512);
300 379
301 // calculate auto-correlation function of detection function 380 // calculate auto-correlation function of detection function
302 acf_bal(df512); 381 calculateBalancedACF(resampledOnsetDF);
303 382
304 // calculate output of comb filterbank 383 // calculate output of comb filterbank
305 getrcfoutput(); 384 calculateOutputOfCombFilterBank();
306 385
307 386
308 // adaptive threshold on rcf 387 // adaptive threshold on rcf
309 adapt_thresh(rcf,128); 388 adaptiveThreshold(combFilterBankOutput,128);
310 389
311 390
312 int t_index; 391 int t_index;
313 int t_index2; 392 int t_index2;
314 // calculate tempo observation vector from bperiod observation vector 393 // calculate tempo observation vector from beat period observation vector
315 for (int i = 0;i < 41;i++) 394 for (int i = 0;i < 41;i++)
316 { 395 {
317 t_index = (int) round(p_fact / ((float) ((2*i)+80))); 396 t_index = (int) round(tempoToLagFactor / ((double) ((2*i)+80)));
318 t_index2 = (int) round(p_fact / ((float) ((4*i)+160))); 397 t_index2 = (int) round(tempoToLagFactor / ((double) ((4*i)+160)));
319 398
320 399
321 t_obs[i] = rcf[t_index-1] + rcf[t_index2-1]; 400 tempoObservationVector[i] = combFilterBankOutput[t_index-1] + combFilterBankOutput[t_index2-1];
322 } 401 }
323 402
324 403
325 float maxval; 404 double maxval;
326 float maxind; 405 double maxind;
327 float curval; 406 double curval;
328 407
329 // if tempo is fixed then always use a fixed set of tempi as the previous observation probability function 408 // if tempo is fixed then always use a fixed set of tempi as the previous observation probability function
330 if (tempofix == 1) 409 if (tempoFixed)
331 { 410 {
332 for (int k = 0;k < 41;k++) 411 for (int k = 0;k < 41;k++)
333 { 412 {
334 prev_delta[k] = prev_delta_fix[k]; 413 prevDelta[k] = prevDeltaFixed[k];
335 } 414 }
336 } 415 }
337 416
338 for (int j=0;j < 41;j++) 417 for (int j=0;j < 41;j++)
339 { 418 {
340 maxval = -1; 419 maxval = -1;
341 for (int i = 0;i < 41;i++) 420 for (int i = 0;i < 41;i++)
342 { 421 {
343 curval = prev_delta[i]*t_tmat[i][j]; 422 curval = prevDelta[i]*tempoTransitionMatrix[i][j];
344 423
345 if (curval > maxval) 424 if (curval > maxval)
346 { 425 {
347 maxval = curval; 426 maxval = curval;
348 } 427 }
349 } 428 }
350 429
351 delta[j] = maxval*t_obs[j]; 430 delta[j] = maxval*tempoObservationVector[j];
352 } 431 }
353 432
354 433
355 normalise(delta,41); 434 normaliseArray(delta,41);
356 435
357 maxind = -1; 436 maxind = -1;
358 maxval = -1; 437 maxval = -1;
359 438
360 for (int j=0;j < 41;j++) 439 for (int j=0;j < 41;j++)
363 { 442 {
364 maxval = delta[j]; 443 maxval = delta[j];
365 maxind = j; 444 maxind = j;
366 } 445 }
367 446
368 prev_delta[j] = delta[j]; 447 prevDelta[j] = delta[j];
369 } 448 }
370 449
371 bperiod = round((60.0*44100.0)/(((2*maxind)+80)*((float) framesize))); 450 beatPeriod = round((60.0*44100.0)/(((2*maxind)+80)*((double) hopSize)));
372 451
373 if (bperiod > 0) 452 if (beatPeriod > 0)
374 { 453 {
375 est_tempo = 60.0/((((float) framesize) / 44100.0)*bperiod); 454 estimatedTempo = 60.0/((((double) hopSize) / 44100.0)*beatPeriod);
376 } 455 }
377 456 }
378 //cout << bperiod << endl; 457
379 } 458 //=======================================================================
380 459 void BTrack::adaptiveThreshold(double *x,int N)
381 //------------------------------------------------------------------------------- 460 {
382 // calculates an adaptive threshold which is used to remove low level energy from detection function and emphasise peaks
383 void BTrack :: adapt_thresh(float x[],int N)
384 {
385 //int N = 512; // length of df
386 int i = 0; 461 int i = 0;
387 int k,t = 0; 462 int k,t = 0;
388 float x_thresh[N]; 463 double x_thresh[N];
389 464
390 int p_post = 7; 465 int p_post = 7;
391 int p_pre = 8; 466 int p_pre = 8;
392 467
393 t = min(N,p_post); // what is smaller, p_post of df size. This is to avoid accessing outside of arrays 468 t = std::min(N,p_post); // what is smaller, p_post of df size. This is to avoid accessing outside of arrays
394 469
395 // find threshold for first 't' samples, where a full average cannot be computed yet 470 // find threshold for first 't' samples, where a full average cannot be computed yet
396 for (i = 0;i <= t;i++) 471 for (i = 0;i <= t;i++)
397 { 472 {
398 k = min((i+p_pre),N); 473 k = std::min((i+p_pre),N);
399 x_thresh[i] = mean_array(x,1,k); 474 x_thresh[i] = calculateMeanOfArray(x,1,k);
400 } 475 }
401 // find threshold for bulk of samples across a moving average from [i-p_pre,i+p_post] 476 // find threshold for bulk of samples across a moving average from [i-p_pre,i+p_post]
402 for (i = t+1;i < N-p_post;i++) 477 for (i = t+1;i < N-p_post;i++)
403 { 478 {
404 x_thresh[i] = mean_array(x,i-p_pre,i+p_post); 479 x_thresh[i] = calculateMeanOfArray(x,i-p_pre,i+p_post);
405 } 480 }
406 // for last few samples calculate threshold, again, not enough samples to do as above 481 // for last few samples calculate threshold, again, not enough samples to do as above
407 for (i = N-p_post;i < N;i++) 482 for (i = N-p_post;i < N;i++)
408 { 483 {
409 k = max((i-p_post),1); 484 k = std::max((i-p_post),1);
410 x_thresh[i] = mean_array(x,k,N); 485 x_thresh[i] = calculateMeanOfArray(x,k,N);
411 } 486 }
412 487
413 // subtract the threshold from the detection function and check that it is not less than 0 488 // subtract the threshold from the detection function and check that it is not less than 0
414 for (i = 0;i < N;i++) 489 for (i = 0;i < N;i++)
415 { 490 {
419 x[i] = 0; 494 x[i] = 0;
420 } 495 }
421 } 496 }
422 } 497 }
423 498
424 //------------------------------------------------------------------------------- 499 //=======================================================================
425 // returns the output of the comb filter 500 void BTrack::calculateOutputOfCombFilterBank()
426 void BTrack :: getrcfoutput()
427 { 501 {
428 int numelem; 502 int numelem;
429 503
430 for (int i = 0;i < 128;i++) 504 for (int i = 0;i < 128;i++)
431 { 505 {
432 rcf[i] = 0; 506 combFilterBankOutput[i] = 0;
433 } 507 }
434 508
435 numelem = 4; 509 numelem = 4;
436 510
437 for (int i = 2;i <= 127;i++) // max beat period 511 for (int i = 2;i <= 127;i++) // max beat period
438 { 512 {
439 for (int a = 1;a <= numelem;a++) // number of comb elements 513 for (int a = 1;a <= numelem;a++) // number of comb elements
440 { 514 {
441 for (int b = 1-a;b <= a-1;b++) // general state using normalisation of comb elements 515 for (int b = 1-a;b <= a-1;b++) // general state using normalisation of comb elements
442 { 516 {
443 rcf[i-1] = rcf[i-1] + (acf[(a*i+b)-1]*wv[i-1])/(2*a-1); // calculate value for comb filter row 517 combFilterBankOutput[i-1] = combFilterBankOutput[i-1] + (acf[(a*i+b)-1]*weightingVector[i-1])/(2*a-1); // calculate value for comb filter row
444 } 518 }
445 } 519 }
446 } 520 }
447 } 521 }
448 522
449 //------------------------------------------------------------------------------- 523 //=======================================================================
450 // calculates the balanced autocorrelation of the smoothed detection function 524 void BTrack::calculateBalancedACF(double *onsetDetectionFunction)
451 void BTrack :: acf_bal(float df_thresh[])
452 { 525 {
453 int l, n = 0; 526 int l, n = 0;
454 float sum, tmp; 527 double sum, tmp;
455 528
456 // for l lags from 0-511 529 // for l lags from 0-511
457 for (l = 0;l < 512;l++) 530 for (l = 0;l < 512;l++)
458 { 531 {
459 sum = 0; 532 sum = 0;
460 533
461 // for n samples from 0 - (512-lag) 534 // for n samples from 0 - (512-lag)
462 for (n = 0;n < (512-l);n++) 535 for (n = 0;n < (512-l);n++)
463 { 536 {
464 tmp = df_thresh[n] * df_thresh[n+l]; // multiply current sample n by sample (n+l) 537 tmp = onsetDetectionFunction[n] * onsetDetectionFunction[n+l]; // multiply current sample n by sample (n+l)
465 sum = sum + tmp; // add to sum 538 sum = sum + tmp; // add to sum
466 } 539 }
467 540
468 acf[l] = sum / (512-l); // weight by number of mults and add to acf buffer 541 acf[l] = sum / (512-l); // weight by number of mults and add to acf buffer
469 } 542 }
470 } 543 }
471 544
472 545 //=======================================================================
473 //------------------------------------------------------------------------------- 546 double BTrack::calculateMeanOfArray(double *array,int startIndex,int endIndex)
474 // calculates the mean of values in an array from index locations [start,end]
475 float BTrack :: mean_array(float array[],int start,int end)
476 { 547 {
477 int i; 548 int i;
478 double sum = 0; 549 double sum = 0;
479 550
480 int length = end - start; 551 int length = endIndex - startIndex;
481 552
482 // find sum 553 // find sum
483 for (i = start;i < end;i++) 554 for (i = startIndex;i < endIndex;i++)
484 { 555 {
485 sum = sum + array[i]; 556 sum = sum + array[i];
486 } 557 }
487 558
488 if (length > 0) 559 if (length > 0)
493 { 564 {
494 return 0; 565 return 0;
495 } 566 }
496 } 567 }
497 568
498 //------------------------------------------------------------------------------- 569 //=======================================================================
499 // normalise the array 570 void BTrack::normaliseArray(double *array,int N)
500 void BTrack :: normalise(float array[],int N)
501 { 571 {
502 double sum = 0; 572 double sum = 0;
503 573
504 for (int i = 0;i < N;i++) 574 for (int i = 0;i < N;i++)
505 { 575 {
516 array[i] = array[i] / sum; 586 array[i] = array[i] / sum;
517 } 587 }
518 } 588 }
519 } 589 }
520 590
521 //------------------------------------------------------------------------------- 591 //=======================================================================
522 // plot contents of detection function buffer 592 void BTrack::updateCumulativeScore(double odfSample)
523 void BTrack :: plotdfbuffer()
524 {
525 for (int i=0;i < dfbuffer_size;i++)
526 {
527 cout << dfbuffer[i] << endl;
528 }
529
530 cout << "--------------------------------" << endl;
531 }
532
533 //-------------------------------------------------------------------------------
534 // update the cumulative score
535 void BTrack :: updatecumscore(float df_sample)
536 { 593 {
537 int start, end, winsize; 594 int start, end, winsize;
538 float max; 595 double max;
539 596
540 start = dfbuffer_size - round(2*bperiod); 597 start = onsetDFBufferSize - round(2*beatPeriod);
541 end = dfbuffer_size - round(bperiod/2); 598 end = onsetDFBufferSize - round(beatPeriod/2);
542 winsize = end-start+1; 599 winsize = end-start+1;
543 600
544 float w1[winsize]; 601 double w1[winsize];
545 float v = -2*bperiod; 602 double v = -2*beatPeriod;
546 float wcumscore; 603 double wcumscore;
547 604
548 605
549 // create window 606 // create window
550 for (int i = 0;i < winsize;i++) 607 for (int i = 0;i < winsize;i++)
551 { 608 {
552 w1[i] = exp((-1*pow(tightness*log(-v/bperiod),2))/2); 609 w1[i] = exp((-1*pow(tightness*log(-v/beatPeriod),2))/2);
553 v = v+1; 610 v = v+1;
554 } 611 }
555 612
556 // calculate new cumulative score value 613 // calculate new cumulative score value
557 max = 0; 614 max = 0;
558 int n = 0; 615 int n = 0;
559 for (int i=start;i <= end;i++) 616 for (int i=start;i <= end;i++)
560 { 617 {
561 wcumscore = cumscore[i]*w1[n]; 618 wcumscore = cumulativeScore[i]*w1[n];
562 619
563 if (wcumscore > max) 620 if (wcumscore > max)
564 { 621 {
565 max = wcumscore; 622 max = wcumscore;
566 } 623 }
567 n++; 624 n++;
568 } 625 }
569 626
570 627
571 // shift cumulative score back one 628 // shift cumulative score back one
572 for (int i = 0;i < (dfbuffer_size-1);i++) 629 for (int i = 0;i < (onsetDFBufferSize-1);i++)
573 { 630 {
574 cumscore[i] = cumscore[i+1]; 631 cumulativeScore[i] = cumulativeScore[i+1];
575 } 632 }
576 633
577 // add new value to cumulative score 634 // add new value to cumulative score
578 cumscore[dfbuffer_size-1] = ((1-alpha)*df_sample) + (alpha*max); 635 cumulativeScore[onsetDFBufferSize-1] = ((1-alpha)*odfSample) + (alpha*max);
579 636
580 cscoreval = cumscore[dfbuffer_size-1]; 637 latestCumulativeScoreValue = cumulativeScore[onsetDFBufferSize-1];
581 638
582 //cout << cumscore[dfbuffer_size-1] << endl; 639 }
583 640
584 } 641 //=======================================================================
585 642 void BTrack::predictBeat()
586 //-------------------------------------------------------------------------------
587 // plot contents of detection function buffer
588 void BTrack :: predictbeat()
589 { 643 {
590 int winsize = (int) bperiod; 644 int windowSize = (int) beatPeriod;
591 float fcumscore[dfbuffer_size + winsize]; 645 double futureCumulativeScore[onsetDFBufferSize + windowSize];
592 float w2[winsize]; 646 double w2[windowSize];
593 // copy cumscore to first part of fcumscore 647 // copy cumscore to first part of fcumscore
594 for (int i = 0;i < dfbuffer_size;i++) 648 for (int i = 0;i < onsetDFBufferSize;i++)
595 { 649 {
596 fcumscore[i] = cumscore[i]; 650 futureCumulativeScore[i] = cumulativeScore[i];
597 } 651 }
598 652
599 // create future window 653 // create future window
600 float v = 1; 654 double v = 1;
601 for (int i = 0;i < winsize;i++) 655 for (int i = 0;i < windowSize;i++)
602 { 656 {
603 w2[i] = exp((-1*pow((v - (bperiod/2)),2)) / (2*pow((bperiod/2) ,2))); 657 w2[i] = exp((-1*pow((v - (beatPeriod/2)),2)) / (2*pow((beatPeriod/2) ,2)));
604 v++; 658 v++;
605 } 659 }
606 660
607 // create past window 661 // create past window
608 v = -2*bperiod; 662 v = -2*beatPeriod;
609 int start = dfbuffer_size - round(2*bperiod); 663 int start = onsetDFBufferSize - round(2*beatPeriod);
610 int end = dfbuffer_size - round(bperiod/2); 664 int end = onsetDFBufferSize - round(beatPeriod/2);
611 int pastwinsize = end-start+1; 665 int pastwinsize = end-start+1;
612 float w1[pastwinsize]; 666 double w1[pastwinsize];
613 667
614 for (int i = 0;i < pastwinsize;i++) 668 for (int i = 0;i < pastwinsize;i++)
615 { 669 {
616 w1[i] = exp((-1*pow(tightness*log(-v/bperiod),2))/2); 670 w1[i] = exp((-1*pow(tightness*log(-v/beatPeriod),2))/2);
617 v = v+1; 671 v = v+1;
618 } 672 }
619 673
620 674
621 675
622 // calculate future cumulative score 676 // calculate future cumulative score
623 float max; 677 double max;
624 int n; 678 int n;
625 float wcumscore; 679 double wcumscore;
626 for (int i = dfbuffer_size;i < (dfbuffer_size+winsize);i++) 680 for (int i = onsetDFBufferSize;i < (onsetDFBufferSize+windowSize);i++)
627 { 681 {
628 start = i - round(2*bperiod); 682 start = i - round(2*beatPeriod);
629 end = i - round(bperiod/2); 683 end = i - round(beatPeriod/2);
630 684
631 max = 0; 685 max = 0;
632 n = 0; 686 n = 0;
633 for (int k=start;k <= end;k++) 687 for (int k=start;k <= end;k++)
634 { 688 {
635 wcumscore = fcumscore[k]*w1[n]; 689 wcumscore = futureCumulativeScore[k]*w1[n];
636 690
637 if (wcumscore > max) 691 if (wcumscore > max)
638 { 692 {
639 max = wcumscore; 693 max = wcumscore;
640 } 694 }
641 n++; 695 n++;
642 } 696 }
643 697
644 fcumscore[i] = max; 698 futureCumulativeScore[i] = max;
645 } 699 }
646 700
647 701
648 // predict beat 702 // predict beat
649 max = 0; 703 max = 0;
650 n = 0; 704 n = 0;
651 705
652 for (int i = dfbuffer_size;i < (dfbuffer_size+winsize);i++) 706 for (int i = onsetDFBufferSize;i < (onsetDFBufferSize+windowSize);i++)
653 { 707 {
654 wcumscore = fcumscore[i]*w2[n]; 708 wcumscore = futureCumulativeScore[i]*w2[n];
655 709
656 if (wcumscore > max) 710 if (wcumscore > max)
657 { 711 {
658 max = wcumscore; 712 max = wcumscore;
659 beat = n; 713 beatCounter = n;
660 } 714 }
661 715
662 n++; 716 n++;
663 } 717 }
664 718
665
666 // set beat
667 beat = beat;
668
669 // set next prediction time 719 // set next prediction time
670 m0 = beat+round(bperiod/2); 720 m0 = beatCounter+round(beatPeriod/2);
671 721
672 722
673 } 723 }