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