Washington Square Arch Through Time

For our final my group, Alan, Xiping, and I, created projection of the Washington Square Arch that can be wiped away by hand to reveal newer images using the programs Isadora and Leap Motion with Processing code. As you wipe away the older image to reveal the new, sounds play that correspond to the time of the photographs. Starting with a projection of the arch in the 1880’s when horse drawn buggies would drive right through the park to current day when the sounds of the city are much different. What we hoped to reveal is how much history architecture can hold.

Although we had some trouble coming up with ideas for the final, partially due to the overwhelming expanse of the subject, it became clear that we had a few themes in mind. Below are the common notes we used when meeting to discuss our ideas:


IDEAS

Language vs Reality

  • The “real world” is to a large extent unconsciously built up in the language habits of the group… We see and hear and otherwise experience very largely as we do because the language habits of our community predispose certain choices of interpretation.
  • Explore how people’s cultural backgrounds affect their most basic cognitive processes: categorization, learning, causal reasoning and even attention and perception.

Online vs Offline Identity

False conceptions of truth based on memories we falsify

Creating something out of nothing

  • an image of a face or something else appears only when the smoke is there.
  • smoke and mirrors : (definition)  the obscuring or embellishing of the truth of a situation with misleading or irrelevant information.
        • What you see isn’t always what you get (also a theme)
        • gaslighting
          • create a temporary piece of art that is destroyed at the end.

Themes

  • Language, Culture, Memory

Methods

Projection mapping, 3D projection mapping?

Projection to smoke

LINKS / MISC.

http://projection-mapping.org/thecave/

Use projection mapping of bending a space to set up the scene, and then project voice recognized words onto smoke

Anthony McCall — pioneer works –

Gaslighting: 1. (slang; origin UK) To manipulate someone psychologically such that they question their own sanity. … The phrase “to gaslight” someone (to deliberately drive someone insane by psychologically manipulating their environment and tricking someone into believing that they are insane), was derived from the film.”

    *The term “gaslighting” comes from a 1938 stage play called Gaslight, in which a husband attempts to drive his wife crazy by dimming the lights in their home (which were natural gas-fueled fixtures), then denying that the lights had changed brightness when the wife asks him about it. Link

https://en.wikipedia.org/wiki/Gas_Light

…..

Immersive interactive experience where a person walks into small space and invited to interact briefly with an object in the dark. They have to say outloud what they think the object they just interacted with was but if they get anything wrong the space around them tightens physically and a flash of light (playing on “gaslighting”) goes off. The more they get wrong the more annoyances happen. (could be something obvious too, for example, bringing someone into a small space and asking them to explain something like a red apple in as many words as they can, and slowly we can tell them they’re wrong in a lot of different ways using noise and light).

3 Types of Memory: Visual, Auditory, and Kinesthetic Memory

https://getweyland.com/pages/3-types-of-memory-visual-auditory-and-kinesthetic-memory

A major breakthrough in visual memory research

http://www.olapic.com/resources/major-breakthrough-visual-memory-research/

“When a tiger starts to move towards you, you need to know whether it is something you are actually seeing or whether it’s just something that you remember or have imagined.”

Memory, a fundamental cognitive skill

https://www.cognifit.com/memory

“Types of Memory: Depending on how long, type of information, and the sensory organ”

Things We Want

Interactivity

A play on memory

Meeting Notes

Good vs bad memories

Ordered memory

Three types of memory:

Sensory Memory.

  • Short-Term (Working) Memory.
  • Long-Term Memory. Declarative (Explicit) and Procedural (Implicit) Memory. Episodic and Semantic Memory. Retrospective and Prospective Memory.

How to create a false memory in the audience?


As you can see from our notes, our ideas were a bit scattered and needed some honing in on. We really wanted to convey the concept of memory and I think our chosen subject of the Washington Square Arch decisively developed the direction toward retrospective memory as a result. The execution of the project consisted of writing the code for Processing and initiating OSC within Isadora in order connect our code. Leap Motion was also included as a library in order to work properly within our Processing script. Using two envelope generators in Isadora, that were set up to trigger every time a key press was initiated, we manually had to press “s” and 3″ in order to change the scenes and to switch the audio tracks correspondingly.

