Use RAII more with alFilter.cpp

This commit is contained in:
Chris Robinson 2018-11-24 09:40:13 -08:00
parent 48154c94d7
commit 505e535655

View File

@ -31,320 +31,16 @@
#include "alError.h"
namespace {
#define FILTER_MIN_GAIN 0.0f
#define FILTER_MAX_GAIN 4.0f /* +12dB */
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)
{
ALuint lidx = (id-1) >> 6;
ALsizei slidx = (id-1) & 0x3f;
if(UNLIKELY(lidx >= device->FilterList.size()))
return nullptr;
FilterSubList &sublist = device->FilterList[lidx];
if(UNLIKELY(sublist.FreeMask & (U64(1)<<slidx)))
return nullptr;
return sublist.Filters + slidx;
}
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
ALCcontext *context;
ALsizei cur = 0;
context = GetContextRef();
if(!context) return;
if(n < 0)
alSetError(context, AL_INVALID_VALUE, "Generating %d filters", n);
else for(cur = 0;cur < n;cur++)
{
ALfilter *filter = AllocFilter(context);
if(!filter)
{
alDeleteFilters(cur, filters);
break;
}
filters[cur] = filter->id;
}
ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
{
ALCdevice *device;
ALCcontext *context;
ALfilter *filter;
ALsizei i;
context = GetContextRef();
if(!context) return;
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)
SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid filter ID %u", filters[i]);
}
for(i = 0;i < n;i++)
{
if((filter=LookupFilter(device, filters[i])) != NULL)
FreeFilter(device, filter);
}
done:
UnlockFilterList(device);
ALCcontext_DecRef(context);
}
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
{
ALCcontext *Context;
ALboolean result;
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);
return result;
}
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
if(param == AL_FILTER_TYPE)
{
if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS ||
value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS)
InitFilterParams(ALFilter, value);
else
alSetError(Context, AL_INVALID_VALUE, "Invalid filter type 0x%04x", value);
}
else
{
/* Call the appropriate handler */
ALfilter_setParami(ALFilter, Context, param, value);
}
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
switch(param)
{
case AL_FILTER_TYPE:
alFilteri(filter, param, values[0]);
return;
}
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_setParamiv(ALFilter, Context, param, values);
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_setParamf(ALFilter, Context, param, value);
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_setParamfv(ALFilter, Context, param, values);
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
if(param == AL_FILTER_TYPE)
*value = ALFilter->type;
else
{
/* Call the appropriate handler */
ALfilter_getParami(ALFilter, Context, param, value);
}
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
switch(param)
{
case AL_FILTER_TYPE:
alGetFilteri(filter, param, values);
return;
}
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_getParamiv(ALFilter, Context, param, values);
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_getParamf(ALFilter, Context, param, value);
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_getParamfv(ALFilter, Context, param, values);
}
UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
static void ALlowpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
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))
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)
void ALlowpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
{
switch(param)
{
@ -364,14 +60,14 @@ static void ALlowpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum pa
alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param);
}
}
static void ALlowpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
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))
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))
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)
void ALlowpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
{
switch(param)
{
@ -387,17 +83,17 @@ static void ALlowpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum pa
alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param);
}
}
static void ALlowpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
void ALlowpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
{ ALlowpass_getParamf(filter, context, param, vals); }
DEFINE_ALFILTER_VTABLE(ALlowpass);
static void ALhighpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
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))
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)
void ALhighpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
{
switch(param)
{
@ -417,14 +113,14 @@ static void ALhighpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum p
alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param);
}
}
static void ALhighpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
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))
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))
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)
void ALhighpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
{
switch(param)
{
@ -440,17 +136,17 @@ static void ALhighpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum p
alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param);
}
}
static void ALhighpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
void ALhighpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
{ ALhighpass_getParamf(filter, context, param, vals); }
DEFINE_ALFILTER_VTABLE(ALhighpass);
static void ALbandpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
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))
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)
void ALbandpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
{
switch(param)
{
@ -476,14 +172,14 @@ static void ALbandpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum p
alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param);
}
}
static void ALbandpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
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))
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))
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)
void ALbandpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
{
switch(param)
{
@ -503,34 +199,75 @@ static void ALbandpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum p
alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param);
}
}
static void ALbandpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
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))
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))
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))
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))
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))
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))
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))
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))
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)
void InitFilterParams(ALfilter *filter, ALenum type)
{
if(type == AL_FILTER_LOWPASS)
{
filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = 1.0f;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALlowpass_vtable;
}
else if(type == AL_FILTER_HIGHPASS)
{
filter->Gain = AL_HIGHPASS_DEFAULT_GAIN;
filter->GainHF = 1.0f;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALhighpass_vtable;
}
else if(type == AL_FILTER_BANDPASS)
{
filter->Gain = AL_BANDPASS_DEFAULT_GAIN;
filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALbandpass_vtable;
}
else
{
filter->Gain = 1.0f;
filter->GainHF = 1.0f;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = 1.0f;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALnullfilter_vtable;
}
filter->type = type;
}
ALfilter *AllocFilter(ALCcontext *context)
{
ALCdevice *device = context->Device;
almtx_lock(&device->FilterLock);
@ -587,7 +324,7 @@ static ALfilter *AllocFilter(ALCcontext *context)
return filter;
}
static void FreeFilter(ALCdevice *device, ALfilter *filter)
void FreeFilter(ALCdevice *device, ALfilter *filter)
{
ALuint id = filter->id - 1;
ALsizei lidx = id >> 6;
@ -598,6 +335,293 @@ static void FreeFilter(ALCdevice *device, ALfilter *filter)
device->FilterList[lidx].FreeMask |= U64(1) << slidx;
}
inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
{
ALuint lidx = (id-1) >> 6;
ALsizei slidx = (id-1) & 0x3f;
if(UNLIKELY(lidx >= device->FilterList.size()))
return nullptr;
FilterSubList &sublist = device->FilterList[lidx];
if(UNLIKELY(sublist.FreeMask & (U64(1)<<slidx)))
return nullptr;
return sublist.Filters + slidx;
}
} // namespace
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
if(UNLIKELY(n < 0))
{
alSetError(context.get(), AL_INVALID_VALUE, "Generating %d filters", n);
return;
}
if(LIKELY(n == 1))
{
/* Special handling for the easy and normal case. */
ALfilter *filter = AllocFilter(context.get());
if(filter) filters[0] = filter->id;
}
else if(n > 1)
{
/* Store the allocated buffer IDs in a separate local list, to avoid
* modifying the user storage in case of failure.
*/
std::vector<ALuint> ids;
ids.reserve(n);
do {
ALfilter *filter = AllocFilter(context.get());
if(!filter)
{
alDeleteFilters(ids.size(), ids.data());
return;
}
ids.emplace_back(filter->id);
} while(--n);
std::copy(ids.begin(), ids.end(), filters);
}
}
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
if(UNLIKELY(n < 0))
{
alSetError(context.get(), AL_INVALID_VALUE, "Deleting %d filters", n);
return;
}
if(UNLIKELY(n == 0))
return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
/* First try to find any buffers that are invalid or in-use. */
const ALuint *filters_end = filters + n;
auto invflt = std::find_if(filters, filters_end,
[device, &context](ALuint fid) -> bool
{
if(!fid) return false;
ALfilter *filter{LookupFilter(device, fid)};
if(UNLIKELY(!filter))
{
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", fid);
return true;
}
return false;
}
);
if(LIKELY(invflt == filters_end))
{
/* All good. Delete non-0 buffer IDs. */
std::for_each(filters, filters_end,
[device](ALuint fid) -> void
{
ALfilter *filter{fid ? LookupFilter(device, fid) : nullptr};
if(filter) FreeFilter(device, filter);
}
);
}
}
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
{
ContextRef context{GetContextRef()};
if(LIKELY(context))
{
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
if(!filter || LookupFilter(device, filter))
return AL_TRUE;
}
return AL_FALSE;
}
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
if(param == AL_FILTER_TYPE)
{
if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS ||
value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS)
InitFilterParams(alfilt, value);
else
alSetError(context.get(), AL_INVALID_VALUE, "Invalid filter type 0x%04x", value);
}
else
{
/* Call the appropriate handler */
ALfilter_setParami(alfilt, context.get(), param, value);
}
}
}
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
{
switch(param)
{
case AL_FILTER_TYPE:
alFilteri(filter, param, values[0]);
return;
}
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_setParamiv(alfilt, context.get(), param, values);
}
}
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_setParamf(alfilt, context.get(), param, value);
}
}
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_setParamfv(alfilt, context.get(), param, values);
}
}
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
if(param == AL_FILTER_TYPE)
*value = alfilt->type;
else
{
/* Call the appropriate handler */
ALfilter_getParami(alfilt, context.get(), param, value);
}
}
}
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
{
switch(param)
{
case AL_FILTER_TYPE:
alGetFilteri(filter, param, values);
return;
}
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_getParamiv(alfilt, context.get(), param, values);
}
}
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_getParamf(alfilt, context.get(), param, value);
}
}
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
{
ContextRef context{GetContextRef()};
if(UNLIKELY(!context)) return;
ALCdevice *device{context->Device};
std::lock_guard<almtx_t> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(UNLIKELY(!alfilt))
alSetError(context.get(), AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
{
/* Call the appropriate handler */
ALfilter_getParamfv(alfilt, context.get(), param, values);
}
}
void ReleaseALFilters(ALCdevice *device)
{
size_t leftover = 0;
@ -619,45 +643,3 @@ void ReleaseALFilters(ALCdevice *device)
if(leftover > 0)
WARN("(%p) Deleted " SZFMT " Filter%s\n", device, leftover, (leftover==1)?"":"s");
}
static void InitFilterParams(ALfilter *filter, ALenum type)
{
if(type == AL_FILTER_LOWPASS)
{
filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = 1.0f;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALlowpass_vtable;
}
else if(type == AL_FILTER_HIGHPASS)
{
filter->Gain = AL_HIGHPASS_DEFAULT_GAIN;
filter->GainHF = 1.0f;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALhighpass_vtable;
}
else if(type == AL_FILTER_BANDPASS)
{
filter->Gain = AL_BANDPASS_DEFAULT_GAIN;
filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALbandpass_vtable;
}
else
{
filter->Gain = 1.0f;
filter->GainHF = 1.0f;
filter->HFReference = LOWPASSFREQREF;
filter->GainLF = 1.0f;
filter->LFReference = HIGHPASSFREQREF;
filter->vtab = &ALnullfilter_vtable;
}
filter->type = type;
}