Mercurial > hg > midi-score-follower
comparison jnmr/midiEventHolder.cpp @ 34:9d2a651a87b2
autoomatically set prior that matches the durations of the songs. Using 120 bpm as default for the recorded part.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Wed, 14 Dec 2011 11:35:31 +0000 |
parents | fa527df85c2c |
children | 6cd3e0075adf |
comparison
equal
deleted
inserted
replaced
33:fa527df85c2c | 34:9d2a651a87b2 |
---|---|
12 | 12 |
13 #include "midiEventHolder.h" | 13 #include "midiEventHolder.h" |
14 | 14 |
15 midiEventHolder::midiEventHolder(){ | 15 midiEventHolder::midiEventHolder(){ |
16 // recordedNoteOnIndex = 0; | 16 // recordedNoteOnIndex = 0; |
17 alignmentPosition = 0; | |
17 | 18 |
18 useTempoPrior = false;//puts sine wave round tempo | 19 useTempoPrior = false;//puts sine wave round tempo |
19 confidenceWeightingUsed = true; | 20 confidenceWeightingUsed = true; |
20 newOptimalMethod = true; | 21 newOptimalMethod = true; |
21 | 22 |
22 matchWindowWidth = 8000;//window size for matching in ms | 23 matchWindowWidth = 16000;//window size for matching in ms |
23 interNoteRange = 1600;//preferred duration | 24 interNoteRange = 1600;//preferred duration |
24 //so max here is really four | 25 //so max here is really four |
25 | 26 |
26 | 27 |
27 likelihoodWidth = 100;//using 100 is good | 28 likelihoodWidth = 100;//using 100 is good |
69 bayesStruct.relativeSpeedPrior.getMaximum(); | 70 bayesStruct.relativeSpeedPrior.getMaximum(); |
70 //bayesStruct.simpleExample(); | 71 //bayesStruct.simpleExample(); |
71 | 72 |
72 | 73 |
73 speedWindowWidthMillis = 1600;//4000 | 74 speedWindowWidthMillis = 1600;//4000 |
74 speedPriorValue = 1.0; | 75 |
75 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); | 76 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); |
76 | 77 |
77 | 78 |
78 intervalsToCheck.push_back(1); | 79 intervalsToCheck.push_back(1); |
79 intervalsToCheck.push_back(2); | 80 intervalsToCheck.push_back(2); |
94 void midiEventHolder::reset(){ | 95 void midiEventHolder::reset(){ |
95 //called when we start playing | 96 //called when we start playing |
96 | 97 |
97 noteArrayIndex = 0; | 98 noteArrayIndex = 0; |
98 tickLocation = 0; | 99 tickLocation = 0; |
99 lastPeriodUpdateTime = getTimeNow(0);//ofGetElapsedTimeMillis(); | 100 startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis(); |
100 bayesStruct.lastEventTime = getTimeNow(0);//ofGetElapsedTimeMillis(); | 101 bayesStruct.lastEventTime = getTimeNow(0);//ofGetElapsedTimeMillis(); |
101 numberOfScreensIn = 0; | 102 numberOfScreensIn = 0; |
102 // recordedNoteOnIndex = 0; | 103 // recordedNoteOnIndex = 0; |
103 bayesStruct.setNewDistributionOffsets(0); | 104 bayesStruct.setNewDistributionOffsets(0); |
104 bayesStruct.posterior.offset = 0; | 105 bayesStruct.posterior.offset = 0; |
109 bestMatchIndex = 0; | 110 bestMatchIndex = 0; |
110 | 111 |
111 recordedTotalNoteCounterByPitch.clear(); | 112 recordedTotalNoteCounterByPitch.clear(); |
112 recordedTotalNoteCounterByPitch.assign(127,0); | 113 recordedTotalNoteCounterByPitch.assign(127,0); |
113 totalNoteCounterIndex = 0; | 114 totalNoteCounterIndex = 0; |
114 | 115 |
115 interNoteIntervals.clear(); | 116 interNoteIntervals.clear(); |
116 | 117 |
118 smoothPlayPosition = 0.0; | |
119 // relativeSpeedForSmooth = 1.0; | |
120 // storedSmoothPlayPosition = smoothPlayPosition; | |
121 // lastSmoothUpdateTime = getTimeNow(0); | |
122 | |
123 printf("reset speed prior is %f\n", speedPriorValue); | |
117 bayesStruct.resetSpeedToOne(); | 124 bayesStruct.resetSpeedToOne(); |
118 bayesStruct.setSpeedPrior(speedPriorValue); | 125 bayesStruct.setSpeedPrior(speedPriorValue); |
119 setMatchedNotesBackToFalse(); | 126 setMatchedNotesBackToFalse(); |
120 | 127 |
128 periodCounter = 0; | |
129 for (int i = 0;i < periodValues.size();i++){ | |
130 // printf("period at %f is %f\n", periodValues[i][2], periodValues[i][1]); | |
131 } | |
132 /* if (periodValues.size() > 0){ | |
133 updatePeriodValue(0);// periodValues[0][2]; | |
134 printf("Resetting period to %f , size is %i\n", period, (int)periodValues.size()); | |
135 } | |
136 */ | |
137 //period = 500.0; | |
121 } | 138 } |
122 | 139 |
123 void midiEventHolder::setMatchedNotesBackToFalse(){ | 140 void midiEventHolder::setMatchedNotesBackToFalse(){ |
124 for (int i = 0;i < noteOnMatches.size();i++) | 141 for (int i = 0;i < noteOnMatches.size();i++) |
125 noteOnMatches[i] = false; | 142 noteOnMatches[i] = false; |
150 } | 167 } |
151 } | 168 } |
152 | 169 |
153 | 170 |
154 double midiEventHolder::getEventTimeTicks(double millis){ | 171 double midiEventHolder::getEventTimeTicks(double millis){ |
155 return (millis * pulsesPerQuarternote / period); | 172 return 0.0; |
173 //return (millis * pulsesPerQuarternote / period); | |
156 } | 174 } |
157 | 175 |
158 double midiEventHolder::getEventTimeMillis(double ticks){ | 176 double midiEventHolder::getEventTimeMillis(double ticks){ |
159 return (period * ticks / (double) pulsesPerQuarternote); | 177 return (period * ticks / (double) pulsesPerQuarternote); |
160 } | 178 } |
188 playedEventTimes.push_back(timePlayed); | 206 playedEventTimes.push_back(timePlayed); |
189 | 207 |
190 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; | 208 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; |
191 double timeDifference = timePlayed - bayesStruct.lastEventTime; | 209 double timeDifference = timePlayed - bayesStruct.lastEventTime; |
192 | 210 |
193 | |
194 | |
195 //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); | 211 //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); |
196 | 212 |
197 //addnoise to the tempo distribution | 213 //addnoise to the tempo distribution |
198 //bayesStruct.decaySpeedDistribution(timeDifference); | 214 //bayesStruct.decaySpeedDistribution(timeDifference); |
199 | 215 |
200 if (timeDifference > 50){ | 216 if (timeDifference > 50){ |
201 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.); | 217 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.); |
202 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.); | 218 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.); |
203 } | 219 } |
204 | 220 |
205 bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate; | 221 // bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate; |
206 bayesStruct.updateBestEstimate(timeDifference); | 222 bayesStruct.updateBestEstimate(timeDifference); |
223 | |
207 bayesStruct.lastBestEstimateUpdateTime = getTimeNow(timePlayed); | 224 bayesStruct.lastBestEstimateUpdateTime = getTimeNow(timePlayed); |
208 | 225 //updatePeriodValue(bayesStruct.lastBestEstimateUpdateTime); |
226 | |
209 // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate); | 227 // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate); |
210 //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis | 228 //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis |
211 | 229 |
212 timeString = "Pitch:"+ofToString(pitch); | 230 timeString = "Pitch:"+ofToString(pitch); |
213 timeString += ", time now:"+ofToString(timeNow, 1); | 231 timeString += ", time now:"+ofToString(timeNow, 1); |
258 | 276 |
259 if (recordedEventTimes.size() > 0){ | 277 if (recordedEventTimes.size() > 0){ |
260 updateTempo(); | 278 updateTempo(); |
261 //calcuateNewInterNoteIntervals(); | 279 //calcuateNewInterNoteIntervals(); |
262 } | 280 } |
281 | |
282 //storedSmoothPlayPosition = smoothPlayPosition; | |
263 | 283 |
264 } | 284 } |
265 | 285 |
266 void midiEventHolder::updateTempo(){ | 286 void midiEventHolder::updateTempo(){ |
267 //having found matches we have matches for new note and matches for previous notes | 287 //having found matches we have matches for new note and matches for previous notes |
805 } | 825 } |
806 */ | 826 */ |
807 | 827 |
808 | 828 |
809 void midiEventHolder::updatePlayPosition(){ | 829 void midiEventHolder::updatePlayPosition(){ |
830 //timeDifference = ofGetElapsedTimeMillis() - startPlayingTime;//elpased | |
810 | 831 |
811 //in actual fact if we are changing the speed of the play position | 832 //in actual fact if we are changing the speed of the play position |
812 //we will need to update this via the file | 833 //we will need to update this via the file |
813 | 834 |
814 //actually time since beginning of file i think | 835 //actually time since beginning of file i think |
815 | 836 |
816 double timeDifference = 0; | 837 double timeDifference = 0; |
817 if (runningInRealTime) | 838 |
818 timeDifference = ofGetElapsedTimeMillis() - lastPeriodUpdateTime;//elpased - lastperiodupdatetime | 839 if (runningInRealTime){ |
840 | |
841 bayesStruct.updateBestEstimate(timeDifference); | |
842 // bayesStruct.updateTmpBestEstimate(timeDifference); | |
843 } | |
844 | |
845 if (smoothPlayPosition < bayesStruct.bestEstimate) | |
846 smoothPlayPosition = bayesStruct.bestEstimate; | |
847 | |
848 // playPositionInMillis = timeDifference;//based on updating from when we change period | |
849 //this to be added | |
850 | |
819 | 851 |
820 //this is time diff in milliseconds | 852 //this is time diff in milliseconds |
821 //then we have | 853 //then we have |
822 double quarterNoteIntervals = (timeDifference / period); | 854 double quarterNoteIntervals = (timeDifference / period); |
823 tickLocation = quarterNoteIntervals * pulsesPerQuarternote; | 855 tickLocation = quarterNoteIntervals * pulsesPerQuarternote; |
824 | 856 |
825 playPositionInMillis = timeDifference;//based on updating from when we change period | |
826 //this to be added | |
827 | |
828 if (runningInRealTime) | |
829 bayesStruct.updateBestEstimate(timeDifference); | |
830 | |
831 updateNoteCounter(); | 857 updateNoteCounter(); |
832 | 858 |
859 } | |
860 | |
861 | |
862 void midiEventHolder::updatePeriodValue(const double& millis){ | |
863 | |
864 double tmp = period; | |
865 /* | |
866 while (periodCounter >= 0 && periodCounter < periodValues.size()-1 && periodValues[periodCounter][2] < millis){ | |
867 periodCounter++; | |
868 } | |
869 while (periodCounter > 0 && periodValues[periodCounter][2] > millis){ | |
870 periodCounter--; | |
871 } | |
872 */ | |
873 //period = periodValues[periodCounter][1]; | |
874 | |
875 if (period != tmp){ | |
876 printf("new period at %f of %f\n", millis, period); | |
877 } | |
833 } | 878 } |
834 | 879 |
835 void midiEventHolder::updateNoteCounter(){ | 880 void midiEventHolder::updateNoteCounter(){ |
836 while (totalNoteCounterIndex < bestMatchIndex){ | 881 while (totalNoteCounterIndex < bestMatchIndex){ |
837 int tmpPitch = recordedNoteOnMatrix[totalNoteCounterIndex][1]; | 882 int tmpPitch = recordedNoteOnMatrix[totalNoteCounterIndex][1]; |
900 int xLocation;// = getLocationFromTicks(tickLocation); | 945 int xLocation;// = getLocationFromTicks(tickLocation); |
901 // ofLine(xLocation, 0, xLocation, (*screenHeight)); | 946 // ofLine(xLocation, 0, xLocation, (*screenHeight)); |
902 | 947 |
903 //orange line at best estimate | 948 //orange line at best estimate |
904 xLocation = getLocationFromMillis(bayesStruct.bestEstimate); | 949 xLocation = getLocationFromMillis(bayesStruct.bestEstimate); |
905 ofSetColor(80,80,80);//250,100,0); | 950 ofSetColor(250,250,20);//250,100,0); |
906 ofLine(xLocation, 0, xLocation, (*screenHeight)); | 951 ofLine(xLocation, 0, xLocation, (*screenHeight)); |
907 | 952 |
908 xLocation = getLocationFromMillis(bayesStruct.tmpBestEstimate); | 953 xLocation = getLocationFromMillis(smoothPlayPosition);//bayesStruct.tmpBestEstimate |
909 ofSetColor(150,150,150);//250,100,0); | 954 ofSetColor(0,250,0);//250,150, 250,100,0); |
910 ofLine(xLocation, 0, xLocation, (*screenHeight)); | 955 ofLine(xLocation, 0, xLocation, (*screenHeight)); |
911 | 956 |
912 | 957 |
913 //lines where matching window start and end are | 958 //lines where matching window start and end are |
914 ofSetColor(0);//0,100,255); | 959 ofSetColor(0);//0,100,255); |
1006 | 1051 |
1007 | 1052 |
1008 void midiEventHolder::drawFile(){ | 1053 void midiEventHolder::drawFile(){ |
1009 drawMidiFile(); | 1054 drawMidiFile(); |
1010 | 1055 |
1056 ofSetColor(0,0,255); | |
1057 ofDrawBitmapString("period"+ofToString(period, 2), ofGetWidth() - 180, 20); | |
1011 | 1058 |
1012 // bayesStruct.drawArrays(); | 1059 // bayesStruct.drawArrays(); |
1013 | 1060 |
1014 // ofSetColor(200,200,0); | 1061 // ofSetColor(200,200,0); |
1015 // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800); | 1062 // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800); |
1073 } | 1120 } |
1074 | 1121 |
1075 } | 1122 } |
1076 | 1123 |
1077 int midiEventHolder::getLocationFromTicks(double tickPosition){ | 1124 int midiEventHolder::getLocationFromTicks(double tickPosition){ |
1078 return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen); | 1125 return 0; |
1126 // return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen); | |
1127 //not used | |
1079 } | 1128 } |
1080 | 1129 |
1081 int midiEventHolder::getLocationFromMillis(double millisPosition){ | 1130 int midiEventHolder::getLocationFromMillis(double millisPosition){ |
1082 //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen | 1131 //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen |
1083 return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen); | 1132 return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen); |
1090 | 1139 |
1091 } | 1140 } |
1092 | 1141 |
1093 | 1142 |
1094 void midiEventHolder::setStartPlayingTimes(){ | 1143 void midiEventHolder::setStartPlayingTimes(){ |
1095 lastPeriodUpdateTime = getTimeNow(0);//ofGetElapsedTimeMillis(); | 1144 startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis(); |
1096 startTime = lastPeriodUpdateTime; | 1145 //startTime = startPlayingTime; |
1097 | 1146 |
1098 /* | 1147 /* |
1099 bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis(); | 1148 bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis(); |
1100 bayesStruct.bestEstimate = 0; | 1149 bayesStruct.bestEstimate = 0; |
1101 bayesStruct.resetArrays(); | 1150 bayesStruct.resetArrays(); |
1212 void midiEventHolder::printNoteCounter(){ | 1261 void midiEventHolder::printNoteCounter(){ |
1213 for (int i = 0;i < recordedTotalNoteCounterByPitch.size();i++){ | 1262 for (int i = 0;i < recordedTotalNoteCounterByPitch.size();i++){ |
1214 printf("RECORDED TOTAL[%i] := %i", i, recordedTotalNoteCounterByPitch[i]); | 1263 printf("RECORDED TOTAL[%i] := %i", i, recordedTotalNoteCounterByPitch[i]); |
1215 } | 1264 } |
1216 } | 1265 } |
1266 | |
1267 /* double timeDiff = 0;//timeDifference; | |
1268 if (runningInRealTime) | |
1269 timeDiff = ofGetElapsedTimeMillis() - lastSmoothUpdateTime; | |
1270 // bayesStruct.lastBestEstimateUpdateTime; | |
1271 | |
1272 //smoothPlayPosition = bayesStruct.bestEstimate + 100; | |
1273 //relativeSpeedForSmooth = 0.1; | |
1274 //bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate); | |
1275 // speedEstimate*2; | |
1276 | |
1277 smoothPlayPosition = storedSmoothPlayPosition + timeDiff * relativeSpeedForSmooth;// * bayesStruct.speedEstimate; | |
1278 storedSmoothPlayPosition = smoothPlayPosition; | |
1279 lastSmoothUpdateTime = getTimeNow(bayesStruct.lastBestEstimateUpdateTime); | |
1280 updateSmoothPlaySpeed(); | |
1281 //bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate) | |
1282 | |
1283 } | |
1284 | |
1285 void midiEventHolder::updateSmoothPlaySpeed(){ | |
1286 //project where current play pos will be in two seconds and aim for it. | |
1287 double timeToAimForMillis = 2000.0; | |
1288 //double timeDiff = ofGetElapsedTimeMillis() - bayesStruct.lastBestEstimateUpdateTime;//since the update need to get to where we are | |
1289 double projection = bayesStruct.bestEstimate + bayesStruct.speedEstimate*timeToAimForMillis;// | |
1290 double timeDifferenceFromSmooth = projection - smoothPlayPosition; | |
1291 relativeSpeedForSmooth = timeDifferenceFromSmooth / timeToAimForMillis; | |
1292 | |
1293 } | |
1294 */ |