diff options
author | Sven Gothel <[email protected]> | 2019-04-07 23:39:04 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2019-04-07 23:39:04 +0200 |
commit | 73233ce69919fc19c53ce8663c5b8cc05227f07e (patch) | |
tree | f2b6ccc1a14d7c387f33398a44ea4511d7ecb212 /OpenAL32/alFilter.c | |
parent | 8efa4c7ba5ee8eb399d31a9884e45f743d4625ad (diff) | |
parent | 99a55c445211fea77af6ab61cbc6a6ec4fbdc9b9 (diff) |
Merge branch 'v1.19' of git://repo.or.cz/openal-soft into v1.19v1.19
Diffstat (limited to 'OpenAL32/alFilter.c')
-rw-r--r-- | OpenAL32/alFilter.c | 542 |
1 files changed, 246 insertions, 296 deletions
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c index 3cf82c32..e57653e0 100644 --- a/OpenAL32/alFilter.c +++ b/OpenAL32/alFilter.c @@ -25,60 +25,56 @@ #include "alMain.h" #include "alu.h" #include "alFilter.h" -#include "alThunk.h" #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 calc_rcpQ_from_slope(ALfloat gain, ALfloat slope); -extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth); +#define FILTER_MIN_GAIN 0.0f +#define FILTER_MAX_GAIN 4.0f /* +12dB */ +extern inline void LockFilterList(ALCdevice *device); +extern inline void UnlockFilterList(ALCdevice *device); + +static ALfilter *AllocFilter(ALCcontext *context); +static void FreeFilter(ALCdevice *device, ALfilter *filter); static void InitFilterParams(ALfilter *filter, ALenum type); +static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) +{ + FilterSubList *sublist; + ALuint lidx = (id-1) >> 6; + ALsizei slidx = (id-1) & 0x3f; + + if(UNLIKELY(lidx >= VECTOR_SIZE(device->FilterList))) + return NULL; + sublist = &VECTOR_ELEM(device->FilterList, lidx); + if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx))) + return NULL; + return sublist->Filters + slidx; +} + AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) { - ALCdevice *device; ALCcontext *context; ALsizei cur = 0; - ALenum err; context = GetContextRef(); if(!context) return; if(!(n >= 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - device = context->Device; - for(cur = 0;cur < n;cur++) + alSetError(context, AL_INVALID_VALUE, "Generating %d filters", n); + else for(cur = 0;cur < n;cur++) { - ALfilter *filter = calloc(1, sizeof(ALfilter)); + ALfilter *filter = AllocFilter(context); if(!filter) { alDeleteFilters(cur, filters); - SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); - } - 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); + break; } filters[cur] = filter->id; } -done: ALCcontext_DecRef(context); } @@ -92,26 +88,23 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters) context = GetContextRef(); if(!context) return; - if(!(n >= 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - device = context->Device; + LockFilterList(device); + if(!(n >= 0)) + SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d filters", n); for(i = 0;i < n;i++) { if(filters[i] && LookupFilter(device, filters[i]) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid filter ID %u", filters[i]); } for(i = 0;i < n;i++) { - if((filter=RemoveFilter(device, filters[i])) == NULL) - continue; - FreeThunkEntry(filter->id); - - memset(filter, 0, sizeof(*filter)); - free(filter); + if((filter=LookupFilter(device, filters[i])) != NULL) + FreeFilter(device, filter); } done: + UnlockFilterList(device); ALCcontext_DecRef(context); } @@ -123,8 +116,10 @@ AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) Context = GetContextRef(); if(!Context) return AL_FALSE; + LockFilterList(Context->Device); result = ((!filter || LookupFilter(Context->Device, filter)) ? AL_TRUE : AL_FALSE); + UnlockFilterList(Context->Device); ALCcontext_DecRef(Context); @@ -141,8 +136,9 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value) if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { if(param == AL_FILTER_TYPE) @@ -151,14 +147,15 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value) value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS) InitFilterParams(ALFilter, value); else - alSetError(Context, AL_INVALID_VALUE); + alSetError(Context, AL_INVALID_VALUE, "Invalid filter type 0x%04x", value); } else { /* Call the appropriate handler */ - ALfilter_SetParami(ALFilter, Context, param, value); + ALfilter_setParami(ALFilter, Context, param, value); } } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -180,13 +177,15 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *v if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { /* Call the appropriate handler */ - ALfilter_SetParamiv(ALFilter, Context, param, values); + ALfilter_setParamiv(ALFilter, Context, param, values); } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -201,13 +200,15 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value) if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { /* Call the appropriate handler */ - ALfilter_SetParamf(ALFilter, Context, param, value); + ALfilter_setParamf(ALFilter, Context, param, value); } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -222,13 +223,15 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { /* Call the appropriate handler */ - ALfilter_SetParamfv(ALFilter, Context, param, values); + ALfilter_setParamfv(ALFilter, Context, param, values); } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -243,8 +246,9 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { if(param == AL_FILTER_TYPE) @@ -252,9 +256,10 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value else { /* Call the appropriate handler */ - ALfilter_GetParami(ALFilter, Context, param, value); + ALfilter_getParami(ALFilter, Context, param, value); } } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -276,13 +281,15 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *valu if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { /* Call the appropriate handler */ - ALfilter_GetParamiv(ALFilter, Context, param, values); + ALfilter_getParamiv(ALFilter, Context, param, values); } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -297,13 +304,15 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *val if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { /* Call the appropriate handler */ - ALfilter_GetParamf(ALFilter, Context, param, value); + ALfilter_getParamf(ALFilter, Context, param, value); } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } @@ -318,159 +327,52 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va if(!Context) return; Device = Context->Device; + LockFilterList(Device); if((ALFilter=LookupFilter(Device, filter)) == NULL) - alSetError(Context, AL_INVALID_NAME); + alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter); else { /* Call the appropriate handler */ - ALfilter_GetParamfv(ALFilter, Context, param, values); + ALfilter_getParamfv(ALFilter, Context, param, values); } + UnlockFilterList(Device); ALCcontext_DecRef(Context); } -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_mult, ALfloat rcpQ) -{ - ALfloat alpha, sqrtgain_alpha_2; - ALfloat w0, sin_w0, cos_w0; - - // Limit gain to -100dB - gain = maxf(gain, 0.00001f); - - w0 = F_TAU * freq_mult; - sin_w0 = sinf(w0); - cos_w0 = cosf(w0); - alpha = sin_w0/2.0f * rcpQ; - - /* Calculate filter coefficients depending on filter type */ - switch(type) - { - case ALfilterType_HighShelf: - sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha; - filter->b[0] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2); - filter->b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0 ); - filter->b[2] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2); - filter->a[0] = (gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2; - filter->a[1] = 2.0f* ((gain-1.0f) - (gain+1.0f)*cos_w0 ); - filter->a[2] = (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2; - break; - case ALfilterType_LowShelf: - sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha; - filter->b[0] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2); - filter->b[1] = 2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0 ); - filter->b[2] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2); - filter->a[0] = (gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2; - filter->a[1] = -2.0f* ((gain-1.0f) + (gain+1.0f)*cos_w0 ); - filter->a[2] = (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2; - break; - case ALfilterType_Peaking: - gain = sqrtf(gain); - filter->b[0] = 1.0f + alpha * gain; - filter->b[1] = -2.0f * cos_w0; - filter->b[2] = 1.0f - alpha * gain; - filter->a[0] = 1.0f + alpha / gain; - filter->a[1] = -2.0f * cos_w0; - filter->a[2] = 1.0f - alpha / gain; - break; - - case ALfilterType_LowPass: - filter->b[0] = (1.0f - cos_w0) / 2.0f; - filter->b[1] = 1.0f - cos_w0; - filter->b[2] = (1.0f - cos_w0) / 2.0f; - filter->a[0] = 1.0f + alpha; - filter->a[1] = -2.0f * cos_w0; - filter->a[2] = 1.0f - alpha; - break; - case ALfilterType_HighPass: - filter->b[0] = (1.0f + cos_w0) / 2.0f; - filter->b[1] = -(1.0f + cos_w0); - filter->b[2] = (1.0f + cos_w0) / 2.0f; - filter->a[0] = 1.0f + alpha; - filter->a[1] = -2.0f * cos_w0; - filter->a[2] = 1.0f - alpha; - break; - case ALfilterType_BandPass: - filter->b[0] = alpha; - filter->b[1] = 0; - filter->b[2] = -alpha; - filter->a[0] = 1.0f + alpha; - filter->a[1] = -2.0f * cos_w0; - filter->a[2] = 1.0f - alpha; - break; - } - - 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]; - - filter->process = ALfilterState_processC; -} - -void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *src, ALuint numsamples) -{ - if(numsamples >= 2) - { - filter->x[1] = src[numsamples-2]; - filter->x[0] = src[numsamples-1]; - filter->y[1] = src[numsamples-2]; - filter->y[0] = src[numsamples-1]; - } - else if(numsamples == 1) - { - filter->x[1] = filter->x[0]; - filter->x[0] = src[0]; - filter->y[1] = filter->y[0]; - filter->y[0] = src[0]; - } -} - - -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) +static void ALlowpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param); } +static void ALlowpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x", param); } +static void ALlowpass_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)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + if(!(val >= FILTER_MIN_GAIN && val <= FILTER_MAX_GAIN)) + SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gain %f out of range", val); filter->Gain = val; break; case AL_LOWPASS_GAINHF: if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gainhf %f out of range", val); filter->GainHF = val; break; default: - SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param); } } -static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) -{ - lp_SetParamf(filter, context, param, vals[0]); -} - -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) +static void ALlowpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ ALlowpass_setParamf(filter, context, param, vals[0]); } + +static void ALlowpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param); } +static void ALlowpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x", param); } +static void ALlowpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) { switch(param) { @@ -483,49 +385,47 @@ static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL break; default: - SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param); } } -static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) -{ - lp_GetParamf(filter, context, param, vals); -} +static void ALlowpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ ALlowpass_getParamf(filter, context, param, vals); } +DEFINE_ALFILTER_VTABLE(ALlowpass); -static void hp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void hp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void hp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) + +static void ALhighpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param); } +static void ALhighpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x", param); } +static void ALhighpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) { switch(param) { case AL_HIGHPASS_GAIN: - if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + if(!(val >= FILTER_MIN_GAIN && val <= FILTER_MAX_GAIN)) + SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gain out of range"); filter->Gain = val; break; case AL_HIGHPASS_GAINLF: if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gainlf out of range"); filter->GainLF = val; break; default: - SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param); } } -static void hp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) -{ - hp_SetParamf(filter, context, param, vals[0]); -} - -static void hp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void hp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +static void ALhighpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ ALhighpass_setParamf(filter, context, param, vals[0]); } + +static void ALhighpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param); } +static void ALhighpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x", param); } +static void ALhighpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) { switch(param) { @@ -538,55 +438,53 @@ static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL break; default: - SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param); } } -static void hp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) -{ - hp_GetParamf(filter, context, param, vals); -} +static void ALhighpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ ALhighpass_getParamf(filter, context, param, vals); } +DEFINE_ALFILTER_VTABLE(ALhighpass); -static void bp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void bp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void bp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) + +static void ALbandpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param); } +static void ALbandpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x", param); } +static void ALbandpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) { switch(param) { case AL_BANDPASS_GAIN: - if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + if(!(val >= FILTER_MIN_GAIN && val <= FILTER_MAX_GAIN)) + SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gain out of range"); filter->Gain = val; break; case AL_BANDPASS_GAINHF: if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gainhf out of range"); filter->GainHF = val; break; case AL_BANDPASS_GAINLF: if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF)) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gainlf out of range"); filter->GainLF = val; break; default: - SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param); } } -static void bp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) -{ - bp_SetParamf(filter, context, param, vals[0]); -} - -static void bp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void bp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) -{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } -static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +static void ALbandpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ ALbandpass_setParamf(filter, context, param, vals[0]); } + +static void ALbandpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param); } +static void ALbandpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x", param); } +static void ALbandpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) { switch(param) { @@ -603,47 +501,131 @@ static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL break; default: - SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param); } } -static void bp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +static void ALbandpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ ALbandpass_getParamf(filter, context, param, vals); } + +DEFINE_ALFILTER_VTABLE(ALbandpass); + + +static void ALnullfilter_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } +static void ALnullfilter_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } +static void ALnullfilter_setParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } +static void ALnullfilter_setParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALfloat *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } + +static void ALnullfilter_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } +static void ALnullfilter_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } +static void ALnullfilter_getParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat *UNUSED(val)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } +static void ALnullfilter_getParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat *UNUSED(vals)) +{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); } + +DEFINE_ALFILTER_VTABLE(ALnullfilter); + + +static ALfilter *AllocFilter(ALCcontext *context) { - bp_GetParamf(filter, context, param, vals); -} + ALCdevice *device = context->Device; + FilterSubList *sublist, *subend; + ALfilter *filter = NULL; + ALsizei lidx = 0; + ALsizei slidx; + + almtx_lock(&device->FilterLock); + sublist = VECTOR_BEGIN(device->FilterList); + subend = VECTOR_END(device->FilterList); + for(;sublist != subend;++sublist) + { + if(sublist->FreeMask) + { + slidx = CTZ64(sublist->FreeMask); + filter = sublist->Filters + slidx; + break; + } + ++lidx; + } + if(UNLIKELY(!filter)) + { + const FilterSubList empty_sublist = { 0, NULL }; + /* Don't allocate so many list entries that the 32-bit ID could + * overflow... + */ + if(UNLIKELY(VECTOR_SIZE(device->FilterList) >= 1<<25)) + { + almtx_unlock(&device->FilterLock); + alSetError(context, AL_OUT_OF_MEMORY, "Too many filters allocated"); + return NULL; + } + lidx = (ALsizei)VECTOR_SIZE(device->FilterList); + VECTOR_PUSH_BACK(device->FilterList, empty_sublist); + sublist = &VECTOR_BACK(device->FilterList); + sublist->FreeMask = ~U64(0); + sublist->Filters = al_calloc(16, sizeof(ALfilter)*64); + if(UNLIKELY(!sublist->Filters)) + { + VECTOR_POP_BACK(device->FilterList); + almtx_unlock(&device->FilterLock); + alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate filter batch"); + return NULL; + } + + slidx = 0; + filter = sublist->Filters + slidx; + } + memset(filter, 0, sizeof(*filter)); + InitFilterParams(filter, AL_FILTER_NULL); -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); } + /* Add 1 to avoid filter ID 0. */ + filter->id = ((lidx<<6) | slidx) + 1; -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); } + sublist->FreeMask &= ~(U64(1)<<slidx); + almtx_unlock(&device->FilterLock); + return filter; +} -ALvoid ReleaseALFilters(ALCdevice *device) +static void FreeFilter(ALCdevice *device, ALfilter *filter) { - ALsizei i; - for(i = 0;i < device->FilterMap.size;i++) + ALuint id = filter->id - 1; + ALsizei lidx = id >> 6; + ALsizei slidx = id & 0x3f; + + memset(filter, 0, sizeof(*filter)); + + VECTOR_ELEM(device->FilterList, lidx).FreeMask |= U64(1) << slidx; +} + +void ReleaseALFilters(ALCdevice *device) +{ + FilterSubList *sublist = VECTOR_BEGIN(device->FilterList); + FilterSubList *subend = VECTOR_END(device->FilterList); + size_t leftover = 0; + for(;sublist != subend;++sublist) { - ALfilter *temp = device->FilterMap.array[i].value; - device->FilterMap.array[i].value = NULL; + ALuint64 usemask = ~sublist->FreeMask; + while(usemask) + { + ALsizei idx = CTZ64(usemask); + ALfilter *filter = sublist->Filters + idx; + + memset(filter, 0, sizeof(*filter)); + ++leftover; - // Release filter structure - FreeThunkEntry(temp->id); - memset(temp, 0, sizeof(ALfilter)); - free(temp); + usemask &= ~(U64(1) << idx); + } + sublist->FreeMask = ~usemask; } + if(leftover > 0) + WARN("(%p) Deleted "SZFMT" Filter%s\n", device, leftover, (leftover==1)?"":"s"); } @@ -656,15 +638,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type) filter->HFReference = LOWPASSFREQREF; filter->GainLF = 1.0f; filter->LFReference = HIGHPASSFREQREF; - - filter->SetParami = lp_SetParami; - filter->SetParamiv = lp_SetParamiv; - filter->SetParamf = lp_SetParamf; - filter->SetParamfv = lp_SetParamfv; - filter->GetParami = lp_GetParami; - filter->GetParamiv = lp_GetParamiv; - filter->GetParamf = lp_GetParamf; - filter->GetParamfv = lp_GetParamfv; + filter->vtab = &ALlowpass_vtable; } else if(type == AL_FILTER_HIGHPASS) { @@ -673,15 +647,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type) filter->HFReference = LOWPASSFREQREF; filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF; filter->LFReference = HIGHPASSFREQREF; - - filter->SetParami = hp_SetParami; - filter->SetParamiv = hp_SetParamiv; - filter->SetParamf = hp_SetParamf; - filter->SetParamfv = hp_SetParamfv; - filter->GetParami = hp_GetParami; - filter->GetParamiv = hp_GetParamiv; - filter->GetParamf = hp_GetParamf; - filter->GetParamfv = hp_GetParamfv; + filter->vtab = &ALhighpass_vtable; } else if(type == AL_FILTER_BANDPASS) { @@ -690,15 +656,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type) filter->HFReference = LOWPASSFREQREF; filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF; filter->LFReference = HIGHPASSFREQREF; - - filter->SetParami = bp_SetParami; - filter->SetParamiv = bp_SetParamiv; - filter->SetParamf = bp_SetParamf; - filter->SetParamfv = bp_SetParamfv; - filter->GetParami = bp_GetParami; - filter->GetParamiv = bp_GetParamiv; - filter->GetParamf = bp_GetParamf; - filter->GetParamfv = bp_GetParamfv; + filter->vtab = &ALbandpass_vtable; } else { @@ -707,15 +665,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type) filter->HFReference = LOWPASSFREQREF; filter->GainLF = 1.0f; filter->LFReference = HIGHPASSFREQREF; - - filter->SetParami = null_SetParami; - filter->SetParamiv = null_SetParamiv; - filter->SetParamf = null_SetParamf; - filter->SetParamfv = null_SetParamfv; - filter->GetParami = null_GetParami; - filter->GetParamiv = null_GetParamiv; - filter->GetParamf = null_GetParamf; - filter->GetParamfv = null_GetParamfv; + filter->vtab = &ALnullfilter_vtable; } filter->type = type; } |