diff options
author | Chris Robinson <[email protected]> | 2016-02-01 22:24:40 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-02-01 22:24:40 -0800 |
commit | d315ca4139c7bfc0ed9b0b89c59bdd3af3708da8 (patch) | |
tree | 2dee0db7a8eb24001ccadfd832e19ea675939475 /Alc/effects | |
parent | b4a9b40d68323a9c67cc4d182189b3be3e74117e (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/effects')
-rw-r--r-- | Alc/effects/reverb.c | 79 |
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); } |