andrew@0
|
1 /*
|
andrew@0
|
2 * BayesianArrayStructure.cpp
|
andrew@0
|
3 * midiCannamReader
|
andrew@0
|
4 *
|
andrew@0
|
5 * Created by Andrew on 17/07/2011.
|
andrew@0
|
6 * Copyright 2011 QMUL. All rights reserved.
|
andrew@0
|
7 *
|
andrew@0
|
8 */
|
andrew@0
|
9
|
andrew@0
|
10 #include "BayesianArrayStructure.h"
|
andrew@0
|
11
|
andrew@0
|
12 BayesianArrayStructure::BayesianArrayStructure(){
|
andrew@0
|
13 printf("Bayesian structure: DeFault constructor called");
|
andrew@0
|
14
|
andrew@0
|
15 prior.createVector(1);
|
andrew@0
|
16 likelihood.createVector(1);
|
andrew@0
|
17 posterior.createVector(1);
|
andrew@0
|
18
|
andrew@0
|
19
|
andrew@0
|
20 tmpPrior.createVector(240);
|
andrew@0
|
21 tmpPrior.addGaussianShape(100, 40, 1);
|
andrew@0
|
22 tmpPrior.addGaussianShape(200, 10, 0.2);
|
andrew@0
|
23 tmpPrior.translateDistribution(20);
|
andrew@0
|
24
|
andrew@0
|
25 lastEventTime = ofGetElapsedTimeMillis();
|
andrew@0
|
26
|
andrew@0
|
27 speedDecayWidth = 20;
|
andrew@0
|
28 speedDecayAmount = 10;
|
andrew@0
|
29 }
|
andrew@0
|
30
|
andrew@0
|
31 BayesianArrayStructure::BayesianArrayStructure(int length){
|
andrew@0
|
32 printf("BAYESIAN STURTUCRE CREATED LENGTH: %i\n", length);
|
andrew@0
|
33 //this constructor isnt called it seems
|
andrew@0
|
34 prior.createVector(length);
|
andrew@0
|
35 likelihood.createVector(length);
|
andrew@0
|
36 posterior.createVector(length);
|
andrew@0
|
37
|
andrew@0
|
38 }
|
andrew@0
|
39
|
andrew@0
|
40
|
andrew@0
|
41
|
andrew@0
|
42 void BayesianArrayStructure::resetSize(int length){
|
andrew@0
|
43 printf("BAYESIAN STRUCTURE size is : %i\n", length);
|
andrew@0
|
44
|
andrew@0
|
45 prior.createVector(length);
|
andrew@0
|
46 likelihood.createVector(length);
|
andrew@0
|
47 posterior.createVector(length);
|
andrew@0
|
48
|
andrew@0
|
49 acceleration.createVector(length);
|
andrew@0
|
50
|
andrew@0
|
51 }
|
andrew@0
|
52
|
andrew@0
|
53
|
andrew@0
|
54
|
andrew@0
|
55 void BayesianArrayStructure::resetSpeedToOne(){
|
andrew@0
|
56 relativeSpeedPrior.zero();
|
andrew@0
|
57 relativeSpeedPosterior.zero();
|
andrew@0
|
58 relativeSpeedLikelihood.zero();
|
andrew@0
|
59
|
andrew@0
|
60 relativeSpeedPosterior.addGaussianShape(40, 5, 0.6);
|
andrew@0
|
61
|
andrew@0
|
62 relativeSpeedPosterior.addGaussianShape(100, 5, 0.8);
|
andrew@0
|
63 relativeSpeedPosterior.renormalise();
|
andrew@0
|
64 relativeSpeedPosterior.getMaximum();
|
andrew@0
|
65
|
andrew@0
|
66 acceleration.addGaussianShape(2000, 20, 0.8);
|
andrew@0
|
67
|
andrew@0
|
68 }
|
andrew@0
|
69
|
andrew@0
|
70 void BayesianArrayStructure::resetSpeedSize(int length){
|
andrew@0
|
71 printf("BAYESIAN SPEED size is : %i\n", length);
|
andrew@0
|
72
|
andrew@0
|
73 relativeSpeedPrior.createVector(length);
|
andrew@0
|
74 relativeSpeedLikelihood.createVector(length);
|
andrew@0
|
75 relativeSpeedPosterior.createVector(length);
|
andrew@0
|
76
|
andrew@0
|
77
|
andrew@0
|
78
|
andrew@0
|
79 }
|
andrew@0
|
80 void BayesianArrayStructure::setRelativeSpeedScalar(double f){
|
andrew@0
|
81 relativeSpeedPrior.scalar = f;
|
andrew@0
|
82 relativeSpeedPosterior.scalar = f;
|
andrew@0
|
83 relativeSpeedLikelihood.scalar = f;
|
andrew@0
|
84 }
|
andrew@0
|
85
|
andrew@0
|
86 void BayesianArrayStructure::simpleExample(){
|
andrew@0
|
87 //simple example
|
andrew@0
|
88 prior.addGaussianShape(50, 10, 1);
|
andrew@0
|
89 prior.addGaussianShape(150, 30, 0.3);
|
andrew@0
|
90 prior.addGaussianShape(250, 30, 0.2);
|
andrew@0
|
91
|
andrew@0
|
92 likelihood.addGaussianShape(90, 20, 0.6);
|
andrew@0
|
93 likelihood.addConstant(0.02);
|
andrew@0
|
94 posterior.doProduct(prior, likelihood);
|
andrew@0
|
95
|
andrew@0
|
96 // relativeSpeedPosterior.addToIndex(100, 1);
|
andrew@0
|
97 // relativeSpeedPosterior.addToIndex(40, 0.7);
|
andrew@0
|
98 relativeSpeedPosterior.addGaussianShape(100, 20, 1);
|
andrew@0
|
99 // relativeSpeedPosterior.addGaussianShape(10, 2, 0.5);
|
andrew@0
|
100 relativeSpeedPosterior.getMaximum();
|
andrew@0
|
101
|
andrew@0
|
102 }
|
andrew@0
|
103
|
andrew@0
|
104 void BayesianArrayStructure::copyPriorToPosterior(){
|
andrew@0
|
105
|
andrew@0
|
106 for (int i = 0;i < prior.arraySize;i++){
|
andrew@0
|
107 posterior.array[i] = prior.array[i];
|
andrew@0
|
108 }
|
andrew@0
|
109 }
|
andrew@0
|
110
|
andrew@0
|
111 void BayesianArrayStructure::resetArrays(){
|
andrew@0
|
112 prior.zero();
|
andrew@0
|
113 likelihood.zero();
|
andrew@0
|
114 prior.addGaussianShape(0, 80, 1);
|
andrew@0
|
115 likelihood.addConstant(1);
|
andrew@0
|
116 posterior.zero();
|
andrew@0
|
117 posterior.addGaussianShape(0, 60, 1);
|
andrew@0
|
118 setNewDistributionOffsets(0);
|
andrew@0
|
119 bestEstimate = 0;
|
andrew@0
|
120 // lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
|
andrew@0
|
121
|
andrew@0
|
122 }
|
andrew@0
|
123
|
andrew@0
|
124 void BayesianArrayStructure::updateBestEstimate(){
|
andrew@0
|
125 double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//lastBestEstimateUpdateTime;
|
andrew@0
|
126
|
andrew@0
|
127 bestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate);
|
andrew@0
|
128 //
|
andrew@0
|
129 //lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
|
andrew@0
|
130 }
|
andrew@0
|
131
|
andrew@0
|
132 void BayesianArrayStructure::calculatePosterior(){
|
andrew@0
|
133 posterior.doProduct(prior, likelihood);
|
andrew@0
|
134 posterior.renormalise();
|
andrew@0
|
135
|
andrew@0
|
136 /*
|
andrew@0
|
137 int i;
|
andrew@0
|
138 for (i = 0;i < prior.length;i++){
|
andrew@0
|
139 // printf("priori [%i] is %f\n", i, prior[i]);
|
andrew@0
|
140 *(posterior+i) = *(prior+i);
|
andrew@0
|
141 // posterior[i] = likelihood[i] * prior[i];
|
andrew@0
|
142 }
|
andrew@0
|
143 */
|
andrew@0
|
144
|
andrew@0
|
145
|
andrew@0
|
146 }
|
andrew@0
|
147
|
andrew@0
|
148
|
andrew@0
|
149
|
andrew@0
|
150
|
andrew@0
|
151 void BayesianArrayStructure::setNewDistributionOffsets(const double& newOffset){
|
andrew@0
|
152 prior.offset = newOffset;
|
andrew@0
|
153 likelihood.offset = newOffset;
|
andrew@0
|
154 // posterior.offset = newOffset;
|
andrew@0
|
155 }
|
andrew@0
|
156
|
andrew@0
|
157
|
andrew@0
|
158 void BayesianArrayStructure::crossUpdateArrays(DynamicVector& position, DynamicVector& speed, double timeDifference){
|
andrew@0
|
159 //set the cutoff for offset of position first! XXX
|
andrew@0
|
160
|
andrew@0
|
161 // printf("time difference %f, ", timeDifference);
|
andrew@0
|
162
|
andrew@0
|
163 double timeDifferenceInPositionVectorUnits = timeDifference / prior.scalar;
|
andrew@0
|
164
|
andrew@0
|
165 prior.zero();//kill prior
|
andrew@0
|
166 calculateNewPriorOffset(timeDifference);//set new prior offset here
|
andrew@0
|
167
|
andrew@0
|
168 for (int i = 0;i < speed.arraySize;i++){
|
andrew@0
|
169 // printf("[%i] %f\n", i, speed.array[i]);
|
andrew@0
|
170 //set speed
|
andrew@0
|
171 double speedValue = speed.getIndexInRealTerms(i);//so for scalar 0.01, 50 -> speed value of 0.5
|
andrew@0
|
172
|
andrew@0
|
173 //so we have moved
|
andrew@0
|
174 int distanceMoved = round(timeDifferenceInPositionVectorUnits * speedValue);//round the value
|
andrew@0
|
175
|
andrew@0
|
176 if (speed.array[i] != 0){
|
andrew@0
|
177
|
andrew@0
|
178 // printf("speed [%i] gives %f moved %i\n", i, speedValue, distanceMoved);
|
andrew@0
|
179
|
andrew@0
|
180 for (int postIndex = 0;postIndex < position.arraySize;postIndex++){
|
andrew@0
|
181 //old posterior contributing to new prior
|
andrew@0
|
182 int newPriorIndex = postIndex + position.offset - prior.offset + distanceMoved;
|
andrew@0
|
183 if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){
|
andrew@0
|
184 prior.addToIndex(newPriorIndex, position.array[postIndex]*speed.array[i]);
|
andrew@0
|
185 // printf("adding [%i] : %f\n", newPriorIndex, posterior.array[postIndex]*speed.array[i]);
|
andrew@0
|
186 }
|
andrew@0
|
187
|
andrew@0
|
188 }
|
andrew@0
|
189
|
andrew@0
|
190 }//if not zero
|
andrew@0
|
191 }//end speed
|
andrew@0
|
192
|
andrew@0
|
193 prior.renormalise();
|
andrew@0
|
194
|
andrew@0
|
195 }
|
andrew@0
|
196
|
andrew@0
|
197 void BayesianArrayStructure::calculateNewPriorOffset(const double& timeDifference){
|
andrew@0
|
198
|
andrew@0
|
199 double maxSpeed = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate);
|
andrew@0
|
200 // printf("Maxspeed is %f\n", maxSpeed);
|
andrew@0
|
201
|
andrew@0
|
202 double priorMax = posterior.getMaximum();
|
andrew@0
|
203 double distanceTravelled = maxSpeed * (timeDifference / prior.scalar);
|
andrew@0
|
204 double newMaxLocation = posterior.MAPestimate + distanceTravelled;
|
andrew@0
|
205 // printf("MAP: %i, tim df %f, distance %f, new location %f\n", posterior.MAPestimate, timeDifference, distanceTravelled, newMaxLocation);
|
andrew@0
|
206
|
andrew@0
|
207 }
|
andrew@0
|
208
|
andrew@0
|
209
|
andrew@0
|
210 void BayesianArrayStructure::decaySpeedDistribution(double timeDifference){
|
andrew@0
|
211
|
andrew@0
|
212 // commented for the moment
|
andrew@0
|
213 double relativeAmount = max(1.0, timeDifference/1000.);
|
andrew@0
|
214 // printf("decay %f around %i \n", timeDifference, relativeSpeedPosterior.MAPestimate);
|
andrew@0
|
215 relativeAmount *= speedDecayAmount;
|
andrew@0
|
216 relativeSpeedPosterior.renormalise();
|
andrew@0
|
217 relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, relativeAmount);
|
andrew@0
|
218
|
andrew@0
|
219 relativeSpeedPosterior.renormalise();
|
andrew@0
|
220 double newMax = relativeSpeedPosterior.getMaximum();
|
andrew@0
|
221
|
andrew@0
|
222 //old code
|
andrew@0
|
223 // relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, 10);
|
andrew@0
|
224 //relativeSpeedPosterior.addConstant(1);
|
andrew@0
|
225
|
andrew@0
|
226 /*
|
andrew@0
|
227 relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
|
andrew@0
|
228 relativeSpeedLikelihood.zero();
|
andrew@0
|
229 relativeSpeedLikelihood.addConstant(0.2);
|
andrew@0
|
230 relativeSpeedLikelihood.addGaussianShape(relativeSpeedPosterior.maximumValue, speedDecayWidth, relativeAmount);
|
andrew@0
|
231 relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
|
andrew@0
|
232 relativeSpeedPosterior.renormalise();
|
andrew@0
|
233 */
|
andrew@0
|
234
|
andrew@0
|
235
|
andrew@0
|
236
|
andrew@0
|
237 }
|
andrew@0
|
238
|
andrew@0
|
239 void BayesianArrayStructure::updateTempoDistribution(const double& speedRatio, const double& matchFactor){
|
andrew@0
|
240 //speedratio is speed of played relative to the recording
|
andrew@0
|
241
|
andrew@0
|
242 double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio);
|
andrew@0
|
243 // printf("\nindex of likelihood would be %f\n", index);
|
andrew@0
|
244 if (index >= 0 && index < relativeSpeedPrior.length){
|
andrew@0
|
245 //then we can do update
|
andrew@0
|
246
|
andrew@0
|
247 //set new likelihood
|
andrew@0
|
248 relativeSpeedLikelihood.zero();
|
andrew@1
|
249 relativeSpeedLikelihood.addConstant(0.05);
|
andrew@0
|
250
|
andrew@0
|
251 relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5*matchFactor);
|
andrew@0
|
252
|
andrew@0
|
253
|
andrew@0
|
254 //copy posterior to prior
|
andrew@0
|
255 relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
|
andrew@0
|
256
|
andrew@0
|
257 //update
|
andrew@0
|
258 relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
|
andrew@0
|
259
|
andrew@0
|
260 //normalise
|
andrew@0
|
261 relativeSpeedPosterior.renormalise();
|
andrew@0
|
262
|
andrew@0
|
263 relativeSpeedPosterior.getMaximum();
|
andrew@0
|
264 }//end if within range
|
andrew@0
|
265
|
andrew@0
|
266
|
andrew@0
|
267 }
|
andrew@0
|
268
|
andrew@0
|
269
|
andrew@0
|
270 void BayesianArrayStructure::setFlatTempoLikelihood(){ //set new likelihood
|
andrew@0
|
271 relativeSpeedLikelihood.zero();
|
andrew@0
|
272 relativeSpeedLikelihood.addConstant(0.3);
|
andrew@0
|
273 }
|
andrew@0
|
274
|
andrew@0
|
275 void BayesianArrayStructure::updateTempoLikelihood(const double& speedRatio, const double& matchFactor){
|
andrew@0
|
276
|
andrew@0
|
277 double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio);
|
andrew@0
|
278
|
andrew@0
|
279 if (index >= 0 && index < relativeSpeedPrior.length){
|
andrew@0
|
280 relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5);//*matchFactor);
|
andrew@0
|
281 }
|
andrew@0
|
282 }
|
andrew@0
|
283
|
andrew@0
|
284
|
andrew@0
|
285 void BayesianArrayStructure::calculateTempoUpdate(){
|
andrew@0
|
286 //copy posterior to prior
|
andrew@0
|
287 relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
|
andrew@0
|
288
|
andrew@0
|
289 //update
|
andrew@0
|
290 relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
|
andrew@0
|
291
|
andrew@0
|
292 //normalise
|
andrew@0
|
293 relativeSpeedPosterior.renormalise();
|
andrew@0
|
294
|
andrew@0
|
295 relativeSpeedPosterior.getMaximum();
|
andrew@0
|
296
|
andrew@0
|
297 }
|
andrew@0
|
298
|
andrew@0
|
299
|
andrew@0
|
300 void BayesianArrayStructure::drawArrays(){
|
andrew@0
|
301
|
andrew@0
|
302 //bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200);
|
andrew@0
|
303 //bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200);
|
andrew@0
|
304
|
andrew@0
|
305 int displaySize = prior.arraySize;
|
andrew@0
|
306 ofSetColor(255,0,0);
|
andrew@0
|
307 prior.drawVector(0, displaySize);
|
andrew@0
|
308 ofSetColor(0,255,0);
|
andrew@0
|
309 likelihood.drawVector(0, displaySize);
|
andrew@0
|
310 ofSetColor(0,0,255);
|
andrew@0
|
311 posterior.drawVector(0, displaySize);
|
andrew@0
|
312 ofSetColor(255,255,0);
|
andrew@0
|
313 relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize);
|
andrew@0
|
314
|
andrew@0
|
315 // ofSetColor(255,255,255);
|
andrew@0
|
316 // tmpPrior.drawVector(0,300);
|
andrew@0
|
317
|
andrew@0
|
318 }
|
andrew@0
|
319
|
andrew@0
|
320
|
andrew@0
|
321 void BayesianArrayStructure::drawTempoArrays(){
|
andrew@0
|
322 ofSetColor(0,255,255);
|
andrew@0
|
323 relativeSpeedPrior.drawVector(0, relativeSpeedPrior.arraySize);
|
andrew@0
|
324
|
andrew@0
|
325 ofSetColor(255,0,255);
|
andrew@0
|
326 relativeSpeedLikelihood.drawVector(0, relativeSpeedLikelihood.arraySize);
|
andrew@0
|
327
|
andrew@0
|
328 ofSetColor(255,255,0);
|
andrew@0
|
329 relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize);
|
andrew@0
|
330
|
andrew@0
|
331 ofSetColor(255,255, 255);
|
andrew@0
|
332 ofLine(screenWidth/2, 0, screenWidth/2, ofGetHeight());//middle of screen
|
andrew@0
|
333
|
andrew@0
|
334 ofSetColor(0, 255, 0);
|
andrew@0
|
335 double fractionOfScreen = ((double)relativeSpeedPosterior.MAPestimate / relativeSpeedPosterior.length);
|
andrew@0
|
336 ofLine(screenWidth * fractionOfScreen, 0, screenWidth * fractionOfScreen, ofGetHeight());
|
andrew@0
|
337 }
|
andrew@0
|
338
|
andrew@0
|
339
|
andrew@0
|
340 void BayesianArrayStructure::drawArraysRelativeToTimeframe(const double& startTimeMillis, const double& endTimeMillis){
|
andrew@0
|
341
|
andrew@0
|
342 screenWidth = ofGetWidth();
|
andrew@0
|
343
|
andrew@0
|
344 int startArrayIndex = 0;
|
andrew@0
|
345
|
andrew@0
|
346 if (prior.getIndexInRealTerms(prior.arraySize-1) > startTimeMillis){
|
andrew@0
|
347 //i.e. the array is on the page
|
andrew@0
|
348
|
andrew@0
|
349 while (prior.getIndexInRealTerms(startArrayIndex) < startTimeMillis){
|
andrew@0
|
350 startArrayIndex++;
|
andrew@0
|
351 }
|
andrew@0
|
352 int endArrayIndex = prior.arraySize-1;
|
andrew@0
|
353 //could find constraints here
|
andrew@0
|
354 if (prior.getIndexInRealTerms(prior.arraySize-1) > endTimeMillis)
|
andrew@0
|
355 endArrayIndex = (floor)((endTimeMillis - prior.offset)/prior.scalar);
|
andrew@0
|
356
|
andrew@0
|
357 //so we need to figure where start and end array are on screen
|
andrew@0
|
358 int startScreenPosition, endScreenPosition;
|
andrew@0
|
359 double screenWidthMillis = endTimeMillis - startTimeMillis;
|
andrew@0
|
360
|
andrew@0
|
361 startScreenPosition = (prior.getIndexInRealTerms(startArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis;
|
andrew@0
|
362 endScreenPosition = (double)(prior.getIndexInRealTerms(endArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis;
|
andrew@0
|
363
|
andrew@0
|
364 ofSetColor(0,0,100);
|
andrew@0
|
365 string relativeString = " offset "+ofToString(prior.offset, 1);//starttimes("+ofToString(startTimeMillis)+", "+ofToString(endTimeMillis);
|
andrew@0
|
366 relativeString += ": index "+ofToString(startArrayIndex)+" , "+ofToString(endArrayIndex)+" [";
|
andrew@0
|
367 // relativeString += ofToString(prior.getIndexInRealTerms(endArrayIndex), 3)+"] (sc-width:"+ofToString(screenWidthMillis, 1)+") ";
|
andrew@0
|
368 relativeString += " mapped to screen "+ofToString(startScreenPosition)+" , "+ofToString(endScreenPosition);
|
andrew@0
|
369 ofDrawBitmapString(relativeString, 100, 180);
|
andrew@0
|
370
|
andrew@1
|
371 ofSetColor(255, 255, 0);
|
andrew@0
|
372 likelihood.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
|
andrew@0
|
373
|
andrew@0
|
374 ofSetColor(0,0,200);
|
andrew@0
|
375 prior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
|
andrew@0
|
376
|
andrew@0
|
377 ofSetColor(200, 0, 0);
|
andrew@0
|
378 posterior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
|
andrew@0
|
379
|
andrew@1
|
380
|
andrew@0
|
381 // ofSetColor(0, 200, 255);
|
andrew@0
|
382 // acceleration.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
|
andrew@0
|
383
|
andrew@0
|
384
|
andrew@0
|
385 }
|
andrew@0
|
386
|
andrew@0
|
387 } |