[Openal-devel] Another extension..
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
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