CommandTracker: Mostly ideas for a music tracker sparse file format
Posted: Fri Jan 15, 2021 7:36 pm
Given VERAsound will now replace the SAA1099, and given some other conversations on the forums (such as the conversation about envelopes in this post), I opted to take another look at my proposed tracker file format, which you can find here:
https://gitlab.com/m00dawg/commander-x16-programs/-/blob/master/command_tracker/index.md
I've talked about this before on the FB group, but I've opted to stop using FB and thought it would be a better conversation had here anyway.
The main issue is that there are 26 channels so to optimize for storage on playback, a sparse format is probably worth the extra complexity in playback routines. I had the idea of supporting multiple effects since this is a common feature in modern trackers (even FamiTracker has this). That may go by the wayside, but even if each channel only had single volume and effect columns, I came up with 5 bytes per channel for VERASound and FM and 3 bytes for DPCM. So a single row would be 126 bytes and a 64 row pattern would be 8064 bytes! The file format I came up with can support multiple effects per channel, and when you include these it balloons to a staggering 41.6k if I did my math right.
But given even complicated patterns have empty space in them, by using a sparse format these requirements go down considerably. Only rows which have data are defined and, within that, only channels which have data are defined. So a row can be as few as 3 bytes if there's only one channel playing on that row with no effects.
I made an attempt to show the proposal row format here but I can't find a way to insert code blocks and it was really hard to read without a monospace font. So I recommend looking at the link (specifically the sparse patterns link)
The trade-off is a playback routine has to track a lot more things as opposed to just reading a pattern row by row. I don't think it would be too terrible since there could be a row counter and if the current row read is greater than the counter, nothing is done. When the counter equals the current row, it then can parse out the row to do the things. This ignores envelopes and some automatic commands (like how the volume slide works in Famitracker as compared to how it works in Impulse Tracker) as those could be firing while there is no row data.
Figuring out how to efficiently edit pattern data is another task entirely though. If one adds data to a previously empty row, the sparse file would have to be reorganized. The best solution here is having a non-sparse pattern buffer - which would be fine for a dedicated tracker where we have room to move about. But given the space requirements, it means patterns would span multiple pages and that could get interesting when adding in things like envelope tables and things.
I should say I'm not an awesome assembly programmer - just a musician who is very excited about the prospects of a tracker, but given the vast sound capabilities of the X16, it feels like it will take some thought to do well given the "limited" space (which is itself far more than the 8-bit systems of yesteryear). That's why I thought it might be good to try and start the conversation by coming up with at least something that can serve as talking points.