The audio lock and unlock functions are now a part of the driver.
authorSam Lantinga
Sat, 30 Mar 2002 20:03:27 +0000
changeset 323b7e8038e40ae
parent 322 fd93a09655e3
child 324 f25f666d609a
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
src/audio/macrom/SDL_romaudio.h
     1.1 --- a/src/audio/macrom/SDL_romaudio.c	Sat Mar 30 19:48:56 2002 +0000
     1.2 +++ b/src/audio/macrom/SDL_romaudio.c	Sat Mar 30 20:03:27 2002 +0000
     1.3 @@ -30,6 +30,7 @@
     1.4  #else
     1.5  #  include <Sound.h> /* SoundManager interface */
     1.6  #  include <Gestalt.h>
     1.7 +#  include <DriverServices.h>
     1.8  #endif
     1.9  
    1.10  #include <stdlib.h>
    1.11 @@ -46,6 +47,8 @@
    1.12  
    1.13  static void Mac_CloseAudio(_THIS);
    1.14  static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec);
    1.15 +static void Mac_LockAudio(_THIS);
    1.16 +static void Mac_UnlockAudio(_THIS);
    1.17  
    1.18  /* Audio driver bootstrap functions */
    1.19  
    1.20 @@ -84,6 +87,8 @@
    1.21      /* Set the function pointers */
    1.22      this->OpenAudio   = Mac_OpenAudio;
    1.23      this->CloseAudio  = Mac_CloseAudio;
    1.24 +    this->LockAudio   = Mac_LockAudio;
    1.25 +    this->UnlockAudio = Mac_UnlockAudio;
    1.26      this->free        = Audio_DeleteDevice;
    1.27  
    1.28      return this;
    1.29 @@ -94,18 +99,71 @@
    1.30  	Audio_Available, Audio_CreateDevice
    1.31  };
    1.32  
    1.33 -#if TARGET_API_MAC_CARBON
    1.34 +#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
    1.35 +/* FIXME: Does this work correctly on MacOS X as well? */
    1.36 +
    1.37 +#pragma options align=power
    1.38 +
    1.39 +static volatile SInt32 audio_is_locked = 0;
    1.40 +static volatile SInt32 need_to_mix = 0;
    1.41  
    1.42  static UInt8  *buffer[2];
    1.43  static volatile UInt32 running = 0;
    1.44  static CmpSoundHeader header;
    1.45 +static volatile Uint32 fill_me = 0;
    1.46 +
    1.47 +static void mix_buffer(SDL_AudioDevice *audio, UInt8 *buffer)
    1.48 +{
    1.49 +   if ( ! audio->paused ) {
    1.50 +        if ( audio->convert.needed ) {
    1.51 +                audio->spec.callback(audio->spec.userdata,
    1.52 +                    (Uint8 *)audio->convert.buf,audio->convert.len);
    1.53 +               SDL_ConvertAudio(&audio->convert);
    1.54 +#if 0
    1.55 +            if ( audio->convert.len_cvt != audio->spec.size ) {
    1.56 +                /* Uh oh... probably crashes here; */
    1.57 +            }
    1.58 +#endif
    1.59 +            memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
    1.60 +        } else {
    1.61 +            audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
    1.62 +        }
    1.63 +    }
    1.64 +
    1.65 +    DecrementAtomic((SInt32 *) &need_to_mix);
    1.66 +}
    1.67 +
    1.68 +static void Mac_LockAudio(_THIS)
    1.69 +{
    1.70 +    IncrementAtomic((SInt32 *) &audio_is_locked);
    1.71 +}
    1.72 +
    1.73 +static void Mac_UnlockAudio(_THIS)
    1.74 +{
    1.75 +    SInt32 oldval;
    1.76 +         
    1.77 +    oldval = DecrementAtomic((SInt32 *) &audio_is_locked);
    1.78 +    if ( oldval != 1 )  /* != 1 means audio is still locked. */
    1.79 +        return;
    1.80 +
    1.81 +    /* Did we miss the chance to mix in an interrupt? Do it now. */
    1.82 +    if ( BitAndAtomic (0xFFFFFFFF, &need_to_mix) ) {
    1.83 +        /*
    1.84 +         * Note that this could be a problem if you missed an interrupt
    1.85 +         *  while the audio was locked, and get preempted by a second
    1.86 +         *  interrupt here, but that means you locked for way too long anyhow.
    1.87 +         */
    1.88 +        mix_buffer (this, buffer[fill_me]);
    1.89 +    }
    1.90 +}
    1.91  
    1.92  static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) {
    1.93 -   
    1.94 -   UInt32 fill_me, play_me;
    1.95 +   UInt32 play_me;
    1.96     SndCommand cmd; 
    1.97     SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo;
    1.98 -   
    1.99 +
   1.100 +   IncrementAtomic((SInt32 *) &need_to_mix);
   1.101 +
   1.102     fill_me = cmd_passed->param2;  /* buffer that has just finished playing, so fill it */      
   1.103     play_me = ! fill_me;           /* filled buffer to play _now_ */
   1.104  
   1.105 @@ -113,55 +171,31 @@
   1.106        return;
   1.107     }
   1.108     
   1.109 +   /* queue previously mixed buffer for playback. */
   1.110     header.samplePtr = (Ptr)buffer[play_me];
   1.111 -   
   1.112     cmd.cmd = bufferCmd;
   1.113     cmd.param1 = 0; 
   1.114     cmd.param2 = (long)&header;
   1.115 +   SndDoCommand (chan, &cmd, 0);
   1.116  
   1.117 -   SndDoCommand (chan, &cmd, 0);
   1.118 -   
   1.119     memset (buffer[fill_me], 0, audio->spec.size);
   1.120 -   
   1.121 -   if ( ! audio->paused ) {
   1.122 -        if ( audio->convert.needed ) {
   1.123 -            #if MACOSX
   1.124 -                SDL_mutexP(audio->mixer_lock);
   1.125 -            #endif
   1.126 -                audio->spec.callback(audio->spec.userdata,
   1.127 -                    (Uint8 *)audio->convert.buf,audio->convert.len);
   1.128 -            #if MACOSX
   1.129 -                SDL_mutexV(audio->mixer_lock);
   1.130 -            #endif 
   1.131 -               SDL_ConvertAudio(&audio->convert);
   1.132 -#if 0
   1.133 -            if ( audio->convert.len_cvt != audio->spec.size ) {
   1.134 -                /* Uh oh... probably crashes here; */
   1.135 -            }
   1.136 -#endif
   1.137 -            memcpy(buffer[fill_me], audio->convert.buf,
   1.138 -                            audio->convert.len_cvt);
   1.139 -        } else {
   1.140 -            #if MACOSX
   1.141 -                SDL_mutexP(audio->mixer_lock);
   1.142 -            #endif
   1.143 -            audio->spec.callback(audio->spec.userdata,
   1.144 -                (Uint8 *)buffer[fill_me], audio->spec.size);
   1.145 -            #if MACOSX
   1.146 -                SDL_mutexV(audio->mixer_lock);
   1.147 -            #endif
   1.148 -        }
   1.149 -    }
   1.150  
   1.151 -    if ( running ) {
   1.152 -         
   1.153 +   /*
   1.154 +    * if audio device isn't locked, mix the next buffer to be queued in
   1.155 +    *  the memory block that just finished playing.
   1.156 +    */
   1.157 +   if ( ! BitAndAtomic(0xFFFFFFFF, &audio_is_locked) ) {
   1.158 +      mix_buffer (audio, buffer[fill_me]);
   1.159 +   } 
   1.160 +
   1.161 +   /* set this callback to run again when current buffer drains. */
   1.162 +   if ( running ) {
   1.163        cmd.cmd = callBackCmd;
   1.164        cmd.param1 = 0;
   1.165        cmd.param2 = play_me;
   1.166     
   1.167        SndDoCommand (chan, &cmd, 0);
   1.168     }
   1.169 -
   1.170  }
   1.171  
   1.172  static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) {
   1.173 @@ -170,7 +204,7 @@
   1.174     int sample_bits;
   1.175     int i;
   1.176     long initOptions;
   1.177 -   
   1.178 +      
   1.179     /* Very few conversions are required, but... */
   1.180      switch (spec->format) {
   1.181          case AUDIO_S8:
   1.182 @@ -231,8 +265,7 @@
   1.183      }
   1.184      channel->userInfo = (long)this;
   1.185      channel->qLength = 128;
   1.186 -    if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) !=
   1.187 -noErr ) {
   1.188 +    if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr ) {
   1.189          SDL_SetError("Unable to create audio channel");
   1.190          free(channel);
   1.191          channel = NULL;
   1.192 @@ -270,7 +303,18 @@
   1.193      }
   1.194  }
   1.195  
   1.196 -#else /* !TARGET_API_MAC_CARBON */
   1.197 +#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */
   1.198 +
   1.199 +static void Mac_LockAudio(_THIS)
   1.200 +{
   1.201 +    /* no-op. */
   1.202 +}
   1.203 +
   1.204 +static void Mac_UnlockAudio(_THIS)
   1.205 +{
   1.206 +    /* no-op. */
   1.207 +}
   1.208 +
   1.209  
   1.210  /* This function is called by Sound Manager when it has exhausted one of
   1.211     the buffers, so we'll zero it to silence and fill it with audio if
   1.212 @@ -336,14 +380,6 @@
   1.213      int i;
   1.214  
   1.215      if ( channel != NULL ) {
   1.216 -#if 0
   1.217 -        SCStatus status;
   1.218 -
   1.219 -        /* Wait for audio to complete */
   1.220 -        do {
   1.221 -            SndChannelStatus(channel, sizeof(status), &status);
   1.222 -        } while ( status.scChannelBusy );
   1.223 -#endif
   1.224          /* Clean up the audio channel */
   1.225          SndDisposeChannel(channel, true);
   1.226          channel = NULL;
   1.227 @@ -446,6 +482,5 @@
   1.228      return 1;
   1.229  }
   1.230  
   1.231 -#endif /* TARGET_API_MAC_CARBON */
   1.232 +#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */
   1.233  
   1.234 -
     2.1 --- a/src/audio/macrom/SDL_romaudio.h	Sat Mar 30 19:48:56 2002 +0000
     2.2 +++ b/src/audio/macrom/SDL_romaudio.h	Sat Mar 30 20:03:27 2002 +0000
     2.3 @@ -30,16 +30,21 @@
     2.4  
     2.5  #include "SDL_sysaudio.h"
     2.6  
     2.7 +/* This is Ryan's improved MacOS sound code, with locking support */
     2.8 +#define USE_RYANS_SOUNDCODE
     2.9 +
    2.10  /* Hidden "this" pointer for the video functions */
    2.11  #define _THIS	SDL_AudioDevice *this
    2.12  
    2.13  struct SDL_PrivateAudioData {
    2.14  	/* Sound manager audio channel */
    2.15  	SndChannelPtr channel;
    2.16 -    #if ! TARGET_API_MAC_CARBON
    2.17 +#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
    2.18 +	/* FIXME: Add Ryan's static data here */
    2.19 +#else
    2.20  	/* Double buffering variables */
    2.21  	SndDoubleBufferPtr audio_buf[2];
    2.22 -    #endif
    2.23 +#endif
    2.24  };
    2.25  
    2.26  /* Old variable names */