SDL  2.0
SDL_audio.c File Reference
#include "../SDL_internal.h"
#include "SDL.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_sysaudio.h"
#include "../thread/SDL_systhread.h"
+ Include dependency graph for SDL_audio.c:

Go to the source code of this file.

Macros

#define _THIS   SDL_AudioDevice *_this
 
#define FILL_STUB(x)
 
#define CHECK_FMT_STRING(x)   if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
 
#define NUM_FORMATS   10
 

Functions

static SDL_AudioDeviceget_audio_device (SDL_AudioDeviceID id)
 
static void SDL_AudioDetectDevices_Default (void)
 
static void SDL_AudioThreadInit_Default (_THIS)
 
static void SDL_AudioThreadDeinit_Default (_THIS)
 
static void SDL_AudioBeginLoopIteration_Default (_THIS)
 
static void SDL_AudioWaitDevice_Default (_THIS)
 
static void SDL_AudioPlayDevice_Default (_THIS)
 
static int SDL_AudioGetPendingBytes_Default (_THIS)
 
static Uint8SDL_AudioGetDeviceBuf_Default (_THIS)
 
static int SDL_AudioCaptureFromDevice_Default (_THIS, void *buffer, int buflen)
 
static void SDL_AudioFlushCapture_Default (_THIS)
 
static void SDL_AudioPrepareToClose_Default (_THIS)
 
static void SDL_AudioCloseDevice_Default (_THIS)
 
static void SDL_AudioDeinitialize_Default (void)
 
static void SDL_AudioFreeDeviceHandle_Default (void *handle)
 
static int SDL_AudioOpenDevice_Default (_THIS, void *handle, const char *devname, int iscapture)
 
static SDL_INLINE SDL_bool is_in_audio_device_thread (SDL_AudioDevice *device)
 
static void SDL_AudioLockDevice_Default (SDL_AudioDevice *device)
 
static void SDL_AudioUnlockDevice_Default (SDL_AudioDevice *device)
 
static void SDL_AudioLockOrUnlockDeviceWithNoMixerLock (SDL_AudioDevice *device)
 
static void finish_audio_entry_points_init (void)
 
static int add_audio_device (const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
 
static SDL_INLINE int add_capture_device (const char *name, void *handle)
 
static SDL_INLINE int add_output_device (const char *name, void *handle)
 
static void free_device_list (SDL_AudioDeviceItem **devices, int *devCount)
 
void SDL_AddAudioDevice (const int iscapture, const char *name, void *handle)
 
void SDL_OpenedAudioDeviceDisconnected (SDL_AudioDevice *device)
 
static void mark_device_removed (void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
 
void SDL_RemoveAudioDevice (const int iscapture, void *handle)
 
static void SDL_BufferQueueDrainCallback (void *userdata, Uint8 *stream, int len)
 
static void SDL_BufferQueueFillCallback (void *userdata, Uint8 *stream, int len)
 
int SDL_QueueAudio (SDL_AudioDeviceID devid, const void *data, Uint32 len)
 
Uint32 SDL_DequeueAudio (SDL_AudioDeviceID devid, void *data, Uint32 len)
 
Uint32 SDL_GetQueuedAudioSize (SDL_AudioDeviceID devid)
 
void SDL_ClearQueuedAudio (SDL_AudioDeviceID devid)
 
static int SDL_RunAudio (void *devicep)
 
static int SDL_CaptureAudio (void *devicep)
 
static SDL_AudioFormat SDL_ParseAudioFormat (const char *string)
 
int SDL_GetNumAudioDrivers (void)
 
const char * SDL_GetAudioDriver (int index)
 
int SDL_AudioInit (const char *driver_name)
 
const char * SDL_GetCurrentAudioDriver ()
 
static void clean_out_device_list (SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
 
int SDL_GetNumAudioDevices (int iscapture)
 
const char * SDL_GetAudioDeviceName (int index, int iscapture)
 
static void close_audio_device (SDL_AudioDevice *device)
 
static int prepare_audiospec (const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
 
static SDL_AudioDeviceID open_audio_device (const char *devname, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes, int min_id)
 
int SDL_OpenAudio (SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
 
SDL_AudioDeviceID SDL_OpenAudioDevice (const char *device, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes)
 
SDL_AudioStatus SDL_GetAudioDeviceStatus (SDL_AudioDeviceID devid)
 
SDL_AudioStatus SDL_GetAudioStatus (void)
 
void SDL_PauseAudioDevice (SDL_AudioDeviceID devid, int pause_on)
 
void SDL_PauseAudio (int pause_on)
 
void SDL_LockAudioDevice (SDL_AudioDeviceID devid)
 
void SDL_LockAudio (void)
 
void SDL_UnlockAudioDevice (SDL_AudioDeviceID devid)
 
void SDL_UnlockAudio (void)
 
void SDL_CloseAudioDevice (SDL_AudioDeviceID devid)
 
void SDL_CloseAudio (void)
 
void SDL_AudioQuit (void)
 
SDL_AudioFormat SDL_FirstAudioFormat (SDL_AudioFormat format)
 
SDL_AudioFormat SDL_NextAudioFormat (void)
 
void SDL_CalculateAudioSpec (SDL_AudioSpec *spec)
 
void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume)
 

Variables

static SDL_AudioDriver current_audio
 
static SDL_AudioDeviceopen_devices [16]
 
static const AudioBootStrap *const bootstrap []
 
static int format_idx
 
static int format_idx_sub
 
static SDL_AudioFormat format_list [NUM_FORMATS][NUM_FORMATS]
 

Macro Definition Documentation

◆ _THIS

#define _THIS   SDL_AudioDevice *_this

Definition at line 31 of file SDL_audio.c.

◆ CHECK_FMT_STRING

#define CHECK_FMT_STRING (   x)    if (SDL_strcmp(string, #x) == 0) return AUDIO_##x

Referenced by SDL_ParseAudioFormat().

◆ FILL_STUB

#define FILL_STUB (   x)
Value:
if (current_audio.impl.x == NULL) { \
current_audio.impl.x = SDL_Audio##x##_Default; \
}
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
#define NULL
Definition: begin_code.h:164
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116

Referenced by finish_audio_entry_points_init().

◆ NUM_FORMATS

#define NUM_FORMATS   10

Definition at line 1557 of file SDL_audio.c.

Referenced by SDL_FirstAudioFormat(), and SDL_NextAudioFormat().

Function Documentation

◆ add_audio_device()

static int add_audio_device ( const char *  name,
void handle,
SDL_AudioDeviceItem **  devices,
int *  devCount 
)
static

Definition at line 378 of file SDL_audio.c.

References SDL_AudioDriver::detectionLock, SDL_AudioDeviceItem::handle, SDL_AudioDeviceItem::name, SDL_AudioDeviceItem::next, NULL, retval, SDL_assert, SDL_INLINE, SDL_LockMutex, SDL_malloc, SDL_strlcpy, SDL_strlen, and SDL_UnlockMutex.

Referenced by add_capture_device(), and add_output_device().

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 
393  item->next = *devices;
394  *devices = item;
395  retval = (*devCount)++;
397 
398  return retval;
399 }
#define SDL_strlcpy
#define SDL_LockMutex
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:101
char name[SDL_VARIABLE_LENGTH_ARRAY]
Definition: SDL_sysaudio.h:102
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
GLuint const GLchar * name
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
SDL_bool retval
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
GLsizeiptr size
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#define SDL_strlen
#define SDL_UnlockMutex
#define SDL_malloc
EGLDeviceEXT * devices
Definition: eglext.h:621

◆ add_capture_device()

static SDL_INLINE int add_capture_device ( const char *  name,
void handle 
)
static

Definition at line 402 of file SDL_audio.c.

References add_audio_device(), SDL_AudioDriverImpl::HasCaptureSupport, SDL_AudioDriver::impl, SDL_AudioDriver::inputDeviceCount, SDL_AudioDriver::inputDevices, SDL_assert, and SDL_INLINE.

Referenced by SDL_AddAudioDevice().

403 {
406 }
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
GLuint const GLchar * name
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
static int add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:378
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:125

◆ add_output_device()

static SDL_INLINE int add_output_device ( const char *  name,
void handle 
)
static

Definition at line 409 of file SDL_audio.c.

References add_audio_device(), SDL_AudioDriver::outputDeviceCount, and SDL_AudioDriver::outputDevices.

Referenced by SDL_AddAudioDevice().

410 {
412 }
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
GLuint const GLchar * name
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
static int add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:378
SDL_AudioDeviceItem * outputDevices
Definition: SDL_sysaudio.h:124

◆ clean_out_device_list()

static void clean_out_device_list ( SDL_AudioDeviceItem **  devices,
int *  devCount,
SDL_bool removedFlag 
)
static

Definition at line 957 of file SDL_audio.c.

References SDL_AudioDeviceItem::handle, SDL_AudioDeviceItem::next, NULL, SDL_FALSE, and SDL_free.

Referenced by SDL_GetNumAudioDevices().

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 }
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:101
#define SDL_free
#define NULL
Definition: begin_code.h:164
EGLDeviceEXT * devices
Definition: eglext.h:621

◆ close_audio_device()

static void close_audio_device ( SDL_AudioDevice device)
static

Definition at line 1051 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, SDL_AudioDriverImpl::CloseDevice, SDL_AudioDevice::enabled, SDL_AudioDevice::hidden, SDL_AudioDevice::id, SDL_AudioDriver::impl, SDL_AudioDevice::mixer_lock, NULL, SDL_assert, SDL_AtomicSet, SDL_DestroyMutex, SDL_free, SDL_FreeAudioStream, SDL_FreeDataQueue(), SDL_WaitThread, SDL_AudioDevice::shutdown, SDL_AudioDevice::stream, SDL_AudioDevice::thread, and SDL_AudioDevice::work_buffer.

Referenced by open_audio_device(), SDL_AudioQuit(), and SDL_CloseAudioDevice().

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 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
struct SDL_PrivateAudioData * hidden
Definition: SDL_sysaudio.h:169
SDL_AudioDeviceID id
Definition: SDL_sysaudio.h:134
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:158
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:147
SDL_atomic_t shutdown
Definition: SDL_sysaudio.h:146
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
#define SDL_free
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:79
#define SDL_DestroyMutex
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define SDL_AtomicSet
#define SDL_FreeAudioStream
SDL_Thread * thread
Definition: SDL_sysaudio.h:161
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88
SDL_AudioStream * stream
Definition: SDL_sysaudio.h:143
Uint8 * work_buffer
Definition: SDL_sysaudio.h:152
#define SDL_WaitThread

◆ finish_audio_entry_points_init()

static void finish_audio_entry_points_init ( void  )
static

Definition at line 334 of file SDL_audio.c.

References FILL_STUB, SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, NULL, SDL_AudioLockOrUnlockDeviceWithNoMixerLock(), SDL_AudioDriverImpl::SkipMixerLock, and SDL_AudioDriverImpl::UnlockDevice.

Referenced by SDL_AudioInit().

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 
344  }
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 }
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
#define FILL_STUB(x)
static void SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice *device)
Definition: SDL_audio.c:329
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
#define NULL
Definition: begin_code.h:164
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116

