aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-05-09 11:50:25 -0700
committerChris Robinson <[email protected]>2017-05-09 11:56:03 -0700
commita2c25378a970792461c961054e2b47cd3a086e05 (patch)
tree58faea77675124e906d5059a5e833f86c821cee4
parent4a4442ad91d34964b1d695381fafbdef07bb14ce (diff)
Reduce LIMITER_VALUE_MAX
The previous value couldn't actually be expressed as a float and got rounded up to the next whole number value, leaving the potential for an overrun in the squared sum.
-rw-r--r--Alc/ALu.c18
-rw-r--r--OpenAL32/Include/alu.h2
2 files changed, 13 insertions, 7 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index b8c93c69..e564ee00 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -1427,6 +1427,8 @@ static void UpdateContextSources(ALCcontext *ctx, const struct ALeffectslotArray
}
+static_assert(LIMITER_VALUE_MAX < (UINT_MAX/LIMITER_WINDOW_SIZE), "LIMITER_VALUE_MAX is too big");
+
static void ApplyLimiter(struct OutputLimiter *Limiter,
ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALsizei NumChans,
const ALfloat AttackRate, const ALfloat ReleaseRate,
@@ -1446,8 +1448,8 @@ static void ApplyLimiter(struct OutputLimiter *Limiter,
{
for(i = 0;i < SamplesToDo;i++)
{
- ALfloat amp_sqr = OutBuffer[c][i] * OutBuffer[c][i];
- Values[i] = maxf(Values[i], amp_sqr);
+ ALfloat amp = OutBuffer[c][i];
+ Values[i] = maxf(Values[i], amp*amp);
}
}
@@ -1456,7 +1458,7 @@ static void ApplyLimiter(struct OutputLimiter *Limiter,
ALfloat lastgain = Limiter->Gain;
ALsizei wpos = Limiter->Pos;
ALuint sum = Limiter->SquaredSum;
- ALfloat gain;
+ ALfloat gain, rms;
for(i = 0;i < SamplesToDo;i++)
{
@@ -1464,9 +1466,13 @@ static void ApplyLimiter(struct OutputLimiter *Limiter,
Limiter->Window[wpos] = fastf2u(minf(Values[i]*65536.0f, LIMITER_VALUE_MAX));
sum += Limiter->Window[wpos];
- /* Clamp limiter range to 0dB...-80dB. */
- gain = 1.0f / clampf(sqrtf((ALfloat)sum / ((ALfloat)LIMITER_WINDOW_SIZE*65536.0f)),
- 1.0f, 1000.0f);
+ rms = sqrtf((ALfloat)sum / ((ALfloat)LIMITER_WINDOW_SIZE*65536.0f));
+
+ /* Clamp the minimum RMS to 0dB. The uint used for the squared sum
+ * inherently limits the maximum RMS to about 21dB, thus the gain
+ * ranges from 0dB to -21dB.
+ */
+ gain = 1.0f / maxf(rms, 1.0f);
if(lastgain >= gain)
lastgain = maxf(lastgain*AttackRate, gain);
else
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 8ac25e35..30b245a5 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -299,7 +299,7 @@ void DeinitVoice(ALvoice *voice);
#define LIMITER_WINDOW_SIZE (1<<7) /* 128 */
#define LIMITER_WINDOW_MASK (LIMITER_WINDOW_SIZE-1)
-#define LIMITER_VALUE_MAX (UINT_MAX / LIMITER_WINDOW_SIZE)
+#define LIMITER_VALUE_MAX (1<<24) /* 16777216 */
struct OutputLimiter {
/* RMS detection window, sum of values in the window, and the next write
* pos. Values are 16.16 fixed-point.