samer@0: function Timer=msched(e0) samer@0: % msched - Schedule events where each event returns the next event. samer@0: % samer@0: % msched :: samer@0: % cell { samer@0: % double ~'time of event', samer@0: % event ~'first event action' samer@0: % } samer@0: % -> action timer ~'timer being used'. samer@0: % samer@0: % event ::= samer@0: % ( double ~'scheduled time', samer@0: % double ~'actual time' samer@0: % -> action ( samer@0: % event ~'the next event action', samer@0: % double ~'time for next action', samer@0: % double ~'execution time of current event' samer@0: % ) samer@0: % ). samer@0: samer@0: % this is most like a Routine or Task in Supercollider, except samer@0: % that instead of coroutining via yield, each action explicitly samer@0: % returns the continuation action. samer@0: samer@0: persistent ERROR samer@0: samer@0: ERROR=[]; samer@0: warning('off','MATLAB:TIMER:STARTDELAYPRECISION'); samer@0: samer@0: [t0,a0]=cdeal(e0); samer@0: samer@0: Timer=timer; samer@0: set(Timer,'TimerFcn',@(o,e)timercb(o,e,t0,a0),'StopFcn',@chain); samer@0: set(Timer,'StartDelay',max(0,t0-nows)); % there will be some small error here.. samer@0: start(Timer); samer@0: samer@0: function timercb(o,e,t,a) samer@0: [a1,t1,tt]=a(t,e.Data.time); samer@0: set(o,'UserData',{a1,t1}); samer@0: ERROR=vertcat(ERROR,tt-t); samer@0: end samer@0: samer@0: function chain(o,e) samer@0: [a1,t1]=cdeal(get(o,'UserData')); samer@0: correction=mean(ERROR); samer@0: while ~isempty(t1) samer@0: tnow=nows; samer@0: delay=t1-correction-tnow; samer@0: if delay>=0, samer@0: set(o,'TimerFcn',@(oo,ee)timercb(oo,ee,t1,a1)); samer@0: set(o,'StartDelay',delay); samer@0: start(o); samer@0: return; samer@0: end samer@0: [a1,t1,tt]=a1(t1,tnow); samer@0: end samer@0: samer@0: fprintf('\n| stopping\n'); samer@0: set(o,'UserData',ERROR); samer@0: timer_release(o); samer@0: end samer@0: end