annotate scanpath.mm @ 1:1d1bf0aac99e

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