This seems pretty bleak. Is there some obvious solution I’m missing
(“upgrade to OS X” doesn’t count), because I can’t see a good way to
make this work, consider how dependent most code (SDL_mixer included)
is
on SDL_LockAudio().
Yep, as far as I know that’s the situation.
Alternately, what recommendations are there for designing SDL audio
applications that don’t rely on SDL_LockAudio() (if this is a better
tactic…)?
The only think that I can think of offhand is to have a pointer to the
"mixing data" which you atomically switch when you want to modify what
data the mixing callback uses.
Any mac guys with great ideas?
Before I go into an idea, perhaps some things to note and rambling to
gather my thoughts and understand the issues involved.
-
The audio callback could interrupt the user program at any time.
-
The audio callback cannot be interrupted by the user process.
-
The audio callback (basically) performs 3 tasks.
- Queue the buffer that was previously mixed in the last callback
for playback.
- Call the SDL mix function on the buffer that was just consumed.
- Queue a command to invoke the callback again when the buffer in
first step is consumed.
-
By this setup, the mix function cannot touch a buffer that is
currently being played.
The primary use for SDL_LockAudio() seems to be that you want to avoid a
race condition when modifying something that will be used later in the
mix callback, which can be accomplished by temporarily disabling the
callback, making the change, then enabling the callback.
So, can we do this?
One approach uses a global variable audio_is_locked. If the low-level
callback is triggered and audio_is_locked is true, the callback does
step 1 and does not do steps 2 and 3.
This will only work if we have atomic test-and-set. Thankfully,
DriverServicesLib can do this, believe it or not. The procedure I
propose is as follows:
The callback would do an atomic test on audio_is_locked right before
step 2. If locked, the callback would abort.
SDL_LockAudio() would do an atomic set on audio_is_locked to true.
SDL_UnLockAudio() would set audio_is_locked to false, and would do step
2 + 3 only if
necessary. For this last part we need an additional global variable to
determine if the callback ever
reached step 2 and aborted.
I think this will work. Who wants to code it?
In the process we can throw out the SndPlayDoubleBuffer() code, which
this can’t be implemented for anyhow.
-DOn Tuesday, March 26, 2002, at 07:57 PM, Sam Lantinga wrote: