5Square — Final Project, PComp + ICM

Computational Media, Physical Computing

5Square

Make your own Music

Collaborators:

Amena Hayat

Max Horwich

Arnav Wagh

Please click the link to go to my previous blog post for the final project proposal:

GESTURAL GRAPHIC INTERFACE

 

 This project consists of
1. code in Tone.js library
2. animations for visuals
3. a glove that adds effects to music
———————————————————————————————–

Tone.js is a framework for creating interactive music in the browser. It provides advanced scheduling capabilities, synths and effects, and intuitive musical abstractions built on top of the Web Audio API.

We used Tone.js to create a musical interface that is easy, fun, interactive and engaging. The intended audience is a non-musician who wants to create music.

CODE

kickOn = false;
snareOn = false;
pianoOn = false;
bassOn = false;

//var upstate = false;
cChordPlaying = false;
fChordPlaying = false;
gChordPlaying = false;
amChordPlaying = false;

cBassPlaying = false;
fBassPlaying = false;
gBassPlaying = false;
amBassPlaying = false;

var serial;
var flex1 = 0,
flex2 = 0,
flex3 = 0;
flex4 = 0;

var pianoAnimation = false;

//KICK SOUND DEFINED
var kick = new Tone.MembraneSynth({
“envelope”: {
“sustain”: 0,
“attack”: 0.02,
“decay”: 0.8
},
“octaves”: 10
}).toMaster();

//KICK LOOP SET
var kickPart = new Tone.Loop(function(time) {
kick.triggerAttack(“C2”);
}, “2n”);

//SNARE FILTER
var snareFilter = new Tone.AutoFilter({
frequency: 1,
type: “sine”,
depth: 1,
baseFrequency: 400,
octaves: 2.6,
filter: {
type: “bandpass”,
rolloff: -12,
Q: 1
}
}).toMaster();

//SNARE SOUND DEFINED
var snare = new Tone.MetalSynth({
volume: -10,
frequency: 60,
envelope: {
attack: 0.001,
decay: 0.4,
release: 0.2
},
harmonicity: 5.1,
modulationIndex: 1,
resonance: 800,
octaves: 1.5
}).connect(snareFilter);

//SNARE LOOP SET
var snarePart = new Tone.Sequence(function(time, freq) {
snare.frequency.setValueAtTime(freq, time, Math.random() * 0.5 + 0.5);
snare.triggerAttack(time);
}, [null, 350, null, 350], “2n”);

//PIANO DELAY
var pianoDelay = new Tone.PingPongDelay({
“delayTime”: “4t”,
“maxDelayTime”: 2,
“wet”: .3,
“feedback”: .1
}).toMaster();

//PIANO TONE DEFINED
var piano = new Tone.MonoSynth(4, Tone.Synth, {
“volume”: -7,
“oscillator”: {
“partials”: [1, 2, 1],
},
“envelope”: {
“attack”: 0.001,
“decay”: 0.1,
“sustain”: 0.3,
“release”: 1
},
“portamento”: 0.001
}).connect(pianoDelay);

//PIANO CHORDS DEFINED
/*
var cChord = [“C4”, [“E4”, “G4”]];
var gChord = [[“B3”, “D4”], “G4”];
var amChord = [[“C4”, “E4”], “A4”];
var fChord = [[“C4”], “F4”, [“A4”]];
*/
var cChord = [“C4”, “E4”, “G4”];
var gChord = [“B3”, “D4”, “G4”];
var amChord = [“C4”, “E4”, “A4”];
var fChord = [“C4”, “F4”, “A4”];

var ellipseCoord = {};

//PIANO LOOP SET

var pianoPart = new Tone.Sequence(function(time, note) {
piano.triggerAttackRelease(note, “16n”, time);
//SEQUENCE OF CHORDS
}, [cChord]);
//pianoPart.probability = 0.5;

//Bass FFT & waveform
var fft = new Tone.FFT(32);
var spectrum = new Tone.Waveform(1024);

var bassDist = new Tone.Distortion({
“distortion”: 0.4,
“oversample”: ‘2x’
}).connect(spectrum).toMaster();

//BASS TONE DEFINED
var bass = new Tone.MonoSynth({
“volume”: -10,
“envelope”: {
“attack”: 0.1,
“decay”: 0.3,
“release”: 2,
},
“filterEnvelope”: {
“attack”: 0.001,
“decay”: 0.01,
“sustain”: 0.5,
“baseFrequency”: 200,
“octaves”: 2.6
}
}).connect(bassDist);

//BASS LOOP SET
var bassPart = new Tone.Sequence(function(time, note) {
bass.triggerAttackRelease(note, “16n”, time);
//SEQUENCE OF BASS NOTES
}, [“C2”]);
//bassPart.probability = 0.5;

//LEAD DELAY
var leadDelay = new Tone.PingPongDelay({
“delayTime”: “8n”,
“maxDelayTime”: 1,
“feedback”: 0.82,
“wet”: .40

}).toMaster();

//LEAD TONE DEFINED
var leadPaint = new Tone.PolySynth({
“volume”: -10,
“oscillator”: {
“type”: “square”
},
“envelope”: {
“attack”: 0.2
},
“portamento”: 0.05

}).connect(leadDelay);

//FX SENDS
var delayKickSend = kick.send(“delayKick”, -Infinity);
var delaySnareSend = snare.send(“delaySnare”, -Infinity);
var crushSend = piano.send(“crush”, -Infinity);
var chebySend = bass.send(“cheby”, -Infinity);

var delayKick = new Tone.FeedbackDelay(“4t”, 0.38)
.receive(“delayKick”)
.toMaster();
var delaySnare = new Tone.FeedbackDelay(“8t”, 0.25)
.receive(“delaySnare”)
.toMaster();
var crushPiano = new Tone.BitCrusher(4)
.receive(“crush”)
.toMaster();
var chebyBass = new Tone.Chebyshev(10)
.receive(“cheby”)
.toMaster();

//SLOWEST POSSIBLE TEMPO
//ALL OTHERS ARE SET AS MULTIPLE OF THIS
//
Tone.Transport.bpm.value = 60;

//HIT IT!!!
Tone.Transport.start();

//—————————————————————-
//BEGINNING OF SETUP

