changeset 2:279d0427ef26

Overhaul prep for first public release.
author Eric Wing <ewing . public |-at-| gmail . com>
date Wed, 27 Oct 2010 16:52:44 -0700
parents a8a8fe374984
children a929285e1db0
files CircularQueue.c CircularQueue.h SDL_ALmixer.c SDL_ALmixer.h
diffstat 4 files changed, 3797 insertions(+), 1865 deletions(-) [+]
line wrap: on
line diff
--- a/CircularQueue.c	Wed Oct 27 16:51:16 2010 -0700
+++ b/CircularQueue.c	Wed Oct 27 16:52:44 2010 -0700
@@ -66,6 +66,8 @@
  */
 unsigned int CircularQueueUnsignedInt_PushBack(CircularQueueUnsignedInt* queue, unsigned int value)
 {
+//	printf("pushBack: %d\n", value);
+	
 	unsigned int temp_index;
 	if(NULL == queue)
 	{
@@ -73,6 +75,8 @@
 	}
 	if(queue->currentSize >= queue->maxSize)
 	{
+		printf("failed to pushBack: %d\n", value);
+		
 		return 0;
 	}
 	temp_index = queue->tailIndex + 1;
@@ -131,6 +135,8 @@
 unsigned int CircularQueueUnsignedInt_PopFront(CircularQueueUnsignedInt* queue)
 {
 	unsigned int temp_index;
+//	printf("PopFront: %d, %d\n", queue->headIndex,queue->internalQueue[queue->headIndex]  );
+	
 	if(NULL == queue)
 	{
 		return 0;
--- a/CircularQueue.h	Wed Oct 27 16:51:16 2010 -0700
+++ b/CircularQueue.h	Wed Oct 27 16:52:44 2010 -0700
@@ -1,6 +1,6 @@
 /*
     CircularQueue
-    Copyright (C) 2002  Eric Wing
+    Copyright (C) 2002  Eric Wing <ewing . public @ playcontrol.net>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
--- a/SDL_ALmixer.c	Wed Oct 27 16:51:16 2010 -0700
+++ b/SDL_ALmixer.c	Wed Oct 27 16:52:44 2010 -0700
@@ -7,8 +7,13 @@
 
 #include "SDL_ALmixer.h"
 
-#include "SDL.h" /* For SDL_GetTicks(), SDL_Delay */
-#include "SDL_sound.h"
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	#include "ALmixer_rwops.h"
+	#include "SoundDecoder.h"
+#else
+	#include "SDL_sound.h"
+#endif
+
 #include "al.h" /* OpenAL */
 #include "alc.h" /* For creating OpenAL contexts */
 
@@ -19,7 +24,15 @@
 	 * define was moved to a new header file and renamed to
 	 * ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING.
 	 */
-	#include <OpenAL/MacOSX_OALExtensions.h>
+/*
+	#include <TargetConditionals.h>
+	#if (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1)
+
+	#else
+		#include <OpenAL/MacOSX_OALExtensions.h>
+	#endif
+*/
+
 #endif
 
 /* For malloc, bsearch, qsort */
@@ -44,8 +57,24 @@
  */
 #include "CircularQueue.h"
 
+#ifdef ENABLE_ALMIXER_THREADS
 /* Needed for the Mutex locks (and threads if enabled) */
-#include "SDL_thread.h"
+	#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+		#include "SimpleMutex.h"
+		#include "SimpleThread.h"
+		typedef struct SimpleMutex SDL_mutex;
+		typedef struct SimpleThread SDL_Thread;
+		#define SDL_CreateMutex SimpleMutex_CreateMutex
+		#define SDL_DestroyMutex SimpleMutex_DestroyMutex
+		#define SDL_LockMutex SimpleMutex_LockMutex
+		#define SDL_UnlockMutex SimpleMutex_UnlockMutex
+		#define SDL_CreateThread SimpleThread_CreateThread
+		#define SDL_WaitThread SimpleThread_WaitThread
+	
+	#else
+		#include "SDL_thread.h"
+	#endif
+#endif
 
 /* Because of the API differences between the Loki
  * and Creative distributions, we need to know which
@@ -59,7 +88,7 @@
  * from the Creative distribution. So for
  * now, the Nvidia distribution gets lumped with the 
  * Creative dist and I hope nothing will break.
- * My aluGetErrorString may be the most vulnerable.
+ * My alGetString may be the most vulnerable.
  */
 #ifdef AL_BYTE_LOKI
 	#define USING_LOKI_AL_DIST
@@ -171,25 +200,139 @@
 #endif
 /************ END REMOVE  ME (Don't need anymore) ********/
 
-static SDL_bool ALmixer_Initialized = 0;
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	#include "tErrorLib.h"
+	static TErrorPool* s_ALmixerErrorPool = NULL;
+#endif
+
+static ALboolean ALmixer_Initialized = 0;
 /* This should be set correctly by Init */
-static Uint32 ALmixer_Frequency_global = ALMIXER_DEFAULT_FREQUENCY;
+static ALuint ALmixer_Frequency_global = ALMIXER_DEFAULT_FREQUENCY;
 
 /* Will be initialized in Init */
-static Sint32 Number_of_Channels_global = 0;
-static Sint32 Number_of_Reserve_Channels_global = 0;
-static Uint32 Is_Playing_global = 0;
-
+static ALint Number_of_Channels_global = 0;
+static ALint Number_of_Reserve_Channels_global = 0;
+static ALuint Is_Playing_global = 0;
+
+#ifdef ENABLE_ALMIXER_THREADS
 /* This is for a simple lock system. It is not meant to be good,
  * but just sufficient to minimize/avoid threading issues
  */
-static SDL_mutex* simple_lock;
-
-#ifdef ENABLE_ALMIXER_THREADS
+static SDL_mutex* s_simpleLock;
 static SDL_Thread* Stream_Thread_global = NULL;
 #endif
 
 
+#ifdef __APPLE__
+static ALvoid Internal_alcMacOSXMixerOutputRate(const ALdouble sample_rate)
+{
+    static void (*alcMacOSXMixerOutputRateProcPtr)(const ALdouble) = NULL;
+    
+    if(NULL == alcMacOSXMixerOutputRateProcPtr)
+	{
+		alcMacOSXMixerOutputRateProcPtr = alGetProcAddress((const ALCchar*) "alcMacOSXMixerOutputRate");
+    }
+	
+    if(NULL != alcMacOSXMixerOutputRateProcPtr)
+	{
+        alcMacOSXMixerOutputRateProcPtr(sample_rate);		
+	}
+	
+    return;
+}
+
+ALdouble Internal_alcMacOSXGetMixerOutputRate()
+{
+    static ALdouble (*alcMacOSXGetMixerOutputRateProcPtr)(void) = NULL;
+    
+    if(NULL == alcMacOSXGetMixerOutputRateProcPtr)
+	{
+		alcMacOSXGetMixerOutputRateProcPtr = alGetProcAddress((const ALCchar*) "alcMacOSXGetMixerOutputRate");
+    }
+	
+    if(NULL != alcMacOSXGetMixerOutputRateProcPtr)
+	{
+        return alcMacOSXGetMixerOutputRateProcPtr();		
+	}
+	
+    return 0.0;
+}
+#endif
+
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+
+	#if defined(__APPLE__)
+		#include <QuartzCore/QuartzCore.h>
+   	  	#include <unistd.h>
+		static CFTimeInterval s_ticksBaseTime = 0.0;
+		
+	#elif defined(_WIN32)
+		#define WIN32_LEAN_AND_MEAN
+		#include <windows.h>
+		#include <winbase.h>
+			LARGE_INTEGER s_hiResTicksPerSecond;
+			double s_hiResSecondsPerTick;
+			LARGE_INTEGER s_ticksBaseTime;
+	#else
+   	  	#include <unistd.h>
+		#include <time.h>
+		static struct timespec s_ticksBaseTime;
+	#endif
+	static void ALmixer_InitTime()
+	{
+		#if defined(__APPLE__)
+			s_ticksBaseTime = CACurrentMediaTime();
+		
+		#elif defined(_WIN32)
+			LARGE_INTEGER hi_res_ticks_per_second;
+			if(TRUE == QueryPerformanceFrequency(&hi_res_ticks_per_second))
+			{
+				QueryPerformanceCounter(&s_ticksBaseTime);
+				s_hiResSecondsPerTick = 1.0 / hi_res_ticks_per_second;
+			}
+			else
+			{
+				ALMixer_SetError("Windows error: High resolution clock failed.");
+				fprintf(stderr, "Windows error: High resolution clock failed. Audio will not work correctly.\n");
+			}
+		#else
+			/* clock_gettime is POSIX.1-2001 */
+			clock_gettime(CLOCK_MONOTONIC, &s_ticksBaseTime);
+		#endif
+
+	}
+	static ALuint ALmixer_GetTicks()
+	{
+		#if defined(__APPLE__)
+			return (ALuint)((CACurrentMediaTime()-s_ticksBaseTime)*1000.0);
+		#elif defined(_WIN32)
+			LARGE_INTEGER current_time;
+			QueryPerformanceCounter(&current_time);
+			return (ALuint)((current_time.QuadPart - s_ticksBaseTime.QuadPart) * 1000 * s_hiResSecondsPerTick);
+
+		#else /* assuming POSIX */
+			/* clock_gettime is POSIX.1-2001 */
+			struct timespec current_time;
+			clock_gettime(CLOCK_MONOTONIC, &current_time);
+			return (ALuint)((current_time.tv_sec - s_ticksBaseTime.tv_sec)*1000.0 + (current_time.tv_nec - s_ticksBaseTime.tv_nsec) / 1000000);
+		#endif
+	}
+	static void ALmixer_Delay(ALuint milliseconds_delay)
+	{
+		#if defined(_WIN32)
+		Sleep(milliseconds_delay);
+		#else
+		usleep(milliseconds_delay);
+		#endif
+	}
+#else
+	#include "SDL.h" /* For SDL_GetTicks(), SDL_Delay */
+	#define ALmixer_GetTicks SDL_GetTicks
+	#define ALmixer_Delay SDL_Delay
+#endif
+
+
+
 /* If ENABLE_PARANOID_SIGNEDNESS_CHECK is used,
  * these values will be reset on Init()
  * Consider these values Read-Only.
@@ -199,11 +342,11 @@
 #define ALMIXER_UNSIGNED_VALUE 255
 
 #ifdef ENABLE_PARANOID_SIGNEDNESS_CHECK
-static Uint16 SIGN_TYPE_16_BIT_FORMAT = AUDIO_S16SYS;
-static Uint16 SIGN_TYPE_8_BIT_FORMAT = AUDIO_S8;
+static ALushort SIGN_TYPE_16_BIT_FORMAT = AUDIO_S16SYS;
+static ALushort SIGN_TYPE_8_BIT_FORMAT = AUDIO_S8;
 #else
-static const Uint16 SIGN_TYPE_16_BIT_FORMAT = AUDIO_S16SYS;
-static const Uint16 SIGN_TYPE_8_BIT_FORMAT = AUDIO_S8;
+static const ALushort SIGN_TYPE_16_BIT_FORMAT = AUDIO_S16SYS;
+static const ALushort SIGN_TYPE_8_BIT_FORMAT = AUDIO_S8;
 #endif
 
 
@@ -215,22 +358,22 @@
 
 struct ALmixer_Data
 {
-	SDL_bool decoded_all; /* dictates different behaviors */
-	Sint32 total_time; /* total playing time of sample (msec) */
-	
-	Uint32 in_use; /* needed to prevent sharing for streams */
-	SDL_bool eof; /* flag for eof, only used for streams  */
-	
-	Uint32 total_bytes; /* For predecoded */
-	Uint32 loaded_bytes; /* For predecoded (for seek) */
+	ALboolean decoded_all; /* dictates different behaviors */
+	ALint total_time; /* total playing time of sample (msec) */
+	
+	ALuint in_use; /* needed to prevent sharing for streams */
+	ALboolean eof; /* flag for eof, only used for streams  */
+	
+	ALuint total_bytes; /* For predecoded */
+	ALuint loaded_bytes; /* For predecoded (for seek) */
 
 	Sound_Sample* sample; /* SDL_Sound provides the data */
 	ALuint* buffer; /* array of OpenAL buffers (at least 1 for predecoded) */
 
 	/* Needed for streamed buffers */
-	Uint32 max_queue_buffers; /* Max number of queue buffers */
-	Uint32 num_startup_buffers; /* Number of ramp-up buffers */
-	Uint32 num_buffers_in_use; /* number of buffers in use */
+	ALuint max_queue_buffers; /* Max number of queue buffers */
+	ALuint num_startup_buffers; /* Number of ramp-up buffers */
+	ALuint num_buffers_in_use; /* number of buffers in use */
 	
 	/* This stuff is for streamed buffers that require data access */
 	ALmixer_Buffer_Map* buffer_map_list; /* translate ALbuffer to index 
@@ -253,20 +396,20 @@
 
 static struct ALmixer_Channel
 {
-	SDL_bool channel_in_use;
-	SDL_bool callback_update; /* For streaming determination */
-	SDL_bool needs_stream; /* For streaming determination */
-	SDL_bool halted;
-	SDL_bool paused;
+	ALboolean channel_in_use;
+	ALboolean callback_update; /* For streaming determination */
+	ALboolean needs_stream; /* For streaming determination */
+	ALboolean halted;
+	ALboolean paused;
 	ALuint alsource;
 	ALmixer_Data* almixer_data;
-	Sint32 loops;
-	Sint32 expire_ticks;
-	Uint32 start_time;
-
-	SDL_bool fade_enabled;
-	Uint32 fade_expire_ticks;
-	Uint32 fade_start_time;
+	ALint loops;
+	ALint expire_ticks;
+	ALuint start_time;
+
+	ALboolean fade_enabled;
+	ALuint fade_expire_ticks;
+	ALuint fade_start_time;
 	ALfloat fade_inv_time;
 	ALfloat fade_start_volume;
 	ALfloat fade_end_volume;
@@ -274,16 +417,16 @@
 	ALfloat min_volume;
 
 	/* Do we need other flags?
-	Uint8 *samples;
+	ALbyte *samples;
 	int volume;
 	int looping;
 	int tag;
-	Uint32 expire;
-	Uint32 start_time;
+	ALuint expire;
+	ALuint start_time;
 	Mix_Fading fading;
 	int fade_volume;
-	Uint32 fade_length;
-	Uint32 ticks_fade;
+	ALuint fade_length;
+	ALuint ticks_fade;
 	effect_info *effects;
 	*/
 } *ALmixer_Channel_List = NULL;
@@ -291,16 +434,16 @@
 struct ALmixer_Buffer_Map
 {
 	ALuint albuffer;
-	Sint32 index; /* might not need */
-	Uint8* data;
-	Uint32 num_bytes;
+	ALint index; /* might not need */
+	ALbyte* data;
+	ALuint num_bytes;
 };
 
 /* This will be used to find a channel if the user supplies a source */
 typedef struct Source_Map
 {
     ALuint source;
-    Sint32 channel;
+    ALint channel;
 } Source_Map;
 /* Keep an array of all sources with their associated channel */
 static Source_Map* Source_Map_List;
@@ -325,74 +468,11 @@
 /* This is for the user defined callback via 
  * ALmixer_ChannelFinished()
  */
-static void (*Channel_Done_Callback)(Sint32 channel, void* userdata) = NULL;
+static void (*Channel_Done_Callback)(ALint which_channel, ALuint al_source, ALmixer_Data* almixer_data, ALboolean finished_naturally, void* user_data) = NULL;
 static void* Channel_Done_Callback_Userdata = NULL;
-static void (*Channel_Data_Callback)(Sint32 which_channel, Uint8* data, Uint32 num_bytes, Uint32 frequency, Uint8 channels, Uint8 bit_depth, SDL_bool is_unsigned, SDL_bool decode_mode_is_predecoded, Uint32 length_in_msec, void* user_data) = NULL;
+static void (*Channel_Data_Callback)(ALint which_channel, ALuint al_source, ALbyte* data, ALuint num_bytes, ALuint frequency, ALubyte channels, ALubyte bit_depth, ALboolean is_unsigned, ALboolean decode_mode_is_predecoded, ALuint length_in_msec, void* user_data) = NULL;
 static void* Channel_Data_Callback_Userdata = NULL;
 
-/* I thought OpenAL seemed to lack an error number to string converter...
-* but I was wrong. Apparently they call it alGetString() which
-* breaks from the OpenGL gluGetErrorString() convention.
-* (And since the documentation for OpenAL is so bad, I didn't see
-   * it until I had already written my own aluGetErrorString().)
-* So for convenience, I will just call alGetString from here.
-*/
-static const ALubyte* aluGetErrorString(ALenum error)
-{
-	return alGetString(error);
-	
-#if 0
-	switch(error)
-	{
-		case AL_NO_ERROR:
-			return NULL;
-			break;
-		case AL_INVALID_NAME:
-			return "Invalid name (ID)";
-			break;
-		case AL_INVALID_VALUE:
-			return "Invalid value";
-			break;
-		case AL_OUT_OF_MEMORY:
-			return "Out of memory";
-			break;
-			/* Damn, even the error values are skewed between distributions */
-			/* For the Creative Labs distributions (don't know about Nvidia) */
-			/* For the Loki based distributions */
-#ifdef USING_LOKI_AL_DIST
-		case AL_ILLEGAL_ENUM:
-			return "Invalid enum value";
-			break;
-		case AL_ILLEGAL_COMMAND:
-			return "Requested operation is not valid";
-			break;
-			/*
-#elif USING_CREATIVE_AL_DIST
-			 */
-#else
-		case AL_INVALID_ENUM:
-			return "Invalid enum value";
-			break;
-		case AL_INVALID_OPERATION:
-			return "Requested operation is not valid";
-			break;
-			/*
-#elif USING_NVIDIA_AL_DIST
-			 */
-			/*
-			 case alGetEnumValue((ALubyte*)"??????");
-			 */
-#endif
-		default:
-			return "Unknown error value passed to aluGetErrorString()";
-			break;
-	}
-	
-	/* Make compiler happy */
-	return NULL;
-#endif
-}
-
 
 static void PrintQueueStatus(ALuint source)
 {
@@ -410,7 +490,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "Error in PrintQueueStatus, Can't get buffers_queued: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	/* Get the number of buffers processed
 	 * so we know if we need to refill 
@@ -423,7 +503,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "Error in PrintQueueStatus, Can't get buffers_processed: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	
 	fprintf(stderr, "For source: %d, buffers_queued=%d, buffers_processed=%d\n",
@@ -435,7 +515,7 @@
 
 
 
-static void Init_Channel(Sint32 channel)
+static void Init_Channel(ALint channel)
 {
 
 fprintf(stderr, "Init channel %d\n", channel);
@@ -462,7 +542,7 @@
 }
 /* Quick helper function to clean up a channel 
  * after it's done playing */
-static void Clean_Channel(Sint32 channel)
+static void Clean_Channel(ALint channel)
 {
 	ALenum error;
 	ALmixer_Channel_List[channel].channel_in_use = 0;
@@ -489,7 +569,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "10Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	
 	alSourcef(ALmixer_Channel_List[channel].alsource, AL_MIN_GAIN, 
@@ -497,7 +577,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "11Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	
 	if(ALmixer_Channel_List[channel].almixer_data != NULL)
@@ -555,7 +635,7 @@
 /* What shoud this return?
  * 127 for signed, 255 for unsigned
  */
-static Uint8 GetSignednessValue(Uint16 format)
+static ALubyte GetSignednessValue(ALushort format)
 {
 	switch(format)
 	{
@@ -576,9 +656,9 @@
 }
 
 
-static Uint8 GetBitDepth(Uint16 format)
-{
-	Uint8 bit_depth = 16;
+static ALubyte GetBitDepth(ALushort format)
+{
+	ALubyte bit_depth = 16;
 	
 	switch(format)
 	{
@@ -613,7 +693,7 @@
  * and OpenAL conventions */
 static ALenum TranslateFormat(Sound_AudioInfo* info)
 {
-	Uint8 bit_depth;
+	ALubyte bit_depth;
 	
 	bit_depth = GetBitDepth(info->format);
 	if(0 == bit_depth)
@@ -653,11 +733,11 @@
 * based upon the number of bytes and audio info.
 * (In prinicple, it should compute the time for any given length) 
 */
-static Uint32 Compute_Total_Time_Decomposed(Uint32 bytes_per_sample, Uint32 frequency, Uint8 channels, Uint32 total_bytes)
+static ALuint Compute_Total_Time_Decomposed(ALuint bytes_per_sample, ALuint frequency, ALubyte channels, size_t total_bytes)
 {
 	double total_sec;
-	Uint32 total_msec;
-	Uint32 bytes_per_sec;
+	ALuint total_msec;
+	ALuint bytes_per_sec;
 	
 	if(0 == total_bytes)
 	{
@@ -676,31 +756,125 @@
 	/* Now convert seconds to milliseconds
 		* Add .5 to the float to do rounding before the final cast
 		*/
-	total_msec = (Uint32) ( (total_sec * 1000) + 0.5 );
+	total_msec = (ALuint) ( (total_sec * 1000) + 0.5 );
 	/*
 	 fprintf(stderr, "freq=%d, bytes_per_sample=%d, channels=%d, total_msec=%d\n", frequency, bytes_per_sample, channels, total_msec);
 	*/
 	return total_msec;
 }
 
-static Uint32 Compute_Total_Time(Sound_AudioInfo *info, Uint32 total_bytes)
-{
-	Uint32 bytes_per_sample;
+static ALuint Compute_Total_Time(Sound_AudioInfo *info, size_t total_bytes)
+{
+	ALuint bytes_per_sample;
 	
 	if(0 == total_bytes)
 	{
 		return 0;
 	}
 	/* SDL has a mask trick I was not aware of. Mask the upper bits
-		* of the format, and you get 8 or 16 which is the bits per sample.
-		* Divide by 8bits_per_bytes and you get bytes_per_sample
-		*/
-	bytes_per_sample = (Uint32) ((info->format & 0xFF) / 8);
+	 * of the format, and you get 8 or 16 which is the bits per sample.
+ 	 * Divide by 8bits_per_bytes and you get bytes_per_sample
+	 * I tested this under 32-bit and 64-bit and big and little endian
+	 * to make sure this still works since I have since moved from 
+	 * Uint32 to unspecified size types like ALuint.
+	 */
+	bytes_per_sample = (ALuint) ((info->format & 0xFF) / 8);
 	
 	return Compute_Total_Time_Decomposed(bytes_per_sample, info->rate, info->channels, total_bytes);
 } /* End Compute_Total_Time */
 	
 
+static size_t Compute_Total_Bytes_Decomposed(ALuint bytes_per_sample, ALuint frequency, ALubyte channels, ALuint total_msec)
+{
+	double total_sec;
+	ALuint bytes_per_sec;
+	size_t total_bytes;
+
+	if(0 >= total_msec)
+	{
+		return 0;
+	}
+	/* To compute Bytes per second, do
+		* samples_per_sec * bytes_per_sample * number_of_channels
+		*/
+	bytes_per_sec = frequency * bytes_per_sample * channels;
+	
+	/* convert milliseconds to seconds */
+	total_sec = total_msec / 1000.0;
+
+	/* Now to get total bytes */
+	total_bytes = (size_t)(((double)bytes_per_sec * total_sec) + 0.5);
+	
+/*	 fprintf(stderr, "freq=%d, bytes_per_sample=%d, channels=%d, total_msec=%d, total_bytes=%d\n", frequency, bytes_per_sample, channels, total_msec, total_bytes);
+*/
+
+	return total_bytes;
+}
+
+static size_t Compute_Total_Bytes(Sound_AudioInfo *info, ALuint total_msec)
+{
+	ALuint bytes_per_sample;
+	
+	if(0 >= total_msec)
+	{
+		return 0;
+	}
+	/* SDL has a mask trick I was not aware of. Mask the upper bits
+	 * of the format, and you get 8 or 16 which is the bits per sample.
+ 	 * Divide by 8bits_per_bytes and you get bytes_per_sample
+	 * I tested this under 32-bit and 64-bit and big and little endian
+	 * to make sure this still works since I have since moved from 
+	 * Uint32 to unspecified size types like ALuint.
+	 */
+	bytes_per_sample = (ALuint) ((info->format & 0xFF) / 8);
+	
+	return Compute_Total_Bytes_Decomposed(bytes_per_sample, info->rate, info->channels, total_msec);
+}
+
+/* The back-end decoders seem to need to decode in quantized frame sizes.
+ * So if I can pad the bytes to the next quanta, things might go more smoothly.
+ */
+static size_t Compute_Total_Bytes_With_Frame_Padding(Sound_AudioInfo *info, ALuint total_msec)
+{
+	ALuint bytes_per_sample;
+	ALuint bytes_per_frame;
+	size_t evenly_divisible_frames;
+	size_t remainder_frames;
+	size_t return_bytes;
+
+	size_t total_bytes = Compute_Total_Bytes(info, total_msec);
+
+	bytes_per_sample = (ALuint) ((info->format & 0xFF) / 8);
+	
+	bytes_per_frame = bytes_per_sample * info->channels;
+
+	evenly_divisible_frames = total_bytes / bytes_per_frame;
+	remainder_frames = total_bytes % bytes_per_frame;
+
+	return_bytes = (evenly_divisible_frames * bytes_per_frame)  + (remainder_frames * bytes_per_frame);
+
+	/* Experimentally, some times I see to come up short in 
+	 * actual bytes decoded and I see a second pass is needed.
+	 * I'm worried this may have additional performance implications.
+	 * Sometimes in the second pass (depending on file), 
+	 * I have seen between 0 and 18 bytes.
+	 * I'm tempted to pad the bytes by some arbitrary amount.
+	 * However, I think currently the way SDL_sound is implemented,
+	 * there is a big waste of memory up front instead of per-pass,
+	 * so maybe I shouldn't worry about this.
+	 */
+	/*
+	return_bytes += 64;
+	*/
+	/*
+	 fprintf(stderr, "remainder_frames=%d, padded_total_bytes=%d\n", remainder_frames, return_bytes);
+	 */
+	 return return_bytes;
+
+}
+
+
+
 
 /**************** REMOVED ****************************/
 /* This was removed because I originally thought
@@ -718,8 +892,8 @@
 
 static void Set_AudioInfo(Sound_AudioInfo* info, ALint frequency, ALint bits, ALint channels)
 {
-	info->rate = (Uint32)frequency;
-	info->channels = (Uint8)channels;
+	info->rate = (ALuint)frequency;
+	info->channels = (ALubyte)channels;
 	
 	/* Not sure if it should be signed or unsigned. Hopefully
 	 * that detail won't be needed.
@@ -738,7 +912,7 @@
 }
 
 
-static Sint32 Reconstruct_Sound_Sample(ALmixer_Data* data)
+static ALint Reconstruct_Sound_Sample(ALmixer_Data* data)
 {
 	ALenum error;	
 	ALint* data_from_albuffer;
@@ -761,7 +935,7 @@
 	alGetBufferi(data->buffer[0], AL_FREQUENCY, &freq);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alGetBufferi(AL_FREQUENCT): %s", aluGetErrorString(error) );
+		ALmixer_SetError("alGetBufferi(AL_FREQUENCY): %s", alGetString(error) );
 		free(data->sample);
 		data->sample = NULL;
 		return -1;
@@ -770,7 +944,7 @@
 	alGetBufferi(data->buffer[0], AL_BITS, &bits);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alGetBufferi(AL_BITS): %s", aluGetErrorString(error) );
+		ALmixer_SetError("alGetBufferi(AL_BITS): %s", alGetString(error) );
 		free(data->sample);
 		data->sample = NULL;
 		return -1;
@@ -779,7 +953,7 @@
 	alGetBufferi(data->buffer[0], AL_CHANNELS, &channels);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alGetBufferi(AL_CHANNELS): %s", aluGetErrorString(error) );
+		ALmixer_SetError("alGetBufferi(AL_CHANNELS): %s", alGetString(error) );
 		free(data->sample);
 		data->sample = NULL;
 		return -1;
@@ -788,7 +962,7 @@
 	alGetBufferi(data->buffer[0], AL_SIZE, &size);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alGetBufferi(AL_SIZE): %s", aluGetErrorString(error) );
+		ALmixer_SetError("alGetBufferi(AL_SIZE): %s", alGetString(error) );
 		free(data->sample);
 		data->sample = NULL;
 		return -1;
@@ -797,7 +971,7 @@
 	alGetBufferi(data->buffer[0], AL_DATA, data_from_albuffer);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alGetBufferi(AL_DATA): %s", aluGetErrorString(error) );
+		ALmixer_SetError("alGetBufferi(AL_DATA): %s", alGetString(error) );
 		free(data->sample);
 		data->sample = NULL;
 		return -1;
@@ -815,7 +989,7 @@
 	 * allocate memory for the buffer and reconstruct
 	 * the AudioInfo attributes.
 	 */
-	data->sample->buffer = malloc(size*sizeof(Uint8));
+	data->sample->buffer = malloc(size*sizeof(ALbyte));
 	if(NULL == data->sample->buffer)
 	{
 		ALmixer_SetError("Out of memory for sample->buffer");
@@ -838,16 +1012,16 @@
 #endif
 /*************** END REMOVED *************************/	
 
-static void Invoke_Channel_Done_Callback(Sint32 channel)
+static void Invoke_Channel_Done_Callback(ALint which_channel, ALboolean did_finish_naturally)
 {
 	if(NULL == Channel_Done_Callback)
 	{
 		return;
 	}
-	Channel_Done_Callback(channel, Channel_Done_Callback_Userdata);
-}
-
-static Sint32 LookUpBuffer(ALuint buffer, ALmixer_Buffer_Map* buffer_map_list, Uint32 num_items_in_list)
+	Channel_Done_Callback(which_channel, ALmixer_Channel_List[which_channel].alsource, ALmixer_Channel_List[which_channel].almixer_data, did_finish_naturally, Channel_Done_Callback_Userdata);
+}
+
+static ALint LookUpBuffer(ALuint buffer, ALmixer_Buffer_Map* buffer_map_list, ALuint num_items_in_list)
 {
 	/* Only the first value is used for the key */
 	ALmixer_Buffer_Map key = { 0, 0, NULL, 0 };
@@ -873,12 +1047,12 @@
  * channels: 1 for mono, 2 for stereo
  *
  */
-static void Invoke_Channel_Data_Callback(Sint32 which_channel, Uint8* data, Uint32 num_bytes, Uint32 frequency, Uint8 channels, Uint16 format, SDL_bool decode_mode_is_predecoded)
-{
-	SDL_bool is_unsigned;
-	Uint8 bits_per_sample = GetBitDepth(format);
-	Uint32 bytes_per_sample;
-	Uint32 length_in_msec;
+static void Invoke_Channel_Data_Callback(ALint which_channel, ALbyte* data, ALuint num_bytes, ALuint frequency, ALubyte channels, ALushort format, ALboolean decode_mode_is_predecoded)
+{
+	ALboolean is_unsigned;
+	ALubyte bits_per_sample = GetBitDepth(format);
+	ALuint bytes_per_sample;
+	ALuint length_in_msec;
 
 	if(GetSignednessValue(format) == ALMIXER_UNSIGNED_VALUE)
 	{
@@ -889,7 +1063,7 @@
 		is_unsigned = 0;
 	}
 
-	bytes_per_sample = (Uint32) (bits_per_sample / 8);
+	bytes_per_sample = (ALuint) (bits_per_sample / 8);
 
 	length_in_msec = Compute_Total_Time_Decomposed(bytes_per_sample, frequency, channels, num_bytes);
 
@@ -903,10 +1077,10 @@
 	/*
 	 * Channel_Data_Callback(which_channel, data, num_bytes, frequency, channels, GetBitDepth(format), format, decode_mode_is_predecoded);
 	*/
-	Channel_Data_Callback(which_channel, data, num_bytes, frequency, channels, bits_per_sample, is_unsigned, decode_mode_is_predecoded, length_in_msec, Channel_Data_Callback_Userdata);
-}
-
-static void Invoke_Predecoded_Channel_Data_Callback(Sint32 channel, ALmixer_Data* data)
+	Channel_Data_Callback(which_channel, ALmixer_Channel_List[which_channel].alsource, data, num_bytes, frequency, channels, bits_per_sample, is_unsigned, decode_mode_is_predecoded, length_in_msec, Channel_Data_Callback_Userdata);
+}
+
+static void Invoke_Predecoded_Channel_Data_Callback(ALint channel, ALmixer_Data* data)
 {
 	if(NULL == data->sample)
 	{
@@ -916,18 +1090,18 @@
 	 * we must adjust the buffer to the seek position
 	 */
 	Invoke_Channel_Data_Callback(channel, 
-		(((Uint8*) data->sample->buffer) + (data->total_bytes - data->loaded_bytes) ),
+		(((ALbyte*) data->sample->buffer) + (data->total_bytes - data->loaded_bytes) ),
 		data->loaded_bytes,
 		data->sample->desired.rate,
 		data->sample->desired.channels,
 		data->sample->desired.format,
-		SDL_TRUE
+		AL_TRUE
 	);
 }
 
-static void Invoke_Streamed_Channel_Data_Callback(Sint32 channel, ALmixer_Data* data, ALuint buffer)
-{
-	Sint32 index;
+static void Invoke_Streamed_Channel_Data_Callback(ALint channel, ALmixer_Data* data, ALuint buffer)
+{
+	ALint index;
 	if(NULL == data->buffer_map_list)
 	{
 		return;
@@ -946,18 +1120,18 @@
 		data->sample->desired.rate,
 		data->sample->desired.channels,
 		data->sample->desired.format,
-		SDL_FALSE
+		AL_FALSE
 	);
 }
 
 /* From SDL_Sound's playsound. Converts milliseconds to byte positions.
  * This is needed for seeking on predecoded samples 
  */
-static Uint32 Convert_Msec_To_Byte_Pos(Sound_AudioInfo *info, Uint32 ms)
+static ALuint Convert_Msec_To_Byte_Pos(Sound_AudioInfo *info, ALuint ms)
 {
 	float frames_per_ms;
-	Uint32 frame_offset;
-	Uint32 frame_size;
+	ALuint frame_offset;
+	ALuint frame_size;
 	fprintf(stderr, "In convert\n" );
 	if(info == NULL)
 	{
@@ -972,14 +1146,14 @@
 	/* "frames" == "sample frames" */
 	frames_per_ms = ((float) info->rate) / 1000.0f;
 	fprintf(stderr, "%f\n", frames_per_ms);
-	frame_offset = (Uint32) (frames_per_ms * ((float) ms));
+	frame_offset = (ALuint) (frames_per_ms * ((float) ms));
 	fprintf(stderr, "%d\n", frame_offset);
-	frame_size = (Uint32) ((info->format & 0xFF) / 8) * info->channels;
+	frame_size = (ALuint) ((info->format & 0xFF) / 8) * info->channels;
 	fprintf(stderr, "%d\n", frame_size);
 	return(frame_offset * frame_size);
 } /* cvtMsToBytePos */
 
-static Sint32 Set_Predecoded_Seek_Position(ALmixer_Data* data, Uint32 byte_position)
+static ALint Set_Predecoded_Seek_Position(ALmixer_Data* data, ALuint byte_position)
 {
 	ALenum error;
 	/* clear error */
@@ -996,7 +1170,7 @@
 	 *
 		alBufferData(data->buffer[0],
 			TranslateFormat(&data->sample->desired), 
-			 (Uint8*) data->sample->buffer,
+			 (ALbyte*) data->sample->buffer,
 			 data->total_bytes,
 			data->sample->desired.rate
 		);
@@ -1010,13 +1184,13 @@
 		 */
 		alBufferData(data->buffer[0],
 			TranslateFormat(&data->sample->desired), 
-			 (((Uint8*) data->sample->buffer) + (data->total_bytes - 8) ),
+			 (((ALbyte*) data->sample->buffer) + (data->total_bytes - 8) ),
 			 8,
 			data->sample->desired.rate
 		);
 		if( (error = alGetError()) != AL_NO_ERROR)
 		{
-			ALmixer_SetError("Can't seek past end and alBufferData failed: %s\n", aluGetErrorString(error));
+			ALmixer_SetError("Can't seek past end and alBufferData failed: %s\n", alGetString(error));
 			return -1;
 		}
 		/* Need to set the loaded_bytes field because I don't trust the OpenAL
@@ -1035,13 +1209,13 @@
 	
 	alBufferData(data->buffer[0],
 		TranslateFormat(&data->sample->desired), 
-		&(((Uint8*)data->sample->buffer)[byte_position]),
+		&(((ALbyte*)data->sample->buffer)[byte_position]),
 		data->total_bytes - byte_position,
 		data->sample->desired.rate
 	);
 	if( (error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alBufferData failed: %s\n", aluGetErrorString(error));
+		ALmixer_SetError("alBufferData failed: %s\n", alGetString(error));
 		return -1;
 	}
 	/* Need to set the loaded_bytes field because I don't trust the OpenAL
@@ -1056,9 +1230,9 @@
 /* Because we have multiple queue buffers and OpenAL won't let
  * us access them, we need to keep copies of each buffer around
  */
-static Sint32 CopyDataToAccessBuffer(ALmixer_Data* data, Uint32 num_bytes, ALuint buffer)
-{
-	Sint32 index;
+static ALint CopyDataToAccessBuffer(ALmixer_Data* data, ALuint num_bytes, ALuint buffer)
+{
+	ALint index;
 	/* We only want to copy if access_data is true.
 	 * This is determined by whether memory has been
 	 * allocated in the buffer_map_list or not
@@ -1084,9 +1258,9 @@
 /* For streamed data, gets more data
  * and prepares it in the active Mix_chunk
  */
-static Uint32 GetMoreData(ALmixer_Data* data, ALuint buffer)
-{
-	Uint32 bytes_decoded;
+static ALuint GetMoreData(ALmixer_Data* data, ALuint buffer)
+{
+	ALuint bytes_decoded;
 	ALenum error;
 	if(NULL == data)
 	{
@@ -1105,14 +1279,16 @@
 		return 0;
 	}
 	
-	
+/*	fprintf(stderr, "GetMoreData bytes_decoded=%d\n", bytes_decoded); */
+
 	/* Don't forget to add check for EOF */
 	/* Will return 0 bytes and pass the buck to check sample->flags */
 	if(0 == bytes_decoded)
 	{
-#if 1 
+		data->eof = 1;
+
+#if 0 
 fprintf(stderr, "Hit eof while trying to buffer\n");
-		data->eof = 1;
 		if(data->sample->flags & SOUND_SAMPLEFLAG_EOF)
 		{
 			fprintf(stderr, "\tEOF flag\n");
@@ -1169,8 +1345,8 @@
 	 */
 	if( (bytes_decoded) < data->sample->buffer_size)
 	{
-		Uint8 bit_depth;
-		Uint8 signedness_value;
+		ALubyte bit_depth;
+		ALubyte signedness_value;
 		int silence_value;
 		/* Crap, memset value needs to be the "silent" value, 
 		 * but it will differ for signed/unsigned and bit depth
@@ -1202,7 +1378,7 @@
 		 * this part since the data is for internal use only
 		 * at this point.
 		 */
-		memset( &( ((Uint8*)(data->sample->buffer))[bytes_decoded] ), silence_value, data->sample->buffer_size - bytes_decoded);
+		memset( &( ((ALbyte*)(data->sample->buffer))[bytes_decoded] ), silence_value, data->sample->buffer_size - bytes_decoded);
 		/* Now reset the bytes_decoded to reflect the entire 
 		 * buffer to tell alBufferData what our full size is.
 		 */
@@ -1224,7 +1400,7 @@
 	);
 	if( (error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alBufferData failed: %s\n", aluGetErrorString(error));
+		ALmixer_SetError("alBufferData failed: %s\n", alGetString(error));
 		return 0;
 	}
 
@@ -1243,9 +1419,9 @@
  * REMOVE LATER
  *********************************************/
 #if 0
-static Sint32 GetMoreData2(ALmixer_Data* data, ALuint buffer)
-{
-	Sint32 bytes_decoded;
+static ALint GetMoreData2(ALmixer_Data* data, ALuint buffer)
+{
+	ALint bytes_decoded;
 	ALenum error;
 	if(NULL == data)
 	{
@@ -1323,7 +1499,7 @@
 		retval = Sound_SetBufferSize(data->sample, 16384-bytes_decoded);
 		if(retval == 1)
 		{
-			Uint32 new_bytes;
+			ALuint new_bytes;
 			Sound_Rewind(data->sample);
 			new_bytes = Sound_Decode(data->sample);
 			fprintf(stderr, "Orig bytes: %d, Make up bytes_decoded=%d, total=%d\n", bytes_decoded, new_bytes, new_bytes+bytes_decoded);
@@ -1361,7 +1537,7 @@
 	);
 	if( (error = alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("alBufferData failed: %s\n", aluGetErrorString(error));
+		ALmixer_SetError("alBufferData failed: %s\n", alGetString(error));
 		return -1;
 	}
 	
@@ -1382,9 +1558,9 @@
 
 /* This function will look up the source for the corresponding channel */
 /* Must return 0 on error instead of -1 because of unsigned int */
-static ALuint Internal_GetSource(Sint32 channel)
-{
-	Sint32 i;
+static ALuint Internal_GetSource(ALint channel)
+{
+	ALint i;
 	/* Make sure channel is in bounds */
 	if(channel >= Number_of_Channels_global)
 	{
@@ -1412,9 +1588,9 @@
 }
 
 /* This function will look up the channel for the corresponding source */
-static Sint32 Internal_GetChannel(ALuint source)
-{
-	Sint32 i;
+static ALint Internal_GetChannel(ALuint source)
+{
+	ALint i;
 	/* Only the first value is used for the key */
 	Source_Map key = { 0, 0 };
 	Source_Map* found_item = NULL;
@@ -1461,12 +1637,12 @@
  * from the specified start channel. Reserved channels to not qualify
  * as available.
  */
-static Sint32 Internal_FindFreeChannel(Sint32 start_channel)
+static ALint Internal_FindFreeChannel(ALint start_channel)
 {
 	/* Start at the number of reserved so we skip over
 	 * all the reserved channels.
 	 */
-	Sint32 i = Number_of_Reserve_Channels_global;
+	ALint i = Number_of_Reserve_Channels_global;
 	/* Quick check to see if we're out of bounds */
 	if(start_channel >= Number_of_Channels_global)
 	{
@@ -1495,6 +1671,231 @@
 
 
 
+/* Will return the number of channels halted
+ * or 0 for error
+ */
+static ALint Internal_HaltChannel(ALint channel, ALboolean did_finish_naturally)
+{
+	ALint retval = 0;
+	ALint counter = 0;
+	ALenum error;
+	ALint buffers_still_queued;
+	ALint buffers_processed;
+
+	if(channel >= Number_of_Channels_global)
+	{
+		ALmixer_SetError("Cannot halt channel %d because it exceeds maximum number of channels (%d)\n", channel, Number_of_Channels_global);
+		return -1;
+	}
+	/* If the user specified a specific channel */
+	if(channel >= 0)
+	{
+		fprintf(stderr, "Halt on channel %d\n", channel);
+		/* only need to process channel if in use */
+		if(ALmixer_Channel_List[channel].channel_in_use)
+		{
+			alSourceStop(ALmixer_Channel_List[channel].alsource);
+			if((error = alGetError()) != AL_NO_ERROR)
+			{
+				fprintf(stderr, "14Testing error: %s\n",
+					alGetString(error));				
+			}
+			/* Here's the situation. My old method of using
+			 * alSourceUnqueueBuffers() seemed to be invalid in light
+			 * of all the problems I suffered through with getting 
+			 * the CoreData backend to work with this code.
+			 * As such, I'm changing all the code to set the buffer to
+			 * AL_NONE. Furthermore, the queued vs. non-queued issue
+			 * doesn't need to apply here. For non-queued, Loki,
+			 * Creative Windows, and CoreAudio seem to leave the 
+			 * buffer queued (Old Mac didn't.) For queued, we need to 
+			 * remove the processed buffers and force remove the
+			 * still-queued buffers.
+			 */
+			fprintf(stderr, "Halt on channel %d, channel in use\n", channel);
+			alGetSourcei(
+				ALmixer_Channel_List[channel].alsource,
+				AL_BUFFERS_QUEUED, &buffers_still_queued
+			);
+			if((error = alGetError()) != AL_NO_ERROR)
+			{
+				fprintf(stderr, "17Testing Error with buffers_still_queued: %s",
+					alGetString(error));
+				ALmixer_SetError("Failed detecting still queued buffers: %s",
+					alGetString(error) );
+				retval = -1;
+			}
+			alGetSourcei(
+				ALmixer_Channel_List[channel].alsource,
+				AL_BUFFERS_PROCESSED, &buffers_processed
+			);
+			if((error = alGetError()) != AL_NO_ERROR)
+			{
+				fprintf(stderr, "17Testing Error with buffers_processed: %s",
+					alGetString(error));
+				ALmixer_SetError("Failed detecting still processed buffers: %s",
+					alGetString(error) );
+				retval = -1;
+			}
+			/* If either of these is greater than 0, it means we need
+			 * to clear the source
+			 */
+			if((buffers_still_queued > 0) || (buffers_processed > 0))
+			{
+				alSourcei(ALmixer_Channel_List[channel].alsource,
+					AL_BUFFER,
+					AL_NONE);
+				if((error = alGetError()) != AL_NO_ERROR)
+				{
+					fprintf(stderr, "17Testing Error with clearing buffer from source: %s",
+						alGetString(error));
+					ALmixer_SetError("Failed to clear buffer from source: %s",
+						alGetString(error) );
+					retval = -1;
+				}
+			}
+
+			ALmixer_Channel_List[channel].almixer_data->num_buffers_in_use  = 0;
+
+			Clean_Channel(channel);
+			Is_Playing_global--;
+			/* Launch callback for consistency? */
+			Invoke_Channel_Done_Callback(channel, did_finish_naturally);
+			counter++;
+		}
+	}
+	/* The user wants to halt all channels */
+	else
+	{
+		ALint i;
+		for(i=0; i<Number_of_Channels_global; i++)
+		{
+			fprintf(stderr, "Halting channel %d\n", i);
+			fprintf(stderr, "in use %d\n", ALmixer_Channel_List[i].channel_in_use );
+			/* only need to process channel if in use */
+			if(ALmixer_Channel_List[i].channel_in_use)
+			{
+				fprintf(stderr, "SourceStop %d\n", i);
+				alSourceStop(ALmixer_Channel_List[i].alsource);
+				if((error = alGetError()) != AL_NO_ERROR)
+				{
+					fprintf(stderr, "19Testing error: %s\n",
+						alGetString(error));				
+				}
+
+				/* Here's the situation. My old method of using
+				 * alSourceUnqueueBuffers() seemed to be invalid in light
+				 * of all the problems I suffered through with getting 
+				 * the CoreData backend to work with this code.
+				 * As such, I'm changing all the code to set the buffer to
+				 * AL_NONE. Furthermore, the queued vs. non-queued issue
+				 * doesn't need to apply here. For non-queued, Loki,
+				 * Creative Windows, and CoreAudio seem to leave the 
+				 * buffer queued (Old Mac didn't.) For queued, we need to 
+				 * remove the processed buffers and force remove the
+				 * still-queued buffers.
+				 */
+				fprintf(stderr, "Halt on channel %d, channel in use\n", channel);
+				alGetSourcei(
+					ALmixer_Channel_List[i].alsource,
+					AL_BUFFERS_QUEUED, &buffers_still_queued
+				);
+				if((error = alGetError()) != AL_NO_ERROR)
+				{
+					fprintf(stderr, "17Testing Error with buffers_still_queued: %s",
+						alGetString(error));
+					ALmixer_SetError("Failed detecting still queued buffers: %s",
+						alGetString(error) );
+					retval = -1;
+				}
+				alGetSourcei(
+					ALmixer_Channel_List[i].alsource,
+					AL_BUFFERS_PROCESSED, &buffers_processed
+				);
+				if((error = alGetError()) != AL_NO_ERROR)
+				{
+					fprintf(stderr, "17Testing Error with buffers_processed: %s",
+						alGetString(error));
+					ALmixer_SetError("Failed detecting still processed buffers: %s",
+						alGetString(error) );
+					retval = -1;
+				}
+				/* If either of these is greater than 0, it means we need
+				 * to clear the source
+				 */
+				if((buffers_still_queued > 0) || (buffers_processed > 0))
+				{
+					alSourcei(ALmixer_Channel_List[i].alsource,
+						AL_BUFFER,
+						AL_NONE);
+					if((error = alGetError()) != AL_NO_ERROR)
+					{
+						fprintf(stderr, "17Testing Error with clearing buffer from source: %s",
+							alGetString(error));
+						ALmixer_SetError("Failed to clear buffer from source: %s",
+							alGetString(error) );
+						retval = -1;
+					}
+				}
+				
+				ALmixer_Channel_List[i].almixer_data->num_buffers_in_use  = 0;
+
+	fprintf(stderr, "Clean channel %d\n", i);
+				Clean_Channel(i);
+				Is_Playing_global--;
+				/* Launch callback for consistency? */
+	fprintf(stderr, "Callback%d\n", i);
+				Invoke_Channel_Done_Callback(i, did_finish_naturally);
+
+				/* Increment the counter */
+				counter++;
+			}
+			/* Let's halt everything just in case there 
+			 * are bugs.
+			 */
+			/*
+			else
+			{
+				alSourceStop(ALmixer_Channel_List[channel].alsource);
+				/ * Can't clean because the in_use counter for
+				 * data will get messed up * /
+				Clean_Channel(channel);
+			}
+			*/
+			/* Just in case */
+			Is_Playing_global = 0;
+		}
+	}
+	if(-1 == retval)
+	{		
+		return -1;	
+	}
+	return counter;
+}
+
+
+/* Will return the source halted or the total number of channels
+ * if all were halted or 0 for error
+ */
+static ALint Internal_HaltSource(ALuint source, ALboolean did_finish_naturally)
+{
+	ALint channel;
+	if(0 == source)
+	{
+		/* Will return the number of sources halted */
+		return Internal_HaltChannel(-1, did_finish_naturally);
+	}
+	
+	channel = Internal_GetChannel(source);
+	if(-1 == channel)
+	{
+		ALmixer_SetError("Cannot halt source: %s", ALmixer_GetError());
+		return -1;
+	}
+	return Internal_HaltChannel(channel, did_finish_naturally);
+}
+
+
 
 /* Note: Behaves, almost like SDL_mixer, but keep in mind
  * that there is no "music" channel anymore, so 0
@@ -1505,7 +1906,7 @@
  * GenSources, but reversing the damage is too painful
  * for me to think about at the moment, so it's not in here.
  */
-static Sint32 Internal_AllocateChannels(Sint32 numchans)
+static ALint Internal_AllocateChannels(ALint numchans)
 {
 	ALenum error;
 	int i;
@@ -1541,7 +1942,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "12Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 			/* Copy the source so the SourceMap has it too */
 			Source_Map_List[i].source = ALmixer_Channel_List[i].alsource;
@@ -1565,14 +1966,14 @@
 		for(i=numchans; i<Number_of_Channels_global; i++)
 		{
 			/* Halt the channel */
-			ALmixer_HaltChannel(i);
+			Internal_HaltChannel(i, AL_FALSE);
 
 			/* Delete source associated with the channel */
 			alDeleteSources(1, &ALmixer_Channel_List[i].alsource);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "13Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 		}
 
@@ -1603,7 +2004,7 @@
 	
 }
 	
-static Sint32 Internal_ReserveChannels(Sint32 num)
+static ALint Internal_ReserveChannels(ALint num)
 {
 	/* Can't reserve more than the max num of channels */
 	/* Actually, I'll allow it for people who just want to
@@ -1621,662 +2022,16 @@
 }
 	
 
-
-
-
-static Sint32 Internal_PlayChannelTimed(Sint32 channel, ALmixer_Data* data, Sint32 loops, Sint32 ticks)
-{
-	ALenum error;
-	int ret_flag = 0;
-	if(NULL == data)
-	{
-		ALmixer_SetError("Can't play because data is NULL\n");
-		return -1;
-	}
-
-	/* There isn't a good way to share streamed files because
-	 * the decoded data doesn't stick around. 
-	 * You must "Load" a brand new instance of
-	 * the data. If you try using the same data,
-	 * bad things may happen. This check will attempt
-	 * to prevent sharing
-	 */
-	if(0 == data->decoded_all)
-	{
-		if(data->in_use)
-		{
-			ALmixer_SetError("Can't play shared streamed sample because it is already in use");
-			return -1;
-		}
-
-		/* Make sure SDL_sound sample is not at EOF.
-		 * This mainly affects streamed files,
-	 	 * so the check is placed here
-		 */
-		if(data->eof)
-		{
-			if( -1 == ALmixer_RewindData(data) )
-			{
-				ALmixer_SetError("Can't play sample because it is at EOF and cannot rewind");
-				return -1;
-			}
-		}
-	}
-	/* We need to provide the user with the first available channel */
-	if(-1 == channel)
-	{
-		Sint32 i;
-		for(i=Number_of_Reserve_Channels_global; i<Number_of_Channels_global; i++)
-		{
-			if(0 == ALmixer_Channel_List[i].channel_in_use)
-			{
-				channel = i;
-				break;
-			}
-		}
-		/* if we couldn't find a channel, return an error */
-		if(i == Number_of_Channels_global)
-		{
-			ALmixer_SetError("No channels available for playing");
-			return -1;
-		}
-	}
-	/* If we didn't assign the channel number, make sure it's not
-	 * out of bounds or in use */
-	else
-	{
-		if(channel >= Number_of_Channels_global)
-		{
-			ALmixer_SetError("Requested channel (%d) exceeds maximum channel (%d) because only %d channels are allocated", channel, Number_of_Channels_global-1, Number_of_Channels_global);
-			return -1;
-		}
-		else if(ALmixer_Channel_List[channel].channel_in_use)
-		{
-			ALmixer_SetError("Requested channel (%d) is in use", channel, Number_of_Channels_global-1, Number_of_Channels_global);
-			return -1;
-		}	
-	}
-	/* Make sure the user doesn't enter some meaningless value */
-	if(loops < -1)
-	{
-		loops = -1;
-	}
-							
-	/* loops will probably have to change to be controlled by SDL_Sound */
-
-	/* Set up the initial values for playing */
-	ALmixer_Channel_List[channel].channel_in_use = 1;
-	data->in_use++;
-		
-	/* Shouldn't need updating until a callback is fired
-	 * (assuming that we call Play in this function 
-	 */
-	ALmixer_Channel_List[channel].needs_stream = 0;
-	ALmixer_Channel_List[channel].almixer_data = data;
-	ALmixer_Channel_List[channel].start_time = SDL_GetTicks();
-
-	/* If user entered -1 (or less), set to -1 */
-	if(ticks < 0)
-	{
-		ALmixer_Channel_List[channel].expire_ticks = -1;
-	}
-	else
-	{
-		ALmixer_Channel_List[channel].expire_ticks = ticks;
-	}
-
-	
-	ALmixer_Channel_List[channel].halted = 0;
-	ALmixer_Channel_List[channel].paused = 0;
-
-	/* Ran just use OpenAL to control loops if predecoded and infinite */
-	ALmixer_Channel_List[channel].loops = loops; 
-	if( (-1 == loops) && (data->decoded_all) )
-	{
-		alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_TRUE);
-	}
-	else
-	{
-		alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_FALSE);
-	}
-	if((error = alGetError()) != AL_NO_ERROR)
-	{
-		fprintf(stderr, "13Testing error: %s\n",
-			aluGetErrorString(error));				
-	}
-
-#if 0
-	/* Because of the corner case, predecoded
-	 * files must add +1 to the loops.
-	 * Streams do not have this problem
-	 * because they can use the eof flag to 
-	 * avoid the conflict.
-	 * Sharing data chunks prevents the use of the eof flag.
-	 * Since streams, cannot share, only predecoded
-	 * files are affected 
-	 */
-	if(data->decoded_all)
-	{
-		/* Corner Case: Now that play calls are pushed
-		 * off to update(), the start call must
-		 * also come through here. So, start loops
-		 * must be +1 
-		 */
-		if(-1 == loops)
-		{
-			/* -1 is a special case, and you don't want
-			 * to add +1 to it */
-			ALmixer_Channel_List[channel].loops = -1;
-			alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_TRUE);
-		}
-		else
-		{
-			ALmixer_Channel_List[channel].loops = loops+1;
-			alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_FALSE);
-		}
-	}
-	else
-	{
-		ALmixer_Channel_List[channel].loops = loops;
-		/* Can we really loop on streamed data? */
-		alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_TRUE);
-	}
-#endif
-
-	/* Should I start playing here or pass the buck to update? */
-	/* Unlike SDL_SoundMixer, I think I'll do it here because
-	 * this library isn't a *total* hack and OpenAL has more 
-	 * built in functionality I need, so less needs to be 
-	 * controlled and directed through the update function.
-	 * The downside is less functionality is centralized.
-	 * The upside is that the update function should be
-	 * easier to maintain.
-	 */
-
-	/* Clear the error flag */
-	alGetError();
-	if(data->decoded_all)
-	{
-		/* Bind the data to the source */
-		alSourcei(
-			ALmixer_Channel_List[channel].alsource, 
-			AL_BUFFER, 
-			data->buffer[0]);
-		if((error = alGetError()) != AL_NO_ERROR)
-		{
-			ALmixer_SetError("Could not bind data to source: %s",
-				aluGetErrorString(error) );
-			Clean_Channel(channel);
-			return -1;
-		}
-
-		/* Make data available if access_data is enabled */
-		Invoke_Predecoded_Channel_Data_Callback(channel, data);
-	}
-	else
-	{
-		/* Need to use the streaming buffer for binding */
-
-		Uint32 bytes_returned;
-		Uint32 j;
-		data->num_buffers_in_use=0;
-/****** MODIFICATION must go here *********/
-		/* Since buffer queuing is pushed off until here to 
-		 * avoid buffer conflicts, we must start reading 
-		 * data here. First we make sure we have at least one
-		 * packet. Then we queue up until we hit our limit.
-		 */
-		bytes_returned = GetMoreData(
-			data,
-			data->buffer[0]);
-		if(0 == bytes_returned)
-		{
-			/* No data or error */
-			ALmixer_SetError("Could not get data for streamed PlayChannel: %s", ALmixer_GetError());
-			Clean_Channel(channel);
-			return -1;
-		}
-		/* Increment the number of buffers in use */
-		data->num_buffers_in_use++;
-		
-
-		/* Now we need to fill up the rest of the buffers.
-		 * There is a corner case where we run out of data
-		 * before the last buffer is filled.
-		 * Stop conditions are we run out of 
-		 * data or we max out our preload buffers.
-		 */
-			
-	fprintf(stderr, "Filling buffer #%d (AL id is %d)\n", 0, data->buffer[0]);
-		for(j=1; j<data->num_startup_buffers; j++)
-		{
-	fprintf(stderr, "Filling buffer #%d (AL id is %d)\n", j, data->buffer[j]);
-	/*
-	fprintf(stderr, ">>>>>>>>>>>>>>>>>>HACK for GetMoreData2\n");
-	*/
-		bytes_returned = GetMoreData(
-				data,
-				data->buffer[j]);
-		/* 
-		 * This might be a problem. I made a mistake with the types. I accidentally
-		 * made the bytes returned an Sint32 and returned -1 on error.
-		 * Bytes returned should be a Uint32, so now I no longer have a -1 case
-		 * to check. I hope I didn't break anything here
-		 */
-		#if 0
-			if(bytes_returned < 0)
-			{
-				/* Error found */
-				ALmixer_SetError("Could not get data for additional startup buffers for PlayChannel: %s", ALmixer_GetError());
-				/* We'll continue on because we do have some valid data */
-				ret_flag = -1;
-				break;
-			}
-			else if(0 == bytes_returned)
-		#endif
-			if(0 == bytes_returned)
-			{
-				/* No more data to buffer */
-				/* Check for loops */
-				if( ALmixer_Channel_List[channel].loops != 0 )
-				{
-fprintf(stderr, "Need to rewind. In RAMPUP, handling loop\n");
-					if(0 == Sound_Rewind(data->sample))
-					{
-fprintf(stderr, "error in rewind\n"); 
-						ALmixer_SetError( Sound_GetError() );
-						ALmixer_Channel_List[channel].loops = 0;
-						ret_flag = -1;
-						/* We'll continue on because we do have some valid data */
-						break;
-					}
-					/* Remember to reset the data->eof flag */
-					data->eof = 0;
-					if(ALmixer_Channel_List[channel].loops > 0)
-					{
-						ALmixer_Channel_List[channel].loops--;
-fprintf(stderr, "Inside 000 >>>>>>>>>>Loops=%d\n", ALmixer_Channel_List[channel].loops); 
-					}
-					/* Would like to redo the loop, but due to 
-					 * Sound_Rewind() bugs, we would risk falling 
-					 * into an infinite loop
-					 */
-					bytes_returned = GetMoreData(
-						data,
-						data->buffer[j]);
-					if(bytes_returned <= 0)
-					{
-						ALmixer_SetError("Could not get data: %s", ALmixer_GetError());
-						/* We'll continue on because we do have some valid data */
-						ret_flag = -1;
-						break;
-					}
-				}
-				else
-				{
-					/* No loops to do so quit here */
-					break;
-				}
-			}
-			/* Increment the number of buffers in use */
-			data->num_buffers_in_use++;
-		}
-		/*
-	fprintf(stderr, "In PlayChannel, about to queue: source=%d, num_buffers_in_use=%d\n",
-			ALmixer_Channel_List[channel].alsource, 
-			data->num_buffers_in_use);
-*/
-		
-		alSourceQueueBuffers(
-			ALmixer_Channel_List[channel].alsource, 
-			data->num_buffers_in_use, 
-			data->buffer);
-		if((error = alGetError()) != AL_NO_ERROR)
-		{
-			ALmixer_SetError("Could not bind data to source: %s",
-				aluGetErrorString(error) );
-			Clean_Channel(channel);
-			return -1;
-		}
-		/* This is part of the hideous Nvidia workaround. In order to figure out
-		 * which buffer to show during callbacks (for things like
-		 * o-scopes), I must keep a copy of the buffers that are queued in my own
-		 * data structure. This code will be called only if
-		 * "access_data" was set, indicated by whether the queue is NULL.
-		 */
-		if(data->circular_buffer_queue != NULL)
-		{
-			Uint32 k;
-			Uint32 queue_ret_flag;
-			for(k=0; k<data->num_buffers_in_use; k++)
-			{
-				queue_ret_flag = CircularQueueUnsignedInt_PushBack(data->circular_buffer_queue, data->buffer[k]);
-				if(0 == queue_ret_flag)
-				{
-					fprintf(stderr, "Serious internal error: CircularQueue could not push into queue.\n");
-					ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue");
-				}
-				/*
-				else
-				{
-					fprintf(stderr, "Queue in PlayTimed\n");
-					CircularQueueUnsignedInt_Print(data->circular_buffer_queue);
-				}
-				 */
-			}
-		}
-				
-		
-/****** END **********/
-	}
-	/* We have finished loading the data (predecoded or queued)
-	 * so now we can play 
-	 */
-	alSourcePlay(ALmixer_Channel_List[channel].alsource);
-	if((error = alGetError()) != AL_NO_ERROR)
-	{
-		ALmixer_SetError("Play failed: %s",
-			aluGetErrorString(error) );
-		Clean_Channel(channel);
-		return -1;
-	}
-
-	/* Add to the counter that something is playing */
-	Is_Playing_global++;
-	if(-1 == ret_flag)
-	{
-			fprintf(stderr, "BACKDOOR ERROR >>>>>>>>>>>>>>>>>>\n");
-		return -1;
-	}
-	return channel;
-}
-
-
-/* In case the user wants to specify a source instead of a channel,
- * they may use this function. This function will look up the 
- * source-to-channel map, and convert the call into a
- * PlayChannelTimed() function call.
- * Returns the channel it's being played on.
- * Note: If you are prefer this method, then you need to be careful
- * about using PlayChannel, particularly if you request the
- * first available channels because source and channels have 
- * a one-to-one mapping in this API. It is quite easy for 
- * a channel/source to already be in use because of this.
- * In this event, an error message will be returned to you.
- */
-static ALuint Internal_PlaySourceTimed(ALuint source, ALmixer_Data* data, Sint32 loops, Sint32 ticks)
-{
-	Sint32 channel;
-	Sint32 retval;
-	if(0 == source)
-	{
-		retval = Internal_PlayChannelTimed(-1, data, loops, ticks);
-		if(-1 == retval)
-		{
-			return 0;
-		}
-		else
-		{
-			return Internal_GetSource(retval);
-		}
-	}
-	
-	channel = Internal_GetChannel(source);
-	if(-1 == channel)
-	{
-		ALmixer_SetError("Cannot Play source: %s", ALmixer_GetError());
-		return 0;
-	}
-	retval = Internal_PlayChannelTimed(channel, data, loops, ticks);
-	if(-1 == retval)
-	{
-		return 0;
-	}
-	else
-	{
-		return source;
-	}
-	/* make compiler happy */
-	return 0;
-}
-
-
-
-/* Will return the number of channels halted
- * or 0 for error
- */
-static Sint32 Internal_HaltChannel(Sint32 channel)
-{
-	Sint32 retval = 0;
-	Sint32 counter = 0;
-	ALenum error;
-	ALint buffers_still_queued;
-	ALint buffers_processed;
-
-	if(channel >= Number_of_Channels_global)
-	{
-		ALmixer_SetError("Cannot halt channel %d because it exceeds maximum number of channels (%d)\n", channel, Number_of_Channels_global);
-		return -1;
-	}
-	/* If the user specified a specific channel */
-	if(channel >= 0)
-	{
-		fprintf(stderr, "Halt on channel %d\n", channel);
-		/* only need to process channel if in use */
-		if(ALmixer_Channel_List[channel].channel_in_use)
-		{
-			alSourceStop(ALmixer_Channel_List[channel].alsource);
-			if((error = alGetError()) != AL_NO_ERROR)
-			{
-				fprintf(stderr, "14Testing error: %s\n",
-					aluGetErrorString(error));				
-			}
-			/* Here's the situation. My old method of using
-			 * alSourceUnqueueBuffers() seemed to be invalid in light
-			 * of all the problems I suffered through with getting 
-			 * the CoreData backend to work with this code.
-			 * As such, I'm changing all the code to set the buffer to
-			 * AL_NONE. Furthermore, the queued vs. non-queued issue
-			 * doesn't need to apply here. For non-queued, Loki,
-			 * Creative Windows, and CoreAudio seem to leave the 
-			 * buffer queued (Old Mac didn't.) For queued, we need to 
-			 * remove the processed buffers and force remove the
-			 * still-queued buffers.
-			 */
-			fprintf(stderr, "Halt on channel %d, channel in use\n", channel);
-			alGetSourcei(
-				ALmixer_Channel_List[channel].alsource,
-				AL_BUFFERS_QUEUED, &buffers_still_queued
-			);
-			if((error = alGetError()) != AL_NO_ERROR)
-			{
-				fprintf(stderr, "17Testing Error with buffers_still_queued: %s",
-					aluGetErrorString(error));
-				ALmixer_SetError("Failed detecting still queued buffers: %s",
-					aluGetErrorString(error) );
-				retval = -1;
-			}
-			alGetSourcei(
-				ALmixer_Channel_List[channel].alsource,
-				AL_BUFFERS_PROCESSED, &buffers_processed
-			);
-			if((error = alGetError()) != AL_NO_ERROR)
-			{
-				fprintf(stderr, "17Testing Error with buffers_processed: %s",
-					aluGetErrorString(error));
-				ALmixer_SetError("Failed detecting still processed buffers: %s",
-					aluGetErrorString(error) );
-				retval = -1;
-			}
-			/* If either of these is greater than 0, it means we need
-			 * to clear the source
-			 */
-			if((buffers_still_queued > 0) || (buffers_processed > 0))
-			{
-				alSourcei(ALmixer_Channel_List[channel].alsource,
-					AL_BUFFER,
-					AL_NONE);
-				if((error = alGetError()) != AL_NO_ERROR)
-				{
-					fprintf(stderr, "17Testing Error with clearing buffer from source: %s",
-						aluGetErrorString(error));
-					ALmixer_SetError("Failed to clear buffer from source: %s",
-						aluGetErrorString(error) );
-					retval = -1;
-				}
-			}
-
-			ALmixer_Channel_List[channel].almixer_data->num_buffers_in_use  = 0;
-
-			Clean_Channel(channel);
-			Is_Playing_global--;
-			/* Launch callback for consistency? */
-			Invoke_Channel_Done_Callback(channel);
-			counter++;
-		}
-	}
-	/* The user wants to halt all channels */
-	else
-	{
-		Sint32 i;
-		for(i=0; i<Number_of_Channels_global; i++)
-		{
-			fprintf(stderr, "Halting channel %d\n", i);
-			fprintf(stderr, "in use %d\n", ALmixer_Channel_List[i].channel_in_use );
-			/* only need to process channel if in use */
-			if(ALmixer_Channel_List[i].channel_in_use)
-			{
-				fprintf(stderr, "SourceStop %d\n", i);
-				alSourceStop(ALmixer_Channel_List[i].alsource);
-				if((error = alGetError()) != AL_NO_ERROR)
-				{
-					fprintf(stderr, "19Testing error: %s\n",
-						aluGetErrorString(error));				
-				}
-
-				/* Here's the situation. My old method of using
-				 * alSourceUnqueueBuffers() seemed to be invalid in light
-				 * of all the problems I suffered through with getting 
-				 * the CoreData backend to work with this code.
-				 * As such, I'm changing all the code to set the buffer to
-				 * AL_NONE. Furthermore, the queued vs. non-queued issue
-				 * doesn't need to apply here. For non-queued, Loki,
-				 * Creative Windows, and CoreAudio seem to leave the 
-				 * buffer queued (Old Mac didn't.) For queued, we need to 
-				 * remove the processed buffers and force remove the
-				 * still-queued buffers.
-				 */
-				fprintf(stderr, "Halt on channel %d, channel in use\n", channel);
-				alGetSourcei(
-					ALmixer_Channel_List[i].alsource,
-					AL_BUFFERS_QUEUED, &buffers_still_queued
-				);
-				if((error = alGetError()) != AL_NO_ERROR)
-				{
-					fprintf(stderr, "17Testing Error with buffers_still_queued: %s",
-						aluGetErrorString(error));
-					ALmixer_SetError("Failed detecting still queued buffers: %s",
-						aluGetErrorString(error) );
-					retval = -1;
-				}
-				alGetSourcei(
-					ALmixer_Channel_List[i].alsource,
-					AL_BUFFERS_PROCESSED, &buffers_processed
-				);
-				if((error = alGetError()) != AL_NO_ERROR)
-				{
-					fprintf(stderr, "17Testing Error with buffers_processed: %s",
-						aluGetErrorString(error));
-					ALmixer_SetError("Failed detecting still processed buffers: %s",
-						aluGetErrorString(error) );
-					retval = -1;
-				}
-				/* If either of these is greater than 0, it means we need
-				 * to clear the source
-				 */
-				if((buffers_still_queued > 0) || (buffers_processed > 0))
-				{
-					alSourcei(ALmixer_Channel_List[i].alsource,
-						AL_BUFFER,
-						AL_NONE);
-					if((error = alGetError()) != AL_NO_ERROR)
-					{
-						fprintf(stderr, "17Testing Error with clearing buffer from source: %s",
-							aluGetErrorString(error));
-						ALmixer_SetError("Failed to clear buffer from source: %s",
-							aluGetErrorString(error) );
-						retval = -1;
-					}
-				}
-				
-				ALmixer_Channel_List[i].almixer_data->num_buffers_in_use  = 0;
-
-	fprintf(stderr, "Clean channel %d\n", i);
-				Clean_Channel(i);
-				Is_Playing_global--;
-				/* Launch callback for consistency? */
-	fprintf(stderr, "Callback%d\n", i);
-				Invoke_Channel_Done_Callback(i);
-
-				/* Increment the counter */
-				counter++;
-			}
-			/* Let's halt everything just in case there 
-			 * are bugs.
-			 */
-			/*
-			else
-			{
-				alSourceStop(ALmixer_Channel_List[channel].alsource);
-				/ * Can't clean because the in_use counter for
-				 * data will get messed up * /
-				Clean_Channel(channel);
-			}
-			*/
-			/* Just in case */
-			Is_Playing_global = 0;
-		}
-	}
-	if(-1 == retval)
-	{		
-		return -1;	
-	}
-	return counter;
-}
-
-
-/* Will return the source halted or the total number of channels
- * if all were halted or 0 for error
- */
-static Sint32 Internal_HaltSource(ALuint source)
-{
-	Sint32 channel;
-	if(0 == source)
-	{
-		/* Will return the number of sources halted */
-		return Internal_HaltChannel(-1);
-	}
-	
-	channel = Internal_GetChannel(source);
-	if(-1 == channel)
-	{
-		ALmixer_SetError("Cannot halt source: %s", ALmixer_GetError());
-		return 0;
-	}
-	return Internal_HaltChannel(channel);
-}
-
-
 /* This will rewind the SDL_Sound sample for streamed
  * samples and start buffering up the data for the next
  * playback. This may require samples to be halted
  */
-static Sint32 Internal_RewindData(ALmixer_Data* data)
-{
-	Sint32 retval = 0;
+static ALint Internal_RewindData(ALmixer_Data* data)
+{
+	ALint retval = 0;
 	/*
-	Sint32 bytes_returned;
-	Sint32 i;
+	ALint bytes_returned;
+	ALint i;
 	*/
 	if(NULL == data)
 	{
@@ -2383,9 +2138,9 @@
 
 
 
-static Sint32 Internal_RewindChannel(Sint32 channel)
-{
-	Sint32 retval = 0;
+static ALint Internal_RewindChannel(ALint channel)
+{
+	ALint retval = 0;
 	ALenum error;
 	ALint state;
 
@@ -2398,7 +2153,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "24Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	/* Clear error */
 	alGetError();
@@ -2424,13 +2179,13 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "25Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 				alSourceRewind(ALmixer_Channel_List[channel].alsource);
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					ALmixer_SetError("%s",
-						aluGetErrorString(error) );
+						alGetString(error) );
 					retval = -1;
 				}
 				/* Need to resume playback if it was originally playing */
@@ -2440,7 +2195,7 @@
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						ALmixer_SetError("%s",
-							aluGetErrorString(error) );
+							alGetString(error) );
 						retval = -1;
 					}
 				}
@@ -2454,13 +2209,13 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "25Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 					alSourcePause(ALmixer_Channel_List[channel].alsource);
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						ALmixer_SetError("%s",
-							aluGetErrorString(error) );
+							alGetString(error) );
 						retval = -1;
 					}
 				}
@@ -2477,10 +2232,10 @@
 			}
 		}
 	}
-	/* The user wants to halt all channels */
+	/* The user wants to rewind all channels */
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 	fprintf(stderr, "in use %d\n", ALmixer_Channel_List[i].channel_in_use );
@@ -2501,13 +2256,13 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "26Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 					alSourceRewind(ALmixer_Channel_List[i].alsource);
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						ALmixer_SetError("%s",
-							aluGetErrorString(error) );
+							alGetString(error) );
 						retval = -1;
 					}
 					/* Need to resume playback if it was originally playing */
@@ -2517,7 +2272,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							ALmixer_SetError("%s",
-								aluGetErrorString(error) );
+								alGetString(error) );
 							retval = -1;
 						}
 					}
@@ -2531,13 +2286,13 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "27Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 						alSourcePause(ALmixer_Channel_List[i].alsource);
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							ALmixer_SetError("%s",
-								aluGetErrorString(error) );
+								alGetString(error) );
 							retval = -1;
 						}
 					}
@@ -2559,12 +2314,12 @@
 }
 
 
-static Sint32 Internal_RewindSource(ALuint source)
-{
-	Sint32 channel;
+static ALint Internal_RewindSource(ALuint source)
+{
+	ALint channel;
 	if(0 == source)
 	{
-		return Internal_RewindChannel(-1);
+		return Internal_RewindChannel(-1) + 1;
 	}
 	
 	channel = Internal_GetChannel(source);
@@ -2573,19 +2328,441 @@
 		ALmixer_SetError("Cannot rewind source: %s", ALmixer_GetError());
 		return 0;
 	}
-	return Internal_RewindChannel(channel);
-}
+	return Internal_RewindChannel(channel) + 1;
+}
+
+
+
+
+
+static ALint Internal_PlayChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALint ticks)
+{
+	ALenum error;
+	int ret_flag = 0;
+	if(NULL == data)
+	{
+		ALmixer_SetError("Can't play because data is NULL\n");
+		return -1;
+	}
+
+	/* There isn't a good way to share streamed files because
+	 * the decoded data doesn't stick around. 
+	 * You must "Load" a brand new instance of
+	 * the data. If you try using the same data,
+	 * bad things may happen. This check will attempt
+	 * to prevent sharing
+	 */
+	if(0 == data->decoded_all)
+	{
+		if(data->in_use)
+		{
+			ALmixer_SetError("Can't play shared streamed sample because it is already in use");
+			return -1;
+		}
+
+		/* Make sure SDL_sound sample is not at EOF.
+		 * This mainly affects streamed files,
+	 	 * so the check is placed here
+		 */
+		if(data->eof)
+		{
+			if( -1 == Internal_RewindData(data) )
+			{
+				ALmixer_SetError("Can't play sample because it is at EOF and cannot rewind");
+				return -1;
+			}
+		}
+	}
+	/* We need to provide the user with the first available channel */
+	if(-1 == channel)
+	{
+		ALint i;
+		for(i=Number_of_Reserve_Channels_global; i<Number_of_Channels_global; i++)
+		{
+			if(0 == ALmixer_Channel_List[i].channel_in_use)
+			{
+				channel = i;
+				break;
+			}
+		}
+		/* if we couldn't find a channel, return an error */
+		if(i == Number_of_Channels_global)
+		{
+			ALmixer_SetError("No channels available for playing");
+			return -1;
+		}
+	}
+	/* If we didn't assign the channel number, make sure it's not
+	 * out of bounds or in use */
+	else
+	{
+		if(channel >= Number_of_Channels_global)
+		{
+			ALmixer_SetError("Requested channel (%d) exceeds maximum channel (%d) because only %d channels are allocated", channel, Number_of_Channels_global-1, Number_of_Channels_global);
+			return -1;
+		}
+		else if(ALmixer_Channel_List[channel].channel_in_use)
+		{
+			ALmixer_SetError("Requested channel (%d) is in use", channel, Number_of_Channels_global-1, Number_of_Channels_global);
+			return -1;
+		}	
+	}
+	/* Make sure the user doesn't enter some meaningless value */
+	if(loops < -1)
+	{
+		loops = -1;
+	}
+							
+	/* loops will probably have to change to be controlled by SDL_Sound */
+
+	/* Set up the initial values for playing */
+	ALmixer_Channel_List[channel].channel_in_use = 1;
+	data->in_use++;
+		
+	/* Shouldn't need updating until a callback is fired
+	 * (assuming that we call Play in this function 
+	 */
+	ALmixer_Channel_List[channel].needs_stream = 0;
+	ALmixer_Channel_List[channel].almixer_data = data;
+	ALmixer_Channel_List[channel].start_time = ALmixer_GetTicks();
+
+	/* If user entered -1 (or less), set to -1 */
+	if(ticks < 0)
+	{
+		ALmixer_Channel_List[channel].expire_ticks = -1;
+	}
+	else
+	{
+		ALmixer_Channel_List[channel].expire_ticks = ticks;
+	}
+
+	
+	ALmixer_Channel_List[channel].halted = 0;
+	ALmixer_Channel_List[channel].paused = 0;
+
+	/* Ran just use OpenAL to control loops if predecoded and infinite */
+	ALmixer_Channel_List[channel].loops = loops; 
+	if( (-1 == loops) && (data->decoded_all) )
+	{
+		alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_TRUE);
+	}
+	else
+	{
+		alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_FALSE);
+	}
+	if((error = alGetError()) != AL_NO_ERROR)
+	{
+		fprintf(stderr, "13Testing error: %s\n",
+			alGetString(error));				
+	}
+
+#if 0
+	/* Because of the corner case, predecoded
+	 * files must add +1 to the loops.
+	 * Streams do not have this problem
+	 * because they can use the eof flag to 
+	 * avoid the conflict.
+	 * Sharing data chunks prevents the use of the eof flag.
+	 * Since streams, cannot share, only predecoded
+	 * files are affected 
+	 */
+	if(data->decoded_all)
+	{
+		/* Corner Case: Now that play calls are pushed
+		 * off to update(), the start call must
+		 * also come through here. So, start loops
+		 * must be +1 
+		 */
+		if(-1 == loops)
+		{
+			/* -1 is a special case, and you don't want
+			 * to add +1 to it */
+			ALmixer_Channel_List[channel].loops = -1;
+			alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_TRUE);
+		}
+		else
+		{
+			ALmixer_Channel_List[channel].loops = loops+1;
+			alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_FALSE);
+		}
+	}
+	else
+	{
+		ALmixer_Channel_List[channel].loops = loops;
+		/* Can we really loop on streamed data? */
+		alSourcei(ALmixer_Channel_List[channel].alsource, AL_LOOPING, AL_TRUE);
+	}
+#endif
+
+	/* Should I start playing here or pass the buck to update? */
+	/* Unlike SDL_SoundMixer, I think I'll do it here because
+	 * this library isn't a *total* hack and OpenAL has more 
+	 * built in functionality I need, so less needs to be 
+	 * controlled and directed through the update function.
+	 * The downside is less functionality is centralized.
+	 * The upside is that the update function should be
+	 * easier to maintain.
+	 */
+
+	/* Clear the error flag */
+	alGetError();
+	if(data->decoded_all)
+	{
+		/* Bind the data to the source */
+		alSourcei(
+			ALmixer_Channel_List[channel].alsource, 
+			AL_BUFFER, 
+			data->buffer[0]);
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			ALmixer_SetError("Could not bind data to source: %s",
+				alGetString(error) );
+			Clean_Channel(channel);
+			return -1;
+		}
+
+		/* Make data available if access_data is enabled */
+		Invoke_Predecoded_Channel_Data_Callback(channel, data);
+	}
+	else
+	{
+		/* Need to use the streaming buffer for binding */
+
+		ALuint bytes_returned;
+		ALuint j;
+		data->num_buffers_in_use=0;
+/****** MODIFICATION must go here *********/
+		/* Since buffer queuing is pushed off until here to 
+		 * avoid buffer conflicts, we must start reading 
+		 * data here. First we make sure we have at least one
+		 * packet. Then we queue up until we hit our limit.
+		 */
+		bytes_returned = GetMoreData(
+			data,
+			data->buffer[0]);
+		if(0 == bytes_returned)
+		{
+			/* No data or error */
+			ALmixer_SetError("Could not get data for streamed PlayChannel: %s", ALmixer_GetError());
+			Clean_Channel(channel);
+			return -1;
+		}
+		/* Increment the number of buffers in use */
+		data->num_buffers_in_use++;
+		
+
+		/* Now we need to fill up the rest of the buffers.
+		 * There is a corner case where we run out of data
+		 * before the last buffer is filled.
+		 * Stop conditions are we run out of 
+		 * data or we max out our preload buffers.
+		 */
+			
+	fprintf(stderr, "Filling buffer #%d (AL id is %d)\n", 0, data->buffer[0]);
+		for(j=1; j<data->num_startup_buffers; j++)
+		{
+	fprintf(stderr, "Filling buffer #%d (AL id is %d)\n", j, data->buffer[j]);
+	/*
+	fprintf(stderr, ">>>>>>>>>>>>>>>>>>HACK for GetMoreData2\n");
+	*/
+		bytes_returned = GetMoreData(
+				data,
+				data->buffer[j]);
+		/* 
+		 * This might be a problem. I made a mistake with the types. I accidentally
+		 * made the bytes returned an ALint and returned -1 on error.
+		 * Bytes returned should be a ALuint, so now I no longer have a -1 case
+		 * to check. I hope I didn't break anything here
+		 */
+		#if 0
+			if(bytes_returned < 0)
+			{
+				/* Error found */
+				ALmixer_SetError("Could not get data for additional startup buffers for PlayChannel: %s", ALmixer_GetError());
+				/* We'll continue on because we do have some valid data */
+				ret_flag = -1;
+				break;
+			}
+			else if(0 == bytes_returned)
+		#endif
+			if(0 == bytes_returned)
+			{
+				/* No more data to buffer */
+				/* Check for loops */
+				if( ALmixer_Channel_List[channel].loops != 0 )
+				{
+fprintf(stderr, "Need to rewind. In RAMPUP, handling loop\n");
+					if(0 == Sound_Rewind(data->sample))
+					{
+fprintf(stderr, "error in rewind\n"); 
+						ALmixer_SetError( Sound_GetError() );
+						ALmixer_Channel_List[channel].loops = 0;
+						ret_flag = -1;
+						/* We'll continue on because we do have some valid data */
+						break;
+					}
+					/* Remember to reset the data->eof flag */
+					data->eof = 0;
+					if(ALmixer_Channel_List[channel].loops > 0)
+					{
+						ALmixer_Channel_List[channel].loops--;
+fprintf(stderr, "Inside 000 >>>>>>>>>>Loops=%d\n", ALmixer_Channel_List[channel].loops); 
+					}
+					/* Would like to redo the loop, but due to 
+					 * Sound_Rewind() bugs, we would risk falling 
+					 * into an infinite loop
+					 */
+					bytes_returned = GetMoreData(
+						data,
+						data->buffer[j]);
+					if(bytes_returned <= 0)
+					{
+						ALmixer_SetError("Could not get data: %s", ALmixer_GetError());
+						/* We'll continue on because we do have some valid data */
+						ret_flag = -1;
+						break;
+					}
+				}
+				else
+				{
+					/* No loops to do so quit here */
+					break;
+				}
+			}
+			/* Increment the number of buffers in use */
+			data->num_buffers_in_use++;
+		}
+		/*
+	fprintf(stderr, "In PlayChannel, about to queue: source=%d, num_buffers_in_use=%d\n",
+			ALmixer_Channel_List[channel].alsource, 
+			data->num_buffers_in_use);
+*/
+		
+		alSourceQueueBuffers(
+			ALmixer_Channel_List[channel].alsource, 
+			data->num_buffers_in_use, 
+			data->buffer);
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			ALmixer_SetError("Could not bind data to source: %s",
+				alGetString(error) );
+			Clean_Channel(channel);
+			return -1;
+		}
+		/* This is part of the hideous Nvidia workaround. In order to figure out
+		 * which buffer to show during callbacks (for things like
+		 * o-scopes), I must keep a copy of the buffers that are queued in my own
+		 * data structure. This code will be called only if
+		 * "access_data" was set, indicated by whether the queue is NULL.
+		 */
+		if(data->circular_buffer_queue != NULL)
+		{
+			ALuint k;
+			ALuint queue_ret_flag;
+			for(k=0; k<data->num_buffers_in_use; k++)
+			{
+//				fprintf(stderr, "56c: CircularQueue_PushBack.\n");
+				queue_ret_flag = CircularQueueUnsignedInt_PushBack(data->circular_buffer_queue, data->buffer[k]);
+				if(0 == queue_ret_flag)
+				{
+					fprintf(stderr, "Serious internal error: CircularQueue could not push into queue.\n");
+					ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue");
+				}
+				/*
+				else
+				{
+					fprintf(stderr, "Queue in PlayTimed\n");
+					CircularQueueUnsignedInt_Print(data->circular_buffer_queue);
+				}
+				 */
+			}
+		}
+				
+		
+/****** END **********/
+	}
+	/* We have finished loading the data (predecoded or queued)
+	 * so now we can play 
+	 */
+	alSourcePlay(ALmixer_Channel_List[channel].alsource);
+	if((error = alGetError()) != AL_NO_ERROR)
+	{
+		ALmixer_SetError("Play failed: %s",
+			alGetString(error) );
+		Clean_Channel(channel);
+		return -1;
+	}
+
+	/* Add to the counter that something is playing */
+	Is_Playing_global++;
+	if(-1 == ret_flag)
+	{
+			fprintf(stderr, "BACKDOOR ERROR >>>>>>>>>>>>>>>>>>\n");
+		return -1;
+	}
+	return channel;
+}
+
+
+/* In case the user wants to specify a source instead of a channel,
+ * they may use this function. This function will look up the 
+ * source-to-channel map, and convert the call into a
+ * PlayChannelTimed() function call.
+ * Returns the channel it's being played on.
+ * Note: If you are prefer this method, then you need to be careful
+ * about using PlayChannel, particularly if you request the
+ * first available channels because source and channels have 
+ * a one-to-one mapping in this API. It is quite easy for 
+ * a channel/source to already be in use because of this.
+ * In this event, an error message will be returned to you.
+ */
+static ALuint Internal_PlaySourceTimed(ALuint source, ALmixer_Data* data, ALint loops, ALint ticks)
+{
+	ALint channel;
+	ALint retval;
+	if(0 == source)
+	{
+		retval = Internal_PlayChannelTimed(-1, data, loops, ticks);
+		if(-1 == retval)
+		{
+			return 0;
+		}
+		else
+		{
+			return Internal_GetSource(retval);
+		}
+	}
+	
+	channel = Internal_GetChannel(source);
+	if(-1 == channel)
+	{
+		ALmixer_SetError("Cannot Play source: %s", ALmixer_GetError());
+		return 0;
+	}
+	retval = Internal_PlayChannelTimed(channel, data, loops, ticks);
+	if(-1 == retval)
+	{
+		return 0;
+	}
+	else
+	{
+		return source;
+	}
+	/* make compiler happy */
+	return 0;
+}
+
 
 
 
 /* Returns the channel or number of channels actually paused */
 
-static Sint32 Internal_PauseChannel(Sint32 channel)
+static ALint Internal_PauseChannel(ALint channel)
 {
 	ALenum error;
 	ALint state;
-	Sint32 retval = 0;
-	Sint32 counter = 0;
+	ALint retval = 0;
+	ALint counter = 0;
 	
 	if(channel >= Number_of_Channels_global)
 	{
@@ -2596,7 +2773,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "28Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	/* Clear error */
 	alGetError();
@@ -2619,7 +2796,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "29Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 			if(AL_PLAYING == state)
 			{
@@ -2630,14 +2807,14 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					ALmixer_SetError("%s",
-						aluGetErrorString(error) );
+						alGetString(error) );
 					retval = -1;
 				}
 				/* We need to pause the expire time count down */
 				if(ALmixer_Channel_List[channel].expire_ticks != -1)
 				{
-					Uint32 current_time = SDL_GetTicks();
-					Uint32 diff_time;
+					ALuint current_time = ALmixer_GetTicks();
+					ALuint diff_time;
 					diff_time = current_time - 
 						ALmixer_Channel_List[channel].start_time;
 					/* When we unpause, we will want to reset
@@ -2660,8 +2837,8 @@
 				/* Do the same as expire time for fading */
 				if(ALmixer_Channel_List[channel].fade_enabled)
 				{
-					Uint32 current_time = SDL_GetTicks();
-					Uint32 diff_time;
+					ALuint current_time = ALmixer_GetTicks();
+					ALuint diff_time;
 					diff_time = current_time - 
 						ALmixer_Channel_List[channel].fade_start_time;
 					/* When we unpause, we will want to reset
@@ -2685,7 +2862,7 @@
 	/* The user wants to halt all channels */
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 	fprintf(stderr, "Pausing channel %d\n", i);
@@ -2704,7 +2881,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "30Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 				if(AL_PLAYING == state)
 				{
@@ -2716,14 +2893,14 @@
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						ALmixer_SetError("%s",
-							aluGetErrorString(error) );
+							alGetString(error) );
 						retval = -1;
 					}
 					/* We need to pause the expire time count down */
 					if(ALmixer_Channel_List[i].expire_ticks != -1)
 					{
-						Uint32 current_time = SDL_GetTicks();
-						Uint32 diff_time;
+						ALuint current_time = ALmixer_GetTicks();
+						ALuint diff_time;
 						diff_time = current_time - 
 							ALmixer_Channel_List[i].start_time;
 						/* When we unpause, we will want to reset
@@ -2746,8 +2923,8 @@
 					/* Do the same as expire time for fading */
 					if(ALmixer_Channel_List[i].fade_enabled)
 					{
-						Uint32 current_time = SDL_GetTicks();
-						Uint32 diff_time;
+						ALuint current_time = ALmixer_GetTicks();
+						ALuint diff_time;
 						diff_time = current_time - 
 							ALmixer_Channel_List[i].fade_start_time;
 						/* When we unpause, we will want to reset
@@ -2777,9 +2954,9 @@
 }
 
 /* Returns the channel or number of channels actually paused */
-static Sint32 Internal_PauseSource(ALuint source)
-{
-	Sint32 channel;
+static ALint Internal_PauseSource(ALuint source)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_PauseChannel(-1);
@@ -2796,12 +2973,12 @@
 
 
 
-static Sint32 Internal_ResumeChannel(Sint32 channel)
+static ALint Internal_ResumeChannel(ALint channel)
 {
 	ALint state;
 	ALenum error;
-	Sint32 retval = 0;
-	Sint32 counter = 0;
+	ALint retval = 0;
+	ALint counter = 0;
 	
 	if(channel >= Number_of_Channels_global)
 	{
@@ -2812,7 +2989,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "31Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	/* Clear error */
 	alGetError();
@@ -2831,7 +3008,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "32Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 			if(AL_PAUSED == state)
 			{
@@ -2841,19 +3018,19 @@
 				/* We need to resume the expire time count down */
 				if(ALmixer_Channel_List[channel].expire_ticks != -1)
 				{
-					ALmixer_Channel_List[channel].start_time = SDL_GetTicks();
+					ALmixer_Channel_List[channel].start_time = ALmixer_GetTicks();
 				}
 				/* Do the same as expire time for fading */
 				if(ALmixer_Channel_List[channel].fade_enabled)
 				{
-					ALmixer_Channel_List[channel].fade_start_time = SDL_GetTicks();
+					ALmixer_Channel_List[channel].fade_start_time = ALmixer_GetTicks();
 				}	
 
 				alSourcePlay(ALmixer_Channel_List[channel].alsource);
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					ALmixer_SetError("%s",
-						aluGetErrorString(error) );
+						alGetString(error) );
 					retval = -1;
 				}
 			}
@@ -2863,7 +3040,7 @@
 	/* The user wants to halt all channels */
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 	fprintf(stderr, "Pausing channel %d\n", i);
@@ -2879,7 +3056,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "33Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 				if(AL_PAUSED == state)
 				{
@@ -2889,19 +3066,19 @@
 					/* We need to resume the expire time count down */
 					if(ALmixer_Channel_List[i].expire_ticks != -1)
 					{
-						ALmixer_Channel_List[i].start_time = SDL_GetTicks();
+						ALmixer_Channel_List[i].start_time = ALmixer_GetTicks();
 					}
 					/* Do the same as expire time for fading */
 					if(ALmixer_Channel_List[i].fade_enabled)
 					{
-						ALmixer_Channel_List[i].fade_start_time = SDL_GetTicks();
+						ALmixer_Channel_List[i].fade_start_time = ALmixer_GetTicks();
 					}	
 						
 					alSourcePlay(ALmixer_Channel_List[i].alsource);
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						ALmixer_SetError("%s",
-							aluGetErrorString(error) );
+							alGetString(error) );
 						retval = -1;
 					}
 				}
@@ -2916,9 +3093,9 @@
 }
 
 
-static Sint32 Internal_ResumeSource(ALuint source)
-{
-	Sint32 channel;
+static ALint Internal_ResumeSource(ALuint source)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_ResumeChannel(-1);
@@ -2937,9 +3114,9 @@
 /* Might consider setting eof to 0 as a "feature"
  * This will allow seek to end to stay there because
  * Play automatically rewinds if at the end */
-static Sint32 Internal_Seek(ALmixer_Data* data, Uint32 msec)
-{
-	Sint32 retval;
+static ALint Internal_SeekData(ALmixer_Data* data, ALuint msec)
+{
+	ALint retval;
 	
 	if(NULL == data)
 	{
@@ -2950,7 +3127,7 @@
 	/* Seek for predecoded files involves moving the chunk pointer around */
 	if(data->decoded_all)
 	{
-		Uint32 byte_position;
+		ALuint byte_position;
 
 		/* OpenAL doesn't seem to like it if I change the buffer
 		 * while playing (crashes), so I must require that Seek only
@@ -3029,13 +3206,13 @@
 		
 
 
-static Sint32 Internal_FadeInChannelTimed(Sint32 channel, ALmixer_Data* data, Sint32 loops, Uint32 fade_ticks, Sint32 expire_ticks)
+static ALint Internal_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks)
 {
 	ALfloat value;
 	ALenum error;
 	ALfloat original_value;
-	Uint32 current_time = SDL_GetTicks();
-	Sint32 retval;
+	ALuint current_time = ALmixer_GetTicks();
+	ALint retval;
 
 	
 	
@@ -3073,22 +3250,14 @@
 	
 	/* Get the original volume in case of a problem */
 	alGetSourcef(ALmixer_Channel_List[channel].alsource,
-		AL_MAX_GAIN, &original_value);
+		AL_GAIN, &original_value);
 	
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "35Testing error: %s\n",
-			aluGetErrorString(error));				
-	}
-	/* Get the Max volume */
-	/*
-	alGetSourcef(ALmixer_Channel_List[channel].alsource,
-		AL_MAX_GAIN, &value);
-	ALmixer_Channel_List[channel].fade_end_volume = value;
-	fprintf(stderr, "MAX gain: %f\n", value);
-	*/
-	ALmixer_Channel_List[channel].fade_end_volume = 
-		ALmixer_Channel_List[channel].max_volume;
+			alGetString(error));				
+	}
+	ALmixer_Channel_List[channel].fade_end_volume = original_value;
 
 	/* Get the Min volume */
 	alGetSourcef(ALmixer_Channel_List[channel].alsource,
@@ -3096,18 +3265,18 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "36Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	ALmixer_Channel_List[channel].fade_start_volume = value;
 	fprintf(stderr, "MIN gain: %f\n", value);
 	
 	/* Set the actual volume */
 	alSourcef(ALmixer_Channel_List[channel].alsource,
-		AL_MAX_GAIN, value);
+		AL_GAIN, value);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "37Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	
 	
@@ -3123,12 +3292,12 @@
 		 * distruption of playback
 		 */
 		alSourcef(ALmixer_Channel_List[channel].alsource,
-			AL_MAX_GAIN, original_value);
-	if((error = alGetError()) != AL_NO_ERROR)
-	{
-		fprintf(stderr, "38Testing error: %s\n",
-			aluGetErrorString(error));				
-	}
+			AL_GAIN, original_value);
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			fprintf(stderr, "38Testing error: %s\n",
+				alGetString(error));				
+		}
 		return retval;
 	}
 
@@ -3139,14 +3308,14 @@
 	if(0 == fade_ticks)
 	{
 		alSourcef(ALmixer_Channel_List[channel].alsource,
-			AL_MAX_GAIN, 
+			AL_GAIN, 
 			ALmixer_Channel_List[channel].fade_end_volume
 		);
-	if((error = alGetError()) != AL_NO_ERROR)
-	{
-		fprintf(stderr, "39Testing error: %s\n",
-			aluGetErrorString(error));				
-	}
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			fprintf(stderr, "39Testing error: %s\n",
+				alGetString(error));				
+		}
 
 		return retval;
 	}
@@ -3168,10 +3337,10 @@
 }
 
 		
-static ALuint Internal_FadeInSourceTimed(ALuint source, ALmixer_Data* data, Sint32 loops, Uint32 fade_ticks, Sint32 expire_ticks)
-{
-	Sint32 channel;
-	Sint32 retval;
+static ALuint Internal_FadeInSourceTimed(ALuint source, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks)
+{
+	ALint channel;
+	ALint retval;
 	if(0 == source)
 	{
 		retval = Internal_FadeInChannelTimed(-1, data, loops, fade_ticks, expire_ticks);
@@ -3209,12 +3378,12 @@
 
 /* Will fade out currently playing channels.
  * It starts at the current volume level and goes down */
-static Sint32 Internal_FadeOutChannel(Sint32 channel, Uint32 ticks)
+static ALint Internal_FadeOutChannel(ALint channel, ALuint ticks)
 {
 	ALfloat value;
 	ALenum error;
-	Uint32 current_time = SDL_GetTicks();
-	Uint32 counter = 0;
+	ALuint current_time = ALmixer_GetTicks();
+	ALuint counter = 0;
 	
 	/* We can't accept 0 as a value because of div-by-zero.
 	 * If zero, just call Halt at normal
@@ -3222,7 +3391,7 @@
 	 */
 	if(0 == ticks)
 	{
-		return Internal_HaltChannel(channel);
+		return Internal_HaltChannel(channel, AL_TRUE);
 	}
 	
 	
@@ -3238,12 +3407,12 @@
 		{
 			/* Get the current volume */
 			alGetSourcef(ALmixer_Channel_List[channel].alsource,
-				AL_MAX_GAIN, &value);
+				AL_GAIN, &value);
 			ALmixer_Channel_List[channel].fade_start_volume = value;
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "40Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 		
 			/* Get the Min volume */
@@ -3252,7 +3421,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "41Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 			ALmixer_Channel_List[channel].fade_end_volume = value;
 			fprintf(stderr, "MIN gain: %f\n", value);
@@ -3277,19 +3446,19 @@
 	/* Else need to fade out all channels */
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			if(ALmixer_Channel_List[i].channel_in_use)
 			{
 				/* Get the current volume */
 				alGetSourcef(ALmixer_Channel_List[i].alsource,
-					AL_MAX_GAIN, &value);
+					AL_GAIN, &value);
 				ALmixer_Channel_List[i].fade_start_volume = value;
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "42Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 			
 				/* Get the Min volume */
@@ -3298,7 +3467,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "43Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 				ALmixer_Channel_List[i].fade_end_volume = value;
 				fprintf(stderr, "MIN gain: %f\n", value);
@@ -3325,9 +3494,9 @@
 }
 
 
-static Sint32 Internal_FadeOutSource(ALuint source, Uint32 ticks)
-{
-	Sint32 channel;
+static ALint Internal_FadeOutSource(ALuint source, ALuint ticks)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_FadeOutChannel(-1, ticks);
@@ -3347,12 +3516,12 @@
  * It starts at the current volume level and go to target 
  * Only affects channels that are playing
  */
-static Sint32 Internal_FadeChannel(Sint32 channel, Uint32 ticks, ALfloat volume)
+static ALint Internal_FadeChannel(ALint channel, ALuint ticks, ALfloat volume)
 {
 	ALfloat value;
 	ALenum error;
-	Uint32 current_time = SDL_GetTicks();
-	Uint32 counter = 0;
+	ALuint current_time = ALmixer_GetTicks();
+	ALuint counter = 0;
 	
 	if(channel >= Number_of_Channels_global)
 	{
@@ -3377,11 +3546,11 @@
 			{
 				/* Get the current volume */
 				alGetSourcef(ALmixer_Channel_List[channel].alsource,
-					AL_MAX_GAIN, &value);
+					AL_GAIN, &value);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "44Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 				ALmixer_Channel_List[channel].fade_start_volume = value;
 			
@@ -3401,11 +3570,11 @@
 			else
 			{
 				alSourcef(ALmixer_Channel_List[channel].alsource,
-					AL_MAX_GAIN, volume);
+					AL_GAIN, volume);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "45Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 			}
 			counter++;
@@ -3414,7 +3583,7 @@
 	/* Else need to fade out all channels */
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			if(volume < ALmixer_Channel_List[i].min_volume)
@@ -3432,11 +3601,11 @@
 				{
 					/* Get the current volume */
 					alGetSourcef(ALmixer_Channel_List[i].alsource,
-						AL_MAX_GAIN, &value);
+						AL_GAIN, &value);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "46Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 					ALmixer_Channel_List[i].fade_start_volume = value;
 				
@@ -3456,11 +3625,11 @@
 				else
 				{
 					alSourcef(ALmixer_Channel_List[i].alsource,
-						AL_MAX_GAIN, volume);
+						AL_GAIN, volume);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "47Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 				}
 				counter++;
@@ -3470,9 +3639,9 @@
 	return counter;
 }
 
-static Sint32 Internal_FadeSource(ALuint source, Uint32 ticks, ALfloat volume)
-{
-	Sint32 channel;
+static ALint Internal_FadeSource(ALuint source, ALuint ticks, ALfloat volume)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_FadeChannel(-1, ticks, volume);
@@ -3492,15 +3661,168 @@
 
 /* Set a volume regardless if it's in use or not.
  */
-static Sint32 Internal_SetMaxVolumeChannel(Sint32 channel, ALfloat volume)
+static ALboolean Internal_SetVolumeChannel(ALint channel, ALfloat volume)
 {
 	ALenum error;
-	Sint32 retval = 0;
+	ALboolean retval = AL_TRUE;
+	
+	if(channel >= Number_of_Channels_global)
+	{
+		ALmixer_SetError("Requested channel (%d) exceeds maximum channel (%d) because only %d channels are allocated", channel, Number_of_Channels_global-1, Number_of_Channels_global);
+		return AL_FALSE;
+	}
+	
+	if(channel >= 0)
+	{
+		if(volume < 0.0f)
+		{
+			volume = 0.0f;
+		}
+		else if(volume > 1.0f)
+		{
+			volume = 1.0f;
+		}
+		alSourcef(ALmixer_Channel_List[channel].alsource,
+				  AL_GAIN, volume);
+		if((error = alGetError()) != AL_NO_ERROR)
+		{
+			ALmixer_SetError("%s",
+							 alGetString(error) );
+			retval = AL_FALSE;
+		}
+	}
+	else
+	{
+		ALint i;
+		for(i=0; i<Number_of_Channels_global; i++)
+		{
+			if(volume < 0.0f)
+			{
+				volume = 0.0f;
+			}
+			else if(volume > 1.0f)
+			{
+				volume = 1.0f;
+			}
+			alSourcef(ALmixer_Channel_List[i].alsource,
+					  AL_GAIN, volume);
+			if((error = alGetError()) != AL_NO_ERROR)
+			{
+				ALmixer_SetError("%s",
+								 alGetString(error) );
+				retval = AL_FALSE;
+			}
+		}
+	}
+	return retval;
+}
+
+static ALboolean Internal_SetVolumeSource(ALuint source, ALfloat volume)
+{
+	ALint channel;
+	if(0 == source)
+	{
+		return Internal_SetVolumeChannel(-1, volume);
+	}
+	
+	channel = Internal_GetChannel(source);
+	if(-1 == channel)
+	{
+		ALmixer_SetError("Cannot SetMaxVolume: %s", ALmixer_GetError());
+		return AL_FALSE;
+	}
+	return Internal_SetVolumeChannel(channel, volume);
+}
+
+
+static ALfloat Internal_GetVolumeChannel(ALint channel)
+{
+	 ALfloat value;
+	 ALenum error;
+	ALfloat running_total = 0.0f;
+	ALfloat retval = 0.0f;
+	
+	if(channel >= Number_of_Channels_global)
+	{
+		ALmixer_SetError("Requested channel (%d) exceeds maximum channel (%d) because only %d channels are allocated", channel, Number_of_Channels_global-1, Number_of_Channels_global);
+		return -1.0f;
+	}
+	
+	if(channel >= 0)
+	{
+		 alGetSourcef(ALmixer_Channel_List[channel].alsource,
+		 AL_GAIN, &value);
+		 if((error = alGetError()) != AL_NO_ERROR)
+		 {
+			 ALmixer_SetError("%s", alGetString(error) );
+			 retval = -1.0f;
+		 }
+		 else
+		 {
+			 retval = value;
+		 }
+	}
+	else
+	{
+		ALint i;
+		for(i=0; i<Number_of_Channels_global; i++)
+		{
+			 alGetSourcef(ALmixer_Channel_List[i].alsource,
+			 AL_GAIN, &value);
+			 if((error = alGetError()) != AL_NO_ERROR)
+			 {
+				 ALmixer_SetError("%s", alGetString(error) );
+				 retval = -1;
+			 }
+			 else
+			 {
+				 running_total += value;
+			 }
+		}
+		if(0 == Number_of_Channels_global)
+		{
+			ALmixer_SetError("No channels are allocated");
+			retval = -1.0f;
+		}
+		else
+		{
+			retval = running_total / Number_of_Channels_global;
+		}
+	}
+	return retval;
+}
+
+static ALfloat Internal_GetVolumeSource(ALuint source)
+{
+	ALint channel;
+	if(0 == source)
+	{
+		return Internal_GetVolumeChannel(-1);
+	}
+	
+	channel = Internal_GetChannel(source);
+	if(-1 == channel)
+	{
+		ALmixer_SetError("Cannot GetVolume: %s", ALmixer_GetError());
+		return -1.0f;
+	}
+	
+	return Internal_GetVolumeChannel(channel);
+}
+
+
+
+/* Set a volume regardless if it's in use or not.
+ */
+static ALboolean Internal_SetMaxVolumeChannel(ALint channel, ALfloat volume)
+{
+	ALenum error;
+	ALboolean retval = AL_TRUE;
 	
 	if(channel >= Number_of_Channels_global)
 	{
 			ALmixer_SetError("Requested channel (%d) exceeds maximum channel (%d) because only %d channels are allocated", channel, Number_of_Channels_global-1, Number_of_Channels_global);
-		return -1;
+		return AL_FALSE;
 	}
 
 	if(channel >= 0)
@@ -3519,8 +3841,8 @@
 		if((error = alGetError()) != AL_NO_ERROR)
 		{
 			ALmixer_SetError("%s",
-				aluGetErrorString(error) );
-			retval = -1;
+				alGetString(error) );
+			retval = AL_FALSE;
 		}
 		if(ALmixer_Channel_List[channel].max_volume < ALmixer_Channel_List[channel].min_volume)
 		{
@@ -3530,14 +3852,14 @@
 			if((error = alGetError()) != AL_NO_ERROR)
 			{
 				ALmixer_SetError("%s",
-					aluGetErrorString(error) );
-				retval = -1;
+					alGetString(error) );
+				retval = AL_FALSE;
 			}
 		}
 	}
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			if(volume < 0.0f)
@@ -3554,8 +3876,8 @@
 			if((error = alGetError()) != AL_NO_ERROR)
 			{
 				ALmixer_SetError("%s",
-					aluGetErrorString(error) );
-				retval = -1;
+					alGetString(error) );
+				retval = AL_FALSE;
 			}
 			if(ALmixer_Channel_List[i].max_volume < ALmixer_Channel_List[i].min_volume)
 			{
@@ -3565,8 +3887,8 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					ALmixer_SetError("%s",
-						aluGetErrorString(error) );
-					retval = -1;
+						alGetString(error) );
+					retval = AL_FALSE;
 				}
 			}
 		}
@@ -3574,9 +3896,9 @@
 	return retval;
 }
 
-static Sint32 Internal_SetMaxVolumeSource(ALuint source, ALfloat volume)
-{
-	Sint32 channel;
+static ALint Internal_SetMaxVolumeSource(ALuint source, ALfloat volume)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_SetMaxVolumeChannel(-1, volume);
@@ -3586,12 +3908,12 @@
 	if(-1 == channel)
 	{
 		ALmixer_SetError("Cannot SetMaxVolume: %s", ALmixer_GetError());
-		return -1;
+		return AL_FALSE;
 	}
 	return Internal_SetMaxVolumeChannel(channel, volume);
 }
 
-static ALfloat Internal_GetMaxVolumeChannel(Sint32 channel)
+static ALfloat Internal_GetMaxVolumeChannel(ALint channel)
 {
 	/*
 	ALfloat value;
@@ -3614,7 +3936,7 @@
 		if((error = alGetError()) != AL_NO_ERROR)
 		{
 			ALmixer_SetError("%s",
-				aluGetErrorString(error) );
+				alGetString(error) );
 			retval = -1.0f;
 		}
 		else
@@ -3627,7 +3949,7 @@
 	}
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			/*
@@ -3636,7 +3958,7 @@
 			if((error = alGetError()) != AL_NO_ERROR)
 			{
 				ALmixer_SetError("%s",
-					aluGetErrorString(error) );
+					alGetString(error) );
 				retval = -1;
 			}
 			else
@@ -3661,7 +3983,7 @@
 
 static ALfloat Internal_GetMaxVolumeSource(ALuint source)
 {
-	Sint32 channel;
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_GetMaxVolumeChannel(-1);
@@ -3680,15 +4002,15 @@
 
 /* Set a volume regardless if it's in use or not.
  */
-static Sint32 Internal_SetMinVolumeChannel(Sint32 channel, ALfloat volume)
+static ALboolean Internal_SetMinVolumeChannel(ALint channel, ALfloat volume)
 {
 	ALenum error;
-	Sint32 retval = 0;
+	ALboolean retval = AL_TRUE;
 	
 	if(channel >= Number_of_Channels_global)
 	{
 			ALmixer_SetError("Requested channel (%d) exceeds maximum channel (%d) because only %d channels are allocated", channel, Number_of_Channels_global-1, Number_of_Channels_global);
-		return -1;
+		return AL_FALSE;
 	}
 
 	if(channel >= 0)
@@ -3707,8 +4029,8 @@
 		if((error = alGetError()) != AL_NO_ERROR)
 		{
 			ALmixer_SetError("%s",
-				aluGetErrorString(error) );
-			retval = -1;
+				alGetString(error) );
+			retval = AL_FALSE;
 		}
 		if(ALmixer_Channel_List[channel].max_volume < ALmixer_Channel_List[channel].min_volume)
 		{
@@ -3718,14 +4040,14 @@
 			if((error = alGetError()) != AL_NO_ERROR)
 			{
 				ALmixer_SetError("%s",
-					aluGetErrorString(error) );
-				retval = -1;
+					alGetString(error) );
+				retval = AL_FALSE;
 			}
 		}
 	}
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			if(volume < 0.0f)
@@ -3742,8 +4064,8 @@
 			if((error = alGetError()) != AL_NO_ERROR)
 			{
 				ALmixer_SetError("%s",
-					aluGetErrorString(error) );
-				retval = -1;
+					alGetString(error) );
+				retval = AL_FALSE;
 			}
 			if(ALmixer_Channel_List[i].max_volume < ALmixer_Channel_List[i].min_volume)
 			{
@@ -3753,8 +4075,8 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					ALmixer_SetError("%s",
-						aluGetErrorString(error) );
-					retval = -1;
+						alGetString(error) );
+					retval = AL_FALSE;
 				}
 			}
 		}
