Creating an ArrayList of SinOsc objects, trouble with adding, removing, play sound and stop sound

edited August 2018 in Library Questions

As the title says I'm trying to create an ArrayList of SinOsc objects. When I click the mouse I want it to add a new SinOsc object to the ArrayList which will play a sine wave. The sin wave will differ in frequency and amplitude based on its x and y location on the screen. When I remove the SinOsc object from the ArrayList I want the sound to stop as well. These sinOsc objects will also be dynamically moving around the screen based on Boids behaviours that are already defined in this code. So ideally when the mouse is clicked both a boid object (which will be displayed on the screen) and a SinOsc object will be created and the same ones removed when needed. I'm having trouble making this work. Any help is appreciated!

//importing sine sound and declaring array
import processing.sound.*;
ArrayList<SinOsc> sine;

ArrayList<Boid> boids;
float globalScale = .91;
float eraseRadius = 20;
String tool = "boids";

// boid control
float maxSpeed;
float friendRadius;
float crowdRadius;
float avoidRadius;
float coheseRadius;

boolean option_friend = true;
boolean option_crowd = true;
boolean option_avoid = true;
boolean option_noise = true;
boolean option_cohese = true;

// gui crap
int messageTimer = 0;
String messageText = "";

void setup () {
  size(700, 700); //3508 pixels x 4961 1754x2480 877, 1240 , just some sizes
  textSize(16);
  recalculateConstants();
  boids = new ArrayList<Boid>();

  //sine is new Arraylist with SinOsc sounds in it
  sine = new ArrayList<SinOsc>();
}

void recalculateConstants () {
  maxSpeed = 2.1 * globalScale;
  friendRadius = 60 * globalScale;
  crowdRadius = (friendRadius / 1.3);
  avoidRadius = 90 * globalScale;
  coheseRadius = friendRadius;
}

void draw () {
  noStroke();
  colorMode(HSB);
  fill(0, 100);
  rect(0, 0, width, height);

  if (tool == "erase") {
    noFill();
    stroke(0, 100, 260);
    rect(mouseX - eraseRadius, mouseY - eraseRadius, eraseRadius * 2, eraseRadius *2);
    if (mousePressed) {
      erase();
    }
  } else if (tool == "avoids") {
    noStroke();
    fill(0, 200, 200);
    ellipse(mouseX, mouseY, 15, 15);
  }
  for (int i = 0; i <boids.size(); i++) {
    Boid current = boids.get(i);
    current.go();
    current.draw();
  }
}

void keyPressed () {
  if (key == 'q') {
    tool = "boids";
  } else if (key == 'e') {
    tool = "erase";
  } else if (key == '-') {
    globalScale *= 0.8;
  } else if (key == '=') {
    globalScale /= 0.8;
  } else if (key == '1') {
    option_friend = option_friend ? false : true;
  } else if (key == '2') {
    option_crowd = option_crowd ? false : true;
  } else if (key == '3') {
    option_avoid = option_avoid ? false : true;
  } else if (key == '4') {
    option_cohese = option_cohese ? false : true;
  } else if (key == '5') {
    option_noise = option_noise ? false : true;
  }
  recalculateConstants();

// screen shot
//  if (key == 'p') {
//    saveFrame("boidsMaster-######.png");
//  }
}


String s(int count) {
  return (count != 1) ? "s" : "";
}

String on(boolean in) {
  return in ? "on" : "off";
}

void mousePressed () {
  switch (tool) {
  case "boids":
    boids.add(new Boid(mouseX, mouseY));

    //adding new sine object/ particle to arraylist
    //sine.add(new SinOsc());

    //does not recognise play as a function
    //sine.play();
    break;
  }
}

void erase () {
  for (int i = boids.size()-1; i > -1; i--) {
    Boid b = boids.get(i);
    if (abs(b.pos.x - mouseX) < eraseRadius && abs(b.pos.y - mouseY) < eraseRadius) {
      boids.remove(i);

      //remove sin particle from array
      sine.remove(i);

      //does not recognise stop as a function
      //sine.stop(i);
    }
  }
}







class Boid {
  // main fields
  PVector pos;
  PVector move;
  float shade;
  ArrayList<Boid> friends;

  // timers
  int thinkTimer = 0;

  Boid (float xx, float yy) {
    move = new PVector(0, 0);
    pos = new PVector(0, 0);
    pos.x = xx;
    pos.y = yy;
    thinkTimer = int(random(10));
    shade = random(255);
    friends = new ArrayList<Boid>();
  }

  void go () {
    increment();
    wrap();

    if (thinkTimer ==0 ) {
      // update our friend array (lots of square roots)
      getFriends();
    }
    flock();
    pos.add(move);
  }

  void flock () {
    PVector allign = getAverageDir();
    PVector avoidDir = getAvoidDir(); 
    PVector avoidObjects = getAvoidAvoids();
    PVector noise = new PVector(random(2) - 1, random(2) -1);
    PVector cohese = getCohesion();

    allign.mult(1);
    if (!option_friend) allign.mult(0);

    avoidDir.mult(1);
    if (!option_crowd) avoidDir.mult(0);

    avoidObjects.mult(3);
    if (!option_avoid) avoidObjects.mult(0);

    noise.mult(0.1);
    if (!option_noise) noise.mult(0);

    cohese.mult(1);
    if (!option_cohese) cohese.mult(0);

    stroke(0, 255, 160);

    move.add(allign);
    move.add(avoidDir);
    move.add(avoidObjects);
    move.add(noise);
    move.add(cohese);

    move.limit(maxSpeed);

    shade += (random(2) - 1) ;
    shade = (shade + 255) % 255; //max(0, min(255, shade));
  }

  void getFriends () {
    ArrayList<Boid> nearby = new ArrayList<Boid>();
    for (int i =0; i < boids.size(); i++) {
      Boid test = boids.get(i);
      if (test == this) continue;
      if (abs(test.pos.x - this.pos.x) < friendRadius &&
        abs(test.pos.y - this.pos.y) < friendRadius) {
        nearby.add(test);
      }
    }
    friends = nearby;
  }

  PVector getAverageDir () {
    PVector sum = new PVector(0, 0);
    //int count = 0;

    for (Boid other : friends) {
      float d = PVector.dist(pos, other.pos);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < friendRadius)) {
        PVector copy = other.move.copy();
        copy.normalize();
        copy.div(d); 
        sum.add(copy);
        //count++;
      }
      //if (count > 0) {
      //  sum.div((float)count);
      //}
    }
    return sum;
  }

  PVector getAvoidDir() {
    PVector steer = new PVector(0, 0);
    int count = 0;

    for (Boid other : friends) {
      float d = PVector.dist(pos, other.pos);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < crowdRadius)) {
        // Calculate vector pointing away from neighbor
        PVector diff = PVector.sub(pos, other.pos);
        diff.normalize();
        diff.div(d);        // Weight by distance
        steer.add(diff);
        count++;            // Keep track of how many
      }
    }
    if (count > 0) {
      //steer.div((float) count);
    }
    return steer;
  }

  PVector getAvoidAvoids() {
    PVector steer = new PVector(0, 0);
    //int count = 0;

    return steer;
  }

  PVector getCohesion () {
    PVector sum = new PVector(0, 0);   // Start with empty vector to accumulate all locations
    int count = 0;
    for (Boid other : friends) {
      float d = PVector.dist(pos, other.pos);
      if ((d > 0) && (d < coheseRadius)) {
        sum.add(other.pos); // Add location
        count++;
      }
    }
    if (count > 0) {
      sum.div(count);

      PVector desired = PVector.sub(sum, pos);  
      return desired.setMag(0.05);
    } else {
      return new PVector(0, 0);
    }
  }

  void draw () {

    noStroke();
    fill(255);
    pushMatrix();
    translate(pos.x, pos.y);
    ellipse(0, 0, 5, 5);
    popMatrix();


  float freqMy = map(pos.y,height,0,0,500);
  float ampMy = map(pos.y,0,height,0,1);
  float panMx = map(pos.x,0,width,-1,1);
  float add= 0;

  //sine.set(freqMy,ampMy,add,panMx);

  }

  // update all those timers!
  void increment () {
    thinkTimer = (thinkTimer + 1) % 5;
  }

  void wrap () {
    pos.x = (pos.x + width) % width;
    pos.y = (pos.y + height) % height;
  }
}






class SinOsc {


  SinOsc(){

  }

}
Tagged:

Answers

  • There is a new forum you want to post in as well

    See processing main page, link to forum please

  • sine in line 128 is your entire array. You want to stop the current Osc so you need sine.get(i).stop() the same for play on 116.

    However, having two parallel arrays like this is asking for trouble. Better to add the SinOsc to the boid class so every boid has an osc

  • @lanelps Please, don't forget to cross-link your posts so people can track the answers and assist more efficiently.

    Kf

Sign In or Register to comment.