// Set the width of your monome, this should work hopefully... 8 => int xsize; 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 // this might need to be changed for non-64 monomes. 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[xsize][8]; for(0=>int i; iint j; j<8; j++) { env[i][j].set(5::ms, 5::ms, 0.95, 5::ms); env[i][j] => filt[j]; } } // Set up delay lines and connect things together Delay dla[xsize - 1]; 125::ms => dur bufferlen; for(0=>int i; i dla[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; // blah. int states[xsize][8]; dur sparkle_length; int x,y; spork ~ check(); spork ~ kb_check(); while (true) { // we don't do much here // random blinking can happen tho. Std.rand2(0,xsize - 1) => x; Std.rand2(0,7) => y; if (std.rand2(1,101) < chance_level) { Std.rand2(50,250)::ms => sparkle_length; spork ~ sparkle(x,y,sparkle_length); } pause_length => now; } // Check make the monome respond to touches // Here we also connect our delay lines to our adsrs, // which are already connected to the filters fun void check() { int o_x,o_y,o_state; 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); if (o_state == 1 && states[o_x][o_y] == 0) { 1 => states[o_x][o_y]; if (o_x == 0) { adc => env[o_x][o_y]; } else { dla[o_x - 1] => env[o_x][o_y]; } env[o_x][o_y].keyOn(); led_set(o_x,o_y,1); 15::ms => now; } else if (o_state == 1 && states[o_x][o_y] == 1) { 0 => states[o_x][o_y]; led_set(o_x,o_y,0); env[o_x][o_y].keyOff(); 15::ms => now; if (o_x == 0) { adc !=> env[o_x][o_y]; } else { dla[o_x - 1] !=> env[o_x][o_y]; } } //<<<"button press: ", o_x, o_y, o_state >>>; } 5::ms => now; } } // 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 sparkle(int x, int y, dur leng) { // determine which buffer to play //<<< "playbuf: ", playbuf>>>; // now connect it to the right filter and start playback //l[playbuf].playPos(0); if (x == 0) { adc => env[x][y]; } else { dla[x - 1] => env[x][y]; } env[x][y].keyOn(); 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 => now; if (x == 0) { adc !=> env[x][y]; } else { dla[x - 1] !=> env[x][y]; } 1::ms => now; } // 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; }