This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_audio.c
803 lines (726 loc) · 20.5 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
/* Available audio drivers */
static AudioBootStrap *bootstrap[] = {
39
#if SDL_AUDIO_DRIVER_BSD
40
&BSD_AUDIO_bootstrap,
41
#endif
42
#if SDL_AUDIO_DRIVER_OSS
43
44
&DSP_bootstrap,
&DMA_bootstrap,
45
#endif
46
#if SDL_AUDIO_DRIVER_ALSA
47
&ALSA_bootstrap,
48
#endif
49
#if SDL_AUDIO_DRIVER_QNXNTO
50
&QNXNTOAUDIO_bootstrap,
51
#endif
52
#if SDL_AUDIO_DRIVER_SUNAUDIO
53
&SUNAUDIO_bootstrap,
54
#endif
55
#if SDL_AUDIO_DRIVER_DMEDIA
56
&DMEDIA_bootstrap,
57
#endif
58
#if SDL_AUDIO_DRIVER_ARTS
59
&ARTS_bootstrap,
60
#endif
61
#if SDL_AUDIO_DRIVER_ESD
62
&ESD_bootstrap,
63
#endif
64
#if SDL_AUDIO_DRIVER_NAS
65
&NAS_bootstrap,
66
#endif
67
#if SDL_AUDIO_DRIVER_DSOUND
68
&DSOUND_bootstrap,
69
#endif
70
#if SDL_AUDIO_DRIVER_WAVEOUT
71
&WAVEOUT_bootstrap,
72
#endif
73
#if SDL_AUDIO_DRIVER_PAUD
74
&Paud_bootstrap,
75
76
#endif
#if SDL_AUDIO_DRIVER_BAUDIO
77
&BAUDIO_bootstrap,
78
#endif
79
#if SDL_AUDIO_DRIVER_COREAUDIO
80
&COREAUDIO_bootstrap,
81
#endif
82
#if SDL_AUDIO_DRIVER_SNDMGR
83
&SNDMGR_bootstrap,
84
#endif
85
#if SDL_AUDIO_DRIVER_AHI
86
&AHI_bootstrap,
87
#endif
88
#if SDL_AUDIO_DRIVER_MINT
89
90
91
92
93
&MINTAUDIO_GSXB_bootstrap,
&MINTAUDIO_MCSN_bootstrap,
&MINTAUDIO_STFA_bootstrap,
&MINTAUDIO_XBIOS_bootstrap,
&MINTAUDIO_DMA8_bootstrap,
94
#endif
95
#if SDL_AUDIO_DRIVER_DISK
96
&DISKAUD_bootstrap,
97
#endif
98
#if SDL_AUDIO_DRIVER_DUMMY
99
&DUMMYAUD_bootstrap,
100
#endif
101
#if SDL_AUDIO_DRIVER_DC
102
&DCAUD_bootstrap,
103
#endif
104
#if SDL_AUDIO_DRIVER_MMEAUDIO
105
&MMEAUDIO_bootstrap,
106
107
#endif
#if SDL_AUDIO_DRIVER_DART
108
&DART_bootstrap,
109
#endif
110
NULL
111
112
113
114
};
SDL_AudioDevice *current_audio = NULL;
/* Various local functions */
115
116
int SDL_AudioInit(const char *driver_name);
void SDL_AudioQuit(void);
117
118
#if SDL_AUDIO_DRIVER_AHI
119
120
static int audio_configured = 0;
#endif
121
122
/* The general mixing thread function */
123
int SDLCALL
124
SDL_RunAudio(void *audiop)
125
{
126
127
128
129
130
131
SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
Uint8 *stream;
int stream_len;
void *udata;
void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
int silence;
132
#if SDL_AUDIO_DRIVER_AHI
133
int started = 0;
134
135
136
/* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
137
D(bug("Task audio started audio struct:<%lx>...\n", audiop));
138
139
140
141
D(bug("Before Openaudio..."));
if (audio->OpenAudio(audio, &audio->spec) == -1) {
D(bug("Open audio failed...\n"));
142
143
return (-1);
}
144
D(bug("OpenAudio...OK\n"));
145
#endif
146
147
148
/* Perform any thread setup */
if (audio->ThreadInit) {
149
audio->ThreadInit(audio);
150
}
151
audio->threadid = SDL_ThreadID();
152
153
154
155
/* Set up the mixing function */
fill = audio->spec.callback;
udata = audio->spec.userdata;
156
157
#if SDL_AUDIO_DRIVER_AHI
158
audio_configured = 1;
159
160
161
162
D(bug("Audio configured... Checking for conversion\n"));
SDL_mutexP(audio->mixer_lock);
D(bug("Semaphore obtained...\n"));
163
164
#endif
165
166
167
168
169
170
171
172
173
174
175
if (audio->convert.needed) {
if (audio->convert.src_format == AUDIO_U8) {
silence = 0x80;
} else {
silence = 0;
}
stream_len = audio->convert.len;
} else {
silence = audio->spec.silence;
stream_len = audio->spec.size;
}
176
177
#if SDL_AUDIO_DRIVER_AHI
178
179
SDL_mutexV(audio->mixer_lock);
D(bug("Entering audio loop...\n"));
180
181
#endif
182
#ifdef __OS2__
183
184
/* Increase the priority of this thread to make sure that
the audio will be continuous all the time! */
185
#ifdef USE_DOSSETPRIORITY
186
if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
187
#ifdef DEBUG_BUILD
188
189
printf
("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
190
SDL_ThreadID());
191
#endif
192
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
193
} else {
194
#ifdef DEBUG_BUILD
195
196
printf
("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
197
SDL_ThreadID());
198
#endif
199
DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
}
#endif
#endif
/* Loop, filling the audio buffers */
while (audio->enabled) {
/* Fill the current buffer with sound */
if (audio->convert.needed) {
if (audio->convert.buf) {
stream = audio->convert.buf;
} else {
continue;
}
} else {
215
stream = audio->GetAudioBuf(audio);
216
217
218
219
if (stream == NULL) {
stream = audio->fake_stream;
}
}
220
SDL_memset(stream, silence, stream_len);
221
222
if (!audio->paused) {
223
SDL_mutexP(audio->mixer_lock);
224
(*fill) (udata, stream, stream_len);
225
SDL_mutexV(audio->mixer_lock);
226
227
228
229
}
/* Convert the audio if necessary */
if (audio->convert.needed) {
230
231
SDL_ConvertAudio(&audio->convert);
stream = audio->GetAudioBuf(audio);
232
233
234
if (stream == NULL) {
stream = audio->fake_stream;
}
235
SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
236
}
237
238
239
/* Ready current buffer for play and change current buffer */
if (stream != audio->fake_stream) {
240
audio->PlayAudio(audio);
241
242
243
244
}
/* Wait for an audio buffer to become available */
if (stream == audio->fake_stream) {
245
SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq);
246
} else {
247
audio->WaitAudio(audio);
248
249
}
}
250
251
252
/* Wait for the audio to drain.. */
if (audio->WaitDone) {
253
audio->WaitDone(audio);
254
}
255
#if SDL_AUDIO_DRIVER_AHI
256
D(bug("WaitAudio...Done\n"));
257
258
audio->CloseAudio(audio);
259
260
D(bug("CloseAudio..Done, subtask exiting...\n"));
261
audio_configured = 0;
262
263
264
#endif
#ifdef __OS2__
#ifdef DEBUG_BUILD
265
printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
266
#endif
267
#endif
268
return (0);
269
270
}
271
static void
272
SDL_LockAudio_Default(SDL_AudioDevice * audio)
273
{
274
if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
275
276
return;
}
277
SDL_mutexP(audio->mixer_lock);
278
279
}
280
static void
281
SDL_UnlockAudio_Default(SDL_AudioDevice * audio)
282
{
283
if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
284
285
return;
}
286
SDL_mutexV(audio->mixer_lock);
287
288
}
289
static Uint16
290
SDL_ParseAudioFormat(const char *string)
291
{
292
293
294
295
296
297
298
299
300
301
302
303
304
305
Uint16 format = 0;
switch (*string) {
case 'U':
++string;
format |= 0x0000;
break;
case 'S':
++string;
format |= 0x8000;
break;
default:
return 0;
}
306
switch (SDL_atoi(string)) {
307
308
309
310
311
312
313
case 8:
string += 1;
format |= 8;
break;
case 16:
string += 2;
format |= 16;
314
if (SDL_strcmp(string, "LSB") == 0
315
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
316
|| SDL_strcmp(string, "SYS") == 0
317
#endif
318
319
320
) {
format |= 0x0000;
}
321
if (SDL_strcmp(string, "MSB") == 0
322
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
323
|| SDL_strcmp(string, "SYS") == 0
324
325
326
327
328
329
330
331
332
#endif
) {
format |= 0x1000;
}
break;
default:
return 0;
}
return format;
333
334
}
335
int
336
SDL_GetNumAudioDrivers(void)
337
{
338
return (SDL_arraysize(bootstrap) - 1);
339
340
}
341
const char *
342
SDL_GetAudioDriver(int index)
343
{
344
if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
345
346
347
return (bootstrap[index]->name);
}
return (NULL);
348
349
}
350
int
351
SDL_AudioInit(const char *driver_name)
352
{
353
354
SDL_AudioDevice *audio;
int i = 0, idx;
355
356
357
/* Check to make sure we don't overwrite 'current_audio' */
if (current_audio != NULL) {
358
SDL_AudioQuit();
359
}
360
361
362
363
/* Select the proper audio driver */
audio = NULL;
idx = 0;
364
#if SDL_AUDIO_DRIVER_ESD
365
if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
366
367
368
369
370
/* 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) {
371
if (SDL_strcmp(bootstrap[i]->name, "esd") == 0) {
372
#ifdef HAVE_PUTENV
373
374
375
const char *esd_no_spawn;
/* Don't start ESD if it's not running */
376
esd_no_spawn = getenv("ESD_NO_SPAWN");
377
if (esd_no_spawn == NULL) {
378
putenv("ESD_NO_SPAWN=1");
379
380
}
#endif
381
382
if (bootstrap[i]->available()) {
audio = bootstrap[i]->create(0);
383
384
break;
}
385
#ifdef HAVE_UNSETENV
386
if (esd_no_spawn == NULL) {
387
unsetenv("ESD_NO_SPAWN");
388
}
389
#endif
390
391
392
}
}
}
393
#endif /* SDL_AUDIO_DRIVER_ESD */
394
395
396
if (audio == NULL) {
if (driver_name != NULL) {
#if 0 /* This will be replaced with a better driver selection API */
397
398
if (SDL_strrchr(driver_name, ':') != NULL) {
idx = atoi(SDL_strrchr(driver_name, ':') + 1);
399
400
401
}
#endif
for (i = 0; bootstrap[i]; ++i) {
402
403
404
405
if (SDL_strncmp(bootstrap[i]->name, driver_name,
SDL_strlen(bootstrap[i]->name)) == 0) {
if (bootstrap[i]->available()) {
audio = bootstrap[i]->create(idx);
406
407
408
409
410
411
}
break;
}
}
} else {
for (i = 0; bootstrap[i]; ++i) {
412
413
if (bootstrap[i]->available()) {
audio = bootstrap[i]->create(idx);
414
415
416
417
418
419
420
421
if (audio != NULL) {
break;
}
}
}
}
if (audio == NULL) {
if (driver_name) {
422
SDL_SetError("%s not available", driver_name);
423
} else {
424
SDL_SetError("No available audio device");
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
}
#if 0 /* Don't fail SDL_Init() if audio isn't available.
SDL_OpenAudio() will handle it at that point. *sigh*
*/
return (-1);
#endif
}
}
current_audio = audio;
if (current_audio) {
current_audio->name = bootstrap[i]->name;
if (!current_audio->LockAudio && !current_audio->UnlockAudio) {
current_audio->LockAudio = SDL_LockAudio_Default;
current_audio->UnlockAudio = SDL_UnlockAudio_Default;
}
}
return (0);
442
443
}
444
445
446
447
/*
* Get the current audio driver name
*/
const char *
448
SDL_GetCurrentAudioDriver()
449
{
450
451
452
453
if (current_audio) {
return current_audio->name;
}
return (NULL);
454
455
}
456
int
457
SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
458
{
459
460
461
462
463
SDL_AudioDevice *audio;
const char *env;
/* Start up the audio driver, if necessary */
if (!current_audio) {
464
if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
465
466
467
468
469
470
471
(current_audio == NULL)) {
return (-1);
}
}
audio = current_audio;
if (audio->opened) {
472
SDL_SetError("Audio device is already opened");
473
474
475
476
477
return (-1);
}
/* Verify some parameters */
if (desired->freq == 0) {
478
env = SDL_getenv("SDL_AUDIO_FREQUENCY");
479
if (env) {
480
desired->freq = SDL_atoi(env);
481
482
483
484
485
486
487
}
}
if (desired->freq == 0) {
/* Pick some default audio frequency */
desired->freq = 22050;
}
if (desired->format == 0) {
488
env = SDL_getenv("SDL_AUDIO_FORMAT");
489
if (env) {
490
desired->format = SDL_ParseAudioFormat(env);
491
492
493
494
495
496
497
}
}
if (desired->format == 0) {
/* Pick some default audio format */
desired->format = AUDIO_S16;
}
if (desired->channels == 0) {
498
env = SDL_getenv("SDL_AUDIO_CHANNELS");
499
if (env) {
500
desired->channels = SDL_atoi(env);
501
502
503
504
505
506
507
508
509
510
511
512
513
}
}
if (desired->channels == 0) {
/* Pick a default number of channels */
desired->channels = 2;
}
switch (desired->channels) {
case 1: /* Mono */
case 2: /* Stereo */
case 4: /* surround */
case 6: /* surround with center and lfe */
break;
default:
514
SDL_SetError("1 (mono) and 2 (stereo) channels supported");
515
516
517
return (-1);
}
if (desired->samples == 0) {
518
env = SDL_getenv("SDL_AUDIO_SAMPLES");
519
if (env) {
520
desired->samples = SDL_atoi(env);
521
522
523
524
525
526
527
528
529
530
531
532
}
}
if (desired->samples == 0) {
/* Pick a default of ~46 ms at desired frequency */
int samples = (desired->freq / 1000) * 46;
int power2 = 1;
while (power2 < samples) {
power2 *= 2;
}
desired->samples = power2;
}
if (desired->callback == NULL) {
533
SDL_SetError("SDL_OpenAudio() passed a NULL callback");
534
535
return (-1);
}
536
#if defined(__MACOS__) || (defined(__RISCOS__) && SDL_THREADS_DISABLED)
537
/* FIXME: Need to implement PPC interrupt asm for SDL_LockAudio() */
538
#else
539
#if defined(__MINT__) && SDL_THREADS_DISABLED
540
/* Uses interrupt driven audio, without thread */
541
#else
542
/* Create a semaphore for locking the sound buffers */
543
audio->mixer_lock = SDL_CreateMutex();
544
if (audio->mixer_lock == NULL) {
545
546
SDL_SetError("Couldn't create mixer lock");
SDL_CloseAudio();
547
548
return (-1);
}
549
#endif /* __MINT__ */
550
#endif /* __MACOS__ */
551
552
/* Calculate the silence and size of the audio specification */
553
SDL_CalculateAudioSpec(desired);
554
555
/* Open the audio subsystem */
556
SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
557
558
559
audio->convert.needed = 0;
audio->enabled = 1;
audio->paused = 1;
560
561
#if !SDL_AUDIO_DRIVER_AHI
562
563
/* AmigaOS opens audio inside the main loop */
564
audio->opened = audio->OpenAudio(audio, &audio->spec) + 1;
565
566
if (!audio->opened) {
567
SDL_CloseAudio();
568
569
return (-1);
}
570
#else
571
572
D(bug("Locking semaphore..."));
SDL_mutexP(audio->mixer_lock);
573
574
575
576
audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
D(bug("Created thread...\n"));
577
578
if (audio->thread == NULL) {
579
580
581
SDL_mutexV(audio->mixer_lock);
SDL_CloseAudio();
SDL_SetError("Couldn't create audio thread");
582
583
584
585
return (-1);
}
while (!audio_configured)
586
SDL_Delay(100);
587
588
589
590
591
#endif
/* If the audio driver changes the buffer size, accept it */
if (audio->spec.samples != desired->samples) {
desired->samples = audio->spec.samples;
592
SDL_CalculateAudioSpec(desired);
593
594
595
}
/* Allocate a fake audio memory buffer */
596
audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
597
if (audio->fake_stream == NULL) {
598
599
SDL_CloseAudio();
SDL_OutOfMemory();
600
601
602
603
604
return (-1);
}
/* See if we need to do any conversion */
if (obtained != NULL) {
605
SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
606
607
608
609
} else if (desired->freq != audio->spec.freq ||
desired->format != audio->spec.format ||
desired->channels != audio->spec.channels) {
/* Build an audio conversion block */
610
611
612
613
614
615
if (SDL_BuildAudioCVT(&audio->convert,
desired->format, desired->channels,
desired->freq,
audio->spec.format, audio->spec.channels,
audio->spec.freq) < 0) {
SDL_CloseAudio();
616
617
618
619
620
return (-1);
}
if (audio->convert.needed) {
audio->convert.len = desired->size;
audio->convert.buf =
621
622
(Uint8 *) SDL_AllocAudioMem(audio->convert.len *
audio->convert.len_mult);
623
if (audio->convert.buf == NULL) {
624
625
SDL_CloseAudio();
SDL_OutOfMemory();
626
627
628
629
return (-1);
}
}
}
630
#if !SDL_AUDIO_DRIVER_AHI
631
632
633
634
/* Start the audio thread if necessary */
switch (audio->opened) {
case 1:
/* Start the audio thread */
635
#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
636
#undef SDL_CreateThread
637
audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
638
#else
639
audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
640
641
#endif
if (audio->thread == NULL) {
642
643
SDL_CloseAudio();
SDL_SetError("Couldn't create audio thread");
644
645
646
647
648
649
650
651
return (-1);
}
break;
default:
/* The audio is now playing */
break;
}
652
#else
653
654
SDL_mutexV(audio->mixer_lock);
D(bug("SDL_OpenAudio USCITA...\n"));
655
656
657
#endif
658
return (0);
659
660
}
661
SDL_audiostatus
662
SDL_GetAudioStatus(void)
663
{
664
665
666
667
668
669
670
671
672
673
674
675
SDL_AudioDevice *audio = current_audio;
SDL_audiostatus status;
status = SDL_AUDIO_STOPPED;
if (audio && audio->enabled) {
if (audio->paused) {
status = SDL_AUDIO_PAUSED;
} else {
status = SDL_AUDIO_PLAYING;
}
}
return (status);
676
677
}
678
void
679
SDL_PauseAudio(int pause_on)
680
{
681
SDL_AudioDevice *audio = current_audio;
682
683
684
685
if (audio) {
audio->paused = pause_on;
}
686
687
}
688
void
689
SDL_LockAudio(void)
690
{
691
SDL_AudioDevice *audio = current_audio;
692
693
694
/* Obtain a lock on the mixing buffers */
if (audio && audio->LockAudio) {
695
audio->LockAudio(audio);
696
}
697
698
}
699
void
700
SDL_UnlockAudio(void)
701
{
702
SDL_AudioDevice *audio = current_audio;
703
704
705
/* Release lock on the mixing buffers */
if (audio && audio->UnlockAudio) {
706
audio->UnlockAudio(audio);
707
}
708
709
}
710
void
711
SDL_CloseAudio(void)
712
{
713
SDL_QuitSubSystem(SDL_INIT_AUDIO);
714
715
}
716
void
717
SDL_AudioQuit(void)
718
{
719
720
721
722
723
SDL_AudioDevice *audio = current_audio;
if (audio) {
audio->enabled = 0;
if (audio->thread != NULL) {
724
SDL_WaitThread(audio->thread, NULL);
725
726
}
if (audio->mixer_lock != NULL) {
727
SDL_DestroyMutex(audio->mixer_lock);
728
729
}
if (audio->fake_stream != NULL) {
730
SDL_FreeAudioMem(audio->fake_stream);
731
732
}
if (audio->convert.needed) {
733
SDL_FreeAudioMem(audio->convert.buf);
734
735
}
736
#if !SDL_AUDIO_DRIVER_AHI
737
if (audio->opened) {
738
audio->CloseAudio(audio);
739
740
741
742
audio->opened = 0;
}
#endif
/* Free the driver data */
743
audio->free(audio);
744
745
current_audio = NULL;
}
746
747
748
749
750
751
}
#define NUM_FORMATS 6
static int format_idx;
static int format_idx_sub;
static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = {
752
753
754
755
756
757
758
759
760
761
762
763
{AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
AUDIO_U16MSB},
{AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
AUDIO_U16MSB},
{AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8,
AUDIO_S8},
{AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8,
AUDIO_S8},
{AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8,
AUDIO_S8},
{AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8,
AUDIO_S8},
764
765
};
766
Uint16
767
SDL_FirstAudioFormat(Uint16 format)
768
{
769
770
771
772
773
774
for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
if (format_list[format_idx][0] == format) {
break;
}
}
format_idx_sub = 0;
775
return (SDL_NextAudioFormat());
776
777
}
778
Uint16
779
SDL_NextAudioFormat(void)
780
{
781
782
783
784
if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
return (0);
}
return (format_list[format_idx][format_idx_sub++]);
785
786
}
787
void
788
SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
789
{
790
791
792
793
794
795
796
797
798
799
800
switch (spec->format) {
case AUDIO_U8:
spec->silence = 0x80;
break;
default:
spec->silence = 0x00;
break;
}
spec->size = (spec->format & 0xFF) / 8;
spec->size *= spec->channels;
spec->size *= spec->samples;
801
}
802
803
/* vi: set ts=4 sw=4 expandtab: */