Mercurial > hg > midi-score-follower
comparison jnmr/midiEventHolder.cpp @ 46:43edc8abe2a7
Fixed bug in complex update due to mismatch between ms and vector units
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Sun, 05 Feb 2012 19:40:21 +0000 |
parents | 6c8a048720c3 |
children | 1726189a6317 |
comparison
equal
deleted
inserted
replaced
45:90ad1817ca56 | 46:43edc8abe2a7 |
---|---|
8 */ | 8 */ |
9 | 9 |
10 | 10 |
11 //Main file to look at here is newNoteEvent() - this calls everything else to update the Bayesian array | 11 //Main file to look at here is newNoteEvent() - this calls everything else to update the Bayesian array |
12 | 12 |
13 //Relative speed is RECORDED / PLAYED | |
14 //so for timedifference t | |
15 //this is t/scalar in terms of position units of played time | |
16 //and by relative speed r, r*t/scalar | |
17 | |
18 | |
13 #include "midiEventHolder.h" | 19 #include "midiEventHolder.h" |
14 | 20 |
15 #include <iostream> | 21 #include <iostream> |
16 #include <fstream> | 22 #include <fstream> |
17 #include <assert.h> | 23 #include <assert.h> |
18 | 24 |
19 midiEventHolder::midiEventHolder(){ | 25 midiEventHolder::midiEventHolder(){ |
20 | 26 |
21 | 27 |
28 double scalarForPositionVectors = 20; | |
22 | 29 |
23 // recordedNoteOnIndex = 0; | 30 // recordedNoteOnIndex = 0; |
24 alignmentPosition = 0; | 31 alignmentPosition = 0; |
25 | 32 |
26 useTempoPrior = false;//puts sine wave round tempo | 33 useTempoPrior = false;//puts sine wave round tempo |
66 | 73 |
67 | 74 |
68 | 75 |
69 speedPriorValue = 1.0; | 76 speedPriorValue = 1.0; |
70 | 77 |
71 | 78 int tmpArraySize = (int)(matchWindowWidth/scalarForPositionVectors); |
72 bayesStruct.resetSize(matchWindowWidth); | 79 bayesStruct.resetSize(tmpArraySize); |
73 bayesStruct.setPositionDistributionScalar(1); | 80 bayesStruct.setPositionDistributionScalar(scalarForPositionVectors); |
81 printf("ARRAY SIZE IS %i\n", tmpArraySize); | |
74 | 82 |
75 bayesStruct.resetSpeedSize(200); | 83 bayesStruct.resetSpeedSize(200); |
76 bayesStruct.setRelativeSpeedScalar(0.01); | 84 bayesStruct.setRelativeSpeedScalar(0.01); |
77 bayesStruct.relativeSpeedPrior.getMaximum(); | 85 bayesStruct.relativeSpeedPrior.getMaximum(); |
78 //bayesStruct.simpleExample(); | 86 //bayesStruct.simpleExample(); |
127 // relativeSpeedForSmooth = 1.0; | 135 // relativeSpeedForSmooth = 1.0; |
128 // storedSmoothPlayPosition = smoothPlayPosition; | 136 // storedSmoothPlayPosition = smoothPlayPosition; |
129 // lastSmoothUpdateTime = getTimeNow(0); | 137 // lastSmoothUpdateTime = getTimeNow(0); |
130 | 138 |
131 printf("reset speed prior is %f\n", speedPriorValue); | 139 printf("reset speed prior is %f\n", speedPriorValue); |
132 bayesStruct.resetSpeedToOne(); | 140 // bayesStruct.resetSpeedToOne(); |
133 bayesStruct.setSpeedPrior(speedPriorValue); | 141 bayesStruct.setSpeedPrior(speedPriorValue); |
134 setMatchedNotesBackToFalse(); | 142 setMatchedNotesBackToFalse(); |
135 | 143 |
136 periodCounter = 0; | 144 // periodCounter = 0; |
137 for (int i = 0;i < periodValues.size();i++){ | 145 // for (int i = 0;i < periodValues.size();i++){ |
138 // printf("period at %f is %f\n", periodValues[i][2], periodValues[i][1]); | 146 // printf("period at %f is %f\n", periodValues[i][2], periodValues[i][1]); |
139 } | 147 // } |
140 /* if (periodValues.size() > 0){ | 148 /* if (periodValues.size() > 0){ |
141 updatePeriodValue(0);// periodValues[0][2]; | 149 updatePeriodValue(0);// periodValues[0][2]; |
142 printf("Resetting period to %f , size is %i\n", period, (int)periodValues.size()); | 150 printf("Resetting period to %f , size is %i\n", period, (int)periodValues.size()); |
143 } | 151 } |
144 */ | 152 */ |
187 return (period * ticks / (double) pulsesPerQuarternote); | 195 return (period * ticks / (double) pulsesPerQuarternote); |
188 } | 196 } |
189 | 197 |
190 void midiEventHolder::newNoteOnEvent(int pitch, int velocity, double timePlayed){ | 198 void midiEventHolder::newNoteOnEvent(int pitch, int velocity, double timePlayed){ |
191 // tempoSpeedString = ""; | 199 // tempoSpeedString = ""; |
192 | 200 |
193 //MOVE INTO BAYESSTRUCT?? XXX | 201 //MOVE INTO BAYESSTRUCT?? XXX |
194 //bayesStruct.copyPriorToPosterior(); | 202 //bayesStruct.copyPriorToPosterior(); |
195 //why was this here?? | 203 //why was this here?? |
196 bayesStruct.prior.copyFromDynamicVector(bayesStruct.posterior);//try the otehr way | 204 bayesStruct.prior.copyFromDynamicVector(bayesStruct.posterior);//try the otehr way |
197 //bayesStruct.copyPriorToPosterior(); | 205 //bayesStruct.copyPriorToPosterior(); |
250 // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0); | 258 // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0); |
251 | 259 |
252 //then we recalculate the window start based on MAP being central | 260 //then we recalculate the window start based on MAP being central |
253 //then we do the matches on these and the likelihood on these. | 261 //then we do the matches on these and the likelihood on these. |
254 | 262 |
255 bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2))); | 263 bayesStruct.setNewDistributionOffsets(max(bayesStruct.posterior.offset, bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2))); |
256 // bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); | 264 //bayesStruct.setNewDistributionOffsets(max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); |
257 | 265 |
258 timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0); | 266 timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0); |
259 timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1); | 267 timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1); |
260 timeString += " error "+ofToString(minimumMatchError, 0); | 268 timeString += " error "+ofToString(minimumMatchError, 0); |
261 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 1); | 269 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 1); |
269 | 277 |
270 timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1); | 278 timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1); |
271 timeString += " notearrayindex "+ofToString(noteArrayIndex, 0); | 279 timeString += " notearrayindex "+ofToString(noteArrayIndex, 0); |
272 //when this is off teh screen there is a problem somehow XXX | 280 //when this is off teh screen there is a problem somehow XXX |
273 | 281 |
274 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)); | 282 bayesStruct.posterior.offset = bayesStruct.prior.offset; |
283 //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)); | |
275 | 284 |
276 //trying to switch to prior | 285 //trying to switch to prior |
277 | 286 |
278 | 287 |
279 bayesStruct.lastEventTime = timePlayed;//bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); | 288 bayesStruct.lastEventTime = timePlayed;//bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); |
287 if (recordedEventTimes.size() > 0){ | 296 if (recordedEventTimes.size() > 0){ |
288 updateTempo(); | 297 updateTempo(); |
289 //calcuateNewInterNoteIntervals(); | 298 //calcuateNewInterNoteIntervals(); |
290 } | 299 } |
291 | 300 |
301 | |
292 //storedSmoothPlayPosition = smoothPlayPosition; | 302 //storedSmoothPlayPosition = smoothPlayPosition; |
293 | 303 |
294 } | 304 } |
295 | 305 |
296 void midiEventHolder::updateTempo(){ | 306 void midiEventHolder::updateTempo(){ |
340 double quantity = likelihoodToNoiseRatio / numberOfMatches; | 350 double quantity = likelihoodToNoiseRatio / numberOfMatches; |
341 | 351 |
342 for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){ | 352 for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){ |
343 // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset); | 353 // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset); |
344 //this is the vent time since start of file | 354 //this is the vent time since start of file |
345 if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){ | 355 if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize*bayesStruct.likelihood.scalar){ |
346 // double confidenceMeasure = 0; | 356 // double confidenceMeasure = 0; |
347 // if (totalConfidence > 0) | 357 // if (totalConfidence > 0) |
348 // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence; | 358 // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence; |
349 | 359 |
350 //bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, quantity);//* confidenceMeasure | 360 //bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, quantity);//* confidenceMeasure |
676 | 686 |
677 | 687 |
678 if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate | 688 if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate |
679 && speedRatio < maximumMatchSpeed && speedRatio > minimumMatchSpeed){ | 689 && speedRatio < maximumMatchSpeed && speedRatio > minimumMatchSpeed){ |
680 | 690 |
681 /* printf("(%i)", previousIndex); | 691 /* printf("(%i)", previousIndex); |
682 printf("[%i] :: ", recordedPreviousIndex); | 692 printf("[%i] :: ", recordedPreviousIndex); |
683 // printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence); | 693 // printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence); |
684 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); | 694 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); |
685 printf("update on speed ratio %f\n", speedRatio); | 695 printf("update on speed ratio %f\n", speedRatio); |
686 */ | 696 */ |
687 // matchString += " speed: "+ofToString(speedRatio, 3); | 697 // matchString += " speed: "+ofToString(speedRatio, 3); |
688 // commented for debug | 698 // commented for debug |
689 | 699 |
690 | 700 |
691 double priorWeighting = 1; | 701 double priorWeighting = 1; |
718 } | 728 } |
719 | 729 |
720 | 730 |
721 if (needToUpdate) | 731 if (needToUpdate) |
722 bayesStruct.updateTempoDistribution(); | 732 bayesStruct.updateTempoDistribution(); |
733 | |
723 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); | 734 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); |
724 } | 735 } |
725 | 736 |
726 | 737 |
727 void midiEventHolder::calcuateNewInterNoteIntervals(){ | 738 void midiEventHolder::calcuateNewInterNoteIntervals(){ |
876 | 887 |
877 smoothPlayPosition = newPosition; | 888 smoothPlayPosition = newPosition; |
878 | 889 |
879 } | 890 } |
880 | 891 |
881 | 892 /* |
882 void midiEventHolder::updatePeriodValue(const double& millis){ | 893 void midiEventHolder::updatePeriodValue(const double& millis){ |
883 | 894 |
884 double tmp = period; | 895 double tmp = period; |
885 /* | 896 |
886 while (periodCounter >= 0 && periodCounter < periodValues.size()-1 && periodValues[periodCounter][2] < millis){ | 897 // while (periodCounter >= 0 && periodCounter < periodValues.size()-1 && periodValues[periodCounter][2] < millis){ |
887 periodCounter++; | 898 // periodCounter++; |
888 } | 899 // } |
889 while (periodCounter > 0 && periodValues[periodCounter][2] > millis){ | 900 // while (periodCounter > 0 && periodValues[periodCounter][2] > millis){ |
890 periodCounter--; | 901 // periodCounter--; |
891 } | 902 // } |
892 */ | 903 // |
893 //period = periodValues[periodCounter][1]; | 904 //period = periodValues[periodCounter][1]; |
894 | 905 |
895 if (period != tmp){ | 906 if (period != tmp){ |
896 printf("new period at %f of %f\n", millis, period); | 907 printf("new period at %f of %f\n", millis, period); |
897 } | 908 } |
898 } | 909 } |
910 */ | |
899 | 911 |
900 void midiEventHolder::updateNoteCounter(){ | 912 void midiEventHolder::updateNoteCounter(){ |
901 while (totalNoteCounterIndex < bestMatchIndex){ | 913 while (totalNoteCounterIndex < bestMatchIndex){ |
902 int tmpPitch = recordedNoteOnMatrix[totalNoteCounterIndex][1]; | 914 int tmpPitch = recordedNoteOnMatrix[totalNoteCounterIndex][1]; |
903 recordedTotalNoteCounterByPitch[tmpPitch] += 1; | 915 recordedTotalNoteCounterByPitch[tmpPitch] += 1; |
905 } | 917 } |
906 } | 918 } |
907 | 919 |
908 | 920 |
909 void midiEventHolder::drawMidiFile(){ | 921 void midiEventHolder::drawMidiFile(){ |
922 //ofBackground(80,80,80); | |
910 | 923 |
911 //draws midi file on scrolling screen | 924 //draws midi file on scrolling screen |
912 int size = recordedNoteOnMatrix.size(); | 925 int size = recordedNoteOnMatrix.size(); |
913 if (size > 0){ | 926 if (size > 0){ |
914 | 927 |
1001 ofDrawBitmapString(indexString, 20, 40); | 1014 ofDrawBitmapString(indexString, 20, 40); |
1002 */ | 1015 */ |
1003 } | 1016 } |
1004 | 1017 |
1005 //ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); | 1018 //ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); |
1006 | 1019 ofSetColor(255,255,255); |
1007 //ofDrawBitmapString(timeString, 20, 60); | 1020 ofDrawBitmapString(timeString, 20, 60); |
1008 | 1021 |
1009 //last played piutch | 1022 //last played piutch |
1010 ofSetColor(0,200,0,50); | 1023 ofSetColor(0,200,0,50); |
1011 int yLocation = (*screenHeight) - ((lastPlayedPitch - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum)); | 1024 int yLocation = (*screenHeight) - ((lastPlayedPitch - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum)); |
1012 ofRect(0,yLocation, 100, noteHeight); | 1025 ofRect(0,yLocation, 100, noteHeight); |
1139 printf("\n"); | 1152 printf("\n"); |
1140 } | 1153 } |
1141 | 1154 |
1142 } | 1155 } |
1143 | 1156 |
1144 int midiEventHolder::getLocationFromTicks(double tickPosition){ | 1157 //int midiEventHolder::getLocationFromTicks(double tickPosition){ |
1145 return 0; | 1158 // return 0; |
1146 // return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen); | 1159 // return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen); |
1147 //not used | 1160 //not used |
1148 } | 1161 //} |
1149 | 1162 |
1150 int midiEventHolder::getLocationFromMillis(double millisPosition){ | 1163 int midiEventHolder::getLocationFromMillis(double millisPosition){ |
1151 //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen | 1164 //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen |
1152 return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen); | 1165 return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen); |
1153 } | 1166 } |
1154 | 1167 |
1155 | 1168 /* |
1156 void midiEventHolder::exampleCrossUpdate(){ | 1169 void midiEventHolder::exampleCrossUpdate(){ |
1157 | 1170 |
1158 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, 200); | 1171 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, 200); |
1159 | 1172 |
1160 } | 1173 } |
1161 | 1174 */ |
1162 | 1175 |
1163 void midiEventHolder::setStartPlayingTimes(){ | 1176 void midiEventHolder::setStartPlayingTimes(){ |
1164 startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis(); | 1177 startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis(); |
1165 //startTime = startPlayingTime; | 1178 //startTime = startPlayingTime; |
1166 printf("starting playing at time %f\n", startPlayingTime); | 1179 printf("starting playing at time %f\n", startPlayingTime); |