src/audio/SDL_audio.c
author Ryan C. Gordon
Thu, 11 Jul 2013 23:53:00 -0400
changeset 7406 fb02213c11d3
parent 7367 d6eabafa8776
child 7407 db8a19d767d7
permissions -rw-r--r--
Explicitly write silence to the audio device while it is paused.

This is what SDL 1.2 did; we'll do this properly (add a method for the target
driver to pause) when I rewrite all this code after the official 2.0 release.

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