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