|
@@ -29,8 +29,10 @@
|
|
|
#include <iterator>
|
|
|
#include <memory>
|
|
|
#include <mutex>
|
|
|
-#include <new>
|
|
|
#include <numeric>
|
|
|
+#include <string>
|
|
|
+#include <unordered_map>
|
|
|
+#include <vector>
|
|
|
|
|
|
#include "AL/al.h"
|
|
|
#include "AL/alc.h"
|
|
@@ -39,252 +41,19 @@
|
|
|
#include "albit.h"
|
|
|
#include "alc/context.h"
|
|
|
#include "alc/device.h"
|
|
|
+#include "alc/inprogext.h"
|
|
|
#include "almalloc.h"
|
|
|
#include "alnumeric.h"
|
|
|
-#include "core/except.h"
|
|
|
+#include "alspan.h"
|
|
|
+#include "direct_defs.h"
|
|
|
+#include "error.h"
|
|
|
+#include "intrusive_ptr.h"
|
|
|
#include "opthelpers.h"
|
|
|
-#include "vector.h"
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
-class filter_exception final : public al::base_exception {
|
|
|
- ALenum mErrorCode;
|
|
|
-
|
|
|
-public:
|
|
|
-#ifdef __USE_MINGW_ANSI_STDIO
|
|
|
- [[gnu::format(gnu_printf, 3, 4)]]
|
|
|
-#else
|
|
|
- [[gnu::format(printf, 3, 4)]]
|
|
|
-#endif
|
|
|
- filter_exception(ALenum code, const char *msg, ...);
|
|
|
- ~filter_exception() override;
|
|
|
-
|
|
|
- ALenum errorCode() const noexcept { return mErrorCode; }
|
|
|
-};
|
|
|
-
|
|
|
-filter_exception::filter_exception(ALenum code, const char* msg, ...) : mErrorCode{code}
|
|
|
-{
|
|
|
- std::va_list args;
|
|
|
- va_start(args, msg);
|
|
|
- setMessage(msg, args);
|
|
|
- va_end(args);
|
|
|
-}
|
|
|
-filter_exception::~filter_exception() = default;
|
|
|
-
|
|
|
-
|
|
|
-#define DEFINE_ALFILTER_VTABLE(T) \
|
|
|
-const ALfilter::Vtable T##_vtable = { \
|
|
|
- T##_setParami, T##_setParamiv, T##_setParamf, T##_setParamfv, \
|
|
|
- T##_getParami, T##_getParamiv, T##_getParamf, T##_getParamfv, \
|
|
|
-}
|
|
|
-
|
|
|
-void ALlowpass_setParami(ALfilter*, ALenum param, int)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; }
|
|
|
-void ALlowpass_setParamiv(ALfilter*, ALenum param, const int*)
|
|
|
-{
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x",
|
|
|
- param};
|
|
|
-}
|
|
|
-void ALlowpass_setParamf(ALfilter *filter, ALenum param, float val)
|
|
|
-{
|
|
|
- switch(param)
|
|
|
- {
|
|
|
- case AL_LOWPASS_GAIN:
|
|
|
- if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
|
|
|
- throw filter_exception{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))
|
|
|
- throw filter_exception{AL_INVALID_VALUE, "Low-pass gainhf %f out of range", val};
|
|
|
- filter->GainHF = val;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param};
|
|
|
- }
|
|
|
-}
|
|
|
-void ALlowpass_setParamfv(ALfilter *filter, ALenum param, const float *vals)
|
|
|
-{ ALlowpass_setParamf(filter, param, vals[0]); }
|
|
|
-
|
|
|
-void ALlowpass_getParami(const ALfilter*, ALenum param, int*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; }
|
|
|
-void ALlowpass_getParamiv(const ALfilter*, ALenum param, int*)
|
|
|
-{
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x",
|
|
|
- param};
|
|
|
-}
|
|
|
-void ALlowpass_getParamf(const ALfilter *filter, ALenum param, float *val)
|
|
|
-{
|
|
|
- switch(param)
|
|
|
- {
|
|
|
- case AL_LOWPASS_GAIN:
|
|
|
- *val = filter->Gain;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_LOWPASS_GAINHF:
|
|
|
- *val = filter->GainHF;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param};
|
|
|
- }
|
|
|
-}
|
|
|
-void ALlowpass_getParamfv(const ALfilter *filter, ALenum param, float *vals)
|
|
|
-{ ALlowpass_getParamf(filter, param, vals); }
|
|
|
-
|
|
|
-DEFINE_ALFILTER_VTABLE(ALlowpass);
|
|
|
-
|
|
|
-
|
|
|
-void ALhighpass_setParami(ALfilter*, ALenum param, int)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; }
|
|
|
-void ALhighpass_setParamiv(ALfilter*, ALenum param, const int*)
|
|
|
-{
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x",
|
|
|
- param};
|
|
|
-}
|
|
|
-void ALhighpass_setParamf(ALfilter *filter, ALenum param, float val)
|
|
|
-{
|
|
|
- switch(param)
|
|
|
- {
|
|
|
- case AL_HIGHPASS_GAIN:
|
|
|
- if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
|
|
|
- throw filter_exception{AL_INVALID_VALUE, "High-pass gain %f out of range", val};
|
|
|
- filter->Gain = val;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_HIGHPASS_GAINLF:
|
|
|
- if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF))
|
|
|
- throw filter_exception{AL_INVALID_VALUE, "High-pass gainlf %f out of range", val};
|
|
|
- filter->GainLF = val;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param};
|
|
|
- }
|
|
|
-}
|
|
|
-void ALhighpass_setParamfv(ALfilter *filter, ALenum param, const float *vals)
|
|
|
-{ ALhighpass_setParamf(filter, param, vals[0]); }
|
|
|
-
|
|
|
-void ALhighpass_getParami(const ALfilter*, ALenum param, int*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; }
|
|
|
-void ALhighpass_getParamiv(const ALfilter*, ALenum param, int*)
|
|
|
-{
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x",
|
|
|
- param};
|
|
|
-}
|
|
|
-void ALhighpass_getParamf(const ALfilter *filter, ALenum param, float *val)
|
|
|
-{
|
|
|
- switch(param)
|
|
|
- {
|
|
|
- case AL_HIGHPASS_GAIN:
|
|
|
- *val = filter->Gain;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_HIGHPASS_GAINLF:
|
|
|
- *val = filter->GainLF;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param};
|
|
|
- }
|
|
|
-}
|
|
|
-void ALhighpass_getParamfv(const ALfilter *filter, ALenum param, float *vals)
|
|
|
-{ ALhighpass_getParamf(filter, param, vals); }
|
|
|
-
|
|
|
-DEFINE_ALFILTER_VTABLE(ALhighpass);
|
|
|
-
|
|
|
-
|
|
|
-void ALbandpass_setParami(ALfilter*, ALenum param, int)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; }
|
|
|
-void ALbandpass_setParamiv(ALfilter*, ALenum param, const int*)
|
|
|
-{
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x",
|
|
|
- param};
|
|
|
-}
|
|
|
-void ALbandpass_setParamf(ALfilter *filter, ALenum param, float val)
|
|
|
-{
|
|
|
- switch(param)
|
|
|
- {
|
|
|
- case AL_BANDPASS_GAIN:
|
|
|
- if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
|
|
|
- throw filter_exception{AL_INVALID_VALUE, "Band-pass gain %f out of range", val};
|
|
|
- filter->Gain = val;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_BANDPASS_GAINHF:
|
|
|
- if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF))
|
|
|
- throw filter_exception{AL_INVALID_VALUE, "Band-pass gainhf %f out of range", val};
|
|
|
- filter->GainHF = val;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_BANDPASS_GAINLF:
|
|
|
- if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF))
|
|
|
- throw filter_exception{AL_INVALID_VALUE, "Band-pass gainlf %f out of range", val};
|
|
|
- filter->GainLF = val;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param};
|
|
|
- }
|
|
|
-}
|
|
|
-void ALbandpass_setParamfv(ALfilter *filter, ALenum param, const float *vals)
|
|
|
-{ ALbandpass_setParamf(filter, param, vals[0]); }
|
|
|
-
|
|
|
-void ALbandpass_getParami(const ALfilter*, ALenum param, int*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; }
|
|
|
-void ALbandpass_getParamiv(const ALfilter*, ALenum param, int*)
|
|
|
-{
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x",
|
|
|
- param};
|
|
|
-}
|
|
|
-void ALbandpass_getParamf(const ALfilter *filter, ALenum param, float *val)
|
|
|
-{
|
|
|
- switch(param)
|
|
|
- {
|
|
|
- case AL_BANDPASS_GAIN:
|
|
|
- *val = filter->Gain;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_BANDPASS_GAINHF:
|
|
|
- *val = filter->GainHF;
|
|
|
- break;
|
|
|
-
|
|
|
- case AL_BANDPASS_GAINLF:
|
|
|
- *val = filter->GainLF;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param};
|
|
|
- }
|
|
|
-}
|
|
|
-void ALbandpass_getParamfv(const ALfilter *filter, ALenum param, float *vals)
|
|
|
-{ ALbandpass_getParamf(filter, param, vals); }
|
|
|
-
|
|
|
-DEFINE_ALFILTER_VTABLE(ALbandpass);
|
|
|
-
|
|
|
-
|
|
|
-void ALnullfilter_setParami(ALfilter*, ALenum param, int)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-void ALnullfilter_setParamiv(ALfilter*, ALenum param, const int*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-void ALnullfilter_setParamf(ALfilter*, ALenum param, float)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-void ALnullfilter_setParamfv(ALfilter*, ALenum param, const float*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-
|
|
|
-void ALnullfilter_getParami(const ALfilter*, ALenum param, int*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-void ALnullfilter_getParamiv(const ALfilter*, ALenum param, int*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-void ALnullfilter_getParamf(const ALfilter*, ALenum param, float*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-void ALnullfilter_getParamfv(const ALfilter*, ALenum param, float*)
|
|
|
-{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
-
|
|
|
-DEFINE_ALFILTER_VTABLE(ALnullfilter);
|
|
|
+using SubListAllocator = al::allocator<std::array<ALfilter,64>>;
|
|
|
|
|
|
|
|
|
void InitFilterParams(ALfilter *filter, ALenum type)
|
|
@@ -293,44 +62,44 @@ void InitFilterParams(ALfilter *filter, ALenum type)
|
|
|
{
|
|
|
filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
|
|
|
filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
|
|
|
- filter->HFReference = LOWPASSFREQREF;
|
|
|
+ filter->HFReference = LowPassFreqRef;
|
|
|
filter->GainLF = 1.0f;
|
|
|
- filter->LFReference = HIGHPASSFREQREF;
|
|
|
- filter->vtab = &ALlowpass_vtable;
|
|
|
+ filter->LFReference = HighPassFreqRef;
|
|
|
+ filter->mTypeVariant.emplace<LowpassFilterTable>();
|
|
|
}
|
|
|
else if(type == AL_FILTER_HIGHPASS)
|
|
|
{
|
|
|
filter->Gain = AL_HIGHPASS_DEFAULT_GAIN;
|
|
|
filter->GainHF = 1.0f;
|
|
|
- filter->HFReference = LOWPASSFREQREF;
|
|
|
+ filter->HFReference = LowPassFreqRef;
|
|
|
filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF;
|
|
|
- filter->LFReference = HIGHPASSFREQREF;
|
|
|
- filter->vtab = &ALhighpass_vtable;
|
|
|
+ filter->LFReference = HighPassFreqRef;
|
|
|
+ filter->mTypeVariant.emplace<HighpassFilterTable>();
|
|
|
}
|
|
|
else if(type == AL_FILTER_BANDPASS)
|
|
|
{
|
|
|
filter->Gain = AL_BANDPASS_DEFAULT_GAIN;
|
|
|
filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF;
|
|
|
- filter->HFReference = LOWPASSFREQREF;
|
|
|
+ filter->HFReference = LowPassFreqRef;
|
|
|
filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
|
|
|
- filter->LFReference = HIGHPASSFREQREF;
|
|
|
- filter->vtab = &ALbandpass_vtable;
|
|
|
+ filter->LFReference = HighPassFreqRef;
|
|
|
+ filter->mTypeVariant.emplace<BandpassFilterTable>();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
filter->Gain = 1.0f;
|
|
|
filter->GainHF = 1.0f;
|
|
|
- filter->HFReference = LOWPASSFREQREF;
|
|
|
+ filter->HFReference = LowPassFreqRef;
|
|
|
filter->GainLF = 1.0f;
|
|
|
- filter->LFReference = HIGHPASSFREQREF;
|
|
|
- filter->vtab = &ALnullfilter_vtable;
|
|
|
+ filter->LFReference = HighPassFreqRef;
|
|
|
+ filter->mTypeVariant.emplace<NullFilterTable>();
|
|
|
}
|
|
|
filter->type = type;
|
|
|
}
|
|
|
|
|
|
-bool EnsureFilters(ALCdevice *device, size_t needed)
|
|
|
-{
|
|
|
- size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), size_t{0},
|
|
|
+auto EnsureFilters(ALCdevice *device, size_t needed) noexcept -> bool
|
|
|
+try {
|
|
|
+ size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), 0_uz,
|
|
|
[](size_t cur, const FilterSubList &sublist) noexcept -> size_t
|
|
|
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
|
|
|
|
|
@@ -339,22 +108,20 @@ bool EnsureFilters(ALCdevice *device, size_t needed)
|
|
|
if(device->FilterList.size() >= 1<<25) UNLIKELY
|
|
|
return false;
|
|
|
|
|
|
- device->FilterList.emplace_back();
|
|
|
- auto sublist = device->FilterList.end() - 1;
|
|
|
- sublist->FreeMask = ~0_u64;
|
|
|
- sublist->Filters = static_cast<ALfilter*>(al_calloc(alignof(ALfilter), sizeof(ALfilter)*64));
|
|
|
- if(!sublist->Filters) UNLIKELY
|
|
|
- {
|
|
|
- device->FilterList.pop_back();
|
|
|
- return false;
|
|
|
- }
|
|
|
- count += 64;
|
|
|
+ FilterSubList sublist{};
|
|
|
+ sublist.FreeMask = ~0_u64;
|
|
|
+ sublist.Filters = SubListAllocator{}.allocate(1);
|
|
|
+ device->FilterList.emplace_back(std::move(sublist));
|
|
|
+ count += std::tuple_size_v<SubListAllocator::value_type>;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
+catch(...) {
|
|
|
+ return false;
|
|
|
+}
|
|
|
|
|
|
|
|
|
-ALfilter *AllocFilter(ALCdevice *device)
|
|
|
+ALfilter *AllocFilter(ALCdevice *device) noexcept
|
|
|
{
|
|
|
auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(),
|
|
|
[](const FilterSubList &entry) noexcept -> bool
|
|
@@ -363,7 +130,7 @@ ALfilter *AllocFilter(ALCdevice *device)
|
|
|
auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask));
|
|
|
ASSUME(slidx < 64);
|
|
|
|
|
|
- ALfilter *filter{al::construct_at(sublist->Filters + slidx)};
|
|
|
+ ALfilter *filter{al::construct_at(al::to_address(sublist->Filters->begin() + slidx))};
|
|
|
InitFilterParams(filter, AL_FILTER_NULL);
|
|
|
|
|
|
/* Add 1 to avoid filter ID 0. */
|
|
@@ -376,17 +143,19 @@ ALfilter *AllocFilter(ALCdevice *device)
|
|
|
|
|
|
void FreeFilter(ALCdevice *device, ALfilter *filter)
|
|
|
{
|
|
|
+ device->mFilterNames.erase(filter->id);
|
|
|
+
|
|
|
const ALuint id{filter->id - 1};
|
|
|
const size_t lidx{id >> 6};
|
|
|
const ALuint slidx{id & 0x3f};
|
|
|
|
|
|
- al::destroy_at(filter);
|
|
|
+ std::destroy_at(filter);
|
|
|
|
|
|
device->FilterList[lidx].FreeMask |= 1_u64 << slidx;
|
|
|
}
|
|
|
|
|
|
|
|
|
-inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
|
|
|
+auto LookupFilter(ALCdevice *device, ALuint id) noexcept -> ALfilter*
|
|
|
{
|
|
|
const size_t lidx{(id-1) >> 6};
|
|
|
const ALuint slidx{(id-1) & 0x3f};
|
|
@@ -396,327 +165,466 @@ inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
|
|
|
FilterSubList &sublist = device->FilterList[lidx];
|
|
|
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
|
|
|
return nullptr;
|
|
|
- return sublist.Filters + slidx;
|
|
|
+ return al::to_address(sublist.Filters->begin() + slidx);
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
-AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
|
|
|
-START_API_FUNC
|
|
|
+/* Null filter parameter handlers */
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::setParami(ALfilter*, ALenum param, int)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::setParamiv(ALfilter*, ALenum param, const int*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::setParamf(ALfilter*, ALenum param, float)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::setParamfv(ALfilter*, ALenum param, const float*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::getParami(const ALfilter*, ALenum param, int*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::getParamiv(const ALfilter*, ALenum param, int*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::getParamf(const ALfilter*, ALenum param, float*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<NullFilterTable>::getParamfv(const ALfilter*, ALenum param, float*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
|
|
|
+
|
|
|
+/* Lowpass parameter handlers */
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::setParami(ALfilter*, ALenum param, int)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
|
|
|
+{ setParami(filter, param, *values); }
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
|
|
|
{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
-
|
|
|
- if(n < 0) UNLIKELY
|
|
|
- context->setError(AL_INVALID_VALUE, "Generating %d filters", n);
|
|
|
- if(n <= 0) UNLIKELY return;
|
|
|
-
|
|
|
- ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
- if(!EnsureFilters(device, static_cast<ALuint>(n)))
|
|
|
+ switch(param)
|
|
|
{
|
|
|
- context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d filter%s", n, (n==1)?"":"s");
|
|
|
+ case AL_LOWPASS_GAIN:
|
|
|
+ if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Low-pass gain %f out of range", val};
|
|
|
+ filter->Gain = val;
|
|
|
return;
|
|
|
- }
|
|
|
|
|
|
- if(n == 1) LIKELY
|
|
|
+ case AL_LOWPASS_GAINHF:
|
|
|
+ if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Low-pass gainhf %f out of range", val};
|
|
|
+ filter->GainHF = val;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param};
|
|
|
+}
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
|
|
|
+{ setParamf(filter, param, *vals); }
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::getParami(const ALfilter*, ALenum param, int*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::getParamiv(const ALfilter *filter, ALenum param, int *values)
|
|
|
+{ getParami(filter, param, values); }
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::getParamf(const ALfilter *filter, ALenum param, float *val)
|
|
|
+{
|
|
|
+ switch(param)
|
|
|
{
|
|
|
- /* Special handling for the easy and normal case. */
|
|
|
- ALfilter *filter{AllocFilter(device)};
|
|
|
- if(filter) filters[0] = filter->id;
|
|
|
+ case AL_LOWPASS_GAIN: *val = filter->Gain; return;
|
|
|
+ case AL_LOWPASS_GAINHF: *val = filter->GainHF; return;
|
|
|
}
|
|
|
- else
|
|
|
+ throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param};
|
|
|
+}
|
|
|
+template<>
|
|
|
+void FilterTable<LowpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
|
|
|
+{ getParamf(filter, param, vals); }
|
|
|
+
|
|
|
+/* Highpass parameter handlers */
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::setParami(ALfilter*, ALenum param, int)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
|
|
|
+{ setParami(filter, param, *values); }
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
|
|
|
+{
|
|
|
+ switch(param)
|
|
|
+ {
|
|
|
+ case AL_HIGHPASS_GAIN:
|
|
|
+ if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "High-pass gain %f out of range", val};
|
|
|
+ filter->Gain = val;
|
|
|
+ return;
|
|
|
+
|
|
|
+ case AL_HIGHPASS_GAINLF:
|
|
|
+ if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "High-pass gainlf %f out of range", val};
|
|
|
+ filter->GainLF = val;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param};
|
|
|
+}
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
|
|
|
+{ setParamf(filter, param, *vals); }
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::getParami(const ALfilter*, ALenum param, int*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::getParamiv(const ALfilter *filter, ALenum param, int *values)
|
|
|
+{ getParami(filter, param, values); }
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::getParamf(const ALfilter *filter, ALenum param, float *val)
|
|
|
+{
|
|
|
+ switch(param)
|
|
|
{
|
|
|
- /* Store the allocated buffer IDs in a separate local list, to avoid
|
|
|
- * modifying the user storage in case of failure.
|
|
|
- */
|
|
|
- al::vector<ALuint> ids;
|
|
|
- ids.reserve(static_cast<ALuint>(n));
|
|
|
- do {
|
|
|
- ALfilter *filter{AllocFilter(device)};
|
|
|
- ids.emplace_back(filter->id);
|
|
|
- } while(--n);
|
|
|
- std::copy(ids.begin(), ids.end(), filters);
|
|
|
+ case AL_HIGHPASS_GAIN: *val = filter->Gain; return;
|
|
|
+ case AL_HIGHPASS_GAINLF: *val = filter->GainLF; return;
|
|
|
}
|
|
|
+ throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param};
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
+template<>
|
|
|
+void FilterTable<HighpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
|
|
|
+{ getParamf(filter, param, vals); }
|
|
|
+
|
|
|
+/* Bandpass parameter handlers */
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::setParami(ALfilter*, ALenum param, int)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
|
|
|
+{ setParami(filter, param, *values); }
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
|
|
|
+{
|
|
|
+ switch(param)
|
|
|
+ {
|
|
|
+ case AL_BANDPASS_GAIN:
|
|
|
+ if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Band-pass gain %f out of range", val};
|
|
|
+ filter->Gain = val;
|
|
|
+ return;
|
|
|
|
|
|
-AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
|
|
|
-START_API_FUNC
|
|
|
+ case AL_BANDPASS_GAINHF:
|
|
|
+ if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Band-pass gainhf %f out of range", val};
|
|
|
+ filter->GainHF = val;
|
|
|
+ return;
|
|
|
+
|
|
|
+ case AL_BANDPASS_GAINLF:
|
|
|
+ if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Band-pass gainlf %f out of range", val};
|
|
|
+ filter->GainLF = val;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param};
|
|
|
+}
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
|
|
|
+{ setParamf(filter, param, *vals); }
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::getParami(const ALfilter*, ALenum param, int*)
|
|
|
+{ throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; }
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::getParamiv(const ALfilter *filter, ALenum param, int *values)
|
|
|
+{ getParami(filter, param, values); }
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::getParamf(const ALfilter *filter, ALenum param, float *val)
|
|
|
{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
+ switch(param)
|
|
|
+ {
|
|
|
+ case AL_BANDPASS_GAIN: *val = filter->Gain; return;
|
|
|
+ case AL_BANDPASS_GAINHF: *val = filter->GainHF; return;
|
|
|
+ case AL_BANDPASS_GAINLF: *val = filter->GainLF; return;
|
|
|
+ }
|
|
|
+ throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param};
|
|
|
+}
|
|
|
+template<>
|
|
|
+void FilterTable<BandpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
|
|
|
+{ getParamf(filter, param, vals); }
|
|
|
+
|
|
|
+
|
|
|
+AL_API DECL_FUNC2(void, alGenFilters, ALsizei,n, ALuint*,filters)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept
|
|
|
+try {
|
|
|
+ if(n < 0)
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Generating %d filters", n};
|
|
|
+ if(n <= 0) UNLIKELY return;
|
|
|
+
|
|
|
+ ALCdevice *device{context->mALDevice.get()};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
+
|
|
|
+ const al::span fids{filters, static_cast<ALuint>(n)};
|
|
|
+ if(!EnsureFilters(device, fids.size()))
|
|
|
+ throw al::context_error{AL_OUT_OF_MEMORY, "Failed to allocate %d filter%s", n,
|
|
|
+ (n == 1) ? "" : "s"};
|
|
|
+
|
|
|
+ std::generate(fids.begin(), fids.end(), [device]{ return AllocFilter(device)->id; });
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
+}
|
|
|
|
|
|
- if(n < 0) UNLIKELY
|
|
|
- context->setError(AL_INVALID_VALUE, "Deleting %d filters", n);
|
|
|
+AL_API DECL_FUNC2(void, alDeleteFilters, ALsizei,n, const ALuint*,filters)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n,
|
|
|
+ const ALuint *filters) noexcept
|
|
|
+try {
|
|
|
+ if(n < 0)
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Deleting %d filters", n};
|
|
|
if(n <= 0) UNLIKELY return;
|
|
|
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
/* First try to find any filters that are invalid. */
|
|
|
auto validate_filter = [device](const ALuint fid) -> bool
|
|
|
{ return !fid || LookupFilter(device, fid) != nullptr; };
|
|
|
|
|
|
- const ALuint *filters_end = filters + n;
|
|
|
- auto invflt = std::find_if_not(filters, filters_end, validate_filter);
|
|
|
- if(invflt != filters_end) UNLIKELY
|
|
|
- {
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", *invflt);
|
|
|
- return;
|
|
|
- }
|
|
|
+ const al::span fids{filters, static_cast<ALuint>(n)};
|
|
|
+ auto invflt = std::find_if_not(fids.begin(), fids.end(), validate_filter);
|
|
|
+ if(invflt != fids.end())
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", *invflt};
|
|
|
|
|
|
/* All good. Delete non-0 filter IDs. */
|
|
|
auto delete_filter = [device](const ALuint fid) -> void
|
|
|
{
|
|
|
- ALfilter *filter{fid ? LookupFilter(device, fid) : nullptr};
|
|
|
- if(filter) FreeFilter(device, filter);
|
|
|
+ if(ALfilter *filter{fid ? LookupFilter(device, fid) : nullptr})
|
|
|
+ FreeFilter(device, filter);
|
|
|
};
|
|
|
- std::for_each(filters, filters_end, delete_filter);
|
|
|
+ std::for_each(fids.begin(), fids.end(), delete_filter);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
|
|
|
-AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
|
|
|
-START_API_FUNC
|
|
|
+AL_API DECL_FUNC1(ALboolean, alIsFilter, ALuint,filter)
|
|
|
+FORCE_ALIGN ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) noexcept
|
|
|
{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(context) LIKELY
|
|
|
- {
|
|
|
- ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
- if(!filter || LookupFilter(device, filter))
|
|
|
- return AL_TRUE;
|
|
|
- }
|
|
|
+ ALCdevice *device{context->mALDevice.get()};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
+ if(!filter || LookupFilter(device, filter))
|
|
|
+ return AL_TRUE;
|
|
|
return AL_FALSE;
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
-
|
|
|
|
|
|
-AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
|
|
|
+AL_API DECL_FUNC3(void, alFilteri, ALuint,filter, ALenum,param, ALint,value)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ ALint value) noexcept
|
|
|
+try {
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
- if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else
|
|
|
+ if(!alfilt)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
+
|
|
|
+ switch(param)
|
|
|
{
|
|
|
- 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
|
|
|
- context->setError(AL_INVALID_VALUE, "Invalid filter type 0x%04x", value);
|
|
|
- }
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->setParami(param, value);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
+ case AL_FILTER_TYPE:
|
|
|
+ if(!(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS
|
|
|
+ || value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS))
|
|
|
+ throw al::context_error{AL_INVALID_VALUE, "Invalid filter type 0x%04x", value};
|
|
|
+ InitFilterParams(alfilt, value);
|
|
|
+ return;
|
|
|
}
|
|
|
+
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,value](auto&& thunk){thunk.setParami(alfilt, param, value);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
|
|
|
-AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
+AL_API DECL_FUNC3(void, alFilteriv, ALuint,filter, ALenum,param, const ALint*,values)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ const ALint *values) noexcept
|
|
|
+try {
|
|
|
switch(param)
|
|
|
{
|
|
|
case AL_FILTER_TYPE:
|
|
|
- alFilteri(filter, param, values[0]);
|
|
|
+ alFilteriDirect(context, filter, param, *values);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
-
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
- if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->setParamiv(param, values);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
-}
|
|
|
-END_API_FUNC
|
|
|
+ if(!alfilt)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
|
|
|
-AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,values](auto&& thunk){thunk.setParamiv(alfilt, param, values);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
+}
|
|
|
|
|
|
+AL_API DECL_FUNC3(void, alFilterf, ALuint,filter, ALenum,param, ALfloat,value)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ ALfloat value) noexcept
|
|
|
+try {
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
- if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->setParamf(param, value);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
-}
|
|
|
-END_API_FUNC
|
|
|
+ if(!alfilt)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
|
|
|
-AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,value](auto&& thunk){thunk.setParamf(alfilt, param, value);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
+}
|
|
|
|
|
|
+AL_API DECL_FUNC3(void, alFilterfv, ALuint,filter, ALenum,param, const ALfloat*,values)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ const ALfloat *values) noexcept
|
|
|
+try {
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
- if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->setParamfv(param, values);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
-}
|
|
|
-END_API_FUNC
|
|
|
+ if(!alfilt)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
|
|
|
-AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,values](auto&& thunk){thunk.setParamfv(alfilt, param, values);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
+}
|
|
|
|
|
|
+AL_API DECL_FUNC3(void, alGetFilteri, ALuint,filter, ALenum,param, ALint*,value)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ ALint *value) noexcept
|
|
|
+try {
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
const ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
- if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else
|
|
|
+ if(!alfilt)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
+
|
|
|
+ switch(param)
|
|
|
{
|
|
|
- if(param == AL_FILTER_TYPE)
|
|
|
- *value = alfilt->type;
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->getParami(param, value);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
+ case AL_FILTER_TYPE:
|
|
|
+ *value = alfilt->type;
|
|
|
+ return;
|
|
|
}
|
|
|
+
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,value](auto&& thunk){thunk.getParami(alfilt, param, value);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
|
|
|
-AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
+AL_API DECL_FUNC3(void, alGetFilteriv, ALuint,filter, ALenum,param, ALint*,values)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ ALint *values) noexcept
|
|
|
+try {
|
|
|
switch(param)
|
|
|
{
|
|
|
case AL_FILTER_TYPE:
|
|
|
- alGetFilteri(filter, param, values);
|
|
|
+ alGetFilteriDirect(context, filter, param, values);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
+ ALCdevice *device{context->mALDevice.get()};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
+
|
|
|
+ const ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
+ if(!alfilt)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
+
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,values](auto&& thunk){thunk.getParamiv(alfilt, param, values);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
+}
|
|
|
|
|
|
+AL_API DECL_FUNC3(void, alGetFilterf, ALuint,filter, ALenum,param, ALfloat*,value)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ ALfloat *value) noexcept
|
|
|
+try {
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
const ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->getParamiv(param, values);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
-}
|
|
|
-END_API_FUNC
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
|
|
|
-AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,value](auto&& thunk){thunk.getParamf(alfilt, param, value);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
+}
|
|
|
|
|
|
+AL_API DECL_FUNC3(void, alGetFilterfv, ALuint,filter, ALenum,param, ALfloat*,values)
|
|
|
+FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param,
|
|
|
+ ALfloat *values) noexcept
|
|
|
+try {
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
const ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->getParamf(param, value);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
|
|
|
+
|
|
|
+ /* Call the appropriate handler */
|
|
|
+ std::visit([alfilt,param,values](auto&& thunk){thunk.getParamfv(alfilt, param, values);},
|
|
|
+ alfilt->mTypeVariant);
|
|
|
+}
|
|
|
+catch(al::context_error& e) {
|
|
|
+ context->setError(e.errorCode(), "%s", e.what());
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
|
|
|
-AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
|
|
|
-START_API_FUNC
|
|
|
-{
|
|
|
- ContextRef context{GetContextRef()};
|
|
|
- if(!context) UNLIKELY return;
|
|
|
|
|
|
+void ALfilter::SetName(ALCcontext *context, ALuint id, std::string_view name)
|
|
|
+{
|
|
|
ALCdevice *device{context->mALDevice.get()};
|
|
|
- std::lock_guard<std::mutex> _{device->FilterLock};
|
|
|
+ std::lock_guard<std::mutex> filterlock{device->FilterLock};
|
|
|
|
|
|
- const ALfilter *alfilt{LookupFilter(device, filter)};
|
|
|
- if(!alfilt) UNLIKELY
|
|
|
- context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
|
|
- else try
|
|
|
- {
|
|
|
- /* Call the appropriate handler */
|
|
|
- alfilt->getParamfv(param, values);
|
|
|
- }
|
|
|
- catch(filter_exception &e) {
|
|
|
- context->setError(e.errorCode(), "%s", e.what());
|
|
|
- }
|
|
|
+ auto filter = LookupFilter(device, id);
|
|
|
+ if(!filter)
|
|
|
+ throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", id};
|
|
|
+
|
|
|
+ device->mFilterNames.insert_or_assign(id, name);
|
|
|
}
|
|
|
-END_API_FUNC
|
|
|
|
|
|
|
|
|
FilterSubList::~FilterSubList()
|
|
|
{
|
|
|
+ if(!Filters)
|
|
|
+ return;
|
|
|
+
|
|
|
uint64_t usemask{~FreeMask};
|
|
|
while(usemask)
|
|
|
{
|
|
|
const int idx{al::countr_zero(usemask)};
|
|
|
- al::destroy_at(Filters+idx);
|
|
|
+ std::destroy_at(al::to_address(Filters->begin() + idx));
|
|
|
usemask &= ~(1_u64 << idx);
|
|
|
}
|
|
|
FreeMask = ~usemask;
|
|
|
- al_free(Filters);
|
|
|
+ SubListAllocator{}.deallocate(Filters, 1);
|
|
|
Filters = nullptr;
|
|
|
}
|