diff options
author | Chris Robinson <[email protected]> | 2018-01-07 21:15:18 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-01-07 21:15:18 -0800 |
commit | 56e9cb69d3aba60016701c6478b3f08c08aa3171 (patch) | |
tree | 9b6d4d4816a40156c9e45d8a16e8bdb86f41eeab | |
parent | 70973035dea8a65630a7c2548dd8e85d87bd36a9 (diff) |
Ensure the chorus delay and depth leave enough padding for resampling
Also use cubic resampling for the modulated tap. Applies to flanger too.
-rw-r--r-- | Alc/effects/chorus.c | 20 | ||||
-rw-r--r-- | Alc/effects/flanger.c | 20 |
2 files changed, 26 insertions, 14 deletions
diff --git a/Alc/effects/chorus.c b/Alc/effects/chorus.c index b4b4ac5a..caea6e93 100644 --- a/Alc/effects/chorus.c +++ b/Alc/effects/chorus.c @@ -116,6 +116,7 @@ static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Dev static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Context, const ALeffectslot *Slot, const ALeffectProps *props) { + const ALsizei mindelay = maxi(MAX_PRE_SAMPLES, MAX_POST_SAMPLES) << FRACTIONBITS; const ALCdevice *device = Context->Device; ALfloat frequency = (ALfloat)device->Frequency; ALfloat coeffs[MAX_AMBI_COEFFS]; @@ -132,9 +133,12 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Conte break; } - /* The LFO depth is scaled to be relative to the sample delay. */ - state->delay = fastf2i(props->Chorus.Delay*frequency*FRACTIONONE + 0.5f); - state->depth = props->Chorus.Depth * state->delay; + /* The LFO depth is scaled to be relative to the sample delay. Clamp the + * delay and depth to allow enough padding for resampling. + */ + state->delay = maxi(fastf2i(props->Chorus.Delay*frequency*FRACTIONONE + 0.5f), + mindelay); + state->depth = minf(props->Chorus.Depth * state->delay, state->delay - mindelay); state->feedback = props->Chorus.Feedback; @@ -249,14 +253,16 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, c // Tap for the left output. delay = offset - (moddelays[0][i]>>FRACTIONBITS); mu = (moddelays[0][i]&FRACTIONMASK) * (1.0f/FRACTIONONE); - temps[0][i] = delaybuf[(delay ) & bufmask]*(1.0f-mu) + - delaybuf[(delay-1) & bufmask]*( mu); + temps[0][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask], + delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], + mu); // Tap for the right output. delay = offset - (moddelays[1][i]>>FRACTIONBITS); mu = (moddelays[1][i]&FRACTIONMASK) * (1.0f/FRACTIONONE); - temps[1][i] = delaybuf[(delay ) & bufmask]*(1.0f-mu) + - delaybuf[(delay-1) & bufmask]*( mu); + temps[1][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask], + delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], + mu); // Accumulate feedback from the average delay of the taps. delaybuf[offset&bufmask] += delaybuf[(offset-avgdelay) & bufmask] * feedback; diff --git a/Alc/effects/flanger.c b/Alc/effects/flanger.c index 3e7cd4a4..b1fd2fda 100644 --- a/Alc/effects/flanger.c +++ b/Alc/effects/flanger.c @@ -116,6 +116,7 @@ static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *D static ALvoid ALflangerState_update(ALflangerState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props) { + const ALsizei mindelay = maxi(MAX_PRE_SAMPLES, MAX_POST_SAMPLES) << FRACTIONBITS; const ALCdevice *device = context->Device; ALfloat frequency = (ALfloat)device->Frequency; ALfloat coeffs[MAX_AMBI_COEFFS]; @@ -132,9 +133,12 @@ static ALvoid ALflangerState_update(ALflangerState *state, const ALCcontext *con break; } - /* The LFO depth is scaled to be relative to the sample delay. */ - state->delay = fastf2i(props->Flanger.Delay*frequency*FRACTIONONE + 0.5f); - state->depth = props->Flanger.Depth * state->delay; + /* The LFO depth is scaled to be relative to the sample delay. Clamp the + * delay and depth to allow enough padding for resampling. + */ + state->delay = maxi(fastf2i(props->Flanger.Delay*frequency*FRACTIONONE + 0.5f), + mindelay); + state->depth = minf(props->Flanger.Depth * state->delay, state->delay - mindelay); state->feedback = props->Flanger.Feedback; @@ -248,14 +252,16 @@ static ALvoid ALflangerState_process(ALflangerState *state, ALsizei SamplesToDo, // Tap for the left output. delay = offset - (moddelays[0][i]>>FRACTIONBITS); mu = (moddelays[0][i]&FRACTIONMASK) * (1.0f/FRACTIONONE); - temps[0][i] = delaybuf[(delay ) & bufmask]*(1.0f-mu) + - delaybuf[(delay-1) & bufmask]*( mu); + temps[0][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask], + delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], + mu); // Tap for the right output. delay = offset - (moddelays[1][i]>>FRACTIONBITS); mu = (moddelays[1][i]&FRACTIONMASK) * (1.0f/FRACTIONONE); - temps[1][i] = delaybuf[(delay ) & bufmask]*(1.0f-mu) + - delaybuf[(delay-1) & bufmask]*( mu); + temps[1][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask], + delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], + mu); // Accumulate feedback from the average delay. delaybuf[offset&bufmask] += delaybuf[(offset-avgdelay) & bufmask] * feedback; |