The output side was tricky however, because you can't write events directly to a MIDI device that's been opened for synchronized streaming (as opposed to immediate output, as in ChordEase). Instead your callback function (which is being called at regular intervals by Windows) has to add the events to its next buffer, which it subsequently queues to the output device. My solution was to add a special input queue for "live" events. At the start of each callback, I check the live input queue, and if there are events in it, I dequeue them and add them to the start of my next MIDI buffer, before any events that may get added from the song's tracks. This is quite safe (provided a thread-safe queue is used) and it works pretty well. It does have some limitations though.
-
MIDI thru is only operational while the sequencer is playing, not
while it's stopped or paused. This is potentially annoying, and the only
solution is to keep the MIDI output device open all the time, not only
during playback. Doing so would have the additional benefit of reducing
the lag between pressing "Play" and playback actually starting. Most of
that lag is caused by opening the device, though some devices are worse
than others. It's a cool idea and it's on the list, but I'm not going to
deal with it right away.
-
The delay can be longer than one might like, depending on how the
sequencer's latency is set. At the default latency of 10ms, it's
probably fine for controlling parameters, but Chopin is out of the
question. The sequencer's latency can be set lower, all the way down to
1ms, but the lower it is, the greater the risk of timing glitches in
song playback, due to the callback taking too long and not being able to
keep up. This also depends on other factors such as tempo and the
density of the sequence.
-
The delay isn't constant. This is because I grab all the live input
events that have occurred since the last callback and write them all to
the start of the buffer. They probably didn't all happen at the same
time, but they're all output at the same time. In other words, the live
input can get "bunched up" into discrete packets.
The live input queue also makes it possible to do live patch changes, along with volume and panning. This is already implemented in the Channels bar. The addition of a MIDI input device is a prerequisite to other useful things, such as MIDI mapping of all parameters, which is also on the list.
No comments:
Post a Comment