function setup() {
createCanvas(windowWidth, windowWidth/2);
background(230);

serial = new p5.SerialPort();
serial.on(‘list’, printList);
serial.on(‘data’, serialEvent);
serial.list();
serial.open(“/dev/cu.usbmodem1431”);
//ALWAYS CHECK IF USB PORT IS CORRECT FOR YOUR PERSONAL LAPTOP

sliderKick = createSlider(1, 6, 2);
sliderKick.position(5, height + 20);
sliderKick.size(width / 4 – 10, 10);
sliderBass = createSlider(1, 4, 1);
sliderBass.position(width / 4 + 5, height + 40);
sliderBass.size(width / 4 – 10, 10);
sliderPiano = createSlider(1, 4, 1);
sliderPiano.position(width / 4 + 5, height + 20);
sliderPiano.size(width / 4 – 10, 10);
sliderSnare = createSlider(1, 6, 2);
sliderSnare.position(5, height + 40);
sliderSnare.size(width / 4 – 10, 10);
//leadDelayPaint = createSlider(1,6,1);

sliderFX1 = createSlider(-100,0,-100);
sliderFX1.position(5, height+60);
sliderFX1.size(width/4-10, 10);
sliderFX2 = createSlider(-100,0,-100);
sliderFX2.position(5, height+80);
sliderFX2.size(width/4-10, 10);
sliderFX3 = createSlider(-100,0,-100);
sliderFX3.position(5, height+100);
sliderFX3.size(width/4-10, 10);
sliderFX4 = createSlider(-100,0,-100);
sliderFX4.position(5, height+120);
sliderFX4.size(width/4-10, 10);

ellipseCoord.c = [width/16, (height/2)*0.2, width/8, (height/2)*0.2, width/5.33, (height/2)*0.2];
ellipseCoord.g = [width/16, (height/2)*0.4, width/8, (height/2)*0.4, width/5.33, (height/2)*0.4];
ellipseCoord.am = [width/16, (height/2)*0.6, width/8, (height/2)*0.6, width/5.33, (height/2)*0.6];
ellipseCoord.f = [width/16, (height/2)*0.8, width/8, (height/2)*0.8, width/5.33, (height/2)*0.8];

// ellipseCoord.c = [80, 80, 160, 80, 240, 80];
// ellipseCoord.g = [80, 80 + 55, 160, 80 + 55, 240, 80 + 55];
// ellipseCoord.am = [80, 80 + 110, 160, 80 + 110, 240, 80 + 110];
// ellipseCoord.f = [80, 80 + 165, 160, 80 + 165, 240, 80 + 165];

}

//END OF SETUP
//—————————————————————-
//BEGIN OF DRAW
function draw() {

var kickPulse = kickPart.progress;
var snarePulse = snarePart.progress;
var pianoPulse = pianoPart.progress;
var bassPulse = bassPart.progress;
var loopstate = pianoPart.state;

var pp = map(pianoPulse, 0, 1, 0.5, 1.1);
var pt = map(snarePulse, 0, 0.3, 1, 1.2);
var pg = map(snarePulse, 0, 1, 1, 0.5);
var pf = map(snarePulse, 0, 1, 1, 0.2);

kickSwellOuter = map(kickPulse, 0, 1, 0, (width / 4.57)/35);
kickSwellMiddle = map(kickPulse, 0, 1, 0, (width / 5.33)/9);
kickSwellInner = map(kickPulse, 0, 1, 0, (width / 6.66)/3);

alphaOuter = map(kickSwellOuter, 0, 5, 50, 20);
alphaMiddle = map(kickSwellMiddle, 0, 16.7, 90, 30);

var wave = spectrum.getValue();
var fftwave = fft.getValue();

// fill(0);
// stroke(0);
// strokeWeight(2)
// //rect(width / 4, 0, width / 4, height / 2);
// rect(0,width,0,height);

//—————————–ANimations———————————
//KICK CIRCLE
push();
translate(0, 0);
fill(225);
noStroke();
rect(0, 0, width / 4, height / 2);
noFill();
ellipseMode(CENTER);

stroke(135, 206, 250, alphaOuter);
strokeWeight(2);
ellipse(width / 8, height / 4, width / 4.57 + (kickSwellOuter * -1));

stroke(135, 206, 250, alphaMiddle);
strokeWeight(2);
ellipse(width / 8, height / 4, width / 5.33 + (kickSwellMiddle * -1));

stroke(135, 206, 250);
strokeWeight(2);
ellipse(width / 8, height / 4, width / 6.66 + (kickSwellInner * -1));
//print(width/4-80);

pop();

//BASS SQUARE
beginShape();
push();
translate(width * 3 / 8, height * 3 / 4);
noStroke();
fill(225);
rect(0 – (width / 8), 0 – (height / 4), width / 4, height / 2)
//rect(0, 0, width / 4, height / 2)
beginShape();
noFill();
stroke(255, 100, 0); // waveform is red
strokeWeight(2);
rectMode(CENTER)
for (var i = 0; i < wave.length; i += 600) {
//var a = map(i, 0, wave.length, -3, 3);
var b = map(wave[i], -1, 1, -40, 40);
rect(0, 0, width / 6.15 + b, height / 3.07 + b);
}
pop();
endShape();

//PIANO TRIANGLE
push();
translate(width * 1 / 8, height/1.25);
print(height*1.25)
noStroke();
fill(225);
rect(0 – (width / 8), 0 – (height*0.25+height*0.05), width / 4, height / 2)
scale(pg);
stroke(255);
point(0, 0)
noFill();
strokeWeight(1);
triangle(width/-11.42, height/9.83, 0, height/-4.917, width/11.42, height/9.83);
//triangle(-70, 40.67, 0, -81.35, 70, 40.67); //for 800/400
pop();

//SLIDERS FOR TEMPO OF DIFFERENT INSTRUMENTS
//PLAYBACK RATE MULTIPLIES TEMPO FOR THAT PART
kickPart.playbackRate = sliderKick.value();
snarePart.playbackRate = sliderSnare.value();

// sliderKick.value(map(flex1, 0, 250, 1, 6));
// sliderSnare.value(map(flex1, 0, 250, 1, 6));
// sliderPiano.value(map(flex2, 0, 250, 1, 4));
// sliderBass.value(map(flex2, 0, 250, 1, 4));
// a = map(flex3, 0, 250, 0.1, 0.9);

push();
translate(width*0.25,0);
fill(225);
noStroke(0);
rect(0,0,width*0.25,height/2);
pop();

if (pianoAnimation == true) {
animateEllipseC(pianoPulse);
}
if (pianoAnimation == true) {
animateEllipseG(pianoPulse);
}
if (pianoAnimation == true) {
animateEllipseAM(pianoPulse);
}
if (pianoAnimation == true) {
animateEllipseF(pianoPulse);
}

//PIANO CHORD SLIDER
if (sliderPiano.value() == 1) {
if (cChordPlaying == false) {
//console.log(“inside value 1”);
pianoPart.removeAll();
pianoPart.add(0, cChord);
cChordPlaying = true;
fChordPlaying = false;
gChordPlaying = false;
amChordPlaying = false;
}
} else if (sliderPiano.value() == 2) {
if (fChordPlaying == false) {
pianoPart.removeAll();
pianoPart.add(0, fChord);
cChordPlaying = false;
fChordPlaying = true;
gChordPlaying = false;
amChordPlaying = false;
}
} else if (sliderPiano.value() == 3) {
if (gChordPlaying == false) {
pianoPart.removeAll();
pianoPart.add(0, gChord);
cChordPlaying = false;
fChordPlaying = false;
gChordPlaying = true;
amChordPlaying = false;
}
} else if (sliderPiano.value() == 4) {
if (amChordPlaying == false) {
pianoPart.removeAll();
pianoPart.add(0, amChord);
cChordPlaying = false;
fChordPlaying = false;
gChordPlaying = false;
amChordPlaying = true;
}
}

//BASS NOTE SLIDER
if (sliderBass.value() == 1) {
if (cBassPlaying == false) {
bassPart.remove(0);
bassPart.add(0, “C2”);
cBassPlaying = true;
fBassPlaying = false;
gBassPlaying = false;
amBassPlaying = false;
}
} else if (sliderBass.value() == 2) {
if (fBassPlaying == false) {
bassPart.remove(0);
bassPart.add(0, “F2”);
cBassBassPlaying = false;
fBassBassPlaying = true;
gBassBassPlaying = false;
amBassBassPlaying = false;
}
} else if (sliderBass.value() == 3) {
if (gBassPlaying == false) {
bassPart.remove(0);
bassPart.add(0, “G1”);
cBassPlaying = false;
fBassPlaying = false;
gBassPlaying = true;
amBassPlaying = false;
}
} else if (sliderBass.value() == 4) {
if (amBassPlaying == false) {
bassPart.remove(0);
bassPart.add(0, “A1”);
cBassPlaying = false;
fBassPlaying = false;
gBassPlaying = false;
amBassPlaying = true;
}
}

//FLEXER FX
delayKickSend.gain.value = sliderFX1.value();
delaySnareSend.gain.value = sliderFX2.value();
crushSend.gain.value = sliderFX3.value();
chebySend.gain.value = sliderFX4.value();

sliderFX1.value(map(flex1,310,400,-100,0));
sliderFX2.value(map(flex2,270,390,-100,0));
sliderFX3.value(map(flex3,230,340,-100,0));
sliderFX4.value(map(flex4,300,370,-100,0));

//RIGHT SIDE DRAWING
if (mouseX > width / 2 && mouseX < width &&
mouseY > 0 && mouseY < width) {
if (mouseIsPressed) {
for (i = 0; i < 15; i++) {
noStroke();
fill(255, 0, 0);
//fill(255, 100 + i * 3, 100 + i * 5, 255 / i);
ellipse(mouseX, mouseY, i, i);
}
}

//SLOW FADE
fill(230,15);
noStroke();
rect(width / 2, 0, width / 2, height);

//ERASE DRAWING AND KILL LEAD
if (keyIsPressed) {
fill(230);
rect(width / 2, 0, width / 2, height);
leadPaint.triggerRelease();
}

}
}

