diff SDL_ALmixer.h @ 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
line wrap: on
line diff
--- 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_ */