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