src/audio/SDL_audio.c
author Sam Lantinga
Tue, 24 Jun 2014 01:38:21 -0700
changeset 8919 c9be8299ba6b
parent 8833 ae720d61d14d
child 9010 6d059ed9b6ca
permissions -rw-r--r--
Fixed bug 2467 - bad memcpy in SDL_OpenAudio/open_audio_device/prepare_audiospec chain

Rainer Deyke

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