Enter Sandman


We listen every day to the specters of many living artists and also dead. Technology allows us to preserve their thoughts and feelings in the form of waveforms and also as words.

When I was turning 18 I received my first dose of Morphine. A friend gave me my first Morphine cd. I can still recall the moment when I played the record on my sisters Sony silver portable player. It was real, real love… Love at first listen… I then started downloading music from this amazing band as crazy as a Morphine Junkie looking for the next hit. When I was able to go to Tower Records to look for their other records I was so happy to spend my aunts birthday money on them. Suddenly I read “Dedicated to Mark Sandman” and then I see: “Mark Sandman, 2 string bass and vocals” then after some neural activity my blood was cold… I felt the shock of losing a very close person who I never met before.  I found out he died at a young age. He took a plunge to the other side as only true rockstar do: he died on stage from a heart attack.

Here, we are summoning the spirit of Mark Sandman. The goal is to share his unique, fun, controversial, sometimes poetic, other times funny, or spicy or fun, as life itself.  He almost fulfilled his wish of sitting on his back porch in 9, 9 , 1999 singing french fries with pepper!. But he didn’t, he passed a couple of months earlier to that date. So now we are giving him some nice as a way to trade it for some of his words and thoughts, that thanks to technology allow him to exist in a virtual way among us.

For this purpose, we are relaying now on computer vision, pepper and some lines of magic spells, also known as code. All randomness in this magical system comes from the physical action of the computer counting pepper and Mr Sandmans spirit assigning a phrase to that number.

This project plays with different ideas such as the practice of Necromancy, in a metaphorical way.  Also with the idea of the ready-made and the practice of decontextualizing, and the idea of appropriation. Concepts inherited from the avant-garde times. Also from the idea of the monument to commemorate the life of an important person and to keep his memory. The idea of the monument as a way to raise interest in the work done by Mark Sandman.

If you are curious about Mark, a good way to start to know about him could be looking at this article about him from the Washington Post. But also I would advise you to listen to his music on YouTube or other web music platforms. There’s also a documentary called “Morphine, a Journey of dreams”. I would definitely advise you to listen to Morphine’s last record “The night”, with a great stereo or headphones.


The technical process

The process for the code was tricky. The problem to be solved was how to use the “random” number that came from counting the pepper and being able to use it to match the range of the phrases from the songs from Mark Sandman’s lyrics. Using the random function from the computer was a possibility, but it was an easy and boring solution.  And we also wanted the result to be linked closely to the pepper’s amount. So after some thinking, I realized I could use a list of different JSON files, each from a single song, and then use the pepper count number again inside the selected song JSON file. Another issue was the problem of having a larger pepper count number than the amount of JSON song files and of lines inside the son JSON song files. After days of code struggle and headaches and suffering, I could finally write a  for loop to change the position inside the array if the incoming pepper count number was larger then the JSON array size.

Another issue at first was working with JSON files. I didn’t realize the importance of the end the lines until I had formatted almost 30 songs. After struggling with incomprehensible mistakes I finally understood how they had to be written, and how a missing coma or double quote could mean a total disaster. I heard Marks Sandmans voice in my mind singing “Have patience, everything will be alright”

The physical part

The next problem to solve was the physical part. I figured out that I needed specific requirement for the code to work. The hat needed to have enough distance to be able to have a proper pepper count reading and also to be able to show an interesting ambiguous “spectral-looking” image.  So the initial simple design had to be modified, and a box was required to solve this issue.  There’s still work to do to make it a more sophisticated and good looking device.  A better visual design for the interface is also needed.

The interaction with the user

The interaction from taping the hat is interesting and works. Some voice recognition could be added to make it better and more magical. Also by adding the sound output to the text would be great.


The Proccesing magic spell:

This code has been written thanks to the help of Danny Rozin, Lisa Jamhoury, Daniel Castano and Leon Eckert!!!
It requires the OPENCV for Processing library installed

import processing.video.*;
import gab.opencv.*;
import processing.pdf.*;
import processing.serial.*;
//Pi mage is a way of refering to images by open cv
PImage src;
OpenCV opencv;
Capture video;
int count = 0;
ArrayList<Contour> contours;
Serial myPort;
//images array
//PImage[] images = new PImage[10]; FOR USING WITH THE DIE
//PImage[] images = new PImage[70];
//PImage img = new PImage();
//inicialize random
//int imageNumber; // **** (is going to be used as the open cv number)