@@ -3762,9 +4084,9 @@
 	return retval;
 }
 
-static Sint32 Internal_SetMinVolumeSource(ALuint source, ALfloat volume)
-{
-	Sint32 channel;
+static ALboolean Internal_SetMinVolumeSource(ALuint source, ALfloat volume)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_SetMinVolumeChannel(-1, volume);
@@ -3774,12 +4096,12 @@
 	if(-1 == channel)
 	{
 		ALmixer_SetError("Cannot SetMaxVolume: %s", ALmixer_GetError());
-		return -1;
+		return AL_FALSE;
 	}
 	return Internal_SetMinVolumeChannel(channel, volume);
 }
 
-static ALfloat Internal_GetMinVolumeChannel(Sint32 channel)
+static ALfloat Internal_GetMinVolumeChannel(ALint channel)
 {
 	/*
 	ALfloat value;
@@ -3802,7 +4124,7 @@
 		if((error = alGetError()) != AL_NO_ERROR)
 		{
 			ALmixer_SetError("%s",
-				aluGetErrorString(error) );
+				alGetString(error) );
 			retval = -1.0f;
 		}
 		else
@@ -3815,7 +4137,7 @@
 	}
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			/*
@@ -3824,7 +4146,7 @@
 			if((error = alGetError()) != AL_NO_ERROR)
 			{
 				ALmixer_SetError("%s",
-					aluGetErrorString(error) );
+					alGetString(error) );
 				retval = -1;
 			}
 			else
@@ -3849,7 +4171,7 @@
 
 static ALfloat Internal_GetMinVolumeSource(ALuint source)
 {
-	Sint32 channel;
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_GetMinVolumeChannel(-1);
@@ -3867,17 +4189,17 @@
 
 
 /* Changes the listener volume */
-static Sint32 Internal_SetMasterVolume(ALfloat volume)
+static ALboolean Internal_SetMasterVolume(ALfloat volume)
 {
 	ALenum error;
 	alListenerf(AL_GAIN, volume);
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		ALmixer_SetError("%s",
-			aluGetErrorString(error) );
-		return -1;
-	}
-	return 0;	
+			alGetString(error) );
+		return AL_FALSE;
+	}
+	return AL_TRUE;
 }
 
 static ALfloat Internal_GetMasterVolume()
