Shazbot, I had a nice long post here and then hit the back button on my mouse and it was gone just that fast. Oh well. I''ll summarize.
I''m implementing background music for my game. I have never done music support in a game before, so this is what I have come up with on my own:
All audio in the game is done with OpenAL for simplicity and some parallelism with the graphics, which are done with OpenGL. There are several "music buffers" (several=a symbol #defined and easily changed) with a length of one second. This length is also easily changable.
bool StartMusic(const char SFilename[], byte SFlags);
This function opens a file that hopefully contains a song. Then, it fills all the music buffers with the first n (number of buffers) buffer lengths of audio. These buffers are queued to the OpenAL sound source from which music buffers are played and the source is told to play. The second parameter to this function contains flags that affect music play. Presently, the only flag I have come up with is whether or not the song should loop.
The function also spawns a thread that enters in another function. This function almost immediately enters a loop that checks for dequeued OpenAL buffers. If a buffer is dequeued (that is, it has finished playing) then it is filled with the next buffer''s worth of music and requeued. Once there are no pending buffers to deal with, the thread sleeps for a few seconds to allow other buffers to finish up so as not to waste time in an idle loop.
When the end of the song is reached, a choice must be made. If we were told to loop originally, we should finish off our buffer with data from the beginning of the song and just continue doing as if nothing happened. If we were not told to loop, we simply pass the buffer with a truncated length and then break out of the loop, after which the thread terminates and OpenAL finishes playing what it is queued on its own.
It would also be useful if, when a song is playing, we could interrupt it. This could happen if we want to stop the music, or to play another song. For this situation, I came up with two possible scenarios: We want the present song to stop instantly, or we want it to fade out.
void StopMusic(byte SEffect);
The parameter to this function defines how the music should stop; abruptly, or a smooth fade over the course of a second. Stopping instantly is easy, we just tell OpenAL to stop and terminate the music thread. Fading is something I have not implemented yet, but have thought about. I had planned to use AL_GAIN to do this, but that would require constantly passing a new value to get a smooth fade, which would not be very efficient. Presently, I am planning on using AL_VELOCITY and falloff parameters to make the music fade out.
My concerns in this are:
* Is this a fair way to implement background music?
* I want to support OGG Vorbis files, ultimately. Presently, the code works with raw audio files. Will this system serve efficiently with a different audio format?
--can a whole buffer of music be decoded in the music thread without causing stuttering in the game?
-->the size of the buffer, number of buffers, and amount of time the thread sleeps are easily configurable