comparison scanpath.mm @ 0:c667dfe12d47

OK. Ther real deal.
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Mon, 19 Nov 2012 13:00:42 +0000
parents
children 1d1bf0aac99e
comparison
equal deleted inserted replaced
-1:000000000000 0:c667dfe12d47
1 /*
2 * scanpath.cpp
3 * springstructure
4 *
5 * Created by Robert Tubb on 09/06/2011.
6 * Copyright 2011 __MyCompanyName__. All rights reserved.
7 *
8 */
9 #include <vector>
10 #include "scanpath.h"
11 #include "testApp.h"
12
13 //----------------------------------------------------------------
14 ScanPath::ScanPath() : maxElements(2048) {
15 // construct an empty scanpath
16 // an ' element ' consists of 1 lump and one spring
17
18
19 numElements = 0; // numElements is a dynamic running count of elements when building - a bit crap
20 springPath = new Spring*[maxElements];
21 lumpPath = new Lump*[maxElements];
22
23 framesPerSample = ofGetFrameRate()/SAMPLE_RATE;
24 frameInterpolator = 0.0;
25 currentLength = 0.0;
26 restLength = 1.0; // ?
27
28 scanMode = DISPLACEMENT;
29
30 initWavetables();
31
32 }
33 //----------------------------------------------------------------
34 ScanPath::~ScanPath(){
35 delete [] springPath;
36 delete [] lumpPath;
37 delete [] wavetableNew;
38 delete [] wavetableOld;
39 delete [] wavetableUpdate;
40 cout << "destructed scanpath\n";
41 }
42
43 void ScanPath::clear(){
44 for(int i = 0; i<numElements; i++){
45 springPath[i]->removeFromScanPath();
46 lumpPath[i]->removeFromScanPath();
47 }
48 numElements = 0;
49 // cant work?
50 }
51 int ScanPath::howManyElements(){
52 return numElements;
53 }
54 //----------------------------------------------------------------
55 void ScanPath::inscribe(double ax, double ay){
56 // look at coordinates, add the closest lump and it's connecting string
57 // if we're further away from current lump
58
59 // check end points of connecting springs, pick closest
60 }
61 void ScanPath::draw(){
62 // draw the actual waveform in the corner
63
64 int width = 768;
65 int height = 128;
66 double sampval = 0.0;
67 int leftsampnum = 0;
68 int rightsampnum = 0;
69 float sampscale = 0.0, prevsampscale = 0.0, interp = 0.0;
70
71 ofSetColor(0, 0, 0);
72 double step = double(numElements)/width; // how much we are stepping thru wave per pixel
73 for(int i = 0; i < width; i++){
74
75 leftsampnum = floor(i * step); // basic nearest neighbour interpolation
76 rightsampnum = ceil(i*step);
77 interp = (i*step)-leftsampnum;
78 if(rightsampnum < numElements){
79 sampval = (1 - interp)*wavetableNew[leftsampnum] + interp*wavetableNew[rightsampnum];
80 }
81 sampscale = (sampval * 700) + height/2.0; // centre and scale
82 ofSetLineWidth(2);
83 ofLine(sampscale, i, prevsampscale, i-1); // draw a line from pixel to pixel (?)
84 prevsampscale = sampscale;
85 }
86
87 }
88 void drawCubic(){
89
90 }
91 //----------------------------------------------------------------
92 // add spring
93 void ScanPath::addSpring(){
94 // see add element
95 }
96 //----------------------------------------------------------------
97 // add lump
98 void ScanPath::addLump(){
99 // see add element
100 }
101 //----------------------------------------------------------------
102 // add lump
103 double ScanPath::getTotalLength(){
104 // for interesting modulations...
105 currentLength = 0.0;
106 for(int i = 0; i < numElements; i++){
107 currentLength += springPath[i]->getLength();
108 }
109 return currentLength;
110
111 }
112 //----------------------------------------------------------------
113 void ScanPath::initWavetables(){
114 wavetableNew = new double[maxElements];
115 wavetableOld = new double[maxElements];
116 wavetableUpdate = new double[maxElements];
117
118 for(int i = 0; i < maxElements; i++){
119 wavetableOld[i] = 0.0;
120 wavetableNew[i] = 0.0;
121 wavetableUpdate[i] = 0.0;
122 }
123
124 }
125 //----------------------------------------------------------------
126 void ScanPath::addElement(Lump* aLump, Spring * aSpring){
127 // insert ptr to the lump and spring into array
128 if(numElements >= maxElements){
129 cerr << "cannot add any more to scanpath - max elements: 2048\n";
130 return;
131 }
132 lumpPath[numElements] = aLump;
133 springPath[numElements] = aSpring;
134
135 aLump->addToScanPath();
136 aSpring->addToScanPath();
137
138 numElements++;
139 }
140 //----------------------------------------------------------------
141 void ScanPath::updateWavetables(){
142 // swap old , new
143 double * temp;
144
145 switch(scanMode){
146 case DISPLACEMENT:
147 // now fill with new values
148 for(int i = 0; i < numElements; i++){
149
150 wavetableUpdate[i] = lumpPath[i]->scanRadialDisplacement()/1.5;
151
152 }
153 break;
154 case SPEED:
155 for(int i = 0; i < numElements; i++){
156 wavetableUpdate[i] = lumpPath[i]->scanLumpSpeed();
157 }
158 break;
159 case SPRING_FORCE:
160 for(int i = 0; i < numElements; i++){
161 wavetableUpdate[i] = springPath[i]->getForceMag();
162 }
163 break;
164 case YPOS:
165 for(int i = 0; i < numElements; i++){
166 wavetableUpdate[i] = lumpPath[i]->scanYPos();
167 }
168 break;
169 default:
170 break;
171
172
173 }
174
175 // reset the interp between frames
176 if(audioAccessing){
177 cout << "buffers swapped while update!\n";
178 }
179 updateAccessing = true;
180 temp = wavetableOld;
181 wavetableOld = wavetableNew;
182 wavetableNew = wavetableUpdate;
183 wavetableUpdate = temp;
184 updateAccessing = false;
185
186 frameInterpolator = 0.0;
187 framesPerSample = 2.0*ofGetFrameRate()/SAMPLE_RATE; // attempt to get a reasonable est. of how fast to interp
188
189 }
190 //----------------------------------------------------------------
191 // get next sample
192 double ScanPath::getNextSample(double aPhasor){
193 // move along path, interpolating between points
194 // move between frames too
195 double alongPath = aPhasor*double(numElements);
196
197 // indexes for interpolated points
198 int n0 = floor(alongPath);
199 int n1 = n0+1;
200 if(n1 >= numElements){
201 n1 = 0;
202 }
203
204 double frac = alongPath - double(n0);
205
206 audioAccessing = true;
207 if (updateAccessing){
208 cout << "update is accessing while audio is\n";
209 }
210 double oldsample = (1 - frac) * wavetableOld[n0] + frac * wavetableOld[n1];
211
212 double newsample = (1 - frac) * wavetableNew[n0] + frac * wavetableNew[n1];
213
214 audioAccessing = false;
215
216 frameInterpolator += framesPerSample;
217 if(frameInterpolator >= 1.0){
218 //cout << "frame interp > 1\n";
219 frameInterpolator = 1.0; // just stays outputting new
220 }
221
222 double sample = (1 - frameInterpolator)*oldsample + frameInterpolator*newsample;
223 //cout << sample << endl;
224 // keep within the bounds of acceptability
225 if(sample > 0.99){
226 // cout << "OUCH\n";
227 sample = 0.99;
228 }else if(sample < -0.99){
229 sample = -0.99;
230 }
231 return sample;
232
233 }
234 //----------------------------------------------------------------
235 // get next sample
236 double ScanPath::getNextSample(){
237 // move along wavetable, no interpolation ie: length of path is pitch
238 static int n = 0;
239 double oldsample = wavetableOld[n];
240
241 double newsample = wavetableNew[n];
242 n++;
243 if (n >= numElements){
244 n = 0;
245 }
246
247 frameInterpolator += framesPerSample;
248 if(frameInterpolator >= 1.0){
249 //cout << "frame interp > 1\n";
250 frameInterpolator = 1.0; // just stays outputting new
251 }
252
253 double sample = (1 - frameInterpolator)*oldsample + frameInterpolator*newsample;
254 return sample*3.0;
255
256 }
257 //----------------------------------------------------------------
258 //----------------------------------------------------------------
259 // get next sample with cubic interpolation
260 double ScanPath::getNextSampleCubic(double aPhasor){
261 // move along path, interpolating between points
262 // move between frames too
263 double alongPath = aPhasor*double(numElements);
264
265 // indexes for interpolated points
266 int n1 = floor(alongPath);
267
268 int n0 = n1-1;
269 if(n0 < 0){
270 n0 = numElements;
271 }
272 int n2 = n1+1;
273 if(n2 >= numElements){
274 n2 = 0;
275 }
276 int n3 = n2+1;
277 if(n3 >= numElements){
278 n3 = 0;
279 }
280 double frac = alongPath - double(n0);
281 double fracSquared = frac * frac;
282 double fracCubed = fracSquared * frac;
283 double a0,a1,a2,a3;
284 //cout << n0 << endl;
285 // cubic interp
286 /*
287 double y0,double y1,
288 double y2,double y3,
289 double mu)
290 {
291 double a0,a1,a2,a3,mu2;
292
293 mu2 = mu*mu;
294 a0 = y3 - y2 - y0 + y1;
295 a1 = y0 - y1 - a0;
296 a2 = y2 - y0;
297 a3 = y1;
298
299 return(a0*mu*mu2+a1*mu2+a2*mu+a3);
300 */
301 a0 = wavetableOld[n3] - wavetableOld[n2] - wavetableOld[n0] + wavetableOld[n1];
302 a1 = wavetableOld[n0] - wavetableOld[n1] - a0; // y0 - y1 - a0;
303 a2 = wavetableOld[n2] - wavetableOld[n0]; // y2 - y0;
304 a3 = wavetableOld[n1];
305
306 double oldsample = a0*fracCubed + a1*fracSquared + a2*frac + a3;
307
308 a0 = wavetableNew[n3] - wavetableNew[n2] - wavetableNew[n0] + wavetableNew[n1];
309 a1 = wavetableNew[n0] - wavetableNew[n1] - a0; // y0 - y1 - a0;
310 a2 = wavetableNew[n2] - wavetableNew[n0]; // y2 - y0;
311 a3 = wavetableNew[n1];
312
313 double newsample = a0*fracCubed + a1*fracSquared + a2*frac + a3;
314
315 frameInterpolator += framesPerSample;
316 if(frameInterpolator >= 1.0){
317 frameInterpolator = 1.0; // just stays outputting new
318 }
319
320 double sample = (1 - frameInterpolator)*oldsample + frameInterpolator*newsample;
321 //cout << sample << endl;
322 // keep within the bounds of acceptability
323
324 // beef up
325 sample = sample*3.0;
326
327 if(sample > 0.99){
328 sample = 0.99;
329 }else if(sample < -0.99){
330 sample = -0.99;
331 }
332
333 return sample;
334
335 }
336 //----------------------------------------------------------------