Skip to content

Commit

Permalink
The audio lock and unlock functions are now a part of the driver.
Browse files Browse the repository at this point in the history
The MacOS audio locking has been implemented, courtesy of Ryan Gordon
  • Loading branch information
slouken committed Mar 30, 2002
1 parent 7c4e91d commit f052802
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 56 deletions.
143 changes: 89 additions & 54 deletions src/audio/macrom/SDL_romaudio.c
Expand Up @@ -30,6 +30,7 @@ static char rcsid =
#else
# include <Sound.h> /* SoundManager interface */
# include <Gestalt.h>
# include <DriverServices.h>
#endif

#include <stdlib.h>
Expand All @@ -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 */

Expand Down Expand Up @@ -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;
Expand All @@ -94,74 +99,103 @@ 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_ */

if ( ! audio->enabled ) {
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) {
Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */

9 changes: 7 additions & 2 deletions src/audio/macrom/SDL_romaudio.h
Expand Up @@ -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 */
Expand Down

0 comments on commit f052802

Please sign in to comment.