aboutsummaryrefslogtreecommitdiffstats
path: root/al
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-11-28 12:51:46 +0100
committerSven Gothel <[email protected]>2023-11-28 12:51:46 +0100
commit1aaf4f070011490bcece50394b9b32dfa593fd9e (patch)
tree17d68284e401a35eea3d3a574d986d446a60763a /al
parent6e7cee4fa9a8af03f28ca26cd89f8357390dfc90 (diff)
parent571b546f35eead77ce109f8d4dd6c3de3199d573 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'al')
-rw-r--r--al/auxeffectslot.cpp229
-rw-r--r--al/auxeffectslot.h7
-rw-r--r--al/buffer.cpp726
-rw-r--r--al/buffer.h7
-rw-r--r--al/debug.cpp570
-rw-r--r--al/debug.h69
-rw-r--r--al/direct_defs.h127
-rw-r--r--al/eax/api.h32
-rw-r--r--al/eax/call.h4
-rw-r--r--al/eax/effect.h113
-rw-r--r--al/eax/exception.cpp47
-rw-r--r--al/eax/exception.h6
-rw-r--r--al/eax/fx_slot_index.h7
-rw-r--r--al/eax/globals.cpp21
-rw-r--r--al/eax/globals.h24
-rw-r--r--al/eax/utils.cpp6
-rw-r--r--al/eax/utils.h12
-rw-r--r--al/eax/x_ram.h11
-rw-r--r--al/effect.cpp143
-rw-r--r--al/effect.h4
-rw-r--r--al/effects/autowah.cpp56
-rw-r--r--al/effects/chorus.cpp32
-rw-r--r--al/effects/compressor.cpp22
-rw-r--r--al/effects/convolution.cpp34
-rw-r--r--al/effects/distortion.cpp64
-rw-r--r--al/effects/echo.cpp64
-rw-r--r--al/effects/equalizer.cpp109
-rw-r--r--al/effects/fshifter.cpp53
-rw-r--r--al/effects/modulator.cpp53
-rw-r--r--al/effects/null.cpp5
-rw-r--r--al/effects/pshifter.cpp32
-rw-r--r--al/effects/reverb.cpp142
-rw-r--r--al/effects/vmorpher.cpp84
-rw-r--r--al/error.cpp54
-rw-r--r--al/event.cpp160
-rw-r--r--al/extension.cpp41
-rw-r--r--al/filter.cpp608
-rw-r--r--al/filter.h45
-rw-r--r--al/listener.cpp196
-rw-r--r--al/source.cpp2631
-rw-r--r--al/source.h14
-rw-r--r--al/state.cpp866
42 files changed, 3768 insertions, 3762 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp
index 285da1d4..fb646389 100644
--- a/al/auxeffectslot.cpp
+++ b/al/auxeffectslot.cpp
@@ -47,6 +47,7 @@
#include "core/except.h"
#include "core/fpu_ctrl.h"
#include "core/logging.h"
+#include "direct_defs.h"
#include "effect.h"
#include "opthelpers.h"
@@ -165,7 +166,7 @@ void AddActiveEffectSlots(const al::span<ALeffectslot*> auxslots, ALCcontext *co
curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel);
context->mDevice->waitForMix();
- al::destroy_n(curarray->end(), curarray->size());
+ std::destroy_n(curarray->end(), curarray->size());
delete curarray;
}
@@ -204,7 +205,7 @@ void RemoveActiveEffectSlots(const al::span<ALeffectslot*> auxslots, ALCcontext
curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel);
context->mDevice->waitForMix();
- al::destroy_n(curarray->end(), curarray->size());
+ std::destroy_n(curarray->end(), curarray->size());
delete curarray;
}
@@ -229,7 +230,7 @@ EffectSlotType EffectSlotTypeFromEnum(ALenum type)
case AL_EFFECT_EAXREVERB: return EffectSlotType::EAXReverb;
case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: return EffectSlotType::DedicatedLFE;
case AL_EFFECT_DEDICATED_DIALOGUE: return EffectSlotType::DedicatedDialog;
- case AL_EFFECT_CONVOLUTION_REVERB_SOFT: return EffectSlotType::Convolution;
+ case AL_EFFECT_CONVOLUTION_SOFT: return EffectSlotType::Convolution;
}
ERR("Unhandled effect enum: 0x%04x\n", type);
return EffectSlotType::None;
@@ -238,7 +239,7 @@ EffectSlotType EffectSlotTypeFromEnum(ALenum type)
bool EnsureEffectSlots(ALCcontext *context, size_t needed)
{
size_t count{std::accumulate(context->mEffectSlotList.cbegin(),
- context->mEffectSlotList.cend(), size_t{0},
+ context->mEffectSlotList.cend(), 0_uz,
[](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
@@ -285,11 +286,13 @@ ALeffectslot *AllocEffectSlot(ALCcontext *context)
void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot)
{
+ context->mEffectSlotNames.erase(slot->id);
+
const ALuint id{slot->id - 1};
const size_t lidx{id >> 6};
const ALuint slidx{id & 0x3f};
- al::destroy_at(slot);
+ std::destroy_at(slot);
context->mEffectSlotList[lidx].FreeMask |= 1_u64 << slidx;
context->mNumEffectSlots--;
@@ -309,12 +312,10 @@ inline void UpdateProps(ALeffectslot *slot, ALCcontext *context)
} // namespace
-AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGenAuxiliaryEffectSlots, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n,
+ ALuint *effectslots) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Generating %d effect slots", n);
if(n <= 0) UNLIKELY return;
@@ -327,7 +328,7 @@ START_API_FUNC
device->AuxiliaryEffectSlotMax, context->mNumEffectSlots, n);
return;
}
- if(!EnsureEffectSlots(context.get(), static_cast<ALuint>(n)))
+ if(!EnsureEffectSlots(context, static_cast<ALuint>(n)))
{
context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effectslot%s", n,
(n==1) ? "" : "s");
@@ -336,29 +337,26 @@ START_API_FUNC
if(n == 1)
{
- ALeffectslot *slot{AllocEffectSlot(context.get())};
+ ALeffectslot *slot{AllocEffectSlot(context)};
effectslots[0] = slot->id;
}
else
{
- al::vector<ALuint> ids;
+ std::vector<ALuint> ids;
ALsizei count{n};
ids.reserve(static_cast<ALuint>(count));
do {
- ALeffectslot *slot{AllocEffectSlot(context.get())};
+ ALeffectslot *slot{AllocEffectSlot(context)};
ids.emplace_back(slot->id);
} while(--count);
std::copy(ids.cbegin(), ids.cend(), effectslots);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alDeleteAuxiliaryEffectSlots, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n,
+ const ALuint *effectslots) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Deleting %d effect slots", n);
if(n <= 0) UNLIKELY return;
@@ -366,7 +364,7 @@ START_API_FUNC
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
if(n == 1)
{
- ALeffectslot *slot{LookupEffectSlot(context.get(), effectslots[0])};
+ ALeffectslot *slot{LookupEffectSlot(context, effectslots[0])};
if(!slot) UNLIKELY
{
context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[0]);
@@ -378,15 +376,15 @@ START_API_FUNC
effectslots[0]);
return;
}
- RemoveActiveEffectSlots({&slot, 1u}, context.get());
- FreeEffectSlot(context.get(), slot);
+ RemoveActiveEffectSlots({&slot, 1u}, context);
+ FreeEffectSlot(context, slot);
}
else
{
- auto slots = al::vector<ALeffectslot*>(static_cast<ALuint>(n));
+ auto slots = std::vector<ALeffectslot*>(static_cast<ALuint>(n));
for(size_t i{0};i < slots.size();++i)
{
- ALeffectslot *slot{LookupEffectSlot(context.get(), effectslots[i])};
+ ALeffectslot *slot{LookupEffectSlot(context, effectslots[i])};
if(!slot) UNLIKELY
{
context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[i]);
@@ -410,30 +408,24 @@ START_API_FUNC
slots.erase(slots_end, slots.end());
/* All effectslots are valid, remove and delete them */
- RemoveActiveEffectSlots(slots, context.get());
+ RemoveActiveEffectSlots(slots, context);
for(ALeffectslot *slot : slots)
- FreeEffectSlot(context.get(), slot);
+ FreeEffectSlot(context, slot);
}
}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsAuxiliaryEffectSlot, ALuint)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context,
+ ALuint effectslot) noexcept
{
- ContextRef context{GetContextRef()};
- if(context) LIKELY
- {
- std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- if(LookupEffectSlot(context.get(), effectslot) != nullptr)
- return AL_TRUE;
- }
+ std::lock_guard<std::mutex> _{context->mEffectSlotLock};
+ if(LookupEffectSlot(context, effectslot) != nullptr)
+ return AL_TRUE;
return AL_FALSE;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid)
-START_API_FUNC
+AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
@@ -454,10 +446,8 @@ START_API_FUNC
AddActiveEffectSlots({&slot, 1}, context.get());
slot->mState = SlotState::Playing;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids)
-START_API_FUNC
+AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
@@ -466,7 +456,7 @@ START_API_FUNC
context->setError(AL_INVALID_VALUE, "Playing %d effect slots", n);
if(n <= 0) UNLIKELY return;
- auto slots = al::vector<ALeffectslot*>(static_cast<ALuint>(n));
+ auto slots = std::vector<ALeffectslot*>(static_cast<ALuint>(n));
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
for(size_t i{0};i < slots.size();++i)
{
@@ -489,10 +479,8 @@ START_API_FUNC
for(auto slot : slots)
slot->mState = SlotState::Playing;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid)
-START_API_FUNC
+AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
@@ -508,10 +496,8 @@ START_API_FUNC
RemoveActiveEffectSlots({&slot, 1}, context.get());
slot->mState = SlotState::Stopped;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids)
-START_API_FUNC
+AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
@@ -520,7 +506,7 @@ START_API_FUNC
context->setError(AL_INVALID_VALUE, "Stopping %d effect slots", n);
if(n <= 0) UNLIKELY return;
- auto slots = al::vector<ALeffectslot*>(static_cast<ALuint>(n));
+ auto slots = std::vector<ALeffectslot*>(static_cast<ALuint>(n));
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
for(size_t i{0};i < slots.size();++i)
{
@@ -538,18 +524,15 @@ START_API_FUNC
for(auto slot : slots)
slot->mState = SlotState::Stopped;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alAuxiliaryEffectSloti, ALuint, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot,
+ ALenum param, ALint value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -565,12 +548,12 @@ START_API_FUNC
std::lock_guard<std::mutex> ___{device->EffectLock};
ALeffect *effect{value ? LookupEffect(device, static_cast<ALuint>(value)) : nullptr};
if(effect)
- err = slot->initEffect(effect->type, effect->Props, context.get());
+ err = slot->initEffect(effect->id, effect->type, effect->Props, context);
else
{
if(value != 0)
return context->setError(AL_INVALID_VALUE, "Invalid effect ID %u", value);
- err = slot->initEffect(AL_EFFECT_NULL, EffectProps{}, context.get());
+ err = slot->initEffect(0, AL_EFFECT_NULL, EffectProps{}, context);
}
}
if(err != AL_NO_ERROR) UNLIKELY
@@ -581,9 +564,9 @@ START_API_FUNC
if(slot->mState == SlotState::Initial) UNLIKELY
{
slot->mPropsDirty = false;
- slot->updateProps(context.get());
+ slot->updateProps(context);
- AddActiveEffectSlots({&slot, 1}, context.get());
+ AddActiveEffectSlots({&slot, 1}, context);
slot->mState = SlotState::Playing;
return;
}
@@ -599,7 +582,7 @@ START_API_FUNC
break;
case AL_EFFECTSLOT_TARGET_SOFT:
- target = LookupEffectSlot(context.get(), static_cast<ALuint>(value));
+ target = LookupEffectSlot(context, static_cast<ALuint>(value));
if(value && !target)
return context->setError(AL_INVALID_VALUE, "Invalid effect slot target ID");
if(slot->Target == target) UNLIKELY
@@ -623,7 +606,7 @@ START_API_FUNC
if(target) IncrementRef(target->ref);
DecrementRef(oldtarget->ref);
slot->Target = target;
- slot->updateProps(context.get());
+ slot->updateProps(context);
return;
}
@@ -677,12 +660,12 @@ START_API_FUNC
return context->setError(AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x",
param);
}
- UpdateProps(slot, context.get());
+ UpdateProps(slot, context);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotiv, ALuint, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot,
+ ALenum param, const ALint *values) noexcept
{
switch(param)
{
@@ -691,15 +674,12 @@ START_API_FUNC
case AL_EFFECTSLOT_TARGET_SOFT:
case AL_EFFECTSLOT_STATE_SOFT:
case AL_BUFFER:
- alAuxiliaryEffectSloti(effectslot, param, values[0]);
+ alAuxiliaryEffectSlotiDirect(context, effectslot, param, values[0]);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -710,17 +690,14 @@ START_API_FUNC
"Invalid effect slot integer-vector property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot,
+ ALenum param, ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -738,25 +715,22 @@ START_API_FUNC
return context->setError(AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x",
param);
}
- UpdateProps(slot, context.get());
+ UpdateProps(slot, context);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotfv, ALuint, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot,
+ ALenum param, const ALfloat *values) noexcept
{
switch(param)
{
case AL_EFFECTSLOT_GAIN:
- alAuxiliaryEffectSlotf(effectslot, param, values[0]);
+ alAuxiliaryEffectSlotfDirect(context, effectslot, param, values[0]);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -767,22 +741,23 @@ START_API_FUNC
"Invalid effect slot float-vector property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSloti, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context,
+ ALuint effectslot, ALenum param, ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
switch(param)
{
+ case AL_EFFECTSLOT_EFFECT:
+ *value = static_cast<ALint>(slot->EffectId);
+ break;
+
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
*value = slot->AuxSendAuto ? AL_TRUE : AL_FALSE;
break;
@@ -809,10 +784,10 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotiv, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context,
+ ALuint effectslot, ALenum param, ALint *values) noexcept
{
switch(param)
{
@@ -821,15 +796,12 @@ START_API_FUNC
case AL_EFFECTSLOT_TARGET_SOFT:
case AL_EFFECTSLOT_STATE_SOFT:
case AL_BUFFER:
- alGetAuxiliaryEffectSloti(effectslot, param, values);
+ alGetAuxiliaryEffectSlotiDirect(context, effectslot, param, values);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -840,16 +812,13 @@ START_API_FUNC
param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context,
+ ALuint effectslot, ALenum param, ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -863,23 +832,20 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotfv, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context,
+ ALuint effectslot, ALenum param, ALfloat *values) noexcept
{
switch(param)
{
case AL_EFFECTSLOT_GAIN:
- alGetAuxiliaryEffectSlotf(effectslot, param, values);
+ alGetAuxiliaryEffectSlotfDirect(context, effectslot, param, values);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
- ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot);
+ ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot);
@@ -890,7 +856,6 @@ START_API_FUNC
param);
}
}
-END_API_FUNC
ALeffectslot::ALeffectslot(ALCcontext *context)
@@ -926,7 +891,7 @@ ALeffectslot::~ALeffectslot()
mSlot->InUse = false;
}
-ALenum ALeffectslot::initEffect(ALenum effectType, const EffectProps &effectProps,
+ALenum ALeffectslot::initEffect(ALuint effectId, ALenum effectType, const EffectProps &effectProps,
ALCcontext *context)
{
EffectSlotType newtype{EffectSlotTypeFromEnum(effectType)};
@@ -955,6 +920,7 @@ ALenum ALeffectslot::initEffect(ALenum effectType, const EffectProps &effectProp
}
else if(newtype != EffectSlotType::None)
Effect.Props = effectProps;
+ EffectId = effectId;
/* Remove state references from old effect slot property updates. */
EffectSlotProps *props{context->mFreeEffectslotProps.load()};
@@ -1003,6 +969,17 @@ void ALeffectslot::updateProps(ALCcontext *context)
}
}
+void ALeffectslot::SetName(ALCcontext* context, ALuint id, std::string_view name)
+{
+ std::lock_guard<std::mutex> _{context->mEffectSlotLock};
+
+ auto slot = LookupEffectSlot(context, id);
+ if(!slot) UNLIKELY
+ return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", id);
+
+ context->mEffectSlotNames.insert_or_assign(id, name);
+}
+
void UpdateAllEffectSlotProps(ALCcontext *context)
{
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
@@ -1023,11 +1000,14 @@ void UpdateAllEffectSlotProps(ALCcontext *context)
EffectSlotSubList::~EffectSlotSubList()
{
+ if(!EffectSlots)
+ return;
+
uint64_t usemask{~FreeMask};
while(usemask)
{
const int idx{al::countr_zero(usemask)};
- al::destroy_at(EffectSlots+idx);
+ std::destroy_at(EffectSlots+idx);
usemask &= ~(1_u64 << idx);
}
FreeMask = ~usemask;
@@ -1272,7 +1252,7 @@ void ALeffectslot::eax_fx_slot_load_effect(int version, ALenum altype)
void ALeffectslot::eax_fx_slot_set_volume()
{
- const auto volume = clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME);
+ const auto volume = std::clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME);
const auto gain = level_mb_to_gain(static_cast<float>(volume));
eax_set_efx_slot_gain(gain);
}
@@ -1470,7 +1450,8 @@ void ALeffectslot::eax_set_efx_slot_effect(EaxEffect &effect)
{
#define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] "
- const auto error = initEffect(effect.al_effect_type_, effect.al_effect_props_, eax_al_context_);
+ const auto error = initEffect(0, effect.al_effect_type_, effect.al_effect_props_,
+ eax_al_context_);
if(error != AL_NO_ERROR) {
ERR(EAX_PREFIX "%s\n", "Failed to initialize an effect.");
diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h
index 3e9a2a4e..1ad0ffc4 100644
--- a/al/auxeffectslot.h
+++ b/al/auxeffectslot.h
@@ -3,6 +3,7 @@
#include <atomic>
#include <cstddef>
+#include <string_view>
#include "AL/al.h"
#include "AL/alc.h"
@@ -45,6 +46,7 @@ enum class SlotState : ALenum {
};
struct ALeffectslot {
+ ALuint EffectId{};
float Gain{1.0f};
bool AuxSendAuto{true};
ALeffectslot *Target{nullptr};
@@ -73,9 +75,12 @@ struct ALeffectslot {
ALeffectslot& operator=(const ALeffectslot&) = delete;
~ALeffectslot();
- ALenum initEffect(ALenum effectType, const EffectProps &effectProps, ALCcontext *context);
+ ALenum initEffect(ALuint effectId, ALenum effectType, const EffectProps &effectProps,
+ ALCcontext *context);
void updateProps(ALCcontext *context);
+ static void SetName(ALCcontext *context, ALuint id, std::string_view name);
+
/* This can be new'd for the context's default effect slot. */
DEF_NEWDEL(ALeffectslot)
diff --git a/al/buffer.cpp b/al/buffer.cpp
index ee506596..7d043036 100644
--- a/al/buffer.cpp
+++ b/al/buffer.cpp
@@ -26,6 +26,7 @@
#include <array>
#include <atomic>
#include <cassert>
+#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
@@ -35,28 +36,31 @@
#include <mutex>
#include <new>
#include <numeric>
+#include <optional>
#include <stdexcept>
#include <utility>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "albit.h"
-#include "albyte.h"
#include "alc/context.h"
#include "alc/device.h"
#include "alc/inprogext.h"
#include "almalloc.h"
#include "alnumeric.h"
-#include "aloptional.h"
#include "atomic.h"
#include "core/except.h"
#include "core/logging.h"
#include "core/voice.h"
+#include "direct_defs.h"
#include "opthelpers.h"
#ifdef ALSOFT_EAX
+#include <unordered_set>
+
#include "eax/globals.h"
#include "eax/x_ram.h"
#endif // ALSOFT_EAX
@@ -64,14 +68,14 @@
namespace {
-al::optional<AmbiLayout> AmbiLayoutFromEnum(ALenum layout)
+std::optional<AmbiLayout> AmbiLayoutFromEnum(ALenum layout)
{
switch(layout)
{
case AL_FUMA_SOFT: return AmbiLayout::FuMa;
case AL_ACN_SOFT: return AmbiLayout::ACN;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum EnumFromAmbiLayout(AmbiLayout layout)
{
@@ -83,7 +87,7 @@ ALenum EnumFromAmbiLayout(AmbiLayout layout)
throw std::runtime_error{"Invalid AmbiLayout: "+std::to_string(int(layout))};
}
-al::optional<AmbiScaling> AmbiScalingFromEnum(ALenum scale)
+std::optional<AmbiScaling> AmbiScalingFromEnum(ALenum scale)
{
switch(scale)
{
@@ -91,7 +95,7 @@ al::optional<AmbiScaling> AmbiScalingFromEnum(ALenum scale)
case AL_SN3D_SOFT: return AmbiScaling::SN3D;
case AL_N3D_SOFT: return AmbiScaling::N3D;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum EnumFromAmbiScaling(AmbiScaling scale)
{
@@ -106,7 +110,7 @@ ALenum EnumFromAmbiScaling(AmbiScaling scale)
}
#ifdef ALSOFT_EAX
-al::optional<EaxStorage> EaxStorageFromEnum(ALenum scale)
+std::optional<EaxStorage> EaxStorageFromEnum(ALenum scale)
{
switch(scale)
{
@@ -114,7 +118,7 @@ al::optional<EaxStorage> EaxStorageFromEnum(ALenum scale)
case AL_STORAGE_ACCESSIBLE: return EaxStorage::Accessible;
case AL_STORAGE_HARDWARE: return EaxStorage::Hardware;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum EnumFromEaxStorage(EaxStorage storage)
{
@@ -170,7 +174,7 @@ constexpr ALbitfieldSOFT INVALID_MAP_FLAGS{~unsigned(AL_MAP_READ_BIT_SOFT | AL_M
bool EnsureBuffers(ALCdevice *device, size_t needed)
{
- size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), size_t{0},
+ size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), 0_uz,
[](size_t cur, const BufferSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
@@ -218,11 +222,13 @@ void FreeBuffer(ALCdevice *device, ALbuffer *buffer)
eax_x_ram_clear(*device, *buffer);
#endif // ALSOFT_EAX
+ device->mBufferNames.erase(buffer->id);
+
const ALuint id{buffer->id - 1};
const size_t lidx{id >> 6};
const ALuint slidx{id & 0x3f};
- al::destroy_at(buffer);
+ std::destroy_at(buffer);
device->BufferList[lidx].FreeMask |= 1_u64 << slidx;
}
@@ -277,7 +283,7 @@ ALuint SanitizeAlignment(FmtType type, ALuint align)
/** Loads the specified data into the buffer, using the specified format. */
void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
- const FmtChannels DstChannels, const FmtType DstType, const al::byte *SrcData,
+ const FmtChannels DstChannels, const FmtType DstType, const std::byte *SrcData,
ALbitfieldSOFT access)
{
if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY
@@ -343,7 +349,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
*/
if(newsize != ALBuf->mDataStorage.size())
{
- auto newdata = al::vector<al::byte,16>(newsize, al::byte{});
+ auto newdata = decltype(ALBuf->mDataStorage)(newsize, std::byte{});
if((access&AL_PRESERVE_DATA_BIT_SOFT))
{
const size_t tocopy{minz(newdata.size(), ALBuf->mDataStorage.size())};
@@ -437,7 +443,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
/** Prepares the buffer to use caller-specified storage. */
void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
- const FmtChannels DstChannels, const FmtType DstType, al::byte *sdata, const ALuint sdatalen)
+ const FmtChannels DstChannels, const FmtType DstType, std::byte *sdata, const ALuint sdatalen)
{
if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY
return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u",
@@ -458,6 +464,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
{
case FmtUByte: return alignof(ALubyte);
case FmtShort: return alignof(ALshort);
+ case FmtInt: return alignof(ALint);
case FmtFloat: return alignof(ALfloat);
case FmtDouble: return alignof(ALdouble);
case FmtMulaw: return alignof(ALubyte);
@@ -506,7 +513,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
#endif
decltype(ALBuf->mDataStorage){}.swap(ALBuf->mDataStorage);
- ALBuf->mData = {static_cast<al::byte*>(sdata), sdatalen};
+ ALBuf->mData = {static_cast<std::byte*>(sdata), sdatalen};
#ifdef ALSOFT_EAX
eax_x_ram_clear(*context->mALDevice, *ALBuf);
@@ -536,108 +543,120 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
struct DecompResult { FmtChannels channels; FmtType type; };
-al::optional<DecompResult> DecomposeUserFormat(ALenum format)
+std::optional<DecompResult> DecomposeUserFormat(ALenum format)
{
struct FormatMap {
ALenum format;
FmtChannels channels;
FmtType type;
};
- static const std::array<FormatMap,63> UserFmtList{{
- { AL_FORMAT_MONO8, FmtMono, FmtUByte },
- { AL_FORMAT_MONO16, FmtMono, FmtShort },
- { AL_FORMAT_MONO_FLOAT32, FmtMono, FmtFloat },
- { AL_FORMAT_MONO_DOUBLE_EXT, FmtMono, FmtDouble },
- { AL_FORMAT_MONO_IMA4, FmtMono, FmtIMA4 },
- { AL_FORMAT_MONO_MSADPCM_SOFT, FmtMono, FmtMSADPCM },
- { AL_FORMAT_MONO_MULAW, FmtMono, FmtMulaw },
- { AL_FORMAT_MONO_ALAW_EXT, FmtMono, FmtAlaw },
-
- { AL_FORMAT_STEREO8, FmtStereo, FmtUByte },
- { AL_FORMAT_STEREO16, FmtStereo, FmtShort },
- { AL_FORMAT_STEREO_FLOAT32, FmtStereo, FmtFloat },
- { AL_FORMAT_STEREO_DOUBLE_EXT, FmtStereo, FmtDouble },
- { AL_FORMAT_STEREO_IMA4, FmtStereo, FmtIMA4 },
- { AL_FORMAT_STEREO_MSADPCM_SOFT, FmtStereo, FmtMSADPCM },
- { AL_FORMAT_STEREO_MULAW, FmtStereo, FmtMulaw },
- { AL_FORMAT_STEREO_ALAW_EXT, FmtStereo, FmtAlaw },
-
- { AL_FORMAT_REAR8, FmtRear, FmtUByte },
- { AL_FORMAT_REAR16, FmtRear, FmtShort },
- { AL_FORMAT_REAR32, FmtRear, FmtFloat },
- { AL_FORMAT_REAR_MULAW, FmtRear, FmtMulaw },
-
- { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtUByte },
- { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
-
- { AL_FORMAT_QUAD8, FmtQuad, FmtUByte },
- { AL_FORMAT_QUAD16, FmtQuad, FmtShort },
- { AL_FORMAT_QUAD32, FmtQuad, FmtFloat },
- { AL_FORMAT_QUAD_MULAW, FmtQuad, FmtMulaw },
-
- { AL_FORMAT_51CHN8, FmtX51, FmtUByte },
- { AL_FORMAT_51CHN16, FmtX51, FmtShort },
- { AL_FORMAT_51CHN32, FmtX51, FmtFloat },
- { AL_FORMAT_51CHN_MULAW, FmtX51, FmtMulaw },
-
- { AL_FORMAT_61CHN8, FmtX61, FmtUByte },
- { AL_FORMAT_61CHN16, FmtX61, FmtShort },
- { AL_FORMAT_61CHN32, FmtX61, FmtFloat },
- { AL_FORMAT_61CHN_MULAW, FmtX61, FmtMulaw },
-
- { AL_FORMAT_71CHN8, FmtX71, FmtUByte },
- { AL_FORMAT_71CHN16, FmtX71, FmtShort },
- { AL_FORMAT_71CHN32, FmtX71, FmtFloat },
- { AL_FORMAT_71CHN_MULAW, FmtX71, FmtMulaw },
-
- { AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtUByte },
- { AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort },
- { AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat },
- { AL_FORMAT_BFORMAT2D_MULAW, FmtBFormat2D, FmtMulaw },
-
- { AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtUByte },
- { AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort },
- { AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat },
- { AL_FORMAT_BFORMAT3D_MULAW, FmtBFormat3D, FmtMulaw },
-
- { AL_FORMAT_UHJ2CHN8_SOFT, FmtUHJ2, FmtUByte },
- { AL_FORMAT_UHJ2CHN16_SOFT, FmtUHJ2, FmtShort },
- { AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, FmtUHJ2, FmtFloat },
- { AL_FORMAT_UHJ2CHN_MULAW_SOFT, FmtUHJ2, FmtMulaw },
- { AL_FORMAT_UHJ2CHN_ALAW_SOFT, FmtUHJ2, FmtAlaw },
- { AL_FORMAT_UHJ2CHN_IMA4_SOFT, FmtUHJ2, FmtIMA4 },
- { AL_FORMAT_UHJ2CHN_MSADPCM_SOFT, FmtUHJ2, FmtMSADPCM },
-
- { AL_FORMAT_UHJ3CHN8_SOFT, FmtUHJ3, FmtUByte },
- { AL_FORMAT_UHJ3CHN16_SOFT, FmtUHJ3, FmtShort },
- { AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, FmtUHJ3, FmtFloat },
- { AL_FORMAT_UHJ3CHN_MULAW_SOFT, FmtUHJ3, FmtMulaw },
- { AL_FORMAT_UHJ3CHN_ALAW_SOFT, FmtUHJ3, FmtAlaw },
-
- { AL_FORMAT_UHJ4CHN8_SOFT, FmtUHJ4, FmtUByte },
- { AL_FORMAT_UHJ4CHN16_SOFT, FmtUHJ4, FmtShort },
- { AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, FmtUHJ4, FmtFloat },
- { AL_FORMAT_UHJ4CHN_MULAW_SOFT, FmtUHJ4, FmtMulaw },
- { AL_FORMAT_UHJ4CHN_ALAW_SOFT, FmtUHJ4, FmtAlaw },
- }};
+ static constexpr std::array UserFmtList{
+ FormatMap{AL_FORMAT_MONO8, FmtMono, FmtUByte },
+ FormatMap{AL_FORMAT_MONO16, FmtMono, FmtShort },
+ FormatMap{AL_FORMAT_MONO_I32, FmtMono, FmtInt },
+ FormatMap{AL_FORMAT_MONO_FLOAT32, FmtMono, FmtFloat },
+ FormatMap{AL_FORMAT_MONO_DOUBLE_EXT, FmtMono, FmtDouble },
+ FormatMap{AL_FORMAT_MONO_IMA4, FmtMono, FmtIMA4 },
+ FormatMap{AL_FORMAT_MONO_MSADPCM_SOFT, FmtMono, FmtMSADPCM},
+ FormatMap{AL_FORMAT_MONO_MULAW, FmtMono, FmtMulaw },
+ FormatMap{AL_FORMAT_MONO_ALAW_EXT, FmtMono, FmtAlaw },
+
+ FormatMap{AL_FORMAT_STEREO8, FmtStereo, FmtUByte },
+ FormatMap{AL_FORMAT_STEREO16, FmtStereo, FmtShort },
+ FormatMap{AL_FORMAT_STEREO_I32, FmtStereo, FmtInt },
+ FormatMap{AL_FORMAT_STEREO_FLOAT32, FmtStereo, FmtFloat },
+ FormatMap{AL_FORMAT_STEREO_DOUBLE_EXT, FmtStereo, FmtDouble },
+ FormatMap{AL_FORMAT_STEREO_IMA4, FmtStereo, FmtIMA4 },
+ FormatMap{AL_FORMAT_STEREO_MSADPCM_SOFT, FmtStereo, FmtMSADPCM},
+ FormatMap{AL_FORMAT_STEREO_MULAW, FmtStereo, FmtMulaw },
+ FormatMap{AL_FORMAT_STEREO_ALAW_EXT, FmtStereo, FmtAlaw },
+
+ FormatMap{AL_FORMAT_REAR8, FmtRear, FmtUByte},
+ FormatMap{AL_FORMAT_REAR16, FmtRear, FmtShort},
+ FormatMap{AL_FORMAT_REAR32, FmtRear, FmtFloat},
+ FormatMap{AL_FORMAT_REAR_I32, FmtRear, FmtInt },
+ FormatMap{AL_FORMAT_REAR_FLOAT32, FmtRear, FmtFloat},
+ FormatMap{AL_FORMAT_REAR_MULAW, FmtRear, FmtMulaw},
+
+ FormatMap{AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtUByte},
+ FormatMap{AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort},
+
+ FormatMap{AL_FORMAT_QUAD8, FmtQuad, FmtUByte},
+ FormatMap{AL_FORMAT_QUAD16, FmtQuad, FmtShort},
+ FormatMap{AL_FORMAT_QUAD32, FmtQuad, FmtFloat},
+ FormatMap{AL_FORMAT_QUAD_I32, FmtQuad, FmtInt },
+ FormatMap{AL_FORMAT_QUAD_FLOAT32, FmtQuad, FmtFloat},
+ FormatMap{AL_FORMAT_QUAD_MULAW, FmtQuad, FmtMulaw},
+
+ FormatMap{AL_FORMAT_51CHN8, FmtX51, FmtUByte},
+ FormatMap{AL_FORMAT_51CHN16, FmtX51, FmtShort},
+ FormatMap{AL_FORMAT_51CHN32, FmtX51, FmtFloat},
+ FormatMap{AL_FORMAT_51CHN_I32, FmtX51, FmtInt },
+ FormatMap{AL_FORMAT_51CHN_FLOAT32, FmtX51, FmtFloat},
+ FormatMap{AL_FORMAT_51CHN_MULAW, FmtX51, FmtMulaw},
+
+ FormatMap{AL_FORMAT_61CHN8, FmtX61, FmtUByte},
+ FormatMap{AL_FORMAT_61CHN16, FmtX61, FmtShort},
+ FormatMap{AL_FORMAT_61CHN32, FmtX61, FmtFloat},
+ FormatMap{AL_FORMAT_61CHN_I32, FmtX61, FmtInt },
+ FormatMap{AL_FORMAT_61CHN_FLOAT32, FmtX61, FmtFloat},
+ FormatMap{AL_FORMAT_61CHN_MULAW, FmtX61, FmtMulaw},
+
+ FormatMap{AL_FORMAT_71CHN8, FmtX71, FmtUByte},
+ FormatMap{AL_FORMAT_71CHN16, FmtX71, FmtShort},
+ FormatMap{AL_FORMAT_71CHN32, FmtX71, FmtFloat},
+ FormatMap{AL_FORMAT_71CHN_I32, FmtX71, FmtInt },
+ FormatMap{AL_FORMAT_71CHN_FLOAT32, FmtX71, FmtFloat},
+ FormatMap{AL_FORMAT_71CHN_MULAW, FmtX71, FmtMulaw},
+
+ FormatMap{AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtUByte},
+ FormatMap{AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort},
+ FormatMap{AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat},
+ FormatMap{AL_FORMAT_BFORMAT2D_MULAW, FmtBFormat2D, FmtMulaw},
+
+ FormatMap{AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtUByte},
+ FormatMap{AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort},
+ FormatMap{AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat},
+ FormatMap{AL_FORMAT_BFORMAT3D_MULAW, FmtBFormat3D, FmtMulaw},
+
+ FormatMap{AL_FORMAT_UHJ2CHN8_SOFT, FmtUHJ2, FmtUByte },
+ FormatMap{AL_FORMAT_UHJ2CHN16_SOFT, FmtUHJ2, FmtShort },
+ FormatMap{AL_FORMAT_UHJ2CHN_I32, FmtUHJ2, FmtInt },
+ FormatMap{AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, FmtUHJ2, FmtFloat },
+ FormatMap{AL_FORMAT_UHJ2CHN_MULAW_SOFT, FmtUHJ2, FmtMulaw },
+ FormatMap{AL_FORMAT_UHJ2CHN_ALAW_SOFT, FmtUHJ2, FmtAlaw },
+ FormatMap{AL_FORMAT_UHJ2CHN_IMA4_SOFT, FmtUHJ2, FmtIMA4 },
+ FormatMap{AL_FORMAT_UHJ2CHN_MSADPCM_SOFT, FmtUHJ2, FmtMSADPCM},
+
+ FormatMap{AL_FORMAT_UHJ3CHN8_SOFT, FmtUHJ3, FmtUByte},
+ FormatMap{AL_FORMAT_UHJ3CHN16_SOFT, FmtUHJ3, FmtShort},
+ FormatMap{AL_FORMAT_UHJ3CHN_I32, FmtUHJ3, FmtInt },
+ FormatMap{AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, FmtUHJ3, FmtFloat},
+ FormatMap{AL_FORMAT_UHJ3CHN_MULAW_SOFT, FmtUHJ3, FmtMulaw},
+ FormatMap{AL_FORMAT_UHJ3CHN_ALAW_SOFT, FmtUHJ3, FmtAlaw },
+
+ FormatMap{AL_FORMAT_UHJ4CHN8_SOFT, FmtUHJ4, FmtUByte},
+ FormatMap{AL_FORMAT_UHJ4CHN16_SOFT, FmtUHJ4, FmtShort},
+ FormatMap{AL_FORMAT_UHJ4CHN_I32, FmtUHJ4, FmtInt },
+ FormatMap{AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, FmtUHJ4, FmtFloat},
+ FormatMap{AL_FORMAT_UHJ4CHN_MULAW_SOFT, FmtUHJ4, FmtMulaw},
+ FormatMap{AL_FORMAT_UHJ4CHN_ALAW_SOFT, FmtUHJ4, FmtAlaw },
+ };
for(const auto &fmt : UserFmtList)
{
if(fmt.format == format)
- return al::make_optional<DecompResult>({fmt.channels, fmt.type});
+ return DecompResult{fmt.channels, fmt.type};
}
- return al::nullopt;
+ return std::nullopt;
}
} // namespace
-AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGenBuffers, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Generating %d buffers", n);
if(n <= 0) UNLIKELY return;
@@ -661,7 +680,7 @@ START_API_FUNC
/* Store the allocated buffer IDs in a separate local list, to avoid
* modifying the user storage in case of failure.
*/
- al::vector<ALuint> ids;
+ std::vector<ALuint> ids;
ids.reserve(static_cast<ALuint>(n));
do {
ALbuffer *buffer{AllocBuffer(device)};
@@ -670,14 +689,11 @@ START_API_FUNC
std::copy(ids.begin(), ids.end(), buffers);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alDeleteBuffers, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n,
+ const ALuint *buffers) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Deleting %d buffers", n);
if(n <= 0) UNLIKELY return;
@@ -714,35 +730,32 @@ START_API_FUNC
};
std::for_each(buffers, buffers_end, delete_buffer);
}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsBuffer, ALuint)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) noexcept
{
- ContextRef context{GetContextRef()};
- if(context) LIKELY
- {
- ALCdevice *device{context->mALDevice.get()};
- std::lock_guard<std::mutex> _{device->BufferLock};
- if(!buffer || LookupBuffer(device, buffer))
- return AL_TRUE;
- }
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard<std::mutex> _{device->BufferLock};
+ if(!buffer || LookupBuffer(device, buffer))
+ return AL_TRUE;
return AL_FALSE;
}
-END_API_FUNC
-
-AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
-START_API_FUNC
-{ alBufferStorageSOFT(buffer, format, data, size, freq, 0); }
-END_API_FUNC
-AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags)
-START_API_FUNC
+AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) noexcept
{
- ContextRef context{GetContextRef()};
+ auto context = GetContextRef();
if(!context) UNLIKELY return;
+ alBufferStorageDirectSOFT(context.get(), buffer, format, data, size, freq, 0);
+}
+FORCE_ALIGN void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) noexcept
+{ alBufferStorageDirectSOFT(context, buffer, format, data, size, freq, 0); }
+
+AL_API DECL_FUNCEXT6(void, alBufferStorage,SOFT, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei, ALbitfieldSOFT)
+FORCE_ALIGN void AL_APIENTRY alBufferStorageDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) noexcept
+{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -766,20 +779,16 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else
{
- LoadData(context.get(), albuf, freq, static_cast<ALuint>(size), usrfmt->channels,
- usrfmt->type, static_cast<const al::byte*>(data), flags);
+ LoadData(context, albuf, freq, static_cast<ALuint>(size), usrfmt->channels,
+ usrfmt->type, static_cast<const std::byte*>(data), flags);
}
}
}
-END_API_FUNC
-void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, ALsizei size,
- ALsizei freq)
-START_API_FUNC
+DECL_FUNC5(void, alBufferDataStatic, ALuint, ALenum, ALvoid*, ALsizei, ALsizei)
+FORCE_ALIGN void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, const ALuint buffer,
+ ALenum format, ALvoid *data, ALsizei size, ALsizei freq) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -795,17 +804,14 @@ START_API_FUNC
if(!usrfmt) UNLIKELY
return context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
- PrepareUserPtr(context.get(), albuf, freq, usrfmt->channels, usrfmt->type,
- static_cast<al::byte*>(data), static_cast<ALuint>(size));
+ PrepareUserPtr(context, albuf, freq, usrfmt->channels, usrfmt->type,
+ static_cast<std::byte*>(data), static_cast<ALuint>(size));
}
-END_API_FUNC
-AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access)
-START_API_FUNC
+AL_API DECL_FUNCEXT4(void*, alMapBuffer,SOFT, ALuint, ALsizei, ALsizei, ALbitfieldSOFT)
+FORCE_ALIGN void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALsizei offset, ALsizei length, ALbitfieldSOFT access) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return nullptr;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -852,14 +858,10 @@ START_API_FUNC
return nullptr;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
-START_API_FUNC
+AL_API DECL_FUNCEXT1(void, alUnmapBuffer,SOFT, ALuint)
+FORCE_ALIGN void AL_APIENTRY alUnmapBufferDirectSOFT(ALCcontext *context, ALuint buffer) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -875,14 +877,11 @@ START_API_FUNC
albuf->MappedSize = 0;
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alFlushMappedBuffer,SOFT, ALuint, ALsizei, ALsizei)
+FORCE_ALIGN void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALsizei offset, ALsizei length) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -900,21 +899,18 @@ START_API_FUNC
else
{
/* FIXME: Need to use some method of double-buffering for the mixer and
- * app to hold separate memory, which can be safely transfered
+ * app to hold separate memory, which can be safely transferred
* asynchronously. Currently we just say the app shouldn't write where
* OpenAL's reading, and hope for the best...
*/
std::atomic_thread_fence(std::memory_order_seq_cst);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alBufferSubData,SOFT, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei)
+FORCE_ALIGN void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -966,61 +962,12 @@ START_API_FUNC
assert(al::to_underlying(usrfmt->type) == al::to_underlying(albuf->mType));
memcpy(albuf->mData.data()+offset, data, static_cast<ALuint>(length));
}
-END_API_FUNC
-
-
-AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplerate*/,
- ALenum /*internalformat*/, ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/,
- const ALvoid* /*data*/)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
-}
-END_API_FUNC
-
-AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/,
- ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, const ALvoid* /*data*/)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
-}
-END_API_FUNC
-
-AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/,
- ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, ALvoid* /*data*/)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
-}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return AL_FALSE;
-
- context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
- return AL_FALSE;
-}
-END_API_FUNC
-
-AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat /*value*/)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alBufferf, ALuint, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALfloat /*value*/) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1032,15 +979,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param,
- ALfloat /*value1*/, ALfloat /*value2*/, ALfloat /*value3*/)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alBuffer3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALfloat /*value1*/, ALfloat /*value2*/, ALfloat /*value3*/) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1052,14 +995,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alBufferfv, ALuint, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ const ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1073,15 +1013,12 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alBufferi, ALuint, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALint value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1135,15 +1072,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param,
- ALint /*value1*/, ALint /*value2*/, ALint /*value3*/)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alBuffer3i, ALuint, ALenum, ALint, ALint, ALint)
+FORCE_ALIGN void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALint /*value1*/, ALint /*value2*/, ALint /*value3*/) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1155,36 +1088,31 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alBufferiv, ALuint, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ const ALint *values) noexcept
{
- if(values)
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ switch(param)
{
- switch(param)
- {
- case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
- case AL_PACK_BLOCK_ALIGNMENT_SOFT:
- case AL_AMBISONIC_LAYOUT_SOFT:
- case AL_AMBISONIC_SCALING_SOFT:
- case AL_UNPACK_AMBISONIC_ORDER_SOFT:
- alBufferi(buffer, param, values[0]);
- return;
- }
+ case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+ case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+ case AL_AMBISONIC_LAYOUT_SOFT:
+ case AL_AMBISONIC_SCALING_SOFT:
+ case AL_UNPACK_AMBISONIC_ORDER_SOFT:
+ alBufferiDirect(context, buffer, param, values[0]);
+ return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if(!albuf) UNLIKELY
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
- else if(!values) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
case AL_LOOP_POINTS_SOFT:
@@ -1206,15 +1134,12 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetBufferf, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1234,14 +1159,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alGetBuffer3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1255,21 +1177,18 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetBufferfv, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALfloat *values) noexcept
{
switch(param)
{
case AL_SEC_LENGTH_SOFT:
- alGetBufferf(buffer, param, values);
+ alGetBufferfDirect(context, buffer, param, values);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1283,15 +1202,12 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetBufferi, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
@@ -1351,14 +1267,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alGetBuffer3i, ALuint, ALenum, ALint*, ALint*, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALint *value1, ALint *value2, ALint *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if(LookupBuffer(device, buffer) == nullptr) UNLIKELY
@@ -1371,10 +1284,10 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetBufferiv, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param,
+ ALint *values) noexcept
{
switch(param)
{
@@ -1390,13 +1303,10 @@ START_API_FUNC
case AL_AMBISONIC_LAYOUT_SOFT:
case AL_AMBISONIC_SCALING_SOFT:
case AL_UNPACK_AMBISONIC_ORDER_SOFT:
- alGetBufferi(buffer, param, values);
+ alGetBufferiDirect(context, buffer, param, values);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
@@ -1415,16 +1325,12 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq,
- ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alBufferCallback,SOFT, ALuint, ALenum, ALsizei, ALBUFFERCALLBACKTYPESOFT, ALvoid*)
+FORCE_ALIGN void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@@ -1441,18 +1347,15 @@ START_API_FUNC
if(!usrfmt) UNLIKELY
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else
- PrepareCallback(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, callback,
+ PrepareCallback(context, albuf, freq, usrfmt->channels, usrfmt->type, callback,
userptr);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetBufferPtr,SOFT, ALuint, ALenum, ALvoid**)
+FORCE_ALIGN void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALenum param, ALvoid **value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
@@ -1463,7 +1366,7 @@ START_API_FUNC
else switch(param)
{
case AL_BUFFER_CALLBACK_FUNCTION_SOFT:
- *value = reinterpret_cast<void*>(albuf->mCallback);
+ *value = al::bit_cast<void*>(albuf->mCallback);
break;
case AL_BUFFER_CALLBACK_USER_PARAM_SOFT:
*value = albuf->mUserData;
@@ -1473,14 +1376,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer pointer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alGetBuffer3Ptr,SOFT, ALuint, ALenum, ALvoid**, ALvoid**, ALvoid**)
+FORCE_ALIGN void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if(LookupBuffer(device, buffer) == nullptr) UNLIKELY
@@ -1493,22 +1393,19 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer 3-pointer property 0x%04x", param);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetBufferPtrv,SOFT, ALuint, ALenum, ALvoid**)
+FORCE_ALIGN void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer,
+ ALenum param, ALvoid **values) noexcept
{
switch(param)
{
case AL_BUFFER_CALLBACK_FUNCTION_SOFT:
case AL_BUFFER_CALLBACK_USER_PARAM_SOFT:
- alGetBufferPtrSOFT(buffer, param, values);
+ alGetBufferPtrDirectSOFT(context, buffer, param, values);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if(LookupBuffer(device, buffer) == nullptr) UNLIKELY
@@ -1521,16 +1418,69 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid buffer pointer-vector property 0x%04x", param);
}
}
-END_API_FUNC
+
+
+AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplerate*/,
+ ALenum /*internalformat*/, ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/,
+ const ALvoid* /*data*/) noexcept
+{
+ ContextRef context{GetContextRef()};
+ if(!context) UNLIKELY return;
+
+ context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
+}
+
+AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/,
+ ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, const ALvoid* /*data*/) noexcept
+{
+ ContextRef context{GetContextRef()};
+ if(!context) UNLIKELY return;
+
+ context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
+}
+
+AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/,
+ ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, ALvoid* /*data*/) noexcept
+{
+ ContextRef context{GetContextRef()};
+ if(!context) UNLIKELY return;
+
+ context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
+}
+
+AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) noexcept
+{
+ ContextRef context{GetContextRef()};
+ if(!context) UNLIKELY return AL_FALSE;
+
+ context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
+ return AL_FALSE;
+}
+
+
+void ALbuffer::SetName(ALCcontext *context, ALuint id, std::string_view name)
+{
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard<std::mutex> _{device->BufferLock};
+
+ auto buffer = LookupBuffer(device, id);
+ if(!buffer) UNLIKELY
+ return context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", id);
+
+ device->mBufferNames.insert_or_assign(id, name);
+}
BufferSubList::~BufferSubList()
{
+ if(!Buffers)
+ return;
+
uint64_t usemask{~FreeMask};
while(usemask)
{
const int idx{al::countr_zero(usemask)};
- al::destroy_at(Buffers+idx);
+ std::destroy_at(Buffers+idx);
usemask &= ~(1_u64 << idx);
}
FreeMask = ~usemask;
@@ -1540,93 +1490,82 @@ BufferSubList::~BufferSubList()
#ifdef ALSOFT_EAX
-FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint* buffers, ALint value)
-START_API_FUNC
+FORCE_ALIGN DECL_FUNC3(ALboolean, EAXSetBufferMode, ALsizei, const ALuint*, ALint)
+FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n,
+ const ALuint *buffers, ALint value) noexcept
{
#define EAX_PREFIX "[EAXSetBufferMode] "
- const auto context = ContextRef{GetContextRef()};
- if(!context)
- {
- ERR(EAX_PREFIX "%s\n", "No current context.");
- return ALC_FALSE;
- }
-
if(!eax_g_is_enabled)
{
context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled.");
- return ALC_FALSE;
+ return AL_FALSE;
}
const auto storage = EaxStorageFromEnum(value);
if(!storage)
{
context->setError(AL_INVALID_ENUM, EAX_PREFIX "Unsupported X-RAM mode 0x%x", value);
- return ALC_FALSE;
+ return AL_FALSE;
}
if(n == 0)
- return ALC_TRUE;
+ return AL_TRUE;
if(n < 0)
{
context->setError(AL_INVALID_VALUE, EAX_PREFIX "Buffer count %d out of range", n);
- return ALC_FALSE;
+ return AL_FALSE;
}
if(!buffers)
{
context->setError(AL_INVALID_VALUE, EAX_PREFIX "%s", "Null AL buffers");
- return ALC_FALSE;
+ return AL_FALSE;
}
auto device = context->mALDevice.get();
std::lock_guard<std::mutex> device_lock{device->BufferLock};
- size_t total_needed{0};
- // Validate the buffers.
- //
- for(auto i = 0;i < n;++i)
+ /* Special-case setting a single buffer, to avoid extraneous allocations. */
+ if(n == 1)
{
- const auto bufid = buffers[i];
+ const auto bufid = buffers[0];
if(bufid == AL_NONE)
- continue;
+ return AL_TRUE;
const auto buffer = LookupBuffer(device, bufid);
if(!buffer) UNLIKELY
{
ERR(EAX_PREFIX "Invalid buffer ID %u.\n", bufid);
- return ALC_FALSE;
+ return AL_FALSE;
}
/* TODO: Is the store location allowed to change for in-use buffers, or
* only when not set/queued on a source?
*/
- if(*storage == EaxStorage::Hardware && !buffer->eax_x_ram_is_hardware)
+ if(*storage == EaxStorage::Hardware)
{
- /* FIXME: This doesn't account for duplicate buffers. When the same
- * buffer ID is specified multiple times in the provided list, it
- * counts each instance as more memory that needs to fit in X-RAM.
- */
- if(std::numeric_limits<size_t>::max()-buffer->OriginalSize < total_needed) UNLIKELY
+ if(!buffer->eax_x_ram_is_hardware
+ && buffer->OriginalSize > device->eax_x_ram_free_size) UNLIKELY
{
- context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Size overflow (%u + %zu)\n",
- buffer->OriginalSize, total_needed);
- return ALC_FALSE;
+ context->setError(AL_OUT_OF_MEMORY,
+ EAX_PREFIX "Out of X-RAM memory (need: %u, avail: %u)", buffer->OriginalSize,
+ device->eax_x_ram_free_size);
+ return AL_FALSE;
}
- total_needed += buffer->OriginalSize;
+
+ eax_x_ram_apply(*device, *buffer);
}
- }
- if(total_needed > device->eax_x_ram_free_size)
- {
- context->setError(AL_OUT_OF_MEMORY,EAX_PREFIX "Out of X-RAM memory (need: %zu, avail: %u)",
- total_needed, device->eax_x_ram_free_size);
- return ALC_FALSE;
+ else
+ eax_x_ram_clear(*device, *buffer);
+ buffer->eax_x_ram_mode = *storage;
+ return AL_TRUE;
}
- // Update the mode.
- //
+ /* Validate the buffers. */
+ std::unordered_set<ALbuffer*> buflist;
for(auto i = 0;i < n;++i)
{
const auto bufid = buffers[i];
@@ -1634,8 +1573,47 @@ START_API_FUNC
continue;
const auto buffer = LookupBuffer(device, bufid);
- assert(buffer);
+ if(!buffer) UNLIKELY
+ {
+ ERR(EAX_PREFIX "Invalid buffer ID %u.\n", bufid);
+ return AL_FALSE;
+ }
+
+ /* TODO: Is the store location allowed to change for in-use buffers, or
+ * only when not set/queued on a source?
+ */
+
+ buflist.emplace(buffer);
+ }
+
+ if(*storage == EaxStorage::Hardware)
+ {
+ size_t total_needed{0};
+ for(ALbuffer *buffer : buflist)
+ {
+ if(!buffer->eax_x_ram_is_hardware)
+ {
+ if(std::numeric_limits<size_t>::max()-buffer->OriginalSize < total_needed) UNLIKELY
+ {
+ context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Size overflow (%u + %zu)\n",
+ buffer->OriginalSize, total_needed);
+ return AL_FALSE;
+ }
+ total_needed += buffer->OriginalSize;
+ }
+ }
+ if(total_needed > device->eax_x_ram_free_size)
+ {
+ context->setError(AL_OUT_OF_MEMORY,
+ EAX_PREFIX "Out of X-RAM memory (need: %zu, avail: %u)", total_needed,
+ device->eax_x_ram_free_size);
+ return AL_FALSE;
+ }
+ }
+ /* Update the mode. */
+ for(ALbuffer *buffer : buflist)
+ {
if(*storage == EaxStorage::Hardware)
eax_x_ram_apply(*device, *buffer);
else
@@ -1647,20 +1625,13 @@ START_API_FUNC
#undef EAX_PREFIX
}
-END_API_FUNC
-FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint* pReserved)
-START_API_FUNC
+FORCE_ALIGN DECL_FUNC2(ALenum, EAXGetBufferMode, ALuint, ALint*)
+FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer,
+ ALint *pReserved) noexcept
{
#define EAX_PREFIX "[EAXGetBufferMode] "
- const auto context = ContextRef{GetContextRef()};
- if(!context)
- {
- ERR(EAX_PREFIX "%s\n", "No current context.");
- return AL_NONE;
- }
-
if(!eax_g_is_enabled)
{
context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled.");
@@ -1687,6 +1658,5 @@ START_API_FUNC
#undef EAX_PREFIX
}
-END_API_FUNC
#endif // ALSOFT_EAX
diff --git a/al/buffer.h b/al/buffer.h
index 64ebe1f3..f936cf98 100644
--- a/al/buffer.h
+++ b/al/buffer.h
@@ -2,10 +2,11 @@
#define AL_BUFFER_H
#include <atomic>
+#include <cstddef>
+#include <string_view>
#include "AL/al.h"
-#include "albyte.h"
#include "alc/inprogext.h"
#include "almalloc.h"
#include "atomic.h"
@@ -26,7 +27,7 @@ enum class EaxStorage : uint8_t {
struct ALbuffer : public BufferStorage {
ALbitfieldSOFT Access{0u};
- al::vector<al::byte,16> mDataStorage;
+ al::vector<std::byte,16> mDataStorage;
ALuint OriginalSize{0};
@@ -47,6 +48,8 @@ struct ALbuffer : public BufferStorage {
/* Self ID */
ALuint id{0};
+ static void SetName(ALCcontext *context, ALuint id, std::string_view name);
+
DISABLE_ALLOC()
#ifdef ALSOFT_EAX
diff --git a/al/debug.cpp b/al/debug.cpp
new file mode 100644
index 00000000..b76ec9af
--- /dev/null
+++ b/al/debug.cpp
@@ -0,0 +1,570 @@
+#include "config.h"
+
+#include "debug.h"
+
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <mutex>
+#include <optional>
+#include <stddef.h>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include "AL/al.h"
+
+#include "alc/context.h"
+#include "alc/inprogext.h"
+#include "alspan.h"
+#include "auxeffectslot.h"
+#include "buffer.h"
+#include "core/logging.h"
+#include "direct_defs.h"
+#include "effect.h"
+#include "filter.h"
+#include "opthelpers.h"
+#include "source.h"
+
+
+/* Declared here to prevent compilers from thinking it should be inlined, which
+ * GCC warns about increasing code size.
+ */
+DebugGroup::~DebugGroup() = default;
+
+namespace {
+
+static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits");
+
+template<typename T, T ...Vals>
+constexpr auto make_array_sequence(std::integer_sequence<T, Vals...>)
+{ return std::array<T,sizeof...(Vals)>{Vals...}; }
+
+template<typename T, size_t N>
+constexpr auto make_array_sequence()
+{ return make_array_sequence(std::make_integer_sequence<T,N>{}); }
+
+
+constexpr std::optional<DebugSource> GetDebugSource(ALenum source) noexcept
+{
+ switch(source)
+ {
+ case AL_DEBUG_SOURCE_API_EXT: return DebugSource::API;
+ case AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT: return DebugSource::System;
+ case AL_DEBUG_SOURCE_THIRD_PARTY_EXT: return DebugSource::ThirdParty;
+ case AL_DEBUG_SOURCE_APPLICATION_EXT: return DebugSource::Application;
+ case AL_DEBUG_SOURCE_OTHER_EXT: return DebugSource::Other;
+ }
+ return std::nullopt;
+}
+
+constexpr std::optional<DebugType> GetDebugType(ALenum type) noexcept
+{
+ switch(type)
+ {
+ case AL_DEBUG_TYPE_ERROR_EXT: return DebugType::Error;
+ case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT: return DebugType::DeprecatedBehavior;
+ case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT: return DebugType::UndefinedBehavior;
+ case AL_DEBUG_TYPE_PORTABILITY_EXT: return DebugType::Portability;
+ case AL_DEBUG_TYPE_PERFORMANCE_EXT: return DebugType::Performance;
+ case AL_DEBUG_TYPE_MARKER_EXT: return DebugType::Marker;
+ case AL_DEBUG_TYPE_PUSH_GROUP_EXT: return DebugType::PushGroup;
+ case AL_DEBUG_TYPE_POP_GROUP_EXT: return DebugType::PopGroup;
+ case AL_DEBUG_TYPE_OTHER_EXT: return DebugType::Other;
+ }
+ return std::nullopt;
+}
+
+constexpr std::optional<DebugSeverity> GetDebugSeverity(ALenum severity) noexcept
+{
+ switch(severity)
+ {
+ case AL_DEBUG_SEVERITY_HIGH_EXT: return DebugSeverity::High;
+ case AL_DEBUG_SEVERITY_MEDIUM_EXT: return DebugSeverity::Medium;
+ case AL_DEBUG_SEVERITY_LOW_EXT: return DebugSeverity::Low;
+ case AL_DEBUG_SEVERITY_NOTIFICATION_EXT: return DebugSeverity::Notification;
+ }
+ return std::nullopt;
+}
+
+
+ALenum GetDebugSourceEnum(DebugSource source)
+{
+ switch(source)
+ {
+ case DebugSource::API: return AL_DEBUG_SOURCE_API_EXT;
+ case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT;
+ case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_EXT;
+ case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_EXT;
+ case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_EXT;
+ }
+ throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))};
+}
+
+ALenum GetDebugTypeEnum(DebugType type)
+{
+ switch(type)
+ {
+ case DebugType::Error: return AL_DEBUG_TYPE_ERROR_EXT;
+ case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT;
+ case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT;
+ case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_EXT;
+ case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_EXT;
+ case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_EXT;
+ case DebugType::PushGroup: return AL_DEBUG_TYPE_PUSH_GROUP_EXT;
+ case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_EXT;
+ case DebugType::Other: return AL_DEBUG_TYPE_OTHER_EXT;
+ }
+ throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))};
+}
+
+ALenum GetDebugSeverityEnum(DebugSeverity severity)
+{
+ switch(severity)
+ {
+ case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_EXT;
+ case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_EXT;
+ case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_EXT;
+ case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_EXT;
+ }
+ throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))};
+}
+
+
+const char *GetDebugSourceName(DebugSource source)
+{
+ switch(source)
+ {
+ case DebugSource::API: return "API";
+ case DebugSource::System: return "Audio System";
+ case DebugSource::ThirdParty: return "Third Party";
+ case DebugSource::Application: return "Application";
+ case DebugSource::Other: return "Other";
+ }
+ return "<invalid source>";
+}
+
+const char *GetDebugTypeName(DebugType type)
+{
+ switch(type)
+ {
+ case DebugType::Error: return "Error";
+ case DebugType::DeprecatedBehavior: return "Deprecated Behavior";
+ case DebugType::UndefinedBehavior: return "Undefined Behavior";
+ case DebugType::Portability: return "Portability";
+ case DebugType::Performance: return "Performance";
+ case DebugType::Marker: return "Marker";
+ case DebugType::PushGroup: return "Push Group";
+ case DebugType::PopGroup: return "Pop Group";
+ case DebugType::Other: return "Other";
+ }
+ return "<invalid type>";
+}
+
+const char *GetDebugSeverityName(DebugSeverity severity)
+{
+ switch(severity)
+ {
+ case DebugSeverity::High: return "High";
+ case DebugSeverity::Medium: return "Medium";
+ case DebugSeverity::Low: return "Low";
+ case DebugSeverity::Notification: return "Notification";
+ }
+ return "<invalid severity>";
+}
+
+} // namespace
+
+
+void ALCcontext::sendDebugMessage(std::unique_lock<std::mutex> &debuglock, DebugSource source,
+ DebugType type, ALuint id, DebugSeverity severity, std::string_view message)
+{
+ if(!mDebugEnabled.load()) UNLIKELY
+ return;
+
+ if(message.length() >= MaxDebugMessageLength) UNLIKELY
+ {
+ ERR("Debug message too long (%zu >= %d):\n-> %.*s\n", message.length(),
+ MaxDebugMessageLength, static_cast<int>(message.length()), message.data());
+ return;
+ }
+
+ DebugGroup &debug = mDebugGroups.back();
+
+ const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source)))
+ | (1_u64 << (DebugTypeBase+al::to_underlying(type)))
+ | (uint64_t{id} << 32)};
+ auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter);
+ if(iditer != debug.mIdFilters.cend() && *iditer == idfilter)
+ return;
+
+ const uint filter{(1u << (DebugSourceBase+al::to_underlying(source)))
+ | (1u << (DebugTypeBase+al::to_underlying(type)))
+ | (1u << (DebugSeverityBase+al::to_underlying(severity)))};
+ auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter);
+ if(iter != debug.mFilters.cend() && *iter == filter)
+ return;
+
+ if(mDebugCb)
+ {
+ auto callback = mDebugCb;
+ auto param = mDebugParam;
+ debuglock.unlock();
+ callback(GetDebugSourceEnum(source), GetDebugTypeEnum(type), id,
+ GetDebugSeverityEnum(severity), static_cast<ALsizei>(message.length()), message.data(),
+ param);
+ }
+ else
+ {
+ if(mDebugLog.size() < MaxDebugLoggedMessages)
+ mDebugLog.emplace_back(source, type, id, severity, message);
+ else UNLIKELY
+ ERR("Debug message log overflow. Lost message:\n"
+ " Source: %s\n"
+ " Type: %s\n"
+ " ID: %u\n"
+ " Severity: %s\n"
+ " Message: \"%.*s\"\n",
+ GetDebugSourceName(source), GetDebugTypeName(type), id,
+ GetDebugSeverityName(severity), static_cast<int>(message.length()),
+ message.data());
+ }
+}
+
+
+FORCE_ALIGN DECL_FUNCEXT2(void, alDebugMessageCallback,EXT, ALDEBUGPROCEXT, void*)
+FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context,
+ ALDEBUGPROCEXT callback, void *userParam) noexcept
+{
+ std::lock_guard<std::mutex> _{context->mDebugCbLock};
+ context->mDebugCb = callback;
+ context->mDebugParam = userParam;
+}
+
+
+FORCE_ALIGN DECL_FUNCEXT6(void, alDebugMessageInsert,EXT, ALenum, ALenum, ALuint, ALenum, ALsizei, const ALchar*)
+FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source,
+ ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept
+{
+ if(!context->mContextFlags.test(ContextFlags::DebugBit))
+ return;
+
+ if(!message) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Null message pointer");
+
+ auto msgview = (length < 0) ? std::string_view{message}
+ : std::string_view{message, static_cast<uint>(length)};
+ if(msgview.length() >= MaxDebugMessageLength) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)",
+ msgview.length(), MaxDebugMessageLength);
+
+ auto dsource = GetDebugSource(source);
+ if(!dsource)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source);
+ if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application)
+ return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source);
+
+ auto dtype = GetDebugType(type);
+ if(!dtype)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type);
+
+ auto dseverity = GetDebugSeverity(severity);
+ if(!dseverity)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity);
+
+ context->debugMessage(*dsource, *dtype, id, *dseverity, msgview);
+}
+
+
+FORCE_ALIGN DECL_FUNCEXT6(void, alDebugMessageControl,EXT, ALenum, ALenum, ALenum, ALsizei, const ALuint*, ALboolean)
+FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source,
+ ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept
+{
+ if(count > 0)
+ {
+ if(!ids)
+ return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count");
+ if(source == AL_DONT_CARE_EXT)
+ return context->setError(AL_INVALID_OPERATION,
+ "Debug source cannot be AL_DONT_CARE_EXT with IDs");
+ if(type == AL_DONT_CARE_EXT)
+ return context->setError(AL_INVALID_OPERATION,
+ "Debug type cannot be AL_DONT_CARE_EXT with IDs");
+ if(severity != AL_DONT_CARE_EXT)
+ return context->setError(AL_INVALID_OPERATION,
+ "Debug severity must be AL_DONT_CARE_EXT with IDs");
+ }
+
+ if(enable != AL_TRUE && enable != AL_FALSE)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug enable %d", enable);
+
+ static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount};
+ static constexpr auto Values = make_array_sequence<uint8_t,ElemCount>();
+
+ auto srcIndices = al::span{Values}.subspan(DebugSourceBase,DebugSourceCount);
+ if(source != AL_DONT_CARE_EXT)
+ {
+ auto dsource = GetDebugSource(source);
+ if(!dsource)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source);
+ srcIndices = srcIndices.subspan(al::to_underlying(*dsource), 1);
+ }
+
+ auto typeIndices = al::span{Values}.subspan(DebugTypeBase,DebugTypeCount);
+ if(type != AL_DONT_CARE_EXT)
+ {
+ auto dtype = GetDebugType(type);
+ if(!dtype)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type);
+ typeIndices = typeIndices.subspan(al::to_underlying(*dtype), 1);
+ }
+
+ auto svrIndices = al::span{Values}.subspan(DebugSeverityBase,DebugSeverityCount);
+ if(severity != AL_DONT_CARE_EXT)
+ {
+ auto dseverity = GetDebugSeverity(severity);
+ if(!dseverity)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity);
+ svrIndices = svrIndices.subspan(al::to_underlying(*dseverity), 1);
+ }
+
+ std::lock_guard<std::mutex> _{context->mDebugCbLock};
+ DebugGroup &debug = context->mDebugGroups.back();
+ if(count > 0)
+ {
+ const uint filterbase{(1u<<srcIndices[0]) | (1u<<typeIndices[0])};
+
+ for(const uint id : al::span{ids, static_cast<uint>(count)})
+ {
+ const uint64_t filter{filterbase | (uint64_t{id} << 32)};
+
+ auto iter = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(),
+ filter);
+ if(!enable && (iter == debug.mIdFilters.cend() || *iter != filter))
+ debug.mIdFilters.insert(iter, filter);
+ else if(enable && iter != debug.mIdFilters.cend() && *iter == filter)
+ debug.mIdFilters.erase(iter);
+ }
+ }
+ else
+ {
+ auto apply_filter = [enable,&debug](const uint filter)
+ {
+ auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter);
+ if(!enable && (iter == debug.mFilters.cend() || *iter != filter))
+ debug.mFilters.insert(iter, filter);
+ else if(enable && iter != debug.mFilters.cend() && *iter == filter)
+ debug.mFilters.erase(iter);
+ };
+ auto apply_severity = [apply_filter,svrIndices](const uint filter)
+ {
+ std::for_each(svrIndices.cbegin(), svrIndices.cend(),
+ [apply_filter,filter](const uint idx){ apply_filter(filter | (1<<idx)); });
+ };
+ auto apply_type = [apply_severity,typeIndices](const uint filter)
+ {
+ std::for_each(typeIndices.cbegin(), typeIndices.cend(),
+ [apply_severity,filter](const uint idx){ apply_severity(filter | (1<<idx)); });
+ };
+ std::for_each(srcIndices.cbegin(), srcIndices.cend(),
+ [apply_type](const uint idx){ apply_type(1<<idx); });
+ }
+}
+
+
+FORCE_ALIGN DECL_FUNCEXT4(void, alPushDebugGroup,EXT, ALenum, ALuint, ALsizei, const ALchar*)
+FORCE_ALIGN void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source,
+ ALuint id, ALsizei length, const ALchar *message) noexcept
+{
+ if(length < 0)
+ {
+ size_t newlen{std::strlen(message)};
+ if(newlen >= MaxDebugMessageLength) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)",
+ newlen, MaxDebugMessageLength);
+ length = static_cast<ALsizei>(newlen);
+ }
+ else if(length >= MaxDebugMessageLength) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length,
+ MaxDebugMessageLength);
+
+ auto dsource = GetDebugSource(source);
+ if(!dsource)
+ return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source);
+ if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application)
+ return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source);
+
+ std::unique_lock<std::mutex> debuglock{context->mDebugCbLock};
+ if(context->mDebugGroups.size() >= MaxDebugGroupDepth)
+ {
+ debuglock.unlock();
+ return context->setError(AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups");
+ }
+
+ context->mDebugGroups.emplace_back(*dsource, id,
+ std::string_view{message, static_cast<uint>(length)});
+ auto &oldback = *(context->mDebugGroups.end()-2);
+ auto &newback = context->mDebugGroups.back();
+
+ newback.mFilters = oldback.mFilters;
+ newback.mIdFilters = oldback.mIdFilters;
+
+ if(context->mContextFlags.test(ContextFlags::DebugBit))
+ context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId,
+ DebugSeverity::Notification, newback.mMessage);
+}
+
+FORCE_ALIGN DECL_FUNCEXT(void, alPopDebugGroup,EXT)
+FORCE_ALIGN void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexcept
+{
+ std::unique_lock<std::mutex> debuglock{context->mDebugCbLock};
+ if(context->mDebugGroups.size() <= 1)
+ {
+ debuglock.unlock();
+ return context->setError(AL_STACK_UNDERFLOW_EXT,
+ "Attempting to pop the default debug group");
+ }
+
+ DebugGroup &debug = context->mDebugGroups.back();
+ const auto source = debug.mSource;
+ const auto id = debug.mId;
+ std::string message{std::move(debug.mMessage)};
+
+ context->mDebugGroups.pop_back();
+ if(context->mContextFlags.test(ContextFlags::DebugBit))
+ context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id,
+ DebugSeverity::Notification, message);
+}
+
+
+FORCE_ALIGN DECL_FUNCEXT8(ALuint, alGetDebugMessageLog,EXT, ALuint, ALsizei, ALenum*, ALenum*, ALuint*, ALenum*, ALsizei*, ALchar*)
+FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count,
+ ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities,
+ ALsizei *lengths, ALchar *logBuf) noexcept
+{
+ if(logBufSize < 0)
+ {
+ context->setError(AL_INVALID_VALUE, "Negative debug log buffer size");
+ return 0;
+ }
+
+ std::lock_guard<std::mutex> _{context->mDebugCbLock};
+ ALsizei logBufWritten{0};
+ for(ALuint i{0};i < count;++i)
+ {
+ if(context->mDebugLog.empty())
+ return i;
+
+ auto &entry = context->mDebugLog.front();
+ const size_t tocopy{entry.mMessage.size() + 1};
+ if(logBuf)
+ {
+ const size_t avail{static_cast<ALuint>(logBufSize - logBufWritten)};
+ if(avail < tocopy)
+ return i;
+ std::copy_n(entry.mMessage.data(), tocopy, logBuf+logBufWritten);
+ logBufWritten += static_cast<ALsizei>(tocopy);
+ }
+
+ if(sources) sources[i] = GetDebugSourceEnum(entry.mSource);
+ if(types) types[i] = GetDebugTypeEnum(entry.mType);
+ if(ids) ids[i] = entry.mId;
+ if(severities) severities[i] = GetDebugSeverityEnum(entry.mSeverity);
+ if(lengths) lengths[i] = static_cast<ALsizei>(tocopy);
+
+ context->mDebugLog.pop_front();
+ }
+
+ return count;
+}
+
+FORCE_ALIGN DECL_FUNCEXT4(void, alObjectLabel,EXT, ALenum, ALuint, ALsizei, const ALchar*)
+FORCE_ALIGN void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier,
+ ALuint name, ALsizei length, const ALchar *label) noexcept
+{
+ if(!label && length != 0) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Null label pointer");
+
+ auto objname = (length < 0) ? std::string_view{label}
+ : std::string_view{label, static_cast<uint>(length)};
+ if(objname.length() >= MaxObjectLabelLength) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Object label length too long (%zu >= %d)",
+ objname.length(), MaxObjectLabelLength);
+
+ if(identifier == AL_SOURCE_EXT)
+ return ALsource::SetName(context, name, objname);
+ if(identifier == AL_BUFFER)
+ return ALbuffer::SetName(context, name, objname);
+ if(identifier == AL_FILTER_EXT)
+ return ALfilter::SetName(context, name, objname);
+ if(identifier == AL_EFFECT_EXT)
+ return ALeffect::SetName(context, name, objname);
+ if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT)
+ return ALeffectslot::SetName(context, name, objname);
+
+ return context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier);
+}
+
+FORCE_ALIGN DECL_FUNCEXT5(void, alGetObjectLabel,EXT, ALenum, ALuint, ALsizei, ALsizei*, ALchar*)
+FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier,
+ ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) noexcept
+{
+ if(bufSize < 0) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Negative label bufSize");
+
+ if(!label && !length) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Null length and label");
+ if(label && bufSize == 0) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "Zero label bufSize");
+
+ auto copy_name = [name,bufSize,length,label](std::unordered_map<ALuint,std::string> &names)
+ {
+ std::string_view objname;
+
+ auto iter = names.find(name);
+ if(iter != names.end())
+ objname = iter->second;
+
+ if(!label)
+ *length = static_cast<ALsizei>(objname.length());
+ else
+ {
+ const size_t tocopy{minz(objname.length(), static_cast<uint>(bufSize)-1)};
+ std::memcpy(label, objname.data(), tocopy);
+ label[tocopy] = '\0';
+ if(length)
+ *length = static_cast<ALsizei>(tocopy);
+ }
+ };
+
+ if(identifier == AL_SOURCE_EXT)
+ {
+ std::lock_guard _{context->mSourceLock};
+ copy_name(context->mSourceNames);
+ }
+ else if(identifier == AL_BUFFER)
+ {
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard _{device->BufferLock};
+ copy_name(device->mBufferNames);
+ }
+ else if(identifier == AL_FILTER_EXT)
+ {
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard _{device->FilterLock};
+ copy_name(device->mFilterNames);
+ }
+ else if(identifier == AL_EFFECT_EXT)
+ {
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard _{device->EffectLock};
+ copy_name(device->mEffectNames);
+ }
+ else if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT)
+ {
+ std::lock_guard _{context->mEffectSlotLock};
+ copy_name(context->mEffectSlotNames);
+ }
+ else
+ context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier);
+}
diff --git a/al/debug.h b/al/debug.h
new file mode 100644
index 00000000..351be9c0
--- /dev/null
+++ b/al/debug.h
@@ -0,0 +1,69 @@
+#ifndef AL_DEBUG_H
+#define AL_DEBUG_H
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+using uint = unsigned int;
+
+
+/* Somewhat arbitrary. Avoid letting it get out of control if the app enables
+ * logging but never reads it.
+ */
+inline constexpr uint8_t MaxDebugLoggedMessages{64};
+inline constexpr uint16_t MaxDebugMessageLength{1024};
+inline constexpr uint8_t MaxDebugGroupDepth{64};
+inline constexpr uint16_t MaxObjectLabelLength{1024};
+
+
+inline constexpr uint DebugSourceBase{0};
+enum class DebugSource : uint8_t {
+ API = 0,
+ System,
+ ThirdParty,
+ Application,
+ Other,
+};
+inline constexpr uint DebugSourceCount{5};
+
+inline constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount};
+enum class DebugType : uint8_t {
+ Error = 0,
+ DeprecatedBehavior,
+ UndefinedBehavior,
+ Portability,
+ Performance,
+ Marker,
+ PushGroup,
+ PopGroup,
+ Other,
+};
+inline constexpr uint DebugTypeCount{9};
+
+inline constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount};
+enum class DebugSeverity : uint8_t {
+ High = 0,
+ Medium,
+ Low,
+ Notification,
+};
+inline constexpr uint DebugSeverityCount{4};
+
+struct DebugGroup {
+ const uint mId;
+ const DebugSource mSource;
+ std::string mMessage;
+ std::vector<uint> mFilters;
+ std::vector<uint64_t> mIdFilters;
+
+ template<typename T>
+ DebugGroup(DebugSource source, uint id, T&& message)
+ : mId{id}, mSource{source}, mMessage{std::forward<T>(message)}
+ { }
+ DebugGroup(const DebugGroup&) = default;
+ DebugGroup(DebugGroup&&) = default;
+ ~DebugGroup();
+};
+
+#endif /* AL_DEBUG_H */
diff --git a/al/direct_defs.h b/al/direct_defs.h
new file mode 100644
index 00000000..7526b611
--- /dev/null
+++ b/al/direct_defs.h
@@ -0,0 +1,127 @@
+#ifndef AL_DIRECT_DEFS_H
+#define AL_DIRECT_DEFS_H
+
+namespace detail_ {
+
+template<typename T>
+constexpr T DefaultVal() noexcept { return T{}; }
+
+template<>
+constexpr void DefaultVal() noexcept { }
+
+} // namespace detail_
+
+#define DECL_FUNC(R, Name) \
+R AL_APIENTRY Name(void) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct(context.get()); \
+}
+
+#define DECL_FUNC1(R, Name, T1) \
+R AL_APIENTRY Name(T1 a) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct(context.get(), a); \
+}
+
+#define DECL_FUNC2(R, Name, T1, T2) \
+R AL_APIENTRY Name(T1 a, T2 b) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct(context.get(), a, b); \
+}
+
+#define DECL_FUNC3(R, Name, T1, T2, T3) \
+R AL_APIENTRY Name(T1 a, T2 b, T3 c) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct(context.get(), a, b, c); \
+}
+
+#define DECL_FUNC4(R, Name, T1, T2, T3, T4) \
+R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct(context.get(), a, b, c, d); \
+}
+
+#define DECL_FUNC5(R, Name, T1, T2, T3, T4, T5) \
+R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d, T5 e) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct(context.get(), a, b, c, d, e); \
+}
+
+
+#define DECL_FUNCEXT(R, Name,Ext) \
+R AL_APIENTRY Name##Ext(void) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get()); \
+}
+
+#define DECL_FUNCEXT1(R, Name,Ext, T1) \
+R AL_APIENTRY Name##Ext(T1 a) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a); \
+}
+
+#define DECL_FUNCEXT2(R, Name,Ext, T1, T2) \
+R AL_APIENTRY Name##Ext(T1 a, T2 b) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a, b); \
+}
+
+#define DECL_FUNCEXT3(R, Name,Ext, T1, T2, T3) \
+R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a, b, c); \
+}
+
+#define DECL_FUNCEXT4(R, Name,Ext, T1, T2, T3, T4) \
+R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a, b, c, d); \
+}
+
+#define DECL_FUNCEXT5(R, Name,Ext, T1, T2, T3, T4, T5) \
+R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a, b, c, d, e); \
+}
+
+#define DECL_FUNCEXT6(R, Name,Ext, T1, T2, T3, T4, T5, T6) \
+R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a, b, c, d, e, f); \
+}
+
+#define DECL_FUNCEXT8(R, Name,Ext, T1, T2, T3, T4, T5, T6, T7, T8) \
+R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f, T7 g, T8 h) noexcept \
+{ \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return detail_::DefaultVal<R>(); \
+ return Name##Direct##Ext(context.get(), a, b, c, d, e, f, g, h); \
+}
+
+#endif /* AL_DIRECT_DEFS_H */
diff --git a/al/eax/api.h b/al/eax/api.h
index d254da1f..18d93ef8 100644
--- a/al/eax/api.h
+++ b/al/eax/api.h
@@ -10,17 +10,18 @@
//
+#include <array>
#include <cfloat>
#include <cstdint>
#include <cstring>
-
-#include <array>
+#ifdef _WIN32
+#include <guiddef.h>
+#endif
#include "AL/al.h"
-#ifndef GUID_DEFINED
-#define GUID_DEFINED
+#ifndef _WIN32
typedef struct _GUID {
std::uint32_t Data1;
std::uint16_t Data2;
@@ -28,16 +29,16 @@ typedef struct _GUID {
std::uint8_t Data4[8];
} GUID;
-#ifndef _SYS_GUID_OPERATOR_EQ_
-#define _SYS_GUID_OPERATOR_EQ_
inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept
{ return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; }
inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept
{ return !(lhs == rhs); }
-#endif // _SYS_GUID_OPERATOR_EQ_
-#endif // GUID_DEFINED
+#endif // _WIN32
+#define DECL_EQOP(T) \
+friend bool operator==(const T &lhs, const T &rhs) noexcept { return std::memcmp(&lhs, &rhs, sizeof(T)) == 0; } \
+friend bool operator!=(const T &lhs, const T &rhs) noexcept { return !(lhs == rhs); }
extern const GUID DSPROPSETID_EAX_ReverbProperties;
@@ -613,7 +614,7 @@ struct EAX30SOURCEPROPERTIES {
float flOcclusionLFRatio; // occlusion low-frequency level re. main control
float flOcclusionRoomRatio; // relative occlusion control for room effect
float flOcclusionDirectRatio; // relative occlusion control for direct path
- long lExclusion; // main exlusion control (attenuation at high frequencies)
+ long lExclusion; // main exclusion control (attenuation at high frequencies)
float flExclusionLFRatio; // exclusion low-frequency level re. main control
long lOutsideVolumeHF; // outside sound cone level at high frequencies
float flDopplerFactor; // like DS3D flDopplerFactor but per source
@@ -836,6 +837,7 @@ struct EAXREVERBPROPERTIES {
float flLFReference; // reference low frequency
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
unsigned long ulFlags; // modifies the behavior of properties
+ DECL_EQOP(EAXREVERBPROPERTIES)
}; // EAXREVERBPROPERTIES
@@ -965,6 +967,7 @@ enum EAXAGCCOMPRESSOR_PROPERTY : unsigned int {
struct EAXAGCCOMPRESSORPROPERTIES {
unsigned long ulOnOff; // Switch Compressor on or off
+ DECL_EQOP(EAXAGCCOMPRESSORPROPERTIES)
}; // EAXAGCCOMPRESSORPROPERTIES
@@ -991,6 +994,7 @@ struct EAXAUTOWAHPROPERTIES {
float flReleaseTime; // Release time (seconds)
long lResonance; // Resonance (mB)
long lPeakLevel; // Peak level (mB)
+ DECL_EQOP(EAXAUTOWAHPROPERTIES)
}; // EAXAUTOWAHPROPERTIES
@@ -1038,6 +1042,7 @@ struct EAXCHORUSPROPERTIES {
float flDepth; // Depth (0 to 1)
float flFeedback; // Feedback (-1 to 1)
float flDelay; // Delay (seconds)
+ DECL_EQOP(EAXCHORUSPROPERTIES)
}; // EAXCHORUSPROPERTIES
@@ -1086,6 +1091,7 @@ struct EAXDISTORTIONPROPERTIES {
float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz)
float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz)
float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz)
+ DECL_EQOP(EAXDISTORTIONPROPERTIES)
}; // EAXDISTORTIONPROPERTIES
@@ -1130,6 +1136,7 @@ struct EAXECHOPROPERTIES {
float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1)
float flFeedback; // Controls the duration of echo repetition (0 to 1)
float flSpread; // Controls the left-right spread of the echoes
+ DECL_EQOP(EAXECHOPROPERTIES)
}; // EAXECHOPROPERTIES
@@ -1184,6 +1191,7 @@ struct EAXEQUALIZERPROPERTIES {
float flMid2Width; // (octaves)
long lHighGain; // (mB)
float flHighCutOff; // (Hz)
+ DECL_EQOP(EAXEQUALIZERPROPERTIES)
}; // EAXEQUALIZERPROPERTIES
@@ -1255,6 +1263,7 @@ struct EAXFLANGERPROPERTIES {
float flDepth; // Depth (0 to 1)
float flFeedback; // Feedback (0 to 1)
float flDelay; // Delay (seconds)
+ DECL_EQOP(EAXFLANGERPROPERTIES)
}; // EAXFLANGERPROPERTIES
@@ -1305,6 +1314,7 @@ struct EAXFREQUENCYSHIFTERPROPERTIES {
float flFrequency; // (Hz)
unsigned long ulLeftDirection; // see enum above
unsigned long ulRightDirection; // see enum above
+ DECL_EQOP(EAXFREQUENCYSHIFTERPROPERTIES)
}; // EAXFREQUENCYSHIFTERPROPERTIES
@@ -1383,6 +1393,7 @@ struct EAXVOCALMORPHERPROPERTIES {
long lPhonemeBCoarseTuning; // (semitones)
unsigned long ulWaveform; // Waveform selector - see enum above
float flRate; // (Hz)
+ DECL_EQOP(EAXVOCALMORPHERPROPERTIES)
}; // EAXVOCALMORPHERPROPERTIES
@@ -1425,6 +1436,7 @@ enum EAXPITCHSHIFTER_PROPERTY : unsigned int {
struct EAXPITCHSHIFTERPROPERTIES {
long lCoarseTune; // Amount of pitch shift (semitones)
long lFineTune; // Amount of pitch shift (cents)
+ DECL_EQOP(EAXPITCHSHIFTERPROPERTIES)
}; // EAXPITCHSHIFTERPROPERTIES
@@ -1460,6 +1472,7 @@ struct EAXRINGMODULATORPROPERTIES {
float flFrequency; // Frequency of modulation (Hz)
float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz)
unsigned long ulWaveform; // Waveform selector - see enum above
+ DECL_EQOP(EAXRINGMODULATORPROPERTIES)
}; // EAXRINGMODULATORPROPERTIES
@@ -1490,4 +1503,5 @@ using LPEAXGET = ALenum(AL_APIENTRY*)(
ALvoid* property_buffer,
ALuint property_size);
+#undef DECL_EQOP
#endif // !EAX_API_INCLUDED
diff --git a/al/eax/call.h b/al/eax/call.h
index 5ec33b0f..45ff328c 100644
--- a/al/eax/call.h
+++ b/al/eax/call.h
@@ -55,13 +55,13 @@ public:
fail_too_small();
const auto count = minz(mPropertyBufferSize / sizeof(TValue), max_count);
- return al::as_span(static_cast<TValue*>(mPropertyBuffer), count);
+ return {static_cast<TValue*>(mPropertyBuffer), count};
}
template<typename TValue>
al::span<TValue> get_values() const
{
- return get_values<TValue>(~size_t{});
+ return get_values<TValue>(~0_uz);
}
template<typename TException, typename TValue>
diff --git a/al/eax/effect.h b/al/eax/effect.h
index a0b4e71b..afe4d94d 100644
--- a/al/eax/effect.h
+++ b/al/eax/effect.h
@@ -4,60 +4,55 @@
#include <cassert>
#include <memory>
+#include <variant>
#include "alnumeric.h"
#include "AL/al.h"
#include "core/effects/base.h"
#include "call.h"
-struct EaxEffectErrorMessages
-{
+struct EaxEffectErrorMessages {
static constexpr auto unknown_property_id() noexcept { return "Unknown property id."; }
static constexpr auto unknown_version() noexcept { return "Unknown version."; }
}; // EaxEffectErrorMessages
-/* TODO: Use std::variant (C++17). */
-enum class EaxEffectType {
- None, Reverb, Chorus, Autowah, Compressor, Distortion, Echo, Equalizer, Flanger,
- FrequencyShifter, Modulator, PitchShifter, VocalMorpher
-};
-struct EaxEffectProps {
- EaxEffectType mType;
- union {
- EAXREVERBPROPERTIES mReverb;
- EAXCHORUSPROPERTIES mChorus;
- EAXAUTOWAHPROPERTIES mAutowah;
- EAXAGCCOMPRESSORPROPERTIES mCompressor;
- EAXDISTORTIONPROPERTIES mDistortion;
- EAXECHOPROPERTIES mEcho;
- EAXEQUALIZERPROPERTIES mEqualizer;
- EAXFLANGERPROPERTIES mFlanger;
- EAXFREQUENCYSHIFTERPROPERTIES mFrequencyShifter;
- EAXRINGMODULATORPROPERTIES mModulator;
- EAXPITCHSHIFTERPROPERTIES mPitchShifter;
- EAXVOCALMORPHERPROPERTIES mVocalMorpher;
- };
-};
-
-constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props)
+using EaxEffectProps = std::variant<std::monostate,
+ EAXREVERBPROPERTIES,
+ EAXCHORUSPROPERTIES,
+ EAXAUTOWAHPROPERTIES,
+ EAXAGCCOMPRESSORPROPERTIES,
+ EAXDISTORTIONPROPERTIES,
+ EAXECHOPROPERTIES,
+ EAXEQUALIZERPROPERTIES,
+ EAXFLANGERPROPERTIES,
+ EAXFREQUENCYSHIFTERPROPERTIES,
+ EAXRINGMODULATORPROPERTIES,
+ EAXPITCHSHIFTERPROPERTIES,
+ EAXVOCALMORPHERPROPERTIES>;
+
+template<typename... Ts>
+struct overloaded : Ts... { using Ts::operator()...; };
+
+template<typename... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
+
+constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props) noexcept
{
- switch(props.mType)
- {
- case EaxEffectType::None: break;
- case EaxEffectType::Reverb: return AL_EFFECT_EAXREVERB;
- case EaxEffectType::Chorus: return AL_EFFECT_CHORUS;
- case EaxEffectType::Autowah: return AL_EFFECT_AUTOWAH;
- case EaxEffectType::Compressor: return AL_EFFECT_COMPRESSOR;
- case EaxEffectType::Distortion: return AL_EFFECT_DISTORTION;
- case EaxEffectType::Echo: return AL_EFFECT_ECHO;
- case EaxEffectType::Equalizer: return AL_EFFECT_EQUALIZER;
- case EaxEffectType::Flanger: return AL_EFFECT_FLANGER;
- case EaxEffectType::FrequencyShifter: return AL_EFFECT_FREQUENCY_SHIFTER;
- case EaxEffectType::Modulator: return AL_EFFECT_RING_MODULATOR;
- case EaxEffectType::PitchShifter: return AL_EFFECT_PITCH_SHIFTER;
- case EaxEffectType::VocalMorpher: return AL_EFFECT_VOCAL_MORPHER;
- }
- return AL_EFFECT_NULL;
+ return std::visit(overloaded{
+ [](const std::monostate&) noexcept { return AL_EFFECT_NULL; },
+ [](const EAXREVERBPROPERTIES&) noexcept { return AL_EFFECT_EAXREVERB; },
+ [](const EAXCHORUSPROPERTIES&) noexcept { return AL_EFFECT_CHORUS; },
+ [](const EAXAUTOWAHPROPERTIES&) noexcept { return AL_EFFECT_AUTOWAH; },
+ [](const EAXAGCCOMPRESSORPROPERTIES&) noexcept { return AL_EFFECT_COMPRESSOR; },
+ [](const EAXDISTORTIONPROPERTIES&) noexcept { return AL_EFFECT_DISTORTION; },
+ [](const EAXECHOPROPERTIES&) noexcept { return AL_EFFECT_ECHO; },
+ [](const EAXEQUALIZERPROPERTIES&) noexcept { return AL_EFFECT_EQUALIZER; },
+ [](const EAXFLANGERPROPERTIES&) noexcept { return AL_EFFECT_FLANGER; },
+ [](const EAXFREQUENCYSHIFTERPROPERTIES&) noexcept { return AL_EFFECT_FREQUENCY_SHIFTER; },
+ [](const EAXRINGMODULATORPROPERTIES&) noexcept { return AL_EFFECT_RING_MODULATOR; },
+ [](const EAXPITCHSHIFTERPROPERTIES&) noexcept { return AL_EFFECT_PITCH_SHIFTER; },
+ [](const EAXVOCALMORPHERPROPERTIES&) noexcept { return AL_EFFECT_VOCAL_MORPHER; }
+ }, props);
}
struct EaxReverbCommitter {
@@ -300,30 +295,30 @@ public:
}
-#define EAXCALL(T, Callable, ...) \
- if(T == EaxEffectType::Reverb) \
+#define EAXCALL(Props, Callable, ...) \
+ if(std::holds_alternative<EAXREVERBPROPERTIES>(Props)) \
return Callable<EaxReverbCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Chorus) \
+ if(std::holds_alternative<EAXCHORUSPROPERTIES>(Props)) \
return Callable<EaxChorusCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Autowah) \
+ if(std::holds_alternative<EAXAUTOWAHPROPERTIES>(Props)) \
return Callable<EaxAutowahCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Compressor) \
+ if(std::holds_alternative<EAXAGCCOMPRESSORPROPERTIES>(Props)) \
return Callable<EaxCompressorCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Distortion) \
+ if(std::holds_alternative<EAXDISTORTIONPROPERTIES>(Props)) \
return Callable<EaxDistortionCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Echo) \
+ if(std::holds_alternative<EAXECHOPROPERTIES>(Props)) \
return Callable<EaxEchoCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Equalizer) \
+ if(std::holds_alternative<EAXEQUALIZERPROPERTIES>(Props)) \
return Callable<EaxEqualizerCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Flanger) \
+ if(std::holds_alternative<EAXFLANGERPROPERTIES>(Props)) \
return Callable<EaxFlangerCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::FrequencyShifter) \
+ if(std::holds_alternative<EAXFREQUENCYSHIFTERPROPERTIES>(Props)) \
return Callable<EaxFrequencyShifterCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::Modulator) \
+ if(std::holds_alternative<EAXRINGMODULATORPROPERTIES>(Props)) \
return Callable<EaxModulatorCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::PitchShifter) \
+ if(std::holds_alternative<EAXPITCHSHIFTERPROPERTIES>(Props)) \
return Callable<EaxPitchShifterCommitter>(__VA_ARGS__); \
- if(T == EaxEffectType::VocalMorpher) \
+ if(std::holds_alternative<EAXVOCALMORPHERPROPERTIES>(Props)) \
return Callable<EaxVocalMorpherCommitter>(__VA_ARGS__); \
return Callable<EaxNullCommitter>(__VA_ARGS__)
@@ -332,7 +327,7 @@ public:
{ return T::Set(std::forward<Args>(args)...); }
static void call_set(const EaxCall &call, EaxEffectProps &props)
- { EAXCALL(props.mType, call_set, call, props); }
+ { EAXCALL(props, call_set, call, props); }
void set(const EaxCall &call)
{
@@ -353,7 +348,7 @@ public:
{ return T::Get(std::forward<Args>(args)...); }
static void call_get(const EaxCall &call, const EaxEffectProps &props)
- { EAXCALL(props.mType, call_get, call, props); }
+ { EAXCALL(props, call_get, call, props); }
void get(const EaxCall &call)
{
@@ -373,7 +368,7 @@ public:
{ return T{props_, al_effect_props_}.commit(std::forward<Args>(args)...); }
bool call_commit(const EaxEffectProps &props)
- { EAXCALL(props.mType, call_commit, props); }
+ { EAXCALL(props, call_commit, props); }
bool commit(int eax_version)
{
diff --git a/al/eax/exception.cpp b/al/eax/exception.cpp
index 435e7442..e4945d88 100644
--- a/al/eax/exception.cpp
+++ b/al/eax/exception.cpp
@@ -6,54 +6,27 @@
#include <string>
-EaxException::EaxException(const char *context, const char *message)
+EaxException::EaxException(std::string_view context, std::string_view message)
: std::runtime_error{make_message(context, message)}
{
}
EaxException::~EaxException() = default;
-std::string EaxException::make_message(const char *context, const char *message)
+std::string EaxException::make_message(std::string_view context, std::string_view message)
{
- const auto context_size = (context ? std::string::traits_type::length(context) : 0);
- const auto has_contex = (context_size > 0);
-
- const auto message_size = (message ? std::string::traits_type::length(message) : 0);
- const auto has_message = (message_size > 0);
-
- if (!has_contex && !has_message)
- {
- return std::string{};
- }
-
- static constexpr char left_prefix[] = "[";
- const auto left_prefix_size = std::string::traits_type::length(left_prefix);
-
- static constexpr char right_prefix[] = "] ";
- const auto right_prefix_size = std::string::traits_type::length(right_prefix);
-
- const auto what_size =
- (
- has_contex ?
- left_prefix_size + context_size + right_prefix_size :
- 0) +
- message_size +
- 1;
-
auto what = std::string{};
- what.reserve(what_size);
-
- if (has_contex)
- {
- what.append(left_prefix, left_prefix_size);
- what.append(context, context_size);
- what.append(right_prefix, right_prefix_size);
- }
+ if(context.empty() && message.empty())
+ return what;
- if (has_message)
+ what.reserve((!context.empty() ? context.size() + 3 : 0) + message.length() + 1);
+ if(!context.empty())
{
- what.append(message, message_size);
+ what += "[";
+ what += context;
+ what += "] ";
}
+ what += message;
return what;
}
diff --git a/al/eax/exception.h b/al/eax/exception.h
index 3ae88cdc..336654f0 100644
--- a/al/eax/exception.h
+++ b/al/eax/exception.h
@@ -1,16 +1,16 @@
#ifndef EAX_EXCEPTION_INCLUDED
#define EAX_EXCEPTION_INCLUDED
-
#include <stdexcept>
#include <string>
+#include <string_view>
class EaxException : public std::runtime_error {
- static std::string make_message(const char *context, const char *message);
+ static std::string make_message(std::string_view context, std::string_view message);
public:
- EaxException(const char *context, const char *message);
+ EaxException(std::string_view context, std::string_view message);
~EaxException() override;
}; // EaxException
diff --git a/al/eax/fx_slot_index.h b/al/eax/fx_slot_index.h
index 63dba037..9f350d9b 100644
--- a/al/eax/fx_slot_index.h
+++ b/al/eax/fx_slot_index.h
@@ -3,17 +3,16 @@
#include <cstddef>
+#include <optional>
-#include "aloptional.h"
#include "api.h"
using EaxFxSlotIndexValue = std::size_t;
-class EaxFxSlotIndex : public al::optional<EaxFxSlotIndexValue>
-{
+class EaxFxSlotIndex : public std::optional<EaxFxSlotIndexValue> {
public:
- using al::optional<EaxFxSlotIndexValue>::optional;
+ using std::optional<EaxFxSlotIndexValue>::optional;
EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; }
EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; }
diff --git a/al/eax/globals.cpp b/al/eax/globals.cpp
deleted file mode 100644
index 80e9dbfe..00000000
--- a/al/eax/globals.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "config.h"
-
-#include "globals.h"
-
-
-bool eax_g_is_enabled = true;
-
-
-const char eax1_ext_name[] = "EAX";
-const char eax2_ext_name[] = "EAX2.0";
-const char eax3_ext_name[] = "EAX3.0";
-const char eax4_ext_name[] = "EAX4.0";
-const char eax5_ext_name[] = "EAX5.0";
-
-const char eax_x_ram_ext_name[] = "EAX-RAM";
-
-const char eax_eax_set_func_name[] = "EAXSet";
-const char eax_eax_get_func_name[] = "EAXGet";
-
-const char eax_eax_set_buffer_mode_func_name[] = "EAXSetBufferMode";
-const char eax_eax_get_buffer_mode_func_name[] = "EAXGetBufferMode";
diff --git a/al/eax/globals.h b/al/eax/globals.h
index 1b4d63b8..ff05d009 100644
--- a/al/eax/globals.h
+++ b/al/eax/globals.h
@@ -1,22 +1,20 @@
#ifndef EAX_GLOBALS_INCLUDED
#define EAX_GLOBALS_INCLUDED
+inline bool eax_g_is_enabled{true};
-extern bool eax_g_is_enabled;
+inline constexpr char eax1_ext_name[]{"EAX"};
+inline constexpr char eax2_ext_name[]{"EAX2.0"};
+inline constexpr char eax3_ext_name[]{"EAX3.0"};
+inline constexpr char eax4_ext_name[]{"EAX4.0"};
+inline constexpr char eax5_ext_name[]{"EAX5.0"};
+inline constexpr char eax_x_ram_ext_name[]{"EAX-RAM"};
-extern const char eax1_ext_name[];
-extern const char eax2_ext_name[];
-extern const char eax3_ext_name[];
-extern const char eax4_ext_name[];
-extern const char eax5_ext_name[];
+inline constexpr char eax_eax_set_func_name[]{"EAXSet"};
+inline constexpr char eax_eax_get_func_name[]{"EAXGet"};
-extern const char eax_x_ram_ext_name[];
-
-extern const char eax_eax_set_func_name[];
-extern const char eax_eax_get_func_name[];
-
-extern const char eax_eax_set_buffer_mode_func_name[];
-extern const char eax_eax_get_buffer_mode_func_name[];
+inline constexpr char eax_eax_set_buffer_mode_func_name[]{"EAXSetBufferMode"};
+inline constexpr char eax_eax_get_buffer_mode_func_name[]{"EAXGetBufferMode"};
#endif // !EAX_GLOBALS_INCLUDED
diff --git a/al/eax/utils.cpp b/al/eax/utils.cpp
index b3ed6ca1..53599ac5 100644
--- a/al/eax/utils.cpp
+++ b/al/eax/utils.cpp
@@ -8,7 +8,7 @@
#include "core/logging.h"
-void eax_log_exception(const char *message) noexcept
+void eax_log_exception(std::string_view message) noexcept
{
const auto exception_ptr = std::current_exception();
assert(exception_ptr);
@@ -18,9 +18,9 @@ void eax_log_exception(const char *message) noexcept
}
catch(const std::exception& ex) {
const auto ex_message = ex.what();
- ERR("%s %s\n", message ? message : "", ex_message);
+ ERR("%.*s %s\n", static_cast<int>(message.length()), message.data(), ex_message);
}
catch(...) {
- ERR("%s %s\n", message ? message : "", "Generic exception.");
+ ERR("%.*s %s\n", static_cast<int>(message.length()), message.data(), "Generic exception.");
}
}
diff --git a/al/eax/utils.h b/al/eax/utils.h
index 8ff75a18..8e0f975f 100644
--- a/al/eax/utils.h
+++ b/al/eax/utils.h
@@ -4,8 +4,11 @@
#include <algorithm>
#include <cstdint>
#include <string>
+#include <string_view>
#include <type_traits>
+#include "opthelpers.h"
+
using EaxDirtyFlags = unsigned int;
struct EaxAlLowPassParam {
@@ -13,16 +16,13 @@ struct EaxAlLowPassParam {
float gain_hf;
};
-void eax_log_exception(const char *message) noexcept;
+void eax_log_exception(std::string_view message) noexcept;
template<typename TException, typename TValue>
-void eax_validate_range(
- const char* value_name,
- const TValue& value,
- const TValue& min_value,
+void eax_validate_range(std::string_view value_name, const TValue& value, const TValue& min_value,
const TValue& max_value)
{
- if (value >= min_value && value <= max_value)
+ if(value >= min_value && value <= max_value) LIKELY
return;
const auto message =
diff --git a/al/eax/x_ram.h b/al/eax/x_ram.h
index 438b9916..d10fe697 100644
--- a/al/eax/x_ram.h
+++ b/al/eax/x_ram.h
@@ -25,14 +25,7 @@ constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE";
constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE";
-ALboolean AL_APIENTRY EAXSetBufferMode(
- ALsizei n,
- const ALuint* buffers,
- ALint value);
-
-ALenum AL_APIENTRY EAXGetBufferMode(
- ALuint buffer,
- ALint* pReserved);
-
+ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buffers, ALint value) noexcept;
+ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint *pReserved) noexcept;
#endif // !EAX_X_RAM_INCLUDED
diff --git a/al/effect.cpp b/al/effect.cpp
index bde89912..3e48e91b 100644
--- a/al/effect.cpp
+++ b/al/effect.cpp
@@ -31,6 +31,7 @@
#include <new>
#include <numeric>
#include <utility>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
@@ -48,8 +49,8 @@
#include "alstring.h"
#include "core/except.h"
#include "core/logging.h"
+#include "direct_defs.h"
#include "opthelpers.h"
-#include "vector.h"
#ifdef ALSOFT_EAX
#include <cassert>
@@ -73,7 +74,7 @@ const EffectList gEffectList[16]{
{ "vmorpher", VMORPHER_EFFECT, AL_EFFECT_VOCAL_MORPHER },
{ "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
{ "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE },
- { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_REVERB_SOFT },
+ { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_SOFT },
};
bool DisabledEffects[MAX_EFFECTS];
@@ -112,7 +113,7 @@ constexpr EffectPropsItem EffectPropsList[] = {
{ AL_EFFECT_VOCAL_MORPHER, VmorpherEffectProps, VmorpherEffectVtable },
{ AL_EFFECT_DEDICATED_DIALOGUE, DedicatedEffectProps, DedicatedEffectVtable },
{ AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedEffectProps, DedicatedEffectVtable },
- { AL_EFFECT_CONVOLUTION_REVERB_SOFT, ConvolutionEffectProps, ConvolutionEffectVtable },
+ { AL_EFFECT_CONVOLUTION_SOFT, ConvolutionEffectProps, ConvolutionEffectVtable },
};
@@ -161,7 +162,7 @@ void InitEffectParams(ALeffect *effect, ALenum type)
bool EnsureEffects(ALCdevice *device, size_t needed)
{
- size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0},
+ size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), 0_uz,
[](size_t cur, const EffectSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
@@ -206,11 +207,13 @@ ALeffect *AllocEffect(ALCdevice *device)
void FreeEffect(ALCdevice *device, ALeffect *effect)
{
+ device->mEffectNames.erase(effect->id);
+
const ALuint id{effect->id - 1};
const size_t lidx{id >> 6};
const ALuint slidx{id & 0x3f};
- al::destroy_at(effect);
+ std::destroy_at(effect);
device->EffectList[lidx].FreeMask |= 1_u64 << slidx;
}
@@ -230,12 +233,9 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
} // namespace
-AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGenEffects, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
if(n <= 0) UNLIKELY return;
@@ -259,7 +259,7 @@ START_API_FUNC
/* Store the allocated buffer IDs in a separate local list, to avoid
* modifying the user storage in case of failure.
*/
- al::vector<ALuint> ids;
+ std::vector<ALuint> ids;
ids.reserve(static_cast<ALuint>(n));
do {
ALeffect *effect{AllocEffect(device)};
@@ -268,14 +268,11 @@ START_API_FUNC
std::copy(ids.cbegin(), ids.cend(), effects);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alDeleteEffects, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n,
+ const ALuint *effects) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
if(n <= 0) UNLIKELY return;
@@ -303,29 +300,21 @@ START_API_FUNC
};
std::for_each(effects, effects_end, delete_effect);
}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsEffect, ALuint)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) noexcept
{
- ContextRef context{GetContextRef()};
- if(context) LIKELY
- {
- ALCdevice *device{context->mALDevice.get()};
- std::lock_guard<std::mutex> _{device->EffectLock};
- if(!effect || LookupEffect(device, effect))
- return AL_TRUE;
- }
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard<std::mutex> _{device->EffectLock};
+ if(!effect || LookupEffect(device, effect))
+ return AL_TRUE;
return AL_FALSE;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alEffecti, ALuint, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param,
+ ALint value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -361,21 +350,18 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alEffectiv, ALuint, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param,
+ const ALint *values) noexcept
{
switch(param)
{
case AL_EFFECT_TYPE:
- alEffecti(effect, param, values[0]);
+ alEffectiDirect(context, effect, param, values[0]);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -391,14 +377,11 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alEffectf, ALuint, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param,
+ ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -414,14 +397,11 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alEffectfv, ALuint, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param,
+ const ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -437,14 +417,11 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetEffecti, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param,
+ ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -462,21 +439,18 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetEffectiv, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param,
+ ALint *values) noexcept
{
switch(param)
{
case AL_EFFECT_TYPE:
- alGetEffecti(effect, param, values);
+ alGetEffectiDirect(context, effect, param, values);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -492,14 +466,11 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetEffectf, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param,
+ ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -515,14 +486,11 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetEffectfv, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param,
+ ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@@ -538,7 +506,6 @@ START_API_FUNC
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
void InitEffect(ALeffect *effect)
@@ -546,13 +513,29 @@ void InitEffect(ALeffect *effect)
InitEffectParams(effect, AL_EFFECT_NULL);
}
+void ALeffect::SetName(ALCcontext* context, ALuint id, std::string_view name)
+{
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard<std::mutex> _{device->EffectLock};
+
+ auto effect = LookupEffect(device, id);
+ if(!effect) UNLIKELY
+ return context->setError(AL_INVALID_NAME, "Invalid effect ID %u", id);
+
+ device->mEffectNames.insert_or_assign(id, name);
+}
+
+
EffectSubList::~EffectSubList()
{
+ if(!Effects)
+ return;
+
uint64_t usemask{~FreeMask};
while(usemask)
{
const int idx{al::countr_zero(usemask)};
- al::destroy_at(Effects+idx);
+ std::destroy_at(Effects+idx);
usemask &= ~(1_u64 << idx);
}
FreeMask = ~usemask;
diff --git a/al/effect.h b/al/effect.h
index a1d43313..27e9dd72 100644
--- a/al/effect.h
+++ b/al/effect.h
@@ -1,6 +1,8 @@
#ifndef AL_EFFECT_H
#define AL_EFFECT_H
+#include <string_view>
+
#include "AL/al.h"
#include "AL/efx.h"
@@ -50,6 +52,8 @@ struct ALeffect {
/* Self ID */
ALuint id{0u};
+ static void SetName(ALCcontext *context, ALuint id, std::string_view name);
+
DISABLE_ALLOC()
};
diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp
index 129318f4..1a8b43fc 100644
--- a/al/effects/autowah.cpp
+++ b/al/effects/autowah.cpp
@@ -192,19 +192,16 @@ template<>
template<>
bool AutowahCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && mEaxProps.mAutowah.flAttackTime == props.mAutowah.flAttackTime
- && mEaxProps.mAutowah.flReleaseTime == props.mAutowah.flReleaseTime
- && mEaxProps.mAutowah.lResonance == props.mAutowah.lResonance
- && mEaxProps.mAutowah.lPeakLevel == props.mAutowah.lPeakLevel)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- mAlProps.Autowah.AttackTime = props.mAutowah.flAttackTime;
- mAlProps.Autowah.ReleaseTime = props.mAutowah.flReleaseTime;
- mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast<float>(props.mAutowah.lResonance));
- mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast<float>(props.mAutowah.lPeakLevel));
+ auto &eaxprops = std::get<EAXAUTOWAHPROPERTIES>(props);
+ mAlProps.Autowah.AttackTime = eaxprops.flAttackTime;
+ mAlProps.Autowah.ReleaseTime = eaxprops.flReleaseTime;
+ mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast<float>(eaxprops.lResonance));
+ mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast<float>(eaxprops.lPeakLevel));
return true;
}
@@ -212,39 +209,46 @@ bool AutowahCommitter::commit(const EaxEffectProps &props)
template<>
void AutowahCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Autowah;
- props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
- props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
- props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
- props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
+ static constexpr EAXAUTOWAHPROPERTIES defprops{[]
+ {
+ EAXAUTOWAHPROPERTIES ret{};
+ ret.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
+ ret.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
+ ret.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
+ ret.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXAUTOWAHPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXAUTOWAH_NONE: break;
- case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props.mAutowah); break;
- case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.mAutowah.flAttackTime); break;
- case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.mAutowah.flReleaseTime); break;
- case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.mAutowah.lResonance); break;
- case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.mAutowah.lPeakLevel); break;
+ case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.flAttackTime); break;
+ case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.flReleaseTime); break;
+ case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.lResonance); break;
+ case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.lPeakLevel); break;
default: fail_unknown_property_id();
}
}
template<>
-void AutowahCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void AutowahCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXAUTOWAHPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXAUTOWAH_NONE: break;
- case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props.mAutowah); break;
- case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.mAutowah.flAttackTime); break;
- case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.mAutowah.flReleaseTime); break;
- case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.mAutowah.lResonance); break;
- case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.mAutowah.lPeakLevel); break;
+ case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.flAttackTime); break;
+ case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.flReleaseTime); break;
+ case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.lResonance); break;
+ case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.lPeakLevel); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp
index 305259a4..90b38e4d 100644
--- a/al/effects/chorus.cpp
+++ b/al/effects/chorus.cpp
@@ -1,13 +1,13 @@
#include "config.h"
+#include <optional>
#include <stdexcept>
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
-#include "aloptional.h"
#include "core/logging.h"
#include "effects.h"
@@ -27,14 +27,14 @@ static_assert(FlangerMaxDelay >= AL_FLANGER_MAX_DELAY, "Flanger max delay too sm
static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch");
static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch");
-inline al::optional<ChorusWaveform> WaveformFromEnum(ALenum type)
+inline std::optional<ChorusWaveform> WaveformFromEnum(ALenum type)
{
switch(type)
{
case AL_CHORUS_WAVEFORM_SINUSOID: return ChorusWaveform::Sinusoid;
case AL_CHORUS_WAVEFORM_TRIANGLE: return ChorusWaveform::Triangle;
}
- return al::nullopt;
+ return std::nullopt;
}
inline ALenum EnumFromWaveform(ChorusWaveform type)
{
@@ -294,9 +294,7 @@ namespace {
struct EaxChorusTraits {
using Props = EAXCHORUSPROPERTIES;
using Committer = EaxChorusCommitter;
- static constexpr auto Field = &EaxEffectProps::mChorus;
- static constexpr auto eax_effect_type() { return EaxEffectType::Chorus; }
static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; }
static constexpr auto eax_none_param_id() { return EAXCHORUS_NONE; }
@@ -361,9 +359,7 @@ struct EaxChorusTraits {
struct EaxFlangerTraits {
using Props = EAXFLANGERPROPERTIES;
using Committer = EaxFlangerCommitter;
- static constexpr auto Field = &EaxEffectProps::mFlanger;
- static constexpr auto eax_effect_type() { return EaxEffectType::Flanger; }
static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; }
static constexpr auto eax_none_param_id() { return EAXFLANGER_NONE; }
@@ -431,8 +427,6 @@ struct ChorusFlangerEffect {
using Committer = typename Traits::Committer;
using Exception = typename Committer::Exception;
- static constexpr auto Field = Traits::Field;
-
struct WaveformValidator {
void operator()(unsigned long ulWaveform) const
{
@@ -514,8 +508,7 @@ struct ChorusFlangerEffect {
public:
static void SetDefaults(EaxEffectProps &props)
{
- auto&& all = props.*Field;
- props.mType = Traits::eax_effect_type();
+ auto&& all = props.emplace<typename Traits::Props>();
all.ulWaveform = Traits::eax_default_waveform();
all.lPhase = Traits::eax_default_phase();
all.flRate = Traits::eax_default_rate();
@@ -527,7 +520,7 @@ public:
static void Get(const EaxCall &call, const EaxEffectProps &props)
{
- auto&& all = props.*Field;
+ auto&& all = std::get<typename Traits::Props>(props);
switch(call.get_property_id())
{
case Traits::eax_none_param_id():
@@ -568,7 +561,7 @@ public:
static void Set(const EaxCall &call, EaxEffectProps &props)
{
- auto&& all = props.*Field;
+ auto&& all = std::get<typename Traits::Props>(props);
switch(call.get_property_id())
{
case Traits::eax_none_param_id():
@@ -609,18 +602,11 @@ public:
static bool Commit(const EaxEffectProps &props, EaxEffectProps &props_, EffectProps &al_props_)
{
- if(props.mType == props_.mType)
- {
- auto&& src = props_.*Field;
- auto&& dst = props.*Field;
- if(dst.ulWaveform == src.ulWaveform && dst.lPhase == src.lPhase
- && dst.flRate == src.flRate && dst.flDepth == src.flDepth
- && dst.flFeedback == src.flFeedback && dst.flDelay == src.flDelay)
- return false;
- }
+ if(props == props_)
+ return false;
props_ = props;
- auto&& dst = props.*Field;
+ auto&& dst = std::get<typename Traits::Props>(props);
al_props_.Chorus.Waveform = Traits::eax_waveform(dst.ulWaveform);
al_props_.Chorus.Phase = static_cast<int>(dst.lPhase);
diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp
index a4aa8e77..ca8af84f 100644
--- a/al/effects/compressor.cpp
+++ b/al/effects/compressor.cpp
@@ -118,43 +118,43 @@ template<>
template<>
bool CompressorCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && props.mCompressor.ulOnOff == mEaxProps.mCompressor.ulOnOff)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- mAlProps.Compressor.OnOff = (props.mCompressor.ulOnOff != 0);
+ mAlProps.Compressor.OnOff = (std::get<EAXAGCCOMPRESSORPROPERTIES>(props).ulOnOff != 0);
return true;
}
template<>
void CompressorCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Compressor;
- props.mCompressor.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
+ props = EAXAGCCOMPRESSORPROPERTIES{EAXAGCCOMPRESSOR_DEFAULTONOFF};
}
template<>
-void CompressorCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void CompressorCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXAGCCOMPRESSORPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXAGCCOMPRESSOR_NONE: break;
- case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value<Exception>(props.mCompressor); break;
- case EAXAGCCOMPRESSOR_ONOFF: call.set_value<Exception>(props.mCompressor.ulOnOff); break;
+ case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXAGCCOMPRESSOR_ONOFF: call.set_value<Exception>(props.ulOnOff); break;
default: fail_unknown_property_id();
}
}
template<>
-void CompressorCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void CompressorCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXAGCCOMPRESSORPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXAGCCOMPRESSOR_NONE: break;
- case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer<AllValidator>(call, props.mCompressor); break;
- case EAXAGCCOMPRESSOR_ONOFF: defer<OnOffValidator>(call, props.mCompressor.ulOnOff); break;
+ case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXAGCCOMPRESSOR_ONOFF: defer<OnOffValidator>(call, props.ulOnOff); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/convolution.cpp b/al/effects/convolution.cpp
index 8e850fd3..9c091e53 100644
--- a/al/effects/convolution.cpp
+++ b/al/effects/convolution.cpp
@@ -1,6 +1,8 @@
#include "config.h"
+#include <cmath>
+
#include "AL/al.h"
#include "alc/inprogext.h"
@@ -36,12 +38,25 @@ void Convolution_setParamf(EffectProps* /*props*/, ALenum param, float /*val*/)
param};
}
}
-void Convolution_setParamfv(EffectProps *props, ALenum param, const float *vals)
+void Convolution_setParamfv(EffectProps *props, ALenum param, const float *values)
{
switch(param)
{
+ case AL_CONVOLUTION_ORIENTATION_SOFT:
+ if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])
+ && std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5])))
+ throw effect_exception{AL_INVALID_VALUE, "Property 0x%04x value out of range", param};
+
+ props->Convolution.OrientAt[0] = values[0];
+ props->Convolution.OrientAt[1] = values[1];
+ props->Convolution.OrientAt[2] = values[2];
+ props->Convolution.OrientUp[0] = values[3];
+ props->Convolution.OrientUp[1] = values[4];
+ props->Convolution.OrientUp[2] = values[5];
+ break;
+
default:
- Convolution_setParamf(props, param, vals[0]);
+ Convolution_setParamf(props, param, values[0]);
}
}
@@ -71,18 +86,29 @@ void Convolution_getParamf(const EffectProps* /*props*/, ALenum param, float* /*
param};
}
}
-void Convolution_getParamfv(const EffectProps *props, ALenum param, float *vals)
+void Convolution_getParamfv(const EffectProps *props, ALenum param, float *values)
{
switch(param)
{
+ case AL_CONVOLUTION_ORIENTATION_SOFT:
+ values[0] = props->Convolution.OrientAt[0];
+ values[1] = props->Convolution.OrientAt[1];
+ values[2] = props->Convolution.OrientAt[2];
+ values[3] = props->Convolution.OrientUp[0];
+ values[4] = props->Convolution.OrientUp[1];
+ values[5] = props->Convolution.OrientUp[2];
+ break;
+
default:
- Convolution_getParamf(props, param, vals);
+ Convolution_getParamf(props, param, values);
}
}
EffectProps genDefaultProps() noexcept
{
EffectProps props{};
+ props.Convolution.OrientAt = {0.0f, 0.0f, -1.0f};
+ props.Convolution.OrientUp = {0.0f, 1.0f, 0.0f};
return props;
}
diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp
index ee298ddf..e046d8e7 100644
--- a/al/effects/distortion.cpp
+++ b/al/effects/distortion.cpp
@@ -207,20 +207,17 @@ template<>
template<>
bool DistortionCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType && mEaxProps.mDistortion.flEdge == props.mDistortion.flEdge
- && mEaxProps.mDistortion.lGain == props.mDistortion.lGain
- && mEaxProps.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff
- && mEaxProps.mDistortion.flEQCenter == props.mDistortion.flEQCenter
- && mEaxProps.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- mAlProps.Distortion.Edge = props.mDistortion.flEdge;
- mAlProps.Distortion.Gain = level_mb_to_gain(static_cast<float>(props.mDistortion.lGain));
- mAlProps.Distortion.LowpassCutoff = props.mDistortion.flLowPassCutOff;
- mAlProps.Distortion.EQCenter = props.mDistortion.flEQCenter;
- mAlProps.Distortion.EQBandwidth = props.mDistortion.flEdge;
+ auto &eaxprops = std::get<EAXDISTORTIONPROPERTIES>(props);
+ mAlProps.Distortion.Edge = eaxprops.flEdge;
+ mAlProps.Distortion.Gain = level_mb_to_gain(static_cast<float>(eaxprops.lGain));
+ mAlProps.Distortion.LowpassCutoff = eaxprops.flLowPassCutOff;
+ mAlProps.Distortion.EQCenter = eaxprops.flEQCenter;
+ mAlProps.Distortion.EQBandwidth = eaxprops.flEdge;
return true;
}
@@ -228,42 +225,49 @@ bool DistortionCommitter::commit(const EaxEffectProps &props)
template<>
void DistortionCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Distortion;
- props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE;
- props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN;
- props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF;
- props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER;
- props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH;
+ static constexpr EAXDISTORTIONPROPERTIES defprops{[]
+ {
+ EAXDISTORTIONPROPERTIES ret{};
+ ret.flEdge = EAXDISTORTION_DEFAULTEDGE;
+ ret.lGain = EAXDISTORTION_DEFAULTGAIN;
+ ret.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF;
+ ret.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER;
+ ret.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXDISTORTIONPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXDISTORTION_NONE: break;
- case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props.mDistortion); break;
- case EAXDISTORTION_EDGE: call.set_value<Exception>(props.mDistortion.flEdge); break;
- case EAXDISTORTION_GAIN: call.set_value<Exception>(props.mDistortion.lGain); break;
- case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.mDistortion.flLowPassCutOff); break;
- case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.mDistortion.flEQCenter); break;
- case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.mDistortion.flEQBandwidth); break;
+ case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXDISTORTION_EDGE: call.set_value<Exception>(props.flEdge); break;
+ case EAXDISTORTION_GAIN: call.set_value<Exception>(props.lGain); break;
+ case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.flLowPassCutOff); break;
+ case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.flEQCenter); break;
+ case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.flEQBandwidth); break;
default: fail_unknown_property_id();
}
}
template<>
-void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXDISTORTIONPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXDISTORTION_NONE: break;
- case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props.mDistortion); break;
- case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.mDistortion.flEdge); break;
- case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.mDistortion.lGain); break;
- case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.mDistortion.flLowPassCutOff); break;
- case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.mDistortion.flEQCenter); break;
- case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.mDistortion.flEQBandwidth); break;
+ case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.flEdge); break;
+ case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.lGain); break;
+ case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.flLowPassCutOff); break;
+ case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.flEQCenter); break;
+ case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.flEQBandwidth); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp
index 2eb37603..48aacef3 100644
--- a/al/effects/echo.cpp
+++ b/al/effects/echo.cpp
@@ -204,20 +204,17 @@ template<>
template<>
bool EchoCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType && mEaxProps.mEcho.flDelay == props.mEcho.flDelay
- && mEaxProps.mEcho.flLRDelay == props.mEcho.flLRDelay
- && mEaxProps.mEcho.flDamping == props.mEcho.flDamping
- && mEaxProps.mEcho.flFeedback == props.mEcho.flFeedback
- && mEaxProps.mEcho.flSpread == props.mEcho.flSpread)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- mAlProps.Echo.Delay = props.mEcho.flDelay;
- mAlProps.Echo.LRDelay = props.mEcho.flLRDelay;
- mAlProps.Echo.Damping = props.mEcho.flDamping;
- mAlProps.Echo.Feedback = props.mEcho.flFeedback;
- mAlProps.Echo.Spread = props.mEcho.flSpread;
+ auto &eaxprops = std::get<EAXECHOPROPERTIES>(props);
+ mAlProps.Echo.Delay = eaxprops.flDelay;
+ mAlProps.Echo.LRDelay = eaxprops.flLRDelay;
+ mAlProps.Echo.Damping = eaxprops.flDamping;
+ mAlProps.Echo.Feedback = eaxprops.flFeedback;
+ mAlProps.Echo.Spread = eaxprops.flSpread;
return true;
}
@@ -225,42 +222,49 @@ bool EchoCommitter::commit(const EaxEffectProps &props)
template<>
void EchoCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Echo;
- props.mEcho.flDelay = EAXECHO_DEFAULTDELAY;
- props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY;
- props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING;
- props.mEcho.flFeedback = EAXECHO_DEFAULTFEEDBACK;
- props.mEcho.flSpread = EAXECHO_DEFAULTSPREAD;
+ static constexpr EAXECHOPROPERTIES defprops{[]
+ {
+ EAXECHOPROPERTIES ret{};
+ ret.flDelay = EAXECHO_DEFAULTDELAY;
+ ret.flLRDelay = EAXECHO_DEFAULTLRDELAY;
+ ret.flDamping = EAXECHO_DEFAULTDAMPING;
+ ret.flFeedback = EAXECHO_DEFAULTFEEDBACK;
+ ret.flSpread = EAXECHO_DEFAULTSPREAD;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXECHOPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXECHO_NONE: break;
- case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props.mEcho); break;
- case EAXECHO_DELAY: call.set_value<Exception>(props.mEcho.flDelay); break;
- case EAXECHO_LRDELAY: call.set_value<Exception>(props.mEcho.flLRDelay); break;
- case EAXECHO_DAMPING: call.set_value<Exception>(props.mEcho.flDamping); break;
- case EAXECHO_FEEDBACK: call.set_value<Exception>(props.mEcho.flFeedback); break;
- case EAXECHO_SPREAD: call.set_value<Exception>(props.mEcho.flSpread); break;
+ case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXECHO_DELAY: call.set_value<Exception>(props.flDelay); break;
+ case EAXECHO_LRDELAY: call.set_value<Exception>(props.flLRDelay); break;
+ case EAXECHO_DAMPING: call.set_value<Exception>(props.flDamping); break;
+ case EAXECHO_FEEDBACK: call.set_value<Exception>(props.flFeedback); break;
+ case EAXECHO_SPREAD: call.set_value<Exception>(props.flSpread); break;
default: fail_unknown_property_id();
}
}
template<>
-void EchoCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void EchoCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXECHOPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXECHO_NONE: break;
- case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props.mEcho); break;
- case EAXECHO_DELAY: defer<DelayValidator>(call, props.mEcho.flDelay); break;
- case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.mEcho.flLRDelay); break;
- case EAXECHO_DAMPING: defer<DampingValidator>(call, props.mEcho.flDamping); break;
- case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.mEcho.flFeedback); break;
- case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.mEcho.flSpread); break;
+ case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXECHO_DELAY: defer<DelayValidator>(call, props.flDelay); break;
+ case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.flLRDelay); break;
+ case EAXECHO_DAMPING: defer<DampingValidator>(call, props.flDamping); break;
+ case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.flFeedback); break;
+ case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.flSpread); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp
index 7dc703db..76d5bdef 100644
--- a/al/effects/equalizer.cpp
+++ b/al/effects/equalizer.cpp
@@ -322,30 +322,22 @@ template<>
template<>
bool EqualizerCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType && mEaxProps.mEqualizer.lLowGain == props.mEqualizer.lLowGain
- && mEaxProps.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff
- && mEaxProps.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain
- && mEaxProps.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center
- && mEaxProps.mEqualizer.flMid1Width == props.mEqualizer.flMid1Width
- && mEaxProps.mEqualizer.lMid2Gain == props.mEqualizer.lMid2Gain
- && mEaxProps.mEqualizer.flMid2Center == props.mEqualizer.flMid2Center
- && mEaxProps.mEqualizer.flMid2Width == props.mEqualizer.flMid2Width
- && mEaxProps.mEqualizer.lHighGain == props.mEqualizer.lHighGain
- && mEaxProps.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lLowGain));
- mAlProps.Equalizer.LowCutoff = props.mEqualizer.flLowCutOff;
- mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lMid1Gain));
- mAlProps.Equalizer.Mid1Center = props.mEqualizer.flMid1Center;
- mAlProps.Equalizer.Mid1Width = props.mEqualizer.flMid1Width;
- mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lMid2Gain));
- mAlProps.Equalizer.Mid2Center = props.mEqualizer.flMid2Center;
- mAlProps.Equalizer.Mid2Width = props.mEqualizer.flMid2Width;
- mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lHighGain));
- mAlProps.Equalizer.HighCutoff = props.mEqualizer.flHighCutOff;
+ auto &eaxprops = std::get<EAXEQUALIZERPROPERTIES>(props);
+ mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast<float>(eaxprops.lLowGain));
+ mAlProps.Equalizer.LowCutoff = eaxprops.flLowCutOff;
+ mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast<float>(eaxprops.lMid1Gain));
+ mAlProps.Equalizer.Mid1Center = eaxprops.flMid1Center;
+ mAlProps.Equalizer.Mid1Width = eaxprops.flMid1Width;
+ mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast<float>(eaxprops.lMid2Gain));
+ mAlProps.Equalizer.Mid2Center = eaxprops.flMid2Center;
+ mAlProps.Equalizer.Mid2Width = eaxprops.flMid2Width;
+ mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast<float>(eaxprops.lHighGain));
+ mAlProps.Equalizer.HighCutoff = eaxprops.flHighCutOff;
return true;
}
@@ -353,57 +345,64 @@ bool EqualizerCommitter::commit(const EaxEffectProps &props)
template<>
void EqualizerCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Equalizer;
- props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
- props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
- props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
- props.mEqualizer.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
- props.mEqualizer.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
- props.mEqualizer.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
- props.mEqualizer.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
- props.mEqualizer.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
- props.mEqualizer.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
- props.mEqualizer.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
+ static constexpr EAXEQUALIZERPROPERTIES defprops{[]
+ {
+ EAXEQUALIZERPROPERTIES ret{};
+ ret.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
+ ret.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
+ ret.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
+ ret.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
+ ret.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
+ ret.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
+ ret.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
+ ret.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
+ ret.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
+ ret.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXEQUALIZERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXEQUALIZER_NONE: break;
- case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props.mEqualizer); break;
- case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.mEqualizer.lLowGain); break;
- case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.mEqualizer.flLowCutOff); break;
- case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.mEqualizer.lMid1Gain); break;
- case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.mEqualizer.flMid1Center); break;
- case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.mEqualizer.flMid1Width); break;
- case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.mEqualizer.lMid2Gain); break;
- case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.mEqualizer.flMid2Center); break;
- case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.mEqualizer.flMid2Width); break;
- case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.mEqualizer.lHighGain); break;
- case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.mEqualizer.flHighCutOff); break;
+ case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.lLowGain); break;
+ case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.flLowCutOff); break;
+ case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.lMid1Gain); break;
+ case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.flMid1Center); break;
+ case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.flMid1Width); break;
+ case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.lMid2Gain); break;
+ case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.flMid2Center); break;
+ case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.flMid2Width); break;
+ case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.lHighGain); break;
+ case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.flHighCutOff); break;
default: fail_unknown_property_id();
}
}
template<>
-void EqualizerCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void EqualizerCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXEQUALIZERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXEQUALIZER_NONE: break;
- case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props.mEqualizer); break;
- case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.mEqualizer.lLowGain); break;
- case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.mEqualizer.flLowCutOff); break;
- case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.mEqualizer.lMid1Gain); break;
- case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.mEqualizer.flMid1Center); break;
- case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.mEqualizer.flMid1Width); break;
- case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.mEqualizer.lMid2Gain); break;
- case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.mEqualizer.flMid2Center); break;
- case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.mEqualizer.flMid2Width); break;
- case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.mEqualizer.lHighGain); break;
- case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.mEqualizer.flHighCutOff); break;
+ case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.lLowGain); break;
+ case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.flLowCutOff); break;
+ case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.lMid1Gain); break;
+ case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.flMid1Center); break;
+ case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.flMid1Width); break;
+ case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.lMid2Gain); break;
+ case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.flMid2Center); break;
+ case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.flMid2Width); break;
+ case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.lHighGain); break;
+ case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.flHighCutOff); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp
index 949db203..37c372c3 100644
--- a/al/effects/fshifter.cpp
+++ b/al/effects/fshifter.cpp
@@ -1,13 +1,13 @@
#include "config.h"
+#include <optional>
#include <stdexcept>
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
-#include "aloptional.h"
#include "effects.h"
#ifdef ALSOFT_EAX
@@ -20,7 +20,7 @@
namespace {
-al::optional<FShifterDirection> DirectionFromEmum(ALenum value)
+std::optional<FShifterDirection> DirectionFromEmum(ALenum value)
{
switch(value)
{
@@ -28,7 +28,7 @@ al::optional<FShifterDirection> DirectionFromEmum(ALenum value)
case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return FShifterDirection::Up;
case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return FShifterDirection::Off;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum EnumFromDirection(FShifterDirection dir)
{
@@ -200,10 +200,7 @@ template<>
template<>
bool FrequencyShifterCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && mEaxProps.mFrequencyShifter.flFrequency == props.mFrequencyShifter.flFrequency
- && mEaxProps.mFrequencyShifter.ulLeftDirection == props.mFrequencyShifter.ulLeftDirection
- && mEaxProps.mFrequencyShifter.ulRightDirection == props.mFrequencyShifter.ulRightDirection)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
@@ -217,9 +214,10 @@ bool FrequencyShifterCommitter::commit(const EaxEffectProps &props)
return FShifterDirection::Off;
};
- mAlProps.Fshifter.Frequency = props.mFrequencyShifter.flFrequency;
- mAlProps.Fshifter.LeftDirection = get_direction(props.mFrequencyShifter.ulLeftDirection);
- mAlProps.Fshifter.RightDirection = get_direction(props.mFrequencyShifter.ulRightDirection);
+ auto &eaxprops = std::get<EAXFREQUENCYSHIFTERPROPERTIES>(props);
+ mAlProps.Fshifter.Frequency = eaxprops.flFrequency;
+ mAlProps.Fshifter.LeftDirection = get_direction(eaxprops.ulLeftDirection);
+ mAlProps.Fshifter.RightDirection = get_direction(eaxprops.ulRightDirection);
return true;
}
@@ -227,36 +225,43 @@ bool FrequencyShifterCommitter::commit(const EaxEffectProps &props)
template<>
void FrequencyShifterCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::FrequencyShifter;
- props.mFrequencyShifter.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
- props.mFrequencyShifter.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
- props.mFrequencyShifter.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
+ static constexpr EAXFREQUENCYSHIFTERPROPERTIES defprops{[]
+ {
+ EAXFREQUENCYSHIFTERPROPERTIES ret{};
+ ret.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
+ ret.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
+ ret.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXFREQUENCYSHIFTERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXFREQUENCYSHIFTER_NONE: break;
- case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props.mFrequencyShifter); break;
- case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value<Exception>(props.mFrequencyShifter.flFrequency); break;
- case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value<Exception>(props.mFrequencyShifter.ulLeftDirection); break;
- case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value<Exception>(props.mFrequencyShifter.ulRightDirection); break;
+ case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value<Exception>(props.flFrequency); break;
+ case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value<Exception>(props.ulLeftDirection); break;
+ case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value<Exception>(props.ulRightDirection); break;
default: fail_unknown_property_id();
}
}
template<>
-void FrequencyShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void FrequencyShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXFREQUENCYSHIFTERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXFREQUENCYSHIFTER_NONE: break;
- case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props.mFrequencyShifter); break;
- case EAXFREQUENCYSHIFTER_FREQUENCY: defer<FrequencyValidator>(call, props.mFrequencyShifter.flFrequency); break;
- case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer<LeftDirectionValidator>(call, props.mFrequencyShifter.ulLeftDirection); break;
- case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer<RightDirectionValidator>(call, props.mFrequencyShifter.ulRightDirection); break;
+ case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXFREQUENCYSHIFTER_FREQUENCY: defer<FrequencyValidator>(call, props.flFrequency); break;
+ case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer<LeftDirectionValidator>(call, props.ulLeftDirection); break;
+ case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer<RightDirectionValidator>(call, props.ulRightDirection); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp
index 5f37d08f..366e7ef7 100644
--- a/al/effects/modulator.cpp
+++ b/al/effects/modulator.cpp
@@ -1,13 +1,13 @@
#include "config.h"
+#include <optional>
#include <stdexcept>
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
-#include "aloptional.h"
#include "effects.h"
#ifdef ALSOFT_EAX
@@ -20,7 +20,7 @@
namespace {
-al::optional<ModulatorWaveform> WaveformFromEmum(ALenum value)
+std::optional<ModulatorWaveform> WaveformFromEmum(ALenum value)
{
switch(value)
{
@@ -28,7 +28,7 @@ al::optional<ModulatorWaveform> WaveformFromEmum(ALenum value)
case AL_RING_MODULATOR_SAWTOOTH: return ModulatorWaveform::Sawtooth;
case AL_RING_MODULATOR_SQUARE: return ModulatorWaveform::Square;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum EnumFromWaveform(ModulatorWaveform type)
{
@@ -206,10 +206,7 @@ template<>
template<>
bool ModulatorCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && mEaxProps.mModulator.flFrequency == props.mModulator.flFrequency
- && mEaxProps.mModulator.flHighPassCutOff == props.mModulator.flHighPassCutOff
- && mEaxProps.mModulator.ulWaveform == props.mModulator.ulWaveform)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
@@ -225,9 +222,10 @@ bool ModulatorCommitter::commit(const EaxEffectProps &props)
return ModulatorWaveform::Sinusoid;
};
- mAlProps.Modulator.Frequency = props.mModulator.flFrequency;
- mAlProps.Modulator.HighPassCutoff = props.mModulator.flHighPassCutOff;
- mAlProps.Modulator.Waveform = get_waveform(props.mModulator.ulWaveform);
+ auto &eaxprops = std::get<EAXRINGMODULATORPROPERTIES>(props);
+ mAlProps.Modulator.Frequency = eaxprops.flFrequency;
+ mAlProps.Modulator.HighPassCutoff = eaxprops.flHighPassCutOff;
+ mAlProps.Modulator.Waveform = get_waveform(eaxprops.ulWaveform);
return true;
}
@@ -235,36 +233,43 @@ bool ModulatorCommitter::commit(const EaxEffectProps &props)
template<>
void ModulatorCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Modulator;
- props.mModulator.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY;
- props.mModulator.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF;
- props.mModulator.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM;
+ static constexpr EAXRINGMODULATORPROPERTIES defprops{[]
+ {
+ EAXRINGMODULATORPROPERTIES ret{};
+ ret.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY;
+ ret.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF;
+ ret.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void ModulatorCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void ModulatorCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXRINGMODULATORPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXRINGMODULATOR_NONE: break;
- case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value<Exception>(props.mModulator); break;
- case EAXRINGMODULATOR_FREQUENCY: call.set_value<Exception>(props.mModulator.flFrequency); break;
- case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value<Exception>(props.mModulator.flHighPassCutOff); break;
- case EAXRINGMODULATOR_WAVEFORM: call.set_value<Exception>(props.mModulator.ulWaveform); break;
+ case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXRINGMODULATOR_FREQUENCY: call.set_value<Exception>(props.flFrequency); break;
+ case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value<Exception>(props.flHighPassCutOff); break;
+ case EAXRINGMODULATOR_WAVEFORM: call.set_value<Exception>(props.ulWaveform); break;
default: fail_unknown_property_id();
}
}
template<>
-void ModulatorCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void ModulatorCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXRINGMODULATORPROPERTIES>(props_);
switch (call.get_property_id())
{
case EAXRINGMODULATOR_NONE: break;
- case EAXRINGMODULATOR_ALLPARAMETERS: defer<AllValidator>(call, props.mModulator); break;
- case EAXRINGMODULATOR_FREQUENCY: defer<FrequencyValidator>(call, props.mModulator.flFrequency); break;
- case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer<HighPassCutOffValidator>(call, props.mModulator.flHighPassCutOff); break;
- case EAXRINGMODULATOR_WAVEFORM: defer<WaveformValidator>(call, props.mModulator.ulWaveform); break;
+ case EAXRINGMODULATOR_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXRINGMODULATOR_FREQUENCY: defer<FrequencyValidator>(call, props.flFrequency); break;
+ case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer<HighPassCutOffValidator>(call, props.flHighPassCutOff); break;
+ case EAXRINGMODULATOR_WAVEFORM: defer<WaveformValidator>(call, props.ulWaveform); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/null.cpp b/al/effects/null.cpp
index 0bbc183a..1e8787e7 100644
--- a/al/effects/null.cpp
+++ b/al/effects/null.cpp
@@ -120,7 +120,7 @@ template<>
template<>
bool NullCommitter::commit(const EaxEffectProps &props)
{
- const bool ret{props.mType != mEaxProps.mType};
+ const bool ret{props != mEaxProps};
mEaxProps = props;
return ret;
}
@@ -128,8 +128,7 @@ bool NullCommitter::commit(const EaxEffectProps &props)
template<>
void NullCommitter::SetDefaults(EaxEffectProps &props)
{
- props = EaxEffectProps{};
- props.mType = EaxEffectType::None;
+ props.emplace<std::monostate>();
}
template<>
diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp
index 634eb186..10824016 100644
--- a/al/effects/pshifter.cpp
+++ b/al/effects/pshifter.cpp
@@ -141,15 +141,14 @@ template<>
template<>
bool PitchShifterCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && mEaxProps.mPitchShifter.lCoarseTune == props.mPitchShifter.lCoarseTune
- && mEaxProps.mPitchShifter.lFineTune == props.mPitchShifter.lFineTune)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- mAlProps.Pshifter.CoarseTune = static_cast<int>(mEaxProps.mPitchShifter.lCoarseTune);
- mAlProps.Pshifter.FineTune = static_cast<int>(mEaxProps.mPitchShifter.lFineTune);
+ auto &eaxprops = std::get<EAXPITCHSHIFTERPROPERTIES>(props);
+ mAlProps.Pshifter.CoarseTune = static_cast<int>(eaxprops.lCoarseTune);
+ mAlProps.Pshifter.FineTune = static_cast<int>(eaxprops.lFineTune);
return true;
}
@@ -157,33 +156,34 @@ bool PitchShifterCommitter::commit(const EaxEffectProps &props)
template<>
void PitchShifterCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::PitchShifter;
- props.mPitchShifter.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE;
- props.mPitchShifter.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE;
+ props = EAXPITCHSHIFTERPROPERTIES{EAXPITCHSHIFTER_DEFAULTCOARSETUNE,
+ EAXPITCHSHIFTER_DEFAULTFINETUNE};
}
template<>
-void PitchShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void PitchShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXPITCHSHIFTERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXPITCHSHIFTER_NONE: break;
- case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props.mPitchShifter); break;
- case EAXPITCHSHIFTER_COARSETUNE: call.set_value<Exception>(props.mPitchShifter.lCoarseTune); break;
- case EAXPITCHSHIFTER_FINETUNE: call.set_value<Exception>(props.mPitchShifter.lFineTune); break;
+ case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props); break;
+ case EAXPITCHSHIFTER_COARSETUNE: call.set_value<Exception>(props.lCoarseTune); break;
+ case EAXPITCHSHIFTER_FINETUNE: call.set_value<Exception>(props.lFineTune); break;
default: fail_unknown_property_id();
}
}
template<>
-void PitchShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void PitchShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXPITCHSHIFTERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXPITCHSHIFTER_NONE: break;
- case EAXPITCHSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props.mPitchShifter); break;
- case EAXPITCHSHIFTER_COARSETUNE: defer<CoarseTuneValidator>(call, props.mPitchShifter.lCoarseTune); break;
- case EAXPITCHSHIFTER_FINETUNE: defer<FineTuneValidator>(call, props.mPitchShifter.lFineTune); break;
+ case EAXPITCHSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
+ case EAXPITCHSHIFTER_COARSETUNE: defer<CoarseTuneValidator>(call, props.lCoarseTune); break;
+ case EAXPITCHSHIFTER_FINETUNE: defer<FineTuneValidator>(call, props.lFineTune); break;
default: fail_unknown_property_id();
}
}
diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp
index 440d7b4e..b037443f 100644
--- a/al/effects/reverb.cpp
+++ b/al/effects/reverb.cpp
@@ -945,7 +945,7 @@ struct EnvironmentSizeDeferrer2 {
if ((props.dwFlags & EAX2LISTENERFLAGS_DECAYTIMESCALE) != 0)
{
- props.flDecayTime = clamp(
+ props.flDecayTime = std::clamp(
props.flDecayTime * scale,
EAXREVERB_MINDECAYTIME,
EAXREVERB_MAXDECAYTIME);
@@ -954,7 +954,7 @@ struct EnvironmentSizeDeferrer2 {
if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSSCALE) != 0 &&
(props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0)
{
- props.lReflections = clamp(
+ props.lReflections = std::clamp(
props.lReflections - static_cast<long>(gain_to_level_mb(scale)),
EAXREVERB_MINREFLECTIONS,
EAXREVERB_MAXREFLECTIONS);
@@ -962,7 +962,7 @@ struct EnvironmentSizeDeferrer2 {
if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0)
{
- props.flReflectionsDelay = clamp(
+ props.flReflectionsDelay = std::clamp(
props.flReflectionsDelay * scale,
EAXREVERB_MINREFLECTIONSDELAY,
EAXREVERB_MAXREFLECTIONSDELAY);
@@ -972,7 +972,7 @@ struct EnvironmentSizeDeferrer2 {
{
const auto log_scalar = ((props.dwFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
- props.lReverb = clamp(
+ props.lReverb = std::clamp(
props.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
EAXREVERB_MINREVERB,
EAXREVERB_MAXREVERB);
@@ -980,7 +980,7 @@ struct EnvironmentSizeDeferrer2 {
if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBDELAYSCALE) != 0)
{
- props.flReverbDelay = clamp(
+ props.flReverbDelay = std::clamp(
props.flReverbDelay * scale,
EAXREVERB_MINREVERBDELAY,
EAXREVERB_MAXREVERBDELAY);
@@ -1015,7 +1015,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0)
{
- props.flDecayTime = clamp(
+ props.flDecayTime = std::clamp(
props.flDecayTime * scale,
EAXREVERB_MINDECAYTIME,
EAXREVERB_MAXDECAYTIME);
@@ -1024,7 +1024,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0 &&
(props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
{
- props.lReflections = clamp(
+ props.lReflections = std::clamp(
props.lReflections - static_cast<long>(gain_to_level_mb(scale)),
EAXREVERB_MINREFLECTIONS,
EAXREVERB_MAXREFLECTIONS);
@@ -1032,7 +1032,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
{
- props.flReflectionsDelay = clamp(
+ props.flReflectionsDelay = std::clamp(
props.flReflectionsDelay * scale,
EAXREVERB_MINREFLECTIONSDELAY,
EAXREVERB_MAXREFLECTIONSDELAY);
@@ -1041,7 +1041,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0)
{
const auto log_scalar = ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
- props.lReverb = clamp(
+ props.lReverb = std::clamp(
props.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
EAXREVERB_MINREVERB,
EAXREVERB_MAXREVERB);
@@ -1049,7 +1049,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0)
{
- props.flReverbDelay = clamp(
+ props.flReverbDelay = std::clamp(
props.flReverbDelay * scale,
EAXREVERB_MINREVERBDELAY,
EAXREVERB_MAXREVERBDELAY);
@@ -1057,7 +1057,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0)
{
- props.flEchoTime = clamp(
+ props.flEchoTime = std::clamp(
props.flEchoTime * scale,
EAXREVERB_MINECHOTIME,
EAXREVERB_MAXECHOTIME);
@@ -1065,7 +1065,7 @@ struct EnvironmentSizeDeferrer3 {
if ((props.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0)
{
- props.flModulationTime = clamp(
+ props.flModulationTime = std::clamp(
props.flModulationTime * scale,
EAXREVERB_MINMODULATIONTIME,
EAXREVERB_MAXMODULATIONTIME);
@@ -1089,48 +1089,35 @@ struct EaxReverbCommitter::Exception : public EaxReverbEffectException
void EaxReverbCommitter::translate(const EAX_REVERBPROPERTIES& src, EaxEffectProps& dst) noexcept
{
assert(src.environment <= EAX1REVERB_MAXENVIRONMENT);
- dst.mType = EaxEffectType::Reverb;
- dst.mReverb = EAXREVERB_PRESETS[src.environment];
- dst.mReverb.flDecayTime = src.fDecayTime_sec;
- dst.mReverb.flDecayHFRatio = src.fDamping;
- dst.mReverb.lReverb = mini(static_cast<int>(gain_to_level_mb(src.fVolume)), 0);
+ auto&& eaxprops = dst.emplace<EAXREVERBPROPERTIES>(EAXREVERB_PRESETS[src.environment]);
+ eaxprops.flDecayTime = src.fDecayTime_sec;
+ eaxprops.flDecayHFRatio = src.fDamping;
+ eaxprops.lReverb = mini(static_cast<int>(gain_to_level_mb(src.fVolume)), 0);
}
void EaxReverbCommitter::translate(const EAX20LISTENERPROPERTIES& src, EaxEffectProps& dst) noexcept
{
assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT);
- const auto& env = EAXREVERB_PRESETS[src.dwEnvironment];
- dst.mType = EaxEffectType::Reverb;
- dst.mReverb.ulEnvironment = src.dwEnvironment;
- dst.mReverb.flEnvironmentSize = src.flEnvironmentSize;
- dst.mReverb.flEnvironmentDiffusion = src.flEnvironmentDiffusion;
- dst.mReverb.lRoom = src.lRoom;
- dst.mReverb.lRoomHF = src.lRoomHF;
- dst.mReverb.lRoomLF = env.lRoomLF;
- dst.mReverb.flDecayTime = src.flDecayTime;
- dst.mReverb.flDecayHFRatio = src.flDecayHFRatio;
- dst.mReverb.flDecayLFRatio = env.flDecayLFRatio;
- dst.mReverb.lReflections = src.lReflections;
- dst.mReverb.flReflectionsDelay = src.flReflectionsDelay;
- dst.mReverb.vReflectionsPan = env.vReflectionsPan;
- dst.mReverb.lReverb = src.lReverb;
- dst.mReverb.flReverbDelay = src.flReverbDelay;
- dst.mReverb.vReverbPan = env.vReverbPan;
- dst.mReverb.flEchoTime = env.flEchoTime;
- dst.mReverb.flEchoDepth = env.flEchoDepth;
- dst.mReverb.flModulationTime = env.flModulationTime;
- dst.mReverb.flModulationDepth = env.flModulationDepth;
- dst.mReverb.flAirAbsorptionHF = src.flAirAbsorptionHF;
- dst.mReverb.flHFReference = env.flHFReference;
- dst.mReverb.flLFReference = env.flLFReference;
- dst.mReverb.flRoomRolloffFactor = src.flRoomRolloffFactor;
- dst.mReverb.ulFlags = src.dwFlags;
+ auto&& eaxprops = dst.emplace<EAXREVERBPROPERTIES>(EAXREVERB_PRESETS[src.dwEnvironment]);
+ eaxprops.ulEnvironment = src.dwEnvironment;
+ eaxprops.flEnvironmentSize = src.flEnvironmentSize;
+ eaxprops.flEnvironmentDiffusion = src.flEnvironmentDiffusion;
+ eaxprops.lRoom = src.lRoom;
+ eaxprops.lRoomHF = src.lRoomHF;
+ eaxprops.flDecayTime = src.flDecayTime;
+ eaxprops.flDecayHFRatio = src.flDecayHFRatio;
+ eaxprops.lReflections = src.lReflections;
+ eaxprops.flReflectionsDelay = src.flReflectionsDelay;
+ eaxprops.lReverb = src.lReverb;
+ eaxprops.flReverbDelay = src.flReverbDelay;
+ eaxprops.flAirAbsorptionHF = src.flAirAbsorptionHF;
+ eaxprops.flRoomRolloffFactor = src.flRoomRolloffFactor;
+ eaxprops.ulFlags = src.dwFlags;
}
void EaxReverbCommitter::translate(const EAXREVERBPROPERTIES& src, EaxEffectProps& dst) noexcept
{
- dst.mType = EaxEffectType::Reverb;
- dst.mReverb = src;
+ dst = src;
}
bool EaxReverbCommitter::commit(const EAX_REVERBPROPERTIES &props)
@@ -1156,41 +1143,41 @@ bool EaxReverbCommitter::commit(const EAXREVERBPROPERTIES &props)
bool EaxReverbCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && memcmp(&props.mReverb, &mEaxProps.mReverb, sizeof(mEaxProps.mReverb)) == 0)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
- const auto size = props.mReverb.flEnvironmentSize;
+ auto &eaxprops = std::get<EAXREVERBPROPERTIES>(props);
+ const auto size = eaxprops.flEnvironmentSize;
const auto density = (size * size * size) / 16.0F;
mAlProps.Reverb.Density = std::min(density, AL_EAXREVERB_MAX_DENSITY);
- mAlProps.Reverb.Diffusion = props.mReverb.flEnvironmentDiffusion;
- mAlProps.Reverb.Gain = level_mb_to_gain(static_cast<float>(props.mReverb.lRoom));
- mAlProps.Reverb.GainHF = level_mb_to_gain(static_cast<float>(props.mReverb.lRoomHF));
- mAlProps.Reverb.GainLF = level_mb_to_gain(static_cast<float>(props.mReverb.lRoomLF));
- mAlProps.Reverb.DecayTime = props.mReverb.flDecayTime;
- mAlProps.Reverb.DecayHFRatio = props.mReverb.flDecayHFRatio;
- mAlProps.Reverb.DecayLFRatio = mEaxProps.mReverb.flDecayLFRatio;
- mAlProps.Reverb.ReflectionsGain = level_mb_to_gain(static_cast<float>(props.mReverb.lReflections));
- mAlProps.Reverb.ReflectionsDelay = props.mReverb.flReflectionsDelay;
- mAlProps.Reverb.ReflectionsPan[0] = props.mReverb.vReflectionsPan.x;
- mAlProps.Reverb.ReflectionsPan[1] = props.mReverb.vReflectionsPan.y;
- mAlProps.Reverb.ReflectionsPan[2] = props.mReverb.vReflectionsPan.z;
- mAlProps.Reverb.LateReverbGain = level_mb_to_gain(static_cast<float>(props.mReverb.lReverb));
- mAlProps.Reverb.LateReverbDelay = props.mReverb.flReverbDelay;
- mAlProps.Reverb.LateReverbPan[0] = props.mReverb.vReverbPan.x;
- mAlProps.Reverb.LateReverbPan[1] = props.mReverb.vReverbPan.y;
- mAlProps.Reverb.LateReverbPan[2] = props.mReverb.vReverbPan.z;
- mAlProps.Reverb.EchoTime = props.mReverb.flEchoTime;
- mAlProps.Reverb.EchoDepth = props.mReverb.flEchoDepth;
- mAlProps.Reverb.ModulationTime = props.mReverb.flModulationTime;
- mAlProps.Reverb.ModulationDepth = props.mReverb.flModulationDepth;
- mAlProps.Reverb.AirAbsorptionGainHF = level_mb_to_gain(props.mReverb.flAirAbsorptionHF);
- mAlProps.Reverb.HFReference = props.mReverb.flHFReference;
- mAlProps.Reverb.LFReference = props.mReverb.flLFReference;
- mAlProps.Reverb.RoomRolloffFactor = props.mReverb.flRoomRolloffFactor;
- mAlProps.Reverb.DecayHFLimit = ((props.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
+ mAlProps.Reverb.Diffusion = eaxprops.flEnvironmentDiffusion;
+ mAlProps.Reverb.Gain = level_mb_to_gain(static_cast<float>(eaxprops.lRoom));
+ mAlProps.Reverb.GainHF = level_mb_to_gain(static_cast<float>(eaxprops.lRoomHF));
+ mAlProps.Reverb.GainLF = level_mb_to_gain(static_cast<float>(eaxprops.lRoomLF));
+ mAlProps.Reverb.DecayTime = eaxprops.flDecayTime;
+ mAlProps.Reverb.DecayHFRatio = eaxprops.flDecayHFRatio;
+ mAlProps.Reverb.DecayLFRatio = eaxprops.flDecayLFRatio;
+ mAlProps.Reverb.ReflectionsGain = level_mb_to_gain(static_cast<float>(eaxprops.lReflections));
+ mAlProps.Reverb.ReflectionsDelay = eaxprops.flReflectionsDelay;
+ mAlProps.Reverb.ReflectionsPan[0] = eaxprops.vReflectionsPan.x;
+ mAlProps.Reverb.ReflectionsPan[1] = eaxprops.vReflectionsPan.y;
+ mAlProps.Reverb.ReflectionsPan[2] = eaxprops.vReflectionsPan.z;
+ mAlProps.Reverb.LateReverbGain = level_mb_to_gain(static_cast<float>(eaxprops.lReverb));
+ mAlProps.Reverb.LateReverbDelay = eaxprops.flReverbDelay;
+ mAlProps.Reverb.LateReverbPan[0] = eaxprops.vReverbPan.x;
+ mAlProps.Reverb.LateReverbPan[1] = eaxprops.vReverbPan.y;
+ mAlProps.Reverb.LateReverbPan[2] = eaxprops.vReverbPan.z;
+ mAlProps.Reverb.EchoTime = eaxprops.flEchoTime;
+ mAlProps.Reverb.EchoDepth = eaxprops.flEchoDepth;
+ mAlProps.Reverb.ModulationTime = eaxprops.flModulationTime;
+ mAlProps.Reverb.ModulationDepth = eaxprops.flModulationDepth;
+ mAlProps.Reverb.AirAbsorptionGainHF = level_mb_to_gain(eaxprops.flAirAbsorptionHF);
+ mAlProps.Reverb.HFReference = eaxprops.flHFReference;
+ mAlProps.Reverb.LFReference = eaxprops.flLFReference;
+ mAlProps.Reverb.RoomRolloffFactor = eaxprops.flRoomRolloffFactor;
+ mAlProps.Reverb.DecayHFLimit = ((eaxprops.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
return true;
}
@@ -1212,8 +1199,7 @@ void EaxReverbCommitter::SetDefaults(EAXREVERBPROPERTIES &props)
void EaxReverbCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::Reverb;
- SetDefaults(props.mReverb);
+ SetDefaults(props.emplace<EAXREVERBPROPERTIES>());
}
@@ -1290,7 +1276,7 @@ void EaxReverbCommitter::Get(const EaxCall &call, const EAXREVERBPROPERTIES &pro
void EaxReverbCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
{
- Get(call, props.mReverb);
+ Get(call, std::get<EAXREVERBPROPERTIES>(props));
}
@@ -1493,7 +1479,7 @@ void EaxReverbCommitter::Set(const EaxCall &call, EAXREVERBPROPERTIES &props)
void EaxReverbCommitter::Set(const EaxCall &call, EaxEffectProps &props)
{
- Set(call, props.mReverb);
+ Set(call, std::get<EAXREVERBPROPERTIES>(props));
}
#endif // ALSOFT_EAX
diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp
index 21ea3680..f2551229 100644
--- a/al/effects/vmorpher.cpp
+++ b/al/effects/vmorpher.cpp
@@ -1,13 +1,13 @@
#include "config.h"
+#include <optional>
#include <stdexcept>
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
-#include "aloptional.h"
#include "effects.h"
#ifdef ALSOFT_EAX
@@ -20,7 +20,7 @@
namespace {
-al::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
+std::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
{
#define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \
return VMorpherPhenome::x
@@ -57,7 +57,7 @@ al::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
HANDLE_PHENOME(V);
HANDLE_PHENOME(Z);
}
- return al::nullopt;
+ return std::nullopt;
#undef HANDLE_PHENOME
}
ALenum EnumFromPhenome(VMorpherPhenome phenome)
@@ -100,7 +100,7 @@ ALenum EnumFromPhenome(VMorpherPhenome phenome)
#undef HANDLE_PHENOME
}
-al::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
+std::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
{
switch(value)
{
@@ -108,7 +108,7 @@ al::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return VMorpherWaveform::Triangle;
case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return VMorpherWaveform::Sawtooth;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum EnumFromWaveform(VMorpherWaveform type)
{
@@ -355,13 +355,7 @@ template<>
template<>
bool VocalMorpherCommitter::commit(const EaxEffectProps &props)
{
- if(props.mType == mEaxProps.mType
- && mEaxProps.mVocalMorpher.ulPhonemeA == props.mVocalMorpher.ulPhonemeA
- && mEaxProps.mVocalMorpher.lPhonemeACoarseTuning == props.mVocalMorpher.lPhonemeACoarseTuning
- && mEaxProps.mVocalMorpher.ulPhonemeB == props.mVocalMorpher.ulPhonemeB
- && mEaxProps.mVocalMorpher.lPhonemeBCoarseTuning == props.mVocalMorpher.lPhonemeBCoarseTuning
- && mEaxProps.mVocalMorpher.ulWaveform == props.mVocalMorpher.ulWaveform
- && mEaxProps.mVocalMorpher.flRate == props.mVocalMorpher.flRate)
+ if(props == mEaxProps)
return false;
mEaxProps = props;
@@ -413,12 +407,13 @@ bool VocalMorpherCommitter::commit(const EaxEffectProps &props)
return VMorpherWaveform::Sinusoid;
};
- mAlProps.Vmorpher.PhonemeA = get_phoneme(props.mVocalMorpher.ulPhonemeA);
- mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast<int>(props.mVocalMorpher.lPhonemeACoarseTuning);
- mAlProps.Vmorpher.PhonemeB = get_phoneme(props.mVocalMorpher.ulPhonemeB);
- mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast<int>(props.mVocalMorpher.lPhonemeBCoarseTuning);
- mAlProps.Vmorpher.Waveform = get_waveform(props.mVocalMorpher.ulWaveform);
- mAlProps.Vmorpher.Rate = props.mVocalMorpher.flRate;
+ auto &eaxprops = std::get<EAXVOCALMORPHERPROPERTIES>(props);
+ mAlProps.Vmorpher.PhonemeA = get_phoneme(eaxprops.ulPhonemeA);
+ mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast<int>(eaxprops.lPhonemeACoarseTuning);
+ mAlProps.Vmorpher.PhonemeB = get_phoneme(eaxprops.ulPhonemeB);
+ mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast<int>(eaxprops.lPhonemeBCoarseTuning);
+ mAlProps.Vmorpher.Waveform = get_waveform(eaxprops.ulWaveform);
+ mAlProps.Vmorpher.Rate = eaxprops.flRate;
return true;
}
@@ -426,49 +421,55 @@ bool VocalMorpherCommitter::commit(const EaxEffectProps &props)
template<>
void VocalMorpherCommitter::SetDefaults(EaxEffectProps &props)
{
- props.mType = EaxEffectType::VocalMorpher;
- props.mVocalMorpher.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
- props.mVocalMorpher.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
- props.mVocalMorpher.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
- props.mVocalMorpher.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
- props.mVocalMorpher.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
- props.mVocalMorpher.flRate = EAXVOCALMORPHER_DEFAULTRATE;
+ static constexpr EAXVOCALMORPHERPROPERTIES defprops{[]
+ {
+ EAXVOCALMORPHERPROPERTIES ret{};
+ ret.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
+ ret.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
+ ret.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
+ ret.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
+ ret.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
+ ret.flRate = EAXVOCALMORPHER_DEFAULTRATE;
+ return ret;
+ }()};
+ props = defprops;
}
template<>
-void VocalMorpherCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
+void VocalMorpherCommitter::Get(const EaxCall &call, const EaxEffectProps &props_)
{
+ auto &props = std::get<EAXVOCALMORPHERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXVOCALMORPHER_NONE:
break;
case EAXVOCALMORPHER_ALLPARAMETERS:
- call.set_value<Exception>(props.mVocalMorpher);
+ call.set_value<Exception>(props);
break;
case EAXVOCALMORPHER_PHONEMEA:
- call.set_value<Exception>(props.mVocalMorpher.ulPhonemeA);
+ call.set_value<Exception>(props.ulPhonemeA);
break;
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
- call.set_value<Exception>(props.mVocalMorpher.lPhonemeACoarseTuning);
+ call.set_value<Exception>(props.lPhonemeACoarseTuning);
break;
case EAXVOCALMORPHER_PHONEMEB:
- call.set_value<Exception>(props.mVocalMorpher.ulPhonemeB);
+ call.set_value<Exception>(props.ulPhonemeB);
break;
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
- call.set_value<Exception>(props.mVocalMorpher.lPhonemeBCoarseTuning);
+ call.set_value<Exception>(props.lPhonemeBCoarseTuning);
break;
case EAXVOCALMORPHER_WAVEFORM:
- call.set_value<Exception>(props.mVocalMorpher.ulWaveform);
+ call.set_value<Exception>(props.ulWaveform);
break;
case EAXVOCALMORPHER_RATE:
- call.set_value<Exception>(props.mVocalMorpher.flRate);
+ call.set_value<Exception>(props.flRate);
break;
default:
@@ -477,39 +478,40 @@ void VocalMorpherCommitter::Get(const EaxCall &call, const EaxEffectProps &props
}
template<>
-void VocalMorpherCommitter::Set(const EaxCall &call, EaxEffectProps &props)
+void VocalMorpherCommitter::Set(const EaxCall &call, EaxEffectProps &props_)
{
+ auto &props = std::get<EAXVOCALMORPHERPROPERTIES>(props_);
switch(call.get_property_id())
{
case EAXVOCALMORPHER_NONE:
break;
case EAXVOCALMORPHER_ALLPARAMETERS:
- defer<AllValidator>(call, props.mVocalMorpher);
+ defer<AllValidator>(call, props);
break;
case EAXVOCALMORPHER_PHONEMEA:
- defer<PhonemeAValidator>(call, props.mVocalMorpher.ulPhonemeA);
+ defer<PhonemeAValidator>(call, props.ulPhonemeA);
break;
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
- defer<PhonemeACoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeACoarseTuning);
+ defer<PhonemeACoarseTuningValidator>(call, props.lPhonemeACoarseTuning);
break;
case EAXVOCALMORPHER_PHONEMEB:
- defer<PhonemeBValidator>(call, props.mVocalMorpher.ulPhonemeB);
+ defer<PhonemeBValidator>(call, props.ulPhonemeB);
break;
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
- defer<PhonemeBCoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeBCoarseTuning);
+ defer<PhonemeBCoarseTuningValidator>(call, props.lPhonemeBCoarseTuning);
break;
case EAXVOCALMORPHER_WAVEFORM:
- defer<WaveformValidator>(call, props.mVocalMorpher.ulWaveform);
+ defer<WaveformValidator>(call, props.ulWaveform);
break;
case EAXVOCALMORPHER_RATE:
- defer<RateValidator>(call, props.mVocalMorpher.flRate);
+ defer<RateValidator>(call, props.flRate);
break;
default:
diff --git a/al/error.cpp b/al/error.cpp
index afa7019a..c2359477 100644
--- a/al/error.cpp
+++ b/al/error.cpp
@@ -29,25 +29,32 @@
#include <csignal>
#include <cstdarg>
#include <cstdio>
+#include <cstdlib>
#include <cstring>
+#include <limits>
#include <mutex>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
+#include "al/debug.h"
+#include "alc/alconfig.h"
#include "alc/context.h"
#include "almalloc.h"
+#include "alstring.h"
#include "core/except.h"
#include "core/logging.h"
+#include "direct_defs.h"
#include "opthelpers.h"
-#include "vector.h"
+#include "strutils.h"
bool TrapALError{false};
void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
{
- auto message = al::vector<char>(256);
+ auto message = std::vector<char>(256);
va_list args, args2;
va_start(args, msg);
@@ -61,8 +68,13 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
va_end(args2);
va_end(args);
- if(msglen >= 0) msg = message.data();
- else msg = "<internal error constructing message>";
+ if(msglen >= 0)
+ msg = message.data();
+ else
+ {
+ msg = "<internal error constructing message>";
+ msglen = static_cast<int>(strlen(msg));
+ }
WARN("Error generated on context %p, code 0x%04x, \"%s\"\n",
decltype(std::declval<void*>()){this}, errorCode, msg);
@@ -79,15 +91,36 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
ALenum curerr{AL_NO_ERROR};
mLastError.compare_exchange_strong(curerr, errorCode);
+
+ debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High,
+ {msg, static_cast<uint>(msglen)});
}
-AL_API ALenum AL_APIENTRY alGetError(void)
-START_API_FUNC
+/* Special-case alGetError since it (potentially) raises a debug signal and
+ * returns a non-default value for a null context.
+ */
+AL_API ALenum AL_APIENTRY alGetError(void) noexcept
{
- ContextRef context{GetContextRef()};
+ auto context = GetContextRef();
if(!context) UNLIKELY
{
- static constexpr ALenum deferror{AL_INVALID_OPERATION};
+ static const ALenum deferror{[](const char *envname, const char *optname) -> ALenum
+ {
+ auto optstr = al::getenv(envname);
+ if(!optstr)
+ optstr = ConfigValueStr(nullptr, "game_compat", optname);
+
+ if(optstr)
+ {
+ char *end{};
+ auto value = std::strtoul(optstr->c_str(), &end, 0);
+ if(end && *end == '\0' && value <= std::numeric_limits<ALenum>::max())
+ return static_cast<ALenum>(value);
+ ERR("Invalid default error value: \"%s\"", optstr->c_str());
+ }
+ return AL_INVALID_OPERATION;
+ }("__ALSOFT_DEFAULT_ERROR", "default-error")};
+
WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
if(TrapALError)
{
@@ -100,7 +133,10 @@ START_API_FUNC
}
return deferror;
}
+ return alGetErrorDirect(context.get());
+}
+FORCE_ALIGN ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept
+{
return context->mLastError.exchange(AL_NO_ERROR);
}
-END_API_FUNC
diff --git a/al/event.cpp b/al/event.cpp
index 1bc39d1e..8b76ceff 100644
--- a/al/event.cpp
+++ b/al/event.cpp
@@ -10,14 +10,15 @@
#include <memory>
#include <mutex>
#include <new>
+#include <optional>
#include <string>
+#include <string_view>
#include <thread>
#include <utility>
#include "AL/al.h"
#include "AL/alc.h"
-#include "albyte.h"
#include "alc/context.h"
#include "alc/effects/base.h"
#include "alc/inprogext.h"
@@ -26,12 +27,21 @@
#include "core/except.h"
#include "core/logging.h"
#include "core/voice_change.h"
+#include "debug.h"
+#include "direct_defs.h"
#include "opthelpers.h"
#include "ringbuffer.h"
-#include "threads.h"
-static int EventThread(ALCcontext *context)
+namespace {
+
+template<typename... Ts>
+struct overloaded : Ts... { using Ts::operator()...; };
+
+template<typename... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
+
+int EventThread(ALCcontext *context)
{
RingBuffer *ring{context->mAsyncEvents.get()};
bool quitnow{false};
@@ -46,74 +56,101 @@ static int EventThread(ALCcontext *context)
std::lock_guard<std::mutex> _{context->mEventCbLock};
do {
- auto *evt_ptr = reinterpret_cast<AsyncEvent*>(evt_data.buf);
+ auto *evt_ptr = std::launder(reinterpret_cast<AsyncEvent*>(evt_data.buf));
evt_data.buf += sizeof(AsyncEvent);
evt_data.len -= 1;
- AsyncEvent evt{*evt_ptr};
- al::destroy_at(evt_ptr);
+ AsyncEvent event{std::move(*evt_ptr)};
+ std::destroy_at(evt_ptr);
ring->readAdvance(1);
- quitnow = evt.EnumType == AsyncEvent::KillThread;
+ quitnow = std::holds_alternative<AsyncKillThread>(event);
if(quitnow) UNLIKELY break;
- if(evt.EnumType == AsyncEvent::ReleaseEffectState)
- {
- al::intrusive_ptr<EffectState>{evt.u.mEffectState};
- continue;
- }
-
auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire);
- if(!context->mEventCb || !enabledevts.test(evt.EnumType))
- continue;
-
- if(evt.EnumType == AsyncEvent::SourceStateChange)
+ auto proc_killthread = [](AsyncKillThread&) { };
+ auto proc_release = [](AsyncEffectReleaseEvent &evt)
+ {
+ al::intrusive_ptr<EffectState>{evt.mEffectState};
+ };
+ auto proc_srcstate = [context,enabledevts](AsyncSourceStateEvent &evt)
{
+ if(!context->mEventCb
+ || !enabledevts.test(al::to_underlying(AsyncEnableBits::SourceState)))
+ return;
+
ALuint state{};
- std::string msg{"Source ID " + std::to_string(evt.u.srcstate.id)};
+ std::string msg{"Source ID " + std::to_string(evt.mId)};
msg += " state has changed to ";
- switch(evt.u.srcstate.state)
+ switch(evt.mState)
{
- case AsyncEvent::SrcState::Reset:
+ case AsyncSrcState::Reset:
msg += "AL_INITIAL";
state = AL_INITIAL;
break;
- case AsyncEvent::SrcState::Stop:
+ case AsyncSrcState::Stop:
msg += "AL_STOPPED";
state = AL_STOPPED;
break;
- case AsyncEvent::SrcState::Play:
+ case AsyncSrcState::Play:
msg += "AL_PLAYING";
state = AL_PLAYING;
break;
- case AsyncEvent::SrcState::Pause:
+ case AsyncSrcState::Pause:
msg += "AL_PAUSED";
state = AL_PAUSED;
break;
}
- context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.u.srcstate.id,
- state, static_cast<ALsizei>(msg.length()), msg.c_str(), context->mEventParam);
- }
- else if(evt.EnumType == AsyncEvent::BufferCompleted)
+ context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.mId, state,
+ static_cast<ALsizei>(msg.length()), msg.c_str(), context->mEventParam);
+ };
+ auto proc_buffercomp = [context,enabledevts](AsyncBufferCompleteEvent &evt)
{
- std::string msg{std::to_string(evt.u.bufcomp.count)};
- if(evt.u.bufcomp.count == 1) msg += " buffer completed";
+ if(!context->mEventCb
+ || !enabledevts.test(al::to_underlying(AsyncEnableBits::BufferCompleted)))
+ return;
+
+ std::string msg{std::to_string(evt.mCount)};
+ if(evt.mCount == 1) msg += " buffer completed";
else msg += " buffers completed";
- context->mEventCb(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, evt.u.bufcomp.id,
- evt.u.bufcomp.count, static_cast<ALsizei>(msg.length()), msg.c_str(),
- context->mEventParam);
- }
- else if(evt.EnumType == AsyncEvent::Disconnected)
+ context->mEventCb(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, evt.mId, evt.mCount,
+ static_cast<ALsizei>(msg.length()), msg.c_str(), context->mEventParam);
+ };
+ auto proc_disconnect = [context,enabledevts](AsyncDisconnectEvent &evt)
{
- context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0,
- static_cast<ALsizei>(strlen(evt.u.disconnect.msg)), evt.u.disconnect.msg,
- context->mEventParam);
- }
+ const std::string_view message{evt.msg};
+
+ context->debugMessage(DebugSource::System, DebugType::Error, 0,
+ DebugSeverity::High, message);
+
+ if(context->mEventCb
+ && enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected)))
+ context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0,
+ static_cast<ALsizei>(message.length()), message.data(),
+ context->mEventParam);
+ };
+
+ std::visit(overloaded{proc_srcstate, proc_buffercomp, proc_release, proc_disconnect,
+ proc_killthread}, event);
} while(evt_data.len != 0);
}
return 0;
}
+constexpr std::optional<AsyncEnableBits> GetEventType(ALenum etype) noexcept
+{
+ switch(etype)
+ {
+ case AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT: return AsyncEnableBits::BufferCompleted;
+ case AL_EVENT_TYPE_DISCONNECTED_SOFT: return AsyncEnableBits::Disconnected;
+ case AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT: return AsyncEnableBits::SourceState;
+ }
+ return std::nullopt;
+}
+
+} // namespace
+
+
void StartEventThrd(ALCcontext *ctx)
{
try {
@@ -138,7 +175,7 @@ void StopEventThrd(ALCcontext *ctx)
evt_data = ring->getWriteVector().first;
} while(evt_data.len == 0);
}
- al::construct_at(reinterpret_cast<AsyncEvent*>(evt_data.buf), AsyncEvent::KillThread);
+ std::ignore = InitAsyncEvent<AsyncKillThread>(evt_data.buf);
ring->writeAdvance(1);
ctx->mEventSem.post();
@@ -146,34 +183,22 @@ void StopEventThrd(ALCcontext *ctx)
ctx->mEventThread.join();
}
-AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alEventControl,SOFT, ALsizei, const ALenum*, ALboolean)
+FORCE_ALIGN void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count,
+ const ALenum *types, ALboolean enable) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(count < 0) context->setError(AL_INVALID_VALUE, "Controlling %d events", count);
if(count <= 0) return;
if(!types) return context->setError(AL_INVALID_VALUE, "NULL pointer");
ContextBase::AsyncEventBitset flags{};
- const ALenum *types_end = types+count;
- auto bad_type = std::find_if_not(types, types_end,
- [&flags](ALenum type) noexcept -> bool
- {
- if(type == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT)
- flags.set(AsyncEvent::BufferCompleted);
- else if(type == AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT)
- flags.set(AsyncEvent::SourceStateChange);
- else if(type == AL_EVENT_TYPE_DISCONNECTED_SOFT)
- flags.set(AsyncEvent::Disconnected);
- else
- return false;
- return true;
- }
- );
- if(bad_type != types_end)
- return context->setError(AL_INVALID_ENUM, "Invalid event type 0x%04x", *bad_type);
+ for(ALenum evttype : al::span{types, static_cast<uint>(count)})
+ {
+ auto etype = GetEventType(evttype);
+ if(!etype)
+ return context->setError(AL_INVALID_ENUM, "Invalid event type 0x%04x", evttype);
+ flags.set(al::to_underlying(*etype));
+ }
if(enable)
{
@@ -199,17 +224,12 @@ START_API_FUNC
std::lock_guard<std::mutex> _{context->mEventCbLock};
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam)
-START_API_FUNC
+AL_API DECL_FUNCEXT2(void, alEventCallback,SOFT, ALEVENTPROCSOFT, void*)
+FORCE_ALIGN void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context,
+ ALEVENTPROCSOFT callback, void *userParam) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- std::lock_guard<std::mutex> _{context->mPropLock};
- std::lock_guard<std::mutex> __{context->mEventCbLock};
+ std::lock_guard<std::mutex> _{context->mEventCbLock};
context->mEventCb = callback;
context->mEventParam = userParam;
}
-END_API_FUNC
diff --git a/al/extension.cpp b/al/extension.cpp
index 3ead0af8..6d1ac327 100644
--- a/al/extension.cpp
+++ b/al/extension.cpp
@@ -30,15 +30,13 @@
#include "alc/context.h"
#include "alstring.h"
#include "core/except.h"
+#include "direct_defs.h"
#include "opthelpers.h"
-AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsExtensionPresent, const ALchar*)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extName) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return AL_FALSE;
-
if(!extName) UNLIKELY
{
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -46,37 +44,36 @@ START_API_FUNC
}
size_t len{strlen(extName)};
- const char *ptr{context->mExtensionList};
- while(ptr && *ptr)
+ for(std::string_view ext : context->mExtensions)
{
- if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
+ if(len == ext.length() && al::strncasecmp(ext.data(), extName, len) == 0)
return AL_TRUE;
-
- if((ptr=strchr(ptr, ' ')) != nullptr)
- {
- do {
- ++ptr;
- } while(isspace(*ptr));
- }
}
return AL_FALSE;
}
-END_API_FUNC
-AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName)
-START_API_FUNC
+AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) noexcept
+{
+ if(!funcName) return nullptr;
+ return alcGetProcAddress(nullptr, funcName);
+}
+
+FORCE_ALIGN ALvoid* AL_APIENTRY alGetProcAddressDirect(ALCcontext*, const ALchar *funcName) noexcept
{
if(!funcName) return nullptr;
return alcGetProcAddress(nullptr, funcName);
}
-END_API_FUNC
-AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName)
-START_API_FUNC
+AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) noexcept
+{
+ if(!enumName) return static_cast<ALenum>(0);
+ return alcGetEnumValue(nullptr, enumName);
+}
+
+FORCE_ALIGN ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext*, const ALchar *enumName) noexcept
{
if(!enumName) return static_cast<ALenum>(0);
return alcGetEnumValue(nullptr, enumName);
}
-END_API_FUNC
diff --git a/al/filter.cpp b/al/filter.cpp
index 73efa01f..f0a078b7 100644
--- a/al/filter.cpp
+++ b/al/filter.cpp
@@ -31,6 +31,7 @@
#include <mutex>
#include <new>
#include <numeric>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
@@ -42,8 +43,8 @@
#include "almalloc.h"
#include "alnumeric.h"
#include "core/except.h"
+#include "direct_defs.h"
#include "opthelpers.h"
-#include "vector.h"
namespace {
@@ -73,20 +74,157 @@ filter_exception::filter_exception(ALenum code, const char* msg, ...) : mErrorCo
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 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->mTypeVariant.emplace<LowpassFilterTable>();
+ }
+ 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->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->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
+ filter->LFReference = HIGHPASSFREQREF;
+ filter->mTypeVariant.emplace<BandpassFilterTable>();
+ }
+ else
+ {
+ filter->Gain = 1.0f;
+ filter->GainHF = 1.0f;
+ filter->HFReference = LOWPASSFREQREF;
+ filter->GainLF = 1.0f;
+ filter->LFReference = HIGHPASSFREQREF;
+ filter->mTypeVariant.emplace<NullFilterTable>();
+ }
+ filter->type = type;
}
-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*)
+bool EnsureFilters(ALCdevice *device, size_t needed)
+{
+ 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)); })};
+
+ while(needed > count)
+ {
+ 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;
+ }
+ return true;
+}
+
+
+ALfilter *AllocFilter(ALCdevice *device)
+{
+ auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(),
+ [](const FilterSubList &entry) noexcept -> bool
+ { return entry.FreeMask != 0; });
+ auto lidx = static_cast<ALuint>(std::distance(device->FilterList.begin(), sublist));
+ auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask));
+ ASSUME(slidx < 64);
+
+ ALfilter *filter{al::construct_at(sublist->Filters + slidx)};
+ InitFilterParams(filter, AL_FILTER_NULL);
+
+ /* Add 1 to avoid filter ID 0. */
+ filter->id = ((lidx<<6) | slidx) + 1;
+
+ sublist->FreeMask &= ~(1_u64 << slidx);
+
+ return filter;
+}
+
+void FreeFilter(ALCdevice *device, ALfilter *filter)
{
- throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x",
- param};
+ device->mFilterNames.erase(filter->id);
+
+ const ALuint id{filter->id - 1};
+ const size_t lidx{id >> 6};
+ const ALuint slidx{id & 0x3f};
+
+ std::destroy_at(filter);
+
+ device->FilterList[lidx].FreeMask |= 1_u64 << slidx;
}
-void ALlowpass_setParamf(ALfilter *filter, ALenum param, float val)
+
+
+inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
+{
+ const size_t lidx{(id-1) >> 6};
+ const ALuint slidx{(id-1) & 0x3f};
+
+ if(lidx >= device->FilterList.size()) UNLIKELY
+ return nullptr;
+ FilterSubList &sublist = device->FilterList[lidx];
+ if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
+ return nullptr;
+ return sublist.Filters + slidx;
+}
+
+} // namespace
+
+/* Null filter parameter handlers */
+template<>
+void FilterTable<NullFilterTable>::setParami(ALfilter*, ALenum param, int)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::setParamiv(ALfilter*, ALenum param, const int*)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::setParamf(ALfilter*, ALenum param, float)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::setParamfv(ALfilter*, ALenum param, const float*)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::getParami(const ALfilter*, ALenum param, int*)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::getParamiv(const ALfilter*, ALenum param, int*)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::getParamf(const ALfilter*, ALenum param, float*)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+template<>
+void FilterTable<NullFilterTable>::getParamfv(const ALfilter*, ALenum param, float*)
+{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
+
+/* Lowpass parameter handlers */
+template<>
+void FilterTable<LowpassFilterTable>::setParami(ALfilter*, ALenum param, int)
+{ throw filter_exception{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[0]); }
+template<>
+void FilterTable<LowpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
{
switch(param)
{
@@ -106,17 +244,17 @@ void ALlowpass_setParamf(ALfilter *filter, ALenum param, float val)
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*)
+template<>
+void FilterTable<LowpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
+{ setParamf(filter, param, vals[0]); }
+template<>
+void FilterTable<LowpassFilterTable>::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)
+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)
{
@@ -132,20 +270,19 @@ void ALlowpass_getParamf(const ALfilter *filter, ALenum param, float *val)
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);
-
+template<>
+void FilterTable<LowpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
+{ getParamf(filter, param, vals); }
-void ALhighpass_setParami(ALfilter*, ALenum param, int)
+/* Highpass parameter handlers */
+template<>
+void FilterTable<HighpassFilterTable>::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)
+template<>
+void FilterTable<HighpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
+{ setParami(filter, param, values[0]); }
+template<>
+void FilterTable<HighpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
{
switch(param)
{
@@ -165,17 +302,17 @@ void ALhighpass_setParamf(ALfilter *filter, ALenum param, float val)
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*)
+template<>
+void FilterTable<HighpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
+{ setParamf(filter, param, vals[0]); }
+template<>
+void FilterTable<HighpassFilterTable>::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)
+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)
{
@@ -191,20 +328,19 @@ void ALhighpass_getParamf(const ALfilter *filter, ALenum param, float *val)
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);
-
+template<>
+void FilterTable<HighpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
+{ getParamf(filter, param, vals); }
-void ALbandpass_setParami(ALfilter*, ALenum param, int)
+/* Bandpass parameter handlers */
+template<>
+void FilterTable<BandpassFilterTable>::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)
+template<>
+void FilterTable<BandpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
+{ setParami(filter, param, values[0]); }
+template<>
+void FilterTable<BandpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
{
switch(param)
{
@@ -230,17 +366,17 @@ void ALbandpass_setParamf(ALfilter *filter, ALenum param, float val)
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*)
+template<>
+void FilterTable<BandpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
+{ setParamf(filter, param, vals[0]); }
+template<>
+void FilterTable<BandpassFilterTable>::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)
+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)
{
switch(param)
{
@@ -260,153 +396,14 @@ void ALbandpass_getParamf(const ALfilter *filter, ALenum param, float *val)
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);
-
-
-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;
-}
-
-bool EnsureFilters(ALCdevice *device, size_t needed)
-{
- size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), size_t{0},
- [](size_t cur, const FilterSubList &sublist) noexcept -> size_t
- { return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
-
- while(needed > count)
- {
- 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;
- }
- return true;
-}
-
-
-ALfilter *AllocFilter(ALCdevice *device)
-{
- auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(),
- [](const FilterSubList &entry) noexcept -> bool
- { return entry.FreeMask != 0; });
- auto lidx = static_cast<ALuint>(std::distance(device->FilterList.begin(), sublist));
- auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask));
- ASSUME(slidx < 64);
-
- ALfilter *filter{al::construct_at(sublist->Filters + slidx)};
- InitFilterParams(filter, AL_FILTER_NULL);
-
- /* Add 1 to avoid filter ID 0. */
- filter->id = ((lidx<<6) | slidx) + 1;
-
- sublist->FreeMask &= ~(1_u64 << slidx);
-
- return filter;
-}
-
-void FreeFilter(ALCdevice *device, ALfilter *filter)
-{
- const ALuint id{filter->id - 1};
- const size_t lidx{id >> 6};
- const ALuint slidx{id & 0x3f};
-
- al::destroy_at(filter);
-
- device->FilterList[lidx].FreeMask |= 1_u64 << slidx;
-}
-
-
-inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
-{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
-
- if(lidx >= device->FilterList.size()) UNLIKELY
- return nullptr;
- FilterSubList &sublist = device->FilterList[lidx];
- if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
- return nullptr;
- return sublist.Filters + slidx;
-}
+template<>
+void FilterTable<BandpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
+{ getParamf(filter, param, vals); }
-} // namespace
-AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGenFilters, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept
{
- 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;
@@ -430,7 +427,7 @@ START_API_FUNC
/* Store the allocated buffer IDs in a separate local list, to avoid
* modifying the user storage in case of failure.
*/
- al::vector<ALuint> ids;
+ std::vector<ALuint> ids;
ids.reserve(static_cast<ALuint>(n));
do {
ALfilter *filter{AllocFilter(device)};
@@ -439,14 +436,11 @@ START_API_FUNC
std::copy(ids.begin(), ids.end(), filters);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alDeleteFilters, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n,
+ const ALuint *filters) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Deleting %d filters", n);
if(n <= 0) UNLIKELY return;
@@ -474,71 +468,58 @@ START_API_FUNC
};
std::for_each(filters, filters_end, delete_filter);
}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsFilter, ALuint)
+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> _{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
+AL_API DECL_FUNC3(void, alFilteri, ALuint, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param,
+ ALint value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt) UNLIKELY
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
- else
+ else if(param == AL_FILTER_TYPE)
{
- 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());
- }
+ 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 */
+ std::visit([alfilt,param,value](auto&& thunk){thunk.setParami(alfilt, param, value);},
+ alfilt->mTypeVariant);
+ }
+ catch(filter_exception &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, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param,
+ const ALint *values) noexcept
{
switch(param)
{
case AL_FILTER_TYPE:
- alFilteri(filter, param, values[0]);
+ alFilteriDirect(context, filter, param, values[0]);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
@@ -548,20 +529,18 @@ START_API_FUNC
else try
{
/* Call the appropriate handler */
- alfilt->setParamiv(param, values);
+ std::visit([alfilt,param,values](auto&& thunk){thunk.setParamiv(alfilt, param, values);},
+ alfilt->mTypeVariant);
}
catch(filter_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alFilterf, ALuint, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param,
+ ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
@@ -571,20 +550,18 @@ START_API_FUNC
else try
{
/* Call the appropriate handler */
- alfilt->setParamf(param, value);
+ std::visit([alfilt,param,value](auto&& thunk){thunk.setParamf(alfilt, param, value);},
+ alfilt->mTypeVariant);
}
catch(filter_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alFilterfv, ALuint, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param,
+ const ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
@@ -594,55 +571,48 @@ START_API_FUNC
else try
{
/* Call the appropriate handler */
- alfilt->setParamfv(param, values);
+ std::visit([alfilt,param,values](auto&& thunk){thunk.setParamfv(alfilt, param, values);},
+ alfilt->mTypeVariant);
}
catch(filter_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetFilteri, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param,
+ ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
const ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt) UNLIKELY
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
- else
+ else if(param == AL_FILTER_TYPE)
+ *value = alfilt->type;
+ else try
{
- 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());
- }
+ /* Call the appropriate handler */
+ std::visit([alfilt,param,value](auto&& thunk){thunk.getParami(alfilt, param, value);},
+ alfilt->mTypeVariant);
+ }
+ catch(filter_exception &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, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param,
+ ALint *values) noexcept
{
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> _{device->FilterLock};
@@ -652,20 +622,18 @@ START_API_FUNC
else try
{
/* Call the appropriate handler */
- alfilt->getParamiv(param, values);
+ std::visit([alfilt,param,values](auto&& thunk){thunk.getParamiv(alfilt, param, values);},
+ alfilt->mTypeVariant);
}
catch(filter_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetFilterf, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param,
+ ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
@@ -675,20 +643,18 @@ START_API_FUNC
else try
{
/* Call the appropriate handler */
- alfilt->getParamf(param, value);
+ std::visit([alfilt,param,value](auto&& thunk){thunk.getParamf(alfilt, param, value);},
+ alfilt->mTypeVariant);
}
catch(filter_exception &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
+AL_API DECL_FUNC3(void, alGetFilterfv, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param,
+ ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->FilterLock};
@@ -698,22 +664,38 @@ START_API_FUNC
else try
{
/* Call the appropriate handler */
- alfilt->getParamfv(param, values);
+ std::visit([alfilt,param,values](auto&& thunk){thunk.getParamfv(alfilt, param, values);},
+ alfilt->mTypeVariant);
}
catch(filter_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
}
}
-END_API_FUNC
+
+
+void ALfilter::SetName(ALCcontext *context, ALuint id, std::string_view name)
+{
+ ALCdevice *device{context->mALDevice.get()};
+ std::lock_guard<std::mutex> _{device->FilterLock};
+
+ auto filter = LookupFilter(device, id);
+ if(!filter) UNLIKELY
+ return context->setError(AL_INVALID_NAME, "Invalid filter ID %u", id);
+
+ device->mFilterNames.insert_or_assign(id, name);
+}
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(Filters+idx);
usemask &= ~(1_u64 << idx);
}
FreeMask = ~usemask;
diff --git a/al/filter.h b/al/filter.h
index 65a9e30f..505900d4 100644
--- a/al/filter.h
+++ b/al/filter.h
@@ -1,6 +1,8 @@
#ifndef AL_FILTER_H
#define AL_FILTER_H
+#include <string_view>
+#include <variant>
#include "AL/al.h"
#include "AL/alc.h"
@@ -12,6 +14,25 @@
#define HIGHPASSFREQREF 250.0f
+template<typename T>
+struct FilterTable {
+ static void setParami(struct ALfilter*, ALenum, int);
+ static void setParamiv(struct ALfilter*, ALenum, const int*);
+ static void setParamf(struct ALfilter*, ALenum, float);
+ static void setParamfv(struct ALfilter*, ALenum, const float*);
+
+ static void getParami(const struct ALfilter*, ALenum, int*);
+ static void getParamiv(const struct ALfilter*, ALenum, int*);
+ static void getParamf(const struct ALfilter*, ALenum, float*);
+ static void getParamfv(const struct ALfilter*, ALenum, float*);
+};
+
+struct NullFilterTable : public FilterTable<NullFilterTable> { };
+struct LowpassFilterTable : public FilterTable<LowpassFilterTable> { };
+struct HighpassFilterTable : public FilterTable<HighpassFilterTable> { };
+struct BandpassFilterTable : public FilterTable<BandpassFilterTable> { };
+
+
struct ALfilter {
ALenum type{AL_FILTER_NULL};
@@ -21,30 +42,14 @@ struct ALfilter {
float GainLF{1.0f};
float LFReference{HIGHPASSFREQREF};
- struct Vtable {
- void (*const setParami )(ALfilter *filter, ALenum param, int val);
- void (*const setParamiv)(ALfilter *filter, ALenum param, const int *vals);
- void (*const setParamf )(ALfilter *filter, ALenum param, float val);
- void (*const setParamfv)(ALfilter *filter, ALenum param, const float *vals);
-
- void (*const getParami )(const ALfilter *filter, ALenum param, int *val);
- void (*const getParamiv)(const ALfilter *filter, ALenum param, int *vals);
- void (*const getParamf )(const ALfilter *filter, ALenum param, float *val);
- void (*const getParamfv)(const ALfilter *filter, ALenum param, float *vals);
- };
- const Vtable *vtab{nullptr};
+ using TableTypes = std::variant<NullFilterTable,LowpassFilterTable,HighpassFilterTable,
+ BandpassFilterTable>;
+ TableTypes mTypeVariant;
/* Self ID */
ALuint id{0};
- void setParami(ALenum param, int value) { vtab->setParami(this, param, value); }
- void setParamiv(ALenum param, const int *values) { vtab->setParamiv(this, param, values); }
- void setParamf(ALenum param, float value) { vtab->setParamf(this, param, value); }
- void setParamfv(ALenum param, const float *values) { vtab->setParamfv(this, param, values); }
- void getParami(ALenum param, int *value) const { vtab->getParami(this, param, value); }
- void getParamiv(ALenum param, int *values) const { vtab->getParamiv(this, param, values); }
- void getParamf(ALenum param, float *value) const { vtab->getParamf(this, param, value); }
- void getParamfv(ALenum param, float *values) const { vtab->getParamfv(this, param, values); }
+ static void SetName(ALCcontext *context, ALuint id, std::string_view name);
DISABLE_ALLOC()
};
diff --git a/al/listener.cpp b/al/listener.cpp
index 06d7c370..ea2ebb3f 100644
--- a/al/listener.cpp
+++ b/al/listener.cpp
@@ -33,6 +33,7 @@
#include "almalloc.h"
#include "atomic.h"
#include "core/except.h"
+#include "direct_defs.h"
#include "opthelpers.h"
@@ -68,12 +69,9 @@ inline void CommitAndUpdateProps(ALCcontext *context)
} // namespace
-AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alListenerf, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
switch(param)
@@ -82,28 +80,25 @@ START_API_FUNC
if(!(value >= 0.0f && std::isfinite(value)))
return context->setError(AL_INVALID_VALUE, "Listener gain out of range");
listener.Gain = value;
- UpdateProps(context.get());
+ UpdateProps(context);
break;
case AL_METERS_PER_UNIT:
if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
return context->setError(AL_INVALID_VALUE, "Listener meters per unit out of range");
listener.mMetersPerUnit = value;
- UpdateProps(context.get());
+ UpdateProps(context);
break;
default:
context->setError(AL_INVALID_ENUM, "Invalid listener float property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
-START_API_FUNC
+AL_API DECL_FUNC4(void, alListener3f, ALenum, ALfloat, ALfloat, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1,
+ ALfloat value2, ALfloat value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
switch(param)
@@ -114,7 +109,7 @@ START_API_FUNC
listener.Position[0] = value1;
listener.Position[1] = value2;
listener.Position[2] = value3;
- CommitAndUpdateProps(context.get());
+ CommitAndUpdateProps(context);
break;
case AL_VELOCITY:
@@ -123,40 +118,34 @@ START_API_FUNC
listener.Velocity[0] = value1;
listener.Velocity[1] = value2;
listener.Velocity[2] = value3;
- CommitAndUpdateProps(context.get());
+ CommitAndUpdateProps(context);
break;
default:
context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alListenerfv, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param,
+ const ALfloat *values) noexcept
{
- if(values)
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ switch(param)
{
- switch(param)
- {
- case AL_GAIN:
- case AL_METERS_PER_UNIT:
- alListenerf(param, values[0]);
- return;
+ case AL_GAIN:
+ case AL_METERS_PER_UNIT:
+ alListenerfDirect(context, param, values[0]);
+ return;
- case AL_POSITION:
- case AL_VELOCITY:
- alListener3f(param, values[0], values[1], values[2]);
- return;
- }
+ case AL_POSITION:
+ case AL_VELOCITY:
+ alListener3fDirect(context, param, values[0], values[1], values[2]);
+ return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- if(!values) UNLIKELY
- return context->setError(AL_INVALID_VALUE, "NULL pointer");
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
switch(param)
@@ -172,22 +161,18 @@ START_API_FUNC
listener.OrientUp[0] = values[3];
listener.OrientUp[1] = values[4];
listener.OrientUp[2] = values[5];
- CommitAndUpdateProps(context.get());
+ CommitAndUpdateProps(context);
break;
default:
context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alListeneri(ALenum param, ALint /*value*/)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alListeneri, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint /*value*/) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
switch(param)
{
@@ -195,23 +180,20 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener integer property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3)
-START_API_FUNC
+AL_API DECL_FUNC4(void, alListener3i, ALenum, ALint, ALint, ALint)
+FORCE_ALIGN void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1,
+ ALint value2, ALint value3) noexcept
{
switch(param)
{
case AL_POSITION:
case AL_VELOCITY:
- alListener3f(param, static_cast<ALfloat>(value1), static_cast<ALfloat>(value2),
- static_cast<ALfloat>(value3));
+ alListener3fDirect(context, param, static_cast<ALfloat>(value1),
+ static_cast<ALfloat>(value2), static_cast<ALfloat>(value3));
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
switch(param)
{
@@ -219,55 +201,48 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alListeneriv, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param,
+ const ALint *values) noexcept
{
- if(values)
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ switch(param)
{
- ALfloat fvals[6];
- switch(param)
- {
- case AL_POSITION:
- case AL_VELOCITY:
- alListener3f(param, static_cast<ALfloat>(values[0]), static_cast<ALfloat>(values[1]),
- static_cast<ALfloat>(values[2]));
- return;
+ case AL_POSITION:
+ case AL_VELOCITY:
+ alListener3fDirect(context, param, static_cast<ALfloat>(values[0]),
+ static_cast<ALfloat>(values[1]), static_cast<ALfloat>(values[2]));
+ return;
- case AL_ORIENTATION:
- fvals[0] = static_cast<ALfloat>(values[0]);
- fvals[1] = static_cast<ALfloat>(values[1]);
- fvals[2] = static_cast<ALfloat>(values[2]);
- fvals[3] = static_cast<ALfloat>(values[3]);
- fvals[4] = static_cast<ALfloat>(values[4]);
- fvals[5] = static_cast<ALfloat>(values[5]);
- alListenerfv(param, fvals);
- return;
- }
+ case AL_ORIENTATION:
+ const ALfloat fvals[6]{
+ static_cast<ALfloat>(values[0]),
+ static_cast<ALfloat>(values[1]),
+ static_cast<ALfloat>(values[2]),
+ static_cast<ALfloat>(values[3]),
+ static_cast<ALfloat>(values[4]),
+ static_cast<ALfloat>(values[5]),
+ };
+ alListenerfvDirect(context, param, fvals);
+ return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
- if(!values) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(param)
+ switch(param)
{
default:
context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetListenerf, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param,
+ ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
if(!value)
@@ -286,14 +261,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener float property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
-START_API_FUNC
+AL_API DECL_FUNC4(void, alGetListener3f, ALenum, ALfloat*, ALfloat*, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param,
+ ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
if(!value1 || !value2 || !value3)
@@ -316,27 +288,24 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetListenerfv, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param,
+ ALfloat *values) noexcept
{
switch(param)
{
case AL_GAIN:
case AL_METERS_PER_UNIT:
- alGetListenerf(param, values);
+ alGetListenerfDirect(context, param, values);
return;
case AL_POSITION:
case AL_VELOCITY:
- alGetListener3f(param, values+0, values+1, values+2);
+ alGetListener3fDirect(context, param, values+0, values+1, values+2);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
if(!values)
@@ -357,15 +326,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetListeneri, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
if(!value)
context->setError(AL_INVALID_VALUE, "NULL pointer");
@@ -375,14 +340,11 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener integer property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3)
-START_API_FUNC
+AL_API DECL_FUNC4(void, alGetListener3i, ALenum, ALint*, ALint*, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param,
+ ALint *value1, ALint *value2, ALint *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
if(!value1 || !value2 || !value3)
@@ -405,22 +367,19 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property");
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetListeneriv, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param,
+ ALint *values) noexcept
{
switch(param)
{
case AL_POSITION:
case AL_VELOCITY:
- alGetListener3i(param, values+0, values+1, values+2);
+ alGetListener3iDirect(context, param, values+0, values+1, values+2);
return;
}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> _{context->mPropLock};
if(!values)
@@ -441,4 +400,3 @@ START_API_FUNC
context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property");
}
}
-END_API_FUNC
diff --git a/al/source.cpp b/al/source.cpp
index cba33862..fe5bba40 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -27,20 +27,22 @@
#include <atomic>
#include <cassert>
#include <chrono>
+#include <cinttypes>
#include <climits>
#include <cmath>
#include <cstdint>
#include <functional>
-#include <inttypes.h>
#include <iterator>
#include <limits>
#include <memory>
#include <mutex>
#include <new>
#include <numeric>
+#include <optional>
#include <stdexcept>
#include <thread>
#include <utility>
+#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
@@ -55,7 +57,6 @@
#include "alc/inprogext.h"
#include "almalloc.h"
#include "alnumeric.h"
-#include "aloptional.h"
#include "alspan.h"
#include "atomic.h"
#include "auxeffectslot.h"
@@ -67,22 +68,21 @@
#include "core/filters/splitter.h"
#include "core/logging.h"
#include "core/voice_change.h"
+#include "direct_defs.h"
#include "event.h"
#include "filter.h"
#include "opthelpers.h"
#include "ringbuffer.h"
-#include "threads.h"
#ifdef ALSOFT_EAX
#include <cassert>
#endif // ALSOFT_EAX
-bool sBufferSubDataCompat{false};
-
namespace {
using namespace std::placeholders;
using std::chrono::nanoseconds;
+using seconds_d = std::chrono::duration<double>;
Voice *GetSourceVoice(ALsource *source, ALCcontext *context)
{
@@ -95,7 +95,7 @@ Voice *GetSourceVoice(ALsource *source, ALCcontext *context)
if(voice->mSourceID.load(std::memory_order_acquire) == sid)
return voice;
}
- source->VoiceIdx = INVALID_VOICE_IDX;
+ source->VoiceIdx = InvalidVoiceIndex;
return nullptr;
}
@@ -281,7 +281,8 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl
* (Bytes, Samples or Seconds). The offset is relative to the start of the
* queue (not the start of the current buffer).
*/
-double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
+template<typename T>
+NOINLINE T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
{
ALCdevice *device{context->mALDevice.get()};
const VoiceBufferItem *Current{};
@@ -304,7 +305,7 @@ double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
} while(refcount != device->MixCount.load(std::memory_order_relaxed));
if(!voice)
- return 0.0;
+ return T{0};
const ALbuffer *BufferFmt{nullptr};
auto BufferList = Source->mQueue.cbegin();
@@ -321,24 +322,48 @@ double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
}
ASSUME(BufferFmt != nullptr);
- double offset{};
+ T offset{};
switch(name)
{
case AL_SEC_OFFSET:
- offset = static_cast<double>(readPos) + readPosFrac/double{MixerFracOne};
- offset /= BufferFmt->mSampleRate;
+ if constexpr(std::is_floating_point_v<T>)
+ {
+ offset = static_cast<T>(readPos) + static_cast<T>(readPosFrac)/T{MixerFracOne};
+ offset /= static_cast<T>(BufferFmt->mSampleRate);
+ }
+ else
+ {
+ readPos /= BufferFmt->mSampleRate;
+ offset = static_cast<T>(clampi64(readPos, std::numeric_limits<T>::min(),
+ std::numeric_limits<T>::max()));
+ }
break;
case AL_SAMPLE_OFFSET:
- offset = static_cast<double>(readPos) + readPosFrac/double{MixerFracOne};
+ if constexpr(std::is_floating_point_v<T>)
+ offset = static_cast<T>(readPos) + static_cast<T>(readPosFrac)/T{MixerFracOne};
+ else
+ offset = static_cast<T>(clampi64(readPos, std::numeric_limits<T>::min(),
+ std::numeric_limits<T>::max()));
break;
case AL_BYTE_OFFSET:
const ALuint BlockSamples{BufferFmt->mBlockAlign};
const ALuint BlockSize{BufferFmt->blockSizeFromFmt()};
-
/* Round down to the block boundary. */
- offset = static_cast<double>(readPos / BlockSamples) * BlockSize;
+ readPos = readPos / BlockSamples * BlockSize;
+
+ if constexpr(std::is_floating_point_v<T>)
+ offset = static_cast<T>(readPos);
+ else
+ {
+ if(readPos > std::numeric_limits<T>::max())
+ offset = RoundDown(std::numeric_limits<T>::max(), static_cast<T>(BlockSize));
+ else if(readPos < std::numeric_limits<T>::min())
+ offset = RoundUp(std::numeric_limits<T>::min(), static_cast<T>(BlockSize));
+ else
+ offset = static_cast<T>(readPos);
+ }
break;
}
return offset;
@@ -349,7 +374,8 @@ double GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
* Gets the length of the given Source's buffer queue, in the appropriate
* format (Bytes, Samples or Seconds).
*/
-double GetSourceLength(const ALsource *source, ALenum name)
+template<typename T>
+NOINLINE T GetSourceLength(const ALsource *source, ALenum name)
{
uint64_t length{0};
const ALbuffer *BufferFmt{nullptr};
@@ -360,25 +386,40 @@ double GetSourceLength(const ALsource *source, ALenum name)
length += listitem.mSampleLen;
}
if(length == 0)
- return 0.0;
+ return T{0};
ASSUME(BufferFmt != nullptr);
switch(name)
{
case AL_SEC_LENGTH_SOFT:
- return static_cast<double>(length) / BufferFmt->mSampleRate;
+ if constexpr(std::is_floating_point_v<T>)
+ return static_cast<T>(length) / static_cast<T>(BufferFmt->mSampleRate);
+ else
+ return static_cast<T>(minu64(length/BufferFmt->mSampleRate,
+ std::numeric_limits<T>::max()));
case AL_SAMPLE_LENGTH_SOFT:
- return static_cast<double>(length);
+ if constexpr(std::is_floating_point_v<T>)
+ return static_cast<T>(length);
+ else
+ return static_cast<T>(minu64(length, std::numeric_limits<T>::max()));
case AL_BYTE_LENGTH_SOFT:
const ALuint BlockSamples{BufferFmt->mBlockAlign};
const ALuint BlockSize{BufferFmt->blockSizeFromFmt()};
-
/* Round down to the block boundary. */
- return static_cast<double>(length / BlockSamples) * BlockSize;
+ length = length / BlockSamples * BlockSize;
+
+ if constexpr(std::is_floating_point_v<T>)
+ return static_cast<T>(length);
+ else
+ {
+ if(length > std::numeric_limits<T>::max())
+ return RoundDown(std::numeric_limits<T>::max(), static_cast<T>(BlockSize));
+ return static_cast<T>(length);
+ }
}
- return 0.0;
+ return T{0};
}
@@ -392,11 +433,11 @@ struct VoicePos {
* GetSampleOffset
*
* Retrieves the voice position, fixed-point fraction, and bufferlist item
- * using the givem offset type and offset. If the offset is out of range,
+ * using the given offset type and offset. If the offset is out of range,
* returns an empty optional.
*/
-al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList, ALenum OffsetType,
- double Offset)
+std::optional<VoicePos> GetSampleOffset(std::deque<ALbufferQueueItem> &BufferList,
+ ALenum OffsetType, double Offset)
{
/* Find the first valid Buffer in the Queue */
const ALbuffer *BufferFmt{nullptr};
@@ -406,7 +447,7 @@ al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList,
if(BufferFmt) break;
}
if(!BufferFmt) UNLIKELY
- return al::nullopt;
+ return std::nullopt;
/* Get sample frame offset */
int64_t offset{};
@@ -452,12 +493,12 @@ al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList,
if(offset < 0)
{
if(offset < std::numeric_limits<int>::min())
- return al::nullopt;
+ return std::nullopt;
return VoicePos{static_cast<int>(offset), frac, &BufferList.front()};
}
if(BufferFmt->mCallback)
- return al::nullopt;
+ return std::nullopt;
int64_t totalBufferLen{0};
for(auto &item : BufferList)
@@ -473,7 +514,7 @@ al::optional<VoicePos> GetSampleOffset(al::deque<ALbufferQueueItem> &BufferList,
}
/* Offset is out of range of the queue */
- return al::nullopt;
+ return std::nullopt;
}
@@ -676,8 +717,7 @@ inline ALenum GetSourceState(ALsource *source, Voice *voice)
bool EnsureSources(ALCcontext *context, size_t needed)
{
- size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(),
- size_t{0},
+ size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(), 0_uz,
[](size_t cur, const SourceSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
@@ -722,6 +762,8 @@ ALsource *AllocSource(ALCcontext *context)
void FreeSource(ALCcontext *context, ALsource *source)
{
+ context->mSourceNames.erase(source->id);
+
const ALuint id{source->id - 1};
const size_t lidx{id >> 6};
const ALuint slidx{id & 0x3f};
@@ -738,7 +780,7 @@ void FreeSource(ALCcontext *context, ALsource *source)
SendVoiceChanges(context, vchg);
}
- al::destroy_at(source);
+ std::destroy_at(source);
context->mSourceList[lidx].FreeMask |= 1_u64 << slidx;
context->mNumSources--;
@@ -758,56 +800,55 @@ inline ALsource *LookupSource(ALCcontext *context, ALuint id) noexcept
return sublist.Sources + slidx;
}
-inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept
+auto LookupBuffer = [](ALCdevice *device, auto id) noexcept -> ALbuffer*
{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
+ const auto lidx{(id-1) >> 6};
+ const auto slidx{(id-1) & 0x3f};
if(lidx >= device->BufferList.size()) UNLIKELY
return nullptr;
- BufferSubList &sublist = device->BufferList[lidx];
+ BufferSubList &sublist = device->BufferList[static_cast<size_t>(lidx)];
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.Buffers + slidx;
-}
+ return sublist.Buffers + static_cast<size_t>(slidx);
+};
-inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) noexcept
+auto LookupFilter = [](ALCdevice *device, auto id) noexcept -> ALfilter*
{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
+ const auto lidx{(id-1) >> 6};
+ const auto slidx{(id-1) & 0x3f};
if(lidx >= device->FilterList.size()) UNLIKELY
return nullptr;
- FilterSubList &sublist = device->FilterList[lidx];
+ FilterSubList &sublist = device->FilterList[static_cast<size_t>(lidx)];
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.Filters + slidx;
-}
+ return sublist.Filters + static_cast<size_t>(slidx);
+};
-inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) noexcept
+auto LookupEffectSlot = [](ALCcontext *context, auto id) noexcept -> ALeffectslot*
{
- const size_t lidx{(id-1) >> 6};
- const ALuint slidx{(id-1) & 0x3f};
+ const auto lidx{(id-1) >> 6};
+ const auto slidx{(id-1) & 0x3f};
if(lidx >= context->mEffectSlotList.size()) UNLIKELY
return nullptr;
- EffectSlotSubList &sublist{context->mEffectSlotList[lidx]};
+ EffectSlotSubList &sublist{context->mEffectSlotList[static_cast<size_t>(lidx)]};
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.EffectSlots + slidx;
-}
+ return sublist.EffectSlots + static_cast<size_t>(slidx);
+};
-al::optional<SourceStereo> StereoModeFromEnum(ALenum mode)
+auto StereoModeFromEnum = [](auto mode) noexcept -> std::optional<SourceStereo>
{
switch(mode)
{
case AL_NORMAL_SOFT: return SourceStereo::Normal;
case AL_SUPER_STEREO_SOFT: return SourceStereo::Enhanced;
}
- WARN("Unsupported stereo mode: 0x%04x\n", mode);
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum EnumFromStereoMode(SourceStereo mode)
{
switch(mode)
@@ -818,7 +859,7 @@ ALenum EnumFromStereoMode(SourceStereo mode)
throw std::runtime_error{"Invalid SourceStereo: "+std::to_string(int(mode))};
}
-al::optional<SpatializeMode> SpatializeModeFromEnum(ALenum mode)
+auto SpatializeModeFromEnum = [](auto mode) noexcept -> std::optional<SpatializeMode>
{
switch(mode)
{
@@ -826,9 +867,8 @@ al::optional<SpatializeMode> SpatializeModeFromEnum(ALenum mode)
case AL_TRUE: return SpatializeMode::On;
case AL_AUTO_SOFT: return SpatializeMode::Auto;
}
- WARN("Unsupported spatialize mode: 0x%04x\n", mode);
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum EnumFromSpatializeMode(SpatializeMode mode)
{
switch(mode)
@@ -840,7 +880,7 @@ ALenum EnumFromSpatializeMode(SpatializeMode mode)
throw std::runtime_error{"Invalid SpatializeMode: "+std::to_string(int(mode))};
}
-al::optional<DirectMode> DirectModeFromEnum(ALenum mode)
+auto DirectModeFromEnum = [](auto mode) noexcept -> std::optional<DirectMode>
{
switch(mode)
{
@@ -848,9 +888,8 @@ al::optional<DirectMode> DirectModeFromEnum(ALenum mode)
case AL_DROP_UNMATCHED_SOFT: return DirectMode::DropMismatch;
case AL_REMIX_UNMATCHED_SOFT: return DirectMode::RemixMismatch;
}
- WARN("Unsupported direct mode: 0x%04x\n", mode);
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum EnumFromDirectMode(DirectMode mode)
{
switch(mode)
@@ -862,7 +901,7 @@ ALenum EnumFromDirectMode(DirectMode mode)
throw std::runtime_error{"Invalid DirectMode: "+std::to_string(int(mode))};
}
-al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
+auto DistanceModelFromALenum = [](auto model) noexcept -> std::optional<DistanceModel>
{
switch(model)
{
@@ -874,8 +913,8 @@ al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent;
case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped;
}
- return al::nullopt;
-}
+ return std::nullopt;
+};
ALenum ALenumFromDistanceModel(DistanceModel model)
{
switch(model)
@@ -973,8 +1012,6 @@ enum SourceProp : ALenum {
};
-constexpr size_t MaxValues{6u};
-
constexpr ALuint IntValsByProp(ALenum prop)
{
switch(static_cast<SourceProp>(prop))
@@ -1276,10 +1313,6 @@ constexpr ALuint DoubleValsByProp(ALenum prop)
}
-void SetSourcefv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<const float> values);
-void SetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<const int> values);
-void SetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<const int64_t> values);
-
struct check_exception : std::exception {
};
struct check_size_exception final : check_exception {
@@ -1327,10 +1360,39 @@ inline void CommitAndUpdateSourceProps(ALsource *source, ALCcontext *context)
#endif
+template<typename T>
+struct PropType { };
+template<>
+struct PropType<ALint> { static const char *Name() { return "integer"; } };
+template<>
+struct PropType<ALint64SOFT> { static const char *Name() { return "int64"; } };
+template<>
+struct PropType<ALfloat> { static const char *Name() { return "float"; } };
+template<>
+struct PropType<ALdouble> { static const char *Name() { return "double"; } };
+
+template<typename T>
+struct HexPrinter {
+ char mStr[sizeof(T)*2 + 3]{};
+ HexPrinter(T value)
+ {
+ using ST = std::make_signed_t<std::remove_cv_t<T>>;
+ if constexpr(std::is_same_v<ST,int>)
+ std::snprintf(mStr, std::size(mStr), "0x%x", value);
+ else if constexpr(std::is_same_v<ST,long>)
+ std::snprintf(mStr, std::size(mStr), "0x%lx", value);
+ else if constexpr(std::is_same_v<ST,long long>)
+ std::snprintf(mStr, std::size(mStr), "0x%llx", value);
+ }
+
+ const char *c_str() const noexcept { return mStr; }
+};
+
+
/**
- * Returns a pair of lambdas to check the following setters and getters.
+ * Returns a pair of lambdas to check the following setter.
*
- * The first lambda checks the size of the span is valid for its given size,
+ * The first lambda checks the size of the span is valid for the required size,
* setting the proper context error and throwing a check_size_exception if it
* fails.
*
@@ -1357,19 +1419,33 @@ auto GetCheckers(ALCcontext *const Context, const SourceProp prop, const al::spa
);
}
-void SetSourcefv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<const float> values)
-try {
- /* Structured bindings would be nice (C++17). */
- auto Checkers = GetCheckers(Context, prop, values);
- auto &CheckSize = Checkers.first;
- auto &CheckValue = Checkers.second;
- int ival;
+template<typename T>
+NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
+ const al::span<const T> values) try
+{
+ auto&& [CheckSize, CheckValue] = GetCheckers(Context, prop, values);
+ ALCdevice *device{Context->mALDevice.get()};
switch(prop)
{
+ case AL_SOURCE_STATE:
+ case AL_SOURCE_TYPE:
+ case AL_BUFFERS_QUEUED:
+ case AL_BUFFERS_PROCESSED:
+ if constexpr(std::is_integral_v<T>)
+ {
+ /* Query only */
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting read-only source property 0x%04x", prop);
+ }
+ break;
+
+ case AL_BYTE_LENGTH_SOFT:
+ case AL_SAMPLE_LENGTH_SOFT:
case AL_SEC_LENGTH_SOFT:
+ case AL_SAMPLE_OFFSET_LATENCY_SOFT:
case AL_SEC_OFFSET_LATENCY_SOFT:
+ case AL_SAMPLE_OFFSET_CLOCK_SOFT:
case AL_SEC_OFFSET_CLOCK_SOFT:
/* Query only */
return Context->setError(AL_INVALID_OPERATION,
@@ -1377,712 +1453,540 @@ try {
case AL_PITCH:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->Pitch = values[0];
+ Source->Pitch = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_CONE_INNER_ANGLE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 360.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{360});
- Source->InnerAngle = values[0];
+ Source->InnerAngle = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_CONE_OUTER_ANGLE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 360.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{360});
- Source->OuterAngle = values[0];
+ Source->OuterAngle = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->Gain = values[0];
+ Source->Gain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_MAX_DISTANCE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->MaxDistance = values[0];
+ Source->MaxDistance = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_ROLLOFF_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->RolloffFactor = values[0];
+ Source->RolloffFactor = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_REFERENCE_DISTANCE:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->RefDistance = values[0];
+ Source->RefDistance = static_cast<float>(values[0]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_MIN_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->MinGain = values[0];
+ Source->MinGain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_MAX_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f);
+ CheckValue(values[0] >= T{0});
- Source->MaxGain = values[0];
+ Source->MaxGain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_CONE_OUTER_GAIN:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->OuterGain = values[0];
+ Source->OuterGain = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_CONE_OUTER_GAINHF:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->OuterGainHF = values[0];
+ Source->OuterGainHF = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_AIR_ABSORPTION_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 10.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{10});
- Source->AirAbsorptionFactor = values[0];
+ Source->AirAbsorptionFactor = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_ROOM_ROLLOFF_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 10.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->RoomRolloffFactor = values[0];
+ Source->RoomRolloffFactor = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_DOPPLER_FACTOR:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->DopplerFactor = values[0];
+ Source->DopplerFactor = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
+
+ case AL_SOURCE_RELATIVE:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
+
+ Source->HeadRelative = values[0] != AL_FALSE;
+ return CommitAndUpdateSourceProps(Source, Context);
+ }
+ break;
+
+ case AL_LOOPING:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
+
+ Source->Looping = values[0] != AL_FALSE;
+ if(Voice *voice{GetSourceVoice(Source, Context)})
+ {
+ if(Source->Looping)
+ voice->mLoopBuffer.store(&Source->mQueue.front(), std::memory_order_release);
+ else
+ voice->mLoopBuffer.store(nullptr, std::memory_order_release);
+
+ /* If the source is playing, wait for the current mix to finish
+ * to ensure it isn't currently looping back or reaching the
+ * end.
+ */
+ device->waitForMix();
+ }
+ return;
+ }
+ break;
+
+ case AL_BUFFER:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ {
+ const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
+ if(state == AL_PLAYING || state == AL_PAUSED)
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting buffer on playing or paused source %u", Source->id);
+ }
+ std::deque<ALbufferQueueItem> oldlist;
+ if(values[0])
+ {
+ using UT = std::make_unsigned_t<T>;
+ std::lock_guard<std::mutex> _{device->BufferLock};
+ ALbuffer *buffer{LookupBuffer(device, static_cast<UT>(values[0]))};
+ if(!buffer) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %s",
+ std::to_string(values[0]).c_str());
+ if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting non-persistently mapped buffer %u", buffer->id);
+ if(buffer->mCallback && ReadRef(buffer->ref) != 0) UNLIKELY
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting already-set callback buffer %u", buffer->id);
+
+ /* Add the selected buffer to a one-item queue */
+ std::deque<ALbufferQueueItem> newlist;
+ newlist.emplace_back();
+ newlist.back().mCallback = buffer->mCallback;
+ newlist.back().mUserData = buffer->mUserData;
+ newlist.back().mBlockAlign = buffer->mBlockAlign;
+ newlist.back().mSampleLen = buffer->mSampleLen;
+ newlist.back().mLoopStart = buffer->mLoopStart;
+ newlist.back().mLoopEnd = buffer->mLoopEnd;
+ newlist.back().mSamples = buffer->mData.data();
+ newlist.back().mBuffer = buffer;
+ IncrementRef(buffer->ref);
+
+ /* Source is now Static */
+ Source->SourceType = AL_STATIC;
+ Source->mQueue.swap(oldlist);
+ Source->mQueue.swap(newlist);
+ }
+ else
+ {
+ /* Source is now Undetermined */
+ Source->SourceType = AL_UNDETERMINED;
+ Source->mQueue.swap(oldlist);
+ }
+
+ /* Delete all elements in the previous queue */
+ for(auto &item : oldlist)
+ {
+ if(ALbuffer *buffer{item.mBuffer})
+ DecrementRef(buffer->ref);
+ }
+ return;
+ }
+ break;
+
+
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
CheckSize(1);
- CheckValue(std::isfinite(values[0]));
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(values[0]));
if(Voice *voice{GetSourceVoice(Source, Context)})
{
- auto vpos = GetSampleOffset(Source->mQueue, prop, values[0]);
+ auto vpos = GetSampleOffset(Source->mQueue, prop, static_cast<double>(values[0]));
if(!vpos) return Context->setError(AL_INVALID_VALUE, "Invalid offset");
if(SetVoiceOffset(voice, *vpos, Source, Context, Context->mALDevice.get()))
return;
}
Source->OffsetType = prop;
- Source->Offset = values[0];
+ Source->Offset = static_cast<double>(values[0]);
return;
case AL_SAMPLE_RW_OFFSETS_SOFT:
+ if(sBufferSubDataCompat)
+ {
+ if constexpr(std::is_integral_v<T>)
+ {
+ /* Query only */
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting read-only source property 0x%04x", prop);
+ }
+ }
break;
case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
if(sBufferSubDataCompat)
+ {
+ if constexpr(std::is_integral_v<T>)
+ {
+ /* Query only */
+ return Context->setError(AL_INVALID_OPERATION,
+ "Setting read-only source property 0x%04x", prop);
+ }
break;
+ }
CheckSize(1);
- CheckValue(values[0] >= 0.0f && std::isfinite(values[0]));
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(values[0] >= T{0} && std::isfinite(static_cast<float>(values[0])));
+ else
+ CheckValue(values[0] >= T{0});
- Source->Radius = values[0];
+ Source->Radius = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_SUPER_STEREO_WIDTH_SOFT:
CheckSize(1);
- CheckValue(values[0] >= 0.0f && values[0] <= 1.0f);
+ CheckValue(values[0] >= T{0} && values[0] <= T{1});
- Source->EnhWidth = values[0];
+ Source->EnhWidth = static_cast<float>(values[0]);
return UpdateSourceProps(Source, Context);
case AL_STEREO_ANGLES:
CheckSize(2);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]));
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1])));
- Source->StereoPan[0] = values[0];
- Source->StereoPan[1] = values[1];
+ Source->StereoPan[0] = static_cast<float>(values[0]);
+ Source->StereoPan[1] = static_cast<float>(values[1]);
return UpdateSourceProps(Source, Context);
case AL_POSITION:
CheckSize(3);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]));
-
- Source->Position[0] = values[0];
- Source->Position[1] = values[1];
- Source->Position[2] = values[2];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2])));
+
+ Source->Position[0] = static_cast<float>(values[0]);
+ Source->Position[1] = static_cast<float>(values[1]);
+ Source->Position[2] = static_cast<float>(values[2]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_VELOCITY:
CheckSize(3);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]));
-
- Source->Velocity[0] = values[0];
- Source->Velocity[1] = values[1];
- Source->Velocity[2] = values[2];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2])));
+
+ Source->Velocity[0] = static_cast<float>(values[0]);
+ Source->Velocity[1] = static_cast<float>(values[1]);
+ Source->Velocity[2] = static_cast<float>(values[2]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_DIRECTION:
CheckSize(3);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]));
-
- Source->Direction[0] = values[0];
- Source->Direction[1] = values[1];
- Source->Direction[2] = values[2];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2])));
+
+ Source->Direction[0] = static_cast<float>(values[0]);
+ Source->Direction[1] = static_cast<float>(values[1]);
+ Source->Direction[2] = static_cast<float>(values[2]);
return CommitAndUpdateSourceProps(Source, Context);
case AL_ORIENTATION:
CheckSize(6);
- CheckValue(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])
- && std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5]));
-
- Source->OrientAt[0] = values[0];
- Source->OrientAt[1] = values[1];
- Source->OrientAt[2] = values[2];
- Source->OrientUp[0] = values[3];
- Source->OrientUp[1] = values[4];
- Source->OrientUp[2] = values[5];
+ if constexpr(std::is_floating_point_v<T>)
+ CheckValue(std::isfinite(static_cast<float>(values[0]))
+ && std::isfinite(static_cast<float>(values[1]))
+ && std::isfinite(static_cast<float>(values[2]))
+ && std::isfinite(static_cast<float>(values[3]))
+ && std::isfinite(static_cast<float>(values[4]))
+ && std::isfinite(static_cast<float>(values[5])));
+
+ Source->OrientAt[0] = static_cast<float>(values[0]);
+ Source->OrientAt[1] = static_cast<float>(values[1]);
+ Source->OrientAt[2] = static_cast<float>(values[2]);
+ Source->OrientUp[0] = static_cast<float>(values[3]);
+ Source->OrientUp[1] = static_cast<float>(values[4]);
+ Source->OrientUp[2] = static_cast<float>(values[5]);
return UpdateSourceProps(Source, Context);
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SOURCE_STATE:
- case AL_SOURCE_TYPE:
- case AL_DISTANCE_MODEL:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- ival = static_cast<int>(values[0]);
- return SetSourceiv(Source, Context, prop, {&ival, 1u});
-
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- CheckSize(1);
- ival = static_cast<int>(static_cast<ALuint>(values[0]));
- return SetSourceiv(Source, Context, prop, {&ival, 1u});
-
- case AL_BUFFER:
case AL_DIRECT_FILTER:
- case AL_AUXILIARY_SEND_FILTER:
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- break;
- }
-
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source float property 0x%04x", prop);
-}
-catch(check_exception&) {
-}
-
-void SetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<const int> values)
-try {
- auto Checkers = GetCheckers(Context, prop, values);
- auto &CheckSize = Checkers.first;
- auto &CheckValue = Checkers.second;
- ALCdevice *device{Context->mALDevice.get()};
- ALeffectslot *slot{nullptr};
- al::deque<ALbufferQueueItem> oldlist;
- std::unique_lock<std::mutex> slotlock;
- float fvals[6];
-
- switch(prop)
- {
- case AL_SOURCE_STATE:
- case AL_SOURCE_TYPE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
-
- case AL_SOURCE_RELATIVE:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->HeadRelative = values[0] != AL_FALSE;
- return CommitAndUpdateSourceProps(Source, Context);
-
- case AL_LOOPING:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->Looping = values[0] != AL_FALSE;
- if(Voice *voice{GetSourceVoice(Source, Context)})
+ if constexpr(std::is_integral_v<T>)
{
- if(Source->Looping)
- voice->mLoopBuffer.store(&Source->mQueue.front(), std::memory_order_release);
+ CheckSize(1);
+ const auto filterid = static_cast<std::make_unsigned_t<T>>(values[0]);
+ if(values[0])
+ {
+ std::lock_guard<std::mutex> _{device->FilterLock};
+ ALfilter *filter{LookupFilter(device, filterid)};
+ if(!filter) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %s",
+ std::to_string(filterid).c_str());
+ Source->Direct.Gain = filter->Gain;
+ Source->Direct.GainHF = filter->GainHF;
+ Source->Direct.HFReference = filter->HFReference;
+ Source->Direct.GainLF = filter->GainLF;
+ Source->Direct.LFReference = filter->LFReference;
+ }
else
- voice->mLoopBuffer.store(nullptr, std::memory_order_release);
-
- /* If the source is playing, wait for the current mix to finish to
- * ensure it isn't currently looping back or reaching the end.
- */
- device->waitForMix();
+ {
+ Source->Direct.Gain = 1.0f;
+ Source->Direct.GainHF = 1.0f;
+ Source->Direct.HFReference = LOWPASSFREQREF;
+ Source->Direct.GainLF = 1.0f;
+ Source->Direct.LFReference = HIGHPASSFREQREF;
+ }
+ return UpdateSourceProps(Source, Context);
}
- return;
+ break;
- case AL_BUFFER:
- CheckSize(1);
- {
- const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
- if(state == AL_PLAYING || state == AL_PAUSED)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting buffer on playing or paused source %u", Source->id);
- }
- if(values[0])
- {
- std::lock_guard<std::mutex> _{device->BufferLock};
- ALbuffer *buffer{LookupBuffer(device, static_cast<ALuint>(values[0]))};
- if(!buffer)
- return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %u",
- static_cast<ALuint>(values[0]));
- if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
- return Context->setError(AL_INVALID_OPERATION,
- "Setting non-persistently mapped buffer %u", buffer->id);
- if(buffer->mCallback && ReadRef(buffer->ref) != 0)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting already-set callback buffer %u", buffer->id);
-
- /* Add the selected buffer to a one-item queue */
- al::deque<ALbufferQueueItem> newlist;
- newlist.emplace_back();
- newlist.back().mCallback = buffer->mCallback;
- newlist.back().mUserData = buffer->mUserData;
- newlist.back().mBlockAlign = buffer->mBlockAlign;
- newlist.back().mSampleLen = buffer->mSampleLen;
- newlist.back().mLoopStart = buffer->mLoopStart;
- newlist.back().mLoopEnd = buffer->mLoopEnd;
- newlist.back().mSamples = buffer->mData.data();
- newlist.back().mBuffer = buffer;
- IncrementRef(buffer->ref);
-
- /* Source is now Static */
- Source->SourceType = AL_STATIC;
- Source->mQueue.swap(oldlist);
- Source->mQueue.swap(newlist);
- }
- else
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- /* Source is now Undetermined */
- Source->SourceType = AL_UNDETERMINED;
- Source->mQueue.swap(oldlist);
- }
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
- /* Delete all elements in the previous queue */
- for(auto &item : oldlist)
- {
- if(ALbuffer *buffer{item.mBuffer})
- DecrementRef(buffer->ref);
+ Source->DryGainHFAuto = values[0] != AL_FALSE;
+ return UpdateSourceProps(Source, Context);
}
- return;
-
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- CheckSize(1);
+ break;
- if(Voice *voice{GetSourceVoice(Source, Context)})
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- auto vpos = GetSampleOffset(Source->mQueue, prop, values[0]);
- if(!vpos) return Context->setError(AL_INVALID_VALUE, "Invalid source offset");
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
- if(SetVoiceOffset(voice, *vpos, Source, Context, device))
- return;
- }
- Source->OffsetType = prop;
- Source->Offset = values[0];
- return;
-
- case AL_DIRECT_FILTER:
- CheckSize(1);
- if(values[0])
- {
- std::lock_guard<std::mutex> _{device->FilterLock};
- ALfilter *filter{LookupFilter(device, static_cast<ALuint>(values[0]))};
- if(!filter)
- return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %u",
- static_cast<ALuint>(values[0]));
- Source->Direct.Gain = filter->Gain;
- Source->Direct.GainHF = filter->GainHF;
- Source->Direct.HFReference = filter->HFReference;
- Source->Direct.GainLF = filter->GainLF;
- Source->Direct.LFReference = filter->LFReference;
- }
- else
- {
- Source->Direct.Gain = 1.0f;
- Source->Direct.GainHF = 1.0f;
- Source->Direct.HFReference = LOWPASSFREQREF;
- Source->Direct.GainLF = 1.0f;
- Source->Direct.LFReference = HIGHPASSFREQREF;
+ Source->WetGainAuto = values[0] != AL_FALSE;
+ return UpdateSourceProps(Source, Context);
}
- return UpdateSourceProps(Source, Context);
-
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->DryGainHFAuto = values[0] != AL_FALSE;
- return UpdateSourceProps(Source, Context);
-
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
-
- Source->WetGainAuto = values[0] != AL_FALSE;
- return UpdateSourceProps(Source, Context);
+ break;
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- CheckSize(1);
- CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE);
- Source->WetGainHFAuto = values[0] != AL_FALSE;
- return UpdateSourceProps(Source, Context);
+ Source->WetGainHFAuto = values[0] != AL_FALSE;
+ return UpdateSourceProps(Source, Context);
+ }
+ break;
case AL_DIRECT_CHANNELS_SOFT:
- CheckSize(1);
- if(auto mode = DirectModeFromEnum(values[0]))
+ if constexpr(std::is_integral_v<T>)
{
- Source->DirectChannels = *mode;
- return UpdateSourceProps(Source, Context);
+ CheckSize(1);
+ if(auto mode = DirectModeFromEnum(values[0]))
+ {
+ Source->DirectChannels = *mode;
+ return UpdateSourceProps(Source, Context);
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid direct channels mode: %s\n",
+ HexPrinter{values[0]}.c_str());
}
- Context->setError(AL_INVALID_VALUE, "Unsupported AL_DIRECT_CHANNELS_SOFT: 0x%04x\n",
- values[0]);
- return;
+ break;
case AL_DISTANCE_MODEL:
- CheckSize(1);
- if(auto model = DistanceModelFromALenum(values[0]))
+ if constexpr(std::is_integral_v<T>)
{
- Source->mDistanceModel = *model;
- if(Context->mSourceDistanceModel)
- UpdateSourceProps(Source, Context);
- return;
+ CheckSize(1);
+ if(auto model = DistanceModelFromALenum(values[0]))
+ {
+ Source->mDistanceModel = *model;
+ if(Context->mSourceDistanceModel)
+ UpdateSourceProps(Source, Context);
+ return;
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid distance model: %s\n",
+ HexPrinter{values[0]}.c_str());
}
- Context->setError(AL_INVALID_VALUE, "Distance model out of range: 0x%04x", values[0]);
- return;
+ break;
case AL_SOURCE_RESAMPLER_SOFT:
- CheckSize(1);
- CheckValue(values[0] >= 0 && values[0] <= static_cast<int>(Resampler::Max));
-
- Source->mResampler = static_cast<Resampler>(values[0]);
- return UpdateSourceProps(Source, Context);
-
- case AL_SOURCE_SPATIALIZE_SOFT:
- CheckSize(1);
- if(auto mode = SpatializeModeFromEnum(values[0]))
+ if constexpr(std::is_integral_v<T>)
{
- Source->mSpatialize = *mode;
- return UpdateSourceProps(Source, Context);
- }
- Context->setError(AL_INVALID_VALUE, "Unsupported AL_SOURCE_SPATIALIZE_SOFT: 0x%04x\n",
- values[0]);
- return;
+ CheckSize(1);
+ CheckValue(values[0] >= 0 && values[0] <= static_cast<int>(Resampler::Max));
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- {
- const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
- if(state == AL_PLAYING || state == AL_PAUSED)
- return Context->setError(AL_INVALID_OPERATION,
- "Modifying stereo mode on playing or paused source %u", Source->id);
- }
- if(auto mode = StereoModeFromEnum(values[0]))
- {
- Source->mStereoMode = *mode;
- return;
- }
- Context->setError(AL_INVALID_VALUE, "Unsupported AL_STEREO_MODE_SOFT: 0x%04x\n",
- values[0]);
- return;
-
- case AL_AUXILIARY_SEND_FILTER:
- CheckSize(3);
- slotlock = std::unique_lock<std::mutex>{Context->mEffectSlotLock};
- if(values[0] && (slot=LookupEffectSlot(Context, static_cast<ALuint>(values[0]))) == nullptr)
- return Context->setError(AL_INVALID_VALUE, "Invalid effect ID %u", values[0]);
- if(static_cast<ALuint>(values[1]) >= device->NumAuxSends)
- return Context->setError(AL_INVALID_VALUE, "Invalid send %u", values[1]);
-
- if(values[2])
- {
- std::lock_guard<std::mutex> _{device->FilterLock};
- ALfilter *filter{LookupFilter(device, static_cast<ALuint>(values[2]))};
- if(!filter)
- return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %u", values[2]);
-
- auto &send = Source->Send[static_cast<ALuint>(values[1])];
- send.Gain = filter->Gain;
- send.GainHF = filter->GainHF;
- send.HFReference = filter->HFReference;
- send.GainLF = filter->GainLF;
- send.LFReference = filter->LFReference;
- }
- else
- {
- /* Disable filter */
- auto &send = Source->Send[static_cast<ALuint>(values[1])];
- send.Gain = 1.0f;
- send.GainHF = 1.0f;
- send.HFReference = LOWPASSFREQREF;
- send.GainLF = 1.0f;
- send.LFReference = HIGHPASSFREQREF;
+ Source->mResampler = static_cast<Resampler>(values[0]);
+ return UpdateSourceProps(Source, Context);
}
+ break;
- /* We must force an update if the current auxiliary slot is valid and
- * about to be changed on an active source, in case the old slot is
- * about to be deleted.
- */
- if(Source->Send[static_cast<ALuint>(values[1])].Slot
- && slot != Source->Send[static_cast<ALuint>(values[1])].Slot
- && IsPlayingOrPaused(Source))
- {
- /* Add refcount on the new slot, and release the previous slot */
- if(slot) IncrementRef(slot->ref);
- if(auto *oldslot = Source->Send[static_cast<ALuint>(values[1])].Slot)
- DecrementRef(oldslot->ref);
- Source->Send[static_cast<ALuint>(values[1])].Slot = slot;
-
- Voice *voice{GetSourceVoice(Source, Context)};
- if(voice) UpdateSourceProps(Source, voice, Context);
- else Source->mPropsDirty = true;
- }
- else
+ case AL_SOURCE_SPATIALIZE_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- if(slot) IncrementRef(slot->ref);
- if(auto *oldslot = Source->Send[static_cast<ALuint>(values[1])].Slot)
- DecrementRef(oldslot->ref);
- Source->Send[static_cast<ALuint>(values[1])].Slot = slot;
- UpdateSourceProps(Source, Context);
+ CheckSize(1);
+ if(auto mode = SpatializeModeFromEnum(values[0]))
+ {
+ Source->mSpatialize = *mode;
+ return UpdateSourceProps(Source, Context);
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid source spatialize mode: %s\n",
+ HexPrinter{values[0]}.c_str());
}
- return;
-
-
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
- break;
-
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
- /*fall-through*/
-
- /* 1x float */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_DOPPLER_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_SEC_LENGTH_SOFT:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- fvals[0] = static_cast<float>(values[0]);
- return SetSourcefv(Source, Context, prop, {fvals, 1u});
-
- /* 3x float */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- return SetSourcefv(Source, Context, prop, {fvals, 3u});
-
- /* 6x float */
- case AL_ORIENTATION:
- CheckSize(6);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- fvals[3] = static_cast<float>(values[3]);
- fvals[4] = static_cast<float>(values[4]);
- fvals[5] = static_cast<float>(values[5]);
- return SetSourcefv(Source, Context, prop, {fvals, 6u});
-
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- case AL_STEREO_ANGLES:
break;
- }
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer property 0x%04x", prop);
-}
-catch(check_exception&) {
-}
-
-void SetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<const int64_t> values)
-try {
- auto Checkers = GetCheckers(Context, prop, values);
- auto &CheckSize = Checkers.first;
- auto &CheckValue = Checkers.second;
- float fvals[MaxValues];
- int ivals[MaxValues];
-
- switch(prop)
- {
- case AL_SOURCE_TYPE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_SOURCE_STATE:
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
-
- /* 1x int */
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_DISTANCE_MODEL:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- CheckValue(values[0] <= INT_MAX && values[0] >= INT_MIN);
-
- ivals[0] = static_cast<int>(values[0]);
- return SetSourceiv(Source, Context, prop, {ivals, 1u});
-
- /* 1x uint */
- case AL_BUFFER:
- case AL_DIRECT_FILTER:
- CheckSize(1);
- CheckValue(values[0] <= UINT_MAX && values[0] >= 0);
-
- ivals[0] = static_cast<int>(values[0]);
- return SetSourceiv(Source, Context, prop, {ivals, 1u});
-
- /* 3x uint */
- case AL_AUXILIARY_SEND_FILTER:
- CheckSize(3);
- CheckValue(values[0] <= UINT_MAX && values[0] >= 0 && values[1] <= UINT_MAX
- && values[1] >= 0 && values[2] <= UINT_MAX && values[2] >= 0);
-
- ivals[0] = static_cast<int>(values[0]);
- ivals[1] = static_cast<int>(values[1]);
- ivals[2] = static_cast<int>(values[2]);
- return SetSourceiv(Source, Context, prop, {ivals, 3u});
-
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
+ if constexpr(std::is_integral_v<T>)
{
- /* Query only */
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
+ CheckSize(1);
+ {
+ const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))};
+ if(state == AL_PLAYING || state == AL_PAUSED)
+ return Context->setError(AL_INVALID_OPERATION,
+ "Modifying stereo mode on playing or paused source %u", Source->id);
+ }
+ if(auto mode = StereoModeFromEnum(values[0]))
+ {
+ Source->mStereoMode = *mode;
+ return;
+ }
+ return Context->setError(AL_INVALID_VALUE, "Invalid stereo mode: %s\n",
+ HexPrinter{values[0]}.c_str());
}
break;
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
- return Context->setError(AL_INVALID_OPERATION,
- "Setting read-only source property 0x%04x", prop);
- /*fall-through*/
-
- /* 1x float */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_DOPPLER_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_SEC_LENGTH_SOFT:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- fvals[0] = static_cast<float>(values[0]);
- return SetSourcefv(Source, Context, prop, {fvals, 1u});
+ case AL_AUXILIARY_SEND_FILTER:
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(3);
+ const auto slotid = static_cast<std::make_unsigned_t<T>>(values[0]);
+ const auto sendidx = static_cast<std::make_unsigned_t<T>>(values[1]);
+ const auto filterid = static_cast<std::make_unsigned_t<T>>(values[2]);
+
+ std::unique_lock slotlock{Context->mEffectSlotLock};
+ ALeffectslot *slot{};
+ if(values[0])
+ {
+ if((slot=LookupEffectSlot(Context, slotid)) == nullptr) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid effect ID %s",
+ std::to_string(slotid).c_str());
+ }
- /* 3x float */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- return SetSourcefv(Source, Context, prop, {fvals, 3u});
+ if(sendidx >= device->NumAuxSends) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid send %s",
+ std::to_string(sendidx).c_str());
+ auto &send = Source->Send[static_cast<size_t>(sendidx)];
- /* 6x float */
- case AL_ORIENTATION:
- CheckSize(6);
- fvals[0] = static_cast<float>(values[0]);
- fvals[1] = static_cast<float>(values[1]);
- fvals[2] = static_cast<float>(values[2]);
- fvals[3] = static_cast<float>(values[3]);
- fvals[4] = static_cast<float>(values[4]);
- fvals[5] = static_cast<float>(values[5]);
- return SetSourcefv(Source, Context, prop, {fvals, 6u});
+ if(values[2])
+ {
+ std::lock_guard<std::mutex> _{device->FilterLock};
+ ALfilter *filter{LookupFilter(device, filterid)};
+ if(!filter) UNLIKELY
+ return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %s",
+ std::to_string(filterid).c_str());
+
+ send.Gain = filter->Gain;
+ send.GainHF = filter->GainHF;
+ send.HFReference = filter->HFReference;
+ send.GainLF = filter->GainLF;
+ send.LFReference = filter->LFReference;
+ }
+ else
+ {
+ /* Disable filter */
+ send.Gain = 1.0f;
+ send.GainHF = 1.0f;
+ send.HFReference = LOWPASSFREQREF;
+ send.GainLF = 1.0f;
+ send.LFReference = HIGHPASSFREQREF;
+ }
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- case AL_STEREO_ANGLES:
+ /* We must force an update if the current auxiliary slot is valid
+ * and about to be changed on an active source, in case the old
+ * slot is about to be deleted.
+ */
+ if(send.Slot && slot != send.Slot && IsPlayingOrPaused(Source))
+ {
+ /* Add refcount on the new slot, and release the previous slot */
+ if(slot) IncrementRef(slot->ref);
+ if(auto *oldslot = send.Slot)
+ DecrementRef(oldslot->ref);
+ send.Slot = slot;
+
+ Voice *voice{GetSourceVoice(Source, Context)};
+ if(voice) UpdateSourceProps(Source, voice, Context);
+ else Source->mPropsDirty = true;
+ }
+ else
+ {
+ if(slot) IncrementRef(slot->ref);
+ if(auto *oldslot = send.Slot)
+ DecrementRef(oldslot->ref);
+ send.Slot = slot;
+ UpdateSourceProps(Source, Context);
+ }
+ return;
+ }
break;
}
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer64 property 0x%04x", prop);
+ ERR("Unexpected %s property: 0x%04x\n", PropType<T>::Name(), prop);
+ Context->setError(AL_INVALID_ENUM, "Invalid source %s property 0x%04x", PropType<T>::Name(),
+ prop);
}
catch(check_exception&) {
}
@@ -2100,245 +2004,292 @@ auto GetSizeChecker(ALCcontext *const Context, const SourceProp prop, const al::
};
}
-bool GetSourcedv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<double> values);
-bool GetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<int> values);
-bool GetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, const al::span<int64_t> values);
-
-bool GetSourcedv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<double> values)
-try {
+template<typename T>
+[[nodiscard]] NOINLINE
+bool GetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
+ const al::span<T> values) try
+{
+ using std::chrono::duration_cast;
auto CheckSize = GetSizeChecker(Context, prop, values);
ALCdevice *device{Context->mALDevice.get()};
- ClockLatency clocktime;
- nanoseconds srcclock;
- int ivals[MaxValues];
- bool err;
switch(prop)
{
case AL_GAIN:
CheckSize(1);
- values[0] = Source->Gain;
+ values[0] = static_cast<T>(Source->Gain);
return true;
case AL_PITCH:
CheckSize(1);
- values[0] = Source->Pitch;
+ values[0] = static_cast<T>(Source->Pitch);
return true;
case AL_MAX_DISTANCE:
CheckSize(1);
- values[0] = Source->MaxDistance;
+ values[0] = static_cast<T>(Source->MaxDistance);
return true;
case AL_ROLLOFF_FACTOR:
CheckSize(1);
- values[0] = Source->RolloffFactor;
+ values[0] = static_cast<T>(Source->RolloffFactor);
return true;
case AL_REFERENCE_DISTANCE:
CheckSize(1);
- values[0] = Source->RefDistance;
+ values[0] = static_cast<T>(Source->RefDistance);
return true;
case AL_CONE_INNER_ANGLE:
CheckSize(1);
- values[0] = Source->InnerAngle;
+ values[0] = static_cast<T>(Source->InnerAngle);
return true;
case AL_CONE_OUTER_ANGLE:
CheckSize(1);
- values[0] = Source->OuterAngle;
+ values[0] = static_cast<T>(Source->OuterAngle);
return true;
case AL_MIN_GAIN:
CheckSize(1);
- values[0] = Source->MinGain;
+ values[0] = static_cast<T>(Source->MinGain);
return true;
case AL_MAX_GAIN:
CheckSize(1);
- values[0] = Source->MaxGain;
+ values[0] = static_cast<T>(Source->MaxGain);
return true;
case AL_CONE_OUTER_GAIN:
CheckSize(1);
- values[0] = Source->OuterGain;
+ values[0] = static_cast<T>(Source->OuterGain);
return true;
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
CheckSize(1);
- values[0] = GetSourceOffset(Source, prop, Context);
+ values[0] = GetSourceOffset<T>(Source, prop, Context);
return true;
case AL_CONE_OUTER_GAINHF:
CheckSize(1);
- values[0] = Source->OuterGainHF;
+ values[0] = static_cast<T>(Source->OuterGainHF);
return true;
case AL_AIR_ABSORPTION_FACTOR:
CheckSize(1);
- values[0] = Source->AirAbsorptionFactor;
+ values[0] = static_cast<T>(Source->AirAbsorptionFactor);
return true;
case AL_ROOM_ROLLOFF_FACTOR:
CheckSize(1);
- values[0] = Source->RoomRolloffFactor;
+ values[0] = static_cast<T>(Source->RoomRolloffFactor);
return true;
case AL_DOPPLER_FACTOR:
CheckSize(1);
- values[0] = Source->DopplerFactor;
+ values[0] = static_cast<T>(Source->DopplerFactor);
return true;
case AL_SAMPLE_RW_OFFSETS_SOFT:
+ if constexpr(std::is_integral_v<T>)
+ {
+ if(sBufferSubDataCompat)
+ {
+ CheckSize(2);
+ values[0] = GetSourceOffset<T>(Source, AL_SAMPLE_OFFSET, Context);
+ /* FIXME: values[1] should be ahead of values[0] by the device
+ * update time. It needs to clamp or wrap the length of the
+ * buffer queue.
+ */
+ values[1] = values[0];
+ return true;
+ }
+ }
break;
case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
- break;
+ if constexpr(std::is_floating_point_v<T>)
+ {
+ if(sBufferSubDataCompat)
+ break;
- CheckSize(1);
- values[0] = Source->Radius;
- return true;
+ CheckSize(1);
+ values[0] = static_cast<T>(Source->Radius);
+ return true;
+ }
+ else
+ {
+ if(sBufferSubDataCompat)
+ {
+ CheckSize(2);
+ values[0] = GetSourceOffset<T>(Source, AL_BYTE_OFFSET, Context);
+ /* FIXME: values[1] should be ahead of values[0] by the device
+ * update time. It needs to clamp or wrap the length of the
+ * buffer queue.
+ */
+ values[1] = values[0];
+ return true;
+ }
+ break;
+ }
case AL_SUPER_STEREO_WIDTH_SOFT:
CheckSize(1);
- values[0] = Source->EnhWidth;
+ values[0] = static_cast<T>(Source->EnhWidth);
return true;
case AL_BYTE_LENGTH_SOFT:
case AL_SAMPLE_LENGTH_SOFT:
case AL_SEC_LENGTH_SOFT:
CheckSize(1);
- values[0] = GetSourceLength(Source, prop);
+ values[0] = GetSourceLength<T>(Source, prop);
return true;
case AL_STEREO_ANGLES:
- CheckSize(2);
- values[0] = Source->StereoPan[0];
- values[1] = Source->StereoPan[1];
- return true;
+ if constexpr(std::is_floating_point_v<T>)
+ {
+ CheckSize(2);
+ values[0] = static_cast<T>(Source->StereoPan[0]);
+ values[1] = static_cast<T>(Source->StereoPan[1]);
+ return true;
+ }
+ break;
- case AL_SEC_OFFSET_LATENCY_SOFT:
- CheckSize(2);
- /* Get the source offset with the clock time first. Then get the clock
- * time with the device latency. Order is important.
- */
- values[0] = GetSourceSecOffset(Source, Context, &srcclock);
+ case AL_SAMPLE_OFFSET_LATENCY_SOFT:
+ if constexpr(std::is_same_v<T,int64_t>)
{
- std::lock_guard<std::mutex> _{device->StateLock};
- clocktime = GetClockLatency(device, device->Backend.get());
+ CheckSize(2);
+ /* Get the source offset with the clock time first. Then get the
+ * clock time with the device latency. Order is important.
+ */
+ ClockLatency clocktime{};
+ nanoseconds srcclock{};
+ values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
+ {
+ std::lock_guard<std::mutex> _{device->StateLock};
+ clocktime = GetClockLatency(device, device->Backend.get());
+ }
+ if(srcclock == clocktime.ClockTime)
+ values[1] = nanoseconds{clocktime.Latency}.count();
+ else
+ {
+ /* If the clock time incremented, reduce the latency by that
+ * much since it's that much closer to the source offset it got
+ * earlier.
+ */
+ const auto diff = std::min(clocktime.Latency, clocktime.ClockTime-srcclock);
+ values[1] = nanoseconds{clocktime.Latency - diff}.count();
+ }
+ return true;
}
- if(srcclock == clocktime.ClockTime)
- values[1] = static_cast<double>(clocktime.Latency.count()) / 1000000000.0;
- else
+ break;
+
+ case AL_SAMPLE_OFFSET_CLOCK_SOFT:
+ if constexpr(std::is_same_v<T,int64_t>)
+ {
+ CheckSize(2);
+ nanoseconds srcclock{};
+ values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
+ values[1] = srcclock.count();
+ return true;
+ }
+ break;
+
+ case AL_SEC_OFFSET_LATENCY_SOFT:
+ if constexpr(std::is_same_v<T,double>)
{
- /* If the clock time incremented, reduce the latency by that much
- * since it's that much closer to the source offset it got earlier.
+ CheckSize(2);
+ /* Get the source offset with the clock time first. Then get the
+ * clock time with the device latency. Order is important.
*/
- const nanoseconds diff{clocktime.ClockTime - srcclock};
- const nanoseconds latency{clocktime.Latency - std::min(clocktime.Latency, diff)};
- values[1] = static_cast<double>(latency.count()) / 1000000000.0;
+ ClockLatency clocktime{};
+ nanoseconds srcclock{};
+ values[0] = GetSourceSecOffset(Source, Context, &srcclock);
+ {
+ std::lock_guard<std::mutex> _{device->StateLock};
+ clocktime = GetClockLatency(device, device->Backend.get());
+ }
+ if(srcclock == clocktime.ClockTime)
+ values[1] = duration_cast<seconds_d>(clocktime.Latency).count();
+ else
+ {
+ /* If the clock time incremented, reduce the latency by that
+ * much since it's that much closer to the source offset it got
+ * earlier.
+ */
+ const auto diff = std::min(clocktime.Latency, clocktime.ClockTime-srcclock);
+ values[1] = duration_cast<seconds_d>(clocktime.Latency - diff).count();
+ }
+ return true;
}
- return true;
+ break;
case AL_SEC_OFFSET_CLOCK_SOFT:
- CheckSize(2);
- values[0] = GetSourceSecOffset(Source, Context, &srcclock);
- values[1] = static_cast<double>(srcclock.count()) / 1000000000.0;
- return true;
+ if constexpr(std::is_same_v<T,double>)
+ {
+ CheckSize(2);
+ nanoseconds srcclock{};
+ values[0] = GetSourceSecOffset(Source, Context, &srcclock);
+ values[1] = duration_cast<seconds_d>(srcclock).count();
+ return true;
+ }
+ break;
case AL_POSITION:
CheckSize(3);
- values[0] = Source->Position[0];
- values[1] = Source->Position[1];
- values[2] = Source->Position[2];
+ values[0] = static_cast<T>(Source->Position[0]);
+ values[1] = static_cast<T>(Source->Position[1]);
+ values[2] = static_cast<T>(Source->Position[2]);
return true;
case AL_VELOCITY:
CheckSize(3);
- values[0] = Source->Velocity[0];
- values[1] = Source->Velocity[1];
- values[2] = Source->Velocity[2];
+ values[0] = static_cast<T>(Source->Velocity[0]);
+ values[1] = static_cast<T>(Source->Velocity[1]);
+ values[2] = static_cast<T>(Source->Velocity[2]);
return true;
case AL_DIRECTION:
CheckSize(3);
- values[0] = Source->Direction[0];
- values[1] = Source->Direction[1];
- values[2] = Source->Direction[2];
+ values[0] = static_cast<T>(Source->Direction[0]);
+ values[1] = static_cast<T>(Source->Direction[1]);
+ values[2] = static_cast<T>(Source->Direction[2]);
return true;
case AL_ORIENTATION:
CheckSize(6);
- values[0] = Source->OrientAt[0];
- values[1] = Source->OrientAt[1];
- values[2] = Source->OrientAt[2];
- values[3] = Source->OrientUp[0];
- values[4] = Source->OrientUp[1];
- values[5] = Source->OrientUp[2];
+ values[0] = static_cast<T>(Source->OrientAt[0]);
+ values[1] = static_cast<T>(Source->OrientAt[1]);
+ values[2] = static_cast<T>(Source->OrientAt[2]);
+ values[3] = static_cast<T>(Source->OrientUp[0]);
+ values[4] = static_cast<T>(Source->OrientUp[1]);
+ values[5] = static_cast<T>(Source->OrientUp[2]);
return true;
- /* 1x int */
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SOURCE_STATE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_SOURCE_TYPE:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_DISTANCE_MODEL:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false)
- values[0] = static_cast<double>(ivals[0]);
- return err;
-
- case AL_BUFFER:
- case AL_DIRECT_FILTER:
- case AL_AUXILIARY_SEND_FILTER:
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- break;
- }
-
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source double property 0x%04x", prop);
- return false;
-}
-catch(check_exception&) {
- return false;
-}
-
-bool GetSourceiv(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<int> values)
-try {
- auto CheckSize = GetSizeChecker(Context, prop, values);
- double dvals[MaxValues];
- bool err;
- switch(prop)
- {
case AL_SOURCE_RELATIVE:
- CheckSize(1);
- values[0] = Source->HeadRelative;
- return true;
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ values[0] = Source->HeadRelative;
+ return true;
+ }
+ break;
case AL_LOOPING:
- CheckSize(1);
- values[0] = Source->Looping;
- return true;
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ values[0] = Source->Looping;
+ return true;
+ }
+ break;
case AL_BUFFER:
- CheckSize(1);
+ if constexpr(std::is_integral_v<T>)
{
+ CheckSize(1);
ALbufferQueueItem *BufferList{};
/* HACK: This query should technically only return the buffer set
* on a static source. However, some apps had used it to detect
@@ -2356,377 +2307,150 @@ try {
BufferList = static_cast<ALbufferQueueItem*>(Current);
}
ALbuffer *buffer{BufferList ? BufferList->mBuffer : nullptr};
- values[0] = buffer ? static_cast<int>(buffer->id) : 0;
+ values[0] = buffer ? static_cast<T>(buffer->id) : T{0};
+ return true;
}
- return true;
+ break;
case AL_SOURCE_STATE:
- CheckSize(1);
- values[0] = GetSourceState(Source, GetSourceVoice(Source, Context));
- return true;
+ if constexpr(std::is_integral_v<T>)
+ {
+ CheckSize(1);
+ values[0] = GetSourceState(Source, GetSourceVoice(Source, Context));
+ return true;
+ }
+ break;
case AL_BUFFERS_QUEUED:
- CheckSize(1);
- values[0] = static_cast<int>(Source->mQueue.size());
- return true;
-
- case AL_BUFFERS_PROCESSED:
- CheckSize(1);
- if(Source->Looping || Source->SourceType != AL_STREAMING)
+ if constexpr(std::is_integral_v<T>)
{
- /* Buffers on a looping source are in a perpetual state of PENDING,
- * so don't report any as PROCESSED
- */
- values[0] = 0;
+ CheckSize(1);
+ values[0] = static_cast<T>(Source->mQueue.size());
+ return true;
}
- else
+ break;
+
+ case AL_BUFFERS_PROCESSED:
+ if constexpr(std::is_integral_v<T>)
{
- int played{0};
- if(Source->state != AL_INITIAL)
+ CheckSize(1);
+ if(Source->Looping || Source->SourceType != AL_STREAMING)
+ {
+ /* Buffers on a looping source are in a perpetual state of
+ * PENDING, so don't report any as PROCESSED
+ */
+ values[0] = 0;
+ }
+ else
{
- const VoiceBufferItem *Current{nullptr};
- if(Voice *voice{GetSourceVoice(Source, Context)})
- Current = voice->mCurrentBuffer.load(std::memory_order_relaxed);
- for(auto &item : Source->mQueue)
+ int played{0};
+ if(Source->state != AL_INITIAL)
{
- if(&item == Current)
- break;
- ++played;
+ const VoiceBufferItem *Current{nullptr};
+ if(Voice *voice{GetSourceVoice(Source, Context)})
+ Current = voice->mCurrentBuffer.load(std::memory_order_relaxed);
+ for(auto &item : Source->mQueue)
+ {
+ if(&item == Current)
+ break;
+ ++played;
+ }
}
+ values[0] = played;
}
- values[0] = played;
+ return true;
}
- return true;
+ break;
case AL_SOURCE_TYPE:
- CheckSize(1);
- values[0] = Source->SourceType;
- return true;
-
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- CheckSize(1);
- values[0] = Source->DryGainHFAuto;
- return true;
-
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- CheckSize(1);
- values[0] = Source->WetGainAuto;
- return true;
-
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- CheckSize(1);
- values[0] = Source->WetGainHFAuto;
- return true;
-
- case AL_DIRECT_CHANNELS_SOFT:
- CheckSize(1);
- values[0] = EnumFromDirectMode(Source->DirectChannels);
- return true;
-
- case AL_DISTANCE_MODEL:
- CheckSize(1);
- values[0] = ALenumFromDistanceModel(Source->mDistanceModel);
- return true;
-
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_SEC_LENGTH_SOFT:
- CheckSize(1);
- values[0] = static_cast<int>(mind(GetSourceLength(Source, prop),
- std::numeric_limits<int>::max()));
- return true;
-
- case AL_SOURCE_RESAMPLER_SOFT:
- CheckSize(1);
- values[0] = static_cast<int>(Source->mResampler);
- return true;
-
- case AL_SOURCE_SPATIALIZE_SOFT:
- CheckSize(1);
- values[0] = EnumFromSpatializeMode(Source->mSpatialize);
- return true;
-
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- values[0] = EnumFromStereoMode(Source->mStereoMode);
- return true;
-
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- const auto offset = GetSourceOffset(Source, AL_SAMPLE_OFFSET, Context);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int>(mind(offset, std::numeric_limits<int>::max()));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = Source->SourceType;
return true;
}
break;
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
+
+ case AL_DIRECT_FILTER_GAINHF_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- const auto offset = GetSourceOffset(Source, AL_BYTE_OFFSET, Context);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int>(mind(offset, std::numeric_limits<int>::max()));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = Source->DryGainHFAuto;
return true;
}
- /*fall-through*/
-
- /* 1x float/double */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- case AL_DOPPLER_FACTOR:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false)
- values[0] = static_cast<int>(dvals[0]);
- return err;
+ break;
- /* 3x float/double */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false)
+ case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int>(dvals[0]);
- values[1] = static_cast<int>(dvals[1]);
- values[2] = static_cast<int>(dvals[2]);
+ CheckSize(1);
+ values[0] = Source->WetGainAuto;
+ return true;
}
- return err;
+ break;
- /* 6x float/double */
- case AL_ORIENTATION:
- CheckSize(6);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false)
+ case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int>(dvals[0]);
- values[1] = static_cast<int>(dvals[1]);
- values[2] = static_cast<int>(dvals[2]);
- values[3] = static_cast<int>(dvals[3]);
- values[4] = static_cast<int>(dvals[4]);
- values[5] = static_cast<int>(dvals[5]);
+ CheckSize(1);
+ values[0] = Source->WetGainHFAuto;
+ return true;
}
- return err;
-
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- break; /* i64 only */
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- break; /* Double only */
- case AL_STEREO_ANGLES:
- break; /* Float/double only */
-
- case AL_DIRECT_FILTER:
- case AL_AUXILIARY_SEND_FILTER:
- break; /* ??? */
- }
-
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer property 0x%04x", prop);
- return false;
-}
-catch(check_exception&) {
- return false;
-}
-
-bool GetSourcei64v(ALsource *const Source, ALCcontext *const Context, const SourceProp prop,
- const al::span<int64_t> values)
-try {
- auto CheckSize = GetSizeChecker(Context, prop, values);
- ALCdevice *device{Context->mALDevice.get()};
- ClockLatency clocktime;
- nanoseconds srcclock;
- double dvals[MaxValues];
- int ivals[MaxValues];
- bool err;
-
- switch(prop)
- {
- case AL_BYTE_LENGTH_SOFT:
- case AL_SAMPLE_LENGTH_SOFT:
- case AL_SEC_LENGTH_SOFT:
- CheckSize(1);
- values[0] = static_cast<int64_t>(GetSourceLength(Source, prop));
- return true;
+ break;
- case AL_SAMPLE_OFFSET_LATENCY_SOFT:
- CheckSize(2);
- /* Get the source offset with the clock time first. Then get the clock
- * time with the device latency. Order is important.
- */
- values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
- {
- std::lock_guard<std::mutex> _{device->StateLock};
- clocktime = GetClockLatency(device, device->Backend.get());
- }
- if(srcclock == clocktime.ClockTime)
- values[1] = clocktime.Latency.count();
- else
+ case AL_DIRECT_CHANNELS_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- /* If the clock time incremented, reduce the latency by that much
- * since it's that much closer to the source offset it got earlier.
- */
- const nanoseconds diff{clocktime.ClockTime - srcclock};
- values[1] = nanoseconds{clocktime.Latency - std::min(clocktime.Latency, diff)}.count();
+ CheckSize(1);
+ values[0] = EnumFromDirectMode(Source->DirectChannels);
+ return true;
}
- return true;
-
- case AL_SAMPLE_OFFSET_CLOCK_SOFT:
- CheckSize(2);
- values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
- values[1] = srcclock.count();
- return true;
+ break;
- case AL_SAMPLE_RW_OFFSETS_SOFT:
- if(sBufferSubDataCompat)
+ case AL_DISTANCE_MODEL:
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int64_t>(GetSourceOffset(Source, AL_SAMPLE_OFFSET, Context));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = ALenumFromDistanceModel(Source->mDistanceModel);
return true;
}
break;
- case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/
- if(sBufferSubDataCompat)
+
+ case AL_SOURCE_RESAMPLER_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- CheckSize(2);
- /* FIXME: values[1] should be ahead of values[0] by the device
- * update time. It needs to clamp or wrap the length of the buffer
- * queue.
- */
- values[0] = static_cast<int64_t>(GetSourceOffset(Source, AL_BYTE_OFFSET, Context));
- values[1] = values[0];
+ CheckSize(1);
+ values[0] = static_cast<T>(Source->mResampler);
return true;
}
- /*fall-through*/
-
- /* 1x float/double */
- case AL_CONE_INNER_ANGLE:
- case AL_CONE_OUTER_ANGLE:
- case AL_PITCH:
- case AL_GAIN:
- case AL_MIN_GAIN:
- case AL_MAX_GAIN:
- case AL_REFERENCE_DISTANCE:
- case AL_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAIN:
- case AL_MAX_DISTANCE:
- case AL_SEC_OFFSET:
- case AL_SAMPLE_OFFSET:
- case AL_BYTE_OFFSET:
- case AL_DOPPLER_FACTOR:
- case AL_AIR_ABSORPTION_FACTOR:
- case AL_ROOM_ROLLOFF_FACTOR:
- case AL_CONE_OUTER_GAINHF:
- case AL_SUPER_STEREO_WIDTH_SOFT:
- CheckSize(1);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false)
- values[0] = static_cast<int64_t>(dvals[0]);
- return err;
+ break;
- /* 3x float/double */
- case AL_POSITION:
- case AL_VELOCITY:
- case AL_DIRECTION:
- CheckSize(3);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false)
+ case AL_SOURCE_SPATIALIZE_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int64_t>(dvals[0]);
- values[1] = static_cast<int64_t>(dvals[1]);
- values[2] = static_cast<int64_t>(dvals[2]);
+ CheckSize(1);
+ values[0] = EnumFromSpatializeMode(Source->mSpatialize);
+ return true;
}
- return err;
+ break;
- /* 6x float/double */
- case AL_ORIENTATION:
- CheckSize(6);
- if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false)
+ case AL_STEREO_MODE_SOFT:
+ if constexpr(std::is_integral_v<T>)
{
- values[0] = static_cast<int64_t>(dvals[0]);
- values[1] = static_cast<int64_t>(dvals[1]);
- values[2] = static_cast<int64_t>(dvals[2]);
- values[3] = static_cast<int64_t>(dvals[3]);
- values[4] = static_cast<int64_t>(dvals[4]);
- values[5] = static_cast<int64_t>(dvals[5]);
+ CheckSize(1);
+ values[0] = EnumFromStereoMode(Source->mStereoMode);
+ return true;
}
- return err;
-
- /* 1x int */
- case AL_SOURCE_RELATIVE:
- case AL_LOOPING:
- case AL_SOURCE_STATE:
- case AL_BUFFERS_QUEUED:
- case AL_BUFFERS_PROCESSED:
- case AL_SOURCE_TYPE:
- case AL_DIRECT_FILTER_GAINHF_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
- case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
- case AL_DIRECT_CHANNELS_SOFT:
- case AL_DISTANCE_MODEL:
- case AL_SOURCE_RESAMPLER_SOFT:
- case AL_SOURCE_SPATIALIZE_SOFT:
- case AL_STEREO_MODE_SOFT:
- CheckSize(1);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false)
- values[0] = ivals[0];
- return err;
+ break;
- /* 1x uint */
- case AL_BUFFER:
case AL_DIRECT_FILTER:
- CheckSize(1);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false)
- values[0] = static_cast<ALuint>(ivals[0]);
- return err;
-
- /* 3x uint */
case AL_AUXILIARY_SEND_FILTER:
- CheckSize(3);
- if((err=GetSourceiv(Source, Context, prop, {ivals, 3u})) != false)
- {
- values[0] = static_cast<ALuint>(ivals[0]);
- values[1] = static_cast<ALuint>(ivals[1]);
- values[2] = static_cast<ALuint>(ivals[2]);
- }
- return err;
-
- case AL_SEC_OFFSET_LATENCY_SOFT:
- case AL_SEC_OFFSET_CLOCK_SOFT:
- break; /* Double only */
- case AL_STEREO_ANGLES:
- break; /* Float/double only */
+ break;
}
- ERR("Unexpected property: 0x%04x\n", prop);
- Context->setError(AL_INVALID_ENUM, "Invalid source integer64 property 0x%04x", prop);
+ ERR("Unexpected %s query property: 0x%04x\n", PropType<T>::Name(), prop);
+ Context->setError(AL_INVALID_ENUM, "Invalid source %s query property 0x%04x",
+ PropType<T>::Name(), prop);
return false;
}
catch(check_exception&) {
@@ -2905,12 +2629,9 @@ void StartSources(ALCcontext *const context, const al::span<ALsource*> srchandle
} // namespace
-AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGenSources, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Generating %d sources", n);
if(n <= 0) UNLIKELY return;
@@ -2923,7 +2644,7 @@ START_API_FUNC
device->SourcesMax, context->mNumSources, n);
return;
}
- if(!EnsureSources(context.get(), static_cast<ALuint>(n)))
+ if(!EnsureSources(context, static_cast<ALuint>(n)))
{
context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d source%s", n, (n==1)?"":"s");
return;
@@ -2931,36 +2652,33 @@ START_API_FUNC
if(n == 1)
{
- ALsource *source{AllocSource(context.get())};
+ ALsource *source{AllocSource(context)};
sources[0] = source->id;
#ifdef ALSOFT_EAX
- source->eaxInitialize(context.get());
+ source->eaxInitialize(context);
#endif // ALSOFT_EAX
}
else
{
- al::vector<ALuint> ids;
+ std::vector<ALuint> ids;
ids.reserve(static_cast<ALuint>(n));
do {
- ALsource *source{AllocSource(context.get())};
+ ALsource *source{AllocSource(context)};
ids.emplace_back(source->id);
#ifdef ALSOFT_EAX
- source->eaxInitialize(context.get());
+ source->eaxInitialize(context);
#endif // ALSOFT_EAX
} while(--n);
std::copy(ids.cbegin(), ids.cend(), sources);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alDeleteSources, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Deleting %d sources", n);
if(n <= 0) UNLIKELY return;
@@ -2968,8 +2686,8 @@ START_API_FUNC
std::lock_guard<std::mutex> _{context->mSourceLock};
/* Check that all Sources are valid */
- auto validate_source = [&context](const ALuint sid) -> bool
- { return LookupSource(context.get(), sid) != nullptr; };
+ auto validate_source = [context](const ALuint sid) -> bool
+ { return LookupSource(context, sid) != nullptr; };
const ALuint *sources_end = sources + n;
auto invsrc = std::find_if_not(sources, sources_end, validate_source);
@@ -2979,577 +2697,462 @@ START_API_FUNC
/* All good. Delete source IDs. */
auto delete_source = [&context](const ALuint sid) -> void
{
- ALsource *src{LookupSource(context.get(), sid)};
- if(src) FreeSource(context.get(), src);
+ ALsource *src{LookupSource(context, sid)};
+ if(src) FreeSource(context, src);
};
std::for_each(sources, sources_end, delete_source);
}
-END_API_FUNC
-AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsSource, ALuint)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) noexcept
{
- ContextRef context{GetContextRef()};
- if(context) LIKELY
- {
- std::lock_guard<std::mutex> _{context->mSourceLock};
- if(LookupSource(context.get(), source) != nullptr)
- return AL_TRUE;
- }
+ std::lock_guard<std::mutex> _{context->mSourceLock};
+ if(LookupSource(context, source) != nullptr)
+ return AL_TRUE;
return AL_FALSE;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourcef, ALuint, ALenum, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), {&value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<float>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1u});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alSource3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat value1, ALfloat value2, ALfloat value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const float fvals[3]{ value1, value2, value3 };
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), fvals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const float fvals[3]{ value1, value2, value3 };
+ SetProperty<float>(Source, context, static_cast<SourceProp>(param), al::span{fvals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourcefv, ALuint, ALenum, const ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param,
+ const ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{FloatValsByProp(param)};
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourced,SOFT, ALuint, ALenum, ALdouble)
+FORCE_ALIGN void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param,
+ ALdouble value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const float fval[1]{static_cast<float>(value)};
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), fval);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<double>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alSource3d,SOFT, ALuint, ALenum, ALdouble, ALdouble, ALdouble)
+FORCE_ALIGN void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param,
+ ALdouble value1, ALdouble value2, ALdouble value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const float fvals[3]{static_cast<float>(value1), static_cast<float>(value2),
- static_cast<float>(value3)};
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), fvals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const double dvals[3]{value1, value2, value3};
+ SetProperty<double>(Source, context, static_cast<SourceProp>(param), al::span{dvals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourcedv,SOFT, ALuint, ALenum, const ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param,
+ const ALdouble *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{DoubleValsByProp(param)};
- float fvals[MaxValues];
- std::copy_n(values, count, fvals);
- SetSourcefv(Source, context.get(), static_cast<SourceProp>(param), {fvals, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourcei, ALuint, ALenum, ALint)
+FORCE_ALIGN void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- SetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {&value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<int>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1u});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alSource3i, ALuint, ALenum, ALint, ALint, ALint)
+FORCE_ALIGN void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint value1, ALint value2, ALint value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const int ivals[3]{ value1, value2, value3 };
- SetSourceiv(Source, context.get(), static_cast<SourceProp>(param), ivals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const int ivals[3]{ value1, value2, value3 };
+ SetProperty<int>(Source, context, static_cast<SourceProp>(param), al::span{ivals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourceiv, ALuint, ALenum, const ALint*)
+FORCE_ALIGN void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param,
+ const ALint *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source = LookupSource(context.get(), source);
+ ALsource *Source = LookupSource(context, source);
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{IntValsByProp(param)};
- SetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourcei64,SOFT, ALuint, ALenum, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- SetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {&value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ SetProperty<int64_t>(Source, context, static_cast<SourceProp>(param), al::span{&value, 1u});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alSource3i64,SOFT, ALuint, ALenum, ALint64SOFT, ALint64SOFT, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else
- {
- const int64_t i64vals[3]{ value1, value2, value3 };
- SetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), i64vals);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+
+ const int64_t i64vals[3]{ value1, value2, value3 };
+ SetProperty<int64_t>(Source, context, static_cast<SourceProp>(param), al::span{i64vals});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alSourcei64v,SOFT, ALuint, ALenum, const ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, const ALint64SOFT *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
std::lock_guard<std::mutex> __{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{Int64ValsByProp(param)};
- SetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ SetProperty(Source, context, static_cast<SourceProp>(param), al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourcef, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- {
- double dval[1];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), dval))
- *value = static_cast<float>(dval[0]);
- }
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alGetSource3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ float fvals[3];
+ if(GetProperty<float>(Source, context, static_cast<SourceProp>(param), al::span{fvals}))
{
- double dvals[3];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), dvals))
- {
- *value1 = static_cast<float>(dvals[0]);
- *value2 = static_cast<float>(dvals[1]);
- *value3 = static_cast<float>(dvals[2]);
- }
+ *value1 = fvals[0];
+ *value2 = fvals[1];
+ *value3 = fvals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourcefv, ALuint, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALfloat *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{FloatValsByProp(param)};
- double dvals[MaxValues];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), {dvals, count}))
- std::copy_n(dvals, count, values);
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourced,SOFT, ALuint, ALenum, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALdouble *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), {value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alGetSource3d,SOFT, ALuint, ALenum, ALdouble*, ALdouble*, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ double dvals[3];
+ if(GetProperty<double>(Source, context, static_cast<SourceProp>(param), al::span{dvals}))
{
- double dvals[3];
- if(GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), dvals))
- {
- *value1 = dvals[0];
- *value2 = dvals[1];
- *value3 = dvals[2];
- }
+ *value1 = dvals[0];
+ *value2 = dvals[1];
+ *value3 = dvals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourcedv,SOFT, ALuint, ALenum, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALdouble *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{DoubleValsByProp(param)};
- GetSourcedv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourcei, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- GetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
-START_API_FUNC
+AL_API DECL_FUNC5(void, alGetSource3i, ALuint, ALenum, ALint*, ALint*, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint *value1, ALint *value2, ALint *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ int ivals[3];
+ if(GetProperty<int>(Source, context, static_cast<SourceProp>(param), al::span{ivals}))
{
- int ivals[3];
- if(GetSourceiv(Source, context.get(), static_cast<SourceProp>(param), ivals))
- {
- *value1 = ivals[0];
- *value2 = ivals[1];
- *value3 = ivals[2];
- }
+ *value1 = ivals[0];
+ *value2 = ivals[1];
+ *value3 = ivals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alGetSourceiv, ALuint, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param,
+ ALint *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{IntValsByProp(param)};
- GetSourceiv(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourcei64,SOFT, ALuint, ALenum, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!value) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
- GetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {value, 1u});
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!value) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param), al::span{value, 1});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
-START_API_FUNC
+AL_API DECL_FUNCEXT5(void, alGetSource3i64,SOFT, ALuint, ALenum, ALint64SOFT*, ALint64SOFT*, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
- context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(value1 && value2 && value3)) UNLIKELY
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
+ if(!(value1 && value2 && value3)) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ int64_t i64vals[3];
+ if(GetProperty<int64_t>(Source, context, static_cast<SourceProp>(param), al::span{i64vals}))
{
- int64_t i64vals[3];
- if(GetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), i64vals))
- {
- *value1 = i64vals[0];
- *value2 = i64vals[1];
- *value3 = i64vals[2];
- }
+ *value1 = i64vals[0];
+ *value2 = i64vals[1];
+ *value3 = i64vals[2];
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
-START_API_FUNC
+AL_API DECL_FUNCEXT3(void, alGetSourcei64v,SOFT, ALuint, ALenum, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source,
+ ALenum param, ALint64SOFT *values) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *Source{LookupSource(context.get(), source)};
+ ALsource *Source{LookupSource(context, source)};
if(!Source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
const ALuint count{Int64ValsByProp(param)};
- GetSourcei64v(Source, context.get(), static_cast<SourceProp>(param), {values, count});
+ std::ignore = GetProperty(Source, context, static_cast<SourceProp>(param),
+ al::span{values, count});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcePlay(ALuint source)
-START_API_FUNC
+AL_API DECL_FUNC1(void, alSourcePlay, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *srchandle{LookupSource(context.get(), source)};
+ ALsource *srchandle{LookupSource(context, source)};
if(!srchandle)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- StartSources(context.get(), {&srchandle, 1});
+ StartSources(context, {&srchandle, 1});
}
-END_API_FUNC
-void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time)
-START_API_FUNC
+FORCE_ALIGN DECL_FUNCEXT2(void, alSourcePlayAtTime,SOFT, ALuint, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source,
+ ALint64SOFT start_time) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(start_time < 0) UNLIKELY
return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time);
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *srchandle{LookupSource(context.get(), source)};
+ ALsource *srchandle{LookupSource(context, source)};
if(!srchandle)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source);
- StartSources(context.get(), {&srchandle, 1}, nanoseconds{start_time});
+ StartSources(context, {&srchandle, 1}, nanoseconds{start_time});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourcePlayv, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Playing %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
}
- StartSources(context.get(), srchandles);
+ StartSources(context, srchandles);
}
-END_API_FUNC
-void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time)
-START_API_FUNC
+FORCE_ALIGN DECL_FUNCEXT3(void, alSourcePlayAtTimev,SOFT, ALsizei, const ALuint*, ALint64SOFT)
+FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n,
+ const ALuint *sources, ALint64SOFT start_time) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Playing %d sources", n);
if(n <= 0) UNLIKELY return;
@@ -3557,61 +3160,57 @@ START_API_FUNC
if(start_time < 0) UNLIKELY
return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time);
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
}
- StartSources(context.get(), srchandles, nanoseconds{start_time});
+ StartSources(context, srchandles, nanoseconds{start_time});
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourcePause(ALuint source)
-START_API_FUNC
-{ alSourcePausev(1, &source); }
-END_API_FUNC
+AL_API DECL_FUNC1(void, alSourcePause, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) noexcept
+{ alSourcePausevDirect(context, 1, &source); }
-AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourcePausev, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Pausing %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
@@ -3624,14 +3223,14 @@ START_API_FUNC
VoiceChange *tail{}, *cur{};
for(ALsource *source : srchandles)
{
- Voice *voice{GetSourceVoice(source, context.get())};
+ Voice *voice{GetSourceVoice(source, context)};
if(GetSourceState(source, voice) == AL_PLAYING)
{
if(!cur)
- cur = tail = GetVoiceChanger(context.get());
+ cur = tail = GetVoiceChanger(context);
else
{
- cur->mNext.store(GetVoiceChanger(context.get()), std::memory_order_relaxed);
+ cur->mNext.store(GetVoiceChanger(context), std::memory_order_relaxed);
cur = cur->mNext.load(std::memory_order_relaxed);
}
cur->mVoice = voice;
@@ -3641,7 +3240,7 @@ START_API_FUNC
}
if(tail) LIKELY
{
- SendVoiceChanges(context.get(), tail);
+ SendVoiceChanges(context, tail);
/* Second, now that the voice changes have been sent, because it's
* possible that the voice stopped after it was detected playing and
* before the voice got paused, recheck that the source is still
@@ -3649,45 +3248,41 @@ START_API_FUNC
*/
for(ALsource *source : srchandles)
{
- Voice *voice{GetSourceVoice(source, context.get())};
+ Voice *voice{GetSourceVoice(source, context)};
if(GetSourceState(source, voice) == AL_PLAYING)
source->state = AL_PAUSED;
}
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceStop(ALuint source)
-START_API_FUNC
-{ alSourceStopv(1, &source); }
-END_API_FUNC
+AL_API DECL_FUNC1(void, alSourceStop, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) noexcept
+{ alSourceStopvDirect(context, 1, &source); }
-AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourceStopv, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Stopping %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
@@ -3696,13 +3291,13 @@ START_API_FUNC
VoiceChange *tail{}, *cur{};
for(ALsource *source : srchandles)
{
- if(Voice *voice{GetSourceVoice(source, context.get())})
+ if(Voice *voice{GetSourceVoice(source, context)})
{
if(!cur)
- cur = tail = GetVoiceChanger(context.get());
+ cur = tail = GetVoiceChanger(context);
else
{
- cur->mNext.store(GetVoiceChanger(context.get()), std::memory_order_relaxed);
+ cur->mNext.store(GetVoiceChanger(context), std::memory_order_relaxed);
cur = cur->mNext.load(std::memory_order_relaxed);
}
voice->mPendingChange.store(true, std::memory_order_relaxed);
@@ -3713,44 +3308,40 @@ START_API_FUNC
}
source->Offset = 0.0;
source->OffsetType = AL_NONE;
- source->VoiceIdx = INVALID_VOICE_IDX;
+ source->VoiceIdx = InvalidVoiceIndex;
}
if(tail) LIKELY
- SendVoiceChanges(context.get(), tail);
+ SendVoiceChanges(context, tail);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceRewind(ALuint source)
-START_API_FUNC
-{ alSourceRewindv(1, &source); }
-END_API_FUNC
+AL_API DECL_FUNC1(void, alSourceRewind, ALuint)
+FORCE_ALIGN void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) noexcept
+{ alSourceRewindvDirect(context, 1, &source); }
-AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alSourceRewindv, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n,
+ const ALuint *sources) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(n < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Rewinding %d sources", n);
if(n <= 0) UNLIKELY return;
- al::vector<ALsource*> extra_sources;
+ std::vector<ALsource*> extra_sources;
std::array<ALsource*,8> source_storage;
al::span<ALsource*> srchandles;
if(static_cast<ALuint>(n) <= source_storage.size()) LIKELY
- srchandles = {source_storage.data(), static_cast<ALuint>(n)};
+ srchandles = al::span{source_storage}.first(static_cast<ALuint>(n));
else
{
extra_sources.resize(static_cast<ALuint>(n));
- srchandles = {extra_sources.data(), extra_sources.size()};
+ srchandles = extra_sources;
}
std::lock_guard<std::mutex> _{context->mSourceLock};
for(auto &srchdl : srchandles)
{
- srchdl = LookupSource(context.get(), *sources);
+ srchdl = LookupSource(context, *sources);
if(!srchdl)
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources);
++sources;
@@ -3759,14 +3350,14 @@ START_API_FUNC
VoiceChange *tail{}, *cur{};
for(ALsource *source : srchandles)
{
- Voice *voice{GetSourceVoice(source, context.get())};
+ Voice *voice{GetSourceVoice(source, context)};
if(source->state != AL_INITIAL)
{
if(!cur)
- cur = tail = GetVoiceChanger(context.get());
+ cur = tail = GetVoiceChanger(context);
else
{
- cur->mNext.store(GetVoiceChanger(context.get()), std::memory_order_relaxed);
+ cur->mNext.store(GetVoiceChanger(context), std::memory_order_relaxed);
cur = cur->mNext.load(std::memory_order_relaxed);
}
if(voice)
@@ -3778,26 +3369,23 @@ START_API_FUNC
}
source->Offset = 0.0;
source->OffsetType = AL_NONE;
- source->VoiceIdx = INVALID_VOICE_IDX;
+ source->VoiceIdx = InvalidVoiceIndex;
}
if(tail) LIKELY
- SendVoiceChanges(context.get(), tail);
+ SendVoiceChanges(context, tail);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALuint *buffers)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourceQueueBuffers, ALuint, ALsizei, const ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint src,
+ ALsizei nb, const ALuint *buffers) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(nb < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Queueing %d buffers", nb);
if(nb <= 0) UNLIKELY return;
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *source{LookupSource(context.get(),src)};
+ ALsource *source{LookupSource(context,src)};
if(!source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", src);
@@ -3912,20 +3500,17 @@ START_API_FUNC
(iter-1)->mNext.store(al::to_address(iter), std::memory_order_release);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers)
-START_API_FUNC
+AL_API DECL_FUNC3(void, alSourceUnqueueBuffers, ALuint, ALsizei, ALuint*)
+FORCE_ALIGN void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint src,
+ ALsizei nb, ALuint *buffers) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(nb < 0) UNLIKELY
context->setError(AL_INVALID_VALUE, "Unqueueing %d buffers", nb);
if(nb <= 0) UNLIKELY return;
std::lock_guard<std::mutex> _{context->mSourceLock};
- ALsource *source{LookupSource(context.get(),src)};
+ ALsource *source{LookupSource(context,src)};
if(!source) UNLIKELY
return context->setError(AL_INVALID_NAME, "Invalid source ID %u", src);
@@ -3940,7 +3525,7 @@ START_API_FUNC
if(source->state != AL_INITIAL) LIKELY
{
VoiceBufferItem *Current{nullptr};
- if(Voice *voice{GetSourceVoice(source, context.get())})
+ if(Voice *voice{GetSourceVoice(source, context)})
Current = voice->mCurrentBuffer.load(std::memory_order_relaxed);
for(auto &item : source->mQueue)
{
@@ -3965,18 +3550,15 @@ START_API_FUNC
source->mQueue.pop_front();
} while(--nb);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALuint*)
-START_API_FUNC
+AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALuint*) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
context->setError(AL_INVALID_OPERATION, "alSourceQueueBufferLayersSOFT not supported");
}
-END_API_FUNC
ALsource::ALsource()
@@ -4028,14 +3610,29 @@ void UpdateAllSourceProps(ALCcontext *context)
}
}
+void ALsource::SetName(ALCcontext *context, ALuint id, std::string_view name)
+{
+ std::lock_guard<std::mutex> _{context->mSourceLock};
+
+ auto source = LookupSource(context, id);
+ if(!source) UNLIKELY
+ return context->setError(AL_INVALID_NAME, "Invalid source ID %u", id);
+
+ context->mSourceNames.insert_or_assign(id, name);
+}
+
+
SourceSubList::~SourceSubList()
{
+ if(!Sources)
+ return;
+
uint64_t usemask{~FreeMask};
while(usemask)
{
const int idx{al::countr_zero(usemask)};
usemask &= ~(1_u64 << idx);
- al::destroy_at(Sources+idx);
+ std::destroy_at(Sources+idx);
}
FreeMask = ~usemask;
al_free(Sources);
@@ -4097,7 +3694,8 @@ ALsource* ALsource::EaxLookupSource(ALCcontext& al_context, ALuint source_id) no
void ALsource::eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept
{
- for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
+ {
auto& send = sends[i];
send.guidReceivingFXSlotID = *(ids[i]);
send.lSend = EAXSOURCE_DEFAULTSEND;
@@ -4209,7 +3807,8 @@ void ALsource::eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noex
void ALsource::eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept
{
- for (auto i = size_t{}; i < eax_max_speakers; ++i) {
+ for(size_t i{0};i < eax_max_speakers;++i)
+ {
auto& speaker_level = speaker_levels[i];
speaker_level.lSpeakerID = static_cast<long>(EAXSPEAKER_FRONT_LEFT + i);
speaker_level.lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
@@ -4251,7 +3850,7 @@ void ALsource::eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept
else
{
dst.source.ulFlags &= ~EAXSOURCEFLAGS_ROOMAUTO;
- dst.sends[0].lSend = clamp(static_cast<long>(gain_to_level_mb(src.fMix)),
+ dst.sends[0].lSend = std::clamp(static_cast<long>(gain_to_level_mb(src.fMix)),
EAXSOURCE_MINSEND, EAXSOURCE_MAXSEND);
}
}
@@ -4280,7 +3879,7 @@ void ALsource::eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept
dst.source.ulFlags = src.dwFlags;
dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
- // Set everyting else to defaults.
+ // Set everything else to defaults.
//
eax5_set_sends_defaults(dst.sends);
eax5_set_active_fx_slots_defaults(dst.active_fx_slots);
@@ -4294,7 +3893,7 @@ void ALsource::eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept
static_cast<Eax3Props&>(dst.source) = src;
dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
- // Set everyting else to defaults.
+ // Set everything else to defaults.
//
eax5_set_sends_defaults(dst.sends);
eax5_set_active_fx_slots_defaults(dst.active_fx_slots);
@@ -4312,7 +3911,7 @@ void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept
//
dst.sends = src.sends;
- for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
dst.sends[i].guidReceivingFXSlotID = *(eax5_fx_slot_ids[i]);
// Active FX slots.
@@ -4374,19 +3973,21 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept
static_cast<float>(mEax.source.lDirectHF) +
static_cast<float>(mEax.source.lObstruction);
- for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
{
if(!mEaxActiveFxSlots[i])
continue;
- if(has_source_occlusion) {
+ if(has_source_occlusion)
+ {
const auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i);
const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot();
const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0);
const auto is_primary = (mEaxPrimaryFxSlotId.value_or(-1) == fx_slot.eax_get_index());
const auto is_listener_environment = (is_environmental_fx && is_primary);
- if(is_listener_environment) {
+ if(is_listener_environment)
+ {
gain_mb += eax_calculate_dst_occlusion_mb(
mEax.source.lOcclusion,
mEax.source.flOcclusionDirectRatio,
@@ -4398,7 +3999,8 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept
const auto& send = mEax.sends[i];
- if(send.lOcclusion != 0) {
+ if(send.lOcclusion != 0)
+ {
gain_mb += eax_calculate_dst_occlusion_mb(
send.lOcclusion,
send.flOcclusionDirectRatio,
@@ -4473,8 +4075,9 @@ void ALsource::eax_update_direct_filter()
void ALsource::eax_update_room_filters()
{
- for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
- if (!mEaxActiveFxSlots[i])
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
+ {
+ if(!mEaxActiveFxSlots[i])
continue;
auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i);
@@ -4486,7 +4089,7 @@ void ALsource::eax_update_room_filters()
void ALsource::eax_set_efx_outer_gain_hf()
{
- OuterGainHF = clamp(
+ OuterGainHF = std::clamp(
level_mb_to_gain(static_cast<float>(mEax.source.lOutsideVolumeHF)),
AL_MIN_CONE_OUTER_GAINHF,
AL_MAX_CONE_OUTER_GAINHF);
@@ -5280,7 +4883,7 @@ void ALsource::eax_commit_active_fx_slots()
// Deactivate EFX auxiliary effect slots for inactive slots. Active slots
// will be updated with the room filters.
- for(auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ for(size_t i{0};i < EAX_MAX_FXSLOTS;++i)
{
if(!mEaxActiveFxSlots[i])
eax_set_al_source_send(nullptr, i, EaxAlLowPassParam{1.0f, 1.0f});
diff --git a/al/source.h b/al/source.h
index ac97c8a7..c7694f83 100644
--- a/al/source.h
+++ b/al/source.h
@@ -4,9 +4,10 @@
#include <array>
#include <atomic>
#include <cstddef>
+#include <deque>
#include <iterator>
#include <limits>
-#include <deque>
+#include <string_view>
#include "AL/al.h"
#include "AL/alc.h"
@@ -14,7 +15,6 @@
#include "alc/alu.h"
#include "alc/context.h"
#include "alc/inprogext.h"
-#include "aldeque.h"
#include "almalloc.h"
#include "alnumeric.h"
#include "atomic.h"
@@ -39,9 +39,9 @@ enum class SourceStereo : bool {
#define DEFAULT_SENDS 2
-#define INVALID_VOICE_IDX static_cast<ALuint>(-1)
+inline constexpr ALuint InvalidVoiceIndex{std::numeric_limits<ALuint>::max()};
-extern bool sBufferSubDataCompat;
+inline bool sBufferSubDataCompat{false};
struct ALbufferQueueItem : public VoiceBufferItem {
ALbuffer *mBuffer{nullptr};
@@ -138,14 +138,14 @@ struct ALsource {
ALenum state{AL_INITIAL};
/** Source Buffer Queue head. */
- al::deque<ALbufferQueueItem> mQueue;
+ std::deque<ALbufferQueueItem> mQueue;
bool mPropsDirty{true};
/* Index into the context's Voices array. Lazily updated, only checked and
* reset when looking up the voice.
*/
- ALuint VoiceIdx{INVALID_VOICE_IDX};
+ ALuint VoiceIdx{InvalidVoiceIndex};
/** Self ID */
ALuint id{0};
@@ -157,6 +157,8 @@ struct ALsource {
ALsource(const ALsource&) = delete;
ALsource& operator=(const ALsource&) = delete;
+ static void SetName(ALCcontext *context, ALuint id, std::string_view name);
+
DISABLE_ALLOC()
#ifdef ALSOFT_EAX
diff --git a/al/state.cpp b/al/state.cpp
index 86d81b13..5131edd9 100644
--- a/al/state.cpp
+++ b/al/state.cpp
@@ -24,7 +24,9 @@
#include <atomic>
#include <cmath>
+#include <cstring>
#include <mutex>
+#include <optional>
#include <stdexcept>
#include <string>
@@ -32,16 +34,18 @@
#include "AL/alc.h"
#include "AL/alext.h"
+#include "al/debug.h"
+#include "albit.h"
#include "alc/alu.h"
#include "alc/context.h"
#include "alc/inprogext.h"
#include "alnumeric.h"
-#include "aloptional.h"
#include "atomic.h"
#include "core/context.h"
#include "core/except.h"
#include "core/mixer/defs.h"
#include "core/voice.h"
+#include "direct_defs.h"
#include "intrusive_ptr.h"
#include "opthelpers.h"
#include "strutils.h"
@@ -67,6 +71,8 @@ constexpr ALchar alErrInvalidEnum[] = "Invalid Enum";
constexpr ALchar alErrInvalidValue[] = "Invalid Value";
constexpr ALchar alErrInvalidOp[] = "Invalid Operation";
constexpr ALchar alErrOutOfMemory[] = "Out of Memory";
+constexpr ALchar alStackOverflow[] = "Stack Overflow";
+constexpr ALchar alStackUnderflow[] = "Stack Underflow";
/* Resampler strings */
template<Resampler rtype> struct ResamplerName { };
@@ -103,7 +109,7 @@ const ALchar *GetResamplerName(const Resampler rtype)
throw std::runtime_error{"Unexpected resampler index"};
}
-al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
+std::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
{
switch(model)
{
@@ -115,7 +121,7 @@ al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent;
case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped;
}
- return al::nullopt;
+ return std::nullopt;
}
ALenum ALenumFromDistanceModel(DistanceModel model)
{
@@ -132,626 +138,352 @@ ALenum ALenumFromDistanceModel(DistanceModel model)
throw std::runtime_error{"Unexpected distance model "+std::to_string(static_cast<int>(model))};
}
-} // namespace
-
-/* WARNING: Non-standard export! Not part of any extension, or exposed in the
- * alcFunctions list.
- */
-AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
-START_API_FUNC
-{
- static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION");
- if(spoof) return spoof->c_str();
- return ALSOFT_VERSION;
-}
-END_API_FUNC
-
-#define DO_UPDATEPROPS() do { \
- if(!context->mDeferUpdates) \
- UpdateContextProps(context.get()); \
- else \
- context->mPropsDirty = true; \
-} while(0)
-
-
-AL_API void AL_APIENTRY alEnable(ALenum capability)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- switch(capability)
- {
- case AL_SOURCE_DISTANCE_MODEL:
- {
- std::lock_guard<std::mutex> _{context->mPropLock};
- context->mSourceDistanceModel = true;
- DO_UPDATEPROPS();
- }
- break;
-
- case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
- context->setError(AL_INVALID_OPERATION, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported");
- break;
-
- default:
- context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
- }
-}
-END_API_FUNC
-
-AL_API void AL_APIENTRY alDisable(ALenum capability)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- switch(capability)
- {
- case AL_SOURCE_DISTANCE_MODEL:
- {
- std::lock_guard<std::mutex> _{context->mPropLock};
- context->mSourceDistanceModel = false;
- DO_UPDATEPROPS();
- }
- break;
-
- case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
- context->mStopVoicesOnDisconnect = false;
- break;
-
- default:
- context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
- }
-}
-END_API_FUNC
-
-AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return AL_FALSE;
-
- std::lock_guard<std::mutex> _{context->mPropLock};
- ALboolean value{AL_FALSE};
- switch(capability)
- {
- case AL_SOURCE_DISTANCE_MODEL:
- value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE;
- break;
-
- case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
- value = context->mStopVoicesOnDisconnect ? AL_TRUE : AL_FALSE;
- break;
-
- default:
- context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
- }
-
- return value;
-}
-END_API_FUNC
-
-AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
-START_API_FUNC
+enum PropertyValue : ALenum {
+ DopplerFactor = AL_DOPPLER_FACTOR,
+ DopplerVelocity = AL_DOPPLER_VELOCITY,
+ DistanceModel = AL_DISTANCE_MODEL,
+ SpeedOfSound = AL_SPEED_OF_SOUND,
+ DeferredUpdates = AL_DEFERRED_UPDATES_SOFT,
+ GainLimit = AL_GAIN_LIMIT_SOFT,
+ NumResamplers = AL_NUM_RESAMPLERS_SOFT,
+ DefaultResampler = AL_DEFAULT_RESAMPLER_SOFT,
+ DebugLoggedMessages = AL_DEBUG_LOGGED_MESSAGES_EXT,
+ DebugNextLoggedMessageLength = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT,
+ MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT,
+ MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT,
+ MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT,
+ MaxLabelLength = AL_MAX_LABEL_LENGTH_EXT,
+ ContextFlags = AL_CONTEXT_FLAGS_EXT,
+#ifdef ALSOFT_EAX
+ EaxRamSize = AL_EAX_RAM_SIZE,
+ EaxRamFree = AL_EAX_RAM_FREE,
+#endif
+};
+
+template<typename T>
+struct PropertyCastType {
+ template<typename U>
+ constexpr auto operator()(U&& value) const noexcept
+ { return static_cast<T>(std::forward<U>(value)); }
+};
+/* Special-case ALboolean to be an actual bool instead of a char type. */
+template<>
+struct PropertyCastType<ALboolean> {
+ template<typename U>
+ constexpr ALboolean operator()(U&& value) const noexcept
+ { return static_cast<bool>(std::forward<U>(value)) ? AL_TRUE : AL_FALSE; }
+};
+
+
+template<typename T>
+void GetValue(ALCcontext *context, ALenum pname, T *values)
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return AL_FALSE;
+ auto cast_value = PropertyCastType<T>{};
- std::lock_guard<std::mutex> _{context->mPropLock};
- ALboolean value{AL_FALSE};
- switch(pname)
+ switch(static_cast<PropertyValue>(pname))
{
case AL_DOPPLER_FACTOR:
- if(context->mDopplerFactor != 0.0f)
- value = AL_TRUE;
- break;
+ *values = cast_value(context->mDopplerFactor);
+ return;
case AL_DOPPLER_VELOCITY:
- if(context->mDopplerVelocity != 0.0f)
- value = AL_TRUE;
- break;
-
- case AL_DISTANCE_MODEL:
- if(context->mDistanceModel == DistanceModel::Default)
- value = AL_TRUE;
- break;
+ if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY
+ context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0,
+ DebugSeverity::Medium,
+ "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; "
+ "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f");
+ *values = cast_value(context->mDopplerVelocity);
+ return;
case AL_SPEED_OF_SOUND:
- if(context->mSpeedOfSound != 0.0f)
- value = AL_TRUE;
- break;
-
- case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates)
- value = AL_TRUE;
- break;
+ *values = cast_value(context->mSpeedOfSound);
+ return;
case AL_GAIN_LIMIT_SOFT:
- if(GainMixMax/context->mGainBoost != 0.0f)
- value = AL_TRUE;
- break;
-
- case AL_NUM_RESAMPLERS_SOFT:
- /* Always non-0. */
- value = AL_TRUE;
- break;
-
- case AL_DEFAULT_RESAMPLER_SOFT:
- value = static_cast<int>(ResamplerDefault) ? AL_TRUE : AL_FALSE;
- break;
-
- default:
- context->setError(AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
- }
-
- return value;
-}
-END_API_FUNC
-
-AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return 0.0;
-
- std::lock_guard<std::mutex> _{context->mPropLock};
- ALdouble value{0.0};
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- value = context->mDopplerFactor;
- break;
-
- case AL_DOPPLER_VELOCITY:
- value = context->mDopplerVelocity;
- break;
-
- case AL_DISTANCE_MODEL:
- value = static_cast<ALdouble>(ALenumFromDistanceModel(context->mDistanceModel));
- break;
-
- case AL_SPEED_OF_SOUND:
- value = context->mSpeedOfSound;
- break;
+ *values = cast_value(GainMixMax / context->mGainBoost);
+ return;
case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates)
- value = static_cast<ALdouble>(AL_TRUE);
- break;
-
- case AL_GAIN_LIMIT_SOFT:
- value = ALdouble{GainMixMax}/context->mGainBoost;
- break;
-
- case AL_NUM_RESAMPLERS_SOFT:
- value = static_cast<ALdouble>(Resampler::Max) + 1.0;
- break;
-
- case AL_DEFAULT_RESAMPLER_SOFT:
- value = static_cast<ALdouble>(ResamplerDefault);
- break;
-
- default:
- context->setError(AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
- }
-
- return value;
-}
-END_API_FUNC
-
-AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return 0.0f;
-
- std::lock_guard<std::mutex> _{context->mPropLock};
- ALfloat value{0.0f};
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- value = context->mDopplerFactor;
- break;
-
- case AL_DOPPLER_VELOCITY:
- value = context->mDopplerVelocity;
- break;
+ *values = cast_value(context->mDeferUpdates ? AL_TRUE : AL_FALSE);
+ return;
case AL_DISTANCE_MODEL:
- value = static_cast<ALfloat>(ALenumFromDistanceModel(context->mDistanceModel));
- break;
-
- case AL_SPEED_OF_SOUND:
- value = context->mSpeedOfSound;
- break;
-
- case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates)
- value = static_cast<ALfloat>(AL_TRUE);
- break;
-
- case AL_GAIN_LIMIT_SOFT:
- value = GainMixMax/context->mGainBoost;
- break;
+ *values = cast_value(ALenumFromDistanceModel(context->mDistanceModel));
+ return;
case AL_NUM_RESAMPLERS_SOFT:
- value = static_cast<ALfloat>(Resampler::Max) + 1.0f;
- break;
+ *values = cast_value(al::to_underlying(Resampler::Max) + 1);
+ return;
case AL_DEFAULT_RESAMPLER_SOFT:
- value = static_cast<ALfloat>(ResamplerDefault);
- break;
+ *values = cast_value(al::to_underlying(ResamplerDefault));
+ return;
- default:
- context->setError(AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
+ case AL_DEBUG_LOGGED_MESSAGES_EXT:
+ {
+ std::lock_guard<std::mutex> _{context->mDebugCbLock};
+ *values = cast_value(context->mDebugLog.size());
+ return;
}
- return value;
-}
-END_API_FUNC
-
-AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return 0;
-
- std::lock_guard<std::mutex> _{context->mPropLock};
- ALint value{0};
- switch(pname)
+ case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT:
{
- case AL_DOPPLER_FACTOR:
- value = static_cast<ALint>(context->mDopplerFactor);
- break;
+ std::lock_guard<std::mutex> _{context->mDebugCbLock};
+ *values = cast_value(context->mDebugLog.empty() ? 0_uz
+ : (context->mDebugLog.front().mMessage.size()+1));
+ return;
+ }
- case AL_DOPPLER_VELOCITY:
- value = static_cast<ALint>(context->mDopplerVelocity);
- break;
+ case AL_MAX_DEBUG_MESSAGE_LENGTH_EXT:
+ *values = cast_value(MaxDebugMessageLength);
+ return;
- case AL_DISTANCE_MODEL:
- value = ALenumFromDistanceModel(context->mDistanceModel);
- break;
+ case AL_MAX_DEBUG_LOGGED_MESSAGES_EXT:
+ *values = cast_value(MaxDebugLoggedMessages);
+ return;
- case AL_SPEED_OF_SOUND:
- value = static_cast<ALint>(context->mSpeedOfSound);
- break;
+ case AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT:
+ *values = cast_value(MaxDebugGroupDepth);
+ return;
- case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates)
- value = AL_TRUE;
- break;
+ case AL_MAX_LABEL_LENGTH_EXT:
+ *values = cast_value(MaxObjectLabelLength);
+ return;
- case AL_GAIN_LIMIT_SOFT:
- value = static_cast<ALint>(GainMixMax/context->mGainBoost);
- break;
-
- case AL_NUM_RESAMPLERS_SOFT:
- value = static_cast<int>(Resampler::Max) + 1;
- break;
-
- case AL_DEFAULT_RESAMPLER_SOFT:
- value = static_cast<int>(ResamplerDefault);
- break;
+ case AL_CONTEXT_FLAGS_EXT:
+ *values = cast_value(context->mContextFlags.to_ulong());
+ return;
#ifdef ALSOFT_EAX
#define EAX_ERROR "[alGetInteger] EAX not enabled."
case AL_EAX_RAM_SIZE:
- if (eax_g_is_enabled)
- {
- value = eax_x_ram_max_size;
- }
- else
+ if(eax_g_is_enabled)
{
- context->setError(AL_INVALID_VALUE, EAX_ERROR);
+ *values = cast_value(eax_x_ram_max_size);
+ return;
}
-
- break;
+ context->setError(AL_INVALID_ENUM, EAX_ERROR);
+ return;
case AL_EAX_RAM_FREE:
- if (eax_g_is_enabled)
+ if(eax_g_is_enabled)
{
auto device = context->mALDevice.get();
std::lock_guard<std::mutex> device_lock{device->BufferLock};
-
- value = static_cast<ALint>(device->eax_x_ram_free_size);
+ *values = cast_value(device->eax_x_ram_free_size);
+ return;
}
- else
- {
- context->setError(AL_INVALID_VALUE, EAX_ERROR);
- }
-
- break;
+ context->setError(AL_INVALID_ENUM, EAX_ERROR);
+ return;
#undef EAX_ERROR
#endif // ALSOFT_EAX
-
- default:
- context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
}
+ context->setError(AL_INVALID_ENUM, "Invalid context property 0x%04x", pname);
+}
- return value;
+
+inline void UpdateProps(ALCcontext *context)
+{
+ if(!context->mDeferUpdates)
+ UpdateContextProps(context);
+ else
+ context->mPropsDirty = true;
}
-END_API_FUNC
-AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
-START_API_FUNC
+} // namespace
+
+/* WARNING: Non-standard export! Not part of any extension, or exposed in the
+ * alcFunctions list.
+ */
+AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return 0_i64;
+ static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION");
+ if(spoof) return spoof->c_str();
+ return ALSOFT_VERSION;
+}
- std::lock_guard<std::mutex> _{context->mPropLock};
- ALint64SOFT value{0};
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- value = static_cast<ALint64SOFT>(context->mDopplerFactor);
- break;
- case AL_DOPPLER_VELOCITY:
- value = static_cast<ALint64SOFT>(context->mDopplerVelocity);
+AL_API DECL_FUNC1(void, alEnable, ALenum)
+FORCE_ALIGN void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) noexcept
+{
+ switch(capability)
+ {
+ case AL_SOURCE_DISTANCE_MODEL:
+ {
+ std::lock_guard<std::mutex> _{context->mPropLock};
+ context->mSourceDistanceModel = true;
+ UpdateProps(context);
+ }
break;
- case AL_DISTANCE_MODEL:
- value = ALenumFromDistanceModel(context->mDistanceModel);
+ case AL_DEBUG_OUTPUT_EXT:
+ context->mDebugEnabled = true;
break;
- case AL_SPEED_OF_SOUND:
- value = static_cast<ALint64SOFT>(context->mSpeedOfSound);
+ case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
+ context->setError(AL_INVALID_OPERATION, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported");
break;
- case AL_DEFERRED_UPDATES_SOFT:
- if(context->mDeferUpdates)
- value = AL_TRUE;
- break;
+ default:
+ context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
+ }
+}
- case AL_GAIN_LIMIT_SOFT:
- value = static_cast<ALint64SOFT>(GainMixMax/context->mGainBoost);
+AL_API DECL_FUNC1(void, alDisable, ALenum)
+FORCE_ALIGN void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) noexcept
+{
+ switch(capability)
+ {
+ case AL_SOURCE_DISTANCE_MODEL:
+ {
+ std::lock_guard<std::mutex> _{context->mPropLock};
+ context->mSourceDistanceModel = false;
+ UpdateProps(context);
+ }
break;
- case AL_NUM_RESAMPLERS_SOFT:
- value = static_cast<ALint64SOFT>(Resampler::Max) + 1;
+ case AL_DEBUG_OUTPUT_EXT:
+ context->mDebugEnabled = false;
break;
- case AL_DEFAULT_RESAMPLER_SOFT:
- value = static_cast<ALint64SOFT>(ResamplerDefault);
+ case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
+ context->mStopVoicesOnDisconnect = false;
break;
default:
- context->setError(AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
+ context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
}
-
- return value;
}
-END_API_FUNC
-AL_API ALvoid* AL_APIENTRY alGetPointerSOFT(ALenum pname)
-START_API_FUNC
+AL_API DECL_FUNC1(ALboolean, alIsEnabled, ALenum)
+FORCE_ALIGN ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return nullptr;
-
std::lock_guard<std::mutex> _{context->mPropLock};
- void *value{nullptr};
- switch(pname)
+ ALboolean value{AL_FALSE};
+ switch(capability)
{
- case AL_EVENT_CALLBACK_FUNCTION_SOFT:
- value = reinterpret_cast<void*>(context->mEventCb);
+ case AL_SOURCE_DISTANCE_MODEL:
+ value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE;
break;
- case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
- value = context->mEventParam;
+ case AL_DEBUG_OUTPUT_EXT:
+ value = context->mDebugEnabled ? AL_TRUE : AL_FALSE;
+ break;
+
+ case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
+ value = context->mStopVoicesOnDisconnect ? AL_TRUE : AL_FALSE;
break;
default:
- context->setError(AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
+ context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
}
return value;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
-START_API_FUNC
-{
- if(values)
- {
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- case AL_DOPPLER_VELOCITY:
- case AL_DISTANCE_MODEL:
- case AL_SPEED_OF_SOUND:
- case AL_DEFERRED_UPDATES_SOFT:
- case AL_GAIN_LIMIT_SOFT:
- case AL_NUM_RESAMPLERS_SOFT:
- case AL_DEFAULT_RESAMPLER_SOFT:
- values[0] = alGetBoolean(pname);
- return;
- }
- }
+#define DECL_GETFUNC(R, Name, Ext) \
+AL_API R AL_APIENTRY Name##Ext(ALenum pname) noexcept \
+{ \
+ R value{}; \
+ auto context = GetContextRef(); \
+ if(!context) UNLIKELY return value; \
+ Name##vDirect##Ext(GetContextRef().get(), pname, &value); \
+ return value; \
+} \
+FORCE_ALIGN R AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept \
+{ \
+ R value{}; \
+ Name##vDirect##Ext(context, pname, &value); \
+ return value; \
+}
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
+DECL_GETFUNC(ALboolean, alGetBoolean,)
+DECL_GETFUNC(ALdouble, alGetDouble,)
+DECL_GETFUNC(ALfloat, alGetFloat,)
+DECL_GETFUNC(ALint, alGetInteger,)
- if(!values)
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(pname)
- {
- default:
- context->setError(AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
- }
-}
-END_API_FUNC
+DECL_GETFUNC(ALint64SOFT, alGetInteger64,SOFT)
+DECL_GETFUNC(ALvoid*, alGetPointer,SOFT)
-AL_API void AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
-START_API_FUNC
-{
- if(values)
- {
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- case AL_DOPPLER_VELOCITY:
- case AL_DISTANCE_MODEL:
- case AL_SPEED_OF_SOUND:
- case AL_DEFERRED_UPDATES_SOFT:
- case AL_GAIN_LIMIT_SOFT:
- case AL_NUM_RESAMPLERS_SOFT:
- case AL_DEFAULT_RESAMPLER_SOFT:
- values[0] = alGetDouble(pname);
- return;
- }
- }
+#undef DECL_GETFUNC
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
- if(!values)
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(pname)
- {
- default:
- context->setError(AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
- }
+AL_API DECL_FUNC2(void, alGetBooleanv, ALenum, ALboolean*)
+FORCE_ALIGN void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum pname, ALboolean *values) noexcept
+{
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+ GetValue(context, pname, values);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetDoublev, ALenum, ALdouble*)
+FORCE_ALIGN void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum pname, ALdouble *values) noexcept
{
- if(values)
- {
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- case AL_DOPPLER_VELOCITY:
- case AL_DISTANCE_MODEL:
- case AL_SPEED_OF_SOUND:
- case AL_DEFERRED_UPDATES_SOFT:
- case AL_GAIN_LIMIT_SOFT:
- case AL_NUM_RESAMPLERS_SOFT:
- case AL_DEFAULT_RESAMPLER_SOFT:
- values[0] = alGetFloat(pname);
- return;
- }
- }
-
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- if(!values)
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(pname)
- {
- default:
- context->setError(AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
- }
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+ GetValue(context, pname, values);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetFloatv, ALenum, ALfloat*)
+FORCE_ALIGN void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum pname, ALfloat *values) noexcept
{
- if(values)
- {
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- case AL_DOPPLER_VELOCITY:
- case AL_DISTANCE_MODEL:
- case AL_SPEED_OF_SOUND:
- case AL_DEFERRED_UPDATES_SOFT:
- case AL_GAIN_LIMIT_SOFT:
- case AL_NUM_RESAMPLERS_SOFT:
- case AL_DEFAULT_RESAMPLER_SOFT:
- values[0] = alGetInteger(pname);
- return;
- }
- }
-
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- if(!values)
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(pname)
- {
- default:
- context->setError(AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
- }
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+ GetValue(context, pname, values);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
-START_API_FUNC
+AL_API DECL_FUNC2(void, alGetIntegerv, ALenum, ALint*)
+FORCE_ALIGN void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum pname, ALint *values) noexcept
{
- if(values)
- {
- switch(pname)
- {
- case AL_DOPPLER_FACTOR:
- case AL_DOPPLER_VELOCITY:
- case AL_DISTANCE_MODEL:
- case AL_SPEED_OF_SOUND:
- case AL_DEFERRED_UPDATES_SOFT:
- case AL_GAIN_LIMIT_SOFT:
- case AL_NUM_RESAMPLERS_SOFT:
- case AL_DEFAULT_RESAMPLER_SOFT:
- values[0] = alGetInteger64SOFT(pname);
- return;
- }
- }
-
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+ GetValue(context, pname, values);
+}
- if(!values)
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(pname)
- {
- default:
- context->setError(AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
- }
+AL_API DECL_FUNCEXT2(void, alGetInteger64v,SOFT, ALenum, ALint64SOFT*)
+FORCE_ALIGN void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) noexcept
+{
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+ GetValue(context, pname, values);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, ALvoid **values)
-START_API_FUNC
+AL_API DECL_FUNCEXT2(void, alGetPointerv,SOFT, ALenum, ALvoid**)
+FORCE_ALIGN void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, ALvoid **values) noexcept
{
- if(values)
+ if(!values) UNLIKELY
+ return context->setError(AL_INVALID_VALUE, "NULL pointer");
+
+ switch(pname)
{
- switch(pname)
- {
- case AL_EVENT_CALLBACK_FUNCTION_SOFT:
- case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
- values[0] = alGetPointerSOFT(pname);
- return;
- }
- }
+ case AL_EVENT_CALLBACK_FUNCTION_SOFT:
+ *values = al::bit_cast<void*>(context->mEventCb);
+ break;
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
+ case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
+ *values = context->mEventParam;
+ break;
+
+ case AL_DEBUG_CALLBACK_FUNCTION_EXT:
+ *values = al::bit_cast<void*>(context->mDebugCb);
+ break;
+
+ case AL_DEBUG_CALLBACK_USER_PARAM_EXT:
+ *values = context->mDebugParam;
+ break;
- if(!values)
- context->setError(AL_INVALID_VALUE, "NULL pointer");
- else switch(pname)
- {
default:
- context->setError(AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
+ context->setError(AL_INVALID_ENUM, "Invalid context pointer property 0x%04x", pname);
}
}
-END_API_FUNC
-AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
-START_API_FUNC
+AL_API DECL_FUNC1(const ALchar*, alGetString, ALenum)
+FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum pname) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return nullptr;
-
const ALchar *value{nullptr};
switch(pname)
{
@@ -768,7 +500,7 @@ START_API_FUNC
break;
case AL_EXTENSIONS:
- value = context->mExtensionList;
+ value = context->mExtensionsString.c_str();
break;
case AL_NO_ERROR:
@@ -795,112 +527,79 @@ START_API_FUNC
value = alErrOutOfMemory;
break;
+ case AL_STACK_OVERFLOW_EXT:
+ value = alStackOverflow;
+ break;
+
+ case AL_STACK_UNDERFLOW_EXT:
+ value = alStackUnderflow;
+ break;
+
default:
context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
}
return value;
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDopplerFactor(ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC1(void, alDopplerFactor, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(!(value >= 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
else
{
std::lock_guard<std::mutex> _{context->mPropLock};
context->mDopplerFactor = value;
- DO_UPDATEPROPS();
+ UpdateProps(context);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value)
-START_API_FUNC
+AL_API DECL_FUNC1(void, alSpeedOfSound, ALfloat)
+FORCE_ALIGN void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
- if(!(value >= 0.0f && std::isfinite(value)))
- context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
- else
- {
- std::lock_guard<std::mutex> _{context->mPropLock};
- context->mDopplerVelocity = value;
- DO_UPDATEPROPS();
- }
-}
-END_API_FUNC
-
-AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value)
-START_API_FUNC
-{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(!(value > 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
else
{
std::lock_guard<std::mutex> _{context->mPropLock};
context->mSpeedOfSound = value;
- DO_UPDATEPROPS();
+ UpdateProps(context);
}
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDistanceModel(ALenum value)
-START_API_FUNC
+AL_API DECL_FUNC1(void, alDistanceModel, ALenum)
+FORCE_ALIGN void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum value) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
if(auto model = DistanceModelFromALenum(value))
{
std::lock_guard<std::mutex> _{context->mPropLock};
context->mDistanceModel = *model;
if(!context->mSourceDistanceModel)
- DO_UPDATEPROPS();
+ UpdateProps(context);
}
else
context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
}
-END_API_FUNC
-AL_API void AL_APIENTRY alDeferUpdatesSOFT(void)
-START_API_FUNC
+AL_API DECL_FUNCEXT(void, alDeferUpdates,SOFT)
+FORCE_ALIGN void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
context->deferUpdates();
}
-END_API_FUNC
-AL_API void AL_APIENTRY alProcessUpdatesSOFT(void)
-START_API_FUNC
+AL_API DECL_FUNCEXT(void, alProcessUpdates,SOFT)
+FORCE_ALIGN void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return;
-
std::lock_guard<std::mutex> _{context->mPropLock};
context->processUpdates();
}
-END_API_FUNC
-AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
-START_API_FUNC
+AL_API DECL_FUNCEXT2(const ALchar*, alGetStringi,SOFT, ALenum,ALsizei)
+FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) noexcept
{
- ContextRef context{GetContextRef()};
- if(!context) UNLIKELY return nullptr;
-
const ALchar *value{nullptr};
switch(pname)
{
@@ -916,7 +615,28 @@ START_API_FUNC
}
return value;
}
-END_API_FUNC
+
+
+AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept
+{
+ ContextRef context{GetContextRef()};
+ if(!context) UNLIKELY return;
+
+ if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY
+ context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0,
+ DebugSeverity::Medium,
+ "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; "
+ "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)");
+
+ if(!(value >= 0.0f && std::isfinite(value)))
+ context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
+ else
+ {
+ std::lock_guard<std::mutex> _{context->mPropLock};
+ context->mDopplerVelocity = value;
+ UpdateProps(context.get());
+ }
+}
void UpdateContextProps(ALCcontext *context)