Coding and programming aside, there was a bit of editing work involved too. All of the photos, videos, and sounds were found online through archival libraries and simple searches and then edited in Adobe Creative Cloud.

Washington Square Arch

Processing Code:
/*
Example: Using Syphon and OSC
With Isadora
Created by Andrew Lazarow
Nothing 2018
*/
//import syphon library
import codeanticode.syphon.*;
//Import the oscP5 Library
import oscP5.*;
import netP5.*;
import com.onformative.leap.LeapMotionP5;
LeapMotionP5 leap;
//initiate value to receive from OSC
//Set at 1 which we can say means draw.
int OSCValue=1;
//Declare an instance of OSC, called oscP5
OscP5 oscP5;
//Declare a net address
NetAddress myRemoteLocation;
//Setting up or declaring your 'canvas' - that piece of paper
PGraphics canvas;
//This boolean restores the black background
boolean addBackground=false;
//Declare our Syphon Server
SyphonServer server;
void settings () {
size (360, 480, P3D);
//PJOGL profile = 1;
//This line is needed for older versions of Processing.
}
void setup () {
//Create our canvas to draw on
canvas = createGraphics(width, height, P3D);
//we want to create our syphon outpout
//Name it MySyphonOutputBlueberries
server = new SyphonServer(this, "MySyphonOutputBlueberries");
/*
Whenever you draw on your canvas you need
to put "canvas." before any drawing call.
So let's set a black background on our canvas.
*/
canvas.beginDraw();
canvas.background(0);
canvas.endDraw();
//Initiate our OSC
oscP5 = new OscP5 (this, 5001);
leap = new LeapMotionP5(this);
myRemoteLocation = new NetAddress("127.0.0.1", 1234);
}
void draw () {
PVector fingerPos = leap.getTip(leap.getFinger(1));
canvas.beginDraw();
//If Add Background is True. Then restore background
//And leave it black.
if (addBackground==true) {
canvas.fill(0, 10);
canvas.rect(0, 0, width, height);
}
// If addBackground is false, then draw the white ellipse
else {
//I set the fill's alpha to 80.
//A bit of a feather effect.
canvas.fill(255, 80);
canvas.noStroke();
//draw a circle following your mouse
//canvas.ellipse(mouseX, mouseY, 50, 50);
canvas.ellipse(fingerPos.x, fingerPos.y, 100, 100);
println ("finger position x = " + fingerPos.x);
}
canvas.endDraw();
//show our canvas in our processing window
image(canvas, 0, 0);
//send our canvas to syphon
server.sendImage(canvas);
}
//Your OSC Receiving event:
void oscEvent(OscMessage theOscMessage) {
// get the first value as an integer
OSCValue = theOscMessage.get(0).intValue();
// print out the message
print("OSC Message Received: ");
print(theOscMessage.addrPattern() + " " +
"is sending: ");
println(OSCValue);
//If the OSC Value you get is '1' then let drawing happen
if (OSCValue==1) {
addBackground=false;
}
//If the value is anything else restore the black background
else {
addBackground=true;
}
}
void keyPressed() {
OscMessage myMessage = new OscMessage("/From_Processing");
//hitting 'b' restores our background.
//and acts as a toggle to restart drawing
if (key=='b') {
addBackground=!addBackground;
}
if (key=='s') {
myMessage.add(1);
oscP5.send(myMessage, myRemoteLocation);
}
if (key=='r') {
myMessage.add(0);
oscP5.send(myMessage, myRemoteLocation);
}
if (key=='3') {
myMessage.add(3);
oscP5.send(myMessage, myRemoteLocation);
}
}

Isadora Screenshots:

Screen Shot 2018-05-13 at 15.09.13

Screen Shot 2018-05-13 at 15.09.24

Sources /  Inspiration:

https://digitalcollections.nypl.org/search/index?utf8=%E2%9C%93&keywords=washington+square+arch#

Downtown Doodler: Hidden History of Washington Square Park in NYC

https://www.wnyc.org/story/sounds-washington-square-park-1962/

http://vectorsdev.usc.edu/NYCsound/777b.html

 

 

 

Finals Update #2: The coding is DONE!!!

HORRAY! The coding side of my project is finished! I have to give thanks where it’s deserved: Mimi, Tom, Mathura, Mithru thank you all so much for your help and support.

