annotate scanpath.mm @ 3:d346ddc50f70

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