◆ free_device_list()

static void free_device_list ( SDL_AudioDeviceItem **  devices,
int *  devCount 
)
static

Definition at line 415 of file SDL_audio.c.

References SDL_AudioDriverImpl::FreeDeviceHandle, SDL_AudioDeviceItem::handle, SDL_AudioDriver::impl, SDL_AudioDeviceItem::next, NULL, and SDL_free.

Referenced by SDL_AudioQuit().

416 {
417  SDL_AudioDeviceItem *item, *next;
418  for (item = *devices; item != NULL; item = next) {
419  next = item->next;
420  if (item->handle != NULL) {
422  }
423  SDL_free(item);
424  }
425  *devices = NULL;
426  *devCount = 0;
427 }
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:101
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
#define SDL_free
#define NULL
Definition: begin_code.h:164
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
void(* FreeDeviceHandle)(void *handle)
Definition: SDL_sysaudio.h:82

◆ get_audio_device()

static SDL_AudioDevice* get_audio_device ( SDL_AudioDeviceID  id)
static

Definition at line 197 of file SDL_audio.c.

References NULL, SDL_arraysize, and SDL_SetError.

Referenced by SDL_ClearQueuedAudio(), SDL_CloseAudioDevice(), SDL_DequeueAudio(), SDL_GetAudioDeviceStatus(), SDL_GetQueuedAudioSize(), SDL_LockAudioDevice(), SDL_MixAudio(), SDL_OpenedAudioDeviceDisconnected(), SDL_PauseAudioDevice(), SDL_QueueAudio(), and SDL_UnlockAudioDevice().

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 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
GLuint id
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93

◆ is_in_audio_device_thread()

static SDL_INLINE SDL_bool is_in_audio_device_thread ( SDL_AudioDevice device)
static

Definition at line 299 of file SDL_audio.c.

References SDL_FALSE, SDL_ThreadID, SDL_TRUE, SDL_AudioDevice::thread, and SDL_AudioDevice::threadid.

Referenced by SDL_AudioLockDevice_Default(), and SDL_AudioUnlockDevice_Default().

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 }
#define SDL_ThreadID
SDL_threadID threadid
Definition: SDL_sysaudio.h:162
SDL_Thread * thread
Definition: SDL_sysaudio.h:161

◆ mark_device_removed()

static void mark_device_removed ( void handle,
SDL_AudioDeviceItem devices,
SDL_bool removedFlag 
)
static

Definition at line 475 of file SDL_audio.c.

References SDL_AudioDeviceItem::handle, SDL_AudioDeviceItem::next, NULL, SDL_assert, and SDL_TRUE.

Referenced by SDL_RemoveAudioDevice().

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 }
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:101
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164

◆ open_audio_device()

static SDL_AudioDeviceID open_audio_device ( const char *  devname,
int  iscapture,
const SDL_AudioSpec desired,
SDL_AudioSpec obtained,
int  allowed_changes,
int  min_id 
)
static

Definition at line 1150 of file SDL_audio.c.

References SDL_AudioDriverImpl::AllowsArbitraryDeviceNames, SDL_AudioDevice::buffer_queue, SDL_AudioSpec::callback, SDL_AudioDevice::callbackspec, SDL_AudioSpec::channels, close_audio_device(), DEFAULT_INPUT_DEVNAME, DEFAULT_OUTPUT_DEVNAME, SDL_AudioDriver::detectionLock, device, SDL_AudioDevice::enabled, SDL_AudioSpec::format, SDL_AudioSpec::freq, SDL_AudioDeviceItem::handle, SDL_AudioDevice::handle, SDL_AudioDriverImpl::HasCaptureSupport, SDL_AudioDevice::hidden, i, SDL_AudioDevice::id, SDL_AudioDriver::impl, SDL_AudioDriver::inputDevices, SDL_AudioDevice::iscapture, SDL_AudioDevice::mixer_lock, SDL_AudioDeviceItem::name, SDL_AudioDeviceItem::next, NULL, SDL_AudioDriverImpl::OnlyHasDefaultCaptureDevice, SDL_AudioDriverImpl::OnlyHasDefaultOutputDevice, SDL_AudioDriverImpl::OpenDevice, SDL_AudioDriver::outputDevices, SDL_AudioDevice::paused, prepare_audiospec(), SDL_AudioDriverImpl::ProvidesOwnCallbackThread, SDL_AudioSpec::samples, SDL_arraysize, SDL_assert, SDL_AtomicSet, SDL_AUDIO_ALLOW_CHANNELS_CHANGE, SDL_AUDIO_ALLOW_FORMAT_CHANGE, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE, SDL_AUDIOBUFFERQUEUE_PACKETLEN, SDL_BufferQueueDrainCallback(), SDL_BufferQueueFillCallback(), SDL_CalculateAudioSpec(), SDL_calloc, SDL_CaptureAudio(), SDL_CreateMutex, SDL_CreateThreadInternal(), SDL_FALSE, SDL_getenv, SDL_INIT_AUDIO, SDL_LockMutex, SDL_malloc, SDL_NewAudioStream, SDL_NewDataQueue(), SDL_OutOfMemory, SDL_RunAudio(), SDL_SetError, SDL_snprintf, SDL_strcmp, SDL_TRUE, SDL_UnlockMutex, SDL_WasInit, SDL_AudioDevice::shutdown, SDL_AudioSpec::size, SDL_AudioDriverImpl::SkipMixerLock, SDL_AudioDevice::spec, SDL_AudioDevice::stream, SDL_AudioDevice::thread, SDL_AudioSpec::userdata, SDL_AudioDevice::work_buffer, and SDL_AudioDevice::work_buffer_len.

