src/audio/SDL_audio.c
author Sam Lantinga
Wed, 27 Feb 2013 15:20:31 -0800
branchSDL-1.2
changeset 6935 b6b2829cd7ef
parent 6353 dfcbd0d9209c
child 11967 e2982541c99c
permissions -rw-r--r--
Allow "pulseaudio" as well as "pulse" so SDL 1.2 and 2.0 support both names for the pulseaudio driver.
     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 	/* SDL 2.0 uses the name "pulseaudio", so we'll support both */
   314 	if ( driver_name && SDL_strcasecmp(driver_name, "pulseaudio") == 0 ) {
   315 		driver_name = "pulse";
   316 	}
   317 
   318 	/* Select the proper audio driver */
   319 	audio = NULL;
   320 	idx = 0;
   321 #if SDL_AUDIO_DRIVER_ESD
   322 	if ( (driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL) ) {
   323 		/* Ahem, we know that if ESPEAKER is set, user probably wants
   324 		   to use ESD, but don't start it if it's not already running.
   325 		   This probably isn't the place to do this, but... Shh! :)
   326 		 */
   327 		for ( i=0; bootstrap[i]; ++i ) {
   328 			if ( SDL_strcasecmp(bootstrap[i]->name, "esd") == 0 ) {
   329 #ifdef HAVE_PUTENV
   330 				const char *esd_no_spawn;
   331 
   332 				/* Don't start ESD if it's not running */
   333 				esd_no_spawn = getenv("ESD_NO_SPAWN");
   334 				if ( esd_no_spawn == NULL ) {
   335 					putenv("ESD_NO_SPAWN=1");
   336 				}
   337 #endif
   338 				if ( bootstrap[i]->available() ) {
   339 					audio = bootstrap[i]->create(0);
   340 					break;
   341 				}
   342 #ifdef HAVE_UNSETENV
   343 				if ( esd_no_spawn == NULL ) {
   344 					unsetenv("ESD_NO_SPAWN");
   345 				}
   346 #endif
   347 			}
   348 		}
   349 	}
   350 #endif /* SDL_AUDIO_DRIVER_ESD */
   351 	if ( audio == NULL ) {
   352 		if ( driver_name != NULL ) {
   353 #if 0	/* This will be replaced with a better driver selection API */
   354 			if ( SDL_strrchr(driver_name, ':') != NULL ) {
   355 				idx = atoi(SDL_strrchr(driver_name, ':')+1);
   356 			}
   357 #endif
   358 			for ( i=0; bootstrap[i]; ++i ) {
   359 				if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
   360 					if ( bootstrap[i]->available() ) {
   361 						audio=bootstrap[i]->create(idx);
   362 						break;
   363 					}
   364 				}
   365 			}
   366 		} else {
   367 			for ( i=0; bootstrap[i]; ++i ) {
   368 				if ( bootstrap[i]->available() ) {
   369 					audio = bootstrap[i]->create(idx);
   370 					if ( audio != NULL ) {
   371 						break;
   372 					}
   373 				}
   374 			}
   375 		}
   376 		if ( audio == NULL ) {
   377 			SDL_SetError("No available audio device");
   378 #if 0 /* Don't fail SDL_Init() if audio isn't available.
   379          SDL_OpenAudio() will handle it at that point.  *sigh*
   380        */
   381 			return(-1);
   382 #endif
   383 		}
   384 	}
   385 	current_audio = audio;
   386 	if ( current_audio ) {
   387 		current_audio->name = bootstrap[i]->name;
   388 		if ( !current_audio->LockAudio && !current_audio->UnlockAudio ) {
   389 			current_audio->LockAudio = SDL_LockAudio_Default;
   390 			current_audio->UnlockAudio = SDL_UnlockAudio_Default;
   391 		}
   392 	}
   393 	return(0);
   394 }
   395 
   396 char *SDL_AudioDriverName(char *namebuf, int maxlen)
   397 {
   398 	if ( current_audio != NULL ) {
   399 		SDL_strlcpy(namebuf, current_audio->name, maxlen);
   400 		return(namebuf);
   401 	}
   402 	return(NULL);
   403 }
   404 
   405 int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
   406 {
   407 	SDL_AudioDevice *audio;
   408 	const char *env;
   409 
   410 	/* Start up the audio driver, if necessary */
   411 	if ( ! current_audio ) {
   412 		if ( (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
   413 		     (current_audio == NULL) ) {
   414 			return(-1);
   415 		}
   416 	}
   417 	audio = current_audio;
   418 
   419 	if (audio->opened) {
   420 		SDL_SetError("Audio device is already opened");
   421 		return(-1);
   422 	}
   423 
   424 	/* Verify some parameters */
   425 	if ( desired->freq == 0 ) {
   426 		env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   427 		if ( env ) {
   428 			desired->freq = SDL_atoi(env);
   429 		}
   430 	}
   431 	if ( desired->freq == 0 ) {
   432 		/* Pick some default audio frequency */
   433 		desired->freq = 22050;
   434 	}
   435 	if ( desired->format == 0 ) {
   436 		env = SDL_getenv("SDL_AUDIO_FORMAT");
   437 		if ( env ) {
   438 			desired->format = SDL_ParseAudioFormat(env);
   439 		}
   440 	}
   441 	if ( desired->format == 0 ) {
   442 		/* Pick some default audio format */
   443 		desired->format = AUDIO_S16;
   444 	}
   445 	if ( desired->channels == 0 ) {
   446 		env = SDL_getenv("SDL_AUDIO_CHANNELS");
   447 		if ( env ) {
   448 			desired->channels = (Uint8)SDL_atoi(env);
   449 		}
   450 	}
   451 	if ( desired->channels == 0 ) {
   452 		/* Pick a default number of channels */
   453 		desired->channels = 2;
   454 	}
   455 	switch ( desired->channels ) {
   456 	    case 1:	/* Mono */
   457 	    case 2:	/* Stereo */
   458 	    case 4:	/* surround */
   459 	    case 6:	/* surround with center and lfe */
   460 		break;
   461 	    default:
   462 		SDL_SetError("1 (mono) and 2 (stereo) channels supported");
   463 		return(-1);
   464 	}
   465 	if ( desired->samples == 0 ) {
   466 		env = SDL_getenv("SDL_AUDIO_SAMPLES");
   467 		if ( env ) {
   468 			desired->samples = (Uint16)SDL_atoi(env);
   469 		}
   470 	}
   471 	if ( desired->samples == 0 ) {
   472 		/* Pick a default of ~46 ms at desired frequency */
   473 		int samples = (desired->freq / 1000) * 46;
   474 		int power2 = 1;
   475 		while ( power2 < samples ) {
   476 			power2 *= 2;
   477 		}
   478 		desired->samples = power2;
   479 	}
   480 	if ( desired->callback == NULL ) {
   481 		SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   482 		return(-1);
   483 	}
   484 
   485 #if SDL_THREADS_DISABLED
   486 	/* Uses interrupt driven audio, without thread */
   487 #else
   488 	/* Create a semaphore for locking the sound buffers */
   489 	audio->mixer_lock = SDL_CreateMutex();
   490 	if ( audio->mixer_lock == NULL ) {
   491 		SDL_SetError("Couldn't create mixer lock");
   492 		SDL_CloseAudio();
   493 		return(-1);
   494 	}
   495 #endif /* SDL_THREADS_DISABLED */
   496 
   497 	/* Calculate the silence and size of the audio specification */
   498 	SDL_CalculateAudioSpec(desired);
   499 
   500 	/* Open the audio subsystem */
   501 	SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
   502 	audio->convert.needed = 0;
   503 	audio->enabled = 1;
   504 	audio->paused  = 1;
   505 
   506 	audio->opened = audio->OpenAudio(audio, &audio->spec)+1;
   507 
   508 	if ( ! audio->opened ) {
   509 		SDL_CloseAudio();
   510 		return(-1);
   511 	}
   512 
   513 	/* If the audio driver changes the buffer size, accept it */
   514 	if ( audio->spec.samples != desired->samples ) {
   515 		desired->samples = audio->spec.samples;
   516 		SDL_CalculateAudioSpec(desired);
   517 	}
   518 
   519 	/* Allocate a fake audio memory buffer */
   520 	audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
   521 	if ( audio->fake_stream == NULL ) {
   522 		SDL_CloseAudio();
   523 		SDL_OutOfMemory();
   524 		return(-1);
   525 	}
   526 
   527 	/* See if we need to do any conversion */
   528 	if ( obtained != NULL ) {
   529 		SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
   530 	} else if ( desired->freq != audio->spec.freq ||
   531                     desired->format != audio->spec.format ||
   532 	            desired->channels != audio->spec.channels ) {
   533 		/* Build an audio conversion block */
   534 		if ( SDL_BuildAudioCVT(&audio->convert,
   535 			desired->format, desired->channels,
   536 					desired->freq,
   537 			audio->spec.format, audio->spec.channels,
   538 					audio->spec.freq) < 0 ) {
   539 			SDL_CloseAudio();
   540 			return(-1);
   541 		}
   542 		if ( audio->convert.needed ) {
   543 			audio->convert.len = (int) ( ((double) audio->spec.size) /
   544                                           audio->convert.len_ratio );
   545 			audio->convert.buf =(Uint8 *)SDL_AllocAudioMem(
   546 			   audio->convert.len*audio->convert.len_mult);
   547 			if ( audio->convert.buf == NULL ) {
   548 				SDL_CloseAudio();
   549 				SDL_OutOfMemory();
   550 				return(-1);
   551 			}
   552 		}
   553 	}
   554 
   555 	/* Start the audio thread if necessary */
   556 	switch (audio->opened) {
   557 		case  1:
   558 			/* Start the audio thread */
   559 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__)
   560 #undef SDL_CreateThread
   561 			audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
   562 #else
   563 			audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
   564 #endif
   565 			if ( audio->thread == NULL ) {
   566 				SDL_CloseAudio();
   567 				SDL_SetError("Couldn't create audio thread");
   568 				return(-1);
   569 			}
   570 			break;
   571 
   572 		default:
   573 			/* The audio is now playing */
   574 			break;
   575 	}
   576 
   577 	return(0);
   578 }
   579 
   580 SDL_audiostatus SDL_GetAudioStatus(void)
   581 {
   582 	SDL_AudioDevice *audio = current_audio;
   583 	SDL_audiostatus status;
   584 
   585 	status = SDL_AUDIO_STOPPED;
   586 	if ( audio && audio->enabled ) {
   587 		if ( audio->paused ) {
   588 			status = SDL_AUDIO_PAUSED;
   589 		} else {
   590 			status = SDL_AUDIO_PLAYING;
   591 		}
   592 	}
   593 	return(status);
   594 }
   595 
   596 void SDL_PauseAudio (int pause_on)
   597 {
   598 	SDL_AudioDevice *audio = current_audio;
   599 
   600 	if ( audio ) {
   601 		audio->paused = pause_on;
   602 	}
   603 }
   604 
   605 void SDL_LockAudio (void)
   606 {
   607 	SDL_AudioDevice *audio = current_audio;
   608 
   609 	/* Obtain a lock on the mixing buffers */
   610 	if ( audio && audio->LockAudio ) {
   611 		audio->LockAudio(audio);
   612 	}
   613 }
   614 
   615 void SDL_UnlockAudio (void)
   616 {
   617 	SDL_AudioDevice *audio = current_audio;
   618 
   619 	/* Release lock on the mixing buffers */
   620 	if ( audio && audio->UnlockAudio ) {
   621 		audio->UnlockAudio(audio);
   622 	}
   623 }
   624 
   625 void SDL_CloseAudio (void)
   626 {
   627 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
   628 }
   629 
   630 void SDL_AudioQuit(void)
   631 {
   632 	SDL_AudioDevice *audio = current_audio;
   633 
   634 	if ( audio ) {
   635 		audio->enabled = 0;
   636 		if ( audio->thread != NULL ) {
   637 			SDL_WaitThread(audio->thread, NULL);
   638 		}
   639 		if ( audio->mixer_lock != NULL ) {
   640 			SDL_DestroyMutex(audio->mixer_lock);
   641 		}
   642 		if ( audio->fake_stream != NULL ) {
   643 			SDL_FreeAudioMem(audio->fake_stream);
   644 		}
   645 		if ( audio->convert.needed ) {
   646 			SDL_FreeAudioMem(audio->convert.buf);
   647 
   648 		}
   649 		if ( audio->opened ) {
   650 			audio->CloseAudio(audio);
   651 			audio->opened = 0;
   652 		}
   653 		/* Free the driver data */
   654 		audio->free(audio);
   655 		current_audio = NULL;
   656 	}
   657 }
   658 
   659 #define NUM_FORMATS	6
   660 static int format_idx;
   661 static int format_idx_sub;
   662 static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = {
   663  { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
   664  { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
   665  { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
   666  { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
   667  { AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
   668  { AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
   669 };
   670 
   671 Uint16 SDL_FirstAudioFormat(Uint16 format)
   672 {
   673 	for ( format_idx=0; format_idx < NUM_FORMATS; ++format_idx ) {
   674 		if ( format_list[format_idx][0] == format ) {
   675 			break;
   676 		}
   677 	}
   678 	format_idx_sub = 0;
   679 	return(SDL_NextAudioFormat());
   680 }
   681 
   682 Uint16 SDL_NextAudioFormat(void)
   683 {
   684 	if ( (format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS) ) {
   685 		return(0);
   686 	}
   687 	return(format_list[format_idx][format_idx_sub++]);
   688 }
   689 
   690 void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
   691 {
   692 	switch (spec->format) {
   693 		case AUDIO_U8:
   694 			spec->silence = 0x80;
   695 			break;
   696 		default:
   697 			spec->silence = 0x00;
   698 			break;
   699 	}
   700 	spec->size = (spec->format&0xFF)/8;
   701 	spec->size *= spec->channels;
   702 	spec->size *= spec->samples;
   703 }
   704 
   705 void SDL_Audio_SetCaption(const char *caption)
   706 {
   707 	if ((current_audio) && (current_audio->SetCaption)) {
   708 		current_audio->SetCaption(current_audio, caption);
   709 	}
   710 }
   711