commit
b2075e5e2d
@ -0,0 +1,289 @@
|
|||||||
|
13475 => int monomeIn;
|
||||||
|
16426 => int monomeOut;
|
||||||
|
"/manager" => string monomePrefix;
|
||||||
|
"127.0.0.1" => string monomeHost;
|
||||||
|
|
||||||
|
OscRecv recv;
|
||||||
|
monomeIn => recv.port;
|
||||||
|
recv.listen();
|
||||||
|
|
||||||
|
fun float[][] toneGrid(int width, int height, int columnStep, int rowStep, float baseFreq, float octaveSteps) {
|
||||||
|
float tones[width][height];
|
||||||
|
Math.pow(2, 1.0/ octaveSteps $ float) => float toneStep;
|
||||||
|
for(0 => int row; row < height; row++) {
|
||||||
|
baseFreq * Math.pow(toneStep, row * rowStep) => float rowBase;
|
||||||
|
for(0 => int col; col < width; col++) {
|
||||||
|
rowBase * Math.pow(toneStep, col * columnStep)
|
||||||
|
=> tones[col][row];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tones;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Monome {
|
||||||
|
|
||||||
|
string prefix;
|
||||||
|
string hostname;
|
||||||
|
OscRecv recv;
|
||||||
|
OscSend snd;
|
||||||
|
|
||||||
|
// PROTECTED FINAL
|
||||||
|
//
|
||||||
|
// Initialization: sets up the monome and listens for incoming messages.
|
||||||
|
fun void init(string _prefix, string _hostname, int in, int out) {
|
||||||
|
preInit();
|
||||||
|
_prefix => prefix;
|
||||||
|
_hostname => hostname;
|
||||||
|
|
||||||
|
OscSend m;
|
||||||
|
m.setHost(hostname, out);
|
||||||
|
m @=> snd;
|
||||||
|
|
||||||
|
in => recv.port;
|
||||||
|
recv.listen();
|
||||||
|
|
||||||
|
spork ~ keyListener();
|
||||||
|
spork ~ tiltListener();
|
||||||
|
all(0);
|
||||||
|
postInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC
|
||||||
|
//
|
||||||
|
// preInit is called before the init cycle finishes.
|
||||||
|
//
|
||||||
|
fun void preInit() {}
|
||||||
|
|
||||||
|
// PUBLIC
|
||||||
|
//
|
||||||
|
// postInit is called after the init cycle finishes.
|
||||||
|
//
|
||||||
|
fun void postInit() {}
|
||||||
|
|
||||||
|
// PUBLIC
|
||||||
|
//
|
||||||
|
// key is called once for every time a key is pressed on the Monome.
|
||||||
|
// Override this method in a child class to define how to handle key
|
||||||
|
// presses from the monome.
|
||||||
|
fun void key(int x, int y, int z) {
|
||||||
|
<<< prefix, "key", x, y, z >>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC
|
||||||
|
//
|
||||||
|
// position change on tilt sensor n, integer (8-bit) values (x, y, z).
|
||||||
|
// This method is called once for each OSC message received from the monome
|
||||||
|
// with regards to its tilt.
|
||||||
|
fun void tilt(int n, int x, int y, int z) {
|
||||||
|
<<< prefix, "tilt", n, x, y, z >>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE
|
||||||
|
//
|
||||||
|
// key press handler. This is invoked automatically by the Monome
|
||||||
|
// constructor, and should not be called. This method starts an infinite
|
||||||
|
// loop and listens for incoming osc messages from the monome. When
|
||||||
|
// messages are received, the monome object's "key" method is called.
|
||||||
|
//
|
||||||
|
fun void keyListener() {
|
||||||
|
recv.event(prefix+"/grid/key", "iii") @=> OscEvent e;
|
||||||
|
while(true) {
|
||||||
|
e => now;
|
||||||
|
while(e.nextMsg() != 0) {
|
||||||
|
e.getInt() => int x;
|
||||||
|
e.getInt() => int y;
|
||||||
|
e.getInt() => int z;
|
||||||
|
key(x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE
|
||||||
|
//
|
||||||
|
// tilt sensor handler. This is invoked automatically by the Monome
|
||||||
|
// constructor, and should not be called. This method starts an infinite
|
||||||
|
// loop and listens for incoming osc messages from the monome. When
|
||||||
|
// messages are received, the monome object's "tilt" method is called.
|
||||||
|
//
|
||||||
|
fun void tiltListener() {
|
||||||
|
recv.event(prefix+"/tilt", "iiii") @=> OscEvent e;
|
||||||
|
while(true) {
|
||||||
|
e => now;
|
||||||
|
while(e.nextMsg() != 0) {
|
||||||
|
e.getInt() => int n;
|
||||||
|
e.getInt() => int x;
|
||||||
|
e.getInt() => int y;
|
||||||
|
e.getInt() => int z;
|
||||||
|
tilt(n, x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PROTECTED FINAL
|
||||||
|
//
|
||||||
|
// set led at (x,y) to state s (0 or 1).
|
||||||
|
//
|
||||||
|
fun void set(int x, int y, int s) {
|
||||||
|
snd.startMsg(prefix+"/grid/led/set", "iii");
|
||||||
|
snd.addInt(x);
|
||||||
|
snd.addInt(y);
|
||||||
|
snd.addInt(s);
|
||||||
|
me.yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PROTECTED FINAL
|
||||||
|
//
|
||||||
|
// set all leds to state s (0 or 1).
|
||||||
|
//
|
||||||
|
fun void all(int i) {
|
||||||
|
snd.startMsg(prefix+"/grid/led/all", "i");
|
||||||
|
snd.addInt(i);
|
||||||
|
me.yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Life extends Monome {
|
||||||
|
float tones[8][8];
|
||||||
|
int lifeState[8][8];
|
||||||
|
int nextLifeState[8][8];
|
||||||
|
100::ms => dur genStep;
|
||||||
|
false => int running;
|
||||||
|
|
||||||
|
fun void preInit() {
|
||||||
|
toneGrid(8, 8, 1, 6, 220, 12) @=> tones;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void postInit() {
|
||||||
|
all(0);
|
||||||
|
spork ~ live();
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void live() {
|
||||||
|
true => running;
|
||||||
|
while(running) {
|
||||||
|
step();
|
||||||
|
genStep => now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void pause() {
|
||||||
|
<<< "pause!" >>>;
|
||||||
|
if(running) {
|
||||||
|
false => running;
|
||||||
|
} else {
|
||||||
|
spork ~ live();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void step() {
|
||||||
|
for(0 => int i; i < 8; i++) {
|
||||||
|
for(0 => int j; j < 8; j++) {
|
||||||
|
step(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(0 => int i; i < 8; i++) {
|
||||||
|
for(0 => int j; j < 8; j++) {
|
||||||
|
if(nextLifeState[i][j] != lifeState[i][j]) {
|
||||||
|
set(i, j, nextLifeState[i][j]);
|
||||||
|
spork ~ play(i, j);
|
||||||
|
}
|
||||||
|
nextLifeState[i][j] => lifeState[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void play(int x, int y) {
|
||||||
|
SinOsc s => ADSR env => dac;
|
||||||
|
tones[x][y] => s.freq;
|
||||||
|
env.set(20::ms, 100::ms, 0.7, 20::ms);
|
||||||
|
env.keyOn();
|
||||||
|
40::ms => now;
|
||||||
|
env.keyOff();
|
||||||
|
40::ms => now;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void step(int x, int y) {
|
||||||
|
countNeighbors(x, y) => int neighborcount;
|
||||||
|
if(lifeState[x][y] == 1) {
|
||||||
|
if(neighborcount == 2 || neighborcount == 3) {
|
||||||
|
1 => nextLifeState[x][y];
|
||||||
|
} else {
|
||||||
|
0 => nextLifeState[x][y];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(neighborcount == 3) {
|
||||||
|
1 => nextLifeState[x][y];
|
||||||
|
} else {
|
||||||
|
0 => nextLifeState[x][y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun int wrap(int x) {
|
||||||
|
if(x > 7) return 0;
|
||||||
|
if(x < 0) return 7;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun int countNeighbors(int x, int y) {
|
||||||
|
0 => int count;
|
||||||
|
wrap(x - 1) => int left_x;
|
||||||
|
wrap(x + 1) => int right_x;
|
||||||
|
wrap(y - 1) => int up_y;
|
||||||
|
wrap(y + 1) => int down_y;
|
||||||
|
|
||||||
|
lifeState[left_x][up_y] +=> count;
|
||||||
|
lifeState[x][up_y] +=> count;
|
||||||
|
lifeState[right_x][up_y] +=> count;
|
||||||
|
lifeState[left_x][y] +=> count;
|
||||||
|
lifeState[right_x][y] +=> count;
|
||||||
|
lifeState[left_x][down_y] +=> count;
|
||||||
|
lifeState[x][down_y] +=> count;
|
||||||
|
lifeState[right_x][down_y] +=> count;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void key(int x, int y, int z) {
|
||||||
|
if(z == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toggle(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun void toggle(int x, int y) {
|
||||||
|
if(lifeState[x][y] == 0) {
|
||||||
|
1 => lifeState[x][y];
|
||||||
|
} else {
|
||||||
|
0 => lifeState[x][y];
|
||||||
|
}
|
||||||
|
set(x, y, lifeState[x][y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Life @=> Life m;
|
||||||
|
m.init(monomePrefix, monomeHost, monomeIn, monomeOut);
|
||||||
|
|
||||||
|
fun void keyboardHandler() {
|
||||||
|
Hid hi;
|
||||||
|
HidMsg msg;
|
||||||
|
if(!hi.openKeyboard(0)) {
|
||||||
|
<<< "can't open keyboard" >>>;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while(true) {
|
||||||
|
hi => now;
|
||||||
|
while(hi.recv(msg)) {
|
||||||
|
if(msg.isButtonDown()) {
|
||||||
|
if(msg.which == 44) {
|
||||||
|
m.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spork ~ keyboardHandler();
|
||||||
|
|
||||||
|
while(true) { 1::second => now; }
|
Loading…
Reference in New Issue