A multi-visualizer for a place that was once home.

I was born in Portland, OR in 1988, at Bess Kaiser Hospital, during a nurse’s strike. My older brother had been a traumatic and difficult birth, and so it was decided that a planned Caesarian section would be the best way to ensure a smooth delivery for me. As an added benefit, this meant that the birth could be scheduled around the strike. And so, that July, on a hot day weeks before my projected due date, my folks got a spot in the parking lot on Interstate Avenue, and went home in the mid-afternoon with a baby, feet and hands rubbed and warmed to make the lingering blue coloration fade. The hospital closed within the next couple of years, and was razed to the ground, replaced by a scrub embankment between the actual interstate highway and the street named for it.

This site is now the national headquarters for Adidas, who design shoes for human feet and shirts for human chests and backs, to be fabricated elsewhere by human hands and shoulders. It’s about two hours drive from there to Mount Hood, and about two hours from there to the low-class beach towns of Tillamook County I’ve been going to since shortly after that finally opening my eyes, a few weeks after returning from the hospital. From there to the Media Lab at CMU, travel time depends on your means of travel.

Waves

Here at CMU, there is a live projection of a wave-like shape on the wall. The waves are as a big as the waves are in Manzanita, OR, just outside the mouth of Tillamook Bay. The height of the waves on the wall is the height of the tide in Garibaldi, OR, just inside that bay. The scale of the waterline is 1:1; if you imagine the floor of this room to be “sea level”, these waves are as high above that as the water is in Oregon, right now. “Sea Level” is of course a relative term– the level of the actual sea is anywhere from +8.0′ to -2.0′ above Sea Level. There’s a certain similarity between this and the notion of a birth time, or a birth location: if not here, where? If not now, whenever.

There is a tiny screen in front of the big wave that shows you what what is happening at Manzanita right now. It’s what’s above, here. The waves you’re seeing in the video are the same waves you’re seeing in the other video, translated through a National Weather Service API and fifteen years of living on the East Coast. The relative scale between these things is about right, don’t you think? Some things are hard to let go, even when they’ve been reduced by time to a tiny picture-in-picture in your memory. I’m reconstructing this using random sinusoidal functions. I’m reconstructing this using a prejudicial feeling that ascetic minimalism, only tighter, only more monochrome, is the only way ethically correct, and accurate, way to model a place like this. I’m reconstructing this memory using another memory. Of something I was never here for. Poorly.

There is also a basin of water, with a bright light pointing into it, reflecting the surface of the water onto the wall. There is a contact speaker attached to the bottom of the basin, playing a filter-swept noise generator that sounds like waves. When the sound gets loud enough, it makes a little pump drip water into the basin from above, and ripples show up on the wall. You’re going to have to trust me here. The pictures didn’t come out. The pictures didn’t come out. But the idea was for it to look something like this:It, of course, didn’t look like this. This is a theater piece I saw maybe ten years ago, with an old friend I don’t get to see much any more– a person whose name starts with D, and for that reason or maybe some other, I would occasionally accidentally call him “dad”. It was very snowy– we made it to the theater at the last section, far up on the Upper East Side, far from everything. I’ve been thinking about it ever since. My friend said it was one of those singular experiences you’ll never forget, that you only get a handful of, and that made me feel proud to have been able to get him the ticket. The key about this show is it’s about memory, but more crucially that there are no people in it.

But, unfortunately, there are people in every room. The concept of “room” implies people, and so you find them there. Speaking of which: the drips from the pump. During critique for this piece, a professor asked me if the timing of the waves and drips was related in any way to the timing and the structure of the video. It’s not. But he asked it in such an aggressive, dismissive way that I lied about it– now, I lied in a way that didn’t make the piece any more conceptually coherent, of course, making some additional claim about the API that really didn’t make any difference. But it felt good to lie to him.

Here’s the code for the max patch:

