Atlas - SDL_audio.c

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