Tracker music looping behavior (state retention)

Hello everyone. The OldUnreal team maintains various audio drivers for Unreal 1 and Unreal Tournament 99, including one based on FMOD, another based on OpenAL Soft + XMP, and one based on Carlo Vogelsang’s Galaxy Music system. The latter came with the original games. We recently noticed a discrepancy in how these three backends handle state retention when a tracker music sample loops automatically (i.e., without a manual loop command).

Galaxy resets all channel and global state when a track loops. This state includes the volume and playback speed.
XMP seems to retain at least some of the state, but added automatic volume reset in versions 4.4.0 and 4.4.1.
FMOD also retains state and does not seem to have an option to reset it.

This is a problem for us since some of the games’ original tracks end with a volume fadeout sequence. When FMOD plays these tracks with looping enabled, they sound fine on the first loop, but are completely silent from the second loop onwards (except for the fadeout sequence at the end).

A good example is the track shown in this screenshot. I can mail this file directly to whoever wishes to look into this, but cannot upload it to a public folder because it is copyrighted.

Pattern 92 gradually reduces the global volume from 0x40 to 0x00. Pattern 93 briefly resets the global volume to 0x40 and then back to 0x00. The pattern then ends without any manual loop commands so FMOD jumps back to the initial pattern in the sequence. The volume control sequence in pattern 93 might seem odd, but we have actually found several tracks with a similar sequence, including some that came with the game.

To play this track with FMOD, we were forced to load them with FMOD_LOOP_OFF | FMOD_ACCURATETIME, and we have to restart it manually when it ends without a manual loop command.

Is there a way to automatically reset all relevant state when a track loops? If not, could such an option be added?


When a song doesn’t loop like this, it is really a problem with the song. Proper tracker behaviour is to jump back to the start point and not interfere with the playing notes. Galaxy is wrong to reset everything.
Like you said, if you want to ‘fix’ these songs, you would use FMOD_ACCURATETIME, play it as a oneshot, and with an end callback, stop and restart the song.

Proper behaviour gets a little fuzzy with implementation driven file formats…

There is merit to resetting and not resetting the state upon loop. OpenMPT addresses this by adding an (off by default) option to reset on loop:

I would appretiate having that as a toggleable (global) option as part of FMOD_SYSTEM’s state as well.

Having worked prior on said OpenAL backend, when porting the Galaxy backend over to FMOD I perceived the low code complexity on the application side needed in FMOD as one of it’s core strengths. Adding more complexity to the code for looping behaviour feels like it undermines one of FMODs core stengths.