@@ -3888,7 +4210,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		ALmixer_SetError("%s",
-			aluGetErrorString(error) );
+			alGetString(error) );
 		return -1.0f;
 	}
 	return volume;	
@@ -3899,10 +4221,10 @@
 
 /* Will fade out currently playing channels.
  * It starts at the current volume level and goes down */
-static Sint32 Internal_ExpireChannel(Sint32 channel, Sint32 ticks)
-{
-	Uint32 current_time = SDL_GetTicks();
-	Uint32 counter = 0;
+static ALint Internal_ExpireChannel(ALint channel, ALint ticks)
+{
+	ALuint current_time = ALmixer_GetTicks();
+	ALuint counter = 0;
 	
 	/* We can't accept 0 as a value because of div-by-zero.
 	 * If zero, just call Halt at normal
@@ -3910,7 +4232,7 @@
 	 */
 	if(0 == ticks)
 	{
-		return Internal_HaltChannel(channel);
+		return Internal_HaltChannel(channel, AL_TRUE);
 	}
 	if(ticks < -1)
 	{
@@ -3939,7 +4261,7 @@
 	/* Else need to fade out all channels */
 	else
 	{
-		Sint32 i;
+		ALint i;
 		for(i=0; i<Number_of_Channels_global; i++)
 		{
 			if(ALmixer_Channel_List[i].channel_in_use)
@@ -3957,9 +4279,9 @@
 }
 
 
-static Sint32 Internal_ExpireSource(ALuint source, Sint32 ticks)
-{
-	Sint32 channel;
+static ALint Internal_ExpireSource(ALuint source, ALint ticks)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_ExpireChannel(-1, ticks);
@@ -3975,10 +4297,10 @@
 }
 
 
-static Sint32 Internal_QueryChannel(Sint32 channel)
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALint Internal_QueryChannel(ALint channel)
+{
+	ALint i;
+	ALint counter = 0;
 	if(channel >= Number_of_Channels_global)
 	{
 		ALmixer_SetError("Invalid channel: %d", channel);
@@ -4002,9 +4324,9 @@
 }
 
 
-static Sint32 Internal_QuerySource(ALuint source)
-{
-	Sint32 channel;
+static ALint Internal_QuerySource(ALuint source)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_QueryChannel(-1);
@@ -4021,10 +4343,10 @@
 }
 
 
-static Sint32 Internal_CountUnreservedUsedChannels()
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALuint Internal_CountUnreservedUsedChannels()
+{
+	ALint i;
+	ALuint counter = 0;
 
 
 	/* Else, return the number of channels in use */
@@ -4038,10 +4360,10 @@
 	return counter;
 }
 
-static Sint32 Internal_CountUnreservedFreeChannels()
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALuint Internal_CountUnreservedFreeChannels()
+{
+	ALint i;
+	ALuint counter = 0;
 
 
 	/* Else, return the number of channels in use */
@@ -4055,10 +4377,10 @@
 	return counter;
 }
 
-static Sint32 Internal_CountAllUsedChannels()
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALuint Internal_CountAllUsedChannels()
+{
+	ALint i;
+	ALuint counter = 0;
 
 
 	/* Else, return the number of channels in use */
@@ -4072,10 +4394,10 @@
 	return counter;
 }
 
-static Sint32 Internal_CountAllFreeChannels()
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALuint Internal_CountAllFreeChannels()
+{
+	ALint i;
+	ALuint counter = 0;
 
 
 	/* Else, return the number of channels in use */
@@ -4090,10 +4412,10 @@
 }
 
 
-static Sint32 Internal_PlayingChannel(Sint32 channel)
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALint Internal_PlayingChannel(ALint channel)
+{
+	ALint i;
+	ALint counter = 0;
 	ALint state;
 	
 	if(channel >= Number_of_Channels_global)
@@ -4137,9 +4459,9 @@
 }
 
 
-static Sint32 Internal_PlayingSource(ALuint source)
-{
-	Sint32 channel;
+static ALint Internal_PlayingSource(ALuint source)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_PlayingChannel(-1);
@@ -4156,10 +4478,10 @@
 }
 
 
-static Sint32 Internal_PausedChannel(Sint32 channel)
-{
-	Sint32 i;
-	Sint32 counter = 0;
+static ALint Internal_PausedChannel(ALint channel)
+{
+	ALint i;
+	ALint counter = 0;
 	ALint state;
 	
 	if(channel >= Number_of_Channels_global)
@@ -4203,9 +4525,9 @@
 }
 
 
-static Sint32 Internal_PausedSource(ALuint source)
-{
-	Sint32 channel;
+static ALint Internal_PausedSource(ALuint source)
+{
+	ALint channel;
 	if(0 == source)
 	{
 		return Internal_PausedChannel(-1);
@@ -4236,23 +4558,27 @@
  * when a buffer is queued, there was probably some
  * CPU intensive looping which took awhile.
  * It's mainly provided as a convenience.
- * Timing the call with SDL_GetTicks() would produce
+ * Timing the call with ALmixer_GetTicks() would produce
  * more accurate information.
  * Returns a negative value if there was an error,
  * the value being the number of errors.
  */
-static Sint32 Update_ALmixer(void* data)
-{
-	Sint32 retval = 0;
-	Sint32 error_flag = 0;
+static ALint Update_ALmixer(void* data)
+{
+	ALint retval = 0;
+	ALint error_flag = 0;
 	ALenum error;
 	ALint state;
-	Sint32 i=0;
-
-	SDL_LockMutex(simple_lock);
+	ALint i=0;
+
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	if(0 == ALmixer_Initialized)
 	{
-		SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+		SDL_UnlockMutex(s_simpleLock);
+#endif
 		return 0;
 	}
 	
@@ -4260,14 +4586,16 @@
 	/* If anything is playing, then we have to do work */
 	if( 0 == Is_Playing_global)
 	{
-		SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+		SDL_UnlockMutex(s_simpleLock);
+#endif
 		return 0;
 	}
 	/* Clear error */
 	if((error = alGetError()) != AL_NO_ERROR)
 				{
 		fprintf(stderr, "08Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-				aluGetErrorString(error));				
+				alGetString(error));				
 				}
 	alGetError();
 
@@ -4280,19 +4608,19 @@
 			 * we can check the timeout and fading values
 			 * and do the appropriate things
 			 */
-			Uint32 current_time = SDL_GetTicks();
+			ALuint current_time = ALmixer_GetTicks();
 
 			/* Check to see if we need to halt due to Timed play */
 			if(ALmixer_Channel_List[i].expire_ticks != -1) 
 			{
-				Uint32 target_time = (Uint32)ALmixer_Channel_List[i].expire_ticks 
+				ALuint target_time = (ALuint)ALmixer_Channel_List[i].expire_ticks 
 					 + ALmixer_Channel_List[i].start_time;
 				alGetSourcei(ALmixer_Channel_List[i].alsource,
 					AL_SOURCE_STATE, &state);
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "06Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-							aluGetErrorString(error));				
+							alGetString(error));				
 				}
 				
 				/* Check the time, and also make sure that it is not
@@ -4304,11 +4632,11 @@
 					&& (state != AL_PAUSED) )
 				{
 					/* Stop the playback */
-					ALmixer_HaltChannel(i);
+					Internal_HaltChannel(i, AL_TRUE);
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						fprintf(stderr, "07Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-								aluGetErrorString(error));				
+								alGetString(error));				
 					}
 					
 					/* Everything should be done so go on to the next loop */
@@ -4319,14 +4647,14 @@
 			/* Check to see if we need to adjust the volume for fading */
 			if( ALmixer_Channel_List[i].fade_enabled )
 			{
-				Uint32 target_time = ALmixer_Channel_List[i].fade_expire_ticks 
+				ALuint target_time = ALmixer_Channel_List[i].fade_expire_ticks 
 					 + ALmixer_Channel_List[i].fade_start_time;
 				alGetSourcei(ALmixer_Channel_List[i].alsource,
 					AL_SOURCE_STATE, &state);
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "05Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-							aluGetErrorString(error));				
+							alGetString(error));				
 				}
 				
 				/* Check the time, and also make sure that it is not
@@ -4337,7 +4665,7 @@
 				if(state != AL_PAUSED)
 				{
 					ALfloat t;
-					Uint32 delta_time;
+					ALuint delta_time;
 					ALfloat current_volume;
 					if(current_time >= target_time)
 					{
@@ -4370,7 +4698,7 @@
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						fprintf(stderr, "04Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-								aluGetErrorString(error));				
+								alGetString(error));				
 					}
 					
 	/*
@@ -4442,7 +4770,7 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "03Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-							aluGetErrorString(error));				
+							alGetString(error));				
 				}
 				
 					
@@ -4453,7 +4781,7 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "02Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-							aluGetErrorString(error));				
+							alGetString(error));				
 				}
 				
 				
@@ -4482,7 +4810,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "50Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 						continue;
 					}
@@ -4524,7 +4852,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							fprintf(stderr, "01Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
-									aluGetErrorString(error));				
+									alGetString(error));				
 						}
 						
 						alGetSourcei(
@@ -4534,9 +4862,9 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 		fprintf(stderr, "Error with unqueue, for OS X this is expected: %s\n",
-							aluGetErrorString(error));
+							alGetString(error));
 							ALmixer_SetError("Failed detecting unqueued predecoded buffer (expected with OS X): %s",
-								aluGetErrorString(error) );
+								alGetString(error) );
 							error_flag--;
 						}
 						if(buffers_still_queued > 0)
@@ -4565,9 +4893,9 @@
 							if((error = alGetError()) != AL_NO_ERROR)
 							{
 		fprintf(stderr, "Error with unqueue, after alSourceUnqueueBuffers, buffers_still_queued=%d, error is: %s", buffers_still_queued,
-								aluGetErrorString(error));
+								alGetString(error));
 								ALmixer_SetError("Predecoded Unqueue buffer failed: %s",
-									aluGetErrorString(error) );
+									alGetString(error) );
 								error_flag--;
 							}
 
@@ -4578,7 +4906,7 @@
 						Is_Playing_global--;
 
 						/* Launch callback */
-						Invoke_Channel_Done_Callback(i);
+						Invoke_Channel_Done_Callback(i, AL_TRUE);
 
 						/* We're done for this loop.
 						 * Go to next channel 
@@ -4631,11 +4959,15 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "51Testing error: %s\n",
-						aluGetErrorString(error));				
+						alGetString(error));				
 				}
 				/* Get the number of buffers processed
 				 * so we know if we need to refill 
 				 */
+				 /* WARNING: It looks like Snow Leopard some times crashes on this call under x86_64
+				  * typically when I suffer a lot of buffer underruns.
+				  */
+//				 fprintf(stderr, "calling AL_BUFFERS_PROCESSED on source:%d", ALmixer_Channel_List[i].alsource);
 				alGetSourcei(
 					ALmixer_Channel_List[i].alsource,
 					AL_BUFFERS_PROCESSED, &buffers_processed
@@ -4643,8 +4975,9 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "52Testing error: %s\n",
-						aluGetErrorString(error));				
+						alGetString(error));				
 				}
+//				fprintf(stderr, "finished AL_BUFFERS_PROCESSED, buffers_processed=%d", buffers_processed);
 
  /* WTF!!! The Nvidia distribution is failing on the alGetSourcei(source, AL_BUFFER, buf_id) call.
  * I need this call to figure out which buffer OpenAL is currently playing. 
@@ -4672,7 +5005,7 @@
 				if((error = alGetError()) != AL_NO_ERROR)
 				{
 					fprintf(stderr, "53Testing error: %s\n",
-						aluGetErrorString(error));				
+						alGetString(error));				
 				}
 
 				/* Before the hard stuff, check to see if the 
@@ -4701,20 +5034,20 @@
 					)
 				   )
 				{
-					Uint32 k;
-					Uint32 queue_ret_flag;
-					Uint8 is_out_of_sync = 0;
-					Uint32 my_queue_size = CircularQueueUnsignedInt_Size(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
+					ALint k;
+					ALuint queue_ret_flag;
+					ALubyte is_out_of_sync = 0;
+					ALuint my_queue_size = CircularQueueUnsignedInt_Size(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
 					/* Ugh, I have to deal with signed/unsigned mismatch here. */
 					ALint buffers_unplayed_int = buffers_still_queued - buffers_processed;
-					Uint32 unplayed_buffers;
+					ALuint unplayed_buffers;
 					if(buffers_unplayed_int < 0)
 					{
 						unplayed_buffers = 0;
 					}
 					else
 					{
-						unplayed_buffers = (Uint32)buffers_unplayed_int;
+						unplayed_buffers = (ALuint)buffers_unplayed_int;
 					}
 /*
 					fprintf(stderr, "Queue in processed check, before pop, buffers_processed=%d\n", buffers_processed);
@@ -4744,19 +5077,16 @@
 					fprintf(stderr, "inside, Buffers processed=%d, Buffers queued=%d, my queue=%d\n",
 							buffers_processed, buffers_still_queued, my_queue_size);
 					#endif	
-					if(my_queue_size > unplayed_buffers)
+					is_out_of_sync = 1;
+					for(k=0; k<buffers_processed; k++)
 					{
-						is_out_of_sync = 1;
-						for(k=0; k<(my_queue_size - unplayed_buffers); k++)
+						queue_ret_flag = CircularQueueUnsignedInt_PopFront(
+							ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
+						if(0 == queue_ret_flag)
 						{
-							queue_ret_flag = CircularQueueUnsignedInt_PopFront(
-								ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
-							if(0 == queue_ret_flag)
-							{
-								fprintf(stderr, "53 Error popping queue\n");
-							}
-						}						
-					}
+							fprintf(stderr, "53 Error popping queue\n");
+						}
+					}		
 					my_queue_size = CircularQueueUnsignedInt_Size(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
 					/* We have several possibilities we need to handle:
 					 * 1) We are in an initial state or underrun and need to do a data callback on the head.
@@ -4846,7 +5176,7 @@
 				 */
 				if( ! ALmixer_Channel_List[i].almixer_data->eof)
 				{
-					Uint32 bytes_returned;
+					ALuint bytes_returned;
 					/* We have a priority. We first must assign
 					 * unused buffers in reserve. If there is nothing
 					 * left, then we may unqueue buffers. We can't
@@ -4889,9 +5219,9 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 				fprintf(stderr, "Error with unqueue: %s",
-							aluGetErrorString(error));
+							alGetString(error));
 							ALmixer_SetError("Unqueue buffer failed: %s",
-								aluGetErrorString(error) );
+								alGetString(error) );
 							error_flag--;
 						}
 /*
@@ -4910,7 +5240,9 @@
 					{
 						/* Might want to check state */
 						/* In case the playback stopped,
-						 * we need to resume */
+						 * we need to resume 
+						 * a.k.a. buffer underrun
+						 */
 						#if 1 
 						/* Try not refetching the state here because I'm getting a duplicate
 						 buffer playback (hiccup) */
@@ -4921,7 +5253,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							fprintf(stderr, "54bTesting error: %s\n",
-								aluGetErrorString(error));				
+								alGetString(error));				
 						}
 						/* Get the number of buffers processed
 						 */
@@ -4933,7 +5265,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							fprintf(stderr, "54cError, Can't get buffers_processed: %s\n",
-								aluGetErrorString(error));				
+								alGetString(error));				
 						}
 #endif
 						if(AL_STOPPED == state)
@@ -4958,10 +5290,10 @@
 							 * to play.
 							 */
 							ALint temp_count;
-/*							
-							fprintf(stderr, "STOPPED1, need to clear processed, status is:\n");
+#if 0
+							fprintf(stderr, "STOPPED1, need to clear processed=%d, status is:\n", buffers_processed);
 							PrintQueueStatus(ALmixer_Channel_List[i].alsource);
-*/
+#endif
 							for(temp_count=0; temp_count<buffers_processed; temp_count++)
 							{
 								alSourceUnqueueBuffers(
@@ -4971,20 +5303,95 @@
 								if((error = alGetError()) != AL_NO_ERROR)
 								{
 									fprintf(stderr, "55aTesting error: %s\n",
-										aluGetErrorString(error));				
+										alGetString(error));				
 									error_flag--;
 								}
 							}
-/*
+#if 0
 							fprintf(stderr, "After unqueue clear...:\n");
 							PrintQueueStatus(ALmixer_Channel_List[i].alsource);
-*/
-							alSourcePlay(ALmixer_Channel_List[i].alsource);
+#endif						
+							/* My assertion: We are STOPPED but not EOF.
+							 * This means we have a buffer underrun.
+							 * We just cleared out the unqueued buffers.
+							 * So we need to reset the mixer_data to reflect we have
+							 * no buffers in queue.
+							 * We need to GetMoreData and then queue up the data.
+							 * Then we need to resume playing.
+							 */
+#if 0
+							int buffers_queued;
+							alGetSourcei(
+										 ALmixer_Channel_List[i].alsource,
+										 AL_BUFFERS_QUEUED, 
+										 &buffers_queued
+										 );
+							
 							if((error = alGetError()) != AL_NO_ERROR)
 							{
-								fprintf(stderr, "55Tbesting error: %s\n",
-									aluGetErrorString(error));				
+								fprintf(stderr, "Error in PrintQueueStatus, Can't get buffers_queued: %s\n",
+										alGetString(error));				
+							} 
+							assert(buffers_queued == 0);
+							fprintf(stderr, "buffer underrun: buffers_queued:%d\n", buffers_queued);
+#endif
+
+							/* Reset the number of buffers in use to 0 */
+							ALmixer_Channel_List[i].almixer_data->num_buffers_in_use = 0;
+
+							/* Get more data and put it in the first buffer */
+							bytes_returned = GetMoreData(
+								ALmixer_Channel_List[i].almixer_data,
+								ALmixer_Channel_List[i].almixer_data->buffer[0]
+							);
+							/* NOTE: We might want to look for EOF and handle it here.
+							 * Currently, I just let the next loop handle it which seems to be working.
+							 */
+							if(bytes_returned > 0)
+							{
+								/* Queue up the new data */
+								alSourceQueueBuffers(
+													 ALmixer_Channel_List[i].alsource,
+													 1, 
+													 &ALmixer_Channel_List[i].almixer_data->buffer[0]
+								);
+								if((error = alGetError()) != AL_NO_ERROR)
+								{
+									fprintf(stderr, "56e alSourceQueueBuffers error: %s\n",
+											alGetString(error));				
+								}
+								/* Increment the number of buffers in use */
+								ALmixer_Channel_List[i].almixer_data->num_buffers_in_use++;
+								
+
+								/* We need to empty and update the circular buffer queue if it is in use */
+								if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL)
+								{
+									ALuint queue_ret_flag;
+									CircularQueueUnsignedInt_Clear(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
+									queue_ret_flag = CircularQueueUnsignedInt_PushBack(
+																					   ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, 
+																					   ALmixer_Channel_List[i].almixer_data->buffer[0]
+																					   );	
+									if(0 == queue_ret_flag)
+									{
+										fprintf(stderr, "56fSerious internal error: CircularQueue could not push into queue.\n");
+										ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue");
+									}
+								}
+								
+								
+
+
+								/* Resume playback from underrun */
+								alSourcePlay(ALmixer_Channel_List[i].alsource);
+								if((error = alGetError()) != AL_NO_ERROR)
+								{
+									fprintf(stderr, "55Tbesting error: %s\n",
+										alGetString(error));				
+								}
 							}
+
 						}
 						/* Let's escape to the next loop.
 						 * All code below this point is for queuing up 
@@ -5002,7 +5409,7 @@
 					 * Let's check it to make sure it's okay,
 					 * and then queue it up
 					 */
-					/* This check doesn't work anymore because it is now Uint32 */
+					/* This check doesn't work anymore because it is now ALuint */
 				#if 0
 					if(-1 == bytes_returned)
 					{
@@ -5151,7 +5558,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							fprintf(stderr, "56Testing error: %s\n",
-								aluGetErrorString(error));				
+								alGetString(error));				
 						}
 						/* This is part of the hideous Nvidia workaround. In order to figure out
 						 * which buffer to show during callbacks (for things like
@@ -5161,7 +5568,8 @@
 						 */
 						if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL)
 						{
-							Uint32 queue_ret_flag;
+							ALuint queue_ret_flag;
+//				fprintf(stderr, "56d: CircularQueue_PushBack.\n");
 							queue_ret_flag = CircularQueueUnsignedInt_PushBack(
 								ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, 
 								ALmixer_Channel_List[i].almixer_data->buffer[ALmixer_Channel_List[i].almixer_data->num_buffers_in_use]
@@ -5196,7 +5604,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							ALmixer_SetError("Could not QueueBuffer: %s",
-								aluGetErrorString(error) );
+								alGetString(error) );
 							error_flag--;
 							continue;
 						}