Referenced by SDL_OpenAudio(), and SDL_OpenAudioDevice().

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;
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  }
1249  }
1250 
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 */
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 */
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 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
struct SDL_PrivateAudioData * hidden
Definition: SDL_sysaudio.h:169
SDL_AudioDeviceID id
Definition: SDL_sysaudio.h:134
#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
Definition: SDL_audio.h:140
#define SDL_LockMutex
GLuint id
static int SDL_CaptureAudio(void *devicep)
Definition: SDL_audio.c:738
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:158
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:147
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:101
SDL_atomic_t paused
Definition: SDL_sysaudio.h:148
#define SDL_CreateMutex
SDL_atomic_t shutdown
Definition: SDL_sysaudio.h:146
SDL_DataQueue * SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack)
Definition: SDL_dataqueue.c:58
Uint16 samples
Definition: SDL_audio.h:183
static int SDL_RunAudio(void *devicep)
Definition: SDL_audio.c:643
SDL_AudioSpec spec
Definition: SDL_sysaudio.h:137
char name[SDL_VARIABLE_LENGTH_ARRAY]
Definition: SDL_sysaudio.h:102
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
Uint32 work_buffer_len
Definition: SDL_sysaudio.h:155
#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE
Definition: SDL_audio.h:142
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_Thread * SDL_CreateThreadInternal(int(*fn)(void *), const char *name, const size_t stacksize, void *data)
Definition: SDL_thread.c:427
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
Uint8 channels
Definition: SDL_audio.h:181
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
static int prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
Definition: SDL_audio.c:1093
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1605
SDL_AudioCallback callback
Definition: SDL_audio.h:186
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
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
#define SDL_assert(condition)
Definition: SDL_assert.h:169
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
static void SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:541
#define SDL_SetError
#define SDL_calloc
#define SDL_INIT_AUDIO
Definition: SDL.h:77
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
Uint32 SDL_AudioDeviceID
Definition: SDL_audio.h:329
SDL_AudioFormat format
Definition: SDL_audio.h:180
#define SDL_AtomicSet
#define SDL_NewAudioStream
void * userdata
Definition: SDL_audio.h:187
#define DEFAULT_OUTPUT_DEVNAME
Definition: SDL_sysaudio.h:32
#define SDL_AUDIO_ALLOW_FORMAT_CHANGE
Definition: SDL_audio.h:141
#define SDL_snprintf
#define DEFAULT_INPUT_DEVNAME
Definition: SDL_sysaudio.h:33
#define SDL_UnlockMutex
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
#define SDL_malloc
#define SDL_strcmp
SDL_Thread * thread
Definition: SDL_sysaudio.h:161
#define SDL_WasInit
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN
Definition: SDL_sysaudio.h:63
SDL_AudioStream * stream
Definition: SDL_sysaudio.h:143
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:125
Uint8 * work_buffer
Definition: SDL_sysaudio.h:152
static void close_audio_device(SDL_AudioDevice *device)
Definition: SDL_audio.c:1051

◆ prepare_audiospec()

static int prepare_audiospec ( const SDL_AudioSpec orig,
SDL_AudioSpec prepared 
)
static

Definition at line 1093 of file SDL_audio.c.

References AUDIO_S16, SDL_AudioSpec::channels, SDL_AudioSpec::format, SDL_AudioSpec::freq, SDL_AudioSpec::samples, SDL_atoi, SDL_CalculateAudioSpec(), SDL_getenv, SDL_memcpy, SDL_ParseAudioFormat(), and SDL_SetError.

Referenced by open_audio_device().

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 }
Uint16 samples
Definition: SDL_audio.h:183
#define SDL_memcpy
Uint8 channels
Definition: SDL_audio.h:181
uint8_t Uint8
Definition: SDL_stdinc.h:157
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1605
#define SDL_atoi
#define SDL_getenv
#define SDL_SetError
SDL_AudioFormat format
Definition: SDL_audio.h:180
#define AUDIO_S16
Definition: SDL_audio.h:96
uint16_t Uint16
Definition: SDL_stdinc.h:169
static SDL_AudioFormat SDL_ParseAudioFormat(const char *string)
Definition: SDL_audio.c:844
GLsizei samples

◆ SDL_AddAudioDevice()

void SDL_AddAudioDevice ( const int  iscapture,
const char *  name,
void handle 
)

Definition at line 432 of file SDL_audio.c.

References add_capture_device(), add_output_device(), SDL_AUDIODEVICEADDED, SDL_ENABLE, SDL_GetEventState, SDL_PushEvent, and SDL_zero.

Referenced by SDL_AudioDetectDevices_Default().

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 }
static SDL_INLINE int add_output_device(const char *name, void *handle)
Definition: SDL_audio.c:409
#define SDL_ENABLE
Definition: SDL_events.h:722
GLuint const GLchar * name
#define SDL_GetEventState(type)
Definition: SDL_events.h:735
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
struct _cl_event * event
#define SDL_PushEvent
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
static SDL_INLINE int add_capture_device(const char *name, void *handle)
Definition: SDL_audio.c:402
General event structure.
Definition: SDL_events.h:525

◆ SDL_AudioBeginLoopIteration_Default()

static void SDL_AudioBeginLoopIteration_Default ( _THIS  )
static

Definition at line 234 of file SDL_audio.c.

235 { /* no-op. */
236 }

◆ SDL_AudioCaptureFromDevice_Default()

static int SDL_AudioCaptureFromDevice_Default ( _THIS  ,
void buffer,
int  buflen 
)
static

Definition at line 261 of file SDL_audio.c.

262 {
263  return -1; /* just fail immediately. */
264 }

◆ SDL_AudioCloseDevice_Default()

static void SDL_AudioCloseDevice_Default ( _THIS  )
static

Definition at line 277 of file SDL_audio.c.

278 { /* no-op. */
279 }

◆ SDL_AudioDeinitialize_Default()

static void SDL_AudioDeinitialize_Default ( void  )
static

Definition at line 282 of file SDL_audio.c.

283 { /* no-op. */
284 }

◆ SDL_AudioDetectDevices_Default()

static void SDL_AudioDetectDevices_Default ( void  )
static

Definition at line 211 of file SDL_audio.c.

References DEFAULT_INPUT_DEVNAME, DEFAULT_OUTPUT_DEVNAME, SDL_AudioDriverImpl::HasCaptureSupport, SDL_AudioDriver::impl, SDL_AudioDriverImpl::OnlyHasDefaultCaptureDevice, SDL_AudioDriverImpl::OnlyHasDefaultOutputDevice, SDL_AddAudioDevice(), SDL_assert, SDL_FALSE, and SDL_TRUE.

212 {
213  /* you have to write your own implementation if these assertions fail. */
216 
217  SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
219  SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
220  }
221 }
GLuint GLfloat GLfloat GLfloat x1
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
GLfixed GLfixed x2
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define DEFAULT_OUTPUT_DEVNAME
Definition: SDL_sysaudio.h:32
#define DEFAULT_INPUT_DEVNAME
Definition: SDL_sysaudio.h:33
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
Definition: SDL_audio.c:432

◆ SDL_AudioFlushCapture_Default()

static void SDL_AudioFlushCapture_Default ( _THIS  )
static

Definition at line 267 of file SDL_audio.c.

268 { /* no-op. */
269 }

◆ SDL_AudioFreeDeviceHandle_Default()

static void SDL_AudioFreeDeviceHandle_Default ( void handle)
static

Definition at line 287 of file SDL_audio.c.

288 { /* no-op. */
289 }

◆ SDL_AudioGetDeviceBuf_Default()

static Uint8* SDL_AudioGetDeviceBuf_Default ( _THIS  )
static

Definition at line 255 of file SDL_audio.c.

References NULL.

256 {
257  return NULL;
258 }
#define NULL
Definition: begin_code.h:164

◆ SDL_AudioGetPendingBytes_Default()

static int SDL_AudioGetPendingBytes_Default ( _THIS  )
static

Definition at line 249 of file SDL_audio.c.

250 {
251  return 0;
252 }

◆ SDL_AudioInit()

int SDL_AudioInit ( const char *  driver_name)

Definition at line 885 of file SDL_audio.c.

