Click to make music!
sketch
/*
Elena Deng and Dani Delgado
Section E
edeng1 and ddelgad1
Final Project
*/
//variables to load sounds into
var ellipseSound;
var arcSound;
var squareSound;
var triSound;
var bgs;
//create the slider to control bg noise pan
var sliderPan;
//variables to inciment the bg
var volInc;
var pitchInc;
//stores the amount of mouse clicks
var mouseClick = 0;
//variables for the bg graphic based on amplitude
var amp;
var volhistory = [];
var objects = []; //sets the array for objects
var bright = 1; //sets the brightness of the screen+background
var xe = []; //sets the x pos array for the centroid
var ye = []; //sets the y pos array for the centroid
function preload() {
//load all of the sounds into the file
ellipseSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/ellipseDrip.mp3");
squareSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/bloopSquare.mp3");
arcSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/bong.mp3");
triSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/ding.mp3");
bgs = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/whiteNoise.mp3");
}
function setup() {
createCanvas(640, 480);
frameRate(14);
angleMode(DEGREES);
//play bg sound
bgs.loop();
bgs.setVolume(1.5);
//get amplitude
amp = new p5.Amplitude();
//create pan slider
sliderPan = createSlider(-1, 1, 0, 0.01);
sliderPan.size(640, AUTO);
for (var i = 0; i < 7; i++) { //sets the centroid points
var t = map(i, 0, 7, 0, TWO_PI);
xe.push(width / 2 + 75 * cos(t));
ye.push(height / 2 + 75 * sin(t));
}
}
function draw() {
background(10, 10, bright); //everytime the mouse is pressed, background brightness increases/decreases
bright = bright - 5;
if (mouseIsPressed) {
bright = 110;
}
//pan slider
bgs.pan(sliderPan.value());
//get bgs amplitude and apply it the the graphic
//the graphic is made from a "begin and end shape" method
//and mapping of amps is made in a forloop
var vol = amp.getLevel();
volhistory.push(vol);
push();
frameRate(40);
translate(width / 2, height / 2);
//create the outer circle
beginShape();
strokeWeight(5);
stroke(20, 20, -bright, 80);
noFill();
for (var i = 0; i < 360; i++) {
var r = (map (volhistory[i], 0, 1, 10, 100)) * 18;
var x = r * cos(i);
var y = r * sin(i);
vertex(x, y);
}
endShape();
//create the inner circle
beginShape();
strokeWeight(0.5);
stroke(80, 80, -bright);
noFill();
for (var i = 0; i < 360; i++) {
var r = (map(volhistory[i], 0, 1, 10, 100)) * 17;
var x = r * cos(i);
var y = r * sin(i);
vertex(x, y);
}
endShape();
if (volhistory.length > 360) {
volhistory.splice(0, 1);
}
pop();
for (var i = 0; i < objects.length; i++) { //sets the order of the objects
if (objects[i].type == "circle") {
drawCir(objects[i]);
}
if (objects[i].type == "rect") {
drawRect(objects[i]);
}
if (objects[i].type == "tri") {
var change = random(0, 2)
drawTri(objects[i].x, objects[i].y, objects[i].s + change);
}
if (objects[i].type == "centroid") {
drawCentroid();
}
}
}
function mousePressed() {
//variables for sounds made to easily reset the mouse clicks
var firstSound = mouseClick < 10;
var secondSound = mouseClick >= 10 & mouseClick <= 20;
var thirdSound = mouseClick > 20 & mouseClick <= 30;
var fourthSound = mouseClick > 30 & mouseClick <= 40;
//images and sounds are based on mouse clicks
if (firstSound) {
//this code is to play the sounds
//only allows a sound effect to be triggered if it's not playing
//that way theres no overlap of sounds
if(!ellipseSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 5, 0.09);
pitchInc = map(mouseX, 0, 640, 0.25, 1.25);
ellipseSound.play();
ellipseSound.setVolume(volInc);
ellipseSound.rate(pitchInc);
}
//pan the sounds based on mouse click
//you'll hear it in every other ear every other click
if (mouseClick % 2) {
ellipseSound.pan(-1.0);
} else {
ellipseSound.pan(1.0);
}
if (objects.length >= 7) {
objects.shift();
}
objects.push(createCir(mouseX, mouseY)); //creates the circle for the first ten mouse clicks
}
if (secondSound) {
if(!squareSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 8, 1.5);
pitchInc = map(mouseX, 0, 640, 0.25, 1.75);
squareSound.play();
squareSound.setVolume(volInc);
squareSound.rate(pitchInc);
// if (mouseClick % 2){
// squareSound.pan(-1.0);
// } else {
// sqaureSound.pan(1.0);
// }
}
if (objects.length >= 7) {
objects.shift();
}
objects.push(createRect(mouseX, mouseY)); //creates the square/rect for the next ten mouse clicks
}
if (thirdSound) {
if(!triSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 7, 0.5);
pitchInc = map(mouseX, 0, 640, 0.5, 1.75);
triSound.play();
triSound.setVolume(volInc);
triSound.rate(pitchInc);
}
if (mouseClick % 2) {
triSound.pan(-1.0);
} else {
triSound.pan(1.0);
}
if (objects.length >= 7) {
objects.shift();
}
objects.push(createTri(mouseX, mouseY, random(1, 2))); //creates the diamond for the next ten mouse clicks
}
if (fourthSound) {
if(!arcSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 8, 0.5);
pitchInc = map(mouseX, 0, 640, 0.25, 1.25);
arcSound.play();
arcSound.setVolume(volInc);
arcSound.rate(pitchInc);
}
if (mouseClick % 2) {
arcSound.pan(-1.0);
} else {
arcSound.pan(1.0);
}
if (objects.length >= 7) {
objects.shift();
}
xe.push(mouseX);
ye.push(mouseY);
objects.push(createCentroid()); //creates the centroid for the next ten mouse clicks
}
if (mouseClick > 40) {
mouseClick = firstSound; //mouseClicks resets the cycle
}
//increment the mouse clicks
mouseClick ++;
}
function createCir(bx,by) { //creates the circle
return {x:bx, y:by, type: "circle", oDiam: 0};
}
function drawCir(cir) { //draws the circle
for (var i = 0; i < 10; i++) {
var diam = cir.oDiam - 70 * i; //adjusts the drip spacing effect
if (diam > 0) {
var fade = map(diam, 0, width / 2, 100, 255); //sets the color
strokeWeight(map(diam, 0, width, 12, 1)); //stroke weight decreases as circle gets larger
stroke(fade, fade / 1.3, fade / 2, 85);
noFill();
ellipse(cir.x, cir.y, diam / 2); //draws ellipse
}
}
cir.oDiam = cir.oDiam + 2; //increases size of the circle
if (cir.oDiam > height / 2) { //once circle is larger than height/2 then the circle enlargement speed decreases
cir.oDiam -= 1.25;
}
}
function createRect(bx,by,bs) {
return {x:bx, y:by, s:bs, type: "rect", oRect: 210}
}
function drawRect(square) {
noStroke();
rectMode(CENTER);
for (var i = 0; i < 6; i++) {
var recta = square.oRect - 100 * i; //sets the frequency/size of squares
if (recta < 0) {
var fade = map(recta, 0, width / 2, 255, 180); //maps the color
strokeWeight(10)
stroke(fade, fade / 1.3, fade / 2); //sets the color fade
noFill();
rect(square.x, square.y, recta / 2, recta / 2); //draws the square
}
}
square.oRect = square.oRect - random(-2, -4); //shrinks square at random rates
}
function createTri(bx, by, bs) { //creates the diamond
return {x:bx, y:by, s:bs, type: "tri"}
}
function drawTri(bx, by, bs) { //draws the diamond
var smashorpass = random(-1, 10); //sets the random rate at which the shapes twinkle
var smashthenpass = random(-1, 5);
noStroke();
//draws the first diamond
fill(map(by, 0, height, 200, 255), map(by, 0, height, 120, 225), map(by, 0, height, 40, 85));
quad(bx - 10 + bs - smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by - 30 + bs - smashthenpass, bx + 10 + smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by + 30 + bs + smashthenpass);
strokeWeight(2); //draws the second diamond outline
stroke(255, 230, 215, 70);
noFill();
quad(bx - 15 + bs - smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by - 35 + bs - smashthenpass, bx + 15 + smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by + 35 + bs + smashthenpass);
}
function createCentroid() { //creates the centroid
return {type: "centroid"};
}
function drawCentroid() { //draws the centroid
noStroke();
fill(map(ye, 0, height, 200, 255), map(ye, 0, height, 120, 225), map(ye, 0, height, 40, 85));
// moving the components of the centroid
var nPoints = xe.length;
for (var i = 0; i < nPoints; i++) {
xe[i] += (noise(i * 1 + millis() / 500.0) - .5) * 10;
ye[i] += (noise(i * 2 + millis() / 500.0) - .5) * 10;
ellipse(xe[i], ye[i], 30, 30);
}
// draw the dots on the outside
for (var i = 0; i < nPoints; i++) {
ellipse(xe[i], ye[i], 1, 1);
}
// finding the average of the dots (x,y)
var xAverage = 0;
var yAverage = 0;
for (var i = 0; i < nPoints; i++) {
xAverage += xe[i];
yAverage += ye[i];
}
xAverage /= nPoints;
yAverage /= nPoints;
// draws line from center to the points
strokeWeight(4);
stroke(255, 255, 255, 10);
for (var i = 0; i < nPoints; i++) {
line(xe[i], ye[i], xAverage, yAverage);
}
// Draw the centroid
stroke(0);
strokeWeight(2);
ellipse(xAverage, yAverage, 10, 10);
}
For our final project, we wanted to create a “digital instrument” which synthesizes user interaction, sound, and generative visuals. We decided to start with a simple background which not only contains a graphic that reacts to the amplitude of the played music, but also flashes brighter when the user clicks in. From there, we added different graphics and corresponding sound effects to increase visual and audio interest. These graphics all have unique movements and correlate to the sound, while the sound effects change based on the mouseX and mouse Y position. As the user clicks, they’ll explore a range of different sounds and shapes that are placed on a loop which resets after every 40 clicks. Also, as they click, the sounds’s panning will change with every other click (e.x. click once, sound effect will play in one ear and click again, it’ll play in the other).
Here are some screenshots of possible screens you would get by interacting with this project!
We really enjoyed working on this project and exploring how different sounds and visuals interact and affect one another! We had difficulty at the beginning decided on exactly what we wished to do, but once we got the ball rolling things started to fall into place!
Since this was a partner project, we divided up the work to make it manageable and easier to code (as two people working on one computer would be slow and painful on our friendship). So we split the work up into such parts:
Elena Deng created the objects and visuals.
Dani Delgado edited the sound effects and created the background graphic.
Together we worked on debugging the code and adding the intended effects.
We hope you click around and have fun!
]]>For this project, Dani Delgado (from Section E) wanted to collaborate and create something that synthesizes user interaction, sound, and generative visuals. Our plan is to start by displaying a still image (we are thinking a graphic cube) which changes a little bit when the user presses certain keys. The whole interaction would work as so: Each key has an assigned sound and “cube distortion” to it. So, when the user presses a key, a note will play and the visual will change slightly, so that when the user plays a full “song” the visual would have morphed a lot. A possible idea we had was with lower pitches the visual could retain the change that the lower pitch enacted, while with a higher pitch, the visual would go back to its original state before the key was enacted.
/*Elena Deng
Section E
edeng1@andrew.cmu.edu
Project-11
}
*/
var t = [];
function setup() {
createCanvas(400, 400);
background(10);
for(var i = 0; i < t.length; i++){ //sets various numbers of turtles
t[i] = makeTurtle(width/2, height / 2 + random(-100, 100));
t[i].setColor(color(random(200), random(200), random(150), 100));
}
}
function draw() {
var targetX = mouseX + noise(frameCount / 100); //sets the target
var targetY = mouseY + noise(frameCount / 100);
strokeWeight(5);
point(targetX, targetY); //turtle will always be inclined to go to target x and y
for (var a = 0; a < t.length; a++){
t[a].setWeight(random(1,5))
t[a].penDown();
t[a].forward(1.5);
t[a].turnToward(targetX, targetY,1);
t[a].left(random(-5,5));} //draws the turtle
}
function mousePressed(){ //sets the number of turtles and increases it when mouse is pressed
var newTurtle = makeTurtle(mouseX, mouseY);
newTurtle.setColor(color(random(150), random(150), random(20), 100));
t.push(newTurtle); //push turtle into t array
}
//////////////////////////
function turtleLeft(d) {
this.angle -= d;
}
function turtleRight(d) {
this.angle += d;
}
function turtleForward(p) {
var rad = radians(this.angle);
var newx = this.x + cos(rad) * p;
var newy = this.y + sin(rad) * p;
this.goto(newx, newy);
}
function turtleBack(p) {
this.forward(-p);
}
function turtlePenDown() {
this.penIsDown = true;
}
function turtlePenUp() {
this.penIsDown = false;
}
function turtleGoTo(x, y) {
if (this.penIsDown) {
stroke(this.color);
strokeWeight(this.weight);
line(this.x, this.y, x, y);
}
this.x = x;
this.y = y;
}
function turtleDistTo(x, y) {
return sqrt(sq(this.x - x) + sq(this.y - y));
}
function turtleAngleTo(x, y) {
var absAngle = degrees(atan2(y - this.y, x - this.x));
var angle = ((absAngle - this.angle) + 360) % 360.0;
return angle;
}
function turtleTurnToward(x, y, d) {
var angle = this.angleTo(x, y);
if (angle < 180) {
this.angle += d;
} else {
this.angle -= d;
}
}
function turtleSetColor(c) {
this.color = c;
}
function turtleSetWeight(w) {
this.weight = w;
}
function turtleFace(angle) {
this.angle = angle;
}
function makeTurtle(tx, ty) {
var turtle = {x: tx, y: ty,
angle: 0.0,
penIsDown: true,
color: color(128),
weight: 1,
left: turtleLeft, right: turtleRight,
forward: turtleForward, back: turtleBack,
penDown: turtlePenDown, penUp: turtlePenUp,
goto: turtleGoTo, angleto: turtleAngleTo,
turnToward: turtleTurnToward,
distanceTo: turtleDistTo, angleTo: turtleAngleTo,
setColor: turtleSetColor, setWeight: turtleSetWeight,
face: turtleFace};
return turtle;
}
This week I was really excited to revisit the concept of turtles. I wanted to revisit the lines seen in the title notes from class. If you click on the screen, a new line will form and attempt to follow the mouse location. Continue clicking and you can see the way the turtle attempts to reach the mouse location more clearly.
]]>Cycling Wheel: The Orchestra – Reimagining Marcel’s bicycle wheel as a light+sound Instrument
Who lives in a pineapple under the sea
/*Elena Deng
Section E
edeng1@andrew.cmu.edu
Project-10
}
*/
var Pineapples = [];
var col;
var frameB = 1;
var bubbles= [];
function setup() {
createCanvas(480, 480);
// create an initial collection of Pineapples
for (var i = 0; i < 10; i++){
var rx = random(width);
Pineapples[i] = makePineapple(rx);
}
for (var i = 0; i < 20; i++) {
var newBub = makeBubbles(random(width));
bubbles.push(newBub);
}
frameRate(38);
}
function draw() {
background(243,233,126);
displayHorizon();
waveOne();
waveTwo();
waveFour();
waveThree();
updateAndDisplayPineapples();
removePineapplesThatHaveSlippedOutOfView();
addNewPineapplesWithSomeRandomProbability();
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].draw();
bubbles[i].move();
//adds the new bubbles
if ((frameB % 5 == 0) & (random(1) < .2)) {
newBub = makeBubbles(width);
bubbles.push(newBub);
}
}
}
function waveOne(){
var waterSpeed = 0.0002;
var waterDetail = 0.004;
stroke(100,200,254);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * waterDetail/4) + (millis() * waterSpeed*2);
var y = map(noise(t), 0, 1, 0, 100);
line(x, y, x, height);
}
endShape();
}
function waveTwo(){
var waterSpeed = 0.0002;
var waterDetail = 0.004;
stroke(20,100,254,70);
push();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * waterDetail) + (millis() * waterSpeed*2);
var y = map(noise(t), 0, 1, 100, 140);
line(x, y, x, height);
}
endShape();
pop();
}
function waveFour(){
var waterSpeed = 0.0002;
var waterDetail = 0.004;
stroke(20,100,254,70);
push();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * waterDetail/6) + (millis() * waterSpeed*2);
var y = map(noise(t), 0, 1, 100, 300);
line(x, y, x, height+400);
}
endShape();
pop();
}
function waveThree(){
var waterSpeed = 0.0002;
var waterDetail = 0.004;
stroke(198,186,146);
push();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * waterDetail/6) + (millis() * waterSpeed/6);
var y = map(noise(t), 0, 1, 200, 300);
line(x, y+160, x, height+150);
}
endShape();
pop();
}
function updateAndDisplayPineapples(){
// Update the Pineapple's positions, and display them.
for (var i = 0; i < Pineapples.length; i++){
Pineapples[i].move();
Pineapples[i].display();
}
}
function makeBubbles(origin) {
var bubble = {
x: origin,
y: random(height),
velX: random(-2, 1.5),
velY: random(-3, 1),
sizeF: random(20),
draw: drawBubble,
move: moveBubble
}
return bubble;
}
function removePineapplesThatHaveSlippedOutOfView(){
// If a Pineapple has dropped off the left edge,
// remove it from the array. This is quite Cutcky, but
// we've seen something like this before with particles.
// The easy part is scanning the array to find Pineapples
// to remove. The Cutcky part is if we remove them
// immediately, we'll alter the array, and our plan to
// step through each item in the array might not work.
// Our solution is to just copy all the Pineapples
// we want to keep into a new array.
var PineapplesToKeep = [];
for (var i = 0; i < Pineapples.length; i++){
if (Pineapples[i].x + Pineapples[i].breadth > 0) {
PineapplesToKeep.push(Pineapples[i]);
}
}
Pineapples = PineapplesToKeep; // remember the surviving Pineapples
}
function addNewPineapplesWithSomeRandomProbability() {
// With a very tiny probability, add a new Pineapple to the end.
var newPineappleLikelihood = 0.01;
if (random(0,1) < newPineappleLikelihood) {
Pineapples.push(makePineapple(width));
}
}
//draws the bubbles that appear at beginning
function drawBubble() {
noFill();
strokeWeight(2);
stroke(255, 255, 255, 80);
ellipse(this.x, this.y, this.sizeF * 1.5, this.sizeF * 1.5);
}
function moveBubble() {
this.x -= 1.5;
this.x += this.velX;
this.y += this.velY;
}
// method to update position of Pineapple every frame
function PineappleMove() {
this.x += this.speed;
}
// draw the Pineapple decorations door and leaves
function PineappleDisplay() {
var CutHeight = 20;
var bHeight = this.nCuts * 20;
// var bWidth = this.nCuts * 30;
push();
noStroke();
//draws leaves of Pineapple
fill(155,182,59);
translate(this.x, height - 40);
rect(10,-bHeight-20,this.breadth/2,bHeight,30);
rect(30,-bHeight-20,this.breadth/2,bHeight,30);
fill(122,167,59);
rect(40,-bHeight-30,this.breadth/4,bHeight);
fill(122,167,59);
rect(20,-bHeight-30,this.breadth/2,bHeight,30);
fill(122,167,59);
rect(40,-bHeight-50,this.breadth/4,bHeight,20);
fill(88,150,59);
rect(10,-bHeight-40,this.breadth/4,bHeight);
fill(88,150,59);
rect(15,-bHeight-50,this.breadth/4,bHeight,10);
fill(61,150,59);
rect(30,-bHeight-60,this.breadth/4,bHeight);
//draws the actual pineapple
fill(255,196,74);
stroke(230,170,50);
strokeWeight(2);
rect(0,-bHeight, this.breadth+15,bHeight,40);
//draw the decorations of the pineapple/grooves
noStroke();
fill(230,170,50);
ellipse(18,-20,10,10);
ellipse(33,-20,10,10);
ellipse(48,-20,10,10);
ellipse(33,-40,10,10);
ellipse(18,-40,10,10);
ellipse(48,-40,10,10);
ellipse(33,-60,10,10);
ellipse(18,-60,10,10);
ellipse(48,-60,10,10);
//draws the door of the pineapple
fill(0)
rect(20,-bHeight/2, 20,40,20)
pop();
}
function makePineapple(LocationX) {
var pin = {x: LocationX,
breadth: 50,
speed: -1.0,
nCuts: round(random(4,7)),
move: PineappleMove,
display: PineappleDisplay}
return pin;
}
function displayHorizon(){
function setup() {
}
}
I had a lot of fun with this project! I really loved Spongebob as a child and I was really excited to have a reason to do this subject because of the wavelike forms the the terrain tool given to us creates. If I had more time I would make the pineapple details look more like pineapples and maybe include a random sponge bob around!
The artist herself focuses on the human senses of touch as well as encouraging the creative participation of the audience. She has a masters in media design from UCLA and currently lives in Los Angeles.
http://www.novajiang.com
sketch
This project was fun because we were able to add aspects of our daily life and apply it to the code. I decided to use a photo of my friend and I together. I used the words “wow” and “cute” to describe us & the photo. If you scroll over the image, you will see little ellipses forming on the photo, reflecting the colors of the underlying image.
var underlyingImage;
function preload() {
var fallImage = "https://i.imgur.com/pUlrsst.jpg";
underlyingImage = loadImage(fallImage);
}
function setup() {
createCanvas(500, 500);
background(0);
underlyingImage.loadPixels();
frameRate(10);
}
function draw() {
var posX = random(width);
var posY = random(height);
var ix = constrain(floor(posX), 0, width-1);
var iy = constrain(floor(posY), 0, height-1);
var theColorAtLocationXY = underlyingImage.get(ix, iy);
noStroke();
fill(theColorAtLocationXY);
text("wow",posX, posY, 200);
text("cute",posX * random(-1,5), posX * random(-3,5), 200);
var theColorAtTheMouse = underlyingImage.get(mouseX, mouseY);
fill(theColorAtTheMouse);
ellipse(pmouseX, pmouseY, 10, 6);
}
For this week’s assignment, I have decided to look at Xindi Lyu’s Week 7 Looking Outwards Project and Lee Krasner’s painting. I decided to review this entry because I really enjoyed that week’s promo of randomness as well as the way that Xindi interpreted this assignment. For me, I still chose to continue with something relating to technology and did not consider stepping out of that field into fine arts. I enjoyed how she describes the simplest elements of strokes and slashes to create something random and yet still beautiful. In addition, the story behind the painting attracted me to reinterpret the visual language of the strokes and look at the painting differently than how it looks upon first glance. (I’m also a huge Jackson Pollock fan). As a whole, I appreciated the choice to step out of conventional choices for projects and this post inspired me to branch out with future subject matters for Looking Outwards.
]]>
Eyeo 2014 – Mouna Andraos and Melissa Mongiat from Eyeo Festival on Vimeo.
This week, I chose to listen to Mouna Andraos speak about their work. Their projects, focusing on participation, design, and technology tend to combine interactive design and environment. She calls her projects daily tous les jours, meaning “everyday” in French. The projects themselves create a magical environment, thus inciting the public to become active contributors to the results of the exhibition. The studio was started by Mouna, a professor at Concordia University, she has won various awards including the 2014 UNESCO Creative Cities Design Award for Young Talents.
One of the projects I really admired was the Sound Capsule created in 2010. It is a place in a loud city that one can just have some time to themselves. Another project that interested me was the conversation wall by Umpqua Bank. It was a temporary installation meant to engage the local community and celebrate the recent opening. By texting the bank they can add topics to a conversation and essentially each of the submissions will be displayed on the wall in real time, inviting everyone looking at the wall to joining in on the conversation.
]]>