Here is the final-ish p5.js code (it will include more songs)
let playbutton, stopbutton, nextbutton, backbutton;
let slider;
let fader = 0;
let songBFileNames = ['SpiritInTheSky', 'RunThroughTheJungle', 'HesSoFine','UnderPressure', 'YouNeedLove', 'AmericanGirl', 'SweetLittleSixteen','MaryJanesLastDance', 'BrownSugar', 'LadyMadonna','DontStopTilYouGetEnough', 'TwoPrinces', 'Mmmbop', 'PumpItUp','ObLaDiObLaDa', 'IWontBackDown', 'Taurus', 'TheAirThatIBreathe','PictureBook','TomorrowNeverKnows', 'LittleMermaid'];
let songAFileNames = ['BabyDidABadBadThing', 'TheOldManDownTheRoad', 'MySweetLord','IceIceBaby', 'WholeLottaLove', 'LastNight', 'SurfinUSA','DaniCalifornia', 'WalkAndTalkIt', 'WhatIGot','SteppinOut', 'SemiCharmedLife', 'Unpretty', 'GetOnYourBoots','WhyDontYouGetAJob', 'StayWithMe', 'StairwayToHeaven', 'Creep','SaladDays','LetForeverBe', 'Nude'];
let songAs = [];
let songBs = [];
let albumAs = [];
let albumBs = [];
let currentIndex = 0;
let serial;
let portName = '/dev/cu.usbmodem1421';
let hasStarted = false;
let isPlaying = false;
let volumeA = 1;
let volumeB = 1;
function preload() {
for (let i = 0; i < songAFileNames.length; i++) { songAs[i] = loadSound("assets/sounds/" + songAFileNames[i] + ".mp3"); songBs[i] = loadSound("assets/sounds/" + songBFileNames[i] + ".mp3"); albumAs[i] = loadImage("assets/images/" + songAFileNames[i] + ".jpg"); albumBs[i] = loadImage("assets/images/" + songBFileNames[i] + ".jpg"); } } function setup() { createCanvas(400, 400); background(255); serial = new p5.SerialPort('192.168.1.151'); // make an instance of the serial library serial.open(portName); // open port serial.on('connected', function(){ console.log("CONNECTED"); background(215); }); serial.on('data', gotData); // declare serial data callback function } function draw() { //checkSliderAndUpdateSound(); if(hasStarted) checkFaderAndUpdateSound(); } function checkFaderAndUpdateSound() { console.log("checkFaderAndUpdateSound"); volumeA = map(fader, 0, 1023, 0, 1); volumeB = map(fader, 0, 1023, 1, 0); console.log(volumeA); songAs[currentIndex].setVolume(volumeA); songBs[currentIndex].setVolume(volumeB); tint(255,255); image(albumBs[currentIndex], 55, 20); tint(255, fader/4); image(albumAs[currentIndex], 55, 20); } function playsound() { songAs[currentIndex].loop(); songBs[currentIndex].loop(); } function pausesound(){ songAs[currentIndex].pause(); songBs[currentIndex].pause(); } function stopsound() { songAs[currentIndex].stop(); songBs[currentIndex].stop(); } function nextsetsound() { stopsound(); currentIndex++; if (currentIndex > songAs.length - 1) {
currentIndex = 0;
}
playsound();
}
function lastsetsound() {
stopsound();
currentIndex--;
if (currentIndex < 0) { currentIndex = songAs.length - 1; } playsound(); } function gotData() { let arduinoInput = serial.readLine(); // read an ASCII-encoded string if(arduinoInput.length > 0) {
if (arduinoInput === 'P') {
if(isPlaying) {
pausesound();
isPlaying = false;
} else {
playsound();
isPlaying = true;
} hasStarted = true;
}
else if (arduinoInput === 'B') {
lastsetsound();
}
else if (arduinoInput === 'N') {
nextsetsound();
}
else {
if(arduinoInput == NaN) arduinoInput = 0;
fader = arduinoInput;
console.log(fader);
}
}
}

