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 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

◆ FILL_STUB

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

◆ NUM_FORMATS

#define NUM_FORMATS   10

Definition at line 1620 of file SDL_audio.c.

Function Documentation

◆ add_audio_device()

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

Definition at line 374 of file SDL_audio.c.

375{
376 int retval = -1;
378 const SDL_AudioDeviceItem *i;
379 int dupenum = 0;
380
381 SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
382 SDL_assert(name != NULL);
383
385 if (!item) {
386 return SDL_OutOfMemory();
387 }
388
390 if (!item->original_name) {
391 SDL_free(item);
392 return SDL_OutOfMemory();
393 }
394
395 item->dupenum = 0;
396 item->name = item->original_name;
397 item->handle = handle;
398
400
401 for (i = *devices; i != NULL; i = i->next) {
402 if (SDL_strcmp(name, i->original_name) == 0) {
403 dupenum = i->dupenum + 1;
404 break; /* stop at the highest-numbered dupe. */
405 }
406 }
407
408 if (dupenum) {
409 const size_t len = SDL_strlen(name) + 16;
410 char *replacement = (char *) SDL_malloc(len);
411 if (!replacement) {
413 SDL_free(item->original_name);
414 SDL_free(item);
416 return -1;
417 }
418
419 SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
420 item->dupenum = dupenum;
421 item->name = replacement;
422 }
423
424 item->next = *devices;
425 *devices = item;
426 retval = (*devCount)++; /* !!! FIXME: this should be an atomic increment */
427
429
430 return retval;
431}
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_LockMutex
#define SDL_malloc
#define SDL_strlen
#define SDL_free
#define SDL_strdup
#define SDL_strcmp
#define SDL_snprintf
#define SDL_UnlockMutex
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
GLenum GLsizei len
GLuint const GLchar * name
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
EGLDeviceEXT * devices
Definition: eglext.h:621
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
struct SDL_AudioDeviceItem * next
Definition: SDL_sysaudio.h:103
SDL_mutex * detectionLock
Definition: SDL_sysaudio.h:120
SDL_bool retval

References current_audio, SDL_AudioDriver::detectionLock, SDL_AudioDeviceItem::dupenum, SDL_AudioDeviceItem::handle, i, SDL_AudioDeviceItem::name, SDL_AudioDeviceItem::next, NULL, SDL_AudioDeviceItem::original_name, retval, SDL_assert, SDL_free, SDL_LockMutex, SDL_malloc, SDL_OutOfMemory, SDL_snprintf, SDL_strcmp, SDL_strdup, SDL_strlen, and SDL_UnlockMutex.

Referenced by add_capture_device(), and add_output_device().

◆ add_capture_device()

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

Definition at line 434 of file SDL_audio.c.

435{
438}
static int add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:374
SDL_AudioDeviceItem * inputDevices
Definition: SDL_sysaudio.h:126

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

Referenced by SDL_AddAudioDevice().

◆ add_output_device()

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

◆ clean_out_device_list()

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

Definition at line 1012 of file SDL_audio.c.

1013{
1015 SDL_AudioDeviceItem *prev = NULL;
1016 int total = 0;
1017
1018 while (item) {
1019 SDL_AudioDeviceItem *next = item->next;
1020 if (item->handle != NULL) {
1021 total++;
1022 prev = item;
1023 } else {
1024 if (prev) {
1025 prev->next = next;
1026 } else {
1027 *devices = next;
1028 }
1029 /* these two pointers are the same if not a duplicate devname */
1030 if (item->name != item->original_name) {
1031 SDL_free(item->name);
1032 }
1033 SDL_free(item->original_name);
1034 SDL_free(item);
1035 }
1036 item = next;
1037 }
1038
1039 *devCount = total;
1040 *removedFlag = SDL_FALSE;
1041}
@ SDL_FALSE
Definition: SDL_stdinc.h:163

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

Referenced by SDL_GetNumAudioDevices().

◆ close_audio_device()

static void close_audio_device ( SDL_AudioDevice device)
static

Definition at line 1110 of file SDL_audio.c.

1111{
1112 if (!device) {
1113 return;
1114 }
1115
1116 /* make sure the device is paused before we do anything else, so the
1117 audio callback definitely won't fire again. */
1119 SDL_AtomicSet(&device->paused, 1);
1120 SDL_AtomicSet(&device->shutdown, 1);
1121 SDL_AtomicSet(&device->enabled, 0);
1123
1124 if (device->thread != NULL) {
1125 SDL_WaitThread(device->thread, NULL);
1126 }
1127 if (device->mixer_lock != NULL) {
1128 SDL_DestroyMutex(device->mixer_lock);
1129 }
1130
1131 SDL_free(device->work_buffer);
1132 SDL_FreeAudioStream(device->stream);
1133
1134 if (device->id > 0) {
1135 SDL_AudioDevice *opendev = open_devices[device->id - 1];
1136 SDL_assert((opendev == device) || (opendev == NULL));
1137 if (opendev == device) {
1138 open_devices[device->id - 1] = NULL;
1139 }
1140 }
1141
1142 if (device->hidden != NULL) {
1144 }
1145
1146 SDL_FreeDataQueue(device->buffer_queue);
1147
1149}
static SDL_AudioDevice * open_devices[16]
Definition: SDL_audio.c:34
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88
#define SDL_AtomicSet
#define SDL_FreeAudioStream
#define SDL_WaitThread
#define SDL_DestroyMutex
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:79

References SDL_AudioDriverImpl::CloseDevice, current_audio, device, SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, NULL, open_devices, SDL_assert, SDL_AtomicSet, SDL_DestroyMutex, SDL_free, SDL_FreeAudioStream, SDL_FreeDataQueue(), SDL_WaitThread, and SDL_AudioDriverImpl::UnlockDevice.

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

◆ finish_audio_entry_points_init()

static void finish_audio_entry_points_init ( void  )
static

Definition at line 331 of file SDL_audio.c.

332{
333 /*
334 * Fill in stub functions for unused driver entry points. This lets us
335 * blindly call them without having to check for validity first.
336 */
337
341 }
344 }
345 }
346
347#define FILL_STUB(x) \
348 if (current_audio.impl.x == NULL) { \
349 current_audio.impl.x = SDL_Audio##x##_Default; \
350 }
351 FILL_STUB(DetectDevices);
352 FILL_STUB(OpenDevice);
353 FILL_STUB(ThreadInit);
354 FILL_STUB(ThreadDeinit);
355 FILL_STUB(BeginLoopIteration);
356 FILL_STUB(WaitDevice);
357 FILL_STUB(PlayDevice);
358 FILL_STUB(GetDeviceBuf);
359 FILL_STUB(CaptureFromDevice);
360 FILL_STUB(FlushCapture);
361 FILL_STUB(PrepareToClose);
362 FILL_STUB(CloseDevice);
363 FILL_STUB(LockDevice);
364 FILL_STUB(UnlockDevice);
365 FILL_STUB(FreeDeviceHandle);
366 FILL_STUB(Deinitialize);
367#undef FILL_STUB
368}
static void SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice *device)
Definition: SDL_audio.c:326
#define FILL_STUB(x)

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

