comparison src/midiEventHolder.cpp @ 2:5581023e0de4

Added separate CannamMidiFileLoader class to handle the loading in.
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 19 Aug 2011 01:26:40 +0100
parents 1a32ce016bb9
children de86d77f2612
comparison
equal deleted inserted replaced
1:1a32ce016bb9 2:5581023e0de4
25 noteMinimum = 30; 25 noteMinimum = 30;
26 noteMaximum = 96; 26 noteMaximum = 96;
27 27
28 minimumMatchSpeed = 0.7; 28 minimumMatchSpeed = 0.7;
29 maximumMatchSpeed = 1.3; 29 maximumMatchSpeed = 1.3;
30
30 likelihoodWidth = 100; 31 likelihoodWidth = 100;
31 likelihoodToNoiseRatio = 50; 32 likelihoodToNoiseRatio = 0.02;
32 33
33 matchWindowWidth = 4000;//window size for matching in ms 34 bayesStruct.speedLikelihoodNoise = 0.05;//was 0.05
35 bayesStruct.speedDecayWidth = 20;
36 bayesStruct.speedDecayAmount = 10;
37
38
39 matchWindowWidth = 8000;//window size for matching in ms
34 40
35 bayesStruct.resetSize(matchWindowWidth); 41 bayesStruct.resetSize(matchWindowWidth);
42 bayesStruct.setPositionDistributionScalar(1);
43
36 bayesStruct.resetSpeedSize(200); 44 bayesStruct.resetSpeedSize(200);
37 bayesStruct.setRelativeSpeedScalar(0.01); 45 bayesStruct.setRelativeSpeedScalar(0.01);
38 bayesStruct.relativeSpeedPrior.getMaximum(); 46 bayesStruct.relativeSpeedPrior.getMaximum();
39 bayesStruct.simpleExample(); 47 //bayesStruct.simpleExample();
48
40 49
41 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); 50 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum);
42 } 51 }
43 52
44 53
45 54
46 void midiEventHolder::reset(){ 55 void midiEventHolder::reset(){
56 //called when we start playing
57
47 noteArrayIndex = 0; 58 noteArrayIndex = 0;
48 tickLocation = 0; 59 tickLocation = 0;
49 lastPeriodUpdateTime = ofGetElapsedTimeMillis(); 60 lastPeriodUpdateTime = ofGetElapsedTimeMillis();
50 bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); 61 bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
51 numberOfScreensIn = 0; 62 numberOfScreensIn = 0;
106 v.push_back(velocity); 117 v.push_back(velocity);
107 playedNoteOnMatrix.push_back(v); 118 playedNoteOnMatrix.push_back(v);
108 119
109 120
110 //would update the arrays at this point to show where out current location (phase) and tempo is. 121 //would update the arrays at this point to show where out current location (phase) and tempo is.
111 double timeNow = ofGetElapsedTimeMillis() - startTime; 122 // double timeNow = ofGetElapsedTimeMillis() - startTime;
112 recentNoteOnTime = timeNow; 123 double timeNow = timePlayed;// - startTime;
113 124 recentNoteOnTime = timePlayed;
114 printf("Max time %f OF time %f \n", timePlayed, timeNow); 125
126 // printf("Max time %f OF time %f \n", timePlayed, timeNow);
115 127
116 playedEventTimes.push_back(timePlayed); 128 playedEventTimes.push_back(timePlayed);
117 129
118 double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; 130 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime;
119 131 double timeDifference = timePlayed - bayesStruct.lastEventTime;
132
133 printf("note %i played at %f and last event %f\n", pitch, timePlayed, bayesStruct.lastEventTime);
120 //addnoise to the tempo distribution 134 //addnoise to the tempo distribution
121 bayesStruct.decaySpeedDistribution(timeDifference); 135 //bayesStruct.decaySpeedDistribution(timeDifference);
122 136 if (timeDifference > 50){
137 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.);
138 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.);
139 }
140
141 bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate;
142 bayesStruct.updateBestEstimate();
143 bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
123 144
124 // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate); 145 // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate);
125 //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis 146 //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis
126 147
127 timeString = "Pitch:"+ofToString(pitch); 148 timeString = "Pitch:"+ofToString(pitch);
147 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.MAPestimate, 1); 168 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.MAPestimate, 1);
148 timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 1); 169 timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 1);
149 170
150 171
151 //be able to draw the prior in correct location relative to the midi notes 172 //be able to draw the prior in correct location relative to the midi notes
173 //this calculates the cross update of all possible speeds and all possible positions
152 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference); 174 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference);
153 // bayesStruct.crossUpdateArrays(bayesStruct.prior, bayesStruct.relativeSpeedPosterior, timeDifference);
154 175
155 176
156 timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1); 177 timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1);
157 timeString += " notearrayindex "+ofToString(noteArrayIndex, 0); 178 timeString += " notearrayindex "+ofToString(noteArrayIndex, 0);
158 //when this is off teh screen there is a problem somehow XXX 179 //when this is off teh screen there is a problem somehow XXX
159 bayesStruct.posterior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); 180 bayesStruct.posterior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
160 // bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); 181 // bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
161 //trying to switch to prior 182 //trying to switch to prior
162 183
163 bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); 184 //bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
185 bayesStruct.lastEventTime = timePlayed;
164 186
165 //do the cross update to find current posterior for location 187 //do the cross update to find current posterior for location
166 // totalConfidence= 0; 188 // totalConfidence= 0;
167 int numberOfMatchesFound = findLocalMatches(pitch); 189 int numberOfMatchesFound = findLocalMatches(pitch);
168 setMatchLikelihoods(numberOfMatchesFound); 190 setMatchLikelihoods(numberOfMatchesFound);
169 bayesStruct.calculatePosterior(); 191 bayesStruct.calculatePosterior();
170 192
171 //having found matches we have matches for new note and matches for previous notes 193 //having found matches we have matches for new note and matches for previous notes
172 findLocalTempoPairs(); 194 findLocalTempoPairs();
173 195
174 196 //bayesStruct.addGaussianNoiseToSpeedPosterior(10);
175 197
176 } 198 }
177 199
178 int midiEventHolder::findLocalMatches(int notePitch){ 200 int midiEventHolder::findLocalMatches(int notePitch){
179 201
195 void midiEventHolder::setMatchLikelihoods(int numberOfMatches){ 217 void midiEventHolder::setMatchLikelihoods(int numberOfMatches){
196 //reset the offset to match the prior 218 //reset the offset to match the prior
197 bayesStruct.likelihood.offset = bayesStruct.prior.offset; 219 bayesStruct.likelihood.offset = bayesStruct.prior.offset;
198 bayesStruct.likelihood.zero();//set to zero 220 bayesStruct.likelihood.zero();//set to zero
199 221
200 222 double quantity = likelihoodToNoiseRatio / numberOfMatches;
201 223
202 for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){ 224 for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){
203 // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset); 225 // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset);
204 //this is the vent time since start of file 226 //this is the vent time since start of file
205 if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){ 227 if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){
206 // double confidenceMeasure = 0; 228 // double confidenceMeasure = 0;
207 // if (totalConfidence > 0) 229 // if (totalConfidence > 0)
208 // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence; 230 // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence;
209 231
210 bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, 0.5 * likelihoodToNoiseRatio );//* confidenceMeasure 232 bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, quantity);//* confidenceMeasure
211 }//end if 233 }//end if
212 } 234 }
213 bayesStruct.likelihood.addConstant(0.01); 235 bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length);
214 } 236 }
215 237
216 int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){ 238 int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){
217 239
218 matchesFound.clear(); 240 matchesFound.clear();
288 310
289 //we want the speed of the recording relative to that of the playing live 311 //we want the speed of the recording relative to that of the playing live
290 312
291 double speedRatio = recordedTimeDifference / playedTimeDifference; 313 double speedRatio = recordedTimeDifference / playedTimeDifference;
292 if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){ 314 if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){
293 printf("(%i)", matchMatrix[currentPlayedIndex][i+1]); 315 /*
316 printf("(%i)", matchMatrix[currentPlayedIndex][i+1]);
294 printf("[%i] :: ", recordedPreviousIndex); 317 printf("[%i] :: ", recordedPreviousIndex);
295 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); 318 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference);
296 printf("update on speed ratio %f\n", speedRatio); 319 printf("update on speed ratio %f\n", speedRatio);
320 */
297 // matchString += " speed: "+ofToString(speedRatio, 3); 321 // matchString += " speed: "+ofToString(speedRatio, 3);
298 // commented for debug 322 // commented for debug
299 bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match 323
324 bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match
300 325
301 } 326 }
302 // printf("\n"); 327 // printf("\n");
303 } 328 }
304 329
305 previousIndex--; 330 previousIndex--;
306 }//end while previousindex countdown 331 }//end while previousindex countdown
307 }//end for loop through possible current matches 332 }//end for loop through possible current matches
308 333
309 334 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
310 } 335 }
311 336
312 337
313 void midiEventHolder::updatePlayPosition(){ 338 void midiEventHolder::updatePlayPosition(){
314 339
378 int xLocation;// = getLocationFromTicks(tickLocation); 403 int xLocation;// = getLocationFromTicks(tickLocation);
379 // ofLine(xLocation, 0, xLocation, (*screenHeight)); 404 // ofLine(xLocation, 0, xLocation, (*screenHeight));
380 405
381 //orange line at best estimate 406 //orange line at best estimate
382 xLocation = getLocationFromMillis(bayesStruct.bestEstimate); 407 xLocation = getLocationFromMillis(bayesStruct.bestEstimate);
408 ofSetColor(250,100,0);
409 ofLine(xLocation, 0, xLocation, (*screenHeight));
410
411 xLocation = getLocationFromMillis(bayesStruct.tmpBestEstimate);
383 ofSetColor(250,100,0); 412 ofSetColor(250,100,0);
384 ofLine(xLocation, 0, xLocation, (*screenHeight)); 413 ofLine(xLocation, 0, xLocation, (*screenHeight));
385 414
386 415
387 //lines where matching window start and end are 416 //lines where matching window start and end are
414 443
415 ofSetColor(0, 0, 0); 444 ofSetColor(0, 0, 0);
416 ofDrawBitmapString(matchString, 20, ofGetHeight() - 20); 445 ofDrawBitmapString(matchString, 20, ofGetHeight() - 20);
417 446
418 double confidence = bayesStruct.posterior.getValueAtMillis(mouseX); 447 double confidence = bayesStruct.posterior.getValueAtMillis(mouseX);
419 string mouseString = "mouseX "+ofToString(confidence, 3)+" ."; 448 /*
449 string mouseString = "mouseX "+ofToString(confidence, 3)+" .";
420 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40); 450 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40);
451 */
452 string mouseString = "updateCounter "+ofToString(bayesStruct.updateCounter);
453 ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40);
454
455 string infostring = "speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 3);
456 ofDrawBitmapString(infostring, 20 , ofGetHeight() - 60);
421 } 457 }
422 458
423 int midiEventHolder::getLocationFromTicks(double tickPosition){ 459 int midiEventHolder::getLocationFromTicks(double tickPosition){
424 return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen); 460 return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen);
425 } 461 }
437 } 473 }
438 474
439 475
440 void midiEventHolder::setStartPlayingTimes(){ 476 void midiEventHolder::setStartPlayingTimes(){
441 lastPeriodUpdateTime = ofGetElapsedTimeMillis(); 477 lastPeriodUpdateTime = ofGetElapsedTimeMillis();
442 bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
443 startTime = lastPeriodUpdateTime; 478 startTime = lastPeriodUpdateTime;
444 479
480 /*
481 bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis();
482 bayesStruct.bestEstimate = 0;
445 bayesStruct.resetArrays(); 483 bayesStruct.resetArrays();
446 // bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); 484 bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
485 */
486 bayesStruct.setStartPlaying();
447 matchString = ""; 487 matchString = "";
448 } 488 }
449 489
450 490
451 void midiEventHolder::printMatchMatrix(){ 491 void midiEventHolder::printMatchMatrix(){