//END OF DRAW MODE
//—————————————-
//BEGINNING OF FUNCTIONS

function animateEllipseC(pianoPulse) {
//console.log(“inside chordAnimation”);
if (sliderPiano.value() == 1) {
var coord = ellipseCoord.c;
//console.log(coord);
var index = 0;
if (pianoPulse > 0 && pianoPulse < 0.3) {
index = 0;
} else if (pianoPulse > 0.3 && pianoPulse < 0.6) {
index = 2;
} else if (pianoPulse > 0.6) {
index = 4;
}
push();
translate(width / 4, 0)
point(0, 0)
fill(200, 50)
fill(124, 225, 0, 200);
noStroke();
var pp = map(pianoPulse, 0, 1, 0.5, 1.1);
ellipse(coord[index], coord[index + 1], pp*60, pp*60);
pop();
}
}

function animateEllipseF(pianoPulse) {
//console.log(“inside chordAnimation”);
if (sliderPiano.value() == 2) {
var coord = ellipseCoord.f;
//console.log(coord);
var index = 0;
if (pianoPulse > 0 && pianoPulse < 0.3) {
index = 0;
} else if (pianoPulse > 0.3 && pianoPulse < 0.6) {
index = 2;
} else if (pianoPulse > 0.6) {
index = 4;
}
push();
translate(width / 4, 0)
point(0, 0)
fill(200, 50)
fill(140, 180, 121, 200);
noStroke();
var pp = map(pianoPulse, 0, 1, 0.5, 1.1);
ellipse(coord[index], coord[index + 1], pp*80, pp*80);
pop();
}
}

function animateEllipseG(pianoPulse) {
//console.log(“inside chordAnimation”);
if (sliderPiano.value() == 3) {
var coord = ellipseCoord.g;
//console.log(coord);
var index = 0;
if (pianoPulse > 0 && pianoPulse < 0.3) {
index = 0;
} else if (pianoPulse > 0.3 && pianoPulse < 0.6) {
index = 2;
} else if (pianoPulse > 0.6) {
index = 4;
}
push();
translate(width / 4, 0)
point(0, 0)
fill(200, 50)
fill(100, 120, 190, 200);
noStroke();
var pp = map(pianoPulse, 0, 1, 0.5, 1.1);
ellipse(coord[index], coord[index + 1], pp*40, pp*40);
pop();
}
}

function animateEllipseAM(pianoPulse) {
//console.log(“inside chordAnimation”);
if (sliderPiano.value() == 4) {
var coord = ellipseCoord.am;
//console.log(coord);
var index = 0;
if (pianoPulse > 0 && pianoPulse < 0.3) {
index = 0;
} else if (pianoPulse > 0.3 && pianoPulse < 0.6) {
index = 2;
} else if (pianoPulse > 0.6) {
index = 4;
}
push();
translate(width / 4, 0)
point(0, 0)
fill(200, 50)
fill(90, 100, 60, 200);
noStroke();
var pp = map(pianoPulse, 0, 1, 0.5, 1.1);
ellipse(coord[index], coord[index + 1], pp*50, pp*50);
pop();
}
}

//DRAG TO PLAY FUNCTION
function touchMoved() {
var paintNote = [“C4”, “E4”, “G4”, “A4”, “C5”, “E5”, “G5”, “A5”, “C6”]

//right side of canvas
if (mouseX > width / 2 && mouseX < width &&
mouseY > 0 && mouseY < height) {

//————NOTE GRID!!!
//column1
if (mouseX > width / 2 && mouseX < width * 5 / 8 &&
mouseY < height && mouseY > height * 3 / 4) {
leadPaint.triggerAttackRelease(paintNote[0], “8n”);
} else if (mouseX > width / 2 && mouseX < width * 5 / 8 &&
mouseY < height * 3 / 4 && mouseY > height / 2) {
leadPaint.triggerAttackRelease(paintNote[1], “8n”);
} else if (mouseX > width / 2 && mouseX < width * 5 / 8 &&
mouseY < height / 2 && mouseY > height / 4) {
leadPaint.triggerAttackRelease(paintNote[2], “8n”);
} else if (mouseX > width / 2 && mouseX < width * 5 / 8 &&
mouseY < height / 2 && mouseY > 0) {
leadPaint.triggerAttackRelease(paintNote[3], “8n”);
//column2
} else if (mouseX > width * 5 / 8 && mouseX < width * 3 / 4 &&
mouseY < height && mouseY > height * 3 / 4) {
leadPaint.triggerAttackRelease(paintNote[1], “8n”);
} else if (mouseX > width * 5 / 8 && mouseX < width * 3 / 4 &&
mouseY < height * 3 / 4 && mouseY > height / 2) {
leadPaint.triggerAttackRelease(paintNote[2], “8n”);
} else if (mouseX > width * 5 / 8 && mouseX < width * 3 / 4 &&
mouseY < height / 2 && mouseY > height / 4) {
leadPaint.triggerAttackRelease(paintNote[3], “8n”);
} else if (mouseX > width * 5 / 8 && mouseX < width * 3 / 4 &&
mouseY < height / 4 && mouseY > 0) {
leadPaint.triggerAttackRelease(paintNote[4], “8n”);
//column3
} else if (mouseX > width * 3 / 4 && mouseX < width * 7 / 8 &&
mouseY < height && mouseY > height * 3 / 4) {
leadPaint.triggerAttackRelease(paintNote[2], “8n”);
} else if (mouseX > width * 3 / 4 && mouseX < width * 7 / 8 &&
mouseY < height * 3 / 4 && mouseY > height / 2) {
leadPaint.triggerAttackRelease(paintNote[3], “8n”);
} else if (mouseX > width * 3 / 4 && mouseX < width * 7 / 8 &&
mouseY < height / 2 && mouseY > height / 4) {
leadPaint.triggerAttackRelease(paintNote[4], “8n”);
} else if (mouseX > width * 3 / 4 && mouseX < width * 7 / 8 &&
mouseY < height / 4 && mouseY > 0) {
leadPaint.triggerAttackRelease(paintNote[5], “8n”);
//column4
} else if (mouseX > width * 7 / 8 && mouseX < width &&
mouseY < height && mouseY > height * 3 / 4) {
leadPaint.triggerAttackRelease(paintNote[3], “8n”);
} else if (mouseX > width * 7 / 8 && mouseX < width &&
mouseY < height * 3 / 4 && mouseY > height / 2) {
leadPaint.triggerAttackRelease(paintNote[4], “8n”);
} else if (mouseX > width * 7 / 8 && mouseX < width &&
mouseY < height / 2 && mouseY > height / 4) {
leadPaint.triggerAttackRelease(paintNote[5], “8n”);
} else if (mouseX > width * 7 / 8 && mouseX < width &&
mouseY < height / 4 && mouseY > 0) {
leadPaint.triggerAttackRelease(paintNote[6], “8n”);
}
}

// print(flex1);
}

