aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c46
-rw-r--r--Alc/ALu.c131
-rw-r--r--CMakeLists.txt5
-rw-r--r--OpenAL32/Include/alAuxEffectSlot.h50
-rw-r--r--OpenAL32/Include/alEffect.h57
-rw-r--r--OpenAL32/Include/alFilter.h55
-rw-r--r--OpenAL32/Include/alListener.h3
-rw-r--r--OpenAL32/Include/alMain.h1
-rw-r--r--OpenAL32/Include/alSource.h33
-rw-r--r--OpenAL32/OpenAL32.c6
-rw-r--r--OpenAL32/alAuxEffectSlot.c422
-rw-r--r--OpenAL32/alEffect.c383
-rw-r--r--OpenAL32/alExtension.c82
-rw-r--r--OpenAL32/alFilter.c421
-rw-r--r--OpenAL32/alListener.c22
-rw-r--r--OpenAL32/alSource.c137
16 files changed, 1832 insertions, 22 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index b4ec8e9f..8c824a2d 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <memory.h>
#include "alMain.h"
+#include "alSource.h"
#include "AL/al.h"
#include "AL/alc.h"
@@ -63,6 +64,9 @@ struct {
///////////////////////////////////////////////////////
+#define ALC_EFX_MAJOR_VERSION 0x20001
+#define ALC_EFX_MINOR_VERSION 0x20002
+#define ALC_MAX_AUXILIARY_SENDS 0x20003
///////////////////////////////////////////////////////
// STRING and EXTENSIONS
@@ -83,6 +87,7 @@ static ALCextension alcExtensions[] = {
{ "ALC_ENUMERATE_ALL_EXT", (ALvoid *) NULL },
{ "ALC_ENUMERATION_EXT", (ALvoid *) NULL },
{ "ALC_EXT_CAPTURE", (ALvoid *) NULL },
+ { "ALC_EXT_EFX", (ALvoid *) NULL },
{ NULL, (ALvoid *) NULL }
};
@@ -132,9 +137,14 @@ static ALenums enumeration[]={
{ (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
{ (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
{ (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
- { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER },
+ { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
{ (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
+ // EFX Properties
+ { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
+ { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
+ { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
+
// ALC Error Message
{ (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
{ (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
@@ -162,10 +172,13 @@ static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
-static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
+static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_EFX";
static ALCint alcMajorVersion = 1;
static ALCint alcMinorVersion = 1;
+static ALCint alcEFXMajorVersion = 1;
+static ALCint alcEFXMinorVersion = 0;
+
///////////////////////////////////////////////////////
@@ -328,6 +341,7 @@ static ALvoid InitContext(ALCcontext *pContext)
{
//Initialise listener
pContext->Listener.Gain = 1.0f;
+ pContext->Listener.MetersPerUnit = 1.0f;
pContext->Listener.Position[0] = 0.0f;
pContext->Listener.Position[1] = 0.0f;
pContext->Listener.Position[2] = 0.0f;
@@ -665,13 +679,34 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
*data = alcMinorVersion;
break;
+ case ALC_EFX_MAJOR_VERSION:
+ if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = alcEFXMajorVersion;
+ break;
+
+ case ALC_EFX_MINOR_VERSION:
+ if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = alcEFXMinorVersion;
+ break;
+
+ case ALC_MAX_AUXILIARY_SENDS:
+ if(!size)
+ SetALCError(ALC_INVALID_VALUE);
+ else
+ *data = MAX_SENDS;
+ break;
+
case ALC_ATTRIBUTES_SIZE:
if(!device)
SetALCError(ALC_INVALID_DEVICE);
else if(!size)
SetALCError(ALC_INVALID_VALUE);
else
- *data = 11;
+ *data = 12;
break;
case ALC_ALL_ATTRIBUTES:
@@ -693,13 +728,16 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
data[i++] = ALC_FALSE;
SuspendContext(NULL);
- if(device->Context && size >= 11)
+ if(device->Context && size >= 12)
{
data[i++] = ALC_MONO_SOURCES;
data[i++] = device->Context->lNumMonoSources;
data[i++] = ALC_STEREO_SOURCES;
data[i++] = device->Context->lNumStereoSources;
+
+ data[i++] = ALC_MAX_AUXILIARY_SENDS;
+ data[i++] = MAX_SENDS;
}
ProcessContext(NULL);
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 87764592..2ae19ed3 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -150,15 +150,40 @@ static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
memcpy(vector, result, sizeof(result));
}
+static __inline ALfloat aluComputeDrySample(ALsource *source, ALfloat DryGainHF, ALfloat sample)
+{
+ if(DryGainHF < 1.0f)
+ {
+ sample *= DryGainHF;
+ sample += source->LastDrySample * (1.0f - DryGainHF);
+ }
+
+ source->LastDrySample = sample;
+ return sample;
+}
+
+static __inline ALfloat aluComputeWetSample(ALsource *source, ALfloat WetGainHF, ALfloat sample)
+{
+ if(WetGainHF < 1.0f)
+ {
+ sample *= WetGainHF;
+ sample += source->LastWetSample * (1.0f - WetGainHF);
+ }
+
+ source->LastWetSample = sample;
+ return sample;
+}
+
static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
ALenum isMono, ALenum OutputFormat,
ALfloat *drysend, ALfloat *wetsend,
- ALfloat *pitch)
+ ALfloat *pitch, ALfloat *drygainhf,
+ ALfloat *wetgainhf)
{
ALfloat ListenerOrientation[6],ListenerPosition[3],ListenerVelocity[3];
ALfloat InnerAngle,OuterAngle,OuterGain,Angle,Distance,DryMix,WetMix;
ALfloat Direction[3],Position[3],Velocity[3],SourceToListener[3];
- ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
+ ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF;
ALfloat Pitch,ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain;
ALfloat U[3],V[3],N[3];
ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity;
@@ -167,6 +192,11 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
ALfloat Matrix[3][3];
ALint HeadRelative;
ALfloat flAttenuation;
+ ALfloat RoomAttenuation;
+ ALfloat MetersPerUnit;
+ ALfloat RoomRolloff;
+ ALfloat DryGainHF = 1.0f;
+ ALfloat WetGainHF = 1.0f;
//Get context properties
DopplerFactor = ALContext->DopplerFactor;
@@ -176,6 +206,7 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
//Get listener properties
ListenerGain = ALContext->Listener.Gain;
+ MetersPerUnit = ALContext->Listener.MetersPerUnit;
memcpy(ListenerPosition, ALContext->Listener.Position, sizeof(ALContext->Listener.Position));
memcpy(ListenerVelocity, ALContext->Listener.Velocity, sizeof(ALContext->Listener.Velocity));
memcpy(&ListenerOrientation[0], ALContext->Listener.Forward, sizeof(ALContext->Listener.Forward));
@@ -196,10 +227,8 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
InnerAngle = ALSource->flInnerAngle;
OuterAngle = ALSource->flOuterAngle;
HeadRelative = ALSource->bHeadRelative;
-
- //Set working variables
- DryMix = (ALfloat)(1.0f);
- WetMix = (ALfloat)(0.0f);
+ OuterGainHF = ALSource->OuterGainHF;
+ RoomRolloff = ALSource->RoomRolloffFactor;
//Only apply 3D calculations for mono buffers
if(isMono != AL_FALSE)
@@ -216,6 +245,7 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
Distance = aluSqrt(aluDotproduct(Position, Position));
flAttenuation = 1.0f;
+ RoomAttenuation = 1.0f;
switch (DistanceModel)
{
case AL_INVERSE_DISTANCE_CLAMPED:
@@ -229,6 +259,8 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
{
if ((MinDist + (Rolloff * (Distance - MinDist))) > 0.0f)
flAttenuation = MinDist / (MinDist + (Rolloff * (Distance - MinDist)));
+ if ((MinDist + (RoomRolloff * (Distance - MinDist))) > 0.0f)
+ RoomAttenuation = MinDist / (MinDist + (RoomRolloff * (Distance - MinDist)));
}
break;
@@ -241,7 +273,10 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
case AL_LINEAR_DISTANCE:
Distance=__min(Distance,MaxDist);
if (MaxDist != MinDist)
+ {
flAttenuation = 1.0f - (Rolloff*(Distance-MinDist)/(MaxDist - MinDist));
+ RoomAttenuation = 1.0f - (RoomRolloff*(Distance-MinDist)/(MaxDist - MinDist));
+ }
break;
case AL_EXPONENT_DISTANCE_CLAMPED:
@@ -252,17 +287,24 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
//fall-through
case AL_EXPONENT_DISTANCE:
if ((Distance > 0.0f) && (MinDist > 0.0f))
+ {
flAttenuation = (ALfloat)pow(Distance/MinDist, -Rolloff);
+ RoomAttenuation = (ALfloat)pow(Distance/MinDist, -RoomRolloff);
+ }
break;
case AL_NONE:
default:
flAttenuation = 1.0f;
+ RoomAttenuation = 1.0f;
break;
}
// Source Gain + Attenuation
DryMix = SourceVolume * flAttenuation;
+ WetMix = SourceVolume * ((ALSource->WetGainAuto &&
+ ALSource->Send[0].Slot.AuxSendAuto) ?
+ RoomAttenuation : 1.0f);
// Clamp to Min/Max Gain
DryMix = __min(DryMix,MaxVolume);
@@ -277,9 +319,26 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
aluNormalize(SourceToListener);
Angle = (ALfloat)(180.0*acos(aluDotproduct(Direction,SourceToListener))/3.141592654f);
if(Angle >= InnerAngle && Angle <= OuterAngle)
- ConeVolume = (1.0f+(OuterGain-1.0f)*(Angle-InnerAngle)/(OuterAngle-InnerAngle));
+ {
+ ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
+ ConeVolume = (1.0f+(OuterGain-1.0f)*scale);
+ if(ALSource->WetGainAuto)
+ WetMix *= ConeVolume;
+ if(ALSource->DryGainHFAuto)
+ DryGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
+ if(ALSource->WetGainHFAuto)
+ WetGainHF *= (1.0f+(OuterGainHF-1.0f)*scale);
+ }
else if(Angle > OuterAngle)
- ConeVolume = (1.0f+(OuterGain-1.0f) );
+ {
+ ConeVolume = (1.0f+(OuterGain-1.0f));
+ if(ALSource->WetGainAuto)
+ WetMix *= ConeVolume;
+ if(ALSource->DryGainHFAuto)
+ DryGainHF *= (1.0f+(OuterGainHF-1.0f));
+ if(ALSource->WetGainHFAuto)
+ WetGainHF *= (1.0f+(OuterGainHF-1.0f));
+ }
else
ConeVolume = 1.0f;
@@ -319,7 +378,34 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
aluMatrixVector(Position, Matrix);
- //6. Convert normalized position into pannings, then into channel volumes
+ //6. Apply filter gains and filters
+ switch(ALSource->DirectFilter.filter)
+ {
+ case AL_FILTER_LOWPASS:
+ DryMix *= ALSource->DirectFilter.Gain;
+ DryGainHF *= ALSource->DirectFilter.GainHF;
+ break;
+ }
+
+ switch(ALSource->Send[0].WetFilter.filter)
+ {
+ case AL_FILTER_LOWPASS:
+ WetMix *= ALSource->Send[0].WetFilter.Gain;
+ WetGainHF *= ALSource->Send[0].WetFilter.GainHF;
+ break;
+ }
+
+ if(ALSource->AirAbsorptionFactor > 0.0f)
+ DryGainHF *= pow(ALSource->AirAbsorptionFactor * AIRABSORBGAINHF,
+ Distance * MetersPerUnit);
+
+ *drygainhf = DryGainHF;
+ *wetgainhf = WetGainHF;
+
+ //7. Convert pannings into channel volumes
+ WetMix *= ALSource->Send[0].Slot.Gain;
+
+ //8. Convert normalized position into pannings, then into channel volumes
aluNormalize(Position);
switch(OutputFormat)
{
@@ -373,6 +459,9 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
wetsend[3] = SourceVolume * 0.0f * ListenerGain;
pitch[0] = Pitch;
+
+ *drygainhf = DryGainHF;
+ *wetgainhf = WetGainHF;
}
}
@@ -382,6 +471,8 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f };
ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ ALfloat DryGainHF = 0.0f;
+ ALfloat WetGainHF = 0.0f;
ALuint BlockAlign,BufferSize;
ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
ALuint Channels,Bits,Frequency,ulExtraSamples;
@@ -441,7 +532,8 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
CalcSourceParams(ALContext, ALSource,
(Channels==1) ? AL_TRUE : AL_FALSE,
- format, DrySend, WetSend, &Pitch);
+ format, DrySend, WetSend, &Pitch,
+ &DryGainHF, &WetGainHF);
Pitch = (Pitch*Frequency) / ALContext->Frequency;
@@ -504,17 +596,24 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
if(Channels==1)
{
//First order interpolator
- value = (ALfloat)((ALshort)(((Data[k]*((1L<<FRACTIONBITS)-fraction))+(Data[k+1]*(fraction)))>>FRACTIONBITS));
+ ALfloat sample = (ALfloat)((ALshort)(((Data[k]*((1L<<FRACTIONBITS)-fraction))+(Data[k+1]*(fraction)))>>FRACTIONBITS));
+
//Direct path final mix buffer and panning
+ value = aluComputeDrySample(ALSource, DryGainHF, sample);
DryBuffer[j][0] += value*DrySend[0];
DryBuffer[j][1] += value*DrySend[1];
DryBuffer[j][2] += value*DrySend[2];
DryBuffer[j][3] += value*DrySend[3];
- //Room path final mix buffer and panning
- WetBuffer[j][0] += value*WetSend[0];
- WetBuffer[j][1] += value*WetSend[1];
- WetBuffer[j][2] += value*WetSend[2];
- WetBuffer[j][3] += value*WetSend[3];
+
+ if(ALSource->Send[0].Slot.effectslot)
+ {
+ //Room path final mix buffer and panning
+ value = aluComputeWetSample(ALSource, WetGainHF, sample);
+ WetBuffer[j][0] += value*WetSend[0];
+ WetBuffer[j][1] += value*WetSend[1];
+ WetBuffer[j][2] += value*WetSend[2];
+ WetBuffer[j][3] += value*WetSend[3];
+ }
}
else
{
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0dea95a6..df42e1f9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -162,9 +162,12 @@ IF(NOT "${HAVE_STDINT_H}")
ENDIF()
-SET(OPENAL_OBJS OpenAL32/alBuffer.c
+SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
+ OpenAL32/alBuffer.c
+ OpenAL32/alEffect.c
OpenAL32/alError.c
OpenAL32/alExtension.c
+ OpenAL32/alFilter.c
OpenAL32/alListener.c
OpenAL32/alSource.c
OpenAL32/alState.c
diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h
new file mode 100644
index 00000000..e34d787d
--- /dev/null
+++ b/OpenAL32/Include/alAuxEffectSlot.h
@@ -0,0 +1,50 @@
+#ifndef _AL_AUXEFFECTSLOT_H_
+#define _AL_AUXEFFECTSLOT_H_
+
+#include "alEffect.h"
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AL_EFFECTSLOT_EFFECT 0x0001
+#define AL_EFFECTSLOT_GAIN 0x0002
+#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
+
+#define AL_EFFECTSLOT_NULL 0x0000
+
+typedef struct ALeffectslot_struct
+{
+ ALeffect effect;
+
+ ALfloat Gain;
+ ALboolean AuxSendAuto;
+
+ // Index to itself
+ ALuint effectslot;
+
+ struct ALeffectslot_struct *next;
+} ALeffectslot;
+
+AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
+AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
+AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
+
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
+
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
+
+ALvoid ReleaseALAuxiliaryEffectSlots(ALvoid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alEffect.h b/OpenAL32/Include/alEffect.h
new file mode 100644
index 00000000..d42f5adc
--- /dev/null
+++ b/OpenAL32/Include/alEffect.h
@@ -0,0 +1,57 @@
+#ifndef _AL_EFFECT_H_
+#define _AL_EFFECT_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AL_EFFECT_TYPE 0x8001
+
+#define AL_EFFECT_NULL 0x0000
+#define AL_EFFECT_REVERB 0x0001
+#define AL_EFFECT_CHORUS 0x0002
+#define AL_EFFECT_DISTORTION 0x0003
+#define AL_EFFECT_ECHO 0x0004
+#define AL_EFFECT_FLANGER 0x0005
+#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
+#define AL_EFFECT_VOCAL_MORPHER 0x0007
+#define AL_EFFECT_PITCH_SHIFTER 0x0008
+#define AL_EFFECT_RING_MODULATOR 0x0009
+#define AL_EFFECT_AUTOWAH 0x000A
+#define AL_EFFECT_COMPRESSOR 0x000B
+#define AL_EFFECT_EQUALIZER 0x000C
+
+typedef struct ALeffect_struct
+{
+ // Effect type (AL_EFFECT_NULL, ...)
+ ALenum type;
+
+ // Index to itself
+ ALuint effect;
+
+ struct ALeffect_struct *next;
+} ALeffect;
+
+AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
+AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
+AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
+
+AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
+AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
+AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
+AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
+
+AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
+AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
+AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
+AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
+
+ALvoid ReleaseALEffects(ALvoid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alFilter.h b/OpenAL32/Include/alFilter.h
new file mode 100644
index 00000000..038304e8
--- /dev/null
+++ b/OpenAL32/Include/alFilter.h
@@ -0,0 +1,55 @@
+#ifndef _AL_FILTER_H_
+#define _AL_FILTER_H_
+
+#include "AL/al.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AL_FILTER_TYPE 0x8001
+
+#define AL_FILTER_NULL 0x0000
+#define AL_FILTER_LOWPASS 0x0001
+#define AL_FILTER_HIGHPASS 0x0002
+#define AL_FILTER_BANDPASS 0x0003
+
+#define AL_LOWPASS_GAIN 0x0001
+#define AL_LOWPASS_GAINHF 0x0002
+
+
+typedef struct ALfilter_struct
+{
+ // Filter type (AL_FILTER_NULL, ...)
+ ALenum type;
+
+ ALfloat Gain;
+ ALfloat GainHF;
+
+ // Index to itself
+ ALuint filter;
+
+ struct ALfilter_struct *next;
+} ALfilter;
+
+AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
+AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
+AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
+
+AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
+AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
+AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
+AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
+
+AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
+AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
+AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
+AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
+
+ALvoid ReleaseALFilters(ALvoid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/OpenAL32/Include/alListener.h b/OpenAL32/Include/alListener.h
index 2075e612..d22261fa 100644
--- a/OpenAL32/Include/alListener.h
+++ b/OpenAL32/Include/alListener.h
@@ -7,6 +7,8 @@
extern "C" {
#endif
+#define AL_METERS_PER_UNIT 0x20004
+
typedef struct ALlistener_struct
{
ALfloat Position[3];
@@ -14,6 +16,7 @@ typedef struct ALlistener_struct
ALfloat Forward[3];
ALfloat Up[3];
ALfloat Gain;
+ ALfloat MetersPerUnit;
} ALlistener;
#ifdef __cplusplus
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 71e29e47..168991b7 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -98,6 +98,7 @@ extern char _alDebug[256];
//#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050)
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
+#define AIRABSORBGAINHF (0.994f)
typedef struct {
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
index 499ddcf4..f54d4721 100644
--- a/OpenAL32/Include/alSource.h
+++ b/OpenAL32/Include/alSource.h
@@ -3,8 +3,22 @@
#define AL_NUM_SOURCE_PARAMS 128
+/* This cannot be changed without working on the code! */
+#define MAX_SENDS 1
+
+#include "alFilter.h"
+#include "alAuxEffectSlot.h"
#include "AL/al.h"
+#define AL_DIRECT_FILTER 0x20005
+#define AL_AUXILIARY_SEND_FILTER 0x20006
+#define AL_AIR_ABSORPTION_FACTOR 0x20007
+#define AL_ROOM_ROLLOFF_FACTOR 0x20008
+#define AL_CONE_OUTER_GAINHF 0x20009
+#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
+#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
+#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,6 +64,25 @@ typedef struct ALsource_struct
ALuint BuffersPlayed; // Number of buffers played on this loop
ALuint BufferPosition; // Read position in audio data of current buffer
+ ALfilter DirectFilter;
+
+ struct {
+ ALeffectslot Slot;
+ ALfilter WetFilter;
+ } Send[MAX_SENDS];
+
+ ALfloat LastDrySample;
+ ALfloat LastWetSample;
+
+ ALboolean DryGainHFAuto;
+ ALboolean WetGainAuto;
+ ALboolean WetGainHFAuto;
+ ALfloat OuterGainHF;
+
+ ALfloat AirAbsorptionFactor;
+
+ ALfloat RoomRolloffFactor;
+
// Index to itself
ALuint source;
diff --git a/OpenAL32/OpenAL32.c b/OpenAL32/OpenAL32.c
index 678888b0..8510c7cb 100644
--- a/OpenAL32/OpenAL32.c
+++ b/OpenAL32/OpenAL32.c
@@ -20,6 +20,9 @@
#include "alMain.h"
#include "alBuffer.h"
+#include "alFilter.h"
+#include "alEffect.h"
+#include "alAuxEffectSlot.h"
#include "alThunk.h"
CRITICAL_SECTION _alMutex;
@@ -55,6 +58,9 @@ static void my_deinit()
once = AL_TRUE;
ReleaseALBuffers();
+ ReleaseALAuxiliaryEffectSlots();
+ ReleaseALEffects();
+ ReleaseALFilters();
FreeALConfig();
ALTHUNK_EXIT();
DeleteCriticalSection(&_alMutex);
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
new file mode 100644
index 00000000..6b8a335c
--- /dev/null
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -0,0 +1,422 @@
+/**
+ * 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 "config.h"
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#include "alMain.h"
+#include "alAuxEffectSlot.h"
+
+static ALeffectslot *g_AuxiliaryEffectSlotList;
+static ALuint g_AuxiliaryEffectSlotCount;
+
+
+AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
+{
+ ALCcontext *Context;
+ ALsizei i;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (n > 0)
+ {
+ /* NOTE: We only support one slot currently */
+ if(n == 1 && g_AuxiliaryEffectSlotCount == 0)
+ {
+ // Check that enough memory has been allocted in the 'sources' array for n Sources
+ if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
+ {
+ ALeffectslot **list = &g_AuxiliaryEffectSlotList;
+ while(*list)
+ list = &(*list)->next;
+
+ i = 0;
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALeffectslot));
+ if(!(*list))
+ {
+ // We must have run out or memory
+ alDeleteAuxiliaryEffectSlots(i, effectslots);
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+ }
+
+ (*list)->Gain = 1.0;
+ (*list)->AuxSendAuto = AL_TRUE;
+
+ effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->effectslot = effectslots[i];
+
+ g_AuxiliaryEffectSlotCount++;
+ i++;
+ }
+ }
+ }
+ else
+ alSetError(AL_INVALID_OPERATION);
+ }
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
+{
+ ALCcontext *Context;
+ ALeffectslot *ALAuxiliaryEffectSlot;
+ ALsizei i;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (n >= 0)
+ {
+ // Check that all effectslots are valid
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsAuxiliaryEffectSlot(effectslots[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ break;
+ }
+ }
+
+ if (i == n)
+ {
+ // All effectslots are valid
+ for (i = 0; i < n; i++)
+ {
+ // Recheck that the effectslot is valid, because there could be duplicated names
+ if (alIsAuxiliaryEffectSlot(effectslots[i]))
+ {
+ ALeffectslot **list;
+
+ ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
+
+ // Remove Source from list of Sources
+ list = &g_AuxiliaryEffectSlotList;
+ while(*list && *list != ALAuxiliaryEffectSlot)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+ ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
+
+ memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
+ free(ALAuxiliaryEffectSlot);
+
+ g_AuxiliaryEffectSlotCount--;
+ }
+ }
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+}
+
+AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
+{
+ ALCcontext *Context;
+ ALeffectslot **list;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ list = &g_AuxiliaryEffectSlotList;
+ while(*list && (*list)->effectslot != effectslot)
+ list = &(*list)->next;
+
+ ProcessContext(Context);
+
+ return (*list ? AL_TRUE : AL_FALSE);
+}
+
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
+
+ switch(param)
+ {
+ case AL_EFFECTSLOT_EFFECT:
+ if(alIsEffect(iValue))
+ {
+ ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
+ if(!effect)
+ {
+ ALEffectSlot->effect.type = AL_EFFECT_NULL;
+ ALEffectSlot->effect.effect = 0;
+ }
+ else
+ memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
+ if(iValue == AL_TRUE || iValue == AL_FALSE)
+ ALEffectSlot->AuxSendAuto = iValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ switch(param)
+ {
+ case AL_EFFECTSLOT_EFFECT:
+ case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
+ alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
+{
+ ALCcontext *Context;
+
+ (void)flValue;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
+
+ switch(param)
+ {
+ case AL_EFFECTSLOT_GAIN:
+ if(flValue >= 0.0f && flValue <= 1.0f)
+ ALEffectSlot->Gain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ switch(param)
+ {
+ case AL_EFFECTSLOT_GAIN:
+ alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
+
+ switch(param)
+ {
+ case AL_EFFECTSLOT_EFFECT:
+ *piValue = ALEffectSlot->effect.effect;
+ break;
+
+ case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
+ *piValue = ALEffectSlot->AuxSendAuto;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ switch(param)
+ {
+ case AL_EFFECTSLOT_EFFECT:
+ case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
+ alGetAuxiliaryEffectSloti(effectslot, param, piValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
+
+ switch(param)
+ {
+ case AL_EFFECTSLOT_GAIN:
+ *pflValue = ALEffectSlot->Gain;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (alIsAuxiliaryEffectSlot(effectslot))
+ {
+ switch(param)
+ {
+ case AL_EFFECTSLOT_GAIN:
+ alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+
+ALvoid ReleaseALAuxiliaryEffectSlots(ALvoid)
+{
+#ifdef _DEBUG
+ if(g_AuxiliaryEffectSlotCount > 0)
+ AL_PRINT("exit() %d AuxiliaryEffectSlot(s) NOT deleted\n", g_AuxiliaryEffectSlotCount);
+#endif
+
+ while(g_AuxiliaryEffectSlotList)
+ {
+ ALeffectslot *temp = g_AuxiliaryEffectSlotList;
+ g_AuxiliaryEffectSlotList = g_AuxiliaryEffectSlotList->next;
+
+ // Release effectslot structure
+ memset(temp, 0, sizeof(ALeffectslot));
+ free(temp);
+ }
+ g_AuxiliaryEffectSlotCount = 0;
+}
diff --git a/OpenAL32/alEffect.c b/OpenAL32/alEffect.c
new file mode 100644
index 00000000..823d09ae
--- /dev/null
+++ b/OpenAL32/alEffect.c
@@ -0,0 +1,383 @@
+/**
+ * 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 "config.h"
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#include "alMain.h"
+#include "alEffect.h"
+
+static ALeffect *g_EffectList;
+static ALuint g_EffectCount;
+
+static void InitEffectParams(ALeffect *effect, ALenum type);
+
+
+AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
+{
+ ALCcontext *Context;
+ ALsizei i;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (n > 0)
+ {
+ // Check that enough memory has been allocted in the 'sources' array for n Sources
+ if (!IsBadWritePtr((void*)effects, n * sizeof(ALuint)))
+ {
+ ALeffect **list = &g_EffectList;
+ while(*list)
+ list = &(*list)->next;
+
+ i = 0;
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALeffect));
+ if(!(*list))
+ {
+ // We must have run out or memory
+ alDeleteEffects(i, effects);
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+ }
+
+ effects[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->effect = effects[i];
+
+ InitEffectParams(*list, AL_EFFECT_NULL);
+ g_EffectCount++;
+ i++;
+ }
+ }
+ }
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects)
+{
+ ALCcontext *Context;
+ ALeffect *ALEffect;
+ ALsizei i;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (n >= 0)
+ {
+ // Check that all effects are valid
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsEffect(effects[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ break;
+ }
+ }
+
+ if (i == n)
+ {
+ // All effects are valid
+ for (i = 0; i < n; i++)
+ {
+ // Recheck that the effect is valid, because there could be duplicated names
+ if (effects[i] && alIsEffect(effects[i]))
+ {
+ ALeffect **list;
+
+ ALEffect = ((ALeffect*)ALTHUNK_LOOKUPENTRY(effects[i]));
+
+ // Remove Source from list of Sources
+ list = &g_EffectList;
+ while(*list && *list != ALEffect)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+ ALTHUNK_REMOVEENTRY(ALEffect->effect);
+
+ memset(ALEffect, 0, sizeof(ALeffect));
+ free(ALEffect);
+
+ g_EffectCount--;
+ }
+ }
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+}
+
+AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
+{
+ ALCcontext *Context;
+ ALeffect **list;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ list = &g_EffectList;
+ while(*list && (*list)->effect != effect)
+ list = &(*list)->next;
+
+ ProcessContext(Context);
+
+ return ((*list || !effect) ? AL_TRUE : AL_FALSE);
+}
+
+AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
+
+ switch(param)
+ {
+ case AL_EFFECT_TYPE:
+ if(iValue == AL_EFFECT_NULL)
+ InitEffectParams(ALEffect, iValue);
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ switch(param)
+ {
+ case AL_EFFECT_TYPE:
+ alEffecti(effect, param, piValues[0]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
+{
+ ALCcontext *Context;
+
+ (void)flValue;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ switch(param)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
+{
+ ALCcontext *Context;
+
+ (void)pflValues;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ switch(param)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
+
+ switch(param)
+ {
+ case AL_EFFECT_TYPE:
+ *piValue = ALEffect->type;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ switch(param)
+ {
+ case AL_EFFECT_TYPE:
+ alGetEffecti(effect, param, piValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
+{
+ ALCcontext *Context;
+
+ (void)pflValue;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ switch(param)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
+{
+ ALCcontext *Context;
+
+ (void)pflValues;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (effect && alIsEffect(effect))
+ {
+ switch(param)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+
+ALvoid ReleaseALEffects(ALvoid)
+{
+#ifdef _DEBUG
+ if(g_EffectCount > 0)
+ AL_PRINT("exit() %d Effect(s) NOT deleted\n", g_EffectCount);
+#endif
+
+ while(g_EffectList)
+ {
+ ALeffect *temp = g_EffectList;
+ g_EffectList = g_EffectList->next;
+
+ // Release effect structure
+ memset(temp, 0, sizeof(ALeffect));
+ free(temp);
+ }
+ g_EffectCount = 0;
+}
+
+
+static void InitEffectParams(ALeffect *effect, ALenum type)
+{
+ effect->type = type;
+}
diff --git a/OpenAL32/alExtension.c b/OpenAL32/alExtension.c
index 269590e9..54371ff4 100644
--- a/OpenAL32/alExtension.c
+++ b/OpenAL32/alExtension.c
@@ -24,6 +24,9 @@
#include "alExtension.h"
#include "alError.h"
#include "alMain.h"
+#include "alFilter.h"
+#include "alEffect.h"
+#include "alAuxEffectSlot.h"
#include "AL/al.h"
#include "AL/alc.h"
@@ -101,6 +104,43 @@ static ALfunction function[]= {
{ "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
{ "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
{ "alDistanceModel", (ALvoid *) alDistanceModel },
+
+ { "alGenFilters", (ALvoid *) alGenFilters },
+ { "alDeleteFilters", (ALvoid *) alDeleteFilters },
+ { "alIsFilter", (ALvoid *) alIsFilter },
+ { "alFilteri", (ALvoid *) alFilteri },
+ { "alFilteriv", (ALvoid *) alFilteriv },
+ { "alFilterf", (ALvoid *) alFilterf },
+ { "alFilterfv", (ALvoid *) alFilterfv },
+ { "alGetFilteri", (ALvoid *) alGetFilteri },
+ { "alGetFilteriv", (ALvoid *) alGetFilteriv },
+ { "alGetFilterf", (ALvoid *) alGetFilterf },
+ { "alGetFilterfv", (ALvoid *) alGetFilterfv },
+
+ { "alGenEffects", (ALvoid *) alGenEffects },
+ { "alDeleteEffects", (ALvoid *) alDeleteEffects },
+ { "alIsEffect", (ALvoid *) alIsEffect },
+ { "alEffecti", (ALvoid *) alEffecti },
+ { "alEffectiv", (ALvoid *) alEffectiv },
+ { "alEffectf", (ALvoid *) alEffectf },
+ { "alEffectfv", (ALvoid *) alEffectfv },
+ { "alGetEffecti", (ALvoid *) alGetEffecti },
+ { "alGetEffectiv", (ALvoid *) alGetEffectiv },
+ { "alGetEffectf", (ALvoid *) alGetEffectf },
+ { "alGetEffectfv", (ALvoid *) alGetEffectfv },
+
+ { "alGenAuxiliaryEffectSlots", (ALvoid *) alGenAuxiliaryEffectSlots },
+ { "alDeleteAuxiliaryEffectSlots",(ALvoid *) alDeleteAuxiliaryEffectSlots},
+ { "alIsAuxiliaryEffectSlot", (ALvoid *) alIsAuxiliaryEffectSlot },
+ { "alAuxiliaryEffectSloti", (ALvoid *) alAuxiliaryEffectSloti },
+ { "alAuxiliaryEffectSlotiv", (ALvoid *) alAuxiliaryEffectSlotiv },
+ { "alAuxiliaryEffectSlotf", (ALvoid *) alAuxiliaryEffectSlotf },
+ { "alAuxiliaryEffectSlotfv", (ALvoid *) alAuxiliaryEffectSlotfv },
+ { "alGetAuxiliaryEffectSloti", (ALvoid *) alGetAuxiliaryEffectSloti },
+ { "alGetAuxiliaryEffectSlotiv", (ALvoid *) alGetAuxiliaryEffectSlotiv},
+ { "alGetAuxiliaryEffectSlotf", (ALvoid *) alGetAuxiliaryEffectSlotf },
+ { "alGetAuxiliaryEffectSlotfv", (ALvoid *) alGetAuxiliaryEffectSlotfv},
+
{ NULL, (ALvoid *) NULL } };
static ALenums enumeration[]={
@@ -135,6 +175,18 @@ static ALenums enumeration[]={
{ (ALchar *)"AL_STATIC", AL_STATIC },
{ (ALchar *)"AL_STREAMING", AL_STREAMING },
{ (ALchar *)"AL_UNDETERMINED", AL_UNDETERMINED },
+ { (ALchar *)"AL_METERS_PER_UNIT", AL_METERS_PER_UNIT },
+
+ // Source EFX Properties
+ { (ALchar *)"AL_DIRECT_FILTER", AL_DIRECT_FILTER },
+ { (ALchar *)"AL_AUXILIARY_SEND_FILTER", AL_AUXILIARY_SEND_FILTER },
+ { (ALchar *)"AL_AIR_ABSORPTION_FACTOR", AL_AIR_ABSORPTION_FACTOR },
+ { (ALchar *)"AL_ROOM_ROLLOFF_FACTOR", AL_ROOM_ROLLOFF_FACTOR },
+ { (ALchar *)"AL_CONE_OUTER_GAINHF", AL_CONE_OUTER_GAINHF },
+ { (ALchar *)"AL_DIRECT_FILTER_GAINHF_AUTO", AL_DIRECT_FILTER_GAINHF_AUTO },
+ { (ALchar *)"AL_AUXILIARY_SEND_FILTER_GAIN_AUTO", AL_AUXILIARY_SEND_FILTER_GAIN_AUTO },
+ { (ALchar *)"AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO", AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO},
+
// Source State information
{ (ALchar *)"AL_SOURCE_STATE", AL_SOURCE_STATE },
@@ -196,8 +248,36 @@ static ALenums enumeration[]={
{ (ALchar *)"AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE },
{ (ALchar *)"AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED },
+ // Filter types
+ { (ALchar *)"AL_FILTER_TYPE", AL_FILTER_TYPE },
+ { (ALchar *)"AL_FILTER_NULL", AL_FILTER_NULL },
+ { (ALchar *)"AL_FILTER_LOWPASS", AL_FILTER_LOWPASS },
+ { (ALchar *)"AL_FILTER_HIGHPASS", AL_FILTER_HIGHPASS },
+ { (ALchar *)"AL_FILTER_BANDPASS", AL_FILTER_BANDPASS },
+
+ // Filter params
+ { (ALchar *)"AL_LOWPASS_GAIN", AL_LOWPASS_GAIN },
+ { (ALchar *)"AL_LOWPASS_GAINHF", AL_LOWPASS_GAINHF },
+
+ // Effect types
+ { (ALchar *)"AL_EFFECT_TYPE", AL_EFFECT_TYPE },
+ { (ALchar *)"AL_EFFECT_NULL", AL_EFFECT_NULL },
+ { (ALchar *)"AL_EFFECT_REVERB", AL_EFFECT_REVERB },
+ { (ALchar *)"AL_EFFECT_CHORUS", AL_EFFECT_CHORUS },
+ { (ALchar *)"AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION },
+ { (ALchar *)"AL_EFFECT_ECHO", AL_EFFECT_ECHO },
+ { (ALchar *)"AL_EFFECT_FLANGER", AL_EFFECT_FLANGER },
+ { (ALchar *)"AL_EFFECT_FREQUENCY_SHIFTER", AL_EFFECT_FREQUENCY_SHIFTER },
+ { (ALchar *)"AL_EFFECT_VOCAL_MORPHER", AL_EFFECT_VOCAL_MORPHER },
+ { (ALchar *)"AL_EFFECT_PITCH_SHIFTER", AL_EFFECT_PITCH_SHIFTER },
+ { (ALchar *)"AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
+ { (ALchar *)"AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH },
+ { (ALchar *)"AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR },
+ { (ALchar *)"AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER },
+
// Default
- { (ALchar *)NULL, (ALenum ) 0 } };
+ { (ALchar *)NULL, (ALenum)0 }
+};
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c
new file mode 100644
index 00000000..80da100a
--- /dev/null
+++ b/OpenAL32/alFilter.c
@@ -0,0 +1,421 @@
+/**
+ * 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 "config.h"
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+#include "alMain.h"
+#include "alFilter.h"
+
+static ALfilter *g_FilterList;
+static ALuint g_FilterCount;
+
+static void InitFilterParams(ALfilter *filter, ALenum type);
+
+
+AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
+{
+ ALCcontext *Context;
+ ALsizei i;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (n > 0)
+ {
+ // Check that enough memory has been allocted in the 'sources' array for n Sources
+ if (!IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
+ {
+ ALfilter **list = &g_FilterList;
+ while(*list)
+ list = &(*list)->next;
+
+ i = 0;
+ while(i < n)
+ {
+ *list = calloc(1, sizeof(ALfilter));
+ if(!(*list))
+ {
+ // We must have run out or memory
+ alDeleteFilters(i, filters);
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+ }
+
+ filters[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
+ (*list)->filter = filters[i];
+
+ InitFilterParams(*list, AL_FILTER_NULL);
+ g_FilterCount++;
+ i++;
+ }
+ }
+ }
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
+{
+ ALCcontext *Context;
+ ALfilter *ALFilter;
+ ALsizei i;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (n >= 0)
+ {
+ // Check that all filters are valid
+ for (i = 0; i < n; i++)
+ {
+ if (!alIsFilter(filters[i]))
+ {
+ alSetError(AL_INVALID_NAME);
+ break;
+ }
+ }
+
+ if (i == n)
+ {
+ // All filters are valid
+ for (i = 0; i < n; i++)
+ {
+ // Recheck that the filter is valid, because there could be duplicated names
+ if (filters[i] && alIsFilter(filters[i]))
+ {
+ ALfilter **list;
+
+ ALFilter = ((ALfilter*)ALTHUNK_LOOKUPENTRY(filters[i]));
+
+ // Remove Source from list of Sources
+ list = &g_FilterList;
+ while(*list && *list != ALFilter)
+ list = &(*list)->next;
+
+ if(*list)
+ *list = (*list)->next;
+ ALTHUNK_REMOVEENTRY(ALFilter->filter);
+
+ memset(ALFilter, 0, sizeof(ALfilter));
+ free(ALFilter);
+
+ g_FilterCount--;
+ }
+ }
+ }
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+
+ ProcessContext(Context);
+}
+
+AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
+{
+ ALCcontext *Context;
+ ALfilter **list;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ list = &g_FilterList;
+ while(*list && (*list)->filter != filter)
+ list = &(*list)->next;
+
+ ProcessContext(Context);
+
+ return ((*list || !filter) ? AL_TRUE : AL_FALSE);
+}
+
+AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
+
+ switch(param)
+ {
+ case AL_FILTER_TYPE:
+ if(iValue == AL_FILTER_NULL ||
+ iValue == AL_FILTER_LOWPASS)
+ InitFilterParams(ALFilter, iValue);
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ switch(param)
+ {
+ case AL_FILTER_TYPE:
+ alFilteri(filter, param, piValues[0]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
+
+ switch(param)
+ {
+ case AL_LOWPASS_GAIN:
+ if(ALFilter->type == AL_FILTER_LOWPASS)
+ {
+ if(flValue >= 0.0f && flValue <= 1.0f)
+ ALFilter->Gain = flValue;
+ }
+ else
+ alSetError(AL_INVALID_ENUM);
+ break;
+
+ case AL_LOWPASS_GAINHF:
+ if(ALFilter->type == AL_FILTER_LOWPASS)
+ {
+ if(flValue >= 0.0f && flValue <= 1.0f)
+ ALFilter->GainHF = flValue;
+ }
+ else
+ alSetError(AL_INVALID_ENUM);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ switch(param)
+ {
+ case AL_LOWPASS_GAIN:
+ case AL_LOWPASS_GAINHF:
+ alFilterf(filter, param, pflValues[0]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
+{
+ ALCcontext *Context;
+
+ (void)piValue;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ switch(param)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
+{
+ ALCcontext *Context;
+
+ (void)piValues;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ switch(param)
+ {
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
+
+ switch(param)
+ {
+ case AL_LOWPASS_GAIN:
+ if(ALFilter->type == AL_FILTER_LOWPASS)
+ *pflValue = ALFilter->Gain;
+ else
+ alSetError(AL_INVALID_ENUM);
+ break;
+
+ case AL_LOWPASS_GAINHF:
+ if(ALFilter->type == AL_FILTER_LOWPASS)
+ *pflValue = ALFilter->GainHF;
+ else
+ alSetError(AL_INVALID_ENUM);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
+{
+ ALCcontext *Context;
+
+ Context = alcGetCurrentContext();
+ SuspendContext(Context);
+
+ if (filter && alIsFilter(filter))
+ {
+ switch(param)
+ {
+ case AL_LOWPASS_GAIN:
+ case AL_LOWPASS_GAINHF:
+ alGetFilterf(filter, param, pflValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else
+ alSetError(AL_INVALID_NAME);
+
+ ProcessContext(Context);
+}
+
+
+ALvoid ReleaseALFilters(ALvoid)
+{
+#ifdef _DEBUG
+ if(g_FilterCount > 0)
+ AL_PRINT("exit() %d Filter(s) NOT deleted\n", g_FilterCount);
+#endif
+
+ while(g_FilterList)
+ {
+ ALfilter *temp = g_FilterList;
+ g_FilterList = g_FilterList->next;
+
+ // Release filter structure
+ memset(temp, 0, sizeof(ALfilter));
+ free(temp);
+ }
+ g_FilterCount = 0;
+}
+
+
+static void InitFilterParams(ALfilter *filter, ALenum type)
+{
+ filter->type = type;
+
+ filter->Gain = 1.0;
+ filter->GainHF = 1.0;
+}
diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c
index 97fc593c..1e02622a 100644
--- a/OpenAL32/alListener.c
+++ b/OpenAL32/alListener.c
@@ -41,6 +41,13 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
alSetError(AL_INVALID_VALUE);
break;
+ case AL_METERS_PER_UNIT:
+ if (flValue > 0.0f)
+ pContext->Listener.MetersPerUnit = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -112,6 +119,13 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
alSetError(AL_INVALID_VALUE);
break;
+ case AL_METERS_PER_UNIT:
+ if (pflValues[0] > 0.0f)
+ pContext->Listener.MetersPerUnit = pflValues[0];
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
case AL_POSITION:
pContext->Listener.Position[0] = pflValues[0];
pContext->Listener.Position[1] = pflValues[1];
@@ -274,6 +288,10 @@ ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
*pflValue = pContext->Listener.Gain;
break;
+ case AL_METERS_PER_UNIT:
+ *pflValue = pContext->Listener.MetersPerUnit;
+ break;
+
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -350,6 +368,10 @@ ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
pflValues[0] = pContext->Listener.Gain;
break;
+ case AL_METERS_PER_UNIT:
+ pflValues[0] = pContext->Listener.MetersPerUnit;
+ break;
+
case AL_POSITION:
pflValues[0] = pContext->Listener.Position[0];
pflValues[1] = pContext->Listener.Position[1];
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index ec8783c3..5b40f7eb 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -341,6 +341,27 @@ ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
alSetError(AL_INVALID_VALUE);
break;
+ case AL_CONE_OUTER_GAINHF:
+ if ((flValue >= 0.0f) && (flValue <= 1.0f))
+ pSource->OuterGainHF = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_AIR_ABSORPTION_FACTOR:
+ if (flValue >= 0.0f && flValue <= 10.0f)
+ pSource->AirAbsorptionFactor = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_ROOM_ROLLOFF_FACTOR:
+ if (flValue >= 0.0f && flValue <= 1.0f)
+ pSource->RoomRolloffFactor = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
@@ -461,9 +482,12 @@ ALAPI ALvoid ALAPIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *
case AL_MIN_GAIN:
case AL_MAX_GAIN:
case AL_CONE_OUTER_GAIN:
+ case AL_CONE_OUTER_GAINHF:
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
+ case AL_AIR_ABSORPTION_FACTOR:
+ case AL_ROOM_ROLLOFF_FACTOR:
alSourcef(source, eParam, pflValues[0]);
break;
@@ -636,6 +660,43 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
alSetError(AL_INVALID_VALUE);
break;
+ case AL_DIRECT_FILTER:
+ if(alIsFilter(lValue))
+ {
+ ALfilter *filter = (ALfilter*)ALTHUNK_LOOKUPENTRY(lValue);
+ if(!filter)
+ {
+ pSource->DirectFilter.type = AL_FILTER_NULL;
+ pSource->DirectFilter.filter = 0;
+ }
+ else
+ memcpy(&pSource->DirectFilter, filter, sizeof(*filter));
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ if(lValue == AL_TRUE || lValue == AL_FALSE)
+ pSource->DryGainHFAuto = lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ if(lValue == AL_TRUE || lValue == AL_FALSE)
+ pSource->WetGainAuto = lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
+ if(lValue == AL_TRUE || lValue == AL_FALSE)
+ pSource->WetGainHFAuto = lValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -664,6 +725,8 @@ ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, AL
if (alIsSource(source))
{
+ ALsource *pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
+
switch (eParam)
{
case AL_POSITION:
@@ -672,6 +735,35 @@ ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, AL
alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
break;
+ case AL_AUXILIARY_SEND_FILTER:
+ if(lValue2 >= 0 && lValue2 < MAX_SENDS &&
+ (alIsAuxiliaryEffectSlot(lValue1) || lValue1 == 0) &&
+ alIsFilter(lValue3))
+ {
+ ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(lValue1);
+ ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(lValue3);
+
+ if(!ALEffectSlot)
+ {
+ /* Disable slot */
+ pSource->Send[lValue2].Slot.effectslot = 0;
+ }
+ else
+ memcpy(&pSource->Send[lValue2].Slot, ALEffectSlot, sizeof(*ALEffectSlot));
+
+ if(!ALFilter)
+ {
+ /* Disable filter */
+ pSource->Send[lValue2].WetFilter.type = 0;
+ pSource->Send[lValue2].WetFilter.filter = 0;
+ }
+ else
+ memcpy(&pSource->Send[lValue2].WetFilter, ALFilter, sizeof(*ALFilter));
+ }
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -716,12 +808,17 @@ ALAPI void ALAPIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plVa
case AL_MAX_DISTANCE:
case AL_ROLLOFF_FACTOR:
case AL_REFERENCE_DISTANCE:
+ case AL_DIRECT_FILTER:
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
alSourcei(source, eParam, plValues[0]);
break;
case AL_POSITION:
case AL_VELOCITY:
case AL_DIRECTION:
+ case AL_AUXILIARY_SEND_FILTER:
alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
break;
@@ -792,6 +889,10 @@ ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflV
*pflValue = pSource->flOuterGain;
break;
+ case AL_CONE_OUTER_GAINHF:
+ *pflValue = pSource->OuterGainHF;
+ break;
+
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
@@ -813,6 +914,14 @@ ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflV
*pflValue = pSource->flRefDistance;
break;
+ case AL_AIR_ABSORPTION_FACTOR:
+ *pflValue = pSource->AirAbsorptionFactor;
+ break;
+
+ case AL_ROOM_ROLLOFF_FACTOR:
+ *pflValue = pSource->RoomRolloffFactor;
+ break;
+
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -920,6 +1029,9 @@ ALAPI ALvoid ALAPIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pfl
case AL_CONE_INNER_ANGLE:
case AL_CONE_OUTER_ANGLE:
case AL_REFERENCE_DISTANCE:
+ case AL_CONE_OUTER_GAINHF:
+ case AL_AIR_ABSORPTION_FACTOR:
+ case AL_ROOM_ROLLOFF_FACTOR:
alGetSourcef(source, eParam, pflValues);
break;
@@ -1044,6 +1156,22 @@ ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValu
alSetError(AL_INVALID_OPERATION);
break;
+ case AL_DIRECT_FILTER:
+ *plValue = pSource->DirectFilter.filter;
+ break;
+
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ *plValue = pSource->DryGainHFAuto;
+ break;
+
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ *plValue = pSource->WetGainAuto;
+ break;
+
+ case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
+ *plValue = pSource->WetGainHFAuto;
+ break;
+
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -1153,6 +1281,10 @@ ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValue
case AL_ROLLOFF_FACTOR:
case AL_REFERENCE_DISTANCE:
case AL_SOURCE_TYPE:
+ case AL_DIRECT_FILTER:
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
alGetSourcei(source, eParam, plValues);
break;
@@ -1830,6 +1962,11 @@ static ALvoid InitSourceParams(ALsource *pSource)
pSource->flMaxGain = 1.0f;
pSource->flOuterGain = 0.0f;
+ pSource->DryGainHFAuto = AL_TRUE;
+ pSource->WetGainAuto = AL_TRUE;
+ pSource->WetGainHFAuto = AL_TRUE;
+ pSource->AirAbsorptionFactor = 0.0f;
+
pSource->state = AL_INITIAL;
pSource->lSourceType = AL_UNDETERMINED;