This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_audio.c
1210 lines (1053 loc) · 34.8 KB
1
/*
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Simple DirectMedia Layer
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_config.h"
22
23
24
25
/* Allow access to a raw mixing buffer */
#include "SDL.h"
26
#include "SDL_audio.h"
27
28
29
30
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
31
#define _THIS SDL_AudioDevice *_this
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
static SDL_AudioDriver current_audio;
static SDL_AudioDevice *open_devices[16];
/* !!! FIXME: These are wordy and unlocalized... */
#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
#define DEFAULT_INPUT_DEVNAME "System audio capture device"
/*
* Not all of these will be compiled and linked in, but it's convenient
* to have a complete list here and saves yet-another block of #ifdefs...
* Please see bootstrap[], below, for the actual #ifdef mess.
*/
extern AudioBootStrap BSD_AUDIO_bootstrap;
extern AudioBootStrap DSP_bootstrap;
extern AudioBootStrap DMA_bootstrap;
extern AudioBootStrap ALSA_bootstrap;
50
extern AudioBootStrap PULSEAUDIO_bootstrap;
51
extern AudioBootStrap QSAAUDIO_bootstrap;
52
53
54
55
56
extern AudioBootStrap SUNAUDIO_bootstrap;
extern AudioBootStrap ARTS_bootstrap;
extern AudioBootStrap ESD_bootstrap;
extern AudioBootStrap NAS_bootstrap;
extern AudioBootStrap DSOUND_bootstrap;
57
extern AudioBootStrap WINWAVEOUT_bootstrap;
58
59
60
extern AudioBootStrap PAUDIO_bootstrap;
extern AudioBootStrap BEOSAUDIO_bootstrap;
extern AudioBootStrap COREAUDIO_bootstrap;
61
extern AudioBootStrap COREAUDIOIPHONE_bootstrap;
62
63
64
65
66
extern AudioBootStrap SNDMGR_bootstrap;
extern AudioBootStrap DISKAUD_bootstrap;
extern AudioBootStrap DUMMYAUD_bootstrap;
extern AudioBootStrap DCAUD_bootstrap;
extern AudioBootStrap DART_bootstrap;
67
extern AudioBootStrap NDSAUD_bootstrap;
68
extern AudioBootStrap FUSIONSOUND_bootstrap;
69
extern AudioBootStrap ANDROIDAUD_bootstrap;
70
71
72
/* Available audio drivers */
73
static const AudioBootStrap *const bootstrap[] = {
74
75
#if SDL_AUDIO_DRIVER_PULSEAUDIO
&PULSEAUDIO_bootstrap,
76
#endif
77
#if SDL_AUDIO_DRIVER_ALSA
78
&ALSA_bootstrap,
79
#endif
80
81
82
#if SDL_AUDIO_DRIVER_BSD
&BSD_AUDIO_bootstrap,
#endif
83
84
85
#if SDL_AUDIO_DRIVER_OSS
&DSP_bootstrap,
&DMA_bootstrap,
86
#endif
87
88
#if SDL_AUDIO_DRIVER_QSA
&QSAAUDIO_bootstrap,
89
#endif
90
#if SDL_AUDIO_DRIVER_SUNAUDIO
91
&SUNAUDIO_bootstrap,
92
#endif
93
#if SDL_AUDIO_DRIVER_ARTS
94
&ARTS_bootstrap,
95
#endif
96
#if SDL_AUDIO_DRIVER_ESD
97
&ESD_bootstrap,
98
#endif
99
#if SDL_AUDIO_DRIVER_NAS
100
&NAS_bootstrap,
101
#endif
102
#if SDL_AUDIO_DRIVER_DSOUND
103
&DSOUND_bootstrap,
104
#endif
105
106
#if SDL_AUDIO_DRIVER_WINWAVEOUT
&WINWAVEOUT_bootstrap,
107
#endif
108
109
#if SDL_AUDIO_DRIVER_PAUDIO
&PAUDIO_bootstrap,
110
#endif
111
112
#if SDL_AUDIO_DRIVER_BEOSAUDIO
&BEOSAUDIO_bootstrap,
113
#endif
114
#if SDL_AUDIO_DRIVER_COREAUDIO
115
&COREAUDIO_bootstrap,
116
#endif
117
118
119
#if SDL_AUDIO_DRIVER_COREAUDIOIPHONE
&COREAUDIOIPHONE_bootstrap,
#endif
120
#if SDL_AUDIO_DRIVER_DISK
121
&DISKAUD_bootstrap,
122
#endif
123
#if SDL_AUDIO_DRIVER_DUMMY
124
&DUMMYAUD_bootstrap,
125
#endif
126
127
#if SDL_AUDIO_DRIVER_NDS
&NDSAUD_bootstrap,
128
129
130
#endif
#if SDL_AUDIO_DRIVER_FUSIONSOUND
&FUSIONSOUND_bootstrap,
131
132
133
#endif
#if SDL_AUDIO_DRIVER_ANDROID
&ANDROIDAUD_bootstrap,
134
#endif
135
NULL
136
137
};
138
139
static SDL_AudioDevice *
get_audio_device(SDL_AudioDeviceID id)
140
141
{
id--;
142
if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
143
144
145
146
147
148
149
150
151
SDL_SetError("Invalid audio device ID");
return NULL;
}
return open_devices[id];
}
/* stubs for audio drivers that don't need a specific entry point... */
152
153
154
155
156
static int
SDL_AudioDetectDevices_Default(int iscapture)
{
return -1;
}
157
158
159
160
161
static void
SDL_AudioThreadInit_Default(_THIS)
{ /* no-op. */
}
162
163
164
165
166
static void
SDL_AudioWaitDevice_Default(_THIS)
{ /* no-op. */
}
167
168
169
170
171
static void
SDL_AudioPlayDevice_Default(_THIS)
{ /* no-op. */
}
172
173
174
175
176
177
static Uint8 *
SDL_AudioGetDeviceBuf_Default(_THIS)
{
return NULL;
}
178
179
180
181
182
static void
SDL_AudioWaitDone_Default(_THIS)
{ /* no-op. */
}
183
184
185
186
187
static void
SDL_AudioCloseDevice_Default(_THIS)
{ /* no-op. */
}
188
189
190
191
192
static void
SDL_AudioDeinitialize_Default(void)
{ /* no-op. */
}
193
194
195
196
197
198
199
static int
SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
{
return 0;
}
200
201
static const char *
SDL_AudioGetDeviceName_Default(int index, int iscapture)
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
{
SDL_SetError("No such device");
return NULL;
}
static void
SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
{
if (device->thread && (SDL_ThreadID() == device->threadid)) {
return;
}
SDL_mutexP(device->mixer_lock);
}
static void
SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
{
if (device->thread && (SDL_ThreadID() == device->threadid)) {
return;
}
SDL_mutexV(device->mixer_lock);
}
226
227
static void
finalize_audio_entry_points(void)
228
229
230
231
232
233
{
/*
* Fill in stub functions for unused driver entry points. This lets us
* blindly call them without having to check for validity first.
*/
234
#define FILL_STUB(x) \
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
if (current_audio.impl.x == NULL) { \
current_audio.impl.x = SDL_Audio##x##_Default; \
}
FILL_STUB(DetectDevices);
FILL_STUB(GetDeviceName);
FILL_STUB(OpenDevice);
FILL_STUB(ThreadInit);
FILL_STUB(WaitDevice);
FILL_STUB(PlayDevice);
FILL_STUB(GetDeviceBuf);
FILL_STUB(WaitDone);
FILL_STUB(CloseDevice);
FILL_STUB(LockDevice);
FILL_STUB(UnlockDevice);
FILL_STUB(Deinitialize);
250
#undef FILL_STUB
251
}
252
253
254
/* Streaming functions (for when the input and output buffer sizes are different) */
/* Write [length] bytes from buf into the streamer */
255
static void
256
257
258
259
260
261
262
263
264
265
266
SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
{
int i;
for (i = 0; i < length; ++i) {
stream->buffer[stream->write_pos] = buf[i];
++stream->write_pos;
}
}
/* Read [length] bytes out of the streamer into buf */
267
static void
268
269
270
271
272
273
274
275
276
277
SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
{
int i;
for (i = 0; i < length; ++i) {
buf[i] = stream->buffer[stream->read_pos];
++stream->read_pos;
}
}
278
static int
279
280
281
282
283
284
SDL_StreamLength(SDL_AudioStreamer * stream)
{
return (stream->write_pos - stream->read_pos) % stream->max_len;
}
/* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
285
#if 0
286
static int
287
288
289
SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
{
/* First try to allocate the buffer */
290
stream->buffer = (Uint8 *) SDL_malloc(max_len);
291
292
293
294
295
296
297
298
299
if (stream->buffer == NULL) {
return -1;
}
stream->max_len = max_len;
stream->read_pos = 0;
stream->write_pos = 0;
/* Zero out the buffer */
300
301
302
SDL_memset(stream->buffer, silence, max_len);
return 0;
303
}
304
#endif
305
306
/* Deinitialize the stream simply by freeing the buffer */
307
static void
308
309
310
SDL_StreamDeinit(SDL_AudioStreamer * stream)
{
if (stream->buffer != NULL) {
311
SDL_free(stream->buffer);
312
313
314
}
}
315
#if defined(ANDROID)
316
#include <android/log.h>
317
#endif
318
319
/* The general mixing thread function */
320
int SDLCALL
321
SDL_RunAudio(void *devicep)
322
{
323
SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
324
325
326
327
328
Uint8 *stream;
int stream_len;
void *udata;
void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
int silence;
329
Uint32 delay;
330
331
/* For streaming when the buffer sizes don't match up */
Uint8 *istream;
332
int istream_len = 0;
333
334
335
336
/* The audio mixing is always a high priority thread */
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
337
/* Perform any thread setup */
338
339
device->threadid = SDL_ThreadID();
current_audio.impl.ThreadInit(device);
340
341
/* Set up the mixing function */
342
343
fill = device->spec.callback;
udata = device->spec.userdata;
344
345
346
347
/* By default do not stream */
device->use_streamer = 0;
348
349
if (device->convert.needed) {
if (device->convert.src_format == AUDIO_U8) {
350
351
352
353
silence = 0x80;
} else {
silence = 0;
}
354
355
#if 0 /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
/* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
stream_max_len = 2 * device->spec.size;
if (device->convert.len_mult > device->convert.len_div) {
stream_max_len *= device->convert.len_mult;
stream_max_len /= device->convert.len_div;
}
if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
0)
return -1;
device->use_streamer = 1;
/* istream_len should be the length of what we grab from the callback and feed to conversion,
so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
*/
istream_len =
device->spec.size * device->convert.len_div /
device->convert.len_mult;
}
376
#endif
377
378
379
/* stream_len = device->convert.len; */
stream_len = device->spec.size;
380
} else {
381
382
silence = device->spec.silence;
stream_len = device->spec.size;
383
}
384
385
386
387
/* Calculate the delay while paused */
delay = ((device->spec.samples * 1000) / device->spec.freq);
388
389
/* Determine if the streamer is necessary here */
if (device->use_streamer == 1) {
390
/* This code is almost the same as the old code. The difference is, instead of reading
391
392
393
394
395
396
397
398
399
400
401
402
directly from the callback into "stream", then converting and sending the audio off,
we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
However, reading and writing with streamer are done separately:
- We only call the callback and write to the streamer when the streamer does not
contain enough samples to output to the device.
- We only read from the streamer and tell the device to play when the streamer
does have enough samples to output.
This allows us to perform resampling in the conversion step, where the output of the
resampling process can be any number. We will have to see what a good size for the
stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
*/
while (device->enabled) {
403
404
405
406
407
408
if (device->paused) {
SDL_Delay(delay);
continue;
}
409
410
411
412
413
414
415
416
417
418
/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
if (SDL_StreamLength(&device->streamer) < stream_len) {
/* Set up istream */
if (device->convert.needed) {
if (device->convert.buf) {
istream = device->convert.buf;
} else {
continue;
}
} else {
419
420
421
/* FIXME: Ryan, this is probably wrong. I imagine we don't want to get
* a device buffer both here and below in the stream output.
*/
422
423
424
425
426
427
428
istream = current_audio.impl.GetDeviceBuf(device);
if (istream == NULL) {
istream = device->fake_stream;
}
}
/* Read from the callback into the _input_ stream */
429
430
431
SDL_mutexP(device->mixer_lock);
(*fill) (udata, istream, istream_len);
SDL_mutexV(device->mixer_lock);
432
433
434
435
436
437
438
439
440
441
442
443
444
/* Convert the audio if necessary and write to the streamer */
if (device->convert.needed) {
SDL_ConvertAudio(&device->convert);
if (istream == NULL) {
istream = device->fake_stream;
}
/*SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
SDL_StreamWrite(&device->streamer, device->convert.buf,
device->convert.len_cvt);
} else {
SDL_StreamWrite(&device->streamer, istream, istream_len);
}
445
}
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
/* Only output audio if the streamer has enough to output */
if (SDL_StreamLength(&device->streamer) >= stream_len) {
/* Set up the output stream */
if (device->convert.needed) {
if (device->convert.buf) {
stream = device->convert.buf;
} else {
continue;
}
} else {
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
}
}
/* Now read from the streamer */
SDL_StreamRead(&device->streamer, stream, stream_len);
/* Ready current buffer for play and change current buffer */
467
if (stream != device->fake_stream) {
468
current_audio.impl.PlayDevice(device);
469
/* Wait for an audio buffer to become available */
470
current_audio.impl.WaitDevice(device);
471
} else {
472
SDL_Delay(delay);
473
}
474
}
475
476
}
477
478
479
480
481
482
} else {
/* Otherwise, do not use the streamer. This is the old code. */
/* Loop, filling the audio buffers */
while (device->enabled) {
483
484
485
486
487
if (device->paused) {
SDL_Delay(delay);
continue;
}
488
489
490
491
492
493
494
495
496
497
498
499
500
/* Fill the current buffer with sound */
if (device->convert.needed) {
if (device->convert.buf) {
stream = device->convert.buf;
} else {
continue;
}
} else {
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
}
}
501
502
503
504
SDL_mutexP(device->mixer_lock);
(*fill) (udata, stream, stream_len);
SDL_mutexV(device->mixer_lock);
505
506
507
508
509
510
511
512
513
514
515
/* Convert the audio if necessary */
if (device->convert.needed) {
SDL_ConvertAudio(&device->convert);
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
}
SDL_memcpy(stream, device->convert.buf,
device->convert.len_cvt);
}
516
517
/* Ready current buffer for play and change current buffer */
518
if (stream != device->fake_stream) {
519
current_audio.impl.PlayDevice(device);
520
/* Wait for an audio buffer to become available */
521
current_audio.impl.WaitDevice(device);
522
} else {
523
SDL_Delay(delay);
524
}
525
526
527
528
}
}
/* Wait for the audio to drain.. */
529
current_audio.impl.WaitDone(device);
530
531
532
533
534
/* If necessary, deinit the streamer */
if (device->use_streamer == 1)
SDL_StreamDeinit(&device->streamer);
535
return (0);
536
537
}
538
539
static SDL_AudioFormat
540
SDL_ParseAudioFormat(const char *string)
541
{
542
#define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
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);
561
#undef CHECK_FMT_STRING
562
return 0;
563
564
}
565
566
int
SDL_GetNumAudioDrivers(void)
567
{
568
569
return (SDL_arraysize(bootstrap) - 1);
}
570
571
572
573
574
575
576
577
578
579
580
581
582
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)
{
583
584
585
int i = 0;
int initialized = 0;
int tried_to_init = 0;
586
587
if (SDL_WasInit(SDL_INIT_AUDIO)) {
588
SDL_AudioQuit(); /* shutdown driver if already running. */
589
590
}
591
592
SDL_memset(¤t_audio, '\0', sizeof(current_audio));
SDL_memset(open_devices, '\0', sizeof(open_devices));
593
594
/* Select the proper audio driver */
595
596
597
if (driver_name == NULL) {
driver_name = SDL_getenv("SDL_AUDIODRIVER");
}
598
599
600
601
for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
/* make sure we should even try this driver before doing so... */
const AudioBootStrap *backend = bootstrap[i];
602
603
if (((driver_name) && (SDL_strcasecmp(backend->name, driver_name))) ||
((!driver_name) && (backend->demand_only))) {
604
continue;
605
}
606
607
tried_to_init = 1;
608
SDL_memset(¤t_audio, 0, sizeof(current_audio));
609
610
current_audio.name = backend->name;
current_audio.desc = backend->desc;
611
initialized = backend->init(¤t_audio.impl);
612
}
613
614
615
616
if (!initialized) {
/* specific drivers will set the error message if they fail... */
if (!tried_to_init) {
617
if (driver_name) {
618
SDL_SetError("Audio target '%s' not available", driver_name);
619
620
621
622
} else {
SDL_SetError("No available audio device");
}
}
623
624
625
SDL_memset(¤t_audio, 0, sizeof(current_audio));
return (-1); /* No driver was available, so fail. */
626
}
627
628
629
finalize_audio_entry_points();
630
return (0);
631
632
}
633
634
635
636
637
/*
* Get the current audio driver name
*/
const char *
SDL_GetCurrentAudioDriver()
638
{
639
return current_audio.name;
640
641
}
642
643
int
644
SDL_GetNumAudioDevices(int iscapture)
645
{
646
647
648
649
650
651
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
return -1;
}
if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
return 0;
}
652
653
654
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
return 1;
655
656
}
657
658
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
return 1;
659
660
}
661
662
663
664
665
666
667
668
669
670
return current_audio.impl.DetectDevices(iscapture);
}
const char *
SDL_GetAudioDeviceName(int index, int iscapture)
{
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_SetError("Audio subsystem is not initialized");
return NULL;
671
}
672
673
674
675
if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
SDL_SetError("No capture support");
return NULL;
676
}
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
if (index < 0) {
SDL_SetError("No such device");
return NULL;
}
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
return DEFAULT_INPUT_DEVNAME;
}
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
return DEFAULT_OUTPUT_DEVNAME;
}
return current_audio.impl.GetDeviceName(index, iscapture);
}
static void
696
close_audio_device(SDL_AudioDevice * device)
697
698
699
700
701
702
703
{
device->enabled = 0;
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
}
if (device->mixer_lock != NULL) {
SDL_DestroyMutex(device->mixer_lock);
704
}
705
706
if (device->fake_stream != NULL) {
SDL_FreeAudioMem(device->fake_stream);
707
}
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
if (device->convert.needed) {
SDL_FreeAudioMem(device->convert.buf);
}
if (device->opened) {
current_audio.impl.CloseDevice(device);
device->opened = 0;
}
SDL_FreeAudioMem(device);
}
/*
* 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
725
prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
726
{
727
SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
728
729
730
731
732
733
734
735
if (orig->callback == NULL) {
SDL_SetError("SDL_OpenAudio() passed a NULL callback");
return 0;
}
if (orig->freq == 0) {
const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
736
737
if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
prepared->freq = 22050; /* a reasonable default */
738
739
}
}
740
741
742
743
if (orig->format == 0) {
const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
744
prepared->format = AUDIO_S16; /* a reasonable default */
745
746
747
748
}
}
switch (orig->channels) {
749
750
case 0:{
const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
751
if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
752
753
754
prepared->channels = 2; /* a reasonable default */
}
break;
755
}
756
757
758
759
760
761
case 1: /* Mono */
case 2: /* Stereo */
case 4: /* surround */
case 6: /* surround with center and lfe */
break;
default:
762
763
SDL_SetError("Unsupported number of audio channels.");
return 0;
764
}
765
766
767
if (orig->samples == 0) {
const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
768
if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
769
770
771
772
773
774
775
776
/* 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;
777
778
}
}
779
780
781
782
783
784
785
786
787
788
/* 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,
789
790
const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
int allowed_changes, int min_id)
791
792
{
SDL_AudioDeviceID id = 0;
793
SDL_AudioSpec _obtained;
794
SDL_AudioDevice *device;
795
SDL_bool build_cvt;
796
797
798
799
800
int i = 0;
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_SetError("Audio subsystem is not initialized");
return 0;
801
}
802
803
804
805
if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
SDL_SetError("No capture support");
return 0;
806
}
807
808
809
810
811
if (!obtained) {
obtained = &_obtained;
}
if (!prepare_audiospec(desired, obtained)) {
812
813
return 0;
}
814
815
816
817
818
/* If app doesn't care about a specific device, let the user override. */
if (devname == NULL) {
devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
}
819
820
821
822
823
824
825
826
827
828
/*
* Catch device names at the high level for the simple case...
* This lets us have a basic "device enumeration" for systems that
* don't have multiple devices, but makes sure the device name is
* always NULL when it hits the low level.
*
* Also make sure that the simple case prevents multiple simultaneous
* opens of the default system device.
*/
829
830
831
832
833
834
835
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
SDL_SetError("No such device");
return 0;
}
devname = NULL;
836
837
838
839
840
841
842
for (i = 0; i < SDL_arraysize(open_devices); i++) {
if ((open_devices[i]) && (open_devices[i]->iscapture)) {
SDL_SetError("Audio device already open");
return 0;
}
}
843
844
}
845
846
847
848
849
850
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
SDL_SetError("No such device");
return 0;
}
devname = NULL;
851
852
853
854
855
856
857
858
for (i = 0; i < SDL_arraysize(open_devices); i++) {
if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
SDL_SetError("Audio device already open");
return 0;
}
}
}
859
860
device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
861
862
863
if (device == NULL) {
SDL_OutOfMemory();
return 0;
864
}
865
SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
866
device->spec = *obtained;
867
868
869
device->enabled = 1;
device->paused = 1;
device->iscapture = iscapture;
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
/* Create a semaphore for locking the sound buffers */
if (!current_audio.impl.SkipMixerLock) {
device->mixer_lock = SDL_CreateMutex();
if (device->mixer_lock == NULL) {
close_audio_device(device);
SDL_SetError("Couldn't create mixer lock");
return 0;
}
}
if (!current_audio.impl.OpenDevice(device, devname, iscapture)) {
close_audio_device(device);
return 0;
}
device->opened = 1;
886
887
/* Allocate a fake audio memory buffer */
888
device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
889
890
if (device->fake_stream == NULL) {
close_audio_device(device);
891
SDL_OutOfMemory();
892
return 0;
893
894
}
895
896
897
898
899
900
/* If the audio driver changes the buffer size, accept it */
if (device->spec.samples != obtained->samples) {
obtained->samples = device->spec.samples;
SDL_CalculateAudioSpec(obtained);
}
901
/* See if we need to do any conversion */
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
build_cvt = SDL_FALSE;
if (obtained->freq != device->spec.freq) {
if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
obtained->freq = device->spec.freq;
} else {
build_cvt = SDL_TRUE;
}
}
if (obtained->format != device->spec.format) {
if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
obtained->format = device->spec.format;
} else {
build_cvt = SDL_TRUE;
}
}
if (obtained->channels != device->spec.channels) {
if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
obtained->channels = device->spec.channels;
} else {
build_cvt = SDL_TRUE;
}
}
if (build_cvt) {
925
/* Build an audio conversion block */
926
if (SDL_BuildAudioCVT(&device->convert,
927
928
obtained->format, obtained->channels,
obtained->freq,
929
930
931
932
device->spec.format, device->spec.channels,
device->spec.freq) < 0) {
close_audio_device(device);
return 0;
933
}
934
if (device->convert.needed) {
935
device->convert.len = (int) (((double) obtained->size) /
936
device->convert.len_ratio);
937
938
939
940
941
942
device->convert.buf =
(Uint8 *) SDL_AllocAudioMem(device->convert.len *
device->convert.len_mult);
if (device->convert.buf == NULL) {
close_audio_device(device);
943
SDL_OutOfMemory();
944
return 0;
945
946
947
}
}
}
948
949
/* Find an available device ID and store the structure... */
950
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
951
952
953
954
955
956
957
958
959
960
961
962
if (open_devices[id] == NULL) {
open_devices[id] = device;
break;
}
}
if (id == SDL_arraysize(open_devices)) {
SDL_SetError("Too many open audio devices");
close_audio_device(device);
return 0;
}
963
/* Start the audio thread if necessary */
964
if (!current_audio.impl.ProvidesOwnCallbackThread) {
965
/* Start the audio thread */
966
/* !!! FIXME: this is nasty. */
967
#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
968
#undef SDL_CreateThread
969
device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
970
#else
971
device->thread = SDL_CreateThread(SDL_RunAudio, device);
972
#endif
973
if (device->thread == NULL) {
974
SDL_CloseAudioDevice(id + 1);
975
SDL_SetError("Couldn't create audio thread");
976
977
978
979
return 0;
}
}
980
return id + 1;
981
982
983
984
}
int
985
SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
986
987
988
989
990
991
{
SDL_AudioDeviceID id = 0;
/* Start up the audio driver, if necessary. This is legacy behaviour! */
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
992
993
return (-1);
}
994
}
995
996
997
998
999
/* 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);
1000
}