Referenced by SDL_AudioInit().

◆ free_device_list()

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

Definition at line 447 of file SDL_audio.c.

448{
449 SDL_AudioDeviceItem *item, *next;
450 for (item = *devices; item != NULL; item = next) {
451 next = item->next;
452 if (item->handle != NULL) {
454 }
455 /* these two pointers are the same if not a duplicate devname */
456 if (item->name != item->original_name) {
457 SDL_free(item->name);
458 }
459 SDL_free(item->original_name);
460 SDL_free(item);
461 }
462 *devices = NULL;
463 *devCount = 0;
464}
void(* FreeDeviceHandle)(void *handle)
Definition: SDL_sysaudio.h:81

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

Referenced by SDL_AudioQuit().

◆ get_audio_device()

static SDL_AudioDevice * get_audio_device ( SDL_AudioDeviceID  id)
static

Definition at line 200 of file SDL_audio.c.

201{
202 id--;
203 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
204 SDL_SetError("Invalid audio device ID");
205 return NULL;
206 }
207
208 return open_devices[id];
209}
#define SDL_SetError
GLuint id
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115

References NULL, open_devices, 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().

◆ is_in_audio_device_thread()

static SDL_INLINE SDL_bool is_in_audio_device_thread ( SDL_AudioDevice device)
static

Definition at line 296 of file SDL_audio.c.

297{
298 /* The device thread locks the same mutex, but not through the public API.
299 This check is in case the application, in the audio callback,
300 tries to lock the thread that we've already locked from the
301 device thread...just in case we only have non-recursive mutexes. */
302 if (device->thread && (SDL_ThreadID() == device->threadid)) {
303 return SDL_TRUE;
304 }
305
306 return SDL_FALSE;
307}
#define SDL_ThreadID
@ SDL_TRUE
Definition: SDL_stdinc.h:164

References device, SDL_FALSE, SDL_ThreadID, and SDL_TRUE.

Referenced by SDL_AudioLockDevice_Default(), and SDL_AudioUnlockDevice_Default().

◆ mark_device_removed()

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

Definition at line 516 of file SDL_audio.c.

517{
520 for (item = devices; item != NULL; item = item->next) {
521 if (item->handle == handle) {
522 item->handle = NULL;
523 *removedFlag = SDL_TRUE;
524 return;
525 }
526 }
527}

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

Referenced by SDL_RemoveAudioDevice().

◆ 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 1216 of file SDL_audio.c.

