aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALu.c17
-rw-r--r--OpenAL32/Include/alu.h8
2 files changed, 12 insertions, 13 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 8d9356c5..b8c93c69 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -1455,24 +1455,18 @@ static void ApplyLimiter(struct OutputLimiter *Limiter,
{
ALfloat lastgain = Limiter->Gain;
ALsizei wpos = Limiter->Pos;
- ALfloat sum = 0.0f;
+ ALuint sum = Limiter->SquaredSum;
ALfloat gain;
- /* Unfortunately we can't store the running sum due to fp inaccuracies
- * causing it to drift over time. So we need to recalculate it every
- * once in a while (i.e. every invocation).
- */
- for(i = 0;i < LIMITER_WINDOW_SIZE;i++)
- sum += Limiter->Window[i];
-
for(i = 0;i < SamplesToDo;i++)
{
sum -= Limiter->Window[wpos];
- Limiter->Window[wpos] = Values[i];
- sum += Values[i];
+ 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(sum / (ALfloat)LIMITER_WINDOW_SIZE), 1.0f, 1000.0f);
+ gain = 1.0f / clampf(sqrtf((ALfloat)sum / ((ALfloat)LIMITER_WINDOW_SIZE*65536.0f)),
+ 1.0f, 1000.0f);
if(lastgain >= gain)
lastgain = maxf(lastgain*AttackRate, gain);
else
@@ -1485,6 +1479,7 @@ static void ApplyLimiter(struct OutputLimiter *Limiter,
Limiter->Gain = lastgain;
Limiter->Pos = wpos;
+ Limiter->SquaredSum = sum;
}
if(do_limit)
{
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 6fdbac6f..8ac25e35 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -299,9 +299,13 @@ 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)
struct OutputLimiter {
- /* RMS detection window and the next write pos. */
- alignas(16) ALfloat Window[LIMITER_WINDOW_SIZE];
+ /* RMS detection window, sum of values in the window, and the next write
+ * pos. Values are 16.16 fixed-point.
+ */
+ ALuint Window[LIMITER_WINDOW_SIZE];
+ ALuint SquaredSum;
ALsizei Pos;
/* In milliseconds. */