aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alFilter.h43
-rw-r--r--OpenAL32/alFilter.c78
2 files changed, 121 insertions, 0 deletions
diff --git a/OpenAL32/Include/alFilter.h b/OpenAL32/Include/alFilter.h
index 94feb3ee..f70b839e 100644
--- a/OpenAL32/Include/alFilter.h
+++ b/OpenAL32/Include/alFilter.h
@@ -46,6 +46,49 @@ static __inline ALfloat lpFilter2PC(const FILTER *iir, ALfloat input)
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw);
+typedef enum ALfilterType {
+ ALfilterType_HighShelf,
+ ALfilterType_LowShelf,
+ ALfilterType_Peaking,
+} ALfilterType;
+
+typedef struct ALfilterState {
+ 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" */
+} ALfilterState;
+
+void ALfilterState_clear(ALfilterState *filter);
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth);
+
+static __inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample)
+{
+ ALfloat outsmp;
+
+ outsmp = filter->b[0] * sample +
+ filter->b[1] * filter->x[0] +
+ filter->b[2] * filter->x[1] -
+ filter->a[1] * filter->y[0] -
+ filter->a[2] * filter->y[1];
+ filter->x[1] = filter->x[0];
+ filter->x[0] = sample;
+ filter->y[1] = filter->y[0];
+ filter->y[0] = outsmp;
+
+ return outsmp;
+}
+
+static __inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample)
+{
+ return filter->b[0] * sample +
+ filter->b[1] * filter->x[0] +
+ filter->b[2] * filter->x[1] -
+ filter->a[1] * filter->y[0] -
+ filter->a[2] * filter->y[1];
+}
+
+
typedef struct ALfilter {
// Filter type (AL_FILTER_NULL, ...)
ALenum type;
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c
index 312cf681..6b4ce633 100644
--- a/OpenAL32/alFilter.c
+++ b/OpenAL32/alFilter.c
@@ -325,6 +325,84 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
}
+void ALfilterState_clear(ALfilterState *filter)
+{
+ filter->x[0] = 0.0f;
+ filter->x[1] = 0.0f;
+ filter->y[0] = 0.0f;
+ filter->y[1] = 0.0f;
+}
+
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth)
+{
+ ALfloat alpha;
+ ALfloat w0;
+
+ w0 = 2.0f*F_PI * freq_scale;
+
+ /* Calculate filter coefficients depending on filter type */
+ switch(type)
+ {
+ case ALfilterType_HighShelf:
+ alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f/gain) *
+ (1.0f/0.75f - 1.0f) + 2.0f);
+ filter->b[0] = gain * ((gain + 1.0f) +
+ (gain - 1.0f) * cosf(w0) +
+ 2.0f * sqrtf(gain) * alpha);
+ filter->b[1] = -2.0f * gain * ((gain - 1.0f) +
+ (gain + 1.0f) * cosf(w0));
+ filter->b[2] = gain * ((gain + 1.0f) +
+ (gain - 1.0f) * cosf(w0) -
+ 2.0f * sqrtf(gain) * alpha);
+ filter->a[0] = (gain + 1.0f) -
+ (gain - 1.0f) * cosf(w0) +
+ 2.0f * sqrtf(gain) * alpha;
+ filter->a[1] = 2.0f * ((gain - 1.0f) -
+ (gain + 1.0f) * cosf(w0));
+ filter->a[2] = (gain + 1.0f) -
+ (gain - 1.0f) * cosf(w0) -
+ 2.0f * sqrtf(gain) * alpha;
+ break;
+ case ALfilterType_LowShelf:
+ alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f / gain) *
+ (1.0f / 0.75f - 1.0f) + 2.0f);
+ filter->b[0] = gain * ((gain + 1.0f) -
+ (gain - 1.0f) * cosf(w0) +
+ 2.0f * sqrtf(gain) * alpha);
+ filter->b[1] = 2.0f * gain * ((gain - 1.0f) -
+ (gain + 1.0f) * cosf(w0));
+ filter->b[2] = gain * ((gain + 1.0f) -
+ (gain - 1.0f) * cosf(w0) -
+ 2.0f * sqrtf(gain) * alpha);
+ filter->a[0] = (gain + 1.0f) +
+ (gain - 1.0f) * cosf(w0) +
+ 2.0f * sqrtf(gain) * alpha;
+ filter->a[1] = -2.0f * ((gain - 1.0f) +
+ (gain + 1.0f) * cosf(w0));
+ filter->a[2] = (gain + 1.0f) +
+ (gain - 1.0f) * cosf(w0) -
+ 2.0f * sqrtf(gain) * alpha;
+ break;
+ case ALfilterType_Peaking:
+ alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
+ filter->b[0] = 1.0f + alpha * gain;
+ filter->b[1] = -2.0f * cosf(w0);
+ filter->b[2] = 1.0f - alpha * gain;
+ filter->a[0] = 1.0f + alpha / gain;
+ filter->a[1] = -2.0f * cosf(w0);
+ filter->a[2] = 1.0f - alpha / gain;
+ break;
+ }
+
+ filter->b[0] /= filter->a[0];
+ filter->b[1] /= filter->a[0];
+ filter->b[2] /= filter->a[0];
+ filter->a[0] /= filter->a[0];
+ filter->a[1] /= filter->a[0];
+ filter->a[2] /= filter->a[0];
+}
+
+
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
ALfloat a = 0.0f;