And the Arduino code:
const int playButton = 2;
const int backButton = 3;
const int nextButton = 4;
int threshold = 2;
const int fader = A0;
int faderValue = 0;
int playButtonState = LOW;
int backButtonState = LOW;
int nextButtonState = LOW;
int prevFaderValue = 1;
int prevPlayButtonState;
int prevBackButtonState;
int prevNextButtonState;
void setup() {
pinMode(playButton, INPUT);
pinMode(backButton, INPUT);
pinMode(nextButton, INPUT);
Serial.begin(9600);
}
void loop() {
faderValue = analogRead(fader);
backButtonState = digitalRead(backButton);
playButtonState = digitalRead(playButton);
nextButtonState = digitalRead(nextButton);
if (playButtonState != prevPlayButtonState && playButtonState == HIGH) {
Serial.println('P');
}
if (backButtonState != prevBackButtonState && backButtonState == HIGH) {
Serial.println('B');
}
if (nextButtonState != prevNextButtonState && nextButtonState == HIGH) {
Serial.println('N');
}
if (abs(faderValue - prevFaderValue) > threshold) {
Serial.println(faderValue);
prevFaderValue = faderValue;
}
prevPlayButtonState = playButtonState;
prevBackButtonState = backButtonState;
prevNextButtonState = nextButtonState;
}

Final proto from Marco Wylie on Vimeo.

Things I need to fix on the coding side:

  1. When streaming the p5.js sketch to the iphone, you have to press on the iphone’s screen in order to start the sketch, even after you press the physical Play button.
  2. When you start the sketch the album cover from the other side of the slider starts on the opposite side and then suddenly switches to the correct one and acts normally when you move the fader.

Similarity JukeBox

My song comparison box has finally started to come together. Although I haven’t figured out one section of code on the p5.js side that will let the physical fader control not only the sound but the album display, the rest of the functionality seems to be working.

What I hope to convey with this project is how similar two songs can be, using clips of the songs to emphasize exactly what sounds the same between the two.

I’ll be running the p5.js script through an old iphone  which will be fastened to the interface shown in the video below. All I need to do is figure out the following:

  1. How to get the songs to play in the order I wanted and not randomly after pressing the next button.
  2. How to map the tint function in p5.js so that the fader works with the album images as well as the song clips.
  3. How to properly fabricate everything so that it fits neatly inside the cigar box.

A p5.js functional sketch version of the project can be seen here.

Serial Problems

I’m having a lot of trouble making a serial connection between my Arduino, the three buttons, and my p5.js sketch. Here is my current Arduino sketch:

const int pinButton2 = 2;
const int pinButton3 = 3;
const int pinButton4 = 4;
int lastButtonState = LOW;
int buttonPressCount = 0;
void setup() {
pinMode(pinButton2, INPUT);
pinMode(pinButton3, INPUT);
pinMode(pinButton4, INPUT);
Serial.begin(9600);
}
void loop() {
char incoming = Serial.read(); // read incoming bytes
if (incoming == 'P') { // if you get P
digitalWrite(2, HIGH); // Play is Pressed
}
int currentButtonState = digitalRead(2); //read the play button
if (currentButtonState != lastButtonState) { // if the button changed
buttonPressCount++; // increment buttonPressCount
Serial.print('P'); // send a P
Serial.println(buttonPressCount);
}
// int stateButton2 = digitalRead(pinButton2);
// int stateButton3 = digitalRead(pinButton3);
// int stateButton4 = digitalRead(pinButton4);
// Serial.println(stateButton2);
// Serial.println(stateButton3);
// Serial.println(stateButton4);
// delay(20);
lastButtonState = currentButtonState; // save the current state for next time
// int sensorValue = analogRead(A0);
// Serial.println(sensorValue);
// int sensorValue1 = analogRead(A1);
// Serial.println(sensorValue1);
}

(Based on this code)

And my p5.js sketch is here.

Every time I press the button on my breadboard I get a serial monitor reading of “P” but then I get another “P” when I release the button as well. This is making the song clips play twice and distorting the sound heavily in my p5.js sketch. Although, now I’m not getting anything on the p5.js side since I changed “1” to “P” in the .js sketch.

Button Press from Marco Wylie on Vimeo.

 

ICM Conclusion

Showing my final ICM project to the class allowed me to see some changes I need to think about when combing this sketch with an Arudino based interface. The p5.js sketch for my ICM final is exactly the way it will look when I combine it with a physical interface. The buttons on the screen were added to illustrate the way the interface will look once it is fabricated. All I’m going to need is the image of the album covers fading and the sound to function through p5.js for my pComp final.