@@ -5208,7 +5616,8 @@
 						 */
 						if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL)
 						{
-							Uint32 queue_ret_flag;
+							ALuint queue_ret_flag;
+//				fprintf(stderr, "56e: CircularQueue_PushBack.\n");
 							queue_ret_flag = CircularQueueUnsignedInt_PushBack(
 								ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, 
 								unqueued_buffer_id
@@ -5218,12 +5627,12 @@
 								fprintf(stderr, "56bSerious internal error: CircularQueue could not push into queue.\n");
 								ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue");
 							}
-							/*
+#if 0
 							else
 							{
 								CircularQueueUnsignedInt_Print(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue);
 							}
-							 */
+#endif
 						}
 					}
 					/* If we used an available buffer queue,
@@ -5248,7 +5657,7 @@
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						fprintf(stderr, "57bTesting error: %s\n",
-							aluGetErrorString(error));				
+							alGetString(error));				
 					}
 					/* Get the number of buffers processed
 					 */
@@ -5260,7 +5669,7 @@
 					if((error = alGetError()) != AL_NO_ERROR)
 					{
 						fprintf(stderr, "57cError, Can't get buffers_processed: %s\n",
-							aluGetErrorString(error));				
+							alGetString(error));				
 					}
 					#endif
 					if(AL_STOPPED == state)
