--- a/src/audio/macrom/SDL_romaudio.c Sat Mar 30 19:48:56 2002 +0000
+++ b/src/audio/macrom/SDL_romaudio.c Sat Mar 30 20:03:27 2002 +0000
@@ -30,6 +30,7 @@
#else
# include <Sound.h> /* SoundManager interface */
# include <Gestalt.h>
+# include <DriverServices.h>
#endif
#include <stdlib.h>
@@ -46,6 +47,8 @@
static void Mac_CloseAudio(_THIS);
static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec);
+static void Mac_LockAudio(_THIS);
+static void Mac_UnlockAudio(_THIS);
/* Audio driver bootstrap functions */
@@ -84,6 +87,8 @@
/* Set the function pointers */
this->OpenAudio = Mac_OpenAudio;
this->CloseAudio = Mac_CloseAudio;
+ this->LockAudio = Mac_LockAudio;
+ this->UnlockAudio = Mac_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
@@ -94,18 +99,71 @@
Audio_Available, Audio_CreateDevice
};
-#if TARGET_API_MAC_CARBON
+#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
+/* FIXME: Does this work correctly on MacOS X as well? */
+
+#pragma options align=power
+
+static volatile SInt32 audio_is_locked = 0;
+static volatile SInt32 need_to_mix = 0;
static UInt8 *buffer[2];
static volatile UInt32 running = 0;
static CmpSoundHeader header;
+static volatile Uint32 fill_me = 0;
+
+static void mix_buffer(SDL_AudioDevice *audio, UInt8 *buffer)
+{
+ if ( ! audio->paused ) {
+ if ( audio->convert.needed ) {
+ audio->spec.callback(audio->spec.userdata,
+ (Uint8 *)audio->convert.buf,audio->convert.len);
+ SDL_ConvertAudio(&audio->convert);
+#if 0
+ if ( audio->convert.len_cvt != audio->spec.size ) {
+ /* Uh oh... probably crashes here; */
+ }
+#endif
+ memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
+ } else {
+ audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
+ }
+ }
+
+ DecrementAtomic((SInt32 *) &need_to_mix);
+}
+
+static void Mac_LockAudio(_THIS)
+{
+ IncrementAtomic((SInt32 *) &audio_is_locked);
+}
+
+static void Mac_UnlockAudio(_THIS)
+{
+ SInt32 oldval;
+
+ oldval = DecrementAtomic((SInt32 *) &audio_is_locked);
+ if ( oldval != 1 ) /* != 1 means audio is still locked. */
+ return;
+
+ /* Did we miss the chance to mix in an interrupt? Do it now. */
+ if ( BitAndAtomic (0xFFFFFFFF, &need_to_mix) ) {
+ /*
+ * Note that this could be a problem if you missed an interrupt
+ * while the audio was locked, and get preempted by a second
+ * interrupt here, but that means you locked for way too long anyhow.
+ */
+ mix_buffer (this, buffer[fill_me]);
+ }
+}
static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) {
-
- UInt32 fill_me, play_me;
+ UInt32 play_me;
SndCommand cmd;
SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo;
-
+
+ IncrementAtomic((SInt32 *) &need_to_mix);
+
fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */
play_me = ! fill_me; /* filled buffer to play _now_ */
@@ -113,55 +171,31 @@
return;
}
+ /* queue previously mixed buffer for playback. */
header.samplePtr = (Ptr)buffer[play_me];
-
cmd.cmd = bufferCmd;
cmd.param1 = 0;
cmd.param2 = (long)&header;
+ SndDoCommand (chan, &cmd, 0);
- SndDoCommand (chan, &cmd, 0);
-
memset (buffer[fill_me], 0, audio->spec.size);
-
- if ( ! audio->paused ) {
- if ( audio->convert.needed ) {
- #if MACOSX
- SDL_mutexP(audio->mixer_lock);
- #endif
- audio->spec.callback(audio->spec.userdata,
- (Uint8 *)audio->convert.buf,audio->convert.len);
- #if MACOSX
- SDL_mutexV(audio->mixer_lock);
- #endif
- SDL_ConvertAudio(&audio->convert);
-#if 0
- if ( audio->convert.len_cvt != audio->spec.size ) {
- /* Uh oh... probably crashes here; */
- }
-#endif
- memcpy(buffer[fill_me], audio->convert.buf,
- audio->convert.len_cvt);
- } else {
- #if MACOSX
- SDL_mutexP(audio->mixer_lock);
- #endif
- audio->spec.callback(audio->spec.userdata,
- (Uint8 *)buffer[fill_me], audio->spec.size);
- #if MACOSX
- SDL_mutexV(audio->mixer_lock);
- #endif
- }
- }
- if ( running ) {
-
+ /*
+ * if audio device isn't locked, mix the next buffer to be queued in
+ * the memory block that just finished playing.
+ */
+ if ( ! BitAndAtomic(0xFFFFFFFF, &audio_is_locked) ) {
+ mix_buffer (audio, buffer[fill_me]);
+ }
+
+ /* set this callback to run again when current buffer drains. */
+ if ( running ) {
cmd.cmd = callBackCmd;
cmd.param1 = 0;
cmd.param2 = play_me;
SndDoCommand (chan, &cmd, 0);
}
-
}
static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) {
@@ -170,7 +204,7 @@
int sample_bits;
int i;
long initOptions;
-
+
/* Very few conversions are required, but... */
switch (spec->format) {
case AUDIO_S8:
@@ -231,8 +265,7 @@
}
channel->userInfo = (long)this;
channel->qLength = 128;
- if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) !=
-noErr ) {
+ if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr ) {
SDL_SetError("Unable to create audio channel");
free(channel);
channel = NULL;
@@ -270,7 +303,18 @@
}
}
-#else /* !TARGET_API_MAC_CARBON */
+#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */
+
+static void Mac_LockAudio(_THIS)
+{
+ /* no-op. */
+}
+
+static void Mac_UnlockAudio(_THIS)
+{
+ /* no-op. */
+}
+
/* This function is called by Sound Manager when it has exhausted one of
the buffers, so we'll zero it to silence and fill it with audio if
@@ -336,14 +380,6 @@
int i;
if ( channel != NULL ) {
-#if 0
- SCStatus status;
-
- /* Wait for audio to complete */
- do {
- SndChannelStatus(channel, sizeof(status), &status);
- } while ( status.scChannelBusy );
-#endif
/* Clean up the audio channel */
SndDisposeChannel(channel, true);
channel = NULL;
@@ -446,6 +482,5 @@
return 1;
}
-#endif /* TARGET_API_MAC_CARBON */
+#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */
-