Upgrades:

  1. On either side of the slider I want to have all the original songs on the left and all the rip offs on the right. √
  2. Slider should start on the left side when the sketch is opened (doesn’t really apply once I have a physical interface) √
  3. Get rid of the Stop button and combine a Play Button with a Pause function
  4. Add master volume (needed for physical interface)

Updated Song List:

SpiritInTheSky 1969 BabyDidABadBadThing 1995
RunThroughTheJungle 1970 TheOldManDownTheRoad 1985
HesSoFine 1962 MySweetLord 1970
UnderPressure 1982 IceIceBaby 1990
YouNeedLove 1962 WholeLottaLove 1969
AmericanGirl 1976 LastNight 2001
SweetLittleSixteen 1958 SurfinUSA 1963
MaryJanesLastDance 1993 DaniCalifornia 2006
BrownSugar 1971 WalkAndTalkIt 1972
LadyMadonna 1969 WhatIGot 1996
DontStopTilYouGetEnough 1979 SteppinOut 1981
TwoPrinces 1991 SemiCharmedLife 1997
Mmmbop 1997 UnPretty 1999
PumpItUp 1978 GetOnYourBoots 2009
ObLaDiObLaDa 1968 WhyDontYouGetAJob 1998
IWontBackDown 1989 StayWithMe 2014
Taurus 1968 StairwayToHeaven 1971
TheAirThatIBreathe 1974 Creep 1993
PictureBook 1968 SaladDays 2014
TomorrowNeverKnows 1966 LetForeverBe 1999
LittleMermaid 1989 Nude 2007

One problem I’ve had since the conception of this idea is the what I’m going to call this project. When trying to come up with a word for the “sound-a-like” song on the other side of the slider I realized that this was part of the problem I’m having with a title. I don’t know what to call the song that songs like the original. And further than that, I don’t know what to call the project itself!

On the left side will be “Original Songs” or just “Original” so the listener knows what they’re listening to, so that they are grounded in the experience, and so hopefully, it will be obvious what the intent of the installation is. On the other side…here are my ideas:

Copy-written, Plagiarized, Trademark, RipOff, Similar, Doppelgänger, Sound-a-like, Imitative, Copy, Stolen, Ripped

For the name of the project itself I want something more than just a one word descriptive  title. A few weeks back I presented a few options for the title in ICM, I’m not really happy with any of the names I came up with. Perhaps this part will come together once I put together the pComp side of the project.

pComp Final Update

Started soldering and testing my connections. My 10k sliding potentiometer is working when tested with this code:

void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
}

Sliding Potentiometer from Marco Wylie on Vimeo.

And the other potentiometer for the volume is working as well.

Potentiometer from Marco Wylie on Vimeo.

Once I got home with all my soldered pieces I assembled the code for the two potentiometers and three buttons to print the sensor values.

const int pinButton2 = 2;
const int pinButton3 = 3;
const int pinButton4 = 4;
void setup() {
pinMode(pinButton2, INPUT);
pinMode(pinButton3, INPUT);
pinMode(pinButton4, INPUT);
Serial.begin(9600);
}
void loop() {
int stateButton2 = digitalRead(pinButton2);
int stateButton3 = digitalRead(pinButton3);
int stateButton4 = digitalRead(pinButton4);
Serial.println(stateButton2);
Serial.println(stateButton3);
Serial.println(stateButton4);
delay(20);
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
int sensorValue1 = analogRead(A1);
Serial.println(sensorValue1);
}

Final progress from Marco Wylie on Vimeo.

I’m having a lot of trouble making a serial connection between my Arduino, the three buttons, and my p5.js sketch. Here is my current Arduino sketch:

const int pinButton2 = 2;
const int pinButton3 = 3;
const int pinButton4 = 4;
int lastButtonState = LOW;
int buttonPressCount = 0;
void setup() {
pinMode(pinButton2, INPUT);
pinMode(pinButton3, INPUT);
pinMode(pinButton4, INPUT);
Serial.begin(9600);
}
void loop() {
char incoming = Serial.read(); // read incoming bytes
if (incoming == 'P') { // if you get P
digitalWrite(2, HIGH); // Play is Pressed
}
int currentButtonState = digitalRead(2); //read the play button
if (currentButtonState != lastButtonState) { // if the button changed
buttonPressCount++; // increment buttonPressCount
Serial.print('P'); // send a P
Serial.println(buttonPressCount);
}
// int stateButton2 = digitalRead(pinButton2);
// int stateButton3 = digitalRead(pinButton3);
// int stateButton4 = digitalRead(pinButton4);
// Serial.println(stateButton2);
// Serial.println(stateButton3);
// Serial.println(stateButton4);
// delay(20);
lastButtonState = currentButtonState; // save the current state for next time
// int sensorValue = analogRead(A0);
// Serial.println(sensorValue);
// int sensorValue1 = analogRead(A1);
// Serial.println(sensorValue1);
}

Every time I press the button on my breadboard I get a serial monitor reading of “P” but then I get another “P” when I release the button as well. This is making the song clips play twice and distorting the sound heavily in my p5.js sketch.

Button Press from Marco Wylie on Vimeo.

ICM Final

Figuring out the code for this was pretty difficult. Thankfully I had a lot of help from my instructor and we got the code up and running! I still haven’t come up with a suitable name for the project but I think that by the time I combine this with the pComp side I should have a better idea of what it should be called. I’m very happy with the results I have so far, and I certainly learned a lot putting it together.

Two more links in case the embedded version above doesn’t load:

http://alpha.editor.p5js.org/marcowylie/sketches/ryw1cVclz

http://alpha.editor.p5js.org/full/ryw1cVclz

let playbutton, stopbutton, nextbutton, backbutton;
let slider;
let songAFileNames = ['BabyDidABadBadThing', 'RunThroughTheJungle', 'MySweetLord',
'UnderPressure', 'YouNeedLove', 'LastNight', 'SurfinUSA',
'DaniCalifornia', 'WalkAndTalkIt', 'WhatIGot',
'SteppinOut', 'SemiCharmedLife', 'Mmmbop', 'GetOnYourBoots',
'WhyDontYouGetAJob', 'Taurus', 'TheAirThatIBreathe',
'PictureBook', 'LetForeverBe', 'LittleMermaid'];
let songBFileNames = ['SpiritInTheSky', 'TheOldManDownTheRoad', 'HesSoFine',
'IceIceBaby', 'WholeLottaLove', 'AmericanGirl', 'SweetLittleSixteen',
'MaryJanesLastDance', 'BrownSugar', 'LadyMadonna',
'DontStopTilYouGetEnough', 'TwoPrinces', 'Unpretty', 'PumpItUp',
'ObLaDiObLaDa', 'StairwayToHeaven', 'Creep',
'Warning', 'TomorrowNeverKnows', 'Nude'];
let songAs = [];
let songBs = [];
let albumAs = [];
let albumBs = [];
let currentIndex = 0;
function preload() {
for (let i = 0; i < songAFileNames.length; i++) { songAs[i] = loadSound("assets/sounds/" + songAFileNames[i] + ".mp3"); songBs[i] = loadSound("assets/sounds/" + songBFileNames[i] + ".mp3"); albumAs[i] = loadImage("assets/images/" + songAFileNames[i] + ".jpg"); albumBs[i] = loadImage("assets/images/" + songBFileNames[i] + ".jpg"); } } function setup() { createCanvas(400, 400); background(215); // slider slider = createSlider(0, 255, 100); slider.position(125, 320); // play button playbutton = createButton('Play'); playbutton.position(140, 350); playbutton.mousePressed(playsound); // stop button stopbutton = createButton('Stop'); stopbutton.position(200, 350); stopbutton.mousePressed(stopsound); // last set button backbutton = createButton('Last Set'); backbutton.position(50, 350); backbutton.mousePressed(lastsetsound); //next set button nextbutton = createButton('Next Set'); nextbutton.position(275, 350); nextbutton.mousePressed(nextsetsound); } function draw() { checkSliderAndUpdateSound(); } function checkSliderAndUpdateSound() { let slidervalue = slider.value(); let volumeA = map(slidervalue, 0, 255, 0, 1); let volumeB = map(slidervalue, 0, 255, 1, 0); songAs[currentIndex].setVolume(volumeA); songBs[currentIndex].setVolume(volumeB); tint(255,255); image(albumBs[currentIndex], 55, 20); tint(255, slidervalue); image(albumAs[currentIndex], 55, 20); } function playsound() { songAs[currentIndex].loop(); songBs[currentIndex].loop(); } function stopsound() { songAs[currentIndex].stop(); songBs[currentIndex].stop(); } function nextsetsound() { stopsound(); currentIndex++; if (currentIndex > songAs.length - 1) {
currentIndex = 0;
}
playsound();
}
function lastsetsound() {
stopsound();
currentIndex--;
if (currentIndex < 0) {
currentIndex = songAs.length - 1;
}
playsound();
}

