Mercurial > sdl-ios-xcode
diff src/audio/macrom/SDL_romaudio.c @ 323:b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
The MacOS audio locking has been implemented, courtesy of Ryan Gordon
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 30 Mar 2002 20:03:27 +0000 |
parents | f6ffac90895c |
children | f25f666d609a |
line wrap: on
line diff
--- 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 */ -