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();
}

sntong-Project 12: Final Project Proposal

For the final project, I decided to take a launch pad idea and apply it to the keyboard and linking movements and visual representation to the sound and key when pressed. I plan to have a general beat looping in the background, which hopefully the users on the page have the option to toggle between a couple of them, and keying sounds to specific keyboard buttons. The visual response for each key would be inspired by its corresponding sound. I also plan to implement an abstracted terrain of “asteroids” that will be flying pass the Canvas.

Quick sketch of visual elements and initial ideas

sntong-Looking Outwards 12: Project Priors and Precursors

 

One of the video overlays viewers can add throughout the video
Multiple layers can be added to the video at the same time by pressing multiple keys.

I came across two interactive website that is video based. The first project is LSD by Spencer Sheridan, that is a keyboard interactive music video for the band Busy Living. Viewers of the music video is able to add and overlay shapes, colors and videos onto the music video to create an unique visual experience every time the music video is played (check out the music video here).

This experiment lets you play your keyboard like an instrument to overlay colors and images to create your own music video, and I am interested in creating an unique experience to a short video.

The second example provides mouse interaction of the user on the page to generate music. GeoSound is a webpage By Yanlin Ma that generates sound through geometric object collision. It provides an interesting way to allow people to make sound and contribute to the sound they are experiencing.

Drag and drop objects to create random collisions and make sound

 

sntong-Project 11: Freestyle: Playing with your Turtle(s)

sketch

// Scarlet Tong
// sntong@andrew.cmu.edu
// Section A
// Project 11: Freestyle: Playing with your Turtle(s)

// intialize global Turtle
var nTurtle;

function setup(){
  createCanvas(400,400);
  background(0);
  frameRate(60);
}


function draw(){
  // draw a new pattern when mouse is pressed located at mouseX and mouseY
if (mouseIsPressed) {

  nTurtle = new makeTurtle(mouseX,mouseY);
  // offset of lines from the center according the location of mouseX on the canvas
  var step = map(mouseX,0,width,2,40);
  // rotation of the lines stop and start at a location that is determined by mouseY
  var ratio = map(mouseY,0,height,100,150);
  // Each pattern as a maxium of 20 lines
  for (var i = 0; i < 20; i++) {
    nTurtle.setColor(color(random(255),random(100,255),random(100,255)));
    // lines function found below draw function
    lines();
    // start drawing shapes
    nTurtle.penUp();
    // offset the next lines step pixels away from the previous one
    nTurtle.forward(step);
    // rotate that new line with a set angle
    nTurtle.right(ratio);
    // end the shape
    nTurtle.penDown();
    }
  }

}


// draw lines
function lines(){
    nTurtle.setWeight(1);
    nTurtle.penDown();
    nTurtle.forward(5);
    nTurtle.penUp();
}


function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}

For this project I wanted to create a changing pattern that will track the mouse when it is pressed down. The pattern is drawn by the turtle graphics and has varying color.

Possible drawings to be made with the code
Drawing 2

 

sntong-LookingOutwards-11- Computer Music

Chris Carlson is a sound artist and software developer. He holds a M.A. from Stanford University’s Center for Computer Research in Music and Acoustics and a B.S. in Physics from James Madison University. His award winning application he developed, the Borderlands Granular, is new visually and tacitly interactive for people to develop music using “grains”. The video below is a short demo showing how users can manipulate music and visual icons that is related to the sound that is being emitted. In one of his recent performance, Body Drift , Carlson partners with Jakob Marsico to an immersive audiovisual performance.

 

sntong-Project 10- Generative Landscape

sketch

//Scqrlet Tong
//sntong@andrew.cmu.edu
//Section A
// Project 10: Generative Landscape

var sheeps = [];
var sSheeps = [];


function setup() {
    createCanvas(480, 480);

    // create an initial collection of objects
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        sheeps[i] = makeSheep(rx);
        sSheeps[i] = makeSmallSheep(rx);
    }
    frameRate(10);
}


function draw() {
    background(170,215,230);
    // changing hillscape
    Hill();
    // moving sun position
    Sun();
    // draw existing to new locationlarge sheeps
    updateSheeps();
    // draw new large sheeps
    addNewSheeps();
    updateSmallSheeps();
    addNewSmallSheeps();
}


