LiSa buffers[3]; string states[3]; Gain g => dac; // set up buffers int primary; for (0 => int i ; i < 3 ; i++) { adc => buffers[i] => g; 60::second => buffers[i].duration; 1 => buffers[i].loop; "silent" => states[i]; } // mix them evenly 0.3333 => g.gain; /* * state: * off - we start in this state, nothing is playing * - move to pri_rec on first tap * pri_rec - recording the first loop * - all rest syncs to this loop * - primary buffer num is stored in primary * - if primary is stopped but others are still running, set primary * to one of them * - set loop len, move to running on retap * - move to off on any other tap * running - loop len has been defined * - taps on pedals move them beteen * - silent - start state * - recording * - pedals in "recording" move to "looping" after one primary cycle * - if all pedals silent, then global off */ "off" => string state; // set up mouse 1 => int device; // if there are args, they're what mouse num to use if( me.args() ) me.arg(0) => Std.atoi => device; int btn; // which button Hid hi; HidMsg msg; if( !hi.openMouse( device ) ) me.exit(); <<< "mouse '" + hi.name() + "' ready...", "" >>>; fun void start_recording(int i) { <<<"recording primary", i>>>; "recording" => states[i]; 0 => buffers[i].play; 1 => buffers[i].record; buffers[i].playPos() => buffers[i].loopStart; buffers[i].playPos() => buffers[i].recPos; } fun void record_secondary(int i) { // record for one rotation of primary, then start looping <<<"waiting to record secondary until primary comes around", i>>>; buffers[primary].loopStart() => now; <<<"recording secondary", i>>>; "recording" => states[i]; 0 => buffers[i].play; 1 => buffers[i].record; buffers[primary].loopStart() => buffers[i].loopStart; buffers[primary].loopStart() => buffers[i].recPos; buffers[primary].loopEnd() => buffers[i].loopEnd; buffers[i].loopEnd() => now; if (states[i] == "recording") { // things might change while sleeping <<<"looping secondary", i>>>; "looping" => states[i]; buffers[i].recPos() => buffers[i].playPos; 0 => buffers[i].record; 1 => buffers[i].play; } else <<<"secondary killed in sleep", i>>>; } fun void start_looping(int i) { <<<"looping", i>>>; "looping" => states[i]; buffers[i].recPos() => buffers[i].loopEnd; buffers[i].recPos() => buffers[i].playPos; 0 => buffers[i].record; 1 => buffers[i].play; } fun void stop(int i) { <<<"stopping", i>>>; "silent" => states[i]; 0 => buffers[i].record; 0 => buffers[i].play; } while( true ) { // wait on event hi => now; // loop over messages while( hi.recv( msg ) ) { if( msg.isButtonDown() ) { msg.which => btn; if (state == "off") { "pri_rec" => state; for (0 => int i; i < 3 ; i++) "silent" => states[i]; btn => primary; primary => start_recording; } else if (state == "pri_rec") { if (btn == primary) { "running" => state; primary => start_looping; } else { "off" => state; primary => stop; } } else if (state == "running") { if (btn == primary) { // find new primary or we're off for (0 => int i; i < 3 ; i++) { if (i != primary && states[i] == "looping") { i => primary; break; } } if (btn == primary) { <<<"didn't find replacement">>>; for (0 => int i; i < 3 ; i++) i => stop; "off" => state; } else btn => stop; } else { // non-primary button if (states[btn] == "silent") spork ~ record_secondary(btn); else btn => stop; } } } } }