diff options
author | Chris Robinson <[email protected]> | 2016-01-28 02:49:40 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-01-28 02:49:40 -0800 |
commit | 210b4c1fcdfff2ada91456dcdb494331d58dd7cc (patch) | |
tree | 9d8211f418e771b40a5572d7e6dd6b3254cbcaba /Alc/effects | |
parent | c1f87414c5452f595f78b7a52a7063a023ce2982 (diff) |
Make the compressor effect multichannel
Diffstat (limited to 'Alc/effects')
-rw-r--r-- | Alc/effects/compressor.c | 83 |
1 files changed, 58 insertions, 25 deletions
diff --git a/Alc/effects/compressor.c b/Alc/effects/compressor.c index 6c3b8375..e3c26bd9 100644 --- a/Alc/effects/compressor.c +++ b/Alc/effects/compressor.c @@ -31,7 +31,7 @@ typedef struct ALcompressorState { DERIVE_FROM_TYPE(ALeffectState); /* Effect gains for each channel */ - ALfloat Gain[MAX_OUTPUT_CHANNELS]; + ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS]; /* Effect parameters */ ALboolean Enabled; @@ -57,73 +57,106 @@ static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdev static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice *device, const ALeffectslot *slot) { + aluMatrixf matrix; + ALfloat scale; + ALuint i; + state->Enabled = slot->EffectProps.Compressor.OnOff; - ComputeAmbientGains(device->AmbiCoeffs, device->NumChannels, slot->Gain, state->Gain); + scale = device->AmbiScale; + aluMatrixfSet(&matrix, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, scale, 0.0f, 0.0f, + 0.0f, 0.0f, scale, 0.0f, + 0.0f, 0.0f, 0.0f, scale + ); + for(i = 0;i < 4;i++) + ComputeBFormatGains(device->AmbiCoeffs, device->NumChannels, + matrix.m[i], slot->Gain, state->Gain[i]); } static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) { - ALuint it, kt; + ALuint i, j, k; ALuint base; for(base = 0;base < SamplesToDo;) { - ALfloat temps[256]; - ALuint td = minu(256, SamplesToDo-base); + ALfloat temps[64][4]; + ALuint td = minu(64, SamplesToDo-base); + + /* Load samples into the temp buffer first. */ + for(j = 0;j < 4;j++) + { + for(i = 0;i < td;i++) + temps[i][j] = SamplesIn[j][i+base]; + } if(state->Enabled) { - ALfloat output, smp, amplitude; ALfloat gain = state->GainCtrl; + ALfloat output, amplitude; - for(it = 0;it < td;it++) + for(i = 0;i < td;i++) { - smp = SamplesIn[0][it+base]; - - amplitude = fabsf(smp); + /* Roughly calculate the maximum amplitude from the 4-channel + * signal, and attack or release the gain control to reach it. + */ + amplitude = fabsf(temps[i][0]); + amplitude = maxf(amplitude + fabsf(temps[i][1]), + maxf(amplitude + fabsf(temps[i][2]), + amplitude + fabsf(temps[i][3]))); 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); - temps[it] = smp * output; + /* Apply the inverse of the gain control to normalize/compress + * the volume. */ + output = 1.0f / clampf(gain, 0.5f, 2.0f); + for(j = 0;j < 4;j++) + temps[i][j] *= output; } state->GainCtrl = gain; } else { - ALfloat output, smp, amplitude; ALfloat gain = state->GainCtrl; + ALfloat output, amplitude; - for(it = 0;it < td;it++) + for(i = 0;i < td;i++) { - smp = SamplesIn[0][it+base]; - + /* Same as above, except the amplitude is forced to 1. This + * helps ensure smooth gain changes when the compressor is + * turned on and off. + */ 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); - temps[it] = smp * output; + output = 1.0f / clampf(gain, 0.5f, 2.0f); + for(j = 0;j < 4;j++) + temps[i][j] *= output; } state->GainCtrl = gain; } - - for(kt = 0;kt < NumChannels;kt++) + /* Now mix to the output. */ + for(j = 0;j < 4;j++) { - ALfloat gain = state->Gain[kt]; - if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) - continue; + for(k = 0;k < NumChannels;k++) + { + ALfloat gain = state->Gain[j][k]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; - for(it = 0;it < td;it++) - SamplesOut[kt][base+it] += gain * temps[it]; + for(i = 0;i < td;i++) + SamplesOut[k][base+i] += gain * temps[i][j]; + } } base += td; |