symbian-qemu-0.9.1-12/libsdl-trunk/src/audio/SDL_audio.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 */
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   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 
       
   617 void SDL_CloseAudio (void)
       
   618 {
       
   619 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
       
   620 }
       
   621 
       
   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 
       
   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 
       
   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 
       
   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 }