src/audio/SDL_audio.c
author Sam Lantinga
Thu, 29 Aug 2013 08:29:21 -0700
changeset 7719 31b5f9ff36ca
parent 7678 286c42d7c5ed
child 7904 915b9b6c9fa0
permissions -rw-r--r--
Christoph Mallon: Remove pointless if (x) before SDL_free(x)
     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     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         return DEFAULT_INPUT_DEVNAME;
   726     }
   727 
   728     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   729         return DEFAULT_OUTPUT_DEVNAME;
   730     }
   731 
   732     if (iscapture) {
   733         if (index >= current_audio.inputDeviceCount) {
   734             goto no_such_device;
   735         }
   736         return current_audio.inputDevices[index];
   737     } else {
   738         if (index >= current_audio.outputDeviceCount) {
   739             goto no_such_device;
   740         }
   741         return current_audio.outputDevices[index];
   742     }
   743 
   744 no_such_device:
   745     SDL_SetError("No such device");
   746     return NULL;
   747 }
   748 
   749 
   750 static void
   751 close_audio_device(SDL_AudioDevice * device)
   752 {
   753     device->enabled = 0;
   754     if (device->thread != NULL) {
   755         SDL_WaitThread(device->thread, NULL);
   756     }
   757     if (device->mixer_lock != NULL) {
   758         SDL_DestroyMutex(device->mixer_lock);
   759     }
   760     SDL_FreeAudioMem(device->fake_stream);
   761     if (device->convert.needed) {
   762         SDL_FreeAudioMem(device->convert.buf);
   763     }
   764     if (device->opened) {
   765         current_audio.impl.CloseDevice(device);
   766         device->opened = 0;
   767     }
   768     SDL_FreeAudioMem(device);
   769 }
   770 
   771 
   772 /*
   773  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
   774  *  Fills in a sanitized copy in (prepared).
   775  *  Returns non-zero if okay, zero on fatal parameters in (orig).
   776  */
   777 static int
   778 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
   779 {
   780     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
   781 
   782     if (orig->callback == NULL) {
   783         SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   784         return 0;
   785     }
   786 
   787     if (orig->freq == 0) {
   788         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   789         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
   790             prepared->freq = 22050;     /* a reasonable default */
   791         }
   792     }
   793 
   794     if (orig->format == 0) {
   795         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
   796         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
   797             prepared->format = AUDIO_S16;       /* a reasonable default */
   798         }
   799     }
   800 
   801     switch (orig->channels) {
   802     case 0:{
   803             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
   804             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
   805                 prepared->channels = 2; /* a reasonable default */
   806             }
   807             break;
   808         }
   809     case 1:                    /* Mono */
   810     case 2:                    /* Stereo */
   811     case 4:                    /* surround */
   812     case 6:                    /* surround with center and lfe */
   813         break;
   814     default:
   815         SDL_SetError("Unsupported number of audio channels.");
   816         return 0;
   817     }
   818 
   819     if (orig->samples == 0) {
   820         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   821         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
   822             /* Pick a default of ~46 ms at desired frequency */
   823             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   824             const int samples = (prepared->freq / 1000) * 46;
   825             int power2 = 1;
   826             while (power2 < samples) {
   827                 power2 *= 2;
   828             }
   829             prepared->samples = power2;
   830         }
   831     }
   832 
   833     /* Calculate the silence and size of the audio specification */
   834     SDL_CalculateAudioSpec(prepared);
   835 
   836     return 1;
   837 }
   838 
   839 
   840 static SDL_AudioDeviceID
   841 open_audio_device(const char *devname, int iscapture,
   842                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
   843                   int allowed_changes, int min_id)
   844 {
   845     SDL_AudioDeviceID id = 0;
   846     SDL_AudioSpec _obtained;
   847     SDL_AudioDevice *device;
   848     SDL_bool build_cvt;
   849     int i = 0;
   850 
   851     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   852         SDL_SetError("Audio subsystem is not initialized");
   853         return 0;
   854     }
   855 
   856     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   857         SDL_SetError("No capture support");
   858         return 0;
   859     }
   860 
   861     if (!obtained) {
   862         obtained = &_obtained;
   863     }
   864     if (!prepare_audiospec(desired, obtained)) {
   865         return 0;
   866     }
   867 
   868     /* If app doesn't care about a specific device, let the user override. */
   869     if (devname == NULL) {
   870         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
   871     }
   872 
   873     /*
   874      * Catch device names at the high level for the simple case...
   875      * This lets us have a basic "device enumeration" for systems that
   876      *  don't have multiple devices, but makes sure the device name is
   877      *  always NULL when it hits the low level.
   878      *
   879      * Also make sure that the simple case prevents multiple simultaneous
   880      *  opens of the default system device.
   881      */
   882 
   883     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   884         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
   885             SDL_SetError("No such device");
   886             return 0;
   887         }
   888         devname = NULL;
   889 
   890         for (i = 0; i < SDL_arraysize(open_devices); i++) {
   891             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
   892                 SDL_SetError("Audio device already open");
   893                 return 0;
   894             }
   895         }
   896     }
   897 
   898     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   899         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
   900             SDL_SetError("No such device");
   901             return 0;
   902         }
   903         devname = NULL;
   904 
   905         for (i = 0; i < SDL_arraysize(open_devices); i++) {
   906             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
   907                 SDL_SetError("Audio device already open");
   908                 return 0;
   909             }
   910         }
   911     }
   912 
   913     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
   914     if (device == NULL) {
   915         SDL_OutOfMemory();
   916         return 0;
   917     }
   918     SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
   919     device->spec = *obtained;
   920     device->enabled = 1;
   921     device->paused = 1;
   922     device->iscapture = iscapture;
   923 
   924     /* Create a semaphore for locking the sound buffers */
   925     if (!current_audio.impl.SkipMixerLock) {
   926         device->mixer_lock = SDL_CreateMutex();
   927         if (device->mixer_lock == NULL) {
   928             close_audio_device(device);
   929             SDL_SetError("Couldn't create mixer lock");
   930             return 0;
   931         }
   932     }
   933 
   934     /* force a device detection if we haven't done one yet. */
   935     if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
   936          ((!iscapture) && (current_audio.outputDevices == NULL)) )
   937         SDL_GetNumAudioDevices(iscapture);
   938 
   939     if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
   940         close_audio_device(device);
   941         return 0;
   942     }
   943     device->opened = 1;
   944 
   945     /* Allocate a fake audio memory buffer */
   946     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
   947     if (device->fake_stream == NULL) {
   948         close_audio_device(device);
   949         SDL_OutOfMemory();
   950         return 0;
   951     }
   952 
   953     /* See if we need to do any conversion */
   954     build_cvt = SDL_FALSE;
   955     if (obtained->freq != device->spec.freq) {
   956         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
   957             obtained->freq = device->spec.freq;
   958         } else {
   959             build_cvt = SDL_TRUE;
   960         }
   961     }
   962     if (obtained->format != device->spec.format) {
   963         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
   964             obtained->format = device->spec.format;
   965         } else {
   966             build_cvt = SDL_TRUE;
   967         }
   968     }
   969     if (obtained->channels != device->spec.channels) {
   970         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
   971             obtained->channels = device->spec.channels;
   972         } else {
   973             build_cvt = SDL_TRUE;
   974         }
   975     }
   976 
   977     /* If the audio driver changes the buffer size, accept it.
   978        This needs to be done after the format is modified above,
   979        otherwise it might not have the correct buffer size.
   980      */
   981     if (device->spec.samples != obtained->samples) {
   982         obtained->samples = device->spec.samples;
   983         SDL_CalculateAudioSpec(obtained);
   984     }
   985 
   986     if (build_cvt) {
   987         /* Build an audio conversion block */
   988         if (SDL_BuildAudioCVT(&device->convert,
   989                               obtained->format, obtained->channels,
   990                               obtained->freq,
   991                               device->spec.format, device->spec.channels,
   992                               device->spec.freq) < 0) {
   993             close_audio_device(device);
   994             return 0;
   995         }
   996         if (device->convert.needed) {
   997             device->convert.len = (int) (((double) device->spec.size) /
   998                                          device->convert.len_ratio);
   999 
  1000             device->convert.buf =
  1001                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
  1002                                             device->convert.len_mult);
  1003             if (device->convert.buf == NULL) {
  1004                 close_audio_device(device);
  1005                 SDL_OutOfMemory();
  1006                 return 0;
  1007             }
  1008         }
  1009     }
  1010 
  1011     /* Find an available device ID and store the structure... */
  1012     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
  1013         if (open_devices[id] == NULL) {
  1014             open_devices[id] = device;
  1015             break;
  1016         }
  1017     }
  1018 
  1019     if (id == SDL_arraysize(open_devices)) {
  1020         SDL_SetError("Too many open audio devices");
  1021         close_audio_device(device);
  1022         return 0;
  1023     }
  1024 
  1025     /* Start the audio thread if necessary */
  1026     if (!current_audio.impl.ProvidesOwnCallbackThread) {
  1027         /* Start the audio thread */
  1028         char name[64];
  1029         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
  1030 /* !!! FIXME: this is nasty. */
  1031 #if defined(__WIN32__) && !defined(HAVE_LIBC)
  1032 #undef SDL_CreateThread
  1033         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1034 #else
  1035         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1036 #endif
  1037         if (device->thread == NULL) {
  1038             SDL_CloseAudioDevice(id + 1);
  1039             SDL_SetError("Couldn't create audio thread");
  1040             return 0;
  1041         }
  1042     }
  1043 
  1044     return id + 1;
  1045 }
  1046 
  1047 
  1048 int
  1049 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1050 {
  1051     SDL_AudioDeviceID id = 0;
  1052 
  1053     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1054     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1055         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1056             return (-1);
  1057         }
  1058     }
  1059 
  1060     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1061     if (open_devices[0] != NULL) {
  1062         SDL_SetError("Audio device is already opened");
  1063         return (-1);
  1064     }
  1065 
  1066     if (obtained) {
  1067         id = open_audio_device(NULL, 0, desired, obtained,
  1068                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1069     } else {
  1070         id = open_audio_device(NULL, 0, desired, desired, 0, 1);
  1071     }
  1072 
  1073     SDL_assert((id == 0) || (id == 1));
  1074     return ((id == 0) ? -1 : 0);
  1075 }
  1076 
  1077 SDL_AudioDeviceID
  1078 SDL_OpenAudioDevice(const char *device, int iscapture,
  1079                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1080                     int allowed_changes)
  1081 {
  1082     return open_audio_device(device, iscapture, desired, obtained,
  1083                              allowed_changes, 2);
  1084 }
  1085 
  1086 SDL_AudioStatus
  1087 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1088 {
  1089     SDL_AudioDevice *device = get_audio_device(devid);
  1090     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1091     if (device && device->enabled) {
  1092         if (device->paused) {
  1093             status = SDL_AUDIO_PAUSED;
  1094         } else {
  1095             status = SDL_AUDIO_PLAYING;
  1096         }
  1097     }
  1098     return (status);
  1099 }
  1100 
  1101 
  1102 SDL_AudioStatus
  1103 SDL_GetAudioStatus(void)
  1104 {
  1105     return SDL_GetAudioDeviceStatus(1);
  1106 }
  1107 
  1108 void
  1109 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1110 {
  1111     SDL_AudioDevice *device = get_audio_device(devid);
  1112     if (device) {
  1113         current_audio.impl.LockDevice(device);
  1114         device->paused = pause_on;
  1115         current_audio.impl.UnlockDevice(device);
  1116     }
  1117 }
  1118 
  1119 void
  1120 SDL_PauseAudio(int pause_on)
  1121 {
  1122     SDL_PauseAudioDevice(1, pause_on);
  1123 }
  1124 
  1125 
  1126 void
  1127 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1128 {
  1129     /* Obtain a lock on the mixing buffers */
  1130     SDL_AudioDevice *device = get_audio_device(devid);
  1131     if (device) {
  1132         current_audio.impl.LockDevice(device);
  1133     }
  1134 }
  1135 
  1136 void
  1137 SDL_LockAudio(void)
  1138 {
  1139     SDL_LockAudioDevice(1);
  1140 }
  1141 
  1142 void
  1143 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1144 {
  1145     /* Obtain a lock on the mixing buffers */
  1146     SDL_AudioDevice *device = get_audio_device(devid);
  1147     if (device) {
  1148         current_audio.impl.UnlockDevice(device);
  1149     }
  1150 }
  1151 
  1152 void
  1153 SDL_UnlockAudio(void)
  1154 {
  1155     SDL_UnlockAudioDevice(1);
  1156 }
  1157 
  1158 void
  1159 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1160 {
  1161     SDL_AudioDevice *device = get_audio_device(devid);
  1162     if (device) {
  1163         close_audio_device(device);
  1164         open_devices[devid - 1] = NULL;
  1165     }
  1166 }
  1167 
  1168 void
  1169 SDL_CloseAudio(void)
  1170 {
  1171     SDL_CloseAudioDevice(1);
  1172 }
  1173 
  1174 void
  1175 SDL_AudioQuit(void)
  1176 {
  1177     SDL_AudioDeviceID i;
  1178 
  1179     if (!current_audio.name) {  /* not initialized?! */
  1180         return;
  1181     }
  1182 
  1183     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1184         if (open_devices[i] != NULL) {
  1185             SDL_CloseAudioDevice(i+1);
  1186         }
  1187     }
  1188 
  1189     /* Free the driver data */
  1190     current_audio.impl.Deinitialize();
  1191     free_device_list(&current_audio.outputDevices,
  1192                      &current_audio.outputDeviceCount);
  1193     free_device_list(&current_audio.inputDevices,
  1194                      &current_audio.inputDeviceCount);
  1195     SDL_memset(&current_audio, '\0', sizeof(current_audio));
  1196     SDL_memset(open_devices, '\0', sizeof(open_devices));
  1197 }
  1198 
  1199 #define NUM_FORMATS 10
  1200 static int format_idx;
  1201 static int format_idx_sub;
  1202 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1203     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1204      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1205     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1206      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1207     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1208      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1209     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1210      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1211     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1212      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1213     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1214      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1215     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1216      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1217     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1218      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1219     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1220      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1221     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1222      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1223 };
  1224 
  1225 SDL_AudioFormat
  1226 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1227 {
  1228     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1229         if (format_list[format_idx][0] == format) {
  1230             break;
  1231         }
  1232     }
  1233     format_idx_sub = 0;
  1234     return (SDL_NextAudioFormat());
  1235 }
  1236 
  1237 SDL_AudioFormat
  1238 SDL_NextAudioFormat(void)
  1239 {
  1240     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1241         return (0);
  1242     }
  1243     return (format_list[format_idx][format_idx_sub++]);
  1244 }
  1245 
  1246 void
  1247 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1248 {
  1249     switch (spec->format) {
  1250     case AUDIO_U8:
  1251         spec->silence = 0x80;
  1252         break;
  1253     default:
  1254         spec->silence = 0x00;
  1255         break;
  1256     }
  1257     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1258     spec->size *= spec->channels;
  1259     spec->size *= spec->samples;
  1260 }
  1261 
  1262 
  1263 /*
  1264  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1265  *  audio device (and is deprecated, by the way!).
  1266  */
  1267 void
  1268 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1269 {
  1270     /* Mix the user-level audio format */
  1271     SDL_AudioDevice *device = get_audio_device(1);
  1272     if (device != NULL) {
  1273         SDL_AudioFormat format;
  1274         if (device->convert.needed) {
  1275             format = device->convert.src_format;
  1276         } else {
  1277             format = device->spec.format;
  1278         }
  1279         SDL_MixAudioFormat(dst, src, format, len, volume);
  1280     }
  1281 }
  1282 
  1283 /* vi: set ts=4 sw=4 expandtab: */