//CLICK 2 PLAY FUNCTION
function mousePressed() {
if (mouseX > 0 && mouseX < width / 4 &&
mouseY > 0 && mouseY < height / 2) {
loopKick();
} else if (mouseX > width / 4 && mouseX < width / 2 &&
mouseY > 0 && mouseY < height / 2) {
loopPiano();
pianoAnimation = true;
} else if (mouseX > 0 && mouseX < width / 4 &&
mouseY > height / 2 && mouseY < height) {
loopSnare();
} else if (mouseX > width / 4 && mouseX < width / 2 &&
mouseY > height / 2 && mouseY < height) {
loopBass();
}
}

//LOOP FUNCTIONS
function loopKick() {
if (!kickOn) {
kickPart.start(0);
kickOn = !kickOn;
} else {
kickPart.stop();
kickOn = !kickOn;
}
}

function loopSnare() {
if (!snareOn) {
snarePart.start(0);
snarePart.loop = true;
snareOn = !snareOn;
} else {
snarePart.loop = false;
snareOn = !snareOn;
}
}

function loopPiano() {
if (!pianoOn) {
pianoPart.start(0);
pianoPart.loop = true;
pianoOn = !pianoOn;
} else {
pianoPart.loop = false;
pianoOn = !pianoOn;
}
}

function loopBass() {
if (!bassOn) {
bassPart.start(0);
bassPart.loop = true;
bassOn = !bassOn;
} else {
bassPart.loop = false;
bassOn = !bassOn;
}
}

function printList(portList) {
for (var i = 0; i < portList.length; i++) {
print(i + ” ” + portList[i]);
}
}

function serialEvent() {
var stringFromSerial = serial.readLine();
if (stringFromSerial.length > 0) {
var trimmedString = trim(stringFromSerial);
var myArray = split(trimmedString, “,”)
flex1 = Number(myArray[0]);
flex2 = Number(myArray[1]);
flex3 = Number(myArray[2]);
flex4 = Number(myArray[3]);
}
}

document.ontouchmove = function(event){
event.preventDefault();

}

ANIMATIONS

BEAT

BASS

PIANO

SNARE

LEAD MELODY

 

THE SKETCH

Click around and draw on the fifth square!

GLOVE

To make the glove, we used Adafruit Flora. FLORA is Adafruit’s fully-featured wearable electronics platform. It’s a round, sewable, Arduino-compatible microcontroller designed to empower  wearables.

Diagram 1: Sensor position on the glove

Arduino Code:

Diagram 2: Circuit for the glove

Initial testing

Serial communication from breadboard circuit:

Soldering:

Using potentiometers for controls for user testing

—————————————————————————

5square

performed by Max Horwich

enjoy

 

Gestural Graphic Interface

Computational Media, Physical Computing

Partnering with two other people, my final project for ICM and PComp is the same: A graphic and musical interface that uses gloves  to enable inexperienced people to create, enhance and play music. After brainstorming for about a week and letting our simple ideas multiply and evolve into something that stays faithful to our project goals, and researching the scope and methods of other similar projects, we decided to take on a multi-faceted, holistic music creating interface that lets the user draw basic music notes in the form of doodles on a screen, and enhance it with the glove. The program will take inputs from the coordinates of the drawings to play and loop it, and from the sensors in the glove to add drastic effects, both musical and visual, to show the fun and the power in the art form itself.

Our inspiration through this research has been the Mi.Mu glove made by Imogen Heap, a glove that records, loops, plays and adds effects to sounds and music, while the user performs.

Inspirations..

Hand gestures — to make the music making process as intuitive as possible

To make this glove possible, we plan to build one using flex sensors, accelerometers, and probably even some tactile sensors, however that will greatly rely on the degrees of control we need.

Circuit diagram of one of the simplest glove designs

Our aim with the glove involves giving super powers to user when it comes to affecting change to the music. the first iteration might look similar to this one.

For the interface on the screen, our designs are still coming together, but the current target is around halfway between a traditional step sequencer and Kandinsky from the Chrome Music Lab Experiments. We researched a new library of functions for our project, Tone.js, and learned about its abilities and pitfalls.

Check it out:

https://musiclab.chromeexperiments.com/Kandinsky

The Progress:

We are currently researching the timeline, looping and how we are add and delete new user-added sounds to an existing loop. It is challenging but our progress is motivational.

Using Tone.js, we have so far created a sketch that uses this library to play beats at different frequencies and note lengths, and a sketch that creates markers to let the user draw, and maps sounds to each coordinate (and adds it to an array).

[Please refresh in case the sketches below do not work]

Or click the link:

TONE.JS

 

Or click the link:

MARKERS AND TONES

We are still understanding the workings of Tone.js and the next step is to serially communicate with the glove and add more changeable parameters to our sounds in code. We’re still in the process of acquiring materials for construction of the glove. This project has turned into an enormous undertaking, but it’s moving steadily forward, and I can’t wait to see how it develops.

 

Faces on a slider

Computational Media

For my PComp midterm, I used a few frames of some hand made sketches that used a proximity sensor to change between them.

For the sake of learning and applying the HTML slider, I uploaded the sketches on to p5.js and used simple if conditions to traverse through the images using the slider and get the animation effect.

Here is my code:

function setup() {
createCanvas(420, 450);
one = loadImage(“faces/1.png”);
two = loadImage(“faces/2.png”);
three = loadImage(“faces/3.png”);
four = loadImage(“faces/4.png”);
five = loadImage(“faces/5.png”);
six = loadImage(“faces/6.png”);
seven = loadImage(“faces/7.png”);
eight = loadImage(“faces/8.png”);
nine = loadImage(“faces/9.png”);
ten = loadImage(“faces/10.png”);
slider = createSlider(0,10,0,0);
slider.position(10,height-40);
slider.size(width-20,20);
x = slider.value();
}

