aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/effects/compressor.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/effects/compressor.c')
-rw-r--r--Alc/effects/compressor.c88
1 files changed, 51 insertions, 37 deletions
diff --git a/Alc/effects/compressor.c b/Alc/effects/compressor.c
index 8c639f43..2131104c 100644
--- a/Alc/effects/compressor.c
+++ b/Alc/effects/compressor.c
@@ -35,10 +35,9 @@ typedef struct ALcompressorState {
/* Effect parameters */
ALboolean Enabled;
- ALfloat Envelope;
- ALfloat EnvGain;
- ALfloat Attack;
- ALfloat Release;
+ ALfloat AttackRate;
+ ALfloat ReleaseRate;
+ ALfloat GainCtrl;
} ALcompressorState;
static ALvoid ALcompressorState_Destruct(ALcompressorState *UNUSED(state))
@@ -47,10 +46,11 @@ static ALvoid ALcompressorState_Destruct(ALcompressorState *UNUSED(state))
static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdevice *device)
{
- state->Attack = expf(-1.0f / (device->Frequency * 0.0001f));
- state->Release = expf(-1.0f / (device->Frequency * 0.3f));
- state->Envelope = 0.0f;
- state->EnvGain = 1.0f;
+ const ALfloat attackTime = device->Frequency * 0.2f; /* 200ms Attack */
+ const ALfloat releaseTime = device->Frequency * 0.4f; /* 400ms Release */
+
+ state->AttackRate = 1.0 / attackTime;
+ state->ReleaseRate = 1.0 / releaseTime;
return AL_TRUE;
}
@@ -60,9 +60,6 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, ALCdevice *Devi
ALfloat gain;
state->Enabled = Slot->EffectProps.Compressor.OnOff;
- /* FIXME: Could maybe use the compressor's attack/release to move the gain to 1? */
- if(!state->Enabled)
- state->EnvGain = 1.0f;
gain = sqrtf(1.0f / Device->NumChan) * Slot->Gain;
SetGains(Device, gain, state->Gain);
@@ -70,46 +67,61 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, ALCdevice *Devi
static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE])
{
- ALfloat env = state->Envelope;
- ALfloat envgain = state->EnvGain;
- ALfloat tattack = state->Attack;
- ALfloat trelease = state->Release;
ALuint it, kt;
ALuint base;
- ALfloat theta;
- ALfloat rms;
for(base = 0;base < SamplesToDo;)
{
ALfloat temps[64];
ALuint td = minu(SamplesToDo-base, 64);
- ALfloat summ = 0.0f;
- for(it = 0;it < td;it++)
+ if(state->Enabled)
{
- ALfloat smp = SamplesIn[it+base] * 0.5f;
- summ += smp * smp;
- temps[it] = smp;
- }
+ ALfloat output, smp, amplitude;
+ ALfloat gain = state->GainCtrl;
- if(state->Enabled)
+ for(it = 0;it < td;it++)
+ {
+ smp = SamplesIn[it+base];
+
+ amplitude = fabs(smp);
+ if(amplitude > gain)
+ gain = minf(gain+state->AttackRate, amplitude);
+ else if(amplitude < gain)
+ gain = maxf(gain-state->ReleaseRate, amplitude);
+ output = 1.0 / clampf(gain, 0.5f, 2.0f);
+
+ temps[it] = smp * output;
+ }
+
+ state->GainCtrl = gain;
+ }
+ else
{
- const ALfloat threshold = 0.5f;
- const ALfloat slope = 0.5f;
+ ALfloat output, smp, amplitude;
+ ALfloat gain = state->GainCtrl;
+
+ for(it = 0;it < td;it++)
+ {
+ smp = SamplesIn[it+base];
+
+ amplitude = 1.0f;
+ if(amplitude > gain)
+ gain = minf(gain+state->AttackRate, amplitude);
+ else if(amplitude < gain)
+ gain = maxf(gain-state->ReleaseRate, amplitude);
+ output = 1.0f / clampf(gain, 0.5f, 2.0f);
- /* computing rms and envelope */
- rms = sqrtf(summ / td);
- theta = ((rms > env) ? tattack : trelease);
- env = (1.0f - theta)*rms + theta*env;
+ temps[it] = smp * output;
+ }
- /* applying a hard-knee rms based compressor */
- if(env > threshold)
- envgain = envgain - (env - threshold) * slope;
+ state->GainCtrl = gain;
}
+
for(kt = 0;kt < MaxChannels;kt++)
{
- ALfloat gain = state->Gain[kt] * envgain * 2.0f;
+ ALfloat gain = state->Gain[kt];
if(!(gain > GAIN_SILENCE_THRESHOLD))
continue;
@@ -119,9 +131,6 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint Samples
base += td;
}
-
- state->Envelope = env;
- state->EnvGain = envgain;
}
static void ALcompressorState_Delete(ALcompressorState *state)
@@ -144,6 +153,11 @@ static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory *
if(!state) return NULL;
SET_VTABLE2(ALcompressorState, ALeffectState, state);
+ state->Enabled = AL_TRUE;
+ state->AttackRate = 0.0f;
+ state->ReleaseRate = 0.0f;
+ state->GainCtrl = 1.0f;
+
return STATIC_CAST(ALeffectState, state);
}