References AudioBootStrap::demand_only, SDL_AudioDriver::desc, AudioBootStrap::desc, SDL_AudioDriverImpl::DetectDevices, SDL_AudioDriver::detectionLock, finish_audio_entry_points_init(), i, SDL_AudioDriver::impl, AudioBootStrap::init, SDL_AudioDriver::name, AudioBootStrap::name, NULL, SDL_AudioQuit(), SDL_CreateMutex, SDL_getenv, SDL_INIT_AUDIO, SDL_SetError, SDL_strlen, SDL_strncasecmp, SDL_WasInit, and SDL_zero.

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 
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;
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 
929  return -1; /* No driver was available, so fail. */
930  }
931 
933 
935 
936  /* Make sure we have a list of devices available at startup. */
938 
939 #ifdef HAVE_LIBSAMPLERATE_H
940  LoadLibSampleRate();
941 #endif
942 
943  return 0;
944 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
const char * name
Definition: SDL_sysaudio.h:110
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67
const char * name
Definition: SDL_sysaudio.h:177
#define SDL_CreateMutex
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
#define SDL_strncasecmp
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
const char * desc
Definition: SDL_sysaudio.h:114
void SDL_AudioQuit(void)
Definition: SDL_audio.c:1527
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
#define SDL_getenv
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
static const AudioBootStrap *const bootstrap[]
Definition: SDL_audio.c:37
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
#define SDL_INIT_AUDIO
Definition: SDL.h:77
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define SDL_strlen
int(* init)(SDL_AudioDriverImpl *impl)
Definition: SDL_sysaudio.h:179
const char * desc
Definition: SDL_sysaudio.h:178
#define SDL_WasInit
static void finish_audio_entry_points_init(void)
Definition: SDL_audio.c:334

◆ SDL_AudioLockDevice_Default()

static void SDL_AudioLockDevice_Default ( SDL_AudioDevice device)
static

Definition at line 313 of file SDL_audio.c.

References is_in_audio_device_thread(), SDL_AudioDevice::mixer_lock, and SDL_LockMutex.

314 {
315  if (!is_in_audio_device_thread(device)) {
316  SDL_LockMutex(device->mixer_lock);
317  }
318 }
#define SDL_LockMutex
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:158
static SDL_INLINE SDL_bool is_in_audio_device_thread(SDL_AudioDevice *device)
Definition: SDL_audio.c:299

◆ SDL_AudioLockOrUnlockDeviceWithNoMixerLock()

static void SDL_AudioLockOrUnlockDeviceWithNoMixerLock ( SDL_AudioDevice device)
static

Definition at line 329 of file SDL_audio.c.

Referenced by finish_audio_entry_points_init().

330 {
331 }

◆ SDL_AudioOpenDevice_Default()

static int SDL_AudioOpenDevice_Default ( _THIS  ,
void handle,
const char *  devname,
int  iscapture 
)
static

Definition at line 293 of file SDL_audio.c.

References SDL_INLINE, and SDL_Unsupported.

294 {
295  return SDL_Unsupported();
296 }
#define SDL_Unsupported()
Definition: SDL_error.h:53

◆ SDL_AudioPlayDevice_Default()

static void SDL_AudioPlayDevice_Default ( _THIS  )
static

Definition at line 244 of file SDL_audio.c.

245 { /* no-op. */
246 }

◆ SDL_AudioPrepareToClose_Default()

static void SDL_AudioPrepareToClose_Default ( _THIS  )
static

Definition at line 272 of file SDL_audio.c.

273 { /* no-op. */
274 }

◆ SDL_AudioQuit()

void SDL_AudioQuit ( void  )

Definition at line 1527 of file SDL_audio.c.

References close_audio_device(), SDL_AudioDriverImpl::Deinitialize, SDL_AudioDriver::detectionLock, free_device_list(), i, SDL_AudioDriver::impl, SDL_AudioDriver::inputDeviceCount, SDL_AudioDriver::inputDevices, SDL_AudioDriver::name, SDL_AudioDriver::outputDeviceCount, SDL_AudioDriver::outputDevices, SDL_arraysize, SDL_DestroyMutex, SDL_FreeResampleFilter(), and SDL_zero.

Referenced by SDL_AudioInit().

1528 {
1530 
1531  if (!current_audio.name) { /* not initialized?! */
1532  return;
1533  }
1534 
1535  for (i = 0; i < SDL_arraysize(open_devices); i++) {
1537  }
1538 
1541 
1542  /* Free the driver data */
1544 
1546 
1549 
1550 #ifdef HAVE_LIBSAMPLERATE_H
1551  UnloadLibSampleRate();
1552 #endif
1553 
1555 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
const char * name
Definition: SDL_sysaudio.h:110
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
void SDL_FreeResampleFilter(void)
Definition: SDL_audiocvt.c:464
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:83
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_AudioDeviceItem * outputDevices
Definition: SDL_sysaudio.h:124
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
static void free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:415
#define SDL_DestroyMutex
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
Uint32 SDL_AudioDeviceID
Definition: SDL_audio.h:329
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:125
static void close_audio_device(SDL_AudioDevice *device)
Definition: SDL_audio.c:1051

◆ SDL_AudioThreadDeinit_Default()

static void SDL_AudioThreadDeinit_Default ( _THIS  )
static

Definition at line 229 of file SDL_audio.c.

230 { /* no-op. */
231 }

◆ SDL_AudioThreadInit_Default()

static void SDL_AudioThreadInit_Default ( _THIS  )
static

Definition at line 224 of file SDL_audio.c.

225 { /* no-op. */
226 }

◆ SDL_AudioUnlockDevice_Default()

static void SDL_AudioUnlockDevice_Default ( SDL_AudioDevice device)
static

Definition at line 321 of file SDL_audio.c.

References is_in_audio_device_thread(), SDL_AudioDevice::mixer_lock, and SDL_UnlockMutex.

322 {
323  if (!is_in_audio_device_thread(device)) {
324  SDL_UnlockMutex(device->mixer_lock);
325  }
326 }
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:158
#define SDL_UnlockMutex
static SDL_INLINE SDL_bool is_in_audio_device_thread(SDL_AudioDevice *device)
Definition: SDL_audio.c:299

◆ SDL_AudioWaitDevice_Default()

static void SDL_AudioWaitDevice_Default ( _THIS  )
static

Definition at line 239 of file SDL_audio.c.

240 { /* no-op. */
241 }

◆ SDL_BufferQueueDrainCallback()

static void SDL_BufferQueueDrainCallback ( void userdata,
Uint8 stream,
int  len 
)
static

Definition at line 520 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, device, SDL_AudioDevice::iscapture, NULL, SDL_assert, SDL_CountDataQueue(), SDL_memset, SDL_ReadFromDataQueue(), SDLCALL, SDL_AudioSpec::silence, and SDL_AudioDevice::spec.

Referenced by open_audio_device(), SDL_GetQueuedAudioSize(), and SDL_QueueAudio().

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 }
Uint8 silence
Definition: SDL_audio.h:182
SDL_AudioSpec spec
Definition: SDL_sysaudio.h:137
GLenum GLsizei len
static SDL_AudioDeviceID device
Definition: loopwave.c:37
GLuint GLuint stream
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
size_t SDL_CountDataQueue(SDL_DataQueue *queue)
#define SDL_memset

◆ SDL_BufferQueueFillCallback()

static void SDL_BufferQueueFillCallback ( void userdata,
Uint8 stream,
int  len 
)
static

Definition at line 541 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, device, SDL_AudioDevice::iscapture, NULL, SDL_assert, and SDL_WriteToDataQueue().

Referenced by open_audio_device(), SDL_DequeueAudio(), and SDL_GetQueuedAudioSize().

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. */
554 }
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
GLenum GLsizei len
static SDL_AudioDeviceID device
Definition: loopwave.c:37
GLuint GLuint stream
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165

◆ SDL_CalculateAudioSpec()

void SDL_CalculateAudioSpec ( SDL_AudioSpec spec)

Definition at line 1605 of file SDL_audio.c.

References AUDIO_U8, SDL_AudioSpec::channels, SDL_AudioSpec::format, SDL_AudioSpec::samples, SDL_AUDIO_BITSIZE, SDL_AudioSpec::silence, and SDL_AudioSpec::size.

Referenced by open_audio_device(), and prepare_audiospec().

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 }
Uint8 silence
Definition: SDL_audio.h:182
Uint16 samples
Definition: SDL_audio.h:183
#define AUDIO_U8
Definition: SDL_audio.h:89
Uint8 channels
Definition: SDL_audio.h:181
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
Uint32 size
Definition: SDL_audio.h:185
SDL_AudioFormat format
Definition: SDL_audio.h:180

◆ SDL_CaptureAudio()

