annotate src/midiEventHolder.cpp @ 2:5581023e0de4

Added separate CannamMidiFileLoader class to handle the loading in.
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 19 Aug 2011 01:26:40 +0100
parents 1a32ce016bb9
children de86d77f2612
rev   line source
andrew@0 1 /*
andrew@0 2 * midiEventHolder.cpp
andrew@0 3 * midiCannamReader3
andrew@0 4 *
andrew@0 5 * Created by Andrew on 19/07/2011.
andrew@0 6 * Copyright 2011 QMUL. All rights reserved.
andrew@0 7 *
andrew@0 8 */
andrew@0 9 //hello
andrew@0 10
andrew@0 11 #include "midiEventHolder.h"
andrew@0 12
andrew@0 13 midiEventHolder::midiEventHolder(){
andrew@0 14 // recordedNoteOnIndex = 0;
andrew@0 15
andrew@0 16 width = ofGetWidth();
andrew@0 17 height = ofGetHeight();
andrew@0 18 screenWidth= &width;
andrew@0 19 screenHeight = &height;
andrew@0 20
andrew@0 21 ticksPerScreen = 4000;
andrew@0 22 tickLocation = 0;
andrew@0 23 pulsesPerQuarternote = 240;
andrew@0 24 noteArrayIndex = 0;
andrew@0 25 noteMinimum = 30;
andrew@0 26 noteMaximum = 96;
andrew@0 27
andrew@1 28 minimumMatchSpeed = 0.7;
andrew@1 29 maximumMatchSpeed = 1.3;
andrew@2 30
andrew@0 31 likelihoodWidth = 100;
andrew@2 32 likelihoodToNoiseRatio = 0.02;
andrew@0 33
andrew@2 34 bayesStruct.speedLikelihoodNoise = 0.05;//was 0.05
andrew@2 35 bayesStruct.speedDecayWidth = 20;
andrew@2 36 bayesStruct.speedDecayAmount = 10;
andrew@2 37
andrew@2 38
andrew@2 39 matchWindowWidth = 8000;//window size for matching in ms
andrew@0 40
andrew@1 41 bayesStruct.resetSize(matchWindowWidth);
andrew@2 42 bayesStruct.setPositionDistributionScalar(1);
andrew@2 43
andrew@0 44 bayesStruct.resetSpeedSize(200);
andrew@0 45 bayesStruct.setRelativeSpeedScalar(0.01);
andrew@0 46 bayesStruct.relativeSpeedPrior.getMaximum();
andrew@2 47 //bayesStruct.simpleExample();
andrew@2 48
andrew@0 49
andrew@0 50 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum);
andrew@0 51 }
andrew@0 52
andrew@0 53
andrew@0 54
andrew@0 55 void midiEventHolder::reset(){
andrew@2 56 //called when we start playing
andrew@2 57
andrew@0 58 noteArrayIndex = 0;
andrew@0 59 tickLocation = 0;
andrew@0 60 lastPeriodUpdateTime = ofGetElapsedTimeMillis();
andrew@0 61 bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
andrew@0 62 numberOfScreensIn = 0;
andrew@0 63 // recordedNoteOnIndex = 0;
andrew@0 64 bayesStruct.setNewDistributionOffsets(0);
andrew@0 65 bayesStruct.posterior.offset = 0;
andrew@0 66
andrew@0 67 playedEventTimes.clear();
andrew@0 68 playedNoteOnMatrix.clear();
andrew@0 69 matchMatrix.clear();
andrew@0 70
andrew@0 71 bayesStruct.resetSpeedToOne();
andrew@0 72
andrew@0 73 }
andrew@0 74
andrew@1 75 void midiEventHolder::clearAllEvents(){
andrew@1 76 recordedNoteOnMatrix.clear();
andrew@1 77 matchesFound.clear();
andrew@1 78 noteOnMatches.clear();
andrew@1 79 recordedEventTimes.clear();
andrew@1 80
andrew@1 81 //played events:
andrew@1 82 playedEventTimes.clear();
andrew@1 83 playedNoteOnMatrix.clear();
andrew@1 84 matchMatrix.clear();
andrew@1 85 }
andrew@1 86
andrew@0 87 void midiEventHolder::printNotes(){
andrew@0 88 printf("RECORDED MATRIX");
andrew@0 89 for (int i = 0;i < recordedNoteOnMatrix.size();i++){
andrew@0 90 printf("%i :: %i @ %f\n", recordedNoteOnMatrix[i][0], recordedNoteOnMatrix[i][1], recordedEventTimes[i]);
andrew@0 91 }
andrew@0 92 }
andrew@0 93
andrew@0 94
andrew@0 95 double midiEventHolder::getEventTimeTicks(double millis){
andrew@0 96 return (millis * pulsesPerQuarternote / period);
andrew@0 97 }
andrew@0 98
andrew@0 99 double midiEventHolder::getEventTimeMillis(double ticks){
andrew@0 100 return (period * ticks / (double) pulsesPerQuarternote);
andrew@0 101 }
andrew@0 102
andrew@0 103 void midiEventHolder::newNoteOnEvent(int pitch, int velocity, double timePlayed){
andrew@0 104
andrew@0 105 //MOVE INTO BAYESSTRUCT?? XXX
andrew@0 106 //bayesStruct.copyPriorToPosterior();
andrew@0 107 //why was this here??
andrew@0 108 bayesStruct.prior.copyFromDynamicVector(bayesStruct.posterior);//try the otehr way
andrew@0 109 //bayesStruct.copyPriorToPosterior();
andrew@0 110 //need to get new MAP position and set the offset of the arrays
andrew@0 111 //currently bestEstimate is the approx for the new MAP position
andrew@0 112
andrew@0 113
andrew@0 114 //add the new event to our played information matrix
andrew@0 115 IntVector v;
andrew@0 116 v.push_back(pitch);
andrew@0 117 v.push_back(velocity);
andrew@0 118 playedNoteOnMatrix.push_back(v);
andrew@0 119
andrew@0 120
andrew@0 121 //would update the arrays at this point to show where out current location (phase) and tempo is.
andrew@2 122 // double timeNow = ofGetElapsedTimeMillis() - startTime;
andrew@2 123 double timeNow = timePlayed;// - startTime;
andrew@2 124 recentNoteOnTime = timePlayed;
andrew@0 125
andrew@2 126 // printf("Max time %f OF time %f \n", timePlayed, timeNow);
andrew@0 127
andrew@0 128 playedEventTimes.push_back(timePlayed);
andrew@0 129
andrew@2 130 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime;
andrew@2 131 double timeDifference = timePlayed - bayesStruct.lastEventTime;
andrew@0 132
andrew@2 133 printf("note %i played at %f and last event %f\n", pitch, timePlayed, bayesStruct.lastEventTime);
andrew@0 134 //addnoise to the tempo distribution
andrew@2 135 //bayesStruct.decaySpeedDistribution(timeDifference);
andrew@2 136 if (timeDifference > 50){
andrew@2 137 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.);
andrew@2 138 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.);
andrew@2 139 }
andrew@2 140
andrew@2 141 bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate;
andrew@2 142 bayesStruct.updateBestEstimate();
andrew@2 143 bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
andrew@0 144
andrew@0 145 // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate);
andrew@0 146 //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis
andrew@0 147
andrew@0 148 timeString = "Pitch:"+ofToString(pitch);
andrew@0 149 timeString += ", time now:"+ofToString(timeNow, 1);
andrew@0 150 timeString += " TD "+ofToString(timeDifference, 1);
andrew@0 151 timeString += " offset "+ofToString(bayesStruct.posterior.offset , 0);
andrew@0 152 timeString += " map Est: "+ofToString(bayesStruct.posterior.MAPestimate, 0);
andrew@0 153 // timeString += " Previous time" + ofToString(newMAPestimateTime,0);
andrew@0 154 timeString += " speedMap "+ofToString(bayesStruct.relativeSpeedPosterior.MAPestimate, 2);
andrew@0 155 timeString += " :: "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 2);
andrew@0 156
andrew@0 157 // newMAPestimateTime += (timeDifference * bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@0 158 // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0);
andrew@0 159
andrew@0 160 //then we recalculate the window start based on MAP being central
andrew@0 161 //then we do the matches on these and the likelihood on these.
andrew@0 162
andrew@0 163 bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)));
andrew@0 164 // bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
andrew@0 165
andrew@0 166 timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0);
andrew@0 167 timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1);
andrew@0 168 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.MAPestimate, 1);
andrew@0 169 timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 1);
andrew@0 170
andrew@0 171
andrew@0 172 //be able to draw the prior in correct location relative to the midi notes
andrew@2 173 //this calculates the cross update of all possible speeds and all possible positions
andrew@0 174 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference);
andrew@0 175
andrew@0 176
andrew@0 177 timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1);
andrew@0 178 timeString += " notearrayindex "+ofToString(noteArrayIndex, 0);
andrew@0 179 //when this is off teh screen there is a problem somehow XXX
andrew@0 180 bayesStruct.posterior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
andrew@0 181 // bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
andrew@0 182 //trying to switch to prior
andrew@0 183
andrew@2 184 //bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
andrew@2 185 bayesStruct.lastEventTime = timePlayed;
andrew@0 186
andrew@0 187 //do the cross update to find current posterior for location
andrew@1 188 // totalConfidence= 0;
andrew@0 189 int numberOfMatchesFound = findLocalMatches(pitch);
andrew@0 190 setMatchLikelihoods(numberOfMatchesFound);
andrew@0 191 bayesStruct.calculatePosterior();
andrew@0 192
andrew@0 193 //having found matches we have matches for new note and matches for previous notes
andrew@0 194 findLocalTempoPairs();
andrew@0 195
andrew@2 196 //bayesStruct.addGaussianNoiseToSpeedPosterior(10);
andrew@0 197
andrew@0 198 }
andrew@0 199
andrew@0 200 int midiEventHolder::findLocalMatches(int notePitch){
andrew@0 201
andrew@0 202 //here we find the matches to the new note within appropriate range
andrew@0 203
andrew@1 204 matchString = "";
andrew@0 205
andrew@0 206 windowStartTime = max(0.0,(bayesStruct.bestEstimate - matchWindowWidth/2));//was playPositionInMillis
andrew@0 207 int numberOfMatches = findMatch(notePitch, windowStartTime, windowStartTime + matchWindowWidth);
andrew@0 208
andrew@1 209 matchString += " pitch: "+ofToString(notePitch)+" matches "+ofToString(numberOfMatches)+" win start "+ofToString(windowStartTime);
andrew@1 210
andrew@0 211 return numberOfMatches;
andrew@0 212
andrew@0 213
andrew@0 214 }
andrew@0 215
andrew@0 216
andrew@0 217 void midiEventHolder::setMatchLikelihoods(int numberOfMatches){
andrew@0 218 //reset the offset to match the prior
andrew@0 219 bayesStruct.likelihood.offset = bayesStruct.prior.offset;
andrew@0 220 bayesStruct.likelihood.zero();//set to zero
andrew@0 221
andrew@2 222 double quantity = likelihoodToNoiseRatio / numberOfMatches;
andrew@0 223
andrew@0 224 for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){
andrew@0 225 // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset);
andrew@0 226 //this is the vent time since start of file
andrew@0 227 if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){
andrew@1 228 // double confidenceMeasure = 0;
andrew@1 229 // if (totalConfidence > 0)
andrew@1 230 // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence;
andrew@2 231
andrew@2 232 bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, quantity);//* confidenceMeasure
andrew@0 233 }//end if
andrew@0 234 }
andrew@2 235 bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length);
andrew@0 236 }
andrew@0 237
andrew@0 238 int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){
andrew@0 239
andrew@0 240 matchesFound.clear();
andrew@0 241 int startIndex = 0;
andrew@0 242
andrew@0 243 if (recordedEventTimes.size() > 0){
andrew@0 244
andrew@0 245 //get to the right range of events to check in
andrew@0 246 while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < startTime)
andrew@0 247 startIndex++;
andrew@0 248
andrew@0 249 }
andrew@0 250
andrew@0 251
andrew@0 252 while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < endTime){
andrew@0 253 if (recordedNoteOnMatrix[startIndex][1] == notePitch){
andrew@0 254 matchesFound.push_back(startIndex);
andrew@1 255 double confidence = bayesStruct.posterior.getValueAtMillis(mouseX);
andrew@1 256 // recordedEventTimes[startIndex]);
andrew@1 257 matchString += "["+ofToString(startIndex)+"] = "+ofToString(confidence, 3)+" .";
andrew@0 258 }
andrew@0 259 startIndex++;
andrew@0 260 }
andrew@0 261
andrew@0 262 // printf("%i MATCHES TO Note %i found\n", (int)matchesFound.size(), notePitch);
andrew@0 263 int size = matchesFound.size();
andrew@0 264
andrew@0 265 IntVector v;
andrew@0 266 v.push_back(size);
andrew@0 267 for (int i = 0;i < matchesFound.size();i++)
andrew@0 268 v.push_back(matchesFound[i]);
andrew@0 269
andrew@0 270 matchMatrix.push_back(v);
andrew@0 271
andrew@0 272 return size;
andrew@0 273 }
andrew@0 274
andrew@0 275 bool midiEventHolder::checkIfMatchedNote(const int& tmpIndex){
andrew@0 276 for (int i = 0;i < matchesFound.size();i++){
andrew@0 277 if (matchesFound[i] == tmpIndex)
andrew@0 278 return true;
andrew@0 279 }
andrew@0 280 return false;
andrew@0 281 }
andrew@0 282
andrew@0 283
andrew@0 284
andrew@0 285 void midiEventHolder::findLocalTempoPairs(){
andrew@0 286
andrew@0 287 int currentPlayedIndex = playedNoteOnMatrix.size()-1;
andrew@0 288 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]);
andrew@0 289 // printMatchesFound();
andrew@0 290 // printMatchMatrix();
andrew@0 291 // printf("possible notes \n");
andrew@0 292
andrew@0 293
andrew@0 294 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){
andrew@0 295
andrew@0 296 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1];
andrew@0 297
andrew@0 298 int previousIndex = currentPlayedIndex-1;
andrew@0 299
andrew@0 300 while (previousIndex >= 0 && playedEventTimes[previousIndex] + 2000 > playedEventTimes[currentPlayedIndex]) {
andrew@0 301 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
andrew@0 302
andrew@0 303 for (int k = 0;k < matchMatrix[previousIndex][0];k++){
andrew@0 304 int recordedPreviousIndex = matchMatrix[previousIndex][k+1];
andrew@0 305
andrew@1 306
andrew@0 307
andrew@0 308 double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex];
andrew@1 309
andrew@0 310
andrew@0 311 //we want the speed of the recording relative to that of the playing live
andrew@0 312
andrew@0 313 double speedRatio = recordedTimeDifference / playedTimeDifference;
andrew@0 314 if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){
andrew@2 315 /*
andrew@2 316 printf("(%i)", matchMatrix[currentPlayedIndex][i+1]);
andrew@1 317 printf("[%i] :: ", recordedPreviousIndex);
andrew@1 318 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference);
andrew@1 319 printf("update on speed ratio %f\n", speedRatio);
andrew@2 320 */
andrew@1 321 // matchString += " speed: "+ofToString(speedRatio, 3);
andrew@0 322 // commented for debug
andrew@2 323
andrew@2 324 bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match
andrew@0 325
andrew@0 326 }
andrew@0 327 // printf("\n");
andrew@0 328 }
andrew@0 329
andrew@0 330 previousIndex--;
andrew@0 331 }//end while previousindex countdown
andrew@0 332 }//end for loop through possible current matches
andrew@0 333
andrew@2 334 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@0 335 }
andrew@0 336
andrew@0 337
andrew@0 338 void midiEventHolder::updatePlayPosition(){
andrew@0 339
andrew@0 340 //in actual fact if we are changing the speed of the play position
andrew@0 341 //we will need to update this via the file
andrew@0 342
andrew@0 343 double timeDifference = ofGetElapsedTimeMillis() - lastPeriodUpdateTime;
andrew@0 344 //this is time diff in milliseconds
andrew@0 345 //then we have
andrew@0 346 double quarterNoteIntervals = (timeDifference / period);
andrew@0 347 tickLocation = quarterNoteIntervals * pulsesPerQuarternote;
andrew@0 348
andrew@0 349 playPositionInMillis = timeDifference;//based on updating from when we change period
andrew@0 350 //this to be added
andrew@0 351
andrew@0 352 bayesStruct.updateBestEstimate();
andrew@0 353
andrew@0 354 }
andrew@0 355
andrew@0 356
andrew@0 357 void midiEventHolder::drawFile(){
andrew@0 358 //draws midi file on scrolling screen
andrew@0 359 int size = recordedNoteOnMatrix.size();
andrew@0 360 if (size > 0){
andrew@0 361
andrew@0 362 numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in
andrew@0 363
andrew@0 364 // numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down
andrew@0 365 timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen);
andrew@0 366
andrew@0 367 while (noteArrayIndex < recordedNoteOnMatrix.size() && tickLocation > recordedNoteOnMatrix[noteArrayIndex][0] )
andrew@0 368 noteArrayIndex++;
andrew@0 369
andrew@0 370
andrew@0 371 while (noteArrayIndex > 0 && noteArrayIndex < size && tickLocation < recordedNoteOnMatrix[noteArrayIndex][0])
andrew@0 372 noteArrayIndex--;
andrew@0 373
andrew@0 374 //need to start where we currently are in file
andrew@0 375 int maxNoteIndexToPrint = noteArrayIndex;
andrew@0 376 int minNoteIndexToPrint = noteArrayIndex;
andrew@0 377
andrew@0 378 while (maxNoteIndexToPrint < recordedNoteOnMatrix.size() && recordedNoteOnMatrix[maxNoteIndexToPrint][0] < (numberOfScreensIn+1)*ticksPerScreen )
andrew@0 379 maxNoteIndexToPrint++;
andrew@0 380
andrew@0 381 while (minNoteIndexToPrint > 0 && minNoteIndexToPrint < size && recordedNoteOnMatrix[minNoteIndexToPrint][0] > numberOfScreensIn*ticksPerScreen)
andrew@0 382 minNoteIndexToPrint--;
andrew@0 383
andrew@0 384 for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)recordedNoteOnMatrix.size());tmpIndex++){
andrew@0 385
andrew@0 386 if (checkIfMatchedNote(tmpIndex))
andrew@0 387 ofSetColor(0,0,255);
andrew@0 388 else
andrew@0 389 ofSetColor(255,255,255);
andrew@0 390
andrew@0 391 // XXX replace ofgetwidth below
andrew@0 392 //if (tmpIndex >= 0 && tmpIndex < size)
andrew@0 393 int xLocation = (float)(recordedNoteOnMatrix[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
andrew@0 394 int duration = (float)(recordedNoteOnMatrix[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen;
andrew@0 395
andrew@0 396
andrew@0 397 int yLocation = (*screenHeight) - ((recordedNoteOnMatrix[tmpIndex][1] - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));
andrew@0 398 ofRect(xLocation,yLocation, duration, noteHeight);
andrew@0 399
andrew@0 400 }
andrew@0 401
andrew@0 402
andrew@0 403 int xLocation;// = getLocationFromTicks(tickLocation);
andrew@0 404 // ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@0 405
andrew@0 406 //orange line at best estimate
andrew@0 407 xLocation = getLocationFromMillis(bayesStruct.bestEstimate);
andrew@0 408 ofSetColor(250,100,0);
andrew@0 409 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@0 410
andrew@2 411 xLocation = getLocationFromMillis(bayesStruct.tmpBestEstimate);
andrew@2 412 ofSetColor(250,100,0);
andrew@2 413 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@2 414
andrew@0 415
andrew@0 416 //lines where matching window start and end are
andrew@0 417 ofSetColor(0,100,255);
andrew@0 418 xLocation = getLocationFromMillis(windowStartTime);
andrew@0 419 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@0 420 xLocation = getLocationFromMillis(windowStartTime+matchWindowWidth);
andrew@0 421 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@0 422
andrew@0 423
andrew@0 424 }
andrew@0 425
andrew@1 426
andrew@1 427
andrew@0 428 ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20);
andrew@0 429
andrew@0 430 ofDrawBitmapString(timeString, 20, 60);
andrew@0 431
andrew@0 432 // bayesStruct.drawArrays();
andrew@0 433
andrew@0 434 // ofSetColor(200,200,0);
andrew@0 435 // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800);
andrew@0 436
andrew@0 437 //need to draw arrays within correct timescope
andrew@0 438 bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen));
andrew@0 439
andrew@1 440 if (drawTempoMode)
andrew@1 441 bayesStruct.drawTempoArrays();
andrew@0 442
andrew@1 443
andrew@1 444 ofSetColor(0, 0, 0);
andrew@0 445 ofDrawBitmapString(matchString, 20, ofGetHeight() - 20);
andrew@0 446
andrew@1 447 double confidence = bayesStruct.posterior.getValueAtMillis(mouseX);
andrew@2 448 /*
andrew@2 449 string mouseString = "mouseX "+ofToString(confidence, 3)+" .";
andrew@1 450 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40);
andrew@2 451 */
andrew@2 452 string mouseString = "updateCounter "+ofToString(bayesStruct.updateCounter);
andrew@2 453 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40);
andrew@2 454
andrew@2 455 string infostring = "speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 3);
andrew@2 456 ofDrawBitmapString(infostring, 20 , ofGetHeight() - 60);
andrew@0 457 }
andrew@0 458
andrew@0 459 int midiEventHolder::getLocationFromTicks(double tickPosition){
andrew@0 460 return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen);
andrew@0 461 }
andrew@0 462
andrew@0 463 int midiEventHolder::getLocationFromMillis(double millisPosition){
andrew@0 464 //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen
andrew@0 465 return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen);
andrew@0 466 }
andrew@0 467
andrew@0 468
andrew@0 469 void midiEventHolder::exampleCrossUpdate(){
andrew@0 470
andrew@0 471 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, 200);
andrew@0 472
andrew@0 473 }
andrew@0 474
andrew@0 475
andrew@0 476 void midiEventHolder::setStartPlayingTimes(){
andrew@0 477 lastPeriodUpdateTime = ofGetElapsedTimeMillis();
andrew@0 478 startTime = lastPeriodUpdateTime;
andrew@0 479
andrew@2 480 /*
andrew@2 481 bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis();
andrew@2 482 bayesStruct.bestEstimate = 0;
andrew@0 483 bayesStruct.resetArrays();
andrew@2 484 bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
andrew@2 485 */
andrew@2 486 bayesStruct.setStartPlaying();
andrew@0 487 matchString = "";
andrew@0 488 }
andrew@0 489
andrew@0 490
andrew@0 491 void midiEventHolder::printMatchMatrix(){
andrew@0 492 printf("match matrix:\n");
andrew@0 493 for (int i = 0;i < matchMatrix.size();i++){
andrew@0 494 for (int k = 0;k < matchMatrix[i].size();k++){
andrew@0 495 printf("%i , ", matchMatrix[i][k]);
andrew@0 496 }
andrew@0 497 printf("\n");
andrew@0 498 }
andrew@0 499
andrew@0 500
andrew@0 501 }