public class Time { 60 => float bpm; static dur length_quarter; static dur length_eight; static dur length_sixteen; 1::minute/bpm => length_quarter; length_quarter/2 => length_eight; length_quarter/4 => length_sixteen; static Event quarter; static Event eight; static Event sixteen; static int ids[10]; 1 => int midi_dev; MidiIn midi_in; MidiMsg midi_msg; 36 => int listen_key; if (!midi_in.open(midi_dev)) me.exit(); Shakers inst => dac; fun static void start() { spork ~ sendQuarter(); } fun void stop() { for(0 => int i; i < ids.cap(); i++) if(ids[i] != 0) { machine.remove(ids[i]); 0 => ids[i]; } } fun void addId(int id) { for(0 => int i; i < ids.cap(); i++) if(ids[i] == 0) { id => ids[i]; ids.cap() => i; } } fun void sendQuarter() { addId(me.id()); while(true){ inst.noteOn( 0.5 ); quarter.broadcast(); length_quarter => now; } } fun void sendEight() { while(true){ quarter.broadcast(); length_eight => now; } } fun void sendSixteen() { while(true){ sixteen.broadcast(); length_sixteen => now; } } fun void update_from_quarter(dur quarter) { quarter => length_quarter; 1::minute/length_quarter => bpm; length_quarter/2 => length_eight; length_quarter/4 => length_sixteen; } fun void listen() { 2::second => dur timeout; now => time first_tap; now => time latest_tap; 0 => int tap_count; 4 => int nb_taps; while(true){ midi_in => now; while(midi_in.recv(midi_msg) ) { // listen for noteon (144) on listen_key if(midi_msg.data1 == 144 && //midi_msg.data2 == listen_key && midi_msg.data3 != 0) { if(now - latest_tap < timeout) { 1 +=> tap_count; if(tap_count == 1) { //now => first_tap; } else if(tap_count == nb_taps ) { stop(); update_from_quarter((now - first_tap)/nb_taps); start(); now => first_tap; 0 => tap_count; } } else { now => first_tap; 0 => tap_count; } now => latest_tap; } } } } } Time T; T.start(); //spork ~ T.sendQuarter(); //spork ~ T.sendEight(); //spork ~ T.sendSixteen(); //spork ~ T.listen(); //2::second => now; //T.stop(); // keep alive while(true){ 100::minute => now; }