aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/alcEcho.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/alcEcho.c')
-rw-r--r--Alc/alcEcho.c66
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;