It is generally working but I need to clean up the source to make it coexist nicely with the standard kernel. The streaming music can be used and configured by specifying:
Code: Select all
-DMUSIC_ENGINE=STREAM
-DSONG_BUFFER_SIZE=24##default if not specified
-DSONG_BUFFER_MIN=6##default if not specified
In addition to the buffer, it uses an added 16 bit value for loopEnd(it doesn't use songStart, so maybe we save those over stock) which is how the entire trick of it all works to avoid race conditions and loop correctly without ever reading bytes it can't use when it "reads past" the end of the song. I figured out how to properly handle out of data situations in a graceful way, so it no longer crashes, but simply extends the current delta time until enough data is available. This has the effect that if a buffer is too small and/or buffer filling operations are too slow for the particular part of the song, it just stretches out over a longer period of time. If it is too extreme it is noticeable but not horribly jarring, and better than other alternatives. So far I see promising results, where just 1 byte written to the buffer per frame with a 24 byte buffer, is able to play a reasonably complex song back, only slowing down gracefully during the most demanding parts. This seems key, since it is hard to predict individual SD card performance, individual game ticks, and developers are of course going to desire pushing things to the absolute limit instead of hauling a huge buffer around. I want to make performance maybe 50% better than this, so that such as 2 bytes read per frame on average, will not slow at all for most songs with a 16 byte buffer. This should work out, and also this would apply to flash music which could probably be 50+% smaller in this format. More to come on this.
BTW I would appreciate if anyone has opinions on uzeboxSoundEngine.c in the new "streaming-music" branch. I added an in process copy of the source that is being cleaned up, and also removed all things related to MIDI_IN. It just cleans the source up, and I do not think anyone ever did much with it, as well as the MIDI connector is not even standard since a long time ago. This seems wise to me because there are better ways to do it anyway(the existing implementation did not use HSYNC buffering, so missed bytes randomly anyway), but let me know if anyone disagrees.
I have been just feeding the stream from flash for now since it was more convenient, but this will give a rough idea of how to interface with it:
Code: Select all
uint16_t soff = 1;
while(!SongBufFull())
SongBufWrite(pgm_read_byte(&Song1[soff++]));
WaitVsync(60);
StartSong(0);
while(1){
WaitVsync(1);
if(loopEnd){//we read past the end of the song..luckily it is padded with bytes from the loop start
soff = (soff-loopEnd)+loopStart;
loopEnd = 0;
}
for(uint8_t i=0;i<1;i++){
if(SongBufFull())
break;
SongBufWrite(pgm_read_byte(&Song1[soff++]));
}
}