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