Open ended questions for class:

  1. What buttons are useful? Should any be taken away?
  2. Which sets of songs are clearly related and which aren’t?
  3. Did you learn anything new about songs you might have heard before after playing with the sketch?
  4. How did the interface feel?

Final Update #3 – The coding part

Having finalized the conceptual part of my project, it’s time to code! Over the break I spent quite some time trying to figure out how to get two preloaded songs mapped out on the slide corresponding to the volume of each track.

Here’s what I have of the sketch so far. I’m adding buttons because this part of my project is due before the pComp part and I won’t have enough of the physical side done in time to present in a few days.

I still need to add images of the album covers fading into each other above the slider to emphasize what’s going on. And if I have time, I’d like to be able to add up to six songs per set. That reminds me I need to get that “Next Set” button working too! A nice background would be nice to have as well.

let playbutton, nextbutton, backbutton;
let slider;
let soundGroupPath1 = ['assets/sounds/BabyDidABadBadThing.wav', 'assets/sounds/LaGrange.wav'];
let soundGroup1 = [];
let soundGroupPath2 = ['assets/sounds/RunThroughTheJungle.mp3', 'assets/sounds/TheOldManDownTheRoad.mp3'];
let soundGroup2 = [];
function preload()
{
for(let i =0; i<soundGroupPath1.length; i ++) {
soundGroup1[i] = loadSound(soundGroupPath1[i])
}
for(let i =0; i<soundGroupPath2.length; i ++) {
soundGroup2[i] = loadSound(soundGroupPath2[i])
}
// album = loadImage('assets/images/BabyDidABadBadThing.jpg');
// album1 = loadImage('assets/images/BoogieChillun.jpg');
}
function setup()
{
createCanvas(350, 300);
background(255);
// slider
slider = createSlider (0, 255, 100);
slider.position(100,100);
// stop sound to prevent it from playing automatically
// soundtrack.stop();
// play button
playbutton = createButton('Play');
playbutton.position(120, 150);
playbutton.mousePressed(playsound);
//next set button
nextbutton = createButton('Next Set');
nextbutton.position(140, 180);
nextbutton.mousePressed(nextsetsound);
// stop button
stopbutton = createButton('Stop');
stopbutton.position(180, 150);
stopbutton.mousePressed(stopsound);
}
function draw()
{
checkSliderAndUpdateSound();
}
function checkSliderAndUpdateSound(){
// console.log(slider.value());
let slidervalue = slider.value();
let volumeOne = map(slidervalue , 0, 255, 0, 0.5);
let volumeTwo = map(slidervalue , 0, 255, 1, 0);
if(soundGroup1[0].isPlaying() == true && soundGroup1[1].isPlaying() == true){
// if(soundGroup1[0].isPlaying() == true ){
soundGroup1[0].setVolume(volumeOne);
soundGroup1[1].setVolume(volumeTwo);
}
if(soundGroup2[0].isPlaying() == true && soundGroup2[1].isPlaying() == true){
soundGroup2[0].setVolume(volumeOne);
soundGroup2[1].setVolume(volumeTwo);
}
}
function playsound()
{
if(soundGroup1[0].isPlaying() == false)
{
for(let i =0; i<soundGroupPath1.length; i ++) {
// soundGroup1[i].play();
soundGroup1[i].loop();
// soundGroup1[i].setVolume(1);
}
}
}
function stopsound()
{
if(soundGroup1[0].isPlaying() == true)
{
for(let i =0; i<soundGroupPath1.length; i ++) {
soundGroup1[i].pause();
}
}
}
function nextsetsound()
{
if(soundGroup1[0].isPlaying() == true)
{
for(let i=0; i<soundGroupPath2.length; i ++) {
soundGroup2[i].loop();
}
}
}