@@ -5300,7 +5709,7 @@
 								if((error = alGetError()) != AL_NO_ERROR)
 								{
 									fprintf(stderr, "58aTesting error: %s\n",
-										aluGetErrorString(error));				
+										alGetString(error));				
 									error_flag--;
 								}
 							}
@@ -5313,7 +5722,7 @@
 							if((error = alGetError()) != AL_NO_ERROR)
 							{
 								fprintf(stderr, "55Tbesting 8rror: %s\n",
-									aluGetErrorString(error));				
+									alGetString(error));				
 							}
 					}
 					continue;
@@ -5331,7 +5740,7 @@
 					 * buffers as they come in. */
 					if(buffers_processed > 0)
 					{
-						Sint32 temp_count;
+						ALint temp_count;
 						/* Do as a for-loop because I don't want
 						 * to have to create an array for the 
 						 * unqueued_buffer_id's
@@ -5346,7 +5755,7 @@
 							if((error = alGetError()) != AL_NO_ERROR)
 							{
 								fprintf(stderr, "59Testing error: %s\n",
-										aluGetErrorString(error));				
+										alGetString(error));				
 							}
 						}
 						fprintf(stderr, "done unqueuing remainder for this loop, %d\n", temp_count);
@@ -5362,7 +5771,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							fprintf(stderr, "5100Testing error: %s\n",
-									aluGetErrorString(error));				
+									alGetString(error));				
 						}
 						/* Get the number of buffers processed
 							* so we know if we need to refill 
@@ -5374,7 +5783,7 @@
 						if((error = alGetError()) != AL_NO_ERROR)
 						{
 							fprintf(stderr, "5200Testing error: %s\n",
-									aluGetErrorString(error));				
+									alGetString(error));				
 						}
 					}
 
@@ -5399,7 +5808,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "60Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 						if(AL_STOPPED == state)
 						{
@@ -5414,7 +5823,7 @@
 							Is_Playing_global--;
 	
 							/* Launch callback */
-							Invoke_Channel_Done_Callback(i);
+							Invoke_Channel_Done_Callback(i, AL_TRUE);
 	
 							/* We're done for this loop.
 							 * Go to next channel 
@@ -5436,7 +5845,7 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "61Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 						if(AL_STOPPED == state)
 						{
@@ -5473,11 +5882,13 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "62Testing error: %s\n",
-			aluGetErrorString(error));				
-	}
-#endif
-
-	SDL_UnlockMutex(simple_lock);
+			alGetString(error));				
+	}
+#endif
+
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	/* Return the number of errors */
 	if(error_flag < 0) 
 	{
@@ -5489,7 +5900,7 @@
 
 #ifdef ENABLE_PARANOID_SIGNEDNESS_CHECK
 /* This is only here so we can call SDL_OpenAudio() */
-static void my_dummy_audio_callback(void* userdata, Uint8* stream, int len)
+static void my_dummy_audio_callback(void* userdata, ALbyte* stream, int len)
 {
 }
 #endif
@@ -5509,7 +5920,7 @@
 
 static int Stream_Data_Thread_Callback(void* data)
 {
-	Sint32 retval;
+	ALint retval;
 	
 	while(ALmixer_Initialized)
 	{
@@ -5525,12 +5936,12 @@
 			/* Make sure times are multiples of 10
 			 * for optimal performance and accuracy in Linux
 			 */
-			SDL_Delay(10);
+			ALmixer_Delay(10);
 		}
 		else
 		{
 			/* should I also be sleeping/yielding here? */
-			SDL_Delay(0);
+			ALmixer_Delay(0);
 		}
 	}
 fprintf(stderr, "Thread is closing\n");
@@ -5539,19 +5950,20 @@
 #endif /* End of ENABLE_ALMIXER_THREADS */
 
 
-/* Using -1 on error and 0 on success to follow SDL/SDL_mixer conventions,
- * though I actually prefer 0/1 conventions (SDL_Sound/OpenAL/GL).
+/* SDL/SDL_mixer returns -1 on error and 0 on success.
+ * I actually prefer false/true conventions (SDL_Sound/OpenAL/GL)
+ * so SDL_mixer porting people beware.
  * Warning: SDL_QuitSubSystem(SDL_INIT_AUDIO) is called which
  * means the SDL audio system will be disabled. It will not
  * be restored (in case SDL is not actually being used) so
  * the user will need to restart it if they need it after
  * OpenAL shuts down.
  */
-Sint32 ALmixer_Init(Uint32 frequency, Sint32 num_sources, Uint32 refresh)
+ALboolean ALmixer_Init(ALuint frequency, ALint num_sources, ALuint refresh)
 {
 	ALCdevice* dev;
 	ALCcontext* context;
-	Sint32 i;
+	ALint i;
 	ALenum error;
 	ALuint* source;
 
@@ -5624,6 +6036,7 @@
 	 * want it in the list so I can get the OpenAL defaults
 	 */
 	ALint attrlist[7];
+	ALsizei current_attrlist_index = 0;
 
 #ifdef ENABLE_PARANOID_SIGNEDNESS_CHECK
 	/* More problems: I'm getting bit by endian/signedness issues on
@@ -5654,12 +6067,10 @@
 #endif
 
 
-
-
 	/* Make sure ALmixer isn't already initialized */
 	if(ALmixer_Initialized)
 	{
-		return -1;
+		return AL_FALSE;
 	}
 #ifdef USING_LOKI_AL_DIST
 fprintf(stderr, "Found Loki dist\n");
@@ -5670,7 +6081,31 @@
 fprintf(stderr, "Found Nvidia dist\n");
 #endif
 
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	ALmixer_InitTime();
+
+	/* Note: The pool may have been created on previous Init's */
+	/* I leave the pool allocated allocated in case the user wants
+	 * to read the pool in case of a failure (such as in this function).
+	 * This is not actually a leak.
+	 */
+	if(NULL == s_ALmixerErrorPool)
+	{
+		s_ALmixerErrorPool = TError_CreateErrorPool();
+	}
+	if(NULL == s_ALmixerErrorPool)
+	{
+		return AL_FALSE;
+	}
+		fprintf(stderr, "tError Test0\n");
+		ALmixer_SetError("Initing (and testing SetError)");
+		fprintf(stderr, "tError Test1: %s\n", ALmixer_GetError());
+		fprintf(stderr, "tError Test2: %s\n", ALmixer_GetError());
+#endif
+
+
 	/* Set the defaults */
+/*
 	attrlist[0] = ALC_FREQUENCY;
 	attrlist[1] = ALMIXER_DEFAULT_FREQUENCY;
 	attrlist[2] = ALC_SYNC;
@@ -5679,45 +6114,43 @@
 #else
 	attrlist[3] = ALC_FALSE;
 #endif
-	
+*/	
 	/* Set frequency value if it is not 0 */
 	if(0 != frequency)
 	{
-		attrlist[1] = (ALint)frequency;
-	}
+		attrlist[current_attrlist_index] = ALC_FREQUENCY;
+		current_attrlist_index++;
+		attrlist[current_attrlist_index] = (ALint)frequency;
+		current_attrlist_index++;
+	}
+
+#ifdef ENABLE_ALMIXER_ALC_SYNC	
+		attrlist[current_attrlist_index] = ALC_SYNC;
+		current_attrlist_index++;
+		attrlist[current_attrlist_index] = ALC_TRUE;
+		current_attrlist_index++;
+#endif
 
 	/* If the user specifies a refresh value,
 	 * make room for it 
 	 */
 	if(0 != refresh)
 	{
-		attrlist[4] = (ALint)ALC_REFRESH;
-		attrlist[5] = refresh;
-		attrlist[6] = '\0';
-	}
-	/* Terminate the list without any refresh values */
-	else
-	{
-		attrlist[4] = '\0';
+		attrlist[current_attrlist_index] = (ALint)ALC_REFRESH;
+		current_attrlist_index++;
+		attrlist[current_attrlist_index] = refresh;
+		current_attrlist_index++;		
 	}
 			
-	/* It looks like OpenAL won't let us ask it what 
-	 * the set frequency is, so we need to save our
-	 * own copy. Yuck.
-	 * Update: J. Valenzuela just updated the Loki 
-	 * dist (2003/01/02) to handle this.
-	 * The demo is in testattrib.c. However, this
-	 * looks kind of cumbersome to parse, and I've
-	 * already put this in my code, so I guess I'll 
-	 * leave it for now.
-	 */
-	ALmixer_Frequency_global = attrlist[1];
-	
+	/* End attribute list */
+	attrlist[current_attrlist_index] = '\0';
+
+
 	/* Initialize SDL_Sound */
 	if(! Sound_Init() )
 	{
 		ALmixer_SetError(Sound_GetError());
-		return -1;
+		return AL_FALSE;
 	}
 #ifdef ENABLE_PARANOID_SIGNEDNESS_CHECK
 	/* Here is the paranoid check that opens
@@ -5760,6 +6193,8 @@
 		SIGN_TYPE_8_BIT_FORMAT = AUDIO_S8;
 	}
 #endif
+
+#ifndef ALMIXER_COMPILE_WITHOUT_SDL
 	/* Weirdness: It seems that SDL_Init(SDL_INIT_AUDIO)
 	 * causes OpenAL and SMPEG to conflict. For some reason
 	 * if SDL_Init on audio is active, then all the SMPEG
@@ -5770,7 +6205,8 @@
 	 * SDL_Sound::Init call and hope it doesn't break SDL_Sound.
 	 */
 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
-	
+#endif
+
 	/* I'm told NULL will call the default string
 	 * and hopefully do the right thing for each platform 
 	 */
@@ -5796,15 +6232,26 @@
 	if(NULL == dev)
 	{
 		ALmixer_SetError("Cannot open sound device for OpenAL");
-		return -1;
-	}
+		return AL_FALSE;
+	}
+
+#ifdef __APPLE__
+	/* The ALC_FREQUENCY attribute is ignored with Apple's implementation. */
+	/* This extension must be called before the context is created. */
+	if(0 != frequency)
+	{
+		Internal_alcMacOSXMixerOutputRate((ALdouble)frequency);
+	}
+	ALmixer_Frequency_global = (ALuint)Internal_alcMacOSXGetMixerOutputRate();
+		fprintf(stderr, "Internal_alcMacOSXMixerOutputRate is: %lf", Internal_alcMacOSXGetMixerOutputRate());
+#endif
 	
 	context = alcCreateContext(dev, attrlist);
 	if(NULL == context)
 	{
 		ALmixer_SetError("Cannot create a context OpenAL");
 		alcCloseDevice(dev);
-		return -1;
+		return AL_FALSE;
 	}
 	fprintf(stderr, "Context checking...\n");
 
@@ -5826,10 +6273,25 @@
 		ALmixer_SetError("Could not MakeContextCurrent");
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
-		return -1;
-	}
-	
-	
+		return AL_FALSE;
+	}
+	
+	/* It looks like OpenAL won't let us ask it what 
+	 * the set frequency is, so we need to save our
+	 * own copy. Yuck.
+	 * Update: J. Valenzuela just updated the Loki 
+	 * dist (2003/01/02) to handle this.
+	 * The demo is in testattrib.c. 
+	 */
+/*
+	ALmixer_Frequency_global = frequency;
+*/
+#ifndef __APPLE__
+	alcGetIntegerv(dev, ALC_FREQUENCY, 1, &ALmixer_Frequency_global);
+	fprintf(stderr, "alcGetIntegerv ALC_FREQUENCY is: %d", ALmixer_Frequency_global);
+#endif
+	
+
 #if 0
 	/* OSX is failing on alcMakeContextCurrent(). Try checking it first? */
 	if(alcGetCurrentContext() != context)
@@ -5850,7 +6312,7 @@
 			ALmixer_SetError("Could not MakeContextCurrent");
 			alcDestroyContext(context);
 			alcCloseDevice(dev);
-			return -1;
+			return AL_FALSE;
 		}
 	}
 #endif
@@ -5873,7 +6335,23 @@
 	 *	calls to alBufferData().
 	 */	
 #ifdef __APPLE__
-	alEnable(ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING);
+/*
+	#if (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1)
+
+	#else
+	#endif
+*/
+	ALenum convert_data_enum = alcGetEnumValue(dev, "ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING");
+	fprintf(stderr, "ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING=0x%x", convert_data_enum);
+	if(0 != convert_data_enum)
+	{
+		alEnable(convert_data_enum);		
+	}
+	if( (AL_NO_ERROR != alGetError()) )
+	{
+		ALmixer_SetError("ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING attempted but failed");
+	}
+	
 #endif
 	
 
@@ -5906,7 +6384,7 @@
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 
 	/* Allocate memory for the list of sources that map to the channels */
@@ -5919,7 +6397,7 @@
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 
 	/* Create array that will hold the sources */
@@ -5933,7 +6411,7 @@
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}	
 
 	/* Clear the error state */
@@ -5942,14 +6420,14 @@
 	alGenSources(Number_of_Channels_global, source);
 	if( (error=alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("Couldn't generate sources: %s\n", aluGetErrorString(error));
+		ALmixer_SetError("Couldn't generate sources: %s\n", alGetString(error));
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 	
 	/* Initialize each channel and associate one source to one channel */
@@ -5988,9 +6466,11 @@
 		fprintf(stderr, "Source: %d, Channel: %d\n", Source_Map_List[i].source, Source_Map_List[i].channel);
 	}
 	fprintf(stderr, "\n");
-	
-	simple_lock = SDL_CreateMutex();
-	if(NULL == simple_lock)
+	ALmixer_OutputDecoders();
+
+#ifdef ENABLE_ALMIXER_THREADS
+	s_simpleLock = SDL_CreateMutex();
+	if(NULL == s_simpleLock)
 	{
 		/* SDL sets the error message already? */
 		free(source);
@@ -6000,16 +6480,15 @@
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 		
 
-#ifdef ENABLE_ALMIXER_THREADS
 	Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL);
 	if(NULL == Stream_Thread_global)
 	{
 		/* SDL sets the error message already? */
-		SDL_DestroyMutex(simple_lock);
+		SDL_DestroyMutex(s_simpleLock);
 		free(source);
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
@@ -6017,7 +6496,7 @@
 		alcCloseDevice(dev);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 		
 	fprintf(stderr, "Using threads\n");
@@ -6027,11 +6506,11 @@
 	 * are connected to channels
 	 */
 	free(source);
-	return 0;
-}
-
-	
-Sint32 ALmixer_Init_Context(Uint32 frequency, Uint32 refresh)
+	return AL_TRUE;
+}
+
+	
+ALboolean ALmixer_InitContext(ALuint frequency, ALuint refresh)
 {
 	ALCdevice* dev;
 	ALCcontext* context;
@@ -6106,6 +6585,7 @@
 	 * want it in the list so I can get the OpenAL defaults
 	 */
 	ALint attrlist[7];
+	ALsizei current_attrlist_index = 0;
 
 #ifdef ENABLE_PARANOID_SIGNEDNESS_CHECK
 	/* More problems: I'm getting bit by endian/signedness issues on
@@ -6141,7 +6621,7 @@
 	/* Make sure ALmixer isn't already initialized */
 	if(ALmixer_Initialized)
 	{
-		return -1;
+		return AL_FALSE;
 	}
 #ifdef USING_LOKI_AL_DIST
 fprintf(stderr, "Found Loki dist\n");
@@ -6161,45 +6641,43 @@
 #else
 	attrlist[3] = ALC_FALSE;
 #endif
-	
 	/* Set frequency value if it is not 0 */
 	if(0 != frequency)
 	{
-		attrlist[1] = (ALint)frequency;
-	}
+		attrlist[current_attrlist_index] = ALC_FREQUENCY;
+		current_attrlist_index++;
+		attrlist[current_attrlist_index] = (ALint)frequency;
+		current_attrlist_index++;
+	}
+
+#ifdef ENABLE_ALMIXER_ALC_SYNC	
+		attrlist[current_attrlist_index] = ALC_SYNC;
+		current_attrlist_index++;
+		attrlist[current_attrlist_index] = ALC_TRUE;
+		current_attrlist_index++;
+#endif
 
 	/* If the user specifies a refresh value,
 	 * make room for it 
 	 */
 	if(0 != refresh)
 	{
-		attrlist[4] = (ALint)ALC_REFRESH;
-		attrlist[5] = refresh;
-		attrlist[6] = '\0';
-	}
-	/* Terminate the list without any refresh values */
-	else
-	{
-		attrlist[4] = '\0';
+		attrlist[current_attrlist_index] = (ALint)ALC_REFRESH;
+		current_attrlist_index++;
+		attrlist[current_attrlist_index] = refresh;
+		current_attrlist_index++;		
 	}
 			
-	/* It looks like OpenAL won't let us ask it what 
-	 * the set frequency is, so we need to save our
-	 * own copy. Yuck.
-	 * Update: J. Valenzuela just updated the Loki 
-	 * dist (2003/01/02) to handle this.
-	 * The demo is in testattrib.c. However, this
-	 * looks kind of cumbersome to parse, and I've
-	 * already put this in my code, so I guess I'll 
-	 * leave it for now.
-	 */
-	ALmixer_Frequency_global = attrlist[1];
-	
+	/* End attribute list */
+	attrlist[current_attrlist_index] = '\0';
+
+
+
 	/* Initialize SDL_Sound */
 	if(! Sound_Init() )
 	{
 		ALmixer_SetError(Sound_GetError());
-		return -1;
+		return AL_FALSE;
 	}
 #ifdef ENABLE_PARANOID_SIGNEDNESS_CHECK
 	/* Here is the paranoid check that opens
@@ -6242,6 +6720,8 @@
 		SIGN_TYPE_8_BIT_FORMAT = AUDIO_S8;
 	}
 #endif
+
+#ifndef ALMIXER_COMPILE_WITHOUT_SDL
 	/* Weirdness: It seems that SDL_Init(SDL_INIT_AUDIO)
 	 * causes OpenAL and SMPEG to conflict. For some reason
 	 * if SDL_Init on audio is active, then all the SMPEG
@@ -6252,7 +6732,8 @@
 	 * SDL_Sound::Init call and hope it doesn't break SDL_Sound.
 	 */
 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
-	
+#endif
+
 	/* I'm told NULL will call the default string
 	 * and hopefully do the right thing for each platform 
 	 */
@@ -6278,15 +6759,27 @@
 	if(NULL == dev)
 	{
 		ALmixer_SetError("Cannot open sound device for OpenAL");
-		return -1;
-	}
+		return AL_FALSE;
+	}
+
+#ifdef __APPLE__
+	/* The ALC_FREQUENCY attribute is ignored with Apple's implementation. */
+	/* This extension must be called before the context is created. */
+	if(0 != frequency)
+	{
+		Internal_alcMacOSXMixerOutputRate((ALdouble)frequency);
+	}
+	ALmixer_Frequency_global = (ALuint)Internal_alcMacOSXGetMixerOutputRate();
+		fprintf(stderr, "Internal_alcMacOSXMixerOutputRate is: %lf", Internal_alcMacOSXGetMixerOutputRate());
+#endif
+	
 	
 	context = alcCreateContext(dev, attrlist);
 	if(NULL == context)
 	{
 		ALmixer_SetError("Cannot create a context OpenAL");
 		alcCloseDevice(dev);
-		return -1;
+		return AL_FALSE;
 	}
 
 
@@ -6307,7 +6800,7 @@
 		ALmixer_SetError("Could not MakeContextCurrent");
 		alcDestroyContext(context);
 		alcCloseDevice(dev);
-		return -1;
+		return AL_FALSE;
 	}
 
 
@@ -6331,11 +6824,24 @@
 			ALmixer_SetError("Could not MakeContextCurrent");
 			alcDestroyContext(context);
 			alcCloseDevice(dev);
-			return -1;
-		}
-
-	}
-#endif
+			return AL_FALSE;
+		}
+
+	}
+#endif
+		
+	/* It looks like OpenAL won't let us ask it what 
+	 * the set frequency is, so we need to save our
+	 * own copy. Yuck.
+	 * Update: J. Valenzuela just updated the Loki 
+	 * dist (2003/01/02) to handle this.
+	 * The demo is in testattrib.c. 
+	 */
+#ifndef __APPLE__
+	alcGetIntegerv(dev, ALC_FREQUENCY, 1, &ALmixer_Frequency_global);
+	fprintf(stderr, "alcGetIntegerv ALC_FREQUENCY is: %d", ALmixer_Frequency_global);
+#endif
+	
 
 	fprintf(stderr, "done Context\n");
 
@@ -6354,22 +6860,62 @@
 	 *	calls to alBufferData().
 	 */	
 #ifdef __APPLE__
-	alEnable(ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING);
-#endif
-	
-	return 0;
-}
-
-	
-Sint32 ALmixer_Init_Mixer(Sint32 num_sources)
+	/*
+	 #if (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1)
+	 
+	 #else
+	 #endif
+	 */
+	ALenum convert_data_enum = alcGetEnumValue(dev, "ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING");
+	fprintf(stderr, "ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING=0x%x", convert_data_enum);
+	if(0 != convert_data_enum)
+	{
+		alEnable(convert_data_enum);		
+	}
+	if( (AL_NO_ERROR != alGetError()) )
+	{
+		ALmixer_SetError("ALC_MAC_OSX_CONVERT_DATA_UPON_LOADING attempted but failed");
+	}
+#endif
+	
+	return AL_TRUE;
+}
+
+	
+ALboolean ALmixer_InitMixer(ALint num_sources)
 {	
-	Sint32 i;
+	ALint i;
 	ALenum error;
 	ALuint* source;
 
 
 	ALmixer_Initialized = 1;
 
+
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	ALmixer_InitTime();
+
+	/* Note: The pool may have been created on previous Init's */
+	/* I leave the pool allocated allocated in case the user wants
+	 * to read the pool in case of a failure (such as in this function).
+	 * This is not actually a leak.
+	 */
+	if(NULL == s_ALmixerErrorPool)
+	{
+		s_ALmixerErrorPool = TError_CreateErrorPool();
+	}
+	if(NULL == s_ALmixerErrorPool)
+	{
+		return AL_FALSE;
+	}
+	/*
+		fprintf(stderr, "tError Test0\n");
+		ALmixer_SetError("Initing (and testing SetError)");
+		fprintf(stderr, "tError Test1: %s\n", ALmixer_GetError());
+		fprintf(stderr, "tError Test2: %s\n", ALmixer_GetError());
+	 */
+#endif
+
 	if(num_sources <= 0)
 	{
 		Number_of_Channels_global = ALMIXER_DEFAULT_NUM_CHANNELS;
@@ -6393,7 +6939,7 @@
 		ALmixer_SetError("Out of Memory for Channel List");
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 
 	/* Allocate memory for the list of sources that map to the channels */
@@ -6404,7 +6950,7 @@
 		free(ALmixer_Channel_List);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 
 	/* Create array that will hold the sources */
@@ -6416,7 +6962,7 @@
 		free(ALmixer_Channel_List);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}	
 
 	/* Clear the error state */
@@ -6425,12 +6971,12 @@
 	alGenSources(Number_of_Channels_global, source);
 	if( (error=alGetError()) != AL_NO_ERROR)
 	{
-		ALmixer_SetError("Couldn't generate sources: %s\n", aluGetErrorString(error));
+		ALmixer_SetError("Couldn't generate sources: %s\n", alGetString(error));
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 	
 	/* Initialize each channel and associate one source to one channel */
@@ -6465,8 +7011,11 @@
 	}
 	fprintf(stderr, "\n");
 	
-	simple_lock = SDL_CreateMutex();
-	if(NULL == simple_lock)
+	
+	
+#ifdef ENABLE_ALMIXER_THREADS
+	s_simpleLock = SDL_CreateMutex();
+	if(NULL == s_simpleLock)
 	{
 		/* SDL sets the error message already? */
 		free(source);
@@ -6474,22 +7023,21 @@
 		free(Source_Map_List);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 		
 
-#ifdef ENABLE_ALMIXER_THREADS
 	Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL);
 	if(NULL == Stream_Thread_global)
 	{
 		/* SDL sets the error message already? */
-		SDL_DestroyMutex(simple_lock);
+		SDL_DestroyMutex(s_simpleLock);
 		free(source);
 		free(ALmixer_Channel_List);
 		free(Source_Map_List);
 		ALmixer_Initialized = 0;
 		Number_of_Channels_global = 0;
-		return -1;
+		return AL_FALSE;
 	}
 		
 	fprintf(stderr, "Using threads\n");
@@ -6499,7 +7047,7 @@
 	 * are connected to channels
 	 */
 	free(source);
-	return 0;
+	return AL_TRUE;
 }
 
 
@@ -6511,29 +7059,29 @@
 {
 	ALCcontext* context;
 	ALCdevice* dev;
-	Sint32 i;
+	ALint i;
 	
 	if( ! ALmixer_Initialized)
 	{
 		return;
 	}
-
-	SDL_LockMutex(simple_lock);
-	
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	/* Shutdown everything before closing context */
 	fprintf(stderr, "Halting channels\n");
-	Internal_HaltChannel(-1);
+	Internal_HaltChannel(-1, AL_FALSE);
 	
 	/* This flag will cause the thread to terminate */
 	ALmixer_Initialized = 0;
-	SDL_UnlockMutex(simple_lock);
 #ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
 	fprintf(stderr, "Closing thread\n");
 	SDL_WaitThread(Stream_Thread_global, NULL);
-#endif
 
 	fprintf(stderr, "Destroying mutex\n");
-	SDL_DestroyMutex(simple_lock);
+	SDL_DestroyMutex(s_simpleLock);
+#endif
 
 	fprintf(stderr, "Deleting OpenAL sources\n");
 	/* Delete all the OpenAL sources */
@@ -6570,32 +7118,73 @@
 	
 	Sound_Quit();
 
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	/* Remember: ALmixer_SetError/GetError calls will not work while this is gone. */
+	TError_FreeErrorPool(s_ALmixerErrorPool);
+	s_ALmixerErrorPool = NULL;
+#endif
 	return;
 }
 
-SDL_bool ALmixer_IsInitialized()
+ALboolean ALmixer_IsInitialized()
 {
 	return ALmixer_Initialized;
 }
 
-Uint32 ALmixer_GetFrequency()
+ALuint ALmixer_GetFrequency()
 {
 	return ALmixer_Frequency_global;
 }
 