function draw() {
background(255);
console.log(slider.value());
if(slider.value() <= 1){
image(one,0,0,width,height);
}
else if(slider.value() > 1 && slider.value() <= 2){
image(two,0,0,width,height);
}
else if(slider.value() > 2 && slider.value() <= 3){
image(three,0,0,width,height);
}
else if(slider.value() > 3 && slider.value() <= 4){
image(four,0,0,width,height);
}
else if(slider.value() > 4 && slider.value() <= 5){
image(five,0,0,width,height);
}
else if(slider.value() > 5 && slider.value() <= 6){
image(six,0,0,width,height);
}
else if(slider.value() > 6 && slider.value() <= 7){
image(seven,0,0,width,height);
}
else if(slider.value() > 7 && slider.value() <= 8){
image(eight,0,0,width,height);
}
else if(slider.value() > 8 && slider.value() <= 9){
image(nine,0,0,width,height);
}
else {
image(ten,0,0,width,height);
}
}

Maternity and Race

Computational Media

This week for ICM I wanted to illustrate statistics for the problems women face, and I wanted to do it in a way that helps viewers understand the issues women of colour or lower education attainment face, and also make it easier to understand and visualise — using emojis of course.

I imported the data in a .csv file from https://mchb.hrsa.gov, HRSA for Maternal and Child Health, and read up on of their surveys done in 2015 for maternity leaves taken in the US, divided by race, educational attainment and reasons for not getting or taking the leave.

Maternity leave from employment after childbirth provides critical time for maternal-infant bonding and adjustment to life with a new baby. Longer length of maternity leave is associated with increased breastfeeding duration, as well as improved maternal mental health and child development. The WOMEN’S HEALTH USA 2011 stated that “the Family and Medical Leave Act (FMLA) guarantees both women and men up to 12 weeks of unpaid leave around the birth or adoption of a child as long as they work for larger employers (50+ employees) and meet certain tenure and working hour requirements.” However, many women cannot afford to take unpaid leave and usually use a combination of short-term disability, sick leave, vacation, and personal days in order to have some portion of their maternity leave paid. The U.S. is one of only 5 countries in the world that does not mandate paid maternity leave.

According to their study:

In 2006-2015, 66.0 percent of women reported being employed during their last pregnancy, of whom 69.7 percent reported taking maternity leave. Thus, nearly one-third of employed women did not report taking any maternity leave (30.3 percent). Women with at least a college degree were more likely to have taken leave than those who had attended college but not graduated (80.0 versus 71.6 percent, respectively) while less than half of women without a high school degree reported having taken leave. Hispanic and non-Hispanic Black women were less likely to report having taken maternity leave than non-Hispanic White women (62.5 and 64.3 percent, respectively, versus 72.2 percent). When taken, the average length of maternity leave was 10.0 weeks (data not shown). Among employed women who did not take maternity leave for their last pregnancy, 5.1 percent did not take it because it was not offered or allowed by their employer. Of non-Hispanic White women, 3.2 percent reported this reason, compared to 8.2 percent of Hispanic women and 10.2 percent of non-Hispanic Black women.

I graphed these using skin colour as a major visual tool to tell the difference between the treatment of women at work.

Below are the visualisations and my code:

 

The key: (will be added to the sketch later)

Women who took maternity leave based on race

Employer’s disagreement on maternity leave based on race

Women of (presented) colour who enrolled in college

Educational Attainment levels:

Less than High School

High School

Some College

Bachelors Degree and higher

CODE:

let dataRace;
let dataEducation;
function preload() {
dataRace = loadTable(“race.csv”,
“csv”,
“header”);
dataEducation = loadTable(“education.csv”,
“csv”,
“header”);
}
function setup() {
createCanvas(430, 400);
console.log(dataRace.getRowCount());
console.log(dataRace.getColumnCount());
white = loadImage(“maternity/white.png”);
black = loadImage(“maternity/black.png”);
hispanic = loadImage(“maternity/hispanic.png”);
mixed = loadImage(“maternity/mixed.png”);
e1 = loadImage(“maternity/e1.png”);
e2 = loadImage(“maternity/e2.png”);
e3 = loadImage(“maternity/e3.png”);
e4 = loadImage(“maternity/e4.png”);
whiteemp = loadImage(“maternity/whiteemp.png”);
blackemp = loadImage(“maternity/blackemp.png”);
hispanicemp = loadImage(“maternity/hispanicemp.png”);
multipleemp = loadImage(“maternity/mixeddemp.png”);
whitegraduate = loadImage(“maternity/whitegraduate.png”);
blackgraduate = loadImage(“maternity/blackgraduate.png”);
multiplegraduate = loadImage(“maternity/mixedgraduate.png”);
hispanicgraduate = loadImage(“maternity/hispanicgraduate.png”);
//slider1 = createSlider(0,100,0,1);
//slider1.position(10,height-70);
//slider1.size(width-20,20);
//x = slider1.value();
console.log(dataRace.getNum(3, “Took Maternity Leave”));
//console.log(dataEducation.getNum(3, “Percent of Women”));

}

function draw() {
background(255);

let whiteNum =dataRace.getNum(1, “Took Maternity Leave”);
let blackNum =dataRace.getNum(2, “Took Maternity Leave”);
let multipleNum =dataRace.getNum(3, “Took Maternity Leave”);
let hispanicNum =dataRace.getNum(4, “Took Maternity Leave”);
let whiteEMP =dataRace.getNum(1, “Did Not Take Maternity Leave – Not Offered or Allowed by Employer”);
let blackEMP =dataRace.getNum(2, “Did Not Take Maternity Leave – Not Offered or Allowed by Employer”);
let multipleEMP=dataRace.getNum(3, “Did Not Take Maternity Leave – Not Offered or Allowed by Employer”);
let hispanicEMP =dataRace.getNum(4, “Did Not Take Maternity Leave – Not Offered or Allowed by Employer”);
let whiteCol =dataRace.getNum(1, “Enrolled in College”);
let blackCol =dataRace.getNum(2, “Enrolled in College”);
let multipleCol =dataRace.getNum(3, “Enrolled in College”);
let hispanicCol =dataRace.getNum(4, “Enrolled in College”);
let lessHigh =dataRace.getNum(1, “Percent of Women”);
let highSchool =dataRace.getNum(2, “Percent of Women”);
let someCol =dataRace.getNum(3, “Percent of Women”);
let colHigher =dataRace.getNum(4, “Percent of Women”);

let y = 25;
let x = 5;
//if(slider1.value() < hispanicNum){
strokeWeight(30);
stroke(145, 86, 34);
line(x+30,y+80,x+30,y+80+hispanicNum);
image(hispanic,x,y,50,85);
//}
//if(slider1.value() < blackNum){
strokeWeight(30);
stroke(51, 30, 12);
line(x+80,y+80,x+80,y+80+blackNum);
image(black,x+50,y,50,85);
//}
//if(slider1.value() < whiteNum){
strokeWeight(30);
stroke(249, 222, 199);
line(x+130,y+80,x+130,y+80+whiteNum);
image(white,x+100,y,50,85);
//}
//if (slider1.value() < multipleNum){
strokeWeight(30);
stroke(183, 143, 110);
line(x+180,y+80,x+180,y+80+multipleNum);
image(mixed,x+150,y,50,85);
//}
//noStroke();
//textSize(30);
//text(slider1.value(),90,200);
//textSize(20);
//text(“% of women”,46,220);
//let edu1 =dataEducation.getNum(
strokeWeight(30);
stroke(100);
line(x+250,y+60,x+250,y+80+lessHigh);
image(e1,x+230,y,45,58);
strokeWeight(30);
stroke(75);
line(x+300,y+60,x+300,y+80+highSchool);
image(e2,x+280,y,45,58);
strokeWeight(30);
stroke(50);
line(x+350,y+60,x+350,y+80+someCol);
image(e3,x+330,y,45,58);
strokeWeight(30);
stroke(0);
line(x+400,y+60,x+400,y+80+colHigher);
image(e4,x+380,y,47,60);

strokeWeight(30);
stroke(145, 86, 34);
line(x+30,y+250,x+30,y+250+hispanicEMP*8);
image(hispanicemp,x,y+200,50,72);
strokeWeight(30);
stroke(33, 20, 9);
line(x+80,y+250,x+80,y+250+blackEMP*8);
image(blackemp,x+50,y+200,50,72);
strokeWeight(30);
stroke(249, 222, 199);
line(x+130,y+250,x+130,y+250+whiteEMP*8);
image(whiteemp,x+100,y+200,50,72);
strokeWeight(30);
stroke(183, 143, 110);
line(x+180,y+250,x+180,y+250+multipleEMP*8);
image(multipleemp,x+150,y+200,50,72);

strokeWeight(30);
stroke(145, 86, 34);
line(x+250,y+260,x+250,y+250+hispanicCol);
image(hispanicgraduate,x+230,y+200,45,58);
strokeWeight(30);
stroke(33, 20, 9);
line(x+300,y+260,x+300,y+260+blackCol);
image(blackgraduate,x+280,y+200,45,58);
strokeWeight(30);
stroke(249, 222, 199);
line(x+350,y+260,x+350,y+260+whiteCol);
image(whitegraduate,x+330,y+200,45,58);
strokeWeight(30);
stroke(183, 143, 110);
line(x+400,y+260,x+400,y+260+multipleCol);
image(multiplegraduate,x+380,y+200,45,58);

}

