diff options
author | Chris Robinson <[email protected]> | 2017-05-19 18:59:04 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-05-19 23:13:39 -0700 |
commit | a306407b6713f0e17d1258e512a465a254f9fba3 (patch) | |
tree | 03f93c10b6de2e6a735f6f6795fbabb6a8f4d422 | |
parent | efd797a6f67d291ef82dd95697b5a1beb17590cc (diff) |
Apply more proper air absorption to the wet path
This properly accounts for the room rolloff factor for normal air absorption
(which makes it none by default, like distance attenuation), and uses the
reverb's decay time, decay hf ratio, decay hf limit, and room air absorption
properties to calculate an initial hf decay with the WetGainAuto flag. This
mirrors the behavior of the initial distance decay.
-rw-r--r-- | Alc/ALu.c | 74 | ||||
-rw-r--r-- | OpenAL32/Include/alAuxEffectSlot.h | 2 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 2 |
3 files changed, 57 insertions, 21 deletions
@@ -337,13 +337,17 @@ static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device) { slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor; slot->Params.DecayTime = props->Props.Reverb.DecayTime; + slot->Params.DecayHFRatio = props->Props.Reverb.DecayHFRatio; slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; + slot->Params.DecayHFLimit = props->Props.Reverb.DecayHFLimit; } else { slot->Params.RoomRolloff = 0.0f; slot->Params.DecayTime = 0.0f; + slot->Params.DecayHFRatio = 0.0f; slot->Params.AirAbsorptionGainHF = 1.0f; + slot->Params.DecayHFLimit = AL_FALSE; } /* Swap effect states. No need to play with the ref counts since they keep @@ -1059,13 +1063,13 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop ALeffectslot *SendSlots[MAX_SENDS]; ALfloat RoomRolloff[MAX_SENDS]; ALfloat DecayDistance[MAX_SENDS]; + ALfloat DecayHFDistance[MAX_SENDS]; ALfloat DryGain, DryGainHF, DryGainLF; ALfloat WetGain[MAX_SENDS]; ALfloat WetGainHF[MAX_SENDS]; ALfloat WetGainLF[MAX_SENDS]; ALfloat dir[3]; ALfloat spread; - ALfloat meters; ALfloat Pitch; ALint i; @@ -1082,14 +1086,22 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop SendSlots[i] = NULL; RoomRolloff[i] = 0.0f; DecayDistance[i] = 0.0f; + DecayHFDistance[i] = 0.0f; RoomAirAbsorption[i] = 1.0f; } else if(SendSlots[i]->Params.AuxSendAuto) { RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + props->RoomRolloffFactor; - DecayDistance[i] = SendSlots[i]->Params.DecayTime * - SPEEDOFSOUNDMETRESPERSEC; + DecayDistance[i] = SendSlots[i]->Params.DecayTime * SPEEDOFSOUNDMETRESPERSEC; + DecayHFDistance[i] = DecayDistance[i] * SendSlots[i]->Params.DecayHFRatio; RoomAirAbsorption[i] = SendSlots[i]->Params.AirAbsorptionGainHF; + if(SendSlots[i]->Params.DecayHFLimit && RoomAirAbsorption[i] < 1.0f) + { + ALfloat limitRatio = log10f(0.001f)/*-60 dB*/ / (log10f(RoomAirAbsorption[i]) * + DecayDistance[i]); + limitRatio = minf(limitRatio, SendSlots[i]->Params.DecayHFRatio); + DecayHFDistance[i] = minf(DecayHFDistance[i], limitRatio*DecayDistance[i]); + } } else { @@ -1097,6 +1109,7 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop * effect slot is the same as the dry path, sans filter effects */ RoomRolloff[i] = props->RolloffFactor; DecayDistance[i] = 0.0f; + DecayHFDistance[i] = 0.0f; RoomAirAbsorption[i] = AIRABSORBGAINHF; } @@ -1215,28 +1228,47 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop } /* Distance-based air absorption */ - meters = (ClampedDist-props->RefDistance) * props->RolloffFactor * - Listener->Params.MetersPerUnit; - if(meters > 0.0f && props->AirAbsorptionFactor > 0.0f) - DryGainHF *= powf(AIRABSORBGAINHF, props->AirAbsorptionFactor*meters); - - if(props->WetGainAuto && meters > 0.0f) + if(ClampedDist > props->RefDistance) { - /* Apply a decay-time transformation to the wet path, based on the - * source distance in meters. The initial decay of the reverb effect is - * calculated and applied to the wet path. - */ - for(i = 0;i < NumSends;i++) + ALfloat meters_base = (ClampedDist-props->RefDistance) * Listener->Params.MetersPerUnit; + if(props->AirAbsorptionFactor > 0.0f) { - if(DecayDistance[i] > 0.0f) - WetGain[i] *= powf(0.001f/*-60dB*/, meters/DecayDistance[i]); + ALfloat absorb = props->AirAbsorptionFactor * meters_base; + DryGainHF *= powf(AIRABSORBGAINHF, absorb*props->RolloffFactor); + for(i = 0;i < NumSends;i++) + { + if(RoomRolloff[i] > 0.0f) + WetGainHF[i] *= powf(RoomAirAbsorption[i], absorb*RoomRolloff[i]); + } } - /* Yes, the wet path's air absorption is applied with WetGainAuto on, - * rather than WetGainHFAuto. - */ - for(i = 0;i < NumSends;i++) - WetGainHF[i] *= powf(RoomAirAbsorption[i], meters); + if(props->WetGainAuto) + { + meters_base *= props->RolloffFactor; + + /* Apply a decay-time transformation to the wet path, based on the + * source distance in meters. The initial decay of the reverb + * effect is calculated and applied to the wet path. + */ + for(i = 0;i < NumSends;i++) + { + ALfloat gain; + + if(!(DecayDistance[i] > 0.0f)) + continue; + + gain = powf(0.001f/*-60dB*/, meters_base/DecayDistance[i]); + WetGain[i] *= gain; + /* Yes, the wet path's air absorption is applied with + * WetGainAuto on, rather than WetGainHFAuto. + */ + if(gain > 0.0f) + { + ALfloat gainhf = powf(0.001f/*-60dB*/, meters_base/DecayHFDistance[i]) / gain; + WetGainHF[i] *= minf(gainhf, 1.0f); + } + } + } } /* Calculate directional soundcones */ diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h index 4eb340a4..7126f8f5 100644 --- a/OpenAL32/Include/alAuxEffectSlot.h +++ b/OpenAL32/Include/alAuxEffectSlot.h @@ -121,7 +121,9 @@ typedef struct ALeffectslot { ALfloat RoomRolloff; /* Added to the source's room rolloff, not multiplied. */ ALfloat DecayTime; + ALfloat DecayHFRatio; ALfloat AirAbsorptionGainHF; + ALboolean DecayHFLimit; } Params; /* Self ID */ diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 5d110500..8a990584 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -615,7 +615,9 @@ ALenum InitEffectSlot(ALeffectslot *slot) slot->Params.EffectState = slot->Effect.State; slot->Params.RoomRolloff = 0.0f; slot->Params.DecayTime = 0.0f; + slot->Params.DecayHFRatio = 0.0f; slot->Params.AirAbsorptionGainHF = 1.0f; + slot->Params.DecayHFLimit = AL_FALSE; return AL_NO_ERROR; } |