/* by nick lally, with help from: Background Subtraction by Golan Levin. */ import processing.serial.*; int[] x = new int[25]; int[] y = new int[25]; int[] time = new int [25]; float[] speed = new float[25]; float[] radius = new float[25]; float[] speedX = new float[25]; String inString; Serial port; int xval = 0; int yval = 0; int NEWLINE = 10; String buff=""; import processing.video.*; import rwmidi.*; // midiNote in C int [] midiNote = {35, 36, 38, 40, 41, 43, 45, 47, 48, 50, 52, 53, 55, 57, 59, 60, 62, 64, 65, 67, 69, 72, 74, 76, 77}; MidiInput input; MidiOutput output; //start with no music mode selected to avoid noise int musicMode = 0; // colorSensor coords int [] colorSensorX = new int[midiNote.length]; int [] colorSensorY = new int[midiNote.length]; int count = 0; int backgroundCount = 0; int midiCount = 0; int numPixels; int[] backgroundPixels; int[] backgroundPixels2; Capture video; Capture video2; void setup() { // Change size to 320 x 240 if too slow at 640 x 480 size(640, 480, P2D); String[] devices = Capture.list(); println(devices); video = new Capture(this, width, height, devices[1], 24); video2 = new Capture(this, width, height, devices[2], 24); numPixels = video.width * video.height; // Create array to store the background image backgroundPixels = new int[numPixels]; backgroundPixels2 = new int[numPixels]; // Make the pixels[] array available for direct manipulation loadPixels(); println("Available serial ports:"); println(Serial.list()); // Uses the first port in this list (number 0). Change this to // select the port corresponding to your Arduino board. The last // parameter (e.g. 9600) is the speed of the communication. It // has to correspond to the value passed to Serial.begin() in your // Arduino sketch. port = new Serial(this, Serial.list()[1], 9600); //populate circle arrays for(int i = 0; i < x.length; i++) { //set start positions x[i] = int(random(width)); y[i] = 0; //set radius radius[i] = i * 4; //set speed speed[i] = random(2, 10); //set x-speed speedX[i] = random(.5); time[i] = 0; } output = RWMidi.getOutputDevices()[0].createOutput(); } void draw() { if (video.available()) { //read arduino while (port.available() >0 ){ serialEvent(port.read()); } //println(xval); video.read(); // Read a new video frame video2.read(); // Read a new video frame video.loadPixels(); // Make the pixels of video available video2.loadPixels(); // Make the pixels of video available // Difference between the current frame and the stored background int presenceSum = 0; for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame... // Fetch the current color in that location, and also the color // of the background in that spot color currColor = video.pixels[i]; color currColor2 = video2.pixels[i]; color bkgdColor = backgroundPixels[i]; color bkgdColor2 = backgroundPixels2[i]; // Extract the red, green, and blue components of the current pixel’s color int currR = (currColor >> 16) & 0xFF; int currG = (currColor >> 8) & 0xFF; int currB = currColor & 0xFF; int currR2 = (currColor2 >> 16) & 0xFF; int currG2 = (currColor2 >> 8) & 0xFF; int currB2 = currColor2 & 0xFF; // Extract the red, green, and blue components of the background pixel’s color int bkgdR = (bkgdColor >> 16) & 0xFF; int bkgdG = (bkgdColor >> 8) & 0xFF; int bkgdB = bkgdColor & 0xFF; int bkgdR2 = (bkgdColor2 >> 16) & 0xFF; int bkgdG2 = (bkgdColor2 >> 8) & 0xFF; int bkgdB2 = bkgdColor2 & 0xFF; // Compute the difference of the red, green, and blue values int diffR = abs(currR - bkgdR); int diffG = abs(currG - bkgdG); int diffB = abs(currB - bkgdB); int diffR2 = abs(currR2 - bkgdR2); int diffG2 = abs(currG2 - bkgdG2); int diffB2 = abs(currB2 - bkgdB2); // Add these differences to the running tally presenceSum += diffR + diffG + diffB; //render difference to grey if(((diffR + diffG + diffB) > 150) || ((diffR2 + diffG2 + diffB2) > 150)){ pixels[i] = color(100); //if both are different, render red if(((diffR + diffG + diffB) > 150) && ((diffR2 + diffG2 + diffB2) > 150)){ pixels[i] = color(255, 0, 0); } } else { pixels[i] = color(255); } } updatePixels(); // Notify that the pixels[] array has changed //draw circle for (int i = 0; i < x.length; i++) { //change x x[i] += speedX[i] * xval; //change y y[i] += speed[i]; //check pixel for grey color p = get(x[i], y[i]); float r = red(p); float g = green(p); //draw circles fill(255); stroke(140); strokeWeight(3); ellipse (x[i], y[i], radius[i], radius[i]); //if pixel is red, reset circle, play note and start timer if (r == 255 && g == 0) { y[i] = 0; x[i] = int(random(width)); speed[i] = random(2, 10); output.sendNoteOn(0, midiNote[i], 100); time[i] = time[i] + 1; //starts timer println(time[0]); } if (time[i] > 0){ time[i]++; } if (time[i] > 15){ time[i] = 0; output.sendNoteOff(0, midiNote[i], 100); println("note off"); } } //redraw circles when off screen for (int i = 0; i < x.length; i++) { if (y[i] > height+100) { y[i] = 0; x[i] = int(random(width)); speed[i] = random(2, 10); } } //println(presenceSum); // Print out the total amount of movement } //println(midiNote.length); //image(video2, 0, 0); } // Check for pressed key. 1, 2, 3 change music mode, everything else runs backgroundCapture() void keyPressed() { if (key == '1') { musicMode = 1; output.sendNoteOn(6, 60, 100); }else if (key == '2') { musicMode = 2; output.sendNoteOn(6, 60, 100); }else if (key == '3'){ musicMode = 3; output.sendNoteOn(6, 60, 100); }else if (key == '4'){ musicMode = 4; output.sendNoteOn(6, 60, 100); }else{ backgroundCapture(); } //send off notes to all channels for (int i = 0; i< midiNote.length; i++) { output.sendNoteOff(0, midiNote[i], 100); output.sendNoteOff(1, midiNote[i], 100); output.sendNoteOff(2, midiNote[i], 100); output.sendNoteOff(3, midiNote[i], 100); output.sendNoteOff(4, midiNote[i], 100); output.sendNoteOff(5, midiNote[i], 100); } output.sendNoteOff(6, 60, 100); } void mousePressed() { backgroundCapture(); //send off notes to all channels for (int i = 0; i< midiNote.length; i++) { output.sendNoteOff(0, midiNote[i], 100); output.sendNoteOff(1, midiNote[i], 100); output.sendNoteOff(2, midiNote[i], 100); output.sendNoteOff(3, midiNote[i], 100); output.sendNoteOff(4, midiNote[i], 100); output.sendNoteOff(5, midiNote[i], 100); } } //capture the background image into the backgroundPixels // buffer, by copying each of the current frame’s pixels into it. void backgroundCapture(){ video.loadPixels(); arraycopy(video.pixels, backgroundPixels); video2.loadPixels(); arraycopy(video2.pixels, backgroundPixels2); } void serialEvent(int serial) { if(serial != NEWLINE) { buff += char(serial); } else { char c = buff.charAt(0); buff = buff.substring(1); // Discard the carriage return at the end of the buffer buff = buff.substring(0, buff.length()-1); // Parse the String into an integer //if (c == 'X') //yval = Integer.parseInt(buff); if (c == 'Y') xval = Integer.parseInt(buff);; // Clear the value of "buff" buff = ""; } }