diff options
author | Chris Robinson <[email protected]> | 2017-12-15 17:26:03 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-12-15 17:26:03 -0800 |
commit | d281b25723e1ee5b71ed2ba19fddd28d066198cd (patch) | |
tree | 2c216ab628e86f631d410430d284cee97ca58b95 | |
parent | 2a3b5ab9e9bf3a47bb61921c6c7d79ca0847a99b (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.c | 29 |
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++) { |