diff options
author | Chris Robinson <[email protected]> | 2020-04-06 15:46:14 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-04-06 15:46:14 -0700 |
commit | 6ff5339112d53e9f7c733d6da5aaaad3acbf057a (patch) | |
tree | 6d056fb0f88feb87c87a8dd7c254d49be905e60c /alc | |
parent | baf14aad2a53f771fd2b398a08c3d3d36cb13d1f (diff) |
Include the average modulation delay for the late reverb feedback
Diffstat (limited to 'alc')
-rw-r--r-- | alc/effects/reverb.cpp | 122 |
1 files changed, 63 insertions, 59 deletions
diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index fdf8897d..d8ec3eb2 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -336,8 +336,7 @@ struct Modulation { /* The vibrato time is tracked with an index over a (MOD_FRACONE) * normalized range. */ - ALuint Index[NUM_LINES]; - ALuint Step; + ALuint Index, Step; /* The depth of frequency change, in samples. */ float Depth[2]; @@ -346,8 +345,8 @@ struct Modulation { void updateModulator(float modTime, float modDepth, float frequency); - void calcDelays(size_t c, size_t todo); - void calcFadedDelays(size_t c, size_t todo, float fadeCount, float fadeStep); + void calcDelays(size_t todo); + void calcFadedDelays(size_t todo, float fadeCount, float fadeStep); }; struct LateReverb { @@ -643,7 +642,7 @@ bool ReverbState::deviceUpdate(const ALCdevice *device) t60.LFFilter.clear(); } - std::fill(std::begin(mLate.Mod.Index), std::end(mLate.Mod.Index), 0); + mLate.Mod.Index = 0; mLate.Mod.Step = 1; std::fill(std::begin(mLate.Mod.Depth), std::end(mLate.Mod.Depth), 0.0f); @@ -793,6 +792,39 @@ void EarlyReflections::updateLines(const ALfloat density, const ALfloat diffusio } } +/* Update the EAX modulation step and depth. Keep in mind that this kind of + * vibrato is additive and not multiplicative as one may expect. The downswing + * will sound stronger than the upswing. + */ +void Modulation::updateModulator(float modTime, float modDepth, float frequency) +{ + /* Modulation is calculated in two parts. + * + * The modulation time effects the sinus rate, altering the speed of + * frequency changes. An index is incremented for each sample with an + * appropriate step size to generate an LFO, which will vary the feedback + * delay over time. + */ + Step = maxu(fastf2u(MOD_FRACONE / (frequency * modTime)), 1); + + /* The modulation depth effects the amount of frequency change over the + * range of the sinus. It needs to be scaled by the modulation time so that + * a given depth produces a consistent change in frequency over all ranges + * of time. Since the depth is applied to a sinus value, it needs to be + * halved once for the sinus range and again for the sinus swing in time + * (half of it is spent decreasing the frequency, half is spent increasing + * it). + */ + Depth[1] = modDepth * MODULATION_DEPTH_COEFF * modTime * frequency / 4.0f; + + /* To cancel the effects of a long period modulation on the reverberation, + * the amount of pitch should be varied (decreased) according to the + * modulation time. The natural form is varying inversely, in fact + * resulting in an invariant over the previous expression. + */ + Depth[1] *= minf(AL_EAXREVERB_DEFAULT_MODULATION_TIME / modTime, 1.0f); +} + /* Update the late reverb line lengths and T60 coefficients. */ void LateReverb::updateLines(const ALfloat density, const ALfloat diffusion, const ALfloat lfDecayTime, const ALfloat mfDecayTime, const ALfloat hfDecayTime, @@ -848,9 +880,11 @@ void LateReverb::updateLines(const ALfloat density, const ALfloat diffusion, /* Approximate the absorption that the vector all-pass would exhibit * given the current diffusion so we don't have to process a full T60 - * filter for each of its four lines. + * filter for each of its four lines. Also include the average + * modulation delay (depth is half the max delay in samples). */ - length += lerp(LATE_ALLPASS_LENGTHS[i], late_allpass_avg, diffusion) * multiplier; + length += lerp(LATE_ALLPASS_LENGTHS[i], late_allpass_avg, diffusion)*multiplier + + Mod.Depth[1]/frequency; /* Calculate the T60 damping coefficients for each line. */ T60[i].calcCoeffs(length, lfDecayTime, mfDecayTime, hfDecayTime, lf0norm, hf0norm); @@ -888,39 +922,6 @@ void ReverbState::updateDelayLine(const ALfloat earlyDelay, const ALfloat lateDe } } -/* Update the EAX modulation step and depth. Keep in mind that this kind of - * vibrato is additive and not multiplicative as one may expect. The downswing - * will sound stronger than the upswing. - */ -void Modulation::updateModulator(float modTime, float modDepth, float frequency) -{ - /* Modulation is calculated in two parts. - * - * The modulation time effects the sinus rate, altering the speed of - * frequency changes. An index is incremented for each sample with an - * appropriate step size to generate an LFO, which will vary the feedback - * delay over time. - */ - Step = maxu(fastf2u(MOD_FRACONE / (frequency * modTime)), 1); - - /* The modulation depth effects the amount of frequency change over the - * range of the sinus. It needs to be scaled by the modulation time so that - * a given depth produces a consistent change in frequency over all ranges - * of time. Since the depth is applied to a sinus value, it needs to be - * halved once for the sinus range and again for the sinus swing in time - * (half of it is spent decreasing the frequency, half is spent increasing - * it). - */ - Depth[1] = modDepth * MODULATION_DEPTH_COEFF * modTime * frequency / 4.0f; - - /* To cancel the effects of a long period modulation on the reverberation, - * the amount of pitch should be varied (decreased) according to the - * modulation time. The natural form is varying inversely, in fact - * resulting in an invariant over the previous expression. - */ - Depth[1] *= minf(AL_EAXREVERB_DEFAULT_MODULATION_TIME / modTime, 1.0f); -} - /* Creates a transform matrix given a reverb vector. The vector pans the reverb * reflections toward the given direction, using its magnitude (up to 1) as a * focal strength. This function results in a B-Format transformation matrix @@ -1031,14 +1032,14 @@ void ReverbState::update(const ALCcontext *Context, const ALeffectslot *Slot, co const ALfloat hfDecayTime{clampf(props->Reverb.DecayTime * hfRatio, AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME)}; + /* Update the modulator rate and depth. */ + mLate.Mod.updateModulator(props->Reverb.ModulationTime, props->Reverb.ModulationDepth, + frequency); + /* Update the late lines. */ mLate.updateLines(props->Reverb.Density, props->Reverb.Diffusion, lfDecayTime, props->Reverb.DecayTime, hfDecayTime, lf0norm, hf0norm, frequency); - /* Update the modulator line. */ - mLate.Mod.updateModulator(props->Reverb.ModulationTime, props->Reverb.ModulationDepth, - frequency); - /* Update early and late 3D panning. */ const ALfloat gain{props->Reverb.Gain * Slot->Params.Gain * ReverbBoost}; update3DPanning(props->Reverb.ReflectionsPan, props->Reverb.LateReverbPan, @@ -1408,23 +1409,25 @@ void ReverbState::earlyFaded(const size_t offset, const size_t todo, const ALflo } -void Modulation::calcDelays(size_t c, size_t todo) +void Modulation::calcDelays(size_t todo) { - ALuint idx{Index[c]}; + constexpr float inv_scale{MOD_FRACONE / al::MathDefs<float>::Tau()}; + ALuint idx{Index}; const ALuint step{Step}; const float depth{Depth[0]}; for(size_t i{0};i < todo;++i) { idx += step; - ModDelays[i] = (std::sin(static_cast<float>(idx & MOD_FRACMASK) / - (MOD_FRACONE / al::MathDefs<float>::Tau())) + 1.0f) * depth; + const float lfo{std::sin(static_cast<float>(idx&MOD_FRACMASK) / inv_scale)}; + ModDelays[i] = (lfo+1.0f) * depth; } - Index[c] = idx; + Index = idx; } -void Modulation::calcFadedDelays(size_t c, size_t todo, float fadeCount, float fadeStep) +void Modulation::calcFadedDelays(size_t todo, float fadeCount, float fadeStep) { - ALuint idx{Index[c]}; + constexpr float inv_scale{MOD_FRACONE / al::MathDefs<float>::Tau()}; + ALuint idx{Index}; const ALuint step{Step}; const float depth{Depth[0]}; const float depthStep{(Depth[1]-depth) * fadeStep}; @@ -1432,10 +1435,10 @@ void Modulation::calcFadedDelays(size_t c, size_t todo, float fadeCount, float f { fadeCount += 1.0f; idx += step; - ModDelays[i] = (std::sin(static_cast<float>(idx & MOD_FRACMASK) / - (MOD_FRACONE / al::MathDefs<float>::Tau())) + 1.0f) * (depth + depthStep*fadeCount); + const float lfo{std::sin(static_cast<float>(idx&MOD_FRACMASK) / inv_scale)}; + ModDelays[i] = (lfo+1.0f) * (depth + depthStep*fadeCount); } - Index[c] = idx; + Index = idx; } @@ -1462,13 +1465,14 @@ void ReverbState::lateUnfaded(const size_t offset, const size_t todo) ASSUME(todo > 0); - /* First, load decorrelated samples from the main and feedback delay lines. + /* First, calculate the modulated delays for the late feedback. */ + mLate.Mod.calcDelays(todo); + + /* Next, load decorrelated samples from the main and feedback delay lines. * Filter the signal to apply its frequency-dependent decay. */ for(size_t j{0u};j < NUM_LINES;j++) { - mLate.Mod.calcDelays(j, todo); - const DelayLineI mod_delay{mLate.Mod.Delay}; size_t late_delay_tap{offset - mLateDelayTap[j][0]}; size_t late_feedb_tap{offset - mLate.Offset[j][0]}; @@ -1529,10 +1533,10 @@ void ReverbState::lateFaded(const size_t offset, const size_t todo, const ALfloa ASSUME(todo > 0); + mLate.Mod.calcFadedDelays(todo, fade, fadeStep); + for(size_t j{0u};j < NUM_LINES;j++) { - mLate.Mod.calcFadedDelays(j, todo, fade, fadeStep); - const DelayLineI mod_delay{mLate.Mod.Delay}; const ALfloat oldMidGain{mLate.T60[j].MidGain[0]}; const ALfloat midGain{mLate.T60[j].MidGain[1]}; |