// Ammar Hassonjee | lee chu
// section c
// ahassonj@andrew.cmu.edu | lrchu@andrew.cmu.edu
// final project
var mode = 0; // variable for cycling through frames
// variables for the beachBall ball scene
// choosing an initial point to launch the ball from
var ballx = 240;
var bally = 100;
var dir1 = 1; // direction of ball
var dir2 = 1; // direction of ball
var speedx = 1; // speed of the ball
var speedy = 0.5;
var size = 100; // size of the ball
// variables for rain scene
var raindrops = []; // array to store rain objects
var rainSpeed = 5; // tracking the speed of the rain
var increment = 0.01; //incrementing the rain values
var tone = 255; // the color of the lightning
var strweight = 30; // stroke weight of the lightning bolt
var cloudNumber; //
var cloudwidth;
var cloudheight;
var frame = 8; // keeping track of the frame count
var myCaptureDevice;
var px = [];
var py = [];
var theColorAtPxPy;
var theBrightnessOfTheColorAtPxPy;
var brightnessThreshold;
var darknessThreshold = 10;
// variables for determining silhouette
var borderX = [];
var borderY = [];
// variables for particles
var parties = [];
var ex = 20;
var why = 20;
function setup() {
createCanvas(480, 360);
myCaptureDevice = createCapture(VIDEO);
myCaptureDevice.size(480, 360); // attempt to size the camera.
myCaptureDevice.hide(); // this hides an unnecessary extra view.
// three variables declared to initialize the lighting function
var xi = random(40, 440);
var xii = random(30, 450);
var xiii = random(20, 460);
//bImage.resize(480, 360);
}
function isColor(c) {
return (c instanceof Array);
}
//--------------------------------------------------------------------
function draw() {
background(220);
myCaptureDevice.loadPixels();
image(myCaptureDevice, 0, -0, width, height); // draw the camera at 1:1 resolution
// ammar's code
if (mode === 0) {
initialScene();
}
if (mode === 1) {
// varying the clouds for each time the rain scene is called
// done before rainFall is called to ensure this code doesn't loop again
cloudNumber = random(3, 8);
cloudwidth = random(105, 140);
cloudheight = random(60, 95);
//calling the beach ball scene
ballSlap();
}
if (mode === 2) {
rainFall();
}
// lee's code
findBorder(); // finding silhouette of person
if (mode === 3) {
// particle effects
addParti();
updateAndDisplayParti();
removeParti();
}
if (mode === 4) {
// censoring effect
censor();
}
}
function mousePressed() {
mode = (mode + 1) % 5; // code to swtich between modes
}
//-------AMMAR'S CODE----------------------------------------------------------------------
// NOTE: the code works best if users are wearing dark clothing against a light background
function initialScene() { // initial scene for webcam text
textAlign(CENTER, CENTER);
textSize(15);
fill(100);
text("WELCOME TO AMMAR AND LEE'S WEBCAM MACHINE", width / 2, height / 2);
text("Press the mouse to cycle between scenes", width / 2, height * .8);
text("Press 'O' to increase darkness threshold", width / 2, height * .85);
text("Press 'P' to decrease darkness threshold", width / 2, height * .9);
text("Press 'R' to detect threshold automatically", width / 2, height * .95);
}
function ballSlap() {
// Creating the ball and setting its movement by changing
// ballx and bally variables
beachBall(ballx, bally, size);
ballx += dir1 * speedx;
bally += dir2 * speedy;
// Making ball bounce off the right
if (ballx >= width - size / 2 || ballx <= size / 2) {
dir1 = -dir1;
}
// Making the ball bounce off the top and bottom
if (bally < size / 2 || bally > height - size / 2) {
dir2 = -dir2;
}
var colorAtBall = myCaptureDevice.get(ballx, (bally + size / 2));
if (isColor(colorAtBall)) {
// setting the brightness to a variable and testing if it meets the
// the threshold values
brightnessAtBall = brightness(colorAtBall);
// if the ball hits the user's head (darker pixel) the ball will bounce up
if (brightnessAtBall < darknessThreshold & dir2 > 0) {
dir2 = -dir2;
speedy = random(0.5, 5);
speedyx = random(-4, 2);
}
}
}
function beachBall(x, y, diameter) { // function for creating rendering the beach ballx
var ballcolors = ["RED", "BLUE", "YELLOW"];
noStroke();
fill(255);
ellipse(x, y, diameter, diameter);
fill(ballcolors[0]);
arc(x, y, diameter, diameter, radians(30), radians(90));
fill(ballcolors[1]);
arc(x, y, diameter, diameter, radians(150), radians(210));
fill(ballcolors[2]);
arc(x, y, diameter, diameter, radians(270), radians(330));
fill(255);
ellipse(x, y, diameter / 5, diameter / 5);
}
function keyPressed() { // allowing the user to alter the beachball size with keys
// increasing the ball size if the a key is pressed
if (key === 'a' || key === 'A') {
if (size < 200) {
size += 10;
}
}
// decreasing the ball size if the d key is pressed
if (key === 'd' || key === 'D') {
if (size > 50) {
size -= 5;
}
}
// this code allows the user to edit the darkness threshold in order to fix bugs in the webcam
if (key === 'o' || key === 'O') {
if (darknessThreshold < 100) {
darknessThreshold += 2;
}
}
// decreasing the darkness threshold
if (key === 'p' || key === 'P') {
if (darknessThreshold > 10) {
darknessThreshold -= 2;
}
}
// finding threshold automatically
if (key ==='r' || key === 'R') {
findThreshold();
}
}
function rainFall() { // function for creating the rain scene
clouds(cloudNumber, cloudwidth, cloudheight); // calling the cloud function
// these lines of called call the function for the rain objects to make ensure
// the rain continuously falls
updateRain();
removeRain();
addRain();
// these if statements remap the speed of the rain to change as time passes
rainSpeed += increment;
if (rainSpeed >= 15) {
increment = -0.01;
}
if (rainSpeed <= 5) {
increment = 0.01;
}
// code to implement the lighting function at a random timeout
// this first if statement sets the lighting variables to an initial value
// and increments the frame variable
if (frameCount % 200 === 0) {
frame++;
tone = 255;
xi = random(40, 440);
xii = random(30, 450);
xiii = random(20, 460);
strweight = 30;
}
// a separate frame variable is used to make sure the lighning stays for multiple frames
if (frame % 3 === 0) {
// a random variable is used to make sure the lightning is called unpredictably
var chance = random(0, 2);
lightning(strweight, tone, xi, xii, xiii);
tone -= 4; // altering the lighting render values for aesthetic effect
strweight -= 1;
}
}
function makeRain(xpos, ypos) { // function for making the rain objects
var rain = {x: xpos, y: ypos, move: rainMove, display: rainDraw};
return rain;
}
function rainDraw() { // function for drawing the rain particles
noStroke();
fill(0, 0, 240);
push();
translate(this.x, this.y);
rotate(radians(15));
ellipse(0, 0, 2, 10);
pop();
}
function rainMove() { // moving the rain by the rain speed global variable
this.y += rainSpeed;
}
function updateRain() {
// for loop that calls train track objects and moves/displays them
for (var i = 0; i < raindrops.length; i++) {
var colorAtRain = myCaptureDevice.get(raindrops[i].x, raindrops[i].y);
raindrops[i].move();
if (isColor(colorAtRain)) {
// setting the brightness to a variable and testing if it meets the
// the threshold values
brightnessAtRain = brightness(colorAtRain);
// this ensures the rain stops falls on top of the figure in the WEBCAM
// by comparing to the pixel brightness
if (brightnessAtRain >= darknessThreshold) {
raindrops[i].display();
}
}
}
}
function addRain() { // function for adding rain objects to raindrops array
for (var i = 0; i < 6; i++) {
raindrops.push(makeRain(random(0, width), 0));
}
}
function removeRain() { // function for removing objects from the array
var rainKeep = [];
for (var i = 0; i < raindrops.length; i++) {
if (raindrops[i].y < 380) {
rainKeep.push(raindrops[i]);
}
}
raindrops = rainKeep; // reassigning the raindrops array to the duplicate array
}
// this function calls the lighting from a list of values that create polylines
function lightning(weight, brightness, xpos, xpos2, xpos3) {
noFill();
strokeWeight(weight);
stroke(brightness);
var x2 = xpos + random(-10, 10);
var x3 = xpos2 + random(-20, 25);
var x4 = xpos3 + random (-30, 40);
var y1 = random(height / 4, height / 3);
var y2 = random(height / 8 * 5, height * 2 / 3);
line(xpos, 0, x2, y1);
line(x2, y1, x3, y2);
line(x3, y2, x4, height);
}
// function that calls the clouds from a list of variables
function clouds(number, length, cheight) {
noStroke();
for (var i = 0; i < number + 1; i++) {
fill( map(i, 0, number, 100, 150));
var cloudx = map(i, 0, number, 0, width);
ellipse(cloudx, 0, length, cheight + 15 * (i % 3));
}
}
//-------LEE'S CODE----------------------------------------------------------------------
function findBorder() {
borderX = [];
borderY = [];
// finds the silhouette of person based on darkness threshold in intervals of 5
for (var i = 0; i < width; i += 5) {
for (var j = 0; j < height; j += 5) {
if (brightness(myCaptureDevice.get(i, j)) < darknessThreshold &
borderX.length < i / 5) {
borderX.push(i);
borderY.push(j);
}
}
}
}
function findThreshold() {
var brightest = 50;
var darkest = 50;
var xColors = [];
var xx = [];
// stores brightnesses of all colors along a line in the image displayed
for (var j = 0; j < width; j += 5) {
xColors.push(brightness(myCaptureDevice.get(j, height / 2)));
xx.push(j);
}
// finds brightest and darkest pixels
for (var k = 0; k < xColors.length; k ++) {
if (xColors[k] > xColors[brightest]) {
brightest = k;
}
if (xColors[k] < xColors[darkest]) {
darkest = k;
}
}
// elementary ratio to determine thresholds
brightnessThreshold = (xColors[brightest] - xColors[darkest]) / 3 + xColors[darkest];
darknessThreshold = (xColors[brightest] - xColors[darkest]) / 5 + xColors[darkest] - 10;
}
function addParti() {
// creating particles along top of person
var likelihood = 0.45;
for (var i = 0; i < borderX.length; i ++) {
if (random(1) < likelihood) {
parties.push(createParticle(borderX[i], borderY[i]));
}
}
}
function removeParti() {
// removes particle when size decreases below 1
var partiesToKeep = [];
for (var i = 0; i < parties.length; i ++) {
if (parties[i].size > 1) {
partiesToKeep.push(parties[i]);
}
}
parties = partiesToKeep;
}
function updateAndDisplayParti() {
for (var i = 0; i < parties.length; i ++) {
parties[i].move();
parties[i].display();
}
}
function createParticle(birthX, birthY) {
var parti = {x: birthX, y: birthY, size: round(random(5, 15)),
speed: -5, move: partiMove, display: partiDisplay,
color: myCaptureDevice.get(birthX, birthY)}
return parti;
}
function partiMove() {
// move particle and decrease size
this.y += this.speed;
this.size -= 1;
}
function partiDisplay() {
strokeWeight(0);
fill(this.color);
push();
translate(this.x, this.y);
rotate(millis() / 1000 * 2 * PI);
rectMode(CENTER);
rect(0, 0, this.size, this.size);
pop();
}
function censor() {
// divides area below silhouette into 25 by 25 squares and extracts colors
for (var i = 0; i < borderX.length; i += 5) {
for (var j = borderY[i]; j < height; j += 25) {
push();
translate(borderX[i], j);
rectMode(CENTER)
fill(myCaptureDevice.get(borderX[i], j));
rect(0, 0, 25, 25);
pop();
}
}
}
Ammar Hassonjee and Lee Chu collaborated on this webcam machine. It consists of four scenes: a beachball headbutting game, a rainy day, snapped by Thanos, and an unnecessary censorship. Click the mouse to cycle through the scenes. Press the keys O and P to increase or decrease the darkness threshold depending on the lighting of your setting. Press the key R to automatically detect the darkness threshold, although this process may not be perfect.
]]>I plan to collaborate with Ammar Hassonjee on the final project. We are thinking about creating a webcam overlay that could detect faces and project a filter over it, much like snapchat or instagram filters. Ideally, by detecting the colors in the frame of the webcam, we can identify and track a face. While tracking the face, sounds may be triggered by a specific action, and the entire filter could be dynamic depending on the user’s movements and actions. We will most definitely need to look into how face tracking generally works, as well.
]]>phonelovesyoutoo: database by Kate Hollenbach displays the feed of both the front and rear-facing cameras. The recordings are displayed at the original time of day, depicting a glimpse of the relationship between human, device, time, and space. This collection of videos really highlights the information we essentially give for free just by owning a device with so many sensors and recording devices.
Kate Hollenbach is an artist, programmer, and educator based in Chicago and Los Angeles. She explores interactive systems and technologies involving body, gesture, and physical space.
]]>// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 11
var islands = [];
var hills = [];
var x; // cloud x
// colors
var navajo = '#FFE4A3';
var lPink = '#FFAFBA';
var peachOrange = '#EDD397';
var mauve = '#E8A0A9';
var peach = '#FFEAB7';
var taupe = '#544244';
var puce = '#4C3C3E';
var middleYellow = '#F4B086';
function setup() {
createCanvas(480, 300);
// create an initial collection of islands
for (var i = 0; i < 2; i++){
var rx = random(40, width - 40);
islands[i] = makeIsland(rx);
}
for (var i = 0; i < 3; i++){
var rx2 = random(40, width - 40);
hills[i] = makeHill(rx2);
}
frameRate(10);
x = random(40, width - 40);
}
function draw() {
sky();
horizon();
// sun
fill(peachOrange);
ellipse(width / 2, height / 2, 100);
// islands
updateAndDisplayIslands();
removeIsland();
addIsland();
// cloud
cloud(x, 80);
x += 1;
if (x - 50 > width - 40) {
x = -10;
}
// hills
updateHills();
removeHill();
addHill();
// window
fill(0, 0, 50);
windowFrame(40, 60);
fill(75, 75, 100);
windowFrame(28, 55);
}
function cloud(x, y) {
strokeWeight(0);
fill(255);
rect(x, y, 20, 10);
rect(x + 10, y + 10, 20, 10);
rect(x - 10, y + 10, 20, 10);
rect(x + 20, y + 20, 20, 10);
rect(x - 10, y + 20, 20, 10);
rect(x - 30, y + 20, 20, 10);
rect(x - 30, y + 30, 20, 10);
rect(x - 50, y + 30, 20, 10);
rect(x - 20, y + 30, 20, 10);
rect(x + 10, y + 30, 20, 10);
rect(x + 30, y + 30, 20, 10);
rect(x - 20, y + 40, 30, 10);
}
function makeIsland(birthLocationX) {
var island = {x: birthLocationX, breadth: round(random(25, 50)),
speed: -1,
height: round(random(80, 150)),
move: islandMove,
display: islandDisplay}
return island;
}
function islandMove() {
this.x += this.speed;
}
function islandDisplay() {
// face
fill(middleYellow);
push();
translate(this.x, height - 150);
beginShape();
vertex(0.4 * this.breadth, -this.height / 2);
vertex(0.6 * this.breadth, -this.height / 2);
vertex(this.breadth, this.height / 2);
vertex(0.8 * this.breadth, this.height / 2 * 1.2);
vertex(0.4 * this.breadth, this.height / 2 * 1.2);
vertex(0.1 * this.breadth, this.height / 2);
endShape(CLOSE);
// shadow
fill(taupe);
beginShape();
vertex(0.4 * this.breadth, -this.height / 2);
vertex(0.1 * this.breadth, this.height / 2);
vertex(0.4 * this.breadth, this.height / 2 * 1.2);
vertex(0.35 * this.breadth, this.height / 2);
endShape(CLOSE);
pop();
}
function updateAndDisplayIslands() {
for (var i = 0; i < islands.length; i ++) {
islands[i].move();
islands[i].display();
}
}
function removeIsland() {
var islandsToKeep = [];
for (var j = 0; j < islands.length; j ++) {
if (islands[j].x + islands[j].breadth > 40) {
islandsToKeep.push(islands[j]);
}
}
islands = islandsToKeep;
}
function addIsland() {
var likelihood = 0.007;
if (random(1) < likelihood) {
islands.push(makeIsland(width));
}
}
function makeHill(x) {
h = round(random(150, 200));
var spike = {x: x, breadth: round(random(25, 50)),
speed: -3,
height: round(random(200, 250)),
move: hillMove,
display: hillDisplay}
return spike;
}
function hillMove() {
this.x += this.speed;
}
function hillDisplay() {
fill(peach);
push();
translate(this.x, height - 50);
beginShape();
vertex(0, 0);
vertex(this.breadth, 0);
vertex(0.9 * this.breadth, -this.height * 0.25);
vertex(0.7 * this.breadth, -this.height / 2);
vertex(0.6 * this.breadth, -this.height);
vertex(0.4 * this.breadth, -this.height);
vertex(0.2 * this.breadth, -this.height / 2);
endShape(CLOSE);
pop();
}
function updateHills() {
for (var i = 0; i < hills.length; i ++) {
hills[i].move();
hills[i].display();
}
}
function removeHill() {
var hillsToKeep = [];
for (var j = 0; j < hills.length; j ++) {
if (hills[j].x + hills[j].breadth > 40) {
hillsToKeep.push(hills[j]);
}
}
hills = hillsToKeep;
}
function addHill() {
var likelihood = 0.01;
if (random(1) < likelihood) {
hills.push(makeHill(width));
}
}
function windowFrame(r, f) {
strokeWeight(0);
// top left
beginShape();
vertex(0, 0);
vertex(100, 0);
vertex(100, r);
bezierVertex(f, r, r, f, r, 100);
vertex(0, 100);
endShape(CLOSE);
rect(100, 0, width - 200, r);
// top right
beginShape();
vertex(0, height);
vertex(100, height);
vertex(100, height - r);
bezierVertex(f, height - r, r, height - f, r, height - 100);
vertex(0, height - 100);
endShape(CLOSE);
rect(width - r, 100, r, height - 200);
// bottom right
beginShape();
vertex(width, 0);
vertex(width - 100, 0);
vertex(width - 100, r);
bezierVertex(width - f, r, width - r, f, width - r, 100);
vertex(width, 100);
endShape(CLOSE);
rect(100, height - r, width - 200, r);
// bottom left
beginShape();
vertex(width, height);
vertex(width - 100, height);
vertex(width - 100, height - r);
bezierVertex(width - f, height - r, width - r, height - f, width - r, height - 100);
vertex(width, height - 100);
endShape(CLOSE);
rect(0, 100, r, height - 200);
// lines
stroke(0);
strokeWeight(0.5);
line(0, height - 20, width, height - 20);
strokeWeight(0.25);
}
function sky() {
for (var y = 40; y < height - 69; y ++) {
var interval = map(y, 40, height - 69, 0, 1);
var c = lerpColor(color(mauve), color(peachOrange), interval);
strokeWeight(1);
stroke(c);
line(0, y, width, y);
}
}
function horizon(){
strokeWeight(0);
fill(navajo);
beginShape();
vertex(0, height - 70);
vertex(width, height - 70);
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
I aimed to emulate the view from inside of a train outwards into a scene with floating islands.
]]>
// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 10
var ampTog;
var freqTog;
var recordSpinL;
var recordSpinR;
var prevR;
var play;
var playToggle;
var scratch;
var scratch2;
var buildup;
var drop;
var volume;
var visualImage;
var px = [];
var py = [];
var dx = [];
var dy = [];
function preload() {
// load sounds
scratch = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/scratch.wav');
scratch.setVolume(0.08);
scratch2 = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/scratch2.wav');
scratch2.setVolume(0.2);
buildup = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/buildup.wav');
buildup.setVolume(0.5);
drop = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/wheredyago.wav');
drop.setVolume(0.3);
// load visuals
visualImage = loadImage('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/visual.jpg');
}
function setup() {
createCanvas(500, 500);
recordSpinL = 0; recordSpinR = 0;
volume = 0.2;
playFill = 'red';
playToggle = 0;
visualImage.resize(width, height);
visualImage.loadPixels();
// visuals setup
for (var i = 0; i < 150; i ++) {
px.push(random(width));
py.push(random(height));
dx.push(1);
dy.push(1);
}
}
function draw() {
if (drop.isPlaying() == false) {
background(255, 255, 220);
}
else {
for (var i = 0; i < px.length; i ++) {
var ix = constrain(floor(px[i]), 0, width-1);
var iy = constrain(floor(py[i]), 0, height-1);
var theColorAtLocationXY = visualImage.get(ix, iy);
noStroke();
fill(theColorAtLocationXY);
rectMode(CENTER);
rect(px[i], py[i], 30, 30);
// random movement
px[i] += dx[i] * random(-2, 10);
py[i] += dy[i] * random(-2, 10);
// keeping painters on the canvas
if (px[i] > width) {
px[i] = 0;
}
else if (px[i] < 0) {
px[i] = width;
}
if (py[i] > height) {
py[i] = 0;
}
else if (py[i] < 0) {
py[i] = height;
}
}
}
// sound board
soundBoard();
dial(width / 2 - 30, 2 * height / 3 - 5);
dial(width / 2 + 30, 2 * height / 3 - 5);
// play button
fill(45);
rect(width / 2 + 4, 3 * height / 4 + 4, 30, 20);
fill(playFill);
stroke('white');
strokeWeight(0.5);
rect(width / 2, 3 * height / 4, 30, 20);
fill('white');
triangle(width / 2 - 5, 3 * height / 4 - 4, width / 2 - 5, 3 * height / 4 + 4,
width / 2 + 5, 3 * height / 4);
// basssss
fill(45);
strokeWeight(0);
ellipse(width / 2 + 4, 3 * height / 4 + 60 + 4, 40);
strokeWeight(0.5);
fill(100);
if (buildup.isPlaying()) {
fill('red');
}
ellipse(width / 2, 3 * height / 4 + 60, 40);
strokeWeight(2);
text('DROP', width / 2 - 17, 3 * height / 4 + 65);
strokeWeight(0);
// record
disc(width / 4, 3 * width / 4 + 10, recordSpinL);
disc(3 * width / 4, 3 * width / 4 + 10, recordSpinR);
if (play == 1) {
recordSpinL += PI / 100;
recordSpinR += PI / 100;
}
}
function disc(x, y, r) {
// shadow
push();
translate(x + 5, y + 5);
fill(25);
ellipse(0, 0, 155);
pop();
// record
push();
translate(x, y);
rotate(r);
fill(25);
stroke(120);
strokeWeight(3);
ellipse(0, 0, 155);
fill(30, 40, 185);
strokeWeight(1);
ellipse(0, 0, 40);
fill(100);
strokeWeight(0);
ellipse(0, 0, 6);
// scratches
noFill();
strokeWeight(0.3);
arc(0, 0, 140, 140, 0, PI / 4);
arc(0, 0, 120, 120, PI / 2, 5 * PI / 4);
strokeWeight(0.25);
arc(0, 0, 75, 75, 0, PI / 2);
arc(0, 0, 85, 85, PI, 7 * PI / 4);
// more scratches
strokeWeight(0.75);
line(0, 30, 0, 66);
line(-30, 0, -70, 0);
strokeWeight(0.35);
line(20, -20, 45, -45);
line(22, 22, 48, 48);
pop();
}
function dial(x, y, r) {
// shadow
push();
translate(x + 5, y + 5);
fill(50);
strokeWeight(0);
ellipse(0, 0, 35);
pop();
// knob
push();
translate(x, y);
rotate(0);
fill(100);
stroke(180);
strokeWeight(0.75);
ellipse(0, 0, 35);
// pointer
stroke('white');
strokeWeight(1);
line(0, 0, 0, -35 / 2);
pop();
}
function soundBoard() {
rectMode(CENTER);
strokeWeight(0);
// shadow
fill(75);
rect(width / 2 + 10, 4 * height / 5 - 20 + 10, 7 * width / 8, height / 2.5, 20);
// red
fill(175, 50, 50);
rect(width / 2, 4 * height / 5 - 20, 7 * width / 8, height / 2.5, 20);
}
function mousePressed() {
// toggles spinning records
play = 1;
// left scratch sound
if (dist(mouseX, mouseY, width / 4, 3 * width / 4 + 10) < 77.5) {
recordSpinL -= PI / 4;
if (scratch.isPlaying()) {
scratch.stop();
}
scratch.play();
}
// right scratch sound
if (dist(mouseX, mouseY, 3 * width / 4, 3 * width / 4 + 10) < 77.5) {
recordSpinR-= PI / 4;
if (scratch2.isPlaying()) {
scratch2.stop();
}
scratch2.play();
}
// play button
if (dist(mouseX, mouseY, width / 2, 3 * height / 4) < 20) {
playFill = 'green';
if (buildup.isPlaying()) {
buildup.stop();
}
buildup.play();
}
// bass button
if (dist(mouseX, mouseY, width / 2, 3 * height / 4 + 60) < 20 & buildup.isPlaying()) {
if (buildup.isPlaying()) {
buildup.stop();
}
if (drop.isPlaying()) {
drop.stop();
}
drop.play();
}
}
In this primitive virtual audio mixer, I included two dj scratch sounds on each disc, a play button to activate the build up, and a button which drops the bass c:
]]>Porter Robinson, renown producer of electronic music, is also well known for his visuals at his live performances. Not only do the visuals need to be visually stunning, but they also need to correlate with and move with the music logically.
Porter aimed to bring beautiful and immersive sounds and visions to a genre of music too often associated with heavy bass drops. Porter sought to transport his audiences into hyper-real, neon-toned worlds of anime and MMORPG’s. These videogame-esque worlds unfold before you to bring back that childhood escapism into fantasy and fictional worlds.
]]>An interesting post I saw was Mike’s looking outwards 09, about Tai’s post, about Refik Anadol, a media artist from Turkey, who currently lives and works in Los Angeles. He thoroughly explores the relationship between architecture and media arts, merging machine learning and visual/audio experiences. He creates installations, but has also projected his work onto existing architecture.
As Mike had mentioned, what’s most impressive is the rigorous amount of effort to perfectly map projections onto a piece of irregular architecture, such as the Disney Hall in Los Angeles. Look at some of his work here.
// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 09
var underlyingImage;
var px = [];
var py = [];
var directionX = [];
var directionY = [];
var ix = [];
var iy = [];
function preload() {
var myImageURL = "https://i.imgur.com/QpJ7uJf.jpg";
underlyingImage = loadImage(myImageURL);
}
function setup() {
createCanvas(600, 300);
background(0);
underlyingImage.loadPixels();
frameRate(60);
// starting arrays for painters
px.push(random(width));
py.push(random(height));
directionX.push(1);
directionY.push(1);
}
function draw() {
underlyingImage.resize(width, height);
// looping for individual painters
for (i = 0; i < px.length; i ++) {
ix = constrain(floor(px[i]), 0, width-1);
iy = constrain(floor(py[i]), 0, height-1);
var theColorAtLocationXY = underlyingImage.get(ix, iy);
noStroke();
fill(theColorAtLocationXY);
rectMode(CENTER);
rect(px[i], py[i], 10, 10);
// random movement
px[i] += directionX[i] * random(-2, 10);
py[i] += directionY[i] * random(-2, 10);
// keeping painters on the canvas
if (px[i] > width) {
px[i] = 0;
}
else if (px[i] < 0) {
px[i] = width;
}
if (py[i] > height) {
py[i] = 0;
}
else if (py[i] < 0) {
py[i] = height;
}
}
}
// adding painters with click
function mousePressed() {
px.push(random(width));
py.push(random(height));
directionX.push(1);
directionY.push(random(-1, 1, 2));
}
I miss Heath Ledger. I had wanted to create a bunch of little rectangular painters which make their way across the canvas.
Nervous System is a design studio that works at the intersection of science, art, and tech. Founded in 2007 by Jesse Louis-Rosenburg and Jessica Rosenkrantz, Nervous System focuses on creating generative online applications in which users can co-create products resulting in infinite design possibilities for homeware, lighting, jewelry, and most fascinating, clothing. Some of their simpler 3-D designs can also be downloaded and printed at home. Check out their website here.
One of their more interesting designs is of a parametric dress which is fully 3-D printed using smaller modules that can fold and make the dress malleable and form-fitting. In addition, they implemented an application which accounts for body shape and size so that almost anyone can rock this dress.
dress in motion
]]>gun death visualization by Periscope for 2013
Kim Ree, co-founder of a data visualization firm Periscopic, is probably best known for her work in visualizing gun deaths in 2010 and 2013. The diagram above illustrates the overwhelming amount of deaths from U.S. owned guns. The orange strokes depict the actual lifespans of gun victims, and the gray projects an estimated lifespan according to the U.S. distribution of deaths and likely causes of death. By also counting the amount of hours that these victims were robbed of, the data is much more impactful than if it were simply a death count. Play with the visualizer here.
Not speaking in relation to this particular piece, but I think the most interesting aspect about data visualization is that it can be depicted in a way to sway or even change one’s impressions of anything.
]]>