1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     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 /* Allow access to a raw mixing buffer */
25 
26 #include "SDL.h"
27 #include "SDL_audio_c.h"
28 #include "SDL_audiomem.h"
29 #include "SDL_sysaudio.h"
30 
31 #ifdef __OS2__
32 /* We'll need the DosSetPriority() API! */
33 #define INCL_DOSPROCESS
34 #include <os2.h>
35 #endif
36 
37 /* Available audio drivers */
38 static AudioBootStrap *bootstrap[] = {
39 #if SDL_AUDIO_DRIVER_PULSE
40 	&PULSE_bootstrap,
41 #endif
42 #if SDL_AUDIO_DRIVER_ALSA
43 	&ALSA_bootstrap,
44 #endif
45 #if SDL_AUDIO_DRIVER_BSD
46 	&BSD_AUDIO_bootstrap,
47 #endif
48 #if SDL_AUDIO_DRIVER_OSS
49 	&DSP_bootstrap,
50 	&DMA_bootstrap,
51 #endif
52 #if SDL_AUDIO_DRIVER_QNXNTO
53 	&QNXNTOAUDIO_bootstrap,
54 #endif
55 #if SDL_AUDIO_DRIVER_SUNAUDIO
56 	&SUNAUDIO_bootstrap,
57 #endif
58 #if SDL_AUDIO_DRIVER_DMEDIA
59 	&DMEDIA_bootstrap,
60 #endif
61 #if SDL_AUDIO_DRIVER_ARTS
62 	&ARTS_bootstrap,
63 #endif
64 #if SDL_AUDIO_DRIVER_ESD
65 	&ESD_bootstrap,
66 #endif
67 #if SDL_AUDIO_DRIVER_NAS
68 	&NAS_bootstrap,
69 #endif
70 #if SDL_AUDIO_DRIVER_DSOUND
71 	&DSOUND_bootstrap,
72 #endif
73 #if SDL_AUDIO_DRIVER_WAVEOUT
74 	&WAVEOUT_bootstrap,
75 #endif
76 #if SDL_AUDIO_DRIVER_PAUD
77 	&Paud_bootstrap,
78 #endif
79 #if SDL_AUDIO_DRIVER_BAUDIO
80 	&BAUDIO_bootstrap,
81 #endif
82 #if SDL_AUDIO_DRIVER_COREAUDIO
83 	&COREAUDIO_bootstrap,
84 #endif
85 #if SDL_AUDIO_DRIVER_SNDMGR
86 	&SNDMGR_bootstrap,
87 #endif
88 #if SDL_AUDIO_DRIVER_MINT
89 	&MINTAUDIO_GSXB_bootstrap,
90 	&MINTAUDIO_MCSN_bootstrap,
91 	&MINTAUDIO_STFA_bootstrap,
92 	&MINTAUDIO_XBIOS_bootstrap,
93 	&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_NDS
105 	&NDSAUD_bootstrap,
106 #endif
107 #if SDL_AUDIO_DRIVER_MMEAUDIO
108 	&MMEAUDIO_bootstrap,
109 #endif
110 #if SDL_AUDIO_DRIVER_DART
111 	&DART_bootstrap,
112 #endif
113 #if SDL_AUDIO_DRIVER_EPOCAUDIO
114 	&EPOCAudio_bootstrap,
115 #endif
116 #if SDL_AUDIO_DRIVER_ANDROID
117 	&ANDROIDAUD_bootstrap,
118 #endif
119 	NULL
120 };
121 SDL_AudioDevice *current_audio = NULL;
122 
123 /* Various local functions */
124 int SDL_AudioInit(const char *driver_name);
125 void SDL_AudioQuit(void);
126 
127 /* The general mixing thread function */
SDL_RunAudio(void * audiop)128 int SDLCALL SDL_RunAudio(void *audiop)
129 {
130 	SDL_AudioDevice *audio = (SDL_AudioDevice *)audiop;
131 	Uint8 *stream;
132 	int    stream_len;
133 	void  *udata;
134 	void (SDLCALL *fill)(void *userdata,Uint8 *stream, int len);
135 	int    silence;
136 
137 	/* Perform any thread setup */
138 	if ( audio->ThreadInit ) {
139 		audio->ThreadInit(audio);
140 	}
141 	audio->threadid = SDL_ThreadID();
142 
143 	/* Set up the mixing function */
144 	fill  = audio->spec.callback;
145 	udata = audio->spec.userdata;
146 
147 	if ( audio->convert.needed ) {
148 		if ( audio->convert.src_format == AUDIO_U8 ) {
149 			silence = 0x80;
150 		} else {
151 			silence = 0;
152 		}
153 		stream_len = audio->convert.len;
154 	} else {
155 		silence = audio->spec.silence;
156 		stream_len = audio->spec.size;
157 	}
158 
159 #ifdef __OS2__
160         /* Increase the priority of this thread to make sure that
161            the audio will be continuous all the time! */
162 #ifdef USE_DOSSETPRIORITY
163         if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO"))
164         {
165 #ifdef DEBUG_BUILD
166           printf("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n", SDL_ThreadID());
167 #endif
168           DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
169         }
170         else
171         {
172 #ifdef DEBUG_BUILD
173           printf("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID());
174 #endif
175           DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
176         }
177 #endif
178 #endif
179 
180 	/* Loop, filling the audio buffers */
181 	while ( audio->enabled ) {
182 
183 		/* Fill the current buffer with sound */
184 		if ( audio->convert.needed ) {
185 			if ( audio->convert.buf ) {
186 				stream = audio->convert.buf;
187 			} else {
188 				continue;
189 			}
190 		} else {
191 			stream = audio->GetAudioBuf(audio);
192 			if ( stream == NULL ) {
193 				stream = audio->fake_stream;
194 			}
195 		}
196 
197 		SDL_memset(stream, silence, stream_len);
198 
199 		if ( ! audio->paused ) {
200 			SDL_mutexP(audio->mixer_lock);
201 			(*fill)(udata, stream, stream_len);
202 			SDL_mutexV(audio->mixer_lock);
203 		}
204 
205 		/* Convert the audio if necessary */
206 		if ( audio->convert.needed ) {
207 			SDL_ConvertAudio(&audio->convert);
208 			stream = audio->GetAudioBuf(audio);
209 			if ( stream == NULL ) {
210 				stream = audio->fake_stream;
211 			}
212 			SDL_memcpy(stream, audio->convert.buf,
213 			               audio->convert.len_cvt);
214 		}
215 
216 		/* Ready current buffer for play and change current buffer */
217 		if ( stream != audio->fake_stream ) {
218 			audio->PlayAudio(audio);
219 		}
220 
221 		/* Wait for an audio buffer to become available */
222 		if ( stream == audio->fake_stream ) {
223 			SDL_Delay((audio->spec.samples*1000)/audio->spec.freq);
224 		} else {
225 			audio->WaitAudio(audio);
226 		}
227 	}
228 
229 	/* Wait for the audio to drain.. */
230 	if ( audio->WaitDone ) {
231 		audio->WaitDone(audio);
232 	}
233 
234 #ifdef __OS2__
235 #ifdef DEBUG_BUILD
236         printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
237 #endif
238 #endif
239 	return(0);
240 }
241 
SDL_LockAudio_Default(SDL_AudioDevice * audio)242 static void SDL_LockAudio_Default(SDL_AudioDevice *audio)
243 {
244 	if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
245 		return;
246 	}
247 	SDL_mutexP(audio->mixer_lock);
248 }
249 
SDL_UnlockAudio_Default(SDL_AudioDevice * audio)250 static void SDL_UnlockAudio_Default(SDL_AudioDevice *audio)
251 {
252 	if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
253 		return;
254 	}
255 	SDL_mutexV(audio->mixer_lock);
256 }
257 
SDL_ParseAudioFormat(const char * string)258 static Uint16 SDL_ParseAudioFormat(const char *string)
259 {
260 	Uint16 format = 0;
261 
262 	switch (*string) {
263 	    case 'U':
264 		++string;
265 		format |= 0x0000;
266 		break;
267 	    case 'S':
268 		++string;
269 		format |= 0x8000;
270 		break;
271 	    default:
272 		return 0;
273 	}
274 	switch (SDL_atoi(string)) {
275 	    case 8:
276 		string += 1;
277 		format |= 8;
278 		break;
279 	    case 16:
280 		string += 2;
281 		format |= 16;
282 		if ( SDL_strcmp(string, "LSB") == 0
283 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
284 		     || SDL_strcmp(string, "SYS") == 0
285 #endif
286 		    ) {
287 			format |= 0x0000;
288 		}
289 		if ( SDL_strcmp(string, "MSB") == 0
290 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
291 		     || SDL_strcmp(string, "SYS") == 0
292 #endif
293 		    ) {
294 			format |= 0x1000;
295 		}
296 		break;
297 	    default:
298 		return 0;
299 	}
300 	return format;
301 }
302 
SDL_AudioInit(const char * driver_name)303 int SDL_AudioInit(const char *driver_name)
304 {
305 	SDL_AudioDevice *audio;
306 	int i = 0, idx;
307 
308 	/* Check to make sure we don't overwrite 'current_audio' */
309 	if ( current_audio != NULL ) {
310 		SDL_AudioQuit();
311 	}
312 
313 	/* Select the proper audio driver */
314 	audio = NULL;
315 	idx = 0;
316 #if SDL_AUDIO_DRIVER_ESD
317 	if ( (driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL) ) {
318 		/* Ahem, we know that if ESPEAKER is set, user probably wants
319 		   to use ESD, but don't start it if it's not already running.
320 		   This probably isn't the place to do this, but... Shh! :)
321 		 */
322 		for ( i=0; bootstrap[i]; ++i ) {
323 			if ( SDL_strcasecmp(bootstrap[i]->name, "esd") == 0 ) {
324 #ifdef HAVE_PUTENV
325 				const char *esd_no_spawn;
326 
327 				/* Don't start ESD if it's not running */
328 				esd_no_spawn = getenv("ESD_NO_SPAWN");
329 				if ( esd_no_spawn == NULL ) {
330 					putenv("ESD_NO_SPAWN=1");
331 				}
332 #endif
333 				if ( bootstrap[i]->available() ) {
334 					audio = bootstrap[i]->create(0);
335 					break;
336 				}
337 #ifdef HAVE_UNSETENV
338 				if ( esd_no_spawn == NULL ) {
339 					unsetenv("ESD_NO_SPAWN");
340 				}
341 #endif
342 			}
343 		}
344 	}
345 #endif /* SDL_AUDIO_DRIVER_ESD */
346 	if ( audio == NULL ) {
347 		if ( driver_name != NULL ) {
348 #if 0	/* This will be replaced with a better driver selection API */
349 			if ( SDL_strrchr(driver_name, ':') != NULL ) {
350 				idx = atoi(SDL_strrchr(driver_name, ':')+1);
351 			}
352 #endif
353 			for ( i=0; bootstrap[i]; ++i ) {
354 				if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
355 					if ( bootstrap[i]->available() ) {
356 						audio=bootstrap[i]->create(idx);
357 						break;
358 					}
359 				}
360 			}
361 		} else {
362 			for ( i=0; bootstrap[i]; ++i ) {
363 				if ( bootstrap[i]->available() ) {
364 					audio = bootstrap[i]->create(idx);
365 					if ( audio != NULL ) {
366 						break;
367 					}
368 				}
369 			}
370 		}
371 		if ( audio == NULL ) {
372 			SDL_SetError("No available audio device");
373 #if 0 /* Don't fail SDL_Init() if audio isn't available.
374          SDL_OpenAudio() will handle it at that point.  *sigh*
375        */
376 			return(-1);
377 #endif
378 		}
379 	}
380 	current_audio = audio;
381 	if ( current_audio ) {
382 		current_audio->name = bootstrap[i]->name;
383 		if ( !current_audio->LockAudio && !current_audio->UnlockAudio ) {
384 			current_audio->LockAudio = SDL_LockAudio_Default;
385 			current_audio->UnlockAudio = SDL_UnlockAudio_Default;
386 		}
387 	}
388 	return(0);
389 }
390 
SDL_AudioDriverName(char * namebuf,int maxlen)391 char *SDL_AudioDriverName(char *namebuf, int maxlen)
392 {
393 	if ( current_audio != NULL ) {
394 		SDL_strlcpy(namebuf, current_audio->name, maxlen);
395 		return(namebuf);
396 	}
397 	return(NULL);
398 }
399 
SDL_OpenAudio(SDL_AudioSpec * desired,SDL_AudioSpec * obtained)400 int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
401 {
402 	SDL_AudioDevice *audio;
403 	const char *env;
404 
405 	/* Start up the audio driver, if necessary */
406 	if ( ! current_audio ) {
407 		if ( (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
408 		     (current_audio == NULL) ) {
409 			return(-1);
410 		}
411 	}
412 	audio = current_audio;
413 
414 	if (audio->opened) {
415 		SDL_SetError("Audio device is already opened");
416 		return(-1);
417 	}
418 
419 	/* Verify some parameters */
420 	if ( desired->freq == 0 ) {
421 		env = SDL_getenv("SDL_AUDIO_FREQUENCY");
422 		if ( env ) {
423 			desired->freq = SDL_atoi(env);
424 		}
425 	}
426 	if ( desired->freq == 0 ) {
427 		/* Pick some default audio frequency */
428 		desired->freq = 22050;
429 	}
430 	if ( desired->format == 0 ) {
431 		env = SDL_getenv("SDL_AUDIO_FORMAT");
432 		if ( env ) {
433 			desired->format = SDL_ParseAudioFormat(env);
434 		}
435 	}
436 	if ( desired->format == 0 ) {
437 		/* Pick some default audio format */
438 		desired->format = AUDIO_S16;
439 	}
440 	if ( desired->channels == 0 ) {
441 		env = SDL_getenv("SDL_AUDIO_CHANNELS");
442 		if ( env ) {
443 			desired->channels = (Uint8)SDL_atoi(env);
444 		}
445 	}
446 	if ( desired->channels == 0 ) {
447 		/* Pick a default number of channels */
448 		desired->channels = 2;
449 	}
450 	switch ( desired->channels ) {
451 	    case 1:	/* Mono */
452 	    case 2:	/* Stereo */
453 	    case 4:	/* surround */
454 	    case 6:	/* surround with center and lfe */
455 		break;
456 	    default:
457 		SDL_SetError("1 (mono) and 2 (stereo) channels supported");
458 		return(-1);
459 	}
460 	if ( desired->samples == 0 ) {
461 		env = SDL_getenv("SDL_AUDIO_SAMPLES");
462 		if ( env ) {
463 			desired->samples = (Uint16)SDL_atoi(env);
464 		}
465 	}
466 	if ( desired->samples == 0 ) {
467 		/* Pick a default of ~46 ms at desired frequency */
468 		int samples = (desired->freq / 1000) * 46;
469 		int power2 = 1;
470 		while ( power2 < samples ) {
471 			power2 *= 2;
472 		}
473 		desired->samples = power2;
474 	}
475 	if ( desired->callback == NULL ) {
476 		SDL_SetError("SDL_OpenAudio() passed a NULL callback");
477 		return(-1);
478 	}
479 
480 #if SDL_THREADS_DISABLED
481 	/* Uses interrupt driven audio, without thread */
482 #else
483 	/* Create a semaphore for locking the sound buffers */
484 	audio->mixer_lock = SDL_CreateMutex();
485 	if ( audio->mixer_lock == NULL ) {
486 		SDL_SetError("Couldn't create mixer lock");
487 		SDL_CloseAudio();
488 		return(-1);
489 	}
490 #endif /* SDL_THREADS_DISABLED */
491 
492 	/* Calculate the silence and size of the audio specification */
493 	SDL_CalculateAudioSpec(desired);
494 
495 	/* Open the audio subsystem */
496 	SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
497 	audio->convert.needed = 0;
498 	audio->enabled = 1;
499 	audio->paused  = 1;
500 
501 	audio->opened = audio->OpenAudio(audio, &audio->spec)+1;
502 
503 	if ( ! audio->opened ) {
504 		SDL_CloseAudio();
505 		return(-1);
506 	}
507 
508 	/* If the audio driver changes the buffer size, accept it */
509 	if ( audio->spec.samples != desired->samples ) {
510 		desired->samples = audio->spec.samples;
511 		SDL_CalculateAudioSpec(desired);
512 	}
513 
514 	/* Allocate a fake audio memory buffer */
515 	audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
516 	if ( audio->fake_stream == NULL ) {
517 		SDL_CloseAudio();
518 		SDL_OutOfMemory();
519 		return(-1);
520 	}
521 
522 	/* See if we need to do any conversion */
523 	if ( obtained != NULL ) {
524 		SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
525 	} else if ( desired->freq != audio->spec.freq ||
526                     desired->format != audio->spec.format ||
527 	            desired->channels != audio->spec.channels ) {
528 		/* Build an audio conversion block */
529 		if ( SDL_BuildAudioCVT(&audio->convert,
530 			desired->format, desired->channels,
531 					desired->freq,
532 			audio->spec.format, audio->spec.channels,
533 					audio->spec.freq) < 0 ) {
534 			SDL_CloseAudio();
535 			return(-1);
536 		}
537 		if ( audio->convert.needed ) {
538 			audio->convert.len = (int) ( ((double) audio->spec.size) /
539                                           audio->convert.len_ratio );
540 			audio->convert.buf =(Uint8 *)SDL_AllocAudioMem(
541 			   audio->convert.len*audio->convert.len_mult);
542 			if ( audio->convert.buf == NULL ) {
543 				SDL_CloseAudio();
544 				SDL_OutOfMemory();
545 				return(-1);
546 			}
547 		}
548 	}
549 
550 	/* Start the audio thread if necessary */
551 	switch (audio->opened) {
552 		case  1:
553 			/* Start the audio thread */
554 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__)
555 #undef SDL_CreateThread
556 			audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
557 #else
558 			audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
559 #endif
560 			if ( audio->thread == NULL ) {
561 				SDL_CloseAudio();
562 				SDL_SetError("Couldn't create audio thread");
563 				return(-1);
564 			}
565 			break;
566 
567 		default:
568 			/* The audio is now playing */
569 			break;
570 	}
571 
572 	return(0);
573 }
574 
SDL_GetAudioStatus(void)575 SDL_audiostatus SDL_GetAudioStatus(void)
576 {
577 	SDL_AudioDevice *audio = current_audio;
578 	SDL_audiostatus status;
579 
580 	status = SDL_AUDIO_STOPPED;
581 	if ( audio && audio->enabled ) {
582 		if ( audio->paused ) {
583 			status = SDL_AUDIO_PAUSED;
584 		} else {
585 			status = SDL_AUDIO_PLAYING;
586 		}
587 	}
588 	return(status);
589 }
590 
SDL_PauseAudio(int pause_on)591 void SDL_PauseAudio (int pause_on)
592 {
593 	SDL_AudioDevice *audio = current_audio;
594 
595 	if ( audio ) {
596 		audio->paused = pause_on;
597 	}
598 }
599 
SDL_LockAudio(void)600 void SDL_LockAudio (void)
601 {
602 	SDL_AudioDevice *audio = current_audio;
603 
604 	/* Obtain a lock on the mixing buffers */
605 	if ( audio && audio->LockAudio ) {
606 		audio->LockAudio(audio);
607 	}
608 }
609 
SDL_UnlockAudio(void)610 void SDL_UnlockAudio (void)
611 {
612 	SDL_AudioDevice *audio = current_audio;
613 
614 	/* Release lock on the mixing buffers */
615 	if ( audio && audio->UnlockAudio ) {
616 		audio->UnlockAudio(audio);
617 	}
618 }
619 
SDL_CloseAudio(void)620 void SDL_CloseAudio (void)
621 {
622 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
623 }
624 
SDL_AudioQuit(void)625 void SDL_AudioQuit(void)
626 {
627 	SDL_AudioDevice *audio = current_audio;
628 
629 	if ( audio ) {
630 		audio->enabled = 0;
631 		if ( audio->thread != NULL ) {
632 			SDL_WaitThread(audio->thread, NULL);
633 		}
634 		if ( audio->mixer_lock != NULL ) {
635 			SDL_DestroyMutex(audio->mixer_lock);
636 		}
637 		if ( audio->fake_stream != NULL ) {
638 			SDL_FreeAudioMem(audio->fake_stream);
639 		}
640 		if ( audio->convert.needed ) {
641 			SDL_FreeAudioMem(audio->convert.buf);
642 
643 		}
644 		if ( audio->opened ) {
645 			audio->CloseAudio(audio);
646 			audio->opened = 0;
647 		}
648 		/* Free the driver data */
649 		audio->free(audio);
650 		current_audio = NULL;
651 	}
652 }
653 
654 #define NUM_FORMATS	6
655 static int format_idx;
656 static int format_idx_sub;
657 static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = {
658  { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
659  { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
660  { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
661  { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
662  { AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
663  { AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
664 };
665 
SDL_FirstAudioFormat(Uint16 format)666 Uint16 SDL_FirstAudioFormat(Uint16 format)
667 {
668 	for ( format_idx=0; format_idx < NUM_FORMATS; ++format_idx ) {
669 		if ( format_list[format_idx][0] == format ) {
670 			break;
671 		}
672 	}
673 	format_idx_sub = 0;
674 	return(SDL_NextAudioFormat());
675 }
676 
SDL_NextAudioFormat(void)677 Uint16 SDL_NextAudioFormat(void)
678 {
679 	if ( (format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS) ) {
680 		return(0);
681 	}
682 	return(format_list[format_idx][format_idx_sub++]);
683 }
684 
SDL_CalculateAudioSpec(SDL_AudioSpec * spec)685 void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
686 {
687 	switch (spec->format) {
688 		case AUDIO_U8:
689 			spec->silence = 0x80;
690 			break;
691 		default:
692 			spec->silence = 0x00;
693 			break;
694 	}
695 	spec->size = (spec->format&0xFF)/8;
696 	spec->size *= spec->channels;
697 	spec->size *= spec->samples;
698 }
699 
SDL_Audio_SetCaption(const char * caption)700 void SDL_Audio_SetCaption(const char *caption)
701 {
702 	if ((current_audio) && (current_audio->SetCaption)) {
703 		current_audio->SetCaption(current_audio, caption);
704 	}
705 }
706 
707