summaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alBuffer.h32
-rw-r--r--OpenAL32/Include/alError.h16
-rw-r--r--OpenAL32/Include/alExtension.h33
-rw-r--r--OpenAL32/Include/alListener.h23
-rw-r--r--OpenAL32/Include/alMain.h170
-rw-r--r--OpenAL32/Include/alSource.h71
-rw-r--r--OpenAL32/Include/alState.h14
-rw-r--r--OpenAL32/Include/alThunk.h42
-rw-r--r--OpenAL32/Include/alu.h26
-rw-r--r--OpenAL32/OpenAL32.c75
-rw-r--r--OpenAL32/alBuffer.c989
-rw-r--r--OpenAL32/alError.c61
-rw-r--r--OpenAL32/alExtension.c274
-rw-r--r--OpenAL32/alListener.c513
-rw-r--r--OpenAL32/alSource.c2108
-rw-r--r--OpenAL32/alState.c677
-rw-r--r--OpenAL32/alThunk.c108
17 files changed, 5232 insertions, 0 deletions
diff --git a/OpenAL32/Include/alBuffer.h b/OpenAL32/Include/alBuffer.h
new file mode 100644
index 00000000..06ffdea0
--- /dev/null
+++ b/OpenAL32/Include/alBuffer.h
@@ -0,0 +1,32 @@
+#ifndef _AL_BUFFER_H_
+#define _AL_BUFFER_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UNUSED 0
+#define PENDING 1
+#define PROCESSED 2
+
+typedef struct ALbuffer_struct
+{
+ ALenum format;
+ ALenum eOriginalFormat;
+ ALshort *data;
+ ALsizei size;
+ ALsizei frequency;
+ ALenum state;
+ ALuint refcount; // Number of sources using this buffer (deletion can only occur when this is 0)
+ struct ALbuffer_struct *next;
+} ALbuffer;
+
+ALvoid ReleaseALBuffers(ALvoid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alError.h b/OpenAL32/Include/alError.h
new file mode 100644
index 00000000..5cee8db8
--- /dev/null
+++ b/OpenAL32/Include/alError.h
@@ -0,0 +1,16 @@
+#ifndef _AL_ERROR_H_
+#define _AL_ERROR_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ALvoid alSetError(ALenum errorCode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alExtension.h b/OpenAL32/Include/alExtension.h
new file mode 100644
index 00000000..1f33f9af
--- /dev/null
+++ b/OpenAL32/Include/alExtension.h
@@ -0,0 +1,33 @@
+#ifndef _AL_EXTENSION_H_
+#define _AL_EXTENSION_H_
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ALextension_struct
+{
+ ALchar *extName;
+ ALvoid *address;
+} ALextension;
+
+typedef struct ALfunction_struct
+{
+ ALchar *funcName;
+ ALvoid *address;
+} ALfunction;
+
+typedef struct ALenum_struct
+{
+ ALchar *enumName;
+ ALenum value;
+} ALenums;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alListener.h b/OpenAL32/Include/alListener.h
new file mode 100644
index 00000000..2075e612
--- /dev/null
+++ b/OpenAL32/Include/alListener.h
@@ -0,0 +1,23 @@
+#ifndef _AL_LISTENER_H_
+#define _AL_LISTENER_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ALlistener_struct
+{
+ ALfloat Position[3];
+ ALfloat Velocity[3];
+ ALfloat Forward[3];
+ ALfloat Up[3];
+ ALfloat Gain;
+} ALlistener;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
new file mode 100644
index 00000000..3d34cf38
--- /dev/null
+++ b/OpenAL32/Include/alMain.h
@@ -0,0 +1,170 @@
+#ifndef AL_MAIN_H
+#define AL_MAIN_H
+
+#define AL_MAX_CHANNELS 4
+#define AL_MAX_SOURCES 32
+
+#include <string.h>
+
+#include "alu.h"
+
+#ifdef _WIN32
+#include <windows.h>
+//#define strcasecmp _stricmp
+
+#else
+
+#include <assert.h>
+#include <pthread.h>
+
+#define IsBadWritePtr(a,b) (0)
+
+typedef pthread_mutex_t CRITICAL_SECTION;
+static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
+{
+ assert(pthread_mutex_lock(cs) == 0);
+}
+static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
+{
+ assert(pthread_mutex_unlock(cs) == 0);
+}
+static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
+{
+ pthread_mutexattr_t attrib;
+
+ assert(pthread_mutexattr_init(&attrib) == 0);
+
+ assert(pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE) == 0);
+ assert(pthread_mutex_init(cs, &attrib) == 0);
+
+ pthread_mutexattr_destroy(&attrib);
+}
+
+static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
+{
+ assert(pthread_mutex_destroy(cs) == 0);
+}
+
+#define min(x,y) (((x)<(y))?(x):(y))
+#define max(x,y) (((x)>(y))?(x):(y))
+#endif
+
+#include "alBuffer.h"
+#include "alError.h"
+#include "alExtension.h"
+#include "alListener.h"
+#include "alSource.h"
+#include "alState.h"
+#include "alThunk.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define AL_FORMAT_MONO_IMA4 0x1300
+#define AL_FORMAT_STEREO_IMA4 0x1301
+// These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer
+// can use 4-channel formats
+#define AL_FORMAT_QUAD8 0x1204
+#define AL_FORMAT_QUAD16 0x1205
+
+#define SWMIXER_OUTPUT_RATE 44100
+//#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050)
+
+#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
+
+typedef struct {
+ ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
+ void (*ClosePlayback)(ALCdevice*);
+
+ ALCboolean (*OpenCapture)(ALCdevice*, const ALCchar*, ALCuint, ALCenum, ALCsizei);
+ void (*CloseCapture)(ALCdevice*);
+ void (*StartCapture)(ALCdevice*);
+ void (*StopCapture)(ALCdevice*);
+ void (*CaptureSamples)(ALCdevice*, void*, ALCuint);
+ ALCuint (*AvailableSamples)(ALCdevice*);
+} BackendFuncs;
+
+struct ALCdevice_struct
+{
+ ALboolean InUse;
+ ALboolean IsCaptureDevice;
+
+ ALuint Frequency;
+ ALuint UpdateFreq;
+ ALuint FrameSize;
+ ALuint Channels;
+ ALenum Format;
+
+ ALCchar szDeviceName[256];
+
+ // Maximum number of sources that can be created
+ ALuint MaxNoOfSources;
+
+ // Context created on this device
+ ALCcontext *Context;
+
+ BackendFuncs *Funcs;
+ void *ExtraData; // For the backend's use
+};
+
+#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
+#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
+#define ALCdevice_OpenCapture(a,b,c,d,e) ((a)->Funcs->OpenCapture((a), (b), (c), (d), (e)))
+#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))
+#define ALCdevice_StartCapture(a) ((a)->Funcs->StartCapture((a)))
+#define ALCdevice_StopCapture(a) ((a)->Funcs->StopCapture((a)))
+#define ALCdevice_CaptureSamples(a,b,c) ((a)->Funcs->CaptureSamples((a), (b), (c)))
+#define ALCdevice_AvailableSamples(a) ((a)->Funcs->AvailableSamples((a)))
+
+struct ALCcontext_struct
+{
+ ALlistener Listener;
+
+ ALsource *Source;
+ ALuint SourceCount;
+
+ ALenum LastError;
+ ALboolean InUse;
+
+ ALuint Frequency;
+
+ ALenum DistanceModel;
+
+ ALfloat DopplerFactor;
+ ALfloat DopplerVelocity;
+ ALfloat flSpeedOfSound;
+
+ ALint lNumMonoSources;
+ ALint lNumStereoSources;
+
+ ALCdevice *Device;
+ ALCchar ExtensionList[1024];
+
+ ALCcontext *next;
+};
+
+ALCchar *AppendDeviceList(char *name);
+ALCchar *AppendAllDeviceList(char *name);
+ALCchar *AppendCaptureDeviceList(char *name);
+
+ALCvoid SetALCError(ALenum errorCode);
+
+ALCvoid SuspendContext(ALCcontext *context);
+ALCvoid ProcessContext(ALCcontext *context);
+
+ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
+ALuint StopThread(ALvoid *thread);
+
+void ReadALConfig(void);
+void FreeALConfig(void);
+const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
+int GetConfigValueInt(const char *blockName, const char *keyName, int def);
+float GetConfigValueFloat(const char *blockName, const char *keyName, float def);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
new file mode 100644
index 00000000..499ddcf4
--- /dev/null
+++ b/OpenAL32/Include/alSource.h
@@ -0,0 +1,71 @@
+#ifndef _AL_SOURCE_H_
+#define _AL_SOURCE_H_
+
+#define AL_NUM_SOURCE_PARAMS 128
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ALbufferlistitem
+{
+ ALuint buffer;
+ ALuint bufferstate;
+ ALuint flag;
+ struct ALbufferlistitem *next;
+} ALbufferlistitem;
+
+typedef struct ALsource_struct
+{
+ ALfloat flPitch;
+ ALfloat flGain;
+ ALfloat flOuterGain;
+ ALfloat flMinGain;
+ ALfloat flMaxGain;
+ ALfloat flInnerAngle;
+ ALfloat flOuterAngle;
+ ALfloat flRefDistance;
+ ALfloat flMaxDistance;
+ ALfloat flRollOffFactor;
+ ALfloat vPosition[3];
+ ALfloat vVelocity[3];
+ ALfloat vOrientation[3];
+ ALboolean bHeadRelative;
+ ALboolean bLooping;
+
+ ALuint ulBufferID;
+
+ ALboolean inuse;
+ ALboolean play;
+ ALenum state;
+ ALuint position;
+ ALuint position_fraction;
+ struct ALbufferlistitem *queue; // Linked list of buffers in queue
+ ALuint BuffersInQueue; // Number of buffers in queue
+ ALuint BuffersProcessed; // Number of buffers already processed (played)
+
+ ALuint TotalBufferDataSize; // Total amount of data contained in the buffers queued for this source
+ ALuint BuffersPlayed; // Number of buffers played on this loop
+ ALuint BufferPosition; // Read position in audio data of current buffer
+
+ // Index to itself
+ ALuint source;
+
+ ALint lBytesPlayed;
+
+ ALint lOffset;
+ ALint lOffsetType;
+
+ // Source Type (Static, Streaming, or Undetermined)
+ ALint lSourceType;
+
+ struct ALsource_struct *next;
+} ALsource;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alState.h b/OpenAL32/Include/alState.h
new file mode 100644
index 00000000..332176b0
--- /dev/null
+++ b/OpenAL32/Include/alState.h
@@ -0,0 +1,14 @@
+#ifndef _AL_STATE_H_
+#define _AL_STATE_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alThunk.h b/OpenAL32/Include/alThunk.h
new file mode 100644
index 00000000..2ed32871
--- /dev/null
+++ b/OpenAL32/Include/alThunk.h
@@ -0,0 +1,42 @@
+#ifndef _AL_THUNK_H_
+#define _AL_THUNK_H_
+
+#include "config.h"
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (SIZEOF_VOIDP > SIZEOF_UINT)
+
+void alThunkInit(void);
+void alThunkExit(void);
+ALuint alThunkAddEntry(ALvoid * ptr);
+void alThunkRemoveEntry(ALuint index);
+ALvoid *alThunkLookupEntry(ALuint index);
+
+#define ALTHUNK_INIT() alThunkInit()
+#define ALTHUNK_EXIT() alThunkExit()
+#define ALTHUNK_ADDENTRY(p) alThunkAddEntry(p)
+#define ALTHUNK_REMOVEENTRY(i) alThunkRemoveEntry(i)
+#define ALTHUNK_LOOKUPENTRY(i) alThunkLookupEntry(i)
+
+#else
+
+#define ALTHUNK_INIT()
+#define ALTHUNK_EXIT()
+#define ALTHUNK_ADDENTRY(p) ((ALuint)p)
+#define ALTHUNK_REMOVEENTRY(i)
+#define ALTHUNK_LOOKUPENTRY(i) ((ALvoid*)(i))
+
+#endif // (SIZEOF_VOIDP > SIZEOF_INT)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_AL_THUNK_H_
+
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
new file mode 100644
index 00000000..e4fe0dc3
--- /dev/null
+++ b/OpenAL32/Include/alu.h
@@ -0,0 +1,26 @@
+#ifndef _ALU_H_
+#define _ALU_H_
+
+#define BUFFERSIZE 48000
+#define FRACTIONBITS 14
+#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
+#define MAX_PITCH 4
+#define OUTPUTCHANNELS 4
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__inline ALuint aluBytesFromFormat(ALenum format);
+__inline ALuint aluChannelsFromFormat(ALenum format);
+ALvoid aluMixData(ALCcontext *context,ALvoid *buffer,ALsizei size,ALenum format);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/OpenAL32/OpenAL32.c b/OpenAL32/OpenAL32.c
new file mode 100644
index 00000000..20ca14f9
--- /dev/null
+++ b/OpenAL32/OpenAL32.c
@@ -0,0 +1,75 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "alMain.h"
+#include "alBuffer.h"
+#include "alThunk.h"
+
+CRITICAL_SECTION g_mutex;
+
+#ifdef _WIN32
+BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
+{
+ (void)lpReserved;
+
+ // Perform actions based on the reason for calling.
+ switch(ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hModule);
+ InitializeCriticalSection(&g_mutex);
+ ALTHUNK_INIT();
+ ReadALConfig();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ ReleaseALBuffers();
+ FreeALConfig();
+ ALTHUNK_EXIT();
+ DeleteCriticalSection(&g_mutex);
+ break;
+ }
+ return TRUE;
+}
+#else
+static void my_init() __attribute__((constructor));
+static void my_init()
+{
+ static ALenum once = AL_FALSE;
+ if(once) return;
+ once = AL_TRUE;
+
+ InitializeCriticalSection(&g_mutex);
+ ALTHUNK_INIT();
+ ReadALConfig();
+}
+static void my_deinit() __attribute__((destructor));
+static void my_deinit()
+{
+ static ALenum once = AL_FALSE;
+ if(once) return;
+ once = AL_TRUE;
+
+ ReleaseALBuffers();
+ FreeALConfig();
+ ALTHUNK_EXIT();
+ DeleteCriticalSection(&g_mutex);
+}
+#endif
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
new file mode 100644
index 00000000..53ee128a
--- /dev/null
+++ b/OpenAL32/alBuffer.c
@@ -0,0 +1,989 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alBuffer.h"
+
+#ifdef _DEBUG
+ char szDebug[256];
+#endif
+
+/*
+ * AL Buffer Functions
+ *
+ * AL Buffers are shared amoung Contexts, so we store the list of generated Buffers
+ * as a global variable in this module. (A valid context is not required to make
+ * AL Buffer function calls
+ *
+ */
+
+/*
+* Global Variables
+*/
+
+static ALbuffer *g_pBuffers = NULL; // Linked List of Buffers
+static ALuint g_uiBufferCount = 0; // Buffer Count
+
+static const long g_IMAStep_size[89]={ // IMA ADPCM Stepsize table
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
+ 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
+ 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
+ 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
+ 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442,11487,12635,13899,
+ 15289,16818,18500,20350,22358,24633,27086,29794,32767
+};
+
+static const long g_IMACodeword_4[16]={ // IMA4 ADPCM Codeword decode table
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ -1,-3,-5,-7,-9,-11,-13,-15,
+};
+
+static const long g_IMAIndex_adjust_4[16]={ // IMA4 ADPCM Step index adjust decode table
+ -1,-1,-1,-1, 2, 4, 6, 8,
+ -1,-1,-1,-1, 2, 4, 6, 8
+};
+
+/*
+* alGenBuffers(ALsizei n, ALuint *puiBuffers)
+*
+* Generates n AL Buffers, and stores the Buffers Names in the array pointed to by puiBuffers
+*/
+ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
+{
+ ALCcontext *Context;
+ ALsizei i=0;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ // Check that we are actually generation some Buffers
+ if (n > 0)
+ {
+ // Check the pointer is valid (and points to enough memory to store Buffer Names)
+ if (!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
+ {
+ ALbuffer **list = &g_pBuffers;
+ while(*list)
+ list = &(*list)->next;
+
+ // Create all the new Buffers
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALbuffer));
+ if(*list)
+ {
+ puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->state = UNUSED;
+ g_uiBufferCount++;
+ i++;
+
+ list = &(*list)->next;
+ }
+ }
+
+ // If we didn't create all the Buffers, we must have run out of memory
+ if (i != n)
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ // Pointer does not point to enough memory to write Buffer names
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+
+ ProcessContext(Context);
+
+ return;
+}
+
+/*
+* alDeleteBuffers(ALsizei n, ALuint *puiBuffers)
+*
+* Deletes the n AL Buffers pointed to by puiBuffers
+*/
+ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
+{
+ ALCcontext *Context;
+ ALbuffer *ALBuf;
+ ALsizei i;
+ ALboolean bFailed = AL_FALSE;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ // Check we are actually Deleting some Buffers
+ if (n >= 0)
+ {
+ if ((ALuint)n <= g_uiBufferCount)
+ {
+ // Check that all the buffers are valid and can actually be deleted
+ for (i = 0; i < n; i++)
+ {
+ // Check for valid Buffer ID (can be NULL buffer)
+ if (alIsBuffer(puiBuffers[i]))
+ {
+ // If not the NULL buffer, check that the reference count is 0
+ ALBuf = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
+ if (ALBuf)
+ {
+ if (ALBuf->refcount != 0)
+ {
+ // Buffer still in use, cannot be deleted
+ alSetError(AL_INVALID_OPERATION);
+ bFailed = AL_TRUE;
+ }
+ }
+ }
+ else
+ {
+ // Invalid Buffer
+ alSetError(AL_INVALID_NAME);
+ bFailed = AL_TRUE;
+ }
+ }
+
+ // If all the Buffers were valid (and have Reference Counts of 0), then we can delete them
+ if (!bFailed)
+ {
+ for (i = 0; i < n; i++)
+ {
+ ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
+ if (ALBuf)
+ {
+ ALbuffer **list = &g_pBuffers;
+ while(*list && *list != ALBuf)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+
+ // Release the memory used to store audio data
+ free(ALBuf->data);
+
+ // Release buffer structure
+ ALTHUNK_REMOVEENTRY(puiBuffers[i]);
+ memset(ALBuf, 0, sizeof(ALbuffer));
+ g_uiBufferCount--;
+ free(ALBuf);
+ }
+ }
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+
+ return;
+
+}
+
+/*
+* alIsBuffer(ALuint uiBuffer)
+*
+* Checks if ulBuffer is a valid Buffer Name
+*/
+ALAPI ALboolean ALAPIENTRY alIsBuffer(ALuint uiBuffer)
+{
+ ALCcontext *Context;
+ ALboolean result=AL_FALSE;
+ ALbuffer *ALBuf;
+ ALbuffer *TgtALBuf;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (uiBuffer)
+ {
+ TgtALBuf = (ALbuffer *)ALTHUNK_LOOKUPENTRY(uiBuffer);
+
+ // Check through list of generated buffers for uiBuffer
+ ALBuf = g_pBuffers;
+ while (ALBuf)
+ {
+ if (ALBuf == TgtALBuf)
+ {
+ result = AL_TRUE;
+ break;
+ }
+
+ ALBuf = ALBuf->next;
+ }
+ }
+ else
+ {
+ result = AL_TRUE;
+ }
+
+
+ ProcessContext(Context);
+
+ return result;
+}
+
+/*
+* alBufferData(ALuint buffer,ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
+*
+* Fill buffer with audio data
+*/
+ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq)
+{
+ ALuint *IMAData,IMACode;
+ ALCcontext *Context;
+ ALint Sample,Index;
+ ALint LeftSample,LeftIndex;
+ ALint RightSample,RightIndex;
+ ALuint LeftIMACode,RightIMACode;
+ ALbuffer *ALBuf;
+ ALsizei i,j,k;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+ if ((ALBuf->refcount==0)&&(data))
+ {
+ switch(format)
+ {
+ case AL_FORMAT_MONO8:
+ if ((size%1) == 0)
+ {
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples (16 bytes)
+ ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_MONO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_MONO8;
+ for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
+ ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
+ memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 16);
+ ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_MONO16:
+ if ((size%2) == 0)
+ {
+ // Allocate 8 extra samples (16 bytes)
+ ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_MONO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_MONO16;
+ memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
+ memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 16);
+ ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_STEREO8:
+ if ((size%2) == 0)
+ {
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples (32 bytes)
+ ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_STEREO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_STEREO8;
+ for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
+ ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
+ memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 32);
+ ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_STEREO16:
+ if ((size%4) == 0)
+ {
+ // Allocate 8 extra samples (32 bytes)
+ ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_STEREO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_STEREO16;
+ memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
+ memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 32);
+ ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_MONO_IMA4:
+ // Here is where things vary:
+ // nVidia and Apple use 64+1 samples per block => block_size=36 bytes
+ // Most PC sound software uses 2040+1 samples per block -> block_size=1024 bytes
+ if ((size%36) == 0)
+ {
+ // Allocate 8 extra samples (16 bytes)
+ ALBuf->data=realloc(ALBuf->data,16+(size/36)*(65*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_MONO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_MONO_IMA4;
+ IMAData=(ALuint *)data;
+ for (i=0;i<size/36;i++)
+ {
+ Sample=((ALshort *)IMAData)[0];
+ Index=((ALshort *)IMAData)[1];
+
+ Index=Index<0?0:Index;
+ Index=Index>88?88:Index;
+
+ ALBuf->data[i*65]=(short)Sample;
+
+ IMAData++;
+
+ for (j=1;j<65;j+=8)
+ {
+ IMACode=*IMAData;
+ for (k=0;k<8;k+=2)
+ {
+ Sample+=((g_IMAStep_size[Index]*g_IMACodeword_4[IMACode&15])/8);
+ Index+=g_IMAIndex_adjust_4[IMACode&15];
+ if (Sample<-32768) Sample=-32768;
+ else if (Sample>32767) Sample=32767;
+ if (Index<0) Index=0;
+ else if (Index>88) Index=88;
+ ALBuf->data[i*65+j+k]=(short)Sample;
+ IMACode>>=4;
+
+ Sample+=((g_IMAStep_size[Index]*g_IMACodeword_4[IMACode&15])/8);
+ Index+=g_IMAIndex_adjust_4[IMACode&15];
+ if (Sample<-32768) Sample=-32768;
+ else if (Sample>32767) Sample=32767;
+ if (Index<0) Index=0;
+ else if (Index>88) Index=88;
+ ALBuf->data[i*65+j+k+1]=(short)Sample;
+ IMACode>>=4;
+ }
+ IMAData++;
+ }
+ }
+ memset(&(ALBuf->data[(size/36*65)]), 0, 16);
+ ALBuf->size=size/36*65*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_FORMAT_STEREO_IMA4:
+ // Here is where things vary:
+ // nVidia and Apple use 64+1 samples per channel per block => block_size=72 bytes
+ // Most PC sound software uses 2040+1 samples per channel per block -> block_size=2048 bytes
+ if ((size%72) == 0)
+ {
+ // Allocate 8 extra samples (32 bytes)
+ ALBuf->data=realloc(ALBuf->data,32+(size/72)*(2*65*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ ALBuf->format = AL_FORMAT_STEREO16;
+ ALBuf->eOriginalFormat = AL_FORMAT_STEREO_IMA4;
+ IMAData=(ALuint *)data;
+ for (i=0;i<size/72;i++)
+ {
+ LeftSample=((ALshort *)IMAData)[0];
+ LeftIndex=((ALshort *)IMAData)[1];
+
+ LeftIndex=LeftIndex<0?0:LeftIndex;
+ LeftIndex=LeftIndex>88?88:LeftIndex;
+
+ ALBuf->data[i*2*65]=(short)LeftSample;
+
+ IMAData++;
+
+ RightSample=((ALshort *)IMAData)[0];
+ RightIndex=((ALshort *)IMAData)[1];
+
+ RightIndex=RightIndex<0?0:RightIndex;
+ RightIndex=RightIndex>88?88:RightIndex;
+
+ ALBuf->data[i*2*65+1]=(short)RightSample;
+
+ IMAData++;
+
+ for (j=2;j<130;j+=16)
+ {
+ LeftIMACode=IMAData[0];
+ RightIMACode=IMAData[1];
+ for (k=0;k<16;k+=4)
+ {
+ LeftSample+=((g_IMAStep_size[LeftIndex]*g_IMACodeword_4[LeftIMACode&15])/8);
+ LeftIndex+=g_IMAIndex_adjust_4[LeftIMACode&15];
+ if (LeftSample<-32768) LeftSample=-32768;
+ else if (LeftSample>32767) LeftSample=32767;
+ if (LeftIndex<0) LeftIndex=0;
+ else if (LeftIndex>88) LeftIndex=88;
+ ALBuf->data[i*2*65+j+k]=(short)LeftSample;
+ LeftIMACode>>=4;
+
+ RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8);
+ RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15];
+ if (RightSample<-32768) RightSample=-32768;
+ else if (RightSample>32767) RightSample=32767;
+ if (RightIndex<0) RightIndex=0;
+ else if (RightIndex>88) RightIndex=88;
+ ALBuf->data[i*2*65+j+k+1]=(short)RightSample;
+ RightIMACode>>=4;
+
+ LeftSample+=((g_IMAStep_size[LeftIndex]*g_IMACodeword_4[LeftIMACode&15])/8);
+ LeftIndex+=g_IMAIndex_adjust_4[LeftIMACode&15];
+ if (LeftSample<-32768) LeftSample=-32768;
+ else if (LeftSample>32767) LeftSample=32767;
+ if (LeftIndex<0) LeftIndex=0;
+ else if (LeftIndex>88) LeftIndex=88;
+ ALBuf->data[i*2*65+j+k+2]=(short)LeftSample;
+ LeftIMACode>>=4;
+
+ RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8);
+ RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15];
+ if (RightSample<-32768) RightSample=-32768;
+ else if (RightSample>32767) RightSample=32767;
+ if (RightIndex<0) RightIndex=0;
+ else if (RightIndex>88) RightIndex=88;
+ ALBuf->data[i*2*65+j+k+3]=(short)RightSample;
+ RightIMACode>>=4;
+ }
+ IMAData+=2;
+ }
+ }
+ memset(&(ALBuf->data[(size/72*2*65)]), 0, 32);
+ ALBuf->size=size/72*2*65*sizeof(ALshort);
+ ALBuf->frequency=freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // Buffer is in use, or data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // Invalid Buffer Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(Context);
+}
+
+
+ALAPI void ALAPIENTRY alBufferf(ALuint buffer, ALenum eParam, ALfloat flValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)flValue;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBuffer3f(ALuint buffer, ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)flValue1;
+ (void)flValue2;
+ (void)flValue3;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBufferfv(ALuint buffer, ALenum eParam, const ALfloat* flValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)flValues;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBufferi(ALuint buffer, ALenum eParam, ALint lValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)lValue;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBuffer3i( ALuint buffer, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)lValue1;
+ (void)lValue2;
+ (void)lValue3;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ (void)plValues;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pflValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (pflValue)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBuffer3f(ALuint buffer, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if ((pflValue1) && (pflValue2) && (pflValue3))
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBufferfv(ALuint buffer, ALenum eParam, ALfloat* pflValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValue)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (plValue)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch (eParam)
+ {
+ case AL_FREQUENCY:
+ *plValue = pBuffer->frequency;
+ break;
+
+ case AL_BITS:
+ *plValue= (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_STEREO8))?8:16);
+ break;
+
+ case AL_CHANNELS:
+ *plValue = (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_MONO16))?1:2);
+ break;
+
+ case AL_SIZE:
+ *plValue = pBuffer->size;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBuffer3i(ALuint buffer, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if ((plValue1) && (plValue2) && (plValue3))
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch(eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALbuffer *pBuffer;
+
+ pContext = alcGetCurrentContext();
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ if (alIsBuffer(buffer) && (buffer != 0))
+ {
+ pBuffer = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
+
+ switch (eParam)
+ {
+ case AL_FREQUENCY:
+ case AL_BITS:
+ case AL_CHANNELS:
+ case AL_SIZE:
+ alGetBufferi(buffer, eParam, plValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+}
+
+
+/*
+* ReleaseALBuffers()
+*
+* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
+*/
+ALvoid ReleaseALBuffers(ALvoid)
+{
+ ALbuffer *ALBuffer;
+ ALbuffer *ALBufferTemp;
+
+#ifdef _DEBUG
+ if(g_uiBufferCount > 0)
+ {
+ sprintf(szDebug, "OpenAL32 : DllMain() %d Buffer(s) NOT deleted\n", g_uiBufferCount);
+ OutputDebugString(szDebug);
+ }
+#endif
+
+ ALBuffer = g_pBuffers;
+ while(ALBuffer)
+ {
+ // Release sample data
+ free(ALBuffer->data);
+
+ // Release Buffer structure
+ ALBufferTemp = ALBuffer;
+ ALBuffer = ALBuffer->next;
+ memset(ALBufferTemp, 0, sizeof(ALbuffer));
+ free(ALBufferTemp);
+ }
+ g_pBuffers = NULL;
+ g_uiBufferCount = 0;
+}
diff --git a/OpenAL32/alError.c b/OpenAL32/alError.c
new file mode 100644
index 00000000..df5c16e4
--- /dev/null
+++ b/OpenAL32/alError.c
@@ -0,0 +1,61 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "alMain.h"
+#include "AL/alc.h"
+#include "alError.h"
+
+ALAPI ALenum ALAPIENTRY alGetError(ALvoid)
+{
+ ALCcontext *Context;
+ ALenum errorCode;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (Context)
+ {
+ errorCode = Context->LastError;
+ Context->LastError = AL_NO_ERROR;
+ }
+ else
+ {
+ errorCode = AL_INVALID_OPERATION;
+ }
+
+ ProcessContext(Context);
+
+ return errorCode;
+}
+
+ALvoid alSetError(ALenum errorCode)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (Context)
+ {
+ Context->LastError=errorCode;
+ }
+
+ ProcessContext(Context);
+}
diff --git a/OpenAL32/alExtension.c b/OpenAL32/alExtension.c
new file mode 100644
index 00000000..1d0928d2
--- /dev/null
+++ b/OpenAL32/alExtension.c
@@ -0,0 +1,274 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "alExtension.h"
+#include "alError.h"
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+static ALfunction function[]= {
+ { "alEnable", (ALvoid *) alEnable },
+ { "alDisable", (ALvoid *) alDisable },
+ { "alIsEnabled", (ALvoid *) alIsEnabled },
+ { "alGetString", (ALvoid *) alGetString },
+ { "alGetBooleanv", (ALvoid *) alGetBooleanv },
+ { "alGetIntegerv", (ALvoid *) alGetIntegerv },
+ { "alGetFloatv", (ALvoid *) alGetFloatv },
+ { "alGetDoublev", (ALvoid *) alGetDoublev },
+ { "alGetBoolean", (ALvoid *) alGetBoolean },
+ { "alGetInteger", (ALvoid *) alGetInteger },
+ { "alGetFloat", (ALvoid *) alGetFloat },
+ { "alGetDouble", (ALvoid *) alGetDouble },
+ { "alGetError", (ALvoid *) alGetError },
+ { "alIsExtensionPresent", (ALvoid *) alIsExtensionPresent },
+ { "alGetProcAddress", (ALvoid *) alGetProcAddress },
+ { "alGetEnumValue", (ALvoid *) alGetEnumValue },
+ { "alListenerf", (ALvoid *) alListenerf },
+ { "alListener3f", (ALvoid *) alListener3f },
+ { "alListenerfv", (ALvoid *) alListenerfv },
+ { "alListeneri", (ALvoid *) alListeneri },
+ { "alListener3i", (ALvoid *) alListener3i },
+ { "alListeneriv", (ALvoid *) alListeneriv },
+ { "alGetListenerf", (ALvoid *) alGetListenerf },
+ { "alGetListener3f", (ALvoid *) alGetListener3f },
+ { "alGetListenerfv", (ALvoid *) alGetListenerfv },
+ { "alGetListeneri", (ALvoid *) alGetListeneri },
+ { "alGetListener3i", (ALvoid *) alGetListener3i },
+ { "alGetListeneriv", (ALvoid *) alGetListeneriv },
+ { "alGenSources", (ALvoid *) alGenSources },
+ { "alDeleteSources", (ALvoid *) alDeleteSources },
+ { "alIsSource", (ALvoid *) alIsSource },
+ { "alSourcef", (ALvoid *) alSourcef },
+ { "alSource3f", (ALvoid *) alSource3f },
+ { "alSourcefv", (ALvoid *) alSourcefv },
+ { "alSourcei", (ALvoid *) alSourcei },
+ { "alSource3i", (ALvoid *) alSource3i },
+ { "alSourceiv", (ALvoid *) alSourceiv },
+ { "alGetSourcef", (ALvoid *) alGetSourcef },
+ { "alGetSource3f", (ALvoid *) alGetSource3f },
+ { "alGetSourcefv", (ALvoid *) alGetSourcefv },
+ { "alGetSourcei", (ALvoid *) alGetSourcei },
+ { "alGetSource3i", (ALvoid *) alGetSource3i },
+ { "alGetSourceiv", (ALvoid *) alGetSourceiv },
+ { "alSourcePlayv", (ALvoid *) alSourcePlayv },
+ { "alSourceStopv", (ALvoid *) alSourceStopv },
+ { "alSourceRewindv", (ALvoid *) alSourceRewindv },
+ { "alSourcePausev", (ALvoid *) alSourcePausev },
+ { "alSourcePlay", (ALvoid *) alSourcePlay },
+ { "alSourceStop", (ALvoid *) alSourceStop },
+ { "alSourceRewind", (ALvoid *) alSourceRewind },
+ { "alSourcePause", (ALvoid *) alSourcePause },
+ { "alSourceQueueBuffers", (ALvoid *) alSourceQueueBuffers },
+ { "alSourceUnqueueBuffers", (ALvoid *) alSourceUnqueueBuffers },
+ { "alGenBuffers", (ALvoid *) alGenBuffers },
+ { "alDeleteBuffers", (ALvoid *) alDeleteBuffers },
+ { "alIsBuffer", (ALvoid *) alIsBuffer },
+ { "alBufferData", (ALvoid *) alBufferData },
+ { "alBufferf", (ALvoid *) alBufferf },
+ { "alBuffer3f", (ALvoid *) alBuffer3f },
+ { "alBufferfv", (ALvoid *) alBufferfv },
+ { "alBufferi", (ALvoid *) alBufferi },
+ { "alBuffer3i", (ALvoid *) alBuffer3i },
+ { "alBufferiv", (ALvoid *) alBufferiv },
+ { "alGetBufferf", (ALvoid *) alGetBufferf },
+ { "alGetBuffer3f", (ALvoid *) alGetBuffer3f },
+ { "alGetBufferfv", (ALvoid *) alGetBufferfv },
+ { "alGetBufferi", (ALvoid *) alGetBufferi },
+ { "alGetBuffer3i", (ALvoid *) alGetBuffer3i },
+ { "alGetBufferiv", (ALvoid *) alGetBufferiv },
+ { "alDopplerFactor", (ALvoid *) alDopplerFactor },
+ { "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
+ { "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
+ { "alDistanceModel", (ALvoid *) alDistanceModel },
+ { NULL, (ALvoid *) NULL } };
+
+static ALenums enumeration[]={
+ // Types
+ { (ALchar *)"AL_INVALID", AL_INVALID },
+ { (ALchar *)"AL_NONE", AL_NONE },
+ { (ALchar *)"AL_FALSE", AL_FALSE },
+ { (ALchar *)"AL_TRUE", AL_TRUE },
+
+ // Source and Listener Properties
+ { (ALchar *)"AL_SOURCE_RELATIVE", AL_SOURCE_RELATIVE },
+ { (ALchar *)"AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE },
+ { (ALchar *)"AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE },
+ { (ALchar *)"AL_PITCH", AL_PITCH },
+ { (ALchar *)"AL_POSITION", AL_POSITION },
+ { (ALchar *)"AL_DIRECTION", AL_DIRECTION },
+ { (ALchar *)"AL_VELOCITY", AL_VELOCITY },
+ { (ALchar *)"AL_LOOPING", AL_LOOPING },
+ { (ALchar *)"AL_BUFFER", AL_BUFFER },
+ { (ALchar *)"AL_GAIN", AL_GAIN },
+ { (ALchar *)"AL_MIN_GAIN", AL_MIN_GAIN },
+ { (ALchar *)"AL_MAX_GAIN", AL_MAX_GAIN },
+ { (ALchar *)"AL_ORIENTATION", AL_ORIENTATION },
+ { (ALchar *)"AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE },
+ { (ALchar *)"AL_ROLLOFF_FACTOR", AL_ROLLOFF_FACTOR },
+ { (ALchar *)"AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN },
+ { (ALchar *)"AL_MAX_DISTANCE", AL_MAX_DISTANCE },
+ { (ALchar *)"AL_SEC_OFFSET", AL_SEC_OFFSET },
+ { (ALchar *)"AL_SAMPLE_OFFSET", AL_SAMPLE_OFFSET },
+ { (ALchar *)"AL_BYTE_OFFSET", AL_BYTE_OFFSET },
+ { (ALchar *)"AL_SOURCE_TYPE", AL_SOURCE_TYPE },
+ { (ALchar *)"AL_STATIC", AL_STATIC },
+ { (ALchar *)"AL_STREAMING", AL_STREAMING },
+ { (ALchar *)"AL_UNDETERMINED", AL_UNDETERMINED },
+
+ // Source State information
+ { (ALchar *)"AL_SOURCE_STATE", AL_SOURCE_STATE },
+ { (ALchar *)"AL_INITIAL", AL_INITIAL },
+ { (ALchar *)"AL_PLAYING", AL_PLAYING },
+ { (ALchar *)"AL_PAUSED", AL_PAUSED },
+ { (ALchar *)"AL_STOPPED", AL_STOPPED },
+
+ // Queue information
+ { (ALchar *)"AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED },
+ { (ALchar *)"AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED },
+
+ // Buffer Formats
+ { (ALchar *)"AL_FORMAT_MONO8", AL_FORMAT_MONO8 },
+ { (ALchar *)"AL_FORMAT_MONO16", AL_FORMAT_MONO16 },
+ { (ALchar *)"AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 },
+ { (ALchar *)"AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 },
+ { (ALchar *)"AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 },
+ { (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 },
+ { (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 },
+ { (ALchar *)"AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 },
+
+ // Buffer attributes
+ { (ALchar *)"AL_FREQUENCY", AL_FREQUENCY },
+ { (ALchar *)"AL_BITS", AL_BITS },
+ { (ALchar *)"AL_CHANNELS", AL_CHANNELS },
+ { (ALchar *)"AL_SIZE", AL_SIZE },
+
+ // Buffer States (not supported yet)
+ { (ALchar *)"AL_UNUSED", AL_UNUSED },
+ { (ALchar *)"AL_PENDING", AL_PENDING },
+ { (ALchar *)"AL_PROCESSED", AL_PROCESSED },
+
+ // AL Error Messages
+ { (ALchar *)"AL_NO_ERROR", AL_NO_ERROR },
+ { (ALchar *)"AL_INVALID_NAME", AL_INVALID_NAME },
+ { (ALchar *)"AL_INVALID_ENUM", AL_INVALID_ENUM },
+ { (ALchar *)"AL_INVALID_VALUE", AL_INVALID_VALUE },
+ { (ALchar *)"AL_INVALID_OPERATION", AL_INVALID_OPERATION },
+ { (ALchar *)"AL_OUT_OF_MEMORY", AL_OUT_OF_MEMORY },
+
+ // Context strings
+ { (ALchar *)"AL_VENDOR", AL_VENDOR },
+ { (ALchar *)"AL_VERSION", AL_VERSION },
+ { (ALchar *)"AL_RENDERER", AL_RENDERER },
+ { (ALchar *)"AL_EXTENSIONS", AL_EXTENSIONS },
+
+ // Global states
+ { (ALchar *)"AL_DOPPLER_FACTOR", AL_DOPPLER_FACTOR },
+ { (ALchar *)"AL_DOPPLER_VELOCITY", AL_DOPPLER_VELOCITY },
+ { (ALchar *)"AL_DISTANCE_MODEL", AL_DISTANCE_MODEL },
+ { (ALchar *)"AL_SPEED_OF_SOUND", AL_SPEED_OF_SOUND },
+
+ // Distance Models
+ { (ALchar *)"AL_INVERSE_DISTANCE", AL_INVERSE_DISTANCE },
+ { (ALchar *)"AL_INVERSE_DISTANCE_CLAMPED", AL_INVERSE_DISTANCE_CLAMPED },
+ { (ALchar *)"AL_LINEAR_DISTANCE", AL_LINEAR_DISTANCE },
+ { (ALchar *)"AL_LINEAR_DISTANCE_CLAMPED", AL_LINEAR_DISTANCE_CLAMPED },
+ { (ALchar *)"AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE },
+ { (ALchar *)"AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED },
+
+ // Default
+ { (ALchar *)NULL, (ALenum ) 0 } };
+
+
+
+ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
+{
+ ALboolean bIsSupported = AL_FALSE;
+ ALCcontext *pContext;
+ char *ptr, *ext;
+
+ if (!extName)
+ {
+ alSetError(AL_INVALID_VALUE);
+ return AL_FALSE;
+ }
+
+ pContext = alcGetCurrentContext();
+ if(!pContext)
+ {
+ alSetError(AL_INVALID_OPERATION);
+ return AL_FALSE;
+ }
+
+ ext = strdup(extName);
+ ptr = ext;
+ do {
+ *ptr = toupper(*ptr);
+ } while(*(ptr++));
+
+ SuspendContext(pContext);
+
+ ptr = pContext->ExtensionList;
+ while((ptr=strstr(ptr, ext)) != NULL)
+ {
+ if(ptr == pContext->ExtensionList || ptr[-1] == ' ')
+ {
+ char e = ptr[strlen(ext)];
+ if(e == ' ' || e == 0)
+ {
+ bIsSupported = AL_TRUE;
+ break;
+ }
+ }
+ ptr++;
+ }
+
+ ProcessContext(pContext);
+
+ free(ext);
+ return bIsSupported;
+}
+
+
+ALAPI ALvoid * ALAPIENTRY alGetProcAddress(const ALchar *funcName)
+{
+ ALsizei i = 0;
+
+ while(function[i].funcName &&
+ strcmp((char*)function[i].funcName, (char*)funcName) != 0)
+ i++;
+
+ return function[i].address;
+}
+
+/* NOTE: This function must be able to run without a context! */
+ALAPI ALenum ALAPIENTRY alGetEnumValue(const ALchar *enumName)
+{
+ ALsizei i = 0;
+
+ while(enumeration[i].enumName &&
+ strcmp(enumeration[i].enumName, enumName) != 0)
+ i++;
+
+ return enumeration[i].value;
+}
diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c
new file mode 100644
index 00000000..97fc593c
--- /dev/null
+++ b/OpenAL32/alListener.c
@@ -0,0 +1,513 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "alMain.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alListener.h"
+
+ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch (eParam)
+ {
+ case AL_GAIN:
+ if (flValue >= 0.0f)
+ pContext->Listener.Gain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ pContext->Listener.Position[0] = flValue1;
+ pContext->Listener.Position[1] = flValue2;
+ pContext->Listener.Position[2] = flValue3;
+ break;
+
+ case AL_VELOCITY:
+ pContext->Listener.Velocity[0] = flValue1;
+ pContext->Listener.Velocity[1] = flValue2;
+ pContext->Listener.Velocity[2] = flValue3;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ switch (eParam)
+ {
+ case AL_GAIN:
+ if (pflValues[0] >= 0.0f)
+ pContext->Listener.Gain = pflValues[0];
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_POSITION:
+ pContext->Listener.Position[0] = pflValues[0];
+ pContext->Listener.Position[1] = pflValues[1];
+ pContext->Listener.Position[2] = pflValues[2];
+ break;
+
+ case AL_VELOCITY:
+ pContext->Listener.Velocity[0] = pflValues[0];
+ pContext->Listener.Velocity[1] = pflValues[1];
+ pContext->Listener.Velocity[2] = pflValues[2];
+ break;
+
+ case AL_ORIENTATION:
+ // AT then UP
+ pContext->Listener.Forward[0] = pflValues[0];
+ pContext->Listener.Forward[1] = pflValues[1];
+ pContext->Listener.Forward[2] = pflValues[2];
+ pContext->Listener.Up[0] = pflValues[3];
+ pContext->Listener.Up[1] = pflValues[4];
+ pContext->Listener.Up[2] = pflValues[5];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alListeneri(ALenum eParam, ALint lValue)
+{
+ ALCcontext *pContext;
+
+ (void)lValue;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch (eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ case AL_VELOCITY:
+ alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
+{
+ ALCcontext *pContext;
+ ALfloat flValues[6];
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ case AL_VELOCITY:
+ flValues[0] = (ALfloat)plValues[0];
+ flValues[1] = (ALfloat)plValues[1];
+ flValues[2] = (ALfloat)plValues[2];
+ alListenerfv(eParam, flValues);
+ break;
+
+ case AL_ORIENTATION:
+ flValues[0] = (ALfloat)plValues[0];
+ flValues[1] = (ALfloat)plValues[1];
+ flValues[2] = (ALfloat)plValues[2];
+ flValues[3] = (ALfloat)plValues[3];
+ flValues[4] = (ALfloat)plValues[4];
+ flValues[5] = (ALfloat)plValues[5];
+ alListenerfv(eParam, flValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValue)
+ {
+ switch (eParam)
+ {
+ case AL_GAIN:
+ *pflValue = pContext->Listener.Gain;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((pflValue1) && (pflValue2) && (pflValue3))
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ *pflValue1 = pContext->Listener.Position[0];
+ *pflValue2 = pContext->Listener.Position[1];
+ *pflValue3 = pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ *pflValue1 = pContext->Listener.Velocity[0];
+ *pflValue2 = pContext->Listener.Velocity[1];
+ *pflValue3 = pContext->Listener.Velocity[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ switch (eParam)
+ {
+ case AL_GAIN:
+ pflValues[0] = pContext->Listener.Gain;
+ break;
+
+ case AL_POSITION:
+ pflValues[0] = pContext->Listener.Position[0];
+ pflValues[1] = pContext->Listener.Position[1];
+ pflValues[2] = pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ pflValues[0] = pContext->Listener.Velocity[0];
+ pflValues[1] = pContext->Listener.Velocity[1];
+ pflValues[2] = pContext->Listener.Velocity[2];
+ break;
+
+ case AL_ORIENTATION:
+ // AT then UP
+ pflValues[0] = pContext->Listener.Forward[0];
+ pflValues[1] = pContext->Listener.Forward[1];
+ pflValues[2] = pContext->Listener.Forward[2];
+ pflValues[3] = pContext->Listener.Up[0];
+ pflValues[4] = pContext->Listener.Up[1];
+ pflValues[5] = pContext->Listener.Up[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetListeneri(ALenum eParam, ALint *plValue)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValue)
+ {
+ switch (eParam)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((plValue1) && (plValue2) && (plValue3))
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ *plValue1 = (ALint)pContext->Listener.Position[0];
+ *plValue2 = (ALint)pContext->Listener.Position[1];
+ *plValue3 = (ALint)pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ *plValue1 = (ALint)pContext->Listener.Velocity[0];
+ *plValue2 = (ALint)pContext->Listener.Velocity[1];
+ *plValue3 = (ALint)pContext->Listener.Velocity[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ switch (eParam)
+ {
+ case AL_POSITION:
+ plValues[0] = (ALint)pContext->Listener.Position[0];
+ plValues[1] = (ALint)pContext->Listener.Position[1];
+ plValues[2] = (ALint)pContext->Listener.Position[2];
+ break;
+
+ case AL_VELOCITY:
+ plValues[0] = (ALint)pContext->Listener.Velocity[0];
+ plValues[1] = (ALint)pContext->Listener.Velocity[1];
+ plValues[2] = (ALint)pContext->Listener.Velocity[2];
+ break;
+
+ case AL_ORIENTATION:
+ // AT then UP
+ plValues[0] = (ALint)pContext->Listener.Forward[0];
+ plValues[1] = (ALint)pContext->Listener.Forward[1];
+ plValues[2] = (ALint)pContext->Listener.Forward[2];
+ plValues[3] = (ALint)pContext->Listener.Up[0];
+ plValues[4] = (ALint)pContext->Listener.Up[1];
+ plValues[5] = (ALint)pContext->Listener.Up[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
new file mode 100644
index 00000000..90d70939
--- /dev/null
+++ b/OpenAL32/alSource.c
@@ -0,0 +1,2108 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alSource.h"
+
+ALvoid InitSourceParams(ALsource *pSource);
+ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset);
+ALvoid ApplyOffset(ALsource *pSource, ALboolean bUpdateContext);
+ALint GetByteOffset(ALsource *pSource);
+
+ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
+{
+ ALCcontext *Context;
+ ALCdevice *Device;
+ ALsizei i=0;
+
+ Context = alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (n > 0)
+ {
+ Device = alcGetContextsDevice(Context);
+
+ if (Device)
+ {
+ // Check that enough memory has been allocted in the 'sources' array for n Sources
+ if (!IsBadWritePtr((void*)sources, n * sizeof(ALuint)))
+ {
+ // Check that the requested number of sources can be generated
+ if ((Context->SourceCount + n) <= Device->MaxNoOfSources)
+ {
+ ALsource **list = &Context->Source;
+ while(*list)
+ list = &(*list)->next;
+
+ // Add additional sources to the list (Source->next points to the location for the next Source structure)
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALsource));
+ if(*list)
+ {
+ sources[i]=(ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->source = sources[i];
+
+ InitSourceParams(*list);
+ Context->SourceCount++;
+ i++;
+
+ list = &(*list)->next;
+ }
+ }
+
+ // If we didn't create all the Sources, we must have run out or memory
+ if(i != n)
+ alSetError(AL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ // Not enough resources to create the Sources
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // Bad pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // No Device created, or attached to Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALCdevice *Device;
+ ALsource *ALSource;
+ ALsource **list;
+ ALsizei i;
+ ALbufferlistitem *ALBufferList;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context = alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (n >= 0)
+ {
+ Device = alcGetContextsDevice(Context);
+
+ if (Device)
+ {
+ if ((ALuint)n <= Context->SourceCount)
+ {
+ // Check that all Sources are valid (and can therefore be deleted)
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ // All Sources are valid, and can be deleted
+ for (i = 0; i < n; i++)
+ {
+ // Recheck that the Source is valid, because there could be duplicated Source names
+ if (alIsSource(sources[i]))
+ {
+ ALSource=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ alSourceStop((ALuint)ALSource->source);
+
+ // For each buffer in the source's queue, decrement its reference counter and remove it
+ while (ALSource->queue != NULL)
+ {
+ ALBufferList = ALSource->queue;
+ // Decrement buffer's reference counter
+ if (ALBufferList->buffer != 0)
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->refcount--;
+ // Update queue to point to next element in list
+ ALSource->queue = ALBufferList->next;
+ // Release memory allocated for buffer list item
+ free(ALBufferList);
+ }
+
+ // Decrement Source count
+ Context->SourceCount--;
+
+ // Remove Source from list of Sources
+ list = &Context->Source;
+ while(*list && *list != ALSource)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+ ALTHUNK_REMOVEENTRY(ALSource->source);
+
+ memset(ALSource,0,sizeof(ALsource));
+ free(ALSource);
+ }
+ }
+
+ }
+ }
+ else
+ {
+ // Trying to delete more Sources than have been generated
+ alSetError(AL_INVALID_NAME);
+ }
+ }
+ else
+ {
+ // No Device created, or attached to Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALboolean ALAPIENTRY alIsSource(ALuint source)
+{
+ ALboolean result=AL_FALSE;
+ ALCcontext *Context;
+ ALsource *Source;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ // To determine if this is a valid Source name, look through the list of generated Sources
+ Source = Context->Source;
+ while(Source)
+ {
+ if (Source == (ALsource*)ALTHUNK_LOOKUPENTRY(source))
+ {
+ result = AL_TRUE;
+ break;
+ }
+
+ Source = Source->next;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return result;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_PITCH:
+ if (flValue >= 0.0f)
+ {
+ pSource->flPitch = flValue;
+ if(pSource->flPitch < 0.001f)
+ pSource->flPitch = 0.001f;
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ if ((flValue >= 0.0f) && (flValue <= 360.0f))
+ pSource->flInnerAngle = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ if ((flValue >= 0.0f) && (flValue <= 360.0f))
+ pSource->flOuterAngle = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_GAIN:
+ if (flValue >= 0.0f)
+ pSource->flGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_MAX_DISTANCE:
+ if (flValue >= 0.0f)
+ pSource->flMaxDistance = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_ROLLOFF_FACTOR:
+ if (flValue >= 0.0f)
+ pSource->flRollOffFactor = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_REFERENCE_DISTANCE:
+ if (flValue >= 0.0f)
+ pSource->flRefDistance = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_MIN_GAIN:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->flMinGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_MAX_GAIN:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->flMaxGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_OUTER_GAIN:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->flOuterGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (flValue >= 0.0f)
+ {
+ pSource->lOffsetType = eParam;
+
+ // Store Offset (convert Seconds into Milliseconds)
+ if (eParam == AL_SEC_OFFSET)
+ pSource->lOffset = (ALint)(flValue * 1000.0f);
+ else
+ pSource->lOffset = (ALint)flValue;
+
+ if ((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED))
+ ApplyOffset(pSource, AL_TRUE);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // Invalid Source Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ // Invalid context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue1,ALfloat flValue2,ALfloat flValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+ switch(eParam)
+ {
+ case AL_POSITION:
+ pSource->vPosition[0] = flValue1;
+ pSource->vPosition[1] = flValue2;
+ pSource->vPosition[2] = flValue3;
+ break;
+
+ case AL_VELOCITY:
+ pSource->vVelocity[0] = flValue1;
+ pSource->vVelocity[1] = flValue2;
+ pSource->vVelocity[2] = flValue3;
+ break;
+
+ case AL_DIRECTION:
+ pSource->vOrientation[0] = flValue1;
+ pSource->vOrientation[1] = flValue2;
+ pSource->vOrientation[2] = flValue3;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_PITCH:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_GAIN:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ case AL_MIN_GAIN:
+ case AL_MAX_GAIN:
+ case AL_CONE_OUTER_GAIN:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ alSourcef(source, eParam, pflValues[0]);
+ break;
+
+ case AL_POSITION:
+ case AL_VELOCITY:
+ case AL_DIRECTION:
+ alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALbufferlistitem *pALBufferListItem;
+ ALint Counter = 0;
+ ALint DataSize = 0;
+ ALint BufferSize;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ alSourcef(source, eParam, (ALfloat)lValue);
+ break;
+
+ case AL_SOURCE_RELATIVE:
+ if ((lValue == AL_FALSE) || (lValue == AL_TRUE))
+ pSource->bHeadRelative = (ALboolean)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ if ((lValue >= 0) && (lValue <= 360))
+ pSource->flInnerAngle = (float)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ if ((lValue >= 0) && (lValue <= 360))
+ pSource->flOuterAngle = (float)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_LOOPING:
+ if ((lValue == AL_FALSE) || (lValue == AL_TRUE))
+ pSource->bLooping = (ALboolean)lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_BUFFER:
+ if ((pSource->state == AL_STOPPED) || (pSource->state == AL_INITIAL))
+ {
+ if (alIsBuffer(lValue))
+ {
+ // Remove all elements in the queue
+ while (pSource->queue != NULL)
+ {
+ pALBufferListItem = pSource->queue;
+ pSource->queue = pALBufferListItem->next;
+ // Decrement reference counter for buffer
+ if (pALBufferListItem->buffer)
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem->buffer)))->refcount--;
+ // Record size of buffer
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pALBufferListItem->buffer))->size;
+ DataSize += BufferSize;
+ // Increment the number of buffers removed from queue
+ Counter++;
+ // Release memory for buffer list item
+ free(pALBufferListItem);
+ // Decrement the number of buffers in the queue
+ pSource->BuffersInQueue--;
+ }
+
+ // Add the buffer to the queue (as long as it is NOT the NULL buffer)
+ if (lValue != 0)
+ {
+ // Source is now in STATIC mode
+ pSource->lSourceType = AL_STATIC;
+
+ // Add the selected buffer to the queue
+ pALBufferListItem = malloc(sizeof(ALbufferlistitem));
+ pALBufferListItem->buffer = lValue;
+ pALBufferListItem->bufferstate = PENDING;
+ pALBufferListItem->flag = 0;
+ pALBufferListItem->next = NULL;
+
+ pSource->queue = pALBufferListItem;
+ pSource->BuffersInQueue = 1;
+
+ DataSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(lValue))->size;
+
+ // Increment reference counter for buffer
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(lValue)))->refcount++;
+ }
+ else
+ {
+ // Source is now in UNDETERMINED mode
+ pSource->lSourceType = AL_UNDETERMINED;
+ }
+
+ // Set Buffers Processed
+ pSource->BuffersProcessed = 0;
+
+ // Update AL_BUFFER parameter
+ pSource->ulBufferID = lValue;
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ case AL_SOURCE_STATE:
+ // Query only
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (lValue >= 0)
+ {
+ pSource->lOffsetType = eParam;
+
+ // Store Offset (convert Seconds into Milliseconds)
+ if (eParam == AL_SEC_OFFSET)
+ pSource->lOffset = lValue * 1000;
+ else
+ pSource->lOffset = lValue;
+
+ if ((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED))
+ ApplyOffset(pSource, AL_TRUE);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_POSITION:
+ case AL_VELOCITY:
+ case AL_DIRECTION:
+ alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_SOURCE_RELATIVE:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_LOOPING:
+ case AL_BUFFER:
+ case AL_SOURCE_STATE:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ alSourcei(source, eParam, plValues[0]);
+ break;
+
+ case AL_POSITION:
+ case AL_VELOCITY:
+ case AL_DIRECTION:
+ alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALfloat flOffset;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValue)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_PITCH:
+ *pflValue = pSource->flPitch;
+ break;
+
+ case AL_GAIN:
+ *pflValue = pSource->flGain;
+ break;
+
+ case AL_MIN_GAIN:
+ *pflValue = pSource->flMinGain;
+ break;
+
+ case AL_MAX_GAIN:
+ *pflValue = pSource->flMaxGain;
+ break;
+
+ case AL_MAX_DISTANCE:
+ *pflValue = pSource->flMaxDistance;
+ break;
+
+ case AL_ROLLOFF_FACTOR:
+ *pflValue = pSource->flRollOffFactor;
+ break;
+
+ case AL_CONE_OUTER_GAIN:
+ *pflValue = pSource->flOuterGain;
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (GetSourceOffset(pSource, eParam, &flOffset))
+ *pflValue = flOffset;
+ else
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ *pflValue = pSource->flInnerAngle;
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ *pflValue = pSource->flOuterAngle;
+ break;
+
+ case AL_REFERENCE_DISTANCE:
+ *pflValue = pSource->flRefDistance;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSource3f(ALuint source, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((pflValue1) && (pflValue2) && (pflValue3))
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ *pflValue1 = pSource->vPosition[0];
+ *pflValue2 = pSource->vPosition[1];
+ *pflValue3 = pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ *pflValue1 = pSource->vVelocity[0];
+ *pflValue2 = pSource->vVelocity[1];
+ *pflValue3 = pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ *pflValue1 = pSource->vOrientation[0];
+ *pflValue2 = pSource->vOrientation[1];
+ *pflValue3 = pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pflValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pflValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_PITCH:
+ case AL_GAIN:
+ case AL_MIN_GAIN:
+ case AL_MAX_GAIN:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_CONE_OUTER_GAIN:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_REFERENCE_DISTANCE:
+ alGetSourcef(source, eParam, pflValues);
+ break;
+
+ case AL_POSITION:
+ pflValues[0] = pSource->vPosition[0];
+ pflValues[1] = pSource->vPosition[1];
+ pflValues[2] = pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ pflValues[0] = pSource->vVelocity[0];
+ pflValues[1] = pSource->vVelocity[1];
+ pflValues[2] = pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ pflValues[0] = pSource->vOrientation[0];
+ pflValues[1] = pSource->vOrientation[1];
+ pflValues[2] = pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValue)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALfloat flOffset;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValue)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_MAX_DISTANCE:
+ *plValue = (ALint)pSource->flMaxDistance;
+ break;
+
+ case AL_ROLLOFF_FACTOR:
+ *plValue = (ALint)pSource->flRollOffFactor;
+ break;
+
+ case AL_REFERENCE_DISTANCE:
+ *plValue = (ALint)pSource->flRefDistance;
+ break;
+
+ case AL_SOURCE_RELATIVE:
+ *plValue = pSource->bHeadRelative;
+ break;
+
+ case AL_CONE_INNER_ANGLE:
+ *plValue = (ALint)pSource->flInnerAngle;
+ break;
+
+ case AL_CONE_OUTER_ANGLE:
+ *plValue = (ALint)pSource->flOuterAngle;
+ break;
+
+ case AL_LOOPING:
+ *plValue = pSource->bLooping;
+ break;
+
+ case AL_BUFFER:
+ *plValue = pSource->ulBufferID;
+ break;
+
+ case AL_SOURCE_STATE:
+ *plValue = pSource->state;
+ break;
+
+ case AL_BUFFERS_QUEUED:
+ *plValue = pSource->BuffersInQueue;
+ break;
+
+ case AL_BUFFERS_PROCESSED:
+ if(pSource->bLooping)
+ {
+ /* Buffers on a looping source are in a perpetual state
+ * of PENDING, so don't report any as PROCESSED */
+ *plValue = 0;
+ }
+ else
+ *plValue = pSource->BuffersProcessed;
+ break;
+
+ case AL_SOURCE_TYPE:
+ *plValue = pSource->lSourceType;
+ break;
+
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ if (GetSourceOffset(pSource, eParam, &flOffset))
+ *plValue = (ALint)flOffset;
+ else
+ alSetError(AL_INVALID_OPERATION);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetSource3i(ALuint source, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if ((plValue1) && (plValue2) && (plValue3))
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch(eParam)
+ {
+ case AL_POSITION:
+ *plValue1 = (ALint)pSource->vPosition[0];
+ *plValue2 = (ALint)pSource->vPosition[1];
+ *plValue3 = (ALint)pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ *plValue1 = (ALint)pSource->vVelocity[0];
+ *plValue2 = (ALint)pSource->vVelocity[1];
+ *plValue3 = (ALint)pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ *plValue1 = (ALint)pSource->vOrientation[0];
+ *plValue2 = (ALint)pSource->vOrientation[1];
+ *plValue3 = (ALint)pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValues)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (plValues)
+ {
+ if (alIsSource(source))
+ {
+ pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
+ switch (eParam)
+ {
+ case AL_SOURCE_RELATIVE:
+ case AL_CONE_INNER_ANGLE:
+ case AL_CONE_OUTER_ANGLE:
+ case AL_LOOPING:
+ case AL_BUFFER:
+ case AL_SOURCE_STATE:
+ case AL_BUFFERS_QUEUED:
+ case AL_BUFFERS_PROCESSED:
+ case AL_SEC_OFFSET:
+ case AL_SAMPLE_OFFSET:
+ case AL_BYTE_OFFSET:
+ case AL_MAX_DISTANCE:
+ case AL_ROLLOFF_FACTOR:
+ case AL_REFERENCE_DISTANCE:
+ case AL_SOURCE_TYPE:
+ alGetSourcei(source, eParam, plValues);
+ break;
+
+ case AL_POSITION:
+ plValues[0] = (ALint)pSource->vPosition[0];
+ plValues[1] = (ALint)pSource->vPosition[1];
+ plValues[2] = (ALint)pSource->vPosition[2];
+ break;
+
+ case AL_VELOCITY:
+ plValues[0] = (ALint)pSource->vVelocity[0];
+ plValues[1] = (ALint)pSource->vVelocity[1];
+ plValues[2] = (ALint)pSource->vVelocity[2];
+ break;
+
+ case AL_DIRECTION:
+ plValues[0] = (ALint)pSource->vOrientation[0];
+ plValues[1] = (ALint)pSource->vOrientation[1];
+ plValues[2] = (ALint)pSource->vOrientation[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourcePlay(ALuint source)
+{
+ alSourcePlayv(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint *pSourceList)
+{
+ ALCcontext *pContext;
+ ALsource *pSource;
+ ALbufferlistitem *ALBufferList;
+ ALboolean bSourcesValid = AL_TRUE;
+ ALboolean bPlay;
+ ALsizei i;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (pSourceList)
+ {
+ // Check that all the Sources are valid
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsSource(pSourceList[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i = 0; i < n; i++)
+ {
+ // Assume Source won't need to play
+ bPlay = AL_FALSE;
+
+ pSource = ((ALsource*)ALTHUNK_LOOKUPENTRY(pSourceList[i]));
+
+ // Check that there is a queue containing at least one non-null, non zero length AL Buffer
+ ALBufferList = pSource->queue;
+ while (ALBufferList)
+ {
+ if ((ALBufferList->buffer != 0) && (((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALBufferList->buffer))->size))
+ {
+ bPlay = AL_TRUE;
+ break;
+ }
+ ALBufferList = ALBufferList->next;
+ }
+
+ if (bPlay)
+ {
+ if (pSource->state != AL_PAUSED)
+ {
+ pSource->state = AL_PLAYING;
+ pSource->inuse = AL_TRUE;
+ pSource->play = AL_TRUE;
+ pSource->position = 0;
+ pSource->position_fraction = 0;
+ pSource->BuffersProcessed = 0;
+ pSource->BuffersPlayed = 0;
+ pSource->BufferPosition = 0;
+ pSource->lBytesPlayed = 0;
+
+ pSource->ulBufferID = pSource->queue->buffer;
+
+ // Make sure all the Buffers in the queue are marked as PENDING
+ ALBufferList = pSource->queue;
+ while (ALBufferList)
+ {
+ ALBufferList->bufferstate = PENDING;
+ ALBufferList = ALBufferList->next;
+ }
+ }
+ else
+ {
+ pSource->state = AL_PLAYING;
+ pSource->inuse = AL_TRUE;
+ pSource->play = AL_TRUE;
+ }
+
+ // Check if an Offset has been set
+ if (pSource->lOffset)
+ ApplyOffset(pSource, AL_FALSE);
+ }
+ else
+ {
+ // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
+ ALBufferList = pSource->queue;
+ while (ALBufferList)
+ {
+ ALBufferList->bufferstate = PROCESSED;
+ ALBufferList = ALBufferList->next;
+ }
+
+ pSource->BuffersPlayed = pSource->BuffersProcessed = pSource->BuffersInQueue;
+ }
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourcePause(ALuint source)
+{
+ alSourcePausev(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALsource *Source;
+ ALsizei i;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (sources)
+ {
+ // Check all the Sources are valid
+ for (i=0;i<n;i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i=0;i<n;i++)
+ {
+ Source=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ if (Source->state==AL_PLAYING)
+ {
+ Source->state=AL_PAUSED;
+ Source->inuse=AL_FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceStop(ALuint source)
+{
+ alSourceStopv(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALsource *Source;
+ ALsizei i;
+ ALbufferlistitem *ALBufferListItem;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (sources)
+ {
+ // Check all the Sources are valid
+ for (i=0;i<n;i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i=0;i<n;i++)
+ {
+ Source=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ if (Source->state!=AL_INITIAL)
+ {
+ Source->state=AL_STOPPED;
+ Source->inuse=AL_FALSE;
+ Source->BuffersPlayed = Source->BuffersProcessed = Source->BuffersInQueue;
+ ALBufferListItem= Source->queue;
+ while (ALBufferListItem != NULL)
+ {
+ ALBufferListItem->bufferstate = PROCESSED;
+ ALBufferListItem = ALBufferListItem->next;
+ }
+ }
+ Source->lOffset = 0;
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceRewind(ALuint source)
+{
+ alSourceRewindv(1, &source);
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
+{
+ ALCcontext *Context;
+ ALsource *Source;
+ ALsizei i;
+ ALbufferlistitem *ALBufferListItem;
+ ALboolean bSourcesValid = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (sources)
+ {
+ // Check all the Sources are valid
+ for (i=0;i<n;i++)
+ {
+ if (!alIsSource(sources[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ bSourcesValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bSourcesValid)
+ {
+ for (i=0;i<n;i++)
+ {
+ Source=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
+ if (Source->state!=AL_INITIAL)
+ {
+ Source->state=AL_INITIAL;
+ Source->inuse=AL_FALSE;
+ Source->position=0;
+ Source->position_fraction=0;
+ Source->BuffersProcessed = 0;
+ ALBufferListItem= Source->queue;
+ while (ALBufferListItem != NULL)
+ {
+ ALBufferListItem->bufferstate = PENDING;
+ ALBufferListItem = ALBufferListItem->next;
+ }
+ if (Source->queue)
+ Source->ulBufferID = Source->queue->buffer;
+ }
+ Source->lOffset = 0;
+ }
+ }
+ }
+ else
+ {
+ // sources is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, const ALuint* buffers )
+{
+ ALCcontext *Context;
+ ALsource *ALSource;
+ ALsizei i;
+ ALbufferlistitem *ALBufferList;
+ ALbufferlistitem *ALBufferListStart;
+ ALuint DataSize;
+ ALuint BufferSize;
+ ALint iFrequency;
+ ALint iFormat;
+ ALboolean bBuffersValid = AL_TRUE;
+
+ if (n == 0)
+ return;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ DataSize = 0;
+ BufferSize = 0;
+
+ // Check that all buffers are valid or zero and that the source is valid
+
+ // Check that this is a valid source
+ if (alIsSource(source))
+ {
+ ALSource = (ALsource*)ALTHUNK_LOOKUPENTRY(source);
+
+ // Check that this is not a STATIC Source
+ if (ALSource->lSourceType != AL_STATIC)
+ {
+ iFrequency = -1;
+ iFormat = -1;
+
+ // Check existing Queue (if any) for a valid Buffers and get its frequency and format
+ ALBufferList = ALSource->queue;
+ while (ALBufferList)
+ {
+ if (ALBufferList->buffer)
+ {
+ iFrequency = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->frequency;
+ iFormat = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->format;
+ break;
+ }
+ ALBufferList = ALBufferList->next;
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ if (alIsBuffer(buffers[i]))
+ {
+ if (buffers[i])
+ {
+ if ((iFrequency == -1) && (iFormat == -1))
+ {
+ iFrequency = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->frequency;
+ iFormat = ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->format;
+ }
+ else
+ {
+ if ((iFrequency != ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->frequency) ||
+ (iFormat != ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->format))
+ {
+ alSetError(AL_INVALID_OPERATION);
+ bBuffersValid = AL_FALSE;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ alSetError(AL_INVALID_NAME);
+ bBuffersValid = AL_FALSE;
+ break;
+ }
+ }
+
+ if (bBuffersValid)
+ {
+ // Change Source Type
+ ALSource->lSourceType = AL_STREAMING;
+
+ // All buffers are valid - so add them to the list
+ ALBufferListStart = malloc(sizeof(ALbufferlistitem));
+ ALBufferListStart->buffer = buffers[0];
+ ALBufferListStart->bufferstate = PENDING;
+ ALBufferListStart->flag = 0;
+ ALBufferListStart->next = NULL;
+
+ if (buffers[0])
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(buffers[0]))->size;
+ else
+ BufferSize = 0;
+
+ DataSize += BufferSize;
+
+ // Increment reference counter for buffer
+ if (buffers[0])
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[0])))->refcount++;
+
+ ALBufferList = ALBufferListStart;
+
+ for (i = 1; i < n; i++)
+ {
+ ALBufferList->next = malloc(sizeof(ALbufferlistitem));
+ ALBufferList->next->buffer = buffers[i];
+ ALBufferList->next->bufferstate = PENDING;
+ ALBufferList->next->flag = 0;
+ ALBufferList->next->next = NULL;
+
+ if (buffers[i])
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(buffers[i]))->size;
+ else
+ BufferSize = 0;
+
+ DataSize += BufferSize;
+
+ // Increment reference counter for buffer
+ if (buffers[i])
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(buffers[i])))->refcount++;
+
+ ALBufferList = ALBufferList->next;
+ }
+
+ if (ALSource->queue == NULL)
+ {
+ ALSource->queue = ALBufferListStart;
+ // Update Current Buffer
+ ALSource->ulBufferID = ALBufferListStart->buffer;
+ }
+ else
+ {
+ // Find end of queue
+ ALBufferList = ALSource->queue;
+ while (ALBufferList->next != NULL)
+ {
+ ALBufferList = ALBufferList->next;
+ }
+
+ ALBufferList->next = ALBufferListStart;
+ }
+
+ // Update number of buffers in queue
+ ALSource->BuffersInQueue += n;
+ }
+ }
+ else
+ {
+ // Invalid Source Type (can't queue on a Static Source)
+ alSetError(AL_INVALID_OPERATION);
+ }
+ }
+ else
+ {
+ // Invalid Source Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+// Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
+// an array of buffer IDs that are to be filled with the names of the buffers removed
+ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers )
+{
+ ALCcontext *Context;
+ ALsource *ALSource;
+ ALsizei i;
+ ALbufferlistitem *ALBufferList;
+ ALuint DataSize;
+ ALuint BufferSize;
+ ALuint BufferID;
+ ALboolean bBuffersProcessed;
+
+ if (n == 0)
+ return;
+
+ DataSize = 0;
+ BufferSize = 0;
+ bBuffersProcessed = AL_TRUE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (alIsSource(source))
+ {
+ ALSource = (ALsource*)ALTHUNK_LOOKUPENTRY(source);
+
+ // Check that all 'n' buffers have been processed
+ ALBufferList = ALSource->queue;
+ for (i = 0; i < n; i++)
+ {
+ if ((ALBufferList != NULL) && (ALBufferList->bufferstate == PROCESSED))
+ {
+ ALBufferList = ALBufferList->next;
+ }
+ else
+ {
+ bBuffersProcessed = AL_FALSE;
+ break;
+ }
+ }
+
+ // If all 'n' buffers have been processed, remove them from the queue
+ if (bBuffersProcessed)
+ {
+ for (i = 0; i < n; i++)
+ {
+ ALBufferList = ALSource->queue;
+
+ ALSource->queue = ALBufferList->next;
+ // Record name of buffer
+ buffers[i] = ALBufferList->buffer;
+ // Decrement buffer reference counter
+ if (ALBufferList->buffer)
+ ((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->refcount--;
+ // Record size of buffer
+ if (ALBufferList->buffer)
+ BufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(ALBufferList->buffer))->size;
+ else
+ BufferSize = 0;
+
+ DataSize += BufferSize;
+ // Release memory for buffer list item
+ free(ALBufferList);
+ ALSource->BuffersInQueue--;
+ ALSource->BuffersProcessed--;
+ }
+
+ if (ALSource->state != AL_PLAYING)
+ {
+ if (ALSource->queue)
+ BufferID = ALSource->queue->buffer;
+ else
+ BufferID = 0;
+
+ ALSource->ulBufferID = BufferID;
+ }
+
+ if((ALuint)n > ALSource->BuffersPlayed)
+ {
+ ALSource->BuffersPlayed = 0;
+ ALSource->BufferPosition = 0;
+ }
+ else
+ ALSource->BuffersPlayed -= n;
+ }
+ else
+ {
+ // Some buffers can't be unqueue because they have not been processed
+ alSetError(AL_INVALID_VALUE);
+ }
+ }
+ else
+ {
+ // Invalid Source Name
+ alSetError(AL_INVALID_NAME);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+
+ALvoid InitSourceParams(ALsource *pSource)
+{
+ pSource->flInnerAngle = 360.0f;
+ pSource->flOuterAngle = 360.0f;
+ pSource->flPitch = 1.0f;
+ pSource->vPosition[0] = 0.0f;
+ pSource->vPosition[1] = 0.0f;
+ pSource->vPosition[2] = 0.0f;
+ pSource->vOrientation[0] = 0.0f;
+ pSource->vOrientation[1] = 0.0f;
+ pSource->vOrientation[2] = 0.0f;
+ pSource->vVelocity[0] = 0.0f;
+ pSource->vVelocity[1] = 0.0f;
+ pSource->vVelocity[2] = 0.0f;
+ pSource->flRefDistance = 1.0f;
+ pSource->flMaxDistance = FLT_MAX;
+ pSource->flRollOffFactor = 1.0f;
+ pSource->bLooping = AL_FALSE;
+ pSource->flGain = 1.0f;
+ pSource->flMinGain = 0.0f;
+ pSource->flMaxGain = 1.0f;
+ pSource->flOuterGain = 0.0f;
+
+ pSource->state = AL_INITIAL;
+ pSource->lSourceType = AL_UNDETERMINED;
+
+ pSource->ulBufferID= 0;
+}
+
+
+/*
+ GetSourceOffset
+
+ Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
+ The offset is relative to the start of the queue (not the start of the current buffer)
+*/
+ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset)
+{
+ ALbufferlistitem *pBufferList;
+ ALfloat flBufferFreq;
+ ALint lBufferSize, lBytesPlayed, lChannels;
+ ALenum eOriginalFormat;
+ ALboolean bReturn = AL_TRUE;
+ ALint lTotalBufferDataSize;
+
+ if (((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED)) && (pSource->ulBufferID))
+ {
+ // Get Current Buffer Size and frequency (in milliseconds)
+ lBufferSize = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->size;
+ flBufferFreq = (ALfloat)(((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->frequency);
+ eOriginalFormat = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->eOriginalFormat;
+ lChannels = ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->format == AL_FORMAT_MONO16)?1:2);
+
+ // Get Current BytesPlayed
+ lBytesPlayed = pSource->position * lChannels * 2; // NOTE : This is the byte offset into the *current* buffer
+ // Add byte length of any processed buffers in the queue
+ pBufferList = pSource->queue;
+ while ((pBufferList) && (pBufferList->bufferstate == PROCESSED))
+ {
+ lBytesPlayed += ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size;
+ pBufferList = pBufferList->next;
+ }
+
+ lTotalBufferDataSize = 0;
+ pBufferList = pSource->queue;
+ while (pBufferList)
+ {
+ if (pBufferList->buffer)
+ lTotalBufferDataSize += ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size;
+ pBufferList = pBufferList->next;
+ }
+
+ if (pSource->bLooping)
+ {
+ if (lBytesPlayed < 0)
+ lBytesPlayed = 0;
+ else
+ lBytesPlayed = lBytesPlayed % lTotalBufferDataSize;
+ }
+ else
+ {
+ // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
+ if(lBytesPlayed < 0)
+ lBytesPlayed = 0;
+ if(lBytesPlayed > lTotalBufferDataSize)
+ lBytesPlayed = lTotalBufferDataSize;
+ }
+
+ switch (eName)
+ {
+ case AL_SEC_OFFSET:
+ *pflOffset = ((ALfloat)lBytesPlayed / (lChannels * 2.0f * flBufferFreq));
+ break;
+ case AL_SAMPLE_OFFSET:
+ *pflOffset = (ALfloat)(lBytesPlayed / (lChannels * 2));
+ break;
+ case AL_BYTE_OFFSET:
+ // Take into account the original format of the Buffer
+ if ((eOriginalFormat == AL_FORMAT_MONO8) || (eOriginalFormat == AL_FORMAT_STEREO8))
+ {
+ *pflOffset = (ALfloat)(lBytesPlayed >> 1);
+ }
+ else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || (eOriginalFormat == AL_FORMAT_STEREO_IMA4))
+ {
+ // Compression rate of the ADPCM supported is 3.6111 to 1
+ lBytesPlayed = (ALint)((ALfloat)lBytesPlayed / 3.6111f);
+ // Round down to nearest ADPCM block
+ *pflOffset = (ALfloat)((lBytesPlayed / (36 * lChannels)) * 36 * lChannels);
+ }
+ else
+ {
+ *pflOffset = (ALfloat)lBytesPlayed;
+ }
+ break;
+ }
+ }
+ else
+ {
+ *pflOffset = 0.0f;
+ }
+
+ return bReturn;
+}
+
+
+/*
+ ApplyOffset
+
+ Apply a playback offset to the Source. This function will update the queue (to correctly
+ mark buffers as 'pending' or 'processed' depending upon the new offset.
+*/
+void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
+{
+ ALbufferlistitem *pBufferList;
+ ALint lBufferSize, lTotalBufferSize;
+ ALint lByteOffset;
+
+ // Get true byte offset
+ lByteOffset = GetByteOffset(pSource);
+
+ // If this is a valid offset apply it
+ if (lByteOffset != -1)
+ {
+ // Sort out the queue (pending and processed states)
+ pBufferList = pSource->queue;
+ lTotalBufferSize = 0;
+ pSource->BuffersPlayed = 0;
+ pSource->BuffersProcessed = 0;
+ while (pBufferList)
+ {
+ lBufferSize = pBufferList->buffer ? ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size : 0;
+
+ if ((lTotalBufferSize + lBufferSize) <= lByteOffset)
+ {
+ // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
+ // update the state to PROCESSED
+ pSource->BuffersPlayed++;
+
+ if (!pSource->bLooping)
+ {
+ pBufferList->bufferstate = PROCESSED;
+ pSource->BuffersProcessed++;
+ }
+ }
+ else if (lTotalBufferSize <= lByteOffset)
+ {
+ // Offset is within this buffer
+ pBufferList->bufferstate = PENDING;
+
+ // Set Current Buffer ID
+ pSource->ulBufferID = pBufferList->buffer;
+
+ // Set current position in this buffer
+ pSource->BufferPosition = lByteOffset - lTotalBufferSize;
+
+ // Set Total Bytes Played to Offset
+ pSource->lBytesPlayed = lByteOffset;
+
+ // SW Mixer Positions are in Samples
+ pSource->position = pSource->BufferPosition / ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->format == AL_FORMAT_MONO16)?2:4);
+ }
+ else
+ {
+ // Offset is before this buffer, so mark as pending
+ pBufferList->bufferstate = PENDING;
+ }
+
+ // Increment the TotalBufferSize
+ lTotalBufferSize += lBufferSize;
+
+ // Move on to next buffer in the Queue
+ pBufferList = pBufferList->next;
+ }
+ }
+ else
+ {
+ if (bUpdateContext)
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ // Clear Offset
+ pSource->lOffset = 0;
+}
+
+
+/*
+ GetByteOffset
+
+ Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
+ offset supplied by the application). This takes into account the fact that the buffer format
+ may have been modifed by AL (e.g 8bit samples are converted to 16bit)
+*/
+ALint GetByteOffset(ALsource *pSource)
+{
+ ALbuffer *pBuffer = NULL;
+ ALbufferlistitem *pBufferList;
+ ALfloat flBufferFreq;
+ ALint lChannels;
+ ALint lByteOffset = -1;
+ ALint lTotalBufferDataSize;
+
+ // Find the first non-NULL Buffer in the Queue
+ pBufferList = pSource->queue;
+ while (pBufferList)
+ {
+ if (pBufferList->buffer)
+ {
+ pBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer);
+ break;
+ }
+ pBufferList = pBufferList->next;
+ }
+
+ if (pBuffer)
+ {
+ flBufferFreq = ((ALfloat)pBuffer->frequency);
+ lChannels = (pBuffer->format == AL_FORMAT_MONO16)?1:2;
+
+ // Determine the ByteOffset (and ensure it is block aligned)
+ switch (pSource->lOffsetType)
+ {
+ case AL_BYTE_OFFSET:
+ // Take into consideration the original format
+ if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO8) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO8))
+ {
+ lByteOffset = pSource->lOffset * 2;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4))
+ {
+ // Round down to nearest ADPCM block
+ lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels;
+ // Multiply by compression rate
+ lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset);
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else
+ {
+ lByteOffset = pSource->lOffset;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ break;
+
+ case AL_SAMPLE_OFFSET:
+ lByteOffset = pSource->lOffset * lChannels * 2;
+ break;
+
+ case AL_SEC_OFFSET:
+ // Note - lOffset is internally stored as Milliseconds
+ lByteOffset = (ALint)(pSource->lOffset * lChannels * 2.0f * flBufferFreq / 1000.0f);
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ break;
+ }
+
+ lTotalBufferDataSize = 0;
+ pBufferList = pSource->queue;
+ while (pBufferList)
+ {
+ if (pBufferList->buffer)
+ lTotalBufferDataSize += ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size;
+ pBufferList = pBufferList->next;
+ }
+
+ // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
+ if (lByteOffset >= lTotalBufferDataSize)
+ lByteOffset = -1;
+ }
+
+ return lByteOffset;
+}
diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c
new file mode 100644
index 00000000..06da8a88
--- /dev/null
+++ b/OpenAL32/alState.c
@@ -0,0 +1,677 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include <stdlib.h>
+#include "alMain.h"
+#include "AL/alc.h"
+#include "alError.h"
+#include "alState.h"
+
+static const ALchar alVendor[] = "OpenAL Community";
+static const ALchar alVersion[] = "1.1";
+static const ALchar alRenderer[] = "OpenAL Sample Implementation";
+
+// Error Messages
+static const ALchar alNoError[] = "No Error";
+static const ALchar alErrInvalidName[] = "Invalid Name";
+static const ALchar alErrInvalidEnum[] = "Invalid Enum";
+static const ALchar alErrInvalidValue[] = "Invalid Value";
+static const ALchar alErrInvalidOp[] = "Invalid Operation";
+static const ALchar alErrOutOfMemory[] = "Out of Memory";
+
+ALAPI ALvoid ALAPIENTRY alEnable(ALenum capability)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (capability)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+}
+
+ALAPI ALvoid ALAPIENTRY alDisable(ALenum capability)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (capability)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+}
+
+ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
+{
+ ALCcontext *Context;
+ ALboolean value=AL_FALSE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (capability)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALboolean ALAPIENTRY alGetBoolean(ALenum pname)
+{
+ ALCcontext *Context;
+ ALboolean value=AL_FALSE;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ if (Context->DopplerFactor != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ if (Context->DopplerVelocity != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ if (Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
+ value = AL_TRUE;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ if (Context->flSpeedOfSound != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALdouble ALAPIENTRY alGetDouble(ALenum pname)
+{
+ ALCcontext *Context;
+ ALdouble value = 0.0;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ value = (double)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ value = (double)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ value = (double)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ value = (double)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALfloat ALAPIENTRY alGetFloat(ALenum pname)
+{
+ ALCcontext *Context;
+ ALfloat value = 0.0f;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ value = Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ value = Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ value = (float)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ value = Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALint ALAPIENTRY alGetInteger(ALenum pname)
+{
+ ALCcontext *Context;
+ ALint value = 0;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ value = (ALint)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ value = (ALint)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ value = (ALint)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ value = (ALint)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return value;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = (Context->DopplerFactor != 0.0f) ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = (Context->DopplerVelocity != 0.0f) ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = (Context->flSpeedOfSound != 0.0f) ? AL_TRUE : AL_FALSE;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetDoublev(ALenum pname,ALdouble *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = (double)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = (double)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (double)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = (double)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetFloatv(ALenum pname,ALfloat *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (float)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alGetIntegerv(ALenum pname,ALint *data)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (data)
+ {
+ switch (pname)
+ {
+ case AL_DOPPLER_FACTOR:
+ *data = (ALint)Context->DopplerFactor;
+ break;
+
+ case AL_DOPPLER_VELOCITY:
+ *data = (ALint)Context->DopplerVelocity;
+ break;
+
+ case AL_DISTANCE_MODEL:
+ *data = (ALint)Context->DistanceModel;
+ break;
+
+ case AL_SPEED_OF_SOUND:
+ *data = (ALint)Context->flSpeedOfSound;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ {
+ // data is a NULL pointer
+ alSetError(AL_INVALID_VALUE);
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
+{
+ const ALchar *value;
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if(!pContext)
+ {
+ alSetError(AL_INVALID_OPERATION);
+ return NULL;
+ }
+
+ SuspendContext(pContext);
+
+ switch(pname)
+ {
+ case AL_VENDOR:
+ value=alVendor;
+ break;
+
+ case AL_VERSION:
+ value=alVersion;
+ break;
+
+ case AL_RENDERER:
+ value=alRenderer;
+ break;
+
+ case AL_EXTENSIONS:
+ value=pContext->ExtensionList;//alExtensions;
+ break;
+
+ case AL_NO_ERROR:
+ value=alNoError;
+ break;
+
+ case AL_INVALID_NAME:
+ value=alErrInvalidName;
+ break;
+
+ case AL_INVALID_ENUM:
+ value=alErrInvalidEnum;
+ break;
+
+ case AL_INVALID_VALUE:
+ value=alErrInvalidValue;
+ break;
+
+ case AL_INVALID_OPERATION:
+ value=alErrInvalidOp;
+ break;
+
+ case AL_OUT_OF_MEMORY:
+ value=alErrOutOfMemory;
+ break;
+
+ default:
+ value=NULL;
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+
+ ProcessContext(pContext);
+
+ return value;
+}
+
+ALAPI ALvoid ALAPIENTRY alDopplerFactor(ALfloat value)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (value>=0.0f)
+ Context->DopplerFactor = value;
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alDopplerVelocity(ALfloat value)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ if (value>0.0f)
+ Context->DopplerVelocity=value;
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
+{
+ ALCcontext *pContext;
+
+ pContext = alcGetCurrentContext();
+ if (pContext)
+ {
+ SuspendContext(pContext);
+
+ if (flSpeedOfSound > 0.0f)
+ pContext->flSpeedOfSound = flSpeedOfSound;
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(pContext);
+ }
+ else
+ {
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
+
+ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
+{
+ ALCcontext *Context;
+
+ Context=alcGetCurrentContext();
+ if (Context)
+ {
+ SuspendContext(Context);
+
+ switch (value)
+ {
+ case AL_NONE:
+ case AL_INVERSE_DISTANCE:
+ case AL_INVERSE_DISTANCE_CLAMPED:
+ case AL_LINEAR_DISTANCE:
+ case AL_LINEAR_DISTANCE_CLAMPED:
+ case AL_EXPONENT_DISTANCE:
+ case AL_EXPONENT_DISTANCE_CLAMPED:
+ Context->DistanceModel = value;
+ break;
+
+ default:
+ alSetError(AL_INVALID_VALUE);
+ break;
+ }
+
+ ProcessContext(Context);
+ }
+ else
+ {
+ // Invalid Context
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ return;
+}
diff --git a/OpenAL32/alThunk.c b/OpenAL32/alThunk.c
new file mode 100644
index 00000000..d050d6b4
--- /dev/null
+++ b/OpenAL32/alThunk.c
@@ -0,0 +1,108 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 by authors.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include <stdlib.h>
+
+#include "alMain.h"
+#include "alThunk.h"
+
+typedef struct {
+ ALvoid *ptr;
+ ALboolean InUse;
+} ThunkEntry;
+
+static ThunkEntry *g_ThunkArray;
+static ALuint g_ThunkArraySize;
+
+static CRITICAL_SECTION g_ThunkLock;
+
+void alThunkInit(void)
+{
+ InitializeCriticalSection(&g_ThunkLock);
+ g_ThunkArraySize = 1;
+ g_ThunkArray = calloc(1, g_ThunkArraySize * sizeof(ThunkEntry));
+}
+
+void alThunkExit(void)
+{
+ free(g_ThunkArray);
+ g_ThunkArray = NULL;
+ g_ThunkArraySize = 0;
+ DeleteCriticalSection(&g_ThunkLock);
+}
+
+ALuint alThunkAddEntry(ALvoid *ptr)
+{
+ ALuint index;
+
+ EnterCriticalSection(&g_ThunkLock);
+
+ for(index = 0;index < g_ThunkArraySize;index++)
+ {
+ if(g_ThunkArray[index].InUse == AL_FALSE)
+ break;
+ }
+
+ if(index == g_ThunkArraySize)
+ {
+ ThunkEntry *NewList;
+
+ NewList = realloc(g_ThunkArray, g_ThunkArraySize*2 * sizeof(ThunkEntry));
+ if(!NewList)
+ {
+ LeaveCriticalSection(&g_ThunkLock);
+ return 0;
+ }
+ memset(&NewList[g_ThunkArraySize], 0, g_ThunkArraySize*sizeof(ThunkEntry));
+ g_ThunkArraySize *= 2;
+ g_ThunkArray = NewList;
+ }
+
+ g_ThunkArray[index].ptr = ptr;
+ g_ThunkArray[index].InUse = AL_TRUE;
+
+ LeaveCriticalSection(&g_ThunkLock);
+
+ return index+1;
+}
+
+void alThunkRemoveEntry(ALuint index)
+{
+ EnterCriticalSection(&g_ThunkLock);
+
+ if(index > 0 && index <= g_ThunkArraySize)
+ g_ThunkArray[index-1].InUse = AL_FALSE;
+
+ LeaveCriticalSection(&g_ThunkLock);
+}
+
+ALvoid *alThunkLookupEntry(ALuint index)
+{
+ ALvoid *ptr = NULL;
+
+ EnterCriticalSection(&g_ThunkLock);
+
+ if(index > 0 && index <= g_ThunkArraySize)
+ ptr = g_ThunkArray[index-1].ptr;
+
+ LeaveCriticalSection(&g_ThunkLock);
+
+ return ptr;
+}