From f052802b7f53b37ba8b2a30328a334f292263ee7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 30 Mar 2002 20:03:27 +0000 Subject: [PATCH] The audio lock and unlock functions are now a part of the driver. The MacOS audio locking has been implemented, courtesy of Ryan Gordon --- src/audio/macrom/SDL_romaudio.c | 143 ++++++++++++++++++++------------ src/audio/macrom/SDL_romaudio.h | 9 +- 2 files changed, 96 insertions(+), 56 deletions(-) diff --git a/src/audio/macrom/SDL_romaudio.c b/src/audio/macrom/SDL_romaudio.c index 964d29c75..4f4eb7a4b 100644 --- a/src/audio/macrom/SDL_romaudio.c +++ b/src/audio/macrom/SDL_romaudio.c @@ -30,6 +30,7 @@ static char rcsid = #else # include /* SoundManager interface */ # include +# include #endif #include @@ -46,6 +47,8 @@ static char rcsid = 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 @@ static SDL_AudioDevice *Audio_CreateDevice(int devindex) /* 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 @@ AudioBootStrap SNDMGR_bootstrap = { 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 @@ static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) { 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); - + 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 @@ static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { int sample_bits; int i; long initOptions; - + /* Very few conversions are required, but... */ switch (spec->format) { case AUDIO_S8: @@ -231,8 +265,7 @@ static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { } 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 @@ static void Mac_CloseAudio(_THIS) { } } -#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 @@ static void Mac_CloseAudio(_THIS) 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 @@ static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) return 1; } -#endif /* TARGET_API_MAC_CARBON */ - +#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */ diff --git a/src/audio/macrom/SDL_romaudio.h b/src/audio/macrom/SDL_romaudio.h index b1e5d76c6..97561b2c6 100644 --- a/src/audio/macrom/SDL_romaudio.h +++ b/src/audio/macrom/SDL_romaudio.h @@ -30,16 +30,21 @@ static char rcsid = #include "SDL_sysaudio.h" +/* This is Ryan's improved MacOS sound code, with locking support */ +#define USE_RYANS_SOUNDCODE + /* Hidden "this" pointer for the video functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData { /* Sound manager audio channel */ SndChannelPtr channel; - #if ! TARGET_API_MAC_CARBON +#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) + /* FIXME: Add Ryan's static data here */ +#else /* Double buffering variables */ SndDoubleBufferPtr audio_buf[2]; - #endif +#endif }; /* Old variable names */