diff options
-rw-r--r-- | Alc/ALc.c | 46 | ||||
-rw-r--r-- | Alc/ALu.c | 245 | ||||
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | OpenAL32/Include/alAuxEffectSlot.h | 50 | ||||
-rw-r--r-- | OpenAL32/Include/alEffect.h | 57 | ||||
-rw-r--r-- | OpenAL32/Include/alFilter.h | 55 | ||||
-rw-r--r-- | OpenAL32/Include/alListener.h | 3 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 1 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 33 | ||||
-rw-r--r-- | OpenAL32/OpenAL32.c | 9 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 424 | ||||
-rw-r--r-- | OpenAL32/alEffect.c | 385 | ||||
-rw-r--r-- | OpenAL32/alExtension.c | 83 | ||||
-rw-r--r-- | OpenAL32/alFilter.c | 423 | ||||
-rw-r--r-- | OpenAL32/alListener.c | 22 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 137 |
16 files changed, 1931 insertions, 47 deletions
@@ -27,6 +27,7 @@ #include <stdio.h> #include <memory.h> #include "alMain.h" +#include "alSource.h" #include "AL/al.h" #include "AL/alc.h" #include "alThunk.h" @@ -67,6 +68,9 @@ struct { /////////////////////////////////////////////////////// +#define ALC_EFX_MAJOR_VERSION 0x20001 +#define ALC_EFX_MINOR_VERSION 0x20002 +#define ALC_MAX_AUXILIARY_SENDS 0x20003 /////////////////////////////////////////////////////// // STRING and EXTENSIONS @@ -87,6 +91,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 } }; @@ -136,9 +141,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 }, @@ -166,10 +176,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; + /////////////////////////////////////////////////////// @@ -334,6 +347,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; @@ -685,13 +699,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: @@ -713,13 +748,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); @@ -207,15 +207,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; @@ -224,6 +249,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; @@ -233,6 +263,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)); @@ -253,10 +284,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) @@ -273,6 +302,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: @@ -286,6 +316,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; @@ -298,7 +330,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: @@ -309,17 +344,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); @@ -334,9 +376,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; @@ -376,22 +435,65 @@ 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 normalized position into pannings, then into channel volumes aluNormalize(Position); + WetMix *= ALSource->Send[0].Slot.Gain; switch(aluChannelsFromFormat(OutputFormat)) { case 1: drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct - wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room - wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room + if(ALSource->Send[0].Slot.effectslot) + { + wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room + wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room + } + else + { + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + *wetgainhf = 1.0f; + } break; case 2: PanningLR = 0.5f + 0.5f*Position[0]; - drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); - drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); - wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); - wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt( PanningLR); + drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); //L Direct + drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); //R Direct + if(ALSource->Send[0].Slot.effectslot) + { + wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); //L Room + wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt( PanningLR); //R Room + } + else + { + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + *wetgainhf = 1.0f; + } break; case 4: /* TODO: Add center/lfe channel in spatial calculations? */ @@ -407,10 +509,21 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); drysend[BACK_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); drysend[BACK_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); - wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); - wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); - wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); - wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); + if(ALSource->Send[0].Slot.effectslot) + { + wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); + wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); + wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); + wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); + } + else + { + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + wetsend[BACK_LEFT] = 0.0f; + wetsend[BACK_RIGHT] = 0.0f; + *wetgainhf = 1.0f; + } break; case 7: case 8: @@ -428,12 +541,25 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[SIDE_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); drysend[FRONT_LEFT] = 0.0f; drysend[FRONT_RIGHT] = 0.0f; - wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); - wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); - wetsend[SIDE_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); - wetsend[SIDE_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); - wetsend[FRONT_LEFT] = 0.0f; - wetsend[FRONT_RIGHT] = 0.0f; + if(ALSource->Send[0].Slot.effectslot) + { + wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); + wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); + wetsend[SIDE_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); + wetsend[SIDE_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + } + else + { + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + wetsend[SIDE_LEFT] = 0.0f; + wetsend[SIDE_RIGHT] = 0.0f; + wetsend[BACK_LEFT] = 0.0f; + wetsend[BACK_RIGHT] = 0.0f; + *wetgainhf = 1.0f; + } } else { @@ -443,12 +569,25 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[SIDE_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); drysend[BACK_LEFT] = 0.0f; drysend[BACK_RIGHT] = 0.0f; - wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); - wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); - wetsend[SIDE_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); - wetsend[SIDE_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); - wetsend[BACK_LEFT] = 0.0f; - wetsend[BACK_RIGHT] = 0.0f; + if(ALSource->Send[0].Slot.effectslot) + { + wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); + wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); + wetsend[SIDE_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); + wetsend[SIDE_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); + wetsend[BACK_LEFT] = 0.0f; + wetsend[BACK_RIGHT] = 0.0f; + } + else + { + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + wetsend[SIDE_LEFT] = 0.0f; + wetsend[SIDE_RIGHT] = 0.0f; + wetsend[BACK_LEFT] = 0.0f; + wetsend[BACK_RIGHT] = 0.0f; + *wetgainhf = 1.0f; + } } default: break; @@ -456,6 +595,9 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, } else { + *drygainhf = DryGainHF; + *wetgainhf = WetGainHF; + //1. Multi-channel buffers always play "normal" drysend[FRONT_LEFT] = SourceVolume * 1.0f * ListenerGain; drysend[FRONT_RIGHT] = SourceVolume * 1.0f * ListenerGain; @@ -465,14 +607,29 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[BACK_RIGHT] = SourceVolume * 1.0f * ListenerGain; drysend[CENTER] = SourceVolume * 1.0f * ListenerGain; drysend[LFE] = SourceVolume * 1.0f * ListenerGain; - wetsend[FRONT_LEFT] = SourceVolume * 0.0f * ListenerGain; - wetsend[FRONT_RIGHT] = SourceVolume * 0.0f * ListenerGain; - wetsend[SIDE_LEFT] = SourceVolume * 0.0f * ListenerGain; - wetsend[SIDE_RIGHT] = SourceVolume * 0.0f * ListenerGain; - wetsend[BACK_LEFT] = SourceVolume * 0.0f * ListenerGain; - wetsend[BACK_RIGHT] = SourceVolume * 0.0f * ListenerGain; - wetsend[CENTER] = SourceVolume * 0.0f * ListenerGain; - wetsend[LFE] = SourceVolume * 0.0f * ListenerGain; + if(ALSource->Send[0].Slot.effectslot) + { + wetsend[FRONT_LEFT] = SourceVolume * 0.0f * ListenerGain; + wetsend[FRONT_RIGHT] = SourceVolume * 0.0f * ListenerGain; + wetsend[SIDE_LEFT] = SourceVolume * 0.0f * ListenerGain; + wetsend[SIDE_RIGHT] = SourceVolume * 0.0f * ListenerGain; + wetsend[BACK_LEFT] = SourceVolume * 0.0f * ListenerGain; + wetsend[BACK_RIGHT] = SourceVolume * 0.0f * ListenerGain; + wetsend[CENTER] = SourceVolume * 0.0f * ListenerGain; + wetsend[LFE] = SourceVolume * 0.0f * ListenerGain; + } + else + { + wetsend[FRONT_LEFT] = 0.0f; + wetsend[FRONT_RIGHT] = 0.0f; + wetsend[SIDE_LEFT] = 0.0f; + wetsend[SIDE_RIGHT] = 0.0f; + wetsend[BACK_LEFT] = 0.0f; + wetsend[BACK_RIGHT] = 0.0f; + wetsend[CENTER] = 0.0f; + wetsend[LFE] = 0.0f; + *wetgainhf = 1.0f; + } pitch[0] = Pitch; } @@ -484,6 +641,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, 0.0f, 0.0f, 0.0f, 0.0f }; ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 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; @@ -543,7 +702,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; @@ -606,8 +766,10 @@ 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][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; @@ -615,6 +777,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; //Room path final mix buffer and panning + value = aluComputeWetSample(ALSource, WetGainHF, sample); WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT]; diff --git a/CMakeLists.txt b/CMakeLists.txt index dc73a4bf..f77f340a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,9 +165,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 d8611a71..a1857c97 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -105,6 +105,7 @@ extern char _alDebug[256]; #define SWMIXER_OUTPUT_RATE 44100 #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 5edbfd1e..09651fa5 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 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..fa5a9d71 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; @@ -38,6 +41,9 @@ BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) case DLL_PROCESS_DETACH: ReleaseALBuffers(); + ReleaseALAuxiliaryEffectSlots(); + ReleaseALEffects(); + ReleaseALFilters(); FreeALConfig(); ALTHUNK_EXIT(); DeleteCriticalSection(&_alMutex); @@ -55,6 +61,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..282b8030 --- /dev/null +++ b/OpenAL32/alAuxEffectSlot.c @@ -0,0 +1,424 @@ +/** + * 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" +#include "alThunk.h" +#include "alError.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..97778f9e --- /dev/null +++ b/OpenAL32/alEffect.c @@ -0,0 +1,385 @@ +/** + * 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" +#include "alThunk.h" +#include "alError.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 82ee3f62..fff46d0a 100644 --- a/OpenAL32/alExtension.c +++ b/OpenAL32/alExtension.c @@ -24,6 +24,10 @@ #include "alExtension.h" #include "alError.h" #include "alMain.h" +#include "alFilter.h" +#include "alEffect.h" +#include "alAuxEffectSlot.h" +#include "alSource.h" #include "AL/al.h" #include "AL/alc.h" @@ -101,6 +105,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 +176,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 }, @@ -211,8 +264,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..0753d799 --- /dev/null +++ b/OpenAL32/alFilter.c @@ -0,0 +1,423 @@ +/** + * 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" +#include "alThunk.h" +#include "alError.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 7fad9b90..746ec821 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -343,6 +343,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: @@ -463,9 +484,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; @@ -638,6 +662,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; @@ -666,6 +727,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: @@ -674,6 +737,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; @@ -718,12 +810,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; @@ -794,6 +891,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: @@ -815,6 +916,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; @@ -922,6 +1031,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; @@ -1046,6 +1158,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; @@ -1155,6 +1283,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; @@ -1832,6 +1964,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; |