static int SDL_CaptureAudio ( void devicep)
static

Definition at line 738 of file SDL_audio.c.

References SDL_AudioDriverImpl::BeginLoopIteration, callback(), SDL_AudioSpec::callback, SDL_AudioDevice::callbackspec, SDL_AudioDriverImpl::CaptureFromDevice, device, SDL_AudioDevice::enabled, SDL_AudioDriverImpl::FlushCapture, SDL_AudioSpec::freq, SDL_AudioDriver::impl, SDL_AudioDevice::iscapture, SDL_AudioDevice::mixer_lock, NULL, SDL_AudioDevice::paused, SDL_AudioSpec::samples, SDL_assert, SDL_AtomicGet, SDL_AudioStreamAvailable, SDL_AudioStreamClear, SDL_AudioStreamGet, SDL_AudioStreamPut, SDL_Delay, SDL_LockMutex, SDL_memset, SDL_OpenedAudioDeviceDisconnected(), SDL_SetThreadPriority, SDL_THREAD_PRIORITY_HIGH, SDL_ThreadID, SDL_UnlockMutex, SDL_AudioDevice::shutdown, SDL_AudioSpec::silence, SDL_AudioSpec::size, SDL_AudioDevice::spec, SDL_AudioDevice::stream, SDL_AudioDriverImpl::ThreadDeinit, SDL_AudioDevice::threadid, SDL_AudioDriverImpl::ThreadInit, SDL_AudioSpec::userdata, and SDL_AudioDevice::work_buffer.

Referenced by open_audio_device().

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 
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 
836 
838 
839  return 0;
840 }
#define SDL_ThreadID
#define SDL_LockMutex
#define SDL_AudioStreamAvailable
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:158
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:147
Uint8 silence
Definition: SDL_audio.h:182
SDL_atomic_t paused
Definition: SDL_sysaudio.h:148
#define SDL_AudioStreamGet
SDL_atomic_t shutdown
Definition: SDL_sysaudio.h:146
void(* ThreadDeinit)(_THIS)
Definition: SDL_sysaudio.h:70
SDL_threadID threadid
Definition: SDL_sysaudio.h:162
Uint16 samples
Definition: SDL_audio.h:183
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:449
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_AudioSpec spec
Definition: SDL_sysaudio.h:137
uint32_t Uint32
Definition: SDL_stdinc.h:181
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* ThreadInit)(_THIS)
Definition: SDL_sysaudio.h:69
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.h:162
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
#define SDL_AudioStreamPut
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
SDL_AudioCallback callback
Definition: SDL_audio.h:186
#define SDL_Delay
Uint32 size
Definition: SDL_audio.h:185
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:76
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:77
#define SDL_AudioStreamClear
#define SDL_AtomicGet
void * userdata
Definition: SDL_audio.h:187
void(* BeginLoopIteration)(_THIS)
Definition: SDL_sysaudio.h:71
#define SDL_UnlockMutex
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
SDL_AudioStream * stream
Definition: SDL_sysaudio.h:143
#define SDL_SetThreadPriority
Uint8 * work_buffer
Definition: SDL_sysaudio.h:152
#define SDL_memset

◆ SDL_ClearQueuedAudio()

void SDL_ClearQueuedAudio ( SDL_AudioDeviceID  dev)

Drop any queued audio data. For playback devices, this is any queued data still waiting to be submitted to the hardware. For capture devices, this is any data that was queued by the device that hasn't yet been dequeued by the application.

Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For playback devices, the hardware will start playing silence if more audio isn't queued. Unpaused capture devices will start filling the queue again as soon as they have more data available (which, depending on the state of the hardware and the thread, could be before this function call returns!).

This will not prevent playback of queued audio that's already been sent to the hardware, as we can not undo that, so expect there to be some fraction of a second of audio that might still be heard. This can be useful if you want to, say, drop any pending music during a level change in your game.

You may not queue audio on a device that is using an application-supplied callback; calling this function on such a device is always a no-op. You have to queue audio with SDL_QueueAudio()/SDL_DequeueAudio(), or use the audio callback, but not both.

You should not call SDL_LockAudio() on the device before clearing the queue; SDL handles locking internally for this function.

This function always succeeds and thus returns void.

Parameters
devThe device ID of which to clear the audio queue.
See also
SDL_QueueAudio
SDL_GetQueuedAudioSize

Definition at line 623 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, SDL_AUDIOBUFFERQUEUE_PACKETLEN, SDL_ClearDataQueue(), SDLCALL, and SDL_AudioDriverImpl::UnlockDevice.

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 
638 }
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN
Definition: SDL_sysaudio.h:63
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_CloseAudio()

void SDL_CloseAudio ( void  )

This function shuts down audio processing and closes the audio device.

Definition at line 1521 of file SDL_audio.c.

References SDL_CloseAudioDevice().

1522 {
1524 }
void SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1515

◆ SDL_CloseAudioDevice()

void SDL_CloseAudioDevice ( SDL_AudioDeviceID  devid)

Definition at line 1515 of file SDL_audio.c.

References close_audio_device(), and get_audio_device().

Referenced by SDL_CloseAudio().

1516 {
1518 }
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197
static void close_audio_device(SDL_AudioDevice *device)
Definition: SDL_audio.c:1051

◆ SDL_DequeueAudio()

Uint32 SDL_DequeueAudio ( SDL_AudioDeviceID  dev,
void data,
Uint32  len 
)

Dequeue more audio on non-callback devices.

(If you are looking to queue audio for output on a non-callback playback device, you want SDL_QueueAudio() instead. This will always return 0 if you use it with playback devices.)

SDL offers two ways to retrieve audio from a capture device: you can either supply a callback that SDL triggers with some frequency as the device records more audio data, (push method), or you can supply no callback, and then SDL will expect you to retrieve data at regular intervals (pull method) with this function.

There are no limits on the amount of data you can queue, short of exhaustion of address space. Data from the device will keep queuing as necessary without further intervention from you. This means you will eventually run out of memory if you aren't routinely dequeueing data.

Capture devices will not queue data when paused; if you are expecting to not need captured audio for some length of time, use SDL_PauseAudioDevice() to stop the capture device from queueing more data. This can be useful during, say, level loading times. When unpaused, capture devices will start queueing data from that point, having flushed any capturable data available while paused.

This function is thread-safe, but dequeueing from the same device from two threads at once does not promise which thread will dequeued data first.

You may not dequeue audio from a device that is using an application-supplied callback; doing so returns an error. You have to use the audio callback, or dequeue audio with this function, but not both.

You should not call SDL_LockAudio() on the device before queueing; SDL handles locking internally for this function.

Parameters
devThe device ID from which we will dequeue audio.
dataA pointer into where audio data should be copied.
lenThe number of bytes (not samples!) to which (data) points.
Returns
number of bytes dequeued, which could be less than requested.
See also
SDL_GetQueuedAudioSize
SDL_ClearQueuedAudio

Definition at line 580 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, SDL_AudioSpec::callback, SDL_AudioDevice::callbackspec, device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDevice::iscapture, SDL_AudioDriverImpl::LockDevice, SDL_BufferQueueFillCallback(), SDL_ReadFromDataQueue(), and SDL_AudioDriverImpl::UnlockDevice.

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);
595  return rc;
596 }
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
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
GLenum GLsizei len
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
SDL_AudioCallback callback
Definition: SDL_audio.h:186
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
static void SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:541
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_FirstAudioFormat()

SDL_AudioFormat SDL_FirstAudioFormat ( SDL_AudioFormat  format)

Definition at line 1584 of file SDL_audio.c.

References format_idx, format_idx_sub, format_list, NUM_FORMATS, and SDL_NextAudioFormat().

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 }
static int format_idx_sub
Definition: SDL_audio.c:1559
static int format_idx
Definition: SDL_audio.c:1558
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS]
Definition: SDL_audio.c:1560
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1596
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
#define NUM_FORMATS
Definition: SDL_audio.c:1557

◆ SDL_GetAudioDeviceName()

const char* SDL_GetAudioDeviceName ( int  index,
int  iscapture 
)

Get the human-readable name of a specific audio device. Must be a value between 0 and (number of audio devices-1). Only valid after a successfully initializing the audio subsystem. The values returned by this function reflect the latest call to SDL_GetNumAudioDevices(); recall that function to redetect available hardware.

The string returned by this function is UTF-8 encoded, read-only, and managed internally. You are not to free it. If you need to keep the string for any length of time, you should make your own copy of it, as it will be invalid next time any of several other SDL functions is called.

