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