1219{
1220 const SDL_bool is_internal_thread = (desired->callback == NULL);
1221 SDL_AudioDeviceID id = 0;
1222 SDL_AudioSpec _obtained;
1224 SDL_bool build_stream;
1225 void *handle = NULL;
1226 int i = 0;
1227
1229 SDL_SetError("Audio subsystem is not initialized");
1230 return 0;
1231 }
1232
1233 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1234 SDL_SetError("No capture support");
1235 return 0;
1236 }
1237
1238 /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
1239 /* Find an available device ID... */
1240 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
1241 if (open_devices[id] == NULL) {
1242 break;
1243 }
1244 }
1245
1246 if (id == SDL_arraysize(open_devices)) {
1247 SDL_SetError("Too many open audio devices");
1248 return 0;
1249 }
1250
1251 if (!obtained) {
1252 obtained = &_obtained;
1253 }
1254 if (!prepare_audiospec(desired, obtained)) {
1255 return 0;
1256 }
1257
1258 /* If app doesn't care about a specific device, let the user override. */
1259 if (devname == NULL) {
1260 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1261 }
1262
1263 /*
1264 * Catch device names at the high level for the simple case...
1265 * This lets us have a basic "device enumeration" for systems that
1266 * don't have multiple devices, but makes sure the device name is
1267 * always NULL when it hits the low level.
1268 *
1269 * Also make sure that the simple case prevents multiple simultaneous
1270 * opens of the default system device.
1271 */
1272
1273 if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
1274 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1275 SDL_SetError("No such device");
1276 return 0;
1277 }
1278 devname = NULL;
1279
1280 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1281 if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1282 SDL_SetError("Audio device already open");
1283 return 0;
1284 }
1285 }
1286 } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1287 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1288 SDL_SetError("No such device");
1289 return 0;
1290 }
1291 devname = NULL;
1292
1293 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1294 if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1295 SDL_SetError("Audio device already open");
1296 return 0;
1297 }
1298 }
1299 } else if (devname != NULL) {
1300 /* if the app specifies an exact string, we can pass the backend
1301 an actual device handle thingey, which saves them the effort of
1302 figuring out what device this was (such as, reenumerating
1303 everything again to find the matching human-readable name).
1304 It might still need to open a device based on the string for,
1305 say, a network audio server, but this optimizes some cases. */
1306 SDL_AudioDeviceItem *item;
1308 for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1309 if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1310 handle = item->handle;
1311 break;
1312 }
1313 }
1315 }
1316
1318 /* has to be in our device list, or the default device. */
1319 if ((handle == NULL) && (devname != NULL)) {
1320 SDL_SetError("No such device.");
1321 return 0;
1322 }
1323 }
1324
1326 if (device == NULL) {
1328 return 0;
1329 }
1330 device->id = id + 1;
1331 device->spec = *obtained;
1332 device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
1333 device->handle = handle;
1334
1335 SDL_AtomicSet(&device->shutdown, 0); /* just in case. */
1336 SDL_AtomicSet(&device->paused, 1);
1337 SDL_AtomicSet(&device->enabled, 1);
1338
1339 /* Create a mutex for locking the sound buffers */
1341 device->mixer_lock = SDL_CreateMutex();
1342 if (device->mixer_lock == NULL) {
1344 SDL_SetError("Couldn't create mixer lock");
1345 return 0;
1346 }
1347 }
1348
1349 if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1351 return 0;
1352 }
1353
1354 /* if your target really doesn't need it, set it to 0x1 or something. */
1355 /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
1356 SDL_assert(device->hidden != NULL);
1357
1358 /* See if we need to do any conversion */
1359 build_stream = SDL_FALSE;
1360 if (obtained->freq != device->spec.freq) {
1361 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1362 obtained->freq = device->spec.freq;
1363 } else {
1364 build_stream = SDL_TRUE;
1365 }
1366 }
1367 if (obtained->format != device->spec.format) {
1368 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1369 obtained->format = device->spec.format;
1370 } else {
1371 build_stream = SDL_TRUE;
1372 }
1373 }
1374 if (obtained->channels != device->spec.channels) {
1375 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1376 obtained->channels = device->spec.channels;
1377 } else {
1378 build_stream = SDL_TRUE;
1379 }
1380 }
1381 if (device->spec.samples != obtained->samples) {
1382 if (allowed_changes & SDL_AUDIO_ALLOW_SAMPLES_CHANGE) {
1383 obtained->samples = device->spec.samples;
1384 } else {
1385 build_stream = SDL_TRUE;
1386 }
1387 }
1388
1389 SDL_CalculateAudioSpec(obtained); /* recalc after possible changes. */
1390
1391 device->callbackspec = *obtained;
1392
1393 if (build_stream) {
1394 if (iscapture) {
1395 device->stream = SDL_NewAudioStream(device->spec.format,
1396 device->spec.channels, device->spec.freq,
1397 obtained->format, obtained->channels, obtained->freq);
1398 } else {
1399 device->stream = SDL_NewAudioStream(obtained->format, obtained->channels,
1400 obtained->freq, device->spec.format,
1401 device->spec.channels, device->spec.freq);
1402 }
1403
1404 if (!device->stream) {
1406 return 0;
1407 }
1408 }
1409
1410 if (device->spec.callback == NULL) { /* use buffer queueing? */
1411 /* pool a few packets to start. Enough for two callbacks. */
1412 device->buffer_queue = SDL_NewDataQueue(SDL_AUDIOBUFFERQUEUE_PACKETLEN, obtained->size * 2);
1413 if (!device->buffer_queue) {
1415 SDL_SetError("Couldn't create audio buffer queue");
1416 return 0;
1417 }
1418 device->callbackspec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
1419 device->callbackspec.userdata = device;
1420 }
1421
1422 /* Allocate a scratch audio buffer */
1423 device->work_buffer_len = build_stream ? device->callbackspec.size : 0;
1424 if (device->spec.size > device->work_buffer_len) {
1425 device->work_buffer_len = device->spec.size;
1426 }
1427 SDL_assert(device->work_buffer_len > 0);
1428
1429 device->work_buffer = (Uint8 *) SDL_malloc(device->work_buffer_len);
1430 if (device->work_buffer == NULL) {
1433 return 0;
1434 }
1435
1436 open_devices[id] = device; /* add it to our list of open devices. */
1437
1438 /* Start the audio thread if necessary */
1440 /* Start the audio thread */
1441 /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
1442 /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
1443 const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
1444 char threadname[64];
1445
1446 SDL_snprintf(threadname, sizeof (threadname), "SDLAudio%c%d", (iscapture) ? 'C' : 'P', (int) device->id);
1447 device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
1448
1449 if (device->thread == NULL) {
1451 SDL_SetError("Couldn't create audio thread");
1452 return 0;
1453 }
1454 }
1455
1456 return device->id;
1457}
#define SDL_INIT_AUDIO
Definition: SDL.h:78
static int SDL_RunAudio(void *devicep)
Definition: SDL_audio.c:682
static void SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:582
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1668
static void close_audio_device(SDL_AudioDevice *device)
Definition: SDL_audio.c:1110
static int prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
Definition: SDL_audio.c:1158
static void SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.c:561
static int SDL_CaptureAudio(void *devicep)
Definition: SDL_audio.c:785
#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE
Definition: SDL_audio.h:143
#define SDL_AUDIO_ALLOW_FORMAT_CHANGE
Definition: SDL_audio.h:141
#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
Definition: SDL_audio.h:140
#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE
Definition: SDL_audio.h:142
Uint32 SDL_AudioDeviceID
Definition: SDL_audio.h:330
SDL_DataQueue * SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack)
Definition: SDL_dataqueue.c:58
#define SDL_NewAudioStream
#define SDL_WasInit
#define SDL_getenv
#define SDL_CreateMutex
#define SDL_calloc
SDL_bool
Definition: SDL_stdinc.h:162
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define DEFAULT_OUTPUT_DEVNAME
Definition: SDL_sysaudio.h:32
#define DEFAULT_INPUT_DEVNAME
Definition: SDL_sysaudio.h:33
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN
Definition: SDL_sysaudio.h:63
SDL_Thread * SDL_CreateThreadInternal(int(*fn)(void *), const char *name, const size_t stacksize, void *data)
Definition: SDL_thread.c:429
SDL_bool iscapture
Definition: SDL_sysaudio.h:150
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint32 size
Definition: SDL_audio.h:186
SDL_AudioCallback callback
Definition: SDL_audio.h:187
Uint16 samples
Definition: SDL_audio.h:184
Uint8 channels
Definition: SDL_audio.h:182
SDL_AudioFormat format
Definition: SDL_audio.h:181

References SDL_AudioDriverImpl::AllowsArbitraryDeviceNames, SDL_AudioSpec::callback, SDL_AudioSpec::channels, close_audio_device(), current_audio, DEFAULT_INPUT_DEVNAME, DEFAULT_OUTPUT_DEVNAME, SDL_AudioDriver::detectionLock, device, SDL_AudioSpec::format, SDL_AudioSpec::freq, SDL_AudioDeviceItem::handle, SDL_AudioDriverImpl::HasCaptureSupport, i, SDL_AudioDriver::impl, SDL_AudioDriver::inputDevices, SDL_AudioDevice::iscapture, SDL_AudioDeviceItem::name, SDL_AudioDeviceItem::next, NULL, SDL_AudioDriverImpl::OnlyHasDefaultCaptureDevice, SDL_AudioDriverImpl::OnlyHasDefaultOutputDevice, open_devices, SDL_AudioDriverImpl::OpenDevice, SDL_AudioDriver::outputDevices, 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_AUDIO_ALLOW_SAMPLES_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_AudioSpec::size, and SDL_AudioDriverImpl::SkipMixerLock.

Referenced by SDL_OpenAudio(), and SDL_OpenAudioDevice().

◆ prepare_audiospec()

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

Definition at line 1158 of file SDL_audio.c.

1159{
1160 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
1161
1162 if (orig->freq == 0) {
1163 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
1164 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
1165 prepared->freq = 22050; /* a reasonable default */
1166 }
1167 }
1168
1169 if (orig->format == 0) {
1170 const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
1171 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
1172 prepared->format = AUDIO_S16; /* a reasonable default */
1173 }
1174 }
1175
1176 switch (orig->channels) {
1177 case 0:{
1178 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
1179 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
1180 prepared->channels = 2; /* a reasonable default */
1181 }
1182 break;
1183 }
1184 case 1: /* Mono */
1185 case 2: /* Stereo */
1186 case 4: /* Quadrophonic */
1187 case 6: /* 5.1 surround */
1188 case 8: /* 7.1 surround */
1189 break;
1190 default:
1191 SDL_SetError("Unsupported number of audio channels.");
1192 return 0;
1193 }
1194
1195 if (orig->samples == 0) {
1196 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
1197 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
1198 /* Pick a default of ~46 ms at desired frequency */
1199 /* !!! FIXME: remove this when the non-Po2 resampling is in. */
1200 const int samples = (prepared->freq / 1000) * 46;
1201 int power2 = 1;
1202 while (power2 < samples) {
1203 power2 *= 2;
1204 }
1205 prepared->samples = power2;
1206 }
1207 }
1208
1209 /* Calculate the silence and size of the audio specification */
1210 SDL_CalculateAudioSpec(prepared);
1211
1212 return 1;
1213}
static SDL_AudioFormat SDL_ParseAudioFormat(const char *string)
Definition: SDL_audio.c:899
#define AUDIO_S16
Definition: SDL_audio.h:96
#define SDL_memcpy
#define SDL_atoi
GLsizei samples
uint16_t Uint16
Definition: SDL_stdinc.h:191

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().

