annotate src/BTrack.cpp @ 18:450c53430540 develop

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