SDL 2.0
SDL_audio.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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_sysaudio.h"
29#include "../thread/SDL_systhread.h"
30
31#define _THIS SDL_AudioDevice *_this
32
35
36/* Available audio drivers */
37static const AudioBootStrap *const bootstrap[] = {
38#if SDL_AUDIO_DRIVER_PULSEAUDIO
40#endif
41#if SDL_AUDIO_DRIVER_ALSA
43#endif
44#if SDL_AUDIO_DRIVER_SNDIO
46#endif
47#if SDL_AUDIO_DRIVER_NETBSD
49#endif
50#if SDL_AUDIO_DRIVER_OSS
52#endif
53#if SDL_AUDIO_DRIVER_QSA
55#endif
56#if SDL_AUDIO_DRIVER_SUNAUDIO
58#endif
59#if SDL_AUDIO_DRIVER_ARTS
61#endif
62#if SDL_AUDIO_DRIVER_ESD
64#endif
65#if SDL_AUDIO_DRIVER_NACL
67#endif
68#if SDL_AUDIO_DRIVER_NAS
70#endif
71#if SDL_AUDIO_DRIVER_WASAPI
73#endif
74#if SDL_AUDIO_DRIVER_DSOUND
76#endif
77#if SDL_AUDIO_DRIVER_WINMM
79#endif
80#if SDL_AUDIO_DRIVER_PAUDIO
82#endif
83#if SDL_AUDIO_DRIVER_HAIKU
85#endif
86#if SDL_AUDIO_DRIVER_COREAUDIO
88#endif
89#if SDL_AUDIO_DRIVER_FUSIONSOUND
91#endif
92#if SDL_AUDIO_DRIVER_OPENSLES
94#endif
95#if SDL_AUDIO_DRIVER_ANDROID
97#endif
98#if SDL_AUDIO_DRIVER_PSP
100#endif
101#if SDL_AUDIO_DRIVER_EMSCRIPTEN
103#endif
104#if SDL_AUDIO_DRIVER_JACK
106#endif
107#if SDL_AUDIO_DRIVER_DISK
109#endif
110#if SDL_AUDIO_DRIVER_DUMMY
112#endif
113 NULL
114};
115
116
117#ifdef HAVE_LIBSAMPLERATE_H
118#ifdef SDL_LIBSAMPLERATE_DYNAMIC
119static void *SRC_lib = NULL;
120#endif
121SDL_bool SRC_available = SDL_FALSE;
122int SRC_converter = 0;
123SRC_STATE* (*SRC_src_new)(int converter_type, int channels, int *error) = NULL;
124int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data) = NULL;
125int (*SRC_src_reset)(SRC_STATE *state) = NULL;
126SRC_STATE* (*SRC_src_delete)(SRC_STATE *state) = NULL;
127const char* (*SRC_src_strerror)(int error) = NULL;
128
129static SDL_bool
130LoadLibSampleRate(void)
131{
133
134 SRC_available = SDL_FALSE;
135 SRC_converter = 0;
136
137 if (!hint || *hint == '0' || SDL_strcasecmp(hint, "default") == 0) {
138 return SDL_FALSE; /* don't load anything. */
139 } else if (*hint == '1' || SDL_strcasecmp(hint, "fast") == 0) {
140 SRC_converter = SRC_SINC_FASTEST;
141 } else if (*hint == '2' || SDL_strcasecmp(hint, "medium") == 0) {
142 SRC_converter = SRC_SINC_MEDIUM_QUALITY;
143 } else if (*hint == '3' || SDL_strcasecmp(hint, "best") == 0) {
144 SRC_converter = SRC_SINC_BEST_QUALITY;
145 } else {
146 return SDL_FALSE; /* treat it like "default", don't load anything. */
147 }
148
149#ifdef SDL_LIBSAMPLERATE_DYNAMIC
150 SDL_assert(SRC_lib == NULL);
152 if (!SRC_lib) {
154 return SDL_FALSE;
155 }
156
157 SRC_src_new = (SRC_STATE* (*)(int converter_type, int channels, int *error))SDL_LoadFunction(SRC_lib, "src_new");
158 SRC_src_process = (int (*)(SRC_STATE *state, SRC_DATA *data))SDL_LoadFunction(SRC_lib, "src_process");
159 SRC_src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(SRC_lib, "src_reset");
160 SRC_src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(SRC_lib, "src_delete");
161 SRC_src_strerror = (const char* (*)(int error))SDL_LoadFunction(SRC_lib, "src_strerror");
162
163 if (!SRC_src_new || !SRC_src_process || !SRC_src_reset || !SRC_src_delete || !SRC_src_strerror) {
164 SDL_UnloadObject(SRC_lib);
165 SRC_lib = NULL;
166 return SDL_FALSE;
167 }
168#else
169 SRC_src_new = src_new;
170 SRC_src_process = src_process;
171 SRC_src_reset = src_reset;
172 SRC_src_delete = src_delete;
173 SRC_src_strerror = src_strerror;
174#endif
175
176 SRC_available = SDL_TRUE;
177 return SDL_TRUE;
178}
179
180static void
181UnloadLibSampleRate(void)
182{
183#ifdef SDL_LIBSAMPLERATE_DYNAMIC
184 if (SRC_lib != NULL) {
185 SDL_UnloadObject(SRC_lib);
186 }
187 SRC_lib = NULL;
188#endif
189
190 SRC_available = SDL_FALSE;
191 SRC_src_new = NULL;
192 SRC_src_process = NULL;
193 SRC_src_reset = NULL;
194 SRC_src_delete = NULL;
195 SRC_src_strerror = NULL;
196}
197#endif
198
199static SDL_AudioDevice *
201{
202 id--;
203 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
204 SDL_SetError("Invalid audio device ID");
205 return NULL;
206 }
207
208 return open_devices[id];
209}
210
211
212/* stubs for audio drivers that don't need a specific entry point... */
213static void
215{
216 /* you have to write your own implementation if these assertions fail. */
219
220 SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
222 SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
223 }
224}
225
226static void
228{ /* no-op. */
229}
230
231static void
233{ /* no-op. */
234}
235
236static void
238{ /* no-op. */
239}
240
241static void
243{ /* no-op. */
244}
245
246static void
248{ /* no-op. */
249}
250
251static Uint8 *
253{
254 return NULL;
255}
256
257static int
259{
260 return -1; /* just fail immediately. */
261}
262
263static void
265{ /* no-op. */
266}
267
268static void
270{ /* no-op. */
271}
272
273static void
275{ /* no-op. */
276}
277
278static void
280{ /* no-op. */
281}
282
283static void
285{ /* no-op. */
286}
287
288
289static int
290SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
291{
292 return SDL_Unsupported();
293}
294
295static SDL_INLINE SDL_bool
297{
298 /* The device thread locks the same mutex, but not through the public API.
299 This check is in case the application, in the audio callback,
300 tries to lock the thread that we've already locked from the
301 device thread...just in case we only have non-recursive mutexes. */
302 if (device->thread && (SDL_ThreadID() == device->threadid)) {
303 return SDL_TRUE;
304 }
305
306 return SDL_FALSE;
307}
308
309static void
311{
313 SDL_LockMutex(device->mixer_lock);
314 }
315}
316
317static void
319{
321 SDL_UnlockMutex(device->mixer_lock);
322 }
323}
324
325static void
327{
328}
329
330static void
332{
333 /*
334 * Fill in stub functions for unused driver entry points. This lets us
335 * blindly call them without having to check for validity first.
336 */
337
341 }
344 }
345 }
346
347#define FILL_STUB(x) \
348 if (current_audio.impl.x == NULL) { \
349 current_audio.impl.x = SDL_Audio##x##_Default; \
350 }
351 FILL_STUB(DetectDevices);
352 FILL_STUB(OpenDevice);
353 FILL_STUB(ThreadInit);
354 FILL_STUB(ThreadDeinit);
355 FILL_STUB(BeginLoopIteration);
356 FILL_STUB(WaitDevice);
357 FILL_STUB(PlayDevice);
358 FILL_STUB(GetDeviceBuf);
359 FILL_STUB(CaptureFromDevice);
360 FILL_STUB(FlushCapture);
361 FILL_STUB(PrepareToClose);
362 FILL_STUB(CloseDevice);
363 FILL_STUB(LockDevice);
364 FILL_STUB(UnlockDevice);
365 FILL_STUB(FreeDeviceHandle);
366 FILL_STUB(Deinitialize);
367#undef FILL_STUB
368}
369
370
371/* device hotplug support... */
372
373static int
374add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
375{
376 int retval = -1;
378 const SDL_AudioDeviceItem *i;
379 int dupenum = 0;
380
381 SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
382 SDL_assert(name != NULL);
383
385 if (!item) {
386 return SDL_OutOfMemory();
387 }
388
390 if (!item->original_name) {
391 SDL_free(item);
392 return SDL_OutOfMemory();
393 }
394
395 item->dupenum = 0;
396 item->name = item->original_name;
397 item->handle = handle;
398
400
401 for (i = *devices; i != NULL; i = i->next) {
402 if (SDL_strcmp(name, i->original_name) == 0) {
403 dupenum = i->dupenum + 1;
404 break; /* stop at the highest-numbered dupe. */
405 }
406 }
407
408 if (dupenum) {
409 const size_t len = SDL_strlen(name) + 16;
410 char *replacement = (char *) SDL_malloc(len);
411 if (!replacement) {
413 SDL_free(item->original_name);
414 SDL_free(item);
416 return -1;
417 }
418
419 SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
420 item->dupenum = dupenum;
421 item->name = replacement;
422 }
423
424 item->next = *devices;
425 *devices = item;
426 retval = (*devCount)++; /* !!! FIXME: this should be an atomic increment */
427
429
430 return retval;
431}
432
433static SDL_INLINE int
434add_capture_device(const char *name, void *handle)
435{
438}
439
440static SDL_INLINE int
441add_output_device(const char *name, void *handle)
442{
444}
445
446static void
448{
449 SDL_AudioDeviceItem *item, *next;
450 for (item = *devices; item != NULL; item = next) {
451 next = item->next;
452 if (item->handle != NULL) {
454 }
455 /* these two pointers are the same if not a duplicate devname */
456 if (item->name != item->original_name) {
457 SDL_free(item->name);
458 }
459 SDL_free(item->original_name);
460 SDL_free(item);
461 }
462 *devices = NULL;
463 *devCount = 0;
464}
465
466
467/* The audio backends call this when a new device is plugged in. */
468void
469SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
470{
471 const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
472 if (device_index != -1) {
473 /* Post the event, if desired */
477 event.adevice.type = SDL_AUDIODEVICEADDED;
478 event.adevice.which = device_index;
479 event.adevice.iscapture = iscapture;
481 }
482 }
483}
484
485/* The audio backends call this when a currently-opened device is lost. */
487{
489
490 if (!SDL_AtomicGet(&device->enabled)) {
491 return; /* don't report disconnects more than once. */
492 }
493
494 if (SDL_AtomicGet(&device->shutdown)) {
495 return; /* don't report disconnect if we're trying to close device. */
496 }
497
498 /* Ends the audio callback and mark the device as STOPPED, but the
499 app still needs to close the device to free resources. */
501 SDL_AtomicSet(&device->enabled, 0);
503
504 /* Post the event, if desired */
508 event.adevice.type = SDL_AUDIODEVICEREMOVED;
509 event.adevice.which = device->id;
510 event.adevice.iscapture = device->iscapture ? 1 : 0;
512 }
513}
514
515static void
517{
520 for (item = devices; item != NULL; item = item->next) {
521 if (item->handle == handle) {
522 item->handle = NULL;
523 *removedFlag = SDL_TRUE;
524 return;
525 }
526 }
527}
528
529/* The audio backends call this when a device is removed from the system. */
530void
531SDL_RemoveAudioDevice(const int iscapture, void *handle)
532{
533 int device_index;
535
537 if (iscapture) {
539 } else {
541 }
542 for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
543 {
544 device = open_devices[device_index];
545 if (device != NULL && device->handle == handle)
546 {
548 break;
549 }
550 }
552
554}
555
556
557
558/* buffer queueing support... */
559
560static void SDLCALL
562{
563 /* this function always holds the mixer lock before being called. */
564 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
565 size_t dequeued;
566
567 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
568 SDL_assert(!device->iscapture); /* this shouldn't ever happen, right?! */
569 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
570
571 dequeued = SDL_ReadFromDataQueue(device->buffer_queue, stream, len);
572 stream += dequeued;
573 len -= (int) dequeued;
574
575 if (len > 0) { /* fill any remaining space in the stream with silence. */
576 SDL_assert(SDL_CountDataQueue(device->buffer_queue) == 0);
577 SDL_memset(stream, device->spec.silence, len);
578 }
579}
580
581static void SDLCALL
583{
584 /* this function always holds the mixer lock before being called. */
585 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
586
587 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
588 SDL_assert(device->iscapture); /* this shouldn't ever happen, right?! */
589 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
590
591 /* note that if this needs to allocate more space and run out of memory,
592 we have no choice but to quietly drop the data and hope it works out
593 later, but you probably have bigger problems in this case anyhow. */
594 SDL_WriteToDataQueue(device->buffer_queue, stream, len);
595}
596
597int
599{
601 int rc = 0;
602
603 if (!device) {
604 return -1; /* get_audio_device() will have set the error state */
605 } else if (device->iscapture) {
606 return SDL_SetError("This is a capture device, queueing not allowed");
607 } else if (device->callbackspec.callback != SDL_BufferQueueDrainCallback) {
608 return SDL_SetError("Audio device has a callback, queueing not allowed");
609 }
610
611 if (len > 0) {
613 rc = SDL_WriteToDataQueue(device->buffer_queue, data, len);
615 }
616
617 return rc;
618}
619
620Uint32
622{
624 Uint32 rc;
625
626 if ( (len == 0) || /* nothing to do? */
627 (!device) || /* called with bogus device id */
628 (!device->iscapture) || /* playback devices can't dequeue */
629 (device->callbackspec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
630 return 0; /* just report zero bytes dequeued. */
631 }
632
634 rc = (Uint32) SDL_ReadFromDataQueue(device->buffer_queue, data, len);
636 return rc;
637}
638
639Uint32
641{
642 Uint32 retval = 0;
644
645 if (!device) {
646 return 0;
647 }
648
649 /* Nothing to do unless we're set up for queueing. */
650 if (device->callbackspec.callback == SDL_BufferQueueDrainCallback ||
651 device->callbackspec.callback == SDL_BufferQueueFillCallback)
652 {
654 retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
656 }
657
658 return retval;
659}
660
661void
663{
665
666 if (!device) {
667 return; /* nothing to do. */
668 }
669
670 /* Blank out the device and release the mutex. Free it afterwards. */
672
673 /* Keep up to two packets in the pool to reduce future malloc pressure. */
675
677}
678
679
680/* The general mixing thread function */
681static int SDLCALL
682SDL_RunAudio(void *devicep)
683{
685 void *udata = device->callbackspec.userdata;
686 SDL_AudioCallback callback = device->callbackspec.callback;
687 int data_len = 0;
688 Uint8 *data;
689
690 SDL_assert(!device->iscapture);
691
692#if SDL_AUDIO_DRIVER_ANDROID
693 {
694 /* Set thread priority to THREAD_PRIORITY_AUDIO */
695 extern void Android_JNI_AudioSetThreadPriority(int, int);
697 }
698#else
699 /* The audio mixing is always a high priority thread */
701#endif
702
703 /* Perform any thread setup */
704 device->threadid = SDL_ThreadID();
706
707 /* Loop, filling the audio buffers */
708 while (!SDL_AtomicGet(&device->shutdown)) {
710 data_len = device->callbackspec.size;
711
712 /* Fill the current buffer with sound */
713 if (!device->stream && SDL_AtomicGet(&device->enabled)) {
714 SDL_assert(data_len == device->spec.size);
716 } else {
717 /* if the device isn't enabled, we still write to the
718 work_buffer, so the app's callback will fire with
719 a regular frequency, in case they depend on that
720 for timing or progress. They can use hotplug
721 now to know if the device failed.
722 Streaming playback uses work_buffer, too. */
723 data = NULL;
724 }
725
726 if (data == NULL) {
727 data = device->work_buffer;
728 }
729
730 /* !!! FIXME: this should be LockDevice. */
731 SDL_LockMutex(device->mixer_lock);
732 if (SDL_AtomicGet(&device->paused)) {
733 SDL_memset(data, device->spec.silence, data_len);
734 } else {
735 callback(udata, data, data_len);
736 }
737 SDL_UnlockMutex(device->mixer_lock);
738
739 if (device->stream) {
740 /* Stream available audio to device, converting/resampling. */
741 /* if this fails...oh well. We'll play silence here. */
742 SDL_AudioStreamPut(device->stream, data, data_len);
743
744 while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->spec.size)) {
745 int got;
747 got = SDL_AudioStreamGet(device->stream, data ? data : device->work_buffer, device->spec.size);
748 SDL_assert((got < 0) || (got == device->spec.size));
749
750 if (data == NULL) { /* device is having issues... */
751 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
752 SDL_Delay(delay); /* wait for as long as this buffer would have played. Maybe device recovers later? */
753 } else {
754 if (got != device->spec.size) {
755 SDL_memset(data, device->spec.silence, device->spec.size);
756 }
759 }
760 }
761 } else if (data == device->work_buffer) {
762 /* nothing to do; pause like we queued a buffer to play. */
763 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
764 SDL_Delay(delay);
765 } else { /* writing directly to the device. */
766 /* queue this buffer and wait for it to finish playing. */
769 }
770 }
771
773
774 /* Wait for the audio to drain. */
775 SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
776
778
779 return 0;
780}
781
782/* !!! FIXME: this needs to deal with device spec changes. */
783/* The general capture thread function */
784static int SDLCALL
785SDL_CaptureAudio(void *devicep)
786{
788 const int silence = (int) device->spec.silence;
789 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
790 const int data_len = device->spec.size;
791 Uint8 *data;
792 void *udata = device->callbackspec.userdata;
793 SDL_AudioCallback callback = device->callbackspec.callback;
794
795 SDL_assert(device->iscapture);
796
797#if SDL_AUDIO_DRIVER_ANDROID
798 {
799 /* Set thread priority to THREAD_PRIORITY_AUDIO */
800 extern void Android_JNI_AudioSetThreadPriority(int, int);
802 }
803#else
804 /* The audio mixing is always a high priority thread */
806#endif
807
808 /* Perform any thread setup */
809 device->threadid = SDL_ThreadID();
811
812 /* Loop, filling the audio buffers */
813 while (!SDL_AtomicGet(&device->shutdown)) {
814 int still_need;
815 Uint8 *ptr;
816
818
819 if (SDL_AtomicGet(&device->paused)) {
820 SDL_Delay(delay); /* just so we don't cook the CPU. */
821 if (device->stream) {
823 }
824 current_audio.impl.FlushCapture(device); /* dump anything pending. */
825 continue;
826 }
827
828 /* Fill the current buffer with sound */
829 still_need = data_len;
830
831 /* Use the work_buffer to hold data read from the device. */
832 data = device->work_buffer;
833 SDL_assert(data != NULL);
834
835 ptr = data;
836
837 /* We still read from the device when "paused" to keep the state sane,
838 and block when there isn't data so this thread isn't eating CPU.
839 But we don't process it further or call the app's callback. */
840
841 if (!SDL_AtomicGet(&device->enabled)) {
842 SDL_Delay(delay); /* try to keep callback firing at normal pace. */
843 } else {
844 while (still_need > 0) {
845 const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
846 SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */
847 if (rc > 0) {
848 still_need -= rc;
849 ptr += rc;
850 } else { /* uhoh, device failed for some reason! */
852 break;
853 }
854 }
855 }
856
857 if (still_need > 0) {
858 /* Keep any data we already read, silence the rest. */
859 SDL_memset(ptr, silence, still_need);
860 }
861
862 if (device->stream) {
863 /* if this fails...oh well. */
864 SDL_AudioStreamPut(device->stream, data, data_len);
865
866 while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->callbackspec.size)) {
867 const int got = SDL_AudioStreamGet(device->stream, device->work_buffer, device->callbackspec.size);
868 SDL_assert((got < 0) || (got == device->callbackspec.size));
869 if (got != device->callbackspec.size) {
870 SDL_memset(device->work_buffer, device->spec.silence, device->callbackspec.size);
871 }
872
873 /* !!! FIXME: this should be LockDevice. */
874 SDL_LockMutex(device->mixer_lock);
875 if (!SDL_AtomicGet(&device->paused)) {
876 callback(udata, device->work_buffer, device->callbackspec.size);
877 }
878 SDL_UnlockMutex(device->mixer_lock);
879 }
880 } else { /* feeding user callback directly without streaming. */
881 /* !!! FIXME: this should be LockDevice. */
882 SDL_LockMutex(device->mixer_lock);
883 if (!SDL_AtomicGet(&device->paused)) {
884 callback(udata, data, device->callbackspec.size);
885 }
886 SDL_UnlockMutex(device->mixer_lock);
887 }
888 }
889
891
893
894 return 0;
895}
896
897
898static SDL_AudioFormat
899SDL_ParseAudioFormat(const char *string)
900{
901#define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
904 CHECK_FMT_STRING(U16LSB);
905 CHECK_FMT_STRING(S16LSB);
906 CHECK_FMT_STRING(U16MSB);
907 CHECK_FMT_STRING(S16MSB);
908 CHECK_FMT_STRING(U16SYS);
909 CHECK_FMT_STRING(S16SYS);
910 CHECK_FMT_STRING(U16);
911 CHECK_FMT_STRING(S16);
912 CHECK_FMT_STRING(S32LSB);
913 CHECK_FMT_STRING(S32MSB);
914 CHECK_FMT_STRING(S32SYS);
916 CHECK_FMT_STRING(F32LSB);
917 CHECK_FMT_STRING(F32MSB);
918 CHECK_FMT_STRING(F32SYS);
919 CHECK_FMT_STRING(F32);
920#undef CHECK_FMT_STRING
921 return 0;
922}
923
924int
926{
927 return SDL_arraysize(bootstrap) - 1;
928}
929
930const char *
932{
933 if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
934 return bootstrap[index]->name;
935 }
936 return NULL;
937}
938
939int
940SDL_AudioInit(const char *driver_name)
941{
942 int i = 0;
943 int initialized = 0;
944 int tried_to_init = 0;
945
947 SDL_AudioQuit(); /* shutdown driver if already running. */
948 }
949
952
953 /* Select the proper audio driver */
954 if (driver_name == NULL) {
955 driver_name = SDL_getenv("SDL_AUDIODRIVER");
956 }
957
958 for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
959 /* make sure we should even try this driver before doing so... */
960 const AudioBootStrap *backend = bootstrap[i];
961 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
962 (!driver_name && backend->demand_only)) {
963 continue;
964 }
965
966 tried_to_init = 1;
968 current_audio.name = backend->name;
969 current_audio.desc = backend->desc;
970 initialized = backend->init(&current_audio.impl);
971 }
972
973 if (!initialized) {
974 /* specific drivers will set the error message if they fail... */
975 if (!tried_to_init) {
976 if (driver_name) {
977 SDL_SetError("Audio target '%s' not available", driver_name);
978 } else {
979 SDL_SetError("No available audio device");
980 }
981 }
982
984 return -1; /* No driver was available, so fail. */
985 }
986
988
990
991 /* Make sure we have a list of devices available at startup. */
993
994#ifdef HAVE_LIBSAMPLERATE_H
995 LoadLibSampleRate();
996#endif
997
998 return 0;
999}
1000
1001/*
1002 * Get the current audio driver name
1003 */
1004const char *
1006{
1007 return current_audio.name;
1008}
1009
1010/* Clean out devices that we've removed but had to keep around for stability. */
1011static void
1013{
1015 SDL_AudioDeviceItem *prev = NULL;
1016 int total = 0;
1017
1018 while (item) {
1019 SDL_AudioDeviceItem *next = item->next;
1020 if (item->handle != NULL) {
1021 total++;
1022 prev = item;
1023 } else {
1024 if (prev) {
1025 prev->next = next;
1026 } else {
1027 *devices = next;
1028 }
1029 /* these two pointers are the same if not a duplicate devname */
1030 if (item->name != item->original_name) {
1031 SDL_free(item->name);
1032 }
1033 SDL_free(item->original_name);
1034 SDL_free(item);
1035 }
1036 item = next;
1037 }
1038
1039 *devCount = total;
1040 *removedFlag = SDL_FALSE;
1041}
1042
1043
1044int
1046{
1047 int retval = 0;
1048
1050 return -1;
1051 }
1052
1054 if (iscapture && current_audio.captureDevicesRemoved) {
1056 }
1057
1058 if (!iscapture && current_audio.outputDevicesRemoved) {
1060 }
1061
1064
1065 return retval;
1066}
1067
1068
1069const char *
1071{
1072 const char *retval = NULL;
1073
1075 SDL_SetError("Audio subsystem is not initialized");
1076 return NULL;
1077 }
1078
1079 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1080 SDL_SetError("No capture support");
1081 return NULL;
1082 }
1083
1084 if (index >= 0) {
1085 SDL_AudioDeviceItem *item;
1086 int i;
1087
1091 if (index < i) {
1092 for (i--; i > index; i--, item = item->next) {
1093 SDL_assert(item != NULL);
1094 }
1095 SDL_assert(item != NULL);
1096 retval = item->name;
1097 }
1099 }
1100
1101 if (retval == NULL) {
1102 SDL_SetError("No such device");
1103 }
1104
1105 return retval;
1106}
1107
1108
1109static void
1111{
1112 if (!device) {
1113 return;
1114 }
1115
1116 /* make sure the device is paused before we do anything else, so the
1117 audio callback definitely won't fire again. */
1119 SDL_AtomicSet(&device->paused, 1);
1120 SDL_AtomicSet(&device->shutdown, 1);
1121 SDL_AtomicSet(&device->enabled, 0);
1123
1124 if (device->thread != NULL) {
1125 SDL_WaitThread(device->thread, NULL);
1126 }
1127 if (device->mixer_lock != NULL) {
1128 SDL_DestroyMutex(device->mixer_lock);
1129 }
1130
1131 SDL_free(device->work_buffer);
1132 SDL_FreeAudioStream(device->stream);
1133
1134 if (device->id > 0) {
1135 SDL_AudioDevice *opendev = open_devices[device->id - 1];
1136 SDL_assert((opendev == device) || (opendev == NULL));
1137 if (opendev == device) {
1138 open_devices[device->id - 1] = NULL;
1139 }
1140 }
1141
1142 if (device->hidden != NULL) {
1144 }
1145
1146 SDL_FreeDataQueue(device->buffer_queue);
1147
1149}
1150
1151
1152/*
1153 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
1154 * Fills in a sanitized copy in (prepared).
1155 * Returns non-zero if okay, zero on fatal parameters in (orig).
1156 */
1157static int
1159{
1160 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
1161
1162 if (orig->freq == 0) {
1163 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
1164 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
1165 prepared->freq = 22050; /* a reasonable default */
1166 }
1167 }
1168
1169 if (orig->format == 0) {
1170 const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
1171 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
1172 prepared->format = AUDIO_S16; /* a reasonable default */
1173 }
1174 }
1175
1176 switch (orig->channels) {
1177 case 0:{
1178 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
1179 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
1180 prepared->channels = 2; /* a reasonable default */
1181 }
1182 break;
1183 }
1184 case 1: /* Mono */
1185 case 2: /* Stereo */
1186 case 4: /* Quadrophonic */
1187 case 6: /* 5.1 surround */
1188 case 8: /* 7.1 surround */
1189 break;
1190 default:
1191 SDL_SetError("Unsupported number of audio channels.");
1192 return 0;
1193 }
1194
1195 if (orig->samples == 0) {
1196 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
1197 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
1198 /* Pick a default of ~46 ms at desired frequency */
1199 /* !!! FIXME: remove this when the non-Po2 resampling is in. */
1200 const int samples = (prepared->freq / 1000) * 46;
1201 int power2 = 1;
1202 while (power2 < samples) {
1203 power2 *= 2;
1204 }
1205 prepared->samples = power2;
1206 }
1207 }
1208
1209 /* Calculate the silence and size of the audio specification */
1210 SDL_CalculateAudioSpec(prepared);
1211
1212 return 1;
1213}
1214
1215static SDL_AudioDeviceID
1216open_audio_device(const char *devname, int iscapture,
1217 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1218 int allowed_changes, int min_id)
1219{
1220 const SDL_bool is_internal_thread = (desired->callback == NULL);
1221 SDL_AudioDeviceID id = 0;
1222 SDL_AudioSpec _obtained;
1224 SDL_bool build_stream;
1225 void *handle = NULL;
1226 int i = 0;
1227
1229 SDL_SetError("Audio subsystem is not initialized");
1230 return 0;
1231 }
1232
1233 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1234 SDL_SetError("No capture support");
1235 return 0;
1236 }
1237
1238 /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
1239 /* Find an available device ID... */
1240 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
1241 if (open_devices[id] == NULL) {
1242 break;
1243 }
1244 }
1245
1246 if (id == SDL_arraysize(open_devices)) {
1247 SDL_SetError("Too many open audio devices");
1248 return 0;
1249 }
1250
1251 if (!obtained) {
1252 obtained = &_obtained;
1253 }
1254 if (!prepare_audiospec(desired, obtained)) {
1255 return 0;
1256 }
1257
1258 /* If app doesn't care about a specific device, let the user override. */
1259 if (devname == NULL) {
1260 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1261 }
1262
1263 /*
1264 * Catch device names at the high level for the simple case...
1265 * This lets us have a basic "device enumeration" for systems that
1266 * don't have multiple devices, but makes sure the device name is
1267 * always NULL when it hits the low level.
1268 *
1269 * Also make sure that the simple case prevents multiple simultaneous
1270 * opens of the default system device.
1271 */
1272
1273 if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
1274 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1275 SDL_SetError("No such device");
1276 return 0;
1277 }
1278 devname = NULL;
1279
1280 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1281 if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1282 SDL_SetError("Audio device already open");
1283 return 0;
1284 }
1285 }
1286 } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1287 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1288 SDL_SetError("No such device");
1289 return 0;
1290 }
1291 devname = NULL;
1292
1293 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1294 if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1295 SDL_SetError("Audio device already open");
1296 return 0;
1297 }
1298 }
1299 } else if (devname != NULL) {
1300 /* if the app specifies an exact string, we can pass the backend
1301 an actual device handle thingey, which saves them the effort of
1302 figuring out what device this was (such as, reenumerating
1303 everything again to find the matching human-readable name).
1304 It might still need to open a device based on the string for,
1305 say, a network audio server, but this optimizes some cases. */
1306 SDL_AudioDeviceItem *item;
1308 for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1309 if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1310 handle = item->handle;
1311 break;
1312 }
1313 }
1315 }
1316
1318 /* has to be in our device list, or the default device. */
1319 if ((handle == NULL) && (devname != NULL)) {
1320 SDL_SetError("No such device.");
1321 return 0;
1322 }
1323 }
1324
1326 if (device == NULL) {
1328 return 0;
1329 }
1330 device->id = id + 1;
1331 device->spec = *obtained;
1332 device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
1333 device->handle = handle;
1334
1335 SDL_AtomicSet(&device->shutdown, 0); /* just in case. */
1336 SDL_AtomicSet(&device->paused, 1);
1337 SDL_AtomicSet(&device->enabled, 1);
1338
1339 /* Create a mutex for locking the sound buffers */
1341 device->mixer_lock = SDL_CreateMutex();
1342 if (device->mixer_lock == NULL) {
1344 SDL_SetError("Couldn't create mixer lock");
1345 return 0;
1346 }
1347 }
1348
1349 if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1351 return 0;
1352 }
1353
1354 /* if your target really doesn't need it, set it to 0x1 or something. */
1355 /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
1356 SDL_assert(device->hidden != NULL);
1357
1358 /* See if we need to do any conversion */
1359 build_stream = SDL_FALSE;
1360 if (obtained->freq != device->spec.freq) {
1361 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1362 obtained->freq = device->spec.freq;
1363 } else {
1364 build_stream = SDL_TRUE;
1365 }
1366 }
1367 if (obtained->format != device->spec.format) {
1368 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1369 obtained->format = device->spec.format;
1370 } else {
1371 build_stream = SDL_TRUE;
1372 }
1373 }
1374 if (obtained->channels != device->spec.channels) {
1375 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1376 obtained->channels = device->spec.channels;
1377 } else {
1378 build_stream = SDL_TRUE;
1379 }
1380 }
1381 if (device->spec.samples != obtained->samples) {
1382 if (allowed_changes & SDL_AUDIO_ALLOW_SAMPLES_CHANGE) {
1383 obtained->samples = device->spec.samples;
1384 } else {
1385 build_stream = SDL_TRUE;
1386 }
1387 }
1388
1389 SDL_CalculateAudioSpec(obtained); /* recalc after possible changes. */
1390
1391 device->callbackspec = *obtained;
1392
1393 if (build_stream) {
1394 if (iscapture) {
1395 device->stream = SDL_NewAudioStream(device->spec.format,
1396 device->spec.channels, device->spec.freq,
1397 obtained->format, obtained->channels, obtained->freq);
1398 } else {
1399 device->stream = SDL_NewAudioStream(obtained->format, obtained->channels,
1400 obtained->freq, device->spec.format,
1401 device->spec.channels, device->spec.freq);
1402 }
1403
1404 if (!device->stream) {
1406 return 0;
1407 }
1408 }
1409
1410 if (device->spec.callback == NULL) { /* use buffer queueing? */
1411 /* pool a few packets to start. Enough for two callbacks. */
1412 device->buffer_queue = SDL_NewDataQueue(SDL_AUDIOBUFFERQUEUE_PACKETLEN, obtained->size * 2);
1413 if (!device->buffer_queue) {
1415 SDL_SetError("Couldn't create audio buffer queue");
1416 return 0;
1417 }
1418 device->callbackspec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
1419 device->callbackspec.userdata = device;
1420 }
1421
1422 /* Allocate a scratch audio buffer */
1423 device->work_buffer_len = build_stream ? device->callbackspec.size : 0;
1424 if (device->spec.size > device->work_buffer_len) {
1425 device->work_buffer_len = device->spec.size;
1426 }
1427 SDL_assert(device->work_buffer_len > 0);
1428
1429 device->work_buffer = (Uint8 *) SDL_malloc(device->work_buffer_len);
1430 if (device->work_buffer == NULL) {
1433 return 0;
1434 }
1435
1436 open_devices[id] = device; /* add it to our list of open devices. */
1437
1438 /* Start the audio thread if necessary */
1440 /* Start the audio thread */
1441 /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
1442 /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
1443 const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
1444 char threadname[64];
1445
1446 SDL_snprintf(threadname, sizeof (threadname), "SDLAudio%c%d", (iscapture) ? 'C' : 'P', (int) device->id);
1447 device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
1448
1449 if (device->thread == NULL) {
1451 SDL_SetError("Couldn't create audio thread");
1452 return 0;
1453 }
1454 }
1455
1456 return device->id;
1457}
1458
1459
1460int
1462{
1463 SDL_AudioDeviceID id = 0;
1464
1465 /* Start up the audio driver, if necessary. This is legacy behaviour! */
1468 return -1;
1469 }
1470 }
1471
1472 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1473 if (open_devices[0] != NULL) {
1474 SDL_SetError("Audio device is already opened");
1475 return -1;
1476 }
1477
1478 if (obtained) {
1479 id = open_audio_device(NULL, 0, desired, obtained,
1481 } else {
1482 SDL_AudioSpec _obtained;
1483 SDL_zero(_obtained);
1484 id = open_audio_device(NULL, 0, desired, &_obtained, 0, 1);
1485 /* On successful open, copy calculated values into 'desired'. */
1486 if (id > 0) {
1487 desired->size = _obtained.size;
1488 desired->silence = _obtained.silence;
1489 }
1490 }
1491
1492 SDL_assert((id == 0) || (id == 1));
1493 return (id == 0) ? -1 : 0;
1494}
1495
1497SDL_OpenAudioDevice(const char *device, int iscapture,
1498 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1499 int allowed_changes)
1500{
1501 return open_audio_device(device, iscapture, desired, obtained,
1502 allowed_changes, 2);
1503}
1504
1507{
1510 if (device && SDL_AtomicGet(&device->enabled)) {
1511 if (SDL_AtomicGet(&device->paused)) {
1512 status = SDL_AUDIO_PAUSED;
1513 } else {
1514 status = SDL_AUDIO_PLAYING;
1515 }
1516 }
1517 return status;
1518}
1519
1520
1523{
1524 return SDL_GetAudioDeviceStatus(1);
1525}
1526
1527void
1529{
1531 if (device) {
1533 SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
1535 }
1536}
1537
1538void
1539SDL_PauseAudio(int pause_on)
1540{
1541 SDL_PauseAudioDevice(1, pause_on);
1542}
1543
1544
1545void
1547{
1548 /* Obtain a lock on the mixing buffers */
1550 if (device) {
1552 }
1553}
1554
1555void
1557{
1559}
1560
1561void
1563{
1564 /* Obtain a lock on the mixing buffers */
1566 if (device) {
1568 }
1569}
1570
1571void
1573{
1575}
1576
1577void
1579{
1581}
1582
1583void
1585{
1587}
1588
1589void
1591{
1593
1594 if (!current_audio.name) { /* not initialized?! */
1595 return;
1596 }
1597
1598 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1600 }
1601
1604
1605 /* Free the driver data */
1607
1609
1612
1613#ifdef HAVE_LIBSAMPLERATE_H
1614 UnloadLibSampleRate();
1615#endif
1616
1618}
1619
1620#define NUM_FORMATS 10
1621static int format_idx;
1644};
1645
1648{
1650 if (format_list[format_idx][0] == format) {
1651 break;
1652 }
1653 }
1654 format_idx_sub = 0;
1655 return SDL_NextAudioFormat();
1656}
1657
1660{
1662 return 0;
1663 }
1665}
1666
1667void
1669{
1670 switch (spec->format) {
1671 case AUDIO_U8:
1672 spec->silence = 0x80;
1673 break;
1674 default:
1675 spec->silence = 0x00;
1676 break;
1677 }
1679 spec->size *= spec->channels;
1680 spec->size *= spec->samples;
1681}
1682
1683
1684/*
1685 * Moved here from SDL_mixer.c, since it relies on internals of an opened
1686 * audio device (and is deprecated, by the way!).
1687 */
1688void
1689SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1690{
1691 /* Mix the user-level audio format */
1693 if (device != NULL) {
1694 SDL_MixAudioFormat(dst, src, device->callbackspec.format, len, volume);
1695 }
1696}
1697
1698/* vi: set ts=4 sw=4 expandtab: */
#define SDL_INIT_AUDIO
Definition: SDL.h:78
void Android_JNI_AudioSetThreadPriority(int iscapture, int device_id)
#define SDL_assert(condition)
Definition: SDL_assert.h:169
static void SDL_AudioWaitDevice_Default(_THIS)
Definition: SDL_audio.c:242
static int SDL_RunAudio(void *devicep)
Definition: SDL_audio.c:682
void SDL_AudioQuit(void)
Definition: SDL_audio.c:1590
static void finish_audio_entry_points_init(void)
Definition: SDL_audio.c:331
SDL_AudioDeviceID SDL_OpenAudioDevice(const char *device, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes)
Definition: SDL_audio.c:1497
static void SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:582
int SDL_GetNumAudioDevices(int iscapture)
Definition: SDL_audio.c:1045
const char * SDL_GetAudioDriver(int index)
Definition: SDL_audio.c:931
static SDL_AudioDeviceID open_audio_device(const char *devname, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes, int min_id)
Definition: SDL_audio.c:1216
static void free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:447
static SDL_INLINE SDL_bool is_in_audio_device_thread(SDL_AudioDevice *device)
Definition: SDL_audio.c:296
static void SDL_AudioUnlockDevice_Default(SDL_AudioDevice *device)
Definition: SDL_audio.c:318
static SDL_AudioFormat SDL_ParseAudioFormat(const char *string)
Definition: SDL_audio.c:899
#define _THIS
Definition: SDL_audio.c:31
static int format_idx_sub
Definition: SDL_audio.c:1622
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS]
Definition: SDL_audio.c:1623
void SDL_CloseAudio(void)
Definition: SDL_audio.c:1584
const char * SDL_GetAudioDeviceName(int index, int iscapture)
Definition: SDL_audio.c:1070
#define NUM_FORMATS
Definition: SDL_audio.c:1620
void SDL_RemoveAudioDevice(const int iscapture, void *handle)
Definition: SDL_audio.c:531
static Uint8 * SDL_AudioGetDeviceBuf_Default(_THIS)
Definition: SDL_audio.c:252
int SDL_GetNumAudioDrivers(void)
Definition: SDL_audio.c:925
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
Definition: SDL_audio.c:469
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1668
static void SDL_AudioThreadInit_Default(_THIS)
Definition: SDL_audio.c:227
static void SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice *device)
Definition: SDL_audio.c:326
#define FILL_STUB(x)
static void close_audio_device(SDL_AudioDevice *device)
Definition: SDL_audio.c:1110
static SDL_INLINE int add_capture_device(const char *name, void *handle)
Definition: SDL_audio.c:434
void SDL_UnlockAudio(void)
Definition: SDL_audio.c:1572
static void SDL_AudioCloseDevice_Default(_THIS)
Definition: SDL_audio.c:274
static void SDL_AudioDeinitialize_Default(void)
Definition: SDL_audio.c:279
Uint32 SDL_DequeueAudio(SDL_AudioDeviceID devid, void *data, Uint32 len)
Definition: SDL_audio.c:621
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1647
static SDL_INLINE int add_output_device(const char *name, void *handle)
Definition: SDL_audio.c:441
const char * SDL_GetCurrentAudioDriver()
Definition: SDL_audio.c:1005
static void clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
Definition: SDL_audio.c:1012
void SDL_MixAudio(Uint8 *dst, const Uint8 *src, Uint32 len, int volume)
Definition: SDL_audio.c:1689
static void mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
Definition: SDL_audio.c:516
static void SDL_AudioThreadDeinit_Default(_THIS)
Definition: SDL_audio.c:232
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
void SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
Definition: SDL_audio.c:1528
void SDL_LockAudio(void)
Definition: SDL_audio.c:1556
void SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1578
static void SDL_AudioPlayDevice_Default(_THIS)
Definition: SDL_audio.c:247
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:486
SDL_AudioStatus SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1506
int SDL_AudioInit(const char *driver_name)
Definition: SDL_audio.c:940
static int add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:374
static void SDL_AudioFlushCapture_Default(_THIS)
Definition: SDL_audio.c:264
void SDL_PauseAudio(int pause_on)
Definition: SDL_audio.c:1539
SDL_AudioStatus SDL_GetAudioStatus(void)
Definition: SDL_audio.c:1522
static const AudioBootStrap *const bootstrap[]
Definition: SDL_audio.c:37
Uint32 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:640
static int format_idx
Definition: SDL_audio.c:1621
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
int SDL_QueueAudio(SDL_AudioDeviceID devid, const void *data, Uint32 len)
Definition: SDL_audio.c:598
static int prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
Definition: SDL_audio.c:1158
#define CHECK_FMT_STRING(x)
static void SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:561
static void SDL_AudioDetectDevices_Default(void)
Definition: SDL_audio.c:214
void SDL_LockAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1546
static void SDL_AudioBeginLoopIteration_Default(_THIS)
Definition: SDL_audio.c:237
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:200
int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
Definition: SDL_audio.c:1461
static void SDL_AudioPrepareToClose_Default(_THIS)
Definition: SDL_audio.c:269
void SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:662
static void SDL_AudioLockDevice_Default(SDL_AudioDevice *device)
Definition: SDL_audio.c:310
static int SDL_CaptureAudio(void *devicep)
Definition: SDL_audio.c:785
static int SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_audio.c:290
static void SDL_AudioFreeDeviceHandle_Default(void *handle)
Definition: SDL_audio.c:284
static int SDL_AudioCaptureFromDevice_Default(_THIS, void *buffer, int buflen)
Definition: SDL_audio.c:258
void SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1562
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
SDL_AudioStatus
Definition: SDL_audio.h:396
@ SDL_AUDIO_STOPPED
Definition: SDL_audio.h:397
@ SDL_AUDIO_PLAYING
Definition: SDL_audio.h:398
@ SDL_AUDIO_PAUSED
Definition: SDL_audio.h:399
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE
Definition: SDL_audio.h:143
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define SDL_AUDIO_ALLOW_FORMAT_CHANGE
Definition: SDL_audio.h:141
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
Definition: SDL_audio.h:140
#define AUDIO_S16
Definition: SDL_audio.h:96
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE
Definition: SDL_audio.h:142
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.h:163
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define SDL_AUDIO_ALLOW_ANY_CHANGE
Definition: SDL_audio.h:144
Uint32 SDL_AudioDeviceID
Definition: SDL_audio.h:330
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
void SDL_FreeResampleFilter(void)
Definition: SDL_audiocvt.c:464
size_t SDL_CountDataQueue(SDL_DataQueue *queue)
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
SDL_DataQueue * SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack)
Definition: SDL_dataqueue.c:58
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88
AudioBootStrap DUMMYAUDIO_bootstrap
#define SDL_AtomicSet
#define SDL_SetError
#define SDL_memset
#define SDL_InitSubSystem
#define SDL_AudioStreamGet
#define SDL_PushEvent
#define SDL_SetThreadPriority
#define SDL_AudioStreamClear
#define SDL_NewAudioStream
#define SDL_LoadObject
#define SDL_WasInit
#define SDL_LockMutex
#define SDL_AudioStreamAvailable
#define SDL_UnloadObject
#define SDL_FreeAudioStream
#define SDL_getenv
#define SDL_malloc
#define SDL_strlen
#define SDL_ThreadID
#define SDL_strcasecmp
#define SDL_CreateMutex
#define SDL_ClearError
#define SDL_free
#define SDL_strdup
#define SDL_strcmp
#define SDL_AudioStreamPut
#define SDL_Delay
#define SDL_WaitThread
#define SDL_AtomicGet
#define SDL_memcpy
#define SDL_DestroyMutex
#define SDL_atoi
#define SDL_snprintf
#define SDL_calloc
#define SDL_GetHint
#define SDL_MixAudioFormat
#define SDL_strncasecmp
#define SDL_UnlockMutex
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
@ SDL_AUDIODEVICEREMOVED
Definition: SDL_events.h:148
@ SDL_AUDIODEVICEADDED
Definition: SDL_events.h:147
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
#define SDL_ENABLE
Definition: SDL_events.h:759
#define SDL_HINT_AUDIO_RESAMPLING_MODE
A variable controlling speed/quality tradeoff of audio resampling.
Definition: SDL_hints.h:1050
#define SDLCALL
Definition: SDL_internal.h:49
void * SDL_LoadFunction(void *handle, const char *name)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLuint GLuint stream
struct _cl_event * event
GLsizei samples
GLenum src
GLuint index
GLuint id
GLenum GLsizei len
GLuint buffer
GLenum GLenum dst
GLuint const GLchar * name
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint16_t Uint16
Definition: SDL_stdinc.h:191
uint8_t Uint8
Definition: SDL_stdinc.h:179
AudioBootStrap DSOUND_bootstrap
AudioBootStrap HAIKUAUDIO_bootstrap
AudioBootStrap SNDIO_bootstrap
AudioBootStrap PULSEAUDIO_bootstrap
AudioBootStrap ARTS_bootstrap
AudioBootStrap EMSCRIPTENAUDIO_bootstrap
AudioBootStrap JACK_bootstrap
AudioBootStrap FUSIONSOUND_bootstrap
AudioBootStrap NACLAUDIO_bootstrap
AudioBootStrap SUNAUDIO_bootstrap
AudioBootStrap NETBSDAUDIO_bootstrap
AudioBootStrap QSAAUDIO_bootstrap
AudioBootStrap PAUDIO_bootstrap
AudioBootStrap openslES_bootstrap
AudioBootStrap ANDROIDAUDIO_bootstrap
AudioBootStrap DSP_bootstrap
#define DEFAULT_OUTPUT_DEVNAME
Definition: SDL_sysaudio.h:32
AudioBootStrap PSPAUDIO_bootstrap
AudioBootStrap COREAUDIO_bootstrap
AudioBootStrap ESD_bootstrap
AudioBootStrap WASAPI_bootstrap
AudioBootStrap WINMM_bootstrap
AudioBootStrap ALSA_bootstrap
#define DEFAULT_INPUT_DEVNAME
Definition: SDL_sysaudio.h:33
AudioBootStrap NAS_bootstrap
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN
Definition: SDL_sysaudio.h:63
AudioBootStrap DISKAUDIO_bootstrap
SDL_Thread * SDL_CreateThreadInternal(int(*fn)(void *), const char *name, const size_t stacksize, void *data)
Definition: SDL_thread.c:429
#define S32
@ SDL_THREAD_PRIORITY_TIME_CRITICAL
Definition: SDL_thread.h:63
@ SDL_THREAD_PRIORITY_HIGH
Definition: SDL_thread.h:62
struct xkb_state * state
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:167
#define SDL_INLINE
Definition: begin_code.h:134
EGLDeviceEXT * devices
Definition: eglext.h:621
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
#define SDL_LIBSAMPLERATE_DYNAMIC
Definition: SDL_config.h:417
SDL_AudioSpec spec
Definition: loopwave.c:31
static SDL_AudioDeviceID device
Definition: loopwave.c:37
const char * name
Definition: SDL_sysaudio.h:178
const char * desc
Definition: SDL_sysaudio.h:179
int(* init)(SDL_AudioDriverImpl *impl)
Definition: SDL_sysaudio.h:180
SDL_bool iscapture
Definition: SDL_sysaudio.h:150
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:103
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:126
SDL_bool captureDevicesRemoved
Definition: SDL_sysaudio.h:121
SDL_bool outputDevicesRemoved
Definition: SDL_sysaudio.h:122
const char * name
Definition: SDL_sysaudio.h:111
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:120
const char * desc
Definition: SDL_sysaudio.h:115
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:117
SDL_AudioDeviceItem * outputDevices
Definition: SDL_sysaudio.h:125
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:76
void(* PrepareToClose)(_THIS)
Definition: SDL_sysaudio.h:77
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:79
void(* ThreadDeinit)(_THIS)
Definition: SDL_sysaudio.h:70
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82
void(* BeginLoopIteration)(_THIS)
Definition: SDL_sysaudio.h:71
void(* ThreadInit)(_THIS)
Definition: SDL_sysaudio.h:69
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
void(* FreeDeviceHandle)(void *handle)
Definition: SDL_sysaudio.h:81
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
Uint32 size
Definition: SDL_audio.h:186
SDL_AudioCallback callback
Definition: SDL_audio.h:187
Uint16 samples
Definition: SDL_audio.h:184
Uint8 channels
Definition: SDL_audio.h:182
Uint8 silence
Definition: SDL_audio.h:183
SDL_AudioFormat format
Definition: SDL_audio.h:181
SDL_bool retval
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
General event structure.
Definition: SDL_events.h:558