KimikoMuffin's picture

Audio-loop with intro?

So, I'd been trying to figure out how to do sounds and music with an intro-and-loop setup (which is to say, it would play the intro part, then seamlessly play the loop part forever or until you stop it). My preleminary research (read: quick Google search) suggests that OpenAL doesn't even have support for "loop points" as such.

After some experimentation, I've figured out something that kind of works:

  • Split the "intro" and "loop" into separate buffers.
  • Enqueue only the "intro" part into the given source. (Or both; technically, it works either way.)
  • Wait until there's only one unprocessed buffer in the source's queue, then add the "loop" buffer to the queue.

Or, code-wise, like this, if we were putting it into an OpenTK.GameWindow:

//...
AudioContext AC;
int IntroBuffer;
int LoopBuffer;
uint SoundSource;
 
//...
 
protected override void OnLoad(EventArgs e)
{
	//...
	AC = new AudioContext();
 
	//Generate sound-buffer: testloop beginning
	AL.GenBuffers(1, out IntroBuffer);
	AudioReader sound = new AudioReader("loopytesty b.wav");
	AL.BufferData(IntroBuffer, sound.ReadToEnd());
 
	//Generate sound-buffer: testloop loop
	AL.GenBuffers(1, out LoopBuffer);
	sound = new AudioReader("loopytesty l.wav");
	AL.BufferData(LoopBuffer, sound.ReadToEnd());
 
	//Generate source
	AL.GenSource(out SoundSource);
 
	//Queue the intro-buffer.
	AL.SourceQueueBuffer((int)SoundSource, IntroBuffer);
 
	//Play the source.
	AL.SourcePlay(SoundSource);
	//...
}
 
protected override void OnUpdateFrame(FrameEventArgs e)
{
	//...
	int getProcessed;
	int getQueued;
	AL.GetSource(SoundSource, ALGetSourcei.BuffersProcessed, out getProcessed);
	AL.GetSource(SoundSource, ALGetSourcei.BuffersQueued, out getQueued);
 
	//If there's only one unprocessed sound in the queue ...
	if (getQueued - getProcessed == 1)
	{
		//... queue the loop-buffer!
		AL.SourceQueueBuffer((int)SoundSource, LoopBuffer);
	}
	//...
}

And this actually works, for the most part! The thing is, this seems like a fairly hack-ish solution. I mean, okay, if there isn't a better way, I'm willing to settle for this, but, well, I'd really prefer it if there was something that could be done within OpenAL itself. (I suppose technically, this would fail if the sound's length is shorter than update-rate, not to mention integer-overflow after 2,147,483,647 loops, but I guess if a programmer honestly expects either of these issues to be common situations which you could reasonably expect to have happen in their game, we have a problem.)

The point is: Is there a better way of doing an audio-loop-with-intro, or is this really the best way of doing it?