◆ SDL_AddAudioDevice()

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

Definition at line 469 of file SDL_audio.c.

470{
471 const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
472 if (device_index != -1) {
473 /* Post the event, if desired */
477 event.adevice.type = SDL_AUDIODEVICEADDED;
478 event.adevice.which = device_index;
479 event.adevice.iscapture = iscapture;
481 }
482 }
483}
static SDL_INLINE int add_capture_device(const char *name, void *handle)
Definition: SDL_audio.c:434
static SDL_INLINE int add_output_device(const char *name, void *handle)
Definition: SDL_audio.c:441
#define SDL_PushEvent
@ SDL_AUDIODEVICEADDED
Definition: SDL_events.h:147
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
#define SDL_ENABLE
Definition: SDL_events.h:759
struct _cl_event * event
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
General event structure.
Definition: SDL_events.h:558

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

Referenced by SDL_AudioDetectDevices_Default().

◆ SDL_AudioBeginLoopIteration_Default()

static void SDL_AudioBeginLoopIteration_Default ( _THIS  )
static

Definition at line 237 of file SDL_audio.c.

238{ /* no-op. */
239}

◆ SDL_AudioCaptureFromDevice_Default()

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

Definition at line 258 of file SDL_audio.c.

259{
260 return -1; /* just fail immediately. */
261}

◆ SDL_AudioCloseDevice_Default()

static void SDL_AudioCloseDevice_Default ( _THIS  )
static

Definition at line 274 of file SDL_audio.c.

275{ /* no-op. */
276}

◆ SDL_AudioDeinitialize_Default()

static void SDL_AudioDeinitialize_Default ( void  )
static

Definition at line 279 of file SDL_audio.c.

280{ /* no-op. */
281}

◆ SDL_AudioDetectDevices_Default()

static void SDL_AudioDetectDevices_Default ( void  )
static

◆ SDL_AudioFlushCapture_Default()

static void SDL_AudioFlushCapture_Default ( _THIS  )
static

Definition at line 264 of file SDL_audio.c.

265{ /* no-op. */
266}

◆ SDL_AudioFreeDeviceHandle_Default()

static void SDL_AudioFreeDeviceHandle_Default ( void handle)
static

Definition at line 284 of file SDL_audio.c.

285{ /* no-op. */
286}

◆ SDL_AudioGetDeviceBuf_Default()

static Uint8 * SDL_AudioGetDeviceBuf_Default ( _THIS  )
static

Definition at line 252 of file SDL_audio.c.

253{
254 return NULL;
255}

References NULL.

◆ SDL_AudioInit()

int SDL_AudioInit ( const char *  driver_name)

Definition at line 940 of file SDL_audio.c.

941{
942 int i = 0;
943 int initialized = 0;
944 int tried_to_init = 0;
945
947 SDL_AudioQuit(); /* shutdown driver if already running. */
948 }
949
952
953 /* Select the proper audio driver */
954 if (driver_name == NULL) {
955 driver_name = SDL_getenv("SDL_AUDIODRIVER");
956 }
957
958 for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
959 /* make sure we should even try this driver before doing so... */
960 const AudioBootStrap *backend = bootstrap[i];
961 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
962 (!driver_name && backend->demand_only)) {
963 continue;
964 }
965
966 tried_to_init = 1;
968 current_audio.name = backend->name;
969 current_audio.desc = backend->desc;
970 initialized = backend->init(&current_audio.impl);
971 }
972
973 if (!initialized) {
974 /* specific drivers will set the error message if they fail... */
975 if (!tried_to_init) {
976 if (driver_name) {
977 SDL_SetError("Audio target '%s' not available", driver_name);
978 } else {
979 SDL_SetError("No available audio device");
980 }
981 }
982
984 return -1; /* No driver was available, so fail. */
985 }
986
988
990
991 /* Make sure we have a list of devices available at startup. */
993
994#ifdef HAVE_LIBSAMPLERATE_H
995 LoadLibSampleRate();
996#endif
997
998 return 0;
999}
void SDL_AudioQuit(void)
Definition: SDL_audio.c:1590
static void finish_audio_entry_points_init(void)
Definition: SDL_audio.c:331
static const AudioBootStrap *const bootstrap[]
Definition: SDL_audio.c:37
#define SDL_strncasecmp
const char * name
Definition: SDL_sysaudio.h:178
const char * desc
Definition: SDL_sysaudio.h:179
int(* init)(SDL_AudioDriverImpl *impl)
Definition: SDL_sysaudio.h:180
const char * name
Definition: SDL_sysaudio.h:111
const char * desc
Definition: SDL_sysaudio.h:115
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67

References bootstrap, current_audio, 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, open_devices, SDL_AudioQuit(), SDL_CreateMutex, SDL_getenv, SDL_INIT_AUDIO, SDL_SetError, SDL_strlen, SDL_strncasecmp, SDL_WasInit, and SDL_zero.

◆ SDL_AudioLockDevice_Default()

static void SDL_AudioLockDevice_Default ( SDL_AudioDevice device)
static

Definition at line 310 of file SDL_audio.c.

311{
313 SDL_LockMutex(device->mixer_lock);
314 }
315}
static SDL_INLINE SDL_bool is_in_audio_device_thread(SDL_AudioDevice *device)
Definition: SDL_audio.c:296

References device, is_in_audio_device_thread(), and SDL_LockMutex.

◆ SDL_AudioLockOrUnlockDeviceWithNoMixerLock()

static void SDL_AudioLockOrUnlockDeviceWithNoMixerLock ( SDL_AudioDevice device)
static

Definition at line 326 of file SDL_audio.c.

327{
328}

Referenced by finish_audio_entry_points_init().

◆ SDL_AudioOpenDevice_Default()

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

Definition at line 290 of file SDL_audio.c.

291{
292 return SDL_Unsupported();
293}
#define SDL_Unsupported()
Definition: SDL_error.h:53

References SDL_Unsupported.

◆ SDL_AudioPlayDevice_Default()

static void SDL_AudioPlayDevice_Default ( _THIS  )
static

Definition at line 247 of file SDL_audio.c.

248{ /* no-op. */
249}

◆ SDL_AudioPrepareToClose_Default()

