Wednesday, 22 September 2010

day 22 - Hacking Hakim

Today, I happened upon this, one of the excellent HTML5 experiments by Hakim el Hattab. Just for fun I thought I'd try to simulate this in Processing without looking at Hakim's code. And it turned out pretty well I think.

I based a lot of it on Lee's bouncing points from earlier posts, but the mouse-proximity detection and ball-expanding is new. UPDATED with colour change built into the ball-expanding, and updated trails from ellipses to lines: they were a stream of trailing ellipses (size 1) but that meant the trails broke up at faster speeds, now replaced with lines.








Ball[] myBall = new Ball[50];

void setup() {
 size(400,400);
 for (int i= 0; i < myBall.length; i++) {
    int randCol = int(random(3));
    myBall [i] = new Ball(randCol, 0, 0, random(0.5, 5), random(0.5, 5));
 }
}


void draw() {
  background(240);
  for (int i= 0; i < myBall.length; i++) {
    myBall[i].bounce();
    myBall[i].display();
  }
}


class Ball {

  int c;
  float xpos;
  float ypos;
  float xspeed;
  float yspeed;
  int i;
  color col;
  float [] holdX = new float[30];
  float [] holdY = new float[30];
  float big = 10;

Ball(int tempC, float tempXpos, float tempYpos, float tempXspeed, float tempYspeed) {

    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
    xspeed = tempXspeed;
    yspeed = tempYspeed;
  
  }
 
 void display() {
  if (c == 0) {
      col = color(1,1,1);
    } else if (c == 1) {
      col = color(255,0,0);    
    } else if (c == 2) {
      col = color(255,255,0);    
    }

    fill(col);  
    noStroke();
    smooth();
  
    int r = (col >> 16) & 0xFF;  // Faster way of getting red(col)
    int g = (col >> 8) & 0xFF;   // Faster way of getting green(col)
    int b = col & 0xFF;          // Faster way of getting blue(col)
  
   float rad = 100;
   float kx = mouseX - xpos;
   float ky = mouseY - ypos;
   float mx = sqrt(pow(kx, 2) + pow(ky, 2));
   if (mx <= rad) {
   big = 10 + (100 - mx);
   r = constrain(r + int(255 - 2.55*mx),0,255);
   g = constrain(g + int(255 - 2.55*mx),0,255);  
   b = constrain(b + int(255 - 2.55*mx),0,255);
   }  
    for (int i=0; i<29; i++) {
      stroke(r,g,b);
       line(holdX[i],holdY[i], holdX[i+1],holdY[i+1]);
    }
   fill(r,g,b);  
   ellipse(xpos,ypos, big, big);  


  for (int i=29; i>=1; i--) {
   holdX[i] = holdX[i - 1];  
   holdY[i] = holdY[i - 1];
  }
 holdX[0] = xpos;
 holdY[0] = ypos;      
 }

  void bounce() {
    xpos = xpos + xspeed;
    if (xpos > width) {
      xspeed = xspeed * -1;
    }

    if (xpos < 0) {
      xspeed = xspeed * -1;
    }

    ypos = ypos - yspeed;
    if (ypos > height) {
      yspeed = yspeed * -1;
    }

    if (ypos < 0) {
      yspeed = yspeed * -1;
    }
  }
}

void mousePressed() {
 saveFrame("pic-####.jpg");
}

Monday, 20 September 2010

day 20 - not much, application of sin() to blending

Not much done today, had a lot of 'work' to do. But I did finally get by head around the sin() function asa way of smoothly traversing something up and down. I really never 'got' this before, feels like a big achievement to me at least :)

In this example sin() is moving through the 0-255 range of the RGB colours art different rates.  made this pretty picture...



float angle = 0.0;

void setup() {
   size(400,400);
  smooth();
}


