better check for clock_gettime_nsec_np() -- cf. bug #5467.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 /* Allow access to a raw mixing buffer */
26 #include "SDL_audio.h"
27 #include "SDL_audio_c.h"
28 #include "SDL_sysaudio.h"
29 #include "../thread/SDL_systhread.h"
31 #define _THIS SDL_AudioDevice *_this
33 static SDL_AudioDriver current_audio;
34 static SDL_AudioDevice *open_devices[16];
36 /* Available audio drivers */
37 static const AudioBootStrap *const bootstrap[] = {
38 #if SDL_AUDIO_DRIVER_PULSEAUDIO
39 &PULSEAUDIO_bootstrap,
41 #if SDL_AUDIO_DRIVER_ALSA
44 #if SDL_AUDIO_DRIVER_SNDIO
47 #if SDL_AUDIO_DRIVER_NETBSD
48 &NETBSDAUDIO_bootstrap,
50 #if SDL_AUDIO_DRIVER_OSS
53 #if SDL_AUDIO_DRIVER_QSA
56 #if SDL_AUDIO_DRIVER_SUNAUDIO
59 #if SDL_AUDIO_DRIVER_ARTS
62 #if SDL_AUDIO_DRIVER_ESD
65 #if SDL_AUDIO_DRIVER_NACL
68 #if SDL_AUDIO_DRIVER_NAS
71 #if SDL_AUDIO_DRIVER_WASAPI
74 #if SDL_AUDIO_DRIVER_DSOUND
77 #if SDL_AUDIO_DRIVER_WINMM
80 #if SDL_AUDIO_DRIVER_PAUDIO
83 #if SDL_AUDIO_DRIVER_HAIKU
84 &HAIKUAUDIO_bootstrap,
86 #if SDL_AUDIO_DRIVER_COREAUDIO
89 #if SDL_AUDIO_DRIVER_FUSIONSOUND
90 &FUSIONSOUND_bootstrap,
92 #if SDL_AUDIO_DRIVER_OPENSLES
95 #if SDL_AUDIO_DRIVER_ANDROID
96 &ANDROIDAUDIO_bootstrap,
98 #if SDL_AUDIO_DRIVER_PSP
101 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
102 &EMSCRIPTENAUDIO_bootstrap,
104 #if SDL_AUDIO_DRIVER_JACK
107 #if SDL_AUDIO_DRIVER_OS2
110 #if SDL_AUDIO_DRIVER_DISK
111 &DISKAUDIO_bootstrap,
113 #if SDL_AUDIO_DRIVER_DUMMY
114 &DUMMYAUDIO_bootstrap,
120 #ifdef HAVE_LIBSAMPLERATE_H
121 #ifdef SDL_LIBSAMPLERATE_DYNAMIC
122 static void *SRC_lib = NULL;
124 SDL_bool SRC_available = SDL_FALSE;
125 int SRC_converter = 0;
126 SRC_STATE* (*SRC_src_new)(int converter_type, int channels, int *error) = NULL;
127 int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data) = NULL;
128 int (*SRC_src_reset)(SRC_STATE *state) = NULL;
129 SRC_STATE* (*SRC_src_delete)(SRC_STATE *state) = NULL;
130 const char* (*SRC_src_strerror)(int error) = NULL;
133 LoadLibSampleRate(void)
135 const char *hint = SDL_GetHint(SDL_HINT_AUDIO_RESAMPLING_MODE);
137 SRC_available = SDL_FALSE;
140 if (!hint || *hint == '0' || SDL_strcasecmp(hint, "default") == 0) {
141 return SDL_FALSE; /* don't load anything. */
142 } else if (*hint == '1' || SDL_strcasecmp(hint, "fast") == 0) {
143 SRC_converter = SRC_SINC_FASTEST;
144 } else if (*hint == '2' || SDL_strcasecmp(hint, "medium") == 0) {
145 SRC_converter = SRC_SINC_MEDIUM_QUALITY;
146 } else if (*hint == '3' || SDL_strcasecmp(hint, "best") == 0) {
147 SRC_converter = SRC_SINC_BEST_QUALITY;
149 return SDL_FALSE; /* treat it like "default", don't load anything. */
152 #ifdef SDL_LIBSAMPLERATE_DYNAMIC
153 SDL_assert(SRC_lib == NULL);
154 SRC_lib = SDL_LoadObject(SDL_LIBSAMPLERATE_DYNAMIC);
160 SRC_src_new = (SRC_STATE* (*)(int converter_type, int channels, int *error))SDL_LoadFunction(SRC_lib, "src_new");
161 SRC_src_process = (int (*)(SRC_STATE *state, SRC_DATA *data))SDL_LoadFunction(SRC_lib, "src_process");
162 SRC_src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(SRC_lib, "src_reset");
163 SRC_src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(SRC_lib, "src_delete");
164 SRC_src_strerror = (const char* (*)(int error))SDL_LoadFunction(SRC_lib, "src_strerror");
166 if (!SRC_src_new || !SRC_src_process || !SRC_src_reset || !SRC_src_delete || !SRC_src_strerror) {
167 SDL_UnloadObject(SRC_lib);
172 SRC_src_new = src_new;
173 SRC_src_process = src_process;
174 SRC_src_reset = src_reset;
175 SRC_src_delete = src_delete;
176 SRC_src_strerror = src_strerror;
179 SRC_available = SDL_TRUE;
184 UnloadLibSampleRate(void)
186 #ifdef SDL_LIBSAMPLERATE_DYNAMIC
187 if (SRC_lib != NULL) {
188 SDL_UnloadObject(SRC_lib);
193 SRC_available = SDL_FALSE;
195 SRC_src_process = NULL;
196 SRC_src_reset = NULL;
197 SRC_src_delete = NULL;
198 SRC_src_strerror = NULL;
202 static SDL_AudioDevice *
203 get_audio_device(SDL_AudioDeviceID id)
206 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
207 SDL_SetError("Invalid audio device ID");
211 return open_devices[id];
215 /* stubs for audio drivers that don't need a specific entry point... */
217 SDL_AudioDetectDevices_Default(void)
219 /* you have to write your own implementation if these assertions fail. */
220 SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
221 SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport);
223 SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
224 if (current_audio.impl.HasCaptureSupport) {
225 SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
230 SDL_AudioThreadInit_Default(_THIS)
235 SDL_AudioThreadDeinit_Default(_THIS)
240 SDL_AudioBeginLoopIteration_Default(_THIS)
245 SDL_AudioWaitDevice_Default(_THIS)
250 SDL_AudioPlayDevice_Default(_THIS)
255 SDL_AudioGetDeviceBuf_Default(_THIS)
261 SDL_AudioCaptureFromDevice_Default(_THIS, void *buffer, int buflen)
263 return -1; /* just fail immediately. */
267 SDL_AudioFlushCapture_Default(_THIS)
272 SDL_AudioPrepareToClose_Default(_THIS)
277 SDL_AudioCloseDevice_Default(_THIS)
282 SDL_AudioDeinitialize_Default(void)
287 SDL_AudioFreeDeviceHandle_Default(void *handle)
293 SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
295 return SDL_Unsupported();
298 static SDL_INLINE SDL_bool
299 is_in_audio_device_thread(SDL_AudioDevice * device)
301 /* The device thread locks the same mutex, but not through the public API.
302 This check is in case the application, in the audio callback,
303 tries to lock the thread that we've already locked from the
304 device thread...just in case we only have non-recursive mutexes. */
305 if (device->thread && (SDL_ThreadID() == device->threadid)) {
313 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
315 if (!is_in_audio_device_thread(device)) {
316 SDL_LockMutex(device->mixer_lock);
321 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
323 if (!is_in_audio_device_thread(device)) {
324 SDL_UnlockMutex(device->mixer_lock);
329 SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
334 finish_audio_entry_points_init(void)
337 * Fill in stub functions for unused driver entry points. This lets us
338 * blindly call them without having to check for validity first.
341 if (current_audio.impl.SkipMixerLock) {
342 if (current_audio.impl.LockDevice == NULL) {
343 current_audio.impl.LockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
345 if (current_audio.impl.UnlockDevice == NULL) {
346 current_audio.impl.UnlockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
350 #define FILL_STUB(x) \
351 if (current_audio.impl.x == NULL) { \
352 current_audio.impl.x = SDL_Audio##x##_Default; \
354 FILL_STUB(DetectDevices);
355 FILL_STUB(OpenDevice);
356 FILL_STUB(ThreadInit);
357 FILL_STUB(ThreadDeinit);
358 FILL_STUB(BeginLoopIteration);
359 FILL_STUB(WaitDevice);
360 FILL_STUB(PlayDevice);
361 FILL_STUB(GetDeviceBuf);
362 FILL_STUB(CaptureFromDevice);
363 FILL_STUB(FlushCapture);
364 FILL_STUB(PrepareToClose);
365 FILL_STUB(CloseDevice);
366 FILL_STUB(LockDevice);
367 FILL_STUB(UnlockDevice);
368 FILL_STUB(FreeDeviceHandle);
369 FILL_STUB(Deinitialize);
374 /* device hotplug support... */
377 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
380 SDL_AudioDeviceItem *item;
381 const SDL_AudioDeviceItem *i;
384 SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
385 SDL_assert(name != NULL);
387 item = (SDL_AudioDeviceItem *) SDL_malloc(sizeof (SDL_AudioDeviceItem));
389 return SDL_OutOfMemory();
392 item->original_name = SDL_strdup(name);
393 if (!item->original_name) {
395 return SDL_OutOfMemory();
399 item->name = item->original_name;
400 item->handle = handle;
402 SDL_LockMutex(current_audio.detectionLock);
404 for (i = *devices; i != NULL; i = i->next) {
405 if (SDL_strcmp(name, i->original_name) == 0) {
406 dupenum = i->dupenum + 1;
407 break; /* stop at the highest-numbered dupe. */
412 const size_t len = SDL_strlen(name) + 16;
413 char *replacement = (char *) SDL_malloc(len);
415 SDL_UnlockMutex(current_audio.detectionLock);
416 SDL_free(item->original_name);
422 SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
423 item->dupenum = dupenum;
424 item->name = replacement;
427 item->next = *devices;
429 retval = (*devCount)++; /* !!! FIXME: this should be an atomic increment */
431 SDL_UnlockMutex(current_audio.detectionLock);
436 static SDL_INLINE int
437 add_capture_device(const char *name, void *handle)
439 SDL_assert(current_audio.impl.HasCaptureSupport);
440 return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
443 static SDL_INLINE int
444 add_output_device(const char *name, void *handle)
446 return add_audio_device(name, handle, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
450 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
452 SDL_AudioDeviceItem *item, *next;
453 for (item = *devices; item != NULL; item = next) {
455 if (item->handle != NULL) {
456 current_audio.impl.FreeDeviceHandle(item->handle);
458 /* these two pointers are the same if not a duplicate devname */
459 if (item->name != item->original_name) {
460 SDL_free(item->name);
462 SDL_free(item->original_name);
470 /* The audio backends call this when a new device is plugged in. */
472 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
474 const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
475 if (device_index != -1) {
476 /* Post the event, if desired */
477 if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
480 event.adevice.type = SDL_AUDIODEVICEADDED;
481 event.adevice.which = device_index;
482 event.adevice.iscapture = iscapture;
483 SDL_PushEvent(&event);
488 /* The audio backends call this when a currently-opened device is lost. */
489 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
491 SDL_assert(get_audio_device(device->id) == device);
493 if (!SDL_AtomicGet(&device->enabled)) {
494 return; /* don't report disconnects more than once. */
497 if (SDL_AtomicGet(&device->shutdown)) {
498 return; /* don't report disconnect if we're trying to close device. */
501 /* Ends the audio callback and mark the device as STOPPED, but the
502 app still needs to close the device to free resources. */
503 current_audio.impl.LockDevice(device);
504 SDL_AtomicSet(&device->enabled, 0);
505 current_audio.impl.UnlockDevice(device);
507 /* Post the event, if desired */
508 if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
511 event.adevice.type = SDL_AUDIODEVICEREMOVED;
512 event.adevice.which = device->id;
513 event.adevice.iscapture = device->iscapture ? 1 : 0;
514 SDL_PushEvent(&event);
519 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
521 SDL_AudioDeviceItem *item;
522 SDL_assert(handle != NULL);
523 for (item = devices; item != NULL; item = item->next) {
524 if (item->handle == handle) {
526 *removedFlag = SDL_TRUE;
532 /* The audio backends call this when a device is removed from the system. */
534 SDL_RemoveAudioDevice(const int iscapture, void *handle)
537 SDL_AudioDevice *device = NULL;
539 SDL_LockMutex(current_audio.detectionLock);
541 mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved);
543 mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved);
545 for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
547 device = open_devices[device_index];
548 if (device != NULL && device->handle == handle)
550 SDL_OpenedAudioDeviceDisconnected(device);
554 SDL_UnlockMutex(current_audio.detectionLock);
556 current_audio.impl.FreeDeviceHandle(handle);
561 /* buffer queueing support... */
564 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
566 /* this function always holds the mixer lock before being called. */
567 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
570 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
571 SDL_assert(!device->iscapture); /* this shouldn't ever happen, right?! */
572 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
574 dequeued = SDL_ReadFromDataQueue(device->buffer_queue, stream, len);
576 len -= (int) dequeued;
578 if (len > 0) { /* fill any remaining space in the stream with silence. */
579 SDL_assert(SDL_CountDataQueue(device->buffer_queue) == 0);
580 SDL_memset(stream, device->callbackspec.silence, len);
585 SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
587 /* this function always holds the mixer lock before being called. */
588 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
590 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
591 SDL_assert(device->iscapture); /* this shouldn't ever happen, right?! */
592 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
594 /* note that if this needs to allocate more space and run out of memory,
595 we have no choice but to quietly drop the data and hope it works out
596 later, but you probably have bigger problems in this case anyhow. */
597 SDL_WriteToDataQueue(device->buffer_queue, stream, len);
601 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *data, Uint32 len)
603 SDL_AudioDevice *device = get_audio_device(devid);
607 return -1; /* get_audio_device() will have set the error state */
608 } else if (device->iscapture) {
609 return SDL_SetError("This is a capture device, queueing not allowed");
610 } else if (device->callbackspec.callback != SDL_BufferQueueDrainCallback) {
611 return SDL_SetError("Audio device has a callback, queueing not allowed");
615 current_audio.impl.LockDevice(device);
616 rc = SDL_WriteToDataQueue(device->buffer_queue, data, len);
617 current_audio.impl.UnlockDevice(device);
624 SDL_DequeueAudio(SDL_AudioDeviceID devid, void *data, Uint32 len)
626 SDL_AudioDevice *device = get_audio_device(devid);
629 if ( (len == 0) || /* nothing to do? */
630 (!device) || /* called with bogus device id */
631 (!device->iscapture) || /* playback devices can't dequeue */
632 (device->callbackspec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
633 return 0; /* just report zero bytes dequeued. */
636 current_audio.impl.LockDevice(device);
637 rc = (Uint32) SDL_ReadFromDataQueue(device->buffer_queue, data, len);
638 current_audio.impl.UnlockDevice(device);
643 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
646 SDL_AudioDevice *device = get_audio_device(devid);
652 /* Nothing to do unless we're set up for queueing. */
653 if (device->callbackspec.callback == SDL_BufferQueueDrainCallback ||
654 device->callbackspec.callback == SDL_BufferQueueFillCallback)
656 current_audio.impl.LockDevice(device);
657 retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
658 current_audio.impl.UnlockDevice(device);
665 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
667 SDL_AudioDevice *device = get_audio_device(devid);
670 return; /* nothing to do. */
673 /* Blank out the device and release the mutex. Free it afterwards. */
674 current_audio.impl.LockDevice(device);
676 /* Keep up to two packets in the pool to reduce future malloc pressure. */
677 SDL_ClearDataQueue(device->buffer_queue, SDL_AUDIOBUFFERQUEUE_PACKETLEN * 2);
679 current_audio.impl.UnlockDevice(device);
683 /* The general mixing thread function */
685 SDL_RunAudio(void *devicep)
687 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
688 void *udata = device->callbackspec.userdata;
689 SDL_AudioCallback callback = device->callbackspec.callback;
693 SDL_assert(!device->iscapture);
695 #if SDL_AUDIO_DRIVER_ANDROID
697 /* Set thread priority to THREAD_PRIORITY_AUDIO */
698 extern void Android_JNI_AudioSetThreadPriority(int, int);
699 Android_JNI_AudioSetThreadPriority(device->iscapture, device->id);
702 /* The audio mixing is always a high priority thread */
703 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
706 /* Perform any thread setup */
707 device->threadid = SDL_ThreadID();
708 current_audio.impl.ThreadInit(device);
710 /* Loop, filling the audio buffers */
711 while (!SDL_AtomicGet(&device->shutdown)) {
712 current_audio.impl.BeginLoopIteration(device);
713 data_len = device->callbackspec.size;
715 /* Fill the current buffer with sound */
716 if (!device->stream && SDL_AtomicGet(&device->enabled)) {
717 SDL_assert(data_len == device->spec.size);
718 data = current_audio.impl.GetDeviceBuf(device);
720 /* if the device isn't enabled, we still write to the
721 work_buffer, so the app's callback will fire with
722 a regular frequency, in case they depend on that
723 for timing or progress. They can use hotplug
724 now to know if the device failed.
725 Streaming playback uses work_buffer, too. */
730 data = device->work_buffer;
733 /* !!! FIXME: this should be LockDevice. */
734 SDL_LockMutex(device->mixer_lock);
735 if (SDL_AtomicGet(&device->paused)) {
736 SDL_memset(data, device->callbackspec.silence, data_len);
738 callback(udata, data, data_len);
740 SDL_UnlockMutex(device->mixer_lock);
742 if (device->stream) {
743 /* Stream available audio to device, converting/resampling. */
744 /* if this fails...oh well. We'll play silence here. */
745 SDL_AudioStreamPut(device->stream, data, data_len);
747 while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->spec.size)) {
749 data = SDL_AtomicGet(&device->enabled) ? current_audio.impl.GetDeviceBuf(device) : NULL;
750 got = SDL_AudioStreamGet(device->stream, data ? data : device->work_buffer, device->spec.size);
751 SDL_assert((got < 0) || (got == device->spec.size));
753 if (data == NULL) { /* device is having issues... */
754 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
755 SDL_Delay(delay); /* wait for as long as this buffer would have played. Maybe device recovers later? */
757 if (got != device->spec.size) {
758 SDL_memset(data, device->spec.silence, device->spec.size);
760 current_audio.impl.PlayDevice(device);
761 current_audio.impl.WaitDevice(device);
764 } else if (data == device->work_buffer) {
765 /* nothing to do; pause like we queued a buffer to play. */
766 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
768 } else { /* writing directly to the device. */
769 /* queue this buffer and wait for it to finish playing. */
770 current_audio.impl.PlayDevice(device);
771 current_audio.impl.WaitDevice(device);
775 current_audio.impl.PrepareToClose(device);
777 /* Wait for the audio to drain. */
778 SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
780 current_audio.impl.ThreadDeinit(device);
785 /* !!! FIXME: this needs to deal with device spec changes. */
786 /* The general capture thread function */
788 SDL_CaptureAudio(void *devicep)
790 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
791 const int silence = (int) device->spec.silence;
792 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
793 const int data_len = device->spec.size;
795 void *udata = device->callbackspec.userdata;
796 SDL_AudioCallback callback = device->callbackspec.callback;
798 SDL_assert(device->iscapture);
800 #if SDL_AUDIO_DRIVER_ANDROID
802 /* Set thread priority to THREAD_PRIORITY_AUDIO */
803 extern void Android_JNI_AudioSetThreadPriority(int, int);
804 Android_JNI_AudioSetThreadPriority(device->iscapture, device->id);
807 /* The audio mixing is always a high priority thread */
808 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
811 /* Perform any thread setup */
812 device->threadid = SDL_ThreadID();
813 current_audio.impl.ThreadInit(device);
815 /* Loop, filling the audio buffers */
816 while (!SDL_AtomicGet(&device->shutdown)) {
820 current_audio.impl.BeginLoopIteration(device);
822 if (SDL_AtomicGet(&device->paused)) {
823 SDL_Delay(delay); /* just so we don't cook the CPU. */
824 if (device->stream) {
825 SDL_AudioStreamClear(device->stream);
827 current_audio.impl.FlushCapture(device); /* dump anything pending. */
831 /* Fill the current buffer with sound */
832 still_need = data_len;
834 /* Use the work_buffer to hold data read from the device. */
835 data = device->work_buffer;
836 SDL_assert(data != NULL);
840 /* We still read from the device when "paused" to keep the state sane,
841 and block when there isn't data so this thread isn't eating CPU.
842 But we don't process it further or call the app's callback. */
844 if (!SDL_AtomicGet(&device->enabled)) {
845 SDL_Delay(delay); /* try to keep callback firing at normal pace. */
847 while (still_need > 0) {
848 const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
849 SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */
853 } else { /* uhoh, device failed for some reason! */
854 SDL_OpenedAudioDeviceDisconnected(device);
860 if (still_need > 0) {
861 /* Keep any data we already read, silence the rest. */
862 SDL_memset(ptr, silence, still_need);
865 if (device->stream) {
866 /* if this fails...oh well. */
867 SDL_AudioStreamPut(device->stream, data, data_len);
869 while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->callbackspec.size)) {
870 const int got = SDL_AudioStreamGet(device->stream, device->work_buffer, device->callbackspec.size);
871 SDL_assert((got < 0) || (got == device->callbackspec.size));
872 if (got != device->callbackspec.size) {
873 SDL_memset(device->work_buffer, device->spec.silence, device->callbackspec.size);
876 /* !!! FIXME: this should be LockDevice. */
877 SDL_LockMutex(device->mixer_lock);
878 if (!SDL_AtomicGet(&device->paused)) {
879 callback(udata, device->work_buffer, device->callbackspec.size);
881 SDL_UnlockMutex(device->mixer_lock);
883 } else { /* feeding user callback directly without streaming. */
884 /* !!! FIXME: this should be LockDevice. */
885 SDL_LockMutex(device->mixer_lock);
886 if (!SDL_AtomicGet(&device->paused)) {
887 callback(udata, data, device->callbackspec.size);
889 SDL_UnlockMutex(device->mixer_lock);
893 current_audio.impl.FlushCapture(device);
895 current_audio.impl.ThreadDeinit(device);
901 static SDL_AudioFormat
902 SDL_ParseAudioFormat(const char *string)
904 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
905 CHECK_FMT_STRING(U8);
906 CHECK_FMT_STRING(S8);
907 CHECK_FMT_STRING(U16LSB);
908 CHECK_FMT_STRING(S16LSB);
909 CHECK_FMT_STRING(U16MSB);
910 CHECK_FMT_STRING(S16MSB);
911 CHECK_FMT_STRING(U16SYS);
912 CHECK_FMT_STRING(S16SYS);
913 CHECK_FMT_STRING(U16);
914 CHECK_FMT_STRING(S16);
915 CHECK_FMT_STRING(S32LSB);
916 CHECK_FMT_STRING(S32MSB);
917 CHECK_FMT_STRING(S32SYS);
918 CHECK_FMT_STRING(S32);
919 CHECK_FMT_STRING(F32LSB);
920 CHECK_FMT_STRING(F32MSB);
921 CHECK_FMT_STRING(F32SYS);
922 CHECK_FMT_STRING(F32);
923 #undef CHECK_FMT_STRING
928 SDL_GetNumAudioDrivers(void)
930 return SDL_arraysize(bootstrap) - 1;
934 SDL_GetAudioDriver(int index)
936 if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
937 return bootstrap[index]->name;
943 SDL_AudioInit(const char *driver_name)
947 int tried_to_init = 0;
949 if (SDL_WasInit(SDL_INIT_AUDIO)) {
950 SDL_AudioQuit(); /* shutdown driver if already running. */
953 SDL_zero(current_audio);
954 SDL_zeroa(open_devices);
956 /* Select the proper audio driver */
957 if (driver_name == NULL) {
958 driver_name = SDL_getenv("SDL_AUDIODRIVER");
961 for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
962 /* make sure we should even try this driver before doing so... */
963 const AudioBootStrap *backend = bootstrap[i];
964 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
965 (!driver_name && backend->demand_only)) {
970 SDL_zero(current_audio);
971 current_audio.name = backend->name;
972 current_audio.desc = backend->desc;
973 initialized = backend->init(¤t_audio.impl);
977 /* specific drivers will set the error message if they fail... */
978 if (!tried_to_init) {
980 SDL_SetError("Audio target '%s' not available", driver_name);
982 SDL_SetError("No available audio device");
986 SDL_zero(current_audio);
987 return -1; /* No driver was available, so fail. */
990 current_audio.detectionLock = SDL_CreateMutex();
992 finish_audio_entry_points_init();
994 /* Make sure we have a list of devices available at startup. */
995 current_audio.impl.DetectDevices();
997 #ifdef HAVE_LIBSAMPLERATE_H
1005 * Get the current audio driver name
1008 SDL_GetCurrentAudioDriver()
1010 return current_audio.name;
1013 /* Clean out devices that we've removed but had to keep around for stability. */
1015 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
1017 SDL_AudioDeviceItem *item = *devices;
1018 SDL_AudioDeviceItem *prev = NULL;
1022 SDL_AudioDeviceItem *next = item->next;
1023 if (item->handle != NULL) {
1032 /* these two pointers are the same if not a duplicate devname */
1033 if (item->name != item->original_name) {
1034 SDL_free(item->name);
1036 SDL_free(item->original_name);
1043 *removedFlag = SDL_FALSE;
1048 SDL_GetNumAudioDevices(int iscapture)
1052 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1056 SDL_LockMutex(current_audio.detectionLock);
1057 if (iscapture && current_audio.captureDevicesRemoved) {
1058 clean_out_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount, ¤t_audio.captureDevicesRemoved);
1061 if (!iscapture && current_audio.outputDevicesRemoved) {
1062 clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
1065 retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
1066 SDL_UnlockMutex(current_audio.detectionLock);
1073 SDL_GetAudioDeviceName(int index, int iscapture)
1075 const char *retval = NULL;
1077 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1078 SDL_SetError("Audio subsystem is not initialized");
1082 if (iscapture && !current_audio.impl.HasCaptureSupport) {
1083 SDL_SetError("No capture support");
1088 SDL_AudioDeviceItem *item;
1091 SDL_LockMutex(current_audio.detectionLock);
1092 item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
1093 i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
1095 for (i--; i > index; i--, item = item->next) {
1096 SDL_assert(item != NULL);
1098 SDL_assert(item != NULL);
1099 retval = item->name;
1101 SDL_UnlockMutex(current_audio.detectionLock);
1104 if (retval == NULL) {
1105 SDL_SetError("No such device");
1113 close_audio_device(SDL_AudioDevice * device)
1119 /* make sure the device is paused before we do anything else, so the
1120 audio callback definitely won't fire again. */
1121 current_audio.impl.LockDevice(device);
1122 SDL_AtomicSet(&device->paused, 1);
1123 SDL_AtomicSet(&device->shutdown, 1);
1124 SDL_AtomicSet(&device->enabled, 0);
1125 current_audio.impl.UnlockDevice(device);
1127 if (device->thread != NULL) {
1128 SDL_WaitThread(device->thread, NULL);
1130 if (device->mixer_lock != NULL) {
1131 SDL_DestroyMutex(device->mixer_lock);
1134 SDL_free(device->work_buffer);
1135 SDL_FreeAudioStream(device->stream);
1137 if (device->id > 0) {
1138 SDL_AudioDevice *opendev = open_devices[device->id - 1];
1139 SDL_assert((opendev == device) || (opendev == NULL));
1140 if (opendev == device) {
1141 open_devices[device->id - 1] = NULL;
1145 if (device->hidden != NULL) {
1146 current_audio.impl.CloseDevice(device);
1149 SDL_FreeDataQueue(device->buffer_queue);
1156 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
1157 * Fills in a sanitized copy in (prepared).
1158 * Returns non-zero if okay, zero on fatal parameters in (orig).
1161 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
1163 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
1165 if (orig->freq == 0) {
1166 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
1167 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
1168 prepared->freq = 22050; /* a reasonable default */
1172 if (orig->format == 0) {
1173 const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
1174 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
1175 prepared->format = AUDIO_S16; /* a reasonable default */
1179 switch (orig->channels) {
1181 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
1182 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
1183 prepared->channels = 2; /* a reasonable default */
1188 case 2: /* Stereo */
1189 case 4: /* Quadrophonic */
1190 case 6: /* 5.1 surround */
1191 case 8: /* 7.1 surround */
1194 SDL_SetError("Unsupported number of audio channels.");
1198 if (orig->samples == 0) {
1199 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
1200 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
1201 /* Pick a default of ~46 ms at desired frequency */
1202 /* !!! FIXME: remove this when the non-Po2 resampling is in. */
1203 const int samples = (prepared->freq / 1000) * 46;
1205 while (power2 < samples) {
1208 prepared->samples = power2;
1212 /* Calculate the silence and size of the audio specification */
1213 SDL_CalculateAudioSpec(prepared);
1218 static SDL_AudioDeviceID
1219 open_audio_device(const char *devname, int iscapture,
1220 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1221 int allowed_changes, int min_id)
1223 const SDL_bool is_internal_thread = (desired->callback == NULL);
1224 SDL_AudioDeviceID id = 0;
1225 SDL_AudioSpec _obtained;
1226 SDL_AudioDevice *device;
1227 SDL_bool build_stream;
1228 void *handle = NULL;
1231 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1232 SDL_SetError("Audio subsystem is not initialized");
1236 if (iscapture && !current_audio.impl.HasCaptureSupport) {
1237 SDL_SetError("No capture support");
1241 /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
1242 /* Find an available device ID... */
1243 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
1244 if (open_devices[id] == NULL) {
1249 if (id == SDL_arraysize(open_devices)) {
1250 SDL_SetError("Too many open audio devices");
1255 obtained = &_obtained;
1257 if (!prepare_audiospec(desired, obtained)) {
1261 /* If app doesn't care about a specific device, let the user override. */
1262 if (devname == NULL) {
1263 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1267 * Catch device names at the high level for the simple case...
1268 * This lets us have a basic "device enumeration" for systems that
1269 * don't have multiple devices, but makes sure the device name is
1270 * always NULL when it hits the low level.
1272 * Also make sure that the simple case prevents multiple simultaneous
1273 * opens of the default system device.
1276 if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
1277 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1278 SDL_SetError("No such device");
1283 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1284 if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1285 SDL_SetError("Audio device already open");
1289 } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1290 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1291 SDL_SetError("No such device");
1296 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1297 if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1298 SDL_SetError("Audio device already open");
1302 } else if (devname != NULL) {
1303 /* if the app specifies an exact string, we can pass the backend
1304 an actual device handle thingey, which saves them the effort of
1305 figuring out what device this was (such as, reenumerating
1306 everything again to find the matching human-readable name).
1307 It might still need to open a device based on the string for,
1308 say, a network audio server, but this optimizes some cases. */
1309 SDL_AudioDeviceItem *item;
1310 SDL_LockMutex(current_audio.detectionLock);
1311 for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1312 if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1313 handle = item->handle;
1317 SDL_UnlockMutex(current_audio.detectionLock);
1320 if (!current_audio.impl.AllowsArbitraryDeviceNames) {
1321 /* has to be in our device list, or the default device. */
1322 if ((handle == NULL) && (devname != NULL)) {
1323 SDL_SetError("No such device.");
1328 device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice));
1329 if (device == NULL) {
1333 device->id = id + 1;
1334 device->spec = *obtained;
1335 device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
1336 device->handle = handle;
1338 SDL_AtomicSet(&device->shutdown, 0); /* just in case. */
1339 SDL_AtomicSet(&device->paused, 1);
1340 SDL_AtomicSet(&device->enabled, 1);
1342 /* Create a mutex for locking the sound buffers */
1343 if (!current_audio.impl.SkipMixerLock) {
1344 device->mixer_lock = SDL_CreateMutex();
1345 if (device->mixer_lock == NULL) {
1346 close_audio_device(device);
1347 SDL_SetError("Couldn't create mixer lock");
1352 if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1353 close_audio_device(device);
1357 /* if your target really doesn't need it, set it to 0x1 or something. */
1358 /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
1359 SDL_assert(device->hidden != NULL);
1361 /* See if we need to do any conversion */
1362 build_stream = SDL_FALSE;
1363 if (obtained->freq != device->spec.freq) {
1364 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1365 obtained->freq = device->spec.freq;
1367 build_stream = SDL_TRUE;
1370 if (obtained->format != device->spec.format) {
1371 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1372 obtained->format = device->spec.format;
1374 build_stream = SDL_TRUE;
1377 if (obtained->channels != device->spec.channels) {
1378 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1379 obtained->channels = device->spec.channels;
1381 build_stream = SDL_TRUE;
1384 if (device->spec.samples != obtained->samples) {
1385 if (allowed_changes & SDL_AUDIO_ALLOW_SAMPLES_CHANGE) {
1386 obtained->samples = device->spec.samples;
1388 build_stream = SDL_TRUE;
1392 SDL_CalculateAudioSpec(obtained); /* recalc after possible changes. */
1394 device->callbackspec = *obtained;
1398 device->stream = SDL_NewAudioStream(device->spec.format,
1399 device->spec.channels, device->spec.freq,
1400 obtained->format, obtained->channels, obtained->freq);
1402 device->stream = SDL_NewAudioStream(obtained->format, obtained->channels,
1403 obtained->freq, device->spec.format,
1404 device->spec.channels, device->spec.freq);
1407 if (!device->stream) {
1408 close_audio_device(device);
1413 if (device->spec.callback == NULL) { /* use buffer queueing? */
1414 /* pool a few packets to start. Enough for two callbacks. */
1415 device->buffer_queue = SDL_NewDataQueue(SDL_AUDIOBUFFERQUEUE_PACKETLEN, obtained->size * 2);
1416 if (!device->buffer_queue) {
1417 close_audio_device(device);
1418 SDL_SetError("Couldn't create audio buffer queue");
1421 device->callbackspec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
1422 device->callbackspec.userdata = device;
1425 /* Allocate a scratch audio buffer */
1426 device->work_buffer_len = build_stream ? device->callbackspec.size : 0;
1427 if (device->spec.size > device->work_buffer_len) {
1428 device->work_buffer_len = device->spec.size;
1430 SDL_assert(device->work_buffer_len > 0);
1432 device->work_buffer = (Uint8 *) SDL_malloc(device->work_buffer_len);
1433 if (device->work_buffer == NULL) {
1434 close_audio_device(device);
1439 open_devices[id] = device; /* add it to our list of open devices. */
1441 /* Start the audio thread if necessary */
1442 if (!current_audio.impl.ProvidesOwnCallbackThread) {
1443 /* Start the audio thread */
1444 /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
1445 /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
1446 const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
1447 char threadname[64];
1449 SDL_snprintf(threadname, sizeof (threadname), "SDLAudio%c%d", (iscapture) ? 'C' : 'P', (int) device->id);
1450 device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
1452 if (device->thread == NULL) {
1453 close_audio_device(device);
1454 SDL_SetError("Couldn't create audio thread");
1464 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
1466 SDL_AudioDeviceID id = 0;
1468 /* Start up the audio driver, if necessary. This is legacy behaviour! */
1469 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1470 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1475 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1476 if (open_devices[0] != NULL) {
1477 SDL_SetError("Audio device is already opened");
1482 id = open_audio_device(NULL, 0, desired, obtained,
1483 SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1485 SDL_AudioSpec _obtained;
1486 SDL_zero(_obtained);
1487 id = open_audio_device(NULL, 0, desired, &_obtained, 0, 1);
1488 /* On successful open, copy calculated values into 'desired'. */
1490 desired->size = _obtained.size;
1491 desired->silence = _obtained.silence;
1495 SDL_assert((id == 0) || (id == 1));
1496 return (id == 0) ? -1 : 0;
1500 SDL_OpenAudioDevice(const char *device, int iscapture,
1501 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1502 int allowed_changes)
1504 return open_audio_device(device, iscapture, desired, obtained,
1505 allowed_changes, 2);
1509 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1511 SDL_AudioDevice *device = get_audio_device(devid);
1512 SDL_AudioStatus status = SDL_AUDIO_STOPPED;
1513 if (device && SDL_AtomicGet(&device->enabled)) {
1514 if (SDL_AtomicGet(&device->paused)) {
1515 status = SDL_AUDIO_PAUSED;
1517 status = SDL_AUDIO_PLAYING;
1525 SDL_GetAudioStatus(void)
1527 return SDL_GetAudioDeviceStatus(1);
1531 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
1533 SDL_AudioDevice *device = get_audio_device(devid);
1535 current_audio.impl.LockDevice(device);
1536 SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
1537 current_audio.impl.UnlockDevice(device);
1542 SDL_PauseAudio(int pause_on)
1544 SDL_PauseAudioDevice(1, pause_on);
1549 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
1551 /* Obtain a lock on the mixing buffers */
1552 SDL_AudioDevice *device = get_audio_device(devid);
1554 current_audio.impl.LockDevice(device);
1561 SDL_LockAudioDevice(1);
1565 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
1567 /* Obtain a lock on the mixing buffers */
1568 SDL_AudioDevice *device = get_audio_device(devid);
1570 current_audio.impl.UnlockDevice(device);
1575 SDL_UnlockAudio(void)
1577 SDL_UnlockAudioDevice(1);
1581 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
1583 close_audio_device(get_audio_device(devid));
1587 SDL_CloseAudio(void)
1589 SDL_CloseAudioDevice(1);
1595 SDL_AudioDeviceID i;
1597 if (!current_audio.name) { /* not initialized?! */
1601 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1602 close_audio_device(open_devices[i]);
1605 free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
1606 free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
1608 /* Free the driver data */
1609 current_audio.impl.Deinitialize();
1611 SDL_DestroyMutex(current_audio.detectionLock);
1613 SDL_zero(current_audio);
1614 SDL_zeroa(open_devices);
1616 #ifdef HAVE_LIBSAMPLERATE_H
1617 UnloadLibSampleRate();
1620 SDL_FreeResampleFilter();
1623 #define NUM_FORMATS 10
1624 static int format_idx;
1625 static int format_idx_sub;
1626 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
1627 {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1628 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1629 {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1630 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1631 {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
1632 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1633 {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
1634 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1635 {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
1636 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1637 {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
1638 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1639 {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
1640 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1641 {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
1642 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1643 {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
1644 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1645 {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
1646 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1650 SDL_FirstAudioFormat(SDL_AudioFormat format)
1652 for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
1653 if (format_list[format_idx][0] == format) {
1658 return SDL_NextAudioFormat();
1662 SDL_NextAudioFormat(void)
1664 if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1667 return format_list[format_idx][format_idx_sub++];
1671 SDL_SilenceValueForFormat(const SDL_AudioFormat format)
1674 /* !!! FIXME: 0x80 isn't perfect for U16, but we can't fit 0x8000 in a
1675 !!! FIXME: byte for memset() use. This is actually 0.1953 percent
1676 !!! FIXME: off from silence. Maybe just don't use U16. */
1689 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
1691 spec->silence = SDL_SilenceValueForFormat(spec->format);
1692 spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
1693 spec->size *= spec->channels;
1694 spec->size *= spec->samples;
1699 * Moved here from SDL_mixer.c, since it relies on internals of an opened
1700 * audio device (and is deprecated, by the way!).
1703 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1705 /* Mix the user-level audio format */
1706 SDL_AudioDevice *device = get_audio_device(1);
1707 if (device != NULL) {
1708 SDL_MixAudioFormat(dst, src, device->callbackspec.format, len, volume);
1712 /* vi: set ts=4 sw=4 expandtab: */