static void SDL_AudioPrepareToClose_Default ( _THIS  )
static

Definition at line 269 of file SDL_audio.c.

270{ /* no-op. */
271}

◆ SDL_AudioQuit()

void SDL_AudioQuit ( void  )

Definition at line 1590 of file SDL_audio.c.

1591{
1593
1594 if (!current_audio.name) { /* not initialized?! */
1595 return;
1596 }
1597
1598 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1600 }
1601
1604
1605 /* Free the driver data */
1607
1609
1612
1613#ifdef HAVE_LIBSAMPLERATE_H
1614 UnloadLibSampleRate();
1615#endif
1616
1618}
static void free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
Definition: SDL_audio.c:447
void SDL_FreeResampleFilter(void)
Definition: SDL_audiocvt.c:464
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82

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

Referenced by SDL_AudioInit().

◆ SDL_AudioThreadDeinit_Default()

static void SDL_AudioThreadDeinit_Default ( _THIS  )
static

Definition at line 232 of file SDL_audio.c.

233{ /* no-op. */
234}

◆ SDL_AudioThreadInit_Default()

static void SDL_AudioThreadInit_Default ( _THIS  )
static

Definition at line 227 of file SDL_audio.c.

228{ /* no-op. */
229}

◆ SDL_AudioUnlockDevice_Default()

static void SDL_AudioUnlockDevice_Default ( SDL_AudioDevice device)
static

Definition at line 318 of file SDL_audio.c.

319{
321 SDL_UnlockMutex(device->mixer_lock);
322 }
323}

References device, is_in_audio_device_thread(), and SDL_UnlockMutex.

◆ SDL_AudioWaitDevice_Default()

static void SDL_AudioWaitDevice_Default ( _THIS  )
static

Definition at line 242 of file SDL_audio.c.

243{ /* no-op. */
244}

◆ SDL_BufferQueueDrainCallback()

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

Definition at line 561 of file SDL_audio.c.

562{
563 /* this function always holds the mixer lock before being called. */
564 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
565 size_t dequeued;
566
567 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
568 SDL_assert(!device->iscapture); /* this shouldn't ever happen, right?! */
569 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
570
571 dequeued = SDL_ReadFromDataQueue(device->buffer_queue, stream, len);
572 stream += dequeued;
573 len -= (int) dequeued;
574
575 if (len > 0) { /* fill any remaining space in the stream with silence. */
576 SDL_assert(SDL_CountDataQueue(device->buffer_queue) == 0);
577 SDL_memset(stream, device->spec.silence, len);
578 }
579}
size_t SDL_CountDataQueue(SDL_DataQueue *queue)
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
#define SDL_memset
GLuint GLuint stream

References device, NULL, SDL_assert, SDL_CountDataQueue(), SDL_memset, and SDL_ReadFromDataQueue().

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

◆ SDL_BufferQueueFillCallback()

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

Definition at line 582 of file SDL_audio.c.

583{
584 /* this function always holds the mixer lock before being called. */
585 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
586
587 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
588 SDL_assert(device->iscapture); /* this shouldn't ever happen, right?! */
589 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
590
591 /* note that if this needs to allocate more space and run out of memory,
592 we have no choice but to quietly drop the data and hope it works out
593 later, but you probably have bigger problems in this case anyhow. */
594 SDL_WriteToDataQueue(device->buffer_queue, stream, len);
595}
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)

References device, NULL, SDL_assert, and SDL_WriteToDataQueue().

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

◆ SDL_CalculateAudioSpec()

void SDL_CalculateAudioSpec ( SDL_AudioSpec spec)

Definition at line 1668 of file SDL_audio.c.

1669{
1670 switch (spec->format) {
1671 case AUDIO_U8:
1672 spec->silence = 0x80;
1673 break;
1674 default:
1675 spec->silence = 0x00;
1676 break;
1677 }
1679 spec->size *= spec->channels;
1680 spec->size *= spec->samples;
1681}
#define AUDIO_U8
Definition: SDL_audio.h:89
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
SDL_AudioSpec spec
Definition: loopwave.c:31
Uint8 silence
Definition: SDL_audio.h:183

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

Referenced by open_audio_device(), and prepare_audiospec().

◆ SDL_CaptureAudio()

static int SDL_CaptureAudio ( void devicep)
static

Definition at line 785 of file SDL_audio.c.

786{
788 const int silence = (int) device->spec.silence;
789 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
790 const int data_len = device->spec.size;
791 Uint8 *data;
792 void *udata = device->callbackspec.userdata;
793 SDL_AudioCallback callback = device->callbackspec.callback;
794
795 SDL_assert(device->iscapture);
796
797#if SDL_AUDIO_DRIVER_ANDROID
798 {
799 /* Set thread priority to THREAD_PRIORITY_AUDIO */
800 extern void Android_JNI_AudioSetThreadPriority(int, int);
802 }
803#else
804 /* The audio mixing is always a high priority thread */
806#endif
807
808 /* Perform any thread setup */
809 device->threadid = SDL_ThreadID();
811
812 /* Loop, filling the audio buffers */
813 while (!SDL_AtomicGet(&device->shutdown)) {
814 int still_need;
815 Uint8 *ptr;
816
818
819 if (SDL_AtomicGet(&device->paused)) {
820 SDL_Delay(delay); /* just so we don't cook the CPU. */
821 if (device->stream) {
823 }
824 current_audio.impl.FlushCapture(device); /* dump anything pending. */
825 continue;
826 }
827
828 /* Fill the current buffer with sound */
829 still_need = data_len;
830
831 /* Use the work_buffer to hold data read from the device. */
832 data = device->work_buffer;
833 SDL_assert(data != NULL);
834
835 ptr = data;
836
837 /* We still read from the device when "paused" to keep the state sane,
838 and block when there isn't data so this thread isn't eating CPU.
839 But we don't process it further or call the app's callback. */
840
841 if (!SDL_AtomicGet(&device->enabled)) {
842 SDL_Delay(delay); /* try to keep callback firing at normal pace. */
843 } else {
844 while (still_need > 0) {
845 const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
846 SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */
847 if (rc > 0) {
848 still_need -= rc;
849 ptr += rc;
850 } else { /* uhoh, device failed for some reason! */
852 break;
853 }
854 }
855 }
856
857 if (still_need > 0) {
858 /* Keep any data we already read, silence the rest. */
859 SDL_memset(ptr, silence, still_need);
860 }
861
862 if (device->stream) {
863 /* if this fails...oh well. */
864 SDL_AudioStreamPut(device->stream, data, data_len);
865
866 while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->callbackspec.size)) {
867 const int got = SDL_AudioStreamGet(device->stream, device->work_buffer, device->callbackspec.size);
868 SDL_assert((got < 0) || (got == device->callbackspec.size));
869 if (got != device->callbackspec.size) {
870 SDL_memset(device->work_buffer, device->spec.silence, device->callbackspec.size);
871 }
872
873 /* !!! FIXME: this should be LockDevice. */
874 SDL_LockMutex(device->mixer_lock);
875 if (!SDL_AtomicGet(&device->paused)) {
876 callback(udata, device->work_buffer, device->callbackspec.size);
877 }
878 SDL_UnlockMutex(device->mixer_lock);
879 }
880 } else { /* feeding user callback directly without streaming. */
881 /* !!! FIXME: this should be LockDevice. */
882 SDL_LockMutex(device->mixer_lock);
883 if (!SDL_AtomicGet(&device->paused)) {
884 callback(udata, data, device->callbackspec.size);
885 }
886 SDL_UnlockMutex(device->mixer_lock);
887 }
888 }
889
891
893
894 return 0;
895}
void Android_JNI_AudioSetThreadPriority(int iscapture, int device_id)
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:486
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.h:163
#define SDL_AudioStreamGet
#define SDL_SetThreadPriority
#define SDL_AudioStreamClear
#define SDL_AudioStreamAvailable
#define SDL_AudioStreamPut
#define SDL_Delay
#define SDL_AtomicGet
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
uint32_t Uint32
Definition: SDL_stdinc.h:203
@ SDL_THREAD_PRIORITY_HIGH
Definition: SDL_thread.h:62
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:76
void(* ThreadDeinit)(_THIS)
Definition: SDL_sysaudio.h:70
void(* BeginLoopIteration)(_THIS)
Definition: SDL_sysaudio.h:71
void(* ThreadInit)(_THIS)
Definition: SDL_sysaudio.h:69
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34

