From 0903a7f1e056079541a40f5d6dfb27756b3e883b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 5 Jul 2011 11:00:52 -0700 Subject: Apply wet path calculations with their dry path equivalents The auxiliary slot (and related effect) properties are retrieved at the same time as the source properties. This will help ensure each property is accessed from the source and slot only once. --- Alc/ALu.c | 198 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 112 insertions(+), 86 deletions(-) (limited to 'Alc') diff --git a/Alc/ALu.c b/Alc/ALu.c index 059c4afd..adb1da67 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -184,7 +184,6 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) DryGain = __min(DryGain,MaxVolume); DryGain = __max(DryGain,MinVolume); DryGainHF = 1.0f; - switch(ALSource->DirectFilter.type) { case AL_FILTER_LOWPASS: @@ -192,6 +191,20 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) DryGainHF *= ALSource->DirectFilter.GainHF; break; } + for(i = 0;i < NumSends;i++) + { + WetGain[i] = SourceVolume; + WetGain[i] = __min(WetGain[i],MaxVolume); + WetGain[i] = __max(WetGain[i],MinVolume); + WetGainHF[i] = 1.0f; + switch(ALSource->Send[i].WetFilter.type) + { + case AL_FILTER_LOWPASS: + WetGain[i] *= ALSource->Send[i].WetFilter.Gain; + WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; + break; + } + } SrcMatrix = ALSource->Params.DryGains; for(i = 0;i < MAXCHANNELS;i++) @@ -309,24 +322,8 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) } } } - for(i = 0;i < NumSends;i++) - { - WetGain[i] = SourceVolume; - WetGain[i] = __min(WetGain[i],MaxVolume); - WetGain[i] = __max(WetGain[i],MinVolume); - WetGainHF[i] = 1.0f; - - switch(ALSource->Send[i].WetFilter.type) - { - case AL_FILTER_LOWPASS: - WetGain[i] *= ALSource->Send[i].WetFilter.Gain; - WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; - break; - } - ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain; - } /* Update filter coefficients. Calculations based on the I3DL2 * spec. */ @@ -336,7 +333,6 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) * square root of the squared gain, which is the same as the base * gain. */ ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw); - for(i = 0;i < NumSends;i++) { /* We use a one-pole filter, so we need to take the squared gain */ @@ -355,13 +351,17 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain; ALfloat DopplerFactor, DopplerVelocity, SpeedOfSound; ALfloat AirAbsorptionFactor; + ALfloat RoomAirAbsorption[MAX_SENDS]; ALbufferlistitem *BufferListItem; ALfloat Attenuation, EffectiveDist; ALfloat RoomAttenuation[MAX_SENDS]; ALfloat MetersPerUnit; + ALfloat RoomRolloffBase; ALfloat RoomRolloff[MAX_SENDS]; + ALfloat DecayDistance[MAX_SENDS]; ALfloat DryGain; ALfloat DryGainHF; + ALboolean DryGainHFAuto; ALfloat WetGain[MAX_SENDS]; ALfloat WetGainHF[MAX_SENDS]; ALboolean WetGainAuto; @@ -395,21 +395,55 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition)); memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation)); memcpy(Velocity, ALSource->vVelocity, sizeof(ALSource->vVelocity)); + MinDist = ALSource->flRefDistance; + MaxDist = ALSource->flMaxDistance; + Rolloff = ALSource->flRollOffFactor; InnerAngle = ALSource->flInnerAngle * ConeScale; OuterAngle = ALSource->flOuterAngle * ConeScale; + AirAbsorptionFactor = ALSource->AirAbsorptionFactor; + DryGainHFAuto = ALSource->DryGainHFAuto; WetGainAuto = ALSource->WetGainAuto; WetGainHFAuto = ALSource->WetGainHFAuto; - AirAbsorptionFactor = ALSource->AirAbsorptionFactor; - Rolloff = ALSource->RoomRolloffFactor; + RoomRolloffBase = ALSource->RoomRolloffFactor; for(i = 0;i < NumSends;i++) { - RoomRolloff[i] = Rolloff; - if(ALSource->Send[i].Slot && IsReverbEffect(ALSource->Send[i].Slot->effect.type)) - RoomRolloff[i] += ALSource->Send[i].Slot->effect.Params.Reverb.RoomRolloffFactor; + ALeffectslot *Slot = ALSource->Send[i].Slot; + + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) + { + RoomRolloff[i] = 0.0f; + DecayDistance[i] = 0.0f; + RoomAirAbsorption[i] = 0.0f; + WetGainAuto = AL_FALSE; + WetGainHFAuto = AL_FALSE; + } + else if(Slot->AuxSendAuto) + { + RoomRolloff[i] = RoomRolloffBase; + if(IsReverbEffect(Slot->effect.type)) + { + RoomRolloff[i] += Slot->effect.Params.Reverb.RoomRolloffFactor; + DecayDistance[i] = Slot->effect.Params.Reverb.DecayTime * + SPEEDOFSOUNDMETRESPERSEC; + RoomAirAbsorption[i] = Slot->effect.Params.Reverb.AirAbsorptionGainHF; + } + else + { + DecayDistance[i] = 0.0f; + RoomAirAbsorption[i] = 0.0f; + } + } + else + { + /* If the slot's auxiliary send auto is off, the data sent to the + * effect slot is the same as the dry path, sans filter effects */ + RoomRolloff[i] = Rolloff; + DecayDistance[i] = 0.0f; + RoomAirAbsorption[i] = AIRABSORBGAINHF; + WetGainAuto = AL_TRUE; + WetGainHFAuto = DryGainHFAuto; + } } - MinDist = ALSource->flRefDistance; - MaxDist = ALSource->flMaxDistance; - Rolloff = ALSource->flRollOffFactor; //1. Translate Listener to origin (convert to head relative) if(ALSource->bHeadRelative == AL_FALSE) @@ -517,16 +551,22 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) break; } - EffectiveDist = 0.0f; - if(MinDist > 0.0f && Attenuation < 1.0f) - EffectiveDist = (MinDist/Attenuation - MinDist)*MetersPerUnit; - // Source Gain + Attenuation DryGain = SourceVolume * Attenuation; + for(i = 0;i < NumSends;i++) + WetGain[i] = SourceVolume * RoomAttenuation[i]; // Distance-based air absorption + EffectiveDist = 0.0f; + if(MinDist > 0.0f && Attenuation < 1.0f) + EffectiveDist = (MinDist/Attenuation - MinDist)*MetersPerUnit; if(AirAbsorptionFactor > 0.0f && EffectiveDist > 0.0f) + { DryGainHF *= aluPow(AIRABSORBGAINHF, AirAbsorptionFactor*EffectiveDist); + for(i = 0;i < NumSends;i++) + WetGainHF[i] *= aluPow(RoomAirAbsorption[i], + AirAbsorptionFactor*EffectiveDist); + } //3. Apply directional soundcones Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * (180.0/M_PI); @@ -548,62 +588,39 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) } DryGain *= ConeVolume; - if(ALSource->DryGainHFAuto) + if(WetGainAuto) + { + for(i = 0;i < NumSends;i++) + WetGain[i] *= ConeVolume; + } + if(DryGainHFAuto) DryGainHF *= ConeHF; + if(WetGainHFAuto) + { + for(i = 0;i < NumSends;i++) + WetGain[i] *= ConeHF; + } // Clamp to Min/Max Gain DryGain = __min(DryGain,MaxVolume); DryGain = __max(DryGain,MinVolume); - for(i = 0;i < NumSends;i++) { - ALeffectslot *Slot = ALSource->Send[i].Slot; - - if(!Slot || Slot->effect.type == AL_EFFECT_NULL) - { - ALSource->Params.Send[i].WetGain = 0.0f; - WetGainHF[i] = 1.0f; - continue; - } - - if(Slot->AuxSendAuto) - { - WetGain[i] = SourceVolume * RoomAttenuation[i]; - if(WetGainAuto) - WetGain[i] *= ConeVolume; - if(WetGainHFAuto) - WetGainHF[i] *= ConeHF; - - // Clamp to Min/Max Gain - WetGain[i] = __min(WetGain[i],MaxVolume); - WetGain[i] = __max(WetGain[i],MinVolume); - - if(IsReverbEffect(Slot->effect.type)) - { - /* Apply a decay-time transformation to the wet path, based on - * the attenuation of the dry path. - * - * Using the approximate (effective) source to listener - * distance, the initial decay of the reverb effect is - * calculated and applied to the wet path. - */ - if(WetGainAuto) - WetGain[i] *= aluPow(0.001f, /* -60dB */ - (1.0f/SPEEDOFSOUNDMETRESPERSEC)*EffectiveDist / - Slot->effect.Params.Reverb.DecayTime); - - WetGainHF[i] *= aluPow(Slot->effect.Params.Reverb.AirAbsorptionGainHF, - AirAbsorptionFactor * EffectiveDist); - } - } - else - { - /* If the slot's auxiliary send auto is off, the data sent to the - * effect slot is the same as the dry path, sans filter effects */ - WetGain[i] = DryGain; - WetGainHF[i] = DryGainHF; - } + WetGain[i] = __min(WetGain[i],MaxVolume); + WetGain[i] = __max(WetGain[i],MinVolume); + } + // Apply filter gains and filters + switch(ALSource->DirectFilter.type) + { + case AL_FILTER_LOWPASS: + DryGain *= ALSource->DirectFilter.Gain; + DryGainHF *= ALSource->DirectFilter.GainHF; + break; + } + DryGain *= ListenerGain; + for(i = 0;i < NumSends;i++) + { switch(ALSource->Send[i].WetFilter.type) { case AL_FILTER_LOWPASS: @@ -611,18 +628,25 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; break; } - ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain; + WetGain[i] *= ListenerGain; } - // Apply filter gains and filters - switch(ALSource->DirectFilter.type) + if(WetGainAuto) { - case AL_FILTER_LOWPASS: - DryGain *= ALSource->DirectFilter.Gain; - DryGainHF *= ALSource->DirectFilter.GainHF; - break; + /* Apply a decay-time transformation to the wet path, based on the + * attenuation of the dry path. + * + * Using the approximate (effective) source to listener distance, the + * initial decay of the reverb effect is calculated and applied to the + * wet path. + */ + for(i = 0;i < NumSends;i++) + { + if(DecayDistance[i] > 0.0f) + WetGain[i] *= aluPow(0.001f /* -60dB */, + EffectiveDist / DecayDistance[i]); + } } - DryGain *= ListenerGain; // Calculate Velocity Pitch = ALSource->flPitch; @@ -740,6 +764,8 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) ALSource->Params.DryGains[0][chan] = DryGain * gain; } } + for(i = 0;i < NumSends;i++) + ALSource->Params.Send[i].WetGain = WetGain[i]; /* Update filter coefficients. */ cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency); -- cgit v1.2.3