aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/effects
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-01-29 07:26:19 -0800
committerChris Robinson <[email protected]>2016-01-29 07:26:19 -0800
commit3ac786c6af35952b056d5ca44afa6fb03acb1e7c (patch)
tree1f2f41e385c109e32192bda5b1efa5fd954d1b97 /Alc/effects
parent210b4c1fcdfff2ada91456dcdb494331d58dd7cc (diff)
Convert the equalizer effect to multichannel
Diffstat (limited to 'Alc/effects')
-rw-r--r--Alc/effects/equalizer.c123
1 files changed, 90 insertions, 33 deletions
diff --git a/Alc/effects/equalizer.c b/Alc/effects/equalizer.c
index 8ef52986..0a1ff1db 100644
--- a/Alc/effects/equalizer.c
+++ b/Alc/effects/equalizer.c
@@ -71,14 +71,20 @@
* filter coefficients" by Robert Bristow-Johnson *
* http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt */
+
+/* The maximum number of sample frames per update. */
+#define MAX_UPDATE_SAMPLES 256
+
typedef struct ALequalizerState {
DERIVE_FROM_TYPE(ALeffectState);
/* Effect gains for each channel */
- ALfloat Gain[MAX_OUTPUT_CHANNELS];
+ ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS];
/* Effect parameters */
- ALfilterState filter[4];
+ ALfilterState filter[4][MAX_EFFECT_CHANNELS];
+
+ ALfloat SampleBuffer[4][MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES];
} ALequalizerState;
static ALvoid ALequalizerState_Destruct(ALequalizerState *UNUSED(state))
@@ -94,8 +100,19 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *
{
ALfloat frequency = (ALfloat)device->Frequency;
ALfloat gain, freq_mult;
-
- ComputeAmbientGains(device->AmbiCoeffs, device->NumChannels, slot->Gain, state->Gain);
+ aluMatrixf matrix;
+ ALuint i;
+
+ gain = device->AmbiScale;
+ aluMatrixfSet(&matrix,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, gain, 0.0f, 0.0f,
+ 0.0f, 0.0f, gain, 0.0f,
+ 0.0f, 0.0f, 0.0f, gain
+ );
+ for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
+ ComputeBFormatGains(device->AmbiCoeffs, device->NumChannels,
+ matrix.m[i], slot->Gain, state->Gain[i]);
/* Calculate coefficients for the each type of filter. Note that the shelf
* filters' gain is for the reference frequency, which is the centerpoint
@@ -103,59 +120,96 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *
*/
gain = sqrtf(slot->EffectProps.Equalizer.LowGain);
freq_mult = slot->EffectProps.Equalizer.LowCutoff/frequency;
- ALfilterState_setParams(&state->filter[0], ALfilterType_LowShelf,
+ ALfilterState_setParams(&state->filter[0][0], ALfilterType_LowShelf,
gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
);
+ /* Copy the filter coefficients for the other input channels. */
+ for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
+ {
+ state->filter[0][i].a1 = state->filter[0][0].a1;
+ state->filter[0][i].a2 = state->filter[0][0].a2;
+ state->filter[0][i].b1 = state->filter[0][0].b1;
+ state->filter[0][i].b2 = state->filter[0][0].b2;
+ state->filter[0][i].input_gain = state->filter[0][0].input_gain;
+ state->filter[0][i].process = state->filter[0][0].process;
+ }
gain = slot->EffectProps.Equalizer.Mid1Gain;
freq_mult = slot->EffectProps.Equalizer.Mid1Center/frequency;
- ALfilterState_setParams(&state->filter[1], ALfilterType_Peaking,
+ ALfilterState_setParams(&state->filter[1][0], ALfilterType_Peaking,
gain, freq_mult, calc_rcpQ_from_bandwidth(freq_mult, slot->EffectProps.Equalizer.Mid1Width)
);
+ for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
+ {
+ state->filter[1][i].a1 = state->filter[1][0].a1;
+ state->filter[1][i].a2 = state->filter[1][0].a2;
+ state->filter[1][i].b1 = state->filter[1][0].b1;
+ state->filter[1][i].b2 = state->filter[1][0].b2;
+ state->filter[1][i].input_gain = state->filter[1][0].input_gain;
+ state->filter[1][i].process = state->filter[1][0].process;
+ }
gain = slot->EffectProps.Equalizer.Mid2Gain;
freq_mult = slot->EffectProps.Equalizer.Mid2Center/frequency;
- ALfilterState_setParams(&state->filter[2], ALfilterType_Peaking,
+ ALfilterState_setParams(&state->filter[2][0], ALfilterType_Peaking,
gain, freq_mult, calc_rcpQ_from_bandwidth(freq_mult, slot->EffectProps.Equalizer.Mid2Width)
);
+ for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
+ {
+ state->filter[2][i].a1 = state->filter[2][0].a1;
+ state->filter[2][i].a2 = state->filter[2][0].a2;
+ state->filter[2][i].b1 = state->filter[2][0].b1;
+ state->filter[2][i].b2 = state->filter[2][0].b2;
+ state->filter[2][i].input_gain = state->filter[2][0].input_gain;
+ state->filter[2][i].process = state->filter[2][0].process;
+ }
gain = sqrtf(slot->EffectProps.Equalizer.HighGain);
freq_mult = slot->EffectProps.Equalizer.HighCutoff/frequency;
- ALfilterState_setParams(&state->filter[3], ALfilterType_HighShelf,
+ ALfilterState_setParams(&state->filter[3][0], ALfilterType_HighShelf,
gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
);
+ for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
+ {
+ state->filter[3][i].a1 = state->filter[3][0].a1;
+ state->filter[3][i].a2 = state->filter[3][0].a2;
+ state->filter[3][i].b1 = state->filter[3][0].b1;
+ state->filter[3][i].b2 = state->filter[3][0].b2;
+ state->filter[3][i].input_gain = state->filter[3][0].input_gain;
+ state->filter[3][i].process = state->filter[3][0].process;
+ }
}
static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
{
+ ALfloat (*Samples)[MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES] = state->SampleBuffer;
+ ALuint it, kt, ft;
ALuint base;
- ALuint it;
- ALuint kt;
- ALuint ft;
for(base = 0;base < SamplesToDo;)
{
- ALfloat temps[256];
- ALuint td = minu(256, SamplesToDo-base);
-
- for(it = 0;it < td;it++)
+ ALuint td = minu(MAX_UPDATE_SAMPLES, SamplesToDo-base);
+
+ for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
+ ALfilterState_process(&state->filter[0][ft], Samples[0][ft], &SamplesIn[ft][base], td);
+ for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
+ ALfilterState_process(&state->filter[1][ft], Samples[1][ft], Samples[0][ft], td);
+ for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
+ ALfilterState_process(&state->filter[2][ft], Samples[2][ft], Samples[1][ft], td);
+ for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
+ ALfilterState_process(&state->filter[3][ft], Samples[3][ft], Samples[2][ft], td);
+
+ for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
{
- ALfloat smp = SamplesIn[0][base+it];
-
- for(ft = 0;ft < 4;ft++)
- smp = ALfilterState_processSingle(&state->filter[ft], smp);
-
- temps[it] = smp;
- }
-
- for(kt = 0;kt < NumChannels;kt++)
- {
- ALfloat gain = state->Gain[kt];
- if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
- continue;
-
- for(it = 0;it < td;it++)
- SamplesOut[kt][base+it] += gain * temps[it];
+ for(kt = 0;kt < NumChannels;kt++)
+ {
+ ALfloat gain = state->Gain[ft][kt];
+ if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
+ continue;
+
+ for(it = 0;it < td;it++)
+ SamplesOut[kt][base+it] += gain * Samples[3][ft][it];
+ }
}
base += td;
@@ -174,7 +228,7 @@ typedef struct ALequalizerStateFactory {
ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(factory))
{
ALequalizerState *state;
- int it;
+ int it, ft;
state = ALequalizerState_New(sizeof(*state));
if(!state) return NULL;
@@ -183,7 +237,10 @@ ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(fa
/* Initialize sample history only on filter creation to avoid */
/* sound clicks if filter settings were changed in runtime. */
for(it = 0; it < 4; it++)
- ALfilterState_clear(&state->filter[it]);
+ {
+ for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
+ ALfilterState_clear(&state->filter[it][ft]);
+ }
return STATIC_CAST(ALeffectState, state);
}