SDL_audio.c (46242B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../SDL_internal.h" 22 23/* Allow access to a raw mixing buffer */ 24 25#include "SDL.h" 26#include "SDL_audio.h" 27#include "SDL_audio_c.h" 28#include "SDL_audiomem.h" 29#include "SDL_sysaudio.h" 30 31#define _THIS SDL_AudioDevice *_this 32 33static SDL_AudioDriver current_audio; 34static SDL_AudioDevice *open_devices[16]; 35 36/* !!! FIXME: These are wordy and unlocalized... */ 37#define DEFAULT_OUTPUT_DEVNAME "System audio output device" 38#define DEFAULT_INPUT_DEVNAME "System audio capture device" 39 40 41/* 42 * Not all of these will be compiled and linked in, but it's convenient 43 * to have a complete list here and saves yet-another block of #ifdefs... 44 * Please see bootstrap[], below, for the actual #ifdef mess. 45 */ 46extern AudioBootStrap BSD_AUDIO_bootstrap; 47extern AudioBootStrap DSP_bootstrap; 48extern AudioBootStrap ALSA_bootstrap; 49extern AudioBootStrap PULSEAUDIO_bootstrap; 50extern AudioBootStrap QSAAUDIO_bootstrap; 51extern AudioBootStrap SUNAUDIO_bootstrap; 52extern AudioBootStrap ARTS_bootstrap; 53extern AudioBootStrap ESD_bootstrap; 54#if SDL_AUDIO_DRIVER_NACL 55extern AudioBootStrap NACLAUD_bootstrap; 56#endif 57extern AudioBootStrap NAS_bootstrap; 58extern AudioBootStrap XAUDIO2_bootstrap; 59extern AudioBootStrap DSOUND_bootstrap; 60extern AudioBootStrap WINMM_bootstrap; 61extern AudioBootStrap PAUDIO_bootstrap; 62extern AudioBootStrap HAIKUAUDIO_bootstrap; 63extern AudioBootStrap COREAUDIO_bootstrap; 64extern AudioBootStrap SNDMGR_bootstrap; 65extern AudioBootStrap DISKAUD_bootstrap; 66extern AudioBootStrap DUMMYAUD_bootstrap; 67extern AudioBootStrap DCAUD_bootstrap; 68extern AudioBootStrap DART_bootstrap; 69extern AudioBootStrap NDSAUD_bootstrap; 70extern AudioBootStrap FUSIONSOUND_bootstrap; 71extern AudioBootStrap ANDROIDAUD_bootstrap; 72extern AudioBootStrap PSPAUD_bootstrap; 73extern AudioBootStrap SNDIO_bootstrap; 74 75 76/* Available audio drivers */ 77static const AudioBootStrap *const bootstrap[] = { 78#if SDL_AUDIO_DRIVER_PULSEAUDIO 79 &PULSEAUDIO_bootstrap, 80#endif 81#if SDL_AUDIO_DRIVER_ALSA 82 &ALSA_bootstrap, 83#endif 84#if SDL_AUDIO_DRIVER_SNDIO 85 &SNDIO_bootstrap, 86#endif 87#if SDL_AUDIO_DRIVER_BSD 88 &BSD_AUDIO_bootstrap, 89#endif 90#if SDL_AUDIO_DRIVER_OSS 91 &DSP_bootstrap, 92#endif 93#if SDL_AUDIO_DRIVER_QSA 94 &QSAAUDIO_bootstrap, 95#endif 96#if SDL_AUDIO_DRIVER_SUNAUDIO 97 &SUNAUDIO_bootstrap, 98#endif 99#if SDL_AUDIO_DRIVER_ARTS 100 &ARTS_bootstrap, 101#endif 102#if SDL_AUDIO_DRIVER_ESD 103 &ESD_bootstrap, 104#endif 105#if SDL_AUDIO_DRIVER_NACL 106 &NACLAUD_bootstrap, 107#endif 108#if SDL_AUDIO_DRIVER_NAS 109 &NAS_bootstrap, 110#endif 111#if SDL_AUDIO_DRIVER_XAUDIO2 112 &XAUDIO2_bootstrap, 113#endif 114#if SDL_AUDIO_DRIVER_DSOUND 115 &DSOUND_bootstrap, 116#endif 117#if SDL_AUDIO_DRIVER_WINMM 118 &WINMM_bootstrap, 119#endif 120#if SDL_AUDIO_DRIVER_PAUDIO 121 &PAUDIO_bootstrap, 122#endif 123#if SDL_AUDIO_DRIVER_HAIKU 124 &HAIKUAUDIO_bootstrap, 125#endif 126#if SDL_AUDIO_DRIVER_COREAUDIO 127 &COREAUDIO_bootstrap, 128#endif 129#if SDL_AUDIO_DRIVER_DISK 130 &DISKAUD_bootstrap, 131#endif 132#if SDL_AUDIO_DRIVER_DUMMY 133 &DUMMYAUD_bootstrap, 134#endif 135#if SDL_AUDIO_DRIVER_FUSIONSOUND 136 &FUSIONSOUND_bootstrap, 137#endif 138#if SDL_AUDIO_DRIVER_ANDROID 139 &ANDROIDAUD_bootstrap, 140#endif 141#if SDL_AUDIO_DRIVER_PSP 142 &PSPAUD_bootstrap, 143#endif 144 NULL 145}; 146 147static SDL_AudioDevice * 148get_audio_device(SDL_AudioDeviceID id) 149{ 150 id--; 151 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) { 152 SDL_SetError("Invalid audio device ID"); 153 return NULL; 154 } 155 156 return open_devices[id]; 157} 158 159 160/* stubs for audio drivers that don't need a specific entry point... */ 161static void 162SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn) 163{ /* no-op. */ 164} 165 166static void 167SDL_AudioThreadInit_Default(_THIS) 168{ /* no-op. */ 169} 170 171static void 172SDL_AudioWaitDevice_Default(_THIS) 173{ /* no-op. */ 174} 175 176static void 177SDL_AudioPlayDevice_Default(_THIS) 178{ /* no-op. */ 179} 180 181static int 182SDL_AudioGetPendingBytes_Default(_THIS) 183{ 184 return 0; 185} 186 187static Uint8 * 188SDL_AudioGetDeviceBuf_Default(_THIS) 189{ 190 return NULL; 191} 192 193static void 194SDL_AudioWaitDone_Default(_THIS) 195{ /* no-op. */ 196} 197 198static void 199SDL_AudioCloseDevice_Default(_THIS) 200{ /* no-op. */ 201} 202 203static void 204SDL_AudioDeinitialize_Default(void) 205{ /* no-op. */ 206} 207 208static int 209SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture) 210{ 211 return -1; 212} 213 214static SDL_INLINE SDL_bool 215is_in_audio_device_thread(SDL_AudioDevice * device) 216{ 217 /* The device thread locks the same mutex, but not through the public API. 218 This check is in case the application, in the audio callback, 219 tries to lock the thread that we've already locked from the 220 device thread...just in case we only have non-recursive mutexes. */ 221 if (device->thread && (SDL_ThreadID() == device->threadid)) { 222 return SDL_TRUE; 223 } 224 225 return SDL_FALSE; 226} 227 228static void 229SDL_AudioLockDevice_Default(SDL_AudioDevice * device) 230{ 231 if (!is_in_audio_device_thread(device)) { 232 SDL_LockMutex(device->mixer_lock); 233 } 234} 235 236static void 237SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device) 238{ 239 if (!is_in_audio_device_thread(device)) { 240 SDL_UnlockMutex(device->mixer_lock); 241 } 242} 243 244 245static void 246finalize_audio_entry_points(void) 247{ 248 /* 249 * Fill in stub functions for unused driver entry points. This lets us 250 * blindly call them without having to check for validity first. 251 */ 252 253#define FILL_STUB(x) \ 254 if (current_audio.impl.x == NULL) { \ 255 current_audio.impl.x = SDL_Audio##x##_Default; \ 256 } 257 FILL_STUB(DetectDevices); 258 FILL_STUB(OpenDevice); 259 FILL_STUB(ThreadInit); 260 FILL_STUB(WaitDevice); 261 FILL_STUB(PlayDevice); 262 FILL_STUB(GetPendingBytes); 263 FILL_STUB(GetDeviceBuf); 264 FILL_STUB(WaitDone); 265 FILL_STUB(CloseDevice); 266 FILL_STUB(LockDevice); 267 FILL_STUB(UnlockDevice); 268 FILL_STUB(Deinitialize); 269#undef FILL_STUB 270} 271 272#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ 273/* Streaming functions (for when the input and output buffer sizes are different) */ 274/* Write [length] bytes from buf into the streamer */ 275static void 276SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length) 277{ 278 int i; 279 280 for (i = 0; i < length; ++i) { 281 stream->buffer[stream->write_pos] = buf[i]; 282 ++stream->write_pos; 283 } 284} 285 286/* Read [length] bytes out of the streamer into buf */ 287static void 288SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length) 289{ 290 int i; 291 292 for (i = 0; i < length; ++i) { 293 buf[i] = stream->buffer[stream->read_pos]; 294 ++stream->read_pos; 295 } 296} 297 298static int 299SDL_StreamLength(SDL_AudioStreamer * stream) 300{ 301 return (stream->write_pos - stream->read_pos) % stream->max_len; 302} 303 304/* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */ 305#if 0 306static int 307SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence) 308{ 309 /* First try to allocate the buffer */ 310 stream->buffer = (Uint8 *) SDL_malloc(max_len); 311 if (stream->buffer == NULL) { 312 return -1; 313 } 314 315 stream->max_len = max_len; 316 stream->read_pos = 0; 317 stream->write_pos = 0; 318 319 /* Zero out the buffer */ 320 SDL_memset(stream->buffer, silence, max_len); 321 322 return 0; 323} 324#endif 325 326/* Deinitialize the stream simply by freeing the buffer */ 327static void 328SDL_StreamDeinit(SDL_AudioStreamer * stream) 329{ 330 SDL_free(stream->buffer); 331} 332#endif 333 334 335/* buffer queueing support... */ 336 337/* this expects that you managed thread safety elsewhere. */ 338static void 339free_audio_queue(SDL_AudioBufferQueue *buffer) 340{ 341 while (buffer) { 342 SDL_AudioBufferQueue *next = buffer->next; 343 SDL_free(buffer); 344 buffer = next; 345 } 346} 347 348static void SDLCALL 349SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len) 350{ 351 /* this function always holds the mixer lock before being called. */ 352 Uint32 len = (Uint32) _len; 353 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata; 354 SDL_AudioBufferQueue *buffer; 355 356 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */ 357 SDL_assert(_len >= 0); /* this shouldn't ever happen, right?! */ 358 359 while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) { 360 const Uint32 avail = buffer->datalen - buffer->startpos; 361 const Uint32 cpy = SDL_min(len, avail); 362 SDL_assert(device->queued_bytes >= avail); 363 364 SDL_memcpy(stream, buffer->data + buffer->startpos, cpy); 365 buffer->startpos += cpy; 366 stream += cpy; 367 device->queued_bytes -= cpy; 368 len -= cpy; 369 370 if (buffer->startpos == buffer->datalen) { /* packet is done, put it in the pool. */ 371 device->buffer_queue_head = buffer->next; 372 SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail)); 373 buffer->next = device->buffer_queue_pool; 374 device->buffer_queue_pool = buffer; 375 } 376 } 377 378 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0)); 379 380 if (len > 0) { /* fill any remaining space in the stream with silence. */ 381 SDL_assert(device->buffer_queue_head == NULL); 382 SDL_memset(stream, device->spec.silence, len); 383 } 384 385 if (device->buffer_queue_head == NULL) { 386 device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */ 387 } 388} 389 390int 391SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len) 392{ 393 SDL_AudioDevice *device = get_audio_device(devid); 394 const Uint8 *data = (const Uint8 *) _data; 395 SDL_AudioBufferQueue *orighead; 396 SDL_AudioBufferQueue *origtail; 397 Uint32 origlen; 398 Uint32 datalen; 399 400 if (!device) { 401 return -1; /* get_audio_device() will have set the error state */ 402 } 403 404 if (device->spec.callback != SDL_BufferQueueDrainCallback) { 405 return SDL_SetError("Audio device has a callback, queueing not allowed"); 406 } 407 408 current_audio.impl.LockDevice(device); 409 410 orighead = device->buffer_queue_head; 411 origtail = device->buffer_queue_tail; 412 origlen = origtail ? origtail->datalen : 0; 413 414 while (len > 0) { 415 SDL_AudioBufferQueue *packet = device->buffer_queue_tail; 416 SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN)); 417 if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) { 418 /* tail packet missing or completely full; we need a new packet. */ 419 packet = device->buffer_queue_pool; 420 if (packet != NULL) { 421 /* we have one available in the pool. */ 422 device->buffer_queue_pool = packet->next; 423 } else { 424 /* Have to allocate a new one! */ 425 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue)); 426 if (packet == NULL) { 427 /* uhoh, reset so we've queued nothing new, free what we can. */ 428 if (!origtail) { 429 packet = device->buffer_queue_head; /* whole queue. */ 430 } else { 431 packet = origtail->next; /* what we added to existing queue. */ 432 origtail->next = NULL; 433 origtail->datalen = origlen; 434 } 435 device->buffer_queue_head = orighead; 436 device->buffer_queue_tail = origtail; 437 device->buffer_queue_pool = NULL; 438 439 current_audio.impl.UnlockDevice(device); 440 441 free_audio_queue(packet); /* give back what we can. */ 442 443 return SDL_OutOfMemory(); 444 } 445 } 446 packet->datalen = 0; 447 packet->startpos = 0; 448 packet->next = NULL; 449 450 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0)); 451 if (device->buffer_queue_tail == NULL) { 452 device->buffer_queue_head = packet; 453 } else { 454 device->buffer_queue_tail->next = packet; 455 } 456 device->buffer_queue_tail = packet; 457 } 458 459 datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen); 460 SDL_memcpy(packet->data + packet->datalen, data, datalen); 461 data += datalen; 462 len -= datalen; 463 packet->datalen += datalen; 464 device->queued_bytes += datalen; 465 } 466 467 current_audio.impl.UnlockDevice(device); 468 469 return 0; 470} 471 472Uint32 473SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid) 474{ 475 Uint32 retval = 0; 476 SDL_AudioDevice *device = get_audio_device(devid); 477 478 /* Nothing to do unless we're set up for queueing. */ 479 if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) { 480 current_audio.impl.LockDevice(device); 481 retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device); 482 current_audio.impl.UnlockDevice(device); 483 } 484 485 return retval; 486} 487 488void 489SDL_ClearQueuedAudio(SDL_AudioDeviceID devid) 490{ 491 SDL_AudioDevice *device = get_audio_device(devid); 492 SDL_AudioBufferQueue *buffer = NULL; 493 if (!device) { 494 return; /* nothing to do. */ 495 } 496 497 /* Blank out the device and release the mutex. Free it afterwards. */ 498 current_audio.impl.LockDevice(device); 499 buffer = device->buffer_queue_head; 500 device->buffer_queue_tail = NULL; 501 device->buffer_queue_head = NULL; 502 device->queued_bytes = 0; 503 current_audio.impl.UnlockDevice(device); 504 505 free_audio_queue(buffer); 506} 507 508 509#if defined(__ANDROID__) 510#include <android/log.h> 511#endif 512 513/* The general mixing thread function */ 514int SDLCALL 515SDL_RunAudio(void *devicep) 516{ 517 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep; 518 Uint8 *stream; 519 int stream_len; 520 void *udata; 521 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); 522 Uint32 delay; 523 524#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ 525 /* For streaming when the buffer sizes don't match up */ 526 Uint8 *istream; 527 int istream_len = 0; 528#endif 529 530 /* The audio mixing is always a high priority thread */ 531 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); 532 533 /* Perform any thread setup */ 534 device->threadid = SDL_ThreadID(); 535 current_audio.impl.ThreadInit(device); 536 537 /* Set up the mixing function */ 538 fill = device->spec.callback; 539 udata = device->spec.userdata; 540 541 /* By default do not stream */ 542 device->use_streamer = 0; 543 544 if (device->convert.needed) { 545#if 0 /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */ 546 /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */ 547 if (device->convert.len_mult != 1 || device->convert.len_div != 1) { 548 /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */ 549 stream_max_len = 2 * device->spec.size; 550 if (device->convert.len_mult > device->convert.len_div) { 551 stream_max_len *= device->convert.len_mult; 552 stream_max_len /= device->convert.len_div; 553 } 554 if (SDL_StreamInit(&device->streamer, stream_max_len, silence) < 555 0) 556 return -1; 557 device->use_streamer = 1; 558 559 /* istream_len should be the length of what we grab from the callback and feed to conversion, 560 so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d 561 */ 562 istream_len = 563 device->spec.size * device->convert.len_div / 564 device->convert.len_mult; 565 } 566#endif 567 stream_len = device->convert.len; 568 } else { 569 stream_len = device->spec.size; 570 } 571 572 /* Calculate the delay while paused */ 573 delay = ((device->spec.samples * 1000) / device->spec.freq); 574 575 /* Determine if the streamer is necessary here */ 576#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ 577 if (device->use_streamer == 1) { 578 /* This code is almost the same as the old code. The difference is, instead of reading 579 directly from the callback into "stream", then converting and sending the audio off, 580 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device. 581 However, reading and writing with streamer are done separately: 582 - We only call the callback and write to the streamer when the streamer does not 583 contain enough samples to output to the device. 584 - We only read from the streamer and tell the device to play when the streamer 585 does have enough samples to output. 586 This allows us to perform resampling in the conversion step, where the output of the 587 resampling process can be any number. We will have to see what a good size for the 588 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure. 589 */ 590 while (device->enabled) { 591 592 if (device->paused) { 593 SDL_Delay(delay); 594 continue; 595 } 596 597 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */ 598 if (SDL_StreamLength(&device->streamer) < stream_len) { 599 /* Set up istream */ 600 if (device->convert.needed) { 601 if (device->convert.buf) { 602 istream = device->convert.buf; 603 } else { 604 continue; 605 } 606 } else { 607/* FIXME: Ryan, this is probably wrong. I imagine we don't want to get 608 * a device buffer both here and below in the stream output. 609 */ 610 istream = current_audio.impl.GetDeviceBuf(device); 611 if (istream == NULL) { 612 istream = device->fake_stream; 613 } 614 } 615 616 /* Read from the callback into the _input_ stream */ 617 SDL_LockMutex(device->mixer_lock); 618 (*fill) (udata, istream, istream_len); 619 SDL_UnlockMutex(device->mixer_lock); 620 621 /* Convert the audio if necessary and write to the streamer */ 622 if (device->convert.needed) { 623 SDL_ConvertAudio(&device->convert); 624 if (istream == NULL) { 625 istream = device->fake_stream; 626 } 627 /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */ 628 SDL_StreamWrite(&device->streamer, device->convert.buf, 629 device->convert.len_cvt); 630 } else { 631 SDL_StreamWrite(&device->streamer, istream, istream_len); 632 } 633 } 634 635 /* Only output audio if the streamer has enough to output */ 636 if (SDL_StreamLength(&device->streamer) >= stream_len) { 637 /* Set up the output stream */ 638 if (device->convert.needed) { 639 if (device->convert.buf) { 640 stream = device->convert.buf; 641 } else { 642 continue; 643 } 644 } else { 645 stream = current_audio.impl.GetDeviceBuf(device); 646 if (stream == NULL) { 647 stream = device->fake_stream; 648 } 649 } 650 651 /* Now read from the streamer */ 652 SDL_StreamRead(&device->streamer, stream, stream_len); 653 654 /* Ready current buffer for play and change current buffer */ 655 if (stream != device->fake_stream) { 656 current_audio.impl.PlayDevice(device); 657 /* Wait for an audio buffer to become available */ 658 current_audio.impl.WaitDevice(device); 659 } else { 660 SDL_Delay(delay); 661 } 662 } 663 664 } 665 } else 666#endif 667 { 668 /* Otherwise, do not use the streamer. This is the old code. */ 669 const int silence = (int) device->spec.silence; 670 671 /* Loop, filling the audio buffers */ 672 while (device->enabled) { 673 674 /* Fill the current buffer with sound */ 675 if (device->convert.needed) { 676 if (device->convert.buf) { 677 stream = device->convert.buf; 678 } else { 679 continue; 680 } 681 } else { 682 stream = current_audio.impl.GetDeviceBuf(device); 683 if (stream == NULL) { 684 stream = device->fake_stream; 685 } 686 } 687 688 SDL_LockMutex(device->mixer_lock); 689 if (device->paused) { 690 SDL_memset(stream, silence, stream_len); 691 } else { 692 (*fill) (udata, stream, stream_len); 693 } 694 SDL_UnlockMutex(device->mixer_lock); 695 696 /* Convert the audio if necessary */ 697 if (device->convert.needed) { 698 SDL_ConvertAudio(&device->convert); 699 stream = current_audio.impl.GetDeviceBuf(device); 700 if (stream == NULL) { 701 stream = device->fake_stream; 702 } 703 SDL_memcpy(stream, device->convert.buf, 704 device->convert.len_cvt); 705 } 706 707 /* Ready current buffer for play and change current buffer */ 708 if (stream != device->fake_stream) { 709 current_audio.impl.PlayDevice(device); 710 /* Wait for an audio buffer to become available */ 711 current_audio.impl.WaitDevice(device); 712 } else { 713 SDL_Delay(delay); 714 } 715 } 716 } 717 718 /* Wait for the audio to drain.. */ 719 current_audio.impl.WaitDone(device); 720 721 /* If necessary, deinit the streamer */ 722#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ 723 if (device->use_streamer == 1) 724 SDL_StreamDeinit(&device->streamer); 725#endif 726 727 return (0); 728} 729 730 731static SDL_AudioFormat 732SDL_ParseAudioFormat(const char *string) 733{ 734#define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x 735 CHECK_FMT_STRING(U8); 736 CHECK_FMT_STRING(S8); 737 CHECK_FMT_STRING(U16LSB); 738 CHECK_FMT_STRING(S16LSB); 739 CHECK_FMT_STRING(U16MSB); 740 CHECK_FMT_STRING(S16MSB); 741 CHECK_FMT_STRING(U16SYS); 742 CHECK_FMT_STRING(S16SYS); 743 CHECK_FMT_STRING(U16); 744 CHECK_FMT_STRING(S16); 745 CHECK_FMT_STRING(S32LSB); 746 CHECK_FMT_STRING(S32MSB); 747 CHECK_FMT_STRING(S32SYS); 748 CHECK_FMT_STRING(S32); 749 CHECK_FMT_STRING(F32LSB); 750 CHECK_FMT_STRING(F32MSB); 751 CHECK_FMT_STRING(F32SYS); 752 CHECK_FMT_STRING(F32); 753#undef CHECK_FMT_STRING 754 return 0; 755} 756 757int 758SDL_GetNumAudioDrivers(void) 759{ 760 return (SDL_arraysize(bootstrap) - 1); 761} 762 763const char * 764SDL_GetAudioDriver(int index) 765{ 766 if (index >= 0 && index < SDL_GetNumAudioDrivers()) { 767 return (bootstrap[index]->name); 768 } 769 return (NULL); 770} 771 772int 773SDL_AudioInit(const char *driver_name) 774{ 775 int i = 0; 776 int initialized = 0; 777 int tried_to_init = 0; 778 779 if (SDL_WasInit(SDL_INIT_AUDIO)) { 780 SDL_AudioQuit(); /* shutdown driver if already running. */ 781 } 782 783 SDL_memset(¤t_audio, '\0', sizeof(current_audio)); 784 SDL_memset(open_devices, '\0', sizeof(open_devices)); 785 786 /* Select the proper audio driver */ 787 if (driver_name == NULL) { 788 driver_name = SDL_getenv("SDL_AUDIODRIVER"); 789 } 790 791 for (i = 0; (!initialized) && (bootstrap[i]); ++i) { 792 /* make sure we should even try this driver before doing so... */ 793 const AudioBootStrap *backend = bootstrap[i]; 794 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) || 795 (!driver_name && backend->demand_only)) { 796 continue; 797 } 798 799 tried_to_init = 1; 800 SDL_memset(¤t_audio, 0, sizeof(current_audio)); 801 current_audio.name = backend->name; 802 current_audio.desc = backend->desc; 803 initialized = backend->init(¤t_audio.impl); 804 } 805 806 if (!initialized) { 807 /* specific drivers will set the error message if they fail... */ 808 if (!tried_to_init) { 809 if (driver_name) { 810 SDL_SetError("Audio target '%s' not available", driver_name); 811 } else { 812 SDL_SetError("No available audio device"); 813 } 814 } 815 816 SDL_memset(¤t_audio, 0, sizeof(current_audio)); 817 return (-1); /* No driver was available, so fail. */ 818 } 819 820 finalize_audio_entry_points(); 821 822 return (0); 823} 824 825/* 826 * Get the current audio driver name 827 */ 828const char * 829SDL_GetCurrentAudioDriver() 830{ 831 return current_audio.name; 832} 833 834static void 835free_device_list(char ***devices, int *devCount) 836{ 837 int i = *devCount; 838 if ((i > 0) && (*devices != NULL)) { 839 while (i--) { 840 SDL_free((*devices)[i]); 841 } 842 } 843 844 SDL_free(*devices); 845 846 *devices = NULL; 847 *devCount = 0; 848} 849 850static 851void SDL_AddCaptureAudioDevice(const char *_name) 852{ 853 char *name = NULL; 854 void *ptr = SDL_realloc(current_audio.inputDevices, 855 (current_audio.inputDeviceCount+1) * sizeof(char*)); 856 if (ptr == NULL) { 857 return; /* oh well. */ 858 } 859 860 current_audio.inputDevices = (char **) ptr; 861 name = SDL_strdup(_name); /* if this returns NULL, that's okay. */ 862 current_audio.inputDevices[current_audio.inputDeviceCount++] = name; 863} 864 865static 866void SDL_AddOutputAudioDevice(const char *_name) 867{ 868 char *name = NULL; 869 void *ptr = SDL_realloc(current_audio.outputDevices, 870 (current_audio.outputDeviceCount+1) * sizeof(char*)); 871 if (ptr == NULL) { 872 return; /* oh well. */ 873 } 874 875 current_audio.outputDevices = (char **) ptr; 876 name = SDL_strdup(_name); /* if this returns NULL, that's okay. */ 877 current_audio.outputDevices[current_audio.outputDeviceCount++] = name; 878} 879 880 881int 882SDL_GetNumAudioDevices(int iscapture) 883{ 884 int retval = 0; 885 886 if (!SDL_WasInit(SDL_INIT_AUDIO)) { 887 return -1; 888 } 889 890 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { 891 return 0; 892 } 893 894 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { 895 return 1; 896 } 897 898 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { 899 return 1; 900 } 901 902 if (iscapture) { 903 free_device_list(¤t_audio.inputDevices, 904 ¤t_audio.inputDeviceCount); 905 current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice); 906 retval = current_audio.inputDeviceCount; 907 } else { 908 free_device_list(¤t_audio.outputDevices, 909 ¤t_audio.outputDeviceCount); 910 current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice); 911 retval = current_audio.outputDeviceCount; 912 } 913 914 return retval; 915} 916 917 918const char * 919SDL_GetAudioDeviceName(int index, int iscapture) 920{ 921 if (!SDL_WasInit(SDL_INIT_AUDIO)) { 922 SDL_SetError("Audio subsystem is not initialized"); 923 return NULL; 924 } 925 926 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { 927 SDL_SetError("No capture support"); 928 return NULL; 929 } 930 931 if (index < 0) { 932 goto no_such_device; 933 } 934 935 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { 936 if (index > 0) { 937 goto no_such_device; 938 } 939 return DEFAULT_INPUT_DEVNAME; 940 } 941 942 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { 943 if (index > 0) { 944 goto no_such_device; 945 } 946 return DEFAULT_OUTPUT_DEVNAME; 947 } 948 949 if (iscapture) { 950 if (index >= current_audio.inputDeviceCount) { 951 goto no_such_device; 952 } 953 return current_audio.inputDevices[index]; 954 } else { 955 if (index >= current_audio.outputDeviceCount) { 956 goto no_such_device; 957 } 958 return current_audio.outputDevices[index]; 959 } 960 961no_such_device: 962 SDL_SetError("No such device"); 963 return NULL; 964} 965 966 967static void 968close_audio_device(SDL_AudioDevice * device) 969{ 970 device->enabled = 0; 971 if (device->thread != NULL) { 972 SDL_WaitThread(device->thread, NULL); 973 } 974 if (device->mixer_lock != NULL) { 975 SDL_DestroyMutex(device->mixer_lock); 976 } 977 SDL_FreeAudioMem(device->fake_stream); 978 if (device->convert.needed) { 979 SDL_FreeAudioMem(device->convert.buf); 980 } 981 if (device->opened) { 982 current_audio.impl.CloseDevice(device); 983 device->opened = 0; 984 } 985 986 free_audio_queue(device->buffer_queue_head); 987 free_audio_queue(device->buffer_queue_pool); 988 989 SDL_FreeAudioMem(device); 990} 991 992 993/* 994 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig). 995 * Fills in a sanitized copy in (prepared). 996 * Returns non-zero if okay, zero on fatal parameters in (orig). 997 */ 998static int 999prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared) 1000{ 1001 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec)); 1002 1003 if (orig->freq == 0) { 1004 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); 1005 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) { 1006 prepared->freq = 22050; /* a reasonable default */ 1007 } 1008 } 1009 1010 if (orig->format == 0) { 1011 const char *env = SDL_getenv("SDL_AUDIO_FORMAT"); 1012 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) { 1013 prepared->format = AUDIO_S16; /* a reasonable default */ 1014 } 1015 } 1016 1017 switch (orig->channels) { 1018 case 0:{ 1019 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS"); 1020 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) { 1021 prepared->channels = 2; /* a reasonable default */ 1022 } 1023 break; 1024 } 1025 case 1: /* Mono */ 1026 case 2: /* Stereo */ 1027 case 4: /* surround */ 1028 case 6: /* surround with center and lfe */ 1029 break; 1030 default: 1031 SDL_SetError("Unsupported number of audio channels."); 1032 return 0; 1033 } 1034 1035 if (orig->samples == 0) { 1036 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES"); 1037 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) { 1038 /* Pick a default of ~46 ms at desired frequency */ 1039 /* !!! FIXME: remove this when the non-Po2 resampling is in. */ 1040 const int samples = (prepared->freq / 1000) * 46; 1041 int power2 = 1; 1042 while (power2 < samples) { 1043 power2 *= 2; 1044 } 1045 prepared->samples = power2; 1046 } 1047 } 1048 1049 /* Calculate the silence and size of the audio specification */ 1050 SDL_CalculateAudioSpec(prepared); 1051 1052 return 1; 1053} 1054 1055static SDL_AudioDeviceID 1056open_audio_device(const char *devname, int iscapture, 1057 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained, 1058 int allowed_changes, int min_id) 1059{ 1060 SDL_AudioDeviceID id = 0; 1061 SDL_AudioSpec _obtained; 1062 SDL_AudioDevice *device; 1063 SDL_bool build_cvt; 1064 int i = 0; 1065 1066 if (!SDL_WasInit(SDL_INIT_AUDIO)) { 1067 SDL_SetError("Audio subsystem is not initialized"); 1068 return 0; 1069 } 1070 1071 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { 1072 SDL_SetError("No capture support"); 1073 return 0; 1074 } 1075 1076 if (!obtained) { 1077 obtained = &_obtained; 1078 } 1079 if (!prepare_audiospec(desired, obtained)) { 1080 return 0; 1081 } 1082 1083 /* If app doesn't care about a specific device, let the user override. */ 1084 if (devname == NULL) { 1085 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME"); 1086 } 1087 1088 /* 1089 * Catch device names at the high level for the simple case... 1090 * This lets us have a basic "device enumeration" for systems that 1091 * don't have multiple devices, but makes sure the device name is 1092 * always NULL when it hits the low level. 1093 * 1094 * Also make sure that the simple case prevents multiple simultaneous 1095 * opens of the default system device. 1096 */ 1097 1098 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { 1099 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) { 1100 SDL_SetError("No such device"); 1101 return 0; 1102 } 1103 devname = NULL; 1104 1105 for (i = 0; i < SDL_arraysize(open_devices); i++) { 1106 if ((open_devices[i]) && (open_devices[i]->iscapture)) { 1107 SDL_SetError("Audio device already open"); 1108 return 0; 1109 } 1110 } 1111 } 1112 1113 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { 1114 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) { 1115 SDL_SetError("No such device"); 1116 return 0; 1117 } 1118 devname = NULL; 1119 1120 for (i = 0; i < SDL_arraysize(open_devices); i++) { 1121 if ((open_devices[i]) && (!open_devices[i]->iscapture)) { 1122 SDL_SetError("Audio device already open"); 1123 return 0; 1124 } 1125 } 1126 } 1127 1128 device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice)); 1129 if (device == NULL) { 1130 SDL_OutOfMemory(); 1131 return 0; 1132 } 1133 SDL_zerop(device); 1134 device->spec = *obtained; 1135 device->enabled = 1; 1136 device->paused = 1; 1137 device->iscapture = iscapture; 1138 1139 /* Create a semaphore for locking the sound buffers */ 1140 if (!current_audio.impl.SkipMixerLock) { 1141 device->mixer_lock = SDL_CreateMutex(); 1142 if (device->mixer_lock == NULL) { 1143 close_audio_device(device); 1144 SDL_SetError("Couldn't create mixer lock"); 1145 return 0; 1146 } 1147 } 1148 1149 /* force a device detection if we haven't done one yet. */ 1150 if ( ((iscapture) && (current_audio.inputDevices == NULL)) || 1151 ((!iscapture) && (current_audio.outputDevices == NULL)) ) { 1152 SDL_GetNumAudioDevices(iscapture); 1153 } 1154 1155 if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) { 1156 close_audio_device(device); 1157 return 0; 1158 } 1159 device->opened = 1; 1160 1161 /* Allocate a fake audio memory buffer */ 1162 device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size); 1163 if (device->fake_stream == NULL) { 1164 close_audio_device(device); 1165 SDL_OutOfMemory(); 1166 return 0; 1167 } 1168 1169 /* See if we need to do any conversion */ 1170 build_cvt = SDL_FALSE; 1171 if (obtained->freq != device->spec.freq) { 1172 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) { 1173 obtained->freq = device->spec.freq; 1174 } else { 1175 build_cvt = SDL_TRUE; 1176 } 1177 } 1178 if (obtained->format != device->spec.format) { 1179 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) { 1180 obtained->format = device->spec.format; 1181 } else { 1182 build_cvt = SDL_TRUE; 1183 } 1184 } 1185 if (obtained->channels != device->spec.channels) { 1186 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) { 1187 obtained->channels = device->spec.channels; 1188 } else { 1189 build_cvt = SDL_TRUE; 1190 } 1191 } 1192 1193 /* If the audio driver changes the buffer size, accept it. 1194 This needs to be done after the format is modified above, 1195 otherwise it might not have the correct buffer size. 1196 */ 1197 if (device->spec.samples != obtained->samples) { 1198 obtained->samples = device->spec.samples; 1199 SDL_CalculateAudioSpec(obtained); 1200 } 1201 1202 if (build_cvt) { 1203 /* Build an audio conversion block */ 1204 if (SDL_BuildAudioCVT(&device->convert, 1205 obtained->format, obtained->channels, 1206 obtained->freq, 1207 device->spec.format, device->spec.channels, 1208 device->spec.freq) < 0) { 1209 close_audio_device(device); 1210 return 0; 1211 } 1212 if (device->convert.needed) { 1213 device->convert.len = (int) (((double) device->spec.size) / 1214 device->convert.len_ratio); 1215 1216 device->convert.buf = 1217 (Uint8 *) SDL_AllocAudioMem(device->convert.len * 1218 device->convert.len_mult); 1219 if (device->convert.buf == NULL) { 1220 close_audio_device(device); 1221 SDL_OutOfMemory(); 1222 return 0; 1223 } 1224 } 1225 } 1226 1227 if (device->spec.callback == NULL) { /* use buffer queueing? */ 1228 /* pool a few packets to start. Enough for two callbacks. */ 1229 const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN; 1230 const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2; 1231 const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0); 1232 for (i = 0; i < wantpackets; i++) { 1233 SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue)); 1234 if (packet) { /* don't care if this fails, we'll deal later. */ 1235 packet->datalen = 0; 1236 packet->startpos = 0; 1237 packet->next = device->buffer_queue_pool; 1238 device->buffer_queue_pool = packet; 1239 } 1240 } 1241 1242 device->spec.callback = SDL_BufferQueueDrainCallback; 1243 device->spec.userdata = device; 1244 } 1245 1246 /* Find an available device ID and store the structure... */ 1247 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) { 1248 if (open_devices[id] == NULL) { 1249 open_devices[id] = device; 1250 break; 1251 } 1252 } 1253 1254 if (id == SDL_arraysize(open_devices)) { 1255 SDL_SetError("Too many open audio devices"); 1256 close_audio_device(device); 1257 return 0; 1258 } 1259 1260 /* Start the audio thread if necessary */ 1261 if (!current_audio.impl.ProvidesOwnCallbackThread) { 1262 /* Start the audio thread */ 1263 char name[64]; 1264 SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1)); 1265/* !!! FIXME: this is nasty. */ 1266#if defined(__WIN32__) && !defined(HAVE_LIBC) 1267#undef SDL_CreateThread 1268#if SDL_DYNAMIC_API 1269 device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL); 1270#else 1271 device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL); 1272#endif 1273#else 1274 device->thread = SDL_CreateThread(SDL_RunAudio, name, device); 1275#endif 1276 if (device->thread == NULL) { 1277 SDL_CloseAudioDevice(id + 1); 1278 SDL_SetError("Couldn't create audio thread"); 1279 return 0; 1280 } 1281 } 1282 1283 return id + 1; 1284} 1285 1286 1287int 1288SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained) 1289{ 1290 SDL_AudioDeviceID id = 0; 1291 1292 /* Start up the audio driver, if necessary. This is legacy behaviour! */ 1293 if (!SDL_WasInit(SDL_INIT_AUDIO)) { 1294 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { 1295 return (-1); 1296 } 1297 } 1298 1299 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */ 1300 if (open_devices[0] != NULL) { 1301 SDL_SetError("Audio device is already opened"); 1302 return (-1); 1303 } 1304 1305 if (obtained) { 1306 id = open_audio_device(NULL, 0, desired, obtained, 1307 SDL_AUDIO_ALLOW_ANY_CHANGE, 1); 1308 } else { 1309 id = open_audio_device(NULL, 0, desired, NULL, 0, 1); 1310 } 1311 1312 SDL_assert((id == 0) || (id == 1)); 1313 return ((id == 0) ? -1 : 0); 1314} 1315 1316SDL_AudioDeviceID 1317SDL_OpenAudioDevice(const char *device, int iscapture, 1318 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained, 1319 int allowed_changes) 1320{ 1321 return open_audio_device(device, iscapture, desired, obtained, 1322 allowed_changes, 2); 1323} 1324 1325SDL_AudioStatus 1326SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid) 1327{ 1328 SDL_AudioDevice *device = get_audio_device(devid); 1329 SDL_AudioStatus status = SDL_AUDIO_STOPPED; 1330 if (device && device->enabled) { 1331 if (device->paused) { 1332 status = SDL_AUDIO_PAUSED; 1333 } else { 1334 status = SDL_AUDIO_PLAYING; 1335 } 1336 } 1337 return (status); 1338} 1339 1340 1341SDL_AudioStatus 1342SDL_GetAudioStatus(void) 1343{ 1344 return SDL_GetAudioDeviceStatus(1); 1345} 1346 1347void 1348SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on) 1349{ 1350 SDL_AudioDevice *device = get_audio_device(devid); 1351 if (device) { 1352 current_audio.impl.LockDevice(device); 1353 device->paused = pause_on; 1354 current_audio.impl.UnlockDevice(device); 1355 } 1356} 1357 1358void 1359SDL_PauseAudio(int pause_on) 1360{ 1361 SDL_PauseAudioDevice(1, pause_on); 1362} 1363 1364 1365void 1366SDL_LockAudioDevice(SDL_AudioDeviceID devid) 1367{ 1368 /* Obtain a lock on the mixing buffers */ 1369 SDL_AudioDevice *device = get_audio_device(devid); 1370 if (device) { 1371 current_audio.impl.LockDevice(device); 1372 } 1373} 1374 1375void 1376SDL_LockAudio(void) 1377{ 1378 SDL_LockAudioDevice(1); 1379} 1380 1381void 1382SDL_UnlockAudioDevice(SDL_AudioDeviceID devid) 1383{ 1384 /* Obtain a lock on the mixing buffers */ 1385 SDL_AudioDevice *device = get_audio_device(devid); 1386 if (device) { 1387 current_audio.impl.UnlockDevice(device); 1388 } 1389} 1390 1391void 1392SDL_UnlockAudio(void) 1393{ 1394 SDL_UnlockAudioDevice(1); 1395} 1396 1397void 1398SDL_CloseAudioDevice(SDL_AudioDeviceID devid) 1399{ 1400 SDL_AudioDevice *device = get_audio_device(devid); 1401 if (device) { 1402 close_audio_device(device); 1403 open_devices[devid - 1] = NULL; 1404 } 1405} 1406 1407void 1408SDL_CloseAudio(void) 1409{ 1410 SDL_CloseAudioDevice(1); 1411} 1412 1413void 1414SDL_AudioQuit(void) 1415{ 1416 SDL_AudioDeviceID i; 1417 1418 if (!current_audio.name) { /* not initialized?! */ 1419 return; 1420 } 1421 1422 for (i = 0; i < SDL_arraysize(open_devices); i++) { 1423 if (open_devices[i] != NULL) { 1424 SDL_CloseAudioDevice(i+1); 1425 } 1426 } 1427 1428 /* Free the driver data */ 1429 current_audio.impl.Deinitialize(); 1430 free_device_list(¤t_audio.outputDevices, 1431 ¤t_audio.outputDeviceCount); 1432 free_device_list(¤t_audio.inputDevices, 1433 ¤t_audio.inputDeviceCount); 1434 SDL_memset(¤t_audio, '\0', sizeof(current_audio)); 1435 SDL_memset(open_devices, '\0', sizeof(open_devices)); 1436} 1437 1438#define NUM_FORMATS 10 1439static int format_idx; 1440static int format_idx_sub; 1441static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = { 1442 {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, 1443 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB}, 1444 {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, 1445 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB}, 1446 {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB, 1447 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8}, 1448 {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB, 1449 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8}, 1450 {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB, 1451 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8}, 1452 {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB, 1453 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8}, 1454 {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB, 1455 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8}, 1456 {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB, 1457 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8}, 1458 {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB, 1459 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8}, 1460 {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB, 1461 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8}, 1462}; 1463 1464SDL_AudioFormat 1465SDL_FirstAudioFormat(SDL_AudioFormat format) 1466{ 1467 for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) { 1468 if (format_list[format_idx][0] == format) { 1469 break; 1470 } 1471 } 1472 format_idx_sub = 0; 1473 return (SDL_NextAudioFormat()); 1474} 1475 1476SDL_AudioFormat 1477SDL_NextAudioFormat(void) 1478{ 1479 if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) { 1480 return (0); 1481 } 1482 return (format_list[format_idx][format_idx_sub++]); 1483} 1484 1485void 1486SDL_CalculateAudioSpec(SDL_AudioSpec * spec) 1487{ 1488 switch (spec->format) { 1489 case AUDIO_U8: 1490 spec->silence = 0x80; 1491 break; 1492 default: 1493 spec->silence = 0x00; 1494 break; 1495 } 1496 spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8; 1497 spec->size *= spec->channels; 1498 spec->size *= spec->samples; 1499} 1500 1501 1502/* 1503 * Moved here from SDL_mixer.c, since it relies on internals of an opened 1504 * audio device (and is deprecated, by the way!). 1505 */ 1506void 1507SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume) 1508{ 1509 /* Mix the user-level audio format */ 1510 SDL_AudioDevice *device = get_audio_device(1); 1511 if (device != NULL) { 1512 SDL_AudioFormat format; 1513 if (device->convert.needed) { 1514 format = device->convert.src_format; 1515 } else { 1516 format = device->spec.format; 1517 } 1518 SDL_MixAudioFormat(dst, src, format, len, volume); 1519 } 1520} 1521 1522/* vi: set ts=4 sw=4 expandtab: */