Final Update #2

I spent the better part of my day collecting songs that sound alike, which led to an inevitable journey into songs that sound like another song that sound like another song and so on. Now I have groups of 5 songs that sound the same that I’ll need to somehow put on the fader. Originally, I had it set up so that I would only preload two songs at once for comparison. This new development is truer to my original idea which was an installation that would allow someone to hear the way I experience music. Usually when I hear a song it automatically flows into another song in my head and that usually leads to a playlist of music that sounds similar. Certain parts of a song will remind me of another and sure enough, I’ll be whistling another tune after a short while. Here is the running list of music so far:

Since I now have some sets of songs that are in groups of as much as 5, I have to rethink how I’m going to incorporate the fader. I know I want to have the songs blend into each other when the fader is moved, but now that 5 songs are going to be in a set at a time, I need to organize them so they flow when played. Originally, I wanted to have the album cover show on the LCD when the fader was all the way to one side. Now I’m going to have to have the album cover show whenever you only hear one particular song. The second the fader is moved to hear something else, the album cover will disappear and the a visualization of the two songs will be on the LCD.

I’m working with clips of songs to enunciate the listeners understanding of the similarities, but I’d like to maybe incorporate a button on the interface that will allow the user to hear the entirety of each song.

On the coding side, I’m going to need to incorporate the following:

Play/Rewind/Next buttons, fader values, serial communication, TFT LCD library, sound library, some kind of music visualization, image and sound files.

Final — Update

I’m considering making the LCD show sound waves of the songs playing to further demonstrate how similar two sets of songs at a time are. After presenting about my idea in ICM it became clear to me that not everyone hears music the way I do, and this could be a great opportunity to let people hear music through my ears.

As Tom suggested, here are two system diagrams to think about:

One thing I need to figure out is whether or not I need a headphone jack that can run through the cigar box or whether I should just use a headphone jack from an iPhone or laptop..

After user testing I realized that my BOM needs to be updated:

ITEM QTY. COST DESC.
Cigar Box 1 $0 Brown 10 1/2″ x 7″ x 2 1/4″ rectangular cigar box with clasp
ON/OFF Button 1 $4.95 Rugged Metal On/Off Switch with White LED Ring – 16mm
Color LCD 1 $24.95 2.2″ 18-bit color TFT LCD Display with microDS card breakout
Potentiometer (fader) 1 $2.95 Slide Potentiometer 10K Ohm 0.5W, 3 1/2″ x 1 1/2″
Play, Back & Next Buttons 3 $1.50 Momentary Pushbutton Switch – 12mm Square
Fader Knob 1 $0.95 Slide Potentiometer Knob, Black
TOTAL —– $35.30

Whether or not I’ll be needing that on/off button will be determined once I really get into fabricating and putting together the whole project. I happened to have the button already so it’s no loss if I don’t end up using it.

I’m considering ditching the fader and going with a knob and three buttons (rewind to beginning, play, and next set). The reason for going with a metal knob instead is because I already have a variable potentiometer and I’ve found it hard to find a fader with an appropriate length and attractive knob.

Instead of trying to buy everything from Sparkfun and Adafruit I’m going to head to Tinkersphere to try and avoid shipping costs. (I’ll update my BOM once I go there later today). Here’s what I’ll need to find:

  • Headphone jack
  • 3 Push Button Caps
  • Potentiometer Cap
  • Color LCD (TFT Arduino compatible)
  • 3 Push Buttons

……………………

Updated BOM:

ITEM QTY. COST DESC.
Cigar Box 1 $0 Brown 10 1/2″ x 7″ x 2 1/4″ rectangular cigar box with clasp
ON/OFF Button 1 $4.95 Rugged Metal On/Off Switch with White LED Ring – 16mm
LCD 1 $15.99 2.2″ color TFT LCD Display with microDS card breakout
Potentiometer (fader) 1 $2.95 Slide Potentiometer 10K Ohm 0.5W, 3 1/2″ x 1 1/2″
Play, Back & Next Buttons 3 $1.50 Momentary Pushbutton Switch – 12mm Square
Fader Knob 1 $0.95 Slide Potentiometer Knob, Black
TOTAL —– $26.34