annotate newOFsrc/testApp.cpp @ 3:6565c7cb9c71

Added KL divergence and entropy
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Wed, 22 Feb 2012 22:29:43 +0000
parents c49a8f33afab
children 1ea18717ba7c
rev   line source
andrew@2 1 #include "testApp.h"
andrew@2 2
andrew@2 3
andrew@2 4 //--------------------------------------------------------------
andrew@2 5 //relooking at this problem
andrew@2 6 //bayesianTempo7 - have had working well with Bayesian8NEW maxmsp set
andrew@2 7
andrew@2 8 //updated in bayesian8
andrew@2 9 //integrate so that maxPhase and tempo are the integrated result across the pdf
andrew@2 10 //rather tahn the maximum index - tends to reflect the actuial distribution better
andrew@2 11 //and is the "correct" bayesian method
andrew@2 12
andrew@2 13 //added [ and ] tpo change the alignment when rescue is needed
andrew@2 14
andrew@2 15 //in Bayesian9 (BayesianTest8NEW)
andrew@2 16 //added noise in phase process
andrew@2 17 //started probability distribution for observed beat events
andrew@2 18
andrew@2 19 //in bayesian 11
andrew@2 20 //get s.d. of posterior
andrew@2 21 //this is set to be used as the s.d. of the likelihood
andrew@2 22
andrew@2 23
andrew@2 24 //Initialiser : the algorithm has an initialisation stage with flat prior that detects liekly tempo
andrew@2 25
andrew@2 26
andrew@2 27
andrew@2 28 //BAYESIAN DISTRIBUTION SET by class BayesianArray
andrew@2 29 //SETUP - initialises array
andrew@2 30 //UPDATE - decay the distribution with noise
andrew@2 31 //this should be done using tempo and noise
andrew@2 32 //DRAW - Draw current distributions and also the maximum
andrew@2 33
andrew@2 34 //Runs with bayesian11NEW
andrew@2 35 //and B-KeeperOldBayesianTestNew in Live
andrew@2 36 //Needs - categorisation of beats and tempo
andrew@2 37 //can we use our distribution to filter the input or is that cheating?
andrew@2 38
andrew@2 39 //INtroduce lock scheme for tempo - we know where the beat fell, so can calculate the appropriate tempo interval
andrew@2 40
andrew@2 41 void testApp::setup(){
andrew@2 42 // listen on the given port
andrew@2 43 cout << "listening for osc messages on port " << PORT << "\n";
andrew@2 44 receiver.setup( PORT );
andrew@2 45
andrew@2 46 // sender.setup( HOST, OUTPORT );
andrew@2 47 ofSetCircleResolution(50);
andrew@2 48 ofBackground(255,255,255);
andrew@2 49 bSmooth = false;
andrew@2 50 msg_string = "setup";
andrew@2 51
andrew@2 52 ofSetWindowTitle("Bayesian Test");
andrew@2 53
andrew@2 54 ofSetFrameRate(60); // if vertical sync is off, we can go a bit fast... this caps the framerate at 60fps.
andrew@2 55
andrew@2 56 KLdiv = 0;
andrew@3 57 entropy = 0;
andrew@2 58 /*
andrew@2 59 beatDistribution.initialiseArray();
andrew@2 60 tempoDistribution.initialiseArray();
andrew@2 61 beatTimes.lastBeatTime = 0;
andrew@2 62 correctionFactor = 0.5;
andrew@2 63
andrew@2 64
andrew@2 65
andrew@2 66 tempoDistribution.likelihoodStdDev = ARRAY_SIZE / 32;
andrew@2 67 // tempoDistribution.likelihoodNoise = 0.96;
andrew@2 68 tempoDistribution.likelihoodNoise = 0.7;
andrew@2 69 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);//wide
andrew@2 70
andrew@2 71 beatDistribution.likelihoodStdDev = ARRAY_SIZE / 32;
andrew@2 72 beatDistribution.likelihoodNoise = 0.56;
andrew@2 73 beatDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);
andrew@2 74
andrew@2 75
andrew@2 76 tempoMinimum = 180;
andrew@2 77 tempoMaximum = 400;
andrew@2 78 posteriorMaximum = 0.1;
andrew@2 79
andrew@2 80 */
andrew@2 81 hidePriorMode = false;
andrew@2 82
andrew@2 83 printInterval = true;
andrew@2 84 drawData = false;
andrew@2 85
andrew@2 86 screenToDraw = 0;
andrew@2 87
andrew@2 88 ofSetLineWidth(2);
andrew@2 89 ofEnableSmoothing();
andrew@2 90
andrew@2 91
andrew@2 92 bSnapshot = false;
andrew@2 93 snapCounter = 0;
andrew@2 94
andrew@2 95 drumTracker.paused = false;
andrew@2 96
andrew@2 97 // setDistributionOnStartTempo = true;
andrew@2 98
andrew@2 99 resetParameters();
andrew@2 100
andrew@2 101 arrayToMsecScaleFactor = (drumTracker.tempoMaximum - drumTracker.tempoMinimum)/ ARRAY_SIZE;//turns array into ms
andrew@2 102 tempoWindowMinimum = 100;
andrew@2 103 tempoWindowMaximum = 150;
andrew@2 104 tempoWindowWidth = 50;
andrew@2 105 }
andrew@2 106
andrew@2 107
andrew@2 108 void testApp::resetParameters(){
andrew@2 109 /*
andrew@2 110 beatTimes.startIndex = 0;
andrew@2 111 beatTimes.lastBeatTime = 0;
andrew@2 112 maxPhase = 0;
andrew@2 113 posteriorMaximum = 0.1;
andrew@2 114
andrew@2 115 accompanimentStarted = false;
andrew@2 116
andrew@2 117 tempoDistribution.likelihoodNoise = 0.8;
andrew@2 118 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/2);//wide
andrew@2 119
andrew@2 120 beatDistribution.initialiseArray();
andrew@2 121 tempoDistribution.initialiseArray();
andrew@2 122
andrew@2 123 tempoDistribution.calculateStandardDeviation();
andrew@2 124 beatDistribution.calculateStandardDeviation();
andrew@2 125
andrew@2 126 tempoStdDev = tempoDistribution.standardDeviation;
andrew@2 127
andrew@2 128 beatTimes.resetBeatTimeArray();
andrew@2 129 */
andrew@2 130 }
andrew@2 131
andrew@2 132 //--------------------------------------------------------------
andrew@2 133 void testApp::update(){
andrew@2 134
andrew@2 135
andrew@2 136 updateOSCmessages();
andrew@2 137
andrew@2 138 //update tempo window range - this for viewing tempo closeup
andrew@2 139 while (tempoWindowMinimum + tempoWindowWidth/4 > drumTracker.tempoDistribution.integratedEstimate)
andrew@2 140 tempoWindowMinimum -= tempoWindowWidth/4;
andrew@2 141
andrew@2 142 while (tempoWindowMinimum + 3*tempoWindowWidth/4 < drumTracker.tempoDistribution.integratedEstimate)
andrew@2 143 tempoWindowMinimum += tempoWindowWidth/4;
andrew@2 144
andrew@2 145 tempoWindowMaximum = tempoWindowMinimum + tempoWindowWidth;
andrew@2 146
andrew@2 147 drumTracker.decayDistributions();
andrew@2 148
andrew@2 149 }
andrew@2 150
andrew@2 151
andrew@2 152 void testApp::updateOSCmessages(){
andrew@2 153
andrew@2 154
andrew@2 155 // check for waiting messages
andrew@2 156 while( receiver.hasWaitingMessages() )
andrew@2 157 {
andrew@2 158 ofxOscMessage m;
andrew@2 159 receiver.getNextMessage( &m );
andrew@2 160 string newAddress = m.getAddress();
andrew@2 161
andrew@2 162 if ( m.getAddress() == "/Reset" ){
andrew@2 163 printf("baysian reset\n");
andrew@2 164 drumTracker.resetParameters();
andrew@2 165 }
andrew@2 166
andrew@2 167
andrew@2 168 if ( m.getAddress() == "/beatError" ){
andrew@2 169 double timeNow = ofGetElapsedTimeMillis();
andrew@2 170 if (timeNow - drumTracker.setBeatToNowTime > 1000)
andrew@2 171 drumTracker.newKickError(m.getArgAsFloat(0), m.getArgAsFloat(2), m.getArgAsString(1));
andrew@2 172 KLdiv = drumTracker.beatDistribution.getKLdivergence();
andrew@3 173 entropy = drumTracker.beatDistribution.getEntropyOfPosterior();
andrew@2 174 }//end if new error
andrew@2 175
andrew@2 176
andrew@2 177
andrew@2 178 if ( m.getAddress() == "/tatum" ){
andrew@2 179 drumTracker.beatTimes.tatum = m.getArgAsFloat(0);
andrew@2 180 printf("got tatum as %f\n", m.getArgAsFloat(0));
andrew@2 181 }
andrew@2 182
andrew@2 183 if ( m.getAddress() == "/startTatum" ){
andrew@2 184 drumTracker.startTatum(m.getArgAsFloat(0));
andrew@2 185 printf("START TATUM %f\n", m.getArgAsFloat(0));
andrew@2 186 //then change so tempo distribution is correct....
andrew@2 187 }//end start tatum
andrew@2 188
andrew@2 189
andrew@2 190 if ( m.getAddress() == "/uniformTempo" ){
andrew@2 191 drumTracker.setUniformTempo();
andrew@2 192
andrew@2 193 }
andrew@2 194
andrew@2 195
andrew@2 196 if ( m.getAddress() == "/uniformPhase" ){
andrew@2 197 drumTracker.setUniformPhase();
andrew@2 198
andrew@2 199 }
andrew@2 200
andrew@2 201
andrew@2 202 if ( m.getAddress() == "/setBeatNow" ){
andrew@2 203
andrew@2 204 double beatTime = m.getArgAsFloat(0);
andrew@2 205 drumTracker.setBeatNow(beatTime);
andrew@2 206 //printf("SET BEAT NOW %f\n", beatTime);
andrew@2 207 }
andrew@2 208
andrew@2 209
andrew@2 210 if ( m.getAddress() == "/clickindex" ){
andrew@2 211
andrew@2 212 int clickIndex = m.getArgAsInt32(0);
andrew@2 213 float clickTime = m.getArgAsFloat(1);
andrew@2 214 drumTracker.setNewClickIndex(clickIndex, clickTime);
andrew@2 215 }
andrew@2 216
andrew@2 217
andrew@2 218 if ( m.getAddress() == "/newBeat" ){
andrew@2 219 int beatIndex = m.getArgAsInt32(0);
andrew@2 220 drumTracker.newBeat(beatIndex);
andrew@2 221 }
andrew@2 222
andrew@2 223
andrew@2 224 if ( m.getAddress() == "/beatCorrection" )
andrew@2 225 {
andrew@2 226 float beatCorrValue = m.getArgAsFloat(0);
andrew@2 227 drumTracker.doBeatCorrection(beatCorrValue);
andrew@2 228
andrew@2 229 }//end correction by
andrew@2 230
andrew@2 231
andrew@2 232 if ( m.getAddress() == "/BayesianNoise" ){
andrew@2 233 drumTracker.beatDistribution.likelihoodNoise = m.getArgAsFloat(0);;
andrew@2 234 printf("bayesian noise set to %f\n", drumTracker.beatDistribution.likelihoodNoise);
andrew@2 235 // beatDistribution.setGaussianLikelihood(beatDistribution.likelihoodMean, beatDistribution.likelihoodStdDev);
andrew@2 236 }
andrew@2 237
andrew@2 238 if ( m.getAddress() == "/BayesianStdDev" ){
andrew@2 239 drumTracker.beatDistribution.likelihoodStdDev = ARRAY_SIZE / m.getArgAsFloat(0);
andrew@2 240 // beatDistribution.setGaussianLikelihood(beatDistribution.likelihoodMean, beatDistribution.likelihoodStdDev);
andrew@2 241 }
andrew@2 242
andrew@2 243
andrew@2 244 }//end while there is new message
andrew@2 245
andrew@2 246
andrew@2 247 }
andrew@2 248
andrew@2 249
andrew@2 250 void testApp::takePictureOfScreen(){
andrew@2 251 // grab a rectangle at 200,200, width and height of 300,180
andrew@2 252 img.grabScreen(0,0,screenWidth,screenHeight);
andrew@2 253 char fileName[255];
andrew@2 254 sprintf(fileName, "snapshot_%0.3i.png", snapCounter);
andrew@2 255 img.saveImage(fileName);
andrew@2 256 //printf("saved %s\n", fileName);
andrew@2 257 snapCounter++;
andrew@2 258 bSnapshot = false;
andrew@2 259 }
andrew@2 260
andrew@2 261 /*
andrew@2 262 void testApp::setBeatDistribution(int beatPosition){
andrew@2 263 switch (beatPosition){
andrew@2 264 //early sixteenth is that the beat is a sixteenth earlier
andrew@2 265 case 0:
andrew@2 266 case 1:
andrew@2 267 case 11:
andrew@2 268 //i.e. these zones are interpreted as "on the beat"
andrew@2 269 beatDistribution.eighthNoteProportion = 0;
andrew@2 270 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@2 271 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@2 272 break;
andrew@2 273 //10 and 2 were here
andrew@2 274
andrew@2 275 case 2:
andrew@2 276 beatDistribution.eighthNoteProportion = 0;
andrew@2 277 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
andrew@2 278 //i.e. a 25% chance it is early sixteenth - 75% that the beat actually lies here
andrew@2 279 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@2 280 break;
andrew@2 281
andrew@2 282 case 3:
andrew@2 283 beatDistribution.eighthNoteProportion = 0;
andrew@2 284 beatDistribution.earlySixteenthNoteProportion = 0.3;//was 0.4 in Bayesian8 //half chance it is early
andrew@2 285 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@2 286 break;
andrew@2 287
andrew@2 288 case 5:
andrew@2 289 case 6:
andrew@2 290 case 7:
andrew@2 291 beatDistribution.eighthNoteProportion = 0.3;//i.e. nearly half a chance we are on the 8th note
andrew@2 292 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@2 293 beatDistribution.lateSixteenthNoteProportion = 0;
andrew@2 294 break;
andrew@2 295
andrew@2 296 case 4:
andrew@2 297 beatDistribution.eighthNoteProportion = 0;
andrew@2 298 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
andrew@2 299 beatDistribution.lateSixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
andrew@2 300 //chsanged to 0.2 and 0.1 then back
andrew@2 301 break;
andrew@2 302
andrew@2 303 case 8:
andrew@2 304 beatDistribution.eighthNoteProportion = 0;
andrew@2 305 beatDistribution.earlySixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
andrew@2 306 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
andrew@2 307 break;
andrew@2 308
andrew@2 309 case 9:
andrew@2 310 beatDistribution.eighthNoteProportion = 0;
andrew@2 311 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@2 312 beatDistribution.lateSixteenthNoteProportion = 0.35;//was 0.4 in Bayesian8
andrew@2 313 break;
andrew@2 314
andrew@2 315 case 10:
andrew@2 316 beatDistribution.eighthNoteProportion = 0;
andrew@2 317 beatDistribution.earlySixteenthNoteProportion = 0;
andrew@2 318 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.2 in Bayesian8
andrew@2 319 break;
andrew@2 320
andrew@2 321 }
andrew@2 322
andrew@2 323 }
andrew@2 324 */
andrew@2 325 //--------------------------------------------------------------
andrew@2 326 void testApp::draw(){
andrew@2 327 //--------------------------- lines
andrew@2 328 // a bunch of red lines, make them smooth if the flag is set
andrew@2 329
andrew@2 330
andrew@2 331
andrew@2 332 if (bSmooth){
andrew@2 333 ofEnableSmoothing();
andrew@2 334 }
andrew@2 335
andrew@2 336 switch (screenToDraw){
andrew@2 337 case 0:
andrew@2 338 drawBayesianDistribution();
andrew@2 339 break;
andrew@2 340 case 1:
andrew@2 341 drawTempoDistribution();
andrew@2 342 break;
andrew@2 343 case 2:
andrew@2 344 drawBeatMap();
andrew@2 345 break;
andrew@2 346 case 3:
andrew@2 347 // drawNormalisedLikelihood();
andrew@2 348 drawRestrictedTempoDistribution(tempoWindowMinimum, tempoWindowMaximum);
andrew@2 349 break;
andrew@2 350 case 4:
andrew@2 351 drawTempoData();
andrew@2 352 break;
andrew@2 353 case 5:
andrew@2 354 drawBeatProbabilityDistribution();
andrew@2 355 break;
andrew@2 356 case 6:
andrew@2 357 drawPosterior();
andrew@2 358 break;
andrew@2 359 case 7:
andrew@2 360 drawGreyscaleBayesianDistribution();
andrew@2 361 break;
andrew@2 362
andrew@2 363 }
andrew@2 364
andrew@2 365
andrew@2 366
andrew@2 367 if (bSnapshot == true){
andrew@2 368 takePictureOfScreen();
andrew@2 369 bSnapshot = false;
andrew@2 370 }
andrew@2 371
andrew@3 372
andrew@3 373
andrew@3 374 drawKLdivAndEntropy();
andrew@3 375
andrew@3 376 }//end draw
andrew@3 377
andrew@3 378
andrew@3 379 void testApp::drawKLdivAndEntropy(){
andrew@2 380 ofDrawBitmapString("KLdiv :"+ofToString(KLdiv, 3), 20, 40);
andrew@2 381 ofSetColor(200,0,0,160);
andrew@2 382 ofRect(0, ofGetHeight()*(1-KLdiv), 40, ofGetHeight()*KLdiv);
andrew@2 383
andrew@3 384 ofSetColor(0,0, 200, 160);
andrew@3 385 ofDrawBitmapString("Entropy :"+ofToString(entropy, 3), 20, 60);
andrew@3 386 double entropyDrawFactor = 0.1;
andrew@3 387 ofRect(60, ofGetHeight()*(1-entropy*entropyDrawFactor), 40, ofGetHeight()*entropy*entropyDrawFactor);
andrew@3 388 }
andrew@2 389
andrew@2 390
andrew@2 391 void testApp::drawTempoData(){
andrew@2 392
andrew@2 393 ofSetColor(0xFFFF00);
andrew@2 394 //yellow line in centre
andrew@2 395 ofLine( 0, (screenHeight/2), screenWidth, (screenHeight/2));
andrew@2 396
andrew@2 397 ofSetColor(0x0000FF);
andrew@2 398 int tempoIndex = 0;
andrew@2 399 int widthOffset = 20;
andrew@2 400 float stepWidth = screenWidth / 16;
andrew@2 401 ofDrawBitmapString("tatums : ", 600,180);
andrew@2 402 ofDrawBitmapString(ofToString(drumTracker.beatTimes.tatum, 1), 700,180);
andrew@2 403 ofDrawBitmapString("bpm : ", 600,200);
andrew@2 404 ofDrawBitmapString(ofToString((drumTracker.beatTimes.tatum/30000), 1), 700,200);
andrew@2 405 int intervalIndex;
andrew@2 406 int intervalWidth = 2;
andrew@2 407 float magnifyingFactor = 8;
andrew@2 408 for (tempoIndex = 0;tempoIndex < 16; tempoIndex++){
andrew@2 409
andrew@2 410 for (intervalIndex = 0;intervalIndex < 16;intervalIndex++){
andrew@2 411 //new color code
andrew@2 412 if (drumTracker.beatTimes.intervalUsed[tempoIndex][intervalIndex] == true){
andrew@2 413 ofSetColor(0x00FFFF);
andrew@2 414 }
andrew@2 415 else{
andrew@2 416 ofSetColor(0xFF00FF);
andrew@2 417 }
andrew@2 418 //end new code
andrew@2 419
andrew@2 420 ofLine((stepWidth*tempoIndex)+ (intervalWidth*intervalIndex) + widthOffset, screenHeight,
andrew@2 421 (stepWidth*tempoIndex) + (intervalWidth*intervalIndex) + widthOffset, (screenHeight/2) * (1 + (magnifyingFactor * (1-drumTracker.beatTimes.intervalDifferences[tempoIndex][intervalIndex]))));
andrew@2 422
andrew@2 423 if (printInterval == true){
andrew@2 424 ofDrawBitmapString(ofToString(drumTracker.beatTimes.intervalDifferences[tempoIndex][intervalIndex], 3),
andrew@2 425 (stepWidth*tempoIndex) + widthOffset,20+(intervalIndex*20));
andrew@2 426 }
andrew@2 427
andrew@2 428
andrew@2 429 ofDrawBitmapString(ofToString(drumTracker.beatTimes.relativeIntervals[tempoIndex][0], 3), 700,220+(tempoIndex*20));
andrew@2 430 ofDrawBitmapString(ofToString(drumTracker.beatTimes.relativeIntervals[tempoIndex][1], 1), 750,220+(tempoIndex*20));
andrew@2 431 }//end for interval index
andrew@2 432 }//end for tempo index
andrew@2 433
andrew@2 434 ofDrawBitmapString(ofToString(drumTracker.beatTimes.clickIndex), 750,20);
andrew@2 435
andrew@2 436 ofDrawBitmapString(ofToString(mouseBPM), 50,20);
andrew@2 437 ofDrawBitmapString(drumTracker.tempoDataString, 50, 100);
andrew@2 438
andrew@2 439 }//end draw tempo data
andrew@2 440
andrew@2 441
andrew@2 442 void testApp::drawTempoDistribution(){
andrew@2 443 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 444 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
andrew@2 445 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
andrew@2 446
andrew@2 447 maximum *= 1.1;
andrew@2 448
andrew@2 449 float stepHeight = screenHeight/maximum;
andrew@2 450
andrew@2 451
andrew@2 452
andrew@2 453 //draw prior in green
andrew@2 454 ofSetColor(0x888888);
andrew@2 455 for (int i = 1; i < ARRAY_SIZE; i+=2){
andrew@2 456 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i]*stepHeight));
andrew@2 457 }
andrew@2 458
andrew@2 459
andrew@2 460 //draw posterior in dark
andrew@2 461 ofSetColor(0x000000);
andrew@2 462 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 463 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i]*stepHeight));
andrew@2 464 }
andrew@2 465
andrew@2 466
andrew@2 467 //black line is the max probability
andrew@2 468 ofSetColor(0x000000);
andrew@2 469 ofLine(drumTracker.tempoDistribution.integratedEstimate *stepSize, screenHeight, drumTracker.tempoDistribution.integratedEstimate *stepSize, 0);
andrew@2 470
andrew@2 471 //blue is the current kick received
andrew@2 472 ofSetColor(0xAAAAAA);
andrew@2 473
andrew@2 474 int altIndex = 0;
andrew@2 475 for (altIndex = 0;altIndex< 16;altIndex++){
andrew@2 476
andrew@2 477 double tempoInterval = drumTracker.beatTimes.intervalDifferences[drumTracker.beatTimes.index][altIndex];
andrew@2 478
andrew@2 479 if (altIndex != drumTracker.beatTimes.index && tempoInterval > drumTracker.tempoMinimum && tempoInterval < drumTracker.tempoMaximum){
andrew@2 480
andrew@2 481
andrew@2 482
andrew@2 483 //draw likelihood
andrew@2 484 //draw likelhood in blue
andrew@2 485 // //need to reset likelihood for this!
andrew@2 486 //XXX remove
andrew@2 487 double timeInterval = drumTracker.beatTimes.beatTimes[drumTracker.beatTimes.index] - drumTracker.beatTimes.beatTimes[altIndex];
andrew@2 488 if (timeInterval > 2*drumTracker.tempoMinimum && timeInterval < 2*drumTracker.tempoMaximum)
andrew@2 489 {
andrew@2 490
andrew@2 491 ofLine(stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)), screenHeight,
andrew@2 492 stepSize*(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)) , 0);
andrew@2 493
andrew@2 494 drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
andrew@2 495 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 496 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i]*stepHeight));
andrew@2 497 }
andrew@2 498 }
andrew@2 499
andrew@2 500 }
andrew@2 501
andrew@2 502 }//end for
andrew@2 503
andrew@2 504 if (bSmooth){
andrew@2 505 ofDisableSmoothing();
andrew@2 506 }
andrew@2 507
andrew@2 508 drawTempoInfo();
andrew@2 509
andrew@2 510 }
andrew@2 511
andrew@2 512
andrew@2 513 int testApp::xcoordinateFromTempoDataPoint(float f){
andrew@2 514 //f is the time
andrew@2 515
andrew@2 516 int xcoordinateForInterval = 0;
andrew@2 517 if (f >= drumTracker.tempoMinimum && f <= drumTracker.tempoMaximum)
andrew@2 518 xcoordinateForInterval = ((float)(f - drumTracker.tempoMinimum)*screenWidth/(float)(drumTracker.tempoMaximum - drumTracker.tempoMinimum));
andrew@2 519 return xcoordinateForInterval;
andrew@2 520
andrew@2 521 }
andrew@2 522
andrew@2 523
andrew@2 524 int testApp::xcoordinateFromRestrictedTempoDataPoint(float f, const int& tmpMin, const int& tmpMax){
andrew@2 525
andrew@2 526
andrew@2 527 int xcoordinateForInterval = -1;
andrew@2 528 if (f >= drumTracker.tempoMinimum+tmpMin && f <= min(drumTracker.tempoMinimum+tmpMax,drumTracker.tempoMaximum))
andrew@2 529 xcoordinateForInterval = ((float)(f - drumTracker.tempoMinimum - tmpMin*arrayToMsecScaleFactor)*screenWidth/(float)((tmpMax - tmpMin)*arrayToMsecScaleFactor));
andrew@2 530 return xcoordinateForInterval;
andrew@2 531
andrew@2 532 }
andrew@2 533
andrew@2 534
andrew@2 535 void testApp::drawTempoInfo(){
andrew@2 536 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 537 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
andrew@2 538 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
andrew@2 539
andrew@2 540
andrew@2 541 ofSetColor(0x000000);
andrew@2 542 string testString;
andrew@2 543 testString = "max is ";
andrew@2 544 testString += ofToString(maximum);
andrew@2 545 ofDrawBitmapString(testString, 700,620);
andrew@2 546
andrew@2 547 ofDrawBitmapString(msg_string, 700,650);
andrew@2 548
andrew@2 549 ofDrawBitmapString(kickString, 700,670);
andrew@2 550
andrew@2 551 testString = "std dev : ";
andrew@2 552 testString += ofToString(drumTracker.tempoStdDev, 6);
andrew@2 553
andrew@2 554 testString += ", ";
andrew@2 555 testString += ofToString(drumTracker.accompanimentStarted);
andrew@2 556 ofDrawBitmapString(testString, 20, 120);
andrew@2 557
andrew@2 558 int tempoUpdateIndex;
andrew@2 559 for (tempoUpdateIndex = 0;tempoUpdateIndex<16;tempoUpdateIndex++){
andrew@2 560 // ofDrawBitmapString(tempoUpdateStrings[tempoUpdateIndex], 700, 200 + (20 * tempoUpdateIndex));
andrew@2 561 }
andrew@2 562
andrew@2 563 ofDrawBitmapString("Mouse located at tempo: ", 50,10);
andrew@2 564 ofDrawBitmapString(ofToString(mouseBPM, 1), 50,20);
andrew@2 565
andrew@2 566 ofDrawBitmapString("Current tempo: ", 50,40);
andrew@2 567 ofDrawBitmapString(ofToString(30000/drumTracker.beatTimes.tatum, 1), 50,50);
andrew@2 568
andrew@2 569 ofDrawBitmapString(drumTracker.tempoDataString, 50, 100);
andrew@2 570
andrew@2 571
andrew@2 572 for (int i = 1;i < 16; i++){
andrew@2 573 for (int altIndex = 0; altIndex < 16;altIndex++){
andrew@2 574 string newString;
andrew@2 575 newString = " :";
andrew@2 576 int recentIndex = (altIndex-i+16)%16;
andrew@2 577 if (drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex] > 0 && drumTracker.beatTimes.intervalUsed[altIndex][recentIndex]){
andrew@2 578
andrew@2 579
andrew@2 580 int xcoordinateForInterval = xcoordinateFromTempoDataPoint(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex]);
andrew@2 581 float beatInterval = (float) drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2;
andrew@2 582
andrew@2 583 if (drumTracker.beatTimes.OnsetIsKick[altIndex])
andrew@2 584 ofSetColor(255*(8-beatInterval)/(float)8, 0, 255*beatInterval/(float)8);
andrew@2 585 else
andrew@2 586 ofSetColor(0, 255*(8-beatInterval)/(float)8, 255*beatInterval/(float)8);
andrew@2 587 //red kick, green snare
andrew@2 588
andrew@2 589 ofCircle(xcoordinateForInterval, 200 + (altIndex * 20), 3);
andrew@2 590
andrew@2 591 newString += ofToString(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex],0);
andrew@2 592 newString += " (";
andrew@2 593 newString += ofToString(drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2, 0);
andrew@2 594 newString += ")";
andrew@2 595
andrew@2 596 }
andrew@2 597 ofSetColor(0,0,0);
andrew@2 598 //ofDrawBitmapString(newString, 200 + i*80, 200 + (altIndex * 20));
andrew@2 599
andrew@2 600
andrew@2 601 }
andrew@2 602 }
andrew@2 603
andrew@2 604 }
andrew@2 605
andrew@2 606
andrew@2 607
andrew@2 608
andrew@2 609 void testApp::drawTempoDataPoints(const int& tmpMin, const int& tmpMax, const float& tmpStepSize){
andrew@2 610
andrew@2 611 for (int i = 1;i < 16; i++){
andrew@2 612 for (int altIndex = 0; altIndex < 16;altIndex++){
andrew@2 613 // string newString;
andrew@2 614 // newString = " :";
andrew@2 615
andrew@2 616 int recentIndex = (altIndex-i+16)%16;
andrew@2 617 if (drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex] > 0 && drumTracker.beatTimes.intervalUsed[altIndex][recentIndex]){
andrew@2 618
andrew@2 619 int xcoordinateForInterval = xcoordinateFromRestrictedTempoDataPoint(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex], tmpMin, tmpMax);
andrew@2 620 float beatInterval = (float) drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2;
andrew@2 621
andrew@2 622 if (drumTracker.beatTimes.OnsetIsKick[altIndex])
andrew@2 623 ofSetColor(255*(7-beatInterval+1)/(float)7, 255*(beatInterval-1)/(float)7, 0);//100+155*(8-beatInterval)/(float)8
andrew@2 624 else
andrew@2 625 ofSetColor(0, 255*(7-beatInterval+1)/(float)7, 255*(beatInterval-1)/(float)7);//, 155*beatInterval/(float)8);
andrew@2 626 //red kick, green snare
andrew@2 627
andrew@2 628 ofCircle(xcoordinateForInterval, 200 + (altIndex * 20), 3);
andrew@2 629 ofDrawBitmapString(ofToString(beatInterval, 0), xcoordinateForInterval-2, 200 + (altIndex * 20) - 3);
andrew@2 630 /* newString += ofToString(beatTimes.intervalDifferences[altIndex][recentIndex],0);
andrew@2 631 newString += " (";
andrew@2 632 newString += ofToString(beatTimes.tatumMultiples[altIndex][recentIndex]/2, 0);
andrew@2 633 newString += ")";
andrew@2 634 */
andrew@2 635 }
andrew@2 636 ofSetColor(0,0,0);
andrew@2 637 //ofDrawBitmapString(newString, 200 + i*80, 200 + (altIndex * 20));
andrew@2 638
andrew@2 639
andrew@2 640 }
andrew@2 641 }
andrew@2 642
andrew@2 643 }
andrew@2 644
andrew@2 645
andrew@2 646 void testApp::drawRestrictedTempoDistribution(int tmpMin, int tmpMax){
andrew@2 647 //min and max are in the tempo array coordinates
andrew@2 648
andrew@2 649 tmpMin = max(tmpMin, 0);
andrew@2 650 tmpMax = min(tmpMax, ARRAY_SIZE-1);
andrew@2 651
andrew@2 652 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 653 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
andrew@2 654 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
andrew@2 655
andrew@2 656 maximum *= 1.1;
andrew@2 657
andrew@2 658 float stepHeight = screenHeight/maximum;
andrew@2 659 int tmpWidth = tmpMax - 1 - tmpMin;
andrew@2 660 float tmpStepSize = screenWidth / (float) tmpWidth;
andrew@2 661
andrew@2 662
andrew@2 663 //draw prior in green
andrew@2 664 ofSetColor(0x888888);
andrew@2 665 for (int i = 1; i < tmpWidth; i+=2){
andrew@2 666 ofLine((i-1)*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.prior[tmpMin+i-1]*stepHeight), i * tmpStepSize, screenHeight - (drumTracker.tempoDistribution.prior[tmpMin+i]*stepHeight));
andrew@2 667 }
andrew@2 668
andrew@2 669
andrew@2 670 //draw posterior in dark
andrew@2 671 ofSetColor(0x000000);
andrew@2 672 for (int i = 1; i < tmpWidth; i++){
andrew@2 673 ofLine((i-1) * tmpStepSize, screenHeight - (drumTracker.tempoDistribution.posterior[tmpMin+i-1]*stepHeight), i*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.posterior[tmpMin+i]*stepHeight));
andrew@2 674 }
andrew@2 675
andrew@2 676
andrew@2 677 //black line is the max probability
andrew@2 678 ofSetColor(0x000000);
andrew@2 679 ofLine((drumTracker.tempoDistribution.integratedEstimate - tmpMin)* tmpStepSize, screenHeight, (drumTracker.tempoDistribution.integratedEstimate-tmpMin) *tmpStepSize, 0);
andrew@2 680
andrew@2 681 //blue is the current kick received
andrew@2 682 ofSetColor(0xAAAAAA);
andrew@2 683
andrew@2 684 int altIndex = 0;
andrew@2 685 for (altIndex = 0;altIndex< 16;altIndex++){
andrew@2 686 //iterate through all recent beat intervals
andrew@2 687
andrew@2 688 double tempoInterval = drumTracker.beatTimes.intervalDifferences[drumTracker.beatTimes.index][altIndex];
andrew@2 689
andrew@2 690 if (altIndex != drumTracker.beatTimes.index && tempoInterval > drumTracker.tempoMinimum && tempoInterval < drumTracker.tempoMaximum){
andrew@2 691
andrew@2 692 double timeInterval = drumTracker.beatTimes.beatTimes[drumTracker.beatTimes.index] - drumTracker.beatTimes.beatTimes[altIndex];
andrew@2 693
andrew@2 694 if (timeInterval > 2*drumTracker.tempoMinimum && timeInterval < 2*drumTracker.tempoMaximum){
andrew@2 695 //i.e. within the beat range only
andrew@2 696 //so we only draw the likelihood realtime for happening beat intervals
andrew@2 697 //in fact much more is going on than this but harder to visualise
andrew@2 698
andrew@2 699 float indexOfNewLocation = ARRAY_SIZE*(tempoInterval-drumTracker.tempoMinimum)/(float)(drumTracker.tempoMaximum - drumTracker.tempoMinimum);
andrew@2 700
andrew@2 701
andrew@2 702 if (indexOfNewLocation >= tmpMin){
andrew@2 703 ofLine(tmpStepSize * (indexOfNewLocation-tmpMin), screenHeight, tmpStepSize * (indexOfNewLocation-tmpMin) , 0);
andrew@2 704 }
andrew@2 705
andrew@2 706
andrew@2 707 drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
andrew@2 708 //setting the tempo distribution likeihood just for visualisation purposes
andrew@2 709 for (int i = 1; i < tmpWidth; i++){
andrew@2 710 ofLine((i-1)*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i+tmpMin-1]*stepHeight), i*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i+tmpMin]*stepHeight));
andrew@2 711
andrew@2 712 }
andrew@2 713 }
andrew@2 714
andrew@2 715 }
andrew@2 716
andrew@2 717 }//end for
andrew@2 718
andrew@2 719 if (bSmooth){
andrew@2 720 ofDisableSmoothing();
andrew@2 721 }
andrew@2 722
andrew@2 723
andrew@2 724 drawTempoDataPoints(tmpMin, tmpMax, tmpStepSize);
andrew@2 725
andrew@2 726 // lines for background
andrew@2 727 for (int i = tmpMin-(tmpMin%20);i < tmpMax; i+=20){
andrew@2 728 ofSetColor(0,0,200,100);
andrew@2 729 ofLine(tmpStepSize * (i-tmpMin), screenHeight, tmpStepSize * (i-tmpMin) , 0);
andrew@2 730 string tmpTempoString = ofToString(drumTracker.tempoMinimum + i*arrayToMsecScaleFactor, 0);
andrew@2 731 ofDrawBitmapString(tmpTempoString, tmpStepSize * (i-tmpMin) , 20);
andrew@2 732 }
andrew@2 733
andrew@2 734 string currentTatumString = "Beat Period : ";
andrew@2 735 currentTatumString += ofToString(drumTracker.beatTimes.tatum, 1);
andrew@2 736 currentTatumString += " MaxIndex : ";
andrew@2 737 currentTatumString += ofToString(drumTracker.tempoDistribution.integratedEstimate, 1);
andrew@2 738
andrew@2 739 ofDrawBitmapString(currentTatumString, 20, 40);
andrew@2 740 //drawTempoInfo();
andrew@2 741
andrew@2 742 }
andrew@2 743
andrew@2 744
andrew@2 745
andrew@2 746
andrew@2 747
andrew@2 748
andrew@2 749
andrew@2 750
andrew@2 751
andrew@2 752
andrew@2 753
andrew@2 754 void testApp::drawBeatMap(){
andrew@2 755 int x,y;
andrew@2 756
andrew@2 757 for (x=0;x < 6;x++){
andrew@2 758 for (y=0;y<8;y++){
andrew@2 759 int cell = x+(y*6);
andrew@2 760 if (cell == drumTracker.beatTimes.beatSegment){
andrew@2 761 if (drumTracker.beatTimes.beatMap[cell] == 1)//for kick
andrew@2 762 ofSetColor(drumTracker.beatTimes.beatMap[cell]*255, 0, 0);
andrew@2 763
andrew@2 764 if (drumTracker.beatTimes.beatMap[cell] == 2)//for kick
andrew@2 765 ofSetColor(0, drumTracker.beatTimes.beatMap[cell]*255, 100);
andrew@2 766
andrew@2 767 }
andrew@2 768 else{
andrew@2 769 if (drumTracker.beatTimes.beatMap[cell] == 1)//for kick
andrew@2 770 ofSetColor(drumTracker.beatTimes.beatMap[cell]*155, 0, 0);
andrew@2 771 else //for snare
andrew@2 772 ofSetColor(0,drumTracker.beatTimes.beatMap[cell]*155, 0);//beatTimes.beatMap[cell]*155);
andrew@2 773
andrew@2 774 }
andrew@2 775 ofRect(screenWidth*x/6, screenHeight*y/8, screenWidth/6, screenHeight/8);
andrew@2 776
andrew@2 777 ofSetColor(255,0,0);
andrew@2 778 ofDrawBitmapString(ofToString(x+(y*6)), screenWidth*x/6, screenHeight*y/8);
andrew@2 779
andrew@2 780 if (drumTracker.beatTimes.beatMap[cell] == 1){
andrew@2 781 ofSetColor(0,255,255);//
andrew@2 782 ofDrawBitmapString(ofToString(drumTracker.beatTimes.beatMapTimeDifferences[cell], 2), (screenWidth*(x+0.5)/6) , (screenHeight*(y+0.5)/8) );
andrew@2 783 }
andrew@2 784 if (drumTracker.beatTimes.beatMap[cell] == 2){
andrew@2 785 ofSetColor(0,0,100);//
andrew@2 786 ofDrawBitmapString(ofToString(drumTracker.beatTimes.beatMapTimeDifferences[cell], 2), (screenWidth*(x+0.5)/6) , (screenHeight*(y+0.5)/8) );
andrew@2 787 }
andrew@2 788
andrew@2 789
andrew@2 790 }
andrew@2 791 }
andrew@2 792
andrew@2 793 }
andrew@2 794
andrew@2 795
andrew@2 796
andrew@2 797
andrew@2 798 void testApp::drawBeatProbabilityDistribution(){
andrew@2 799 int x,y;
andrew@2 800
andrew@2 801 for (x=0;x < 6;x++){
andrew@2 802 for (y=0;y<4;y++){
andrew@2 803 int cell = x+(y*6);
andrew@2 804 ofSetColor(drumTracker.beatTimes.beatProbabilityDistribution[y][x][0]*255, 0, 0);
andrew@2 805 ofRect(screenWidth*x/6, screenHeight*y/8, screenWidth/6, screenHeight/8);
andrew@2 806 }
andrew@2 807 }
andrew@2 808 for (x=0;x < 6;x++){
andrew@2 809 for (y=0;y<4;y++){
andrew@2 810 int cell = x+(y*6);
andrew@2 811 ofSetColor(0, drumTracker.beatTimes.beatProbabilityDistribution[y][x][1]*255, 0);
andrew@2 812 ofRect(screenWidth*x/6, screenHeight*(y+4)/8, screenWidth/6, screenHeight/8);
andrew@2 813 }
andrew@2 814 }
andrew@2 815
andrew@2 816 }
andrew@2 817
andrew@2 818
andrew@2 819 void testApp::drawNormalisedLikelihood(){
andrew@2 820 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 821 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
andrew@2 822 //maximum = max(maximum, beatDistribution.getMaximum(&beatDistribution.posterior[0], ARRAY_SIZE));
andrew@2 823 float stepHeight = screenHeight/maximum;
andrew@2 824
andrew@2 825 if (!hidePriorMode){
andrew@2 826 //draw likelhood in blue
andrew@2 827
andrew@2 828 ofSetColor(0x0000FF);
andrew@2 829 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 830 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
andrew@2 831 }
andrew@2 832
andrew@2 833 //draw prior in green
andrew@2 834 ofSetColor(0x00AA00);
andrew@2 835 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 836 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
andrew@2 837 }
andrew@2 838 }//end hide prior mode
andrew@2 839
andrew@2 840
andrew@2 841
andrew@2 842 }
andrew@2 843
andrew@2 844
andrew@2 845
andrew@2 846 void testApp::drawPosterior(){
andrew@2 847 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE);
andrew@2 848
andrew@2 849 if (drumTracker.posteriorMaximum < maximum){
andrew@2 850 drumTracker.posteriorMaximum = 1.2*maximum;
andrew@2 851 }
andrew@2 852
andrew@2 853 float stepHeight = screenHeight/drumTracker.posteriorMaximum;
andrew@2 854 ofSetColor(0xFF00FF);
andrew@2 855 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 856 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
andrew@2 857 }
andrew@2 858
andrew@2 859
andrew@2 860 //yellow is the middle
andrew@2 861 ofSetColor(0xFFFF00);
andrew@2 862 ofLine(ARRAY_SIZE*stepSize/2, screenHeight, ARRAY_SIZE*stepSize/2, 0);
andrew@2 863
andrew@2 864
andrew@2 865
andrew@2 866 //blue is the current kick received
andrew@2 867 ofSetColor(0x0000FF);
andrew@2 868 ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), screenHeight,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), 0);
andrew@2 869
andrew@2 870 //purple line is the integrated max probability
andrew@2 871 int integratedBeatEstimateDrawPoint = round(drumTracker.beatDistribution.integratedEstimate*stepSize) ;
andrew@2 872 ofSetColor(0xFF22FF);
andrew@2 873 ofLine(integratedBeatEstimateDrawPoint, screenHeight, integratedBeatEstimateDrawPoint, 0);
andrew@2 874
andrew@2 875 string testString = "maximum: ";
andrew@2 876 testString += ofToString(drumTracker.posteriorMaximum, 2);
andrew@2 877 ofDrawBitmapString(testString, 100,120);
andrew@2 878
andrew@2 879
andrew@2 880 }
andrew@2 881
andrew@2 882
andrew@2 883
andrew@2 884
andrew@2 885
andrew@2 886 void testApp::drawBayesianDistribution(){
andrew@2 887 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 888 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
andrew@2 889 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
andrew@2 890 float stepHeight = screenHeight/maximum;
andrew@2 891
andrew@2 892 if (!hidePriorMode){
andrew@2 893 //draw likelhood in blue
andrew@2 894 if (drumTracker.onsetType == "kick")
andrew@2 895 ofSetColor(0xff0000);//red : kick
andrew@2 896 else
andrew@2 897 ofSetColor(0x00FF00);//green : snare
andrew@2 898
andrew@2 899 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 900 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
andrew@2 901 }
andrew@2 902
andrew@2 903 //;line where the current kick is received
andrew@2 904 ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), screenHeight,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), 0);
andrew@2 905
andrew@2 906
andrew@2 907 //draw prior in aqua blue
andrew@2 908 ofSetColor(0x00AAAA);
andrew@2 909 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 910 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
andrew@2 911 }
andrew@2 912 }//end hide prior mode
andrew@2 913
andrew@2 914 //draw posterior in red
andrew@2 915 ofSetColor(0x0000FF);
andrew@2 916 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 917 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
andrew@2 918 }
andrew@2 919
andrew@2 920 //draw the previous updated posteriror in purple
andrew@2 921 /* ofSetColor(0xFF22FF);
andrew@2 922 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 923 ofLine((i-1)*stepSize, screenHeight - (tmpArray[i-1]*stepHeight), i*stepSize, screenHeight - (tmpArray[i]*stepHeight));
andrew@2 924 }
andrew@2 925 */
andrew@2 926
andrew@2 927 //yellow is the middle
andrew@2 928 ofSetColor(0xFFFF00);
andrew@2 929 ofLine(ARRAY_SIZE*stepSize/2, screenHeight, ARRAY_SIZE*stepSize/2, 0);
andrew@2 930
andrew@2 931 //black line is the max probability
andrew@2 932 ofSetColor(0x000000);
andrew@2 933 ofLine(drumTracker.beatDistribution.maximumIndex*stepSize, screenHeight, drumTracker.beatDistribution.maximumIndex*stepSize, 0);
andrew@2 934
andrew@2 935
andrew@2 936 //purple line is the integrated max probability
andrew@2 937 int integratedBeatEstimate = drumTracker.beatDistribution.integratedEstimate ;
andrew@2 938 ofSetColor(0x2222FF);
andrew@2 939 ofLine(integratedBeatEstimate *stepSize, screenHeight, integratedBeatEstimate *stepSize, 0);
andrew@2 940
andrew@2 941
andrew@2 942 if (bSmooth){
andrew@2 943 ofDisableSmoothing();
andrew@2 944 }
andrew@2 945
andrew@2 946 printBayesianData();
andrew@2 947 }
andrew@2 948
andrew@2 949 void testApp::printBayesianData(){
andrew@2 950 //not optimised!!! XXX
andrew@2 951 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 952 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
andrew@2 953 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
andrew@2 954
andrew@2 955 ofSetColor(0x000000);
andrew@2 956 string testString;
andrew@2 957 testString = "max2 is ";
andrew@2 958 testString += ofToString(maximum, 3);
andrew@2 959 testString += " :: ";
andrew@2 960
andrew@2 961 testString = "correction of ";
andrew@2 962 testString += ofToString(drumTracker.beatCorrection);
andrew@2 963 testString += " corr by :";
andrew@2 964 testString += ofToString(drumTracker.correctBeatBy);
andrew@2 965
andrew@2 966 //ofDrawBitmapString(testString, 100,120);
andrew@2 967
andrew@2 968 testString = "MaxPhase ";
andrew@2 969 testString += ofToString(drumTracker.maxPhase);
andrew@2 970 // ofDrawBitmapString(testString, 100,140);
andrew@2 971
andrew@2 972
andrew@2 973 testString = "Likelihood noise ";
andrew@2 974 testString += ofToString(drumTracker.beatDistribution.likelihoodNoise, 2);
andrew@2 975 //ofDrawBitmapString(testString, 100,160);
andrew@2 976
andrew@2 977 // ofDrawBitmapString(msg_string, 100,140);
andrew@2 978
andrew@2 979 // ofDrawBitmapString(kickString, 100,180);
andrew@2 980
andrew@2 981 /* debugString = "Min Debug = ";
andrew@2 982 debugString += ofToString(drumTracker.tempoDistribution.maximumIndex + drumTracker.minTempoIndex);
andrew@2 983 debugString += " Max Debug = ";
andrew@2 984 debugString += ofToString(drumTracker.tempoDistribution.maximumIndex + drumTracker.maxTempoIndex);
andrew@2 985 */
andrew@2 986 //ofDrawBitmapString(debugString, 300,370);
andrew@2 987
andrew@2 988 debugString = "CLICK INDEX = ";
andrew@2 989 debugString += ofToString(drumTracker.beatTimes.clickIndex);
andrew@2 990 //ofDrawBitmapString(debugString, 100, 20);
andrew@2 991
andrew@2 992 debugString = "STD DEV = ";
andrew@2 993 debugString += ofToString(drumTracker.beatDistribution.standardDeviation, 2);
andrew@2 994 // ofDrawBitmapString(debugString, 100, 40);
andrew@2 995
andrew@2 996
andrew@2 997
andrew@2 998 debugString = "interval ";
andrew@2 999 debugString += ofToString(drumTracker.debugArray[2], 2);
andrew@2 1000 debugString += " time int = ";
andrew@2 1001 debugString += ofToString(drumTracker.debugArray[1], 2);
andrew@2 1002 debugString += " Beat max = ";
andrew@2 1003 debugString += ofToString(drumTracker.debugArray[0 ], 2);
andrew@2 1004 debugString += " Tempo max = ";
andrew@2 1005 debugString += ofToString(drumTracker.debugArray[3 ], 2);
andrew@2 1006 // ofDrawBitmapString(debugString, 300,570);
andrew@2 1007
andrew@2 1008 debugString = " last = ";
andrew@2 1009 debugString += ofToString(drumTracker.beatTimes.lastBeatTime, 2);
andrew@2 1010 // ofDrawBitmapString(debugString, 300,470);
andrew@2 1011
andrew@2 1012
andrew@2 1013 string closestClickString = "Closest Click ";
andrew@2 1014 closestClickString += ofToString(drumTracker.beatTimes.closestClickIndexToBeat[drumTracker.beatTimes.index]);
andrew@2 1015 closestClickString += " beat seg ";
andrew@2 1016 closestClickString += ofToString(drumTracker.beatTimes.beatSegment%12);
andrew@2 1017 closestClickString += " lastCindex";
andrew@2 1018 closestClickString += ofToString(drumTracker.beatTimes.lastClickIndex);
andrew@2 1019 closestClickString += " TD ";
andrew@2 1020 closestClickString += ofToString(drumTracker.beatTimes.timeDifference);
andrew@2 1021
andrew@2 1022 // ofDrawBitmapString(closestClickString, 100,100);
andrew@2 1023
andrew@2 1024 // ofDrawBitmapString(timeString, 100,60);
andrew@2 1025 }
andrew@2 1026
andrew@2 1027
andrew@2 1028
andrew@2 1029 void testApp::drawGreyscaleBayesianDistribution(){
andrew@2 1030 ofSetColor(255,255,255);
andrew@2 1031 ofRect(0,0,screenWidth, screenHeight);
andrew@2 1032
andrew@2 1033 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 1034 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
andrew@2 1035 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
andrew@2 1036 maximum *= 1.1;
andrew@2 1037 float stepHeight = screenHeight/maximum;
andrew@2 1038
andrew@2 1039 if (!hidePriorMode){
andrew@2 1040 //draw likelhood in blue
andrew@2 1041 ofSetColor(0x555555);
andrew@2 1042 for (int i = 1; i < ARRAY_SIZE; i+=2){
andrew@2 1043 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
andrew@2 1044 }
andrew@2 1045
andrew@2 1046 //draw prior in green
andrew@2 1047 ofSetColor(0xAAAAAA);
andrew@2 1048 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 1049 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
andrew@2 1050 }
andrew@2 1051 }//end hide prior mode
andrew@2 1052
andrew@2 1053 //draw posterior in dark grey
andrew@2 1054 ofSetColor(0x222222);
andrew@2 1055 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 1056 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
andrew@2 1057 }
andrew@2 1058
andrew@2 1059 /*
andrew@2 1060 //dotted the middle
andrew@2 1061 ofSetColor(0x555555);
andrew@2 1062 for (int i = 1; i < screenHeight; i+=4){
andrew@2 1063 ofLine(ARRAY_SIZE*stepSize/2, i, ARRAY_SIZE*stepSize/2, i-2);
andrew@2 1064 }
andrew@2 1065 */
andrew@2 1066
andrew@2 1067 //purple line is the integrated max probability
andrew@2 1068 // int integratedBeatEstimate = beatDistribution.integratedEstimate ;
andrew@2 1069 // ofSetColor(0x000000);
andrew@2 1070 // ofLine(integratedBeatEstimate *stepSize, screenHeight, integratedBeatEstimate *stepSize, 0);
andrew@2 1071
andrew@2 1072 //purple line is the integrated max probability
andrew@2 1073 float tmpIntegratedBeatEstimate = drumTracker.beatDistribution.getIntegratedEstimateIndex();
andrew@2 1074 ofSetColor(0x000000);
andrew@2 1075 int drawLinePoint = round(tmpIntegratedBeatEstimate *stepSize);
andrew@2 1076 ofLine(drawLinePoint, screenHeight, drawLinePoint, 0);
andrew@2 1077
andrew@2 1078 //blue is the current kick received
andrew@2 1079 ofSetColor(0x555555);
andrew@2 1080 for (int i = 1; i < screenHeight; i+=40){
andrew@2 1081 ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), i,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), i-20);
andrew@2 1082 }
andrew@2 1083
andrew@2 1084
andrew@2 1085 }
andrew@2 1086
andrew@2 1087
andrew@2 1088
andrew@2 1089
andrew@2 1090 void testApp::drawGreyscaleTempoDistribution(double tempoInterval){
andrew@2 1091 ofSetColor(255,255,255);
andrew@2 1092 ofRect(0,0,screenWidth, screenHeight);
andrew@2 1093
andrew@2 1094 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
andrew@2 1095 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
andrew@2 1096 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
andrew@2 1097
andrew@2 1098 maximum *= 1.1;
andrew@2 1099
andrew@2 1100 float stepHeight = screenHeight/maximum;
andrew@2 1101
andrew@2 1102 //draw prior in green
andrew@2 1103 ofSetColor(0x777777);
andrew@2 1104 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 1105 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i]*stepHeight));
andrew@2 1106 }
andrew@2 1107
andrew@2 1108
andrew@2 1109 //draw posterior in dark
andrew@2 1110 ofSetColor(0x000000);
andrew@2 1111 for (int i = 1; i < ARRAY_SIZE; i++){
andrew@2 1112 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i]*stepHeight));
andrew@2 1113 }
andrew@2 1114
andrew@2 1115
andrew@2 1116 //black line is the max probability
andrew@2 1117 ofSetColor(0xFF0000);
andrew@2 1118 ofLine(drumTracker.tempoDistribution.integratedEstimate *stepSize, screenHeight, drumTracker.tempoDistribution.integratedEstimate *stepSize, 0);
andrew@2 1119
andrew@2 1120 //blue is the current kick received
andrew@2 1121 ofSetColor(0xAAAAAA);
andrew@2 1122
andrew@2 1123
andrew@2 1124
andrew@2 1125
andrew@2 1126 for (int k =1;k < screenHeight/12;k+=2){
andrew@2 1127 ofLine(stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)), 12*k,
andrew@2 1128 stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)) , 12*(k-1));
andrew@2 1129 }
andrew@2 1130
andrew@2 1131 drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
andrew@2 1132 for (int i = 1; i < ARRAY_SIZE; i+=2){
andrew@2 1133 //dotted line likelihood fn
andrew@2 1134 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i]*stepHeight));
andrew@2 1135 }
andrew@2 1136
andrew@2 1137
andrew@2 1138
andrew@2 1139
andrew@2 1140 if (bSmooth){
andrew@2 1141 ofDisableSmoothing();
andrew@2 1142 }
andrew@2 1143
andrew@2 1144 }
andrew@2 1145
andrew@2 1146
andrew@2 1147
andrew@2 1148
andrew@2 1149 //--------------------------------------------------------------
andrew@2 1150 void testApp::keyPressed (int key){
andrew@2 1151 if (key == 's'){
andrew@2 1152 bSmooth = !bSmooth;
andrew@2 1153 }
andrew@2 1154
andrew@2 1155 if (key == 'x'){
andrew@2 1156 printInterval = !printInterval;
andrew@2 1157 }
andrew@2 1158
andrew@2 1159
andrew@2 1160 if (key == 'y'){
andrew@2 1161 drawData = !drawData;
andrew@2 1162 }
andrew@2 1163
andrew@2 1164 if (key == 'f'){
andrew@2 1165 ofToggleFullscreen();
andrew@2 1166 }
andrew@2 1167
andrew@2 1168 if (key == 'h' || key == 'H'){
andrew@2 1169 hidePriorMode = !hidePriorMode;//drawData;
andrew@2 1170 }
andrew@2 1171
andrew@2 1172
andrew@2 1173
andrew@2 1174 if ( key =='a' || key == 'A' )
andrew@2 1175 {
andrew@2 1176
andrew@2 1177 }
andrew@2 1178
andrew@2 1179 if (key == ' '){
andrew@2 1180 drumTracker.paused = !drumTracker.paused;
andrew@2 1181 }
andrew@2 1182
andrew@2 1183 if (key == OF_KEY_RIGHT){
andrew@2 1184 screenToDraw++;
andrew@2 1185 screenToDraw = screenToDraw % NUMBER_OF_SCREENS;
andrew@2 1186 }
andrew@2 1187 if (key == OF_KEY_LEFT){
andrew@2 1188 screenToDraw += NUMBER_OF_SCREENS - 1;
andrew@2 1189 screenToDraw = screenToDraw % NUMBER_OF_SCREENS;
andrew@2 1190 }
andrew@2 1191
andrew@2 1192 if (key == ']')
andrew@2 1193 drumTracker.beatDistribution.translateDistribution(ARRAY_SIZE / 4);
andrew@2 1194
andrew@2 1195 if (key == '[')
andrew@2 1196 drumTracker.beatDistribution.translateDistribution(-1*ARRAY_SIZE / 4);
andrew@2 1197
andrew@2 1198 if (key == 'x'){
andrew@2 1199 bSnapshot = true;
andrew@2 1200 }
andrew@2 1201
andrew@2 1202 if (key == 'q')
andrew@2 1203 drumTracker.adaptiveStandardDeviationMode = !drumTracker.adaptiveStandardDeviationMode;
andrew@2 1204
andrew@2 1205 }
andrew@2 1206
andrew@2 1207 /*
andrew@2 1208 void testApp::sendMaxTempo(){
andrew@2 1209 ofxOscMessage m;
andrew@2 1210 m.setAddress( "/tempo" );
andrew@2 1211
andrew@2 1212 //maxTempo = tempoDistribution.maximumIndex * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
andrew@2 1213 //would be introduced new in bayesian8
andrew@2 1214 maxTempo = drumTracker.tempoDistribution.getIntegratedEstimateIndex() * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
andrew@2 1215 maxTempo += tempoMinimum;
andrew@2 1216
andrew@2 1217
andrew@2 1218 m.addFloatArg( maxTempo );
andrew@2 1219 sender.sendMessage( m );
andrew@2 1220
andrew@2 1221 printf("max tempo %f\n", maxTempo);
andrew@2 1222
andrew@2 1223 }
andrew@2 1224
andrew@2 1225 void testApp::sendMaxPhase(){
andrew@2 1226
andrew@2 1227
andrew@2 1228 // maxPhase = (beatDistribution.maximumIndex - (ARRAY_SIZE/2)) / ARRAY_SIZE;
andrew@2 1229 maxPhase = (drumTracker.beatDistribution.getIntegratedEstimateIndex() - (ARRAY_SIZE/2)) / ARRAY_SIZE;
andrew@2 1230 printf("\nphase index %f :: %i\n", drumTracker.beatDistribution.integratedEstimate , maxPhase);
andrew@2 1231 ofxOscMessage m;
andrew@2 1232 m.setAddress( "/phase" );
andrew@2 1233 m.addFloatArg( maxPhase );
andrew@2 1234 sender.sendMessage( m );
andrew@2 1235
andrew@2 1236 //beatCorrection = maxPhase * beatTimes.tatum / 4;
andrew@2 1237 }
andrew@2 1238 */
andrew@2 1239 //--------------------------------------------------------------
andrew@2 1240 void testApp::keyReleased (int key){
andrew@2 1241
andrew@2 1242 }
andrew@2 1243
andrew@2 1244 //--------------------------------------------------------------
andrew@2 1245 void testApp::mouseMoved(int x, int y ){
andrew@2 1246
andrew@2 1247 mouseBPM = convertToBPM(drumTracker.tempoMinimum+ ((x * (drumTracker.tempoMaximum - drumTracker.tempoMinimum) ) / ofGetWidth() )) ;
andrew@2 1248 }
andrew@2 1249
andrew@2 1250 //--------------------------------------------------------------
andrew@2 1251 void testApp::mouseDragged(int x, int y, int button){
andrew@2 1252 }
andrew@2 1253
andrew@2 1254 //--------------------------------------------------------------
andrew@2 1255 void testApp::mousePressed(int x, int y, int button){
andrew@2 1256 }
andrew@2 1257
andrew@2 1258
andrew@2 1259 //--------------------------------------------------------------
andrew@2 1260 void testApp::mouseReleased(int x, int y, int button){
andrew@2 1261
andrew@2 1262 }
andrew@2 1263
andrew@2 1264 //--------------------------------------------------------------
andrew@2 1265 void testApp::windowResized(int w, int h){
andrew@2 1266 screenWidth = ofGetWidth();
andrew@2 1267 screenHeight = ofGetHeight();
andrew@2 1268 stepSize = screenWidth / (float)(ARRAY_SIZE);
andrew@2 1269 }
andrew@2 1270
andrew@2 1271 double testApp::convertToBPM(double interval){
andrew@2 1272 //interval is in ms and is the tatum interval - eighth nbote - so 250ms for 120bpm
andrew@2 1273 return (30000/interval);
andrew@2 1274
andrew@2 1275 }
andrew@2 1276 /*
andrew@2 1277 noyt needed?
andrew@2 1278 float testApp::tempoIndexToMsec(int index){
andrew@2 1279 float msec;
andrew@2 1280 msec = index * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
andrew@2 1281 msec += tempoMinimum;
andrew@2 1282 return msec;
andrew@2 1283 }
andrew@2 1284
andrew@2 1285 float testApp::beatIndexToMsec(int index){
andrew@2 1286 float msec;
andrew@2 1287 msec = index * maxTempo / ARRAY_SIZE;
andrew@2 1288 msec += tempoMinimum;
andrew@2 1289 return msec;
andrew@2 1290 }
andrew@2 1291 */
andrew@2 1292 /*
andrew@2 1293
andrew@2 1294 bool testApp::filterBeatTime(double newBeatTime){
andrew@2 1295 bool newBeatFound = false;
andrew@2 1296 if ((newBeatTime - beatTimes.lastBeatTime) > 20 || beatTimes.lastBeatTime == 0){
andrew@2 1297
andrew@2 1298 crossUpdateArrays((float)(newBeatTime - beatTimes.lastBeatTime));
andrew@2 1299 beatTimes.lastBeatTime = newBeatTime;
andrew@2 1300 newBeatFound = true;
andrew@2 1301 }
andrew@2 1302 return newBeatFound;
andrew@2 1303 }
andrew@2 1304
andrew@2 1305 void testApp::crossUpdateArrays(float timeInterval){
andrew@2 1306
andrew@2 1307 int finalBeatIndex, tmpTempoIndex, startBeatIndex;
andrew@2 1308 //finalBeat has contribution from BEAT[finalBeat + INT.k] * TEMPO[Max_tempo + k] where INT = INTERVAL
andrew@2 1309 float interval;
andrew@2 1310 interval = timeInterval / maxTempo;//beatTimes.tatum;
andrew@2 1311 tempoDistribution.resetMaximumPosterior();
andrew@2 1312 beatDistribution.resetMaximumPosterior();
andrew@2 1313
andrew@2 1314
andrew@2 1315 int tmpBeatIndex;
andrew@2 1316 //&& interval > 0.8 idea?
andrew@2 1317 if (timeInterval > 0 && timeInterval < 12000 ){//need between 0 and 12 seconds only to update
andrew@2 1318
andrew@2 1319 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
andrew@2 1320
andrew@2 1321 tmpArray[tmpBeatIndex] = 0;
andrew@2 1322 float minusMsecToMakeUp = beatIndexToMsec(tmpBeatIndex) / interval;
andrew@2 1323 float plusMsecToMakeUp = beatIndexToMsec(ARRAY_SIZE - tmpBeatIndex) / interval;
andrew@2 1324 float convertMsecToTempoIndex = ARRAY_SIZE / (tempoMaximum - tempoMinimum) ;
andrew@2 1325
andrew@2 1326
andrew@2 1327 int minTempoIndex = -1 * (int)(minusMsecToMakeUp * convertMsecToTempoIndex);
andrew@2 1328 int maxTempoIndex = (int)(plusMsecToMakeUp * convertMsecToTempoIndex);
andrew@2 1329
andrew@2 1330
andrew@2 1331 if (tmpBeatIndex == beatDistribution.maximumIndex){
andrew@2 1332 minTmpDebug = tempoDistribution.maximumIndex + minTempoIndex;
andrew@2 1333 maxTmpDebug = tempoDistribution.maximumIndex + maxTempoIndex;
andrew@2 1334 debugArray[0] = beatDistribution.maximumIndex;//
andrew@2 1335 debugArray[1] = timeInterval;
andrew@2 1336 debugArray[2] = interval;//beatDistribution.maximumIndex;
andrew@2 1337 debugArray[3] = tempoDistribution.maximumIndex;
andrew@2 1338 }
andrew@2 1339
andrew@2 1340 for (tmpTempoIndex = minTempoIndex;tmpTempoIndex <= maxTempoIndex;tmpTempoIndex++){
andrew@2 1341
andrew@2 1342 if ((tempoDistribution.maximumIndex + tmpTempoIndex) >= 0
andrew@2 1343 && (tempoDistribution.maximumIndex + tmpTempoIndex) < ARRAY_SIZE
andrew@2 1344 && (tmpBeatIndex - (int)(interval*tmpTempoIndex)) >= 0
andrew@2 1345 && (tmpBeatIndex - (int)(interval*tmpTempoIndex))< ARRAY_SIZE){
andrew@2 1346 tmpArray[tmpBeatIndex] += beatDistribution.posterior[tmpBeatIndex - (int)(interval*tmpTempoIndex)] * tempoDistribution.posterior[(int)tempoDistribution.maximumIndex + tmpTempoIndex];
andrew@2 1347 }
andrew@2 1348 }//end for tmpTmepo
andrew@2 1349
andrew@2 1350
andrew@2 1351
andrew@2 1352 }
andrew@2 1353
andrew@2 1354 float tmpFloat;
andrew@2 1355 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
andrew@2 1356 //debug - dont actually update::
andrew@2 1357
andrew@2 1358 tmpFloat = beatDistribution.posterior[tmpBeatIndex];
andrew@2 1359 beatDistribution.posterior[tmpBeatIndex] = tmpArray[tmpBeatIndex];
andrew@2 1360 tmpArray[tmpBeatIndex] = tmpFloat;
andrew@2 1361 }
andrew@2 1362 beatDistribution.renormaliseArray(&beatDistribution.posterior[0], ARRAY_SIZE);
andrew@2 1363
andrew@2 1364 } //end if
andrew@2 1365
andrew@2 1366
andrew@2 1367 }
andrew@2 1368
andrew@2 1369
andrew@2 1370 void testApp::updateTempoProcess(double cpuTime, string onsetDescription){
andrew@2 1371
andrew@2 1372 if (filterBeatTime(cpuTime) == true){
andrew@2 1373 //checks for no repeat
andrew@2 1374
andrew@2 1375 if (onsetDescription == "kick")
andrew@2 1376 beatTimes.addBeatTime(cpuTime, 1);
andrew@2 1377 else
andrew@2 1378 beatTimes.addBeatTime(cpuTime, 2);
andrew@2 1379
andrew@2 1380
andrew@2 1381 //recalculate the distribution
andrew@2 1382 int altIndex = 0;
andrew@2 1383
andrew@2 1384 tempoDataString = "Tatum :";
andrew@2 1385 tempoDataString += ofToString(beatTimes.tatum, 2);
andrew@2 1386 tempoDataString += " BPM ";
andrew@2 1387 tempoDataString += ofToString((double)30000/beatTimes.tatum, 2);
andrew@2 1388
andrew@2 1389 timeString = "Last BEAT ";
andrew@2 1390 timeString += ofToString(beatTimes.lastBeatTime);
andrew@2 1391 timeString += " CLICK ";
andrew@2 1392 timeString += ofToString(beatTimes.lastClickTime);
andrew@2 1393 timeString += " DIFDF ";
andrew@2 1394 timeString += ofToString(beatTimes.timeDifference);
andrew@2 1395 timeString += " segment ";
andrew@2 1396 timeString += ofToString(beatTimes.beatSegment);
andrew@2 1397
andrew@2 1398
andrew@2 1399 for (altIndex = 0;altIndex< 16;altIndex++){
andrew@2 1400 tempoInterval = beatTimes.intervalDifferences[beatTimes.index][altIndex];
andrew@2 1401 integerMultipleOfTatum = beatTimes.relativeIntervals[altIndex][1];
andrew@2 1402
andrew@2 1403
andrew@2 1404 ///NEW VERSION
andrew@2 1405 tempoUpdateStrings[altIndex] = "";
andrew@2 1406 double timeInterval = beatTimes.beatTimes[beatTimes.index] - beatTimes.beatTimes[altIndex];
andrew@2 1407 //raw time difference
andrew@2 1408 beatTimes.intervalDifferences[beatTimes.index][altIndex] = 0;
andrew@2 1409 beatTimes.intervalUsed[beatTimes.index][altIndex] = false;
andrew@2 1410
andrew@2 1411 if (onsetType == "kick")
andrew@2 1412 beatTimes.OnsetIsKick[beatTimes.index] = true;
andrew@2 1413 else
andrew@2 1414 beatTimes.OnsetIsKick[beatTimes.index] = false;
andrew@2 1415
andrew@2 1416
andrew@2 1417
andrew@2 1418 if (!accompanimentStarted){
andrew@2 1419 //if we need to find tempo and start use this method
andrew@2 1420 //we have 'started' once std dev is sufficiently low
andrew@2 1421
andrew@2 1422 updateTempoIfWithinRange(timeInterval);//taken as being the tatum interval
andrew@2 1423
andrew@2 1424
andrew@2 1425
andrew@2 1426 for (int i = 1;i <= 4;i++){
andrew@2 1427 //we test the main beats and the two bar (16 tatum intervals)
andrew@2 1428
andrew@2 1429 double testInterval = timeInterval / 2*i;//pow(2, i);//pow(2.0, i);
andrew@2 1430
andrew@2 1431 if (updateTempoIfWithinRange(testInterval)){
andrew@2 1432 printf("test time %f, beats %i\n", testInterval, i);
andrew@2 1433
andrew@2 1434 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
andrew@2 1435 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
andrew@2 1436 //xx what if two within range here?
andrew@2 1437
andrew@2 1438 tempoUpdateStrings[altIndex] = "Tempo Updates (";
andrew@2 1439 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
andrew@2 1440 tempoUpdateStrings[altIndex] += ") : [";
andrew@2 1441 tempoUpdateStrings[altIndex] += ofToString(altIndex);
andrew@2 1442 tempoUpdateStrings[altIndex] += "]] : ";
andrew@2 1443 tempoUpdateStrings[altIndex] += ofToString(timeInterval);
andrew@2 1444 tempoUpdateStrings[altIndex] += ", ioi:";
andrew@2 1445 tempoUpdateStrings[altIndex] += ofToString(i);
andrew@2 1446 //tempoUpdateStrings[altIndex] += "";
andrew@2 1447
andrew@2 1448 }
andrew@2 1449
andrew@2 1450 }
andrew@2 1451
andrew@2 1452 double testInterval = timeInterval / 16;//pow(2, i);//pow(2.0, i);
andrew@2 1453 if (updateTempoIfWithinRange(testInterval)){
andrew@2 1454 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
andrew@2 1455 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
andrew@2 1456 }
andrew@2 1457
andrew@2 1458 }else{
andrew@2 1459 //OLD VERSON
andrew@2 1460 //THIS USES THE CURRENT TEMPO ESTIMATE TO DECIDE WHAT THE BEST INTERVAL IS
andrew@2 1461 //&& integerMultipleOfTatum % 2 == 0 removed below XXX put back
andrew@2 1462 if (altIndex != beatTimes.index && integerMultipleOfTatum < 17
andrew@2 1463 && integerMultipleOfTatum > 0 && beatTimes.startIndex > 8//beattimes.index > 8 - the start
andrew@2 1464 && integerMultipleOfTatum%2 == 0){//mod 2 - i.e. proper beat intervals only
andrew@2 1465
andrew@2 1466 double testInterval = timeInterval / integerMultipleOfTatum;
andrew@2 1467
andrew@2 1468 if (updateTempoIfWithinRange(testInterval)){
andrew@2 1469
andrew@2 1470 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
andrew@2 1471 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
andrew@2 1472
andrew@2 1473 if (paused == false){
andrew@2 1474 tempoUpdateStrings[altIndex] = "Tempo Updates : (";
andrew@2 1475 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
andrew@2 1476 tempoUpdateStrings[altIndex] += ") : [";
andrew@2 1477 tempoUpdateStrings[altIndex] += ofToString(altIndex, 0);
andrew@2 1478 tempoUpdateStrings[altIndex] += "] :: ";
andrew@2 1479 tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
andrew@2 1480 tempoUpdateStrings[altIndex] += " intervals :: ";
andrew@2 1481 tempoUpdateStrings[altIndex] += ofToString(tempoInterval);
andrew@2 1482 tempoUpdateStrings[altIndex] += " ms.";
andrew@2 1483 // tempoUpdateStrings[altIndex] += ", ioi:";
andrew@2 1484
andrew@2 1485 // tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
andrew@2 1486
andrew@2 1487
andrew@2 1488
andrew@2 1489
andrew@2 1490 }//end if not paused
andrew@2 1491
andrew@2 1492
andrew@2 1493 }//end if good interval to update
andrew@2 1494
andrew@2 1495 }//end if not same index etc
andrew@2 1496
andrew@2 1497
andrew@2 1498 }
andrew@2 1499
andrew@2 1500
andrew@2 1501
andrew@2 1502 }//end for all intervals
andrew@2 1503
andrew@2 1504 sendMaxTempo();
andrew@2 1505 }//end if new beat time
andrew@2 1506 double tempoEstimate = tempoDistribution.getIntegratedEstimateIndex();
andrew@2 1507 tempoDistribution.calculateStandardDeviation();
andrew@2 1508 tempoStdDev = tempoDistribution.standardDeviation;
andrew@2 1509
andrew@2 1510 }
andrew@2 1511
andrew@2 1512
andrew@2 1513 bool testApp::updateTempoIfWithinRange(double timeInterval){
andrew@2 1514
andrew@2 1515 bool updated = false;
andrew@2 1516
andrew@2 1517 if (timeInterval > tempoMinimum && timeInterval < tempoMaximum ){
andrew@2 1518 calculateTempoUpdate(timeInterval);
andrew@2 1519 updated = true;
andrew@2 1520 }
andrew@2 1521
andrew@2 1522 return updated;
andrew@2 1523 }
andrew@2 1524
andrew@2 1525
andrew@2 1526 */
andrew@2 1527 //end
andrew@2 1528 /*
andrew@2 1529 void testApp::calculateTempoUpdate(double tempoInterval){
andrew@2 1530
andrew@2 1531
andrew@2 1532 tempoDistribution.resetPrior();
andrew@2 1533 //need to relook at likelihood for the tempo distribution - not the same as....
andrew@2 1534 tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval-tempoMinimum)/(tempoMaximum - tempoMinimum), tempoDistribution.likelihoodStdDev);
andrew@2 1535 tempoDistribution.calculatePosterior();
andrew@2 1536 tempoDistribution.renormalisePosterior();
andrew@2 1537
andrew@2 1538 //did take pic of screen here - see initialiser4
andrew@2 1539 }
andrew@2 1540 */
andrew@2 1541