//---------------------------------------------------- //BOX EMITTING - Aaron Steed 2005 //Data is stored on a byte tape That corresponds to an //Illustrator maximum page length (16000 lines long). //Each box is 8 bytes. //Sound input increases the opacity of the boxes when //the volume passes a threshold. //Boxes (emitted) are spawned when the emitters sense //chnages in colour - more change, bigger box //---------------------------------------------------- import processing.opengl.*; import processing.video.*; Capture myCapture; Emitter [] emitter; Emitted [] emitted; color [] cFill; float micThreshold = 0.25; int [] xTable, captureXTable, greyDifferenceTable; String [] saveLog; int scrCount = 0; //scroll count - saves at 16000 int saveCount = 0; int saveLogCount = 0; int emittedMax = 1000; int emitSize = 20; int captureWidth = 320; int captureHeight = 240; int captureRatio = 3; boolean thisColor = false; int captureMaxSize = captureWidth/16; int maxSize = 50; byte marker = 2; byte [] record,saveBlock; boolean calibrate = true; int boxCount = 0; void setup(){ size(800, 600, OPENGL); String s = "TRUST 120 SPACEC@M-WDM"; //String s = "Logitech QuickCam Communicate-WDM"; myCapture = new Capture(this, s, captureWidth, captureHeight, 6); Sonia.start(this); LiveInput.start(); cFill = new color[128]; emitter = new Emitter[(width/maxSize)]; println("emitters:"+emitter.length); xTable = new int[(width/maxSize)]; captureXTable = new int[xTable.length]; greyDifferenceTable = new int[xTable.length]; emitted = new Emitted[emittedMax]; record = new byte[131072]; saveLog = new String[10000]; for (int i = 0; i < cFill.length; i++){ cFill[i] = color(255,255,255,(i*2)+1); } for (int i = 0; i < emitted.length; i++){ emitted[i] = new Emitted(0,0,10,i); } for (int i = 0; i < emitter.length; i++){ emitter[i] = new Emitter(i,525); xTable[i] = (i*maxSize)+(maxSize>>1); captureXTable[i] = (i*captureMaxSize)+(captureMaxSize>>1); greyDifferenceTable[i] = 200; } noStroke(); } void draw(){ if (calibrate){ background(0); image(myCapture,0,0,width,height); } else{ background(0); } micMethod(); stroke(255); //---------------------------------------------------- //emitters //---------------------------------------------------- for (int i = 0; i < emitter.length; i++){ if (calibrate){ emitter[i].draw(); } int difference = abs(grey(myCapture.pixels[captureXTable[emitter[i].x] + 210 * myCapture.width]) - greyDifferenceTable[i]); if (difference > 20){ emitSize = (difference/6)<<1; int lastEmit = emitter[i].lastEmit; if (lastEmit > -1){ if (emitted[lastEmit].y < emitter[i].y - ((emitted[lastEmit].size-1)>>2) - ((emitSize-1)>>2)){ emitter[i].emit(emitSize); } } else{ emitter[i].emit(emitSize); } } greyDifferenceTable[i] = grey(myCapture.pixels[captureXTable[emitter[i].x] + 210 * myCapture.width]); } //---------------------------------------------------- //emitted //---------------------------------------------------- for (int i = 0; i < emitted.length; i++){ if (emitted[i].active){ emitted[i].update(thisColor); emitted[i].draw(); if (emitted[i].y < -maxSize<<1){ emitted[i].active = false; if(!calibrate){ byteWriter(i); } } } } if (!calibrate){ scrCount++; if (scrCount == 16000){ saveBoxes(); } } } //---------------------------------------------------- //events //---------------------------------------------------- void keyPressed(){ switch(key){ case 'c': case 'C': calibrate = !calibrate; println("calibrating:"+calibrate); if (calibrate){ println("screen count stopped at:"+scrCount); } break; case 's': case 'S': saveBytes("stop.dat", record); saveStrings("saveLogStop.txt", saveLog); println("saved stop files"); break; case '+': case '=': if (calibrate){ micThreshold = constrain(micThreshold+0.01,0.0,0.5); } break; case '-': case '_': if (calibrate){ micThreshold = constrain(micThreshold-0.01,0.0,0.5); } break; } } void captureEvent(Capture myCapture){ myCapture.read(); } //---------------------------------------------------- //methods //---------------------------------------------------- void micMethod(){ float getLevel = LiveInput.getLevel();//returns a value from 0 to 0.5 if (calibrate){ noStroke(); fill(255); rect(0,0,100,30); fill(255,0,0); rect(0,0,getLevel*200.0,30); stroke(0,255,0); line(micThreshold*200.0,0,micThreshold*200.0,30); } if (getLevel > micThreshold){ thisColor = true; } else{ thisColor = false; } } int grey(color p) { return max((p >> 16) & 0xff, (p >> 8) & 0xff, p & 0xff); } byte [] int4Bytes (int source){ byte [] sendBack = new byte[4]; sendBack[0]=byte((source&0xFF000000)>>24); sendBack[1]=byte((source&0x00FF0000)>>16); sendBack[2]=byte((source&0x0000FF00)>>8); sendBack[3]=byte((source&0x000000FF)); return sendBack; } void byteWriter(int i){ /* saves in 8 byte snacks (two words) screenCount (4 bytes), x location, size, colour, marker to signify actual data */ int recCount = boxCount*8; byte [] temp = int4Bytes(scrCount); System.arraycopy(temp, 0, record, recCount, temp.length); record[recCount+4] = byte(emitted[i].x); record[recCount+5] = byte(emitted[i].size); record[recCount+6] = byte(emitted[i].c>>1); record[recCount+7] = marker; boxCount++; } void saveBoxes(){ saveBlock = new byte[boxCount*8]; System.arraycopy(record, 0, saveBlock, 0, saveBlock.length); saveBytes("log"+saveCount+".dat", saveBlock); int s = saveCount - (saveLogCount*10000); saveLog[s] = "saved "+saveCount+" boxes:"+boxCount+" at "+hour()+":"+minute()+":"+second(); println(saveLog[s]); record = new byte[131072]; boxCount = 0; scrCount = 0; saveCount++; if (s == 9999){ saveStrings("saveLog"+(++saveLogCount)+".txt", saveLog); saveLog = new String[10000]; } } void cube(int x, int y, int size){ int z = 0; //back face beginShape(QUADS); vertex(xTable[x]-size,y-size,z-size); vertex(xTable[x]+size,y-size,z-size); vertex(xTable[x]+size,y+size,z-size); vertex(xTable[x]-size,y+size,z-size); endShape(); //left face beginShape(QUADS); vertex(xTable[x]-size,y-size,z+size); vertex(xTable[x]-size,y-size,z-size); vertex(xTable[x]-size,y+size,z-size); vertex(xTable[x]-size,y+size,z+size); endShape(); //right face beginShape(QUADS); vertex(xTable[x]+size,y-size,z-size); vertex(xTable[x]+size,y-size,z+size); vertex(xTable[x]+size,y+size,z+size); vertex(xTable[x]+size,y+size,z-size); endShape(); //top face beginShape(QUADS); vertex(xTable[x]-size,y-size,z-size); vertex(xTable[x]+size,y-size,z-size); vertex(xTable[x]+size,y-size,z+size); vertex(xTable[x]-size,y-size,z+size); endShape(); //bottom face beginShape(QUADS); vertex(xTable[x]-size,y+size,z-size); vertex(xTable[x]+size,y+size,z-size); vertex(xTable[x]+size,y+size,z+size); vertex(xTable[x]-size,y+size,z+size); endShape(); //front face beginShape(QUADS); vertex(xTable[x]-size,y-size,z+size); vertex(xTable[x]+size,y-size,z+size); vertex(xTable[x]+size,y+size,z+size); vertex(xTable[x]-size,y+size,z+size); endShape(); } //---------------------------------------------------- //classes //---------------------------------------------------- class Box{ int x,y,size; Box(){ } } class Emitted extends Box{ int index,c,growSize; boolean active; Emitted(int x, int y, int size, int index){ this.x = x; this.y = y; this.size = size; this.index = index; active = false; c = 1; } void draw(){ fill(cFill[c>>1]); cube(x,y,growSize); } void emit(int x, int y, int input){ this.x = x; this.y = y; growSize = 1; size = input; c = 1; active = true; } void update(boolean burn){ y -= 1; if (growSize < size){ growSize++; } if (burn){ c = constrain(c+1,0,127); } } } class Emitter extends Box{ boolean fire; int lastEmit; Emitter(int x, int y){ this.x = x; this.y = y; this.size = maxSize; lastEmit = -1; } void emit(int input){ for(int i = 0; i < emitted.length; i++){ if (!emitted[i].active){ lastEmit = i; emitted[i].emit(x, y, input); break; } } } //callibration boxes void draw(){ pushMatrix(); translate(xTable[x],y); fill(150,150,150); box(maxSize>>1,maxSize>>1,maxSize>>3); popMatrix(); } }