comparison src/BTrack.cpp @ 21:ef4721e7466c develop

Did more renaming of obscurely named variables and added a couple of accessor methods
author Adam <adamstark.uk@gmail.com>
date Thu, 23 Jan 2014 18:00:53 +0000
parents baf35f208814
children a8e3e95d14e4
comparison
equal deleted inserted replaced
20:baf35f208814 21:ef4721e7466c
71 71
72 // initialise parameters 72 // initialise parameters
73 tightness = 5; 73 tightness = 5;
74 alpha = 0.9; 74 alpha = 0.9;
75 tempo = 120; 75 tempo = 120;
76 est_tempo = 120; 76 estimatedTempo = 120.0;
77 p_fact = 60.*44100./512.; 77 p_fact = 60.*44100./512.;
78 78
79 m0 = 10; 79 m0 = 10;
80 beat = -1; 80 beatCounter = -1;
81 81
82 beatDueInFrame = false; 82 beatDueInFrame = false;
83 83
84 84
85
86
87 // create rayleigh weighting vector 85 // create rayleigh weighting vector
88 for (int n = 0;n < 128;n++) 86 for (int n = 0;n < 128;n++)
89 { 87 {
90 wv[n] = ((double) n / pow(rayparam,2)) * exp((-1*pow((double)-n,2)) / (2*pow(rayparam,2))); 88 weightingVector[n] = ((double) n / pow(rayparam,2)) * exp((-1*pow((double)-n,2)) / (2*pow(rayparam,2)));
91 } 89 }
92 90
93 // initialise prev_delta 91 // initialise prev_delta
94 for (int i = 0;i < 41;i++) 92 for (int i = 0;i < 41;i++)
95 { 93 {
96 prev_delta[i] = 1; 94 prevDelta[i] = 1;
97 } 95 }
98 96
99 double t_mu = 41/2; 97 double t_mu = 41/2;
100 double m_sig; 98 double m_sig;
101 double x; 99 double x;
105 { 103 {
106 for (int j = 0;j < 41;j++) 104 for (int j = 0;j < 41;j++)
107 { 105 {
108 x = j+1; 106 x = j+1;
109 t_mu = i+1; 107 t_mu = i+1;
110 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)) );
111 } 109 }
112 } 110 }
113 111
114 // tempo is not fixed 112 // tempo is not fixed
115 tempofix = 0; 113 tempoFixed = false;
114
115 // initialise latest cumulative score value
116 // in case it is requested before any processing takes place
117 latestCumulativeScoreValue = 0;
116 118
117 // initialise algorithm given the hopsize 119 // initialise algorithm given the hopsize
118 setHopSize(hopSize_); 120 setHopSize(hopSize_);
119 } 121 }
120 122
121 //======================================================================= 123 //=======================================================================
122 void BTrack::setHopSize(int hopSize_) 124 void BTrack::setHopSize(int hopSize_)
123 { 125 {
124 hopSize = hopSize_; 126 hopSize = hopSize_;
125 dfbuffer_size = (512*512)/hopSize; // calculate df buffer size 127 onsetDFBufferSize = (512*512)/hopSize; // calculate df buffer size
126 128
127 beatPeriod = round(60/((((double) hopSize)/44100)*tempo)); 129 beatPeriod = round(60/((((double) hopSize)/44100)*tempo));
128 130
129 dfbuffer = new double[dfbuffer_size]; // create df_buffer 131 onsetDF = new double[onsetDFBufferSize]; // create df_buffer
130 cumscore = new double[dfbuffer_size]; // create cumscore 132 cumulativeScore = new double[onsetDFBufferSize]; // create cumscore
131 133
132 134
133 // initialise df_buffer to zeros 135 // initialise df_buffer to zeros
134 for (int i = 0;i < dfbuffer_size;i++) 136 for (int i = 0;i < onsetDFBufferSize;i++)
135 { 137 {
136 dfbuffer[i] = 0; 138 onsetDF[i] = 0;
137 cumscore[i] = 0; 139 cumulativeScore[i] = 0;
138 140
139 141
140 if ((i % ((int) round(beatPeriod))) == 0) 142 if ((i % ((int) round(beatPeriod))) == 0)
141 { 143 {
142 dfbuffer[i] = 1; 144 onsetDF[i] = 1;
143 } 145 }
144 } 146 }
145 } 147 }
146 148
147 //======================================================================= 149 //=======================================================================
152 154
153 //======================================================================= 155 //=======================================================================
154 int BTrack::getHopSize() 156 int BTrack::getHopSize()
155 { 157 {
156 return hopSize; 158 return hopSize;
159 }
160
161 //=======================================================================
162 double BTrack::getLatestCumulativeScoreValue()
163 {
164 return latestCumulativeScoreValue;
157 } 165 }
158 166
159 //======================================================================= 167 //=======================================================================
160 void BTrack::processAudioFrame(double *frame) 168 void BTrack::processAudioFrame(double *frame)
161 { 169 {
178 // add a tiny constant to the sample to stop it from ever going 186 // add a tiny constant to the sample to stop it from ever going
179 // to zero. this is to avoid problems further down the line 187 // to zero. this is to avoid problems further down the line
180 newSample = newSample + 0.0001; 188 newSample = newSample + 0.0001;
181 189
182 m0--; 190 m0--;
183 beat--; 191 beatCounter--;
184 beatDueInFrame = false; 192 beatDueInFrame = false;
185 193
186 // move all samples back one step 194 // move all samples back one step
187 for (int i=0;i < (dfbuffer_size-1);i++) 195 for (int i=0;i < (onsetDFBufferSize-1);i++)
188 { 196 {
189 dfbuffer[i] = dfbuffer[i+1]; 197 onsetDF[i] = onsetDF[i+1];
190 } 198 }
191 199
192 // add new sample at the end 200 // add new sample at the end
193 dfbuffer[dfbuffer_size-1] = newSample; 201 onsetDF[onsetDFBufferSize-1] = newSample;
194 202
195 // update cumulative score 203 // update cumulative score
196 updateCumulativeScore(newSample); 204 updateCumulativeScore(newSample);
197 205
198 // if we are halfway between beats 206 // if we are halfway between beats
200 { 208 {
201 predictBeat(); 209 predictBeat();
202 } 210 }
203 211
204 // if we are at a beat 212 // if we are at a beat
205 if (beat == 0) 213 if (beatCounter == 0)
206 { 214 {
207 beatDueInFrame = true; // indicate a beat should be output 215 beatDueInFrame = true; // indicate a beat should be output
208 216
209 // recalculate the tempo 217 // recalculate the tempo
210 resampleOnsetDetectionFunction(); 218 resampleOnsetDetectionFunction();
233 int tempo_index = (int) round((tempo - 80)/2); 241 int tempo_index = (int) round((tempo - 80)/2);
234 242
235 // now set previous tempo observations to zero 243 // now set previous tempo observations to zero
236 for (int i=0;i < 41;i++) 244 for (int i=0;i < 41;i++)
237 { 245 {
238 prev_delta[i] = 0; 246 prevDelta[i] = 0;
239 } 247 }
240 248
241 // set desired tempo index to 1 249 // set desired tempo index to 1
242 prev_delta[tempo_index] = 1; 250 prevDelta[tempo_index] = 1;
243 251
244 252
245 /////////// CUMULATIVE SCORE ARTIFICAL TEMPO UPDATE ////////////////// 253 /////////// CUMULATIVE SCORE ARTIFICAL TEMPO UPDATE //////////////////
246 254
247 // calculate new beat period 255 // calculate new beat period
248 int new_bperiod = (int) round(60/((((double) hopSize)/44100)*tempo)); 256 int new_bperiod = (int) round(60/((((double) hopSize)/44100)*tempo));
249 257
250 int bcounter = 1; 258 int bcounter = 1;
251 // initialise df_buffer to zeros 259 // initialise df_buffer to zeros
252 for (int i = (dfbuffer_size-1);i >= 0;i--) 260 for (int i = (onsetDFBufferSize-1);i >= 0;i--)
253 { 261 {
254 if (bcounter == 1) 262 if (bcounter == 1)
255 { 263 {
256 cumscore[i] = 150; 264 cumulativeScore[i] = 150;
257 dfbuffer[i] = 150; 265 onsetDF[i] = 150;
258 } 266 }
259 else 267 else
260 { 268 {
261 cumscore[i] = 10; 269 cumulativeScore[i] = 10;
262 dfbuffer[i] = 10; 270 onsetDF[i] = 10;
263 } 271 }
264 272
265 bcounter++; 273 bcounter++;
266 274
267 if (bcounter > new_bperiod) 275 if (bcounter > new_bperiod)
271 } 279 }
272 280
273 /////////// INDICATE THAT THIS IS A BEAT ////////////////// 281 /////////// INDICATE THAT THIS IS A BEAT //////////////////
274 282
275 // beat is now 283 // beat is now
276 beat = 0; 284 beatCounter = 0;
277 285
278 // offbeat is half of new beat period away 286 // offbeat is half of new beat period away
279 m0 = (int) round(((double) new_bperiod)/2); 287 m0 = (int) round(((double) new_bperiod)/2);
280 } 288 }
281 289
297 int tempo_index = (int) round((tempo - 80)/2); 305 int tempo_index = (int) round((tempo - 80)/2);
298 306
299 // now set previous fixed previous tempo observation values to zero 307 // now set previous fixed previous tempo observation values to zero
300 for (int i=0;i < 41;i++) 308 for (int i=0;i < 41;i++)
301 { 309 {
302 prev_delta_fix[i] = 0; 310 prevDeltaFixed[i] = 0;
303 } 311 }
304 312
305 // set desired tempo index to 1 313 // set desired tempo index to 1
306 prev_delta_fix[tempo_index] = 1; 314 prevDeltaFixed[tempo_index] = 1;
307 315
308 // set the tempo fix flag 316 // set the tempo fix flag
309 tempofix = 1; 317 tempoFixed = true;
310 } 318 }
311 319
312 //======================================================================= 320 //=======================================================================
313 void BTrack::doNotFixTempo() 321 void BTrack::doNotFixTempo()
314 { 322 {
315 // set the tempo fix flag 323 // set the tempo fix flag
316 tempofix = 0; 324 tempoFixed = false;
317 } 325 }
318 326
319 //======================================================================= 327 //=======================================================================
320 void BTrack::resampleOnsetDetectionFunction() 328 void BTrack::resampleOnsetDetectionFunction()
321 { 329 {
322 float output[512]; 330 float output[512];
323 float input[dfbuffer_size]; 331 float input[onsetDFBufferSize];
324 332
325 for (int i = 0;i < dfbuffer_size;i++) 333 for (int i = 0;i < onsetDFBufferSize;i++)
326 { 334 {
327 input[i] = (float) dfbuffer[i]; 335 input[i] = (float) onsetDF[i];
328 } 336 }
329 337
330 double src_ratio = 512.0/((double) dfbuffer_size); 338 double src_ratio = 512.0/((double) onsetDFBufferSize);
331 int BUFFER_LEN = dfbuffer_size; 339 int BUFFER_LEN = onsetDFBufferSize;
332 int output_len; 340 int output_len;
333 SRC_DATA src_data ; 341 SRC_DATA src_data ;
334 342
335 //output_len = (int) floor (((double) BUFFER_LEN) * src_ratio) ; 343 //output_len = (int) floor (((double) BUFFER_LEN) * src_ratio) ;
336 output_len = 512; 344 output_len = 512;
345 353
346 src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1); 354 src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
347 355
348 for (int i = 0;i < output_len;i++) 356 for (int i = 0;i < output_len;i++)
349 { 357 {
350 df512[i] = (double) src_data.data_out[i]; 358 resampledOnsetDF[i] = (double) src_data.data_out[i];
351 } 359 }
352 } 360 }
353 361
354 //======================================================================= 362 //=======================================================================
355 void BTrack::calculateTempo() 363 void BTrack::calculateTempo()
356 { 364 {
357 // adaptive threshold on input 365 // adaptive threshold on input
358 adaptiveThreshold(df512,512); 366 adaptiveThreshold(resampledOnsetDF,512);
359 367
360 // calculate auto-correlation function of detection function 368 // calculate auto-correlation function of detection function
361 calculateBalancedACF(df512); 369 calculateBalancedACF(resampledOnsetDF);
362 370
363 // calculate output of comb filterbank 371 // calculate output of comb filterbank
364 calculateOutputOfCombFilterBank(); 372 calculateOutputOfCombFilterBank();
365 373
366 374
367 // adaptive threshold on rcf 375 // adaptive threshold on rcf
368 adaptiveThreshold(rcf,128); 376 adaptiveThreshold(combFilterBankOutput,128);
369 377
370 378
371 int t_index; 379 int t_index;
372 int t_index2; 380 int t_index2;
373 // calculate tempo observation vector from bperiod observation vector 381 // calculate tempo observation vector from bperiod observation vector
375 { 383 {
376 t_index = (int) round(p_fact / ((double) ((2*i)+80))); 384 t_index = (int) round(p_fact / ((double) ((2*i)+80)));
377 t_index2 = (int) round(p_fact / ((double) ((4*i)+160))); 385 t_index2 = (int) round(p_fact / ((double) ((4*i)+160)));
378 386
379 387
380 t_obs[i] = rcf[t_index-1] + rcf[t_index2-1]; 388 tempoObservationVector[i] = combFilterBankOutput[t_index-1] + combFilterBankOutput[t_index2-1];
381 } 389 }
382 390
383 391
384 double maxval; 392 double maxval;
385 double maxind; 393 double maxind;
386 double curval; 394 double curval;
387 395
388 // if tempo is fixed then always use a fixed set of tempi as the previous observation probability function 396 // if tempo is fixed then always use a fixed set of tempi as the previous observation probability function
389 if (tempofix == 1) 397 if (tempoFixed)
390 { 398 {
391 for (int k = 0;k < 41;k++) 399 for (int k = 0;k < 41;k++)
392 { 400 {
393 prev_delta[k] = prev_delta_fix[k]; 401 prevDelta[k] = prevDeltaFixed[k];
394 } 402 }
395 } 403 }
396 404
397 for (int j=0;j < 41;j++) 405 for (int j=0;j < 41;j++)
398 { 406 {
399 maxval = -1; 407 maxval = -1;
400 for (int i = 0;i < 41;i++) 408 for (int i = 0;i < 41;i++)
401 { 409 {
402 curval = prev_delta[i]*t_tmat[i][j]; 410 curval = prevDelta[i]*tempoTransitionMatrix[i][j];
403 411
404 if (curval > maxval) 412 if (curval > maxval)
405 { 413 {
406 maxval = curval; 414 maxval = curval;
407 } 415 }
408 } 416 }
409 417
410 delta[j] = maxval*t_obs[j]; 418 delta[j] = maxval*tempoObservationVector[j];
411 } 419 }
412 420
413 421
414 normaliseArray(delta,41); 422 normaliseArray(delta,41);
415 423
422 { 430 {
423 maxval = delta[j]; 431 maxval = delta[j];
424 maxind = j; 432 maxind = j;
425 } 433 }
426 434
427 prev_delta[j] = delta[j]; 435 prevDelta[j] = delta[j];
428 } 436 }
429 437
430 beatPeriod = round((60.0*44100.0)/(((2*maxind)+80)*((double) hopSize))); 438 beatPeriod = round((60.0*44100.0)/(((2*maxind)+80)*((double) hopSize)));
431 439
432 if (beatPeriod > 0) 440 if (beatPeriod > 0)
433 { 441 {
434 est_tempo = 60.0/((((double) hopSize) / 44100.0)*beatPeriod); 442 estimatedTempo = 60.0/((((double) hopSize) / 44100.0)*beatPeriod);
435 } 443 }
436 } 444 }
437 445
438 //======================================================================= 446 //=======================================================================
439 void BTrack::adaptiveThreshold(double *x,int N) 447 void BTrack::adaptiveThreshold(double *x,int N)
482 { 490 {
483 int numelem; 491 int numelem;
484 492
485 for (int i = 0;i < 128;i++) 493 for (int i = 0;i < 128;i++)
486 { 494 {
487 rcf[i] = 0; 495 combFilterBankOutput[i] = 0;
488 } 496 }
489 497
490 numelem = 4; 498 numelem = 4;
491 499
492 for (int i = 2;i <= 127;i++) // max beat period 500 for (int i = 2;i <= 127;i++) // max beat period
493 { 501 {
494 for (int a = 1;a <= numelem;a++) // number of comb elements 502 for (int a = 1;a <= numelem;a++) // number of comb elements
495 { 503 {
496 for (int b = 1-a;b <= a-1;b++) // general state using normalisation of comb elements 504 for (int b = 1-a;b <= a-1;b++) // general state using normalisation of comb elements
497 { 505 {
498 rcf[i-1] = rcf[i-1] + (acf[(a*i+b)-1]*wv[i-1])/(2*a-1); // calculate value for comb filter row 506 combFilterBankOutput[i-1] = combFilterBankOutput[i-1] + (acf[(a*i+b)-1]*weightingVector[i-1])/(2*a-1); // calculate value for comb filter row
499 } 507 }
500 } 508 }
501 } 509 }
502 } 510 }
503 511
573 void BTrack::updateCumulativeScore(double df_sample) 581 void BTrack::updateCumulativeScore(double df_sample)
574 { 582 {
575 int start, end, winsize; 583 int start, end, winsize;
576 double max; 584 double max;
577 585
578 start = dfbuffer_size - round(2*beatPeriod); 586 start = onsetDFBufferSize - round(2*beatPeriod);
579 end = dfbuffer_size - round(beatPeriod/2); 587 end = onsetDFBufferSize - round(beatPeriod/2);
580 winsize = end-start+1; 588 winsize = end-start+1;
581 589
582 double w1[winsize]; 590 double w1[winsize];
583 double v = -2*beatPeriod; 591 double v = -2*beatPeriod;
584 double wcumscore; 592 double wcumscore;
594 // calculate new cumulative score value 602 // calculate new cumulative score value
595 max = 0; 603 max = 0;
596 int n = 0; 604 int n = 0;
597 for (int i=start;i <= end;i++) 605 for (int i=start;i <= end;i++)
598 { 606 {
599 wcumscore = cumscore[i]*w1[n]; 607 wcumscore = cumulativeScore[i]*w1[n];
600 608
601 if (wcumscore > max) 609 if (wcumscore > max)
602 { 610 {
603 max = wcumscore; 611 max = wcumscore;
604 } 612 }
605 n++; 613 n++;
606 } 614 }
607 615
608 616
609 // shift cumulative score back one 617 // shift cumulative score back one
610 for (int i = 0;i < (dfbuffer_size-1);i++) 618 for (int i = 0;i < (onsetDFBufferSize-1);i++)
611 { 619 {
612 cumscore[i] = cumscore[i+1]; 620 cumulativeScore[i] = cumulativeScore[i+1];
613 } 621 }
614 622
615 // add new value to cumulative score 623 // add new value to cumulative score
616 cumscore[dfbuffer_size-1] = ((1-alpha)*df_sample) + (alpha*max); 624 cumulativeScore[onsetDFBufferSize-1] = ((1-alpha)*df_sample) + (alpha*max);
617 625
618 cscoreval = cumscore[dfbuffer_size-1]; 626 latestCumulativeScoreValue = cumulativeScore[onsetDFBufferSize-1];
619 627
620 //cout << cumscore[dfbuffer_size-1] << endl;
621
622 } 628 }
623 629
624 //======================================================================= 630 //=======================================================================
625 void BTrack::predictBeat() 631 void BTrack::predictBeat()
626 { 632 {
627 int winsize = (int) beatPeriod; 633 int windowSize = (int) beatPeriod;
628 double fcumscore[dfbuffer_size + winsize]; 634 double futureCumulativeScore[onsetDFBufferSize + windowSize];
629 double w2[winsize]; 635 double w2[windowSize];
630 // copy cumscore to first part of fcumscore 636 // copy cumscore to first part of fcumscore
631 for (int i = 0;i < dfbuffer_size;i++) 637 for (int i = 0;i < onsetDFBufferSize;i++)
632 { 638 {
633 fcumscore[i] = cumscore[i]; 639 futureCumulativeScore[i] = cumulativeScore[i];
634 } 640 }
635 641
636 // create future window 642 // create future window
637 double v = 1; 643 double v = 1;
638 for (int i = 0;i < winsize;i++) 644 for (int i = 0;i < windowSize;i++)
639 { 645 {
640 w2[i] = exp((-1*pow((v - (beatPeriod/2)),2)) / (2*pow((beatPeriod/2) ,2))); 646 w2[i] = exp((-1*pow((v - (beatPeriod/2)),2)) / (2*pow((beatPeriod/2) ,2)));
641 v++; 647 v++;
642 } 648 }
643 649
644 // create past window 650 // create past window
645 v = -2*beatPeriod; 651 v = -2*beatPeriod;
646 int start = dfbuffer_size - round(2*beatPeriod); 652 int start = onsetDFBufferSize - round(2*beatPeriod);
647 int end = dfbuffer_size - round(beatPeriod/2); 653 int end = onsetDFBufferSize - round(beatPeriod/2);
648 int pastwinsize = end-start+1; 654 int pastwinsize = end-start+1;
649 double w1[pastwinsize]; 655 double w1[pastwinsize];
650 656
651 for (int i = 0;i < pastwinsize;i++) 657 for (int i = 0;i < pastwinsize;i++)
652 { 658 {
658 664
659 // calculate future cumulative score 665 // calculate future cumulative score
660 double max; 666 double max;
661 int n; 667 int n;
662 double wcumscore; 668 double wcumscore;
663 for (int i = dfbuffer_size;i < (dfbuffer_size+winsize);i++) 669 for (int i = onsetDFBufferSize;i < (onsetDFBufferSize+windowSize);i++)
664 { 670 {
665 start = i - round(2*beatPeriod); 671 start = i - round(2*beatPeriod);
666 end = i - round(beatPeriod/2); 672 end = i - round(beatPeriod/2);
667 673
668 max = 0; 674 max = 0;
669 n = 0; 675 n = 0;
670 for (int k=start;k <= end;k++) 676 for (int k=start;k <= end;k++)
671 { 677 {
672 wcumscore = fcumscore[k]*w1[n]; 678 wcumscore = futureCumulativeScore[k]*w1[n];
673 679
674 if (wcumscore > max) 680 if (wcumscore > max)
675 { 681 {
676 max = wcumscore; 682 max = wcumscore;
677 } 683 }
678 n++; 684 n++;
679 } 685 }
680 686
681 fcumscore[i] = max; 687 futureCumulativeScore[i] = max;
682 } 688 }
683 689
684 690
685 // predict beat 691 // predict beat
686 max = 0; 692 max = 0;
687 n = 0; 693 n = 0;
688 694
689 for (int i = dfbuffer_size;i < (dfbuffer_size+winsize);i++) 695 for (int i = onsetDFBufferSize;i < (onsetDFBufferSize+windowSize);i++)
690 { 696 {
691 wcumscore = fcumscore[i]*w2[n]; 697 wcumscore = futureCumulativeScore[i]*w2[n];
692 698
693 if (wcumscore > max) 699 if (wcumscore > max)
694 { 700 {
695 max = wcumscore; 701 max = wcumscore;
696 beat = n; 702 beatCounter = n;
697 } 703 }
698 704
699 n++; 705 n++;
700 } 706 }
701 707
702 // set next prediction time 708 // set next prediction time
703 m0 = beat+round(beatPeriod/2); 709 m0 = beatCounter+round(beatPeriod/2);
704 710
705 711
706 } 712 }