aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-05-19 18:59:04 -0700
committerChris Robinson <[email protected]>2017-05-19 23:13:39 -0700
commita306407b6713f0e17d1258e512a465a254f9fba3 (patch)
tree03f93c10b6de2e6a735f6f6795fbabb6a8f4d422
parentefd797a6f67d291ef82dd95697b5a1beb17590cc (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.c74
-rw-r--r--OpenAL32/Include/alAuxEffectSlot.h2
-rw-r--r--OpenAL32/alAuxEffectSlot.c2
3 files changed, 57 insertions, 21 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 0fca7a73..32043cdd 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -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;
}