This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_audio.c
974 lines (853 loc) · 26.8 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.GetDeviceBuf(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
if (device->convert.needed) {
SDL_ConvertAudio(&device->convert);
253
stream = current_audio.impl.GetDeviceBuf(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
if (stream != device->fake_stream) {
262
current_audio.impl.PlayDevice(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.WaitDevice(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("WaitDevice...Done\n"));
279
280
audio->CloseDevice(audio);
281
282
D(bug("CloseDevice..Done, subtask exiting...\n"));
283
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
static void
294
SDL_LockDevice_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
static void
303
SDL_UnlockDevice_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.LockDevice && !current_audio.impl.UnlockDevice) {
current_audio.impl.LockDevice = SDL_LockDevice_Default;
current_audio.impl.UnlockDevice = SDL_UnlockDevice_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
460
461
462
463
464
465
466
467
468
469
int
SDL_GetNumAudioDevices(int iscapture)
{
if (!SDL_WasInit(SDL_INIT_AUDIO) || !current_audio.impl.DetectDevices) {
return -1;
}
return current_audio.impl.DetectDevices(iscapture);
}
const char *
470
SDL_GetAudioDeviceName(int index, int iscapture)
471
472
473
474
475
476
{
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_SetError("Audio subsystem is not initialized");
return NULL;
}
477
if ((index < 0) && (!current_audio.impl.GetDeviceName)) {
478
479
480
481
SDL_SetError("No such device");
return NULL;
}
482
return current_audio.impl.GetDeviceName(index, iscapture);
483
484
485
}
486
487
static void
close_audio_device(SDL_AudioDevice *device)
488
{
489
490
491
device->enabled = 0;
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
492
}
493
494
495
496
497
498
499
500
501
502
503
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) {
504
current_audio.impl.CloseDevice(device);
505
506
507
508
509
device->opened = 0;
}
#endif
SDL_FreeAudioMem(device);
}
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
/*
* 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;
525
526
}
527
528
529
530
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 */
531
532
}
}
533
534
535
536
537
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 */
538
539
}
}
540
541
542
543
544
545
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 */
546
}
547
break;
548
549
550
551
552
553
554
}
case 1: /* Mono */
case 2: /* Stereo */
case 4: /* surround */
case 6: /* surround with center and lfe */
break;
default:
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
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;
570
571
}
}
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
/* 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 */
593
}
594
595
596
597
598
599
600
601
602
603
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_SetError("Audio subsystem is not initialized");
return 0;
}
if (!prepare_audiospec(_desired, &desired)) {
return 0;
}
604
605
606
607
608
/* If app doesn't care about a specific device, let the user override. */
if (devname == NULL) {
devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
}
609
610
611
612
device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice));
if (device == NULL) {
SDL_OutOfMemory();
return 0;
613
}
614
615
616
617
618
619
620
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. */
621
#if defined(__MINT__) && SDL_THREADS_DISABLED
622
/* Uses interrupt driven audio, without thread */
623
#else
624
/* Create a semaphore for locking the sound buffers */
625
626
device->mixer_lock = SDL_CreateMutex();
if (device->mixer_lock == NULL) {
627
SDL_SetError("Couldn't create mixer lock");
628
return 0;
629
}
630
#endif /* __MINT__ */
631
632
/* !!! FIXME: Get this #if out of the core. */
633
/* AmigaOS opens audio inside the main loop */
634
#if !SDL_AUDIO_DRIVER_AHI
635
if (!current_audio.impl.OpenDevice(device, devname, iscapture)) {
636
637
close_audio_device(device);
return 0;
638
}
639
device->opened = 2; /* !!! FIXME */
640
#else
641
642
# error needs to be fixed for new internal API. Email Ryan for details.
643
644
645
646
647
648
649
650
651
652
653
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");
654
return 0;
655
656
657
658
659
660
661
}
while (!audio_configured)
SDL_Delay(100);
#endif
/* If the audio driver changes the buffer size, accept it */
662
663
664
if (device->spec.samples != desired.samples) {
desired.samples = device->spec.samples;
SDL_CalculateAudioSpec(&device->spec);
665
666
667
}
/* Allocate a fake audio memory buffer */
668
669
670
device->fake_stream = SDL_AllocAudioMem(device->spec.size);
if (device->fake_stream == NULL) {
close_audio_device(device);
671
SDL_OutOfMemory();
672
return 0;
673
674
675
676
}
/* See if we need to do any conversion */
if (obtained != NULL) {
677
678
679
680
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) {
681
/* Build an audio conversion block */
682
683
684
685
686
687
688
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;
689
}
690
691
692
693
694
695
696
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);
697
SDL_OutOfMemory();
698
return 0;
699
700
701
}
}
}
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
/* 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;
}
718
#if !SDL_AUDIO_DRIVER_AHI
719
/* Start the audio thread if necessary */
720
switch (device->opened) { /* !!! FIXME: what is this?! */
721
722
case 1:
/* Start the audio thread */
723
/* !!! FIXME: this is nasty. */
724
#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
725
#undef SDL_CreateThread
726
device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
727
#else
728
device->thread = SDL_CreateThread(SDL_RunAudio, device);
729
#endif
730
731
if (device->thread == NULL) {
SDL_CloseAudioDevice(id+1);
732
SDL_SetError("Couldn't create audio thread");
733
return 0;
734
735
736
737
738
739
740
}
break;
default:
/* The audio is now playing */
break;
}
741
#else
742
743
SDL_mutexV(audio->mixer_lock);
D(bug("SDL_OpenAudio USCITA...\n"));
744
745
746
#endif
747
return id+1;
748
749
}
750
751
752
int
SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
753
{
754
SDL_AudioDeviceID id = 0;
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
/* 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) {
793
794
795
796
797
798
status = SDL_AUDIO_PAUSED;
} else {
status = SDL_AUDIO_PLAYING;
}
}
return (status);
799
800
}
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
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;
}
}
817
818
void
SDL_PauseAudio(int pause_on)
819
{
820
821
822
SDL_PauseAudioDevice(1, pause_on);
}
823
824
825
826
void
SDL_LockAudioDevice(SDL_AudioDeviceID devid)
{
827
if (current_audio.impl.LockDevice != NULL) {
828
829
830
SDL_AudioDevice *device = get_audio_device(devid);
/* Obtain a lock on the mixing buffers */
if (device) {
831
current_audio.impl.LockDevice(device);
832
}
833
}
834
835
}
836
837
void
SDL_LockAudio(void)
838
{
839
840
SDL_LockAudioDevice(1);
}
841
842
843
844
void
SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
{
845
if (current_audio.impl.UnlockDevice != NULL) {
846
847
848
SDL_AudioDevice *device = get_audio_device(devid);
/* Obtain a lock on the mixing buffers */
if (device) {
849
current_audio.impl.UnlockDevice(device);
850
}
851
}
852
853
}
854
855
void
SDL_UnlockAudio(void)
856
{
857
858
SDL_UnlockAudioDevice(1);
}
859
860
861
862
863
864
865
866
void
SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = get_audio_device(devid);
if (device) {
close_audio_device(device);
open_devices[devid-1] = NULL;
867
}
868
869
}
870
871
void
SDL_CloseAudio(void)
872
{
873
SDL_CloseAudioDevice(1);
874
875
}
876
877
void
SDL_AudioQuit(void)
878
{
879
880
881
SDL_AudioDeviceID i;
for (i = 0; i < SDL_arraysize(open_devices); i++) {
SDL_CloseAudioDevice(i);
882
}
883
884
/* Free the driver data */
885
current_audio.impl.Deinitialize();
886
887
SDL_memset(¤t_audio, '\0', sizeof (current_audio));
SDL_memset(open_devices, '\0', sizeof (open_devices));
888
889
}
890
#define NUM_FORMATS 10
891
892
static int format_idx;
static int format_idx_sub;
893
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
894
{AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
895
AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
896
{AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
897
898
899
900
901
902
903
904
905
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},
906
907
908
909
910
911
912
913
{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},
914
915
};
916
917
SDL_AudioFormat
SDL_FirstAudioFormat(SDL_AudioFormat format)
918
{
919
920
921
922
923
924
925
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());
926
927
}
928
SDL_AudioFormat
929
SDL_NextAudioFormat(void)
930
{
931
932
933
934
if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
return (0);
}
return (format_list[format_idx][format_idx_sub++]);
935
936
}
937
938
void
SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
939
{
940
941
942
943
944
945
946
947
switch (spec->format) {
case AUDIO_U8:
spec->silence = 0x80;
break;
default:
spec->silence = 0x00;
break;
}
948
spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
949
950
spec->size *= spec->channels;
spec->size *= spec->samples;
951
}
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
/*
* 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);
}
}
974
/* vi: set ts=4 sw=4 expandtab: */