andrew@0
|
1 /*
|
andrew@0
|
2 * DynamicVector.cpp
|
andrew@0
|
3 * midiCannamReader
|
andrew@0
|
4 *
|
andrew@0
|
5 * Created by Andrew on 18/07/2011.
|
andrew@0
|
6 * Copyright 2011 QMUL. All rights reserved.
|
andrew@0
|
7 *
|
andrew@0
|
8 */
|
andrew@0
|
9
|
andrew@0
|
10
|
andrew@0
|
11 #include "DynamicVector.h"
|
andrew@0
|
12
|
andrew@50
|
13 bool printOutput = false;
|
andrew@50
|
14
|
andrew@0
|
15 DynamicVector::DynamicVector(){
|
andrew@0
|
16 length = 0;
|
andrew@0
|
17 arraySize = 0;
|
andrew@0
|
18 maximumValue = 0;
|
andrew@0
|
19 MAPestimate = 0;
|
andrew@0
|
20 offset = 0;
|
andrew@36
|
21 scalar = 6;
|
andrew@0
|
22 integratedEstimate = length/2;
|
andrew@0
|
23
|
andrew@0
|
24 gaussianLookupMean = (double) GAUSSIAN_LOOKUP_LENGTH/2;
|
andrew@0
|
25 gaussianLookupStdDev = (double)(GAUSSIAN_LOOKUP_LENGTH/16);
|
andrew@0
|
26 double factor = 1.0;//(1.0 / (gaussianLookupStdDev*sqrt(2*PI)) );//1.0;//-1.0/(2*PI*sqrt(gaussianLookupStdDev));
|
andrew@0
|
27 for (int i = 0;i < GAUSSIAN_LOOKUP_LENGTH;i++){
|
andrew@0
|
28 gaussianLookupTable[i] = factor*exp(-1.0*(i-gaussianLookupMean)*(i-gaussianLookupMean)/(2.0*gaussianLookupStdDev*gaussianLookupStdDev));
|
andrew@0
|
29 }
|
andrew@0
|
30
|
andrew@0
|
31 }
|
andrew@0
|
32
|
andrew@0
|
33 void DynamicVector::copyFromDynamicVector(const DynamicVector& dynamicVec){
|
andrew@3
|
34
|
andrew@0
|
35 if (dynamicVec.length == length){
|
andrew@3
|
36 offset = dynamicVec.offset;
|
andrew@0
|
37 for (int i = 0;i < length;i++)
|
andrew@0
|
38 array[i] = dynamicVec.array[i];
|
andrew@0
|
39 }
|
andrew@0
|
40 else{
|
andrew@0
|
41 printf("CANNOT COPY VECTORS OF NON SAME LENGTH!!\n");
|
andrew@0
|
42 }
|
andrew@0
|
43 }
|
andrew@0
|
44
|
andrew@0
|
45 void DynamicVector::createVector(int len){
|
andrew@0
|
46 array.clear();
|
andrew@0
|
47 for (int i = 0; i < len;i++){
|
andrew@0
|
48 array.push_back(0);
|
andrew@0
|
49 }
|
andrew@0
|
50 length = len;
|
andrew@0
|
51 arraySize = array.size();
|
andrew@0
|
52 integratedEstimate = length/2;
|
andrew@0
|
53 }
|
andrew@0
|
54
|
andrew@0
|
55
|
andrew@0
|
56 double DynamicVector::getMaximum(){
|
andrew@0
|
57 int i;
|
andrew@0
|
58 double max = 0;
|
andrew@0
|
59 for (i=0;i < length;i++){
|
andrew@0
|
60 if (array[i] > max){
|
andrew@0
|
61 max = array[i];
|
andrew@0
|
62 MAPestimate = i;
|
andrew@0
|
63 }
|
andrew@0
|
64 }
|
andrew@0
|
65 maximumValue = max;
|
andrew@0
|
66 return max;
|
andrew@0
|
67 }
|
andrew@0
|
68
|
andrew@4
|
69 int DynamicVector::getMAPestimate(){
|
andrew@4
|
70 int i;
|
andrew@4
|
71 double max = 0;
|
andrew@4
|
72 for (i=0;i < length;i++){
|
andrew@4
|
73 if (array[i] > max){
|
andrew@4
|
74 max = array[i];
|
andrew@4
|
75 MAPestimate = i;
|
andrew@4
|
76 }
|
andrew@4
|
77 }
|
andrew@4
|
78 maximumValue = max;
|
andrew@4
|
79 return MAPestimate;
|
andrew@4
|
80 }
|
andrew@4
|
81
|
andrew@0
|
82 double DynamicVector::getIntegratedEstimate(){
|
andrew@0
|
83 //returns the index of the integrated average - where the probability distribution is centred
|
andrew@0
|
84 integratedEstimate = 0;
|
andrew@0
|
85 double integratedTotal = 0;
|
andrew@0
|
86 for (int i = 0;i < length;i++){
|
andrew@0
|
87 integratedEstimate += array[i]*i;
|
andrew@0
|
88 integratedTotal += array[i];
|
andrew@0
|
89 }
|
andrew@0
|
90 if (integratedTotal > 0){
|
andrew@0
|
91 integratedEstimate /= integratedTotal;
|
andrew@0
|
92 }
|
andrew@0
|
93 return integratedEstimate;
|
andrew@0
|
94 }
|
andrew@0
|
95
|
andrew@0
|
96 void DynamicVector::updateIntegratedEstimate(){
|
andrew@0
|
97 //returns the index of the integrated average - where the probability distribution is centred
|
andrew@0
|
98 integratedEstimate = 0;
|
andrew@0
|
99 double integratedTotal = 0;
|
andrew@0
|
100 for (int i = 0;i < length;i++){
|
andrew@0
|
101 integratedEstimate += array[i]*i;
|
andrew@0
|
102 integratedTotal += array[i];
|
andrew@0
|
103 }
|
andrew@0
|
104 if (integratedTotal > 0){
|
andrew@0
|
105 integratedEstimate /= integratedTotal;
|
andrew@0
|
106 }
|
andrew@0
|
107
|
andrew@0
|
108 }
|
andrew@0
|
109
|
andrew@0
|
110 void DynamicVector::updateLimitedIntegratedEstimate(){
|
andrew@0
|
111 //returns the index of the integrated average - where the probability distribution is centred
|
andrew@0
|
112 //but limited round the MAP estimate
|
andrew@0
|
113 double tmp = getMaximum();
|
andrew@0
|
114 int limit = min(MAPestimate, length - MAPestimate);
|
andrew@0
|
115 int start = max(0, MAPestimate - limit);
|
andrew@0
|
116 int end = min(MAPestimate + limit, length-1);
|
andrew@0
|
117
|
andrew@0
|
118 integratedEstimate = 0;
|
andrew@0
|
119 double integratedTotal = 0;
|
andrew@0
|
120 for (int i = start;i <= end;i++){
|
andrew@0
|
121 integratedEstimate += array[i]*i;
|
andrew@0
|
122 integratedTotal += array[i];
|
andrew@0
|
123 }
|
andrew@0
|
124 if (integratedTotal > 0){
|
andrew@0
|
125 integratedEstimate /= integratedTotal;
|
andrew@0
|
126 }
|
andrew@0
|
127
|
andrew@0
|
128 }
|
andrew@0
|
129
|
andrew@0
|
130
|
andrew@0
|
131 void DynamicVector::zero(){
|
andrew@0
|
132 for (int i = 0;i < array.size();i++)
|
andrew@0
|
133 array[i] = 0;
|
andrew@0
|
134 }
|
andrew@0
|
135
|
andrew@0
|
136 void DynamicVector::renormalise(){
|
andrew@0
|
137 double tmpMax = getMaximum();
|
andrew@0
|
138 if (tmpMax > 0){
|
andrew@0
|
139 // printf("renormalise : max is %f and size is %i\n", tmpMax, arraySize);
|
andrew@0
|
140 for (int i = 0;i < array.size();i++)
|
andrew@0
|
141 array[i] /= tmpMax;
|
andrew@0
|
142
|
andrew@0
|
143 }
|
andrew@0
|
144 //printArray();
|
andrew@0
|
145 }
|
andrew@0
|
146
|
andrew@0
|
147 void DynamicVector::doProduct(DynamicVector& arrayOne, DynamicVector& arrayTwo){
|
andrew@0
|
148
|
andrew@0
|
149 for (int i = 0;i < arrayOne.length;i++)
|
andrew@0
|
150 array[i] = arrayOne.array[i] * arrayTwo.array[i];
|
andrew@0
|
151 }
|
andrew@0
|
152
|
andrew@0
|
153
|
andrew@0
|
154 void DynamicVector::printArray(){
|
andrew@0
|
155 for (int i = 0;i < arraySize;i++){
|
andrew@0
|
156 printf("[%i] = %f\n", i, array[i]);
|
andrew@0
|
157 }
|
andrew@0
|
158 }
|
andrew@0
|
159
|
andrew@0
|
160 void DynamicVector::translateDistribution(int translationIndex){
|
andrew@0
|
161 int tmpIndex;
|
andrew@0
|
162 DoubleVector tmpArray;
|
andrew@0
|
163 int i;
|
andrew@0
|
164
|
andrew@0
|
165 for (i=0;i < arraySize;i++){
|
andrew@0
|
166 tmpArray.push_back(array[i]);
|
andrew@0
|
167 }
|
andrew@0
|
168 //translate values
|
andrew@0
|
169 for (i=0;i < arraySize;i++){
|
andrew@0
|
170 tmpIndex = (i + translationIndex + arraySize)%arraySize;
|
andrew@0
|
171 array[tmpIndex] = tmpArray[i];
|
andrew@0
|
172 }
|
andrew@0
|
173 tmpArray.clear();
|
andrew@0
|
174 //now delete tmp array
|
andrew@0
|
175 }
|
andrew@0
|
176
|
andrew@2
|
177
|
andrew@2
|
178
|
andrew@2
|
179 void DynamicVector::addGaussianShapeFromRealTime(const double& actualTime, const double& StdDev, double factor){
|
andrew@20
|
180 //could be further optimised
|
andrew@2
|
181 double mean = getRealTermsAsIndex(actualTime);
|
andrew@20
|
182 double standardDeviation = StdDev / scalar;//in vector indices from real time (ms)
|
andrew@20
|
183 //printf("Gaussian realtime %f at index %f std dev %f vec indices %f\n", actualTime, mean, StdDev, standardDeviation );
|
andrew@2
|
184 int i;
|
andrew@20
|
185 double std_dev_factor = (2*standardDeviation*standardDeviation);
|
andrew@20
|
186 factor *= (1/(standardDeviation*sqrt(2*PI)));
|
andrew@20
|
187 int maxVal = min((int) array.size(), (int)(mean + 4.8*standardDeviation));
|
andrew@20
|
188 int minVal = max(0, (int)(mean - 4.8*standardDeviation));
|
andrew@2
|
189
|
andrew@2
|
190 for (i=minVal;i < maxVal;i++){
|
andrew@2
|
191 array[i] += factor*exp(-1*(i-mean)*(i-mean)/(std_dev_factor));
|
andrew@2
|
192 }
|
andrew@2
|
193
|
andrew@2
|
194 // addGaussianShapeByLookupTable(mean, StdDev, factor);
|
andrew@2
|
195 }
|
andrew@2
|
196
|
andrew@2
|
197
|
andrew@0
|
198 void DynamicVector::addGaussianShape(const double& mean, const double& StdDev, double factor){
|
andrew@0
|
199
|
andrew@0
|
200 int i;
|
andrew@0
|
201 double std_dev_factor = (2*StdDev*StdDev);
|
andrew@0
|
202 factor *= (1/(StdDev*sqrt(2*PI)));
|
andrew@0
|
203 int maxVal = min((int) array.size(), (int)(mean + 4.8*StdDev));
|
andrew@0
|
204 int minVal = max(0, (int)(mean - 4.8*StdDev));
|
andrew@0
|
205
|
andrew@0
|
206 for (i=minVal;i < maxVal;i++){
|
andrew@0
|
207 array[i] += factor*exp(-1*(i-mean)*(i-mean)/(std_dev_factor));
|
andrew@0
|
208 }
|
andrew@0
|
209
|
andrew@0
|
210 // addGaussianShapeByLookupTable(mean, StdDev, factor);
|
andrew@0
|
211 }
|
andrew@0
|
212
|
andrew@0
|
213 void DynamicVector::addGaussianShapeByLookupTable(double& mean, double& StdDev, double factor){
|
andrew@0
|
214 int i;
|
andrew@0
|
215 int lookupIndex ;
|
andrew@0
|
216 factor *= (1/(StdDev*sqrt(2*PI)));
|
andrew@0
|
217 for (i=0;i<array.size()-1;i++){
|
andrew@0
|
218 lookupIndex = round(getLookupIndex(i, mean, StdDev));
|
andrew@0
|
219 array[i] += factor*gaussianLookupTable[lookupIndex];
|
andrew@0
|
220 }
|
andrew@0
|
221 //printf("ADDED GAUSSIAN SHAPE %i\n", (int)array.size());
|
andrew@0
|
222 }
|
andrew@0
|
223
|
andrew@0
|
224 double DynamicVector::getLookupIndex(const int& i, const double& mean, const double& StdDev){
|
andrew@0
|
225
|
andrew@0
|
226 double Z = ((double)i - mean)/StdDev;
|
andrew@0
|
227 double lookupIndex = Z*gaussianLookupStdDev + gaussianLookupMean;
|
andrew@0
|
228
|
andrew@0
|
229 if (lookupIndex < 0)
|
andrew@0
|
230 lookupIndex = 0;
|
andrew@0
|
231
|
andrew@0
|
232 if (lookupIndex >= GAUSSIAN_LOOKUP_LENGTH)
|
andrew@0
|
233 lookupIndex = GAUSSIAN_LOOKUP_LENGTH-1;
|
andrew@0
|
234
|
andrew@0
|
235 // (i - mean)*(i-mean)*(GAUSSIAN_LOOKUP_LENGTH*GAUSSIAN_LOOKUP_LENGTH/16.0)/(StdDev*StdDev);
|
andrew@0
|
236 return lookupIndex;
|
andrew@0
|
237 }
|
andrew@0
|
238
|
andrew@0
|
239 void DynamicVector::addTriangularShape(double mean, double width, double factor){
|
andrew@0
|
240 int i;
|
andrew@0
|
241
|
andrew@0
|
242 for (i= max(0., (double)(mean - width));i < min((mean+width), (double)array.size());i++){
|
andrew@0
|
243 array[i] += factor * abs(i - mean) / mean;
|
andrew@0
|
244 }
|
andrew@0
|
245
|
andrew@0
|
246 }
|
andrew@0
|
247
|
andrew@0
|
248 void DynamicVector::addConstant(const double& value){
|
andrew@0
|
249 for (int i=0;i<array.size();i++){
|
andrew@0
|
250 array[i] += value;
|
andrew@0
|
251 }
|
andrew@0
|
252 }
|
andrew@0
|
253
|
andrew@0
|
254
|
andrew@0
|
255 void DynamicVector::addToIndex(const int& index, const double& constant){
|
andrew@0
|
256 array[index] += constant;
|
andrew@0
|
257 }
|
andrew@0
|
258
|
andrew@0
|
259
|
andrew@0
|
260 double DynamicVector::getIndexInRealTerms(const int& index){
|
andrew@0
|
261 if (index < arraySize)
|
andrew@0
|
262 return (offset + scalar*index);
|
andrew@0
|
263 else
|
andrew@0
|
264 return 0;
|
andrew@0
|
265 }
|
andrew@0
|
266
|
andrew@0
|
267 double DynamicVector::getRealTermsAsIndex(double value){
|
andrew@0
|
268 value -= offset;
|
andrew@0
|
269 value /= scalar;
|
andrew@0
|
270
|
andrew@0
|
271 return value;
|
andrew@0
|
272
|
andrew@0
|
273 }
|
andrew@0
|
274
|
andrew@55
|
275
|
andrew@55
|
276
|
andrew@0
|
277 double DynamicVector::getValueAtMillis(const double& millis){
|
andrew@0
|
278
|
andrew@0
|
279 int index = round(getRealTermsAsIndex(millis));
|
andrew@0
|
280 if (index >= 0 && index < length)
|
andrew@0
|
281 return array[index];
|
andrew@0
|
282 else
|
andrew@0
|
283 return 0;
|
andrew@0
|
284 }
|
andrew@0
|
285
|
andrew@15
|
286
|
andrew@15
|
287 double DynamicVector::millisToVectorUnits(const double& millis){
|
andrew@15
|
288 return millis/scalar;
|
andrew@15
|
289 }
|
andrew@15
|
290
|
andrew@52
|
291 #pragma mark -draw
|
andrew@52
|
292
|
andrew@0
|
293 void DynamicVector::drawVector(const int& minIndex, const int& maxIndex){
|
andrew@0
|
294
|
andrew@0
|
295
|
andrew@0
|
296 double stepSize = ofGetWidth() / (double)(maxIndex - minIndex);
|
andrew@0
|
297 double screenHeight = (double) ofGetHeight();
|
andrew@0
|
298 double maxVal = getMaximum();
|
andrew@0
|
299
|
andrew@0
|
300 int startInt = max(1,minIndex+1);
|
andrew@0
|
301 int endInt = min(maxIndex, (int)array.size());
|
andrew@0
|
302 double heightConstant = screenHeight / maxVal;
|
andrew@0
|
303 int lastHeightPixel = heightConstant * (maxVal - array[startInt-1]);
|
andrew@0
|
304 int newHeightPixel;
|
andrew@0
|
305 for (int i = startInt;i < endInt;i++){
|
andrew@0
|
306 newHeightPixel = (int) heightConstant * (maxVal - array[i]);
|
andrew@3
|
307 int xPos = i - startInt;
|
andrew@3
|
308 ofLine (stepSize*(xPos-1), lastHeightPixel, stepSize*xPos, newHeightPixel);
|
andrew@0
|
309 lastHeightPixel = newHeightPixel;
|
andrew@0
|
310 }
|
andrew@0
|
311
|
andrew@0
|
312 }
|
andrew@0
|
313
|
andrew@0
|
314
|
andrew@0
|
315 void DynamicVector::drawVector(const int& minIndex, const int& maxIndex, ofxWindowRegion window){
|
andrew@0
|
316
|
andrew@0
|
317
|
andrew@0
|
318 double stepSize = window.width / (double)(maxIndex - minIndex);
|
andrew@0
|
319 double screenHeight = (double) window.height;
|
andrew@0
|
320 double maxVal = getMaximum();
|
andrew@0
|
321
|
andrew@0
|
322 int startInt = max(1,minIndex+1);
|
andrew@0
|
323 int endInt = min(maxIndex, (int)array.size());
|
andrew@0
|
324 double heightConstant = screenHeight / maxVal;
|
andrew@0
|
325 int lastHeightPixel = heightConstant * (maxVal - array[startInt-1]);
|
andrew@0
|
326 int newHeightPixel;
|
andrew@0
|
327 for (int i = startInt;i < endInt;i++){
|
andrew@0
|
328 newHeightPixel = (int) heightConstant * (maxVal - array[i]);
|
andrew@3
|
329 int xPos = i - startInt;
|
andrew@3
|
330 ofLine (window.x+stepSize*(xPos-1), window.y+lastHeightPixel, window.x+stepSize*xPos, window.y+newHeightPixel);
|
andrew@0
|
331 lastHeightPixel = newHeightPixel;
|
andrew@0
|
332 }
|
andrew@3
|
333 ofDrawBitmapString("start index "+ofToString(startInt)+" end "+ofToString(endInt), window.x+20, window.y+20);
|
andrew@0
|
334 }
|
andrew@0
|
335
|
andrew@0
|
336
|
andrew@0
|
337 void DynamicVector::drawConstrainedVector(const int& minIndex, const int& maxIndex, const int& minScreenIndex, const int& maxScreenIndex){
|
andrew@0
|
338 //constrain the height and width
|
andrew@0
|
339
|
andrew@0
|
340 double stepSize = (maxScreenIndex - minScreenIndex) / (double)(maxIndex - minIndex);//step size in pixels per array bin
|
andrew@0
|
341 double screenHeight = ofGetHeight();
|
andrew@0
|
342 double maxVal = getMaximum();
|
andrew@6
|
343
|
andrew@0
|
344 //OPTIMIZE!! XXX could just add stepsize each time
|
andrew@0
|
345 //not add minindex each time
|
andrew@0
|
346 int i = max(1,minIndex+1);
|
andrew@6
|
347 // ofDrawBitmapString("i = "+ofToString(i)+" :: screen min: "+ofToString(minScreenIndex + stepSize*(i-minIndex-1)), 20, 640);
|
andrew@0
|
348
|
andrew@0
|
349 while ((minScreenIndex + stepSize*(i-minIndex)) < 0)
|
andrew@0
|
350 i++;//only draw what is on the screen
|
andrew@0
|
351
|
andrew@0
|
352 for ( ; i < min(maxIndex+1, (int)array.size());i++){
|
andrew@0
|
353 ofLine (minScreenIndex + (stepSize*(i-minIndex-1)), screenHeight * (1 - array[i-1] / maxVal),
|
andrew@0
|
354 minScreenIndex + (stepSize*(i-minIndex)), screenHeight * (1 - array[i] / maxVal) );
|
andrew@0
|
355
|
andrew@0
|
356 }
|
andrew@0
|
357
|
andrew@0
|
358 ofLine(minScreenIndex, screenHeight, minScreenIndex, screenHeight/2);
|
andrew@0
|
359 ofLine(maxScreenIndex, screenHeight, maxScreenIndex, screenHeight/2);
|
andrew@0
|
360
|
andrew@6
|
361 // ofDrawBitmapString(ofToString(stepSize, 2)+" "+ofToString(maxScreenIndex - minScreenIndex, 0), 20, 600);
|
andrew@6
|
362
|
andrew@6
|
363 }
|
andrew@6
|
364
|
andrew@6
|
365
|
andrew@6
|
366 void DynamicVector::drawConstrainedVector(const int& minIndex, const int& maxIndex, const int& minScreenIndex, const int& maxScreenIndex, const ofxWindowRegion& window){
|
andrew@6
|
367 //constrain the height and width
|
andrew@6
|
368
|
andrew@6
|
369 double stepSize = (maxScreenIndex - minScreenIndex) / (double)(maxIndex - minIndex);//step size in pixels per array bin
|
andrew@6
|
370 double screenHeight = window.height;
|
andrew@6
|
371 double maxVal = getMaximum();
|
andrew@6
|
372
|
andrew@6
|
373 //OPTIMIZE!! XXX could just add stepsize each time
|
andrew@6
|
374 //not add minindex each time
|
andrew@6
|
375 int i = max(1,minIndex+1);
|
andrew@6
|
376 // ofDrawBitmapString("i = "+ofToString(i)+" :: screen min: "+ofToString(minScreenIndex + stepSize*(i-minIndex-1)), 20, 640);
|
andrew@6
|
377
|
andrew@6
|
378 while ((minScreenIndex + stepSize*(i-minIndex)) < 0)
|
andrew@6
|
379 i++;//only draw what is on the screen
|
andrew@6
|
380
|
andrew@6
|
381 for ( ; i < min(maxIndex+1, (int)array.size());i++){
|
andrew@6
|
382 ofLine (window.x+minScreenIndex + (stepSize*(i-minIndex-1)), window.y + screenHeight * (1 - array[i-1] / maxVal),
|
andrew@6
|
383 window.x + minScreenIndex + (stepSize*(i-minIndex)), window.y + screenHeight * (1 - array[i] / maxVal) );
|
andrew@6
|
384
|
andrew@6
|
385 }
|
andrew@6
|
386
|
andrew@6
|
387 //some lines where the bounaries are
|
andrew@6
|
388 ofLine(window.x + minScreenIndex, window.y + screenHeight, window.x + minScreenIndex, window.y + screenHeight/2);
|
andrew@6
|
389 ofLine(window.x + maxScreenIndex, window.y + screenHeight, window.x + maxScreenIndex, window.y + screenHeight/2);
|
andrew@6
|
390
|
andrew@50
|
391 /*
|
andrew@50
|
392 string infoString = "max "+ofToString(maxVal);
|
andrew@50
|
393 infoString += "\n offset "+ofToString(offset);
|
andrew@50
|
394 ofDrawBitmapString(infoString, window.x + window.width/2, window.y + 15);
|
andrew@50
|
395 */
|
andrew@0
|
396 // ofDrawBitmapString(ofToString(stepSize, 2)+" "+ofToString(maxScreenIndex - minScreenIndex, 0), 20, 600);
|
andrew@0
|
397
|
andrew@0
|
398 }
|