References Android_JNI_AudioSetThreadPriority(), SDL_AudioDriverImpl::BeginLoopIteration, callback(), SDL_AudioDriverImpl::CaptureFromDevice, current_audio, device, SDL_AudioDriverImpl::FlushCapture, SDL_AudioDriver::impl, NULL, 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_AudioDriverImpl::ThreadDeinit, and SDL_AudioDriverImpl::ThreadInit.

Referenced by open_audio_device().

◆ 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 662 of file SDL_audio.c.

663{
665
666 if (!device) {
667 return; /* nothing to do. */
668 }
669
670 /* Blank out the device and release the mutex. Free it afterwards. */
672
673 /* Keep up to two packets in the pool to reduce future malloc pressure. */
675
677}
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Definition: SDL_audio.c:200
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98

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

◆ SDL_CloseAudio()

void SDL_CloseAudio ( void  )

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

Definition at line 1584 of file SDL_audio.c.

1585{
1587}
void SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1578

References SDL_CloseAudioDevice().

◆ SDL_CloseAudioDevice()

void SDL_CloseAudioDevice ( SDL_AudioDeviceID  devid)

Definition at line 1578 of file SDL_audio.c.

1579{
1581}

References close_audio_device(), and get_audio_device().

Referenced by SDL_CloseAudio().

◆ 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 621 of file SDL_audio.c.

622{
624 Uint32 rc;
625
626 if ( (len == 0) || /* nothing to do? */
627 (!device) || /* called with bogus device id */
628 (!device->iscapture) || /* playback devices can't dequeue */
629 (device->callbackspec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
630 return 0; /* just report zero bytes dequeued. */
631 }
632
634 rc = (Uint32) SDL_ReadFromDataQueue(device->buffer_queue, data, len);
636 return rc;
637}

References current_audio, device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, SDL_BufferQueueFillCallback(), SDL_ReadFromDataQueue(), and SDL_AudioDriverImpl::UnlockDevice.

◆ SDL_FirstAudioFormat()

SDL_AudioFormat SDL_FirstAudioFormat ( SDL_AudioFormat  format)

Definition at line 1647 of file SDL_audio.c.

1648{
1650 if (format_list[format_idx][0] == format) {
1651 break;
1652 }
1653 }
1654 format_idx_sub = 0;
1655 return SDL_NextAudioFormat();
1656}
static int format_idx_sub
Definition: SDL_audio.c:1622
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS]
Definition: SDL_audio.c:1623
#define NUM_FORMATS
Definition: SDL_audio.c:1620
static int format_idx
Definition: SDL_audio.c:1621
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572

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

◆ 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 1070 of file SDL_audio.c.

1071{
1072 const char *retval = NULL;
1073
1075 SDL_SetError("Audio subsystem is not initialized");
1076 return NULL;
1077 }
1078
1079 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1080 SDL_SetError("No capture support");
1081 return NULL;
1082 }
1083
1084 if (index >= 0) {
1085 SDL_AudioDeviceItem *item;
1086 int i;
1087
1091 if (index < i) {
1092 for (i--; i > index; i--, item = item->next) {
1093 SDL_assert(item != NULL);
1094 }
1095 SDL_assert(item != NULL);
1096 retval = item->name;
1097 }
1099 }
1100
1101 if (retval == NULL) {
1102 SDL_SetError("No such device");
1103 }
1104
1105 return retval;
1106}
GLuint index

References current_audio, 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.

◆ SDL_GetAudioDeviceStatus()

SDL_AudioStatus SDL_GetAudioDeviceStatus ( SDL_AudioDeviceID  devid)

Definition at line 1506 of file SDL_audio.c.

1507{
1510 if (device && SDL_AtomicGet(&device->enabled)) {
1511 if (SDL_AtomicGet(&device->paused)) {
1512 status = SDL_AUDIO_PAUSED;
1513 } else {
1514 status = SDL_AUDIO_PLAYING;
1515 }
1516 }
1517 return status;
1518}
SDL_AudioStatus
Definition: SDL_audio.h:396
@ SDL_AUDIO_STOPPED
Definition: SDL_audio.h:397
@ SDL_AUDIO_PLAYING
Definition: SDL_audio.h:398
@ SDL_AUDIO_PAUSED
Definition: SDL_audio.h:399

References device, get_audio_device(), SDL_AtomicGet, SDL_AUDIO_PAUSED, SDL_AUDIO_PLAYING, and SDL_AUDIO_STOPPED.

Referenced by SDL_GetAudioStatus().

◆ SDL_GetAudioDriver()

const char * SDL_GetAudioDriver ( int  index)

Definition at line 931 of file SDL_audio.c.

932{
933 if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
934 return bootstrap[index]->name;
935 }
936 return NULL;
937}
int SDL_GetNumAudioDrivers(void)
Definition: SDL_audio.c:925

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

◆ SDL_GetAudioStatus()

SDL_AudioStatus SDL_GetAudioStatus ( void  )

Definition at line 1522 of file SDL_audio.c.

1523{
1524 return SDL_GetAudioDeviceStatus(1);
1525}
SDL_AudioStatus SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1506

References SDL_GetAudioDeviceStatus().

◆ 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 1005 of file SDL_audio.c.

1006{
1007 return current_audio.name;
1008}

References current_audio, and SDL_AudioDriver::name.

◆ 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 1045 of file SDL_audio.c.

