aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-02-01 22:24:40 -0800
committerChris Robinson <[email protected]>2016-02-01 22:24:40 -0800
commitd315ca4139c7bfc0ed9b0b89c59bdd3af3708da8 (patch)
tree2dee0db7a8eb24001ccadfd832e19ea675939475 /Alc
parentb4a9b40d68323a9c67cc4d182189b3be3e74117e (diff)
Try to map reverb outputs directly to output channels
HRTF and B-Format output still need to use virtual panning directions, but the reverb works better when it outputs directly to an output channel. Ambient and directional panning is used to properly mask and attenuate each output channel. Note that currently the "direct panning" output is quieter than it should be. Work is underway to attenuate the early reflections and late reverb better.
Diffstat (limited to 'Alc')
-rw-r--r--Alc/effects/reverb.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index fab049f6..bc12bc3b 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -1055,6 +1055,77 @@ static ALvoid UpdateEchoLine(ALfloat lateGain, ALfloat echoTime, ALfloat decayTi
}
// Update the early and late 3D panning gains.
+static ALvoid UpdateDirectPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALreverbState *State)
+{
+ ALfloat AmbientGains[MAX_OUTPUT_CHANNELS];
+ ALfloat DirGains[MAX_OUTPUT_CHANNELS];
+ ALfloat coeffs[MAX_AMBI_COEFFS];
+ ALfloat length;
+ ALuint i;
+
+ ComputeAmbientGains(Device->AmbiCoeffs, Device->NumChannels, Gain, AmbientGains);
+
+ memset(State->Early.PanGain, 0, sizeof(State->Early.PanGain));
+ length = sqrtf(ReflectionsPan[0]*ReflectionsPan[0] + ReflectionsPan[1]*ReflectionsPan[1] + ReflectionsPan[2]*ReflectionsPan[2]);
+ if(!(length > FLT_EPSILON))
+ {
+ for(i = 0;i < MAX_OUTPUT_CHANNELS && Device->ChannelName[i] != InvalidChannel;i++)
+ {
+ if(Device->ChannelName[i] == LFE)
+ continue;
+ State->Early.PanGain[i&3][i] = AmbientGains[i];
+ }
+ }
+ else
+ {
+ ALfloat pan[3] = {
+ ReflectionsPan[0] / length,
+ ReflectionsPan[1] / length,
+ -ReflectionsPan[2] / length,
+ };
+ length = minf(length, 1.0f);
+
+ CalcDirectionCoeffs(pan, coeffs);
+ ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, Gain, DirGains);
+ for(i = 0;i < MAX_OUTPUT_CHANNELS && Device->ChannelName[i] != InvalidChannel;i++)
+ {
+ if(Device->ChannelName[i] == LFE)
+ continue;
+ State->Early.PanGain[i&3][i] = lerp(AmbientGains[i], DirGains[i], length);
+ }
+ }
+
+ memset(State->Late.PanGain, 0, sizeof(State->Late.PanGain));
+ length = sqrtf(LateReverbPan[0]*LateReverbPan[0] + LateReverbPan[1]*LateReverbPan[1] + LateReverbPan[2]*LateReverbPan[2]);
+ if(!(length > FLT_EPSILON))
+ {
+ for(i = 0;i < MAX_OUTPUT_CHANNELS && Device->ChannelName[i] != InvalidChannel;i++)
+ {
+ if(Device->ChannelName[i] == LFE)
+ continue;
+ State->Late.PanGain[i&3][i] = AmbientGains[i];
+ }
+ }
+ else
+ {
+ ALfloat pan[3] = {
+ LateReverbPan[0] / length,
+ LateReverbPan[1] / length,
+ -LateReverbPan[2] / length,
+ };
+ length = minf(length, 1.0f);
+
+ CalcDirectionCoeffs(pan, coeffs);
+ ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, Gain, DirGains);
+ for(i = 0;i < MAX_OUTPUT_CHANNELS && Device->ChannelName[i] != InvalidChannel;i++)
+ {
+ if(Device->ChannelName[i] == LFE)
+ continue;
+ State->Late.PanGain[i&3][i] = lerp(AmbientGains[i], DirGains[i], length);
+ }
+ }
+}
+
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALreverbState *State)
{
static const ALfloat EarlyPanAngles[4] = {
@@ -1187,8 +1258,12 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device
gain = props->Reverb.Gain * Slot->Gain * ReverbBoost;
// Update early and late 3D panning.
- Update3DPanning(Device, props->Reverb.ReflectionsPan,
- props->Reverb.LateReverbPan, gain, State);
+ if(Device->Hrtf || Device->FmtChans == DevFmtBFormat3D)
+ Update3DPanning(Device, props->Reverb.ReflectionsPan,
+ props->Reverb.LateReverbPan, gain, State);
+ else
+ UpdateDirectPanning(Device, props->Reverb.ReflectionsPan,
+ props->Reverb.LateReverbPan, gain, State);
}