summaryrefslogtreecommitdiffstats
path: root/Alc/alcReverb.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2010-08-09 05:11:58 -0700
committerChris Robinson <[email protected]>2010-08-09 05:11:58 -0700
commite007dc36140a0359b9ae1e1bf495c2afa5ab70f8 (patch)
tree191549f5425adf51918a18964642e8c20ed733ba /Alc/alcReverb.c
parent2ed929eadc2e6bbc9b4aee95d8ad5e31a0c76ac6 (diff)
Fix early/late reverb panning, and only output reverb on available channels
Diffstat (limited to 'Alc/alcReverb.c')
-rw-r--r--Alc/alcReverb.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/Alc/alcReverb.c b/Alc/alcReverb.c
index 6ca47d2d..e1f6df45 100644
--- a/Alc/alcReverb.c
+++ b/Alc/alcReverb.c
@@ -130,8 +130,9 @@ typedef struct ALverbState {
// The current read offset for all delay lines.
ALuint Offset;
- // Gain scale to account for device down-mixing
- ALfloat Scale;
+ // The gain for each output channel (non-EAX path only; aliased from
+ // Late.PanGain)
+ ALfloat *Gain;
} ALverbState;
/* This coefficient is used to define the maximum frequency range controlled
@@ -588,16 +589,17 @@ static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoT
}
// Update the early and late 3D panning gains.
-static ALvoid Update3DPanning(const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat *PanningLUT, ALverbState *State)
+static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALverbState *State)
{
- ALfloat length;
ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
ReflectionsPan[2] };
ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
LateReverbPan[2] };
- ALint pos;
- ALfloat *speakerGain, dirGain, ambientGain;
+ const ALfloat *speakerGain;
+ ALfloat dirGain, ambientGain;
+ ALfloat length;
ALuint index;
+ ALint pos;
// Calculate the 3D-panning gains for the early reflections and late
// reverb.
@@ -625,18 +627,30 @@ static ALvoid Update3DPanning(const ALfloat *ReflectionsPan, const ALfloat *Late
* panning direction.
*/
pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
- speakerGain = &PanningLUT[OUTPUTCHANNELS * pos];
+ speakerGain = &Device->PanningLUT[OUTPUTCHANNELS * pos];
dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
ambientGain = (1.0 - dirGain);
for(index = 0;index < OUTPUTCHANNELS;index++)
- State->Early.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
+ State->Early.PanGain[index] = 0.0f;
+ for(index = 0;index < Device->NumChan;index++)
+ {
+ Channel chan = Device->Speaker2Chan[index];
+ State->Early.PanGain[chan] = speakerGain[chan]*dirGain +
+ ambientGain;
+ }
pos = aluCart2LUTpos(latePan[2], latePan[0]);
- speakerGain = &PanningLUT[OUTPUTCHANNELS * pos];
+ speakerGain = &Device->PanningLUT[OUTPUTCHANNELS * pos];
dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
ambientGain = (1.0 - dirGain);
for(index = 0;index < OUTPUTCHANNELS;index++)
- State->Late.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
+ State->Late.PanGain[index] = 0.0f;
+ for(index = 0;index < Device->NumChan;index++)
+ {
+ Channel chan = Device->Speaker2Chan[index];
+ State->Late.PanGain[chan] = speakerGain[chan]*dirGain +
+ ambientGain;
+ }
}
// Basic delay line input/output routines.
@@ -984,14 +998,13 @@ static ALvoid VerbDestroy(ALeffectState *effect)
static ALboolean VerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
{
ALverbState *State = (ALverbState*)effect;
- ALuint frequency = Device->Frequency, index;
+ ALuint frequency = Device->Frequency;
+ ALuint index;
// Allocate the delay lines.
if(!AllocLines(AL_FALSE, frequency, State))
return AL_FALSE;
- State->Scale = aluSqrt(Device->NumChan / 8.0f);
-
// The early reflection and late all-pass filter line lengths are static,
// so their offsets only need to be calculated once.
for(index = 0;index < 4;index++)
@@ -1002,6 +1015,14 @@ static ALboolean VerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
frequency);
}
+ for(index = 0;index < OUTPUTCHANNELS;index++)
+ State->Gain[index] = 0.0f;
+ for(index = 0;index < Device->NumChan;index++)
+ {
+ Channel chan = Device->Speaker2Chan[index];
+ State->Gain[chan] = 1.0f;
+ }
+
return AL_TRUE;
}
@@ -1017,8 +1038,6 @@ static ALboolean EAXVerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
if(!AllocLines(AL_TRUE, frequency, State))
return AL_FALSE;
- State->Scale = aluSqrt(Device->NumChan / 8.0f);
-
// Calculate the modulation filter coefficient. Notice that the exponent
// is calculated given the current sample rate. This ensures that the
// resulting filter response over time is consistent across all sample
@@ -1137,8 +1156,8 @@ static ALvoid EAXVerbUpdate(ALeffectState *effect, ALCcontext *Context, const AL
hfRatio, cw, frequency, State);
// Update early and late 3D panning.
- Update3DPanning(Effect->Reverb.ReflectionsPan, Effect->Reverb.LateReverbPan,
- Context->Device->PanningLUT, State);
+ Update3DPanning(Context->Device, Effect->Reverb.ReflectionsPan,
+ Effect->Reverb.LateReverbPan, State);
}
// This processes the reverb state, given the input samples and an output
@@ -1148,7 +1167,8 @@ static ALvoid VerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuin
ALverbState *State = (ALverbState*)effect;
ALuint index;
ALfloat early[4], late[4], out[4];
- ALfloat gain = Slot->Gain * State->Scale;
+ ALfloat gain = Slot->Gain;
+ const ALfloat *panGain = State->Gain;
for(index = 0;index < SamplesToDo;index++)
{
@@ -1162,14 +1182,14 @@ static ALvoid VerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuin
out[3] = (early[3] + late[3]) * gain;
// Output the results.
- SamplesOut[index][FRONT_LEFT] += out[0];
- SamplesOut[index][FRONT_RIGHT] += out[1];
- SamplesOut[index][FRONT_CENTER] += out[3];
- SamplesOut[index][SIDE_LEFT] += out[0];
- SamplesOut[index][SIDE_RIGHT] += out[1];
- SamplesOut[index][BACK_LEFT] += out[0];
- SamplesOut[index][BACK_RIGHT] += out[1];
- SamplesOut[index][BACK_CENTER] += out[2];
+ SamplesOut[index][FRONT_LEFT] += panGain[FRONT_LEFT] * out[0];
+ SamplesOut[index][FRONT_RIGHT] += panGain[FRONT_RIGHT] * out[1];
+ SamplesOut[index][FRONT_CENTER] += panGain[FRONT_CENTER] * out[3];
+ SamplesOut[index][SIDE_LEFT] += panGain[SIDE_LEFT] * out[0];
+ SamplesOut[index][SIDE_RIGHT] += panGain[SIDE_RIGHT] * out[1];
+ SamplesOut[index][BACK_LEFT] += panGain[BACK_LEFT] * out[0];
+ SamplesOut[index][BACK_RIGHT] += panGain[BACK_RIGHT] * out[1];
+ SamplesOut[index][BACK_CENTER] += panGain[BACK_CENTER] * out[2];
}
}
@@ -1180,7 +1200,7 @@ static ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, AL
ALverbState *State = (ALverbState*)effect;
ALuint index;
ALfloat early[4], late[4];
- ALfloat gain = Slot->Gain * State->Scale;
+ ALfloat gain = Slot->Gain;
for(index = 0;index < SamplesToDo;index++)
{
@@ -1311,7 +1331,7 @@ ALeffectState *VerbCreate(void)
State->Offset = 0;
- State->Scale = 1.0f;
+ State->Gain = State->Late.PanGain;
return &State->state;
}