1046{
1047 int retval = 0;
1048
1050 return -1;
1051 }
1052
1054 if (iscapture && current_audio.captureDevicesRemoved) {
1056 }
1057
1058 if (!iscapture && current_audio.outputDevicesRemoved) {
1060 }
1061
1064
1065 return retval;
1066}
static void clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
Definition: SDL_audio.c:1012
SDL_bool captureDevicesRemoved
Definition: SDL_sysaudio.h:121
SDL_bool outputDevicesRemoved
Definition: SDL_sysaudio.h:122

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

◆ SDL_GetNumAudioDrivers()

int SDL_GetNumAudioDrivers ( void  )

Definition at line 925 of file SDL_audio.c.

926{
927 return SDL_arraysize(bootstrap) - 1;
928}

References bootstrap, and SDL_arraysize.

Referenced by SDL_GetAudioDriver().

◆ 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 640 of file SDL_audio.c.

641{
642 Uint32 retval = 0;
644
645 if (!device) {
646 return 0;
647 }
648
649 /* Nothing to do unless we're set up for queueing. */
650 if (device->callbackspec.callback == SDL_BufferQueueDrainCallback ||
651 device->callbackspec.callback == SDL_BufferQueueFillCallback)
652 {
654 retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
656 }
657
658 return retval;
659}

References current_audio, device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, retval, SDL_BufferQueueDrainCallback(), SDL_BufferQueueFillCallback(), SDL_CountDataQueue(), and SDL_AudioDriverImpl::UnlockDevice.

◆ SDL_LockAudio()

void SDL_LockAudio ( void  )

Definition at line 1556 of file SDL_audio.c.

1557{
1559}
void SDL_LockAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1546

References SDL_LockAudioDevice().

◆ SDL_LockAudioDevice()

void SDL_LockAudioDevice ( SDL_AudioDeviceID  devid)

Definition at line 1546 of file SDL_audio.c.

1547{
1548 /* Obtain a lock on the mixing buffers */
1550 if (device) {
1552 }
1553}

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

Referenced by SDL_LockAudio().

◆ 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 1689 of file SDL_audio.c.

1690{
1691 /* Mix the user-level audio format */
1693 if (device != NULL) {
1694 SDL_MixAudioFormat(dst, src, device->callbackspec.format, len, volume);
1695 }
1696}
#define SDL_MixAudioFormat
GLenum src
GLenum GLenum dst

References device, get_audio_device(), NULL, and SDL_MixAudioFormat.

◆ SDL_NextAudioFormat()

SDL_AudioFormat SDL_NextAudioFormat ( void  )

Definition at line 1659 of file SDL_audio.c.

1660{
1662 return 0;
1663 }
1665}

References format_idx, format_idx_sub, format_list, and NUM_FORMATS.

Referenced by SDL_FirstAudioFormat().

◆ 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 1461 of file SDL_audio.c.

1462{
1463 SDL_AudioDeviceID id = 0;
1464
1465 /* Start up the audio driver, if necessary. This is legacy behaviour! */
1468 return -1;
1469 }
1470 }
1471
1472 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1473 if (open_devices[0] != NULL) {
1474 SDL_SetError("Audio device is already opened");
1475 return -1;
1476 }
1477
1478 if (obtained) {
1479 id = open_audio_device(NULL, 0, desired, obtained,
1481 } else {
1482 SDL_AudioSpec _obtained;
1483 SDL_zero(_obtained);
1484 id = open_audio_device(NULL, 0, desired, &_obtained, 0, 1);
1485 /* On successful open, copy calculated values into 'desired'. */
1486 if (id > 0) {
1487 desired->size = _obtained.size;
1488 desired->silence = _obtained.silence;
1489 }
1490 }
1491
1492 SDL_assert((id == 0) || (id == 1));
1493 return (id == 0) ? -1 : 0;
1494}
static SDL_AudioDeviceID open_audio_device(const char *devname, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes, int min_id)
Definition: SDL_audio.c:1216
#define SDL_AUDIO_ALLOW_ANY_CHANGE
Definition: SDL_audio.h:144
#define SDL_InitSubSystem

References NULL, open_audio_device(), open_devices, 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.

◆ 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 1497 of file SDL_audio.c.

1500{
1501 return open_audio_device(device, iscapture, desired, obtained,
1502 allowed_changes, 2);
1503}

References device, and open_audio_device().

◆ SDL_OpenedAudioDeviceDisconnected()

void SDL_OpenedAudioDeviceDisconnected ( SDL_AudioDevice device)

Definition at line 486 of file SDL_audio.c.

487{
489
490 if (!SDL_AtomicGet(&device->enabled)) {
491 return; /* don't report disconnects more than once. */
492 }
493
494 if (SDL_AtomicGet(&device->shutdown)) {
495 return; /* don't report disconnect if we're trying to close device. */
496 }
497
498 /* Ends the audio callback and mark the device as STOPPED, but the
499 app still needs to close the device to free resources. */
501 SDL_AtomicSet(&device->enabled, 0);
503
504 /* Post the event, if desired */
508 event.adevice.type = SDL_AUDIODEVICEREMOVED;
509 event.adevice.which = device->id;
510 event.adevice.iscapture = device->iscapture ? 1 : 0;
512 }
513}
@ SDL_AUDIODEVICEREMOVED
Definition: SDL_events.h:148

References current_audio, device, get_audio_device(), SDL_AudioDriver::impl, 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().

◆ SDL_ParseAudioFormat()

static SDL_AudioFormat SDL_ParseAudioFormat ( const char *  string)
static

Definition at line 899 of file SDL_audio.c.

900{
901#define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
904 CHECK_FMT_STRING(U16LSB);
905 CHECK_FMT_STRING(S16LSB);
906 CHECK_FMT_STRING(U16MSB);
907 CHECK_FMT_STRING(S16MSB);
908 CHECK_FMT_STRING(U16SYS);
909 CHECK_FMT_STRING(S16SYS);
910 CHECK_FMT_STRING(U16);
911 CHECK_FMT_STRING(S16);
912 CHECK_FMT_STRING(S32LSB);
913 CHECK_FMT_STRING(S32MSB);
914 CHECK_FMT_STRING(S32SYS);
916 CHECK_FMT_STRING(F32LSB);
917 CHECK_FMT_STRING(F32MSB);
918 CHECK_FMT_STRING(F32SYS);
919 CHECK_FMT_STRING(F32);
920#undef CHECK_FMT_STRING
921 return 0;
922}
#define CHECK_FMT_STRING(x)
#define S32

References CHECK_FMT_STRING, and S32.

Referenced by prepare_audiospec().

◆ SDL_PauseAudio()

void SDL_PauseAudio ( int  pause_on)

Definition at line 1539 of file SDL_audio.c.

1540{
1541 SDL_PauseAudioDevice(1, pause_on);
1542}
void SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
Definition: SDL_audio.c:1528

