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