function updateSheeps(){
    // Update and draw the large sheep positions
    for (var i = 0; i < sheeps.length; i++){
        sheeps[i].move();
        sheeps[i].display();
    }
}

function addNewSheeps() {
    // With a very tiny probability, add a new building to the end.
    var newSheepLikelihood = 0.05;
    if (random(0,1) < newSheepLikelihood) {
        sheeps.push(makeSheep(width));
    }
}


// shift sheeps
function oMove() {
    this.x += this.speed;
}


// draw large sheeps
function sheepDisplay() {
    push();
    translate(this.x+50,height-80+this.scatter);
    // legs
    stroke(60);
    strokeWeight(2);
    var loc1 = random (5,7);
    line(this.x-10,loc1-10,this.x-10,loc1+12);
    line(this.x+10,loc1-10,this.x+10,loc1+12);
    //body
    strokeWeight(0.5);
    fill(255);
    stroke(200);
    ellipse(this.x, loc1-3, this.fat+20, 20);
    fill(150);
    //head
    ellipse(this.x-18, loc1-6, this.fat-8, 12);
    stroke(120);
    pop();
}

// object large sheep
function makeSheep(make) {
    var sheep = {x: make,
                fat: 20,
                speed: -1.0,
                move: oMove,
                scatter: random(5),
                display: sheepDisplay}
    return sheep;
}


// update location of existing small sheeps
function updateSmallSheeps(){
    // Update the small sheep's positions, and draw them.
    for (var i = 0; i < sSheeps.length; i++){
        sSheeps[i].move();
        sSheeps[i].display();
    }
}

// generate new small sheeps
function addNewSmallSheeps() {
    // add a new small sheep to the end.
    var newSheepLikelihood = 0.05;
    if (random(0,1) < newSheepLikelihood) {
        sSheeps.push(makeSmallSheep(width));
    }
}

// draw farer (smaller) sheeps in the field
function smallSheepDisplay() {
    push();
    translate(this.x+20,height-150+this.scatter);
    // legs
    stroke(60);
    strokeWeight(1);
    var loc1 = random (5,6);
    line(this.x-5,loc1-5,this.x-5,loc1+6);
    line(this.x+5,loc1-5,this.x+5,loc1+6);
    //body
    strokeWeight(0.5);
    fill(255);
    stroke(200);
    ellipse(this.x, loc1-1.5, this.fat+10, 10);
    fill(150);
    //head
    ellipse(this.x-9, loc1-3, this.fat-4, 6);
    stroke(120);
    pop();
}

// smalls sheep object
function makeSmallSheep(pop) {
    var sSheep = {x: pop,
                fat: 10,
                speed: -0.5,
                move: oMove,
                scatter: random(20),
                display: smallSheepDisplay}
    return sSheep;
}

// function for drawing moving sun
function Sun (){
  for (var i = 0; i < width; i++) {
      var t = (i * 0.003) + (millis() * 0.0002);
      fill(250,200,100);
      ellipse(width-t-25,100,50,50);
  } noFill();
}

// to creste Landscape
function Hill(){
  fill(70,175,100);
  noStroke();
  beginShape();
  for (var x = 0; x < width; x++) {
      var t = (x * 0.003) + (millis() * 0.00002);
      var y = map(noise(t), 0,1, 100, height-100);
      vertex(x, y);
      vertex(0,height);
      vertex(width,height);
  }
  endShape();
}

I was imagining the view one could get while seating on a train and looking out to the fields in Australia. The larger and smaller sheep suggests their distance to the person. As time passes the sun also moves with the viewer. As I am not familiar with objects, this project is much harder for me as it is working with objects.

A quick sketch I made to visualize how things would look

sntong-Looking Outwards-10

Photo of Höweler + Yoon office with J. Meejin Yoon standing on the right

As the founder of Höweler + Yoonarge, an internationally recognized architecture firm,Meejin Yoon‘s practice works with a wide range of scales to furniture scale installations to buildings to landscaping projects. With her partner, the two leads their practice to constantly challenge the relationship between architecture, art and landscape. Media is often used to enrich the architectural experience she designs. A lot of experiential installations are made so she can observe and propose new ways for the public to interact with. One example of this is the UNI project that was installed in New York, with aims to create a mobile, and reconfigurable public “reading” space. A series of yellow caps, or “quills” as they are referred to by the architects, doubles as a bench and also protects the books on the wood shelves. Yoon’s personal accomplishments are also notable with as she is a Professor and Head of the Department of Architecture at the Massachusetts Institute of Technology, where she received the Irwin Sizer Award for the Most Significant Improvement to MIT Education. She was also awarded Architectural Review’s New Generation Design Leadership Award.

 