Definition at line 1011 of file SDL_audio.c.

References SDL_AudioDriver::detectionLock, SDL_AudioDriverImpl::HasCaptureSupport, i, SDL_AudioDriver::impl, SDL_AudioDriver::inputDeviceCount, SDL_AudioDriver::inputDevices, SDL_AudioDeviceItem::next, NULL, SDL_AudioDriver::outputDeviceCount, SDL_AudioDriver::outputDevices, retval, SDL_assert, SDL_INIT_AUDIO, SDL_LockMutex, SDL_SetError, SDL_UnlockMutex, and SDL_WasInit.

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 
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  }
1040  }
1041 
1042  if (retval == NULL) {
1043  SDL_SetError("No such device");
1044  }
1045 
1046  return retval;
1047 }
#define SDL_LockMutex
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:101
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
SDL_bool retval
GLuint index
SDL_AudioDeviceItem * outputDevices
Definition: SDL_sysaudio.h:124
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 SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
#define SDL_INIT_AUDIO
Definition: SDL.h:77
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define SDL_UnlockMutex
#define SDL_WasInit
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:125

◆ SDL_GetAudioDeviceStatus()

SDL_AudioStatus SDL_GetAudioDeviceStatus ( SDL_AudioDeviceID  devid)

Definition at line 1443 of file SDL_audio.c.

References device, SDL_AudioDevice::enabled, get_audio_device(), SDL_AudioDevice::paused, SDL_AtomicGet, SDL_AUDIO_PAUSED, SDL_AUDIO_PLAYING, and SDL_AUDIO_STOPPED.

Referenced by SDL_GetAudioStatus().

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 }
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:147
SDL_atomic_t paused
Definition: SDL_sysaudio.h:148
SDL_AudioStatus
Definition: SDL_audio.h:394
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_AtomicGet
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_GetAudioDriver()

const char* SDL_GetAudioDriver ( int  index)

Definition at line 876 of file SDL_audio.c.

References AudioBootStrap::name, NULL, and SDL_GetNumAudioDrivers().

877 {
878  if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
879  return bootstrap[index]->name;
880  }
881  return NULL;
882 }
int SDL_GetNumAudioDrivers(void)
Definition: SDL_audio.c:870
const char * name
Definition: SDL_sysaudio.h:177
GLuint index
static const AudioBootStrap *const bootstrap[]
Definition: SDL_audio.c:37
#define NULL
Definition: begin_code.h:164

◆ SDL_GetAudioStatus()

SDL_AudioStatus SDL_GetAudioStatus ( void  )

Definition at line 1459 of file SDL_audio.c.

References SDL_GetAudioDeviceStatus().

1460 {
1461  return SDL_GetAudioDeviceStatus(1);
1462 }
SDL_AudioStatus SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1443

◆ SDL_GetCurrentAudioDriver()

const char* SDL_GetCurrentAudioDriver ( void  )

This function returns the name of the current audio driver, or NULL if no driver has been initialized.

Definition at line 950 of file SDL_audio.c.

References SDL_AudioDriver::name.

951 {
952  return current_audio.name;
953 }
const char * name
Definition: SDL_sysaudio.h:110
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33

◆ SDL_GetNumAudioDevices()

int SDL_GetNumAudioDevices ( int  iscapture)

Get the number of available devices exposed by the current driver. Only valid after a successfully initializing the audio subsystem. Returns -1 if an explicit list of devices can't be determined; this is not an error. For example, if SDL is set up to talk to a remote audio server, it can't list every one available on the Internet, but it will still allow a specific host to be specified to SDL_OpenAudioDevice().

In many common cases, when this function returns a value <= 0, it can still successfully open the default device (NULL for first argument of SDL_OpenAudioDevice()).

Definition at line 985 of file SDL_audio.c.

References SDL_AudioDriver::captureDevicesRemoved, clean_out_device_list(), SDL_AudioDriver::detectionLock, SDL_AudioDriver::inputDeviceCount, SDL_AudioDriver::inputDevices, SDL_AudioDriver::outputDeviceCount, SDL_AudioDriver::outputDevices, SDL_AudioDriver::outputDevicesRemoved, retval, SDL_FALSE, SDL_INIT_AUDIO, SDL_LockMutex, SDL_UnlockMutex, and SDL_WasInit.

986 {
987  int retval = 0;
988 
989  if (!SDL_WasInit(SDL_INIT_AUDIO)) {
990  return -1;
991  }
992 
994  if (iscapture && current_audio.captureDevicesRemoved) {
996  }
997 
998  if (!iscapture && current_audio.outputDevicesRemoved) {
1001  }
1002 
1005 
1006  return retval;
1007 }
#define SDL_LockMutex
SDL_bool captureDevicesRemoved
Definition: SDL_sysaudio.h:120
static void clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
Definition: SDL_audio.c:957
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
SDL_bool retval
SDL_AudioDeviceItem * outputDevices
Definition: SDL_sysaudio.h:124
SDL_bool outputDevicesRemoved
Definition: SDL_sysaudio.h:121
#define SDL_INIT_AUDIO
Definition: SDL.h:77
#define SDL_UnlockMutex
#define SDL_WasInit
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:125

◆ SDL_GetNumAudioDrivers()

int SDL_GetNumAudioDrivers ( void  )

Definition at line 870 of file SDL_audio.c.

References SDL_arraysize.

Referenced by SDL_GetAudioDriver().

871 {
872  return SDL_arraysize(bootstrap) - 1;
873 }
static const AudioBootStrap *const bootstrap[]
Definition: SDL_audio.c:37
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93

◆ SDL_GetQueuedAudioSize()

Uint32 SDL_GetQueuedAudioSize ( SDL_AudioDeviceID  dev)

Get the number of bytes of still-queued audio.

For playback device:

This is the number of bytes that have been queued for playback with SDL_QueueAudio(), but have not yet been sent to the hardware. This number may shrink at any time, so this only informs of pending data.

Once we've sent it to the hardware, this function can not decide the exact byte boundary of what has been played. It's possible that we just gave the hardware several kilobytes right before you called this function, but it hasn't played any of it yet, or maybe half of it, etc.

For capture devices:

This is the number of bytes that have been captured by the device and are waiting for you to dequeue. This number may grow at any time, so this only informs of the lower-bound of available data.

You may not queue audio on a device that is using an application-supplied callback; calling this function on such a device always returns 0. You have to queue audio with SDL_QueueAudio()/SDL_DequeueAudio(), or use the audio callback, but not both.

You should not call SDL_LockAudio() on the device before querying; SDL handles locking internally for this function.

Parameters
devThe device ID of which we will query queued audio size.
Returns
Number of bytes (not samples!) of queued audio.
See also
SDL_QueueAudio
SDL_ClearQueuedAudio

Definition at line 599 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, SDL_AudioSpec::callback, SDL_AudioDevice::callbackspec, device, get_audio_device(), SDL_AudioDriverImpl::GetPendingBytes, SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, retval, SDL_BufferQueueDrainCallback(), SDL_BufferQueueFillCallback(), SDL_CountDataQueue(), and SDL_AudioDriverImpl::UnlockDevice.

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);
613  } else if (device->callbackspec.callback == SDL_BufferQueueFillCallback) {
614  current_audio.impl.LockDevice(device);
615  retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
617  }
618 
619  return retval;
620 }
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
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_bool retval
SDL_AudioCallback callback
Definition: SDL_audio.h:186
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
static void SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:520
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
static void SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:541
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
size_t SDL_CountDataQueue(SDL_DataQueue *queue)
int(* GetPendingBytes)(_THIS)
Definition: SDL_sysaudio.h:74
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_LockAudio()

void SDL_LockAudio ( void  )

Definition at line 1493 of file SDL_audio.c.

References SDL_LockAudioDevice().

1494 {
1496 }
void SDL_LockAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1483

◆ SDL_LockAudioDevice()

void SDL_LockAudioDevice ( SDL_AudioDeviceID  devid)

Definition at line 1483 of file SDL_audio.c.

References device, get_audio_device(), SDL_AudioDriver::impl, and SDL_AudioDriverImpl::LockDevice.

Referenced by SDL_LockAudio().

1484 {
1485  /* Obtain a lock on the mixing buffers */
1487  if (device) {
1488  current_audio.impl.LockDevice(device);
1489  }
1490 }
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_MixAudio()