<pre><code>
----------begin_max5_patcher----------
1342.3ocyZ0zbhaCF9L7qviO1kFrrrMvdnW5N6zCcu0sW5rSFgQPzFgkqkbR
n6D9sWYIYBjXqnrHfbHFirhezy6GOuuxleLbP3b1CXdXvGC9mfAC9wvACTC0
Lv.y2GDtF8PNEwUSKrjh1PIbw1vQ5qVTulTPwB0kAOMHqVzNZpYzRjH+FRwp
qqv4BMnooWEMJHY1jlO.oQMe.kGC9l4+grPAKa92+U.D1Bp9lK1Th02lPNYU
AhFNp6yZ9aAIWPXEnpMg6t4bwFp5ND1diWfDHC6MzePXNkTtyFs2EjWZIghK
Pq02iufxIEBF+lf+3Seb7W43J9X7bbwMrkKwUi+DKudMtPvG+6e4qAelQWTo
OCQoAfIi+a4BjUsY7mYL4bP0KHrw+I69f+hUfu5dzclkXKr2RJzlF0LaFYuI
PYrx87GJVvJDRzulKPBbKE2mLRyAstRPVaro64ETWcNhKWg0ERGndBIIGNgk
LJkc+JJaNhJvqKYl6yylT0ZTgHmU0DDHcHcMo+sFQIhMFeqB3vClPIQFIwug
rzDFAd1ZkUQVQjNeo2Yk3l07tYzZ1Bb+XvKw3Ece6aRB5Zc2X73hJrbw00kO
bUsaMICNEj7a4cPQ6lIisztIXOOAHVYAZmyiCG1dhYP8HpiONbjiJBRJyQqZ
i9BE3GTqHYZCii6TkHtSUBP+pDvoPkLQlRl.Nq4Xbb2pDS6WjnyDeOxXVItv
SDNBnHb5TEgmXivYSO4DVvVshheCJ9Vn1Lk2KQSv3j1icwrz9YFoIr+a6PoR
pAKvUWKEimq4YjWHdA9d4B4EN5eSl1NyOdZs4.JirSkeL0liNMwMywwQ4kTl
bw+F70wuJ4fph75h68RNKosiZzmap57Fc3lQTxjpUTl+BAJwnaQqK2FDmF40
HgHkT2L6FqndMVR2GxawB8vcYmMDDMXdvrrnH+Do.lk0P3rDUFvDqJ7I1kEF
4OcuyG+0N+3rTGn+jKL8+PSSK.+DzCln67OKVUUHwJwgmon950ywUdJtVWmy
vO6Rfvo9WBzmdcoRmmj5ZsJ55cIVq5AyNGU85gzKppKtUtbihjG5j6veVtGo
RxmZs0NX5Ej6iU79J+lma731Y8Yp5lO6zokeSm8544wydm1piOay2XPLdZqs
4GO4cZa9RvpXMYAdMGPWcWWou2Pj9S7OL73zp5Ej5IMOS1gVyah0p7fKol2G
j8y6K2cJPKzOK40KxARdsmr4IVqWxa+xZnpgGHvJqgWVVK81.+x5HUVMzZtM
H9bwZO1GahtvFLF9502l8dtM1eYqbK19NE2zcer0GS2kMVOeSNEusYmaodk6
Zw7IVod5kk576Vt8MTGKwxikMQ8TJh0jVlEjZY2p+juqJ+ZRv+2BT912fGOp
e1GCMpaY5mMc6wN6gO7T5QKXDNdqeZTs0mBLuhAqR2GYfr5xgTRwyemqp0Uy
3GZK3r5p7VHZe4FO8RfBWf4BRA5o2OztmOVf4877B6sqHkM8rgjC.0zezQCT
5YiRoINfTpWPxk.hTuX8hbAInOPxk.hXO.ThKFulcqe7H4hs6PCLqZgr4sFc
5SNxvtAFbV.F7RfiNJfgtjlmoQ93.xEkKnOxxgtjRztbNNjbIKOwGY4s4U1y
I7APSbIK2KH4jaJ8Tjs4Dzfdf93x2.Nw5HOXeAtnoj3gLa0uzLWkM8.R.2zI
ORjbTV7noTrKghdw34X3vg3naBGUVdGthalrBB4VO9NSkPLYj5qjB8WU6SLr
BeGoc9peQignJ4lIDxcRTWo60+go5c4q9kkUUTSLI1Rjeb3+CYljYjC
-----------end_max5_patcher-----------
</code></pre>

And while we’re at it, here’s the code for the P5.js wave modeler:

var weather;
const tideURL = 'https://www.tidesandcurrents.noaa.gov/api/datagetter?date=latest&station=9437540&product=one_minute_water_level&datum=MLLW&time_zone=lst&units=english&format=json';
const waveURL = 'https://api.weather.gov/gridpoints/PQR/46,124';
const canvasHeight = 800;
const canvasWidth = 1280;
const wallHeight = 10.0;
const wallBottom = 3;
const numWaves = 4;
const zeroPoint = canvasHeight - (canvasHeight/(wallHeight+wallBottom)*wallBottom);
var ampCtr = 10;
var newAmpCtr = 10;
var waterHeight;
var newWaterHeight;
var xSpacing;

var serial;
var portName = '/dev/tty.usbmodem14201'; 
var inData;                            
var outByte = 0;  

let waves = [];
let period = 500.0;
let fontsize = 20;
var time = "";
var name = "";

function preload(){
    askNOAA();
}

function setup() {
  waterHeight = newWaterHeight;
  ampCtr = newAmpCtr;
  createCanvas(canvasWidth,canvasHeight);
  serial = new p5.SerialPort();
  //serial.on('data', serialEvent);
  //serial.on('error', serialError);
  serial.open(portName); 
  setInterval(askNOAA, 60000);
  setInterval(serialDrip, 1000);
  for (let i=0; i<numWaves; i++) {waves[i] = new wave();}
  textSize(fontsize);
}