void draw() {
   translate(mouseX,mouseY);
  rotate(angle);
  float circ = ((1+sin(angle))*(255/2));  //sin(angle) = -1 to +1, so add one to get range 1 to 2, then multiply by colour range 255 divided by 2
  float circ1 = ((1+sin(angle/3))*(255/2));
  float circ2 = ((1+sin(angle/7))*(255/2));
  fill(circ, circ1, circ2);
 rect(-15,-15,60,10);
  angle += .1;
}

void mouseClicked() {
 saveFrame("pic-####.jpg");
}

Saturday, 18 September 2010

day 18 - joined my worm to Lee's movers

Been following Lee's wonderful swarm work over the past few days and added my worms into his swarm. Also added in a jitter factor as my worms were clumping too much, though this seems to have messed with the original patch and added some odd behaviour where the worms all clump to the bottom right of the screen once they're released from following the mouse (as opposed to travelling in straight lines as before...)

If you run the code, pressing any key releases the worms from following the mouse, 'w' sends them straight to the mouse, 'q' is inbetween.

Code below.


Mover[] mover = new Mover[20];


void setup() {

  size(640, 480);

  smooth();

  background(0);

  for (int i = 0; i < mover.length; i++) {

    mover[i] = new Mover();

  }

}

void draw() {

  background(180, 100, 180);

  for (int i = 0; i < mover.length; i++) {

    mover[i].update();

    mover[i].checkEdges();

    mover[i].display();

  }

}

class Mover {

  PVector location;

  PVector velocity;

  PVector acceleration;
  
  PVector jitter;

  float topspeed;
  
  float [] holdX = new float[20];
  float [] holdY = new float[20];
  color col = color(random(255),random(255),100,255);

  Mover() {

    location = new PVector(random(width), random(height));

    velocity = new PVector(0, 0);
    
    // adds a random jitter factor to each worm to stop them clumping
    float l = random(1)/2; 
    float m = random(1)/2;
    jitter = new PVector(l,m);

    topspeed = 7;

  }

  void update() {

    PVector mouse = new PVector(mouseX, mouseY);

    PVector dir = PVector.sub(mouse, location);

    dir.normalize();

    // any key pressed will stop them following mouse, q,w,e have specific effects
    if (keyPressed) {
      if (key == 'q') {

      dir.mult(0.2);

    } else if (key == 'e') {

      dir.mult(1);

    } else if (key == 'w') {

      dir.mult(5);

    } else {

      dir.mult(0.000001);

    }
    }


    acceleration = dir;

    acceleration.add(jitter);
    
    velocity.add(acceleration);

    velocity.limit(topspeed);

    location.add(velocity);

  }

  void display() {

    stroke(location.x, location.y, location.y);

    fill(col);

    ellipse(holdX[0], holdY[0] , 20, 20);
  
  // generates the tail drawing
   for (int i=0; i<20; i++) {
    fill(col - i*(col/20));
    ellipse(holdX[i],holdY[i], 20-i,20-i); 
   } 
    
   // stores the current location and shifts previous locations down the tail
   for (int i=19; i>=1; i--) {
     holdX[i] = holdX[i - 1];   
     holdY[i] = holdY[i - 1];
   }
   holdX[0] = location.x;
   holdY[0] = location.y;

  }

  void checkEdges() {

    if ((location.x > width) || (location.x < 0)) {

      velocity.x = velocity.x * -1;

    } 

    if ((location.y > height) || (location.y < 0)) {

      velocity.y = velocity.y * -1;

    }

  }

}

day 17 - mouse-following psychedelic worm in Processing

Great work today! I managed to half figure-out how to do a proper echo effect in video using Processing. I had been cheating by having a rectangle with very low alpha value as the bottom layer, so when "void draw" runs there's always a shadow of the previous image left behind, essentially an echo effect. But this technique is very limiting. So I flexed my array muscles and got this together, creating an array that tracks the current position as [0] and continually shunts the previous 20 positions down the array, creating a tail. In this version I've also made the previous positions shrink and change colour, getting this pleasing psychedelic effect.

