aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alFilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32/alFilter.c')
-rw-r--r--OpenAL32/alFilter.c296
1 files changed, 193 insertions, 103 deletions
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c
index a03ee2d8..692109f5 100644
--- a/OpenAL32/alFilter.c
+++ b/OpenAL32/alFilter.c
@@ -29,87 +29,89 @@
#include "alError.h"
+extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
+extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id);
+extern inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample);
+extern inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample);
+
static void InitFilterParams(ALfilter *filter, ALenum type);
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
- ALCcontext *Context;
- ALsizei cur = 0;
+ ALCdevice *device;
+ ALCcontext *context;
+ ALsizei cur = 0;
+ ALenum err;
- Context = GetContextRef();
- if(!Context) return;
+ context = GetContextRef();
+ if(!context) return;
- al_try
- {
- ALCdevice *device = Context->Device;
- ALenum err;
+ if(!(n >= 0))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
- CHECK_VALUE(Context, n >= 0);
- for(cur = 0;cur < n;cur++)
+ device = context->Device;
+ for(cur = 0;cur < n;cur++)
+ {
+ ALfilter *filter = calloc(1, sizeof(ALfilter));
+ if(!filter)
{
- ALfilter *filter = calloc(1, sizeof(ALfilter));
- if(!filter)
- al_throwerr(Context, AL_OUT_OF_MEMORY);
- InitFilterParams(filter, AL_FILTER_NULL);
-
- err = NewThunkEntry(&filter->id);
- if(err == AL_NO_ERROR)
- err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
- if(err != AL_NO_ERROR)
- {
- FreeThunkEntry(filter->id);
- memset(filter, 0, sizeof(ALfilter));
- free(filter);
-
- al_throwerr(Context, err);
- }
-
- filters[cur] = filter->id;
+ alDeleteFilters(cur, filters);
+ SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
}
- }
- al_catchany()
- {
- if(cur > 0)
+ InitFilterParams(filter, AL_FILTER_NULL);
+
+ err = NewThunkEntry(&filter->id);
+ if(err == AL_NO_ERROR)
+ err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
+ if(err != AL_NO_ERROR)
+ {
+ FreeThunkEntry(filter->id);
+ memset(filter, 0, sizeof(ALfilter));
+ free(filter);
+
alDeleteFilters(cur, filters);
+ SET_ERROR_AND_GOTO(context, err, done);
+ }
+
+ filters[cur] = filter->id;
}
- al_endtry;
- ALCcontext_DecRef(Context);
+done:
+ ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
{
- ALCcontext *Context;
- ALfilter *Filter;
+ ALCdevice *device;
+ ALCcontext *context;
+ ALfilter *filter;
ALsizei i;
- Context = GetContextRef();
- if(!Context) return;
+ context = GetContextRef();
+ if(!context) return;
- al_try
- {
- ALCdevice *device = Context->Device;
- CHECK_VALUE(Context, n >= 0);
- for(i = 0;i < n;i++)
- {
- if(filters[i] && LookupFilter(device, filters[i]) == NULL)
- al_throwerr(Context, AL_INVALID_NAME);
- }
+ if(!(n >= 0))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
- for(i = 0;i < n;i++)
- {
- if((Filter=RemoveFilter(device, filters[i])) == NULL)
- continue;
- FreeThunkEntry(Filter->id);
+ device = context->Device;
+ for(i = 0;i < n;i++)
+ {
+ if(filters[i] && LookupFilter(device, filters[i]) == NULL)
+ SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+ }
+ for(i = 0;i < n;i++)
+ {
+ if((filter=RemoveFilter(device, filters[i])) == NULL)
+ continue;
+ FreeThunkEntry(filter->id);
- memset(Filter, 0, sizeof(*Filter));
- free(Filter);
- }
+ memset(filter, 0, sizeof(*filter));
+ free(filter);
}
- al_endtry;
- ALCcontext_DecRef(Context);
+done:
+ ALCcontext_DecRef(context);
}
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
@@ -326,48 +328,137 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
}
-ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
+void ALfilterState_clear(ALfilterState *filter)
{
- ALfloat a = 0.0f;
+ filter->x[0] = 0.0f;
+ filter->x[1] = 0.0f;
+ filter->y[0] = 0.0f;
+ filter->y[1] = 0.0f;
+}
- if(g < 0.9999f) /* 1-epsilon */
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth)
+{
+ ALfloat alpha;
+ ALfloat w0;
+
+ // Limit gain to -100dB
+ gain = maxf(gain, 0.00001f);
+
+ w0 = F_2PI * freq_scale;
+
+ /* Calculate filter coefficients depending on filter type */
+ switch(type)
{
- /* Be careful with gains < 0.001, as that causes the coefficient head
- * towards 1, which will flatten the signal */
- g = maxf(g, 0.001f);
- a = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
- (1 - g);
+ 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;
+
+ case ALfilterType_LowPass:
+ alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
+ filter->b[0] = (1.0f - cosf(w0)) / 2.0f;
+ filter->b[1] = 1.0f - cosf(w0);
+ filter->b[2] = (1.0f - cosf(w0)) / 2.0f;
+ filter->a[0] = 1.0f + alpha;
+ filter->a[1] = -2.0f * cosf(w0);
+ filter->a[2] = 1.0f - alpha;
+ break;
+ case ALfilterType_HighPass:
+ alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
+ filter->b[0] = (1.0f + cosf(w0)) / 2.0f;
+ filter->b[1] = 1.0f + cosf(w0);
+ filter->b[2] = (1.0f + cosf(w0)) / 2.0f;
+ filter->a[0] = 1.0f + alpha;
+ filter->a[1] = -2.0f * cosf(w0);
+ filter->a[2] = 1.0f - alpha;
+ break;
+ case ALfilterType_BandPass:
+ alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
+ filter->b[0] = alpha;
+ filter->b[1] = 0;
+ filter->b[2] = -alpha;
+ filter->a[0] = 1.0f + alpha;
+ filter->a[1] = -2.0f * cosf(w0);
+ filter->a[2] = 1.0f - alpha;
+ break;
}
- return a;
+ filter->b[2] /= filter->a[0];
+ filter->b[1] /= filter->a[0];
+ filter->b[0] /= filter->a[0];
+ filter->a[2] /= filter->a[0];
+ filter->a[1] /= filter->a[0];
+ filter->a[0] /= filter->a[0];
}
-static void lp_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
-{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
-static void lp_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
-{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
+static void lp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void lp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
{
switch(param)
{
case AL_LOWPASS_GAIN:
- if(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)
- filter->Gain = val;
- else
- alSetError(context, AL_INVALID_VALUE);
+ if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
+ SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+ filter->Gain = val;
break;
case AL_LOWPASS_GAINHF:
- if(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)
- filter->GainHF = val;
- else
- alSetError(context, AL_INVALID_VALUE);
+ if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF))
+ SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+ filter->GainHF = val;
break;
default:
- alSetError(context, AL_INVALID_ENUM);
- break;
+ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
}
}
static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
@@ -375,10 +466,10 @@ static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, c
lp_SetParamf(filter, context, param, vals[0]);
}
-static void lp_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
-{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
-static void lp_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
-{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
+static void lp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void lp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
{
switch(param)
@@ -392,8 +483,7 @@ static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL
break;
default:
- alSetError(context, AL_INVALID_ENUM);
- break;
+ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
}
}
static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
@@ -402,23 +492,23 @@ static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, A
}
-static void null_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
-{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
-static void null_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
-{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
-static void null_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
-{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
-static void null_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
-{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
-
-static void null_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
-{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
-static void null_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
-{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
-static void null_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
-{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
-static void null_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
-{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
+static void null_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void null_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void null_SetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void null_SetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALfloat *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+
+static void null_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void null_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void null_GetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void null_GetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
ALvoid ReleaseALFilters(ALCdevice *device)