src/audio/SDL_audio.c
author Ryan C. Gordon
Sun, 08 Jul 2012 07:20:50 -0400
branchSDL-1.2
changeset 6353 dfcbd0d9209c
parent 6137 4720145f848b
child 6935 b6b2829cd7ef
permissions -rw-r--r--
Added OpenBSD "sndio" audio target.

Thanks to Brad Smith and the OpenBSD team for the patch!
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2012 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_SNDIO
    46 	&SNDIO_bootstrap,
    47 #endif
    48 #if SDL_AUDIO_DRIVER_BSD
    49 	&BSD_AUDIO_bootstrap,
    50 #endif
    51 #if SDL_AUDIO_DRIVER_OSS
    52 	&DSP_bootstrap,
    53 	&DMA_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 #endif
    82 #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_MINT
    92 	&MINTAUDIO_GSXB_bootstrap,
    93 	&MINTAUDIO_MCSN_bootstrap,
    94 	&MINTAUDIO_STFA_bootstrap,
    95 	&MINTAUDIO_XBIOS_bootstrap,
    96 	&MINTAUDIO_DMA8_bootstrap,
    97 #endif
    98 #if SDL_AUDIO_DRIVER_DISK
    99 	&DISKAUD_bootstrap,
   100 #endif
   101 #if SDL_AUDIO_DRIVER_DUMMY
   102 	&DUMMYAUD_bootstrap,
   103 #endif
   104 #if SDL_AUDIO_DRIVER_DC
   105 	&DCAUD_bootstrap,
   106 #endif
   107 #if SDL_AUDIO_DRIVER_NDS
   108 	&NDSAUD_bootstrap,
   109 #endif
   110 #if SDL_AUDIO_DRIVER_MMEAUDIO
   111 	&MMEAUDIO_bootstrap,
   112 #endif
   113 #if SDL_AUDIO_DRIVER_DART
   114 	&DART_bootstrap,
   115 #endif
   116 #if SDL_AUDIO_DRIVER_EPOCAUDIO
   117 	&EPOCAudio_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 */
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   620 void SDL_CloseAudio (void)
   621 {
   622 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
   623 }
   624 
   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 
   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 
   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 
   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 
   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