comparison src/AudioEventMatcher.cpp @ 6:746a5af43c02

windowed bayesian distributions - drawn within constrained portion of the screen
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Thu, 02 Feb 2012 17:52:08 +0000
parents 5ef00d1dfe68
children 33dedfe32893
comparison
equal deleted inserted replaced
5:5ef00d1dfe68 6:746a5af43c02
39 bayesianStruct.setStartPlaying(); 39 bayesianStruct.setStartPlaying();
40 //bayesianStruct.posterior.printArray(); 40 //bayesianStruct.posterior.printArray();
41 } 41 }
42 42
43 void AudioEventMatcher::draw(){ 43 void AudioEventMatcher::draw(){
44 //draw some outlines in blue
44 ofSetColor(20,200,200); 45 ofSetColor(20,200,200);
45 bayesPositionWindow.drawOutline(); 46 bayesPositionWindow.drawOutline();
46 bayesTempoWindow.drawOutline(); 47 bayesTempoWindow.drawOutline();
47 48
49 //draw the scrolling audio tracks
48 recordedTracks.drawTracks(); 50 recordedTracks.drawTracks();
49 51
50 ofSetColor(255); 52 ofSetColor(255);
51 // bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow); 53 // bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow);
52 54
55 drawBayesianDistributions();
56 // bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow);
57
58 //bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow);
59
60 // bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow);
61
62 }
63
64 void AudioEventMatcher::drawBayesianDistributions(){
65
66
53 double screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber); 67 double screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber);
54 68
55 bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); 69
56 70 double screenStartTimeMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.drawParams.windowStartFrame);
57 // bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); 71 double screenEndTimeMillis = screenStartTimeMillis + screenWidthMillis;
58 72 int startIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenStartTimeMillis);
59 73 int endIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenEndTimeMillis);
60 bayesianStruct.likelihood.drawVector(bayesianStruct.likelihood.getRealTermsAsIndex(0), bayesianStruct.likelihood.getRealTermsAsIndex(screenWidthMillis), bayesLikelihoodWindow); 74
61 75 bayesianStruct.posterior.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesPositionWindow);
62 bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); 76
63 77 string tmpString = "start "+ofToString(screenStartTimeMillis)+" (index "+ofToString(startIndex)+"), end "+ofToString(screenEndTimeMillis);
64 78 ofDrawBitmapString(tmpString, bayesPositionWindow.x+20, bayesPositionWindow.y+20);
79
80
81
82 bayesianStruct.likelihood.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesLikelihoodWindow);
83
84
85 //bayesianStruct.likelihood.drawVector(bayesianStruct.likelihood.getRealTermsAsIndex(0), bayesianStruct.likelihood.getRealTermsAsIndex(screenWidthMillis), bayesLikelihoodWindow);
86
87 bayesianStruct.relativeSpeedPosterior.drawConstrainedVector(0, bayesianStruct.relativeSpeedPosterior.arraySize, 0, ofGetWidth(), bayesTempoWindow);
88
65 string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0)); 89 string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0));
66 tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset); 90 tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset);
67 tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis)); 91 tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis));
68 ofDrawBitmapString(tmpStr, 20,140); 92 ofDrawBitmapString(tmpStr, 20,140);
69 tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate); 93 tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate);
72 ofDrawBitmapString("screenamp "+ofToString(screenWidthMillis), 20, 100); 96 ofDrawBitmapString("screenamp "+ofToString(screenWidthMillis), 20, 100);
73 97
74 98
75 } 99 }
76 100
77 101 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){
78 void AudioEventMatcher::newPitchEvent(const double& pitchIn, const double& timeIn){
79 liveInput.addPitchEvent(pitchIn, timeIn); 102 liveInput.addPitchEvent(pitchIn, timeIn);
80 103
81 //tmp print stuff 104 //tmp print stuff
82 printf("New pitch MAP post estimate now %i, ", bayesianStruct.posterior.MAPestimate); 105 printf("New pitch MAP post estimate now %i, ", bayesianStruct.posterior.MAPestimate);
83 double tmp = bayesianStruct.posterior.getMAPestimate(); 106 double tmp = bayesianStruct.posterior.getMAPestimate();
84 printf(" getting it %f and offset %f == %f ms\n", tmp, bayesianStruct.posterior.offset, bayesianStruct.posterior.getIndexInRealTerms(tmp)); 107 printf(" getting it %f and offset %f == %f ms\n", tmp, bayesianStruct.posterior.offset, bayesianStruct.posterior.getIndexInRealTerms(tmp));
85 108
86 matchNewPitchEvent(0, pitchIn, timeIn); 109 matchNewPitchEvent(channel, pitchIn, timeIn);
87 } 110 }
88 111
89 void AudioEventMatcher::newKickEvent(const double& timeIn){ 112 void AudioEventMatcher::newKickEvent(const double& timeIn){
90 // liveInput.addKickEvent(time); 113 // liveInput.addKickEvent(timeIn);
91 matchNewOnsetEvent(0, timeIn); 114 matchNewOnsetEvent(0, timeIn);
92 } 115 }
93 116
117 void AudioEventMatcher::newKickEvent(const int& channel, const double& timeIn){
118 // liveInput.addKickEvent(timeIn);
119 matchNewOnsetEvent(channel, timeIn);
120 }
121
94 122
95 void AudioEventMatcher::newSnareEvent(const double& timeIn){ 123 void AudioEventMatcher::newSnareEvent(const double& timeIn){
96 matchNewOnsetEvent(0, timeIn); 124 matchNewOnsetEvent(2, timeIn);
97 } 125 }
98 126
99 //Needs just to set bounds for the matching process, not have TimeIn 127 //Needs just to set bounds for the matching process, not have TimeIn
100 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){ 128 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){
101 129
102 130
131 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets
132
103 //start at beginning but OPTIMISE later 133 //start at beginning but OPTIMISE later
104 double onsetLikelihoodToNoise = 0.5; 134 double onsetLikelihoodToNoise = 0.3;
105 135
106 double likelihoodWidth = 40; 136 double likelihoodWidth = 40;
107 137
108 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; 138 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset;
109 bayesianStruct.likelihood.zero();//set to zero 139 bayesianStruct.likelihood.zero();//set to zero
119 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ 149 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){
120 double millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime; 150 double millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime;
121 if (millisTime >= startTime && millisTime <= endTime){ 151 if (millisTime >= startTime && millisTime <= endTime){
122 bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, likelihoodWidth, quantity); 152 bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, likelihoodWidth, quantity);
123 numberOfMatchesFound++; 153 numberOfMatchesFound++;
124 printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset); 154 // printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset);
125 155
126 } 156 }
127 } 157 }
128 } 158 }
129 159
131 bayesianStruct.likelihood.addConstant(numberOfMatchesFound*(1-onsetLikelihoodToNoise)/(onsetLikelihoodToNoise*bayesianStruct.likelihood.length)); 161 bayesianStruct.likelihood.addConstant(numberOfMatchesFound*(1-onsetLikelihoodToNoise)/(onsetLikelihoodToNoise*bayesianStruct.likelihood.length));
132 162
133 bayesianStruct.likelihood.renormalise(); 163 bayesianStruct.likelihood.renormalise();
134 164
135 165
166
136 } 167 }
137 168
138 169
139 170
140 void AudioEventMatcher::matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ 171 void AudioEventMatcher::matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){
141 //start at beginning but OPTIMISE later 172 //start at beginning but OPTIMISE later
142 173
143 174
144 updateBayesianDistributions(timeIn); 175 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets
145 176
146 ///set offsets 177 ///set offsets
147 // bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; 178 // bayesianStruct.likelihood.offset = bayesianStruct.prior.offset;
148 double pitchLikelihoodToNoise = 0.5; 179 double pitchLikelihoodToNoise = 0.2;//more noise
149 int numberOfMatches = 0; 180 int numberOfMatches = 0;
150 bayesianStruct.likelihood.zero();//set to zero 181 bayesianStruct.likelihood.zero();//set to zero
151 182
152 double quantity = 0; 183 double quantity = 0;
153 if (channel <= recordedTracks.numberOfAudioTracks){ 184 if (channel <= recordedTracks.numberOfAudioTracks){
154 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ 185 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){
155 186
156 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { 187 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) {
157 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 40); 188 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 20);
158 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); 189 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity);
159 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; 190 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true;
160 numberOfMatches++; 191 numberOfMatches++;
161 } 192 }
162 else{ 193 else{
163 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false; 194 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false;
164 } 195 }
165 196
166 } 197 }
167 } 198 }
168 199
169 bayesianStruct.likelihood.addConstant(numberOfMatches*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length)); 200 if (numberOfMatches > 0){//no point updating unless there is a match
170 201 bayesianStruct.likelihood.addConstant(numberOfMatches*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length));
171 recordedTracks.recentPitch = pitchIn;
172
173 202
174 //tmp set likelihood constant and calculate using that 203 //tmp set likelihood constant and calculate using that
175 bayesianStruct.likelihood.zero(); 204 //bayesianStruct.likelihood.zero();
176 bayesianStruct.likelihood.addConstant(1); 205 //bayesianStruct.likelihood.addConstant(1);
177 206
178 bayesianStruct.calculatePosterior(); 207 bayesianStruct.calculatePosterior();
179 208 }
180 //tmp print stuff
181 printf("After CALC");
182 printPostOffset();
183 209
184 } 210 }
185 211
186 double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){ 212 double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){
187 213
212 bayesPositionWindow.resized(w,h); 238 bayesPositionWindow.resized(w,h);
213 } 239 }
214 240
215 241
216 242
217 void AudioEventMatcher::updateBayesianDistributions(const double& newEventTime){
218 //MOVE INTO bayesianStruct?? XX
219
220 //NEED TO CHECK HERE THAT THEY HAVE THE SAME OFFSETS
221 bayesianStruct.prior.copyFromDynamicVector(bayesianStruct.posterior);//try the otehr way
222
223 //bayesianStruct.copyPriorToPosterior();
224 //need to get new MAP position and set the offset of the arrays
225 //currently bestEstimate is the approx for the new MAP position
226 int tmpMap = bayesianStruct.posterior.getMAPestimate();
227
228 double timeDifference = newEventTime - bayesianStruct.lastEventTime;
229 printf("updating distributions at time %f diff %f offset %f tmpmap est %i\n", newEventTime, timeDifference, bayesianStruct.posterior.offset, tmpMap);
230
231 //addnoise to the tempo distribution
232 //bayesianStruct.decaySpeedDistribution(timeDifference);
233
234 if (timeDifference > 50){
235 bayesianStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.);
236 }
237
238 bayesianStruct.updateBestEstimate(timeDifference);
239 bayesianStruct.lastBestEstimateUpdateTime = newEventTime;//getTimeNow(timePlayed);
240
241 // printf("set new distrb max 0 or %f\n", bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2));
242
243 //tmp print stuff
244
245 printf("HALFWAY BEST ");
246 printPostOffset();
247
248 bayesianStruct.setNewDistributionOffsets(max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2)));
249 bayesianStruct.crossUpdateArrays(bayesianStruct.posterior, bayesianStruct.relativeSpeedPosterior, timeDifference);
250
251 //i.e. using the same offset as prior
252 bayesianStruct.posterior.offset = bayesianStruct.prior.offset;//
253
254 // float tmpPrior = max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2));// bayesianStruct.prior.offset = max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2));
255 // printf("Using prior offset of %f not %f\n", tmpPrior, bayesianStruct.prior.offset);
256
257 bayesianStruct.lastEventTime = newEventTime;//bayesianStruct.lastEventTime = ofGetElapsedTimeMillis();
258
259 }
260
261 void AudioEventMatcher::printPostOffset(){
262 double tmp = bayesianStruct.posterior.getMAPestimate();
263 printf(" MAP index %i post offset %f == %f ms\n", bayesianStruct.posterior.MAPestimate, bayesianStruct.posterior.offset, bayesianStruct.posterior.getIndexInRealTerms(bayesianStruct.posterior.MAPestimate));
264 }