Re: Sources and Buffers

Chris Robinson <[email protected]> Mon, 19 Nov 2012 13:50:57 -0800
Newsgroups gmane.comp.lib.openal
Message-ID <[email protected]>
On 11/19/2012 11:57 AM, [email protected] wrote:
> Now, it occurs to me I could do something similar by having a single
> Source for the Engine, and queuing up buffers in the right sequence for
> that single Source to play...
>
> Engine_Source.queueBuffer(N1_loop_buffer)
> Engine_Source.setLooping(true)
> Engine_Source.play()
> <throttle change event>
> Engine_Source.setLooping(false)
> Engine_Source.queueBuffer(N1-N2_buffer)
> Engine_Source.queueBuffer(N2_loop_buffer)
> <Wait long enough to be sure we're in the N2_loop buffer>
> Engine_Source.setLooping(true)
>
> BUT ... this seems to create two issues... one is that it's not entirely
> clear to me how to tell the Source to loop ONLY the last buffer, nor is it
> clear to me how to tell which buffer is currently being played (I think
> for the latter I can poll the AL_BUFFER property or do some math on
> AL_BUFFERS_QUEUED and AL_BUFFERS_PROCESSED).

If you want to avoid gaps in playback, you'd pretty much need to go with 
a one-source streaming method:

// Set up the current Notch sound to play
Current_Notch = Notch1;
...
while(running) {
     // Check if the Notch was changed. Consecutive changes will queue
     // up, so for example going from 1 to 2, then 2 to 3 quickly will
     // make it play 1 to 2 to 3 in succession, before the new notch
     // sound plays.
     while(<throttle change event>)
     {
         Current_Notch = New_Notch;
         Engine_Source.queueBuffer(OldNotch_to_NewNotch);
     }

     // Remove processed buffers
     while(Engine_Source.processedBuffers() > 0)
         Engine_Source.unqueueBuffer();

     // Keep the source fed with the current Notch sound
     while(Engine_Source.queuedBuffers() < 2)
         Engine_Source.queueBuffer(Current_Notch);

     // Make sure the source is still playing
     if(Engine_Source.getState() != AL_PLAYING)
         Engine_Source.play();
}

How well this will work depends on the length of the sounds. If the 
sounds are short you may need to keep more copies queued so it doesn't 
underrun, but longer sounds will increase the lag since the current 
queue has to finish before the changes are heard.


You could reduce the lag by switching to a two-source method, but that 
brings a risk of a slight break when changing between sources:

Notch_Source.setLooping(true);
Notch_Source.setBuffer(Notch1);
Notch_Source.play();

while(running) {
     // Check if the Notch was changed.
     while(<throttle change event>)
     {
         NotchRamp_Source.queueBuffer(OldNotch_to_NewNotch);
         if(NotchRamp_Source.getState != AL_PLAYING)
             NotchRamp_Source.play();

         Notch_Source.stop();
         Notch_Source.setBuffer(NewNetch);
     }

     // Remove processed buffers
     while(NotchRamp_Source.processedBuffers() > 0)
     {
         NotchRamp_Source.unqueueBuffer();
         // Start playing the new Notch when finished ramping
         if(NotchRamp_Source.queuedBuffers() == 0)
             Notch_Source.play();
     }
}

This will cause the engine sound to start changing right when it's 
modified, but the new notch sound may start with a slight break after 
the change is finished.

You could probably mask the problem, however, by restarting Notch_Source 
earlier and fading it in before NotchRamp_Source finishes, if you don't 
mind a little overlap.
_______________________________________________
Openal mailing list
[email protected]
http://opensource.creative.com/mailman/listinfo/openal