annotate src/midiEventHolder.cpp @ 6:6f5836d432ca

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