// 510 333 7809 Peter //cellular automata to use q3osc - based on q3Osc and its example by Rob Hamilton // at https://ccrma.stanford.edu/~rob/q3osc/q3osc_balls2_stereo.ck 100 => int CA_SIZE; 1000 => int PROJECTILE_COUNT; 6662 => int INPUT_PORT; 57122 => int OUTPUT_PORT; MidiOut midiOut; midiOut.open(1); //if(!midiOut.open(1)) // me.exit(); //MidiIn min; //min.open(1); <<< "MIDI controller device:", midiOut.num(), " -> ", midiOut.name() >>>; // extended event class BallEvent extends Event { int newball; string type; int owner; int id; float x; float y; float z; int target; int bounce; int explode; } OscRecv recv; INPUT_PORT => recv.port; recv.listen(); recv.event( "/projectile, s i i f f f i i i" ) @=> OscEvent oeProjectile; OscSend xmit; xmit.setHost("localhost", OUTPUT_PORT); string type; int owner; int id; float x; float y; float z; int target; int bounce; int explode; BallEvent @ bprojectiles[PROJECTILE_COUNT]; ////////////////////////////////////////////////////////////////////// class CA { int size; int maxStates; int generation; int states[CA_SIZE][CA_SIZE]; fun void init(int size) { //<<<"inside init">>>; size => this.size; for (int i; i < size; i++) for (int j; j < size; j++) { int value; if (maybe) 1 => value; value => states[i][j]; } } fun int toInt(int row) { int value; for (int j; j < size; j+1=>j) { value + states[row][j] * (Math.pow(2, j) $ int) => value; } return value; } fun void init(CA ca) { int state; size => ca.size; ca.maxStates => maxStates; ca.generation => generation; for (int i; i < size; i++) for (int j; j < size; j++) { ca.getCellState(i, j) => state; setCellState(i, j, state); } } fun int getCellState(int i, int j) { if (i < 0 || j < 0 || i >= size || j >= size) return 0; return states[i][j]; } fun void setCellState(int i, int j, int val) { val => states[i][j]; } fun int getNextState(int i, int j) { //abstract } fun int addCountIfInState(int i, int j, int state, int count) { getCellState(i, j) => int cellState; if (cellState == state) count + 1 => count; return count; } fun int countNeighboursInState(int i, int j, int state) { int count; addCountIfInState(i - 1, j - 1, state, count) => count; addCountIfInState(i - 1, j, state, count) => count; addCountIfInState(i - 1, j + 1, state, count) => count; addCountIfInState(i, j - 1, state, count) => count; addCountIfInState(i, j + 1, state, count) => count; addCountIfInState(i + 1, j - 1, state, count) => count; addCountIfInState(i + 1, j, state, count) => count; addCountIfInState(i + 1, j + 1, state, count) => count; return count; } fun void advanceGeneration() { int newStates[size][size]; for (int i; i < size; i + 1 => i) for (int j; j < size; j + 1 => j) { getNextState(i, j) => int nextState; nextState => newStates[i][j]; } for (int i; i < size; i + 1 => i) for (int j; j < size; j + 1 => j) { getNextState(i, j) => int nextState; newStates[i][j] => states[i][j]; } generation + 1 => generation; } fun void display() { for (int i; i < size; i + 1 => i) { for (int j; j < size; j + 1 => j) { <<>>; } } } } ////////////////////////////////////////////////////////////////////// class GameOfLifeCA extends CA { fun int getNextState(int i, int j) { getCellState(i, j) => int currentState; countNeighboursInState(i, j, 1) => int aliveNeighbours; currentState => int nextState; if (currentState == 0 && aliveNeighbours == 3) { //birth 1 => nextState ; } if (currentState == 1 && (aliveNeighbours < 2 || aliveNeighbours > 3)) //isolation, over-population { //death 0 => nextState; } return nextState; } } ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////// class NoiseSynth { Noise noise => LPF filter => Pan2 panner; panner.chan(0)=>NRev r1=>dac.chan(0); panner.chan(1)=>NRev r2=>dac.chan(1); 0.01 => r1.mix; 0.01 => r2.mix; 0.7 => static float amp; 0.1 => static float res; 0.5 => static float pan; 0.2 => static float cutOffFreq; 0.1 => static float modDepth; 0.9 => static float modRate; 0 => static int mute; fun void run() { while (true) { 60 + cutOffFreq * 1000 => float f; modDepth * 500 => float d; 60 + modRate * 3000 => float r; float modFreq; Math.random2f(0, d - 1) => modFreq; filter.freq(f + modFreq); filter.gain(amp * 0.5); panner.pan(pan * 2 - 1.0); filter.Q(res * 20); 20::ms +=> now; } } } ////////////////////////////////////////////////////////////////////// class Main { 0.5 => static float amp; 0.5 => static float transpose; fun float toFreq(int value) { //return Std.mtof(32 + value / 2); return Std.mtof(32 + value / 5 + (transpose) * 50); // return Std.mtof(32 + (transpose - 0.5) * 20); } fun float toGain(int value) { //value $ float / (127.0 ) + 0.25 / 10 => float gain; <<<"amp = ", amp>>>; // value $ float / (127.0 ) * amp => float gain; // amp => float gain; amp * 0.9 + (value $ float / (127.0 ) ) * 0.1=> float gain; // if (gain < 0.1) // 0.1 => gain; return gain; } fun void runCA(BallEvent e) { GameOfLifeCA ca; ca.init(7); e.id => int id; while (true) { // wait on event e e => now; if(e.id != id) continue; // listen if (e.explode == 1) { 3::second=>now; //let decay break; } if (e.bounce == 1) { int r[7]; for (int i; i < 7; i + 1 => i) ca.toInt(i) => r[i]; int pitch1, pitch2, pitch3; int velo; MidiMsg msg; Std.ftom(toFreq(r[0]) ) $ int => pitch1; if (pitch1 < 33) //33 + Std.rand2(1, 12) => pitch1; //33 => pitch1; 0 => pitch1; if (pitch1 > 96) 96 => pitch1; (toGain(r[1]) * 127) $ int => velo; <<<"1:", pitch1, velo , "sent">>>; // NOTE_ON is 144 144 + 1=> msg.data1; pitch1 => msg.data2; velo => msg.data3; midiOut.send(msg); Std.ftom(toFreq(r[2])) $ int => pitch2; if (pitch2 < 33) // while (pitch1 == pitch2) // 33 + Std.rand2(1, 12) => pitch2; //33 => pitch2; 0 => pitch2; if (pitch2 > 96) 96 => pitch2; (toGain(r[3]) * 127) $ int => velo; <<<"2:",pitch2, velo, "sent">>>; 144 => msg.data1; pitch2 => msg.data2; velo => msg.data3; midiOut.send(msg); Std.ftom(toFreq(r[4])) $ int => pitch3; if (pitch3 < 33) // while (pitch3 == pitch1 || pitch3 == pitch2) // 33 + Std.rand2(1, 12) => pitch3; //33 => pitch3; 0 => pitch3; if (pitch3 > 96) 96 => pitch3; (toGain(r[5]) * 127) $ int => velo; <<<"3:", pitch3, velo , "sent">>>; // NOTE_ON is 144 144 => msg.data1; pitch3 => msg.data2; velo => msg.data3; midiOut.send(msg); (r[6] * 2)::ms => now; // NOTE_OFF is 128 128 => msg.data1; pitch1 => msg.data2; 0 => msg.data3; midiOut.send(msg); <<<"1:", pitch1, 0 , "sent">>>; 128 => msg.data1; pitch2 => msg.data2; 0 => msg.data3; midiOut.send(msg); <<<"2:", pitch2, 0 , "sent">>>; 128 => msg.data1; pitch3 => msg.data2; 0 => msg.data3; midiOut.send(msg); <<<"3:", pitch3, 0 , "sent">>>; if (r[6] < 10 || r[0] < 10 || r[2] < 10 || r[4] < 10) ca.init(7); //70::ms => now; ca.advanceGeneration(); } } } fun void receiveProjectile() { <<>>; while ( true ) { oeProjectile => now; while ( oeProjectile.nextMsg() != 0) { oeProjectile.getString() => type; oeProjectile.getInt() => owner; oeProjectile.getInt() => id; oeProjectile.getFloat() => x; oeProjectile.getFloat() => y; oeProjectile.getFloat() => z; oeProjectile.getInt() => target; oeProjectile.getInt() => bounce; oeProjectile.getInt() => explode; // <<<"projectile:", x,y,z>>>; if(bprojectiles[id]==null) { BallEvent @tempBall; new BallEvent @=> tempBall @=>bprojectiles[id]; //<<<"new projectile">>>; type => tempBall.type; owner => tempBall.owner; id => tempBall.id; x =>tempBall.x; y => tempBall.y; z =>tempBall.z; target => tempBall.target; bounce => tempBall.bounce; explode => tempBall.explode; 1 => tempBall.newball; spork ~ runCA( tempBall ); me.yield(); tempBall.broadcast(); // send events to all balls } else { // <<<"projectile with id=", id>>>; bprojectiles[id] @=> BallEvent @ temp2Ball; if(explode == 1) { null @=> bprojectiles[id]; //1::second=>now; } type => temp2Ball.type; owner => temp2Ball.owner; id => temp2Ball.id; x =>temp2Ball.x; y => temp2Ball.y; z =>temp2Ball.z; target => temp2Ball.target; bounce => temp2Ball.bounce; explode => temp2Ball.explode; -1 => temp2Ball.newball; // not a new ball temp2Ball.broadcast(); // send events to all balls } } } } fun OscEvent makeEvent(string messagePattern) { OscRecv recv; OscEvent oscEvent; INPUT_PORT => recv.port; recv.listen(); recv.event(messagePattern) @=> oscEvent; return oscEvent; } fun void receiveY() { makeEvent("/wii/1/accel/pry/0, f") @=> OscEvent oscEvent; while ( true ) { oscEvent => now; while ( oscEvent.nextMsg() != 0) { oscEvent.getFloat() => amp; // <<<"amp received", amp>>>; if (!NoiseSynth.mute) amp => NoiseSynth.amp; // if (controlAmp && !NoiseSynth.mute) // if (!NoiseSynth.mute) // amp => NoiseSynth.amp; // xmit.startMsg("/wii/1/accel/pry/0", "f"); // xmit.addFloat(amp); } } } fun void receiveX() { makeEvent("/wii/1/accel/pry/1, f") @=> OscEvent oscEvent; while ( true ) { oscEvent => now; while ( oscEvent.nextMsg() != 0) { oscEvent.getFloat() => transpose; if (!NoiseSynth.mute) transpose => NoiseSynth.pan; // if (controlAmp && !NoiseSynth.mute) // if (!NoiseSynth.mute) // amp => NoiseSynth.amp; // xmit.startMsg("/wii/1/accel/pry/0", "f"); // xmit.addFloat(amp); } } } ///////////////////////////////////////////////////// fun void receiveRes() { float buttonState; makeEvent("/wii/1/button/A, f") @=> OscEvent oscEvent; while ( true ) { oscEvent => now; while ( oscEvent.nextMsg() != 0) oscEvent.getFloat() => buttonState; <<<"mute received", buttonState>>>; if (buttonState == 0 && !NoiseSynth.mute) { 1 - NoiseSynth.res => NoiseSynth.res; } } } fun void receiveCutOffFreq() { makeEvent("/cam/motion/y, f") @=> OscEvent oscEvent; while ( true ) { oscEvent => now; while ( oscEvent.nextMsg() != 0) if (!NoiseSynth.mute) oscEvent.getFloat() => NoiseSynth.cutOffFreq; } } fun void receiveModDepth() { makeEvent("/cam/motion/x, f") @=> OscEvent oscEvent; while ( true ) { oscEvent => now; while ( oscEvent.nextMsg() != 0) if (!NoiseSynth.mute) oscEvent.getFloat() => NoiseSynth.modDepth; } } fun void receiveMute() { float buttonState; makeEvent("/wii/1/button/B, f") @=> OscEvent oscEvent; while ( true ) { oscEvent => now; while ( oscEvent.nextMsg() != 0) oscEvent.getFloat() => buttonState; <<<"mute received", buttonState>>>; if (buttonState == 0) { !NoiseSynth.mute => NoiseSynth.mute; if (NoiseSynth.mute) 0 => NoiseSynth.amp; } } } //fun void receiveMIDI() //{ // MidiMsg msg; // while( true ) // { // wait on the event 'min' // min => now; // get the message(s) // while( min.recv(msg) ) // { // midiOut.send(msg); //<<< msg.data1, msg.data2, msg.data3 >>>; // } // } //} } //NoiseSynth synth; Main main; spork ~ main.receiveY(); spork ~ main.receiveX(); spork ~ main.receiveProjectile(); //spork ~ synth.run(); //spork ~ main.receiveRes(); //spork ~ main.receiveCutOffFreq(); //spork ~ main.receiveModDepth(); //spork ~ main.receiveMute(); //spork ~ main.receiveMIDI(); ///////////////////////////////////////////////////// 20::minute => now;