diff options
author | Chris Robinson <[email protected]> | 2017-12-24 16:23:30 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-12-24 16:23:30 -0800 |
commit | 254ebe5f9649bf338a6f584c0924d54e4f413bff (patch) | |
tree | d8d8a9947090570397a6ed91d39ca0f69a2eb372 | |
parent | b32a3661375487184c7f4e13b7037ae9e7122895 (diff) |
Fade between depths in the reverb modulator
-rw-r--r-- | Alc/effects/reverb.c | 74 |
1 files changed, 26 insertions, 48 deletions
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c index d30fceb0..8b31266e 100644 --- a/Alc/effects/reverb.c +++ b/Alc/effects/reverb.c @@ -226,14 +226,6 @@ static const ALfloat LATE_LINE_LENGTHS[4] = */ static const ALfloat MODULATION_DEPTH_COEFF = 0.0032f; -/* A filter is used to avoid the terrible distortion caused by changing - * modulation time and/or depth. To be consistent across different sample - * rates, the coefficient must be raised to a constant divided by the sample - * rate: coeff^(constant / rate). - */ -static const ALfloat MODULATION_FILTER_COEFF = 0.048f; -static const ALfloat MODULATION_FILTER_CONST = 100000.0f; - /* Prior to VS2013, MSVC lacks the round() family of functions. */ #if defined(_MSC_VER) && _MSC_VER < 1800 @@ -322,9 +314,7 @@ typedef struct ALreverbState { ALfloat Scale; /* The depth of frequency change (also in samples) and its filter. */ - ALfloat Depth; - ALfloat Coeff; - ALfloat Filter; + ALfloat Depth[2]; } Mod; /* EAX only */ struct { @@ -363,6 +353,7 @@ typedef struct ALreverbState { ALsizei Offset; /* Temporary storage used when processing. */ + alignas(16) ALint ModUlationDelays[MAX_UPDATE_SAMPLES][2]; alignas(16) ALfloat AFormatSamples[4][MAX_UPDATE_SAMPLES]; alignas(16) ALfloat ReverbSamples[4][MAX_UPDATE_SAMPLES]; alignas(16) ALfloat EarlySamples[4][MAX_UPDATE_SAMPLES]; @@ -432,9 +423,8 @@ static void ALreverbState_Construct(ALreverbState *state) state->Mod.Index = 0; state->Mod.Range = 1; state->Mod.Scale = 0.0f; - state->Mod.Depth = 0.0f; - state->Mod.Coeff = 0.0f; - state->Mod.Filter = 0.0f; + state->Mod.Depth[0] = 0.0f; + state->Mod.Depth[1] = 0.0f; state->Late.DensityGain = 0.0f; @@ -608,28 +598,19 @@ static ALboolean AllocLines(const ALuint frequency, ALreverbState *State) static ALboolean ALreverbState_deviceUpdate(ALreverbState *State, ALCdevice *Device) { - ALuint frequency = Device->Frequency, i; + ALuint frequency = Device->Frequency; ALfloat multiplier; /* Allocate the delay lines. */ if(!AllocLines(frequency, State)) return AL_FALSE; - /* Calculate the modulation filter coefficient. Notice that the exponent - * is calculated given the current sample rate. This ensures that the - * resulting filter response over time is consistent across all sample - * rates. - */ - State->Mod.Coeff = powf(MODULATION_FILTER_COEFF, - MODULATION_FILTER_CONST / frequency); - - multiplier = 1.0f + LINE_MULTIPLIER; + multiplier = 1.0f + AL_EAXREVERB_MAX_DENSITY*LINE_MULTIPLIER; /* The late feed taps are set a fixed position past the latest delay tap. */ - for(i = 0;i < 4;i++) - State->LateFeedTap = fastf2i((AL_EAXREVERB_MAX_REFLECTIONS_DELAY + - EARLY_TAP_LENGTHS[3]*multiplier) * - frequency); + State->LateFeedTap = fastf2i((AL_EAXREVERB_MAX_REFLECTIONS_DELAY + + EARLY_TAP_LENGTHS[3]*multiplier) * + frequency); return AL_TRUE; } @@ -1068,9 +1049,9 @@ static ALvoid UpdateModulator(const ALfloat modTime, const ALfloat modDepth, * that a given depth produces a consistent shift in frequency over all * ranges of time. */ - State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * - (modTime / AL_EAXREVERB_MAX_MODULATION_TIME) * - frequency; + State->Mod.Depth[1] = modDepth * MODULATION_DEPTH_COEFF * + (modTime / AL_EAXREVERB_MAX_MODULATION_TIME) * + frequency; } /* Update the offsets for the main effect delay line. */ @@ -1396,7 +1377,8 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCcontext *Conte (State->Early.Offset[i][1] != State->Early.Offset[i][0]) || (State->LateDelayTap[i][1] != State->LateDelayTap[i][0]) || (State->Late.VecAp.Offset[i][1] != State->Late.VecAp.Offset[i][0]) || - (State->Late.Offset[i][1] != State->Late.Offset[i][0])) + (State->Late.Offset[i][1] != State->Late.Offset[i][0]) || + (State->Mod.Depth[1] != State->Mod.Depth[0])) { State->FadeCount = 0; break; @@ -1447,13 +1429,13 @@ static inline ALvoid DelayLineIn4Rev(DelayLineI *Delay, ALsizei offset, const AL Delay->Line[offset][i] = in[3-i]; } -static void CalcModulationDelays(ALreverbState *State, ALint *restrict delays, const ALsizei todo) +static void CalcModulationDelays(ALreverbState *State, ALint (*restrict delays)[2], + const ALsizei todo) { - ALfloat sinus, depth; + ALfloat sinus; ALsizei index, i; index = State->Mod.Index; - depth = State->Mod.Filter; for(i = 0;i < todo;i++) { /* Calculate the sinus rhythm (dependent on modulation time and the @@ -1464,17 +1446,11 @@ static void CalcModulationDelays(ALreverbState *State, ALint *restrict delays, c /* Step the modulation index forward, keeping it bound to its range. */ index = (index+1) % State->Mod.Range; - /* The depth determines the range over which to read the input samples - * from, so it must be filtered to reduce the distortion caused by even - * small parameter changes. - */ - depth = lerp(depth, State->Mod.Depth, State->Mod.Coeff); - /* Calculate the read offset. */ - delays[i] = lroundf(depth*sinus); + delays[i][0] = lroundf(sinus * State->Mod.Depth[0]); + delays[i][1] = lroundf(sinus * State->Mod.Depth[1]); } State->Mod.Index = index; - State->Mod.Filter = depth; } /* Applies a scattering matrix to the 4-line (vector) input. This is used @@ -1683,11 +1659,11 @@ static ALvoid LateReverb_##T(ALreverbState *State, const ALsizei todo, \ ALfloat fade, \ ALfloat (*restrict out)[MAX_UPDATE_SAMPLES]) \ { \ + ALint (*restrict moddelay)[2] = State->ModUlationDelays; \ const ALfloat apFeedCoeff = State->ApFeedCoeff; \ const ALfloat mixX = State->MixX; \ const ALfloat mixY = State->MixY; \ - ALint moddelay[MAX_UPDATE_SAMPLES]; \ - ALsizei delay; \ + ALsizei delay[2]; \ ALsizei offset; \ ALsizei i, j; \ ALfloat f[4]; \ @@ -1703,11 +1679,12 @@ static ALvoid LateReverb_##T(ALreverbState *State, const ALsizei todo, \ offset-State->LateDelayTap[j][1], j, fade \ ) * State->Late.DensityGain; \ \ - delay = offset - moddelay[i]; \ + delay[0] = offset - moddelay[i][0]; \ + delay[1] = offset - moddelay[i][1]; \ for(j = 0;j < 4;j++) \ out[j][i] = f[j] + DELAY_OUT_##T(&State->Late.Delay, \ - delay-State->Late.Offset[j][0], \ - delay-State->Late.Offset[j][1], j, fade \ + delay[0]-State->Late.Offset[j][0], \ + delay[1]-State->Late.Offset[j][1], j, fade \ ); \ \ for(j = 0;j < 4;j++) \ @@ -1874,6 +1851,7 @@ static ALvoid ALreverbState_process(ALreverbState *State, ALsizei SamplesToDo, c State->Late.VecAp.Offset[c][0] = State->Late.VecAp.Offset[c][1]; State->Late.Offset[c][0] = State->Late.Offset[c][1]; } + State->Mod.Depth[0] = State->Mod.Depth[1]; } /* Mix the A-Format results to output, implicitly converting back to |