References SDL_PauseAudioDevice().

◆ SDL_PauseAudioDevice()

void SDL_PauseAudioDevice ( SDL_AudioDeviceID  devid,
int  pause_on 
)

◆ 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 598 of file SDL_audio.c.

599{
601 int rc = 0;
602
603 if (!device) {
604 return -1; /* get_audio_device() will have set the error state */
605 } else if (device->iscapture) {
606 return SDL_SetError("This is a capture device, queueing not allowed");
607 } else if (device->callbackspec.callback != SDL_BufferQueueDrainCallback) {
608 return SDL_SetError("Audio device has a callback, queueing not allowed");
609 }
610
611 if (len > 0) {
613 rc = SDL_WriteToDataQueue(device->buffer_queue, data, len);
615 }
616
617 return rc;
618}

References current_audio, device, get_audio_device(), SDL_AudioDriver::impl, SDL_AudioDriverImpl::LockDevice, SDL_BufferQueueDrainCallback(), SDL_SetError, SDL_WriteToDataQueue(), and SDL_AudioDriverImpl::UnlockDevice.

◆ SDL_RemoveAudioDevice()

void SDL_RemoveAudioDevice ( const int  iscapture,
void handle 
)

◆ SDL_RunAudio()

static int SDL_RunAudio ( void devicep)
static

Definition at line 682 of file SDL_audio.c.

683{
685 void *udata = device->callbackspec.userdata;
686 SDL_AudioCallback callback = device->callbackspec.callback;
687 int data_len = 0;
688 Uint8 *data;
689
690 SDL_assert(!device->iscapture);
691
692#if SDL_AUDIO_DRIVER_ANDROID
693 {
694 /* Set thread priority to THREAD_PRIORITY_AUDIO */
695 extern void Android_JNI_AudioSetThreadPriority(int, int);
697 }
698#else
699 /* The audio mixing is always a high priority thread */
701#endif
702
703 /* Perform any thread setup */
704 device->threadid = SDL_ThreadID();
706
707 /* Loop, filling the audio buffers */
708 while (!SDL_AtomicGet(&device->shutdown)) {
710 data_len = device->callbackspec.size;
711
712 /* Fill the current buffer with sound */
713 if (!device->stream && SDL_AtomicGet(&device->enabled)) {
714 SDL_assert(data_len == device->spec.size);
716 } else {
717 /* if the device isn't enabled, we still write to the
718 work_buffer, so the app's callback will fire with
719 a regular frequency, in case they depend on that
720 for timing or progress. They can use hotplug
721 now to know if the device failed.
722 Streaming playback uses work_buffer, too. */
723 data = NULL;
724 }
725
726 if (data == NULL) {
727 data = device->work_buffer;
728 }
729
730 /* !!! FIXME: this should be LockDevice. */
731 SDL_LockMutex(device->mixer_lock);
732 if (SDL_AtomicGet(&device->paused)) {
733 SDL_memset(data, device->spec.silence, data_len);
734 } else {
735 callback(udata, data, data_len);
736 }
737 SDL_UnlockMutex(device->mixer_lock);
738
739 if (device->stream) {
740 /* Stream available audio to device, converting/resampling. */
741 /* if this fails...oh well. We'll play silence here. */
742 SDL_AudioStreamPut(device->stream, data, data_len);
743
744 while (SDL_AudioStreamAvailable(device->stream) >= ((int) device->spec.size)) {
745 int got;
747 got = SDL_AudioStreamGet(device->stream, data ? data : device->work_buffer, device->spec.size);
748 SDL_assert((got < 0) || (got == device->spec.size));
749
750 if (data == NULL) { /* device is having issues... */
751 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
752 SDL_Delay(delay); /* wait for as long as this buffer would have played. Maybe device recovers later? */
753 } else {
754 if (got != device->spec.size) {
755 SDL_memset(data, device->spec.silence, device->spec.size);
756 }
759 }
760 }
761 } else if (data == device->work_buffer) {
762 /* nothing to do; pause like we queued a buffer to play. */
763 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
764 SDL_Delay(delay);
765 } else { /* writing directly to the device. */
766 /* queue this buffer and wait for it to finish playing. */
769 }
770 }
771
773
774 /* Wait for the audio to drain. */
775 SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
776
778
779 return 0;
780}
@ SDL_THREAD_PRIORITY_TIME_CRITICAL
Definition: SDL_thread.h:63
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void(* PrepareToClose)(_THIS)
Definition: SDL_sysaudio.h:77
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74

References Android_JNI_AudioSetThreadPriority(), SDL_AudioDriverImpl::BeginLoopIteration, callback(), current_audio, device, SDL_AudioDriverImpl::GetDeviceBuf, SDL_AudioDriver::impl, NULL, SDL_AudioDriverImpl::PlayDevice, SDL_AudioDriverImpl::PrepareToClose, SDL_assert, SDL_AtomicGet, SDL_AudioStreamAvailable, SDL_AudioStreamGet, SDL_AudioStreamPut, SDL_Delay, SDL_LockMutex, SDL_memset, SDL_SetThreadPriority, SDL_THREAD_PRIORITY_TIME_CRITICAL, SDL_ThreadID, SDL_UnlockMutex, SDL_AudioDriverImpl::ThreadDeinit, SDL_AudioDriverImpl::ThreadInit, and SDL_AudioDriverImpl::WaitDevice.

Referenced by open_audio_device().

◆ SDL_UnlockAudio()

void SDL_UnlockAudio ( void  )

Definition at line 1572 of file SDL_audio.c.

1573{
1575}
void SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
Definition: SDL_audio.c:1562

References SDL_UnlockAudioDevice().

◆ SDL_UnlockAudioDevice()

void SDL_UnlockAudioDevice ( SDL_AudioDeviceID  devid)

Definition at line 1562 of file SDL_audio.c.

1563{
1564 /* Obtain a lock on the mixing buffers */
1566 if (device) {
1568 }
1569}

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

Referenced by SDL_UnlockAudio().

Variable Documentation

◆ bootstrap

const AudioBootStrap* const bootstrap[]
static

Definition at line 37 of file SDL_audio.c.

Referenced by SDL_AudioInit(), SDL_GetAudioDriver(), and SDL_GetNumAudioDrivers().

◆ current_audio

◆ format_idx

int format_idx
static

Definition at line 1621 of file SDL_audio.c.

Referenced by SDL_FirstAudioFormat(), and SDL_NextAudioFormat().

◆ format_idx_sub

int format_idx_sub
static

Definition at line 1622 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_U16LSB
Definition: SDL_audio.h:91
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
#define AUDIO_S8
Definition: SDL_audio.h:90
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define AUDIO_F32LSB
Definition: SDL_audio.h:112

Definition at line 1623 of file SDL_audio.c.

Referenced by SDL_FirstAudioFormat(), and SDL_NextAudioFormat().

◆ open_devices