-const SDL_version* ALmixer_Linked_Version()
-{
-	static SDL_version linked_mixver;
-	ALMIXER_VERSION(&linked_mixver);
+const ALmixer_version* ALmixer_GetLinkedVersion()
+{
+	static ALmixer_version linked_mixver;
+	ALMIXER_GET_COMPILED_VERSION(&linked_mixver);
 	return(&linked_mixver);
 }
 
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+
+const char* ALmixer_GetError()
+{
+	const char* error_string = NULL;
+	if(NULL == s_ALmixerErrorPool)
+	{
+		return "Error: You should not call ALmixer_GetError while ALmixer is not initialized";
+	}
+	error_string = TError_GetLastErrorStr(s_ALmixerErrorPool);
+	/* SDL returns empty strings instead of NULL */
+	if(NULL == error_string)
+	{
+		return "";
+	}
+	else
+	{
+		return error_string;
+	}
+}
+
+void ALmixer_SetError(const char* err_str, ...)
+{
+	if(NULL == s_ALmixerErrorPool)
+	{
+		fprintf(stderr, "Error: You should not call ALmixer_SetError while ALmixer is not initialized\n");
+		return;
+	}
+	va_list argp;
+	va_start(argp, err_str);
+	// SDL_SetError which I'm emulating has no number parameter.
+	TError_SetErrorv(s_ALmixerErrorPool, 1, err_str, argp);
+	va_end(argp);
+}
+
+#endif
 
 
 
 
 #if 0
-void ALmixer_Output_Attributes()
+void ALmixer_OutputAttributes()
 {
 	ALint num_flags = 0;
 	ALint* flags = 0;
@@ -6628,7 +7217,7 @@
 #endif
 
 
-void ALmixer_Output_Decoders()
+void ALmixer_OutputDecoders()
 {
 	Sound_Version sound_compile_version;
 	Sound_Version sound_link_version;
@@ -6673,10 +7262,10 @@
 	fprintf(stream, "\n");
 } 
 
-void ALmixer_Output_OpenAL_Info()
-{
-	SDL_version mixer_compile_version;
-	const SDL_version * mixer_link_version=ALmixer_Linked_Version();
+void ALmixer_OutputOpenALInfo()
+{
+	ALmixer_version mixer_compile_version;
+	const ALmixer_version * mixer_link_version=ALmixer_GetLinkedVersion();
 	FILE* stream = stdout;
 
 	fprintf(stream, "OpenAL Information:\n");
@@ -6685,7 +7274,7 @@
 	fprintf(stream, "\tAL_RENDERER: %s\n", alGetString( AL_RENDERER ) );
 	fprintf(stream, "\tAL_EXTENSIONS: %s\n", alGetString( AL_EXTENSIONS ) );
 
-	ALMIXER_VERSION(&mixer_compile_version);
+	ALMIXER_GET_COMPILED_VERSION(&mixer_compile_version);
 	fprintf(stream, "\nSDL_ALmixer Information:\n");
 	fprintf(stream, "\tCompiled with SDL_ALmixer version: %d.%d.%d\n",
 		mixer_compile_version.major,
@@ -6711,31 +7300,39 @@
 }
 
 
-Sint32 ALmixer_AllocateChannels(Sint32 numchans)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_AllocateChannels(ALint numchans)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_AllocateChannels(numchans);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
 	
-Sint32 ALmixer_ReserveChannels(Sint32 num)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_ReserveChannels(ALint num)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_ReserveChannels(num);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
 	
 
 
-static ALmixer_Data* DoLoad(Sound_Sample* sample, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data)
-{
-	Uint32 bytes_decoded;
+static ALmixer_Data* DoLoad(Sound_Sample* sample, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data)
+{
+	ALuint bytes_decoded;
 	ALmixer_Data* ret_data;
 	ALenum error;
 
@@ -6795,7 +7392,7 @@
 	/* Different cases for Streamed and Predecoded 
 	 * Streamed might turn into a predecoded if buffersize
 	 * is large enough */
-	if(SDL_FALSE == decode_mode_is_predecoded)
+	if(AL_FALSE == decode_mode_is_predecoded)
 	{
 		bytes_decoded = Sound_Decode(sample);
 		if(sample->flags & SOUND_SAMPLEFLAG_ERROR)
@@ -6881,7 +7478,7 @@
 			alGenBuffers(1, ret_data->buffer);
 			if( (error = alGetError()) != AL_NO_ERROR)
 			{
-				ALmixer_SetError("alGenBuffers failed: %s\n", aluGetErrorString(error));
+				ALmixer_SetError("alGenBuffers failed: %s\n", alGetString(error));
 				Sound_FreeSample(sample);
 				free(ret_data->buffer);
 				free(ret_data);
@@ -6900,7 +7497,7 @@
 			);
 			if( (error = alGetError()) != AL_NO_ERROR)
 			{
-				ALmixer_SetError("alBufferData failed: %s\n", aluGetErrorString(error));
+				ALmixer_SetError("alBufferData failed: %s\n", alGetString(error));
 				Sound_FreeSample(sample);
 				alDeleteBuffers(1, ret_data->buffer);
 				free(ret_data->buffer);
@@ -6982,7 +7579,7 @@
 			alGenBuffers(max_queue_buffers, ret_data->buffer);
 			if( (error = alGetError()) != AL_NO_ERROR)
 			{
-				ALmixer_SetError("alGenBuffers failed: %s\n", aluGetErrorString(error));
+				ALmixer_SetError("alGenBuffers failed: %s\n", alGetString(error));
 				Sound_FreeSample(sample);
 				free(ret_data->buffer);
 				free(ret_data);
@@ -7032,7 +7629,7 @@
 			 */
 			if(access_data)
 			{
-				Uint32 j;
+				ALuint j;
 				/* Create buffers for data access
 				 * Should be the same number as the number of queue buffers
 				 */
@@ -7063,7 +7660,7 @@
 					ret_data->buffer_map_list[j].albuffer = ret_data->buffer[j];
 					ret_data->buffer_map_list[j].index = j;
 					ret_data->buffer_map_list[j].num_bytes = 0;
-					ret_data->buffer_map_list[j].data = (Uint8*)malloc( sizeof(Uint8) * buffersize);
+					ret_data->buffer_map_list[j].data = (ALbyte*)malloc( sizeof(ALbyte) * buffersize);
 					if(NULL == ret_data->buffer_map_list[j].data)
 					{
 						ALmixer_SetError("Out of Memory");
@@ -7095,8 +7692,35 @@
 		} /* End of do stream */
 	} /* end of DECODE_STREAM */
 	/* User requested decode all (easy, nothing to figure out) */
-	else if(SDL_TRUE == decode_mode_is_predecoded)
-	{
+	else if(AL_TRUE == decode_mode_is_predecoded)
+	{
+#ifndef ALMIXER_DISABLE_PREDECODED_PRECOMPUTE_BUFFER_SIZE_OPTIMIZATION
+		/* SDL_sound (behind the scenes) seems to loop on buffer_size chunks 
+		 * until the buffer is filled. It seems like we can 
+		 * do much better and precompute the size of the buffer
+		 * so looping isn't needed.
+		 * WARNING: Due to the way SDL_sound is currently implemented,
+		 * this may waste a lot of memory up front.
+		 * SDL_sound seems to pre-create a buffer of the requested size,
+		 * but on DecodeAll, an entirely new buffer is created and 
+		 * everything is memcpy'd into the new buffer in read chunks
+		 * of the buffer_size. This means we need roughly twice the memory
+		 * to load a file.
+		 */
+		ALint sound_duration = Sound_GetDuration(sample);
+		if(sound_duration > 0)
+		{
+			size_t total_bytes = Compute_Total_Bytes_With_Frame_Padding(&sample->desired, (ALuint)sound_duration);
+			int buffer_resize_succeeded = Sound_SetBufferSize(sample, total_bytes);
+			if(0 == buffer_resize_succeeded)
+			{
+				ALmixer_SetError(Sound_GetError());
+				Sound_FreeSample(sample);
+				free(ret_data);
+				return NULL;
+			}
+		}
+#endif /* ALMIXER_DISABLE_PREDECODED_PRECOMPUTE_BUFFER_SIZE_OPTIMIZATION */
 		bytes_decoded = Sound_DecodeAll(sample);
 		if(sample->flags & SOUND_SAMPLEFLAG_ERROR)
 		{
@@ -7147,7 +7771,7 @@
 		alGenBuffers(1, ret_data->buffer);
 		if( (error = alGetError()) != AL_NO_ERROR)
 		{
-			ALmixer_SetError("alGenBuffers failed: %s\n", aluGetErrorString(error));
+			ALmixer_SetError("alGenBuffers failed: %s\n", alGetString(error));
 			Sound_FreeSample(sample);
 			free(ret_data->buffer);
 			free(ret_data);
@@ -7166,7 +7790,7 @@
 		);
 		if( (error = alGetError()) != AL_NO_ERROR)
 		{
-			ALmixer_SetError("alBufferData failed: %s\n", aluGetErrorString(error));
+			ALmixer_SetError("alBufferData failed: %s\n", alGetString(error));
 			Sound_FreeSample(sample);
 			alDeleteBuffers(1, ret_data->buffer);
 			free(ret_data->buffer);
@@ -7238,7 +7862,7 @@
  * must specify it, so I had to bring it back.
  * Remember I must close the rwops if there is an error before NewSample()
  */
-ALmixer_Data* ALmixer_LoadSample_RW(SDL_RWops* rwops, const char* fileext, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data)
+ALmixer_Data* ALmixer_LoadSample_RW(ALmixer_RWops* rwops, const char* fileext, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data)
 {
 	Sound_Sample* sample = NULL;
 	Sound_AudioInfo target;
@@ -7284,7 +7908,7 @@
  * error checking and the fact that streamed/predecoded files
  * must be treated differently.
  */
-ALmixer_Data* ALmixer_LoadSample(const char* filename, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data)
+ALmixer_Data* ALmixer_LoadSample(const char* filename, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data)
 {
 	Sound_Sample* sample = NULL;
 	Sound_AudioInfo target;
@@ -7385,7 +8009,7 @@
 /* This is a back door for RAW samples or if you need the
  * AudioInfo field. Use at your own risk.
  */
-ALmixer_Data* ALmixer_LoadSample_RAW_RW(SDL_RWops* rwops, const char* fileext, ALmixer_AudioInfo* desired, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data)
+ALmixer_Data* ALmixer_LoadSample_RAW_RW(ALmixer_RWops* rwops, const char* fileext, ALmixer_AudioInfo* desired, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data)
 {
 	Sound_Sample* sample = NULL;
 	Sound_AudioInfo sound_desired;
@@ -7421,7 +8045,7 @@
 /* This is a back door for RAW samples or if you need the
  * AudioInfo field. Use at your own risk.
  */
-ALmixer_Data* ALmixer_LoadSample_RAW(const char* filename, ALmixer_AudioInfo* desired, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data)
+ALmixer_Data* ALmixer_LoadSample_RAW(const char* filename, ALmixer_AudioInfo* desired, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data)
 {
 	Sound_Sample* sample = NULL;
 	Sound_AudioInfo sound_desired;
@@ -7476,13 +8100,13 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "70Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 
 	}
 	else
 	{
-		Uint32 i;
+		ALuint i;
 		
 		/* Delete buffer copies if access_data was enabled */
 		if(data->buffer_map_list != NULL)
@@ -7503,45 +8127,61 @@
 	if((error = alGetError()) != AL_NO_ERROR)
 	{
 		fprintf(stderr, "71Testing error: %s\n",
-			aluGetErrorString(error));				
+			alGetString(error));				
 	}
 	}
 	free(data->buffer);
 	free(data);
 }
 
-Sint32 ALmixer_GetTotalTime(ALmixer_Data* data)
-{
+ALint ALmixer_GetTotalTime(ALmixer_Data* data)
+{
+	if(NULL == data)
+	{
+		return -1;
+	}
 	return data->total_time;
 }
 
 /* This function will look up the source for the corresponding channel */
 /* Must return 0 on error instead of -1 because of unsigned int */
-ALuint ALmixer_GetSource(Sint32 channel)
+ALuint ALmixer_GetSource(ALint channel)
 {
 	ALuint retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetSource(channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS	
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
 /* This function will look up the channel for the corresponding source */
-Sint32 ALmixer_GetChannel(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_GetChannel(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetChannel(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS	
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_FindFreeChannel(Sint32 start_channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_FindFreeChannel(ALint start_channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_FindFreeChannel(start_channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS	
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
@@ -7556,12 +8196,12 @@
  * when a buffer is queued, there was probably some
  * CPU intensive looping which took awhile.
  * It's mainly provided as a convenience.
- * Timing the call with SDL_GetTicks() would produce
+ * Timing the call with ALmixer_GetTicks() would produce
  * more accurate information.
  * Returns a negative value if there was an error,
  * the value being the number of errors.
  */
-Sint32 ALmixer_Update()
+ALint ALmixer_Update()
 {
 #ifdef ENABLE_ALMIXER_THREADS
 	/* The thread will handle all updates by itself.
@@ -7575,33 +8215,45 @@
 
 
 
-void ALmixer_ChannelFinished(void (*channel_finished)(Sint32 channel, void* userdata), void* userdata)
-{
-	SDL_LockMutex(simple_lock);
-	Channel_Done_Callback = channel_finished;
-	Channel_Done_Callback_Userdata = userdata;
-	SDL_UnlockMutex(simple_lock);
-}
-
-
-void ALmixer_ChannelData(void (*channel_data)(Sint32 which_chan, Uint8* data, Uint32 num_bytes, Uint32 frequency, Uint8 channels, Uint8 bit_depth, SDL_bool is_unsigned, SDL_bool decode_mode_is_predecoded, Uint32 length_in_msec, void* user_data), void* user_data)
-{
-	SDL_LockMutex(simple_lock);
-	Channel_Data_Callback = channel_data;
+void ALmixer_SetPlaybackFinishedCallback(void (*playback_finished_callback)(ALint which_channel, ALuint al_source, ALmixer_Data* almixer_data, ALboolean finished_naturally, void* user_data), void* user_data)
+{
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	Channel_Done_Callback = playback_finished_callback;
+	Channel_Done_Callback_Userdata = user_data;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+}
+
+
+void ALmixer_SetPlaybackDataCallback(void (*playback_data_callback)(ALint which_chan, ALuint al_source, ALbyte* data, ALuint num_bytes, ALuint frequency, ALubyte channels, ALubyte bit_depth, ALboolean is_unsigned, ALboolean decode_mode_is_predecoded, ALuint length_in_msec, void* user_data), void* user_data)
+{
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	Channel_Data_Callback = playback_data_callback;
 	Channel_Data_Callback_Userdata = user_data;
-	SDL_UnlockMutex(simple_lock);
-}
-
-
-
-
-
-Sint32 ALmixer_PlayChannelTimed(Sint32 channel, ALmixer_Data* data, Sint32 loops, Sint32 ticks)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+}
+
+
+
+
+
+ALint ALmixer_PlayChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALint ticks)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_PlayChannelTimed(channel, data, loops, ticks);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
@@ -7618,12 +8270,16 @@
  * a channel/source to already be in use because of this.
  * In this event, an error message will be returned to you.
  */
-ALuint ALmixer_PlaySourceTimed(ALuint source, ALmixer_Data* data, Sint32 loops, Sint32 ticks)
+ALuint ALmixer_PlaySourceTimed(ALuint source, ALmixer_Data* data, ALint loops, ALint ticks)
 {
 	ALuint retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_PlaySourceTimed(source, data, loops, ticks);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
@@ -7631,24 +8287,32 @@
 /* Will return the number of channels halted
  * or 0 for error
  */
-Sint32 ALmixer_HaltChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_HaltChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+ALint ALmixer_HaltChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_HaltChannel(channel, AL_FALSE);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
 /* Will return the number of channels halted
  * or 0 for error
  */
-Sint32 ALmixer_HaltSource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_HaltSource(source);
-	SDL_UnlockMutex(simple_lock);
+ALint ALmixer_HaltSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_HaltSource(source, AL_FALSE);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
@@ -7657,349 +8321,554 @@
  * samples and start buffering up the data for the next
  * playback. This may require samples to be halted
  */
-Sint32 ALmixer_RewindData(ALmixer_Data* data)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_RewindData(ALmixer_Data* data)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_RewindData(data);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_RewindChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_RewindChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_RewindChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_RewindSource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_RewindSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_RewindSource(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_PauseChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_PauseChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_PauseChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_PauseSource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_PauseSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_PauseSource(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_ResumeChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_ResumeChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_ResumeChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_ResumeSource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_ResumeSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_ResumeSource(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
 /* Might consider setting eof to 0 as a "feature"
  * This will allow seek to end to stay there because
  * Play automatically rewinds if at the end */
-Sint32 ALmixer_Seek(ALmixer_Data* data, Uint32 msec)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_Seek(data, msec);
-	SDL_UnlockMutex(simple_lock);
+ALint ALmixer_SeekData(ALmixer_Data* data, ALuint msec)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_SeekData(data, msec);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_FadeInChannelTimed(Sint32 channel, ALmixer_Data* data, Sint32 loops, Uint32 fade_ticks, Sint32 expire_ticks)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_FadeInChannelTimed(channel, data, loops, fade_ticks, expire_ticks);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-ALuint ALmixer_FadeInSourceTimed(ALuint source, ALmixer_Data* data, Sint32 loops, Uint32 fade_ticks, Sint32 expire_ticks)
+ALuint ALmixer_FadeInSourceTimed(ALuint source, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks)
 {
 	ALuint retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_FadeInSourceTimed(source, data, loops, fade_ticks, expire_ticks);
-	SDL_UnlockMutex(simple_lock);
-	return retval;
-}
-
-Sint32 ALmixer_FadeOutChannel(Sint32 channel, Uint32 ticks)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_FadeOutChannel(channel, ticks);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
-	
-Sint32 ALmixer_FadeOutSource(ALuint source, Uint32 ticks)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_FadeOutSource(source, ticks);
-	SDL_UnlockMutex(simple_lock);
+
+ALint ALmixer_FadeOutChannel(ALint channel, ALuint ticks)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_FadeOutChannel(channel, ticks);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
-
-Sint32 ALmixer_FadeChannel(Sint32 channel, Uint32 ticks, ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_FadeChannel(channel, ticks, volume);
-	SDL_UnlockMutex(simple_lock);
+	
+ALint ALmixer_FadeOutSource(ALuint source, ALuint ticks)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_FadeOutSource(source, ticks);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_FadeSource(ALuint source, Uint32 ticks, ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_FadeChannel(ALint channel, ALuint ticks, ALfloat volume)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_FadeChannel(channel, ticks, volume);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+	return retval;
+}
+
+ALint ALmixer_FadeSource(ALuint source, ALuint ticks, ALfloat volume)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_FadeSource(source, ticks, volume);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_SetMaxVolumeChannel(Sint32 channel, ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_SetMaxVolumeChannel(channel, volume);
-	SDL_UnlockMutex(simple_lock);
+
+ALboolean ALmixer_SetVolumeChannel(ALint channel, ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_SetVolumeChannel(channel, volume);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_SetMaxVolumeSource(ALuint source, ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_SetMaxVolumeSource(source, volume);
-	SDL_UnlockMutex(simple_lock);
+ALboolean ALmixer_SetVolumeSource(ALuint source, ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_SetVolumeSource(source, volume);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-ALfloat ALmixer_GetMaxVolumeChannel(Sint32 channel)
+ALfloat ALmixer_GetVolumeChannel(ALint channel)
 {
 	ALfloat retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_GetVolumeChannel(channel);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+	return retval;	
+}
+
+ALfloat ALmixer_GetVolumeSource(ALuint source)
+{
+	ALfloat retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_GetVolumeSource(source);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+	return retval;	
+}
+
+ALboolean ALmixer_SetMaxVolumeChannel(ALint channel, ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_SetMaxVolumeChannel(channel, volume);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+	return retval;
+}
+
+ALboolean ALmixer_SetMaxVolumeSource(ALuint source, ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_SetMaxVolumeSource(source, volume);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+	return retval;
+}
+
+ALfloat ALmixer_GetMaxVolumeChannel(ALint channel)
+{
+	ALfloat retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetMaxVolumeChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;	
 }
 
 ALfloat ALmixer_GetMaxVolumeSource(ALuint source)
 {
 	ALfloat retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetMaxVolumeSource(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;	
 }
 
 
-Sint32 ALmixer_SetMinVolumeChannel(Sint32 channel, ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALboolean ALmixer_SetMinVolumeChannel(ALint channel, ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_SetMinVolumeChannel(channel, volume);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_SetMinVolumeSource(ALuint source, ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALboolean ALmixer_SetMinVolumeSource(ALuint source, ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_SetMinVolumeSource(source, volume);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-ALfloat ALmixer_GetMinVolumeChannel(Sint32 channel)
+ALfloat ALmixer_GetMinVolumeChannel(ALint channel)
 {
 	ALfloat retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetMinVolumeChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;	
 }
 
 ALfloat ALmixer_GetMinVolumeSource(ALuint source)
 {
 	ALfloat retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetMinVolumeSource(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;	
 }
 
 
 
-Sint32 ALmixer_SetMasterVolume(ALfloat volume)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALboolean ALmixer_SetMasterVolume(ALfloat volume)
+{
+	ALboolean retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_SetMasterVolume(volume);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;	
 }
 
 ALfloat ALmixer_GetMasterVolume()
 {
 	ALfloat retval;
-	SDL_LockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_GetMasterVolume();
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;	
 }
 
-Sint32 ALmixer_ExpireChannel(Sint32 channel, Sint32 ticks)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_ExpireChannel(ALint channel, ALint ticks)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_ExpireChannel(channel, ticks);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_ExpireSource(ALuint source, Sint32 ticks)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_ExpireSource(ALuint source, ALint ticks)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_ExpireSource(source, ticks);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_QueryChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALint ALmixer_IsActiveChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_QueryChannel(channel);
-	SDL_UnlockMutex(simple_lock);
-	return retval;
-}
-
-Sint32 ALmixer_QuerySource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_QuerySource(source);
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-
-Sint32 ALmixer_PlayingChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_PlayingChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+ALint ALmixer_IsActiveSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_QuerySource(source);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_PlayingSource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_PlayingSource(source);
-	SDL_UnlockMutex(simple_lock);
+
+ALint ALmixer_IsPlayingChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_PlayingChannel(channel);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-
-Sint32 ALmixer_PausedChannel(Sint32 channel)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_PausedChannel(channel);
-	SDL_UnlockMutex(simple_lock);
+ALint ALmixer_IsPlayingSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_PlayingSource(source);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_PausedSource(ALuint source)
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_PausedSource(source);
-	SDL_UnlockMutex(simple_lock);
+
+ALint ALmixer_IsPausedChannel(ALint channel)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_PausedChannel(channel);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-
-Sint32 ALmixer_CountAllFreeChannels()
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_CountAllFreeChannels();
-	SDL_UnlockMutex(simple_lock);
+ALint ALmixer_IsPausedSource(ALuint source)
+{
+	ALint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_PausedSource(source);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_CountUnreservedFreeChannels()
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
-	retval = Internal_CountUnreservedFreeChannels();
-	SDL_UnlockMutex(simple_lock);
+
+ALuint ALmixer_CountAllFreeChannels()
+{
+	ALuint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_CountAllFreeChannels();
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_CountAllUsedChannels()
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALuint ALmixer_CountUnreservedFreeChannels()
+{
+	ALuint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
+	retval = Internal_CountUnreservedFreeChannels();
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
+	return retval;
+}
+
+ALuint ALmixer_CountAllUsedChannels()
+{
+	ALuint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_CountAllUsedChannels();
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-Sint32 ALmixer_CountUnreservedUsedChannels()
-{
-	Sint32 retval;
-	SDL_LockMutex(simple_lock);
+ALuint ALmixer_CountUnreservedUsedChannels()
+{
+	ALuint retval;
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_LockMutex(s_simpleLock);
+#endif
 	retval = Internal_CountUnreservedUsedChannels();
-	SDL_UnlockMutex(simple_lock);
+#ifdef ENABLE_ALMIXER_THREADS
+	SDL_UnlockMutex(s_simpleLock);
+#endif
 	return retval;
 }
 
-SDL_bool ALmixer_IsPredecoded(ALmixer_Data* data)
+ALboolean ALmixer_IsPredecoded(ALmixer_Data* data)
 {
 	if(NULL == data)
 	{
-		return SDL_FALSE;
+		return AL_FALSE;
 	}
 	return data->decoded_all;
 }
 
-
-
-
-
+ALboolean ALmixer_CompiledWithThreadBackend()
+{
+#ifdef ENABLE_ALMIXER_THREADS
+	return AL_TRUE;
+#else
+	return AL_FALSE;
+#endif
+}
+
+
+
+
--- a/SDL_ALmixer.h	Wed Oct 27 16:51:16 2010 -0700
+++ b/SDL_ALmixer.h	Wed Oct 27 16:52:44 2010 -0700
@@ -1,8 +1,7 @@
 /*
-    SDL_ALmixer:  A library to make playing sounds and music easier,
-	which uses OpenAL to manage sounds and SDL_Sound (by Ryan C. Gordon)
-	to decode files.
-    Copyright 2002 Eric Wing 
+    ALmixer:  A library to make playing pre-loaded sounds and streams easier
+	with high performance and potential access to OpenAL effects.
+    Copyright 2002, 2010 Eric Wing <ewing . public @ playcontrol.net>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
@@ -19,84 +18,472 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 */
+
+
+ /**
+ * @mainpage
+ * ALmixer (which I sometimes call "SDL-OpenAL-Mixer" or "SDL_ALmixer") is a cross-platform audio library built 
+ * on top of OpenAL to make playing and managing sounds easier. 
+ * ALmixer provides a simple API inspired by SDL_mixer to make playing sounds easy 
+ * with having to worry about directly dealing with OpenAL sources, buffers, 
+ * and buffer queuing directly.
+ * ALmixer currently utilizes SDL_sound behind the scenes to decode 
+ * various audio formats such as WAV, MP3, AAC, MP4, OGG, etc.
+ *
+ * This library is targeted towards two major groups:
+ * - People who just want an easy, high performance, way to play audio (don't care if its OpenAL or not)
+ * - People who want to an easy way to play audio in OpenAL but still want access to OpenAL directly.
+ *  
+ * ALmixer exposes OpenAL sources in the API so you can freely use ALmixer 
+ * in larger OpenAL applications that need to apply OpenAL 3D effects and features 
+ * to playing sounds.
+ *
+ * The API is heavily influenced and inspired by SDL_mixer, though there is one major
+ * conceptual design difference. ALmixer doesn't divide sound and music playback into two
+ * separate play APIs. Instead, there is one unified play API and you specify via the 
+ * load API whether you want the audio resource loaded as a stream or completely preloaded.
+ * This allows you to have any arbitrary number of streaming sources playing simultaneously
+ * (such as music and speech) unlike SDL_mixer where you are limited to only one "music" 
+ * channel.
+ *
+ * A less major conceptual design difference is every "Channel" API has a corresponding "Source" API.
+ * Every "channel" (in the SDL_mixer definition context) maps to a corresponding OpenAL source id. You can use
+ * this source ID directly with OpenAL API commands to utilize OpenAL effects such as position, Doppler, etc.
+ * Convenience APIs are provided to let you convert channel numbers to source ids and vice-versa.
+ *
+ * Another change which is a pet-peev of mine with SDL_mixer is the lack of a user_data parameter in callbacks.
+ * ALmixer callbacks allow you to pass user_data (aka context) pointers through the callback functions.
+ *
+ * @note There are some #defines you can set to change the behavior at compile time. Most you shouldn't touch.
+ * The one worth noting is ENABLE_ALMIXER_THREADS. If enabled, ALmixer_Update() is automatically called on a 
+ * background thread so you no longer have to explicitly call it. (The function turns into a no-op so your existing
+ * code won't break.) Having Update run in a separate thread has some advantages, particularly for streaming
+ * audio as all the OpenAL buffer queuing happens in this function. It is less likely the background thread will
+ * be blocked for long periods and thus less likely your buffer queues will be starved. However, this means you 
+ * need to be extra careful about what you do in callback functions as they are invoked from the background thread.
+ * I still consider this feature a experimental (though I am starting to use it more myself) and there
+ * may still be bugs.
+ *
+ * @author Eric Wing
+ */
+
+/**
+ * @file
+ * ALmixer (which I sometimes call "SDL-OpenAL-Mixer" or "SDL_ALmixer") is a cross-platform audio library built 
+ * on top of OpenAL to make playing and managing sounds easier. 
+ * ALmixer provides a simple API inspired by SDL_mixer to make playing sounds easy 
+ * with having to worry about directly dealing with OpenAL sources, buffers, 
+ * and buffer queuing directly.
+ * ALmixer currently utilizes SDL_sound behind the scenes to decode 
+ * various audio formats such as WAV, MP3, AAC, MP4, OGG, etc.
+ *
+ * This library is targeted towards two major groups:
+ * - People who just want an easy, high performance, way to play audio (don't care if its OpenAL or not)
+ * - People who want to an easy way to play audio in OpenAL but still want access to OpenAL directly.
+ *  
+ * ALmixer exposes OpenAL sources in the API so you can freely use ALmixer 
+ * in larger OpenAL applications that need to apply OpenAL 3D effects and features 
+ * to playing sounds.
+ *
+ * The API is heavily influenced and inspired by SDL_mixer, though there is one major
+ * conceptual design difference. ALmixer doesn't divide sound and music playback into two
+ * separate play APIs. Instead, there is one unified play API and you specify via the 
+ * load API whether you want the audio resource loaded as a stream or completely preloaded.
+ * This allows you to have any arbitrary number of streaming sources playing simultaneously
+ * (such as music and speech) unlike SDL_mixer where you are limited to only one "music" 
+ * channel.
+ *
+ * A less major conceptual design difference is every "Channel" API has a corresponding "Source" API.
+ * Every "channel" (in the SDL_mixer definition context) maps to a corresponding OpenAL source id. You can use
+ * this source ID directly with OpenAL API commands to utilize OpenAL effects such as position, Doppler, etc.
+ * Convenience APIs are provided to let you convert channel numbers to source ids and vice-versa.
+ *
+ * Another change which is a pet-peev of mine with SDL_mixer is the lack of a user_data parameter in callbacks.
+ * ALmixer callbacks allow you to pass user_data (aka context) pointers through the callback functions.
+ *
+ * @note There are some #defines you can set to change the behavior at compile time. Most you shouldn't touch.
+ * The one worth noting is ENABLE_ALMIXER_THREADS. If enabled, ALmixer_Update() is automatically called on a 
+ * background thread so you no longer have to explicitly call it. (The function turns into a no-op so your existing
+ * code won't break.) Having Update run in a separate thread has some advantages, particularly for streaming
+ * audio as all the OpenAL buffer queuing happens in this function. It is less likely the background thread will
+ * be blocked for long periods and thus less likely your buffer queues will be starved. However, this means you 
+ * need to be extra careful about what you do in callback functions as they are invoked from the background thread.
+ * I still consider this feature a experimental (though I am starting to use it more myself) and there
+ * may still be bugs.
+ *
+ * @author Eric Wing
+ */
+
+
 #ifndef _SDL_ALMIXER_H_
 #define _SDL_ALMIXER_H_
 
-#include "SDL_types.h"
-#include "SDL_rwops.h"
-#include "SDL_error.h"
-#include "SDL_version.h"
-/*
-#include "SDL_audio.h"
-#include "SDL_byteorder.h"
-*/
+
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+/** @cond DOXYGEN_SHOULD_IGNORE_THIS */
+
+/* Note: For Doxygen to produce clean output, you should set the 
+ * PREDEFINED option to remove ALMIXER_DECLSPEC, ALMIXER_CALL, and
+ * the DOXYGEN_SHOULD_IGNORE_THIS blocks.
+ * PREDEFINED = DOXYGEN_SHOULD_IGNORE_THIS=1 ALMIXER_DECLSPEC= ALMIXER_CALL=
+ */
 
-/*
-#include "begin_code.h"
-*/
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	#if defined(_WIN32)
+		#if defined(ALMIXER_BUILD_LIBRARY)
+			#define ALMIXER_DECLSPEC __declspec(dllexport)
+		#else
+			#define ALMIXER_DECLSPEC __declspec(dllimport)
+		#endif
+	#else
+		#if defined(ALMIXER_BUILD_LIBRARY)
+			#if defined (__GNUC__) && __GNUC__ >= 4
+				#define ALMIXER_DECLSPEC __attribute__((visibility("default")))
+			#else
+				#define ALMIXER_DECLSPEC
+			#endif
+		#else
+			#define ALMIXER_DECLSPEC
+		#endif
+	#endif
 
-/*
-#include "SDL_sound.h"
-*/
-/* Crap! altypes.h is missing from 1.1
-#include "altypes.h"
-*/
+	#if defined(_WIN32)
+		#define ALMIXER_CALL __cdecl
+	#else
+		#define ALMIXER_CALL
+	#endif
+#else
+	#include "SDL_types.h" /* will include begin_code.h which is what I really want */
+	#define ALMIXER_DECLSPEC DECLSPEC
+	#define ALMIXER_CALL SDLCALL
+#endif
+
+/** @endcond DOXYGEN_SHOULD_IGNORE_THIS */
+#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
+
+
+
+/* Needed for OpenAL types since altypes.h was removed in 1.1 */
 #include "al.h"
 
 /* Set up for C function definitions, even when using C++ */
 #ifdef __cplusplus
 extern "C" {
 #endif
-		
+
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	/**
+	 * Struct that contains the version information of this library.
+	 * This represents the library's version as three levels: major revision
+	 * (increments with massive changes, additions, and enhancements),
+	 * minor revision (increments with backwards-compatible changes to the
+	 * major revision), and patchlevel (increments with fixes to the minor
+	 * revision).
+	 * @see ALMIXER_VERSION, ALmixer_GetLinkedVersion
+	 */
+	typedef struct ALmixer_version
+	{
+		ALubyte major;
+		ALubyte minor;
+		ALubyte patch;
+	} ALmixer_version;
+#else
+	#include "SDL_version.h"
+	#define ALmixer_version SDL_version
+#endif
+
 /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
-*/
+ */
 #define ALMIXER_MAJOR_VERSION		0
 #define ALMIXER_MINOR_VERSION		1
 #define ALMIXER_PATCHLEVEL			0
 
-/* This macro can be used to fill a version structure with the compile-time
- * version of the SDL_mixer library.
+
+/** 
+ * @defgroup CoreOperation Initialization, Tear-down, and Core Operational Commands
+ * @{
+ * Functions for setting up and using ALmixer.
+ */
+ 
+ 
+/**
+ * This macro fills in a version structure with the version of the
+ * library you compiled against. This is determined by what header the
+ * compiler uses. Note that if you dynamically linked the library, you might
+ * have a slightly newer or older version at runtime. That version can be
+ * determined with ALmixer_GetLinkedVersion(), which, unlike 
+ * ALMIXER_GET_COMPILED_VERSION, is not a macro.
+ *
+ * @note When compiled with SDL, this macro can be used to fill a version structure 
+ * compatible with SDL_version.
+ *
+ * @param X A pointer to a ALmixer_version struct to initialize.
+ *
+ * @see ALmixer_version, ALmixer_GetLinkedVersion
+ */
+#define ALMIXER_GET_COMPILED_VERSION(X)                                           \
+	{                                                                       \
+		(X)->major = ALMIXER_MAJOR_VERSION;                          \
+		(X)->minor = ALMIXER_MINOR_VERSION;                          \
+		(X)->patch = ALMIXER_PATCHLEVEL;                             \
+	}
+
+/**
+ * Gets the library version of the dynamically linked ALmixer you are using.
+ * This gets the version of ALmixer that is linked against your program.
+ * If you are using a shared library (DLL) version of ALmixer, then it is
+ * possible that it will be different than the version you compiled against.
+ *
+ * This is a real function; the macro ALMIXER_GET_COMPILED_VERSION 
+ * tells you what version of tErrorLib you compiled against:
+ *
+ * @code
+ * ALmixer_version compiled;
+ * ALmixer_version linked;
+ *
+ * ALMIXER_GET_COMPILED_VERSION(&compiled);
+ * ALmixer_GetLinkedVersion(&linked);
+ * printf("We compiled against tError version %d.%d.%d ...\n",
+ *           compiled.major, compiled.minor, compiled.patch);
+ * printf("But we linked against tError version %d.%d.%d.\n",
+ *           linked.major, linked.minor, linked.patch);
+ * @endcode
+ *
+ * @see ALmixer_version, ALMIXER_GET_COMPILED_VERSION
  */
-#define ALMIXER_VERSION(X)                                           \
-{                                                                       \
-        (X)->major = ALMIXER_MAJOR_VERSION;                          \
-        (X)->minor = ALMIXER_MINOR_VERSION;                          \
-        (X)->patch = ALMIXER_PATCHLEVEL;                             \
-}
+extern ALMIXER_DECLSPEC const ALmixer_version* ALMIXER_CALL ALmixer_GetLinkedVersion(void);
+
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	/**
+	 * Gets the last error string that was set by the system and clears the error.
+	 *
+	 * @note When compiled with SDL, this directly uses SDL_GetError.
+	 * 
+	 * @return Returns a string containing the last error or "" when no error is set.
+	 */
+	extern ALMIXER_DECLSPEC const char* ALMIXER_CALL ALmixer_GetError(void);
+	/**
+	 * Sets an error string that can be retrieved by ALmixer_GetError.
+	 *
+	 * @note When compiled with SDL, this directly uses SDL_SetError.
+	 * 
+	 * param The error string to set.
+	 */
+	extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_SetError(const char *fmt, ...);
+#else
+	#include "SDL_error.h"
+	/**
+	 * Gets the last error string that was set by the system and clears the error.
+	 *
+	 * @note When compiled with SDL, this directly uses SDL_GetError.
+	 * 
+	 * @return Returns a string containing the last error or "" when no error is set.
+	 */
+	#define ALmixer_GetError 	SDL_GetError
+	/**
+	 * Sets an error string that can be retrieved by ALmixer_GetError.
+	 *
+	 * @note When compiled with SDL, this directly uses SDL_SetError.
+	 * 
+	 * param The error string to set.
+	 */
+	#define ALmixer_SetError 	SDL_SetError
+#endif
+
+
+#ifdef ALMIXER_COMPILE_WITHOUT_SDL
+	#include "ALmixer_rwops.h"
+#else
+	#include "SDL_rwops.h"
+	/**
+	 * A struct that mimicks the SDL_RWops structure.
+	 *
+	 * @note When compiled with SDL, this directly uses SDL_RWops.
+	 */
+	#define ALmixer_RWops 	SDL_RWops
+#endif
+
+
+#define ALMIXER_DEFAULT_FREQUENCY 	0
+#define ALMIXER_DEFAULT_REFRESH 	0
+#define ALMIXER_DEFAULT_NUM_CHANNELS	16
+#define ALMIXER_DEFAULT_NUM_SOURCES		ALMIXER_DEFAULT_NUM_CHANNELS
+
+/** 
+ * This is the recommended Init function. This will initialize the context, SDL_sound,
+ * and the mixer system. You should call this in the setup of your code, after SDL_Init.
+ * If you attempt to bypass this function, you do so at your own risk.
+ *
+ * @note ALmixer expects the SDL audio subsystem to be disabled. In some cases, an enabled
+ * SDL audio subsystem will interfere and cause problems in your app. This Init method explicitly
+ * disables the SDL subsystem if SDL is compiled in. 
+ *
+ * @note The maximum number of sources is OpenAL implementation dependent.
+ * Currently 16 is lowest common denominator for all OpenAL implementations in current use.
+ * 32 is currently the second lowest common denominator.
+ * If you try to allocate more sources than are actually available, this function may return false depending
+ * if the OpenAL implementation returns an error or not. It is possible for OpenAL to silently fail
+ * so be very careful about picking too many sources.
+ *
+ * @param playback_frequency The sample rate you want OpenAL to play at, e.g. 44100
+ * Note that OpenAL is not required to actually respect this value.
+ * Pass in 0 or ALMIXER_DEFAULT_FREQUENCY to specify you want to use your implementation's default value.
+ * @param num_sources The number of OpenAL sources (also can be thought of as 
+ * SDL_mixer channels) you wish to allocate.
+ * Pass in 0 or ALMIXER_DEFAULT_NUM_SOURCES to use ALmixer's default value.
+ * @param refresh_rate The refresh rate you want OpenAL to operate at. 
+ * Note that OpenAL is not required to respect this value.
+ * Pass in 0 or ALMIXER_DEFAULT_REFRESH to use OpenAL default behaviors.
+ * @return Returns AL_FALSE on a failure or AL_TRUE if successfully initialized.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_Init(ALuint playback_frequency, ALint num_sources, ALuint refresh_rate);
 
-/* This function gets the version of the dynamically linked SDL_ALmixer library.
-   it should NOT be used to fill a version structure, instead you should
-   use the ALMIXER_VERSION() macro.
+/** 
+ * InitContext will only initialize the OpenAL context (and not the mixer part).
+ * Note that SDL_Sound is also initialized here because load order matters
+ * because SDL audio will conflict with OpenAL when using SMPEG. This is only 
+ * provided as a backdoor and is not recommended.
+ *
+ * @note This is a backdoor in case you need to initialize the AL context and 
+ * the mixer system separately. I strongly recommend avoiding these two functions
+ * and use the normal Init() function.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_InitContext(ALuint playback_frequency, ALuint refresh_rate);
+
+/** 
+ * InitMixer will only initialize the Mixer system. This is provided in the case 
+ * that you need control over the loading of the context. You may load the context 
+ * yourself, and then call this function. This is not recommended practice, but is 
+ * provided as a backdoor in case you have good reason to 
+ * do this. Be warned that if ALmixer_InitMixer() fails,
+ * it will not clean up the AL context. Also be warned that Quit() still does try to 
+ * clean up everything.
+ *
+ * @note This is a backdoor in case you need to initialize the AL context and 
+ * the mixer system separately. I strongly recommend avoiding these two functions
+ * and use the normal Init() function.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_InitMixer(ALint num_sources);
+
+/**
+ * This shuts down ALmixer. Please remember to free your ALmixer_Data* instances
+ * before calling this method.
+ */
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_Quit(void);
+/**
+ * Returns whether ALmixer has been initializatized (via Init) or not.
+ * @return Returns true for initialized and false for not initialized.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_IsInitialized(void);
+
+/**
+ * Returns the frequency that OpenAL is set to.
+ * @note This function is not guaranteed to give correct information and is OpenAL implementation dependent.
+ * @return Returns the frequency, e.g. 44100.
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_GetFrequency(void);
+
+/**
+ * Let's you change the maximum number of channels/sources available.
+ * This function is not heavily tested. It is probably better to simply initialize
+ * ALmixer with the number of sources you want when you initialize it instead of 
+ * dynamically changing it later.
  */
-extern DECLSPEC const SDL_version * SDLCALL ALmixer_Linked_Version();
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_AllocateChannels(ALint num_chans);
+
+/**
+ * Allows you to reserve a certain number of channels so they won't be automatically
+ * allocated to play on.
+ * This function will effectively block off a certain number of channels so they won't
+ * be automatically assigned to be played on when you call various play functions
+ * (applies to both play-channel and play-source functions since they are the same under the hood).
+ * The lowest number channels will always be blocked off first.
+ * For example, if there are 16 channels available, and you pass 2 into this function,
+ * channels 0 and 1 will be reserved so they won't be played on automatically when you specify
+ * you want to play a sound on any available channel/source. You can 
+ * still play on channels 0 and 1 if you explicitly designate you want to play on their channel
+ * number or source id.
+ * Setting back to 0 will clear all the reserved channels so all will be available again for 
+ * auto-assignment.
+ * As an example, this feature can be useful if you always want your music to be on channel 0 and
+ * speech on channel 1 and you don't want sound effects to ever occupy those channels. This allows
+ * you to build in certain assumptions about your code, perhaps for deciding which data you want
+ * to analyze in a data callback.
+ * Specifying the number of reserve channels to the maximum number of channels will effectively
+ * disable auto-assignment.
+ * @param number_of_reserve_channels The number of channels/sources to reserve.
+ * Or pass -1 to find out how many channels are currently reserved.
+ * @return Returns the number of currently reserved channels.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_ReserveChannels(ALint number_of_reserve_channels);
+
+
+/**
+ * The update function that allows ALmixer to update its internal state.
+ * If not compiled with/using threads, this function must be periodically called
+ * to poll ALmixer to force streamed music and other events to
+ * take place. 
+ * The typical place to put this function is in your main-loop. 
+ * If threads are enabled, then this function just
+ * returns 0 and is effectively a no-op. With threads, it is not necessary to call this function
+ * because updates are handled internally on another thread. However, because threads are still considered
+ * experimental, it is recommended you call this function in a proper place in your code in case
+ * future versions of this library need to abandon threads.
+ * @return Returns 0 if using threads. If not using threads, for debugging purposes, it returns
+ * the number of buffers queued during the loop, or a negative value indicating the numer of errors encountered.
+ * This is subject to change and should not be relied on.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_Update(void);
+
+/**
+ * @}
+ */
+ 
+/** 
+ * @defgroup LoadAPI Load Audio Functions
+ * @{
+ * Functions for loading and unloading audio data.
+ */
+
+
 
 /*
 #define ALmixer_AudioInfo 	Sound_AudioInfo
 */
 
-#define ALMIXER_DEFAULT_FREQUENCY 	44100
-#define ALMIXER_DEFAULT_REFRESH 	0
-#define ALMIXER_DEFAULT_NUM_CHANNELS	16
-#define ALMIXER_DEFAULT_NUM_SOURCES		ALMIXER_DEFAULT_NUM_CHANNELS
-
+/*
 #define ALMIXER_DEFAULT_BUFFERSIZE 32768
-/* #define ALMIXER_DEFAULT_BUFFERSIZE 16384 */
+#define ALMIXER_DEFAULT_BUFFERSIZE 4096
+*/
+#define ALMIXER_DEFAULT_BUFFERSIZE 16384 
 
-/* Default Queue Buffers must be at least 2 */
+/* You probably never need to use these macros directly. */
+#ifndef ALMIXER_DISABLE_PREDECODED_PRECOMPUTE_BUFFER_SIZE_OPTIMIZATION
+	#define ALMIXER_DEFAULT_PREDECODED_BUFFERSIZE ALMIXER_DEFAULT_BUFFERSIZE * 4
+#else
+	/* I'm picking a smaller buffer because ALmixer will try to create a new larger buffer
+	 * based on the length of the audio. So creating a large block up-front might just be a waste.
+	 * However, if my attempts fail for some reason, this buffer size becomes a fallback.
+	 * Having too small of a buffer might cause performance bottlenecks.
+	 */
+	#define ALMIXER_DEFAULT_PREDECODED_BUFFERSIZE 1024
+#endif
+
+/**
+ * Specifies the maximum number of queue buffers to use for a sound stream.
+ * Default Queue Buffers must be at least 2.
+ */
 #define ALMIXER_DEFAULT_QUEUE_BUFFERS 5
-/* Default startup buffers should be at least 1 */
-#define ALMIXER_DEFAULT_STARTUP_BUFFERS 2
+/**
+ * Specifies the number of queue buffers initially filled when first loading a stream.
+ * Default startup buffers should be at least 1. */
+#define ALMIXER_DEFAULT_STARTUP_BUFFERS 2 
 
 /*
 #define ALMIXER_DECODE_STREAM 	0
 #define ALMIXER_DECODE_ALL 		1
 */
 
-
-#define ALmixer_GetError 	SDL_GetError
-#define ALmixer_SetError 	SDL_SetError
-
-
 /* This is a trick I picked up from Lua. Doing the typedef separately 
 * (and I guess before the definition) instead of a single 
 * entry: typedef struct {...} YourName; seems to allow me
@@ -108,8 +495,11 @@
 typedef struct ALmixer_AudioInfo ALmixer_AudioInfo;
 
 /**
- * Equvialent to the Sound_AudioInfo struct in SDL_sound.
- * Originally, I just used the Sound_AudioInfo directly, but
+ * Roughly the equvialent to the Sound_AudioInfo struct in SDL_sound.
+ * Types have been changed to use AL types because I know those are available.
+ * This is different than SDL which uses fixed types so there might be subtle
+ * things you need to pay attention to..
+ * @note Originally, I just used the Sound_AudioInfo directly, but
  * I've been trying to reduce the header dependencies for this file.
  * But more to the point, I've been interested in dealing with the 
  * WinMain override problem Josh faced when trying to use SDL components
@@ -120,134 +510,317 @@
  */
 struct ALmixer_AudioInfo
 {
-	Uint16 format;  /**< Equivalent of SDL_AudioSpec.format. */
-	Uint8 channels; /**< Number of sound channels. 1 == mono, 2 == stereo. */
-	Uint32 rate;    /**< Sample rate; frequency of sample points per second. */
+	ALushort format;  /**< Equivalent of SDL_AudioSpec.format. */
+	ALubyte channels; /**< Number of sound channels. 1 == mono, 2 == stereo. */
+	ALuint rate;    /**< Sample rate; frequency of sample points per second. */
 };
 
 
-#if 0
-typedef struct {
-	Sound_Sample* sample;
-	Mix_Chunk** chunk; /* provide two chunks for double buffering */
-	Uint8** double_buffer; /* Only used for streaming */
-	Uint8 active_buffer; /* used to index the above chunk */
-	void (*channel_done_callback)(int channel);
-} ALmixer_Chunk;
-#endif
-
-/*
-extern DECLSPEC int SDLCALL ALmixer_Init(int frequency, Uint16 format, int channels, int chunksize);
-*/
-/* Frequency == 0 means ALMIXER_DEFAULT_FREQUENCY */
-/* This is the recommended Init function. This will initialize the context, SDL_sound,
- * and the mixer system. If you attempt to bypass this function, you do so at 
- * your own risk.
- */
-extern DECLSPEC Sint32 SDLCALL ALmixer_Init(Uint32 frequency, Sint32 num_sources, Uint32 refresh);
-
-/* This is a backdoor in case you need to initialize the AL context and 
- * the mixer system separately. I strongly recommend avoiding these two functions
- * and use the normal Init() function.
- */
-/* Init_Context will only initialize the OpenAL context (and not the mixer part).
- * Note that SDL_Sound is also initialized here because load order matters
- * because SDL audio will conflict with OpenAL when using SMPEG. This is only 
- * provided as a backdoor and is not recommended.
- */
-extern DECLSPEC Sint32 SDLCALL ALmixer_Init_Context(Uint32 frequency, Uint32 refresh);
-/* Init_Mixer will only initialize the Mixer system. This is provided in the case 
- * that you need control over the loading of the context. You may load the context 
- * yourself, and then call this function. This is not recommended practice, but is 
- * provided as a backdoor in case you have good reason to 
- * do this. Be warned that if ALmixer_Init_Mixer() fails,
- * it will not clean up the AL context. Also be warned that Quit() still does try to 
- * clean up everything.
- */
-extern DECLSPEC Sint32 SDLCALL ALmixer_Init_Mixer(Sint32 num_sources);
-
-extern DECLSPEC void SDLCALL ALmixer_Quit();
-extern DECLSPEC SDL_bool SDLCALL ALmixer_IsInitialized();
-
-extern DECLSPEC Uint32 SDLCALL ALmixer_GetFrequency();
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_AllocateChannels(Sint32 numchans);
-extern DECLSPEC Sint32 SDLCALL ALmixer_ReserveChannels(Sint32 num);
-
-extern DECLSPEC ALmixer_Data * SDLCALL ALmixer_LoadSample_RW(SDL_RWops* rwops, const char* fileext, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data);
-
-
-#define ALmixer_LoadStream_RW(rwops,fileext,buffersize,max_queue_buffers,num_startup_buffers,access_data) ALmixer_LoadSample_RW(rwops,fileext,buffersize, SDL_FALSE, max_queue_buffers, num_startup_buffers,access_data)
-
-#define ALmixer_LoadAll_RW(rwops,fileext,buffersize,access_data) ALmixer_LoadSample_RW(rwops,fileext,buffersize, SDL_TRUE, 0, 0,access_data)
-
-
 
-extern DECLSPEC ALmixer_Data * SDLCALL ALmixer_LoadSample(const char* filename, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data);
-
+/**
+ * This is a general loader function to load an audio resource from an RWops.
+ * Generally, you should use the LoadStream and LoadAll specializations of this function instead which call this.
+ * @param rw_ops The rwops pointing to the audio resource you want to load.
+ * @param file_ext The file extension of your audio type which is used as a hint by the backend to decide which
+ * decoder to use.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * If the file is to be predecoded, optimizations may occur and this value might be ignored.
+ * @param decode_mode_is_predecoded Specifies whether you want to completely preload the data or stream the data in chunks.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+extern ALMIXER_DECLSPEC ALmixer_Data* ALMIXER_CALL ALmixer_LoadSample_RW(ALmixer_RWops* rw_ops, const char* file_ext, ALuint buffer_size, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
 
-#define ALmixer_LoadStream(filename,buffersize,max_queue_buffers,num_startup_buffers,access_data) ALmixer_LoadSample(filename,buffersize, SDL_FALSE, max_queue_buffers, num_startup_buffers,access_data)
-
-#define ALmixer_LoadAll(filename,buffersize,access_data) ALmixer_LoadSample(filename,buffersize, SDL_TRUE, 0, 0,access_data)
-
+#ifdef DOXYGEN_ONLY
+/**
+ * This is the loader function to load an audio resource from an RWops as a stream.
+ * @param rw_ops The rwops pointing to the audio resource you want to load.
+ * @param file_ext The file extension of your audio type which is used as a hint by the backend to decide which
+ * decoder to use.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadStream_RW(ALmixer_RWops* rw_ops, const char* file_ext, ALuint buffer_size, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
+#else
+#define ALmixer_LoadStream_RW(rw_ops, file_ext, buffer_size, max_queue_buffers, num_startup_buffers, access_data) ALmixer_LoadSample_RW(rw_ops,file_ext, buffer_size, AL_FALSE, max_queue_buffers, num_startup_buffers, access_data)
+#endif
 
-extern DECLSPEC ALmixer_Data * SDLCALL ALmixer_LoadSample_RAW_RW(SDL_RWops* rwops, const char* fileext, ALmixer_AudioInfo* desired, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data);
-
-#define ALmixer_LoadStream_RAW_RW(rwops,fileext,desired,buffersize,max_queue_buffers,num_startup_buffers,access_data) ALmixer_LoadSample_RAW_RW(rwops,fileext,desired,buffersize, SDL_FALSE, max_queue_buffers, num_startup_buffers,access_data)
+#ifdef DOXYGEN_ONLY
+/**
+ * This is the loader function to completely preload an audio resource from an RWops into RAM.
+ * @param rw_ops The rwops pointing to the audio resource you want to load.
+ * @param file_ext The file extension of your audio type which is used as a hint by the backend to decide which
+ * decoder to use.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadAll_RW(ALmixer_RWops* rw_ops, const char* file_ext, ALboolean access_data);
+#else
+#define ALmixer_LoadAll_RW(rw_ops, file_ext, access_data) ALmixer_LoadSample_RW(rw_ops, fileext, ALMIXER_DEFAULT_PREDECODED_BUFFERSIZE, AL_TRUE, 0, 0, access_data)
+#endif
 
-#define ALmixer_LoadAll_RAW_RW(rwops,fileext,desired,buffersize,access_data) ALmixer_LoadSample_RAW_RW(rwops,fileext,desired,buffersize, SDL_TRUE, 0, 0,access_data)
+/**
+ * This is a general loader function to load an audio resource from a file.
+ * Generally, you should use the LoadStream and LoadAll specializations of this function instead which call this.
+ * @param file_name The file of the audio resource you want to load.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * If the file is to be predecoded, optimizations may occur and this value might be ignored.
+ * @param decode_mode_is_predecoded Specifies whether you want to completely preload the data or stream the data in chunks.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+extern ALMIXER_DECLSPEC ALmixer_Data * ALMIXER_CALL ALmixer_LoadSample(const char* file_name, ALuint buffer_size, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
 
-extern DECLSPEC ALmixer_Data * SDLCALL ALmixer_LoadSample_RAW(const char* filename, ALmixer_AudioInfo* desired, Uint32 buffersize, SDL_bool decode_mode_is_predecoded, Uint32 max_queue_buffers, Uint32 num_startup_buffers, SDL_bool access_data);
+#ifdef DOXYGEN_ONLY
+/**
+ * This is the loader function to load an audio resource from a file.
+ * @param file_name The file to the audio resource you want to load.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadStream(const char* file_name, ALuint buffer_size, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
+#else
+#define ALmixer_LoadStream(file_name, buffer_size, max_queue_buffers, num_startup_buffers,access_data) ALmixer_LoadSample(file_name, buffer_size, AL_FALSE, max_queue_buffers, num_startup_buffers, access_data)
+#endif
+
+#ifdef DOXYGEN_ONLY
+/**
+ * This is the loader function to completely preload an audio resource from a file into RAM.
+ * @param file_name The file to the audio resource you want to load.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadAll(const char* file_name, ALboolean access_data);
+#else
+#define ALmixer_LoadAll(file_name, access_data) ALmixer_LoadSample(file_name, ALMIXER_DEFAULT_PREDECODED_BUFFERSIZE, AL_TRUE, 0, 0, access_data)
+#endif
 
-
+/**
+ * This is a back door general loader function for RAW samples or if you need to specify the ALmixer_AudioInfo field.
+ * Use at your own risk.
+ * Generally, you should use the LoadStream and LoadAll specializations of this function instead which call this.
+ * @param rw_ops The rwops pointing to the audio resource you want to load.
+ * @param file_ext The file extension of your audio type which is used as a hint by the backend to decide which
+ * decoder to use. Pass "raw" for raw formats.
+ * @param desired_format The format you want audio decoded to. NULL will pick a default for you.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * If the file is to be predecoded, optimizations may occur and this value might be ignored.
+ * @param decode_mode_is_predecoded Specifies whether you want to completely preload the data or stream the data in chunks.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+extern ALMIXER_DECLSPEC ALmixer_Data * ALMIXER_CALL ALmixer_LoadSample_RAW_RW(ALmixer_RWops* rw_ops, const char* file_ext, ALmixer_AudioInfo* desired_format, ALuint buffer_size, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
 
-extern DECLSPEC void SDLCALL ALmixer_FreeData(ALmixer_Data* data);
+#ifdef DOXYGEN_ONLY
+/**
+ * This is a back door stream loader function for RAW samples or if you need to specify the ALmixer_AudioInfo field.
+ * Use at your own risk.
+ * @param rw_ops The rwops pointing to the audio resource you want to load.
+ * @param file_ext The file extension of your audio type which is used as a hint by the backend to decide which
+ * decoder to use. Pass "raw" for raw formats.
+ * @param desired_format The format you want audio decoded to. NULL will pick a default for you.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * If the file is to be predecoded, optimizations may occur and this value might be ignored.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadStream_RAW_RW(ALmixer_RWops* rw_ops, const char* file_ext, ALmixer_AudioInfo* desired_format, ALuint buffer_size, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
+#else
+#define ALmixer_LoadStream_RAW_RW(rw_ops, file_ext, desired_format, buffer_size, max_queue_buffers, num_startup_buffers, access_data) ALmixer_LoadSample_RAW_RW(rw_ops, file_ext, desired_format, buffer_size, AL_FALSE, max_queue_buffers, num_startup_buffers, access_data)
+#endif
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_GetTotalTime(ALmixer_Data* data);
-
+#ifdef DOXYGEN_ONLY
+/**
+ * This is a back door loader function for complete preloading RAW samples into RAM or if you need to specify the ALmixer_AudioInfo field.
+ * Use at your own risk.
+ * @param rw_ops The rwops pointing to the audio resource you want to load.
+ * @param file_ext The file extension of your audio type which is used as a hint by the backend to decide which
+ * decoder to use. Pass "raw" for raw formats.
+ * @param desired_format The format you want audio decoded to. NULL will pick a default for you.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadAll_RAW_RW(ALmixer_RWops* rw_ops, const char* file_ext, ALmixer_AudioInfo* desired_format, ALboolean access_data);
+#else
+#define ALmixer_LoadAll_RAW_RW(rw_ops, file_ext, desired_format, access_data) ALmixer_LoadSample_RAW_RW(rw_ops, file_ext, desired_format, ALMIXER_DEFAULT_PREDECODED_BUFFERSIZE, AL_TRUE, 0, 0, access_data)
+#endif
 
-/* If not using threads, this function must be periodically called
- * to poll ALmixer to force streamed music and other events to
- * take place. If threads are enabled, then this function just
- * returns 0.
+/**
+ * This is a back door general loader function for RAW samples or if you need to specify the ALmixer_AudioInfo field.
+ * Use at your own risk.
+ * Generally, you should use the LoadStream and LoadAll specializations of this function instead which call this.
+ * @param file_name The file to the audio resource you want to load. Extension should be "raw" for raw formats.
+ * @param desired_format The format you want audio decoded to. NULL will pick a default for you.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * If the file is to be predecoded, optimizations may occur and this value might be ignored.
+ * @param decode_mode_is_predecoded Specifies whether you want to completely preload the data or stream the data in chunks.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
  */
-extern DECLSPEC Sint32 SDLCALL ALmixer_Update();
+extern ALMIXER_DECLSPEC ALmixer_Data * ALMIXER_CALL ALmixer_LoadSample_RAW(const char* file_name, ALmixer_AudioInfo* desired_format, ALuint buffer_size, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
+
+#ifdef DOXYGEN_ONLY
+/**
+ * This is a back door stream loader function for RAW samples or if you need to specify the ALmixer_AudioInfo field.
+ * Use at your own risk.
+ * @param file_name The file to the audio resource you want to load.Extension should be "raw" for raw formats.
+ * @param desired_format The format you want audio decoded to. NULL will pick a default for you.
+ * @param buffer_size The size of a buffer to allocate for read chunks. This number should be in quantized with 
+ * the valid frame sizes of your audio data. If the data is streamed, the data will be read in buffer_size chunks.
+ * If the file is to be predecoded, optimizations may occur and this value might be ignored.
+ * @param max_queue_buffers For streamed data, specifies the maximum number of buffers that can be queued at any given time.
+ * @param num_startup_buffers For streamed data, specifies the number of buffers to fill before playback starts.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadStream_RAW(const char* file_name, ALmixer_AudioInfo* desired_format, ALuint buffer_size, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data);
+#else
+#define ALmixer_LoadStream_RAW(file_name, desired_format, buffer_size, max_queue_buffers, num_startup_buffers, access_data) ALmixer_LoadSample_RAW(file_name, desired_format, buffer_size, AL_FALSE, max_queue_buffers, num_startup_buffers, access_data)
+#endif
 
+#ifdef DOXYGEN_ONLY
+/**
+ * This is a back door loader function for complete preloading RAW samples into RAM or if you need to specify the ALmixer_AudioInfo field.
+ * Use at your own risk.
+ * @param file_name The file to the audio resource you want to load. Extension should be "raw" for raw formats.
+ * @param desired_format The format you want audio decoded to. NULL will pick a default for you.
+ * @param access_data A boolean that specifies if you want the data contained in the currently playing buffer to be handed
+ * to you in a callback function. Note that for predecoded data, you get back the entire buffer in one callback when the 
+ * audio first starts playing. With streamed data, you get the data in buffer_size chunks. Callbacks are not guarnanteed
+ * to be perfectly in-sync as this is a best-effort implementaiton. There are memory and performance considerations for 
+ * using this feature, so if you don't need data callbacks, you should pass false to this function.
+ * @return Returns an ALmixer_Data* of the loaded sample or NULL if failed.
+ */
+ALmixer_Data* ALmixer_LoadAll_RAW(const char* file_name, ALmixer_AudioInfo* desired_format, ALboolean access_data);
+#else
+#define ALmixer_LoadAll_RAW(file_name, desired_format, access_data) ALmixer_LoadSample_RAW(file_name, desired_format, ALMIXER_DEFAULT_PREDECODED_BUFFERSIZE, AL_TRUE, 0, 0, access_data)
+#endif
 
+/**
+ * Frees an ALmixer_Data.
+ * Releases the memory associated with a ALmixer_Data. Use this when you are done playing the audio sample
+ * and wish to release the memory.
+ * @warning Do not try releasing data that is currently in use (e.g. playing, paused).
+ * @warning Make sure to free your data before calling ALmixer_Quit. Do not free data aftter ALmixer_Quit().
+ * @param almixer_data The ALmixer_Data* you want to free.
+ */
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_FreeData(ALmixer_Data* almixer_data);
 
 
-/* Play a sound on a channel with a time limit */
-extern DECLSPEC Sint32 SDLCALL ALmixer_PlayChannelTimed(Sint32 channel, ALmixer_Data* data, Sint32 loops, Sint32 ticks);
-
-/* The same as above, but the sound is played without time limits */ 
-#define ALmixer_PlayChannel(channel,data,loops) ALmixer_PlayChannelTimed(channel,data,loops,-1)
-/* These functions are the same as PlayChannel*(), but use sources 
- * instead of channels
+/**
+ * Returns true if the almixer_data was completely loaded into memory or false if it was loaded
+ * as a stream.
+ * @param almixer_data The audio resource you want to know about.
+ * @return AL_TRUE is predecoded, or AL_FALSE if streamed.
  */
-extern DECLSPEC ALuint SDLCALL ALmixer_PlaySourceTimed(ALuint source, ALmixer_Data* data, Sint32 loops, Sint32 ticks);
-
-#define ALmixer_PlaySource(source,data,loops) ALmixer_PlaySourceTimed(source,data,loops,-1)
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_IsPredecoded(ALmixer_Data* almixer_data);
 
-/* This function will look up the source for the corresponding channel.
- * If -1 is supplied, it will try to return a source not in use 
- * Must return 0 on error instead of -1 because of unsigned int 
+/**
+ * @}
+ */
+ 
+/** 
+ * @defgroup CallbackAPI Callbacks
+ * @{
+ * Functions for callbacks
  */
-extern DECLSPEC ALuint SDLCALL ALmixer_GetSource(Sint32 channel);
-/* This function will look up the channel for the corresponding source.
- * If -1 is supplied, it will try to return the first channel not in use. 
- * Returns -1 on error, or the channel.
- */
-extern DECLSPEC Sint32 SDLCALL ALmixer_GetChannel(ALuint source);
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_FindFreeChannel(Sint32 start_channel);
-
-extern DECLSPEC void SDLCALL ALmixer_ChannelFinished(void (*channel_finished)(Sint32 channel, void* userdata), void* userdata);
+/**
+ * Allows you to set a callback for when a sound has finished playing on a channel/source.
+ * @param playback_finished_callback The function you want to be invoked when a sound finishes.
+ * The callback function will pass you back the channel number which just finished playing,
+ * the OpenAL source id associated with the channel, the ALmixer_Data* that was played,
+ * a boolean telling you whether a sound finished playing because it ended normally or because
+ * something interrupted the playback (such as the user calling ALmixer_Halt*), and the
+ * user_data supplied as the second parameter to this function.
+ * @param which_chan The ALmixer channel that the data is currently playing on.
+ * @param al_source The OpenAL source that the data is currently playing on.
+ * @param almixer_data The ALmixer_Data that was played.
+ * @param finished_naturally AL_TRUE if the sound finished playing because it ended normally 
+ * or AL_FALSE because something interrupted playback (such as the user calling ALmixer_Halt*).
+ * @param user_data This will be passed back to you in the callback.
+ *
+ * @warning You should not call other ALmixer functions in this callback. 
+ * Particularly in the case of when compiled with threads, recursive locking
+ * will occur which will lead to deadlocks. Also be aware that particularly in the 
+ * threaded case, the callbacks may (and currently do) occur on a background thread.
+ * One typical thread safe strategy is to set flags or schedule events to occur on the
+ * main thread.
+ * One possible exception to the no-calling ALmixer functions rule is ALmixer_Free. ALmixer_Free
+ * currently does not lock so it might okay to call this to free your data. However, this is not
+ * tested and not the expected pattern to be used.
+ */
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_SetPlaybackFinishedCallback(void (*playback_finished_callback)(ALint which_channel, ALuint al_source, ALmixer_Data* almixer_data, ALboolean finished_naturally, void* user_data), void* user_data);
 
-/*
-extern DECLSPEC void SDLCALL ALmixer_ChannelData(void (*channel_data)(Sint32 which_chan, Uint8* data, Uint32 num_bytes, Uint32 frequency, Uint8 channels, Uint8 bitdepth, Uint16 format, Uint8 decode_mode));
-*/
 /**
- * Audio data callback system.
+ * Allows you to set a callback for getting audio data.
  * This is a callback function pointer that when set, will trigger a function
  * anytime there is new data loaded for a sample. The appropriate load 
  * parameter must be set in order for a sample to appear here.
@@ -263,9 +836,18 @@
  * underruns. If you decode more data, you have to deal with the syncronization
  * issues if you want to display the data during playback in something like an
  * oscilloscope.
+ *
+ * @warning You should not call other ALmixer functions in this callback. 
+ * Particularly in the case of when compiled with threads, recursive locking
+ * will occur which will lead to deadlocks. Also be aware that particularly in the 
+ * threaded case, the callbacks may (and currently do) occur on a background thread.
+ * One typical thread safe strategy is to set flags or schedule events to occur on the
+ * main thread.
  * 
- * @param which_chan The ALmixer channel that the data is currently playing on.
- * @param data This is a pointer to the data buffer containing ALmixer's 
+ * @param playback_data_callback The function you want called back.
+ * @param which_channel The ALmixer channel that the data is currently playing on.
+ * @param al_source The OpenAL source that the data is currently playing on.
+ * @param pcm_data This is a pointer to the data buffer containing ALmixer's 
  * version of the decoded data. Consider this data as read-only. In the 
  * non-threaded backend, this data will persist until potentially the next call
  * to Update(). Currently, data buffers are preallocated and not destroyed
@@ -277,23 +859,22 @@
  * so you can try referencing data from these buffers without worrying 
  * about crashing. (You still need to be aware that the data could be 
  * modified behind the scenes on an Update().)
- *
- * The data type listed is an Unsigned 8-bit format, but the real data may
- * not actually be this. Uint8 was chosen as a convenience. If you have 
- * a 16 bit format, you will want to cast the data and also divide the num_bytes
- * by 2. Typically, data is either Sint16 or Uint8. This seems to be a 
+ * The data type listed is an signed 8-bit format, but the real data may
+ * not actually be this. ALbyte was chosen as a convenience. If you have 
+ * a 16 bit format, you will want to cast the data and divide the num_bytes by 2.
+ * Typically, data is either Sint16. This seems to be a 
  * convention audio people seem to follow though I'm not sure what the 
  * underlying reasons (if any) are for this. I suspect that there may be 
- * some nice alignment/conversion property if you need to cast from Uint8
- * to Sint16.
+ * some nice alignment/conversion property if you need to cast between ALbyte
+ * and ALubyte.
  * 
  * @param num_bytes This is the total length of the data buffer. It presumes
- * that this length is measured for Uint8. So if you have Sint16 data, you
+ * that this length is measured for ALbyte. So if you have Sint16 data, you
  * should divide num_bytes by two if you access the data as Sint16.
  * 
  * @param frequency The frequency the data was decoded at.
  *
- * @param channels 1 for mono, 2 for stereo.
+ * @param num_channels_in_sample 1 for mono, 2 for stereo. Not to be confused with the ALmixer which_channel.
  *
  * @param bit_depth Bits per sample. This is expected to be 8 or 16. This 
  * number will tell you if you if you need to treat the data buffer as 
@@ -301,7 +882,7 @@
  * 
  * @param is_unsigned 1 if the data is unsigned, 0 if signed. Using this
  * combined with bit_depth will tell you if you need to treat the data
- * as Uint8, Sint8, Uint32, or Sint32.
+ * as ALubyte, ALbyte, ALuint, or ALint.
  *
  * @param decode_mode_is_predecoded This is here to tell you if the data was totally 
  * predecoded or loaded as a stream. If predecoded, you will only get 
@@ -315,132 +896,610 @@
  * buffer in milliseconds. This could be computed yourself, but is provided
  * as a convenince.
  *
- * 
+ * @param user_data The user data you pass in will be passed back to you in the callback. 
  */
-extern DECLSPEC void SDLCALL ALmixer_ChannelData(void (*channel_data)(Sint32 which_chan, Uint8* data, Uint32 num_bytes, Uint32 frequency, Uint8 channels, Uint8 bit_depth, SDL_bool is_unsigned, SDL_bool decode_mode_is_predecoded, Uint32 length_in_msec, void* user_data), void* user_data);
-
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_HaltChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_HaltSource(ALuint source);
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_SetPlaybackDataCallback(void (*playback_data_callback)(ALint which_channel, ALuint al_source, ALbyte* pcm_data, ALuint num_bytes, ALuint frequency, ALubyte num_channels_in_sample, ALubyte bit_depth, ALboolean is_unsigned, ALboolean decode_mode_is_predecoded, ALuint length_in_msec, void* user_data), void* user_data);
 
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_RewindData(ALmixer_Data* data);
-
-/* If decoded all, rewind will instantly rewind it. Data is not 
- * affected, so it will start at the "Seek"'ed positiond.
- * Streamed data will rewind the actual data, but the effect
- * will not be noticed until the currently buffered data is played.
- * Use Halt before this call for instantaneous changes
+/**
+ * @}
  */
-extern DECLSPEC Sint32 SDLCALL ALmixer_RewindChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_RewindSource(ALuint source);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_PauseChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_PauseSource(ALuint source);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_ResumeChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_ResumeSource(ALuint source);
+ 
+ /** 
+ * @defgroup PlayAPI Functions useful for playback.
+ * @{
+ * These are core functions that are useful for controlling playback.
+ * Also see the Volume functions for additional playback functions and Query functions for additional information.
+ */
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_Seek(ALmixer_Data* data, Uint32 msec);
-
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_FadeInChannelTimed(Sint32 channel, ALmixer_Data* data, Sint32 loops, Uint32 fade_ticks, Sint32 expire_ticks);
-
-#define ALmixer_FadeInChannel(channel,data,loops,fade_ticks) ALmixer_FadeInChannelTimed(channel,data,loops,fade_ticks,-1)
-
-extern DECLSPEC ALuint SDLCALL ALmixer_FadeInSourceTimed(ALuint source, ALmixer_Data* data, Sint32 loops, Uint32 fade_ticks, Sint32 expire_ticks);
-
-#define ALmixer_FadeInSource(source,data,loops,fade_ticks) ALmixer_FadeInSourceTimed(source,data,loops,fade_ticks,-1)
+/**
+ * Returns the total time in milliseconds of the audio resource.
+ * Returns the total time in milliseconds of the audio resource.
+ * If the total length cannot be determined, -1 will be returned.
+ * @param almixer_data The audio sample you want to know the total time of.
+ * @return The total time in milliseconds or -1 if some kind of failure.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_GetTotalTime(ALmixer_Data* almixer_data);
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_FadeOutChannel(Sint32 channel, Uint32 ticks);
-extern DECLSPEC Sint32 SDLCALL ALmixer_FadeOutSource(ALuint source, Uint32 ticks);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_FadeChannel(Sint32 channel, Uint32 ticks, ALfloat volume);
-extern DECLSPEC Sint32 SDLCALL ALmixer_FadeSource(ALuint source, Uint32 ticks, ALfloat volume);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_SetMaxVolumeChannel(Sint32 channel, ALfloat volume);
-extern DECLSPEC Sint32 SDLCALL ALmixer_SetMaxVolumeSource(ALuint source, ALfloat volume);
-extern DECLSPEC ALfloat SDLCALL ALmixer_GetMaxVolumeChannel(Sint32 channel);
-extern DECLSPEC ALfloat SDLCALL ALmixer_GetMaxVolumeSource(ALuint source);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_SetMinVolumeChannel(Sint32 channel, ALfloat volume);
-extern DECLSPEC Sint32 SDLCALL ALmixer_SetMinVolumeSource(ALuint source, ALfloat volume);
-extern DECLSPEC ALfloat SDLCALL ALmixer_GetMinVolumeChannel(Sint32 channel);
-extern DECLSPEC ALfloat SDLCALL ALmixer_GetMinVolumeSource(ALuint source);
-
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_SetMasterVolume(ALfloat volume);
-extern DECLSPEC ALfloat SDLCALL ALmixer_GetMasterVolume();
+/** 
+ * This function will look up the OpenAL source id for the corresponding channel number.
+ * @param which_channel The channel which you want to find the corresponding OpenAL source id for.
+ * If -1 was specified, an available source for playback will be returned.
+ * @return The OpenAL source id corresponding to the channel. 0 if you specified an illegal channel value.
+ * Or 0 if you specified -1 and no sources were currently available.
+ * @note ALmixer assumes your OpenAL implementation does not use 0 as a valid source ID. While the OpenAL spec
+ * does not disallow 0 for valid source ids, as of now, there are no known OpenAL implementations in use that 
+ * use 0 as a valid source id (partly due to problems this has caused developers in the past).
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_GetSource(ALint which_channel);
 
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_ExpireChannel(Sint32 channel, Sint32 ticks);
-extern DECLSPEC Sint32 SDLCALL ALmixer_ExpireSource(ALuint source, Sint32 ticks);
+/**
+ * This function will look up the channel for the corresponding source.
+ * @param al_source The source id you want to find the corresponding channel number for.
+ * If -1 is supplied, it will try to return the first channel not in use. 
+ * Returns -1 on error, or the channel.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_GetChannel(ALuint al_source);
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_QueryChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_QuerySource(ALuint source);
-extern DECLSPEC Sint32 SDLCALL ALmixer_PlayingChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_PlayingSource(ALuint source);
-extern DECLSPEC Sint32 SDLCALL ALmixer_PausedChannel(Sint32 channel);
-extern DECLSPEC Sint32 SDLCALL ALmixer_PausedSource(ALuint source);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_CountAllFreeChannels();
-extern DECLSPEC Sint32 SDLCALL ALmixer_CountUnreservedFreeChannels();
-extern DECLSPEC Sint32 SDLCALL ALmixer_CountAllUsedChannels();
-extern DECLSPEC Sint32 SDLCALL ALmixer_CountUnreservedUsedChannels();
-#define ALmixer_CountTotalChannels() ALmixer_AllocateChannels(-1)
-#define ALmixer_CountReservedChannels() ALmixer_ReserveChannels(-1)
-
-extern DECLSPEC SDL_bool SDLCALL ALmixer_IsPredecoded(ALmixer_Data* data);
+/**
+ * Will look for a channel available for playback.
+ * Given a start channel number, the search will increase to the highest channel until it finds one available.
+ * @param start_channel The channel number you want to start looking at.
+ * @return A channel available or -1 if none could be found.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_FindFreeChannel(ALint start_channel);
 
 
 
-/* For testing */
-#if 0
-extern DECLSPEC void SDLCALL ALmixer_Output_Attributes();
+/**
+ * Play a sound on a channel with a time limit.
+ * Plays a sound on a channel and will auto-stop after a specified number of milliseconds.
+ * @param which_channel Allows you to specify the specific channel you want to play on. 
+ * Channels range from 0 to the (Number of allocated channels - 1). If you specify -1, 
+ * an available channel will be chosen automatically for you.
+ * @note While paused, the auto-stop clock will also be paused. This makes it easy to always stop
+ * a sample by a predesignated length without worrying about whether the user paused playback which would 
+ * throw off your calculations.
+ * @param almixer_data The audio resource you want to play.
+ * @param number_of_loops The number of times to loop (repeat) playing the data. 
+ * 0 means the data will play exactly once without repeat. -1 means infinitely loop.
+ * @param number_of_milliseconds The number of milliseconds that should be played until the sample is auto-stopped.
+ * -1 means don't auto-stop playing and let the sample finish playing normally (or if looping is set to infinite, 
+ * the sample will never stop playing).
+ * @return Returns the channel that was selected for playback or -1 if no channels were available.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_PlayChannelTimed(ALint which_channel, ALmixer_Data* almixer_data, ALint number_of_loops, ALint number_of_milliseconds);
+
+#ifdef DOXYGEN_ONLY
+/**
+ * The same as ALmixer_PlayChannelTimed, but the sound is played without time limits.
+ * @see ALmixer_PlayChannelTimed.
+ */ 
+ALint ALmixer_PlayChannelTimed(ALint which_channel, ALmixer_Data* almixer_data, ALint number_of_loops);
+#else
+#define ALmixer_PlayChannel(channel,data,loops) ALmixer_PlayChannelTimed(channel,data,loops,-1)
+#endif
+
+
+/**
+ * Play a sound on an OpenAL source with a time limit.
+ * Plays a sound on an OpenAL source and will auto-stop after a specified number of milliseconds.
+ * @param al_source Allows you to specify the OpenAL source you want to play on. 
+ * If you specify 0, an available source will be chosen automatically for you.
+ * @note Source values are not necessarily continguous and their values are implementation dependent.
+ * Always use ALmixer functions to determine source values.
+ * @note While paused, the auto-stop clock will also be paused. This makes it easy to always stop
+ * a sample by a predesignated length without worrying about whether the user paused playback which would 
+ * throw off your calculations.
+ * @param almixer_data The audio resource you want to play.
+ * @param number_of_loops The number of times to loop (repeat) playing the data. 
+ * 0 means the data will play exactly once without repeat. -1 means infinitely loop.
+ * @param number_of_milliseconds The number of milliseconds that should be played until the sample is auto-stopped.
+ * -1 means don't auto-stop playing and let the sample finish playing normally (or if looping is set to infinite, 
+ * the sample will never stop playing).
+ * @return Returns the OpenAL source that was selected for playback or 0 if no sources were available.
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_PlaySourceTimed(ALuint al_source, ALmixer_Data* almixer_data, ALint number_of_loops, ALint number_of_milliseconds);
+
+#ifdef DOXYGEN_ONLY
+/**
+ * The same as ALmixer_PlaySourceTimed, but the sound is played without time limits.
+ * @see ALmixer_PlaySourceTimed.
+ */ 
+ALint ALmixer_PlayChannelTimed(ALuint al_source, ALmixer_Data* almixer_data, ALint number_of_loops);
+#else
+#define ALmixer_PlaySource(al_source, almixer_data, number_of_loops) ALmixer_PlaySourceTimed(al_source, almixer_data, number_of_loops, -1)
+#endif
+
+/**
+ * Stops playback on a channel.
+ * Stops playback on a channel and clears the channel so it can be played on again.
+ * @note Callbacks will still be invoked, but the finished_naturally flag will be set to AL_FALSE.
+ * @param which_channel The channel to halt or -1 to halt all channels.
+ * @return The actual number of channels halted on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_HaltChannel(ALint which_channel);
+
+/**
+ * Stops playback on a channel.
+ * Stops playback on a channel and clears the channel so it can be played on again.
+ * @note Callbacks will still be invoked, but the finished_naturally flag will be set to AL_FALSE.
+ * @param al_source The source to halt or 0 to halt all sources.
+ * @return The actual number of sources halted on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_HaltSource(ALuint al_source);
+
+/**
+ * Rewinds the sound to the beginning for a given data.
+ * Rewinds the actual data, but the effect
+ * may not be noticed until the currently buffered data is played.
+ * @param almixer_data The data to rewind.
+ * @returns 0 on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_RewindData(ALmixer_Data* almixer_data);
+
+/**
+ * Rewinds the sound to the beginning that is playing on a specific channel.
+ * If decoded all, rewind will instantly rewind it. Data is not 
+ * affected, so it will start at the "Seek"'ed positiond.
+ * Streamed data will rewind the actual data, but the effect
+ * may not be noticed until the currently buffered data is played.
+ * @param which_channel The channel to rewind or -1 to rewind all channels.
+ * @returns 0 on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_RewindChannel(ALint which_channel);
+/**
+ * Rewinds the sound to the beginning that is playing on a specific source.
+ * If decoded all, rewind will instantly rewind it. Data is not 
+ * affected, so it will start at the "Seek"'ed positiond.
+ * Streamed data will rewind the actual data, but the effect
+ * may not be noticed until the currently buffered data is played.
+ * @param al_source The source to rewind or 0 to rewind all sources.
+ * @returns 1 on success or 0 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_RewindSource(ALuint al_source);
+
+/**
+ * Seek the sound for a given data.
+ * Seeks the actual data to the given millisecond. It
+ * may not be noticed until the currently buffered data is played.
+ * @param almixer_data
+ * @param msec_pos The time position to seek to in the audio in milliseconds.
+ * @returns 0 on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_SeekData(ALmixer_Data* almixer_data, ALuint msec_pos);
+
+/**
+ * Pauses playback on a channel.
+ * Pauses playback on a channel. Should have no effect on channels that aren't playing.
+ * @param which_channel The channel to pause or -1 to pause all channels.
+ * @return The actual number of channels paused on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_PauseChannel(ALint which_channel);
+/**
+ * Pauses playback on a source.
+ * Pauses playback on a source. Should have no effect on source that aren't playing.
+ * @param al_source The source to pause or -1 to pause all source.
+ * @return The actual number of source paused on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_PauseSource(ALuint al_source);
+
+/**
+ * Resumes playback on a channel that is paused.
+ * Resumes playback on a channel that is paused. Should have no effect on channels that aren't paused.
+ * @param which_channel The channel to resume or -1 to resume all channels.
+ * @return The actual number of channels resumed on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_ResumeChannel(ALint which_channel);
+
+/**
+ * Resumes playback on a source that is paused.
+ * Resumes playback on a source that is paused. Should have no effect on sources that aren't paused.
+ * @param al_source The source to resume or -1 to resume all sources.
+ * @return The actual number of sources resumed on success or -1 on error.
+ */
+ extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_ResumeSource(ALuint al_source);
+
+ 
+/**
+ * Will cause a currently playing channel to stop playing in the specified number of milliseconds.
+ * Will cause a currently playing channel to stop playing in the specified number of milliseconds.
+ * This will override the value that was set when PlayChannelTimed or PlaySourceTimed was called
+ * or override any previous calls to ExpireChannel or ExpireSource.
+ * @param which_channel The channel to expire or -1 to apply to all channels.
+ * @param number_of_milliseconds How many milliseconds from now until the expire triggers.
+ * @return The actual number of channels this action is applied to on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_ExpireChannel(ALint which_channel, ALint number_of_milliseconds);
+/**
+ * Will cause a currently playing source to stop playing in the specified number of milliseconds.
+ * Will cause a currently playing source to stop playing in the specified number of milliseconds.
+ * This will override the value that was set when PlayChannelTimed or PlaySourceTimed was called
+ * or override any previous calls to ExpireChannel or ExpireSource.
+ * @param al_source The source to expire or 0 to apply to all sources.
+ * @param number_of_milliseconds How many milliseconds from now until the expire triggers.
+ * @return The actual number of sources this action is applied to on success or -1 on error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_ExpireSource(ALuint al_source, ALint number_of_milliseconds);
+
+/**
+ * @}
+ */
+
+/** 
+ * @defgroup VolumeAPI Volume and Fading
+ * @{
+ * Fade and volume functions directly call OpenAL functions related to AL_GAIN.
+ * These functions are provided mostly for those who just want to play audio but are not planning
+ * to use OpenAL features directly.
+ * If you are using OpenAL directly (e.g. for 3D effects), you may want to be careful about using these as
+ * they may fight/override values you directly set yourself.
+ */
+
+/**
+ * Similar to ALmixer_PlayChannelTimed except that sound volume fades in from the minimum volume to the current AL_GAIN over the specified amount of time.
+ * @see ALmixer_PlayChannelTimed.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_FadeInChannelTimed(ALint which_channel, ALmixer_Data* almixer_data, ALint number_of_loops, ALuint fade_ticks, ALint expire_ticks);
+
+#ifdef DOXYGEN_ONLY
+/**
+ * The same as ALmixer_FadeInChannelTimed, but the sound is played without time limits.
+ * @see ALmixer_FadeInChannelTimed, ALmixer_PlayChannel.
+ */ 
+ALint ALmixer_FadeInChannel(ALint which_channel, ALmixer_Data* almixer_data, ALint number_of_loops, ALuint fade_ticks);
+#else
+#define ALmixer_FadeInChannel(which_channel, almixer_data, number_of_loops, fade_ticks) ALmixer_FadeInChannelTimed(which_channel, almixer_data, number_of_loops, fade_ticks, -1)
+#endif
+
+/**
+ * Similar to ALmixer_PlaySourceTimed except that sound volume fades in from the minimum volume to the max volume over the specified amount of time.
+ * @see ALmixer_PlaySourceTimed.
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_FadeInSourceTimed(ALuint al_source, ALmixer_Data* almixer_data, ALint number_of_loops, ALuint fade_ticks, ALint expire_ticks);
+
+#ifdef DOXYGEN_ONLY
+/**
+ * The same as ALmixer_FadeInSourceTimed, but the sound is played without time limits.
+ * @see ALmixer_FadeInSourceTimed, ALmixer_PlaySource.
+ */ 
+extern ALuint ALmixer_FadeInSource(ALuint al_source, ALmixer_Data* almixer_data, ALint number_of_loops, ALuint fade_ticks);
+#else
+#define ALmixer_FadeInSource(al_source, almixer_data, number_of_loops, fade_ticks) ALmixer_FadeInSourceTimed(al_source, almixer_data, number_of_loops, fade_ticks, -1)
 #endif
-extern DECLSPEC void SDLCALL ALmixer_Output_Decoders();
-extern DECLSPEC void SDLCALL ALmixer_Output_OpenAL_Info();
+
+/**
+ * Fade out a current playing channel.
+ * Will fade out a currently playing channel over the specified period of time starting from now. 
+ * The volume will be changed from the current AL_GAIN level to the AL_MIN_GAIN. 
+ * The volume fade will interpolate over the specified period of time. 
+ * The playback will halt at the end of the time period.
+ * @param which_channel The channel to fade or -1 to fade all playing channels.
+ * @param fade_ticks In milliseconds, the amount of time the fade out should take to complete.
+ * @return Returns -1 on error or the number of channels faded.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_FadeOutChannel(ALint which_channel, ALuint fade_ticks);
+
+/**
+ * Fade out a current playing source.
+ * Will fade out a currently playing source over the specified period of time starting from now. 
+ * The volume will be changed from the current AL_GAIN level to the AL_MIN_GAIN. 
+ * The volume fade will interpolate over the specified period of time. 
+ * The playback will halt at the end of the time period.
+ * @param al_source The source to fade or -1 to fade all playing sources.
+ * @param fade_ticks In milliseconds, the amount of time the fade out should take to complete.
+ * @return Returns -1 on error or the number of sources faded.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_FadeOutSource(ALuint al_source, ALuint fade_ticks);
+
+/**
+ * Gradually changes the volume from the current AL_GAIN to the specified volume.
+ * Gradually changes the volume from the current AL_GAIN to the specified volume over the specified period of time.
+ * This is some times referred to as volume ducking. 
+ * Note that this function works for setting the volume higher as well as lower.
+ * @param which_channel The channel to fade or -1 to fade all playing channels.
+ * @param fade_ticks In milliseconds, the amount of time the volume change should take to complete.
+ * @param volume The volume to change to. Valid values are 0.0 to 1.0.
+ * @return Returns -1 on error or the number of channels faded.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_FadeChannel(ALint which_channel, ALuint fade_ticks, ALfloat volume);
+
+/**
+ * Gradually changes the volume from the current AL_GAIN to the specified volume.
+ * Gradually changes the volume from the current AL_GAIN to the specified volume over the specified period of time.
+ * This is some times referred to as volume ducking. 
+ * Note that this function works for setting the volume higher as well as lower.
+ * @param al_source The source to fade or -1 to fade all playing sources.
+ * @param fade_ticks In milliseconds, the amount of time the volume change should take to complete.
+ * @param volume The volume to change to. Valid values are 0.0 to 1.0.
+ * @return Returns -1 on error or the number of sources faded.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_FadeSource(ALuint al_source, ALuint fade_ticks, ALfloat volume);
+
+/**
+ * Sets the volume via the AL_GAIN source property.
+ * Sets the volume for a given channel via the AL_GAIN source property.
+ * @param which_channel The channel to set the volume to or -1 to set on all channels.
+ * @param volume The new volume to use. Valid values are 0.0 to 1.0.
+ * @return AL_TRUE on success or AL_FALSE on error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetVolumeChannel(ALint which_channel, ALfloat volume);
+
+/**
+ * Sets the volume via the AL_GAIN source property.
+ * Sets the volume for a given source via the AL_GAIN source property.
+ * @param al_source The source to set the volume to or 0 to set on all sources.
+ * @param volume The new volume to use. Valid values are 0.0 to 1.0.
+ * @return AL_TRUE on success or AL_FALSE on error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetVolumeSource(ALuint al_source, ALfloat volume);
+
+/**
+ * Gets the volume via the AL_GAIN source property.
+ * Gets the volume for a given channel via the AL_GAIN source property.
+ * @param which_channel The channel to get the volume from.
+ * -1 will return the average volume set across all channels.
+ * @return Returns the volume for the specified channel, or the average set volume for all channels, or -1.0 on error.
+ */
+extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetVolumeChannel(ALint which_channel);
+
+/**
+ * Gets the volume via the AL_GAIN source property.
+ * Gets the volume for a given source via the AL_GAIN source property.
+ * @param al_source The source to get the volume from.
+ * -1 will return the average volume set across all source.
+ * @return Returns the volume for the specified source, or the average set volume for all sources, or -1.0 on error.
+ */
+extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetVolumeSource(ALuint al_source);
+
+/**
+ * Sets the maximum volume via the AL_MAX_GAIN source property.
+ * Sets the maximum volume for a given channel via the AL_MAX_GAIN source property.
+ * Max volumes will be clamped to this value.
+ * @param which_channel The channel to set the volume to or -1 to set on all channels.
+ * @param volume The new volume to use. Valid values are 0.0 to 1.0.
+ * @return AL_TRUE on success or AL_FALSE on error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetMaxVolumeChannel(ALint which_channel, ALfloat volume);
+
+/**
+ * Sets the maximum volume via the AL_MAX_GAIN source property.
+ * Sets the maximum volume for a given source via the AL_MAX_GAIN source property.
+ * @param al_source The source to set the volume to or 0 to set on all sources.
+ * @param volume The new volume to use. Valid values are 0.0 to 1.0.
+ * @return AL_TRUE on success or AL_FALSE on error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetMaxVolumeSource(ALuint al_source, ALfloat volume);
+
+/**
+ * Gets the max volume via the AL_MAX_GAIN source property.
+ * Gets the max volume for a given channel via the AL_MAX_GAIN source property.
+ * @param which_channel The channel to get the volume from.
+ * -1 will return the average volume set across all channels.
+ * @return Returns the volume for the specified channel, or the average set volume for all channels, or -1.0 on error.
+ */
+extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetMaxVolumeChannel(ALint which_channel);
+
+/**
+ * Gets the maximum volume via the AL_MAX_GAIN source property.
+ * Gets the maximum volume for a given source via the AL_MAX_GAIN source property.
+ * @param al_source The source to set the volume to or 0 to set on all sources.
+ * 0 will return the average volume set across all channels.
+ * @return Returns the volume for the specified channel, or the average set volume for all channels, or -1.0 on error.
+ */
+extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetMaxVolumeSource(ALuint al_source);
+
+/**
+ * Sets the minimum volume via the AL_MIN_GAIN source property.
+ * Sets the minimum volume for a given channel via the AL_MIN_GAIN source property.
+ * Min volumes will be clamped to this value.
+ * @param which_channel The channel to set the volume to or -1 to set on all channels.
+ * @param volume The new volume to use. Valid values are 0.0 to 1.0.
+ * @return AL_TRUE on success or AL_FALSE on error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetMinVolumeChannel(ALint which_channel, ALfloat volume);
+
+/**
+ * Sets the minimum volume via the AL_MIN_GAIN source property.
+ * Sets the minimum volume for a given source via the AL_MIN_GAIN source property.
+ * @param al_source The source to set the volume to or 0 to set on all sources.
+ * @param volume The new volume to use. Valid values are 0.0 to 1.0.
+ * @return AL_TRUE on success or AL_FALSE on error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetMinVolumeSource(ALuint al_source, ALfloat volume);
 
-#if 0
+/**
+ * Gets the min volume via the AL_MIN_GAIN source property.
+ * Gets the min volume for a given channel via the AL_MIN_GAIN source property.
+ * @param which_channel The channel to get the volume from.
+ * -1 will return the average volume set across all channels.
+ * @return Returns the volume for the specified channel, or the average set volume for all channels, or -1.0 on error.
+ */
+extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetMinVolumeChannel(ALint which_channel);
+
+/**
+ * Gets the min volume via the AL_MIN_GAIN source property.
+ * Gets the min volume for a given source via the AL_MIN_GAIN source property.
+ * @param al_source The source to set the volume to or 0 to set on all sources.
+ * 0 will return the average volume set across all channels.
+ * @return Returns the volume for the specified channel, or the average set volume for all channels, or -1.0 on error.
+ */
+extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetMinVolumeSource(ALuint al_source);
+
+/**
+ * Sets the OpenAL listener AL_GAIN which can be thought of as the "master volume".
+ * Sets the OpenAL listener AL_GAIN which can be thought of as the "master volume".
+ * @param new_volume The new volume level to be set. Range is 0.0 to 1.0 where 1.0 is the max volume.
+ * @return AL_TRUE on success or AL_FALSE on an error.
+ */
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SetMasterVolume(ALfloat new_volume);
+
+/**
+ * Gets the OpenAL listener AL_GAIN which can be thought of as the "master volume".
+ * Gets the OpenAL listener AL_GAIN which can be thought of as the "master volume".
+ * @return The current volume level on the listener. -1.0 will be returned on an error.
+ */
+ extern ALMIXER_DECLSPEC ALfloat ALMIXER_CALL ALmixer_GetMasterVolume(void);
+
+/**
+ * @}
+ */
+ 
+/**
+ * @defgroup QueryAPI Query APIs
+ * @{
+ * Functions to query ALmixer.
+ */
+ 
+
+/**
+ * Returns true if the specified channel is currently playing or paused, 
+ * or if -1 is passed the number of channels that are currently playing or paused.
+ * @param which_channel The channel you want to know about or -1 to get the count of
+ * currently playing/paused channels.
+ * @return For a specific channel, 1 if the channel is playing or paused, 0 if not.
+ * Or returns the count of currently playing/paused channels.
+ * Or -1 on an error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_IsActiveChannel(ALint which_channel);
+
+/**
+ * Returns true if the specified source is currently playing or paused,
+ * or if -1 is passed the number of sources that are currently playing or paused.
+ * @param al_source The channel you want to know about or -1 to get the count of
+ * currently playing/paused sources.
+ * @return For a specific sources, 1 if the channel is playing or paused, 0 if not.
+ * Or returns the count of currently playing/paused sources.
+ * Or -1 on an error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_IsActiveSource(ALuint al_source);
+
+/**
+ * Returns true if the specified channel is currently playing. 
+ * or if -1 is passed the number of channels that are currently playing.
+ * @param which_channel The channel you want to know about or -1 to get the count of
+ * currently playing channels.
+ * @return For a specific channel, 1 if the channel is playing, 0 if not.
+ * Or returns the count of currently playing channels.
+ * Or -1 on an error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_IsPlayingChannel(ALint which_channel);
+
+/**
+ * Returns true if the specified sources is currently playing. 
+ * or if -1 is passed the number of sources that are currently playing.
+ * @param al_source The sources you want to know about or -1 to get the count of
+ * currently playing sources.
+ * @return For a specific source, 1 if the source is playing, 0 if not.
+ * Or returns the count of currently playing sources.
+ * Or -1 on an error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_IsPlayingSource(ALuint al_source);
+
+/**
+ * Returns true if the specified channel is currently paused. 
+ * or if -1 is passed the number of channels that are currently paused.
+ * @param which_channel The channel you want to know about or -1 to get the count of
+ * currently paused channels.
+ * @return For a specific channel, 1 if the channel is paused, 0 if not.
+ * Or returns the count of currently paused channels.
+ * Or -1 on an error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_IsPausedChannel(ALint which_channel);
+
+/**
+ * Returns true if the specified sources is currently paused. 
+ * or if -1 is passed the number of sources that are currently paused.
+ * @param al_source The source you want to know about or -1 to get the count of
+ * currently paused sources.
+ * @return For a specific source, 1 if the source is paused, 0 if not.
+ * Or returns the count of currently paused sources.
+ * Or -1 on an error.
+ */
+extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_IsPausedSource(ALuint al_source);
+
+/**
+ * Returns the number of channels that are currently available for playback (not playing, not paused).
+ * @return The number of channels that are currently free.
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_CountAllFreeChannels(void);
+
+/**
+ * Returns the number of channels that are currently available for playback (not playing, not paused),
+ * excluding the channels that have been reserved.
+ * @return The number of channels that are currently in free, excluding the channels that have been reserved.
+ * @see ALmixer_ReserveChannels
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_CountUnreservedFreeChannels(void);
+
+/**
+ * Returns the number of channels that are currently in use (playing/paused),
+ * excluding the channels that have been reserved.
+ * @return The number of channels that are currently in use.
+ * @see ALmixer_ReserveChannels
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_CountAllUsedChannels(void);
+
+/**
+ * Returns the number of channels that are currently in use (playing/paused),
+ * excluding the channels that have been reserved.
+ * @return The number of channels that are currently in use excluding the channels that have been reserved.
+ * @see ALmixer_ReserveChannels
+ */
+extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_CountUnreservedUsedChannels(void);
+
+
+#ifdef DOXYGEN_ONLY
+/**
+ * Returns the number of allocated channels.
+ * This is just a convenience alias to ALmixer_AllocateChannels(-1).
+ * @see ALmixer_AllocateChannels
+ */ 
+ALint ALmixer_CountTotalChannels(void);
+#else
+#define ALmixer_CountTotalChannels() ALmixer_AllocateChannels(-1)
+#endif
 
 
 
-extern DECLSPEC Uint32 SDLCALL ALmixer_Volume(Sint32 channel, Sint32 volume);
+
+#ifdef DOXYGEN_ONLY
+/**
+ * Returns the number of allocated channels.
+ * This is just a convenience alias to ALmixer_ReserveChannels(-1).
+ * @see ALmixer_ReserveChannels
+ */ 
+ALint ALmixer_CountReservedChannels(void);
+#else
+#define ALmixer_CountReservedChannels() ALmixer_ReserveChannels(-1)
+#endif
 
 
-/* I'm going to blindly throw in the Mixer effects sections and
- * hope they work.
- */
-#define ALmixer_EffectFunc_t 			Mix_EffectFunc_t
-#define ALmixer_EffectDone_t 			Mix_EffectDone_t
-/*
-#define ALmixer_RegisterEffect 			Mix_RegisterEffect
-#define ALmixer_UnregisterEffect			Mix_UnregisterEffect
-#define ALmixer_UnregisterAllEffects		Mix_RegisterEffect
-*/
-
-#define ALmixer_SetPostMix				Mix_SetPostMix
-#define ALmixer_SetPanning				Mix_SetPanning
-#define ALmixer_SetDistance 				Mix_SetDistance
-#define ALmixer_SetPosition				Mix_SetPosition
-#define ALmixer_SetReverseStereo			Mix_SetReverseStereo
-
-/* Unfortunately, effects have a nasty behavior of unregistering 
- * themselves after the channel finishes. This is incompatible
- * with the streaming system that this library uses.
- * Implementing a proper effects system will take more time.
- * For now, I need to be able to retrieve the playing data
- * for an oscilloscope, so I am hacking together a 1 effect
- * system. You can't have more than one.
+/**
+ * @}
  */
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_RegisterEffect(Sint32 chan, ALmixer_EffectFunc_t f, ALmixer_EffectDone_t d, void* arg);
-
-extern DECLSPEC Sint32 SDLCALL ALmixer_UnregisterEffect(Sint32 chan, ALmixer_EffectFunc_t f);
+/**
+ * @defgroup DebugAPI Debug APIs
+ * @{
+ * Functions for debugging purposes. These may be removed in future versions.
+ */
+ 
 
-extern DECLSPEC Sint32 SDLCALL ALmixer_UnregisterAllEffects(Sint32 chan);
+/* For testing */
+#if 0
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_OutputAttributes(void);
+#endif
+/** This function may be removed in the future. For debugging. Prints to stderr. Lists the decoders available. */ 
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_OutputDecoders(void);
+/** This function may be removed in the future. For debugging. Prints to stderr. */ 
+extern ALMIXER_DECLSPEC void ALMIXER_CALL ALmixer_OutputOpenALInfo(void);
 
-#endif
+/** This function may be removed in the future. Returns true if compiled with threads, false if not. */ 
+extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_CompiledWithThreadBackend(void);
+
+/**
+ * @}
+ */
 
 
 
@@ -449,9 +1508,7 @@
 #ifdef __cplusplus
 }
 #endif
-/*
-#include "close_code.h"
-*/
+
 
 #endif /* _SDL_ALMIXER_H_ */