diff options
Diffstat (limited to 'OpenAL32/alFilter.c')
-rw-r--r-- | OpenAL32/alFilter.c | 296 |
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) |