https://alpha.editor.p5js.org/amena91/sketches/BJpwh9TAb

All Shapes and Sizes Barbie

Computational Media

Barbie, and the world in general, has been known to celebrate and look up to one particular kind of beauty, which is tall, skinny and white skinned. Not only is this standard highly difficult to achieve, but the non-inclusivity of the concepts of beauty that the general public has held for generations has been making women all over the world feel less comfortable in their own skin. Women are body shamed when they don’t fit a certain mould or skin color.

Generic old iconic-ass Barbie

Doll companies, alongside the people who control famous actresses and models, and popular media from advertisements to fashion magazines promote unattainable and restrictive beauty standards and cause a lot of pain, body dysphoria, and low self esteem among women and girls. Capitalism uses low self esteem as fuel to sell women products, and sometimes it all starts with a little girls first Barbie doll. Fortunately, recently women are now taking charge of what these beauty standards may be. A movement of acceptance has started, aiming towards more body positivity and diversity.

Body Positivity + Diversity

This has not only led to the Photoshopping of fashion magazines to be revealed more often, to models speaking about eating disorders, belly rolls, and stretch marks, but also doll companies to invest in dolls that more people can relate to. Ideals are being shifted, and capitalism is tweaking itself.

These are the dolls of the All Shapes and Sizes Barbie campaign:

In this assignment, I decided to make a function that takes as arguments weight, height and ethnicity, and outputs a doll.

function allShapesBarbie(x,y,heavy,tall,ethnicity)

(x,y): Coordinates on canvas

Heavy: Weight in pounds, ranging from 90 to 200 lbs

Tall: Height in inches, ranging from 5 foot 2 inches to 6 feet

Ethnicity: 1 for White, 2 for South Asian, 3 for African American — limited to three in my code to keep it simple but more can be added.

My code:

function setup() {
createCanvas(650, 500);
}

function draw() {
allShapesBarbie(50,100,90,67,1);
allShapesBarbie(150,126,130,63,2);
allShapesBarbie(250,78,105,70,3);
allShapesBarbie(350,145,90,60,1);
allShapesBarbie(465,146,190,60,3);
allShapesBarbie(580,68,90,72,2);
}

function allShapesBarbie(x,y,heavy,tall,ethnicity){

let skinColor;
let white = color(252, 226, 199);
let black = color(140, 95, 49);
let southasian = color(229, 166, 114);

if (ethnicity == 1){
skinColor = white;
}
else if (ethnicity == 2){
skinColor = southasian;
}
else if (ethnicity == 3){
skinColor = black;
}
else {print(“Invalid Ethinicty Number, Enter 1, 2 or 3 please.”);}

//Face
let faceWidth = map(heavy,90,200,40,54);
ellipseMode(CENTER);
rectMode(CENTER);
noStroke();
fill(112, 60, 4);
arc(x+7,y-22,42,26,PI,0);
arc(x-14,y-22,24,22,PI,0);
rect(x+1,y+5,54,59);
fill(skinColor);
ellipse(x,y,faceWidth,54);//faceshape
strokeWeight(1);
stroke(0);
fill(255);
ellipse(x-10,y-5,8,10);//eyes
ellipse(x+10,y-5,8,10);
fill(0);
ellipse(x-10,y-4,6,6);
ellipse(x+10,y-4,6,6);
noStroke();
fill(168, 24, 11);
ellipse(x-3,y+10,9,9);//lips
ellipse(x+3,y+10,9,9);
fill(242, 53, 36);
arc(x,y+10,15,12,0,PI);
fill(112, 60, 4);
arc(x+7,y-28.5,30,30,0,PI);//fringe

//Dress

let shoulder = map(heavy,90,200,30,40);
let waistx1 = map(heavy,90,200,20,40);
let waisty1 = map(tall,60,72,78,98);
let waistx2 = map(heavy,90,200,40,70);
let waisty2 = map(tall,60,72,140,170);
fill(0);
beginShape();
vertex(x-(shoulder),y+34);
vertex(x-10,y+34);
vertex(x-10,y+24);
vertex(x+10,y+24);
vertex(x+10,y+34);
vertex(x+(shoulder),y+34);
vertex(x+(waistx1),y+(waisty1));
vertex(x+(waistx2),y+(waisty2));
vertex(x-(waistx2),y+(waisty2));
vertex(x-(waistx1),y+(waisty1));
vertex(x-(shoulder),y+34);
endShape(CLOSE);

//Arms //put behind dress?

noFill();
let armFat = map(heavy,90,200,13,26);
let armLength = map(tall,60,72,80,122);
strokeWeight(armFat);
stroke(skinColor);
arc(x-(waistx1),y+(waisty1),36,armLength,HALF_PI,(3/2)*PI);
arc(x+(waistx1),y+(waisty1),36,armLength,(3/2)*PI,HALF_PI);

//Thighs

fill(skinColor);
let thighx1 = map(heavy,90,200,28,31);
let thighx2 = map(heavy,90,200,10,4);
let thighy = map(tall,60,72,140,170);
let kneex1 = map(heavy,90,200,18,26);
let kneex2 = map(heavy,90,200,10,16);
let kneey = map(tall,60,72,190,250);

beginShape();
vertex(x-(thighx1),y+(thighy));
vertex(x-(kneex1),y+(kneey));
vertex(x-(kneex2),y+(kneey));
vertex(x-(thighx2),y+(thighy));
endShape(CLOSE);
beginShape();
vertex(x+(thighx1),y+(thighy));
vertex(x+(kneex1),y+(kneey));
vertex(x+(kneex2),y+(kneey));
vertex(x+(thighx2),y+(thighy));
endShape(CLOSE);

//Boots
fill(0);
noStroke();
let bootx1 = map(heavy,90,200,32,40);
let bootx2 = map(heavy,90,200,0,2);
let booty = map(tall,60,72,195,250);
let bootheelx = (bootx1 + bootx2)/2
let bootheely = map(tall,60,72,270,350);

triangle(x-(bootx1),y+(booty),x-(bootheelx),y+(bootheely)+10,x-(bootx2),y+(booty));
ellipse(x-(bootheelx),y+(bootheely),25,20);
rect(x-(bootheelx),y+(bootheely)+7.5,25,5);

triangle(x+(bootx1),y+(booty),x+(bootheelx),y+(bootheely)+10,x+(bootx2),y+(booty));
ellipse(x+(bootheelx),y+(bootheely),25,20);
rect(x+(bootheelx),y+(bootheely)+7.5,25,5);

}

The output:

Play with more dolls here:

http://alpha.editor.p5js.org/amena91/sketches/HkEdfl53-

 

White Noise on TV Simulation

Computational Media

Group Members

Amena Hayat

Sofia Luisa

The inspiration for this week’s ICM assignment came a bit late. Me and Sofia were trying different things at first, from pointillism sketches to Eadward Muybridge’s horse. But after not being able to conceptualise an algorithm for either of those, we tried our hand at the white noise TV screen:

You can almost hear it

To build this with for loops was a challenge, because we had to incorporate two different designs in them and nest them together with the same variable.

We got the white noise working, with the stripes on a click, in a separate file:

The next thing was to make it fun and interactive. For that we fit the code onto the dimensions of a TV we created, and made the stripes appear at the click of the button on this TV. If it looks easy, well it was not.

Here’s the final thing, CLICK:

Our Code:

// coordinates
let x = 0
let y = 0

//height and width
let wh = 5

//button coordinates
let bx = 342;
let by = 190;
let bsize = 40;

function setup() {
createCanvas(400, 400);
}

function draw() {
background(237, 170, 37);
print(“X=”, mouseX, ” Y=”, mouseY);

//TV box:
strokeWeight(7);
stroke(137, 136, 134);
line(196, 130, 204, 10);
line(200, 140, 358, 16);
strokeWeight(3);
stroke(186, 184, 180);
line(191, 130, 199, 10);
line(195, 140, 353, 16);
noStroke();
fill(186, 184, 180);
ellipse(204, 10, 15, 15);
ellipse(360, 14, 15, 15);
fill(137, 136, 134);
ellipse(207, 10, 15, 15);
ellipse(362.5, 14, 15, 15);
strokeWeight(10);
stroke(63, 36, 10);
fill(114, 65, 18);
rect(5, 130, width – 10, height – 145, 10);
strokeWeight(4);
fill(0);
rect(18, 135, 280, 245, 10);
strokeWeight(6);
stroke(168, 164, 159);
fill(112, 109, 106);

ellipse(bx, by, bsize, bsize); //button

strokeWeight(6);
stroke(0);
line(307, 242, 378, 242);
line(307, 252, 378, 252);
line(307, 262, 378, 262);
line(307, 272, 378, 272);
line(307, 282, 378, 282);
line(307, 292, 378, 292);
line(307, 302, 378, 302);
line(307, 312, 378, 312);
line(307, 322, 378, 322);
line(307, 332, 378, 332);
//noise:
noStroke();
//how much x coordinate grows
push();
for (x = 25; x <= (293); x += 10) {  //TVscreen limits
for (y = 141; y <= (375); y += 10) {
pop();

if (mouseIsPressed == true){  //&& if (dist(mouseX,mouseY,bx,by)<bsize/2)
fill(random(0, 255), random(0, 255), random(0, 255));
rect(x – 3, y * 6, (width / 6) – 55, -height * 6);
fill(237, 170, 37);
rect(22,0,275,125);
rect(21,390,275,100);
strokeWeight(7);
stroke(137, 136, 134);
line(196, 130, 204, 10);
line(212, 130, 358, 16);
strokeWeight(3);
stroke(186, 184, 180);
line(191, 130, 199, 10);
line(198, 135, 353, 16);
noStroke();
fill(186, 184, 180);
ellipse(204, 10, 15, 15);
ellipse(360, 14, 15, 15);
fill(137, 136, 134);
ellipse(207, 10, 15, 15);
ellipse(362.5, 14, 15, 15);
fill(63, 36, 10);
rect(21,125,275,13);
rect(21,379,275,11);

} else {
fill(random(0, 255), 0, 0);
rect(x, y, wh, wh);
fill(0, 0, random(0, 255));
rect(x + 2, y + 2, wh, wh);
fill(100, random(0, 255), 0);
rect(x – 3, y – 3, wh, wh);
}
}
}
}

 

 

Bye now, sweet dreams.

Interactive Self Portrait

Computational Media

PLAY WITH ME — Move the mouse around and click for a wink! Refresh for a fresh choker.

http://alpha.editor.p5js.org/amena91/sketches/HkN9-Ks9W

Inspired by this photo of me 🙂

Changes to my code: 

[Please visit the post:

SELF PORTRAIT IN P5.JS!

for a refresher on my earlier code]

  • Surprise choker colour every time the sketch is run:

let c1;
let c2;
let c3;

