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 */