sntong-Final-Project

This is a simple audio and visualization program that deals mainly with interaction of the keypad with music and geometric visualization. To start the program, press enter and play around with timing of sounds and visualization by pressing keys such as “W”,”A”,”S”,”D”, “I”, “J”, “K”, “L” that will work with the background music. Last but not least, have fun and explore different combination of keys to create cool visualizations.

sketch

// Scarlet Tong
//sntong@andrew.cmu.edu
// Final Project

// incrementally increase the x, y  parameter
var inc = 0.02;
// ze of each grid spacing
var scl = 48;
// rows and columns of the grid
var cols, rows;
// introducing a "time" parameter for the lines to move
var zoff = 0;
// variables the squares function will use
var topX;
var topY;
var topX1;
var topY1;
// difference variable that is used for the frames function below
var m = 0;

// declaring variables to store sound files
var backg;
var bass;
var chime;
var beat;
var popp;
// intializing variables that holds and stores Amplitude of the sound for
// the "sound wave" visualization
var amp;
var volhistory = [];
// to make sure sounds don't play and overlap with itself
var dJ = false;
// difference variable that the rings function uses
var step = 0;
// track click count to start the background music and other visualizations
var numClick = 0;
// difference variable used for the knitted function below
var column = 0;

function preload(){
  backg = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/background-1.wav");
  bass = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/bass.wav");
  chime = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/chimes.wav");
  beat = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/steady-beat.wav");
  popp = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/pop.wav");
}

function setup() {
  createCanvas(480, 480);
  // define grid spacing for field function below
  cols = floor(width/scl);
  rows = floor(height/scl);
  // defining variables of for squares function
  topX = width/2;
  topY = height/2;
  topX1 = width/2;
  topY1 = height/2;
}

function draw() {
  background(0);
  // startup page for users before rest of the code runs
  if (numClick == 0) {
    // Ready? icon, press enter key to start
    fill(255);
    rect(200,200,80,80);
    textAlign(CENTER);
    fill(255,255,255,160);
    text("READY?",width/2,height/2-40);
    stroke(180,15,85,100);
    rect(210,245,60,20);
    text("PRESS",width/2,height/2);
    text("ENTER",width/2,height/2+20);
  }
   if (keyIsDown(13) & numClick == 0) {
    numClick +=1;
    // play background music and loop it
    backg.amp(0.5);
    backg.play()
    backg.loop();
    // variable that stores the values of amplitude of the music playing
    amp = new p5.Amplitude();
    stroke(255);
  } if (numClick == 1) {
    // draw the graph that changes based on amplitude of the music
      soundWave();
  }

    // if key "w" is pressed create a "random vector field" with low bass sound
  if (keyIsDown(87)) {
    field();
  }
    // if key "a" is pressed, separating squares with a drum sound
  if (keyIsDown(65)) {
    square();
  } else {
    topX= width/2;
    topY=height/2;
    topX1= width/2;
    topY1=height/2;
  }
  // if "s" is presssed, a series of "rings" will display along with chime sound
  if (keyIsDown(83)) {
    rings();
  }

  // if "d" is pressed, pattern of yellow dots start to appear with pop sound
  if (keyIsDown(68)) {
    pattern();
  }
  // if "i" is pressed a vizualization of corners moving apart
  if (keyIsDown(73)) {
    frames();
  }

  // if "j" is pressed, bars of orange and pink strips start to extend and overlap
  if (keyIsDown(74)) {
    knitted();
  }

  // if "k" is pressed, a set of three rotating shapes appears
  if (keyIsDown(75)) {
    triangles();
  }

  // if "l" is pressed, a grid of pink dots appears
  if (keyIsDown(76)) {
    for (var x = 0; x < width; x+=48) {
      for (var y = 0; y < height; y+=48) {
        fill(180,15,85,100,20);
        noStroke();
        ellipse(x+24+random(1),y+24+random(1),10,10);
      }
    }
  }
  // small text to help prompt users to use the keys to add sound or visual effects
  push();
  fill(100);
  noStroke();
  text("W",30,450);
  text("A   S   D",30,470);
  text("I",440,450);
  text("J   K   L",440,470);
  pop();

}

// assign sound to each key
  function keyPressed(){
    // if key "w" is pressed, play the low bass sound
    if (keyCode === 87) {
      bass.play();
      dJ = true;
    }
    // if key "s" is pressed, a small "chime" sound is played
    if (keyCode === 83) {
      chime.play();
      dJ = true;
    }
    // if "a" is pressed play the short drum sound
    if (keyCode === 65) {
      beat.play();
      dJ = true;
    }
    // if "d" is pressed, play pop sound
    if (keyCode === 68) {
      popp.play();
      dJ = true;
    }
  }

// graph the Amplitude of the sound
function soundWave(){
  // get Amplitude of sound and add it to the array
  var vol = amp.getLevel();
  volhistory.push(vol);
  stroke(255,255,255,170);
  noFill();
  push();
  // map the graph in the middle of the canvas
  translate(0,-height/2+40);
  beginShape();
  for (var i = 0; i < volhistory.length; i++) {
    // remap the values of the amplitude to fit within the canvas size
    var y = map(volhistory[i],0,1,height,0);
    strokeWeight(2);
    vertex(i,y);
    stroke(250,250,250,50);
    strokeWeight(1);
    // draw diagonal lines that help give a 3D sense
    line(i,y,-i,-y);
  }
  endShape();
  pop();
  if (volhistory.length> width) {
  // keep updating and shifting "old" graph backwards to draw new ones.
  volhistory.splice(0,1);
  }
}

