src/audio/SDL_audio.c
author Ryan C. Gordon
Sun, 24 Nov 2013 23:56:17 -0500
changeset 8093 b43765095a6f
parent 7981 6d538bc1b395
child 8094 9efaae827924
permissions -rw-r--r--
Make internal SDL sources include SDL_internal.h instead of SDL_config.h

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