src/audio/SDL_audio.c
author Ryan C. Gordon
Tue, 22 Jul 2014 23:12:21 -0400
changeset 9010 6d059ed9b6ca
parent 8919 c9be8299ba6b
child 9012 aa058c87737b
permissions -rw-r--r--
Clarifying hard-to-understand piece of code.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../SDL_internal.h"
    22 
    23 /* Allow access to a raw mixing buffer */
    24 
    25 #include "SDL.h"
    26 #include "SDL_audio.h"
    27 #include "SDL_audio_c.h"
    28 #include "SDL_audiomem.h"
    29 #include "SDL_sysaudio.h"
    30 
    31 #define _THIS SDL_AudioDevice *_this
    32 
    33 static SDL_AudioDriver current_audio;
    34 static SDL_AudioDevice *open_devices[16];
    35 
    36 /* !!! FIXME: These are wordy and unlocalized... */
    37 #define DEFAULT_OUTPUT_DEVNAME "System audio output device"
    38 #define DEFAULT_INPUT_DEVNAME "System audio capture device"
    39 
    40 
    41 /*
    42  * Not all of these will be compiled and linked in, but it's convenient
    43  *  to have a complete list here and saves yet-another block of #ifdefs...
    44  *  Please see bootstrap[], below, for the actual #ifdef mess.
    45  */
    46 extern AudioBootStrap BSD_AUDIO_bootstrap;
    47 extern AudioBootStrap DSP_bootstrap;
    48 extern AudioBootStrap ALSA_bootstrap;
    49 extern AudioBootStrap PULSEAUDIO_bootstrap;
    50 extern AudioBootStrap QSAAUDIO_bootstrap;
    51 extern AudioBootStrap SUNAUDIO_bootstrap;
    52 extern AudioBootStrap ARTS_bootstrap;
    53 extern AudioBootStrap ESD_bootstrap;
    54 #if SDL_AUDIO_DRIVER_NACL
    55 extern AudioBootStrap NACLAUD_bootstrap;
    56 #endif
    57 extern AudioBootStrap NAS_bootstrap;
    58 extern AudioBootStrap XAUDIO2_bootstrap;
    59 extern AudioBootStrap DSOUND_bootstrap;
    60 extern AudioBootStrap WINMM_bootstrap;
    61 extern AudioBootStrap PAUDIO_bootstrap;
    62 extern AudioBootStrap HAIKUAUDIO_bootstrap;
    63 extern AudioBootStrap COREAUDIO_bootstrap;
    64 extern AudioBootStrap SNDMGR_bootstrap;
    65 extern AudioBootStrap DISKAUD_bootstrap;
    66 extern AudioBootStrap DUMMYAUD_bootstrap;
    67 extern AudioBootStrap DCAUD_bootstrap;
    68 extern AudioBootStrap DART_bootstrap;
    69 extern AudioBootStrap NDSAUD_bootstrap;
    70 extern AudioBootStrap FUSIONSOUND_bootstrap;
    71 extern AudioBootStrap ANDROIDAUD_bootstrap;
    72 extern AudioBootStrap PSPAUD_bootstrap;
    73 extern AudioBootStrap SNDIO_bootstrap;
    74 
    75 
    76 /* Available audio drivers */
    77 static const AudioBootStrap *const bootstrap[] = {
    78 #if SDL_AUDIO_DRIVER_PULSEAUDIO
    79     &PULSEAUDIO_bootstrap,
    80 #endif
    81 #if SDL_AUDIO_DRIVER_ALSA
    82     &ALSA_bootstrap,
    83 #endif
    84 #if SDL_AUDIO_DRIVER_SNDIO
    85     &SNDIO_bootstrap,
    86 #endif
    87 #if SDL_AUDIO_DRIVER_BSD
    88     &BSD_AUDIO_bootstrap,
    89 #endif
    90 #if SDL_AUDIO_DRIVER_OSS
    91     &DSP_bootstrap,
    92 #endif
    93 #if SDL_AUDIO_DRIVER_QSA
    94     &QSAAUDIO_bootstrap,
    95 #endif
    96 #if SDL_AUDIO_DRIVER_SUNAUDIO
    97     &SUNAUDIO_bootstrap,
    98 #endif
    99 #if SDL_AUDIO_DRIVER_ARTS
   100     &ARTS_bootstrap,
   101 #endif
   102 #if SDL_AUDIO_DRIVER_ESD
   103     &ESD_bootstrap,
   104 #endif
   105 #if SDL_AUDIO_DRIVER_NACL
   106    &NACLAUD_bootstrap,
   107 #endif
   108 #if SDL_AUDIO_DRIVER_NAS
   109     &NAS_bootstrap,
   110 #endif
   111 #if SDL_AUDIO_DRIVER_XAUDIO2
   112     &XAUDIO2_bootstrap,
   113 #endif
   114 #if SDL_AUDIO_DRIVER_DSOUND
   115     &DSOUND_bootstrap,
   116 #endif
   117 #if SDL_AUDIO_DRIVER_WINMM
   118     &WINMM_bootstrap,
   119 #endif
   120 #if SDL_AUDIO_DRIVER_PAUDIO
   121     &PAUDIO_bootstrap,
   122 #endif
   123 #if SDL_AUDIO_DRIVER_HAIKU
   124     &HAIKUAUDIO_bootstrap,
   125 #endif
   126 #if SDL_AUDIO_DRIVER_COREAUDIO
   127     &COREAUDIO_bootstrap,
   128 #endif
   129 #if SDL_AUDIO_DRIVER_DISK
   130     &DISKAUD_bootstrap,
   131 #endif
   132 #if SDL_AUDIO_DRIVER_DUMMY
   133     &DUMMYAUD_bootstrap,
   134 #endif
   135 #if SDL_AUDIO_DRIVER_FUSIONSOUND
   136     &FUSIONSOUND_bootstrap,
   137 #endif
   138 #if SDL_AUDIO_DRIVER_ANDROID
   139     &ANDROIDAUD_bootstrap,
   140 #endif
   141 #if SDL_AUDIO_DRIVER_PSP
   142     &PSPAUD_bootstrap,
   143 #endif
   144     NULL
   145 };
   146 
   147 static SDL_AudioDevice *
   148 get_audio_device(SDL_AudioDeviceID id)
   149 {
   150     id--;
   151     if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
   152         SDL_SetError("Invalid audio device ID");
   153         return NULL;
   154     }
   155 
   156     return open_devices[id];
   157 }
   158 
   159 
   160 /* stubs for audio drivers that don't need a specific entry point... */
   161 static void
   162 SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
   163 {                               /* no-op. */
   164 }
   165 
   166 static void
   167 SDL_AudioThreadInit_Default(_THIS)
   168 {                               /* no-op. */
   169 }
   170 
   171 static void
   172 SDL_AudioWaitDevice_Default(_THIS)
   173 {                               /* no-op. */
   174 }
   175 
   176 static void
   177 SDL_AudioPlayDevice_Default(_THIS)
   178 {                               /* no-op. */
   179 }
   180 
   181 static Uint8 *
   182 SDL_AudioGetDeviceBuf_Default(_THIS)
   183 {
   184     return NULL;
   185 }
   186 
   187 static void
   188 SDL_AudioWaitDone_Default(_THIS)
   189 {                               /* no-op. */
   190 }
   191 
   192 static void
   193 SDL_AudioCloseDevice_Default(_THIS)
   194 {                               /* no-op. */
   195 }
   196 
   197 static void
   198 SDL_AudioDeinitialize_Default(void)
   199 {                               /* no-op. */
   200 }
   201 
   202 static int
   203 SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
   204 {
   205     return -1;
   206 }
   207 
   208 static SDL_INLINE SDL_bool
   209 is_in_audio_device_thread(SDL_AudioDevice * device)
   210 {
   211     /* The device thread locks the same mutex, but not through the public API.
   212        This check is in case the application, in the audio callback,
   213        tries to lock the thread that we've already locked from the
   214        device thread...just in case we only have non-recursive mutexes. */
   215     if (device->thread && (SDL_ThreadID() == device->threadid)) {
   216         return SDL_TRUE;
   217     }
   218 
   219     return SDL_FALSE;
   220 }
   221 
   222 static void
   223 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
   224 {
   225     if (!is_in_audio_device_thread(device)) {
   226         SDL_LockMutex(device->mixer_lock);
   227     }
   228 }
   229 
   230 static void
   231 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
   232 {
   233     if (!is_in_audio_device_thread(device)) {
   234         SDL_UnlockMutex(device->mixer_lock);
   235     }
   236 }
   237 
   238 
   239 static void
   240 finalize_audio_entry_points(void)
   241 {
   242     /*
   243      * Fill in stub functions for unused driver entry points. This lets us
   244      *  blindly call them without having to check for validity first.
   245      */
   246 
   247 #define FILL_STUB(x) \
   248         if (current_audio.impl.x == NULL) { \
   249             current_audio.impl.x = SDL_Audio##x##_Default; \
   250         }
   251     FILL_STUB(DetectDevices);
   252     FILL_STUB(OpenDevice);
   253     FILL_STUB(ThreadInit);
   254     FILL_STUB(WaitDevice);
   255     FILL_STUB(PlayDevice);
   256     FILL_STUB(GetDeviceBuf);
   257     FILL_STUB(WaitDone);
   258     FILL_STUB(CloseDevice);
   259     FILL_STUB(LockDevice);
   260     FILL_STUB(UnlockDevice);
   261     FILL_STUB(Deinitialize);
   262 #undef FILL_STUB
   263 }
   264 
   265 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   266 /* Streaming functions (for when the input and output buffer sizes are different) */
   267 /* Write [length] bytes from buf into the streamer */
   268 static void
   269 SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
   270 {
   271     int i;
   272 
   273     for (i = 0; i < length; ++i) {
   274         stream->buffer[stream->write_pos] = buf[i];
   275         ++stream->write_pos;
   276     }
   277 }
   278 
   279 /* Read [length] bytes out of the streamer into buf */
   280 static void
   281 SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
   282 {
   283     int i;
   284 
   285     for (i = 0; i < length; ++i) {
   286         buf[i] = stream->buffer[stream->read_pos];
   287         ++stream->read_pos;
   288     }
   289 }
   290 
   291 static int
   292 SDL_StreamLength(SDL_AudioStreamer * stream)
   293 {
   294     return (stream->write_pos - stream->read_pos) % stream->max_len;
   295 }
   296 
   297 /* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
   298 #if 0
   299 static int
   300 SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
   301 {
   302     /* First try to allocate the buffer */
   303     stream->buffer = (Uint8 *) SDL_malloc(max_len);
   304     if (stream->buffer == NULL) {
   305         return -1;
   306     }
   307 
   308     stream->max_len = max_len;
   309     stream->read_pos = 0;
   310     stream->write_pos = 0;
   311 
   312     /* Zero out the buffer */
   313     SDL_memset(stream->buffer, silence, max_len);
   314 
   315     return 0;
   316 }
   317 #endif
   318 
   319 /* Deinitialize the stream simply by freeing the buffer */
   320 static void
   321 SDL_StreamDeinit(SDL_AudioStreamer * stream)
   322 {
   323     SDL_free(stream->buffer);
   324 }
   325 #endif
   326 
   327 #if defined(__ANDROID__)
   328 #include <android/log.h>
   329 #endif
   330 
   331 /* The general mixing thread function */
   332 int SDLCALL
   333 SDL_RunAudio(void *devicep)
   334 {
   335     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   336     Uint8 *stream;
   337     int stream_len;
   338     void *udata;
   339     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   340     Uint32 delay;
   341 
   342 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   343     /* For streaming when the buffer sizes don't match up */
   344     Uint8 *istream;
   345     int istream_len = 0;
   346 #endif
   347 
   348     /* The audio mixing is always a high priority thread */
   349     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
   350 
   351     /* Perform any thread setup */
   352     device->threadid = SDL_ThreadID();
   353     current_audio.impl.ThreadInit(device);
   354 
   355     /* Set up the mixing function */
   356     fill = device->spec.callback;
   357     udata = device->spec.userdata;
   358 
   359     /* By default do not stream */
   360     device->use_streamer = 0;
   361 
   362     if (device->convert.needed) {
   363 #if 0                           /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
   364         /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
   365         if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
   366             /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
   367             stream_max_len = 2 * device->spec.size;
   368             if (device->convert.len_mult > device->convert.len_div) {
   369                 stream_max_len *= device->convert.len_mult;
   370                 stream_max_len /= device->convert.len_div;
   371             }
   372             if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
   373                 0)
   374                 return -1;
   375             device->use_streamer = 1;
   376 
   377             /* istream_len should be the length of what we grab from the callback and feed to conversion,
   378                so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
   379              */
   380             istream_len =
   381                 device->spec.size * device->convert.len_div /
   382                 device->convert.len_mult;
   383         }
   384 #endif
   385         stream_len = device->convert.len;
   386     } else {
   387         stream_len = device->spec.size;
   388     }
   389 
   390     /* Calculate the delay while paused */
   391     delay = ((device->spec.samples * 1000) / device->spec.freq);
   392 
   393     /* Determine if the streamer is necessary here */
   394 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   395     if (device->use_streamer == 1) {
   396         /* This code is almost the same as the old code. The difference is, instead of reading
   397            directly from the callback into "stream", then converting and sending the audio off,
   398            we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   399            However, reading and writing with streamer are done separately:
   400            - We only call the callback and write to the streamer when the streamer does not
   401            contain enough samples to output to the device.
   402            - We only read from the streamer and tell the device to play when the streamer
   403            does have enough samples to output.
   404            This allows us to perform resampling in the conversion step, where the output of the
   405            resampling process can be any number. We will have to see what a good size for the
   406            stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   407          */
   408         while (device->enabled) {
   409 
   410             if (device->paused) {
   411                 SDL_Delay(delay);
   412                 continue;
   413             }
   414 
   415             /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   416             if (SDL_StreamLength(&device->streamer) < stream_len) {
   417                 /* Set up istream */
   418                 if (device->convert.needed) {
   419                     if (device->convert.buf) {
   420                         istream = device->convert.buf;
   421                     } else {
   422                         continue;
   423                     }
   424                 } else {
   425 /* FIXME: Ryan, this is probably wrong.  I imagine we don't want to get
   426  * a device buffer both here and below in the stream output.
   427  */
   428                     istream = current_audio.impl.GetDeviceBuf(device);
   429                     if (istream == NULL) {
   430                         istream = device->fake_stream;
   431                     }
   432                 }
   433 
   434                 /* Read from the callback into the _input_ stream */
   435                 SDL_LockMutex(device->mixer_lock);
   436                 (*fill) (udata, istream, istream_len);
   437                 SDL_UnlockMutex(device->mixer_lock);
   438 
   439                 /* Convert the audio if necessary and write to the streamer */
   440                 if (device->convert.needed) {
   441                     SDL_ConvertAudio(&device->convert);
   442                     if (istream == NULL) {
   443                         istream = device->fake_stream;
   444                     }
   445                     /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
   446                     SDL_StreamWrite(&device->streamer, device->convert.buf,
   447                                     device->convert.len_cvt);
   448                 } else {
   449                     SDL_StreamWrite(&device->streamer, istream, istream_len);
   450                 }
   451             }
   452 
   453             /* Only output audio if the streamer has enough to output */
   454             if (SDL_StreamLength(&device->streamer) >= stream_len) {
   455                 /* Set up the output stream */
   456                 if (device->convert.needed) {
   457                     if (device->convert.buf) {
   458                         stream = device->convert.buf;
   459                     } else {
   460                         continue;
   461                     }
   462                 } else {
   463                     stream = current_audio.impl.GetDeviceBuf(device);
   464                     if (stream == NULL) {
   465                         stream = device->fake_stream;
   466                     }
   467                 }
   468 
   469                 /* Now read from the streamer */
   470                 SDL_StreamRead(&device->streamer, stream, stream_len);
   471 
   472                 /* Ready current buffer for play and change current buffer */
   473                 if (stream != device->fake_stream) {
   474                     current_audio.impl.PlayDevice(device);
   475                     /* Wait for an audio buffer to become available */
   476                     current_audio.impl.WaitDevice(device);
   477                 } else {
   478                     SDL_Delay(delay);
   479                 }
   480             }
   481 
   482         }
   483     } else
   484 #endif
   485     {
   486         /* Otherwise, do not use the streamer. This is the old code. */
   487         const int silence = (int) device->spec.silence;
   488 
   489         /* Loop, filling the audio buffers */
   490         while (device->enabled) {
   491 
   492             /* Fill the current buffer with sound */
   493             if (device->convert.needed) {
   494                 if (device->convert.buf) {
   495                     stream = device->convert.buf;
   496                 } else {
   497                     continue;
   498                 }
   499             } else {
   500                 stream = current_audio.impl.GetDeviceBuf(device);
   501                 if (stream == NULL) {
   502                     stream = device->fake_stream;
   503                 }
   504             }
   505 
   506             SDL_LockMutex(device->mixer_lock);
   507             if (device->paused) {
   508                 SDL_memset(stream, silence, stream_len);
   509             } else {
   510                 (*fill) (udata, stream, stream_len);
   511             }
   512             SDL_UnlockMutex(device->mixer_lock);
   513 
   514             /* Convert the audio if necessary */
   515             if (device->convert.needed) {
   516                 SDL_ConvertAudio(&device->convert);
   517                 stream = current_audio.impl.GetDeviceBuf(device);
   518                 if (stream == NULL) {
   519                     stream = device->fake_stream;
   520                 }
   521                 SDL_memcpy(stream, device->convert.buf,
   522                            device->convert.len_cvt);
   523             }
   524 
   525             /* Ready current buffer for play and change current buffer */
   526             if (stream != device->fake_stream) {
   527                 current_audio.impl.PlayDevice(device);
   528                 /* Wait for an audio buffer to become available */
   529                 current_audio.impl.WaitDevice(device);
   530             } else {
   531                 SDL_Delay(delay);
   532             }
   533         }
   534     }
   535 
   536     /* Wait for the audio to drain.. */
   537     current_audio.impl.WaitDone(device);
   538 
   539     /* If necessary, deinit the streamer */
   540 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   541     if (device->use_streamer == 1)
   542         SDL_StreamDeinit(&device->streamer);
   543 #endif
   544 
   545     return (0);
   546 }
   547 
   548 
   549 static SDL_AudioFormat
   550 SDL_ParseAudioFormat(const char *string)
   551 {
   552 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
   553     CHECK_FMT_STRING(U8);
   554     CHECK_FMT_STRING(S8);
   555     CHECK_FMT_STRING(U16LSB);
   556     CHECK_FMT_STRING(S16LSB);
   557     CHECK_FMT_STRING(U16MSB);
   558     CHECK_FMT_STRING(S16MSB);
   559     CHECK_FMT_STRING(U16SYS);
   560     CHECK_FMT_STRING(S16SYS);
   561     CHECK_FMT_STRING(U16);
   562     CHECK_FMT_STRING(S16);
   563     CHECK_FMT_STRING(S32LSB);
   564     CHECK_FMT_STRING(S32MSB);
   565     CHECK_FMT_STRING(S32SYS);
   566     CHECK_FMT_STRING(S32);
   567     CHECK_FMT_STRING(F32LSB);
   568     CHECK_FMT_STRING(F32MSB);
   569     CHECK_FMT_STRING(F32SYS);
   570     CHECK_FMT_STRING(F32);
   571 #undef CHECK_FMT_STRING
   572     return 0;
   573 }
   574 
   575 int
   576 SDL_GetNumAudioDrivers(void)
   577 {
   578     return (SDL_arraysize(bootstrap) - 1);
   579 }
   580 
   581 const char *
   582 SDL_GetAudioDriver(int index)
   583 {
   584     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
   585         return (bootstrap[index]->name);
   586     }
   587     return (NULL);
   588 }
   589 
   590 int
   591 SDL_AudioInit(const char *driver_name)
   592 {
   593     int i = 0;
   594     int initialized = 0;
   595     int tried_to_init = 0;
   596 
   597     if (SDL_WasInit(SDL_INIT_AUDIO)) {
   598         SDL_AudioQuit();        /* shutdown driver if already running. */
   599     }
   600 
   601     SDL_memset(&current_audio, '\0', sizeof(current_audio));
   602     SDL_memset(open_devices, '\0', sizeof(open_devices));
   603 
   604     /* Select the proper audio driver */
   605     if (driver_name == NULL) {
   606         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   607     }
   608 
   609     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   610         /* make sure we should even try this driver before doing so... */
   611         const AudioBootStrap *backend = bootstrap[i];
   612         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
   613             (!driver_name && backend->demand_only)) {
   614             continue;
   615         }
   616 
   617         tried_to_init = 1;
   618         SDL_memset(&current_audio, 0, sizeof(current_audio));
   619         current_audio.name = backend->name;
   620         current_audio.desc = backend->desc;
   621         initialized = backend->init(&current_audio.impl);
   622     }
   623 
   624     if (!initialized) {
   625         /* specific drivers will set the error message if they fail... */
   626         if (!tried_to_init) {
   627             if (driver_name) {
   628                 SDL_SetError("Audio target '%s' not available", driver_name);
   629             } else {
   630                 SDL_SetError("No available audio device");
   631             }
   632         }
   633 
   634         SDL_memset(&current_audio, 0, sizeof(current_audio));
   635         return (-1);            /* No driver was available, so fail. */
   636     }
   637 
   638     finalize_audio_entry_points();
   639 
   640     return (0);
   641 }
   642 
   643 /*
   644  * Get the current audio driver name
   645  */
   646 const char *
   647 SDL_GetCurrentAudioDriver()
   648 {
   649     return current_audio.name;
   650 }
   651 
   652 static void
   653 free_device_list(char ***devices, int *devCount)
   654 {
   655     int i = *devCount;
   656     if ((i > 0) && (*devices != NULL)) {
   657         while (i--) {
   658             SDL_free((*devices)[i]);
   659         }
   660     }
   661 
   662     SDL_free(*devices);
   663 
   664     *devices = NULL;
   665     *devCount = 0;
   666 }
   667 
   668 static
   669 void SDL_AddCaptureAudioDevice(const char *_name)
   670 {
   671     char *name = NULL;
   672     void *ptr = SDL_realloc(current_audio.inputDevices,
   673                           (current_audio.inputDeviceCount+1) * sizeof(char*));
   674     if (ptr == NULL) {
   675         return;  /* oh well. */
   676     }
   677 
   678     current_audio.inputDevices = (char **) ptr;
   679     name = SDL_strdup(_name);  /* if this returns NULL, that's okay. */
   680     current_audio.inputDevices[current_audio.inputDeviceCount++] = name;
   681 }
   682 
   683 static
   684 void SDL_AddOutputAudioDevice(const char *_name)
   685 {
   686     char *name = NULL;
   687     void *ptr = SDL_realloc(current_audio.outputDevices,
   688                           (current_audio.outputDeviceCount+1) * sizeof(char*));
   689     if (ptr == NULL) {
   690         return;  /* oh well. */
   691     }
   692 
   693     current_audio.outputDevices = (char **) ptr;
   694     name = SDL_strdup(_name);  /* if this returns NULL, that's okay. */
   695     current_audio.outputDevices[current_audio.outputDeviceCount++] = name;
   696 }
   697 
   698 
   699 int
   700 SDL_GetNumAudioDevices(int iscapture)
   701 {
   702     int retval = 0;
   703 
   704     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   705         return -1;
   706     }
   707 
   708     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   709         return 0;
   710     }
   711 
   712     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   713         return 1;
   714     }
   715 
   716     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   717         return 1;
   718     }
   719 
   720     if (iscapture) {
   721         free_device_list(&current_audio.inputDevices,
   722                          &current_audio.inputDeviceCount);
   723         current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
   724         retval = current_audio.inputDeviceCount;
   725     } else {
   726         free_device_list(&current_audio.outputDevices,
   727                          &current_audio.outputDeviceCount);
   728         current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
   729         retval = current_audio.outputDeviceCount;
   730     }
   731 
   732     return retval;
   733 }
   734 
   735 
   736 const char *
   737 SDL_GetAudioDeviceName(int index, int iscapture)
   738 {
   739     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   740         SDL_SetError("Audio subsystem is not initialized");
   741         return NULL;
   742     }
   743 
   744     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   745         SDL_SetError("No capture support");
   746         return NULL;
   747     }
   748 
   749     if (index < 0) {
   750         goto no_such_device;
   751     }
   752 
   753     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   754         if (index > 0) {
   755             goto no_such_device;
   756         }
   757         return DEFAULT_INPUT_DEVNAME;
   758     }
   759 
   760     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   761         if (index > 0) {
   762             goto no_such_device;
   763         }
   764         return DEFAULT_OUTPUT_DEVNAME;
   765     }
   766 
   767     if (iscapture) {
   768         if (index >= current_audio.inputDeviceCount) {
   769             goto no_such_device;
   770         }
   771         return current_audio.inputDevices[index];
   772     } else {
   773         if (index >= current_audio.outputDeviceCount) {
   774             goto no_such_device;
   775         }
   776         return current_audio.outputDevices[index];
   777     }
   778 
   779 no_such_device:
   780     SDL_SetError("No such device");
   781     return NULL;
   782 }
   783 
   784 
   785 static void
   786 close_audio_device(SDL_AudioDevice * device)
   787 {
   788     device->enabled = 0;
   789     if (device->thread != NULL) {
   790         SDL_WaitThread(device->thread, NULL);
   791     }
   792     if (device->mixer_lock != NULL) {
   793         SDL_DestroyMutex(device->mixer_lock);
   794     }
   795     SDL_FreeAudioMem(device->fake_stream);
   796     if (device->convert.needed) {
   797         SDL_FreeAudioMem(device->convert.buf);
   798     }
   799     if (device->opened) {
   800         current_audio.impl.CloseDevice(device);
   801         device->opened = 0;
   802     }
   803     SDL_FreeAudioMem(device);
   804 }
   805 
   806 
   807 /*
   808  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
   809  *  Fills in a sanitized copy in (prepared).
   810  *  Returns non-zero if okay, zero on fatal parameters in (orig).
   811  */
   812 static int
   813 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
   814 {
   815     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
   816 
   817     if (orig->callback == NULL) {
   818         SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   819         return 0;
   820     }
   821 
   822     if (orig->freq == 0) {
   823         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   824         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
   825             prepared->freq = 22050;     /* a reasonable default */
   826         }
   827     }
   828 
   829     if (orig->format == 0) {
   830         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
   831         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
   832             prepared->format = AUDIO_S16;       /* a reasonable default */
   833         }
   834     }
   835 
   836     switch (orig->channels) {
   837     case 0:{
   838             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
   839             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
   840                 prepared->channels = 2; /* a reasonable default */
   841             }
   842             break;
   843         }
   844     case 1:                    /* Mono */
   845     case 2:                    /* Stereo */
   846     case 4:                    /* surround */
   847     case 6:                    /* surround with center and lfe */
   848         break;
   849     default:
   850         SDL_SetError("Unsupported number of audio channels.");
   851         return 0;
   852     }
   853 
   854     if (orig->samples == 0) {
   855         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   856         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
   857             /* Pick a default of ~46 ms at desired frequency */
   858             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   859             const int samples = (prepared->freq / 1000) * 46;
   860             int power2 = 1;
   861             while (power2 < samples) {
   862                 power2 *= 2;
   863             }
   864             prepared->samples = power2;
   865         }
   866     }
   867 
   868     /* Calculate the silence and size of the audio specification */
   869     SDL_CalculateAudioSpec(prepared);
   870 
   871     return 1;
   872 }
   873 
   874 
   875 static SDL_AudioDeviceID
   876 open_audio_device(const char *devname, int iscapture,
   877                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
   878                   int allowed_changes, int min_id)
   879 {
   880     SDL_AudioDeviceID id = 0;
   881     SDL_AudioSpec _obtained;
   882     SDL_AudioDevice *device;
   883     SDL_bool build_cvt;
   884     int i = 0;
   885 
   886     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   887         SDL_SetError("Audio subsystem is not initialized");
   888         return 0;
   889     }
   890 
   891     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   892         SDL_SetError("No capture support");
   893         return 0;
   894     }
   895 
   896     if (!obtained) {
   897         obtained = &_obtained;
   898     }
   899     if (!prepare_audiospec(desired, obtained)) {
   900         return 0;
   901     }
   902 
   903     /* If app doesn't care about a specific device, let the user override. */
   904     if (devname == NULL) {
   905         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
   906     }
   907 
   908     /*
   909      * Catch device names at the high level for the simple case...
   910      * This lets us have a basic "device enumeration" for systems that
   911      *  don't have multiple devices, but makes sure the device name is
   912      *  always NULL when it hits the low level.
   913      *
   914      * Also make sure that the simple case prevents multiple simultaneous
   915      *  opens of the default system device.
   916      */
   917 
   918     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   919         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
   920             SDL_SetError("No such device");
   921             return 0;
   922         }
   923         devname = NULL;
   924 
   925         for (i = 0; i < SDL_arraysize(open_devices); i++) {
   926             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
   927                 SDL_SetError("Audio device already open");
   928                 return 0;
   929             }
   930         }
   931     }
   932 
   933     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   934         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
   935             SDL_SetError("No such device");
   936             return 0;
   937         }
   938         devname = NULL;
   939 
   940         for (i = 0; i < SDL_arraysize(open_devices); i++) {
   941             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
   942                 SDL_SetError("Audio device already open");
   943                 return 0;
   944             }
   945         }
   946     }
   947 
   948     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
   949     if (device == NULL) {
   950         SDL_OutOfMemory();
   951         return 0;
   952     }
   953     SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
   954     device->spec = *obtained;
   955     device->enabled = 1;
   956     device->paused = 1;
   957     device->iscapture = iscapture;
   958 
   959     /* Create a semaphore for locking the sound buffers */
   960     if (!current_audio.impl.SkipMixerLock) {
   961         device->mixer_lock = SDL_CreateMutex();
   962         if (device->mixer_lock == NULL) {
   963             close_audio_device(device);
   964             SDL_SetError("Couldn't create mixer lock");
   965             return 0;
   966         }
   967     }
   968 
   969     /* force a device detection if we haven't done one yet. */
   970     if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
   971          ((!iscapture) && (current_audio.outputDevices == NULL)) )
   972         SDL_GetNumAudioDevices(iscapture);
   973 
   974     if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
   975         close_audio_device(device);
   976         return 0;
   977     }
   978     device->opened = 1;
   979 
   980     /* Allocate a fake audio memory buffer */
   981     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
   982     if (device->fake_stream == NULL) {
   983         close_audio_device(device);
   984         SDL_OutOfMemory();
   985         return 0;
   986     }
   987 
   988     /* See if we need to do any conversion */
   989     build_cvt = SDL_FALSE;
   990     if (obtained->freq != device->spec.freq) {
   991         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
   992             obtained->freq = device->spec.freq;
   993         } else {
   994             build_cvt = SDL_TRUE;
   995         }
   996     }
   997     if (obtained->format != device->spec.format) {
   998         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
   999             obtained->format = device->spec.format;
  1000         } else {
  1001             build_cvt = SDL_TRUE;
  1002         }
  1003     }
  1004     if (obtained->channels != device->spec.channels) {
  1005         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
  1006             obtained->channels = device->spec.channels;
  1007         } else {
  1008             build_cvt = SDL_TRUE;
  1009         }
  1010     }
  1011 
  1012     /* If the audio driver changes the buffer size, accept it.
  1013        This needs to be done after the format is modified above,
  1014        otherwise it might not have the correct buffer size.
  1015      */
  1016     if (device->spec.samples != obtained->samples) {
  1017         obtained->samples = device->spec.samples;
  1018         SDL_CalculateAudioSpec(obtained);
  1019     }
  1020 
  1021     if (build_cvt) {
  1022         /* Build an audio conversion block */
  1023         if (SDL_BuildAudioCVT(&device->convert,
  1024                               obtained->format, obtained->channels,
  1025                               obtained->freq,
  1026                               device->spec.format, device->spec.channels,
  1027                               device->spec.freq) < 0) {
  1028             close_audio_device(device);
  1029             return 0;
  1030         }
  1031         if (device->convert.needed) {
  1032             device->convert.len = (int) (((double) device->spec.size) /
  1033                                          device->convert.len_ratio);
  1034 
  1035             device->convert.buf =
  1036                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
  1037                                             device->convert.len_mult);
  1038             if (device->convert.buf == NULL) {
  1039                 close_audio_device(device);
  1040                 SDL_OutOfMemory();
  1041                 return 0;
  1042             }
  1043         }
  1044     }
  1045 
  1046     /* Find an available device ID and store the structure... */
  1047     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
  1048         if (open_devices[id] == NULL) {
  1049             open_devices[id] = device;
  1050             break;
  1051         }
  1052     }
  1053 
  1054     if (id == SDL_arraysize(open_devices)) {
  1055         SDL_SetError("Too many open audio devices");
  1056         close_audio_device(device);
  1057         return 0;
  1058     }
  1059 
  1060     /* Start the audio thread if necessary */
  1061     if (!current_audio.impl.ProvidesOwnCallbackThread) {
  1062         /* Start the audio thread */
  1063         char name[64];
  1064         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
  1065 /* !!! FIXME: this is nasty. */
  1066 #if defined(__WIN32__) && !defined(HAVE_LIBC)
  1067 #undef SDL_CreateThread
  1068 #if SDL_DYNAMIC_API
  1069         device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
  1070 #else
  1071         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1072 #endif
  1073 #else
  1074         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1075 #endif
  1076         if (device->thread == NULL) {
  1077             SDL_CloseAudioDevice(id + 1);
  1078             SDL_SetError("Couldn't create audio thread");
  1079             return 0;
  1080         }
  1081     }
  1082 
  1083     return id + 1;
  1084 }
  1085 
  1086 
  1087 int
  1088 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1089 {
  1090     SDL_AudioDeviceID id = 0;
  1091 
  1092     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1093     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1094         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1095             return (-1);
  1096         }
  1097     }
  1098 
  1099     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1100     if (open_devices[0] != NULL) {
  1101         SDL_SetError("Audio device is already opened");
  1102         return (-1);
  1103     }
  1104 
  1105     if (obtained) {
  1106         id = open_audio_device(NULL, 0, desired, obtained,
  1107                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1108     } else {
  1109         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
  1110     }
  1111 
  1112     SDL_assert((id == 0) || (id == 1));
  1113     return ((id == 0) ? -1 : 0);
  1114 }
  1115 
  1116 SDL_AudioDeviceID
  1117 SDL_OpenAudioDevice(const char *device, int iscapture,
  1118                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1119                     int allowed_changes)
  1120 {
  1121     return open_audio_device(device, iscapture, desired, obtained,
  1122                              allowed_changes, 2);
  1123 }
  1124 
  1125 SDL_AudioStatus
  1126 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1127 {
  1128     SDL_AudioDevice *device = get_audio_device(devid);
  1129     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1130     if (device && device->enabled) {
  1131         if (device->paused) {
  1132             status = SDL_AUDIO_PAUSED;
  1133         } else {
  1134             status = SDL_AUDIO_PLAYING;
  1135         }
  1136     }
  1137     return (status);
  1138 }
  1139 
  1140 
  1141 SDL_AudioStatus
  1142 SDL_GetAudioStatus(void)
  1143 {
  1144     return SDL_GetAudioDeviceStatus(1);
  1145 }
  1146 
  1147 void
  1148 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1149 {
  1150     SDL_AudioDevice *device = get_audio_device(devid);
  1151     if (device) {
  1152         current_audio.impl.LockDevice(device);
  1153         device->paused = pause_on;
  1154         current_audio.impl.UnlockDevice(device);
  1155     }
  1156 }
  1157 
  1158 void
  1159 SDL_PauseAudio(int pause_on)
  1160 {
  1161     SDL_PauseAudioDevice(1, pause_on);
  1162 }
  1163 
  1164 
  1165 void
  1166 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1167 {
  1168     /* Obtain a lock on the mixing buffers */
  1169     SDL_AudioDevice *device = get_audio_device(devid);
  1170     if (device) {
  1171         current_audio.impl.LockDevice(device);
  1172     }
  1173 }
  1174 
  1175 void
  1176 SDL_LockAudio(void)
  1177 {
  1178     SDL_LockAudioDevice(1);
  1179 }
  1180 
  1181 void
  1182 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1183 {
  1184     /* Obtain a lock on the mixing buffers */
  1185     SDL_AudioDevice *device = get_audio_device(devid);
  1186     if (device) {
  1187         current_audio.impl.UnlockDevice(device);
  1188     }
  1189 }
  1190 
  1191 void
  1192 SDL_UnlockAudio(void)
  1193 {
  1194     SDL_UnlockAudioDevice(1);
  1195 }
  1196 
  1197 void
  1198 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1199 {
  1200     SDL_AudioDevice *device = get_audio_device(devid);
  1201     if (device) {
  1202         close_audio_device(device);
  1203         open_devices[devid - 1] = NULL;
  1204     }
  1205 }
  1206 
  1207 void
  1208 SDL_CloseAudio(void)
  1209 {
  1210     SDL_CloseAudioDevice(1);
  1211 }
  1212 
  1213 void
  1214 SDL_AudioQuit(void)
  1215 {
  1216     SDL_AudioDeviceID i;
  1217 
  1218     if (!current_audio.name) {  /* not initialized?! */
  1219         return;
  1220     }
  1221 
  1222     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1223         if (open_devices[i] != NULL) {
  1224             SDL_CloseAudioDevice(i+1);
  1225         }
  1226     }
  1227 
  1228     /* Free the driver data */
  1229     current_audio.impl.Deinitialize();
  1230     free_device_list(&current_audio.outputDevices,
  1231                      &current_audio.outputDeviceCount);
  1232     free_device_list(&current_audio.inputDevices,
  1233                      &current_audio.inputDeviceCount);
  1234     SDL_memset(&current_audio, '\0', sizeof(current_audio));
  1235     SDL_memset(open_devices, '\0', sizeof(open_devices));
  1236 }
  1237 
  1238 #define NUM_FORMATS 10
  1239 static int format_idx;
  1240 static int format_idx_sub;
  1241 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1242     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1243      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1244     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1245      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1246     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1247      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1248     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1249      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1250     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1251      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1252     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1253      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1254     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1255      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1256     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1257      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1258     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1259      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1260     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1261      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1262 };
  1263 
  1264 SDL_AudioFormat
  1265 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1266 {
  1267     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1268         if (format_list[format_idx][0] == format) {
  1269             break;
  1270         }
  1271     }
  1272     format_idx_sub = 0;
  1273     return (SDL_NextAudioFormat());
  1274 }
  1275 
  1276 SDL_AudioFormat
  1277 SDL_NextAudioFormat(void)
  1278 {
  1279     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1280         return (0);
  1281     }
  1282     return (format_list[format_idx][format_idx_sub++]);
  1283 }
  1284 
  1285 void
  1286 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1287 {
  1288     switch (spec->format) {
  1289     case AUDIO_U8:
  1290         spec->silence = 0x80;
  1291         break;
  1292     default:
  1293         spec->silence = 0x00;
  1294         break;
  1295     }
  1296     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1297     spec->size *= spec->channels;
  1298     spec->size *= spec->samples;
  1299 }
  1300 
  1301 
  1302 /*
  1303  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1304  *  audio device (and is deprecated, by the way!).
  1305  */
  1306 void
  1307 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1308 {
  1309     /* Mix the user-level audio format */
  1310     SDL_AudioDevice *device = get_audio_device(1);
  1311     if (device != NULL) {
  1312         SDL_AudioFormat format;
  1313         if (device->convert.needed) {
  1314             format = device->convert.src_format;
  1315         } else {
  1316             format = device->spec.format;
  1317         }
  1318         SDL_MixAudioFormat(dst, src, format, len, volume);
  1319     }
  1320 }
  1321 
  1322 /* vi: set ts=4 sw=4 expandtab: */