First track from the Chopin MIDI generated from the examples directory:
top is generated using a version with PR fixes
bottom is the currently released version
There were 2 issues I had to tackle to fix this problem.
First was low precision in the addition of triplet and dotted durations causing rounding issues.
Second, harder part was delta slippage - even though it was calculated correctly, rounding was being done per note, and that meant that every 33.66 would always round up to 34. In reality this caused a slight shift forward or backwards whenever a complex duration event happened. Use 3 triplets and you were already 3 ticks ahead. To mitigate, I've added a concept of precision loss tracking within a track, which will apply the loss to each subsequent event in effort to correct it. This means that the same duration will sometimes last 34 and sometimes 33 ticks and so the rounding issue self-corrects with every subsequent event.
Incidentally I've added support more flexible durations (all durations are calculated dynamically).
This enables things like quintuplets (or any other custom tuplet), by adding a classifier after the duration name (e.g. 8t5). Triplets are the implied tuplet type - so same behavior as previously: 8t is same as 8t3.
Also, any power of 2 note duration is supported, so 128ths will work with all combinations too. And one can do triple dotted notes or quadruple dotted if one's into that 😄 (e.g. dddd4).
Finally, you can also do tuples of dotted notes (d4t) and more complex things like dd8t7 - a septuplet of double dotted eights 😂.
Hope this is satisfactory! Added a bunch of tests for these fixes and new behaviors too.
Wow, amazing job on this @niieani! Thanks very much for this contribution, adds so much value to the library. Will create new 1.7.5 release to include this.
Fixes #69.
First track from the Chopin MIDI generated from the examples directory:
There were 2 issues I had to tackle to fix this problem.
First was low precision in the addition of triplet and dotted durations causing rounding issues.
Second, harder part was delta slippage - even though it was calculated correctly, rounding was being done per note, and that meant that every 33.66 would always round up to 34. In reality this caused a slight shift forward or backwards whenever a complex duration event happened. Use 3 triplets and you were already 3 ticks ahead. To mitigate, I've added a concept of precision loss tracking within a track, which will apply the loss to each subsequent event in effort to correct it. This means that the same duration will sometimes last 34 and sometimes 33 ticks and so the rounding issue self-corrects with every subsequent event.
Incidentally I've added support more flexible durations (all durations are calculated dynamically).
This enables things like quintuplets (or any other custom tuplet), by adding a classifier after the duration name (e.g.
8t5
). Triplets are the implied tuplet type - so same behavior as previously:8t
is same as8t3
.Also, any power of 2 note duration is supported, so 128ths will work with all combinations too. And one can do triple dotted notes or quadruple dotted if one's into that 😄 (e.g.
dddd4
).Finally, you can also do tuples of dotted notes (
d4t
) and more complex things likedd8t7
- a septuplet of double dotted eights 😂.Hope this is satisfactory! Added a bunch of tests for these fixes and new behaviors too.