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