void SDL_MixAudio ( Uint8 dst,
const Uint8 src,
Uint32  len,
int  volume 
)

This takes two audio buffers of the playing audio format and mixes them, performing addition, volume adjustment, and overflow clipping. The volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME for full audio volume. Note this does not change hardware volume. This is provided for convenience – you can mix your own audio data.

Definition at line 1626 of file SDL_audio.c.

References SDL_AudioDevice::callbackspec, device, SDL_AudioSpec::format, get_audio_device(), NULL, and SDL_MixAudioFormat.

1627 {
1628  /* Mix the user-level audio format */
1630  if (device != NULL) {
1631  SDL_MixAudioFormat(dst, src, device->callbackspec.format, len, volume);
1632  }
1633 }
GLenum GLenum dst
#define SDL_MixAudioFormat
GLenum src
GLenum GLsizei len
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define NULL
Definition: begin_code.h:164
SDL_AudioFormat format
Definition: SDL_audio.h:180
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_NextAudioFormat()

SDL_AudioFormat SDL_NextAudioFormat ( void  )

Definition at line 1596 of file SDL_audio.c.

References format_idx, format_idx_sub, format_list, and NUM_FORMATS.

Referenced by SDL_FirstAudioFormat().

1597 {
1598  if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1599  return 0;
1600  }
1602 }
static int format_idx_sub
Definition: SDL_audio.c:1559
static int format_idx
Definition: SDL_audio.c:1558
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS]
Definition: SDL_audio.c:1560
#define NUM_FORMATS
Definition: SDL_audio.c:1557

◆ SDL_OpenAudio()

int SDL_OpenAudio ( SDL_AudioSpec desired,
SDL_AudioSpec obtained 
)

This function opens the audio device with the desired parameters, and returns 0 if successful, placing the actual hardware parameters in the structure pointed to by obtained. If obtained is NULL, the audio data passed to the callback function will be guaranteed to be in the requested format, and will be automatically converted to the hardware audio format if necessary. This function returns -1 if it failed to open the audio device, or couldn't set up the audio thread.

When filling in the desired audio spec structure,

  • desired->freq should be the desired audio frequency in samples-per- second.
  • desired->format should be the desired audio format.
  • desired->samples is the desired size of the audio buffer, in samples. This number should be a power of two, and may be adjusted by the audio driver to a value more suitable for the hardware. Good values seem to range between 512 and 8096 inclusive, depending on the application and CPU speed. Smaller values yield faster response time, but can lead to underflow if the application is doing heavy processing and cannot fill the audio buffer in time. A stereo sample consists of both right and left channels in LR ordering. Note that the number of samples is directly related to time by the following formula:
    ms = (samples*1000)/freq
  • desired->size is the size in bytes of the audio buffer, and is calculated by SDL_OpenAudio().
  • desired->silence is the value used to set the buffer to silence, and is calculated by SDL_OpenAudio().
  • desired->callback should be set to a function that will be called when the audio device is ready for more data. It is passed a pointer to the audio buffer, and the length in bytes of the audio buffer. This function usually runs in a separate thread, and so you should protect data structures that it accesses by calling SDL_LockAudio() and SDL_UnlockAudio() in your code. Alternately, you may pass a NULL pointer here, and call SDL_QueueAudio() with some frequency, to queue more audio samples to be played (or for capture devices, call SDL_DequeueAudio() with some frequency, to obtain audio samples).
  • desired->userdata is passed as the first parameter to your callback function. If you passed a NULL callback, this value is ignored.

The audio device starts out playing silence when it's opened, and should be enabled for playing by calling SDL_PauseAudio(0) when you are ready for your audio callback function to be called. Since the audio driver may modify the requested size of the audio buffer, you should allocate any local mixing buffers after you open the audio device.

Definition at line 1398 of file SDL_audio.c.

References NULL, open_audio_device(), SDL_assert, SDL_AUDIO_ALLOW_ANY_CHANGE, SDL_INIT_AUDIO, SDL_InitSubSystem, SDL_SetError, SDL_WasInit, SDL_zero, SDL_AudioSpec::silence, and SDL_AudioSpec::size.

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 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
Uint8 silence
Definition: SDL_audio.h:182
#define SDL_InitSubSystem
#define SDL_AUDIO_ALLOW_ANY_CHANGE
Definition: SDL_audio.h:143
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
Uint32 size
Definition: SDL_audio.h:185
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#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
#define SDL_INIT_AUDIO
Definition: SDL.h:77
Uint32 SDL_AudioDeviceID
Definition: SDL_audio.h:329
#define SDL_WasInit

◆ SDL_OpenAudioDevice()

SDL_AudioDeviceID SDL_OpenAudioDevice ( const char *  device,
int  iscapture,
const SDL_AudioSpec desired,
SDL_AudioSpec obtained,
int  allowed_changes 
)

Open a specific audio device. Passing in a device name of NULL requests the most reasonable default (and is equivalent to calling SDL_OpenAudio()).

The device name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but some drivers allow arbitrary and driver-specific strings, such as a hostname/IP address for a remote audio server, or a filename in the diskaudio driver.

Returns
0 on error, a valid device ID that is >= 2 on success.

SDL_OpenAudio(), unlike this function, always acts on device ID 1.

Definition at line 1434 of file SDL_audio.c.

References open_audio_device().

1437 {
1438  return open_audio_device(device, iscapture, desired, obtained,
1439  allowed_changes, 2);
1440 }
static SDL_AudioDeviceID device
Definition: loopwave.c:37
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

◆ SDL_OpenedAudioDeviceDisconnected()

void SDL_OpenedAudioDeviceDisconnected ( SDL_AudioDevice device)

Definition at line 449 of file SDL_audio.c.

References SDL_AudioDevice::enabled, get_audio_device(), SDL_AudioDevice::id, SDL_AudioDriver::impl, SDL_AudioDevice::iscapture, SDL_AudioDriverImpl::LockDevice, SDL_assert, SDL_AtomicGet, SDL_AtomicSet, SDL_AUDIODEVICEREMOVED, SDL_ENABLE, SDL_GetEventState, SDL_PushEvent, SDL_zero, and SDL_AudioDriverImpl::UnlockDevice.

Referenced by SDL_CaptureAudio(), and SDL_RemoveAudioDevice().

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);
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 }
SDL_AudioDeviceID id
Definition: SDL_sysaudio.h:134
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:147
#define SDL_ENABLE
Definition: SDL_events.h:722
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
#define SDL_GetEventState(type)
Definition: SDL_events.h:735
struct _cl_event * event
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
#define SDL_PushEvent
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define SDL_AtomicSet
#define SDL_AtomicGet
General event structure.
Definition: SDL_events.h:525
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_ParseAudioFormat()

static SDL_AudioFormat SDL_ParseAudioFormat ( const char *  string)
static

Definition at line 844 of file SDL_audio.c.

References CHECK_FMT_STRING, and S32.

Referenced by prepare_audiospec().

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 }
#define S32
#define CHECK_FMT_STRING(x)

◆ SDL_PauseAudio()

void SDL_PauseAudio ( int  pause_on)

Definition at line 1476 of file SDL_audio.c.

References SDL_PauseAudioDevice().

1477 {
1478  SDL_PauseAudioDevice(1, pause_on);
1479 }
void SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
Definition: SDL_audio.c:1465

◆ SDL_PauseAudioDevice()

void SDL_PauseAudioDevice ( SDL_AudioDeviceID  devid,
int  pause_on 
)

Definition at line 1465 of file SDL_audio.c.

References device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, SDL_AudioDevice::paused, SDL_AtomicSet, and SDL_AudioDriverImpl::UnlockDevice.

Referenced by SDL_PauseAudio().

1466 {
1468  if (device) {
1469  current_audio.impl.LockDevice(device);
1470  SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
1472  }
1473 }
SDL_atomic_t paused
Definition: SDL_sysaudio.h:148
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
#define SDL_AtomicSet
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_QueueAudio()

int SDL_QueueAudio ( SDL_AudioDeviceID  dev,
const void data,
Uint32  len 
)

Queue more audio on non-callback devices.

(If you are looking to retrieve queued audio from a non-callback capture device, you want SDL_DequeueAudio() instead. This will return -1 to signify an error if you use it with capture devices.)

SDL offers two ways to feed audio to the device: you can either supply a callback that SDL triggers with some frequency to obtain more audio (pull method), or you can supply no callback, and then SDL will expect you to supply data at regular intervals (push method) with this function.