function setup() {
createCanvas(800, 690);
c1= random(0,255);
c2= random(0,255);
c3= random(0,255);

//Choker [PLACED IN FUNCTION DRAW()]
noFill();
strokeWeight(30);
stroke(c1,c2,c3);
arc(376, 618, 155, 20, 0, PI);


  • Fading the background and dancing stars from black to while inversely:

let sinval = sin(angle/10);
let sky = map(sinval, -1, 1, 0, 255);
let stars = map(sinval, -1, 1, 255, 0);
background(sky);
angle += 0.1;


  • Making the eyes follow mouseX position without them leaving their socket

+

  • Creating a wink with one eye while the mouse is pressed:

via GIPHY

let eyeX2 = 439 + ((mouseX/width)*20);
let eyeX1 = 295 + ((mouseX/width)*20);

ellipse(305, 348, 54, 31);
ellipse(449, 348, 54, 31);
fill(0);
ellipse(eyeX1, 348, 30, 30);
ellipse(eyeX2, 348, 30, 30);

Here, to make the eyes follow the mouse X position without leaving the eye socket, the map function could’ve been used but I used pure math to solve the problem. I learned about map later into the exercise while fading the background.

Following the mouse position within the eye socket

 


if (mouseIsPressed)
{
noStroke();
fill(197,154,131);
ellipse(449,348,59,39);
strokeWeight(2);
stroke(0);
line(430,360,425,366);
line(437,364,437,373);
line(448,367,448,374);
line(459,364,466,372);
line(473,359,484,364);

noFill();
strokeWeight(7);
stroke(0);
arc(449,348,54,34,0,PI);
}
else
{ellipse(eyeX2,348,30,30);
}

 

Computation in Art

Computational Media

I’ve been both, artist and engineer. The lack of creativity in my engineering program, however, had always made me crave art and artistic practices more, since back then, incorporating the two was a little impossible. Now that that isn’t the case anymore, I want to show you the kind of work I want to make in ps.js, and what has influenced my past work as well.

Photography

Taken in the outskirts of Lahore, my hometown, in a village which got a supply of clean water recently. These photos capture the joy of a newfound utility and contrast facial activity with the surroundings.

Faces are one of my deepest interests in art; capturing, creating, everything.

One of my most significant goals in art pursuits is creating empathy between people.

 

I’ve found that my art tends to be very “branchy”

These images were made on Photoshop while I learned Infinite Surface Design for digital printing on textiles at Rhode Island School of Design during a summer.

 

 

 

 

 

 

 

 

Digital Prints

 

 

 

 

One of my favourite pieces: Tree branches with urban photography backdrop. Noise and order.

For computing the kind of art I am inspired by, I want to be able to merge these

 

This image by Ryan Alexander amazes me. The smokey effect made with narrow branches, creating a portrait this defined: definitely something I want to be able to make. Maybe a generative software too.

I want to make GIFs like these for a better understand of certain logics or data, and to just make learning attractive for younger students.

This one merged with Ryan’s artwork above certainly ignites a chain of ideas in my head. One project I’m interested in is morphing one face from another in a similar way.

 

 

 

 

Self Portrait in p5.js!

Computational Media

To start off, I’ll say I’m pretty proud of myself to pull off a sketch like this after just learning p5.js. Its not really accurate (I could work on that) but at least its not ugly.

I decided on this photo of my face as a guide:

“Cheese! ..not”

As an attempt to extract coordinates, I imported the image onto Photoshop and marked the points, lines, ellipses and arcs (symbolised by T formations since all I needed were the centre, height and width)

Boo

I used the rulers on Photoshop and my cursor

To map coordinates on a drawing. Wonder why the result still wasn’t very ~accurate~

 

 

 

 

 

 

 

I picked colours on Photoshop as well, and noted their RGB

For more colours later, I just found the best Google extension ever

After this I started coding, and many coordinate errors (I was sleepy) and frustrations later (see Exhibit A), after almost reaching the end point, I reached a Eureka moment and coded the following line:

print(“X=”,mouseX,” Y=”,mouseY);  //you idiot

And suddenly the task became a lot easier.

Exhibit A

My Code:

https://gist.github.com/amena91/4bc1786f9b0bddee46ea47e5345f4337

function setup() {
createCanvas(800, 690);
}

function draw() {
background(0); //change to black

//HELP W/ COORDINATES, shouldv’e done this way sooner!
print(“X=”,mouseX,” Y=”,mouseY);

//DANCING STARS
fill(255);
noStroke();
ellipse(random()*800,random()*800,3,3);
ellipse(random()*800,random()*800,5,5);
ellipse(random()*800,random()*800,1,1);
ellipse(random()*800,random()*800,2,2);
ellipse(random()*800,random()*800,5,5);
ellipse(random()*800,random()*800,3,3);
ellipse(random()*800,random()*800,10,10);
ellipse(random()*800,random()*800,2,2);
ellipse(random()*800,random()*800,7,7);
ellipse(random()*800,random()*800,6,6);
ellipse(random()*800,random()*800,3,3);
ellipse(random()*800,random()*800,1.5,1.5);
ellipse(random()*800,random()*800,8,8);
ellipse(random()*800,random()*800,13,13);
ellipse(random()*800,random()*800,10,10);
ellipse(random()*800,random()*800,2,2);
ellipse(random()*800,random()*800,12,12);
ellipse(random()*800,random()*800,2,2);
ellipse(random()*800,random()*800,2,2);
ellipse(random()*800,random()*800,5,5);
ellipse(random()*800,random()*800,5,5);

//Hair Head and Back Hair
fill(58, 31, 1);
arc(380,200,400,270,PI,0);
beginShape();
vertex(181,194);
vertex(163,463);
vertex(135,646);
vertex(130,666);
vertex(669,682);
vertex(613,424);
vertex(580,193);
endShape(CLOSE);

//Neck
fill(197,139,117);
beginShape();
vertex(298,540);
vertex(303,571);
vertex(260,310);
vertex(303,609);
vertex(284,671);
vertex(486,689);
vertex(472,660);
vertex(455,624);
vertex(455,589);
vertex(467,540);
endShape(CLOSE);

//Face Shape
fill(238,187,166);
arc(385,330,300,340,PI,0);
quad(237,390,259,478,495,487,528,382);
arc(380,480,215,203, 0,PI);
quad(534,330, 532,432, 239,432, 238,315);
beginShape(); //just smoothing edges
vertex(256,468);
vertex(296,538);
vertex(323,472);
endShape(CLOSE);
beginShape();
vertex(476,521);
vertex(497,479);
vertex(445,478);
endShape(CLOSE);

//Eyes
fill(255);
ellipse(305,348,54,31);
ellipse(449,348,54,31);
fill(0);
ellipse(305,348,30,30);
ellipse(449,348,30,30);
noFill();
strokeWeight(7); //damn you, my love for eyeliner!
stroke(0);
arc(305,348,54,34,PI,0);
arc(449,348,54,34,PI,0);
fill(0);
triangle(275,350,276,345,265,345); //and it has to be winged too..
triangle(480,350,489,345,481,345);
strokeWeight(1);
stroke(0);

//Eyebrows
noStroke();
fill(58, 31, 1);
beginShape();
vertex(395,312);
vertex(462,292);
vertex(502,310);
vertex(510,325);
vertex(502,318);
vertex(472,310);
vertex(400,330);
endShape(CLOSE);
beginShape();
vertex(350,310);
vertex(349,322);
vertex(260,310);
vertex(240,315);
vertex(250,310);
vertex(280,295);
endShape(CLOSE);

//Lips
fill(205,120,115);
arc(375,500,87,36 ,0,PI);
fill(169,92,84);
beginShape();
vertex(335,500);
vertex(360,490);
vertex(375,495);
vertex(390,490);
vertex(425,505);
endShape(CLOSE);

//Nose
noFill();
strokeWeight(1);
stroke(0);
arc(380,440,40,15,0,PI);
fill(0);
ellipse(360,444,3,3);
ellipse(400,444,3,3);
noFill();
arc(360,441,14,15,PI/2,3*PI/2);
arc(400,441,14,15,3*PI/2,PI/2);

//Front Hair
fill(79, 48, 12);
beginShape();
vertex(397,156);
vertex(357,160);
vertex(310,179);
vertex(271,213);
vertex(245,249);
vertex(211,326);
vertex(199,348);
vertex(260,671);
vertex(177,670);
vertex(187,283);
vertex(215,209);
vertex(260,154);
vertex(340,120);
vertex(397,133);
endShape(CLOSE);

//Glasses
noFill();
strokeWeight(3);
stroke(0);
arc(375,325,324,10,PI,0);
//line(205,318,534,318);
arc(375,360,40,8,PI,0);
line(355,362,318,321);
line(397,359,435,321);
line(213,325,232,381);
line(357,361,351,381);
line(397,361,401,381);
line(539,325,529,381);
arc(291.5,381,120,100,0,PI);
arc(465,381,125,100,0,PI);
line(233,380,200,346);
line(200,346,316,322);
line(437,320,548,340);
line(548,340,529,381);

//Earrings
noStroke();
fill(100);
ellipse(235,435,26,30);
ellipse(532,420,26,30);

//Choker
noFill();
strokeWeight(30);
stroke(0);
arc(376,618,155,20,0,PI);

}

Check it out:

And Voila!