[Openal-devel] Another extension..

Chris Robinson chris.kcat at gmail.com
Thu Nov 6 09:53:32 PST 2008


On Thursday 06 November 2008 02:25:30 am you wrote:
> Hi Chris,
>
> I'm not sure how safe this extension would be ...
>
> The same Buffer can be attached to more than one Source - which could all
> be playing the Buffer at different playback positions (and at different
> pitches).    You would need to know where all the Source read (or write)
> cursors are in an atomic operation if you wanted to be sure to avoid
> glitches.

Wouldn't this also be the case for DirectSound, though? 
IDirectSound::DuplicateSoundBuffer in essence creates another source that 
shares the original's buffer. Locking one dsound buffer affects the other, 
and each dsound buffer can have its own read/write position and pitch (and 
have such pitch be modified by doppler).

> FYI ... In ALchemy (DirectSound -> OpenAL converter) I had to emulate
> DirectSound circular buffer streaming using OpenAL buffer queuing.   I do
> that by creating a few small AL Buffers that are constantly unqueued,
> filled and re-queued using a multimedia timer.   Each time a Buffer is
> processed, the emulated DirectSoundBuffer play cursor is incremented by the
> processed buffer length. Each time a new buffer is queued, the
> DirectSoundBuffer write cursor is incremented by the queued buffer length
> (these happen all in the same update so the play and write cursors maintain
> the same distance apart).   As the application should never be writing
> between the play and write cursors (which would be the data contained in my
> Source Buffer Queue) everything works OK.   Would something similar work
> for you?

This is something I tried, but I ran into difficult issues. To be completely 
honest and open about this, I'm also trying to make a dsound->openal wrapper. 
Mostly for Wine (which with an openal dll thunk can make dsound apps work 
using the host system's openal lib, whichever it may be; I currently have 
Morrowind/Oblivion outputting full 3D surround sound via openal-soft on 
Linux), but also to provide a native Linux/Unix dsound lib to help with 
porting over Windows apps. It is working, but without an extension like this, 
updating the buffer is unstable. The main issues I had were:

A) Actually getting a dsound buffer into streaming mode. I wouldn't trust the 
lack of the DSBCAPS_STATIC flag to mean the buffer would definitely be 
updated during play, nor does the presence of it mean it can't be updated 
during play. I would attach the buffer to the source on dsound buffer init so 
that SetCurrentPosition and other such calls would work. Because of this, on 
Unlock I would have to try get the source's position, stop/rewind it, detach 
the buffer, rebuffer the data (and hope there wasn't a duplicated buffer also 
using it that would prevent alBufferData from failing), reattach the buffer, 
then reset the source's position. One or two alBufferSubDataEXT calls would 
do less work than the alBufferData+reattach calls alone, as it would just 
update an existing section of data instead of reloading the whole thing.

B) No way to keep a sane write-ahead value. Freq/refresh would come out to be 
somewhere around 1K for me (~4K buffer with 4 periods). 1K on 48khz output is 
21ms. This is best case.. an update will take 21ms worth of data, then rest, 
allowing me to unqueue and requeue a buffer. Realistically I'll need at least 
two buffers so I can requeue one while the other is being played, but I'll 
likely need three or four if I want to be sure I won't miss requeues due to 
unexpected CPU use or thread locks, getting up to 84ms of data queued at any 
given time. Some games start breaking down when they get a write cursor more 
than 15ms in front of the read cursor (Wine had documented this; a particular 
game would break if the write cursor was 20ms or more ahead of the read 
cursor, but would be fine if it was reported as only 10 or 15ms ahead).

And that's saying nothing about the added CPU cost, or extra code complexity 
for bugs to hide in, etc. AL_EXT_buffer_sub_data solves all of that by 
providing the necessary functionality cleanly. If you need a write cursor, 
sure.. a read-only source property AL_SAMPLE_RW_OFFSETS_EXT that returns two 
ints (the read and write sample offsets repsectively) is more than 
possible... possibly even with pairing AL_BYTE_RW_OFFSETS_EXT and 
AL_SEC_RW_OFFSETS_EXT. Though I'm not sure it would be too useful in this 
context since the difference may be larger than some apps will like. Might 
just be better to take the play position and move it up 10 or 15ms to use as 
the write position.


More information about the Openal-devel mailing list