I say half figured-out because this works fine in grayscale but the colour implementation isn't quite a successful in making the transparency work. This is mainly because I'm being lazy and using "color" rather than just sending the RGBA values through as separate variables. I'd like to figure out how to manipulate the alpha in "color" separately.

So this version is a worm rather than an echo. Code below.



float x;
float y;
float easing = 0.05;

void setup() {
 size(400,400);
smooth();

}

float [] holdX = new float[20];
float [] holdY = new float[20];
color col = color(200,0,100,255);

void draw() {
  background(0);
  noStroke();
  fill(255);
  float targetX = mouseX;
  x += (targetX - x) * easing;
    float targetY = mouseY;
  y += (targetY - y) * easing;
 ellipse(x,y, 20, 20);
 for (int i=0; i<20; i++) {
   //fill((255-i*(255/20)), (255-i*(255/20)));
   fill(col - i*(col/20));
   ellipse(holdX[i],holdY[i], 20-i,20-i);
 }

 for (int i=19; i>=1; i--) {
   holdX[i] = holdX[i - 1];
   holdY[i] = holdY[i - 1];
 }
 holdX[0] = x;
 holdY[0] = y;
}

void mouseClicked() {
 for (int i=1; i<19; i++) {
   println(holdX[i]);
 }
}

Friday, 17 September 2010

days 16

Today I went back to the books to do what I originally intended with my creativepact, to learn Processing properly. So I managed to plough through the first 71 pages of Getting started with Processing and filled in some serious knowledge gaps, as well as picking up some neat tricks in general coding, stuff that had stumped me before such as 'easing' to make response to mouse input less jerky. also got to understand 'for loops' a bit better.

so here's a few gifs of things I messed around with: hopefully these animate correctly, if not try downloading them... They don't seem to animate, oh well, you get the idea.

This is a grid (code) made from for-loop with randomised trace lines in the background and colour changes across the grid using the loop variables.





This is an inkpen-style mouse drawing (code) with timed colour changes, speed-linked width and time-linked colour changes.


Wednesday, 15 September 2010

Day 15 - back to processing

I seem to be doing my best work hacking other people's code lately, so here's my minor alterations to Lee Freeman's bouncing balls. I've added some small changes to the balls' appearance over time.



I really wanted to make the balls path curve but that didn't turn out to be so easy, but I did make something kind mental instead, today I might try to work out why it's so bonkers. That code is below, after the normal code.


Variation on Lee's balls


Point[] myPoint = new Point[100];

void setup() {

 size(400, 400);

 for (int i= 0; i < myPoint.length; i++) {

myPoint[i] = new Point(0, 100, random(0.1, 2), random(0.1, 2));

 }

}

void draw() {

  background(mouseY, mouseY, mouseX);

  for (int i= 0; i < myPoint.length; i++) {

  myPoint[i].bounce();

  myPoint[i].display();

  }

}

class Point {

  color c;

  float xpos;

  float ypos;

  float xspeed;

  float yspeed;

  int[] bigs = {0, 5, 10, 15, 20, 15, 10, 5};

  int i;
  int t;

  Point(float tempXpos, float tempYpos, float tempXspeed, float tempYspeed) {

    xpos = tempXpos;

    ypos = tempYpos;

    xspeed = tempXspeed;

    yspeed = tempYspeed;

  }

  void display() {

    int k = (t*10) % 255;
    int l = abs(255-t*10);
    stroke(k, l);

    fill((10 + t*7)%255, (10 + t*11)%255, abs(255 - t*5), abs(255-t*10));

    smooth();

    ellipse(xpos, ypos, 10 + bigs[i], 10 + bigs[i]);

  }

