public
Description: COmpact Sequencing sYntax
Home | Edit | New

midilib notes

Absolute Time Requires Stable Sorting

By default, midilib wants to insert events into a track using delta times. I found this to be rather inconvenient. It’s easier to work with absolute times. midilib supports absolute times, but it requires that a call to Track#recalc_delta_from_times.

Here’s a problem: recalc_delta_from_times uses Ruby’s built in Array#sort which is not a stable sorting algorithm. A stable sort will maintain the relative positions of any elements that are equal, while a non-stable sort will randomly reorder equal elements. This is important when we are generating a perfectly legato MIDI sequence (which Cosy does by default). In a legato sequence, a noteoff may occur at the same MIDI tick as a noteon. If we are repeating the same note, the noteoff must occur first or else we’ll start a new note and then immediately turn it off.

So for example, say we are repeating a note C4. The events at a MIDI tick should look like this:
[time]: [event]
0: C4 noteon
480: C4 noteoff
480: C4 noteon
960: C4 noteoff

If we were to sort these events using a non-stable sorting algorithm, then we could randomly end up with this:
0: C4 noteon
480: C4 noteon
480: C4 noteoff
960: C4 noteoff
And the second C4 noteon will immediately be turned off by the noteoff that was intended for the first C4.

To correct this issue, I had to introduce a stable sorting algorithm (merge sort) and redefine Track#recalc_delta_from_times to use it.

Last edited by adamjmurray, Sun Nov 16 22:06:02 -0800 2008
Home | Edit | New
Versions: