This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_audio.c
946 lines (832 loc) · 26.2 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 Sam Lantinga
4
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
Sam Lantinga
20
slouken@libsdl.org
21
*/
22
#include "SDL_config.h"
23
24
25
26
27
28
29
30
/* Allow access to a raw mixing buffer */
#include "SDL.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
31
#ifdef __OS2__
32
/* We'll need the DosSetPriority() API! */
33
34
35
36
#define INCL_DOSPROCESS
#include <os2.h>
#endif
37
38
39
40
41
42
static SDL_AudioDriver current_audio;
/* !!! FIXME: don't use a static array, but it's Good Enough For Now... */
static SDL_AudioDevice *open_devices[16];
43
44
/* Available audio drivers */
static AudioBootStrap *bootstrap[] = {
45
#if SDL_AUDIO_DRIVER_BSD
46
&BSD_AUDIO_bootstrap,
47
#endif
48
#if SDL_AUDIO_DRIVER_OSS
49
50
&DSP_bootstrap,
&DMA_bootstrap,
51
#endif
52
#if SDL_AUDIO_DRIVER_ALSA
53
&ALSA_bootstrap,
54
#endif
55
#if SDL_AUDIO_DRIVER_QNXNTO
56
&QNXNTOAUDIO_bootstrap,
57
#endif
58
#if SDL_AUDIO_DRIVER_SUNAUDIO
59
&SUNAUDIO_bootstrap,
60
#endif
61
#if SDL_AUDIO_DRIVER_DMEDIA
62
&DMEDIA_bootstrap,
63
#endif
64
#if SDL_AUDIO_DRIVER_ARTS
65
&ARTS_bootstrap,
66
#endif
67
#if SDL_AUDIO_DRIVER_ESD
68
&ESD_bootstrap,
69
#endif
70
#if SDL_AUDIO_DRIVER_NAS
71
&NAS_bootstrap,
72
#endif
73
#if SDL_AUDIO_DRIVER_DSOUND
74
&DSOUND_bootstrap,
75
#endif
76
#if SDL_AUDIO_DRIVER_WAVEOUT
77
&WAVEOUT_bootstrap,
78
#endif
79
#if SDL_AUDIO_DRIVER_PAUD
80
&Paud_bootstrap,
81
82
#endif
#if SDL_AUDIO_DRIVER_BAUDIO
83
&BAUDIO_bootstrap,
84
#endif
85
#if SDL_AUDIO_DRIVER_COREAUDIO
86
&COREAUDIO_bootstrap,
87
#endif
88
#if SDL_AUDIO_DRIVER_SNDMGR
89
&SNDMGR_bootstrap,
90
#endif
91
#if SDL_AUDIO_DRIVER_AHI
92
&AHI_bootstrap,
93
#endif
94
#if SDL_AUDIO_DRIVER_MINT
95
96
97
98
99
&MINTAUDIO_GSXB_bootstrap,
&MINTAUDIO_MCSN_bootstrap,
&MINTAUDIO_STFA_bootstrap,
&MINTAUDIO_XBIOS_bootstrap,
&MINTAUDIO_DMA8_bootstrap,
100
#endif
101
#if SDL_AUDIO_DRIVER_DISK
102
&DISKAUD_bootstrap,
103
#endif
104
#if SDL_AUDIO_DRIVER_DUMMY
105
&DUMMYAUD_bootstrap,
106
#endif
107
#if SDL_AUDIO_DRIVER_DC
108
&DCAUD_bootstrap,
109
#endif
110
#if SDL_AUDIO_DRIVER_MMEAUDIO
111
&MMEAUDIO_bootstrap,
112
113
#endif
#if SDL_AUDIO_DRIVER_DART
114
&DART_bootstrap,
115
#endif
116
NULL
117
118
};
119
#if SDL_AUDIO_DRIVER_AHI
120
121
static int audio_configured = 0;
#endif
122
123
124
125
126
127
128
129
130
131
132
133
134
static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id)
{
id--;
if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) {
SDL_SetError("Invalid audio device ID");
return NULL;
}
return open_devices[id];
}
135
/* The general mixing thread function */
136
int SDLCALL
137
SDL_RunAudio(void *devicep)
138
{
139
140
SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
const int legacy_device = (device == open_devices[0]);
141
142
143
144
145
Uint8 *stream;
int stream_len;
void *udata;
void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
int silence;
146
147
/* !!! FIXME: can we push this into the Amiga driver? */
148
#if SDL_AUDIO_DRIVER_AHI
149
#error this is probably broken.
150
int started = 0;
151
152
153
/* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
154
D(bug("Task audio started audio struct:<%lx>...\n", audiop));
155
156
157
158
159
160
161
D(bug("Before Openaudio..."));
if (audio->OpenAudio(audio, &audio->spec) == -1) {
D(bug("Open audio failed...\n"));
return (-1);
}
D(bug("OpenAudio...OK\n"));
162
#endif
163
164
/* Perform any thread setup */
165
166
if (current_audio.impl.ThreadInit != NULL) {
current_audio.impl.ThreadInit(device);
167
}
168
device->threadid = SDL_ThreadID();
169
170
/* Set up the mixing function */
171
172
fill = device->spec.callback;
udata = device->spec.userdata;
173
174
#if SDL_AUDIO_DRIVER_AHI
175
audio_configured = 1;
176
177
178
179
D(bug("Audio configured... Checking for conversion\n"));
SDL_mutexP(audio->mixer_lock);
D(bug("Semaphore obtained...\n"));
180
181
#endif
182
183
if (device->convert.needed) {
if (device->convert.src_format == AUDIO_U8) {
184
185
186
187
silence = 0x80;
} else {
silence = 0;
}
188
stream_len = device->convert.len;
189
} else {
190
191
silence = device->spec.silence;
stream_len = device->spec.size;
192
}
193
194
#if SDL_AUDIO_DRIVER_AHI
195
SDL_mutexV(device->mixer_lock);
196
D(bug("Entering audio loop...\n"));
197
198
#endif
199
/* !!! FIXME: push this out of core. */
200
#ifdef __OS2__
201
202
/* Increase the priority of this thread to make sure that
the audio will be continuous all the time! */
203
#ifdef USE_DOSSETPRIORITY
204
if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
205
#ifdef DEBUG_BUILD
206
207
208
printf
("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
SDL_ThreadID());
209
#endif
210
211
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
} else {
212
#ifdef DEBUG_BUILD
213
214
215
216
217
218
219
220
221
222
printf
("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
SDL_ThreadID());
#endif
DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
}
#endif
#endif
/* Loop, filling the audio buffers */
223
while (device->enabled) {
224
225
/* Fill the current buffer with sound */
226
227
228
if (device->convert.needed) {
if (device->convert.buf) {
stream = device->convert.buf;
229
230
231
232
} else {
continue;
}
} else {
233
stream = current_audio.impl.GetAudioBuf(device);
234
if (stream == NULL) {
235
stream = device->fake_stream;
236
}
237
}
238
239
240
241
242
243
244
245
/* New code should fill buffer or set it to silence themselves. */
if (legacy_device) {
SDL_memset(stream, silence, stream_len);
}
if (!device->paused) {
SDL_mutexP(device->mixer_lock);
246
(*fill) (udata, stream, stream_len);
247
SDL_mutexV(device->mixer_lock);
248
}
249
250
/* Convert the audio if necessary */
251
252
253
if (device->convert.needed) {
SDL_ConvertAudio(&device->convert);
stream = current_audio.impl.GetAudioBuf(device);
254
if (stream == NULL) {
255
stream = device->fake_stream;
256
}
257
SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
258
259
260
}
/* Ready current buffer for play and change current buffer */
261
262
if (stream != device->fake_stream) {
current_audio.impl.PlayAudio(device);
263
264
265
}
/* Wait for an audio buffer to become available */
266
267
if (stream == device->fake_stream) {
SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
268
} else {
269
current_audio.impl.WaitAudio(device);
270
271
272
273
}
}
/* Wait for the audio to drain.. */
274
275
if (current_audio.impl.WaitDone) {
current_audio.impl.WaitDone(device);
276
}
277
#if SDL_AUDIO_DRIVER_AHI
278
D(bug("WaitAudio...Done\n"));
279
280
audio->CloseAudio(audio);
281
282
283
D(bug("CloseAudio..Done, subtask exiting...\n"));
audio_configured = 0;
284
285
286
#endif
#ifdef __OS2__
#ifdef DEBUG_BUILD
287
printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
288
#endif
289
#endif
290
return (0);
291
292
}
293
294
static void
SDL_LockAudio_Default(SDL_AudioDevice * audio)
295
{
296
297
298
299
if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
return;
}
SDL_mutexP(audio->mixer_lock);
300
301
}
302
303
static void
SDL_UnlockAudio_Default(SDL_AudioDevice * audio)
304
{
305
306
307
308
if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
return;
}
SDL_mutexV(audio->mixer_lock);
309
310
}
311
static SDL_AudioFormat
312
SDL_ParseAudioFormat(const char *string)
313
{
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#define CHECK_FMT_STRING(x) if (strcmp(string, #x) == 0) return AUDIO_##x
CHECK_FMT_STRING(U8);
CHECK_FMT_STRING(S8);
CHECK_FMT_STRING(U16LSB);
CHECK_FMT_STRING(S16LSB);
CHECK_FMT_STRING(U16MSB);
CHECK_FMT_STRING(S16MSB);
CHECK_FMT_STRING(U16SYS);
CHECK_FMT_STRING(S16SYS);
CHECK_FMT_STRING(U16);
CHECK_FMT_STRING(S16);
CHECK_FMT_STRING(S32LSB);
CHECK_FMT_STRING(S32MSB);
CHECK_FMT_STRING(S32SYS);
CHECK_FMT_STRING(S32);
CHECK_FMT_STRING(F32LSB);
CHECK_FMT_STRING(F32MSB);
CHECK_FMT_STRING(F32SYS);
CHECK_FMT_STRING(F32);
#undef CHECK_FMT_STRING
return 0;
335
336
}
337
338
int
SDL_GetNumAudioDrivers(void)
339
{
340
341
return (SDL_arraysize(bootstrap) - 1);
}
342
343
344
345
346
347
348
349
350
351
352
353
354
const char *
SDL_GetAudioDriver(int index)
{
if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
return (bootstrap[index]->name);
}
return (NULL);
}
int
SDL_AudioInit(const char *driver_name)
{
355
356
int i = 0;
int initialized = 0;
357
358
359
if (SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_AudioQuit(); /* shutdown driver if already running. */
360
361
}
362
363
364
365
366
SDL_memset(¤t_audio, '\0', sizeof (current_audio));
SDL_memset(open_devices, '\0', sizeof (open_devices));
/* !!! FIXME: build a priority list of available drivers... */
367
/* Select the proper audio driver */
368
369
370
if (driver_name == NULL) {
driver_name = SDL_getenv("SDL_AUDIODRIVER");
}
371
372
/* !!! FIXME: move this esound shite into the esound driver... */
373
#if SDL_AUDIO_DRIVER_ESD
374
375
376
377
378
379
if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
/* Ahem, we know that if ESPEAKER is set, user probably wants
to use ESD, but don't start it if it's not already running.
This probably isn't the place to do this, but... Shh! :)
*/
for (i = 0; bootstrap[i]; ++i) {
380
if (SDL_strcasecmp(bootstrap[i]->name, "esd") == 0) {
381
#ifdef HAVE_PUTENV
382
383
384
385
386
387
388
389
390
const char *esd_no_spawn;
/* Don't start ESD if it's not running */
esd_no_spawn = getenv("ESD_NO_SPAWN");
if (esd_no_spawn == NULL) {
putenv("ESD_NO_SPAWN=1");
}
#endif
if (bootstrap[i]->available()) {
391
392
393
394
SDL_memset(¤t_audio, 0, sizeof (current_audio));
current_audio.name = bootstrap[i]->name;
current_audio.desc = bootstrap[i]->desc;
initialized = bootstrap[i]->init(¤t_audio.impl);
395
396
break;
}
397
#ifdef HAVE_UNSETENV
398
399
400
if (esd_no_spawn == NULL) {
unsetenv("ESD_NO_SPAWN");
}
401
#endif
402
403
404
}
}
}
405
#endif /* SDL_AUDIO_DRIVER_ESD */
406
407
if (!initialized) {
408
409
if (driver_name != NULL) {
for (i = 0; bootstrap[i]; ++i) {
410
if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
411
if (bootstrap[i]->available()) {
412
413
414
415
SDL_memset(¤t_audio, 0, sizeof (current_audio));
current_audio.name = bootstrap[i]->name;
current_audio.desc = bootstrap[i]->desc;
initialized = bootstrap[i]->init(¤t_audio.impl);
416
417
418
419
420
}
break;
}
}
} else {
421
for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
422
if (bootstrap[i]->available()) {
423
424
425
426
SDL_memset(¤t_audio, 0, sizeof (current_audio));
current_audio.name = bootstrap[i]->name;
current_audio.desc = bootstrap[i]->desc;
initialized = bootstrap[i]->init(¤t_audio.impl);
427
428
429
}
}
}
430
if (!initialized) {
431
432
433
434
435
if (driver_name) {
SDL_SetError("%s not available", driver_name);
} else {
SDL_SetError("No available audio device");
}
436
437
SDL_memset(¤t_audio, 0, sizeof (current_audio));
return (-1); /* No driver was available, so fail. */
438
439
}
}
440
441
442
443
if (!current_audio.impl.LockAudio && !current_audio.impl.UnlockAudio) {
current_audio.impl.LockAudio = SDL_LockAudio_Default;
current_audio.impl.UnlockAudio = SDL_UnlockAudio_Default;
444
}
445
446
return (0);
447
448
}
449
450
451
452
453
/*
* Get the current audio driver name
*/
const char *
SDL_GetCurrentAudioDriver()
454
{
455
return current_audio.name;
456
457
}
458
459
static void
close_audio_device(SDL_AudioDevice *device)
460
{
461
462
463
device->enabled = 0;
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
464
}
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
if (device->mixer_lock != NULL) {
SDL_DestroyMutex(device->mixer_lock);
}
if (device->fake_stream != NULL) {
SDL_FreeAudioMem(device->fake_stream);
}
if (device->convert.needed) {
SDL_FreeAudioMem(device->convert.buf);
}
#if !SDL_AUDIO_DRIVER_AHI /* !!! FIXME: get rid of this #if. */
if (device->opened) {
current_audio.impl.CloseAudio(device);
device->opened = 0;
}
#endif
SDL_FreeAudioMem(device);
}
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
/*
* Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
* Fills in a sanitized copy in (prepared).
* Returns non-zero if okay, zero on fatal parameters in (orig).
*/
static int
prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
{
SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec));
if (orig->callback == NULL) {
SDL_SetError("SDL_OpenAudio() passed a NULL callback");
return 0;
497
498
}
499
500
501
502
if (orig->freq == 0) {
const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) {
prepared->freq = 22050; /* a reasonable default */
503
504
}
}
505
506
507
508
509
if (orig->format == 0) {
const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
prepared->format = AUDIO_S16; /* a reasonable default */
510
511
}
}
512
513
514
515
516
517
switch (orig->channels) {
case 0: {
const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) {
prepared->channels = 2; /* a reasonable default */
518
}
519
break;
520
521
522
523
524
525
526
}
case 1: /* Mono */
case 2: /* Stereo */
case 4: /* surround */
case 6: /* surround with center and lfe */
break;
default:
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
SDL_SetError("Unsupported number of audio channels.");
return 0;
}
if (orig->samples == 0) {
const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) {
/* Pick a default of ~46 ms at desired frequency */
/* !!! FIXME: remove this when the non-Po2 resampling is in. */
const int samples = (prepared->freq / 1000) * 46;
int power2 = 1;
while (power2 < samples) {
power2 *= 2;
}
prepared->samples = power2;
542
543
}
}
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
/* Calculate the silence and size of the audio specification */
SDL_CalculateAudioSpec(prepared);
return 1;
}
static SDL_AudioDeviceID
open_audio_device(const char *devname, int iscapture,
const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained,
int min_id)
{
int i = 0;
SDL_AudioDeviceID id = 0;
SDL_AudioSpec desired;
SDL_AudioDevice *device;
if (iscapture) {
SDL_SetError("Audio capture support not implemented yet!");
return 0; /* !!! FIXME */
565
}
566
567
568
569
570
571
572
573
574
575
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_SetError("Audio subsystem is not initialized");
return 0;
}
if (!prepare_audiospec(_desired, &desired)) {
return 0;
}
576
577
578
579
580
/* If app doesn't care about a specific device, let the user override. */
if (devname == NULL) {
devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
}
581
582
583
584
device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice));
if (device == NULL) {
SDL_OutOfMemory();
return 0;
585
}
586
587
588
589
590
591
592
SDL_memset(device, '\0', sizeof (SDL_AudioDevice));
SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec));
device->driver = ¤t_audio; /* !!! FIXME: unused... */
device->enabled = 1;
device->paused = 1;
/* !!! FIXME: Get this out of the core. */
593
#if defined(__MINT__) && SDL_THREADS_DISABLED
594
/* Uses interrupt driven audio, without thread */
595
#else
596
/* Create a semaphore for locking the sound buffers */
597
598
device->mixer_lock = SDL_CreateMutex();
if (device->mixer_lock == NULL) {
599
SDL_SetError("Couldn't create mixer lock");
600
return 0;
601
}
602
#endif /* __MINT__ */
603
604
/* !!! FIXME: Get this #if out of the core. */
605
/* AmigaOS opens audio inside the main loop */
606
607
608
609
#if !SDL_AUDIO_DRIVER_AHI
if (!current_audio.impl.OpenAudio(device, devname, iscapture)) {
close_audio_device(device);
return 0;
610
}
611
device->opened = 2; /* !!! FIXME */
612
#else
613
614
# error needs to be fixed for new internal API. Email Ryan for details.
615
616
617
618
619
620
621
622
623
624
625
D(bug("Locking semaphore..."));
SDL_mutexP(audio->mixer_lock);
audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
D(bug("Created thread...\n"));
if (audio->thread == NULL) {
SDL_mutexV(audio->mixer_lock);
SDL_CloseAudio();
SDL_SetError("Couldn't create audio thread");
626
return 0;
627
628
629
630
631
632
633
}
while (!audio_configured)
SDL_Delay(100);
#endif
/* If the audio driver changes the buffer size, accept it */
634
635
636
if (device->spec.samples != desired.samples) {
desired.samples = device->spec.samples;
SDL_CalculateAudioSpec(&device->spec);
637
638
639
}
/* Allocate a fake audio memory buffer */
640
641
642
device->fake_stream = SDL_AllocAudioMem(device->spec.size);
if (device->fake_stream == NULL) {
close_audio_device(device);
643
SDL_OutOfMemory();
644
return 0;
645
646
647
648
}
/* See if we need to do any conversion */
if (obtained != NULL) {
649
650
651
652
SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec));
} else if (desired.freq != device->spec.freq ||
desired.format != device->spec.format ||
desired.channels != device->spec.channels) {
653
/* Build an audio conversion block */
654
655
656
657
658
659
660
if (SDL_BuildAudioCVT(&device->convert,
desired.format, desired.channels,
desired.freq,
device->spec.format, device->spec.channels,
device->spec.freq) < 0) {
close_audio_device(device);
return 0;
661
}
662
663
664
665
666
667
668
if (device->convert.needed) {
device->convert.len = desired.size;
device->convert.buf =
(Uint8 *) SDL_AllocAudioMem(device->convert.len *
device->convert.len_mult);
if (device->convert.buf == NULL) {
close_audio_device(device);
669
SDL_OutOfMemory();
670
return 0;
671
672
673
}
}
}
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
/* Find an available device ID and store the structure... */
for (id = min_id-1; id < SDL_arraysize(open_devices); id++) {
if (open_devices[id] == NULL) {
open_devices[id] = device;
break;
}
}
/* !!! FIXME: remove static array... */
if (id == SDL_arraysize(open_devices)) {
SDL_SetError("Too many open audio devices");
close_audio_device(device);
return 0;
}
690
#if !SDL_AUDIO_DRIVER_AHI
691
/* Start the audio thread if necessary */
692
switch (device->opened) { /* !!! FIXME: what is this?! */
693
694
case 1:
/* Start the audio thread */
695
/* !!! FIXME: this is nasty. */
696
#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
697
#undef SDL_CreateThread
698
device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
699
#else
700
device->thread = SDL_CreateThread(SDL_RunAudio, device);
701
#endif
702
703
if (device->thread == NULL) {
SDL_CloseAudioDevice(id+1);
704
SDL_SetError("Couldn't create audio thread");
705
return 0;
706
707
708
709
710
711
712
}
break;
default:
/* The audio is now playing */
break;
}
713
#else
714
715
SDL_mutexV(audio->mixer_lock);
D(bug("SDL_OpenAudio USCITA...\n"));
716
717
718
#endif
719
return id+1;
720
721
}
722
723
724
int
SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
725
{
726
SDL_AudioDeviceID id = 0;
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
/* Start up the audio driver, if necessary. This is legacy behaviour! */
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
return (-1);
}
}
/* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
if (open_devices[0] != NULL) {
SDL_SetError("Audio device is already opened");
return (-1);
}
id = open_audio_device(NULL, 0, desired, obtained, 1);
if (id > 1) { /* this should never happen in theory... */
SDL_CloseAudioDevice(id);
SDL_SetError("Internal error"); /* MUST be Device ID #1! */
return (-1);
}
return ((id == 0) ? -1 : 0);
}
SDL_AudioDeviceID
SDL_OpenAudioDevice(const char *device, int iscapture,
const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
{
return open_audio_device(device, iscapture, desired, obtained, 2);
}
SDL_audiostatus
SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = get_audio_device(devid);
SDL_audiostatus status = SDL_AUDIO_STOPPED;
if (device && device->enabled) {
if (device->paused) {
765
766
767
768
769
770
status = SDL_AUDIO_PAUSED;
} else {
status = SDL_AUDIO_PLAYING;
}
}
return (status);
771
772
}
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
SDL_audiostatus
SDL_GetAudioStatus(void)
{
return SDL_GetAudioDeviceStatus(1);
}
void
SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
{
SDL_AudioDevice *device = get_audio_device(devid);
if (device) {
device->paused = pause_on;
}
}
789
790
void
SDL_PauseAudio(int pause_on)
791
{
792
793
794
SDL_PauseAudioDevice(1, pause_on);
}
795
796
797
798
799
800
801
802
803
804
void
SDL_LockAudioDevice(SDL_AudioDeviceID devid)
{
if (current_audio.impl.LockAudio != NULL) {
SDL_AudioDevice *device = get_audio_device(devid);
/* Obtain a lock on the mixing buffers */
if (device) {
current_audio.impl.LockAudio(device);
}
805
}
806
807
}
808
809
void
SDL_LockAudio(void)
810
{
811
812
SDL_LockAudioDevice(1);
}
813
814
815
816
817
818
819
820
821
822
void
SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
{
if (current_audio.impl.UnlockAudio != NULL) {
SDL_AudioDevice *device = get_audio_device(devid);
/* Obtain a lock on the mixing buffers */
if (device) {
current_audio.impl.UnlockAudio(device);
}
823
}
824
825
}
826
827
void
SDL_UnlockAudio(void)
828
{
829
830
SDL_UnlockAudioDevice(1);
}
831
832
833
834
835
836
837
838
void
SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = get_audio_device(devid);
if (device) {
close_audio_device(device);
open_devices[devid-1] = NULL;
839
}
840
841
}
842
843
void
SDL_CloseAudio(void)
844
{
845
SDL_CloseAudioDevice(1);
846
847
}
848
849
void
SDL_AudioQuit(void)
850
{
851
852
853
SDL_AudioDeviceID i;
for (i = 0; i < SDL_arraysize(open_devices); i++) {
SDL_CloseAudioDevice(i);
854
}
855
856
/* Free the driver data */
857
current_audio.impl.Deinitialize();
858
859
SDL_memset(¤t_audio, '\0', sizeof (current_audio));
SDL_memset(open_devices, '\0', sizeof (open_devices));
860
861
}
862
#define NUM_FORMATS 10
863
864
static int format_idx;
static int format_idx_sub;
865
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
866
{AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
867
AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
868
{AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
869
870
871
872
873
874
875
876
877
AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
{AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
{AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
{AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
{AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
878
879
880
881
882
883
884
885
{AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
{AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
{AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
{AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
886
887
};
888
889
SDL_AudioFormat
SDL_FirstAudioFormat(SDL_AudioFormat format)
890
{
891
892
893
894
895
896
897
for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
if (format_list[format_idx][0] == format) {
break;
}
}
format_idx_sub = 0;
return (SDL_NextAudioFormat());
898
899
}
900
SDL_AudioFormat
901
SDL_NextAudioFormat(void)
902
{
903
904
905
906
if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
return (0);
}
return (format_list[format_idx][format_idx_sub++]);
907
908
}
909
910
void
SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
911
{
912
913
914
915
916
917
918
919
switch (spec->format) {
case AUDIO_U8:
spec->silence = 0x80;
break;
default:
spec->silence = 0x00;
break;
}
920
spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
921
922
spec->size *= spec->channels;
spec->size *= spec->samples;
923
}
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
/*
* Moved here from SDL_mixer.c, since it relies on internals of an opened
* audio device (and is deprecated, by the way!).
*/
void
SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
{
/* Mix the user-level audio format */
SDL_AudioDevice *device = get_audio_device(1);
if (device != NULL) {
SDL_AudioFormat format;
if (device->convert.needed) {
format = device->convert.src_format;
} else {
format = device->spec.format;
}
SDL_MixAudioFormat(dst, src, format, len, volume);
}
}
946
/* vi: set ts=4 sw=4 expandtab: */