diff options
author | Chris Robinson <[email protected]> | 2010-08-09 05:11:58 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2010-08-09 05:11:58 -0700 |
commit | e007dc36140a0359b9ae1e1bf495c2afa5ab70f8 (patch) | |
tree | 191549f5425adf51918a18964642e8c20ed733ba /Alc/alcReverb.c | |
parent | 2ed929eadc2e6bbc9b4aee95d8ad5e31a0c76ac6 (diff) |
Fix early/late reverb panning, and only output reverb on available channels
Diffstat (limited to 'Alc/alcReverb.c')
-rw-r--r-- | Alc/alcReverb.c | 76 |
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; } |