function wave(){
  this.size = Math.floor(Math.random()*10+7);
  this.offset = +(Math.random()*6.3).toFixed(2);
  this.speed = +(Math.random()/100).toFixed(5)+0.001;
  this.shade = Math.floor(Math.random()*75)+180;
  this.yVals = [];
  this.theta= 0;
  this.ampVar = Math.random()*ampCtr-ampCtr/2;
  this.amp = ampCtr + this.ampVar;
}

function askNOAA(){
  loadJSON(tideURL, gotTide);
  loadJSON(waveURL, gotWave);
}


function gotTide(data){
  weather = data;
  if (weather){
    newWaterHeight = (weather.data[0].v);
    newWaterHeight = map(newWaterHeight, 0.0, wallHeight, 0, canvasHeight);
    newWaterHeight = newWaterHeight.toFixed(2);
    name = weather.metadata.name;
    time = weather.data[0].t;
  }
}

function gotWave(data){
  weather = data;
  if (weather){
    waveHeight = (weather.properties.waveHeight.values[0].value);
    waveHeight = waveHeight * 3.28;
    if  (waveHeight !=0){
      newAmpCtr = Math.floor(waveHeight*(wallHeight+wallBottom));
    }
  }
}

function serialDrip(){
  serial.write("hello");
 // s = ['A','B','C','D'];
  //i = Math.floor(Math.random()*4)
  //Serial.write(s[i]);
}

function draw() {
  increment();

  background(0);
  for (let wave of waves){
    calcWave(wave);
    drawWave(wave);
  }
  drawText();
}

function increment(){
  if(waterHeight < newWaterHeight) waterHeight+=.01;
  else if (waterHeight > newWaterHeight) waterHeight -=.01;
  if (ampCtr<newAmpCtr) ampCtr++;
  else if (ampCtr<newAmpCtr) ampCtr--;
  for (let wave of waves){
    wave.amp = ampCtr + wave.ampVar;
    }

}


function calcWave(wave){
  var w = canvasWidth+wave.size;
  dx = (3.14159*2 / period)*wave.size;
  wave.theta += wave.speed;
  let x = wave.theta;
   for (let i=0; i <= w/wave.size; i++){
     wave.yVals[i] = sin(x+wave.offset)*wave.amp + (zeroPoint-waterHeight);
     x+=dx;
   }
}

function drawWave(wave){
  noStroke();
  fill(wave.shade);
  for (x=0; x<wave.yVals.length; x++){
    ellipse(x*wave.size, wave.yVals[x], wave.size, wave.size);
  }
  //yValues = [];
}

function drawText(){
  textAlign(RIGHT);
  text(name + " | " + time, canvasWidth, canvasHeight-10);
  textAlign(LEFT);
  let divisions = canvasHeight/(wallHeight+wallBottom);
  let n = -wallBottom;
  for (let i=canvasHeight;i>0;i-=divisions){
    text('> '+n, 0, i);
    n++;
  }
}

And as for the Arduino that controlled the pump, it was just a single transistor switching a 12v power supply, triggered over the serial port from Max. With some basic filtering to make less like the sky was peeing into the basin. Code:

const int buttonPin = 2;
const int pumpPin = 9;
const int ledPin = 13;
int newByte;
int lastByte;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(pumpPin, OUTPUT);
  pinMode(ledPin, OUTPUT);

}

void loop() {
  if (Serial.available()){
    newByte = Serial.read();

    if (newByte == lastByte) newByte = 0;
  
    if (digitalRead(buttonPin) == HIGH || newByte == 1){
      digitalWrite(ledPin, HIGH);
      digitalWrite(pumpPin, HIGH);
    } else{
      digitalWrite(ledPin, LOW);
      digitalWrite(pumpPin, LOW);
    }
    lastByte = newByte;
  }
}

They say you can never go home, because it’s always different. Which is of course true: people change and times change and cities undergo massive gentrification driven by an insane belief that unyielding and constant growth is an unimpeachable positive that will continue to be sustainable for the same amount of time that human civilization has existed thus far. And besides, your parents get old and die, and your friends move, or lose their minds, or slowly disappear into themselves; and maybe you realize that nothing ever made any sense, and indeed that’s the one constant through all of this.

On the other hand, for all its environmentalist overtones, isn’t that a remarkably anthropocentric way to look at the world? Decay is a constant, and you’re part of it. Standing at the upper lip of a waterfall watching the freezing white water whip past, one notices that the water is always different, and the rock always smoothing and decaying, the gorge filled with fallen trees that decay and rejoin, your feet the same stupid feet standing and supporting your towering eyes, the feet that won’t stop walking despite mounting evidence that the contrary would be a better move– what makes these things is constantly in flux, never the same, always immaterial, and yet we try and call it by the same name as long as we possibly can.

Life is, properly, a curse: inescapable, defining, visited upon you when you weren’t paying attention, destined to define your ultimate end. Comforting in its familiarity, becoming ‘you’ through lack of any other serious offers.
The water comes and goes, and comes, and goes.