  void bounce() {

    xpos = xpos + xspeed;

    if (xpos > width) {

      xspeed = xspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (xpos < 0) {

      xspeed = xspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }
    }

    ypos = ypos - yspeed;

    if (ypos > height) {

      yspeed = yspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (ypos < 0) {

      yspeed = yspeed * -1;
    
      t++;
      if (t%5 == 0) {
      i = (i+1)%8;
      }
    
    }

  }

}


******************************************************

Bonkers but nice 


Point[] myPoint = new Point[100];

void setup() {

 size(400, 400);
 frameRate(20);

 for (int i= 0; i < myPoint.length; i++) {

myPoint[i] = new Point(0, 100, random(0.1, 2), random(0.1, 2));

 }

}

void draw() {

  background(mouseY, mouseY, mouseX);

  for (int i= 0; i < myPoint.length; i++) {

  myPoint[i].bounce();

  myPoint[i].display();

  }

}

class Point {

  color c;

  float xpos;

  float ypos;

  float xspeed;

  float yspeed;
  
  int[] bigs = {0, 5, 10, 15, 20, 15, 10, 5};
  
  int i;
  int t;
  
  Point(float tempXpos, float tempYpos, float tempXspeed, float tempYspeed) {

    xpos = tempXpos;

    ypos = tempYpos;

    xspeed = tempXspeed;

    yspeed = tempYspeed;

  }

  void display() {

    int k = (t*10) % 255;
    int l = abs(255-t*10);
    stroke(k, l);

    fill((10 + t*7)%255, (10 + t*11)%255, abs(255 - t*5), abs(255-t*10));

    smooth();

    ellipse(xpos, ypos, 10 + bigs[i], 10 + bigs[i]);

  }

  void bounce() {

    xpos = abs(10*(tan(xpos))) + xspeed;

    if (xpos > width) {

      xspeed = xspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (xpos < 0) {

      xspeed = xspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }
    }

    ypos = ypos - yspeed;

    if (ypos > height) {

      yspeed = yspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }

    }

    if (ypos < 0) {

      yspeed = yspeed * -1;
      
      t++; 
      if (t%5 == 0) {
      i = (i+1)%8;
      }
      
    }

  }

}

Tuesday, 14 September 2010

day 14 - a dip into HTML5

Being doing a lot of maxmsp lately for a contract, and not been putting it up here much for various reasons, but also completely fallen off the horse as regards my original Processing intentions.