//ArrayList<DrawDice> drawDiceResults;
JSONArray introWords; //frases de instrucciones
String introWordsLine=””;
JSONArray songs; // jason array de coleccion de canciones
String line=””; //linea de la cancion que va a ser seleccionada
JSONArray hiSandman; // mensaje de saludo de Mark #1
String hiSandmanLine=””;
JSONArray sandmanSays; // mensaje de saludo de Mark #1
String sandmanSaysLine=””;

void setup() {
size(1900, 1200);

myPort = new Serial(this, Serial.list()[7], 9600); // 7 puede cambiar segun el puerto de conexion

String[] cameras=Capture.list();
if (cameras.length == 0) {
println(“There are no cameras available for capture.”);
} else {
println(“Available cameras:”);
for (int i = 0; i < cameras.length; i++) {
println(“Id: ” + i + “–> ” +cameras[i]);

video = new Capture(this, 960, 540, cameras[19], 15); //camera id(19) 15 (frame rate)match the space for open cv to work to the same camera space
opencv = new OpenCV(this, 960, 540);

hiSandman = loadJSONArray(“hisandman.json”); // my name is mark, do you like french fries?
sandmanSays = loadJSONArray(“sandmansays.json”); // hey,
songs = loadJSONArray(“alltexts.json”);

void draw() {
background (0);

opencv.useGray(); // turn our pic to grayscale
image(video, 444 , 230, 950, 750); // visualize the open cv filtered image
fill(255, 255, 255, 200);
text(“Hello my name is Mark Sanman, I used to play with a band called Morphine, but crossed to the other side in 1999. My spirit lives now as data inside this computer.”, 160, 60);
text(“All I eat now are imaginary french fries, but I would appreciate nice and spicy real pepper, so I can turn it into ghost pepper!”, 280, 105);
text(“Pour some pepper on a plate for me. Soflty whisper Sandman and tap the top of the hat and I’ll tell you whats going through my mind”, 395, 155);

fill(255, 255, 255, 200);
text(line, 50, 1050); // hisandman
fill(255, 255, 255, 200);
text(hiSandmanLine, 720, 195); // hisandman
text(sandmanSaysLine, 850, 1111); // hisandman


void mousePressed() { //change for serial event using read line

void serialEvent(Serial p) {
String inString = p.readString();
if (inString.equals(“s”)){

void doProcess(){

opencv.threshold(205); //opencv.threshold(225); // dice and water and oil and paper tolerance adjustment for the blob recognition with open cv.

opencv.blur(1); //opencv.blur(11); //for water and oil and paper

contours = opencv.findContours(); // tell opencv to find the contours and return as an array list
int countPepperGrounds=0; //count blobs
for (Contour thisContour : contours) { // visit all elements of the array list “contour” naming each one as “thisContour”
stroke(204, 102, 0);
countPepperGrounds=countPepperGrounds+1; //count++;
if(countPepperGrounds == 0){ // to prevent that counter = 0


// *** code below working only with open cv random using blob count
int songSelector= (countPepperGrounds-1)%songs.size(); // number will always be between 0 and the total size of the array
JSONArray songLines = songs.getJSONArray(songSelector); //-1 == correccion de la cuenta SELECTING THE SONG FROM THE ARRAY LIST (FIRST FILTER)
// print(song);

int songLineSelector = (countPepperGrounds-1)%songLines.size();
line = songLines.getString(songLineSelector); // Line is declared as a global variable so we can called in daw functionSELECTING LINES FROM THE SELECTED SONG
// println(line);

int hiSandmanSelector = (countPepperGrounds-1)%hiSandman.size();
hiSandmanLine = hiSandman.getString(hiSandmanSelector);

// println(hiSandmanLine);

int sandmanSaysSelector = (countPepperGrounds-1)%sandmanSays.size();
sandmanSaysLine = sandmanSays.getString(sandmanSaysSelector); // SELECTING LINES FROM THE SELECTED SONG

// println(sandmanSaysLine);


void captureEvent(Capture c) {

Leave a Reply

Your email address will not be published. Required fields are marked *