diff options
-rw-r--r-- | Alc/alcEcho.c | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/Alc/alcEcho.c b/Alc/alcEcho.c index 9bfb19b3..17cc492e 100644 --- a/Alc/alcEcho.c +++ b/Alc/alcEcho.c @@ -43,14 +43,11 @@ typedef struct ALechoState { ALuint delay; } Tap[2]; ALuint Offset; - // The LR gains for the first tap. The second tap uses the reverse - ALfloat GainL; - ALfloat GainR; + /* The panning gains for the two taps */ + ALfloat Gain[2][MAXCHANNELS]; ALfloat FeedGain; - ALfloat Gain[MAXCHANNELS]; - FILTER iirFilter; ALfloat history[2]; } ALechoState; @@ -98,16 +95,16 @@ static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeff ALechoState *state = (ALechoState*)effect; ALCdevice *Device = Context->Device; ALuint frequency = Device->Frequency; + ALfloat dirGain, ambientGain; + const ALfloat *speakerGain; ALfloat lrpan, cw, g, gain; - ALuint i; + ALuint i, pos; state->Tap[0].delay = fastf2u(Slot->effect.Echo.Delay * frequency) + 1; state->Tap[1].delay = fastf2u(Slot->effect.Echo.LRDelay * frequency); state->Tap[1].delay += state->Tap[0].delay; - lrpan = Slot->effect.Echo.Spread*0.5f + 0.5f; - state->GainL = aluSqrt( lrpan); - state->GainR = aluSqrt(1.0f-lrpan); + lrpan = Slot->effect.Echo.Spread; state->FeedGain = Slot->effect.Echo.Feedback; @@ -117,11 +114,32 @@ static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeff gain = Slot->Gain; for(i = 0;i < MAXCHANNELS;i++) - state->Gain[i] = 0.0f; + { + state->Gain[0][i] = 0.0f; + state->Gain[1][i] = 0.0f; + } + + ambientGain = aluSqrt(1.0f/Device->NumChan); + dirGain = aluFabs(lrpan); + + /* First tap panning */ + pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?-1.0f:1.0f)); + speakerGain = Device->PanningLUT[pos]; + + for(i = 0;i < Device->NumChan;i++) + { + enum Channel chan = Device->Speaker2Chan[i]; + state->Gain[0][chan] = lerp(ambientGain, speakerGain[chan], dirGain) * gain; + } + + /* Second tap panning */ + pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?1.0f:-1.0f)); + speakerGain = Device->PanningLUT[pos]; + for(i = 0;i < Device->NumChan;i++) { enum Channel chan = Device->Speaker2Chan[i]; - state->Gain[chan] = gain; + state->Gain[1][chan] = lerp(ambientGain, speakerGain[chan], dirGain) * gain; } } @@ -132,31 +150,25 @@ static ALvoid EchoProcess(ALeffectState *effect, ALuint SamplesToDo, const ALflo const ALuint tap1 = state->Tap[0].delay; const ALuint tap2 = state->Tap[1].delay; ALuint offset = state->Offset; - ALfloat samp[2], smp; - ALuint i; + ALfloat smp; + ALuint i, k; for(i = 0;i < SamplesToDo;i++,offset++) { - // Sample first tap + /* First tap */ smp = state->SampleBuffer[(offset-tap1) & mask]; - samp[0] = smp * state->GainL; - samp[1] = smp * state->GainR; - // Sample second tap. Reverse LR panning + for(k = 0;k < MAXCHANNELS;k++) + SamplesOut[i][k] += smp * state->Gain[0][k]; + + /* Second tap */ smp = state->SampleBuffer[(offset-tap2) & mask]; - samp[0] += smp * state->GainR; - samp[1] += smp * state->GainL; + for(k = 0;k < MAXCHANNELS;k++) + SamplesOut[i][k] += smp * state->Gain[1][k]; // Apply damping and feedback gain to the second tap, and mix in the // new sample smp = lpFilter2P(&state->iirFilter, 0, smp+SamplesIn[i]); state->SampleBuffer[offset&mask] = smp * state->FeedGain; - - SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp[0]; - SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp[1]; - SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp[0]; - SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp[1]; - SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp[0]; - SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp[1]; } state->Offset = offset; } @@ -180,8 +192,6 @@ ALeffectState *EchoCreate(void) state->Tap[0].delay = 0; state->Tap[1].delay = 0; state->Offset = 0; - state->GainL = 0.0f; - state->GainR = 0.0f; state->iirFilter.coeff = 0.0f; state->iirFilter.history[0] = 0.0f; |