sntong-Project-09-Portrait

sketch

// Scarlet Tong
// sntong@andrew.cmu.edu
// Section A
// Project 09 - Computational Portrait (Custom Pixel)

// variable to store the image
var pic;

function preload(){
  // load image into variable
  pic = loadImage("https://i.imgur.com/fLLh0am.jpg")
}

function setup(){
  createCanvas (280,480);
  imageMode(CENTER);
  background(255);
}

function draw(){
  // extract pixes from image
  pic.loadPixels();
  // select random x and y values to generate the "cross"
  var x = floor(random(pic.width));
  var y = floor(random(pic.height));
  // extract color from that pixel
  var pixCol = pic.get(x, y);
  //set stroke color to color of the pixel
  stroke(pixCol);
  // distance to allow to draw ther lines to form a cross
  var dis = random(10);
  // draw crosses
  line(x,y,x+dis,y+dis);
  line(x,y+dis,x+dis,y);
  // create small cicles that are located at the center of the crosses
  fill(pixCol);
  ellipse(x+(dis/2)+0.5, y+(dis/2)+0.5,dis/3,dis/3);
}

I decided to make a pixel that is a cross with a dot in the middle, which I will use to trace a self portrait of myself. I used random to select where every new pixel is drawn to create the image.

Portrait generated from code

sntong-Looking Outwards 09: on Looking Outwards

I viewed the Botanicus Interacticus project by Disney Research (in collaboration with Philipp Schoessler, Jonas Loh/Studio NAND, Munehiko Sato) as an interesting project that aims to bridge the gap between our ability to understand, and communicating, to nature and to understand how nature will react. By projecting images around the plants due to the physical interaction by other objects around it starts to allow us to read, empathize the world plants experience in their perspective. It also suggests ideas of Deep Ecology that strive for a more responsible stance of human activity in this era of Anthropocene. As I did not focus on much of the technical implications the project which Jamie did in her post, I am fascinated by the cultural implications the project begins to tease out.

Interactions of the person with the plant produces amazing visual images

 

 

sntong-Looking Outwards 08: The Creative Practice of an Individual

Afroditi Psarra is a multidisciplinary artist who bases a focus of electronic textiles (or “soft” circuits) and sound. She completed her PhD in Image, Technology and Design from the Complutense University of Madrid and is an assistant professor at the Center for Digital Arts & Experimental Media (DXARTS) at the University of Washington, Seattle. Her rigorous research in Cyberpunk and New Media Art with focus on integrating science fiction ideas with performative and digital fields allows her to apply a humanistic approach to how technology is perceived and utilized.

In the lecture at Institute Systems Biology she introduces her work based on her believes that we will have to integrate and envision technologies as extensions of our body that enables us to live in a complicated and dynamic society that is increasingly digital. By partnering with other  multidisciplinary artist Psarra is continuously exploring ways to interpret the “invisible” data that connects various aspects of society and how to allow people to be able to interact with and understand that “invisible” space of the world by creating smart e-textiles and “use technology to be used in a more human way” (Psarra, in the lecture). One of her most recent works is called Cosmic Bitcasting a collaboration with  Cécile Lapoire to create a wearable cosmic ray detector which communicates the “invisible” information that is embedded in the space around us. The attire created would respond to the gamma radiation, X-rays, alpha and beta particles that are passing through the person’s body by using a series of light and vibrations.

 

The process of her work is documented on her website which shows the experimentation and coding of the Arduino modules she used to detect the rays and how she translates that data to soft circuits and finally to fabric.

Psarra’s work inspires us to rethink of technology, providing a different, often a sense of fictional sci-fi sensibility to her work that gets people who view and experience her work to be excited and engaged because working with textile is something very common in our daily lives. The integration and making them more digitally compatible will do more than just becoming an extension of our bodies, but also become a medium that connects us to the digital world and the digital world to the realm of the tangible.