Hi, I love your player!! But there's just a few bugs. Thanks to you making it open source I was able to investigate the occasional "zero duration notes" issue even in non-staccato channels. I think the fix is to simply alter sort_ascending() in beat_detection.gd to look like this:
func sort_ascending(a, b):
if a[2] == b[2]:
if a[1] == -100 or a[1] == -128:
return true
if a[2] < b[2]:
return true
return false
With that little addition the MIDI note off events will be sorted before new note on events. I didn't look into your note processing logic for a reason as to why that causes an issue, but it was definitely related to note on/off triggering at the same time, and with this change I didn't see the issue come up on my test songs.
Hope it's useful, and thanks for making this great player!! :)