//generate a vector field of swaying lines
function field (){
  var yoff = 0;
  // asgn a vector component to the grid that has x number of columns and y number of rows.
  for (var y = 0; y < rows+1; y++) {
    var xoff = 0;
    for (var x = 0; x < cols+1; x++) {
      // create random angle
      var angle = noise(xoff, yoff,zoff)* 40;
      // define angle as an vector to make the lines turn
      var v = p5.Vector.fromAngle(angle);
      xoff += inc;
      stroke(255);
      push();
      // tranlate lines to each intersection of the grid and draw it
      translate(x*scl+scl,y*scl);
      rotate(v.heading());
      strokeWeight(3);
      stroke(180,15,85,100,50);
      line(0,0,scl*2,0);
      pop();
    }
    yoff += inc;
    zoff += 0.00005;
  }
}


// draw two separating squares that move apart until they reach the edge of the canva
// before going back to the center of the canvas.
function square(){
  noStroke();
    // light red color
  fill(180,15,85,100);
  rectMode(CENTER);
  rect(topX1,topY1,200,200);
  // light orange color
  fill(215,122,97,100);
  rect(topX,topY,200,200)
  topX1+=1;
  topY1+=1;
  topX-=1;
  topY-=1;
  // reset squared to the middle of the canvas
  if (topX <80) {
    topX= width/2;
    topY=height/2;
    topX1= width/2;
    topY1=height/2;
  }
}

// make cirlces appear at a random rate to make a pattern
function pattern(){
  push();
  translate(width/2, height/2); // so that the curve is within the canvas
  beginShape();
  for(var i = 0; i < volhistory.length; i++){
    var theta = map(i,0,100,0,500);
    // give the randomly apparenting circles to make a pattern
    var a = map(volhistory[i], 0,1,-10,10);
    //Conchoid of de Sluze equation from Wolfram MathWorld
    var x = (1/cos(theta)+(a*cos(theta)))*cos(theta);
    var y = (1/cos(theta)+(a*cos(theta)))*sin(theta);
    noStroke();
    fill(215,122,97,100);
    //"polar array" the Conchoid from the center
    rotate(90);
    ellipse(x*20+random(0,1),y*20+random(0,1),4,4);
  }
  endShape(CLOSE);
  pop();
}

// draw spinning rings
function rings(){
  push();
  stroke(215,122,97);
  strokeWeight(5);
  strokeCap(SQUARE);
  arc(width/2,height/2,100,100,0-step,HALF_PI-step);
  strokeWeight(3);
  arc(width/2,height/2,80,80,QUARTER_PI-step,PI+HALF_PI-step);
  strokeWeight(2);
  arc(width/2,height/2,150,150,HALF_PI+QUARTER_PI+step,PI+HALF_PI+step);
  strokeWeight(1);
  arc(width/2,height/2, 200,200,0+step,PI+HALF_PI+step);
  // the variable makes each arc to change and rotate
  step+=0.1;
  pop();
}

function frames(){
  // setting up variable that governs the rate of which the corners move away
  if (m >= 0) {
    m+=0.5;
  } // if the displacement of the corners is more than 50 pixels, reset to 0
  if(m == 50) {
    m = 0;
  }
  // small frame
  stroke(255,255,255,150);
  strokeWeight(4);
  // top left corner
  line(190-m,190-m,190-m,240-m);
  line(190-m,190-m,240-m,190-m);
  // top right corner
  line(240+m,190-m,290+m,190-m);
  line(290+m,190-m,290+m,240-m);
  // bottom right corner
  line(290+m,240+m,290+m,290+m);
  line(290+m,290+m,240+m,290+m);
  // bottom left corner
  line(240-m,290+m,190-m,290+m);
  line(190-m,290+m,190-m,240+m);
}

function knitted(){
  // setting up the x and y values to draw the colored columns and rows
  for (var i = 0; i < 8; i++) {
    if (column >= 0) {
      column+=0.25;
    } if(column == width) {
      column = 0;
    }
    noStroke();
    fill(215,122,97,100);
    // yellow bars
    rect(i*width/8,0,30,height/8+column);
    fill(180,15,85,100);
    // pink bars
    rect(0,i*height/8,column,30);
  }
}

function triangles (){
  stroke(215,122,97,100);
  strokeWeight(2);
  push();
  translate(width/2,height/2);
  // set rotation of the triangles to increase with the frameCount
  rotate(radians(frameCount));
  triangle(-50,50,0,-50,50,50);
  strokeWeight(4);
  rotate(radians(frameCount*.5));
  triangle(-60,60,0,-60,60,60);
  strokeWeight(2);
  rotate(radians(frameCount*2));
  triangle(-65,65,0,-65,65,65);
  pop();
}

Leave a Reply