summaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2013-06-06 03:24:44 -0700
committerChris Robinson <[email protected]>2013-06-06 03:24:44 -0700
commit647398d7c6b6198ca85675ae75ff0debc275fc3b (patch)
tree701ec596eefac86290f9a5c531de62d7562dd807 /Alc
parentdcefeac6e6afd5c21e0e463c6f780f14ea8eeab5 (diff)
Use ALfilterState for the distortion effect filters
Diffstat (limited to 'Alc')
-rw-r--r--Alc/effects/distortion.c84
1 files changed, 14 insertions, 70 deletions
diff --git a/Alc/effects/distortion.c b/Alc/effects/distortion.c
index 4fd116f6..a1058415 100644
--- a/Alc/effects/distortion.c
+++ b/Alc/effects/distortion.c
@@ -37,23 +37,6 @@ typedef struct ALdistortionStateFactory {
static ALdistortionStateFactory DistortionFactory;
-/* Filters implementation is based on the "Cookbook formulae for audio *
- * EQ biquad filter coefficients" by Robert Bristow-Johnson *
- * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt */
-
-typedef enum ALEQFilterType {
- LOWPASS,
- BANDPASS,
-} ALEQFilterType;
-
-typedef struct ALEQFilter {
- ALEQFilterType type;
- ALfloat x[2]; /* History of two last input samples */
- ALfloat y[2]; /* History of two last output samples */
- ALfloat a[3]; /* Transfer function coefficients "a" */
- ALfloat b[3]; /* Transfer function coefficients "b" */
-} ALEQFilter;
-
typedef struct ALdistortionState {
DERIVE_FROM_TYPE(ALeffectState);
@@ -61,8 +44,8 @@ typedef struct ALdistortionState {
ALfloat Gain[MaxChannels];
/* Effect parameters */
- ALEQFilter bandpass;
- ALEQFilter lowpass;
+ ALfilterState lowpass;
+ ALfilterState bandpass;
ALfloat attenuation;
ALfloat edge_coeff;
} ALdistortionState;
@@ -84,8 +67,6 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, ALCdevice *Devi
ALfloat gain = sqrtf(1.0f / Device->NumChan) * Slot->Gain;
ALfloat frequency = (ALfloat)Device->Frequency;
ALuint it;
- ALfloat w0;
- ALfloat alpha;
ALfloat bandwidth;
ALfloat cutoff;
ALfloat edge;
@@ -109,34 +90,21 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, ALCdevice *Devi
cutoff = Slot->EffectProps.Distortion.LowpassCutoff;
/* Bandwidth value is constant in octaves */
bandwidth = (cutoff / 2.0f) / (cutoff * 0.67f);
- w0 = 2.0f*F_PI * cutoff / (frequency*4.0f);
- alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
- state->lowpass.b[0] = (1.0f - cosf(w0)) / 2.0f;
- state->lowpass.b[1] = 1.0f - cosf(w0);
- state->lowpass.b[2] = (1.0f - cosf(w0)) / 2.0f;
- state->lowpass.a[0] = 1.0f + alpha;
- state->lowpass.a[1] = -2.0f * cosf(w0);
- state->lowpass.a[2] = 1.0f - alpha;
+ ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f,
+ cutoff / (frequency*4.0f), bandwidth);
/* Bandpass filter */
cutoff = Slot->EffectProps.Distortion.EQCenter;
/* Convert bandwidth in Hz to octaves */
bandwidth = Slot->EffectProps.Distortion.EQBandwidth / (cutoff * 0.67f);
- w0 = 2.0f*F_PI * cutoff / (frequency*4.0f);
- alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
- state->bandpass.b[0] = alpha;
- state->bandpass.b[1] = 0;
- state->bandpass.b[2] = -alpha;
- state->bandpass.a[0] = 1.0f + alpha;
- state->bandpass.a[1] = -2.0f * cosf(w0);
- state->bandpass.a[2] = 1.0f - alpha;
+ ALfilterState_setParams(&state->bandpass, ALfilterType_BandPass, 1.0f,
+ cutoff / (frequency*4.0f), bandwidth);
}
static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
{
const ALfloat fc = state->edge_coeff;
float oversample_buffer[64][4];
- ALfloat tempsmp;
ALuint base;
ALuint it;
ALuint ot;
@@ -171,18 +139,11 @@ static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint Samples
{
for(ot = 0;ot < 4;ot++)
{
- tempsmp = state->lowpass.b[0] / state->lowpass.a[0] * oversample_buffer[it][ot] +
- state->lowpass.b[1] / state->lowpass.a[0] * state->lowpass.x[0] +
- state->lowpass.b[2] / state->lowpass.a[0] * state->lowpass.x[1] -
- state->lowpass.a[1] / state->lowpass.a[0] * state->lowpass.y[0] -
- state->lowpass.a[2] / state->lowpass.a[0] * state->lowpass.y[1];
-
- state->lowpass.x[1] = state->lowpass.x[0];
- state->lowpass.x[0] = oversample_buffer[it][ot];
- state->lowpass.y[1] = state->lowpass.y[0];
- state->lowpass.y[0] = tempsmp;
+ ALfloat smp;
+ smp = ALfilterState_processSingle(&state->lowpass, oversample_buffer[it][ot]);
+
/* Restore signal power by multiplying sample by amount of oversampling */
- oversample_buffer[it][ot] = tempsmp * 4.0f;
+ oversample_buffer[it][ot] = smp * 4.0f;
}
}
@@ -201,18 +162,8 @@ static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint Samples
smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp));
/* Third step, do bandpass filtering of distorted signal */
- tempsmp = state->bandpass.b[0] / state->bandpass.a[0] * smp +
- state->bandpass.b[1] / state->bandpass.a[0] * state->bandpass.x[0] +
- state->bandpass.b[2] / state->bandpass.a[0] * state->bandpass.x[1] -
- state->bandpass.a[1] / state->bandpass.a[0] * state->bandpass.y[0] -
- state->bandpass.a[2] / state->bandpass.a[0] * state->bandpass.y[1];
-
- state->bandpass.x[1] = state->bandpass.x[0];
- state->bandpass.x[0] = smp;
- state->bandpass.y[1] = state->bandpass.y[0];
- state->bandpass.y[0] = tempsmp;
-
- oversample_buffer[it][ot] = tempsmp;
+ smp = ALfilterState_processSingle(&state->bandpass, smp);
+ oversample_buffer[it][ot] = smp;
}
/* Fourth step, final, do attenuation and perform decimation, */
@@ -251,15 +202,8 @@ static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory *
if(!state) return NULL;
SET_VTABLE2(ALdistortionState, ALeffectState, state);
- state->bandpass.type = BANDPASS;
- state->lowpass.type = LOWPASS;
-
- /* Initialize sample history only on filter creation to avoid */
- /* sound clicks if filter settings were changed in runtime. */
- state->bandpass.x[0] = 0.0f;
- state->bandpass.x[1] = 0.0f;
- state->lowpass.y[0] = 0.0f;
- state->lowpass.y[1] = 0.0f;
+ ALfilterState_clear(&state->lowpass);
+ ALfilterState_clear(&state->bandpass);
return STATIC_CAST(ALeffectState, state);
}