annotate jnmr/midiEventHolder.cpp @ 36:5a1b0c6fa1fb

Added class to read in the csv Annotation file, then write out the respective difference between the performed piece as followed here, and the annotation of RWC by Ewert and Muller
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Thu, 15 Dec 2011 02:28:49 +0000
parents 6cd3e0075adf
children 795a99987875
rev   line source
andrew@33 1 /*
andrew@33 2 * midiEventHolder.cpp
andrew@33 3 * midiCannamReader3
andrew@33 4 *
andrew@33 5 * Created by Andrew on 19/07/2011.
andrew@33 6 * Copyright 2011 QMUL. All rights reserved.
andrew@33 7 *
andrew@33 8 */
andrew@33 9
andrew@33 10
andrew@33 11 //Main file to look at here is newNoteEvent() - this calls everything else to update the Bayesian array
andrew@33 12
andrew@33 13 #include "midiEventHolder.h"
andrew@36 14
andrew@36 15 //#include <iostream>
andrew@36 16 //#include <fstream>
andrew@33 17
andrew@33 18 midiEventHolder::midiEventHolder(){
andrew@36 19
andrew@36 20 myNotation.readInSomeValues();
andrew@36 21
andrew@33 22 // recordedNoteOnIndex = 0;
andrew@34 23 alignmentPosition = 0;
andrew@33 24
andrew@33 25 useTempoPrior = false;//puts sine wave round tempo
andrew@33 26 confidenceWeightingUsed = true;
andrew@33 27 newOptimalMethod = true;
andrew@33 28
andrew@34 29 matchWindowWidth = 16000;//window size for matching in ms
andrew@33 30 interNoteRange = 1600;//preferred duration
andrew@33 31 //so max here is really four
andrew@33 32
andrew@33 33
andrew@33 34 likelihoodWidth = 100;//using 100 is good
andrew@33 35 likelihoodToNoiseRatio = 0.20;//was 0.02 on 18/11/11, changing to give more weight to observations
andrew@33 36 //was 0.08 on 11/12/11 but need more for tempo varn in rwc database
andrew@33 37
andrew@33 38 bayesStruct.speedLikelihoodNoise = 0.1;//was 0.05
andrew@33 39 bayesStruct.speedDecayWidth = 40;
andrew@33 40 bayesStruct.speedDecayAmount = 10;
andrew@33 41
andrew@33 42
andrew@33 43 //there is option to use MAP estinate or integral in beayesianarraystricture class
andrew@33 44
andrew@33 45 runningInRealTime = true;
andrew@33 46 bayesStruct.realTimeMode = &runningInRealTime;
andrew@33 47
andrew@33 48 minimumMatchSpeed = 0.0;
andrew@33 49 maximumMatchSpeed = 2.0;
andrew@33 50 minimumTimeIntervalForTempoUpdate = 150;
andrew@33 51
andrew@33 52 width = ofGetWidth();
andrew@33 53 height = ofGetHeight();
andrew@33 54 screenWidth= &width;
andrew@33 55 screenHeight = &height;
andrew@33 56
andrew@33 57 ticksPerScreen = 4000;
andrew@33 58 tickLocation = 0;
andrew@33 59 pulsesPerQuarternote = 240;
andrew@33 60 noteArrayIndex = 0;
andrew@33 61 noteMinimum = 30;
andrew@33 62 noteMaximum = 96;
andrew@33 63
andrew@33 64
andrew@33 65
andrew@33 66
andrew@33 67
andrew@33 68 speedPriorValue = 1.0;
andrew@33 69
andrew@33 70
andrew@33 71 bayesStruct.resetSize(matchWindowWidth);
andrew@33 72 bayesStruct.setPositionDistributionScalar(1);
andrew@33 73
andrew@33 74 bayesStruct.resetSpeedSize(200);
andrew@33 75 bayesStruct.setRelativeSpeedScalar(0.01);
andrew@33 76 bayesStruct.relativeSpeedPrior.getMaximum();
andrew@33 77 //bayesStruct.simpleExample();
andrew@33 78
andrew@33 79
andrew@33 80 speedWindowWidthMillis = 1600;//4000
andrew@34 81
andrew@33 82 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum);
andrew@33 83
andrew@33 84
andrew@33 85 intervalsToCheck.push_back(1);
andrew@33 86 intervalsToCheck.push_back(2);
andrew@33 87 //intervalsToCheck.push_back(3);
andrew@33 88 intervalsToCheck.push_back(4);
andrew@33 89 intervalsToCheck.push_back(6);
andrew@33 90 intervalsToCheck.push_back(8);
andrew@33 91 intervalsToCheck.push_back(16);
andrew@33 92
andrew@33 93
andrew@33 94 drawPhaseMode = true;
andrew@33 95
andrew@33 96 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@33 97 }
andrew@33 98
andrew@33 99
andrew@33 100
andrew@33 101 void midiEventHolder::reset(){
andrew@33 102 //called when we start playing
andrew@33 103
andrew@33 104 noteArrayIndex = 0;
andrew@33 105 tickLocation = 0;
andrew@34 106 startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis();
andrew@33 107 bayesStruct.lastEventTime = getTimeNow(0);//ofGetElapsedTimeMillis();
andrew@33 108 numberOfScreensIn = 0;
andrew@33 109 // recordedNoteOnIndex = 0;
andrew@33 110 bayesStruct.setNewDistributionOffsets(0);
andrew@33 111 bayesStruct.posterior.offset = 0;
andrew@33 112
andrew@33 113 playedEventTimes.clear();
andrew@33 114 playedNoteOnMatrix.clear();
andrew@33 115 matchMatrix.clear();
andrew@33 116 bestMatchIndex = 0;
andrew@33 117
andrew@33 118 recordedTotalNoteCounterByPitch.clear();
andrew@33 119 recordedTotalNoteCounterByPitch.assign(127,0);
andrew@33 120 totalNoteCounterIndex = 0;
andrew@34 121
andrew@33 122 interNoteIntervals.clear();
andrew@33 123
andrew@35 124 smoothIndex = 0;
andrew@34 125 smoothPlayPosition = 0.0;
andrew@34 126 // relativeSpeedForSmooth = 1.0;
andrew@34 127 // storedSmoothPlayPosition = smoothPlayPosition;
andrew@34 128 // lastSmoothUpdateTime = getTimeNow(0);
andrew@34 129
andrew@34 130 printf("reset speed prior is %f\n", speedPriorValue);
andrew@33 131 bayesStruct.resetSpeedToOne();
andrew@33 132 bayesStruct.setSpeedPrior(speedPriorValue);
andrew@33 133 setMatchedNotesBackToFalse();
andrew@34 134
andrew@34 135 periodCounter = 0;
andrew@34 136 for (int i = 0;i < periodValues.size();i++){
andrew@34 137 // printf("period at %f is %f\n", periodValues[i][2], periodValues[i][1]);
andrew@34 138 }
andrew@34 139 /* if (periodValues.size() > 0){
andrew@34 140 updatePeriodValue(0);// periodValues[0][2];
andrew@34 141 printf("Resetting period to %f , size is %i\n", period, (int)periodValues.size());
andrew@34 142 }
andrew@34 143 */
andrew@34 144 //period = 500.0;
andrew@33 145 }
andrew@33 146
andrew@33 147 void midiEventHolder::setMatchedNotesBackToFalse(){
andrew@33 148 for (int i = 0;i < noteOnMatches.size();i++)
andrew@33 149 noteOnMatches[i] = false;
andrew@33 150 }
andrew@33 151
andrew@33 152 void midiEventHolder::clearAllEvents(){
andrew@33 153 recordedNoteOnMatrix.clear();
andrew@33 154 matchesFound.clear();
andrew@33 155 noteOnMatches.clear();
andrew@33 156 recordedEventTimes.clear();
andrew@33 157 measureVector.clear();
andrew@33 158 //played events:
andrew@33 159 playedEventTimes.clear();
andrew@33 160 playedNoteOnMatrix.clear();
andrew@33 161 matchMatrix.clear();
andrew@33 162 bestMatchFound.clear();
andrew@33 163 periodValues.clear();
andrew@33 164
andrew@35 165 beatPositions.clear();
andrew@35 166
andrew@33 167 recordedTotalNoteCounterByPitch.clear();
andrew@33 168 recordedTotalNoteCounterByPitch.assign(127, 0);
andrew@33 169 totalNoteCounterIndex = 0;
andrew@33 170 }
andrew@33 171
andrew@33 172 void midiEventHolder::printNotes(){
andrew@33 173 printf("RECORDED MATRIX\n");
andrew@33 174 for (int i = 0;i < recordedNoteOnMatrix.size();i++){
andrew@33 175 printf("ticktime %i :: pitch %i @ millis %f\n", recordedNoteOnMatrix[i][0], recordedNoteOnMatrix[i][1], recordedEventTimes[i]);
andrew@33 176 }
andrew@33 177 }
andrew@33 178
andrew@33 179
andrew@33 180 double midiEventHolder::getEventTimeTicks(double millis){
andrew@34 181 return 0.0;
andrew@34 182 //return (millis * pulsesPerQuarternote / period);
andrew@33 183 }
andrew@33 184
andrew@33 185 double midiEventHolder::getEventTimeMillis(double ticks){
andrew@33 186 return (period * ticks / (double) pulsesPerQuarternote);
andrew@33 187 }
andrew@33 188
andrew@33 189 void midiEventHolder::newNoteOnEvent(int pitch, int velocity, double timePlayed){
andrew@33 190 // tempoSpeedString = "";
andrew@33 191
andrew@33 192 //MOVE INTO BAYESSTRUCT?? XXX
andrew@33 193 //bayesStruct.copyPriorToPosterior();
andrew@33 194 //why was this here??
andrew@33 195 bayesStruct.prior.copyFromDynamicVector(bayesStruct.posterior);//try the otehr way
andrew@33 196 //bayesStruct.copyPriorToPosterior();
andrew@33 197 //need to get new MAP position and set the offset of the arrays
andrew@33 198 //currently bestEstimate is the approx for the new MAP position
andrew@33 199
andrew@33 200 lastPlayedPitch = pitch;
andrew@33 201 //add the new event to our played information matrix
andrew@33 202 IntVector v;
andrew@33 203 v.push_back(pitch);
andrew@33 204 v.push_back(velocity);
andrew@33 205 playedNoteOnMatrix.push_back(v);
andrew@33 206
andrew@33 207
andrew@33 208 //would update the arrays at this point to show where out current location (phase) and tempo is.
andrew@33 209 // double timeNow = ofGetElapsedTimeMillis() - startTime;
andrew@33 210 double timeNow = timePlayed;// - startTime;
andrew@33 211 recentNoteOnTime = timePlayed;
andrew@33 212
andrew@33 213 // printf("Max time %f OF time %f \n", timePlayed, timeNow);
andrew@33 214
andrew@33 215 playedEventTimes.push_back(timePlayed);
andrew@33 216
andrew@33 217 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime;
andrew@33 218 double timeDifference = timePlayed - bayesStruct.lastEventTime;
andrew@33 219
andrew@33 220 //printf("note %i played at %f and last event %f time difference %f and current best estmate %f\n", pitch, timePlayed, bayesStruct.lastEventTime, timeDifference, bayesStruct.bestEstimate);
andrew@33 221
andrew@33 222 //addnoise to the tempo distribution
andrew@33 223 //bayesStruct.decaySpeedDistribution(timeDifference);
andrew@33 224
andrew@33 225 if (timeDifference > 50){
andrew@33 226 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.);
andrew@33 227 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.);
andrew@33 228 }
andrew@33 229
andrew@34 230 // bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate;
andrew@33 231 bayesStruct.updateBestEstimate(timeDifference);
andrew@34 232
andrew@33 233 bayesStruct.lastBestEstimateUpdateTime = getTimeNow(timePlayed);
andrew@34 234 //updatePeriodValue(bayesStruct.lastBestEstimateUpdateTime);
andrew@34 235
andrew@33 236 // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate);
andrew@33 237 //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis
andrew@33 238
andrew@33 239 timeString = "Pitch:"+ofToString(pitch);
andrew@33 240 timeString += ", time now:"+ofToString(timeNow, 1);
andrew@33 241 timeString += " TD "+ofToString(timeDifference, 1);
andrew@33 242 timeString += " offset "+ofToString(bayesStruct.posterior.offset , 0);
andrew@33 243 timeString += " map Est: "+ofToString(bayesStruct.posterior.MAPestimate, 0);
andrew@33 244 // timeString += " Previous time" + ofToString(newMAPestimateTime,0);
andrew@33 245 timeString += " speedMap "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 2);
andrew@33 246 timeString += " :: "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 2);
andrew@33 247
andrew@33 248 // newMAPestimateTime += (timeDifference * bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@33 249 // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0);
andrew@33 250
andrew@33 251 //then we recalculate the window start based on MAP being central
andrew@33 252 //then we do the matches on these and the likelihood on these.
andrew@33 253
andrew@33 254 bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)));
andrew@33 255 // bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
andrew@33 256
andrew@33 257 timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0);
andrew@33 258 timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1);
andrew@33 259 timeString += " error "+ofToString(minimumMatchError, 0);
andrew@33 260 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 1);
andrew@33 261 timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 2);
andrew@33 262
andrew@33 263
andrew@33 264 //be able to draw the prior in correct location relative to the midi notes
andrew@33 265 //this calculates the cross update of all possible speeds and all possible positions
andrew@33 266 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference);
andrew@33 267
andrew@33 268
andrew@33 269 timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1);
andrew@33 270 timeString += " notearrayindex "+ofToString(noteArrayIndex, 0);
andrew@33 271 //when this is off teh screen there is a problem somehow XXX
andrew@33 272
andrew@33 273 bayesStruct.posterior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));// bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
andrew@33 274
andrew@33 275 //trying to switch to prior
andrew@33 276
andrew@33 277
andrew@33 278 bayesStruct.lastEventTime = timePlayed;//bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
andrew@33 279
andrew@33 280 //do the cross update to find current posterior for location
andrew@33 281 // totalConfidence= 0;
andrew@33 282 int numberOfMatchesFound = findLocalMatches(pitch);
andrew@33 283 setMatchLikelihoods(numberOfMatchesFound);
andrew@33 284 bayesStruct.calculatePosterior();
andrew@33 285
andrew@33 286 if (recordedEventTimes.size() > 0){
andrew@33 287 updateTempo();
andrew@33 288 //calcuateNewInterNoteIntervals();
andrew@33 289 }
andrew@34 290
andrew@34 291 //storedSmoothPlayPosition = smoothPlayPosition;
andrew@33 292
andrew@33 293 }
andrew@33 294
andrew@33 295 void midiEventHolder::updateTempo(){
andrew@33 296 //having found matches we have matches for new note and matches for previous notes
andrew@33 297 if (newOptimalMethod)
andrew@33 298 findOptimumTempoPairsToCurrentBestMatch();
andrew@33 299 else if (!confidenceWeightingUsed)
andrew@33 300 findLocalTempoPairs();
andrew@33 301 else
andrew@33 302 findLocalTempoPairsWeightedForConfidence();
andrew@33 303
andrew@33 304
andrew@33 305 //bayesStruct.addGaussianNoiseToSpeedPosterior(10);
andrew@33 306 }
andrew@33 307
andrew@33 308 double midiEventHolder::getTimeNow(double eventTime){
andrew@33 309 double timeNow = eventTime;
andrew@33 310 if (runningInRealTime)
andrew@33 311 timeNow = ofGetElapsedTimeMillis();
andrew@33 312 return timeNow;
andrew@33 313 }
andrew@33 314
andrew@33 315 int midiEventHolder::findLocalMatches(int notePitch){
andrew@33 316
andrew@33 317 //here we find the matches to the new note within appropriate range
andrew@33 318
andrew@33 319 matchString = "";
andrew@33 320
andrew@33 321 windowStartTime = max(0.0,(bayesStruct.bestEstimate - matchWindowWidth/2));//was playPositionInMillis
andrew@33 322 // cout << "best estimate is " << bayesStruct.bestEstimate << endl;
andrew@33 323 int numberOfMatches = findMatch(notePitch, windowStartTime, windowStartTime + matchWindowWidth);
andrew@33 324
andrew@33 325
andrew@33 326 //matchString += " pitch: "+ofToString(notePitch)+" matches "+ofToString(numberOfMatches)+" win start "+ofToString(windowStartTime);
andrew@33 327
andrew@33 328 return numberOfMatches;
andrew@33 329
andrew@33 330
andrew@33 331 }
andrew@33 332
andrew@33 333
andrew@33 334 void midiEventHolder::setMatchLikelihoods(int numberOfMatches){
andrew@33 335 //reset the offset to match the prior
andrew@33 336 bayesStruct.likelihood.offset = bayesStruct.prior.offset;
andrew@33 337 bayesStruct.likelihood.zero();//set to zero
andrew@33 338
andrew@33 339 double quantity = likelihoodToNoiseRatio / numberOfMatches;
andrew@33 340
andrew@33 341 for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){
andrew@33 342 // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset);
andrew@33 343 //this is the vent time since start of file
andrew@33 344 if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){
andrew@33 345 // double confidenceMeasure = 0;
andrew@33 346 // if (totalConfidence > 0)
andrew@33 347 // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence;
andrew@33 348
andrew@33 349 bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, quantity);//* confidenceMeasure
andrew@33 350 }//end if
andrew@33 351 }
andrew@33 352 bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length);
andrew@33 353 }
andrew@33 354
andrew@33 355 int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){
andrew@33 356
andrew@33 357 matchesFound.clear();
andrew@33 358 int startIndex = 0;
andrew@33 359
andrew@33 360 if (recordedEventTimes.size() > 0){
andrew@33 361
andrew@33 362 //get to the right range of events to check in
andrew@33 363 while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < startTime)
andrew@33 364 startIndex++;
andrew@33 365
andrew@33 366 }
andrew@33 367
andrew@33 368 IntVector v;
andrew@33 369 DoubleVector d;
andrew@33 370 double tmpError = 100000.;//v high error
andrew@33 371
andrew@33 372 double minimumConfidence = 0;
andrew@33 373 while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < endTime){
andrew@33 374 if (recordedNoteOnMatrix[startIndex][1] == notePitch){
andrew@33 375
andrew@33 376 matchesFound.push_back(startIndex);
andrew@33 377 v.push_back(startIndex);
andrew@33 378 //so startIndex is registered as a match
andrew@33 379
andrew@33 380 double eventConfidence = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[startIndex]);
andrew@33 381 if (eventConfidence > minimumConfidence){
andrew@33 382 minimumConfidence = eventConfidence;
andrew@33 383 bestMatchIndex = startIndex;
andrew@33 384 }
andrew@33 385 d.push_back(eventConfidence);
andrew@33 386
andrew@33 387 double confidence = eventConfidence;//bayesStruct.posterior.getValueAtMillis(mouseX);
andrew@33 388 // recordedEventTimes[startIndex]);
andrew@33 389 // matchString += "["+ofToString(startIndex)+"] = "+ofToString(confidence, 3)+" .";
andrew@33 390
andrew@33 391 if (abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate) < tmpError){
andrew@33 392 //record the error between expected and observed times
andrew@33 393 tmpError = abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate);
andrew@33 394 minimumMatchError = tmpError;//recordedEventTimes[startIndex] - bayesStruct.bestEstimate;
andrew@33 395 }
andrew@33 396
andrew@33 397 }
andrew@33 398 startIndex++;
andrew@33 399 }
andrew@33 400
andrew@33 401
andrew@33 402 // printf("%i MATCHES TO Note %i found\n", (int)matchesFound.size(), notePitch);
andrew@33 403 int size = matchesFound.size();
andrew@33 404 if (size > 0)
andrew@33 405 noteOnMatches[bestMatchIndex] = true;
andrew@33 406
andrew@33 407 v.insert(v.begin() , (int)size);//at beginning, we list how many matches there are that we have found
andrew@33 408 d.insert(d.begin() , (double)size);
andrew@33 409
andrew@33 410 //v.push_back(size);
andrew@33 411 //d.push_back(size);
andrew@33 412 //for (int i = 0;i < matchesFound.size()+1;i++){
andrew@33 413 // v.push_back(matchesFound[i]);
andrew@33 414 // printf("match %i,[%i] is %i\n", startIndex, i, v[i]);
andrew@33 415 //}
andrew@33 416
andrew@33 417
andrew@33 418 matchMatrix.push_back(v);
andrew@33 419 matchConfidence.push_back(d);
andrew@33 420
andrew@33 421 //bringing in way to list only the best matches and use these in tempo process
andrew@33 422 bestMatchFound.push_back(bestMatchIndex);
andrew@33 423
andrew@33 424 // printf("BEST MATCH TO note %i, start time %i, endtime %i, time %i is recorded time %i, confidence %0.2f\n", notePitch, startTime, endTime, (int) recordedEventTimes[bestMatchIndex], minimumConfidence);
andrew@33 425
andrew@33 426 return size;
andrew@33 427 }
andrew@33 428
andrew@33 429 bool midiEventHolder::checkIfMatchedNote(const int& tmpIndex){
andrew@33 430 for (int i = 0;i < matchesFound.size();i++){
andrew@33 431 if (matchesFound[i] == tmpIndex)
andrew@33 432 return true;
andrew@33 433 }
andrew@33 434 return false;
andrew@33 435 }
andrew@33 436
andrew@33 437
andrew@33 438
andrew@33 439 void midiEventHolder::findLocalTempoPairs(){
andrew@33 440
andrew@33 441 int currentPlayedIndex = playedNoteOnMatrix.size()-1;
andrew@33 442 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]);
andrew@33 443 // printMatchesFound();
andrew@33 444 // printMatchMatrix();
andrew@33 445 // printf("possible notes \n");
andrew@33 446 bool needToUpdate = false;
andrew@33 447 bayesStruct.setLikelihoodToConstant();
andrew@33 448
andrew@33 449
andrew@33 450 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){
andrew@33 451 //iterate through the recently matched events - even dodgy matches included
andrew@33 452 //size, index of match0, index of match1, ....
andrew@33 453
andrew@33 454
andrew@33 455 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1];
andrew@33 456
andrew@33 457 int previousIndex = currentPlayedIndex-1;
andrew@33 458
andrew@33 459
andrew@33 460 while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) {
andrew@33 461 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
andrew@33 462
andrew@33 463 for (int k = 0;k < matchMatrix[previousIndex][0];k++){
andrew@33 464
andrew@33 465 int recordedPreviousIndex = matchMatrix[previousIndex][k+1];
andrew@33 466
andrew@33 467 double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex];
andrew@33 468
andrew@33 469
andrew@33 470 //we want the speed of the recording relative to that of the playing live
andrew@33 471
andrew@33 472 double speedRatio = recordedTimeDifference / playedTimeDifference;
andrew@33 473 if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate &&
andrew@33 474 speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){
andrew@33 475
andrew@33 476 //adding in a prior that prefers 1
andrew@33 477 double priorWeighting = 1;
andrew@33 478 if (useTempoPrior)
andrew@33 479 priorWeighting = sin(speedRatio * PI/2);
andrew@33 480
andrew@33 481
andrew@33 482
andrew@33 483 /*
andrew@33 484 printf("(%i)", matchMatrix[currentPlayedIndex][i+1]);
andrew@33 485 printf("[%i] :: ", recordedPreviousIndex);
andrew@33 486 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference);
andrew@33 487 printf("update on speed ratio %f\n", speedRatio);
andrew@33 488 */
andrew@33 489 // matchString += " speed: "+ofToString(speedRatio, 3);
andrew@33 490 // commented for debug
andrew@33 491
andrew@33 492 //bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match
andrew@33 493 double amount = (1-bayesStruct.speedLikelihoodNoise)/10;
andrew@33 494 amount *= priorWeighting;
andrew@33 495 bayesStruct.updateTempoLikelihood(speedRatio, amount);
andrew@33 496 // tempoSpeedString += ofToString(recordedPreviousIndex) + " "+ ofToString(speedRatio, 2) + " "+ofToString(amount, 2) += " \n";
andrew@33 497 needToUpdate = true;
andrew@33 498 }
andrew@33 499 // printf("\n");
andrew@33 500 }
andrew@33 501
andrew@33 502 previousIndex--;
andrew@33 503 }//end while previousindex countdown
andrew@33 504 }//end for loop through possible current matches
andrew@33 505
andrew@33 506 if (needToUpdate)
andrew@33 507 bayesStruct.updateTempoDistribution();
andrew@33 508
andrew@33 509 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@33 510 }
andrew@33 511
andrew@33 512
andrew@33 513 void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){
andrew@33 514 bool needToUpdate = false;
andrew@33 515
andrew@33 516 DoubleVector speedIntervalsFound;
andrew@33 517
andrew@33 518 //adapted this to just use the best match for each note
andrew@33 519
andrew@33 520 int currentPlayedIndex = playedNoteOnMatrix.size()-1;
andrew@33 521 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]);
andrew@33 522 // printMatchesFound();
andrew@33 523 // printMatchMatrix();
andrew@33 524 // printf("possible notes \n");
andrew@33 525
andrew@33 526 bayesStruct.setLikelihoodToConstant();
andrew@33 527
andrew@33 528 int recordedCurrentIndex = bestMatchFound[currentPlayedIndex];
andrew@33 529 //we only look at intervals between the current best match and other recent best matched notes
andrew@33 530 //that is the difference in confidence method
andrew@33 531
andrew@33 532
andrew@33 533 //printf("BEST MATCH FOUND for index %i is %i ", currentPlayedIndex, bestMatchFound[currentPlayedIndex]);
andrew@33 534
andrew@33 535 int previousIndex = currentPlayedIndex-1;
andrew@33 536
andrew@33 537 //withing speedwindow i.e. 4 seconds
andrew@33 538 while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) {
andrew@33 539 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
andrew@33 540
andrew@33 541 int recordedPreviousIndex = bestMatchFound[previousIndex];
andrew@33 542
andrew@33 543 double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex];
andrew@33 544
andrew@33 545
andrew@33 546 //we want the speed of the recording relative to that of the playing live
andrew@33 547
andrew@33 548 double speedRatio = recordedTimeDifference / playedTimeDifference;
andrew@33 549 if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate
andrew@33 550 && speedRatio < maximumMatchSpeed && speedRatio > minimumMatchSpeed){
andrew@33 551
andrew@33 552 /* printf("(%i)", previousIndex);
andrew@33 553 printf("[%i] :: ", recordedPreviousIndex);
andrew@33 554 // printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence);
andrew@33 555 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference);
andrew@33 556 printf("update on speed ratio %f\n", speedRatio);
andrew@33 557 */
andrew@33 558 // matchString += " speed: "+ofToString(speedRatio, 3);
andrew@33 559 // commented for debug
andrew@33 560
andrew@33 561
andrew@33 562 double priorWeighting = 1;
andrew@33 563
andrew@33 564 if (useTempoPrior)
andrew@33 565 priorWeighting = sin(speedRatio * PI/2);//adding in a prior that prefers 1.0 speed
andrew@33 566
andrew@33 567
andrew@33 568 // double weighting = previousMatchConfidence * currentMatchConfidence ;
andrew@33 569 double amount = (1-bayesStruct.speedLikelihoodNoise)*priorWeighting/16;//was 9
andrew@33 570
andrew@33 571 speedIntervalsFound.push_back(speedRatio);
andrew@33 572 // bayesStruct.updateTempoLikelihood(speedRatio, amount);//second paramter is confidence in the match
andrew@33 573
andrew@33 574 // tempoSpeedString += ofToString(recordedCurrentIndex) + " :: " + ofToString(recordedPreviousIndex);
andrew@33 575 // tempoSpeedString += " " + ofToString(recordedTimeDifference)+ " " + ofToString(speedRatio, 2) + " "+ofToString(amount, 2) += " \n";
andrew@33 576
andrew@33 577 needToUpdate = true;
andrew@33 578 }
andrew@33 579 // printf("\n");
andrew@33 580
andrew@33 581
andrew@33 582 previousIndex--;
andrew@33 583 }//end while previousindex countdown
andrew@33 584
andrew@33 585 if (speedIntervalsFound.size() > 0){
andrew@33 586 double amount = (1 - bayesStruct.speedLikelihoodNoise) / speedIntervalsFound.size();
andrew@33 587 for (int i = 0;i < speedIntervalsFound.size();i++)
andrew@33 588 bayesStruct.updateTempoLikelihood(speedIntervalsFound[i], amount);
andrew@33 589 }
andrew@33 590
andrew@33 591
andrew@33 592 if (needToUpdate)
andrew@33 593 bayesStruct.updateTempoDistribution();
andrew@33 594 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@33 595 }
andrew@33 596
andrew@33 597 double midiEventHolder::getBestSpeedEstimate(const int& currentPlayedIndex, const int& equivalentRecordedIndex){
andrew@33 598 double estimate = 1.0;
andrew@33 599 if (bestMatchIndex > 0){
andrew@33 600 double accordingToFileLengthEstimate = recordedEventTimes[equivalentRecordedIndex] - recordedEventTimes[0];
andrew@33 601 double playedEquivalent = (playedEventTimes[currentPlayedIndex] - playedEventTimes[0]);
andrew@33 602 if (accordingToFileLengthEstimate > 0 && playedEquivalent > 0)
andrew@33 603 accordingToFileLengthEstimate /= playedEquivalent;
andrew@33 604 estimate = accordingToFileLengthEstimate;
andrew@33 605 }
andrew@33 606 return estimate;
andrew@33 607 }
andrew@33 608
andrew@33 609 void midiEventHolder::findOptimumTempoPairsToCurrentBestMatch(){
andrew@33 610 bool needToUpdate = false;
andrew@33 611
andrew@33 612 DoubleVector speedIntervalsFound;
andrew@33 613
andrew@33 614 double currentSpeedEstimate = bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate);
andrew@33 615
andrew@33 616 int currentPlayedIndex = playedNoteOnMatrix.size()-1;
andrew@33 617
andrew@33 618 bayesStruct.setLikelihoodToConstant();
andrew@33 619
andrew@33 620 int recordedCurrentIndex = bestMatchFound[currentPlayedIndex];
andrew@33 621 //we only look at intervals between the current best match and other recent best matched notes
andrew@33 622
andrew@33 623 //printf("BEST MATCH FOUND for index %i is %i ", currentPlayedIndex, bestMatchFound[currentPlayedIndex]);
andrew@33 624
andrew@33 625 int previousIndex = currentPlayedIndex-1;
andrew@33 626
andrew@33 627 //withing speedwindow i.e. 4 seconds
andrew@33 628 while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) {
andrew@33 629
andrew@33 630 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
andrew@33 631
andrew@33 632 int recordedPreviousIndex = bestMatchFound[previousIndex];
andrew@33 633
andrew@33 634 double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex];
andrew@33 635
andrew@33 636 //we want the speed of the recording relative to that of the playing live
andrew@33 637 double speedRatio = recordedTimeDifference / playedTimeDifference;
andrew@33 638
andrew@33 639 //now check if this can be closer the observed value
andrew@33 640 int checkRecordedCurrentIndex = recordedCurrentIndex;
andrew@33 641 int checkRecordedPreviousIndex ;//= recordedCurrentIndex;
andrew@33 642 int currentPlayedPitch = playedNoteOnMatrix[currentPlayedIndex][1];
andrew@33 643 int previousPlayedPitch = playedNoteOnMatrix[previousIndex][1];
andrew@33 644
andrew@33 645 double recordedTimeOfBestMatch = recordedEventTimes[recordedCurrentIndex];
andrew@33 646
andrew@33 647 //change this so we start first in window and go to end
andrew@33 648
andrew@33 649 while (checkRecordedCurrentIndex >= 0 && recordedEventTimes[checkRecordedCurrentIndex] > recordedTimeOfBestMatch - matchWindowWidth){
andrew@33 650
andrew@33 651 checkRecordedCurrentIndex--;
andrew@33 652 }
andrew@33 653
andrew@33 654 double bestSpeedEstimate = getBestSpeedEstimate(currentPlayedIndex, bestMatchIndex);
andrew@33 655
andrew@33 656 while (checkRecordedCurrentIndex < recordedEventTimes.size() && recordedEventTimes[checkRecordedCurrentIndex] < recordedTimeOfBestMatch + matchWindowWidth ){
andrew@33 657 if (recordedNoteOnMatrix[checkRecordedCurrentIndex][1] == currentPlayedPitch ){
andrew@33 658 checkRecordedPreviousIndex = checkRecordedCurrentIndex;
andrew@33 659 double recordedTimeCurrent = recordedEventTimes[checkRecordedCurrentIndex] ;
andrew@33 660 while (checkRecordedPreviousIndex >= 0 && recordedEventTimes[checkRecordedPreviousIndex] + maximumMatchSpeed*playedTimeDifference > recordedTimeCurrent ) {
andrew@33 661 if (recordedNoteOnMatrix[checkRecordedPreviousIndex][1] == previousPlayedPitch){
andrew@33 662 //we have a candidate
andrew@33 663 double speedToTest = recordedEventTimes[checkRecordedCurrentIndex] - recordedEventTimes[checkRecordedPreviousIndex];
andrew@33 664 speedToTest /= playedTimeDifference;
andrew@33 665 if (abs(speedToTest-currentSpeedEstimate) < abs(speedRatio - currentSpeedEstimate) ){
andrew@33 666 speedRatio = speedToTest;
andrew@33 667 }
andrew@33 668 }
andrew@33 669 checkRecordedPreviousIndex--;
andrew@33 670 }
andrew@33 671 }
andrew@33 672 checkRecordedCurrentIndex++;
andrew@33 673 }
andrew@33 674
andrew@33 675
andrew@33 676 if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate
andrew@33 677 && speedRatio < maximumMatchSpeed && speedRatio > minimumMatchSpeed){
andrew@33 678
andrew@33 679 /* printf("(%i)", previousIndex);
andrew@33 680 printf("[%i] :: ", recordedPreviousIndex);
andrew@33 681 // printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence);
andrew@33 682 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference);
andrew@33 683 printf("update on speed ratio %f\n", speedRatio);
andrew@33 684 */
andrew@33 685 // matchString += " speed: "+ofToString(speedRatio, 3);
andrew@33 686 // commented for debug
andrew@33 687
andrew@33 688
andrew@33 689 double priorWeighting = 1;
andrew@33 690
andrew@33 691 if (useTempoPrior)
andrew@33 692 priorWeighting = sin(speedRatio * PI/2);//adding in a prior that prefers 1.0 speed
andrew@33 693
andrew@33 694
andrew@33 695 // double weighting = previousMatchConfidence * currentMatchConfidence ;
andrew@33 696 double amount = (1-bayesStruct.speedLikelihoodNoise)*priorWeighting/16;//was 9
andrew@33 697
andrew@33 698 speedIntervalsFound.push_back(speedRatio);
andrew@33 699 // bayesStruct.updateTempoLikelihood(speedRatio, amount);//second paramter is confidence in the match
andrew@33 700
andrew@33 701 // tempoSpeedString += ofToString(recordedCurrentIndex) + " :: " + ofToString(recordedPreviousIndex);
andrew@33 702 // tempoSpeedString += " " + ofToString(recordedTimeDifference)+ " " + ofToString(speedRatio, 2) + " "+ofToString(amount, 2) += " \n";
andrew@33 703
andrew@33 704 needToUpdate = true;
andrew@33 705 }
andrew@33 706 // printf("\n");
andrew@33 707
andrew@33 708
andrew@33 709 previousIndex--;
andrew@33 710 }//end while previousindex countdown
andrew@33 711
andrew@33 712 if (speedIntervalsFound.size() > 0){
andrew@33 713 double amount = (1 - bayesStruct.speedLikelihoodNoise) / speedIntervalsFound.size();
andrew@33 714 for (int i = 0;i < speedIntervalsFound.size();i++)
andrew@33 715 bayesStruct.updateTempoLikelihood(speedIntervalsFound[i], amount);
andrew@33 716 }
andrew@33 717
andrew@33 718
andrew@33 719 if (needToUpdate)
andrew@33 720 bayesStruct.updateTempoDistribution();
andrew@33 721 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@33 722 }
andrew@33 723
andrew@33 724
andrew@33 725 void midiEventHolder::calcuateNewInterNoteIntervals(){
andrew@33 726 DoubleVector v;
andrew@33 727
andrew@33 728 int currentPlayedIndex = playedNoteOnMatrix.size()-1;
andrew@33 729 // int recordedCurrentIndex = bestMatchFound[currentPlayedIndex];
andrew@33 730 int previousIndex = currentPlayedIndex-1;
andrew@33 731
andrew@33 732 //withing speedwindow i.e. 4 seconds
andrew@33 733 while (previousIndex >= 0 && playedEventTimes[previousIndex] + interNoteRange > playedEventTimes[currentPlayedIndex]) {
andrew@33 734
andrew@33 735 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
andrew@33 736
andrew@33 737 checkForCorrectInterval(playedTimeDifference, &v);
andrew@33 738
andrew@33 739 previousIndex--;
andrew@33 740 }
andrew@33 741
andrew@33 742 if (v.size() > 0)
andrew@33 743 interNoteIntervals.push_back(v);
andrew@33 744 //printf("\n");
andrew@33 745 }
andrew@33 746
andrew@33 747 void midiEventHolder::checkForCorrectInterval(const double& playedTimeDifference, DoubleVector* v){
andrew@33 748 double intervalDuration = 0.0;
andrew@33 749
andrew@33 750 for (int intervalIndex = 0;intervalIndex < 3;intervalIndex++){
andrew@33 751 //on;y check 1,2 and 4
andrew@33 752 double possibleDuration = playedTimeDifference / intervalsToCheck[intervalIndex];
andrew@33 753 if (possibleDuration >= 200 && possibleDuration < 400){
andrew@33 754 v->push_back(possibleDuration);
andrew@33 755 // printf("int %f / %i :: %f ", playedTimeDifference, intervalsToCheck[intervalIndex], possibleDuration);
andrew@33 756 }
andrew@33 757 }
andrew@33 758 }
andrew@33 759
andrew@33 760
andrew@33 761 void midiEventHolder::updatePlayPosition(){
andrew@34 762 //timeDifference = ofGetElapsedTimeMillis() - startPlayingTime;//elpased
andrew@33 763
andrew@33 764 //in actual fact if we are changing the speed of the play position
andrew@33 765 //we will need to update this via the file
andrew@33 766
andrew@33 767 //actually time since beginning of file i think
andrew@33 768
andrew@33 769 double timeDifference = 0;
andrew@34 770
andrew@34 771 if (runningInRealTime){
andrew@34 772
andrew@34 773 bayesStruct.updateBestEstimate(timeDifference);
andrew@34 774 // bayesStruct.updateTmpBestEstimate(timeDifference);
andrew@34 775 }
andrew@34 776
andrew@35 777
andrew@35 778
andrew@35 779 if (smoothPlayPosition < bayesStruct.bestEstimate){
andrew@35 780 updateSmoothPositionTo(bayesStruct.bestEstimate);
andrew@35 781 //smoothPlayPosition = bayesStruct.bestEstimate;
andrew@35 782 }
andrew@34 783
andrew@34 784 // playPositionInMillis = timeDifference;//based on updating from when we change period
andrew@34 785 //this to be added
andrew@34 786
andrew@33 787
andrew@33 788 //this is time diff in milliseconds
andrew@33 789 //then we have
andrew@33 790 double quarterNoteIntervals = (timeDifference / period);
andrew@33 791 tickLocation = quarterNoteIntervals * pulsesPerQuarternote;
andrew@33 792
andrew@33 793 updateNoteCounter();
andrew@33 794
andrew@33 795 }
andrew@33 796
andrew@35 797 void midiEventHolder::updateSmoothPositionTo(const double& newPosition){
andrew@35 798 while (smoothIndex > 0 && recordedEventTimes[smoothIndex] > smoothPlayPosition){
andrew@35 799 smoothIndex--;
andrew@35 800 }
andrew@35 801 while (smoothIndex < recordedEventTimes.size()-1 && recordedEventTimes[smoothIndex] < smoothPlayPosition){
andrew@35 802 smoothIndex++;
andrew@35 803 }
andrew@35 804
andrew@35 805
andrew@35 806 double playingTime = ofGetElapsedTimeMillis();
andrew@35 807 playingTime -= startPlayingTime;
andrew@35 808 //now at the last one
andrew@35 809
andrew@36 810
andrew@36 811
andrew@35 812 while (smoothIndex < recordedEventTimes.size() && recordedEventTimes[smoothIndex] < newPosition){
andrew@36 813 float annotationTime = 0;
andrew@36 814 int annotationNote = 0;
andrew@36 815 if (smoothIndex < myNotation.rwcAnnotations.size()){
andrew@36 816 annotationTime = myNotation.rwcAnnotations[smoothIndex].eventTime;
andrew@36 817 annotationNote = myNotation.rwcAnnotations[smoothIndex].midiNote;
andrew@36 818 }
andrew@36 819
andrew@36 820
andrew@35 821 if ((*fileOutput).is_open()){
andrew@36 822 (*fileOutput) << fixed << beatPositions[smoothIndex] <<",\t" << recordedNoteOnMatrix[smoothIndex][1] << ",\t";
andrew@36 823 (*fileOutput) << playingTime ;
andrew@36 824 float difference = playingTime - (annotationTime*1000.0);
andrew@36 825 if ( recordedNoteOnMatrix[smoothIndex][1] == annotationNote){
andrew@36 826 (*fileOutput) << " corresponds to " << annotationTime;
andrew@36 827 }
andrew@36 828 (*fileOutput) << " \n";
andrew@36 829
andrew@36 830 printf("midi %i beat pos %f now at %f :: annotaion %i time %f diff \t%f ms\n", recordedNoteOnMatrix[smoothIndex][1],
andrew@36 831 beatPositions[smoothIndex], playingTime, annotationNote, annotationTime, difference);
andrew@35 832 }
andrew@35 833
andrew@35 834 smoothIndex++;
andrew@35 835 }
andrew@35 836
andrew@35 837
andrew@35 838 smoothPlayPosition = newPosition;
andrew@35 839
andrew@35 840 }
andrew@35 841
andrew@34 842
andrew@34 843 void midiEventHolder::updatePeriodValue(const double& millis){
andrew@34 844
andrew@34 845 double tmp = period;
andrew@34 846 /*
andrew@34 847 while (periodCounter >= 0 && periodCounter < periodValues.size()-1 && periodValues[periodCounter][2] < millis){
andrew@34 848 periodCounter++;
andrew@34 849 }
andrew@34 850 while (periodCounter > 0 && periodValues[periodCounter][2] > millis){
andrew@34 851 periodCounter--;
andrew@34 852 }
andrew@34 853 */
andrew@34 854 //period = periodValues[periodCounter][1];
andrew@34 855
andrew@34 856 if (period != tmp){
andrew@34 857 printf("new period at %f of %f\n", millis, period);
andrew@34 858 }
andrew@34 859 }
andrew@34 860
andrew@33 861 void midiEventHolder::updateNoteCounter(){
andrew@33 862 while (totalNoteCounterIndex < bestMatchIndex){
andrew@33 863 int tmpPitch = recordedNoteOnMatrix[totalNoteCounterIndex][1];
andrew@33 864 recordedTotalNoteCounterByPitch[tmpPitch] += 1;
andrew@33 865 totalNoteCounterIndex++;
andrew@33 866 }
andrew@33 867 }
andrew@33 868
andrew@33 869
andrew@33 870 void midiEventHolder::drawMidiFile(){
andrew@33 871
andrew@33 872 //draws midi file on scrolling screen
andrew@33 873 int size = recordedNoteOnMatrix.size();
andrew@33 874 if (size > 0){
andrew@33 875
andrew@33 876 numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in
andrew@33 877
andrew@33 878 // numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down
andrew@33 879 timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen);
andrew@33 880
andrew@33 881 while (noteArrayIndex < recordedNoteOnMatrix.size()-1 && tickLocation > recordedNoteOnMatrix[noteArrayIndex][0] )
andrew@33 882 noteArrayIndex++;
andrew@33 883
andrew@33 884
andrew@33 885 while (noteArrayIndex > 0 && noteArrayIndex < size && tickLocation < recordedNoteOnMatrix[noteArrayIndex][0])
andrew@33 886 noteArrayIndex--;
andrew@33 887
andrew@33 888 //need to start where we currently are in file
andrew@33 889 int maxNoteIndexToPrint = noteArrayIndex;
andrew@33 890 int minNoteIndexToPrint = min(size-1,noteArrayIndex);//not needed as changed above
andrew@33 891
andrew@33 892 while (maxNoteIndexToPrint < recordedNoteOnMatrix.size() && recordedNoteOnMatrix[maxNoteIndexToPrint][0] < (numberOfScreensIn+1)*ticksPerScreen )
andrew@33 893 maxNoteIndexToPrint++;
andrew@33 894
andrew@33 895 while (minNoteIndexToPrint > 0 && recordedNoteOnMatrix[minNoteIndexToPrint][0] > numberOfScreensIn*ticksPerScreen)//&& minNoteIndexToPrint < size
andrew@33 896 minNoteIndexToPrint--;
andrew@33 897
andrew@33 898 for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)recordedNoteOnMatrix.size());tmpIndex++){
andrew@33 899
andrew@33 900 ofSetColor(255,255,255);
andrew@33 901 if (checkIfMatchedNote(tmpIndex))
andrew@33 902 ofSetColor(100,100,100);//0,0,255);
andrew@33 903 else if(noteOnMatches[tmpIndex]){
andrew@33 904 ofSetColor(255,0,255);//dark grey
andrew@33 905 }
andrew@33 906 else{
andrew@33 907 ofSetColor(255,255,255);//255,255,255);
andrew@33 908 }
andrew@33 909
andrew@33 910 //ofSetColor(255,255,255);
andrew@33 911 if (tmpIndex == bestMatchIndex)
andrew@33 912 ofSetColor(255,0,0);//best recent match is in red
andrew@33 913
andrew@33 914 // XXX replace ofgetwidth below
andrew@33 915 //if (tmpIndex >= 0 && tmpIndex < size)
andrew@33 916 int xLocation = (float)(recordedNoteOnMatrix[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
andrew@33 917 int duration = (float)(recordedNoteOnMatrix[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen;
andrew@33 918
andrew@33 919
andrew@33 920 int yLocation = (*screenHeight) - ((recordedNoteOnMatrix[tmpIndex][1] - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));
andrew@33 921 ofRect(xLocation,yLocation, duration, noteHeight);
andrew@33 922
andrew@33 923 }
andrew@33 924
andrew@33 925
andrew@33 926 int xLocation;// = getLocationFromTicks(tickLocation);
andrew@33 927 // ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@33 928
andrew@33 929 //orange line at best estimate
andrew@33 930 xLocation = getLocationFromMillis(bayesStruct.bestEstimate);
andrew@34 931 ofSetColor(250,250,20);//250,100,0);
andrew@33 932 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@33 933
andrew@34 934 xLocation = getLocationFromMillis(smoothPlayPosition);//bayesStruct.tmpBestEstimate
andrew@34 935 ofSetColor(0,250,0);//250,150, 250,100,0);
andrew@33 936 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@33 937
andrew@33 938
andrew@33 939 //lines where matching window start and end are
andrew@33 940 ofSetColor(0);//0,100,255);
andrew@33 941 xLocation = getLocationFromMillis(windowStartTime);
andrew@33 942 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@33 943 xLocation = getLocationFromMillis(windowStartTime+matchWindowWidth);
andrew@33 944 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@33 945
andrew@33 946
andrew@33 947 int maxSize = recordedNoteOnMatrix[size-1][0];
andrew@33 948
andrew@33 949 int tmpIndex = 0;
andrew@33 950 while (tmpIndex < measureVector.size() && measureVector[tmpIndex] < (numberOfScreensIn+1)*ticksPerScreen){
andrew@33 951 int measureLocation = measureVector[tmpIndex];
andrew@33 952 int xLocation = (float)(measureLocation - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
andrew@33 953 ofSetColor(155,155,0);
andrew@33 954 ofLine(xLocation, 0, xLocation, (*screenHeight));
andrew@33 955 tmpIndex++;
andrew@33 956 }
andrew@33 957
andrew@33 958
andrew@33 959 // ofDrawBitmapString(tempoSpeedString, 20, 20);
andrew@33 960 /* string indexString = "num screens in "+ofToString(numberOfScreensIn)+"; min index to print "+ofToString(minNoteIndexToPrint)+", max index to print "+ofToString(maxNoteIndexToPrint);
andrew@33 961 indexString += " size "+ofToString(size)+" tick loc "+ofToString(tickLocation)+" max size "+ofToString(maxSize);
andrew@33 962 ofDrawBitmapString(indexString, 20, 40);
andrew@33 963 */
andrew@33 964 }
andrew@33 965
andrew@33 966 //ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20);
andrew@33 967
andrew@33 968 //ofDrawBitmapString(timeString, 20, 60);
andrew@33 969
andrew@33 970 //last played piutch
andrew@33 971 ofSetColor(0,200,0,50);
andrew@33 972 int yLocation = (*screenHeight) - ((lastPlayedPitch - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));
andrew@33 973 ofRect(0,yLocation, 100, noteHeight);
andrew@33 974
andrew@33 975
andrew@33 976
andrew@33 977 }
andrew@33 978
andrew@33 979
andrew@33 980
andrew@33 981 void midiEventHolder::drawMidiFile(IntMatrix& midiFileToDraw){
andrew@33 982
andrew@33 983 //using this to draw the live input
andrew@33 984
andrew@33 985 //draws midi file on scrolling screen
andrew@33 986 int size = midiFileToDraw.size();
andrew@33 987 if (size > 0){
andrew@33 988
andrew@33 989 numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in
andrew@33 990
andrew@33 991 // numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down
andrew@33 992 timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen);
andrew@33 993
andrew@33 994 while (noteArrayIndex < midiFileToDraw.size()-1 && tickLocation > midiFileToDraw[noteArrayIndex][0] )
andrew@33 995 noteArrayIndex++;
andrew@33 996
andrew@33 997
andrew@33 998 while (noteArrayIndex > 0 && noteArrayIndex < size && tickLocation < midiFileToDraw[noteArrayIndex][0])
andrew@33 999 noteArrayIndex--;
andrew@33 1000
andrew@33 1001 //need to start where we currently are in file
andrew@33 1002 int maxNoteIndexToPrint = noteArrayIndex;
andrew@33 1003 int minNoteIndexToPrint = min(size-1,noteArrayIndex);//not needed as changed above
andrew@33 1004
andrew@33 1005 while (maxNoteIndexToPrint < midiFileToDraw.size() && midiFileToDraw[maxNoteIndexToPrint][0] < (numberOfScreensIn+1)*ticksPerScreen )
andrew@33 1006 maxNoteIndexToPrint++;
andrew@33 1007
andrew@33 1008 while (minNoteIndexToPrint > 0 && midiFileToDraw[minNoteIndexToPrint][0] > numberOfScreensIn*ticksPerScreen)//&& minNoteIndexToPrint < size
andrew@33 1009 minNoteIndexToPrint--;
andrew@33 1010
andrew@33 1011 for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)midiFileToDraw.size());tmpIndex++){
andrew@33 1012
andrew@33 1013 ofSetColor(0,0,255, 200);
andrew@33 1014
andrew@33 1015 int xLocation = (float)(midiFileToDraw[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
andrew@33 1016 int duration = (float)(midiFileToDraw[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen;
andrew@33 1017
andrew@33 1018
andrew@33 1019 int yLocation = (*screenHeight) - ((midiFileToDraw[tmpIndex][1] - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));
andrew@33 1020 ofRect(xLocation,yLocation, duration, noteHeight);
andrew@33 1021
andrew@33 1022 }
andrew@33 1023
andrew@33 1024
andrew@33 1025
andrew@33 1026 }
andrew@33 1027
andrew@33 1028
andrew@33 1029
andrew@33 1030 }
andrew@33 1031
andrew@33 1032
andrew@33 1033
andrew@33 1034 void midiEventHolder::drawFile(){
andrew@33 1035 drawMidiFile();
andrew@33 1036
andrew@34 1037 ofSetColor(0,0,255);
andrew@34 1038 ofDrawBitmapString("period"+ofToString(period, 2), ofGetWidth() - 180, 20);
andrew@33 1039
andrew@33 1040 // bayesStruct.drawArrays();
andrew@33 1041
andrew@33 1042 // ofSetColor(200,200,0);
andrew@33 1043 // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800);
andrew@33 1044
andrew@33 1045 //need to draw arrays within correct timescope
andrew@33 1046 if (drawPhaseMode)
andrew@33 1047 bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen));
andrew@33 1048
andrew@33 1049 if (drawTempoMode)
andrew@33 1050 bayesStruct.drawTempoArrays();
andrew@33 1051
andrew@33 1052
andrew@33 1053 ofSetColor(0, 0, 0);
andrew@33 1054 //ofDrawBitmapString(matchString, 20, ofGetHeight() - 20);
andrew@33 1055
andrew@33 1056 double confidence = bayesStruct.posterior.getValueAtMillis(mouseX);
andrew@33 1057 /*
andrew@33 1058 string mouseString = "mouseX "+ofToString(confidence, 3)+" .";
andrew@33 1059 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40);
andrew@33 1060
andrew@33 1061 string mouseString = "updateCounter "+ofToString(bayesStruct.updateCounter);
andrew@33 1062 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40);
andrew@33 1063
andrew@33 1064 string infostring = "speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 3);
andrew@33 1065 ofDrawBitmapString(infostring, 20 , ofGetHeight() - 60);
andrew@33 1066 */
andrew@33 1067
andrew@33 1068 //drawInterNoteIntervals();
andrew@33 1069
andrew@33 1070 }
andrew@33 1071
andrew@33 1072 void midiEventHolder::drawInterNoteIntervals(){
andrew@33 1073
andrew@33 1074 ofSetColor(0,0,150);
andrew@33 1075 int size = interNoteIntervals.size();
andrew@33 1076 int numberToShow = min(100, size);
andrew@33 1077 double x ;
andrew@33 1078 for (int y = 1;y < numberToShow;y++){
andrew@33 1079 for (int point = 0;point < interNoteIntervals[y].size();point++){
andrew@33 1080 double interval = interNoteIntervals[size - y][point];
andrew@33 1081 x = interval - 200;
andrew@33 1082 x *= (*screenWidth) / 200.0;
andrew@33 1083 }
andrew@33 1084 double h = (double)(y * (*screenHeight)) / numberToShow;
andrew@33 1085 ofCircle(x, h, 5);
andrew@33 1086 }
andrew@33 1087
andrew@33 1088 }
andrew@33 1089
andrew@33 1090
andrew@33 1091 void midiEventHolder::printInterNoteIntervals(){
andrew@33 1092
andrew@33 1093 int size = interNoteIntervals.size();
andrew@33 1094 int numberToShow = 20;
andrew@33 1095 double x ;
andrew@33 1096 for (int y = max(0, size - numberToShow);y < interNoteIntervals.size();y++){
andrew@33 1097 for (int point = 0;point < interNoteIntervals[y].size();point++){
andrew@33 1098 printf("[%i][%i] : %f", y, point, interNoteIntervals[y][point]);
andrew@33 1099 }
andrew@33 1100 printf("\n");
andrew@33 1101 }
andrew@33 1102
andrew@33 1103 }
andrew@33 1104
andrew@33 1105 int midiEventHolder::getLocationFromTicks(double tickPosition){
andrew@34 1106 return 0;
andrew@34 1107 // return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen);
andrew@34 1108 //not used
andrew@33 1109 }
andrew@33 1110
andrew@33 1111 int midiEventHolder::getLocationFromMillis(double millisPosition){
andrew@33 1112 //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen
andrew@33 1113 return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen);
andrew@33 1114 }
andrew@33 1115
andrew@33 1116
andrew@33 1117 void midiEventHolder::exampleCrossUpdate(){
andrew@33 1118
andrew@33 1119 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, 200);
andrew@33 1120
andrew@33 1121 }
andrew@33 1122
andrew@33 1123
andrew@33 1124 void midiEventHolder::setStartPlayingTimes(){
andrew@34 1125 startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis();
andrew@34 1126 //startTime = startPlayingTime;
andrew@33 1127
andrew@33 1128 /*
andrew@33 1129 bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis();
andrew@33 1130 bayesStruct.bestEstimate = 0;
andrew@33 1131 bayesStruct.resetArrays();
andrew@33 1132 bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
andrew@33 1133 */
andrew@33 1134 bayesStruct.setStartPlaying();
andrew@33 1135 matchString = "";
andrew@33 1136 }
andrew@33 1137
andrew@33 1138
andrew@33 1139 void midiEventHolder::printMatchMatrix(){
andrew@33 1140 printf("match matrix:\n");
andrew@33 1141 for (int i = 0;i < matchMatrix.size();i++){
andrew@33 1142 for (int k = 0;k < matchMatrix[i].size();k++){
andrew@33 1143 printf("%i , ", matchMatrix[i][k]);
andrew@33 1144 }
andrew@33 1145 printf("\n");
andrew@33 1146 }
andrew@33 1147
andrew@33 1148 }
andrew@33 1149
andrew@33 1150
andrew@33 1151
andrew@33 1152 void midiEventHolder::printRecordedEvents(){
andrew@33 1153 printf("Recorded Events:\n");
andrew@33 1154 for (int i = 0;i < recordedNoteOnMatrix.size();i++){
andrew@33 1155 for (int k = 0;k < recordedNoteOnMatrix[i].size();k++){
andrew@33 1156 printf("[%i] = %i ,", i, recordedNoteOnMatrix[i][k]);
andrew@33 1157 }
andrew@33 1158 if (i < recordedEventTimes.size())
andrew@33 1159 printf("time %f \n", recordedEventTimes[i]);
andrew@33 1160 else
andrew@33 1161 printf("\n");
andrew@33 1162 }
andrew@33 1163
andrew@33 1164 }
andrew@33 1165
andrew@33 1166
andrew@33 1167
andrew@33 1168 void midiEventHolder::reorderMatrixFromNoteTimes(IntMatrix& noteOnMatrix){
andrew@33 1169 double currentTime = -19999.;
andrew@33 1170 for (int i = 0;i < noteOnMatrix.size();i++){
andrew@33 1171 int nextIndex = getIndexOfMinimumAboveTime(currentTime, noteOnMatrix);
andrew@33 1172 // cout << "index of min time " << currentTime << " is " << nextIndex << " at time " << noteOnMatrix[nextIndex][0] << endl;
andrew@33 1173
andrew@33 1174 if (nextIndex >= 0 && nextIndex > i && noteOnMatrix[nextIndex][0] < noteOnMatrix[i][0] ){
andrew@33 1175 //which it should be
andrew@33 1176 // cout << " index " << nextIndex << " at time " << noteOnMatrix[nextIndex][0] << " swaps with inex " << i << " at time " << noteOnMatrix[i][0] << endl;
andrew@33 1177 noteOnMatrix[i].swap(noteOnMatrix[nextIndex]);
andrew@35 1178 // double tmp = beatPositions[i];
andrew@35 1179 // beatPositions[i] = beatPositions[nextIndex];
andrew@35 1180 // = tmp;
andrew@35 1181
andrew@35 1182 swap (beatPositions[i], beatPositions[nextIndex]);
andrew@35 1183
andrew@35 1184
andrew@33 1185 currentTime = noteOnMatrix[i][0];
andrew@33 1186 }
andrew@33 1187
andrew@33 1188 }
andrew@33 1189 //printRecordedEvents();
andrew@33 1190
andrew@33 1191 }
andrew@33 1192
andrew@33 1193
andrew@33 1194
andrew@33 1195
andrew@33 1196 void midiEventHolder::doublecheckOrder(IntMatrix& noteOnMatrix){
andrew@33 1197
andrew@33 1198 for (int i = 0;i < noteOnMatrix.size();i++){
andrew@33 1199 int nextIndex = getIndexOfMinimumAboveIndex(i, noteOnMatrix);
andrew@33 1200 if (nextIndex > i){
andrew@33 1201 noteOnMatrix[i].swap(noteOnMatrix[nextIndex]);
andrew@35 1202 swap (beatPositions[i], beatPositions[nextIndex]);
andrew@35 1203
andrew@33 1204 }
andrew@33 1205 }
andrew@33 1206 }
andrew@33 1207
andrew@33 1208 int midiEventHolder::getIndexOfMinimumAboveIndex(const int& index, IntMatrix& noteOnMatrix){
andrew@33 1209 int returnIndex = index;
andrew@33 1210 int min = noteOnMatrix[index][0];
andrew@33 1211 for (int i = index;i < noteOnMatrix.size();i++){
andrew@33 1212 if (noteOnMatrix[i][0] < min){
andrew@33 1213 returnIndex = i;
andrew@33 1214 min = noteOnMatrix[i][0];
andrew@33 1215 }
andrew@33 1216 }
andrew@33 1217 return returnIndex;
andrew@33 1218 }
andrew@33 1219
andrew@33 1220
andrew@33 1221 int midiEventHolder::getIndexOfMinimumAboveTime(const double& time, IntMatrix& noteOnMatrix){
andrew@33 1222 int index = 0;
andrew@33 1223 double minimumTime = 100000000.;
andrew@33 1224 int bestIndex = -1;
andrew@33 1225 while (index < noteOnMatrix.size()){
andrew@33 1226
andrew@33 1227 if (noteOnMatrix[index][0] > time && noteOnMatrix[index][0] < minimumTime){
andrew@33 1228 bestIndex = index;
andrew@33 1229 minimumTime = noteOnMatrix[index][0];
andrew@33 1230 }
andrew@33 1231 index++;
andrew@33 1232 }
andrew@33 1233 return bestIndex;
andrew@33 1234 }
andrew@33 1235
andrew@33 1236
andrew@33 1237
andrew@33 1238
andrew@33 1239 void midiEventHolder::correctTiming(IntMatrix& noteOnMatrix){
andrew@33 1240
andrew@33 1241 if (noteOnMatrix.size() > 0 && noteOnMatrix[0][0] < 0) {
andrew@33 1242 int offset = noteOnMatrix[0][0];
andrew@33 1243 for (int i = 0;i < noteOnMatrix.size();i++){
andrew@33 1244 noteOnMatrix[i][0] -= offset;
andrew@33 1245 }
andrew@33 1246 }
andrew@33 1247
andrew@33 1248 }
andrew@33 1249
andrew@33 1250
andrew@33 1251 void midiEventHolder::printNoteCounter(){
andrew@33 1252 for (int i = 0;i < recordedTotalNoteCounterByPitch.size();i++){
andrew@33 1253 printf("RECORDED TOTAL[%i] := %i", i, recordedTotalNoteCounterByPitch[i]);
andrew@33 1254 }
andrew@34 1255 }
andrew@34 1256
andrew@34 1257 /* double timeDiff = 0;//timeDifference;
andrew@34 1258 if (runningInRealTime)
andrew@34 1259 timeDiff = ofGetElapsedTimeMillis() - lastSmoothUpdateTime;
andrew@34 1260 // bayesStruct.lastBestEstimateUpdateTime;
andrew@34 1261
andrew@34 1262 //smoothPlayPosition = bayesStruct.bestEstimate + 100;
andrew@34 1263 //relativeSpeedForSmooth = 0.1;
andrew@34 1264 //bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate);
andrew@34 1265 // speedEstimate*2;
andrew@34 1266
andrew@34 1267 smoothPlayPosition = storedSmoothPlayPosition + timeDiff * relativeSpeedForSmooth;// * bayesStruct.speedEstimate;
andrew@34 1268 storedSmoothPlayPosition = smoothPlayPosition;
andrew@34 1269 lastSmoothUpdateTime = getTimeNow(bayesStruct.lastBestEstimateUpdateTime);
andrew@34 1270 updateSmoothPlaySpeed();
andrew@34 1271 //bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate)
andrew@34 1272
andrew@34 1273 }
andrew@34 1274
andrew@34 1275 void midiEventHolder::updateSmoothPlaySpeed(){
andrew@34 1276 //project where current play pos will be in two seconds and aim for it.
andrew@34 1277 double timeToAimForMillis = 2000.0;
andrew@34 1278 //double timeDiff = ofGetElapsedTimeMillis() - bayesStruct.lastBestEstimateUpdateTime;//since the update need to get to where we are
andrew@34 1279 double projection = bayesStruct.bestEstimate + bayesStruct.speedEstimate*timeToAimForMillis;//
andrew@34 1280 double timeDifferenceFromSmooth = projection - smoothPlayPosition;
andrew@34 1281 relativeSpeedForSmooth = timeDifferenceFromSmooth / timeToAimForMillis;
andrew@34 1282
andrew@34 1283 }
andrew@34 1284 */
andrew@35 1285
andrew@35 1286
andrew@35 1287 /*
andrew@35 1288 void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){
andrew@35 1289 bool needToUpdate = false;
andrew@35 1290
andrew@35 1291 //adapted this to just use the best match for each note
andrew@35 1292
andrew@35 1293 int currentPlayedIndex = playedNoteOnMatrix.size()-1;
andrew@35 1294 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]);
andrew@35 1295 // printMatchesFound();
andrew@35 1296 // printMatchMatrix();
andrew@35 1297 // printf("possible notes \n");
andrew@35 1298
andrew@35 1299 bayesStruct.setLikelihoodToConstant();
andrew@35 1300
andrew@35 1301 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){
andrew@35 1302
andrew@35 1303 //iterate through the recently matched events - even dodgy matches included
andrew@35 1304 //size, index of match0, index of match1, ....
andrew@35 1305 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1];
andrew@35 1306
andrew@35 1307 double currentMatchConfidence = matchConfidence[currentPlayedIndex][i+1];//new confidence
andrew@35 1308
andrew@35 1309 int previousIndex = currentPlayedIndex-1;
andrew@35 1310
andrew@35 1311 while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) {
andrew@35 1312 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
andrew@35 1313
andrew@35 1314 // for (int k = 0;k < matchMatrix[previousIndex][0];k++)
andrew@35 1315 int recordedPreviousIndex = bestMatchFound[previousIndex];//matchMatrix[previousIndex][k+1];
andrew@35 1316
andrew@35 1317 //double previousMatchConfidence = matchConfidence[previousIndex][k+1];
andrew@35 1318
andrew@35 1319
andrew@35 1320 double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex];
andrew@35 1321
andrew@35 1322
andrew@35 1323 //we want the speed of the recording relative to that of the playing live
andrew@35 1324
andrew@35 1325 double speedRatio = recordedTimeDifference / playedTimeDifference;
andrew@35 1326 if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){
andrew@35 1327
andrew@35 1328 printf("(%i)", matchMatrix[currentPlayedIndex][i+1]);
andrew@35 1329 printf("[%i] :: ", recordedPreviousIndex);
andrew@35 1330 // printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence);
andrew@35 1331 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference);
andrew@35 1332 printf("update on speed ratio %f\n", speedRatio);
andrew@35 1333
andrew@35 1334 // matchString += " speed: "+ofToString(speedRatio, 3);
andrew@35 1335 // commented for debug
andrew@35 1336
andrew@35 1337
andrew@35 1338 double priorWeighting = 1;
andrew@35 1339
andrew@35 1340 if (useTempoPrior)
andrew@35 1341 priorWeighting = sin(speedRatio * PI/2);//adding in a prior that prefers 1.0 speed
andrew@35 1342
andrew@35 1343
andrew@35 1344 // double weighting = previousMatchConfidence * currentMatchConfidence ;
andrew@35 1345 double amount = (1-bayesStruct.speedLikelihoodNoise)*priorWeighting/10;
andrew@35 1346 bayesStruct.updateTempoLikelihood(speedRatio, amount);//second paramter is confidence in the match
andrew@35 1347 tempoSpeedString += ofToString(recordedPreviousIndex) + " " + ofToString(speedRatio, 2) + " "+ofToString(amount, 2) += " \n";
andrew@35 1348
andrew@35 1349 needToUpdate = true;
andrew@35 1350 }
andrew@35 1351 // printf("\n");
andrew@35 1352
andrew@35 1353
andrew@35 1354 previousIndex--;
andrew@35 1355 }//end while previousindex countdown
andrew@35 1356 }//end for loop through possible current matches
andrew@35 1357
andrew@35 1358 if (needToUpdate)
andrew@35 1359 bayesStruct.updateTempoDistribution();
andrew@35 1360 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
andrew@35 1361 }
andrew@35 1362 */
andrew@35 1363