src/audio/SDL_audio.c
author Gabriel Jacobo <gabomdq@gmail.com>
Wed, 21 Aug 2013 09:47:10 -0300
changeset 7678 286c42d7c5ed
parent 7518 febc83bc2a43
child 7719 31b5f9ff36ca
permissions -rw-r--r--
OCD fixes: Adds a space after /* (glory to regular expressions!)
     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         stream_len = device->convert.len;
   364     } else {
   365         stream_len = device->spec.size;
   366     }
   367 
   368     /* Calculate the delay while paused */
   369     delay = ((device->spec.samples * 1000) / device->spec.freq);
   370 
   371     /* Determine if the streamer is necessary here */
   372     if (device->use_streamer == 1) {
   373         /* This code is almost the same as the old code. The difference is, instead of reading
   374            directly from the callback into "stream", then converting and sending the audio off,
   375            we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   376            However, reading and writing with streamer are done separately:
   377            - We only call the callback and write to the streamer when the streamer does not
   378            contain enough samples to output to the device.
   379            - We only read from the streamer and tell the device to play when the streamer
   380            does have enough samples to output.
   381            This allows us to perform resampling in the conversion step, where the output of the
   382            resampling process can be any number. We will have to see what a good size for the
   383            stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   384          */
   385         while (device->enabled) {
   386 
   387             if (device->paused) {
   388                 SDL_Delay(delay);
   389                 continue;
   390             }
   391 
   392             /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   393             if (SDL_StreamLength(&device->streamer) < stream_len) {
   394                 /* Set up istream */
   395                 if (device->convert.needed) {
   396                     if (device->convert.buf) {
   397                         istream = device->convert.buf;
   398                     } else {
   399                         continue;
   400                     }
   401                 } else {
   402 /* FIXME: Ryan, this is probably wrong.  I imagine we don't want to get
   403  * a device buffer both here and below in the stream output.
   404  */
   405                     istream = current_audio.impl.GetDeviceBuf(device);
   406                     if (istream == NULL) {
   407                         istream = device->fake_stream;
   408                     }
   409                 }
   410 
   411                 /* Read from the callback into the _input_ stream */
   412                 SDL_LockMutex(device->mixer_lock);
   413                 (*fill) (udata, istream, istream_len);
   414                 SDL_UnlockMutex(device->mixer_lock);
   415 
   416                 /* Convert the audio if necessary and write to the streamer */
   417                 if (device->convert.needed) {
   418                     SDL_ConvertAudio(&device->convert);
   419                     if (istream == NULL) {
   420                         istream = device->fake_stream;
   421                     }
   422                     /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
   423                     SDL_StreamWrite(&device->streamer, device->convert.buf,
   424                                     device->convert.len_cvt);
   425                 } else {
   426                     SDL_StreamWrite(&device->streamer, istream, istream_len);
   427                 }
   428             }
   429 
   430             /* Only output audio if the streamer has enough to output */
   431             if (SDL_StreamLength(&device->streamer) >= stream_len) {
   432                 /* Set up the output stream */
   433                 if (device->convert.needed) {
   434                     if (device->convert.buf) {
   435                         stream = device->convert.buf;
   436                     } else {
   437                         continue;
   438                     }
   439                 } else {
   440                     stream = current_audio.impl.GetDeviceBuf(device);
   441                     if (stream == NULL) {
   442                         stream = device->fake_stream;
   443                     }
   444                 }
   445 
   446                 /* Now read from the streamer */
   447                 SDL_StreamRead(&device->streamer, stream, stream_len);
   448 
   449                 /* Ready current buffer for play and change current buffer */
   450                 if (stream != device->fake_stream) {
   451                     current_audio.impl.PlayDevice(device);
   452                     /* Wait for an audio buffer to become available */
   453                     current_audio.impl.WaitDevice(device);
   454                 } else {
   455                     SDL_Delay(delay);
   456                 }
   457             }
   458 
   459         }
   460     } else {
   461         /* Otherwise, do not use the streamer. This is the old code. */
   462         const int silence = (int) device->spec.silence;
   463 
   464         /* Loop, filling the audio buffers */
   465         while (device->enabled) {
   466 
   467             /* Fill the current buffer with sound */
   468             if (device->convert.needed) {
   469                 if (device->convert.buf) {
   470                     stream = device->convert.buf;
   471                 } else {
   472                     continue;
   473                 }
   474             } else {
   475                 stream = current_audio.impl.GetDeviceBuf(device);
   476                 if (stream == NULL) {
   477                     stream = device->fake_stream;
   478                 }
   479             }
   480 
   481             SDL_LockMutex(device->mixer_lock);
   482             if (device->paused) {
   483                 SDL_memset(stream, silence, stream_len);
   484             } else {
   485                 (*fill) (udata, stream, stream_len);
   486             }
   487             SDL_UnlockMutex(device->mixer_lock);
   488 
   489             /* Convert the audio if necessary */
   490             if (device->convert.needed) {
   491                 SDL_ConvertAudio(&device->convert);
   492                 stream = current_audio.impl.GetDeviceBuf(device);
   493                 if (stream == NULL) {
   494                     stream = device->fake_stream;
   495                 }
   496                 SDL_memcpy(stream, device->convert.buf,
   497                            device->convert.len_cvt);
   498             }
   499 
   500             /* Ready current buffer for play and change current buffer */
   501             if (stream != device->fake_stream) {
   502                 current_audio.impl.PlayDevice(device);
   503                 /* Wait for an audio buffer to become available */
   504                 current_audio.impl.WaitDevice(device);
   505             } else {
   506                 SDL_Delay(delay);
   507             }
   508         }
   509     }
   510 
   511     /* Wait for the audio to drain.. */
   512     current_audio.impl.WaitDone(device);
   513 
   514     /* If necessary, deinit the streamer */
   515     if (device->use_streamer == 1)
   516         SDL_StreamDeinit(&device->streamer);
   517 
   518     return (0);
   519 }
   520 
   521 
   522 static SDL_AudioFormat
   523 SDL_ParseAudioFormat(const char *string)
   524 {
   525 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
   526     CHECK_FMT_STRING(U8);
   527     CHECK_FMT_STRING(S8);
   528     CHECK_FMT_STRING(U16LSB);
   529     CHECK_FMT_STRING(S16LSB);
   530     CHECK_FMT_STRING(U16MSB);
   531     CHECK_FMT_STRING(S16MSB);
   532     CHECK_FMT_STRING(U16SYS);
   533     CHECK_FMT_STRING(S16SYS);
   534     CHECK_FMT_STRING(U16);
   535     CHECK_FMT_STRING(S16);
   536     CHECK_FMT_STRING(S32LSB);
   537     CHECK_FMT_STRING(S32MSB);
   538     CHECK_FMT_STRING(S32SYS);
   539     CHECK_FMT_STRING(S32);
   540     CHECK_FMT_STRING(F32LSB);
   541     CHECK_FMT_STRING(F32MSB);
   542     CHECK_FMT_STRING(F32SYS);
   543     CHECK_FMT_STRING(F32);
   544 #undef CHECK_FMT_STRING
   545     return 0;
   546 }
   547 
   548 int
   549 SDL_GetNumAudioDrivers(void)
   550 {
   551     return (SDL_arraysize(bootstrap) - 1);
   552 }
   553 
   554 const char *
   555 SDL_GetAudioDriver(int index)
   556 {
   557     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
   558         return (bootstrap[index]->name);
   559     }
   560     return (NULL);
   561 }
   562 
   563 int
   564 SDL_AudioInit(const char *driver_name)
   565 {
   566     int i = 0;
   567     int initialized = 0;
   568     int tried_to_init = 0;
   569 
   570     if (SDL_WasInit(SDL_INIT_AUDIO)) {
   571         SDL_AudioQuit();        /* shutdown driver if already running. */
   572     }
   573 
   574     SDL_memset(&current_audio, '\0', sizeof(current_audio));
   575     SDL_memset(open_devices, '\0', sizeof(open_devices));
   576 
   577     /* Select the proper audio driver */
   578     if (driver_name == NULL) {
   579         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   580     }
   581 
   582     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   583         /* make sure we should even try this driver before doing so... */
   584         const AudioBootStrap *backend = bootstrap[i];
   585         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
   586             (!driver_name && backend->demand_only)) {
   587             continue;
   588         }
   589 
   590         tried_to_init = 1;
   591         SDL_memset(&current_audio, 0, sizeof(current_audio));
   592         current_audio.name = backend->name;
   593         current_audio.desc = backend->desc;
   594         initialized = backend->init(&current_audio.impl);
   595     }
   596 
   597     if (!initialized) {
   598         /* specific drivers will set the error message if they fail... */
   599         if (!tried_to_init) {
   600             if (driver_name) {
   601                 SDL_SetError("Audio target '%s' not available", driver_name);
   602             } else {
   603                 SDL_SetError("No available audio device");
   604             }
   605         }
   606 
   607         SDL_memset(&current_audio, 0, sizeof(current_audio));
   608         return (-1);            /* No driver was available, so fail. */
   609     }
   610 
   611     finalize_audio_entry_points();
   612 
   613     return (0);
   614 }
   615 
   616 /*
   617  * Get the current audio driver name
   618  */
   619 const char *
   620 SDL_GetCurrentAudioDriver()
   621 {
   622     return current_audio.name;
   623 }
   624 
   625 static void
   626 free_device_list(char ***devices, int *devCount)
   627 {
   628     int i = *devCount;
   629     if ((i > 0) && (*devices != NULL)) {
   630         while (i--) {
   631             SDL_free((*devices)[i]);
   632         }
   633     }
   634 
   635     if (*devices != NULL) {
   636         SDL_free(*devices);
   637     }
   638 
   639     *devices = NULL;
   640     *devCount = 0;
   641 }
   642 
   643 static
   644 void SDL_AddCaptureAudioDevice(const char *_name)
   645 {
   646     char *name = NULL;
   647     void *ptr = SDL_realloc(current_audio.inputDevices,
   648                           (current_audio.inputDeviceCount+1) * sizeof(char*));
   649     if (ptr == NULL) {
   650         return;  /* oh well. */
   651     }
   652 
   653     current_audio.inputDevices = (char **) ptr;
   654     name = SDL_strdup(_name);  /* if this returns NULL, that's okay. */
   655     current_audio.inputDevices[current_audio.inputDeviceCount++] = name;
   656 }
   657 
   658 static
   659 void SDL_AddOutputAudioDevice(const char *_name)
   660 {
   661     char *name = NULL;
   662     void *ptr = SDL_realloc(current_audio.outputDevices,
   663                           (current_audio.outputDeviceCount+1) * sizeof(char*));
   664     if (ptr == NULL) {
   665         return;  /* oh well. */
   666     }
   667 
   668     current_audio.outputDevices = (char **) ptr;
   669     name = SDL_strdup(_name);  /* if this returns NULL, that's okay. */
   670     current_audio.outputDevices[current_audio.outputDeviceCount++] = name;
   671 }
   672 
   673 
   674 int
   675 SDL_GetNumAudioDevices(int iscapture)
   676 {
   677     int retval = 0;
   678 
   679     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   680         return -1;
   681     }
   682 
   683     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   684         return 0;
   685     }
   686 
   687     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   688         return 1;
   689     }
   690 
   691     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   692         return 1;
   693     }
   694 
   695     if (iscapture) {
   696         free_device_list(&current_audio.inputDevices,
   697                          &current_audio.inputDeviceCount);
   698         current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
   699         retval = current_audio.inputDeviceCount;
   700     } else {
   701         free_device_list(&current_audio.outputDevices,
   702                          &current_audio.outputDeviceCount);
   703         current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
   704         retval = current_audio.outputDeviceCount;
   705     }
   706 
   707     return retval;
   708 }
   709 
   710 
   711 const char *
   712 SDL_GetAudioDeviceName(int index, int iscapture)
   713 {
   714     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   715         SDL_SetError("Audio subsystem is not initialized");
   716         return NULL;
   717     }
   718 
   719     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   720         SDL_SetError("No capture support");
   721         return NULL;
   722     }
   723 
   724     if (index < 0) {
   725         goto no_such_device;
   726     }
   727 
   728     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   729         return DEFAULT_INPUT_DEVNAME;
   730     }
   731 
   732     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   733         return DEFAULT_OUTPUT_DEVNAME;
   734     }
   735 
   736     if (iscapture) {
   737         if (index >= current_audio.inputDeviceCount) {
   738             goto no_such_device;
   739         }
   740         return current_audio.inputDevices[index];
   741     } else {
   742         if (index >= current_audio.outputDeviceCount) {
   743             goto no_such_device;
   744         }
   745         return current_audio.outputDevices[index];
   746     }
   747 
   748 no_such_device:
   749     SDL_SetError("No such device");
   750     return NULL;
   751 }
   752 
   753 
   754 static void
   755 close_audio_device(SDL_AudioDevice * device)
   756 {
   757     device->enabled = 0;
   758     if (device->thread != NULL) {
   759         SDL_WaitThread(device->thread, NULL);
   760     }
   761     if (device->mixer_lock != NULL) {
   762         SDL_DestroyMutex(device->mixer_lock);
   763     }
   764     if (device->fake_stream != NULL) {
   765         SDL_FreeAudioMem(device->fake_stream);
   766     }
   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         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1040 #else
  1041         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1042 #endif
  1043         if (device->thread == NULL) {
  1044             SDL_CloseAudioDevice(id + 1);
  1045             SDL_SetError("Couldn't create audio thread");
  1046             return 0;
  1047         }
  1048     }
  1049 
  1050     return id + 1;
  1051 }
  1052 
  1053 
  1054 int
  1055 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1056 {
  1057     SDL_AudioDeviceID id = 0;
  1058 
  1059     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1060     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1061         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1062             return (-1);
  1063         }
  1064     }
  1065 
  1066     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1067     if (open_devices[0] != NULL) {
  1068         SDL_SetError("Audio device is already opened");
  1069         return (-1);
  1070     }
  1071 
  1072     if (obtained) {
  1073         id = open_audio_device(NULL, 0, desired, obtained,
  1074                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1075     } else {
  1076         id = open_audio_device(NULL, 0, desired, desired, 0, 1);
  1077     }
  1078 
  1079     SDL_assert((id == 0) || (id == 1));
  1080     return ((id == 0) ? -1 : 0);
  1081 }
  1082 
  1083 SDL_AudioDeviceID
  1084 SDL_OpenAudioDevice(const char *device, int iscapture,
  1085                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1086                     int allowed_changes)
  1087 {
  1088     return open_audio_device(device, iscapture, desired, obtained,
  1089                              allowed_changes, 2);
  1090 }
  1091 
  1092 SDL_AudioStatus
  1093 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1094 {
  1095     SDL_AudioDevice *device = get_audio_device(devid);
  1096     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1097     if (device && device->enabled) {
  1098         if (device->paused) {
  1099             status = SDL_AUDIO_PAUSED;
  1100         } else {
  1101             status = SDL_AUDIO_PLAYING;
  1102         }
  1103     }
  1104     return (status);
  1105 }
  1106 
  1107 
  1108 SDL_AudioStatus
  1109 SDL_GetAudioStatus(void)
  1110 {
  1111     return SDL_GetAudioDeviceStatus(1);
  1112 }
  1113 
  1114 void
  1115 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1116 {
  1117     SDL_AudioDevice *device = get_audio_device(devid);
  1118     if (device) {
  1119         current_audio.impl.LockDevice(device);
  1120         device->paused = pause_on;
  1121         current_audio.impl.UnlockDevice(device);
  1122     }
  1123 }
  1124 
  1125 void
  1126 SDL_PauseAudio(int pause_on)
  1127 {
  1128     SDL_PauseAudioDevice(1, pause_on);
  1129 }
  1130 
  1131 
  1132 void
  1133 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1134 {
  1135     /* Obtain a lock on the mixing buffers */
  1136     SDL_AudioDevice *device = get_audio_device(devid);
  1137     if (device) {
  1138         current_audio.impl.LockDevice(device);
  1139     }
  1140 }
  1141 
  1142 void
  1143 SDL_LockAudio(void)
  1144 {
  1145     SDL_LockAudioDevice(1);
  1146 }
  1147 
  1148 void
  1149 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1150 {
  1151     /* Obtain a lock on the mixing buffers */
  1152     SDL_AudioDevice *device = get_audio_device(devid);
  1153     if (device) {
  1154         current_audio.impl.UnlockDevice(device);
  1155     }
  1156 }
  1157 
  1158 void
  1159 SDL_UnlockAudio(void)
  1160 {
  1161     SDL_UnlockAudioDevice(1);
  1162 }
  1163 
  1164 void
  1165 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1166 {
  1167     SDL_AudioDevice *device = get_audio_device(devid);
  1168     if (device) {
  1169         close_audio_device(device);
  1170         open_devices[devid - 1] = NULL;
  1171     }
  1172 }
  1173 
  1174 void
  1175 SDL_CloseAudio(void)
  1176 {
  1177     SDL_CloseAudioDevice(1);
  1178 }
  1179 
  1180 void
  1181 SDL_AudioQuit(void)
  1182 {
  1183     SDL_AudioDeviceID i;
  1184 
  1185     if (!current_audio.name) {  /* not initialized?! */
  1186         return;
  1187     }
  1188 
  1189     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1190         if (open_devices[i] != NULL) {
  1191             SDL_CloseAudioDevice(i+1);
  1192         }
  1193     }
  1194 
  1195     /* Free the driver data */
  1196     current_audio.impl.Deinitialize();
  1197     free_device_list(&current_audio.outputDevices,
  1198                      &current_audio.outputDeviceCount);
  1199     free_device_list(&current_audio.inputDevices,
  1200                      &current_audio.inputDeviceCount);
  1201     SDL_memset(&current_audio, '\0', sizeof(current_audio));
  1202     SDL_memset(open_devices, '\0', sizeof(open_devices));
  1203 }
  1204 
  1205 #define NUM_FORMATS 10
  1206 static int format_idx;
  1207 static int format_idx_sub;
  1208 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1209     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1210      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1211     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1212      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1213     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1214      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1215     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1216      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1217     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1218      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1219     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1220      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1221     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1222      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1223     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1224      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1225     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1226      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1227     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1228      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1229 };
  1230 
  1231 SDL_AudioFormat
  1232 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1233 {
  1234     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1235         if (format_list[format_idx][0] == format) {
  1236             break;
  1237         }
  1238     }
  1239     format_idx_sub = 0;
  1240     return (SDL_NextAudioFormat());
  1241 }
  1242 
  1243 SDL_AudioFormat
  1244 SDL_NextAudioFormat(void)
  1245 {
  1246     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1247         return (0);
  1248     }
  1249     return (format_list[format_idx][format_idx_sub++]);
  1250 }
  1251 
  1252 void
  1253 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1254 {
  1255     switch (spec->format) {
  1256     case AUDIO_U8:
  1257         spec->silence = 0x80;
  1258         break;
  1259     default:
  1260         spec->silence = 0x00;
  1261         break;
  1262     }
  1263     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1264     spec->size *= spec->channels;
  1265     spec->size *= spec->samples;
  1266 }
  1267 
  1268 
  1269 /*
  1270  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1271  *  audio device (and is deprecated, by the way!).
  1272  */
  1273 void
  1274 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1275 {
  1276     /* Mix the user-level audio format */
  1277     SDL_AudioDevice *device = get_audio_device(1);
  1278     if (device != NULL) {
  1279         SDL_AudioFormat format;
  1280         if (device->convert.needed) {
  1281             format = device->convert.src_format;
  1282         } else {
  1283             format = device->spec.format;
  1284         }
  1285         SDL_MixAudioFormat(dst, src, format, len, volume);
  1286     }
  1287 }
  1288 
  1289 /* vi: set ts=4 sw=4 expandtab: */