import processing.video.*; import oscP5.*; import netP5.*; import processing.video.*; import controlP5.Button; import controlP5.ControlP5; import controlP5.ControlEvent; import controlP5.ControlBehavior; import controlP5.Slider; import controlP5.Toggle; import controlP5.Knob; import controlP5.Textfield; final static int MOTION_THRESHOLD = 100; static int RECEIVE_PORT = 57128; static int SEND_PORT = 57129; OscP5 oscReceiver; OscP5 oscSender; NetAddress remoteLocation; ControlP5 cp5; Capture video; PImage prevFrame; Slider ySlider; Slider[] gainSliders = new Slider[8]; Knob[] panKnobs = new Knob[8]; Textfield panKnobField; Textfield panKnobTargetField; Slider reverbSlider; Slider playRateSlider; Slider volumeSlider; //Slider acczSlider; Slider grainSizeSlider; Textfield grainSizeField; Slider grainSizeRandSlider; Slider playRateRandSlider; Slider playPosRandSlider; Toggle enableCamToggle; Toggle playRateToggle; Toggle gainToggle; Button clearButton; Button normalButton; Button distributeButton; Button sp1Button; int WIDTH = 1200; int HEIGHT = 800; void setup() { size(WIDTH , HEIGHT); video = new Capture(this, width, height, 30); video.start(); // Create an empty image the same size as the video prevFrame = createImage(video.width,video.height,RGB); oscReceiver = new OscP5(this, RECEIVE_PORT); oscSender = new OscP5(this, SEND_PORT); remoteLocation = new NetAddress("127.0.0.1", SEND_PORT); cp5 = new ControlP5(this); for (int i = 0; i < 8; i++) { panKnobs[i] = cp5.addKnob("panKnob" + String.valueOf(i)).setPosition(400 + i * 50, HEIGHT - 100).setRange(-1, 1); panKnobs[i].setColorCaptionLabel(255); panKnobs[i].setRadius(30); } for (int i = 0; i < 8; i++) { gainSliders[i] = cp5.addSlider("gain" + String.valueOf(i)).setPosition(400 + i * 50, HEIGHT - 300).setRange(0, 1).setSize(20, 100); gainSliders[i].setColorCaptionLabel(255); gainSliders[i].setValue(0.0); } panKnobField = cp5.addTextfield("pan Knob").setPosition(400, HEIGHT - 160).setSize(50,20); panKnobField.getCaptionLabel().setColor(100); panKnobTargetField = cp5.addTextfield("pan Knob Target").setPosition(470, HEIGHT - 160).setSize(50,20); panKnobTargetField.getCaptionLabel().setColor(100); sp1Button = cp5.addButton("spatialize") .setPosition(560, HEIGHT - 160) .setSize(70, 40); reverbSlider = cp5.addSlider("reverb").setPosition(350, HEIGHT - 150).setSize(20, 100) .setRange(0, 0.1).setColorValueLabel(100).setValue(0.05); reverbSlider.getCaptionLabel().setColor(100); ySlider = cp5.addSlider("ySlider").setPosition(20, 0).setSize(20, 100) .setRange(0, HEIGHT); ySlider.setColorValueLabel(100); ySlider.setValue(50.0); enableCamToggle = cp5.addToggle("enableCamToggle", false, 20, 120, 20, 20); grainSizeSlider = cp5.addSlider("grainSizeSlider").setPosition(WIDTH - 500, 0).setSize(700, 20) .setRange(0, 2000).setCaptionLabel("Grain Size"); grainSizeSlider.setValue(50.0); grainSizeField = cp5.addTextfield("grainSizeField").setPosition(WIDTH - 300,30).setSize(50,20); grainSizeRandSlider = cp5.addSlider("grainSizeRandSlider").setPosition(WIDTH - 100, HEIGHT - 150).setSize(20, 100) .setRange(0, 1).setCaptionLabel("Grain Size Rand"); grainSizeRandSlider.getCaptionLabel().setColor(100); grainSizeRandSlider.setColorValueLabel(100); playRateSlider = cp5.addSlider("playRateSlider").setPosition(20, 350).setSize(500, 20) .setRange(0, 2).setCaptionLabel("Play Rate"); playRateSlider.getCaptionLabel().setColor(100); playRateSlider.setColorValueLabel(100); playRateSlider.setValue(1); playRateRandSlider = cp5.addSlider("playRateRandSlider").setPosition(100, 380).setSize(20, 100) .setRange(0, 1).setCaptionLabel("Play Rate Rand"); playRateRandSlider.getCaptionLabel().setColor(100); playRateRandSlider.setColorValueLabel(100); playRateRandSlider.setValue(0.2); playPosRandSlider = cp5.addSlider("playPosRandSlider").setPosition(20, 200).setSize(20, 100) .setRange(0, 1).setCaptionLabel("Play Pos Rand"); playPosRandSlider.getCaptionLabel().setColor(100); playPosRandSlider.setColorValueLabel(100); playPosRandSlider.setValue(0.5); volumeSlider = cp5.addSlider("volumeSlider").setPosition(100, 0).setSize(20, 100) .setRange(0, 1).setCaptionLabel("Volume"); volumeSlider.getCaptionLabel().setColor(100); volumeSlider.setColorValueLabel(100); volumeSlider.setValue(0.5); playRateToggle = cp5.addToggle("playRateToggle", false, 20, 470, 20, 20); gainToggle = cp5.addToggle("gainToggle", false, 100, 120, 20, 20); clearButton = cp5.addButton("clear") .setPosition(WIDTH / 2, 20) .setSize(30, 40); normalButton = cp5.addButton("normal") .setPosition(WIDTH / 2, 120) .setSize(50, 40); distributeButton = cp5.addButton("distribute") .setPosition(WIDTH / 2 + 100, 640) .setSize(70, 40); distribute(); } void distribute() { for (int i = 0; i < 8; i++) panKnobs[i].setValue((float)i / 4.0 - 1.0 + 0.01); } class SpatialBehavior extends ControlBehavior { int interval = 250;//ms long startTime = millis(); final float step = 0.05; float target; boolean enabled = true; SpatialBehavior(float target) { this.target = target; enabled = true; } public void update() { float value = getController().getValue(); if (enabled && millis() - startTime > interval) { if (target - value > step && value < (1 - step) ) getController().setValue(value + step); else if (value - target > step && value > (step - 1) ) getController().setValue(value - step); else enabled = false; startTime = millis(); } } }; void spatialize(String panNumString) { int panNum= Integer.parseInt(panKnobField.getText()); float target = Float.parseFloat(panKnobTargetField.getText()); if (panNum == -3) for (int i = 0; i < 8; i++) panKnobs[i].setBehavior(new SpatialBehavior(target)); else if (panNum == -1) for (int i = 0; i < 4; i++) panKnobs[i].setBehavior(new SpatialBehavior(target)); else if (panNum == -2) for (int i = 4; i < 8; i++) panKnobs[i].setBehavior(new SpatialBehavior(target)); else panKnobs[panNum].setBehavior(new SpatialBehavior(target)); } void controlEvent(ControlEvent event) { OscMessage oscMessage; if(event.isController()) { if(event.controller().name()=="clear") { oscMessage = new OscMessage("/ccc"); oscSender.send(oscMessage, remoteLocation); System.out.println("clear sent"); volumeSlider.setValue(0); } if(event.controller().name()=="normal") { playRateSlider.setValue(1.0); playRateRandSlider.setValue(0.0); playPosRandSlider.setValue(0.0); } if(event.controller().name()=="distribute") { distribute(); } if(event.controller().name()=="spatialize") { int panNum = 3; spatialize("0"); } if(event.controller().name().startsWith("gain")) { float gain = event.controller().value(); oscMessage = new OscMessage("/gain"); String[] parts = event.controller().name().split("gain"); oscMessage.add(Integer.parseInt(parts[1])); oscMessage.add(gain); oscSender.send(oscMessage, remoteLocation); System.out.println("gain sent"); } if(event.controller().name().startsWith("panKnob")) { float pan = event.controller().value(); oscMessage = new OscMessage("/pan"); String[] parts = event.controller().name().split("panKnob"); oscMessage.add(Integer.parseInt(parts[1])); oscMessage.add(pan); oscSender.send(oscMessage, remoteLocation); System.out.println("pan sent"); } if(event.controller().name()=="reverbSlider") { float reverb = event.controller().value(); oscMessage = new OscMessage("/reverb"); oscMessage.add(reverb); oscSender.send(oscMessage, remoteLocation); System.out.println("reverb sent"); } if(event.controller().name()=="playRateSlider") { float x = event.controller().value(); oscMessage = new OscMessage("/accx"); oscMessage.add(x); oscSender.send(oscMessage, remoteLocation); System.out.println("x sent"); } if(event.controller().name()=="volumeSlider") { float volume = event.controller().value(); System.out.println(volume); for (int i = 0; i < 8; i++) gainSliders[i].setValue(volume); } if(event.controller().name()=="grainSizeField") { String grainSizeString = grainSizeField.getText(); System.out.println(grainSizeString); grainSizeSlider.setValue(Float.parseFloat(grainSizeString)); } if(event.controller().name()=="grainSizeSlider") { float grainSize = event.controller().value(); oscMessage = new OscMessage("/grainSize"); oscMessage.add(grainSize); oscSender.send(oscMessage, remoteLocation); System.out.println("grainSize sent"); } if(event.controller().name()=="grainSizeRandSlider") { float grainSizeRand = event.controller().value(); oscMessage = new OscMessage("/grainSizeRand"); oscMessage.add(grainSizeRand); oscSender.send(oscMessage, remoteLocation); System.out.println("grainSizeRand sent"); } if(event.controller().name()=="playRateRandSlider") { float playRateRand = event.controller().value(); oscMessage = new OscMessage("/playRateRand"); oscMessage.add(playRateRand); oscSender.send(oscMessage, remoteLocation); System.out.println("playRateRand sent"); } if(event.controller().name()=="playPosRandSlider") { float playPosRand = event.controller().value(); oscMessage = new OscMessage("/playPosRand"); oscMessage.add(playPosRand); oscSender.send(oscMessage, remoteLocation); System.out.println("playPosRand sent"); } } } void draw() { // super.draw(); boolean motionDetected = false; int minY = HEIGHT; int minX = WIDTH; int m = 0; if (video.available()) { // Save previous frame for motion detection prevFrame.copy(video,0,0,video.width,video.height,0,0,video.width,video.height); prevFrame.updatePixels(); video.read(); } loadPixels(); video.loadPixels(); prevFrame.loadPixels(); for (int x = 0; x < video.width; x ++ ) { for (int y = 0; y < video.height; y ++ ) { int loc = x + y * video.width; int displayLoc = WIDTH - x - 1+ y*video.width; color current = video.pixels[loc]; color previous = prevFrame.pixels[loc]; // Step 4, compare colors (previous vs. current) float r1 = red(current); float g1 = green(current); float b1 = blue(current); float r2 = red(previous); float g2 = green(previous); float b2 = blue(previous); float diff = dist(r1,g1,b1,r2,g2,b2); m += diff; if (diff > MOTION_THRESHOLD) { // If motion, display black pixels[displayLoc] = color(0); if (minY > y) minY = y; if (minX > x) minX = x; motionDetected = true; } else { // If not, display white pixels[displayLoc] = color(255); } } } if (motionDetected && enableCamToggle.getState()) { int finalX = WIDTH - minX; int finalY = HEIGHT - minY; ySlider.setValue(finalY); OscMessage oscMessage; oscMessage = new OscMessage("/cam/motion/x"); oscMessage.add((float)finalX / WIDTH); oscSender.send(oscMessage, remoteLocation); oscMessage = new OscMessage("/cam/motion/y"); oscMessage.add((float)finalY / HEIGHT); oscSender.send(oscMessage, remoteLocation); volumeSlider.setValue((float)finalY / HEIGHT); } //background(204); //loadPixels(); updatePixels(); } void oscEvent(OscMessage oscMessage) { if (oscMessage == null) return; String address = oscMessage.addrPattern(); OscArgument arg; int value = 0; if (address.equals("/accxyz") && oscMessage.checkTypetag("fff")) { float x = 0, y = 0, z = 0; if (playRateToggle.getState()) { arg = oscMessage.get(0); if (arg != null) { x = 2 * (arg.floatValue() / 2 + 0.5); playRateSlider.setValue(x); } } if (gainToggle.getState()) { arg = oscMessage.get(1); if (arg != null) { y = (1.0 - arg.floatValue()) / 2; volumeSlider.setValue(y); } } } if (address.equals("/1/fader1") && oscMessage.checkTypetag("f")) { arg = oscMessage.get(0); if (arg != null) { System.out.println(arg.floatValue()); grainSizeSlider.setValue(arg.floatValue() * 2000); } } if (address.startsWith("/2/fader") && oscMessage.checkTypetag("f")) { String[] parts = address.split("/2/fader"); arg = oscMessage.get(0); if (arg != null) { System.out.println(arg.floatValue()); panKnobs[Integer.parseInt(parts[1]) - 1].setValue(arg.floatValue() * 2 - 1); } } if (address.equals("/1/toggle1/z")) { System.out.println("clear"); clearButton.setValue(0); } }