There are no limits on the amount of data you can queue, short of exhaustion of address space. Queued data will drain to the device as necessary without further intervention from you. If the device needs audio but there is not enough queued, it will play silence to make up the difference. This means you will have skips in your audio playback if you aren't routinely queueing sufficient data.

This function copies the supplied data, so you are safe to free it when the function returns. This function is thread-safe, but queueing to the same device from two threads at once does not promise which buffer will be queued first.

You may not queue audio on a device that is using an application-supplied callback; doing so returns an error. You have to use the audio callback or queue audio with this function, but not both.

You should not call SDL_LockAudio() on the device before queueing; SDL handles locking internally for this function.

Parameters
devThe device ID to which we will queue audio.
dataThe data to queue to the device for later playback.
lenThe number of bytes (not samples!) to which (data) points.
Returns
0 on success, or -1 on error.
See also
SDL_GetQueuedAudioSize
SDL_ClearQueuedAudio

Definition at line 557 of file SDL_audio.c.

References SDL_AudioDevice::buffer_queue, SDL_AudioSpec::callback, SDL_AudioDevice::callbackspec, device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDevice::iscapture, SDL_AudioDriverImpl::LockDevice, SDL_BufferQueueDrainCallback(), SDL_SetError, SDL_WriteToDataQueue(), and SDL_AudioDriverImpl::UnlockDevice.

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);
574  }
575 
576  return rc;
577 }
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
GLenum GLsizei len
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
SDL_AudioCallback callback
Definition: SDL_audio.h:186
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
static void SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:520
SDL_DataQueue * buffer_queue
Definition: SDL_sysaudio.h:165
#define SDL_SetError
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

◆ SDL_RemoveAudioDevice()

void SDL_RemoveAudioDevice ( const int  iscapture,
void handle 
)

Definition at line 490 of file SDL_audio.c.

References SDL_AudioDriver::captureDevicesRemoved, SDL_AudioDriver::detectionLock, device, SDL_AudioDriverImpl::FreeDeviceHandle, SDL_AudioDevice::handle, SDL_AudioDriver::impl, SDL_AudioDriver::inputDevices, mark_device_removed(), NULL, SDL_AudioDriver::outputDevices, SDL_AudioDriver::outputDevicesRemoved, SDL_arraysize, SDL_LockMutex, SDL_OpenedAudioDeviceDisconnected(), SDL_UnlockMutex, and SDLCALL.

491 {
492  int device_index;
494 
496  if (iscapture) {
498  } else {
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  }
511 
513 }
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
#define SDL_LockMutex
SDL_bool captureDevicesRemoved
Definition: SDL_sysaudio.h:120
static void mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
Definition: SDL_audio.c:475
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:449
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:119
static SDL_AudioDeviceID device
Definition: loopwave.c:37
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioDeviceItem * outputDevices
Definition: SDL_sysaudio.h:124
#define NULL
Definition: begin_code.h:164
SDL_bool outputDevicesRemoved
Definition: SDL_sysaudio.h:121
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
void(* FreeDeviceHandle)(void *handle)
Definition: SDL_sysaudio.h:82
#define SDL_UnlockMutex
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:125

◆ SDL_RunAudio()

static int SDL_RunAudio ( void devicep)
static

Definition at line 643 of file SDL_audio.c.

References SDL_AudioDriverImpl::BeginLoopIteration, callback(), SDL_AudioSpec::callback, SDL_AudioDevice::callbackspec, device, SDL_AudioDevice::enabled, SDL_AudioSpec::freq, SDL_AudioDriverImpl::GetDeviceBuf, SDL_AudioDriver::impl, SDL_AudioDevice::iscapture, SDL_AudioDevice::mixer_lock, NULL, SDL_AudioDevice::paused, SDL_AudioDriverImpl::PlayDevice, SDL_AudioDriverImpl::PrepareToClose, SDL_AudioSpec::samples, SDL_assert, SDL_AtomicGet, SDL_AudioStreamAvailable, SDL_AudioStreamGet, SDL_AudioStreamPut, SDL_Delay, SDL_LockMutex, SDL_memset, SDL_SetThreadPriority, SDL_THREAD_PRIORITY_HIGH, SDL_ThreadID, SDL_UnlockMutex, SDLCALL, SDL_AudioDevice::shutdown, SDL_AudioSpec::silence, SDL_AudioSpec::size, SDL_AudioDevice::spec, SDL_AudioDevice::stream, SDL_AudioDriverImpl::ThreadDeinit, SDL_AudioDevice::threadid, SDL_AudioDriverImpl::ThreadInit, SDL_AudioSpec::userdata, SDL_AudioDriverImpl::WaitDevice, and SDL_AudioDevice::work_buffer.

Referenced by open_audio_device().

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)) {
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 
726 
727  /* Wait for the audio to drain. */
728  SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
729 
731 
732  return 0;
733 }
#define SDL_ThreadID
#define SDL_LockMutex
#define SDL_AudioStreamAvailable
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:158
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:147
Uint8 silence
Definition: SDL_audio.h:182
SDL_atomic_t paused
Definition: SDL_sysaudio.h:148
#define SDL_AudioStreamGet
SDL_atomic_t shutdown
Definition: SDL_sysaudio.h:146
void(* ThreadDeinit)(_THIS)
Definition: SDL_sysaudio.h:70
SDL_threadID threadid
Definition: SDL_sysaudio.h:162
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
Uint16 samples
Definition: SDL_audio.h:183
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_AudioSpec spec
Definition: SDL_sysaudio.h:137
uint32_t Uint32
Definition: SDL_stdinc.h:181
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* ThreadInit)(_THIS)
Definition: SDL_sysaudio.h:69
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.h:162
uint8_t Uint8
Definition: SDL_stdinc.h:157
void(* PrepareToClose)(_THIS)
Definition: SDL_sysaudio.h:78
SDL_bool iscapture
Definition: SDL_sysaudio.h:149
#define SDL_AudioStreamPut
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
SDL_AudioCallback callback
Definition: SDL_audio.h:186
#define SDL_Delay
Uint32 size
Definition: SDL_audio.h:185
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:75
#define SDL_AtomicGet
void * userdata
Definition: SDL_audio.h:187
void(* BeginLoopIteration)(_THIS)
Definition: SDL_sysaudio.h:71
#define SDL_UnlockMutex
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:140
SDL_AudioStream * stream
Definition: SDL_sysaudio.h:143
#define SDL_SetThreadPriority
Uint8 * work_buffer
Definition: SDL_sysaudio.h:152
#define SDL_memset

◆ SDL_UnlockAudio()

void SDL_UnlockAudio ( void  )

Definition at line 1509 of file SDL_audio.c.

References SDL_UnlockAudioDevice().

1510 {
1512 }
void SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1499

◆ SDL_UnlockAudioDevice()

void SDL_UnlockAudioDevice ( SDL_AudioDeviceID  devid)

Definition at line 1499 of file SDL_audio.c.

References device, get_audio_device(), SDL_AudioDriver::impl, and SDL_AudioDriverImpl::UnlockDevice.

Referenced by SDL_UnlockAudio().

1500 {
1501  /* Obtain a lock on the mixing buffers */
1503  if (device) {
1505  }
1506 }
static SDL_AudioDriver current_audio
Definition: SDL_audio.c:33
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_AudioDriverImpl impl
Definition: SDL_sysaudio.h:116
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:197

Variable Documentation

◆ bootstrap

const AudioBootStrap* const bootstrap[]
static

Definition at line 37 of file SDL_audio.c.

◆ current_audio

SDL_AudioDriver current_audio
static

Definition at line 33 of file SDL_audio.c.

◆ format_idx

int format_idx
static

Definition at line 1558 of file SDL_audio.c.

Referenced by SDL_FirstAudioFormat(), and SDL_NextAudioFormat().

◆ format_idx_sub

int format_idx_sub
static

Definition at line 1559 of file SDL_audio.c.

Referenced by SDL_FirstAudioFormat(), and SDL_NextAudioFormat().

◆ format_list

SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS]
static
Initial value:
= {
}
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
#define AUDIO_S8
Definition: SDL_audio.h:90
#define AUDIO_U16MSB
Definition: SDL_audio.h:93

Definition at line 1560 of file SDL_audio.c.

Referenced by SDL_FirstAudioFormat(), and SDL_NextAudioFormat().

◆ open_devices

SDL_AudioDevice* open_devices[16]
static

Definition at line 34 of file SDL_audio.c.