// Soundingbody standalone/internet installation // by bobby whelan // bobby@soundingbody.co.uk // started tuesday 21 March 2006 16:02 import processing.opengl.*; //all graphics rendered with OPENGL import oscP5.*; //this is an external library, available from http://www.sojamo.de/iv/index.php?n=11 import oscP5.osc.*; // declare variables int stage =1, repeats=0, direction=1, wait=0; //vars can be used by many functions, and reset at the end int ex, ye, toggle1=0, toggle2=0, toggle3=0, toggle4=0, toShorten, rebuild=0, snapshot=0; float rx, ry; int[] pointsx = new int[1]; int[] pointsy = new int[1]; float[] rotationsx = new float[1]; float[] rotationsy = new float[1]; int squareSize=0; float[] Mpoint1 = new float[1]; float[] Mpoint2 = new float[1]; float[] Mpoint3 = new float[1]; float[] Mpoint4 = new float[1]; float[] Mrotationsx = new float[1]; float[] Mrotationsy = new float[1]; boolean justStopped=false; char key1, key2, key3, key4; PFont foont; OscP5 oscP5; int sendToPort; String host; String oscP5event; void oscEvent() { println("woweeeee! an OSC event!"); } void initOsc() { //open sound control is used by the standalone, to send vars to Pd sendToPort = 57130; //the port which Pd will receive on... Pd MUST be started FIRST. host = "127.0.0.1"; oscP5event = "oscEvent"; oscP5 = new OscP5( this, host, sendToPort, oscP5event ); } // here the overall format of the applet is set up, and the OSC initted. void setup() { size(800, 550, OPENGL); //using opengl, because P3D messed up my fonts! awwwww background(255); framerate(25); foont = loadFont("HelveticaNeue-Light-48.vlw"); //my favorite crappy font textFont(foont, 32); initOsc(); } //this is the main loop of the program, which is called at a rate of 25 fps //depending on what stage of the site you are on, (like pages) different //drawing functions are called, giving the impression of different sections and areas of content. void draw() { if(key!=key4){ //store the last four qwerty key-presses, for use in navigation of the site key1=key2; key2=key3; key3=key4; key4 = key; } switch(stage) { case 1: wordIntro(); break; case 2: choice(); break; case 3: reading(); break; case 4: body(); transition(); break; case 5: body(); } } ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// //this function sends variables to the Pd patch. either with OSC or Javascript. void sendPDvars(String name, int arg) { //if in browser use javascript, else use OSC for debugging, send one int at a time if(online){ link("javascript:pd.send('" + name + "', " + arg + ");"); }else{ OscMessage oscMsg = oscP5.newMsg(name); //start new OSC message, with a node name oscMsg.add(arg); //add an integer value to be sent. oscP5.sendMsg(oscMsg); //send the OSC message } } ////////////////////////////////////////////////////////////////// String[] loadStatus() //load parameters from txt file for redrawing the body from the last session { String[] params = loadStrings("body.txt"); return params; } ////////////////////////////////////////// //called when the user ends a drawing (this should preserve drawing order) -save what the body looks like void saveStatus(String[] addition, int instances){ //String[] stored = loadStrings("body.txt"); //stored = splice(stored, addition, stored.length); String[] instan=new String[0]; instan=append(instan, str(instances)); saveStrings("bodypd.txt", instan); saveStrings("body.txt", addition); //store it all back to the txt file } ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// void wordIntro() //intro sequence { if(wait==0 && online) { link("javascript:pd.start();"); //start synthesis engine, if in the browser wait++; } if(wait==10) //using counters to sequence events over time { sendPDvars("/intro", 1); //switch on low drone sound in Pd wait++; } if(wait<50) { wait++; fill( 0, 0, 0, 205); background(255); textSize(39); text("© 2006 bobby whelan.", 20, 560); }else { if(repeats==2) { //start of word-intro + start the intro sample/sound in Pd sendPDvars("/intro", 2); wait++; } //fade the text in/out during the intro if(repeats<75 && direction==1){repeats++;} if(repeats==75){direction=0;} if(direction==0 && repeats>0){repeats=repeats-2;} if(repeats==1 && direction==0){stage=2; repeats=0; wait=0;} textSize(20); background(255); fill( 0, 0, 0, repeats); text("welcome to", 30, 60); textSize(40); fill(0, 0, 0, repeats*4); text("soundingbody", 30, 90); } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void choice() //navigation page, 'read or play' { background(255); fill(100, 90); textSize(40); text("read", 300, 255); textSize(40); text("play", 405, 255); fill(100, 40); textSize(20); if(repeats==0){ text("type", 175, 250); } fill(100, 70); text("or", 382, 250); textSize(40); fill(10); if((key3=='r' && key4!='e') || (key3=='e' && key4!='a') || (key3=='a' && key4!='d')){ sendPDvars("/readword", 0); } if(key4=='r'){ sendPDvars("/readword", 1); text("r", 300, 255); } if(key3=='r' && key4=='e'){ sendPDvars("/readword", 2); text("re", 300, 255); } if(key2=='r' && key3=='e' && key4=='a'){ sendPDvars("/readword", 3); text("rea", 300, 255); } if(key1=='r' && key2=='e' && key3=='a' && key4=='d'){ sendPDvars("/readword", 4); text("read", 300, 255); stage=3; repeats=1; } if(key4=='p'){ text("p", 405, 255); } if(key3=='p' && key4=='l'){ text("pl", 405, 255); } if(key2=='p' && key3=='l' && key4=='a'){ text("pla", 405, 255); } if(key1=='p' && key2=='l' && key3=='a' && key4=='y'){ text("play", 405, 255); key4='o'; //prevent endless re-triggering stage=4; background(255); } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void transition() { //background(255); if(wait<250){ sendPDvars("/fade", wait); //fade out the drone in Pd noStroke(); fill(255, 255, 255, 255); rect(0, wait, 800, 250); rect(0, 251, 800, 500-wait); stroke(200); line(0, wait, 800, wait); line(0, 500-wait, 800, 500-wait); if(wait>=0){ fill(100, 90-wait); textSize(40); text("read", 300, 255); } textSize(40); fill(10, 250-(wait*2)); text("play", 405, 255); wait+=2; }else{stage=5; wait=0; sendPDvars("/startbody", 1);} //start the body sounds in Pd } ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// void reading() { background(255); textSize(25); text("this is an ongoing exploration of shared composition", 60, 70); text("your actions are fragile, and leave behind them fragments", 57, 118); text("residual impressions of brief visits. ", 62, 160); text("sound and image are together constructed and manipulated", 40, 200); text(" in the here and now, building upon data collected", 67, 248); text("from each use. ", 62, 280); fill(100, 80); textSize(20); text("type", 580, 540); textSize(40); text("back", 620, 540); fill(10); if((key3=='b' && key4!='a') || (key3=='a' && key4!='c') || (key3=='c' && key4!='k')){ sendPDvars("/readword", 0); } if(key4=='b'){ sendPDvars("/readword", 1); text("b", 620, 540); } if(key3=='b' && key4=='a'){ sendPDvars("/readword", 2); text("ba", 620, 540); } if(key2=='b' && key3=='a' && key4=='c'){ sendPDvars("/readword", 3); text("bac", 620, 540); } if(key1=='b' && key2=='a' && key3=='c' && key4=='k'){ sendPDvars("/readword", 4); sendPDvars("/readword", 5); text("back", 620, 540); stage=2;} } ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// // and now for the main event.... void body(){ //first of all, rebuild the body from the last session if(rebuild==0){ String[] todraw = loadStatus(); rebuild++; println(todraw[1]); for(int i=0; i405 || pointsy[o]>405 || rotationsx[o]<0.2)) { pointsy[o]+=10;} if(pointsy[o]>550){ toShorten=o; } popMatrix(); }} if(Mpoint1.length==Mrotationsx.length){ for(int o = 0; o < Mpoint1.length; o++){ pushMatrix(); rotateX(Mrotationsx[o]); rotateY(Mrotationsy[o]); stroke(int(random(255)), 0, 0, int(random(255))); bezier(Mpoint1[o], 200, 210, 10, Mpoint2[o], 150, Mpoint3[o], Mpoint4[o]); if(Mpoint1[o]>200){ Mpoint1[o]+=10; sendPDvars("/lines1",int(Mpoint1[o])); } if(Mpoint2[o]>200){ Mpoint2[o]+=10; sendPDvars("/lines2",int(Mpoint2[o])); } if(Mpoint3[o]>200){ Mpoint3[o]+=10; sendPDvars("/lines3",int(Mpoint3[o])); } if(Mpoint4[o]>200){ Mpoint4[o]+=10; sendPDvars("/lines4",int(Mpoint4[o])); } popMatrix(); }} //justStopped==false; if(toggle1==1) { storm(); } if(toggle2==1) { sun(); } if(toggle3==1) { moscral(); } if(toggle4==1) { jumboFilter(); } /*for(int i = pointsx.length; i>toShorten; i--){ pointsx = shorten(pointsx); pointsy = shorten(pointsy); rotationsx = shorten(rotationsx); rotationsy = shorten(rotationsy); } */ fill(255); stroke(0); //rect(350, 245, 100, 60); if(mouseX>width-32 && mouseY<30){ fill(255, 0, 0); }else{fill(255);} rect(width-32, 1, 30, 30); if(mouseX<30 && mouseY>height-31){ fill(255, 0, 0); }else{fill(255);} rect(2, height-31, 30, 30); if(mouseX>width-32 && mouseY>height-31){ fill(255, 0, 0); }else{fill(255);} rect(width-32, height-31, 30, 30); if(mouseX<30 && mouseY<30){ fill(255, 0, 0); }else{fill(255);} rect(2, 1, 30, 30); } ///////////////////////////////////////////////////////////////////////// void saveShapes() { int saved = 0; String[] toStore = new String[1]; for(int i=0; i380){ pointsx=append(pointsx, r); pointsy=append(pointsy, r); rotationsx=append(rotationsx, rx); rotationsy=append(rotationsy, ry); sendPDvars("/new", 1); } // bezier(ye-(i/3.0), 40+i, 210, 10, random(220), 150, ye-(i/18.0), ex+(i/14.0)); }} popMatrix(); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void sun() { float x = mouseX - width/2; // background(255); // translate(width/2, height/2); // rotateZ(radians(mouseY)); if(Mpoint1.length>1){ Mpoint1 = shorten(Mpoint1); Mpoint2 = shorten(Mpoint2); Mpoint3 = shorten(Mpoint3); Mpoint4 = shorten(Mpoint4); Mrotationsx = shorten(Mrotationsx); Mrotationsy = shorten(Mrotationsy);} if(Mpoint1.length>1){ Mpoint1 = shorten(Mpoint1); Mpoint2 = shorten(Mpoint2); Mpoint3 = shorten(Mpoint3); Mpoint4 = shorten(Mpoint4); Mrotationsx = shorten(Mrotationsx); Mrotationsy = shorten(Mrotationsy);} if(pointsx.length>1 && mouseX>400){ pointsx = shorten(pointsx); pointsy = shorten(pointsy); rotationsx = shorten(rotationsx); rotationsy = shorten(rotationsy);} for(int i=mouseX; i230 && r<280){ Mpoint1=append(Mpoint1, ye-(i/3.0)); Mpoint2=append(Mpoint2, ye*3); Mpoint3=append(Mpoint3, ye-(i/18.0)); Mpoint4=append(Mpoint4, ex+(i/14.0)); Mrotationsx=append(Mrotationsx, rx); Mrotationsy=append(Mrotationsy, ry); } bezier(width-ye-(i/3.0), width-600, width-210, width-10, width-ye*3, width-150, width-ye-(i/18.0), width-ex+(i/14.0)); bezier(width-ye-(i/3.0),660, 210, 10, width-ye*2.1, 150, width-ye-(i/18.0), width-ex+(i/14.0)); }} popMatrix(); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void mousePressed() { ex = mouseX; ye = mouseY; if(ex<30 && ye<30){ if(toggle1==0){ toggle1=1; }else{ toggle1=0; //saveShapes(); } } if(ex<30 && ye>height-30){ if(toggle2==0){ toggle2=1; }else{ toggle2=0; saveShapes(); } } if(ex>width-30 && ye<30){ if(toggle3==0){ toggle3=1; }else{ toggle3=0; saveShapes(); } } if(ex>width-30 && ye>height-30){ if(toggle4==0){ toggle4=1; }else{ toggle4=0; squareSize=0; } } } //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// void jumboFilter() { for(int i = mouseX; i400){ squareSize=int((800-mouseX)/10); } if(mouseX<=400){ squareSize=int(mouseX/10); } sendPDvars("/filter", squareSize); popMatrix(); } }