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