aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-12-15 17:26:03 -0800
committerChris Robinson <[email protected]>2017-12-15 17:26:03 -0800
commitd281b25723e1ee5b71ed2ba19fddd28d066198cd (patch)
tree2c216ab628e86f631d410430d284cee97ca58b95
parent2a3b5ab9e9bf3a47bb61921c6c7d79ca0847a99b (diff)
Use a separate LFO offset in the chorus effect
Given that the LFO range is not a power-of-two, it won't correctly wrap on overflow.
-rw-r--r--Alc/effects/chorus.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/Alc/effects/chorus.c b/Alc/effects/chorus.c
index 94e366cc..aa62e8b9 100644
--- a/Alc/effects/chorus.c
+++ b/Alc/effects/chorus.c
@@ -41,6 +41,8 @@ typedef struct ALchorusState {
ALfloat *SampleBuffer[2];
ALsizei BufferLength;
ALsizei offset;
+
+ ALsizei lfo_offset;
ALsizei lfo_range;
ALfloat lfo_scale;
ALint lfo_disp;
@@ -73,6 +75,7 @@ static void ALchorusState_Construct(ALchorusState *state)
state->SampleBuffer[0] = NULL;
state->SampleBuffer[1] = NULL;
state->offset = 0;
+ state->lfo_offset = 0;
state->lfo_range = 1;
state->waveform = CWF_Triangle;
}
@@ -155,14 +158,21 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Conte
rate = props->Chorus.Rate;
if(!(rate > 0.0f))
{
- state->lfo_scale = 0.0f;
+ state->lfo_offset = 0;
state->lfo_range = 1;
+ state->lfo_scale = 0.0f;
state->lfo_disp = 0;
}
else
{
- /* Calculate LFO coefficient */
- state->lfo_range = fastf2i(frequency/rate + 0.5f);
+ /* Calculate LFO coefficient (number of samples per cycle). Limit the
+ * max range to avoid overflow when calculating the displacement.
+ */
+ ALsizei lfo_range = mini(fastf2i(frequency/rate + 0.5f), INT_MAX/360 - 180);
+
+ state->lfo_offset = fastf2i((ALfloat)state->lfo_offset/state->lfo_range*
+ lfo_range + 0.5f) % lfo_range;
+ state->lfo_range = lfo_range;
switch(state->waveform)
{
case CWF_Triangle:
@@ -174,10 +184,8 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Conte
}
/* Calculate lfo phase displacement */
- if(phase >= 0)
- state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f));
- else
- state->lfo_disp = fastf2i(state->lfo_range * ((360+phase)/360.0f));
+ if(phase < 0) phase = 360 + phase;
+ state->lfo_disp = (state->lfo_range*phase + 180) / 360;
}
}
@@ -225,16 +233,16 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, c
ALint disp_offset = state->lfo_disp*c;
ALint moddelays[128];
- offset = state->offset;
if(state->waveform == CWF_Triangle)
- GetTriangleDelays(moddelays, (offset+disp_offset)%state->lfo_range,
+ GetTriangleDelays(moddelays, (state->lfo_offset+disp_offset)%state->lfo_range,
state->lfo_range, state->lfo_scale, state->depth, state->delay,
todo);
else /*if(state->waveform == CWF_Sinusoid)*/
- GetSinusoidDelays(moddelays, (offset+disp_offset)%state->lfo_range,
+ GetSinusoidDelays(moddelays, (state->lfo_offset+disp_offset)%state->lfo_range,
state->lfo_range, state->lfo_scale, state->depth, state->delay,
todo);
+ offset = state->offset;
for(i = 0;i < todo;i++)
{
ALint delay = moddelays[i] >> FRACTIONBITS;
@@ -248,6 +256,7 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, c
}
}
state->offset = offset;
+ state->lfo_offset = (state->lfo_offset+todo) % state->lfo_range;
for(c = 0;c < NumChannels;c++)
{