//basic timing operations abbreviated public class TimeGrid { dur beat; dur meas; dur sect; int nbeat; int nmeas; //phase and magnitude of offset float measPhase; dur measOffset; fun void set(dur mybeat, int nb, int nm) { mybeat => beat; nb => nbeat; beat*nbeat => meas; nm => nmeas; meas*nmeas => sect; } //sync to beat fun void sync() { beat - (now % beat) => now; } fun void sync(dur T) { T - (now % T) => now; } //how long to sync to this duration fun dur syncDur(dur T) { return (T - (now % T)); } //minimum time fun dur tmin(dur a, dur b) { return (a < b) ? a : b; } //get beat in relation to section fun int guess() { //this approach would not count sections //return ((now % sect) / beat) $ int; //this approach is completely global return (now / beat) $ int; } //get the mod rhythm fun int bmod(int r) { return (r%nbeat); } fun int mmod(int r) { return (r/nbeat%nmeas); } fun int smod(int r) { return (r/nbeat/nmeas); } //section markers int g; int b; int m; int s; int i; int j; //for anything, really int c; //counter in measure int d; //counter in section //events for stuff Event newMeas; Event newSect; //update markers fun int up() { guess() => g; //experimental if ( b-bmod(g)>0 ) { //if b decreases 0=>c; newMeas.broadcast(); } else c++; //TODO: make a c but for the measure if ( m-mmod(g)>0 ) { //if m decreases 0 => d; newSect.broadcast(); } else d++; bmod(g) => b; mmod(g) => m; smod(g) => s; i++; return true; } //update the markers of another timeGrid fun int up( TimeGrid tg ) { this.up(); b => tg.b; m => tg.m; s => tg.s; g => tg.g; c => tg.c; i => tg.i; j => tg.j; return true; } //pause: make shred wait until input low //ill-concieved, really!, because it can't monitor a changing input /* fun void pause( int a ) { while ( a ) { beat=>now; sync(); } } */ }