But thanks to Sam Freeman's creativePact looking at HTML5 audio, I've solved a problem that stumped me six months ago when I was first looking at HTML5 audio (and I haven't been back there since).

I took Sam's sine wave generator and extended the envelopes so that Test is a reverse envelope, and Test1 is an A(D)SR envelope: fades in across 1/3 of the sample, sustains for 1/3, and fades out for 1/3.

test and test1

Wednesday, 8 September 2010

Day 8 - more Max/MSP

So today I found some time in Amsterdam to mess around more with the patching this new piece. Ended up writing several little modules, incrementally building up to the whole patch: although I did end up going down a direction that didn't quite work, it showed me some other possibilities.

One thing I learned today was that sometimes I should not let "vanilla pride" get in the way too much. While it would be great to only code in built-in objects, I've wasted too much time in the past trying to build something that someone else has already found a much better solution for. Today I spent an hour or so messing with a sub-patch that would keep track of how many notes are being sustained on a keyboard, after making a terribly complex patch but buggy patch I decided that it wasn't worth it and found (almost instantly) that Lreg did that job perfectly. I figure this just wasn't the time for me to make that, I'll concentrate on the piece first.

Here's some screenshots of what I did with brief explanations.

"kbd hold pitch" - this started to get messy, trying to keep track of what keys are depressed and released, gave up on this...



...for this, much simpler; Lreg to the rescue.

Then finally to a system that treats the first key depressed as normal pitch, with subsequent keys as transpositions of the file played simultaneously. Releasing all keys resets the system. Also on the left in this image is the sampleplayer.


This was where things went wrong, because of course I don't want it always to be at normal pitch for the initial key depress. so tomorrow I'll make it work at different starting pitches.


Here's all the max patches from today: they're all Max5 patches, and they also need Peter Elsea's Lreg to work.

Sunday, 5 September 2010

Amsterdam - offline

just to quickly say that I'm in amsterdam till friday doing rehearsals, will be squeezing in som CreativePact but have minimal internet access. Hopefully this means I have a splurge of stuff to put up on Saturday :)

Friday, 3 September 2010

day 1-3 getting on the horse

Ok, I've been rubbish the past few days, had a ton of work on that took all my brainspace.

So, now I've slowly started going. It's been a few months since I looked at Processing, started back into it today but found it difficult. However, I have done some good Max/MSP work on new piece (that's been on my mind all day). Managed to get a basic sample-grabber up and running, and a pitch-changer.

The idea is to have a midi keyboard "playing" a live musician by constantly sampling them and spawning off copies of that at slightly different pitches. In hindsight, it might be easier to build a delay/pitchshifter for this job, but sampling was the first patch I tried.

code/screenshots below, apologies for slightly messy code.











Keyboard sampleSpeed controller:

{
"boxes" : [ {
"box" : {
"maxclass" : "comment",
"text" : "middle C is normal speed playback, try higher and lower keys",
"linecount" : 3,
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-38",
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 66.0, 14.0, 150.0, 48.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "* -1",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-35",
"outlettype" : [ "int" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 233.0, 97.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "loadmess 2000",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-33",
"outlettype" : [ "" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 121.0, 178.0, 92.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "+ 1.",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-32",
"outlettype" : [ "float" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 238.0, 149.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "/ 100.",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-31",
"outlettype" : [ "float" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 235.0, 125.0, 41.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "button",
"numoutlets" : 1,
"id" : "obj-29",
"outlettype" : [ "bang" ],
"fgcolor" : [ 0.152941, 0.956863, 0.152941, 1.0 ],
"numinlets" : 1,
"patching_rect" : [ 36.0, 329.0, 31.0, 31.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "line~",
"numoutlets" : 2,
"fontsize" : 11.595187,
"id" : "obj-24",
"outlettype" : [ "signal", "bang" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 214.5, 437.0, 35.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "play~ test",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-26",
"outlettype" : [ "signal" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 213.0, 463.0, 62.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "t b f",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-23",
"outlettype" : [ "bang", "float" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 236.0, 200.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "0, 2000 2000",
"numoutlets" : 1,
"fontsize" : 11.595187,
"id" : "obj-20",
"outlettype" : [ "" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 219.0, 416.333313, 78.0, 18.0 ]
}

}
, {
"box" : {
"maxclass" : "gswitch",
"numoutlets" : 1,
"int" : 1,
"id" : "obj-17",
"outlettype" : [ "" ],
"numinlets" : 3,
"patching_rect" : [ 64.0, 410.0, 41.0, 32.0 ]
}

}
, {
"box" : {
"maxclass" : "flonum",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-15",
"outlettype" : [ "float", "bang" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 238.0, 175.0, 50.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "* 1.",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-11",
"outlettype" : [ "float" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 231.0, 224.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "number",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-10",
"outlettype" : [ "int", "bang" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 171.0, 203.0, 50.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "t b i",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-40",
"outlettype" : [ "bang", "int" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 212.0, 287.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "t b i",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-39",
"outlettype" : [ "bang", "int" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 167.0, 287.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "number",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-36",
"outlettype" : [ "int", "bang" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 240.0, 256.0, 50.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "number",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-34",
"outlettype" : [ "int", "bang" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 182.0, 255.0, 50.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "number",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-30",
"outlettype" : [ "int", "bang" ],
"minimum" : 0,
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 121.0, 254.0, 50.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sprintf %ld\\, %ld %ld",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-28",
"outlettype" : [ "" ],
"fontname" : "Arial",
"numinlets" : 3,
"patching_rect" : [ 117.0, 317.0, 120.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "toggle",
"numoutlets" : 1,
"id" : "obj-25",
"outlettype" : [ "int" ],
"numinlets" : 1,
"patching_rect" : [ 41.0, 462.0, 20.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "0, 2000 2000",
"numoutlets" : 1,
"fontsize" : 11.595187,
"id" : "obj-18",
"outlettype" : [ "" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 116.0, 406.333313, 78.0, 18.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "line~",
"numoutlets" : 2,
"fontsize" : 11.595187,
"id" : "obj-19",
"outlettype" : [ "signal", "bang" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 112.5, 428.0, 35.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "*~ 0.7",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-16",
"outlettype" : [ "signal" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 114.0, 481.0, 42.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "dac~",
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 114.0, 524.0, 37.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "play~ test",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-13",
"outlettype" : [ "signal" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 111.0, 454.0, 62.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "read",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-8",
"outlettype" : [ "" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 351.0, 91.0, 35.0, 18.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "buffer~ test 2000",
"numoutlets" : 2,
"fontsize" : 12.0,
"id" : "obj-6",
"outlettype" : [ "float", "bang" ],
"fontname" : "Arial",
"numinlets" : 1,
"patching_rect" : [ 345.0, 124.0, 101.0, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "- 48",
"numoutlets" : 1,
"fontsize" : 12.0,
"id" : "obj-4",
"outlettype" : [ "int" ],
"fontname" : "Arial",
"numinlets" : 2,
"patching_rect" : [ 225.0, 72.0, 32.5, 20.0 ]
}

}
, {
"box" : {
"maxclass" : "kslider",
"numoutlets" : 2,
"id" : "obj-1",
"outlettype" : [ "int", "int" ],
"presentation_rect" : [ 0.0, 0.0, 168.0, 53.0 ],
"numinlets" : 2,
"range" : 24,
"patching_rect" : [ 224.0, 9.0, 168.0, 53.0 ]
}

}
 ],
"lines" : [ {
"patchline" : {
"source" : [ "obj-1", 0 ],
"destination" : [ "obj-4", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-8", 0 ],
"destination" : [ "obj-6", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-25", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-18", 0 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-13", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-40", 0 ],
"destination" : [ "obj-28", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-40", 1 ],
"destination" : [ "obj-28", 2 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-36", 0 ],
"destination" : [ "obj-40", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-39", 0 ],
"destination" : [ "obj-28", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-39", 1 ],
"destination" : [ "obj-28", 1 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-34", 0 ],
"destination" : [ "obj-39", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-28", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-28", 0 ],
"destination" : [ "obj-18", 1 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-36", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-10", 0 ],
"destination" : [ "obj-34", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-10", 0 ],
"destination" : [ "obj-11", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-16", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-16", 0 ],
"destination" : [ "obj-14", 1 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-16", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-15", 0 ],
"destination" : [ "obj-23", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-23", 1 ],
"destination" : [ "obj-11", 1 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-23", 0 ],
"destination" : [ "obj-11", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-24", 0 ],
"destination" : [ "obj-26", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-26", 0 ],
"destination" : [ "obj-16", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-20", 0 ],
"destination" : [ "obj-24", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-29", 0 ],
"destination" : [ "obj-20", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-29", 0 ],
"destination" : [ "obj-18", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-24", 1 ],
"destination" : [ "obj-17", 1 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-32", 0 ],
"destination" : [ "obj-15", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-17", 0 ],
"destination" : [ "obj-29", 0 ],
"hidden" : 0,
"midpoints" : [ 73.5, 451.0, 35.5, 451.0, 35.5, 319.0, 45.5, 319.0 ]
}

}
, {
"patchline" : {
"source" : [ "obj-31", 0 ],
"destination" : [ "obj-32", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-33", 0 ],
"destination" : [ "obj-10", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-35", 0 ],
"destination" : [ "obj-31", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
, {
"patchline" : {
"source" : [ "obj-4", 0 ],
"destination" : [ "obj-35", 0 ],
"hidden" : 0,
"midpoints" : [  ]
}

}
 ]
}