aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/effects/reverb.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-06-07 10:33:56 -0700
committerChris Robinson <[email protected]>2017-06-07 10:39:19 -0700
commit10ff6cba9cf538e534138ac716e57324e8f71d06 (patch)
tree4e2ae25b0309fccb415a22b747f334621b20a151 /Alc/effects/reverb.c
parent61e43d4039277c538f3f6e0af7c988e7d71d8558 (diff)
Make the late lines' delay the delay average for modulation
Similar to the recent chorus and flanger changes, the modulation delay now swings between -n to +n, where n is less than the delay length. This brings up a slight issue with the linear interpolation, as modff doesn't produce the correct fraction value for interpolation (it's inverted, with 0 being closer to the next sample and 1 being closer to the base). So it's using nearest interpolation for now.
Diffstat (limited to 'Alc/effects/reverb.c')
-rw-r--r--Alc/effects/reverb.c95
1 files changed, 36 insertions, 59 deletions
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index f5d32d93..e0c0831a 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -331,21 +331,6 @@ ALfloat ReverbBoost = 1.0f;
*/
ALboolean EmulateEAXReverb = AL_FALSE;
-/* This coefficient is used to define the sinus depth according to the
- * modulation depth property. This value must be below 1, which would cause the
- * sampler to stall on the downswing, and above 1 it will cause it to sample
- * backwards.
- */
-static const ALfloat MODULATION_DEPTH_COEFF = 1.0f / 2048.0f;
-
-/* 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;
-
/* The all-pass and delay lines have a variable length dependent on the
* effect's density parameter. The resulting density multiplier is:
*
@@ -473,20 +458,33 @@ static const ALfloat LATE_LINE_LENGTHS[4] =
9.709681e-3f, 1.223343e-2f, 1.689561e-2f, 1.941936e-2f
};
-/* HACK: Workaround for a modff bug in 32-bit Windows, which attempts to write
- * a 64-bit double to the 32-bit float parameter.
+/* This coefficient is used to define the sinus depth according to the
+ * modulation depth property. This value must be below half the shortest late
+ * line length (0.0097/2 = ~0.0048), otherwise with certain parameters (high
+ * mod time, low density) the downswing can sample before the input.
*/
-#if defined(_WIN32) && !defined (_M_X64) && !defined(_M_ARM)
-static inline float hack_modff(float x, float *y)
+static const ALfloat MODULATION_DEPTH_COEFF = 1.0f / 4096.0f;
+
+/* 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
+static inline long lroundf(float val)
{
- double di;
- double df = modf((double)x, &di);
- *y = (float)di;
- return (float)df;
+ if(val < 0.0)
+ return fastf2i(ceilf(val-0.5f));
+ return fastf2i(floorf(val+0.5f));
}
-#define modff hack_modff
#endif
+
/**************************************
* Device Update *
**************************************/
@@ -1067,12 +1065,12 @@ static ALvoid UpdateModulator(const ALfloat modTime, const ALfloat modDepth,
* time changes the pitch, creating the modulation effect. The scale needs
* to be multiplied by the modulation time so that a given depth produces a
* consistent shift 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 (-1...+1 to 0...1) and again for the sinus swing in time (half of
- * it is spent decreasing the frequency, half is spent increasing it).
+ * is applied to a sinus value, it needs to be halved for the sinus swing
+ * in time (half of it is spent decreasing the frequency, half is spent
+ * increasing it).
*/
- State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
- 2.0f * frequency;
+ State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f *
+ frequency;
}
/* Update the offsets for the main effect delay line. */
@@ -1446,7 +1444,7 @@ static inline ALvoid DelayLineIn4Rev(DelayLineI *Delay, ALsizei offset, const AL
Delay->Line[offset][i] = in[3-i];
}
-static void CalcModulationDelays(ALreverbState *State, ALfloat *restrict delays, const ALsizei todo)
+static void CalcModulationDelays(ALreverbState *State, ALint *restrict delays, const ALsizei todo)
{
ALfloat sinus, range;
ALsizei index, i;
@@ -1456,10 +1454,9 @@ static void CalcModulationDelays(ALreverbState *State, ALfloat *restrict delays,
for(i = 0;i < todo;i++)
{
/* Calculate the sinus rhythm (dependent on modulation time and the
- * sampling rate). The center of the sinus is moved to reduce the
- * delay of the effect when the time or depth are low.
+ * sampling rate).
*/
- sinus = 1.0f - cosf(F_TAU * index / State->Mod.Range);
+ sinus = sinf(F_TAU * index / State->Mod.Range);
/* Step the modulation index forward, keeping it bound to its range. */
index = (index+1) % State->Mod.Range;
@@ -1470,8 +1467,8 @@ static void CalcModulationDelays(ALreverbState *State, ALfloat *restrict delays,
*/
range = lerp(range, State->Mod.Depth, State->Mod.Coeff);
- /* Calculate the read offset with fraction. */
- delays[i] = range*sinus;
+ /* Calculate the read offset. */
+ delays[i] = lroundf(range*sinus);
}
State->Mod.Index = index;
State->Mod.Filter = range;
@@ -1686,14 +1683,13 @@ static ALvoid LateReverb_##T(ALreverbState *State, const ALsizei todo, \
const ALfloat apFeedCoeff = State->ApFeedCoeff; \
const ALfloat mixX = State->MixX; \
const ALfloat mixY = State->MixY; \
- ALfloat fdelay, frac; \
+ ALint moddelay[MAX_UPDATE_SAMPLES]; \
ALsizei delay; \
ALsizei offset; \
ALsizei i, j; \
ALfloat f[4]; \
\
- /* Calculations modulation delays, uing the output as temp storage. */ \
- CalcModulationDelays(State, &out[0][0], todo); \
+ CalcModulationDelays(State, moddelay, todo); \
\
offset = State->Offset; \
for(i = 0;i < todo;i++) \
@@ -1704,31 +1700,12 @@ static ALvoid LateReverb_##T(ALreverbState *State, const ALsizei todo, \
offset-State->LateDelayTap[j][1], j, fade \
) * State->Late.DensityGain; \
\
- /* Separate the integer offset and fraction between it and the next \
- * sample. \
- */ \
- frac = modff(out[0][i], &fdelay); \
- delay = offset - fastf2i(fdelay); \
- \
+ delay = offset - moddelay[i]; \
for(j = 0;j < 4;j++) \
- { \
- ALfloat out0, out1; \
- \
- /* Get the two samples crossed by the offset delay. */ \
- out0 = DELAY_OUT_##T(&State->Late.Delay, \
+ f[j] += DELAY_OUT_##T(&State->Late.Delay, \
delay-State->Late.Offset[j][0], \
delay-State->Late.Offset[j][1], j, fade \
); \
- out1 = DELAY_OUT_##T(&State->Late.Delay, \
- delay-State->Late.Offset[j][0]-1, \
- delay-State->Late.Offset[j][1]-1, j, fade \
- ); \
- \
- /* The modulated result is obtained by linearly interpolating the \
- * two samples that were acquired above. \
- */ \
- f[j] += lerp(out0, out1, frac); \
- } \
\
for(j = 0;j < 4;j++) \
f[j] = LateT60Filter(j, f[j], State); \