// prototype circle sequencer // Now With Serial - 180 degree circle // note - if using serial, may need to uncomment // all the firstContact lines // problems... quantizing doesn't work with mouse // once the sequence starts. /**
circlesequencer has many (often arbitrary) keyboard commands: space: restart 1: quantize off 2: quantize 6 steps 3: quantize 9 steps 4: quantize 12 steps s: switch smoothing (anti-aliasing) d: draw sequence f: draw sequence as shape / lines q: line width 1 w: line width 2 e: line width 3 r: line width 4 j: jsyn volume 0.0 k: jsyn volume 0.4 g: dump sequence 0: switch allow 0 frequency through (otherwise freq stays the same until next non-zero)*/ /*//^STARTOSC import oscP5.*; import oscP5.osc.*; OscP5 osc; *///^ENDOSC /*//STARTSERIAL import processing.serial.*; *///ENDSERIAL import com.softsynth.jsyn.*; int qLevel = 1; int button = 0; int erad = 5; int radius = 150; int maxRadius = 255; int angle = 0; int numSteps = 8; int[] sequence = new int[180]; int sequenceLineWeight = 2; int potAngle, potRadius; int workingWidth = 510, workingHeight = 510; float endX,endY; float mousepX, mousepY; boolean overball = false; boolean balllock = false; boolean playing = false; boolean firstContact = false; boolean weSmooth = true; boolean drawSequence = true; boolean drawSequenceShape = true; boolean allowZero = true; Serial port; int serialCount = 0; int serialIn[] = new int[3]; SineOscillator sine; LineOut lineout; void setup() { size(520, 520); // 255*2 Synth.startEngine(0); background(100); ellipseMode(CENTER_RADIUS); PFont font = loadFont("CenturyGothic-10.vlw"); textFont(font, 10); textAlign(RIGHT); /*//STARTSERIAL println(Serial.list()); port = new Serial(this, Serial.list()[0], 9600); port.write(65); // good ol 'A' *///ENDSERIAL /*//^STARTOSC // send recv osc = new OscP5(this,"127.0.0.1",9000,9001, "oscEvent"); *///^ENDOSC sine = new SineOscillator(); lineout = new LineOut(); sine.output.connect(0, lineout.input, 0); sine.output.connect(0, lineout.input, 1); sine.frequency.set(0); sine.amplitude.set(0.3); lineout.start(); sine.start(); restart(); } void draw() { if(weSmooth) smooth(); else noSmooth(); background(66, 98, 121); translate(5,5); // this is turning into a bad hack background(66, 98, 121); // if(button==1) restart(); stroke(255); fill(200); strokeWeight(1); textAlign(RIGHT); text("press spacebar to restart", workingWidth-1, 10); text(framerate,workingWidth-1,workingHeight-1); textAlign(LEFT); text("< ="+angle, 0, workingHeight); text("Q ="+qLevel, 44, workingHeight); text("nn ="+radius/2+" "+(8.1758 * pow(2,((radius/2)/12)))+"hz", 88, workingHeight); // draw a big circle around everything strokeWeight(4); fill(140, 173, 201); if(weSmooth) smooth(); else noSmooth(); ellipse(workingWidth/2, workingHeight/2, workingWidth/2, workingHeight/2); fill(200); strokeWeight(sequenceLineWeight); if(drawSequence) { // draw the sequence as lines from center if(drawSequenceShape) { beginShape(); for(int i=1; i<180; i++) { stroke(sequence[i]); vertex(((cos(radians(i*2))*sequence[i])+workingWidth/2), ((sin(radians(i*2))*sequence[i])+workingWidth/2)); } endShape(); } else { for(int i=1; i<180; i++) { stroke(sequence[i]); line( workingWidth/2, workingHeight/2, ((cos(radians(i*2))*sequence[i])+workingWidth/2), ((sin(radians(i*2))*sequence[i])+workingWidth/2)); } } } endX = (cos(radians(angle*2))*radius)+workingWidth/2; endY = (sin(radians(angle*2))*radius)+workingWidth/2; // draw wiper for sequence: stroke(255); strokeWeight(1); ellipse(endX, endY, erad, erad); line(workingWidth/2, workingHeight/2, endX, endY); // draw orange time marker strokeWeight(4); stroke(240, 191, 56); line((cos(radians((angle-1)*2))*255)+workingWidth/2, (sin(radians((angle-1)*2))*255)+workingWidth/2, (cos(radians((angle+1)*2))*255)+workingWidth/2, (sin(radians((angle+1)*2))*255)+workingWidth/2); if(playing) { if(allowZero) radius = sequence[angle]; else { if(sequence[angle] != 0) radius = sequence[angle]; } angle++; if(angle>=180) angle = 0; sine.frequency.set(8.1758 * pow(2,((radius/2)/12))); /*//^STARTOSC oscSend(radius/2); *///^ENDOSC strokeWeight(1); stroke(200); fill(80,150,200); //smooth(); float px = (cos(radians(potAngle*2))*(potRadius))+workingWidth/2; float py = (sin(radians(potAngle*2))*(potRadius))+workingWidth/2; ellipse(px, py, erad, erad); line(workingWidth/2,workingHeight/2, px, py); if(button==1) { quantize(potRadius, potAngle); } if(mousePressed) { quantize(potRadius, potAngle); // sequence[potAngle] = potRadius; } } else { angle = potAngle; radius = potRadius; quantize(radius, angle); if(angle == 179) { playing=true; } } /* if (firstContact == false) { delay(100); port.write(65); } */ if(mouseX > endX-erad && mouseX < endX+erad && mouseY > endY-erad && mouseY < endY+erad) { overball = true; } else { overball = false; } } /*//STARTSERIAL void serialEvent(Serial port) { if(firstContact==false) firstContact = true; serialIn[serialCount] = port.read(); serialCount++; if(serialCount == 3) { if(serialIn[0] < 180) { potAngle = serialIn[0]; } else { potAngle = 179; } potRadius = serialIn[1]; button = serialIn[2]; println(serialIn[0]+"\t"+serialIn[1]); port.write(65); serialCount = 0; } } *///ENDSERIAL void keyPressed() { if(key == ' ') { println("starting over..."); restart(); } else if(key == '1') { qLevel = 1; } else if(key == '2') { qLevel = 180/6; } else if(key == '3') { qLevel = 180/9; } else if(key == '4') { qLevel = 180/12; } else if(key == 's') { weSmooth = !weSmooth; } else if(key == 'd') { drawSequence = !drawSequence; } else if(key == 'f') { drawSequenceShape = !drawSequenceShape; } else if(key == 'q') { sequenceLineWeight = 1; } else if(key == 'w') { sequenceLineWeight = 2; } else if(key == 'e') { sequenceLineWeight = 3; } else if(key == 'r') { sequenceLineWeight = 4; } else if(key == 'j') { sine.amplitude.set(0.0); } else if(key == 'k') { sine.amplitude.set(0.3); } else if(key == 'g') { dumpSequence(); } else if(key =='0') { allowZero = !allowZero; } } /*//^STARTOSC void oscEvent(OscIn oi) { } *///^ENDOSC void restart() { angle = 0; potAngle = 0; playing = false; sequence = new int[180]; radius = 150; potRadius = 150; sine.frequency.set(0); /*//^STARTOSC oscSend(0); *///^ENDOSC } /*//^STARTOSC void oscSend(int val) { OscMessage om = osc.newMsg("/sequence"); om.add(val); osc.sendMsg(om); } *///^ENDOSC void quantize(int to, int angl) { int lo = 0; while(lo < angl-qLevel) lo += qLevel; setRange(to, lo, lo+qLevel); } void setRange(int to, int lo, int hi) { //println("to "+to+" lo " +lo+" hi "+hi); // AWFUL SAFETY CHECK if(hi > 179) hi = 179; for(int i=lo; i < hi; i++) { sequence[i] = to; } } void mousePressed() { if (overball) { balllock = true; } else { balllock = false; } } //void mouseMoved() { void mouseDragged() { potRadius = int(min(dist(workingWidth/2,workingHeight/2,mouseX,mouseY),maxRadius)); potAngle = int( degrees( atan2( ((mouseY- workingHeight/2.0)/(workingHeight/2.0)), ((mouseX- workingWidth/2.0 )/(workingWidth/2.0)) ) ) / 2 ); // WHOA if(potAngle < 0) potAngle = potAngle+180; // println("sequence["+angle+"] = "+radius); // sequence[potAngle] = potRadius; // println("potAngle = "+potAngle); } void mouseReleased() { balllock = false; } void destroy() { Synth.stopEngine(); } void dumpSequence() { for(int i=0; i<180; i++) println(i+" "+sequence[i]); }