Work around crashes in MIDIUtil
#5
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The test project triggers several bugs in the third-party
MIDIUtil
dependency.These bugs are caused by the de-duplication algorithm in
MIDIUtil
and a mismatch of expectations between itself and the de-interleaving step that follows.Bug 1: Crash due to de-duplication
The first bug can be triggered by two or more
NoteOn
events that happen at the same time but have different durations. In that case, the de-duplication algorithm removes duplicateNoteOn
events but leaves theNoteOff
events untouched because they occur on different ticks.This throws the ratio of
NoteOn
toNoteOff
events out of balance and causes a stack underrun in the de-interleaving algorithm.Example for such a group of events, discovered in the included test pattern:
Reproducer
Output
The output reveals a duplicate note at tick 1680 but with different durations, and another at tick 1920:
This bug is one of the causes for upstream issue MarkCWirt/MIDIUtil#34.
A fix for the de-interleaving algorithm has been proposed upstream, allowing unbalanced event ratios. However, the upstream project appears unmaintained so the fix might never make it into a new release of
MIDIUtil
.As a workaround for
polyendtracker-midi-export
, this PR skips MIDIUtil’s de-duplication step, which seems to be unnecessary for the use case of this project anyway.Bug 2: Crash due to zero-duration notes
If a
NoteOff
event appears at exactly the same MIDI tick as its correspondingNoteOn
event, then MIDIUtil’s sorting key causes theNoteOff
to appear first, crashing its de-interleaving algorithm.Hence, MIDIUtil always crashes on a note whose duration is 0.
Example for a zero-duration note, discovered in the included test pattern:
Reproducer
Output
The output reveals a zero-duration note at tick 4559, which would cause MIDIUtil’s de-interleaver to crash:
To work around this issue, this PR skips generating a MIDI note if its duration would be zero in MIDIUtil’s time granularity, which is currently 960 ticks per quarter beat.
This bug is probably another cause for MarkCWirt/MIDIUtil#34.