Schedulers and Real-time Performance

Event lists have events sorted by their relative start times. One "performs" event lists by placing them in a schedule for performance. A schedule can have one or more client objects (usually event lists) that are assumed to be able to do something in response to the (scheduleAt: aTime) message. The return value from this message is assumed to be the delay before calling the client again. Event lists typically perform the next event (by passing it to its voice) and answer the relative delta time to the next event (which may be 0 for simultaneous events).

The global EventScheduler instance can be accessed by a class message (schedule) to class Siren; it can be used to sequence and synchronize event lists that may include a variety of events, event lists, and voices.

The Scheduler messages for adding a new "client" and running the schedule are as follow.

   [EventScheduler instance addClient: (EventList randomExample: 20) at: 500 msec.
    EventScheduler instance run]

   [EventScheduler instance addClient: ActionEvent listExample in: (1000 msec); run]

   [EventScheduler instance isRunning]
   [EventScheduler instance interrupt]
   [EventScheduler instance flush]

The standard voices for MIDI and OSC output use the built-in schedule for their timing.

Play 64 notes lasting 80 msec--a good test of real-time performance.
This is scheduled in the port, i.e., at the lowest-possible level.

   [MIDIPort testRandomPlay2: 64 dur: 80]

Test a roll--it's easier to hear scheduler jitter here. The first example uses the low-level port delays. (try it several times to hear the changes in the jitter.)

   [MIDIPort testRoll: 40 dur: 60]

This should sound about the same, but plays an event generator over the the high-level scheduler.

   [((Roll length: 2400 rhythm: 60 note: 60) ampl: 96) play]

This example uses the high-level EventScheduler to play a scale. (Jitter is harder to hear here.)

   [MIDIDevice scheduleExample]