OscSend xmit; xmit.setHost("localhost", 8080); // Set the prefix to /sparkle xmit.startMsg("/sys/prefix,s"); "/sparkle" => xmit.addString; 1::ms =>now; OscRecv recv; 8000 => recv.port; recv.listen(); recv.event("/sparkle/press,iii") @=> OscEvent oe; // filter setup; going for 8 octave-wides BPF filt[8]; filt[7].set(60.0,1.41); filt[6].set(120.0,1.41); filt[5].set(240.0,1.41); filt[4].set(480.0,1.41); filt[3].set(960.0,1.41); filt[2].set(1920.0,1.41); filt[1].set(3840.0,1.41); filt[0].set(7680.0,1.41); // Now we're going to declare an 8x8 array of ADSRs, (one for each possible grain) to fight the clicks ADSR env[8][8]; for(0=>int i; i<8; i++) { for(0=>int j; j<8; j++) { env[i][j].set(3::ms, 5::ms, 0.95, 3::ms); env[i][j] => filt[j]; } } //LiSa setup LiSa l[8]; 0 => int recbuf; 125::ms => dur bufferlen; for(0=>int i; i<8; i++) { l[i].duration(bufferlen); l[i].maxVoices(8); l[i].clear(); l[i].recRamp(15::ms); //l[i].loopEndRec(bufferlen); l[i].record(0); 1.25 => l[i].gain; adc => l[i]; filt[i] => dac; 0.9 => filt[i].gain; } // random chance percentage !!! // 0 means never random, 100 means always! 0 => int chance_level; // change as it suits you; this affects sparkle density 10::ms => dur pause_length; // change this for models other than 40h and 64 // ACTUALLY JUST CHANGING THIS WILL NOT WORK RIGHT NOW 7 => int x_size; 7 => int y_size; // blah. [ 0, 0, 0, 0, 0, 0, 0, 0 ] @=> int states[]; [ 0, 0, 0, 0, 0, 0, 0, 0 ] @=> int breaker[]; dur sparkle_length; int x,y; spork ~ check(); spork ~ recCycle(); spork ~ kb_check(); while (true) { Std.rand2(0,x_size) => x; Std.rand2(0,y_size) => y; //make sure first rand argument is greater than bufferlen plus a bit if (std.rand2(1,101) < chance_level) { Std.rand2(50,250)::ms => sparkle_length; spork ~ sparkle(x,y,sparkle_length); pause_length => now; } else { for (0=>int i; i<8; i++) { if (states[i] == 0 ) { spork ~ sparkle(0,i,bufferlen - pause_length); } } pause_length => now; } } // Check and trail make the monome respond to touches // start trails for most touches, or abort for touches in the left column // change the long and short times if you don't like them fun void check() { int o_x,o_y,o_state; dur long, short; while (true) { while(oe.nextMsg() != 0) { oe.getInt() => o_x; oe.getInt() => o_y; oe.getInt() => o_state; led_set(o_x,o_y,o_state); Std.rand2(400,4000)::ms =>long; Std.rand2(75,250)::ms => short; if (o_x == 0 && o_state == 1) { 1 => breaker[o_y]; } if (o_x == 0 && o_state == 0) { 0 => breaker[o_y]; } if (o_state == 1) { spork ~ trail(o_x,o_y,long,short); } //<<<"button press: ", o_x, o_y, o_state >>>; } 5::ms => now; } } // here we'll keep our LiSa buffers recording circularly // borrowed from LiSa munger2... fun void recCycle() { l[recbuf].recPos(0::ms); l[recbuf].record(1); while(true) { now + bufferlen => time later; while (now now; } l[recbuf++].record(0); if(recbuf == 8) 0 => recbuf; l[recbuf].record(1); } } // Now let's watch the keyboard so we can adjust our randomness fun void kb_check() { Hid hi; HidMsg msg; // which keyboard 0 => int device; // I'll just assume we use the first one... // open keyboard (get device number from command line) if( !hi.openKeyboard( device ) ) me.exit(); <<< "keyboard '" + hi.name() + "' ready", "" >>>; // infinite event loop while( true ) { // wait on event hi => now; // get one or more messages while( hi.recv( msg ) ) { // check for action type if( msg.isButtonDown() ) { // this is where we need that switch/case jammy jam // also these numbers are for the mac keyboard! you might need to change them. if (msg.which == 46 && chance_level < 100) { 2 +=> chance_level; } else if (msg.which == 45 && chance_level > 0) { 2 -=> chance_level; } else if (msg.which == 18 || msg.which == 39) { 0 => chance_level; } // <<< "chance_level= ", chance_level>>>; // uncomment if you want to see the current level //<<< "down:", msg.which, "(code)", msg.key, "(usb key)", msg.ascii, "(ascii)" >>>; } } } } fun void trail(int x, int y, dur long, dur short) { long + now => time later; while (now < later) { if (breaker[y] == 0) { if (maybe) { sparkle(x,y,short); // or sparkle(Std.rand2(1,x),y,short); short / 2 =>now; } 5::ms => now; } else { break; } } } fun void sparkle(int x, int y, dur leng) { states[y]++; // determine which buffer to play (8 + recbuf - x ) % 8 => int playbuf; //<<< "playbuf: ", playbuf>>>; // now connect it to the right filter and start playback //l[playbuf].playPos(0); if (playbuf == recbuf) { adc => env[x][y]; } else { l[playbuf] => env[x][y]; l[playbuf].playPos(0); } env[x][y].keyOn(); 10::ms => l[playbuf].rampUp; led_set(x,y,1); leng - 21::ms => now; led_set(x,y,0); // now stop ramp down, stop play, and disconnect env[x][y].keyOff(); 10::ms => l[playbuf].rampDown; 10::ms => now; if (playbuf == recbuf) { adc !=> env[x][y]; } else { l[playbuf] !=> env[x][y]; } 1::ms => now; states[y]--; } // Add error checking in here somewhere. fun void led_set(int x,int y,int s) { xmit.startMsg("/sparkle/led,iii"); x => xmit.addInt; y => xmit.addInt; s => xmit.addInt; }