[SDL_Tizen] Fix SDL_Test
[platform/upstream/SDL.git] / src / audio / SDL_audio.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 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 NACLAUD_bootstrap;
55 extern AudioBootStrap NAS_bootstrap;
56 extern AudioBootStrap XAUDIO2_bootstrap;
57 extern AudioBootStrap DSOUND_bootstrap;
58 extern AudioBootStrap WINMM_bootstrap;
59 extern AudioBootStrap PAUDIO_bootstrap;
60 extern AudioBootStrap HAIKUAUDIO_bootstrap;
61 extern AudioBootStrap COREAUDIO_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 extern AudioBootStrap PSPAUD_bootstrap;
71 extern AudioBootStrap SNDIO_bootstrap;
72 extern AudioBootStrap EmscriptenAudio_bootstrap;
73
74
75 /* Available audio drivers */
76 static const AudioBootStrap *const bootstrap[] = {
77 #if SDL_AUDIO_DRIVER_PULSEAUDIO
78     &PULSEAUDIO_bootstrap,
79 #endif
80 #if SDL_AUDIO_DRIVER_ALSA
81     &ALSA_bootstrap,
82 #endif
83 #if SDL_AUDIO_DRIVER_SNDIO
84     &SNDIO_bootstrap,
85 #endif
86 #if SDL_AUDIO_DRIVER_BSD
87     &BSD_AUDIO_bootstrap,
88 #endif
89 #if SDL_AUDIO_DRIVER_OSS
90     &DSP_bootstrap,
91 #endif
92 #if SDL_AUDIO_DRIVER_QSA
93     &QSAAUDIO_bootstrap,
94 #endif
95 #if SDL_AUDIO_DRIVER_SUNAUDIO
96     &SUNAUDIO_bootstrap,
97 #endif
98 #if SDL_AUDIO_DRIVER_ARTS
99     &ARTS_bootstrap,
100 #endif
101 #if SDL_AUDIO_DRIVER_ESD
102     &ESD_bootstrap,
103 #endif
104 #if SDL_AUDIO_DRIVER_NACL
105    &NACLAUD_bootstrap,
106 #endif
107 #if SDL_AUDIO_DRIVER_NAS
108     &NAS_bootstrap,
109 #endif
110 #if SDL_AUDIO_DRIVER_XAUDIO2
111     &XAUDIO2_bootstrap,
112 #endif
113 #if SDL_AUDIO_DRIVER_DSOUND
114     &DSOUND_bootstrap,
115 #endif
116 #if SDL_AUDIO_DRIVER_WINMM
117     &WINMM_bootstrap,
118 #endif
119 #if SDL_AUDIO_DRIVER_PAUDIO
120     &PAUDIO_bootstrap,
121 #endif
122 #if SDL_AUDIO_DRIVER_HAIKU
123     &HAIKUAUDIO_bootstrap,
124 #endif
125 #if SDL_AUDIO_DRIVER_COREAUDIO
126     &COREAUDIO_bootstrap,
127 #endif
128 #if SDL_AUDIO_DRIVER_DISK
129     &DISKAUD_bootstrap,
130 #endif
131 #if SDL_AUDIO_DRIVER_DUMMY
132     &DUMMYAUD_bootstrap,
133 #endif
134 #if SDL_AUDIO_DRIVER_FUSIONSOUND
135     &FUSIONSOUND_bootstrap,
136 #endif
137 #if SDL_AUDIO_DRIVER_ANDROID
138     &ANDROIDAUD_bootstrap,
139 #endif
140 #if SDL_AUDIO_DRIVER_PSP
141     &PSPAUD_bootstrap,
142 #endif
143 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
144     &EmscriptenAudio_bootstrap,
145 #endif
146     NULL
147 };
148
149 static SDL_AudioDevice *
150 get_audio_device(SDL_AudioDeviceID id)
151 {
152     id--;
153     if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
154         SDL_SetError("Invalid audio device ID");
155         return NULL;
156     }
157
158     return open_devices[id];
159 }
160
161
162 /* stubs for audio drivers that don't need a specific entry point... */
163 static void
164 SDL_AudioDetectDevices_Default(void)
165 {
166     /* you have to write your own implementation if these assertions fail. */
167     SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
168     SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
169
170     SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
171     if (current_audio.impl.HasCaptureSupport) {
172         SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
173     }
174 }
175
176 static void
177 SDL_AudioThreadInit_Default(_THIS)
178 {                               /* no-op. */
179 }
180
181 static void
182 SDL_AudioWaitDevice_Default(_THIS)
183 {                               /* no-op. */
184 }
185
186 static void
187 SDL_AudioPlayDevice_Default(_THIS)
188 {                               /* no-op. */
189 }
190
191 static int
192 SDL_AudioGetPendingBytes_Default(_THIS)
193 {
194     return 0;
195 }
196
197 static Uint8 *
198 SDL_AudioGetDeviceBuf_Default(_THIS)
199 {
200     return NULL;
201 }
202
203 static void
204 SDL_AudioWaitDone_Default(_THIS)
205 {                               /* no-op. */
206 }
207
208 static void
209 SDL_AudioCloseDevice_Default(_THIS)
210 {                               /* no-op. */
211 }
212
213 static void
214 SDL_AudioDeinitialize_Default(void)
215 {                               /* no-op. */
216 }
217
218 static void
219 SDL_AudioFreeDeviceHandle_Default(void *handle)
220 {                               /* no-op. */
221 }
222
223
224 static int
225 SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
226 {
227     return SDL_Unsupported();
228 }
229
230 static SDL_INLINE SDL_bool
231 is_in_audio_device_thread(SDL_AudioDevice * device)
232 {
233     /* The device thread locks the same mutex, but not through the public API.
234        This check is in case the application, in the audio callback,
235        tries to lock the thread that we've already locked from the
236        device thread...just in case we only have non-recursive mutexes. */
237     if (device->thread && (SDL_ThreadID() == device->threadid)) {
238         return SDL_TRUE;
239     }
240
241     return SDL_FALSE;
242 }
243
244 static void
245 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
246 {
247     if (!is_in_audio_device_thread(device)) {
248         SDL_LockMutex(device->mixer_lock);
249     }
250 }
251
252 static void
253 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
254 {
255     if (!is_in_audio_device_thread(device)) {
256         SDL_UnlockMutex(device->mixer_lock);
257     }
258 }
259
260
261 static void
262 finalize_audio_entry_points(void)
263 {
264     /*
265      * Fill in stub functions for unused driver entry points. This lets us
266      *  blindly call them without having to check for validity first.
267      */
268
269 #define FILL_STUB(x) \
270         if (current_audio.impl.x == NULL) { \
271             current_audio.impl.x = SDL_Audio##x##_Default; \
272         }
273     FILL_STUB(DetectDevices);
274     FILL_STUB(OpenDevice);
275     FILL_STUB(ThreadInit);
276     FILL_STUB(WaitDevice);
277     FILL_STUB(PlayDevice);
278     FILL_STUB(GetPendingBytes);
279     FILL_STUB(GetDeviceBuf);
280     FILL_STUB(WaitDone);
281     FILL_STUB(CloseDevice);
282     FILL_STUB(LockDevice);
283     FILL_STUB(UnlockDevice);
284     FILL_STUB(FreeDeviceHandle);
285     FILL_STUB(Deinitialize);
286 #undef FILL_STUB
287 }
288
289
290 /* device hotplug support... */
291
292 static int
293 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
294 {
295     int retval = -1;
296     const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
297     SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
298     if (item == NULL) {
299         return -1;
300     }
301
302     SDL_assert(handle != NULL);  /* we reserve NULL, audio backends can't use it. */
303
304     item->handle = handle;
305     SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
306
307     SDL_LockMutex(current_audio.detectionLock);
308     item->next = *devices;
309     *devices = item;
310     retval = (*devCount)++;
311     SDL_UnlockMutex(current_audio.detectionLock);
312
313     return retval;
314 }
315
316 static SDL_INLINE int
317 add_capture_device(const char *name, void *handle)
318 {
319     /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
320     return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
321 }
322
323 static SDL_INLINE int
324 add_output_device(const char *name, void *handle)
325 {
326     return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
327 }
328
329 static void
330 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
331 {
332     SDL_AudioDeviceItem *item, *next;
333     for (item = *devices; item != NULL; item = next) {
334         next = item->next;
335         if (item->handle != NULL) {
336             current_audio.impl.FreeDeviceHandle(item->handle);
337         }
338         SDL_free(item);
339     }
340     *devices = NULL;
341     *devCount = 0;
342 }
343
344
345 /* The audio backends call this when a new device is plugged in. */
346 void
347 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
348 {
349     const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
350     if (device_index != -1) {
351         /* Post the event, if desired */
352         if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
353             SDL_Event event;
354             SDL_zero(event);
355             event.adevice.type = SDL_AUDIODEVICEADDED;
356             event.adevice.which = device_index;
357             event.adevice.iscapture = iscapture;
358             SDL_PushEvent(&event);
359         }
360     }
361 }
362
363 /* The audio backends call this when a currently-opened device is lost. */
364 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
365 {
366     SDL_assert(get_audio_device(device->id) == device);
367
368     if (!device->enabled) {
369         return;
370     }
371
372     /* Ends the audio callback and mark the device as STOPPED, but the
373        app still needs to close the device to free resources. */
374     current_audio.impl.LockDevice(device);
375     device->enabled = 0;
376     current_audio.impl.UnlockDevice(device);
377
378     /* Post the event, if desired */
379     if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
380         SDL_Event event;
381         SDL_zero(event);
382         event.adevice.type = SDL_AUDIODEVICEREMOVED;
383         event.adevice.which = device->id;
384         event.adevice.iscapture = device->iscapture ? 1 : 0;
385         SDL_PushEvent(&event);
386     }
387 }
388
389 static void
390 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
391 {
392     SDL_AudioDeviceItem *item;
393     SDL_assert(handle != NULL);
394     for (item = devices; item != NULL; item = item->next) {
395         if (item->handle == handle) {
396             item->handle = NULL;
397             *removedFlag = SDL_TRUE;
398             return;
399         }
400     }
401 }
402
403 /* The audio backends call this when a device is removed from the system. */
404 void
405 SDL_RemoveAudioDevice(const int iscapture, void *handle)
406 {
407     SDL_LockMutex(current_audio.detectionLock);
408     if (iscapture) {
409         mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
410     } else {
411         mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
412     }
413     SDL_UnlockMutex(current_audio.detectionLock);
414     current_audio.impl.FreeDeviceHandle(handle);
415 }
416
417
418
419 /* buffer queueing support... */
420
421 /* this expects that you managed thread safety elsewhere. */
422 static void
423 free_audio_queue(SDL_AudioBufferQueue *buffer)
424 {
425     while (buffer) {
426         SDL_AudioBufferQueue *next = buffer->next;
427         SDL_free(buffer);
428         buffer = next;
429     }
430 }
431
432 static void SDLCALL
433 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
434 {
435     /* this function always holds the mixer lock before being called. */
436     Uint32 len = (Uint32) _len;
437     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
438     SDL_AudioBufferQueue *buffer;
439
440     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
441     SDL_assert(_len >= 0);  /* this shouldn't ever happen, right?! */
442
443     while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
444         const Uint32 avail = buffer->datalen - buffer->startpos;
445         const Uint32 cpy = SDL_min(len, avail);
446         SDL_assert(device->queued_bytes >= avail);
447
448         SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
449         buffer->startpos += cpy;
450         stream += cpy;
451         device->queued_bytes -= cpy;
452         len -= cpy;
453
454         if (buffer->startpos == buffer->datalen) {  /* packet is done, put it in the pool. */
455             device->buffer_queue_head = buffer->next;
456             SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
457             buffer->next = device->buffer_queue_pool;
458             device->buffer_queue_pool = buffer;
459         }
460     }
461
462     SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
463
464     if (len > 0) {  /* fill any remaining space in the stream with silence. */
465         SDL_assert(device->buffer_queue_head == NULL);
466         SDL_memset(stream, device->spec.silence, len);
467     }
468
469     if (device->buffer_queue_head == NULL) {
470         device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
471     }
472 }
473
474 int
475 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
476 {
477     SDL_AudioDevice *device = get_audio_device(devid);
478     const Uint8 *data = (const Uint8 *) _data;
479     SDL_AudioBufferQueue *orighead;
480     SDL_AudioBufferQueue *origtail;
481     Uint32 origlen;
482     Uint32 datalen;
483
484     if (!device) {
485         return -1;  /* get_audio_device() will have set the error state */
486     }
487
488     if (device->spec.callback != SDL_BufferQueueDrainCallback) {
489         return SDL_SetError("Audio device has a callback, queueing not allowed");
490     }
491
492     current_audio.impl.LockDevice(device);
493
494     orighead = device->buffer_queue_head;
495     origtail = device->buffer_queue_tail;
496     origlen = origtail ? origtail->datalen : 0;
497
498     while (len > 0) {
499         SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
500         SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
501         if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
502             /* tail packet missing or completely full; we need a new packet. */
503             packet = device->buffer_queue_pool;
504             if (packet != NULL) {
505                 /* we have one available in the pool. */
506                 device->buffer_queue_pool = packet->next;
507             } else {
508                 /* Have to allocate a new one! */
509                 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
510                 if (packet == NULL) {
511                     /* uhoh, reset so we've queued nothing new, free what we can. */
512                     if (!origtail) {
513                         packet = device->buffer_queue_head;  /* whole queue. */
514                     } else {
515                         packet = origtail->next;  /* what we added to existing queue. */
516                         origtail->next = NULL;
517                         origtail->datalen = origlen;
518                     }
519                     device->buffer_queue_head = orighead;
520                     device->buffer_queue_tail = origtail;
521                     device->buffer_queue_pool = NULL;
522
523                     current_audio.impl.UnlockDevice(device);
524
525                     free_audio_queue(packet);  /* give back what we can. */
526
527                     return SDL_OutOfMemory();
528                 }
529             }
530             packet->datalen = 0;
531             packet->startpos = 0;
532             packet->next = NULL;
533
534             SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
535             if (device->buffer_queue_tail == NULL) {
536                 device->buffer_queue_head = packet;
537             } else {
538                 device->buffer_queue_tail->next = packet;
539             }
540             device->buffer_queue_tail = packet;
541         }
542
543         datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
544         SDL_memcpy(packet->data + packet->datalen, data, datalen);
545         data += datalen;
546         len -= datalen;
547         packet->datalen += datalen;
548         device->queued_bytes += datalen;
549     }
550
551     current_audio.impl.UnlockDevice(device);
552
553     return 0;
554 }
555
556 Uint32
557 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
558 {
559     Uint32 retval = 0;
560     SDL_AudioDevice *device = get_audio_device(devid);
561
562     /* Nothing to do unless we're set up for queueing. */
563     if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
564         current_audio.impl.LockDevice(device);
565         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
566         current_audio.impl.UnlockDevice(device);
567     }
568
569     return retval;
570 }
571
572 void
573 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
574 {
575     SDL_AudioDevice *device = get_audio_device(devid);
576     SDL_AudioBufferQueue *buffer = NULL;
577     if (!device) {
578         return;  /* nothing to do. */
579     }
580
581     /* Blank out the device and release the mutex. Free it afterwards. */
582     current_audio.impl.LockDevice(device);
583     buffer = device->buffer_queue_head;
584     device->buffer_queue_tail = NULL;
585     device->buffer_queue_head = NULL;
586     device->queued_bytes = 0;
587     current_audio.impl.UnlockDevice(device);
588
589     free_audio_queue(buffer);
590 }
591
592
593 /* The general mixing thread function */
594 int SDLCALL
595 SDL_RunAudio(void *devicep)
596 {
597     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
598     const int silence = (int) device->spec.silence;
599     const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
600     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
601     Uint8 *stream;
602     void *udata = device->spec.userdata;
603     void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
604
605     /* The audio mixing is always a high priority thread */
606     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
607
608     /* Perform any thread setup */
609     device->threadid = SDL_ThreadID();
610     current_audio.impl.ThreadInit(device);
611
612     /* Loop, filling the audio buffers */
613     while (!device->shutdown) {
614         /* Fill the current buffer with sound */
615         if (device->convert.needed) {
616             stream = device->convert.buf;
617         } else if (device->enabled) {
618             stream = current_audio.impl.GetDeviceBuf(device);
619         } else {
620             /* if the device isn't enabled, we still write to the
621                fake_stream, so the app's callback will fire with
622                a regular frequency, in case they depend on that
623                for timing or progress. They can use hotplug
624                now to know if the device failed. */
625             stream = NULL;
626         }
627
628         if (stream == NULL) {
629             stream = device->fake_stream;
630         }
631
632         /* !!! FIXME: this should be LockDevice. */
633         SDL_LockMutex(device->mixer_lock);
634         if (device->paused) {
635             SDL_memset(stream, silence, stream_len);
636         } else {
637             (*fill) (udata, stream, stream_len);
638         }
639         SDL_UnlockMutex(device->mixer_lock);
640
641         /* Convert the audio if necessary */
642         if (device->enabled && device->convert.needed) {
643             SDL_ConvertAudio(&device->convert);
644             stream = current_audio.impl.GetDeviceBuf(device);
645             if (stream == NULL) {
646                 stream = device->fake_stream;
647             } else {
648                 SDL_memcpy(stream, device->convert.buf,
649                            device->convert.len_cvt);
650             }
651         }
652
653         /* Ready current buffer for play and change current buffer */
654         if (stream == device->fake_stream) {
655             SDL_Delay(delay);
656         } else {
657             current_audio.impl.PlayDevice(device);
658             current_audio.impl.WaitDevice(device);
659         }
660     }
661
662     /* Wait for the audio to drain. */
663     current_audio.impl.WaitDone(device);
664
665     return 0;
666 }
667
668
669 static SDL_AudioFormat
670 SDL_ParseAudioFormat(const char *string)
671 {
672 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
673     CHECK_FMT_STRING(U8);
674     CHECK_FMT_STRING(S8);
675     CHECK_FMT_STRING(U16LSB);
676     CHECK_FMT_STRING(S16LSB);
677     CHECK_FMT_STRING(U16MSB);
678     CHECK_FMT_STRING(S16MSB);
679     CHECK_FMT_STRING(U16SYS);
680     CHECK_FMT_STRING(S16SYS);
681     CHECK_FMT_STRING(U16);
682     CHECK_FMT_STRING(S16);
683     CHECK_FMT_STRING(S32LSB);
684     CHECK_FMT_STRING(S32MSB);
685     CHECK_FMT_STRING(S32SYS);
686     CHECK_FMT_STRING(S32);
687     CHECK_FMT_STRING(F32LSB);
688     CHECK_FMT_STRING(F32MSB);
689     CHECK_FMT_STRING(F32SYS);
690     CHECK_FMT_STRING(F32);
691 #undef CHECK_FMT_STRING
692     return 0;
693 }
694
695 int
696 SDL_GetNumAudioDrivers(void)
697 {
698     return SDL_arraysize(bootstrap) - 1;
699 }
700
701 const char *
702 SDL_GetAudioDriver(int index)
703 {
704     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
705         return bootstrap[index]->name;
706     }
707     return NULL;
708 }
709
710 int
711 SDL_AudioInit(const char *driver_name)
712 {
713     int i = 0;
714     int initialized = 0;
715     int tried_to_init = 0;
716
717     if (SDL_WasInit(SDL_INIT_AUDIO)) {
718         SDL_AudioQuit();        /* shutdown driver if already running. */
719     }
720
721     SDL_zero(current_audio);
722     SDL_zero(open_devices);
723
724     /* Select the proper audio driver */
725     if (driver_name == NULL) {
726         driver_name = SDL_getenv("SDL_AUDIODRIVER");
727     }
728
729     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
730         /* make sure we should even try this driver before doing so... */
731         const AudioBootStrap *backend = bootstrap[i];
732         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
733             (!driver_name && backend->demand_only)) {
734             continue;
735         }
736
737         tried_to_init = 1;
738         SDL_zero(current_audio);
739         current_audio.name = backend->name;
740         current_audio.desc = backend->desc;
741         initialized = backend->init(&current_audio.impl);
742     }
743
744     if (!initialized) {
745         /* specific drivers will set the error message if they fail... */
746         if (!tried_to_init) {
747             if (driver_name) {
748                 SDL_SetError("Audio target '%s' not available", driver_name);
749             } else {
750                 SDL_SetError("No available audio device");
751             }
752         }
753
754         SDL_zero(current_audio);
755         return -1;            /* No driver was available, so fail. */
756     }
757
758     current_audio.detectionLock = SDL_CreateMutex();
759
760     finalize_audio_entry_points();
761
762     /* Make sure we have a list of devices available at startup. */
763     current_audio.impl.DetectDevices();
764
765     return 0;
766 }
767
768 /*
769  * Get the current audio driver name
770  */
771 const char *
772 SDL_GetCurrentAudioDriver()
773 {
774     return current_audio.name;
775 }
776
777 /* Clean out devices that we've removed but had to keep around for stability. */
778 static void
779 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
780 {
781     SDL_AudioDeviceItem *item = *devices;
782     SDL_AudioDeviceItem *prev = NULL;
783     int total = 0;
784
785     while (item) {
786         SDL_AudioDeviceItem *next = item->next;
787         if (item->handle != NULL) {
788             total++;
789             prev = item;
790         } else {
791             if (prev) {
792                 prev->next = next;
793             } else {
794                 *devices = next;
795             }
796             SDL_free(item);
797         }
798         item = next;
799     }
800
801     *devCount = total;
802     *removedFlag = SDL_FALSE;
803 }
804
805
806 int
807 SDL_GetNumAudioDevices(int iscapture)
808 {
809     int retval = 0;
810
811     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
812         return -1;
813     }
814
815     SDL_LockMutex(current_audio.detectionLock);
816     if (iscapture && current_audio.captureDevicesRemoved) {
817         clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
818     }
819
820     if (!iscapture && current_audio.outputDevicesRemoved) {
821         clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
822         current_audio.outputDevicesRemoved = SDL_FALSE;
823     }
824
825     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
826         SDL_SetError("No capture support");
827         return 0;
828     }
829
830     retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
831     SDL_UnlockMutex(current_audio.detectionLock);
832
833     return retval;
834 }
835
836
837 const char *
838 SDL_GetAudioDeviceName(int index, int iscapture)
839 {
840     const char *retval = NULL;
841
842     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
843         SDL_SetError("Audio subsystem is not initialized");
844         return NULL;
845     }
846
847     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
848         SDL_SetError("No capture support");
849         return NULL;
850     }
851
852     if (index >= 0) {
853         SDL_AudioDeviceItem *item;
854         int i;
855
856         SDL_LockMutex(current_audio.detectionLock);
857         item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
858         i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
859         if (index < i) {
860             for (i--; i > index; i--, item = item->next) {
861                 SDL_assert(item != NULL);
862             }
863             SDL_assert(item != NULL);
864             retval = item->name;
865         }
866         SDL_UnlockMutex(current_audio.detectionLock);
867     }
868
869     if (retval == NULL) {
870         SDL_SetError("No such device");
871     }
872
873     return retval;
874 }
875
876
877 static void
878 close_audio_device(SDL_AudioDevice * device)
879 {
880     device->enabled = 0;
881     device->shutdown = 1;
882     if (device->thread != NULL) {
883         SDL_WaitThread(device->thread, NULL);
884     }
885     if (device->mixer_lock != NULL) {
886         SDL_DestroyMutex(device->mixer_lock);
887     }
888     SDL_FreeAudioMem(device->fake_stream);
889     if (device->convert.needed) {
890         SDL_FreeAudioMem(device->convert.buf);
891     }
892     if (device->opened) {
893         current_audio.impl.CloseDevice(device);
894         device->opened = 0;
895     }
896
897     free_audio_queue(device->buffer_queue_head);
898     free_audio_queue(device->buffer_queue_pool);
899
900     SDL_FreeAudioMem(device);
901 }
902
903
904 /*
905  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
906  *  Fills in a sanitized copy in (prepared).
907  *  Returns non-zero if okay, zero on fatal parameters in (orig).
908  */
909 static int
910 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
911 {
912     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
913
914     if (orig->freq == 0) {
915         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
916         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
917             prepared->freq = 22050;     /* a reasonable default */
918         }
919     }
920
921     if (orig->format == 0) {
922         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
923         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
924             prepared->format = AUDIO_S16;       /* a reasonable default */
925         }
926     }
927
928     switch (orig->channels) {
929     case 0:{
930             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
931             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
932                 prepared->channels = 2; /* a reasonable default */
933             }
934             break;
935         }
936     case 1:                    /* Mono */
937     case 2:                    /* Stereo */
938     case 4:                    /* surround */
939     case 6:                    /* surround with center and lfe */
940         break;
941     default:
942         SDL_SetError("Unsupported number of audio channels.");
943         return 0;
944     }
945
946     if (orig->samples == 0) {
947         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
948         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
949             /* Pick a default of ~46 ms at desired frequency */
950             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
951             const int samples = (prepared->freq / 1000) * 46;
952             int power2 = 1;
953             while (power2 < samples) {
954                 power2 *= 2;
955             }
956             prepared->samples = power2;
957         }
958     }
959
960     /* Calculate the silence and size of the audio specification */
961     SDL_CalculateAudioSpec(prepared);
962
963     return 1;
964 }
965
966 static SDL_AudioDeviceID
967 open_audio_device(const char *devname, int iscapture,
968                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
969                   int allowed_changes, int min_id)
970 {
971     SDL_AudioDeviceID id = 0;
972     SDL_AudioSpec _obtained;
973     SDL_AudioDevice *device;
974     SDL_bool build_cvt;
975     void *handle = NULL;
976     Uint32 stream_len;
977     int i = 0;
978
979     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
980         SDL_SetError("Audio subsystem is not initialized");
981         return 0;
982     }
983
984     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
985         SDL_SetError("No capture support");
986         return 0;
987     }
988
989     /* Find an available device ID... */
990     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
991         if (open_devices[id] == NULL) {
992             break;
993         }
994     }
995
996     if (id == SDL_arraysize(open_devices)) {
997         SDL_SetError("Too many open audio devices");
998         return 0;
999     }
1000
1001     if (!obtained) {
1002         obtained = &_obtained;
1003     }
1004     if (!prepare_audiospec(desired, obtained)) {
1005         return 0;
1006     }
1007
1008     /* If app doesn't care about a specific device, let the user override. */
1009     if (devname == NULL) {
1010         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1011     }
1012
1013     /*
1014      * Catch device names at the high level for the simple case...
1015      * This lets us have a basic "device enumeration" for systems that
1016      *  don't have multiple devices, but makes sure the device name is
1017      *  always NULL when it hits the low level.
1018      *
1019      * Also make sure that the simple case prevents multiple simultaneous
1020      *  opens of the default system device.
1021      */
1022
1023     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
1024         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1025             SDL_SetError("No such device");
1026             return 0;
1027         }
1028         devname = NULL;
1029
1030         for (i = 0; i < SDL_arraysize(open_devices); i++) {
1031             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1032                 SDL_SetError("Audio device already open");
1033                 return 0;
1034             }
1035         }
1036     } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1037         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1038             SDL_SetError("No such device");
1039             return 0;
1040         }
1041         devname = NULL;
1042
1043         for (i = 0; i < SDL_arraysize(open_devices); i++) {
1044             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1045                 SDL_SetError("Audio device already open");
1046                 return 0;
1047             }
1048         }
1049     } else if (devname != NULL) {
1050         /* if the app specifies an exact string, we can pass the backend
1051            an actual device handle thingey, which saves them the effort of
1052            figuring out what device this was (such as, reenumerating
1053            everything again to find the matching human-readable name).
1054            It might still need to open a device based on the string for,
1055            say, a network audio server, but this optimizes some cases. */
1056         SDL_AudioDeviceItem *item;
1057         SDL_LockMutex(current_audio.detectionLock);
1058         for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1059             if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1060                 handle = item->handle;
1061                 break;
1062             }
1063         }
1064         SDL_UnlockMutex(current_audio.detectionLock);
1065     }
1066
1067     if (!current_audio.impl.AllowsArbitraryDeviceNames) {
1068         /* has to be in our device list, or the default device. */
1069         if ((handle == NULL) && (devname != NULL)) {
1070             SDL_SetError("No such device.");
1071             return 0;
1072         }
1073     }
1074
1075     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
1076     if (device == NULL) {
1077         SDL_OutOfMemory();
1078         return 0;
1079     }
1080     SDL_zerop(device);
1081     device->id = id + 1;
1082     device->spec = *obtained;
1083     device->enabled = 1;
1084     device->paused = 1;
1085     device->iscapture = iscapture;
1086
1087     /* Create a mutex for locking the sound buffers */
1088     if (!current_audio.impl.SkipMixerLock) {
1089         device->mixer_lock = SDL_CreateMutex();
1090         if (device->mixer_lock == NULL) {
1091             close_audio_device(device);
1092             SDL_SetError("Couldn't create mixer lock");
1093             return 0;
1094         }
1095     }
1096
1097     if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1098         close_audio_device(device);
1099         return 0;
1100     }
1101     device->opened = 1;
1102
1103     /* See if we need to do any conversion */
1104     build_cvt = SDL_FALSE;
1105     if (obtained->freq != device->spec.freq) {
1106         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1107             obtained->freq = device->spec.freq;
1108         } else {
1109             build_cvt = SDL_TRUE;
1110         }
1111     }
1112     if (obtained->format != device->spec.format) {
1113         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1114             obtained->format = device->spec.format;
1115         } else {
1116             build_cvt = SDL_TRUE;
1117         }
1118     }
1119     if (obtained->channels != device->spec.channels) {
1120         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1121             obtained->channels = device->spec.channels;
1122         } else {
1123             build_cvt = SDL_TRUE;
1124         }
1125     }
1126
1127     /* If the audio driver changes the buffer size, accept it.
1128        This needs to be done after the format is modified above,
1129        otherwise it might not have the correct buffer size.
1130      */
1131     if (device->spec.samples != obtained->samples) {
1132         obtained->samples = device->spec.samples;
1133         SDL_CalculateAudioSpec(obtained);
1134     }
1135
1136     if (build_cvt) {
1137         /* Build an audio conversion block */
1138         if (SDL_BuildAudioCVT(&device->convert,
1139                               obtained->format, obtained->channels,
1140                               obtained->freq,
1141                               device->spec.format, device->spec.channels,
1142                               device->spec.freq) < 0) {
1143             close_audio_device(device);
1144             return 0;
1145         }
1146         if (device->convert.needed) {
1147             device->convert.len = (int) (((double) device->spec.size) /
1148                                          device->convert.len_ratio);
1149
1150             device->convert.buf =
1151                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
1152                                             device->convert.len_mult);
1153             if (device->convert.buf == NULL) {
1154                 close_audio_device(device);
1155                 SDL_OutOfMemory();
1156                 return 0;
1157             }
1158         }
1159     }
1160
1161     /* Allocate a fake audio memory buffer */
1162     stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
1163     if (device->spec.size > stream_len) {
1164         stream_len = device->spec.size;
1165     }
1166     SDL_assert(stream_len > 0);
1167     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
1168     if (device->fake_stream == NULL) {
1169         close_audio_device(device);
1170         SDL_OutOfMemory();
1171         return 0;
1172     }
1173
1174     if (device->spec.callback == NULL) {  /* use buffer queueing? */
1175         /* pool a few packets to start. Enough for two callbacks. */
1176         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
1177         const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
1178         const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
1179         for (i = 0; i < wantpackets; i++) {
1180             SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
1181             if (packet) { /* don't care if this fails, we'll deal later. */
1182                 packet->datalen = 0;
1183                 packet->startpos = 0;
1184                 packet->next = device->buffer_queue_pool;
1185                 device->buffer_queue_pool = packet;
1186             }
1187         }
1188
1189         device->spec.callback = SDL_BufferQueueDrainCallback;
1190         device->spec.userdata = device;
1191     }
1192
1193     /* add it to our list of open devices. */
1194     open_devices[id] = device;
1195
1196     /* Start the audio thread if necessary */
1197     if (!current_audio.impl.ProvidesOwnCallbackThread) {
1198         /* Start the audio thread */
1199         char name[64];
1200         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
1201 /* !!! FIXME: this is nasty. */
1202 #if defined(__WIN32__) && !defined(HAVE_LIBC)
1203 #undef SDL_CreateThread
1204 #if SDL_DYNAMIC_API
1205         device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
1206 #else
1207         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
1208 #endif
1209 #else
1210         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
1211 #endif
1212         if (device->thread == NULL) {
1213             SDL_CloseAudioDevice(device->id);
1214             SDL_SetError("Couldn't create audio thread");
1215             return 0;
1216         }
1217     }
1218
1219     return device->id;
1220 }
1221
1222
1223 int
1224 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
1225 {
1226     SDL_AudioDeviceID id = 0;
1227
1228     /* Start up the audio driver, if necessary. This is legacy behaviour! */
1229     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1230         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1231             return -1;
1232         }
1233     }
1234
1235     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1236     if (open_devices[0] != NULL) {
1237         SDL_SetError("Audio device is already opened");
1238         return -1;
1239     }
1240
1241     if (obtained) {
1242         id = open_audio_device(NULL, 0, desired, obtained,
1243                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1244     } else {
1245         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
1246     }
1247
1248     SDL_assert((id == 0) || (id == 1));
1249     return (id == 0) ? -1 : 0;
1250 }
1251
1252 SDL_AudioDeviceID
1253 SDL_OpenAudioDevice(const char *device, int iscapture,
1254                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1255                     int allowed_changes)
1256 {
1257     return open_audio_device(device, iscapture, desired, obtained,
1258                              allowed_changes, 2);
1259 }
1260
1261 SDL_AudioStatus
1262 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1263 {
1264     SDL_AudioDevice *device = get_audio_device(devid);
1265     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
1266     if (device && device->enabled) {
1267         if (device->paused) {
1268             status = SDL_AUDIO_PAUSED;
1269         } else {
1270             status = SDL_AUDIO_PLAYING;
1271         }
1272     }
1273     return status;
1274 }
1275
1276
1277 SDL_AudioStatus
1278 SDL_GetAudioStatus(void)
1279 {
1280     return SDL_GetAudioDeviceStatus(1);
1281 }
1282
1283 void
1284 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
1285 {
1286     SDL_AudioDevice *device = get_audio_device(devid);
1287     if (device) {
1288         current_audio.impl.LockDevice(device);
1289         device->paused = pause_on;
1290         current_audio.impl.UnlockDevice(device);
1291     }
1292 }
1293
1294 void
1295 SDL_PauseAudio(int pause_on)
1296 {
1297     SDL_PauseAudioDevice(1, pause_on);
1298 }
1299
1300
1301 void
1302 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
1303 {
1304     /* Obtain a lock on the mixing buffers */
1305     SDL_AudioDevice *device = get_audio_device(devid);
1306     if (device) {
1307         current_audio.impl.LockDevice(device);
1308     }
1309 }
1310
1311 void
1312 SDL_LockAudio(void)
1313 {
1314     SDL_LockAudioDevice(1);
1315 }
1316
1317 void
1318 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
1319 {
1320     /* Obtain a lock on the mixing buffers */
1321     SDL_AudioDevice *device = get_audio_device(devid);
1322     if (device) {
1323         current_audio.impl.UnlockDevice(device);
1324     }
1325 }
1326
1327 void
1328 SDL_UnlockAudio(void)
1329 {
1330     SDL_UnlockAudioDevice(1);
1331 }
1332
1333 void
1334 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
1335 {
1336     SDL_AudioDevice *device = get_audio_device(devid);
1337     if (device) {
1338         close_audio_device(device);
1339         open_devices[devid - 1] = NULL;
1340     }
1341 }
1342
1343 void
1344 SDL_CloseAudio(void)
1345 {
1346     SDL_CloseAudioDevice(1);
1347 }
1348
1349 void
1350 SDL_AudioQuit(void)
1351 {
1352     SDL_AudioDeviceID i;
1353
1354     if (!current_audio.name) {  /* not initialized?! */
1355         return;
1356     }
1357
1358     for (i = 0; i < SDL_arraysize(open_devices); i++) {
1359         if (open_devices[i] != NULL) {
1360             SDL_CloseAudioDevice(i+1);
1361         }
1362     }
1363
1364     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
1365     free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
1366
1367     /* Free the driver data */
1368     if(current_audio.impl.Deinitialize)
1369         current_audio.impl.Deinitialize();
1370
1371     SDL_DestroyMutex(current_audio.detectionLock);
1372
1373     SDL_zero(current_audio);
1374     SDL_zero(open_devices);
1375 }
1376
1377 #define NUM_FORMATS 10
1378 static int format_idx;
1379 static int format_idx_sub;
1380 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
1381     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1382      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1383     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1384      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1385     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
1386      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1387     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
1388      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1389     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
1390      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1391     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
1392      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1393     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
1394      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1395     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
1396      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1397     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
1398      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1399     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
1400      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1401 };
1402
1403 SDL_AudioFormat
1404 SDL_FirstAudioFormat(SDL_AudioFormat format)
1405 {
1406     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
1407         if (format_list[format_idx][0] == format) {
1408             break;
1409         }
1410     }
1411     format_idx_sub = 0;
1412     return SDL_NextAudioFormat();
1413 }
1414
1415 SDL_AudioFormat
1416 SDL_NextAudioFormat(void)
1417 {
1418     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1419         return 0;
1420     }
1421     return format_list[format_idx][format_idx_sub++];
1422 }
1423
1424 void
1425 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
1426 {
1427     switch (spec->format) {
1428     case AUDIO_U8:
1429         spec->silence = 0x80;
1430         break;
1431     default:
1432         spec->silence = 0x00;
1433         break;
1434     }
1435     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
1436     spec->size *= spec->channels;
1437     spec->size *= spec->samples;
1438 }
1439
1440
1441 /*
1442  * Moved here from SDL_mixer.c, since it relies on internals of an opened
1443  *  audio device (and is deprecated, by the way!).
1444  */
1445 void
1446 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1447 {
1448     /* Mix the user-level audio format */
1449     SDL_AudioDevice *device = get_audio_device(1);
1450     if (device != NULL) {
1451         SDL_AudioFormat format;
1452         if (device->convert.needed) {
1453             format = device->convert.src_format;
1454         } else {
1455             format = device->spec.format;
1456         }
1457         SDL_MixAudioFormat(dst, src, format, len, volume);
1458     }
1459 }
1460
1461 /* vi: set ts=4 sw=4 expandtab: */