annotate src/BayesDrumTracker.cpp @ 12:e148d1534733 tip

adding new max player
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 09 Mar 2012 20:42:34 +0000
parents 0f9165f96bdb
children
rev   line source
andrew@0 1 /*
andrew@0 2 * BayesDrumTracker.cpp
andrew@0 3 * bayesianTempoInitialiser5
andrew@0 4 *
andrew@0 5 * Created by Andrew on 14/07/2011.
andrew@0 6 * Copyright 2011 QMUL. All rights reserved.
andrew@0 7 *
andrew@0 8 */
andrew@0 9
andrew@0 10 #include "BayesDrumTracker.h"
andrew@0 11 #define OUTPORT 12346
andrew@0 12 #define HOST "localhost"
andrew@0 13
andrew@0 14
andrew@0 15 //beatCorrection process indicates how the phase is changing from max
andrew@0 16
andrew@0 17
andrew@0 18 BayesDrumTracker::BayesDrumTracker(){
andrew@0 19
andrew@0 20 initialiseTracker();
andrew@0 21 sender.setup( HOST, OUTPORT );
andrew@0 22 }
andrew@0 23
andrew@0 24
andrew@0 25 BayesDrumTracker::~BayesDrumTracker(){}
andrew@0 26
andrew@0 27 void BayesDrumTracker::initialiseTracker(){
andrew@0 28
andrew@0 29 beatDistribution.initialiseArray();
andrew@0 30 tempoDistribution.initialiseArray();
andrew@0 31 beatTimes.lastBeatTime = 0;
andrew@0 32 correctionFactor = 0.5;
andrew@0 33
andrew@0 34 tempoDistribution.likelihoodStdDev = ARRAY_SIZE / 32;
andrew@0 35 // tempoDistribution.likelihoodNoise = 0.96;
andrew@0 36 tempoDistribution.likelihoodNoise = 0.7;
andrew@0 37 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);//wide
andrew@0 38
andrew@0 39 beatDistribution.likelihoodStdDev = ARRAY_SIZE / 32;
andrew@0 40 beatDistribution.likelihoodNoise = 0.56;
andrew@0 41 beatDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);
andrew@0 42
andrew@0 43
andrew@0 44 tempoMinimum = 180;
andrew@0 45 tempoMaximum = 400;
andrew@0 46 posteriorMaximum = 0.1;
andrew@0 47
andrew@0 48 adaptiveStandardDeviationMode = false;
andrew@0 49 setDistributionOnStartTempo = true;
andrew@0 50
andrew@0 51 setBeatToNowTime = ofGetElapsedTimeMillis();
andrew@0 52 recentClickTime = ofGetElapsedTimeMillis();
andrew@0 53
andrew@0 54 resetParameters();
andrew@0 55 //check what we can delete above SINCE RESET CALLED
andrew@0 56
andrew@0 57 }
andrew@0 58
andrew@0 59
andrew@0 60 void BayesDrumTracker::resetParameters(){
andrew@0 61
andrew@0 62 beatTimes.startIndex = 0;
andrew@0 63 beatTimes.lastBeatTime = 0;
andrew@0 64 maxPhase = 0;
andrew@0 65 posteriorMaximum = 0.1;
andrew@0 66
andrew@0 67 accompanimentStarted = false;
andrew@0 68
andrew@0 69 tempoDistribution.likelihoodNoise = 0.8;
andrew@0 70 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/2);//wide
andrew@0 71
andrew@0 72 beatDistribution.initialiseArray();
andrew@0 73 tempoDistribution.initialiseArray();
andrew@0 74
andrew@0 75 tempoDistribution.calculateStandardDeviation();
andrew@0 76 beatDistribution.calculateStandardDeviation();
andrew@0 77
andrew@0 78 tempoStdDev = tempoDistribution.standardDeviation;
andrew@0 79
andrew@0 80 beatTimes.resetBeatTimeArray();
andrew@0 81
andrew@0 82 }
andrew@0 83
andrew@0 84
andrew@0 85
andrew@0 86 void BayesDrumTracker::decayDistributions(){
andrew@0 87
andrew@0 88 if (accompanimentStarted){
andrew@0 89 tempoDistribution.decayPosteriorWithGaussianNoise ();
andrew@0 90 beatDistribution.decayPosteriorWithGaussianNoise();
andrew@0 91 }
andrew@0 92 else{
andrew@0 93 if (tempoStdDev < 0.8 && beatDistribution.standardDeviation < 5)
andrew@0 94 accompanimentStarted = true;
andrew@0 95
andrew@0 96 }
andrew@0 97 }
andrew@0 98
andrew@0 99
andrew@0 100 void BayesDrumTracker::setBeatDistribution(int beatPosition){
andrew@0 101 switch (beatPosition){
andrew@0 102 //early sixteenth is that the beat is a sixteenth earlier
andrew@0 103 case 0:
andrew@0 104 case 1:
andrew@0 105 case 11:
andrew@0 106 //i.e. these zones are interpreted as "on the beat"
andrew@0 107 beatDistribution.eighthNoteProportion = 0;
andrew@0 108 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@0 109 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@0 110 break;
andrew@0 111 //10 and 2 were here
andrew@0 112
andrew@0 113 case 2:
andrew@0 114 beatDistribution.eighthNoteProportion = 0;
andrew@0 115 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
andrew@0 116 //i.e. a 25% chance it is early sixteenth - 75% that the beat actually lies here
andrew@0 117 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@0 118 break;
andrew@0 119
andrew@0 120 case 3:
andrew@0 121 beatDistribution.eighthNoteProportion = 0;
andrew@0 122 beatDistribution.earlySixteenthNoteProportion = 0.3;//was 0.4 in Bayesian8 //half chance it is early
andrew@0 123 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@0 124 break;
andrew@0 125
andrew@0 126 case 5:
andrew@0 127 case 6:
andrew@0 128 case 7:
andrew@0 129 beatDistribution.eighthNoteProportion = 0.3;//i.e. nearly half a chance we are on the 8th note
andrew@0 130 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@0 131 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@0 132 break;
andrew@0 133
andrew@0 134 case 4:
andrew@0 135 beatDistribution.eighthNoteProportion = 0;
andrew@0 136 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
andrew@0 137 beatDistribution.lateSixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
andrew@0 138 //chsanged to 0.2 and 0.1 then back
andrew@0 139 break;
andrew@0 140
andrew@0 141 case 8:
andrew@0 142 beatDistribution.eighthNoteProportion = 0;
andrew@0 143 beatDistribution.earlySixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
andrew@0 144 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
andrew@0 145 break;
andrew@0 146
andrew@0 147 case 9:
andrew@0 148 beatDistribution.eighthNoteProportion = 0;
andrew@0 149 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@0 150 beatDistribution.lateSixteenthNoteProportion = 0.35;//was 0.4 in Bayesian8
andrew@0 151 break;
andrew@0 152
andrew@0 153 case 10:
andrew@0 154 beatDistribution.eighthNoteProportion = 0;
andrew@0 155 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@0 156 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.2 in Bayesian8
andrew@0 157 break;
andrew@0 158
andrew@0 159 }
andrew@0 160
andrew@0 161 }
andrew@0 162
andrew@0 163 void BayesDrumTracker::newKickError(const float& error, const double& cpuEventTime, const string& onsetTypeString){
andrew@0 164
andrew@0 165 onsetType = onsetTypeString;
andrew@0 166 cpuBeatTime = cpuEventTime;
andrew@0 167 kickError = error;
andrew@0 168
andrew@0 169 //printf("beat errror %f time %f\n", kickError, cpuBeatTime);
andrew@0 170
andrew@0 171 while (kickError > 0.5){
andrew@0 172 kickError -= 1;
andrew@0 173 }
andrew@0 174
andrew@0 175 if (paused != true){
andrew@0 176 updateTempoProcess(cpuBeatTime, onsetType);
andrew@0 177 //this also cross updates the distributions
andrew@0 178 beatTimes.beatMapTimeDifferences[beatTimes.beatSegment] = kickError*beatTimes.tatum;
andrew@0 179 }//end if paused
andrew@0 180
andrew@0 181
andrew@0 182
andrew@0 183 if (onsetType == "kick"){
andrew@0 184 if (accompanimentStarted)
andrew@0 185 beatDistribution.likelihoodNoise = 0.5;
andrew@0 186 else
andrew@0 187 beatDistribution.likelihoodNoise = 0.5;
andrew@0 188 // printf("kick %f ", cpuBeatTime);
andrew@0 189 }
andrew@0 190 else{
andrew@0 191 //snare
andrew@0 192 if (accompanimentStarted)
andrew@0 193 beatDistribution.likelihoodNoise = 0.7;
andrew@0 194 else
andrew@0 195 beatDistribution.likelihoodNoise = 0.85;
andrew@0 196 // printf("snare %f ", cpuBeatTime);
andrew@0 197 }
andrew@0 198
andrew@0 199
andrew@0 200 setBeatDistribution(beatTimes.beatSegment%12);
andrew@0 201
andrew@0 202 if (kickError <= 0.5 && kickError >= -0.5)
andrew@0 203 {
andrew@0 204 float beatStandardDeviation;
andrew@0 205 if (adaptiveStandardDeviationMode)
andrew@0 206 beatStandardDeviation = min((double)beatDistribution.likelihoodStdDev, beatDistribution.standardDeviation);
andrew@0 207 else
andrew@0 208 beatStandardDeviation = beatDistribution.likelihoodStdDev;
andrew@0 209
andrew@0 210
andrew@0 211 beatDistribution.resetPrior();
andrew@0 212 beatDistribution.setGaussianLikelihoodForBeats((ARRAY_SIZE/2)+(kickError*ARRAY_SIZE), beatStandardDeviation);
andrew@0 213 beatDistribution.calculatePosterior();
andrew@0 214 beatDistribution.renormalisePosterior();
andrew@0 215
andrew@0 216 sendMaxPhase();
andrew@0 217
andrew@0 218 beatDistribution.calculateStandardDeviation();
andrew@0 219
andrew@0 220 }//end if error < 0.5
andrew@0 221
andrew@0 222
andrew@0 223
andrew@0 224 if (beatTimes.beatSegment % 12 == 6){
andrew@0 225 kickString = "Kick ";
andrew@0 226 kickString += ofToString(kickError);
andrew@0 227 kickString += " ERROR ";
andrew@0 228 kickString += ofToString(kickError, 2);
andrew@0 229 kickString += " at time diff ";
andrew@0 230 kickString += ofToString(cpuBeatTime - beatTimes.lastClickTime, 2);
andrew@0 231 kickString += " index ";
andrew@0 232 kickString += ofToString(beatTimes.lastClickIndex, 2);
andrew@0 233 kickString += " TYPE ";
andrew@0 234 kickString += ofToString(beatTimes.beatSegment%12);
andrew@0 235 kickString += " Time diff ";
andrew@0 236 kickString += ofToString(beatTimes.timeDifference, 2);
andrew@0 237 }
andrew@0 238
andrew@0 239
andrew@0 240 }
andrew@0 241
andrew@0 242
andrew@0 243
andrew@0 244 void BayesDrumTracker::startTatum(const float& startTatum){
andrew@0 245 beatTimes.tatum = startTatum;
andrew@0 246
andrew@0 247 if (setDistributionOnStartTempo){
andrew@0 248 beatDistribution.setGaussianPosterior(ARRAY_SIZE/2, 8);
andrew@0 249 tempoDistribution.setGaussianPosterior(ARRAY_SIZE/2, 12);
andrew@0 250 float tmpIndex;
andrew@0 251 tmpIndex = ( (beatTimes.tatum - ((tempoMinimum+tempoMaximum)/2) ) * ARRAY_SIZE)/(tempoMaximum - tempoMinimum);
andrew@0 252 tempoDistribution.translateDistribution(tmpIndex);
andrew@0 253
andrew@0 254 sendMaxTempo();
andrew@0 255 }
andrew@0 256 }
andrew@0 257
andrew@0 258
andrew@0 259 void BayesDrumTracker::setUniformTempo(){
andrew@0 260 for (int i = 0;i < ARRAY_SIZE;i++)
andrew@0 261 tempoDistribution.posterior[i] = (float)1/ARRAY_SIZE;
andrew@0 262 }
andrew@0 263
andrew@0 264
andrew@0 265 void BayesDrumTracker::setUniformPhase(){
andrew@0 266 for (int i = 0;i < ARRAY_SIZE;i++)
andrew@0 267 beatDistribution.posterior[i] = (float)1/ARRAY_SIZE;
andrew@0 268 }
andrew@0 269
andrew@0 270 void BayesDrumTracker::setBeatNow(const double& beatTime){
andrew@0 271 for (int i = 0;i < ARRAY_SIZE;i++)
andrew@0 272 beatDistribution.prior[i] = (float)1/ARRAY_SIZE;
andrew@0 273
andrew@0 274 setBeatToNowTime = ofGetElapsedTimeMillis();
andrew@0 275 double difference = (setBeatToNowTime - recentClickTime);
andrew@0 276 printf("SET BEAT TO NOW %f vs %f :: diff %f tatum %f :: ", setBeatToNowTime, recentClickTime, difference, beatTimes.tatum );
andrew@0 277
andrew@0 278 double beatTimeToUse = 0;
andrew@0 279
andrew@0 280 if (difference < beatTimes.tatum)//tatum is the eighth note time
andrew@0 281 beatTimeToUse = difference/ (2*beatTimes.tatum);
andrew@0 282 else
andrew@0 283 beatTimeToUse = -1*(2*beatTimes.tatum - difference) / (2*beatTimes.tatum);
andrew@0 284
andrew@0 285 printf("sending %f \n", beatTimeToUse);
andrew@0 286
andrew@0 287 beatDistribution.setGaussianLikelihoodForBeats((ARRAY_SIZE/2)+(beatTimeToUse*ARRAY_SIZE), 2);
andrew@0 288 beatDistribution.calculatePosterior();
andrew@0 289 beatDistribution.renormalisePosterior();
andrew@0 290
andrew@0 291 sendMaxPhase();
andrew@0 292
andrew@0 293
andrew@0 294 }
andrew@0 295
andrew@0 296
andrew@0 297 void BayesDrumTracker::newBeat(int& beatIndex){
andrew@0 298 ofxOscMessage m;
andrew@0 299 m.setAddress( "/beatInfo" );
andrew@0 300
andrew@0 301 m.addFloatArg(beatTimes.tatum);
andrew@0 302 m.addFloatArg(maxPhase);
andrew@0 303
andrew@0 304 beatTimes.tatum = maxTempo;
andrew@0 305 printf("BEAT INFO %f, %f\n", beatTimes.tatum, maxPhase);
andrew@0 306
andrew@0 307 sender.sendMessage( m );
andrew@0 308
andrew@0 309 }
andrew@0 310
andrew@0 311 void BayesDrumTracker::sendMaxTempo(){
andrew@0 312 ofxOscMessage m;
andrew@0 313 m.setAddress( "/tempo" );
andrew@0 314
andrew@0 315 //maxTempo = tempoDistribution.maximumIndex * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
andrew@0 316 //would be introduced new in bayesian8
andrew@0 317 maxTempo = tempoDistribution.getIntegratedEstimateIndex() * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
andrew@0 318 maxTempo += tempoMinimum;
andrew@0 319
andrew@0 320 beatTimes.tatum = maxTempo;
andrew@0 321 printf("SEND TATUM %f\n", beatTimes.tatum);
andrew@0 322
andrew@0 323 m.addFloatArg( maxTempo );
andrew@0 324 sender.sendMessage( m );
andrew@0 325
andrew@0 326 //printf("max tempo %f\n", maxTempo);
andrew@0 327
andrew@0 328 }
andrew@0 329
andrew@0 330 void BayesDrumTracker::sendMaxPhase(){
andrew@0 331
andrew@0 332
andrew@0 333 // maxPhase = (beatDistribution.maximumIndex - (ARRAY_SIZE/2)) / ARRAY_SIZE;
andrew@0 334 maxPhase = (beatDistribution.getIntegratedEstimateIndex() - (ARRAY_SIZE/2)) / ARRAY_SIZE;
andrew@0 335 // printf("\nphase index %f :: %f\n", (float) beatDistribution.integratedEstimate , maxPhase);
andrew@0 336 ofxOscMessage m;
andrew@0 337 m.setAddress( "/phase" );
andrew@0 338 m.addFloatArg( maxPhase );
andrew@0 339 sender.sendMessage( m );
andrew@0 340
andrew@0 341 //beatCorrection = maxPhase * beatTimes.tatum / 4;
andrew@0 342 }
andrew@0 343
andrew@0 344
andrew@0 345 void BayesDrumTracker::setNewClickIndex(const int& clickIndex, const float& clickTime){
andrew@0 346
andrew@0 347 beatTimes.lastClickIndex = clickIndex;
andrew@0 348 beatTimes.lastClickTime = clickTime;
andrew@0 349
andrew@0 350 int clickIndexToUse = clickIndex % 16;
andrew@0 351 beatTimes.clickIndex = clickIndex;
andrew@0 352 beatTimes.clickNumber[clickIndexToUse] = clickIndex;
andrew@0 353 beatTimes.clickTimes[clickIndexToUse] = clickTime;
andrew@0 354
andrew@0 355 recentClickTime = ofGetElapsedTimeMillis();
andrew@0 356
andrew@0 357 }
andrew@0 358
andrew@0 359
andrew@0 360 void BayesDrumTracker::doBeatCorrection(const float& beatCorrFloat){
andrew@0 361 beatCorrection = beatCorrFloat;
andrew@0 362 correctBeatBy = round(correctionFactor * beatCorrection * ARRAY_SIZE / (2 * beatTimes.tatum));
andrew@0 363 beatDistribution.translateDistribution(-1 * correctBeatBy);
andrew@0 364 }
andrew@0 365
andrew@0 366
andrew@0 367 bool BayesDrumTracker::filterBeatTime(double newBeatTime){
andrew@0 368 bool newBeatFound = false;
andrew@0 369 if ((newBeatTime - beatTimes.lastBeatTime) > 20 || beatTimes.lastBeatTime == 0){
andrew@0 370
andrew@0 371 crossUpdateArrays((float)(newBeatTime - beatTimes.lastBeatTime));
andrew@0 372 beatTimes.lastBeatTime = newBeatTime;
andrew@0 373 newBeatFound = true;
andrew@0 374 }
andrew@0 375 return newBeatFound;
andrew@0 376 }
andrew@0 377
andrew@0 378 void BayesDrumTracker::crossUpdateArrays(float timeInterval){
andrew@0 379
andrew@0 380 int finalBeatIndex, tmpTempoIndex, startBeatIndex;
andrew@0 381 //finalBeat has contribution from BEAT[finalBeat + INT.k] * TEMPO[Max_tempo + k] where INT = INTERVAL
andrew@0 382 float interval;
andrew@0 383 interval = timeInterval / maxTempo;//beatTimes.tatum;
andrew@0 384 tempoDistribution.resetMaximumPosterior();
andrew@0 385 beatDistribution.resetMaximumPosterior();
andrew@0 386
andrew@0 387
andrew@0 388 int tmpBeatIndex;
andrew@0 389 //&& interval > 0.8 idea?
andrew@0 390 if (timeInterval > 0 && timeInterval < 12000 ){//need between 0 and 12 seconds only to update
andrew@0 391
andrew@0 392 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
andrew@0 393
andrew@0 394 tmpArray[tmpBeatIndex] = 0;
andrew@0 395 float minusMsecToMakeUp = beatIndexToMsec(tmpBeatIndex) / interval;
andrew@0 396 float plusMsecToMakeUp = beatIndexToMsec(ARRAY_SIZE - tmpBeatIndex) / interval;
andrew@0 397 float convertMsecToTempoIndex = ARRAY_SIZE / (tempoMaximum - tempoMinimum) ;
andrew@0 398
andrew@0 399
andrew@0 400 int minTempoIndex = -1 * (int)(minusMsecToMakeUp * convertMsecToTempoIndex);
andrew@0 401 int maxTempoIndex = (int)(plusMsecToMakeUp * convertMsecToTempoIndex);
andrew@0 402
andrew@0 403
andrew@0 404 if (tmpBeatIndex == beatDistribution.maximumIndex){
andrew@0 405 // minTmpDebug = tempoDistribution.maximumIndex + minTempoIndex;
andrew@0 406 // maxTmpDebug = tempoDistribution.maximumIndex + maxTempoIndex;
andrew@0 407 debugArray[0] = beatDistribution.maximumIndex;//
andrew@0 408 debugArray[1] = timeInterval;
andrew@0 409 debugArray[2] = interval;//beatDistribution.maximumIndex;
andrew@0 410 debugArray[3] = tempoDistribution.maximumIndex;
andrew@0 411 }
andrew@0 412
andrew@0 413 for (tmpTempoIndex = minTempoIndex;tmpTempoIndex <= maxTempoIndex;tmpTempoIndex++){
andrew@0 414
andrew@0 415 if ((tempoDistribution.maximumIndex + tmpTempoIndex) >= 0
andrew@0 416 && (tempoDistribution.maximumIndex + tmpTempoIndex) < ARRAY_SIZE
andrew@0 417 && (tmpBeatIndex - (int)(interval*tmpTempoIndex)) >= 0
andrew@0 418 && (tmpBeatIndex - (int)(interval*tmpTempoIndex))< ARRAY_SIZE){
andrew@0 419 tmpArray[tmpBeatIndex] += beatDistribution.posterior[tmpBeatIndex - (int)(interval*tmpTempoIndex)] * tempoDistribution.posterior[(int)tempoDistribution.maximumIndex + tmpTempoIndex];
andrew@0 420 }
andrew@0 421 }//end for tmpTmepo
andrew@0 422
andrew@0 423
andrew@0 424
andrew@0 425 }
andrew@0 426
andrew@0 427 float tmpFloat;
andrew@0 428 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
andrew@0 429 //debug - dont actually update::
andrew@0 430
andrew@0 431 tmpFloat = beatDistribution.posterior[tmpBeatIndex];
andrew@0 432 beatDistribution.posterior[tmpBeatIndex] = tmpArray[tmpBeatIndex];
andrew@0 433 tmpArray[tmpBeatIndex] = tmpFloat;
andrew@0 434 }
andrew@0 435 beatDistribution.renormaliseArray(&beatDistribution.posterior[0], ARRAY_SIZE);
andrew@0 436
andrew@0 437 } //end if
andrew@0 438
andrew@0 439
andrew@0 440 }
andrew@0 441
andrew@0 442
andrew@0 443 void BayesDrumTracker::updateTempoProcess(const double& cpuTime, const string& onsetDescription){
andrew@0 444
andrew@0 445 if (filterBeatTime(cpuTime) == true){
andrew@0 446 //checks for no repeat
andrew@0 447
andrew@0 448 if (onsetDescription == "kick")
andrew@0 449 beatTimes.addBeatTime(cpuTime, 1);
andrew@0 450 else
andrew@0 451 beatTimes.addBeatTime(cpuTime, 2);
andrew@0 452
andrew@0 453
andrew@0 454 //recalculate the distribution
andrew@0 455 int altIndex = 0;
andrew@0 456
andrew@0 457 tempoDataString = "Tatum :";
andrew@0 458 tempoDataString += ofToString(beatTimes.tatum, 2);
andrew@0 459 tempoDataString += " BPM ";
andrew@0 460 tempoDataString += ofToString((double)30000/beatTimes.tatum, 2);
andrew@0 461
andrew@0 462 timeString = "Last BEAT ";
andrew@0 463 timeString += ofToString(beatTimes.lastBeatTime);
andrew@0 464 timeString += " CLICK ";
andrew@0 465 timeString += ofToString(beatTimes.lastClickTime);
andrew@0 466 timeString += " DIFDF ";
andrew@0 467 timeString += ofToString(beatTimes.timeDifference);
andrew@0 468 timeString += " segment ";
andrew@0 469 timeString += ofToString(beatTimes.beatSegment);
andrew@0 470
andrew@0 471
andrew@0 472 for (altIndex = 0;altIndex< 16;altIndex++){
andrew@0 473 tempoInterval = beatTimes.intervalDifferences[beatTimes.index][altIndex];
andrew@0 474 integerMultipleOfTatum = beatTimes.relativeIntervals[altIndex][1];
andrew@0 475
andrew@0 476
andrew@0 477 ///NEW VERSION
andrew@0 478 tempoUpdateStrings[altIndex] = "";
andrew@0 479 double timeInterval = beatTimes.beatTimes[beatTimes.index] - beatTimes.beatTimes[altIndex];
andrew@0 480 //raw time difference
andrew@0 481 beatTimes.intervalDifferences[beatTimes.index][altIndex] = 0;
andrew@0 482 beatTimes.intervalUsed[beatTimes.index][altIndex] = false;
andrew@0 483
andrew@0 484 if (onsetType == "kick")
andrew@0 485 beatTimes.OnsetIsKick[beatTimes.index] = true;
andrew@0 486 else
andrew@0 487 beatTimes.OnsetIsKick[beatTimes.index] = false;
andrew@0 488
andrew@0 489
andrew@0 490
andrew@0 491 if (!accompanimentStarted){
andrew@0 492 //if we need to find tempo and start use this method
andrew@0 493 //we have 'started' once std dev is sufficiently low
andrew@0 494
andrew@0 495 updateTempoIfWithinRange(timeInterval);//taken as being the tatum interval
andrew@0 496
andrew@0 497
andrew@0 498
andrew@0 499 for (int i = 1;i <= 4;i++){
andrew@0 500 //we test the main beats and the two bar (16 tatum intervals)
andrew@0 501
andrew@0 502 double testInterval = timeInterval / 2*i;//pow(2, i);//pow(2.0, i);
andrew@0 503
andrew@0 504 if (updateTempoIfWithinRange(testInterval)){
andrew@0 505 //printf("test time %f, beats %i\n", testInterval, i);
andrew@0 506
andrew@0 507 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
andrew@0 508 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
andrew@0 509 //xx what if two within range here?
andrew@0 510
andrew@0 511 tempoUpdateStrings[altIndex] = "Tempo Updates (";
andrew@0 512 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
andrew@0 513 tempoUpdateStrings[altIndex] += ") : [";
andrew@0 514 tempoUpdateStrings[altIndex] += ofToString(altIndex);
andrew@0 515 tempoUpdateStrings[altIndex] += "]] : ";
andrew@0 516 tempoUpdateStrings[altIndex] += ofToString(timeInterval);
andrew@0 517 tempoUpdateStrings[altIndex] += ", ioi:";
andrew@0 518 tempoUpdateStrings[altIndex] += ofToString(i);
andrew@0 519 //tempoUpdateStrings[altIndex] += "";
andrew@0 520
andrew@0 521 }
andrew@0 522
andrew@0 523 }
andrew@0 524
andrew@0 525 double testInterval = timeInterval / 16;//pow(2, i);//pow(2.0, i);
andrew@0 526 if (updateTempoIfWithinRange(testInterval)){
andrew@0 527 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
andrew@0 528 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
andrew@0 529 }
andrew@0 530
andrew@0 531 }else{
andrew@0 532 //OLD VERSON
andrew@0 533 //THIS USES THE CURRENT TEMPO ESTIMATE TO DECIDE WHAT THE BEST INTERVAL IS
andrew@0 534 //&& integerMultipleOfTatum % 2 == 0 removed below XXX put back
andrew@0 535 if (altIndex != beatTimes.index && integerMultipleOfTatum < 17
andrew@0 536 && integerMultipleOfTatum > 0 && beatTimes.startIndex > 8//beattimes.index > 8 - the start
andrew@0 537 && integerMultipleOfTatum%2 == 0){//mod 2 - i.e. proper beat intervals only
andrew@0 538
andrew@0 539 double testInterval = timeInterval / integerMultipleOfTatum;
andrew@0 540
andrew@0 541 if (updateTempoIfWithinRange(testInterval)){
andrew@0 542
andrew@0 543 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
andrew@0 544 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
andrew@0 545
andrew@0 546 if (paused == false){
andrew@0 547 tempoUpdateStrings[altIndex] = "Tempo Updates : (";
andrew@0 548 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
andrew@0 549 tempoUpdateStrings[altIndex] += ") : [";
andrew@0 550 tempoUpdateStrings[altIndex] += ofToString(altIndex, 0);
andrew@0 551 tempoUpdateStrings[altIndex] += "] :: ";
andrew@0 552 tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
andrew@0 553 tempoUpdateStrings[altIndex] += " intervals :: ";
andrew@0 554 tempoUpdateStrings[altIndex] += ofToString(tempoInterval);
andrew@0 555 tempoUpdateStrings[altIndex] += " ms.";
andrew@0 556 // tempoUpdateStrings[altIndex] += ", ioi:";
andrew@0 557
andrew@0 558 // tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
andrew@0 559
andrew@0 560
andrew@0 561
andrew@0 562
andrew@0 563 }//end if not paused
andrew@0 564
andrew@0 565
andrew@0 566 }//end if good interval to update
andrew@0 567
andrew@0 568 }//end if not same index etc
andrew@0 569
andrew@0 570
andrew@0 571 }
andrew@0 572
andrew@0 573
andrew@0 574
andrew@0 575 }//end for all intervals
andrew@0 576
andrew@0 577 sendMaxTempo();
andrew@0 578 }//end if new beat time
andrew@0 579 double tempoEstimate = tempoDistribution.getIntegratedEstimateIndex();
andrew@0 580 tempoDistribution.calculateStandardDeviation();
andrew@0 581 tempoStdDev = tempoDistribution.standardDeviation;
andrew@0 582
andrew@0 583 }
andrew@0 584
andrew@0 585
andrew@0 586 bool BayesDrumTracker::updateTempoIfWithinRange(double timeInterval){
andrew@0 587
andrew@0 588 bool updated = false;
andrew@0 589
andrew@0 590 if (timeInterval > tempoMinimum && timeInterval < tempoMaximum ){
andrew@0 591 calculateTempoUpdate(timeInterval);
andrew@0 592 updated = true;
andrew@0 593 }
andrew@0 594
andrew@0 595 return updated;
andrew@0 596 }
andrew@0 597
andrew@0 598
andrew@0 599 void BayesDrumTracker::calculateTempoUpdate(double tempoInterval){
andrew@0 600
andrew@0 601
andrew@0 602 tempoDistribution.resetPrior();
andrew@0 603 //need to relook at likelihood for the tempo distribution - not the same as....
andrew@0 604 tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval-tempoMinimum)/(tempoMaximum - tempoMinimum), tempoDistribution.likelihoodStdDev);
andrew@0 605 tempoDistribution.calculatePosterior();
andrew@0 606 tempoDistribution.renormalisePosterior();
andrew@0 607
andrew@0 608 //did take pic of screen here - see initialiser4
andrew@0 609 }
andrew@0 610
andrew@0 611
andrew@0 612 float BayesDrumTracker::tempoIndexToMsec(const int& index){
andrew@0 613 float msec;
andrew@0 614 msec = index * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
andrew@0 615 msec += tempoMinimum;
andrew@0 616 return msec;
andrew@0 617 }
andrew@0 618
andrew@0 619 float BayesDrumTracker::beatIndexToMsec(const int& index){
andrew@0 620 float msec;
andrew@0 621 msec = index * maxTempo / ARRAY_SIZE;
andrew@0 622 msec += tempoMinimum;
andrew@0 623 return msec;
andrew@0 624 }
andrew@0 625