update openal-soft to 1.24.3

keeping the alt 87514151c4 (diff-73a8dc1ce58605f6c5ea53548454c3bae516ec5132a29c9d7ff7edf9730c75be)
This commit is contained in:
AzaezelX 2025-09-03 11:09:27 -05:00
parent 12db0500e8
commit ba32094b7b
276 changed files with 49304 additions and 8712 deletions

View file

@ -31,7 +31,6 @@
#include <mutex>
#include <numeric>
#include <stdexcept>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
@ -54,27 +53,27 @@
#include "buffer.h"
#include "core/buffer_storage.h"
#include "core/device.h"
#include "core/except.h"
#include "core/fpu_ctrl.h"
#include "core/logging.h"
#include "direct_defs.h"
#include "effect.h"
#include "error.h"
#include "flexarray.h"
#include "opthelpers.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include "eax/api.h"
#include "eax/call.h"
#include "eax/effect.h"
#include "eax/fx_slot_index.h"
#include "eax/utils.h"
#endif
namespace {
using SubListAllocator = al::allocator<std::array<ALeffectslot,64>>;
EffectStateFactory *getFactoryByType(EffectSlotType type)
[[nodiscard]]
auto getFactoryByType(EffectSlotType type) -> EffectStateFactory*
{
switch(type)
{
@ -98,6 +97,7 @@ EffectStateFactory *getFactoryByType(EffectSlotType type)
}
[[nodiscard]]
auto LookupEffectSlot(ALCcontext *context, ALuint id) noexcept -> ALeffectslot*
{
const size_t lidx{(id-1) >> 6};
@ -111,7 +111,8 @@ auto LookupEffectSlot(ALCcontext *context, ALuint id) noexcept -> ALeffectslot*
return al::to_address(sublist.EffectSlots->begin() + slidx);
}
inline auto LookupEffect(ALCdevice *device, ALuint id) noexcept -> ALeffect*
[[nodiscard]]
inline auto LookupEffect(al::Device *device, ALuint id) noexcept -> ALeffect*
{
const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f};
@ -124,7 +125,8 @@ inline auto LookupEffect(ALCdevice *device, ALuint id) noexcept -> ALeffect*
return al::to_address(sublist.Effects->begin() + slidx);
}
inline auto LookupBuffer(ALCdevice *device, ALuint id) noexcept -> ALbuffer*
[[nodiscard]]
inline auto LookupBuffer(al::Device *device, ALuint id) noexcept -> ALbuffer*
{
const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f};
@ -217,6 +219,7 @@ void RemoveActiveEffectSlots(const al::span<ALeffectslot*> auxslots, ALCcontext
}
[[nodiscard]]
constexpr auto EffectSlotTypeFromEnum(ALenum type) noexcept -> EffectSlotType
{
switch(type)
@ -239,10 +242,11 @@ constexpr auto EffectSlotTypeFromEnum(ALenum type) noexcept -> EffectSlotType
case AL_EFFECT_DEDICATED_DIALOGUE: return EffectSlotType::Dedicated;
case AL_EFFECT_CONVOLUTION_SOFT: return EffectSlotType::Convolution;
}
ERR("Unhandled effect enum: 0x%04x\n", type);
ERR("Unhandled effect enum: {:#04x}", as_unsigned(type));
return EffectSlotType::None;
}
[[nodiscard]]
auto EnsureEffectSlots(ALCcontext *context, size_t needed) noexcept -> bool
try {
size_t count{std::accumulate(context->mEffectSlotList.cbegin(),
@ -267,7 +271,8 @@ catch(...) {
return false;
}
ALeffectslot *AllocEffectSlot(ALCcontext *context)
[[nodiscard]]
auto AllocEffectSlot(ALCcontext *context) -> ALeffectslot*
{
auto sublist = std::find_if(context->mEffectSlotList.begin(), context->mEffectSlotList.end(),
[](const EffectSlotSubList &entry) noexcept -> bool
@ -322,20 +327,21 @@ FORCE_ALIGN void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context
ALuint *effectslots) noexcept
try {
if(n < 0)
throw al::context_error{AL_INVALID_VALUE, "Generating %d effect slots", n};
context->throw_error(AL_INVALID_VALUE, "Generating {} effect slots", n);
if(n <= 0) UNLIKELY return;
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALCdevice *device{context->mALDevice.get()};
auto slotlock = std::lock_guard{context->mEffectSlotLock};
auto *device = context->mALDevice.get();
const al::span eids{effectslots, static_cast<ALuint>(n)};
if(eids.size() > device->AuxiliaryEffectSlotMax-context->mNumEffectSlots)
throw al::context_error{AL_OUT_OF_MEMORY, "Exceeding %u effect slot limit (%u + %d)",
device->AuxiliaryEffectSlotMax, context->mNumEffectSlots, n};
if(context->mNumEffectSlots > device->AuxiliaryEffectSlotMax
|| eids.size() > device->AuxiliaryEffectSlotMax-context->mNumEffectSlots)
context->throw_error(AL_OUT_OF_MEMORY, "Exceeding {} effect slot limit ({} + {})",
device->AuxiliaryEffectSlotMax, context->mNumEffectSlots, n);
if(!EnsureEffectSlots(context, eids.size()))
throw al::context_error{AL_OUT_OF_MEMORY, "Failed to allocate %d effectslot%s", n,
(n == 1) ? "" : "s"};
context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} effectslot{}", n,
(n==1) ? "" : "s");
std::vector<ALeffectslot*> slots;
try {
@ -355,16 +361,18 @@ try {
}
}
catch(std::exception& e) {
ERR("Exception allocating effectslot %zu of %d: %s\n", slots.size()+1, n, e.what());
ERR("Exception allocating effectslot {} of {}: {}", slots.size()+1, n, e.what());
auto delete_effectslot = [context](ALeffectslot *slot) -> void
{ FreeEffectSlot(context, slot); };
std::for_each(slots.begin(), slots.end(), delete_effectslot);
throw al::context_error{AL_INVALID_OPERATION, "Exception allocating %d effectslots: %s", n,
e.what()};
context->throw_error(AL_INVALID_OPERATION, "Exception allocating {} effectslots: {}", n,
e.what());
}
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alDeleteAuxiliaryEffectSlots, ALsizei,n, const ALuint*,effectslots)
@ -372,7 +380,7 @@ FORCE_ALIGN void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *cont
const ALuint *effectslots) noexcept
try {
if(n < 0) UNLIKELY
throw al::context_error{AL_INVALID_VALUE, "Deleting %d effect slots", n};
context->throw_error(AL_INVALID_VALUE, "Deleting {} effect slots", n);
if(n <= 0) UNLIKELY return;
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
@ -380,10 +388,10 @@ try {
{
ALeffectslot *slot{LookupEffectSlot(context, *effectslots)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", *effectslots};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", *effectslots);
if(slot->ref.load(std::memory_order_relaxed) != 0)
throw al::context_error{AL_INVALID_OPERATION, "Deleting in-use effect slot %u",
*effectslots};
context->throw_error(AL_INVALID_OPERATION, "Deleting in-use effect slot {}",
*effectslots);
RemoveActiveEffectSlots({&slot, 1u}, context);
FreeEffectSlot(context, slot);
@ -398,10 +406,9 @@ try {
{
ALeffectslot *slot{LookupEffectSlot(context, eid)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", eid};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", eid);
if(slot->ref.load(std::memory_order_relaxed) != 0)
throw al::context_error{AL_INVALID_OPERATION, "Deleting in-use effect slot %u",
eid};
context->throw_error(AL_INVALID_OPERATION, "Deleting in-use effect slot {}", eid);
return slot;
};
std::transform(eids.cbegin(), eids.cend(), std::back_inserter(slots), lookupslot);
@ -417,8 +424,10 @@ try {
std::for_each(eids.begin(), eids.end(), delete_effectslot);
}
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC1(ALboolean, alIsAuxiliaryEffectSlot, ALuint,effectslot)
@ -436,7 +445,6 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotPlaySOFT not supported");
}
@ -444,7 +452,6 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei, const ALuint*) n
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotPlayvSOFT not supported");
}
@ -452,7 +459,6 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint) noexcept
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotStopSOFT not supported");
}
@ -460,7 +466,6 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei, const ALuint*) n
{
ContextRef context{GetContextRef()};
if(!context) UNLIKELY return;
context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotStopvSOFT not supported");
}
@ -474,7 +479,7 @@ try {
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot) UNLIKELY
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
ALeffectslot *target{};
ALenum err{};
@ -482,20 +487,20 @@ try {
{
case AL_EFFECTSLOT_EFFECT:
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
ALeffect *effect{value ? LookupEffect(device, static_cast<ALuint>(value)) : nullptr};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
auto *effect = value ? LookupEffect(device, static_cast<ALuint>(value)) : nullptr;
if(effect)
err = slot->initEffect(effect->id, effect->type, effect->Props, context);
else
{
if(value != 0)
throw al::context_error{AL_INVALID_VALUE, "Invalid effect ID %u", value};
context->throw_error(AL_INVALID_VALUE, "Invalid effect ID {}", value);
err = slot->initEffect(0, AL_EFFECT_NULL, EffectProps{}, context);
}
}
if(err != AL_NO_ERROR)
throw al::context_error{err, "Effect initialization failed"};
context->throw_error(err, "Effect initialization failed");
if(slot->mState == SlotState::Initial) UNLIKELY
{
@ -511,8 +516,7 @@ try {
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
if(!(value == AL_TRUE || value == AL_FALSE))
throw al::context_error{AL_INVALID_VALUE,
"Effect slot auxiliary send auto out of range"};
context->throw_error(AL_INVALID_VALUE, "Effect slot auxiliary send auto out of range");
if(!(slot->AuxSendAuto == !!value)) LIKELY
{
slot->AuxSendAuto = !!value;
@ -523,7 +527,7 @@ try {
case AL_EFFECTSLOT_TARGET_SOFT:
target = LookupEffectSlot(context, static_cast<ALuint>(value));
if(value && !target)
throw al::context_error{AL_INVALID_VALUE, "Invalid effect slot target ID"};
context->throw_error(AL_INVALID_VALUE, "Invalid effect slot target ID {}", value);
if(slot->Target == target) UNLIKELY
return;
if(target)
@ -532,9 +536,9 @@ try {
while(checker && checker != slot)
checker = checker->Target;
if(checker)
throw al::context_error{AL_INVALID_OPERATION,
"Setting target of effect slot ID %u to %u creates circular chain", slot->id,
target->id};
context->throw_error(AL_INVALID_OPERATION,
"Setting target of effect slot ID {} to {} creates circular chain", slot->id,
target->id);
}
if(ALeffectslot *oldtarget{slot->Target})
@ -569,17 +573,17 @@ try {
assert(factory);
al::intrusive_ptr<EffectState> state{factory->create()};
ALCdevice *device{context->mALDevice.get()};
auto *device = context->mALDevice.get();
auto bufferlock = std::unique_lock{device->BufferLock};
ALbuffer *buffer{};
if(value)
{
buffer = LookupBuffer(device, static_cast<ALuint>(value));
if(!buffer)
throw al::context_error{AL_INVALID_VALUE, "Invalid buffer ID %u", value};
context->throw_error(AL_INVALID_VALUE, "Invalid buffer ID {}", value);
if(buffer->mCallback)
throw al::context_error{AL_INVALID_OPERATION,
"Callback buffer not valid for effects"};
context->throw_error(AL_INVALID_OPERATION,
"Callback buffer not valid for effects");
IncrementRef(buffer->ref);
}
@ -605,17 +609,17 @@ try {
}
else
{
ALCdevice *device{context->mALDevice.get()};
auto *device = context->mALDevice.get();
auto bufferlock = std::unique_lock{device->BufferLock};
ALbuffer *buffer{};
if(value)
{
buffer = LookupBuffer(device, static_cast<ALuint>(value));
if(!buffer)
throw al::context_error{AL_INVALID_VALUE, "Invalid buffer ID %u", value};
context->throw_error(AL_INVALID_VALUE, "Invalid buffer ID {}", value);
if(buffer->mCallback)
throw al::context_error{AL_INVALID_OPERATION,
"Callback buffer not valid for effects"};
context->throw_error(AL_INVALID_OPERATION,
"Callback buffer not valid for effects");
IncrementRef(buffer->ref);
}
@ -633,13 +637,16 @@ try {
return;
case AL_EFFECTSLOT_STATE_SOFT:
throw al::context_error{AL_INVALID_OPERATION, "AL_EFFECTSLOT_STATE_SOFT is read-only"};
context->throw_error(AL_INVALID_OPERATION, "AL_EFFECTSLOT_STATE_SOFT is read-only");
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotiv, ALuint,effectslot, ALenum,param, const ALint*,values)
@ -660,16 +667,15 @@ try {
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotf, ALuint,effectslot, ALenum,param, ALfloat,value)
@ -681,13 +687,13 @@ try {
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
if(!(value >= 0.0f && value <= 1.0f))
throw al::context_error{AL_INVALID_VALUE, "Effect slot gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Effect slot gain {} out of range", value);
if(!(slot->Gain == value)) LIKELY
{
slot->Gain = value;
@ -696,10 +702,13 @@ try {
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotfv, ALuint,effectslot, ALenum,param, const ALfloat*,values)
@ -716,16 +725,15 @@ try {
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -736,7 +744,7 @@ try {
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
@ -767,10 +775,13 @@ try {
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotiv, ALuint,effectslot, ALenum,param, ALint*,values)
@ -791,16 +802,15 @@ try {
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALeffectslot *slot = LookupEffectSlot(context, effectslot);
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotf, ALuint,effectslot, ALenum,param, ALfloat*,value)
@ -810,19 +820,20 @@ try {
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
*value = slot->Gain;
return;
case AL_EFFECTSLOT_GAIN: *value = slot->Gain; return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotfv, ALuint,effectslot, ALenum,param, ALfloat*,values)
@ -839,16 +850,15 @@ try {
std::lock_guard<std::mutex> slotlock{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context, effectslot)};
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot);
switch(param)
{
}
throw al::context_error{AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -890,12 +900,13 @@ ALenum ALeffectslot::initEffect(ALuint effectId, ALenum effectType, const Effect
EffectStateFactory *factory{getFactoryByType(newtype)};
if(!factory)
{
ERR("Failed to find factory for effect slot type %d\n", static_cast<int>(newtype));
ERR("Failed to find factory for effect slot type {}",
int{al::to_underlying(newtype)});
return AL_INVALID_ENUM;
}
al::intrusive_ptr<EffectState> state{factory->create()};
ALCdevice *device{context->mALDevice.get()};
auto *device = context->mALDevice.get();
state->mOutTarget = device->Dry.Buffer;
{
FPUCtl mixer_mode{};
@ -964,7 +975,7 @@ void ALeffectslot::SetName(ALCcontext* context, ALuint id, std::string_view name
auto slot = LookupEffectSlot(context, id);
if(!slot)
throw al::context_error{AL_INVALID_NAME, "Invalid effect slot ID %u", id};
context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", id);
context->mEffectSlotNames.insert_or_assign(id, name);
}
@ -1004,51 +1015,51 @@ EffectSlotSubList::~EffectSlotSubList()
EffectSlots = nullptr;
}
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
void ALeffectslot::eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index)
{
if(index >= EAX_MAX_FXSLOTS)
eax_fail("Index out of range.");
eax_al_context_ = &al_context;
eax_fx_slot_index_ = index;
mEaxALContext = &al_context;
mEaxFXSlotIndex = index;
eax_fx_slot_set_defaults();
eax_effect_ = std::make_unique<EaxEffect>();
if(index == 0) eax_effect_->init<EaxReverbCommitter>();
else if(index == 1) eax_effect_->init<EaxChorusCommitter>();
else eax_effect_->init<EaxNullCommitter>();
mEaxEffect = std::make_unique<EaxEffect>();
if(index == 0) mEaxEffect->init<EaxReverbCommitter>();
else if(index == 1) mEaxEffect->init<EaxChorusCommitter>();
else mEaxEffect->init<EaxNullCommitter>();
}
void ALeffectslot::eax_commit()
{
if(eax_df_ != EaxDirtyFlags{})
if(mEaxDf.any())
{
auto df = EaxDirtyFlags{};
switch(eax_version_)
auto df = std::bitset<eax_dirty_bit_count>{};
switch(mEaxVersion)
{
case 1:
case 2:
case 3:
eax5_fx_slot_commit(eax123_, df);
eax5_fx_slot_commit(mEax123, df);
break;
case 4:
eax4_fx_slot_commit(df);
break;
case 5:
eax5_fx_slot_commit(eax5_, df);
eax5_fx_slot_commit(mEax5, df);
break;
}
eax_df_ = EaxDirtyFlags{};
mEaxDf.reset();
if((df & eax_volume_dirty_bit) != EaxDirtyFlags{})
if(df.test(eax_volume_dirty_bit))
eax_fx_slot_set_volume();
if((df & eax_flags_dirty_bit) != EaxDirtyFlags{})
if(df.test(eax_flags_dirty_bit))
eax_fx_slot_set_flags();
}
if(eax_effect_->commit(eax_version_))
eax_set_efx_slot_effect(*eax_effect_);
if(mEaxEffect->commit(mEaxVersion))
eax_set_efx_slot_effect(*mEaxEffect);
}
[[noreturn]] void ALeffectslot::eax_fail(const char* message)
@ -1111,7 +1122,7 @@ ALenum ALeffectslot::eax_get_efx_effect_type(const GUID& guid)
const GUID& ALeffectslot::eax_get_eax_default_effect_guid() const noexcept
{
switch(eax_fx_slot_index_)
switch(mEaxFXSlotIndex)
{
case 0: return EAX_REVERB_EFFECT;
case 1: return EAX_CHORUS_EFFECT;
@ -1124,7 +1135,7 @@ long ALeffectslot::eax_get_eax_default_lock() const noexcept
return eax4_fx_slot_is_legacy() ? EAXFXSLOT_LOCKED : EAXFXSLOT_UNLOCKED;
}
void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) noexcept
void ALeffectslot::eax4_fx_slot_set_defaults(EAX40FXSLOTPROPERTIES& props) noexcept
{
props.guidLoadEffect = eax_get_eax_default_effect_guid();
props.lVolume = EAXFXSLOT_DEFAULTVOLUME;
@ -1132,7 +1143,7 @@ void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) noexcept
props.ulFlags = EAX40FXSLOT_DEFAULTFLAGS;
}
void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) noexcept
void ALeffectslot::eax5_fx_slot_set_defaults(EAX50FXSLOTPROPERTIES& props) noexcept
{
props.guidLoadEffect = eax_get_eax_default_effect_guid();
props.lVolume = EAXFXSLOT_DEFAULTVOLUME;
@ -1144,14 +1155,14 @@ void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) noexcept
void ALeffectslot::eax_fx_slot_set_defaults()
{
eax5_fx_slot_set_defaults(eax123_.i);
eax4_fx_slot_set_defaults(eax4_.i);
eax5_fx_slot_set_defaults(eax5_.i);
eax_ = eax5_.i;
eax_df_ = EaxDirtyFlags{};
eax5_fx_slot_set_defaults(mEax123.i);
eax4_fx_slot_set_defaults(mEax4.i);
eax5_fx_slot_set_defaults(mEax5.i);
mEax = mEax5.i;
mEaxDf.reset();
}
void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props)
void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const EAX40FXSLOTPROPERTIES& props)
{
switch(call.get_property_id())
{
@ -1175,7 +1186,7 @@ void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props)
}
}
void ALeffectslot::eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props)
void ALeffectslot::eax5_fx_slot_get(const EaxCall& call, const EAX50FXSLOTPROPERTIES& props)
{
switch(call.get_property_id())
{
@ -1209,8 +1220,8 @@ void ALeffectslot::eax_fx_slot_get(const EaxCall& call) const
{
switch(call.get_version())
{
case 4: eax4_fx_slot_get(call, eax4_.i); break;
case 5: eax5_fx_slot_get(call, eax5_.i); break;
case 4: eax4_fx_slot_get(call, mEax4.i); break;
case 5: eax5_fx_slot_get(call, mEax5.i); break;
default: eax_fail_unknown_version();
}
}
@ -1223,7 +1234,7 @@ bool ALeffectslot::eax_get(const EaxCall& call)
eax_fx_slot_get(call);
break;
case EaxCallPropertySetId::fx_slot_effect:
eax_effect_->get(call);
mEaxEffect->get(call);
break;
default:
eax_fail_unknown_property_id();
@ -1236,19 +1247,19 @@ void ALeffectslot::eax_fx_slot_load_effect(int version, ALenum altype)
{
if(!IsValidEffectType(altype))
altype = AL_EFFECT_NULL;
eax_effect_->set_defaults(version, altype);
mEaxEffect->set_defaults(version, altype);
}
void ALeffectslot::eax_fx_slot_set_volume()
{
const auto volume = std::clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME);
const auto volume = std::clamp(mEax.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME);
const auto gain = level_mb_to_gain(static_cast<float>(volume));
eax_set_efx_slot_gain(gain);
}
void ALeffectslot::eax_fx_slot_set_environment_flag()
{
eax_set_efx_slot_send_auto((eax_.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0u);
eax_set_efx_slot_send_auto((mEax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0u);
}
void ALeffectslot::eax_fx_slot_set_flags()
@ -1261,11 +1272,11 @@ void ALeffectslot::eax4_fx_slot_set_all(const EaxCall& call)
eax4_fx_slot_ensure_unlocked();
const auto& src = call.get_value<Exception, const EAX40FXSLOTPROPERTIES>();
Eax4AllValidator{}(src);
auto& dst = eax4_.i;
eax_df_ |= eax_load_effect_dirty_bit; // Always reset the effect.
eax_df_ |= (dst.lVolume != src.lVolume ? eax_volume_dirty_bit : EaxDirtyFlags{});
eax_df_ |= (dst.lLock != src.lLock ? eax_lock_dirty_bit : EaxDirtyFlags{});
eax_df_ |= (dst.ulFlags != src.ulFlags ? eax_flags_dirty_bit : EaxDirtyFlags{});
auto& dst = mEax4.i;
mEaxDf.set(eax_load_effect_dirty_bit); // Always reset the effect.
if(dst.lVolume != src.lVolume) mEaxDf.set(eax_volume_dirty_bit);
if(dst.lLock != src.lLock) mEaxDf.set(eax_lock_dirty_bit);
if(dst.ulFlags != src.ulFlags) mEaxDf.set(eax_flags_dirty_bit);
dst = src;
}
@ -1273,30 +1284,30 @@ void ALeffectslot::eax5_fx_slot_set_all(const EaxCall& call)
{
const auto& src = call.get_value<Exception, const EAX50FXSLOTPROPERTIES>();
Eax5AllValidator{}(src);
auto& dst = eax5_.i;
eax_df_ |= eax_load_effect_dirty_bit; // Always reset the effect.
eax_df_ |= (dst.lVolume != src.lVolume ? eax_volume_dirty_bit : EaxDirtyFlags{});
eax_df_ |= (dst.lLock != src.lLock ? eax_lock_dirty_bit : EaxDirtyFlags{});
eax_df_ |= (dst.ulFlags != src.ulFlags ? eax_flags_dirty_bit : EaxDirtyFlags{});
eax_df_ |= (dst.lOcclusion != src.lOcclusion ? eax_flags_dirty_bit : EaxDirtyFlags{});
eax_df_ |= (dst.flOcclusionLFRatio != src.flOcclusionLFRatio ? eax_flags_dirty_bit : EaxDirtyFlags{});
auto& dst = mEax5.i;
mEaxDf.set(eax_load_effect_dirty_bit); // Always reset the effect.
if(dst.lVolume != src.lVolume) mEaxDf.set(eax_volume_dirty_bit);
if(dst.lLock != src.lLock) mEaxDf.set(eax_lock_dirty_bit);
if(dst.ulFlags != src.ulFlags) mEaxDf.set(eax_flags_dirty_bit);
if(dst.lOcclusion != src.lOcclusion) mEaxDf.set(eax_flags_dirty_bit);
if(dst.flOcclusionLFRatio != src.flOcclusionLFRatio) mEaxDf.set(eax_flags_dirty_bit);
dst = src;
}
bool ALeffectslot::eax_fx_slot_should_update_sources() const noexcept
{
static constexpr auto dirty_bits =
eax_occlusion_dirty_bit |
eax_occlusion_lf_ratio_dirty_bit |
eax_flags_dirty_bit;
return (eax_df_ & dirty_bits) != EaxDirtyFlags{};
static constexpr auto dirty_bits = std::bitset<eax_dirty_bit_count>{
(1u << eax_occlusion_dirty_bit)
| (1u << eax_occlusion_lf_ratio_dirty_bit)
| (1u << eax_flags_dirty_bit)
};
return (mEaxDf & dirty_bits).any();
}
// Returns `true` if all sources should be updated, or `false` otherwise.
bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call)
{
auto& dst = eax4_.i;
auto& dst = mEax4.i;
switch(call.get_property_id())
{
@ -1304,24 +1315,25 @@ bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call)
break;
case EAXFXSLOT_ALLPARAMETERS:
eax4_fx_slot_set_all(call);
if((eax_df_ & eax_load_effect_dirty_bit))
if(mEaxDf.test(eax_load_effect_dirty_bit))
eax_fx_slot_load_effect(4, eax_get_efx_effect_type(dst.guidLoadEffect));
break;
case EAXFXSLOT_LOADEFFECT:
eax4_fx_slot_ensure_unlocked();
eax_fx_slot_set_dirty<Eax4GuidLoadEffectValidator, eax_load_effect_dirty_bit>(call, dst.guidLoadEffect, eax_df_);
if((eax_df_ & eax_load_effect_dirty_bit))
eax_fx_slot_set_dirty<Eax4GuidLoadEffectValidator, eax_load_effect_dirty_bit>(call,
dst.guidLoadEffect, mEaxDf);
if(mEaxDf.test(eax_load_effect_dirty_bit))
eax_fx_slot_load_effect(4, eax_get_efx_effect_type(dst.guidLoadEffect));
break;
case EAXFXSLOT_VOLUME:
eax_fx_slot_set<Eax4VolumeValidator, eax_volume_dirty_bit>(call, dst.lVolume, eax_df_);
eax_fx_slot_set<Eax4VolumeValidator, eax_volume_dirty_bit>(call, dst.lVolume, mEaxDf);
break;
case EAXFXSLOT_LOCK:
eax4_fx_slot_ensure_unlocked();
eax_fx_slot_set<Eax4LockValidator, eax_lock_dirty_bit>(call, dst.lLock, eax_df_);
eax_fx_slot_set<Eax4LockValidator, eax_lock_dirty_bit>(call, dst.lLock, mEaxDf);
break;
case EAXFXSLOT_FLAGS:
eax_fx_slot_set<Eax4FlagsValidator, eax_flags_dirty_bit>(call, dst.ulFlags, eax_df_);
eax_fx_slot_set<Eax4FlagsValidator, eax_flags_dirty_bit>(call, dst.ulFlags, mEaxDf);
break;
default:
eax_fail_unknown_property_id();
@ -1333,7 +1345,7 @@ bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call)
// Returns `true` if all sources should be updated, or `false` otherwise.
bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call)
{
auto& dst = eax5_.i;
auto& dst = mEax5.i;
switch(call.get_property_id())
{
@ -1341,28 +1353,31 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call)
break;
case EAXFXSLOT_ALLPARAMETERS:
eax5_fx_slot_set_all(call);
if((eax_df_ & eax_load_effect_dirty_bit))
if(mEaxDf.test(eax_load_effect_dirty_bit))
eax_fx_slot_load_effect(5, eax_get_efx_effect_type(dst.guidLoadEffect));
break;
case EAXFXSLOT_LOADEFFECT:
eax_fx_slot_set_dirty<Eax4GuidLoadEffectValidator, eax_load_effect_dirty_bit>(call, dst.guidLoadEffect, eax_df_);
if((eax_df_ & eax_load_effect_dirty_bit))
eax_fx_slot_set_dirty<Eax4GuidLoadEffectValidator, eax_load_effect_dirty_bit>(call,
dst.guidLoadEffect, mEaxDf);
if(mEaxDf.test(eax_load_effect_dirty_bit))
eax_fx_slot_load_effect(5, eax_get_efx_effect_type(dst.guidLoadEffect));
break;
case EAXFXSLOT_VOLUME:
eax_fx_slot_set<Eax4VolumeValidator, eax_volume_dirty_bit>(call, dst.lVolume, eax_df_);
eax_fx_slot_set<Eax4VolumeValidator, eax_volume_dirty_bit>(call, dst.lVolume, mEaxDf);
break;
case EAXFXSLOT_LOCK:
eax_fx_slot_set<Eax4LockValidator, eax_lock_dirty_bit>(call, dst.lLock, eax_df_);
eax_fx_slot_set<Eax4LockValidator, eax_lock_dirty_bit>(call, dst.lLock, mEaxDf);
break;
case EAXFXSLOT_FLAGS:
eax_fx_slot_set<Eax5FlagsValidator, eax_flags_dirty_bit>(call, dst.ulFlags, eax_df_);
eax_fx_slot_set<Eax5FlagsValidator, eax_flags_dirty_bit>(call, dst.ulFlags, mEaxDf);
break;
case EAXFXSLOT_OCCLUSION:
eax_fx_slot_set<Eax5OcclusionValidator, eax_occlusion_dirty_bit>(call, dst.lOcclusion, eax_df_);
eax_fx_slot_set<Eax5OcclusionValidator, eax_occlusion_dirty_bit>(call, dst.lOcclusion,
mEaxDf);
break;
case EAXFXSLOT_OCCLUSIONLFRATIO:
eax_fx_slot_set<Eax5OcclusionLfRatioValidator, eax_occlusion_lf_ratio_dirty_bit>(call, dst.flOcclusionLFRatio, eax_df_);
eax_fx_slot_set<Eax5OcclusionLfRatioValidator, eax_occlusion_lf_ratio_dirty_bit>(call,
dst.flOcclusionLFRatio, mEaxDf);
break;
default:
eax_fail_unknown_property_id();
@ -1374,7 +1389,7 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call)
// Returns `true` if all sources should be updated, or `false` otherwise.
bool ALeffectslot::eax_fx_slot_set(const EaxCall& call)
{
switch (call.get_version())
switch(call.get_version())
{
case 4: return eax4_fx_slot_set(call);
case 5: return eax5_fx_slot_set(call);
@ -1390,39 +1405,41 @@ bool ALeffectslot::eax_set(const EaxCall& call)
switch(call.get_property_set_id())
{
case EaxCallPropertySetId::fx_slot: ret = eax_fx_slot_set(call); break;
case EaxCallPropertySetId::fx_slot_effect: eax_effect_->set(call); break;
case EaxCallPropertySetId::fx_slot_effect: mEaxEffect->set(call); break;
default: eax_fail_unknown_property_id();
}
const auto version = call.get_version();
if(eax_version_ != version)
eax_df_ = ~EaxDirtyFlags{};
eax_version_ = version;
if(mEaxVersion != version)
mEaxDf.set();
mEaxVersion = version;
return ret;
}
void ALeffectslot::eax4_fx_slot_commit(EaxDirtyFlags& dst_df)
void ALeffectslot::eax4_fx_slot_commit(std::bitset<eax_dirty_bit_count>& dst_df)
{
eax_fx_slot_commit_property<eax_load_effect_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::guidLoadEffect);
eax_fx_slot_commit_property<eax_volume_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lVolume);
eax_fx_slot_commit_property<eax_lock_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lLock);
eax_fx_slot_commit_property<eax_flags_dirty_bit>(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::ulFlags);
eax_fx_slot_commit_property<eax_load_effect_dirty_bit>(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::guidLoadEffect);
eax_fx_slot_commit_property<eax_volume_dirty_bit>(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::lVolume);
eax_fx_slot_commit_property<eax_lock_dirty_bit>(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::lLock);
eax_fx_slot_commit_property<eax_flags_dirty_bit>(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::ulFlags);
auto& dst_i = eax_;
auto& dst_i = mEax;
if(dst_i.lOcclusion != EAXFXSLOT_DEFAULTOCCLUSION) {
dst_df |= eax_occlusion_dirty_bit;
if(dst_i.lOcclusion != EAXFXSLOT_DEFAULTOCCLUSION)
{
dst_df.set(eax_occlusion_dirty_bit);
dst_i.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION;
}
if(dst_i.flOcclusionLFRatio != EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO) {
dst_df |= eax_occlusion_lf_ratio_dirty_bit;
if(dst_i.flOcclusionLFRatio != EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO)
{
dst_df.set(eax_occlusion_lf_ratio_dirty_bit);
dst_i.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO;
}
}
void ALeffectslot::eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df)
void ALeffectslot::eax5_fx_slot_commit(Eax5State& state, std::bitset<eax_dirty_bit_count>& dst_df)
{
eax_fx_slot_commit_property<eax_load_effect_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::guidLoadEffect);
eax_fx_slot_commit_property<eax_volume_dirty_bit>(state, dst_df, &EAX50FXSLOTPROPERTIES::lVolume);
@ -1437,18 +1454,19 @@ void ALeffectslot::eax_set_efx_slot_effect(EaxEffect &effect)
#define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] "
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.");
mEaxALContext);
if(error != AL_NO_ERROR)
{
ERR(EAX_PREFIX "Failed to initialize an effect.");
return;
}
if(mState == SlotState::Initial) {
if(mState == SlotState::Initial)
{
mPropsDirty = false;
updateProps(eax_al_context_);
updateProps(mEaxALContext);
auto effect_slot_ptr = this;
AddActiveEffectSlots({&effect_slot_ptr, 1}, eax_al_context_);
AddActiveEffectSlots({&effect_slot_ptr, 1}, mEaxALContext);
mState = SlotState::Playing;
return;
}
@ -1474,7 +1492,7 @@ void ALeffectslot::eax_set_efx_slot_gain(ALfloat gain)
if(gain == Gain)
return;
if(gain < 0.0f || gain > 1.0f)
ERR(EAX_PREFIX "Gain out of range (%f)\n", gain);
ERR(EAX_PREFIX "Slot gain out of range ({:f})", gain);
Gain = std::clamp(gain, 0.0f, 1.0f);
mPropsDirty = true;
@ -1484,7 +1502,7 @@ void ALeffectslot::eax_set_efx_slot_gain(ALfloat gain)
void ALeffectslot::EaxDeleter::operator()(ALeffectslot* effect_slot)
{
eax_delete_al_effect_slot(*effect_slot->eax_al_context_, *effect_slot);
eax_delete_al_effect_slot(*effect_slot->mEaxALContext, *effect_slot);
}
EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context)
@ -1494,13 +1512,15 @@ EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context)
std::lock_guard<std::mutex> slotlock{context.mEffectSlotLock};
auto& device = *context.mALDevice;
if(context.mNumEffectSlots == device.AuxiliaryEffectSlotMax) {
ERR(EAX_PREFIX "%s\n", "Out of memory.");
if(context.mNumEffectSlots == device.AuxiliaryEffectSlotMax)
{
ERR(EAX_PREFIX "Out of memory.");
return nullptr;
}
if(!EnsureEffectSlots(&context, 1)) {
ERR(EAX_PREFIX "%s\n", "Failed to ensure.");
if(!EnsureEffectSlots(&context, 1))
{
ERR(EAX_PREFIX "Failed to ensure.");
return nullptr;
}
@ -1517,7 +1537,7 @@ void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot)
if(effect_slot.ref.load(std::memory_order_relaxed) != 0)
{
ERR(EAX_PREFIX "Deleting in-use effect slot %u.\n", effect_slot.id);
ERR(EAX_PREFIX "Deleting in-use effect slot {}.", effect_slot.id);
return;
}

View file

@ -1,8 +1,11 @@
#ifndef AL_AUXEFFECTSLOT_H
#define AL_AUXEFFECTSLOT_H
#include "config.h"
#include <array>
#include <atomic>
#include <bitset>
#include <cstdint>
#include <string_view>
#include <utility>
@ -16,7 +19,7 @@
#include "core/effectslot.h"
#include "intrusive_ptr.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include <memory>
#include "eax/api.h"
#include "eax/call.h"
@ -28,7 +31,7 @@
struct ALbuffer;
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
class EaxFxSlotException : public EaxException {
public:
explicit EaxFxSlotException(const char* message)
@ -50,7 +53,7 @@ struct ALeffectslot {
struct EffectData {
EffectSlotType Type{EffectSlotType::None};
EffectProps Props{};
EffectProps Props;
al::intrusive_ptr<EffectState> State;
};
@ -67,7 +70,7 @@ struct ALeffectslot {
/* Self ID */
ALuint id{};
ALeffectslot(ALCcontext *context);
explicit ALeffectslot(ALCcontext *context);
ALeffectslot(const ALeffectslot&) = delete;
ALeffectslot& operator=(const ALeffectslot&) = delete;
~ALeffectslot();
@ -79,13 +82,14 @@ struct ALeffectslot {
static void SetName(ALCcontext *context, ALuint id, std::string_view name);
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
public:
void eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index);
[[nodiscard]] auto eax_get_index() const noexcept -> EaxFxSlotIndexValue { return eax_fx_slot_index_; }
[[nodiscard]] auto eax_get_eax_fx_slot() const noexcept -> const EAX50FXSLOTPROPERTIES&
{ return eax_; }
[[nodiscard]]
auto eax_get_index() const noexcept -> EaxFxSlotIndexValue { return mEaxFXSlotIndex; }
[[nodiscard]]
auto eax_get_eax_fx_slot() const noexcept -> const EAX50FXSLOTPROPERTIES& { return mEax; }
// Returns `true` if all sources should be updated, or `false` otherwise.
[[nodiscard]] auto eax_dispatch(const EaxCall& call) -> bool
@ -94,25 +98,24 @@ public:
void eax_commit();
private:
static constexpr auto eax_load_effect_dirty_bit = EaxDirtyFlags{1} << 0;
static constexpr auto eax_volume_dirty_bit = EaxDirtyFlags{1} << 1;
static constexpr auto eax_lock_dirty_bit = EaxDirtyFlags{1} << 2;
static constexpr auto eax_flags_dirty_bit = EaxDirtyFlags{1} << 3;
static constexpr auto eax_occlusion_dirty_bit = EaxDirtyFlags{1} << 4;
static constexpr auto eax_occlusion_lf_ratio_dirty_bit = EaxDirtyFlags{1} << 5;
enum {
eax_load_effect_dirty_bit,
eax_volume_dirty_bit,
eax_lock_dirty_bit,
eax_flags_dirty_bit,
eax_occlusion_dirty_bit,
eax_occlusion_lf_ratio_dirty_bit,
eax_dirty_bit_count
};
using Exception = EaxFxSlotException;
using Eax4Props = EAX40FXSLOTPROPERTIES;
struct Eax4State {
Eax4Props i; // Immediate.
EAX40FXSLOTPROPERTIES i; // Immediate.
};
using Eax5Props = EAX50FXSLOTPROPERTIES;
struct Eax5State {
Eax5Props i; // Immediate.
EAX50FXSLOTPROPERTIES i; // Immediate.
};
struct EaxRangeValidator {
@ -237,15 +240,15 @@ private:
}
};
ALCcontext* eax_al_context_{};
EaxFxSlotIndexValue eax_fx_slot_index_{};
int eax_version_{}; // Current EAX version.
EaxDirtyFlags eax_df_{}; // Dirty flags for the current EAX version.
EaxEffectUPtr eax_effect_{};
Eax5State eax123_{}; // EAX1/EAX2/EAX3 state.
Eax4State eax4_{}; // EAX4 state.
Eax5State eax5_{}; // EAX5 state.
Eax5Props eax_{}; // Current EAX state.
ALCcontext* mEaxALContext{};
EaxFxSlotIndexValue mEaxFXSlotIndex{};
int mEaxVersion{}; // Current EAX version.
std::bitset<eax_dirty_bit_count> mEaxDf; // Dirty flags for the current EAX version.
EaxEffectUPtr mEaxEffect;
Eax5State mEax123{}; // EAX1/EAX2/EAX3 state.
Eax4State mEax4{}; // EAX4 state.
Eax5State mEax5{}; // EAX5 state.
EAX50FXSLOTPROPERTIES mEax{}; // Current EAX state.
[[noreturn]] static void eax_fail(const char* message);
[[noreturn]] static void eax_fail_unknown_effect_id();
@ -256,12 +259,14 @@ private:
// validates it,
// sets a dirty flag only if the new value differs form the old one,
// and assigns the new value.
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
static void eax_fx_slot_set(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags)
template<typename TValidator, size_t DirtyBit, typename TProperties>
static void eax_fx_slot_set(const EaxCall& call, TProperties& dst,
std::bitset<eax_dirty_bit_count>& dirty_flags)
{
const auto& src = call.get_value<Exception, const TProperties>();
TValidator{}(src);
dirty_flags |= (dst != src ? TDirtyBit : EaxDirtyFlags{});
if(dst != src)
dirty_flags.set(DirtyBit);
dst = src;
}
@ -269,18 +274,18 @@ private:
// validates it,
// sets a dirty flag without comparing the values,
// and assigns the new value.
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
template<typename TValidator, size_t DirtyBit, typename TProperties>
static void eax_fx_slot_set_dirty(const EaxCall& call, TProperties& dst,
EaxDirtyFlags& dirty_flags)
std::bitset<eax_dirty_bit_count>& dirty_flags)
{
const auto& src = call.get_value<Exception, const TProperties>();
TValidator{}(src);
dirty_flags |= TDirtyBit;
dirty_flags.set(DirtyBit);
dst = src;
}
[[nodiscard]] constexpr auto eax4_fx_slot_is_legacy() const noexcept -> bool
{ return eax_fx_slot_index_ < 2; }
{ return mEaxFXSlotIndex < 2; }
void eax4_fx_slot_ensure_unlocked() const;
@ -288,15 +293,15 @@ private:
[[nodiscard]] auto eax_get_eax_default_effect_guid() const noexcept -> const GUID&;
[[nodiscard]] auto eax_get_eax_default_lock() const noexcept -> long;
void eax4_fx_slot_set_defaults(Eax4Props& props) noexcept;
void eax5_fx_slot_set_defaults(Eax5Props& props) noexcept;
void eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept;
void eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept;
void eax4_fx_slot_set_defaults(EAX40FXSLOTPROPERTIES& props) noexcept;
void eax5_fx_slot_set_defaults(EAX50FXSLOTPROPERTIES& props) noexcept;
void eax4_fx_slot_set_current_defaults(const EAX40FXSLOTPROPERTIES& props) noexcept;
void eax5_fx_slot_set_current_defaults(const EAX50FXSLOTPROPERTIES& props) noexcept;
void eax_fx_slot_set_current_defaults();
void eax_fx_slot_set_defaults();
static void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props);
static void eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props);
static void eax4_fx_slot_get(const EaxCall& call, const EAX40FXSLOTPROPERTIES& props);
static void eax5_fx_slot_get(const EaxCall& call, const EAX50FXSLOTPROPERTIES& props);
void eax_fx_slot_get(const EaxCall& call) const;
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax_get(const EaxCall& call);
@ -321,25 +326,25 @@ private:
bool eax_set(const EaxCall& call);
template<
EaxDirtyFlags TDirtyBit,
size_t DirtyBit,
typename TMemberResult,
typename TProps,
typename TState>
void eax_fx_slot_commit_property(TState& state, EaxDirtyFlags& dst_df,
void eax_fx_slot_commit_property(TState& state, std::bitset<eax_dirty_bit_count>& dst_df,
TMemberResult TProps::*member) noexcept
{
auto& src_i = state.i;
auto& dst_i = eax_;
auto& dst_i = mEax;
if((eax_df_ & TDirtyBit) != EaxDirtyFlags{})
if(mEaxDf.test(DirtyBit))
{
dst_df |= TDirtyBit;
dst_df.set(DirtyBit);
dst_i.*member = src_i.*member;
}
}
void eax4_fx_slot_commit(EaxDirtyFlags& dst_df);
void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df);
void eax4_fx_slot_commit(std::bitset<eax_dirty_bit_count>& dst_df);
void eax5_fx_slot_commit(Eax5State& state, std::bitset<eax_dirty_bit_count>& dst_df);
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)`
void eax_set_efx_slot_effect(EaxEffect &effect);
@ -360,7 +365,7 @@ public:
void UpdateAllEffectSlotProps(ALCcontext *context);
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
using EaxAlEffectSlotUPtr = std::unique_ptr<ALeffectslot, ALeffectslot::EaxDeleter>;
EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context);

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,8 @@
#ifndef AL_BUFFER_H
#define AL_BUFFER_H
#include "config.h"
#include <array>
#include <atomic>
#include <cstddef>
@ -17,7 +19,7 @@
#include "core/buffer_storage.h"
#include "vector.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
enum class EaxStorage : uint8_t {
Automatic,
Accessible,
@ -54,7 +56,7 @@ struct ALbuffer : public BufferStorage {
DISABLE_ALLOC
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
EaxStorage eax_x_ram_mode{EaxStorage::Automatic};
bool eax_x_ram_is_hardware{};
#endif // ALSOFT_EAX

View file

@ -21,18 +21,17 @@
#include "alc/context.h"
#include "alc/device.h"
#include "alc/inprogext.h"
#include "alnumeric.h"
#include "alspan.h"
#include "alstring.h"
#include "auxeffectslot.h"
#include "buffer.h"
#include "core/except.h"
#include "core/logging.h"
#include "core/voice.h"
#include "direct_defs.h"
#include "effect.h"
#include "error.h"
#include "filter.h"
#include "fmt/core.h"
#include "intrusive_ptr.h"
#include "opthelpers.h"
#include "source.h"
@ -45,6 +44,8 @@ DebugGroup::~DebugGroup() = default;
namespace {
using namespace std::string_view_literals;
static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits");
template<typename T, T ...Vals>
@ -109,7 +110,8 @@ constexpr auto GetDebugSourceEnum(DebugSource source) -> ALenum
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))};
throw std::runtime_error{fmt::format("Unexpected debug source value: {}",
int{al::to_underlying(source)})};
}
constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum
@ -126,7 +128,8 @@ constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum
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))};
throw std::runtime_error{fmt::format("Unexpected debug type value: {}",
int{al::to_underlying(type)})};
}
constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum
@ -138,50 +141,51 @@ constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum
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))};
throw std::runtime_error{fmt::format("Unexpected debug severity value: {}",
int{al::to_underlying(severity)})};
}
constexpr auto GetDebugSourceName(DebugSource source) noexcept -> const char*
constexpr auto GetDebugSourceName(DebugSource source) noexcept -> std::string_view
{
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";
case DebugSource::API: return "API"sv;
case DebugSource::System: return "Audio System"sv;
case DebugSource::ThirdParty: return "Third Party"sv;
case DebugSource::Application: return "Application"sv;
case DebugSource::Other: return "Other"sv;
}
return "<invalid source>";
return "<invalid source>"sv;
}
constexpr auto GetDebugTypeName(DebugType type) noexcept -> const char*
constexpr auto GetDebugTypeName(DebugType type) noexcept -> std::string_view
{
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";
case DebugType::Error: return "Error"sv;
case DebugType::DeprecatedBehavior: return "Deprecated Behavior"sv;
case DebugType::UndefinedBehavior: return "Undefined Behavior"sv;
case DebugType::Portability: return "Portability"sv;
case DebugType::Performance: return "Performance"sv;
case DebugType::Marker: return "Marker"sv;
case DebugType::PushGroup: return "Push Group"sv;
case DebugType::PopGroup: return "Pop Group"sv;
case DebugType::Other: return "Other"sv;
}
return "<invalid type>";
return "<invalid type>"sv;
}
constexpr auto GetDebugSeverityName(DebugSeverity severity) noexcept -> const char*
constexpr auto GetDebugSeverityName(DebugSeverity severity) noexcept -> std::string_view
{
switch(severity)
{
case DebugSeverity::High: return "High";
case DebugSeverity::Medium: return "Medium";
case DebugSeverity::Low: return "Low";
case DebugSeverity::Notification: return "Notification";
case DebugSeverity::High: return "High"sv;
case DebugSeverity::Medium: return "Medium"sv;
case DebugSeverity::Low: return "Low"sv;
case DebugSeverity::Notification: return "Notification"sv;
}
return "<invalid severity>";
return "<invalid severity>"sv;
}
} // namespace
@ -195,8 +199,8 @@ void ALCcontext::sendDebugMessage(std::unique_lock<std::mutex> &debuglock, Debug
if(message.length() >= MaxDebugMessageLength) UNLIKELY
{
ERR("Debug message too long (%zu >= %d):\n-> %.*s\n", message.length(),
MaxDebugMessageLength, al::sizei(message), message.data());
ERR("Debug message too long ({} >= {}):\n-> {}", message.length(),
MaxDebugMessageLength, message);
return;
}
@ -231,13 +235,13 @@ void ALCcontext::sendDebugMessage(std::unique_lock<std::mutex> &debuglock, Debug
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",
" Source: {}\n"
" Type: {}\n"
" ID: {}\n"
" Severity: {}\n"
" Message: \"{}\"",
GetDebugSourceName(source), GetDebugTypeName(type), id,
GetDebugSeverityName(severity), al::sizei(message), message.data());
GetDebugSeverityName(severity), message);
}
}
@ -260,32 +264,36 @@ try {
return;
if(!message)
throw al::context_error{AL_INVALID_VALUE, "Null message pointer"};
context->throw_error(AL_INVALID_VALUE, "Null message pointer");
auto msgview = (length < 0) ? std::string_view{message}
: std::string_view{message, static_cast<uint>(length)};
if(msgview.size() >= MaxDebugMessageLength)
throw al::context_error{AL_INVALID_VALUE, "Debug message too long (%zu >= %d)",
msgview.size(), MaxDebugMessageLength};
context->throw_error(AL_INVALID_VALUE, "Debug message too long ({} >= {})", msgview.size(),
MaxDebugMessageLength);
auto dsource = GetDebugSource(source);
if(!dsource)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug source 0x%04x", source};
context->throw_error(AL_INVALID_ENUM, "Invalid debug source {:#04x}", as_unsigned(source));
if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application)
throw al::context_error{AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source};
context->throw_error(AL_INVALID_ENUM, "Debug source {:#04x} not allowed",
as_unsigned(source));
auto dtype = GetDebugType(type);
if(!dtype)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug type 0x%04x", type};
context->throw_error(AL_INVALID_ENUM, "Invalid debug type {:#04x}", as_unsigned(type));
auto dseverity = GetDebugSeverity(severity);
if(!dseverity)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity};
context->throw_error(AL_INVALID_ENUM, "Invalid debug severity {:#04x}",
as_unsigned(severity));
context->debugMessage(*dsource, *dtype, id, *dseverity, msgview);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -296,20 +304,20 @@ try {
if(count > 0)
{
if(!ids)
throw al::context_error{AL_INVALID_VALUE, "IDs is null with non-0 count"};
context->throw_error(AL_INVALID_VALUE, "IDs is null with non-0 count");
if(source == AL_DONT_CARE_EXT)
throw al::context_error{AL_INVALID_OPERATION,
"Debug source cannot be AL_DONT_CARE_EXT with IDs"};
context->throw_error(AL_INVALID_OPERATION,
"Debug source cannot be AL_DONT_CARE_EXT with IDs");
if(type == AL_DONT_CARE_EXT)
throw al::context_error{AL_INVALID_OPERATION,
"Debug type cannot be AL_DONT_CARE_EXT with IDs"};
context->throw_error(AL_INVALID_OPERATION,
"Debug type cannot be AL_DONT_CARE_EXT with IDs");
if(severity != AL_DONT_CARE_EXT)
throw al::context_error{AL_INVALID_OPERATION,
"Debug severity must be AL_DONT_CARE_EXT with IDs"};
context->throw_error(AL_INVALID_OPERATION,
"Debug severity must be AL_DONT_CARE_EXT with IDs");
}
if(enable != AL_TRUE && enable != AL_FALSE)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug enable %d", enable};
context->throw_error(AL_INVALID_ENUM, "Invalid debug enable {}", enable);
static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount};
static constexpr auto Values = make_array_sequence<uint8_t,ElemCount>();
@ -319,7 +327,8 @@ try {
{
auto dsource = GetDebugSource(source);
if(!dsource)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug source 0x%04x", source};
context->throw_error(AL_INVALID_ENUM, "Invalid debug source {:#04x}",
as_unsigned(source));
srcIndices = srcIndices.subspan(al::to_underlying(*dsource), 1);
}
@ -328,7 +337,7 @@ try {
{
auto dtype = GetDebugType(type);
if(!dtype)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug type 0x%04x", type};
context->throw_error(AL_INVALID_ENUM, "Invalid debug type {:#04x}", as_unsigned(type));
typeIndices = typeIndices.subspan(al::to_underlying(*dtype), 1);
}
@ -337,7 +346,8 @@ try {
{
auto dseverity = GetDebugSeverity(severity);
if(!dseverity)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity};
context->throw_error(AL_INVALID_ENUM, "Invalid debug severity {:#04x}",
as_unsigned(severity));
svrIndices = svrIndices.subspan(al::to_underlying(*dseverity), 1);
}
@ -383,8 +393,10 @@ try {
[apply_type](const uint idx){ apply_type(1<<idx); });
}
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -396,23 +408,24 @@ try {
{
size_t newlen{std::strlen(message)};
if(newlen >= MaxDebugMessageLength)
throw al::context_error{AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", newlen,
MaxDebugMessageLength};
context->throw_error(AL_INVALID_VALUE, "Debug message too long ({} >= {})", newlen,
MaxDebugMessageLength);
length = static_cast<ALsizei>(newlen);
}
else if(length >= MaxDebugMessageLength)
throw al::context_error{AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length,
MaxDebugMessageLength};
context->throw_error(AL_INVALID_VALUE, "Debug message too long ({} >= {})", length,
MaxDebugMessageLength);
auto dsource = GetDebugSource(source);
if(!dsource)
throw al::context_error{AL_INVALID_ENUM, "Invalid debug source 0x%04x", source};
context->throw_error(AL_INVALID_ENUM, "Invalid debug source {:#04x}", as_unsigned(source));
if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application)
throw al::context_error{AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source};
context->throw_error(AL_INVALID_ENUM, "Debug source {:#04x} not allowed",
as_unsigned(source));
std::unique_lock<std::mutex> debuglock{context->mDebugCbLock};
if(context->mDebugGroups.size() >= MaxDebugGroupDepth)
throw al::context_error{AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups"};
context->throw_error(AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups");
context->mDebugGroups.emplace_back(*dsource, id,
std::string_view{message, static_cast<uint>(length)});
@ -426,8 +439,10 @@ try {
context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId,
DebugSeverity::Notification, newback.mMessage);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
FORCE_ALIGN DECL_FUNCEXT(void, alPopDebugGroup,EXT)
@ -435,8 +450,7 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexc
try {
std::unique_lock<std::mutex> debuglock{context->mDebugCbLock};
if(context->mDebugGroups.size() <= 1)
throw al::context_error{AL_STACK_UNDERFLOW_EXT,
"Attempting to pop the default debug group"};
context->throw_error(AL_STACK_UNDERFLOW_EXT, "Attempting to pop the default debug group");
DebugGroup &debug = context->mDebugGroups.back();
const auto source = debug.mSource;
@ -448,8 +462,10 @@ try {
context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id,
DebugSeverity::Notification, message);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -458,66 +474,60 @@ FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context
ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities,
ALsizei *lengths, ALchar *logBuf) noexcept
try {
if(logBufSize < 0)
throw al::context_error{AL_INVALID_VALUE, "Negative debug log buffer size"};
if(logBuf && logBufSize < 0)
context->throw_error(AL_INVALID_VALUE, "Negative debug log buffer size");
auto sourcesOut = al::span{sources, sources ? count : 0u};
auto typesOut = al::span{types, types ? count : 0u};
auto idsOut = al::span{ids, ids ? count : 0u};
auto severitiesOut = al::span{severities, severities ? count : 0u};
auto lengthsOut = al::span{lengths, lengths ? count : 0u};
auto logOut = al::span{logBuf, logBuf ? static_cast<ALuint>(logBufSize) : 0u};
const auto sourcesSpan = al::span{sources, sources ? count : 0u};
const auto typesSpan = al::span{types, types ? count : 0u};
const auto idsSpan = al::span{ids, ids ? count : 0u};
const auto severitiesSpan = al::span{severities, severities ? count : 0u};
const auto lengthsSpan = al::span{lengths, lengths ? count : 0u};
const auto logSpan = al::span{logBuf, logBuf ? static_cast<ALuint>(logBufSize) : 0u};
std::lock_guard<std::mutex> debuglock{context->mDebugCbLock};
auto sourceiter = sourcesSpan.begin();
auto typeiter = typesSpan.begin();
auto iditer = idsSpan.begin();
auto severityiter = severitiesSpan.begin();
auto lengthiter = lengthsSpan.begin();
auto logiter = logSpan.begin();
auto debuglock = std::lock_guard{context->mDebugCbLock};
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(logOut.data() != nullptr)
const auto tocopy = size_t{entry.mMessage.size() + 1};
if(al::to_address(logiter) != nullptr)
{
if(logOut.size() < tocopy)
if(static_cast<size_t>(std::distance(logiter, logSpan.end())) < tocopy)
return i;
auto oiter = std::copy(entry.mMessage.cbegin(), entry.mMessage.cend(), logOut.begin());
*oiter = '\0';
logOut = {oiter+1, logOut.end()};
logiter = std::copy(entry.mMessage.cbegin(), entry.mMessage.cend(), logiter);
*(logiter++) = '\0';
}
if(!sourcesOut.empty())
{
sourcesOut.front() = GetDebugSourceEnum(entry.mSource);
sourcesOut = sourcesOut.subspan<1>();
}
if(!typesOut.empty())
{
typesOut.front() = GetDebugTypeEnum(entry.mType);
typesOut = typesOut.subspan<1>();
}
if(!idsOut.empty())
{
idsOut.front() = entry.mId;
idsOut = idsOut.subspan<1>();
}
if(!severitiesOut.empty())
{
severitiesOut.front() = GetDebugSeverityEnum(entry.mSeverity);
severitiesOut = severitiesOut.subspan<1>();
}
if(!lengthsOut.empty())
{
lengthsOut.front() = static_cast<ALsizei>(tocopy);
lengthsOut = lengthsOut.subspan<1>();
}
if(al::to_address(sourceiter) != nullptr)
*(sourceiter++) = GetDebugSourceEnum(entry.mSource);
if(al::to_address(typeiter) != nullptr)
*(typeiter++) = GetDebugTypeEnum(entry.mType);
if(al::to_address(iditer) != nullptr)
*(iditer++) = entry.mId;
if(al::to_address(severityiter) != nullptr)
*(severityiter++) = GetDebugSeverityEnum(entry.mSeverity);
if(al::to_address(lengthiter) != nullptr)
*(lengthiter++) = static_cast<ALsizei>(tocopy);
context->mDebugLog.pop_front();
}
return count;
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
return 0;
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
return 0;
}
@ -526,13 +536,13 @@ FORCE_ALIGN void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum
ALuint name, ALsizei length, const ALchar *label) noexcept
try {
if(!label && length != 0)
throw al::context_error{AL_INVALID_VALUE, "Null label pointer"};
context->throw_error(AL_INVALID_VALUE, "Null label pointer");
auto objname = (length < 0) ? std::string_view{label}
: std::string_view{label, static_cast<uint>(length)};
if(objname.size() >= MaxObjectLabelLength)
throw al::context_error{AL_INVALID_VALUE, "Object label length too long (%zu >= %d)",
objname.size(), MaxObjectLabelLength};
context->throw_error(AL_INVALID_VALUE, "Object label length too long ({} >= {})",
objname.size(), MaxObjectLabelLength);
switch(identifier)
{
@ -543,10 +553,13 @@ try {
case AL_AUXILIARY_EFFECT_SLOT_EXT: ALeffectslot::SetName(context, name, objname); return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier};
context->throw_error(AL_INVALID_ENUM, "Invalid name identifier {:#04x}",
as_unsigned(identifier));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
FORCE_ALIGN DECL_FUNCEXT5(void, alGetObjectLabel,EXT, ALenum,identifier, ALuint,name, ALsizei,bufSize, ALsizei*,length, ALchar*,label)
@ -554,12 +567,12 @@ FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALen
ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) noexcept
try {
if(bufSize < 0)
throw al::context_error{AL_INVALID_VALUE, "Negative label bufSize"};
context->throw_error(AL_INVALID_VALUE, "Negative label bufSize");
if(!label && !length)
throw al::context_error{AL_INVALID_VALUE, "Null length and label"};
context->throw_error(AL_INVALID_VALUE, "Null length and label");
if(label && bufSize == 0)
throw al::context_error{AL_INVALID_VALUE, "Zero label bufSize"};
context->throw_error(AL_INVALID_VALUE, "Zero label bufSize");
const auto labelOut = al::span{label, label ? static_cast<ALuint>(bufSize) : 0u};
auto copy_name = [name,length,labelOut](std::unordered_map<ALuint,std::string> &names)
@ -589,20 +602,20 @@ try {
}
else if(identifier == AL_BUFFER)
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard buflock{device->BufferLock};
auto *device = context->mALDevice.get();
auto buflock = std::lock_guard{device->BufferLock};
copy_name(device->mBufferNames);
}
else if(identifier == AL_FILTER_EXT)
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto buflock = std::lock_guard{device->FilterLock};
copy_name(device->mFilterNames);
}
else if(identifier == AL_EFFECT_EXT)
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto buflock = std::lock_guard{device->EffectLock};
copy_name(device->mEffectNames);
}
else if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT)
@ -611,8 +624,11 @@ try {
copy_name(context->mEffectSlotNames);
}
else
throw al::context_error{AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier};
context->throw_error(AL_INVALID_ENUM, "Invalid name identifier {:#04x}",
as_unsigned(identifier));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}

View file

@ -21,6 +21,8 @@
#include "AL/al.h"
#include "opthelpers.h"
#ifndef _WIN32
using GUID = struct _GUID { /* NOLINT(*-reserved-identifier) */
@ -37,14 +39,16 @@ inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept
{ return !(lhs == rhs); }
#endif // _WIN32
/* TODO: This seems to create very inefficient comparisons. C++20 should allow
* creating default comparison operators, avoiding the need for this.
*/
#define DECL_EQOP(T, ...) \
[[nodiscard]] auto get_members() const noexcept { return std::forward_as_tuple(__VA_ARGS__); } \
[[nodiscard]] friend bool operator==(const T &lhs, const T &rhs) noexcept \
{ return lhs.get_members() == rhs.get_members(); } \
[[nodiscard]] friend bool operator!=(const T &lhs, const T &rhs) noexcept \
{ return !(lhs == rhs); }
{ return lhs.get_members() == rhs.get_members(); } \
[[nodiscard]] friend bool operator!=(const T &lhs, const T &rhs) noexcept { return !(lhs == rhs); }
extern const GUID DSPROPSETID_EAX_ReverbProperties;
DECL_HIDDEN extern const GUID DSPROPSETID_EAX_ReverbProperties;
enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int {
DSPROPERTY_EAX_ALL,
@ -62,7 +66,7 @@ struct EAX_REVERBPROPERTIES {
}; // EAX_REVERBPROPERTIES
extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties;
DECL_HIDDEN extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties;
enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int {
DSPROPERTY_EAXBUFFER_ALL,
@ -78,7 +82,7 @@ constexpr auto EAX_BUFFER_MAXREVERBMIX = 1.0F;
constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F;
extern const GUID DSPROPSETID_EAX20_ListenerProperties;
DECL_HIDDEN extern const GUID DSPROPSETID_EAX20_ListenerProperties;
enum DSPROPERTY_EAX20_LISTENERPROPERTY : unsigned int {
DSPROPERTY_EAX20LISTENER_NONE,
@ -216,7 +220,7 @@ constexpr auto EAX2LISTENER_DEFAULTFLAGS =
EAX2LISTENERFLAGS_DECAYHFLIMIT;
extern const GUID DSPROPSETID_EAX20_BufferProperties;
DECL_HIDDEN extern const GUID DSPROPSETID_EAX20_BufferProperties;
enum DSPROPERTY_EAX20_BUFFERPROPERTY : unsigned int {
DSPROPERTY_EAX20BUFFER_NONE,
@ -252,9 +256,9 @@ struct EAX20BUFFERPROPERTIES {
unsigned long dwFlags; // modifies the behavior of properties
}; // EAX20BUFFERPROPERTIES
extern const GUID DSPROPSETID_EAX30_ListenerProperties;
DECL_HIDDEN extern const GUID DSPROPSETID_EAX30_ListenerProperties;
extern const GUID DSPROPSETID_EAX30_BufferProperties;
DECL_HIDDEN extern const GUID DSPROPSETID_EAX30_BufferProperties;
constexpr auto EAX_MAX_FXSLOTS = 4;
@ -272,31 +276,29 @@ constexpr auto EAXERR_INCOMPATIBLE_SOURCE_TYPE = -5L;
constexpr auto EAXERR_INCOMPATIBLE_EAX_VERSION = -6L;
extern const GUID EAX_NULL_GUID;
DECL_HIDDEN extern const GUID EAX_NULL_GUID;
extern const GUID EAX_PrimaryFXSlotID;
DECL_HIDDEN extern const GUID EAX_PrimaryFXSlotID;
struct EAXVECTOR {
float x;
float y;
float z;
[[nodiscard]]
auto get_members() const noexcept { return std::forward_as_tuple(x, y, z); }
}; // EAXVECTOR
};
[[nodiscard]]
inline bool operator==(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept
{ return lhs.get_members() == rhs.get_members(); }
{ return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; }
[[nodiscard]]
inline bool operator!=(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept
{ return !(lhs == rhs); }
extern const GUID EAXPROPERTYID_EAX40_Context;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_Context;
extern const GUID EAXPROPERTYID_EAX50_Context;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_Context;
// EAX50
constexpr auto HEADPHONES = 0UL;
@ -372,17 +374,17 @@ constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F;
constexpr auto EAXCONTEXT_DEFAULTLASTERROR = EAX_OK;
extern const GUID EAXPROPERTYID_EAX40_FXSlot0;
extern const GUID EAXPROPERTYID_EAX50_FXSlot0;
extern const GUID EAXPROPERTYID_EAX40_FXSlot1;
extern const GUID EAXPROPERTYID_EAX50_FXSlot1;
extern const GUID EAXPROPERTYID_EAX40_FXSlot2;
extern const GUID EAXPROPERTYID_EAX50_FXSlot2;
extern const GUID EAXPROPERTYID_EAX40_FXSlot3;
extern const GUID EAXPROPERTYID_EAX50_FXSlot3;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot0;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot0;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot1;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot1;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot2;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot2;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot3;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot3;
extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
DECL_HIDDEN extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
DECL_HIDDEN extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
enum EAXFXSLOT_PROPERTY : unsigned int {
EAXFXSLOT_PARAMETER = 0,
@ -445,8 +447,8 @@ struct EAX50FXSLOTPROPERTIES : public EAX40FXSLOTPROPERTIES {
float flOcclusionLFRatio;
}; // EAX50FXSLOTPROPERTIES
extern const GUID EAXPROPERTYID_EAX40_Source;
extern const GUID EAXPROPERTYID_EAX50_Source;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_Source;
DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_Source;
// Source object properties
enum EAXSOURCE_PROPERTY : unsigned int {
@ -713,16 +715,16 @@ struct EAXSOURCEEXCLUSIONSENDPROPERTIES {
float flExclusionLFRatio;
}; // EAXSOURCEEXCLUSIONSENDPROPERTIES
extern const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
DECL_HIDDEN extern const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
DECL_HIDDEN extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID;
DECL_HIDDEN extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID;
// EAX Reverb Effect
extern const GUID EAX_REVERB_EFFECT;
DECL_HIDDEN extern const GUID EAX_REVERB_EFFECT;
// Reverb effect properties
enum EAXREVERB_PROPERTY : unsigned int {
@ -959,18 +961,18 @@ constexpr auto EAXREVERB_DEFAULTFLAGS =
using Eax1ReverbPresets = std::array<EAX_REVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>;
extern const Eax1ReverbPresets EAX1REVERB_PRESETS;
DECL_HIDDEN extern const Eax1ReverbPresets EAX1REVERB_PRESETS;
using Eax2ReverbPresets = std::array<EAX20LISTENERPROPERTIES, EAX2_ENVIRONMENT_COUNT>;
extern const Eax2ReverbPresets EAX2REVERB_PRESETS;
DECL_HIDDEN extern const Eax2ReverbPresets EAX2REVERB_PRESETS;
using EaxReverbPresets = std::array<EAXREVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>;
extern const EaxReverbPresets EAXREVERB_PRESETS;
DECL_HIDDEN extern const EaxReverbPresets EAXREVERB_PRESETS;
// AGC Compressor Effect
extern const GUID EAX_AGCCOMPRESSOR_EFFECT;
DECL_HIDDEN extern const GUID EAX_AGCCOMPRESSOR_EFFECT;
enum EAXAGCCOMPRESSOR_PROPERTY : unsigned int {
EAXAGCCOMPRESSOR_NONE,
@ -991,7 +993,7 @@ constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF;
// Autowah Effect
extern const GUID EAX_AUTOWAH_EFFECT;
DECL_HIDDEN extern const GUID EAX_AUTOWAH_EFFECT;
enum EAXAUTOWAH_PROPERTY : unsigned int {
EAXAUTOWAH_NONE,
@ -1030,7 +1032,7 @@ constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L;
// Chorus Effect
extern const GUID EAX_CHORUS_EFFECT;
DECL_HIDDEN extern const GUID EAX_CHORUS_EFFECT;
enum EAXCHORUS_PROPERTY : unsigned int {
EAXCHORUS_NONE,
@ -1086,7 +1088,7 @@ constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F;
// Distortion Effect
extern const GUID EAX_DISTORTION_EFFECT;
DECL_HIDDEN extern const GUID EAX_DISTORTION_EFFECT;
enum EAXDISTORTION_PROPERTY : unsigned int {
EAXDISTORTION_NONE,
@ -1131,7 +1133,7 @@ constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F;
// Echo Effect
extern const GUID EAX_ECHO_EFFECT;
DECL_HIDDEN extern const GUID EAX_ECHO_EFFECT;
enum EAXECHO_PROPERTY : unsigned int {
EAXECHO_NONE,
@ -1176,7 +1178,7 @@ constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F;
// Equalizer Effect
extern const GUID EAX_EQUALIZER_EFFECT;
DECL_HIDDEN extern const GUID EAX_EQUALIZER_EFFECT;
enum EAXEQUALIZER_PROPERTY : unsigned int {
EAXEQUALIZER_NONE,
@ -1252,7 +1254,7 @@ constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F;
// Flanger Effect
extern const GUID EAX_FLANGER_EFFECT;
DECL_HIDDEN extern const GUID EAX_FLANGER_EFFECT;
enum EAXFLANGER_PROPERTY : unsigned int {
EAXFLANGER_NONE,
@ -1308,7 +1310,7 @@ constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F;
// Frequency Shifter Effect
extern const GUID EAX_FREQUENCYSHIFTER_EFFECT;
DECL_HIDDEN extern const GUID EAX_FREQUENCYSHIFTER_EFFECT;
enum EAXFREQUENCYSHIFTER_PROPERTY : unsigned int {
EAXFREQUENCYSHIFTER_NONE,
@ -1347,7 +1349,7 @@ constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_M
// Vocal Morpher Effect
extern const GUID EAX_VOCALMORPHER_EFFECT;
DECL_HIDDEN extern const GUID EAX_VOCALMORPHER_EFFECT;
enum EAXVOCALMORPHER_PROPERTY : unsigned int {
EAXVOCALMORPHER_NONE,
@ -1439,7 +1441,7 @@ constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F;
// Pitch Shifter Effect
extern const GUID EAX_PITCHSHIFTER_EFFECT;
DECL_HIDDEN extern const GUID EAX_PITCHSHIFTER_EFFECT;
enum EAXPITCHSHIFTER_PROPERTY : unsigned int {
EAXPITCHSHIFTER_NONE,
@ -1466,7 +1468,7 @@ constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L;
// Ring Modulator Effect
extern const GUID EAX_RINGMODULATOR_EFFECT;
DECL_HIDDEN extern const GUID EAX_RINGMODULATOR_EFFECT;
enum EAXRINGMODULATOR_PROPERTY : unsigned int {
EAXRINGMODULATOR_NONE,

View file

@ -15,13 +15,8 @@ public:
} // namespace
EaxCall::EaxCall(
EaxCallType type,
const GUID& property_set_guid,
ALuint property_id,
ALuint property_source_id,
ALvoid* property_buffer,
ALuint property_size)
EaxCall::EaxCall(EaxCallType type, const GUID &property_set_guid, ALuint property_id,
ALuint property_source_id, ALvoid *property_buffer, ALuint property_size)
: mCallType{type}, mIsDeferred{(property_id & deferred_flag) != 0}
, mPropertyId{property_id & ~deferred_flag}, mPropertySourceId{property_source_id}
, mPropertyBuffer{property_buffer}, mPropertyBufferSize{property_size}
@ -145,23 +140,34 @@ EaxCall::EaxCall(
fail("Unsupported property set id.");
}
switch(mPropertyId)
if(mPropertySetId == EaxCallPropertySetId::context)
{
case EAXCONTEXT_LASTERROR:
case EAXCONTEXT_SPEAKERCONFIG:
case EAXCONTEXT_EAXSESSION:
case EAXFXSLOT_NONE:
case EAXFXSLOT_ALLPARAMETERS:
case EAXFXSLOT_LOADEFFECT:
case EAXFXSLOT_VOLUME:
case EAXFXSLOT_LOCK:
case EAXFXSLOT_FLAGS:
case EAXFXSLOT_OCCLUSION:
case EAXFXSLOT_OCCLUSIONLFRATIO:
// EAX allow to set "defer" flag on immediate-only properties.
// If we don't clear our flag then "applyAllUpdates" in EAX context won't be called.
mIsDeferred = false;
break;
switch(mPropertyId)
{
case EAXCONTEXT_LASTERROR:
case EAXCONTEXT_SPEAKERCONFIG:
case EAXCONTEXT_EAXSESSION:
// EAX allow to set "defer" flag on immediate-only properties.
// If we don't clear our flag then "applyAllUpdates" in EAX context won't be called.
mIsDeferred = false;
break;
}
}
else if(mPropertySetId == EaxCallPropertySetId::fx_slot)
{
switch(mPropertyId)
{
case EAXFXSLOT_NONE:
case EAXFXSLOT_ALLPARAMETERS:
case EAXFXSLOT_LOADEFFECT:
case EAXFXSLOT_VOLUME:
case EAXFXSLOT_LOCK:
case EAXFXSLOT_FLAGS:
case EAXFXSLOT_OCCLUSION:
case EAXFXSLOT_OCCLUSIONLFRATIO:
mIsDeferred = false;
break;
}
}
if(!mIsDeferred)

View file

@ -1,17 +1,17 @@
#ifndef EAX_EFFECT_INCLUDED
#define EAX_EFFECT_INCLUDED
#include <cassert>
#include <memory>
#include <variant>
#include "alnumeric.h"
#include "AL/al.h"
#include "AL/alext.h"
#include "core/effects/base.h"
#include "call.h"
inline bool EaxTraceCommits{false};
struct EaxEffectErrorMessages {
static constexpr auto unknown_property_id() noexcept { return "Unknown property id."; }
static constexpr auto unknown_version() noexcept { return "Unknown version."; }
@ -123,10 +123,6 @@ template<typename T>
struct EaxCommitter {
struct Exception;
EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops)
: mEaxProps{eaxprops}, mAlProps{alprops}
{ }
EaxEffectProps &mEaxProps;
EffectProps &mAlProps;
@ -141,10 +137,18 @@ struct EaxCommitter {
[[noreturn]] static void fail(const char *message);
[[noreturn]] static void fail_unknown_property_id()
{ fail(EaxEffectErrorMessages::unknown_property_id()); }
private:
EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops)
: mEaxProps{eaxprops}, mAlProps{alprops}
{ }
friend T;
};
struct EaxAutowahCommitter : public EaxCommitter<EaxAutowahCommitter> {
using EaxCommitter<EaxAutowahCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxAutowahCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXAUTOWAHPROPERTIES &props);
@ -153,7 +157,8 @@ struct EaxAutowahCommitter : public EaxCommitter<EaxAutowahCommitter> {
static void Set(const EaxCall &call, EAXAUTOWAHPROPERTIES &props);
};
struct EaxChorusCommitter : public EaxCommitter<EaxChorusCommitter> {
using EaxCommitter<EaxChorusCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxChorusCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXCHORUSPROPERTIES &props);
@ -162,7 +167,8 @@ struct EaxChorusCommitter : public EaxCommitter<EaxChorusCommitter> {
static void Set(const EaxCall &call, EAXCHORUSPROPERTIES &props);
};
struct EaxCompressorCommitter : public EaxCommitter<EaxCompressorCommitter> {
using EaxCommitter<EaxCompressorCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxCompressorCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXAGCCOMPRESSORPROPERTIES &props);
@ -171,7 +177,8 @@ struct EaxCompressorCommitter : public EaxCommitter<EaxCompressorCommitter> {
static void Set(const EaxCall &call, EAXAGCCOMPRESSORPROPERTIES &props);
};
struct EaxDistortionCommitter : public EaxCommitter<EaxDistortionCommitter> {
using EaxCommitter<EaxDistortionCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxDistortionCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXDISTORTIONPROPERTIES &props);
@ -180,7 +187,8 @@ struct EaxDistortionCommitter : public EaxCommitter<EaxDistortionCommitter> {
static void Set(const EaxCall &call, EAXDISTORTIONPROPERTIES &props);
};
struct EaxEchoCommitter : public EaxCommitter<EaxEchoCommitter> {
using EaxCommitter<EaxEchoCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxEchoCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXECHOPROPERTIES &props);
@ -189,7 +197,8 @@ struct EaxEchoCommitter : public EaxCommitter<EaxEchoCommitter> {
static void Set(const EaxCall &call, EAXECHOPROPERTIES &props);
};
struct EaxEqualizerCommitter : public EaxCommitter<EaxEqualizerCommitter> {
using EaxCommitter<EaxEqualizerCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxEqualizerCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXEQUALIZERPROPERTIES &props);
@ -198,7 +207,8 @@ struct EaxEqualizerCommitter : public EaxCommitter<EaxEqualizerCommitter> {
static void Set(const EaxCall &call, EAXEQUALIZERPROPERTIES &props);
};
struct EaxFlangerCommitter : public EaxCommitter<EaxFlangerCommitter> {
using EaxCommitter<EaxFlangerCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxFlangerCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXFLANGERPROPERTIES &props);
@ -207,7 +217,8 @@ struct EaxFlangerCommitter : public EaxCommitter<EaxFlangerCommitter> {
static void Set(const EaxCall &call, EAXFLANGERPROPERTIES &props);
};
struct EaxFrequencyShifterCommitter : public EaxCommitter<EaxFrequencyShifterCommitter> {
using EaxCommitter<EaxFrequencyShifterCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxFrequencyShifterCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXFREQUENCYSHIFTERPROPERTIES &props);
@ -216,7 +227,8 @@ struct EaxFrequencyShifterCommitter : public EaxCommitter<EaxFrequencyShifterCom
static void Set(const EaxCall &call, EAXFREQUENCYSHIFTERPROPERTIES &props);
};
struct EaxModulatorCommitter : public EaxCommitter<EaxModulatorCommitter> {
using EaxCommitter<EaxModulatorCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxModulatorCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXRINGMODULATORPROPERTIES &props);
@ -225,7 +237,8 @@ struct EaxModulatorCommitter : public EaxCommitter<EaxModulatorCommitter> {
static void Set(const EaxCall &call, EAXRINGMODULATORPROPERTIES &props);
};
struct EaxPitchShifterCommitter : public EaxCommitter<EaxPitchShifterCommitter> {
using EaxCommitter<EaxPitchShifterCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxPitchShifterCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXPITCHSHIFTERPROPERTIES &props);
@ -234,7 +247,8 @@ struct EaxPitchShifterCommitter : public EaxCommitter<EaxPitchShifterCommitter>
static void Set(const EaxCall &call, EAXPITCHSHIFTERPROPERTIES &props);
};
struct EaxVocalMorpherCommitter : public EaxCommitter<EaxVocalMorpherCommitter> {
using EaxCommitter<EaxVocalMorpherCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxVocalMorpherCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const EAXVOCALMORPHERPROPERTIES &props);
@ -243,7 +257,8 @@ struct EaxVocalMorpherCommitter : public EaxCommitter<EaxVocalMorpherCommitter>
static void Set(const EaxCall &call, EAXVOCALMORPHERPROPERTIES &props);
};
struct EaxNullCommitter : public EaxCommitter<EaxNullCommitter> {
using EaxCommitter<EaxNullCommitter>::EaxCommitter;
template<typename ...Args>
explicit EaxNullCommitter(Args&& ...args) : EaxCommitter{std::forward<Args>(args)...} { }
bool commit(const std::monostate &props);
@ -279,7 +294,7 @@ public:
~EaxEffect() = default;
ALenum al_effect_type_{AL_EFFECT_NULL};
EffectProps al_effect_props_{};
EffectProps al_effect_props_;
using Props1 = EAX_REVERBPROPERTIES;
using Props2 = EAX20LISTENERPROPERTIES;
@ -308,7 +323,7 @@ public:
int version_{};
bool changed_{};
Props4 props_{};
Props4 props_;
State1 state1_{};
State2 state2_{};
State3 state3_{};

View file

@ -5,7 +5,6 @@
#include <cassert>
#include <exception>
#include "alstring.h"
#include "core/logging.h"
@ -18,9 +17,9 @@ void eax_log_exception(std::string_view message) noexcept
std::rethrow_exception(exception_ptr);
}
catch(const std::exception& ex) {
ERR("%.*s %s\n", al::sizei(message), message.data(), ex.what());
ERR("{} {}", message, ex.what());
}
catch(...) {
ERR("%.*s %s\n", al::sizei(message), message.data(), "Generic exception.");
ERR("{} {}", message, "Generic exception.");
}
}

View file

@ -1,15 +1,11 @@
#ifndef EAX_UTILS_INCLUDED
#define EAX_UTILS_INCLUDED
#include <algorithm>
#include <cstdint>
#include <string>
#include <string_view>
#include <type_traits>
#include "fmt/core.h"
#include "opthelpers.h"
using EaxDirtyFlags = unsigned int;
struct EaxAlLowPassParam {
float gain;
@ -25,71 +21,9 @@ void eax_validate_range(std::string_view value_name, const TValue& value, const
if(value >= min_value && value <= max_value) LIKELY
return;
const auto message =
std::string{value_name} +
" out of range (value: " +
std::to_string(value) + "; min: " +
std::to_string(min_value) + "; max: " +
std::to_string(max_value) + ").";
const auto message = fmt::format("{} out of range (value: {}; min: {}; max: {}).", value_name,
value, min_value, max_value);
throw TException{message.c_str()};
}
namespace detail {
template<typename T>
struct EaxIsBitFieldStruct {
private:
using yes = std::true_type;
using no = std::false_type;
template<typename U>
static auto test(int) -> decltype(std::declval<typename U::EaxIsBitFieldStruct>(), yes{});
template<typename>
static no test(...);
public:
static constexpr auto value = std::is_same<decltype(test<T>(0)), yes>::value;
};
template<typename T, typename TValue>
inline bool eax_bit_fields_are_equal(const T& lhs, const T& rhs) noexcept
{
static_assert(sizeof(T) == sizeof(TValue), "Invalid type size.");
return reinterpret_cast<const TValue&>(lhs) == reinterpret_cast<const TValue&>(rhs);
}
} // namespace detail
template<
typename T,
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
>
inline bool operator==(const T& lhs, const T& rhs) noexcept
{
using Value = std::conditional_t<
sizeof(T) == 1,
std::uint8_t,
std::conditional_t<
sizeof(T) == 2,
std::uint16_t,
std::conditional_t<
sizeof(T) == 4,
std::uint32_t,
void>>>;
static_assert(!std::is_same<Value, void>::value, "Unsupported type.");
return detail::eax_bit_fields_are_equal<T, Value>(lhs, rhs);
}
template<
typename T,
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
>
inline bool operator!=(const T& lhs, const T& rhs) noexcept
{
return !(lhs == rhs);
}
#endif // !EAX_UTILS_INCLUDED

View file

@ -51,9 +51,9 @@
#include "alnumeric.h"
#include "alspan.h"
#include "alstring.h"
#include "core/except.h"
#include "core/logging.h"
#include "direct_defs.h"
#include "error.h"
#include "intrusive_ptr.h"
#include "opthelpers.h"
@ -139,7 +139,8 @@ void InitEffectParams(ALeffect *effect, ALenum type) noexcept
effect->type = type;
}
auto EnsureEffects(ALCdevice *device, size_t needed) noexcept -> bool
[[nodiscard]]
auto EnsureEffects(al::Device *device, size_t needed) noexcept -> bool
try {
size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), 0_uz,
[](size_t cur, const EffectSubList &sublist) noexcept -> size_t
@ -162,7 +163,8 @@ catch(...) {
return false;
}
ALeffect *AllocEffect(ALCdevice *device) noexcept
[[nodiscard]]
auto AllocEffect(al::Device *device) noexcept -> ALeffect*
{
auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(),
[](const EffectSubList &entry) noexcept -> bool
@ -182,7 +184,7 @@ ALeffect *AllocEffect(ALCdevice *device) noexcept
return effect;
}
void FreeEffect(ALCdevice *device, ALeffect *effect)
void FreeEffect(al::Device *device, ALeffect *effect)
{
device->mEffectNames.erase(effect->id);
@ -195,7 +197,8 @@ void FreeEffect(ALCdevice *device, ALeffect *effect)
device->EffectList[lidx].FreeMask |= 1_u64 << slidx;
}
inline auto LookupEffect(ALCdevice *device, ALuint id) noexcept -> ALeffect*
[[nodiscard]] inline
auto LookupEffect(al::Device *device, ALuint id) noexcept -> ALeffect*
{
const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f};
@ -214,21 +217,23 @@ AL_API DECL_FUNC2(void, alGenEffects, ALsizei,n, ALuint*,effects)
FORCE_ALIGN void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) noexcept
try {
if(n < 0)
throw al::context_error{AL_INVALID_VALUE, "Generating %d effects", n};
context->throw_error(AL_INVALID_VALUE, "Generating {} effects", n);
if(n <= 0) UNLIKELY return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
const al::span eids{effects, static_cast<ALuint>(n)};
if(!EnsureEffects(device, eids.size()))
throw al::context_error{AL_OUT_OF_MEMORY, "Failed to allocate %d effect%s", n,
(n == 1) ? "" : "s"};
context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} effect{}", n,
(n==1) ? "" : "s");
std::generate(eids.begin(), eids.end(), [device]{ return AllocEffect(device)->id; });
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alDeleteEffects, ALsizei,n, const ALuint*,effects)
@ -236,11 +241,11 @@ FORCE_ALIGN void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei
const ALuint *effects) noexcept
try {
if(n < 0)
throw al::context_error{AL_INVALID_VALUE, "Deleting %d effects", n};
context->throw_error(AL_INVALID_VALUE, "Deleting {} effects", n);
if(n <= 0) UNLIKELY return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
/* First try to find any effects that are invalid. */
auto validate_effect = [device](const ALuint eid) -> bool
@ -249,7 +254,7 @@ try {
const al::span eids{effects, static_cast<ALuint>(n)};
auto inveffect = std::find_if_not(eids.begin(), eids.end(), validate_effect);
if(inveffect != eids.end())
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", *inveffect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", *inveffect);
/* All good. Delete non-0 effect IDs. */
auto delete_effect = [device](ALuint eid) -> void
@ -259,15 +264,17 @@ try {
};
std::for_each(eids.begin(), eids.end(), delete_effect);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC1(ALboolean, alIsEffect, ALuint,effect)
FORCE_ALIGN ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) noexcept
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
if(!effect || LookupEffect(device, effect))
return AL_TRUE;
return AL_FALSE;
@ -277,12 +284,12 @@ AL_API DECL_FUNC3(void, alEffecti, ALuint,effect, ALenum,param, ALint,value)
FORCE_ALIGN void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param,
ALint value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
switch(param)
{
@ -292,8 +299,8 @@ try {
auto check_effect = [value](const EffectList &item) -> bool
{ return value == item.val && !DisabledEffects.test(item.type); };
if(!std::any_of(gEffectList.cbegin(), gEffectList.cend(), check_effect))
throw al::context_error{AL_INVALID_VALUE, "Effect type 0x%04x not supported",
value};
context->throw_error(AL_INVALID_VALUE, "Effect type {:#04x} not supported",
as_unsigned(value));
}
InitEffectParams(aleffect, value);
@ -301,15 +308,17 @@ try {
}
/* Call the appropriate handler */
std::visit([aleffect,param,value](auto &arg)
std::visit([context,aleffect,param,value](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.SetParami(std::get<PropType>(aleffect->Props), param, value);
return arg.SetParami(context, std::get<PropType>(aleffect->Props), param, value);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alEffectiv, ALuint,effect, ALenum,param, const ALint*,values)
@ -323,81 +332,87 @@ try {
return;
}
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
/* Call the appropriate handler */
std::visit([aleffect,param,values](auto &arg)
std::visit([context,aleffect,param,values](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.SetParamiv(std::get<PropType>(aleffect->Props), param, values);
return arg.SetParamiv(context, std::get<PropType>(aleffect->Props), param, values);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alEffectf, ALuint,effect, ALenum,param, ALfloat,value)
FORCE_ALIGN void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param,
ALfloat value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect) UNLIKELY
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
if(!aleffect)
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
/* Call the appropriate handler */
std::visit([aleffect,param,value](auto &arg)
std::visit([context,aleffect,param,value](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.SetParamf(std::get<PropType>(aleffect->Props), param, value);
return arg.SetParamf(context, std::get<PropType>(aleffect->Props), param, value);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alEffectfv, ALuint,effect, ALenum,param, const ALfloat*,values)
FORCE_ALIGN void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param,
const ALfloat *values) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
/* Call the appropriate handler */
std::visit([aleffect,param,values](auto &arg)
std::visit([context,aleffect,param,values](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.SetParamfv(std::get<PropType>(aleffect->Props), param, values);
return arg.SetParamfv(context, std::get<PropType>(aleffect->Props), param, values);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetEffecti, ALuint,effect, ALenum,param, ALint*,value)
FORCE_ALIGN void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param,
ALint *value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
switch(param)
{
@ -407,15 +422,17 @@ try {
}
/* Call the appropriate handler */
std::visit([aleffect,param,value](auto &arg)
std::visit([context,aleffect,param,value](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.GetParami(std::get<PropType>(aleffect->Props), param, value);
return arg.GetParami(context, std::get<PropType>(aleffect->Props), param, value);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetEffectiv, ALuint,effect, ALenum,param, ALint*,values)
@ -429,69 +446,75 @@ try {
return;
}
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
/* Call the appropriate handler */
std::visit([aleffect,param,values](auto &arg)
std::visit([context,aleffect,param,values](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.GetParamiv(std::get<PropType>(aleffect->Props), param, values);
return arg.GetParamiv(context, std::get<PropType>(aleffect->Props), param, values);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetEffectf, ALuint,effect, ALenum,param, ALfloat*,value)
FORCE_ALIGN void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param,
ALfloat *value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
/* Call the appropriate handler */
std::visit([aleffect,param,value](auto &arg)
std::visit([context,aleffect,param,value](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.GetParamf(std::get<PropType>(aleffect->Props), param, value);
return arg.GetParamf(context, std::get<PropType>(aleffect->Props), param, value);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetEffectfv, ALuint,effect, ALenum,param, ALfloat*,values)
FORCE_ALIGN void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param,
ALfloat *values) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if(!aleffect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", effect};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect);
/* Call the appropriate handler */
std::visit([aleffect,param,values](auto &arg)
std::visit([context,aleffect,param,values](auto &arg)
{
using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
using PropType = typename Type::prop_type;
return arg.GetParamfv(std::get<PropType>(aleffect->Props), param, values);
return arg.GetParamfv(context, std::get<PropType>(aleffect->Props), param, values);
}, aleffect->PropsVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -502,12 +525,12 @@ void InitEffect(ALeffect *effect)
void ALeffect::SetName(ALCcontext* context, ALuint id, std::string_view name)
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> effectlock{device->EffectLock};
auto *device = context->mALDevice.get();
auto effectlock = std::lock_guard{device->EffectLock};
auto effect = LookupEffect(device, id);
if(!effect)
throw al::context_error{AL_INVALID_NAME, "Invalid effect ID %u", id};
context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", id);
device->mEffectNames.insert_or_assign(id, name);
}
@ -673,7 +696,7 @@ void LoadReverbPreset(const std::string_view name, ALeffect *effect)
if(al::case_compare(name, "NONE"sv) == 0)
{
InitEffectParams(effect, AL_EFFECT_NULL);
TRACE("Loading reverb '%s'\n", "NONE");
TRACE("Loading reverb '{}'", "NONE");
return;
}
@ -688,7 +711,7 @@ void LoadReverbPreset(const std::string_view name, ALeffect *effect)
if(al::case_compare(name, std::data(reverbitem.name)) != 0)
continue;
TRACE("Loading reverb '%s'\n", std::data(reverbitem.name));
TRACE("Loading reverb '{}'", std::data(reverbitem.name));
const auto &props = reverbitem.props;
auto &dst = std::get<ReverbProps>(effect->Props);
dst.Density = props.flDensity;
@ -721,7 +744,7 @@ void LoadReverbPreset(const std::string_view name, ALeffect *effect)
return;
}
WARN("Reverb preset '%.*s' not found\n", al::sizei(name), name.data());
WARN("Reverb preset '{}' not found", name);
}
bool IsValidEffectType(ALenum type) noexcept

View file

@ -6,6 +6,7 @@
#include <cstdint>
#include <string_view>
#include <utility>
#include <variant>
#include "AL/al.h"
#include "AL/alc.h"
@ -43,7 +44,7 @@ struct EffectList {
ALuint type;
ALenum val;
};
extern const std::array<EffectList,16> gEffectList;
DECL_HIDDEN extern const std::array<EffectList,16> gEffectList;
using EffectHandlerVariant = std::variant<NullEffectHandler,ReverbEffectHandler,
StdReverbEffectHandler,AutowahEffectHandler,ChorusEffectHandler,CompressorEffectHandler,
@ -56,7 +57,7 @@ struct ALeffect {
ALenum type{AL_EFFECT_NULL};
EffectHandlerVariant PropsVariant;
EffectProps Props{};
EffectProps Props;
/* Self ID */
ALuint id{0u};

View file

@ -4,15 +4,13 @@
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -35,75 +33,68 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps AutowahEffectProps{genDefaultProps()};
void AutowahEffectHandler::SetParami(AutowahProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
void AutowahEffectHandler::SetParamiv(AutowahProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
param};
}
void AutowahEffectHandler::SetParami(ALCcontext *context, AutowahProps&, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer property {:#04x}", as_unsigned(param)); }
void AutowahEffectHandler::SetParamiv(ALCcontext *context, AutowahProps&, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer vector property {:#04x}", as_unsigned(param)); }
void AutowahEffectHandler::SetParamf(AutowahProps &props, ALenum param, float val)
void AutowahEffectHandler::SetParamf(ALCcontext *context, AutowahProps &props, ALenum param, float val)
{
switch(param)
{
case AL_AUTOWAH_ATTACK_TIME:
if(!(val >= AL_AUTOWAH_MIN_ATTACK_TIME && val <= AL_AUTOWAH_MAX_ATTACK_TIME))
throw effect_exception{AL_INVALID_VALUE, "Autowah attack time out of range"};
context->throw_error(AL_INVALID_VALUE, "Autowah attack time out of range");
props.AttackTime = val;
break;
return;
case AL_AUTOWAH_RELEASE_TIME:
if(!(val >= AL_AUTOWAH_MIN_RELEASE_TIME && val <= AL_AUTOWAH_MAX_RELEASE_TIME))
throw effect_exception{AL_INVALID_VALUE, "Autowah release time out of range"};
context->throw_error(AL_INVALID_VALUE, "Autowah release time out of range");
props.ReleaseTime = val;
break;
return;
case AL_AUTOWAH_RESONANCE:
if(!(val >= AL_AUTOWAH_MIN_RESONANCE && val <= AL_AUTOWAH_MAX_RESONANCE))
throw effect_exception{AL_INVALID_VALUE, "Autowah resonance out of range"};
context->throw_error(AL_INVALID_VALUE, "Autowah resonance out of range");
props.Resonance = val;
break;
return;
case AL_AUTOWAH_PEAK_GAIN:
if(!(val >= AL_AUTOWAH_MIN_PEAK_GAIN && val <= AL_AUTOWAH_MAX_PEAK_GAIN))
throw effect_exception{AL_INVALID_VALUE, "Autowah peak gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Autowah peak gain out of range");
props.PeakGain = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
return;
}
}
void AutowahEffectHandler::SetParamfv(AutowahProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void AutowahEffectHandler::GetParami(const AutowahProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
void AutowahEffectHandler::GetParamiv(const AutowahProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid autowah float property {:#04x}",
as_unsigned(param));
}
void AutowahEffectHandler::SetParamfv(ALCcontext *context, AutowahProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void AutowahEffectHandler::GetParamf(const AutowahProps &props, ALenum param, float *val)
void AutowahEffectHandler::GetParami(ALCcontext *context, const AutowahProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer property {:#04x}", as_unsigned(param)); }
void AutowahEffectHandler::GetParamiv(ALCcontext *context, const AutowahProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer vector property {:#04x}", as_unsigned(param)); }
void AutowahEffectHandler::GetParamf(ALCcontext *context, const AutowahProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_AUTOWAH_ATTACK_TIME: *val = props.AttackTime; break;
case AL_AUTOWAH_RELEASE_TIME: *val = props.ReleaseTime; break;
case AL_AUTOWAH_RESONANCE: *val = props.Resonance; break;
case AL_AUTOWAH_PEAK_GAIN: *val = props.PeakGain; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
case AL_AUTOWAH_ATTACK_TIME: *val = props.AttackTime; return;
case AL_AUTOWAH_RELEASE_TIME: *val = props.ReleaseTime; return;
case AL_AUTOWAH_RESONANCE: *val = props.Resonance; return;
case AL_AUTOWAH_PEAK_GAIN: *val = props.PeakGain; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid autowah float property {:#04x}",
as_unsigned(param));
}
void AutowahEffectHandler::GetParamfv(const AutowahProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void AutowahEffectHandler::GetParamfv(ALCcontext *context, const AutowahProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using AutowahCommitter = EaxCommitter<EaxAutowahCommitter>;

View file

@ -7,9 +7,12 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "core/logging.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include <cassert>
#include "al/eax/effect.h"
#include "al/eax/exception.h"
@ -41,7 +44,8 @@ constexpr ALenum EnumFromWaveform(ChorusWaveform type)
case ChorusWaveform::Sinusoid: return AL_CHORUS_WAVEFORM_SINUSOID;
case ChorusWaveform::Triangle: return AL_CHORUS_WAVEFORM_TRIANGLE;
}
throw std::runtime_error{"Invalid chorus waveform: "+std::to_string(static_cast<int>(type))};
throw std::runtime_error{fmt::format("Invalid chorus waveform: {}",
int{al::to_underlying(type)})};
}
constexpr EffectProps genDefaultChorusProps() noexcept
@ -72,7 +76,7 @@ constexpr EffectProps genDefaultFlangerProps() noexcept
const EffectProps ChorusEffectProps{genDefaultChorusProps()};
void ChorusEffectHandler::SetParami(ChorusProps &props, ALenum param, int val)
void ChorusEffectHandler::SetParami(ALCcontext *context, ChorusProps &props, ALenum param, int val)
{
switch(param)
{
@ -80,89 +84,90 @@ void ChorusEffectHandler::SetParami(ChorusProps &props, ALenum param, int val)
if(auto formopt = WaveformFromEnum(val))
props.Waveform = *formopt;
else
throw effect_exception{AL_INVALID_VALUE, "Invalid chorus waveform: 0x%04x", val};
break;
context->throw_error(AL_INVALID_VALUE, "Invalid chorus waveform: {:#04x}",
as_unsigned(val));
return;
case AL_CHORUS_PHASE:
if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
throw effect_exception{AL_INVALID_VALUE, "Chorus phase out of range: %d", val};
context->throw_error(AL_INVALID_VALUE, "Chorus phase out of range: {}", val);
props.Phase = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param};
return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid chorus integer property {:#04x}",
as_unsigned(param));
}
void ChorusEffectHandler::SetParamiv(ChorusProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void ChorusEffectHandler::SetParamf(ChorusProps &props, ALenum param, float val)
void ChorusEffectHandler::SetParamiv(ALCcontext *context, ChorusProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void ChorusEffectHandler::SetParamf(ALCcontext *context, ChorusProps &props, ALenum param, float val)
{
switch(param)
{
case AL_CHORUS_RATE:
if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
throw effect_exception{AL_INVALID_VALUE, "Chorus rate out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Chorus rate out of range: {:f}", val);
props.Rate = val;
break;
return;
case AL_CHORUS_DEPTH:
if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
throw effect_exception{AL_INVALID_VALUE, "Chorus depth out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Chorus depth out of range: {:f}", val);
props.Depth = val;
break;
return;
case AL_CHORUS_FEEDBACK:
if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
throw effect_exception{AL_INVALID_VALUE, "Chorus feedback out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Chorus feedback out of range: {:f}", val);
props.Feedback = val;
break;
return;
case AL_CHORUS_DELAY:
if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
throw effect_exception{AL_INVALID_VALUE, "Chorus delay out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Chorus delay out of range: {:f}", val);
props.Delay = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param};
return;
}
}
void ChorusEffectHandler::SetParamfv(ChorusProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void ChorusEffectHandler::GetParami(const ChorusProps &props, ALenum param, int *val)
context->throw_error(AL_INVALID_ENUM, "Invalid chorus float property {:#04x}",
as_unsigned(param));
}
void ChorusEffectHandler::SetParamfv(ALCcontext *context, ChorusProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void ChorusEffectHandler::GetParami(ALCcontext *context, const ChorusProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_CHORUS_WAVEFORM: *val = EnumFromWaveform(props.Waveform); break;
case AL_CHORUS_PHASE: *val = props.Phase; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param};
case AL_CHORUS_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return;
case AL_CHORUS_PHASE: *val = props.Phase; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid chorus integer property {:#04x}",
as_unsigned(param));
}
void ChorusEffectHandler::GetParamiv(const ChorusProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void ChorusEffectHandler::GetParamf(const ChorusProps &props, ALenum param, float *val)
void ChorusEffectHandler::GetParamiv(ALCcontext *context, const ChorusProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void ChorusEffectHandler::GetParamf(ALCcontext *context, const ChorusProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_CHORUS_RATE: *val = props.Rate; break;
case AL_CHORUS_DEPTH: *val = props.Depth; break;
case AL_CHORUS_FEEDBACK: *val = props.Feedback; break;
case AL_CHORUS_DELAY: *val = props.Delay; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param};
case AL_CHORUS_RATE: *val = props.Rate; return;
case AL_CHORUS_DEPTH: *val = props.Depth; return;
case AL_CHORUS_FEEDBACK: *val = props.Feedback; return;
case AL_CHORUS_DELAY: *val = props.Delay; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid chorus float property {:#04x}",
as_unsigned(param));
}
void ChorusEffectHandler::GetParamfv(const ChorusProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void ChorusEffectHandler::GetParamfv(ALCcontext *context, const ChorusProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
const EffectProps FlangerEffectProps{genDefaultFlangerProps()};
void FlangerEffectHandler::SetParami(ChorusProps &props, ALenum param, int val)
void FlangerEffectHandler::SetParami(ALCcontext *context, ChorusProps &props, ALenum param, int val)
{
switch(param)
{
@ -170,87 +175,88 @@ void FlangerEffectHandler::SetParami(ChorusProps &props, ALenum param, int val)
if(auto formopt = WaveformFromEnum(val))
props.Waveform = *formopt;
else
throw effect_exception{AL_INVALID_VALUE, "Invalid flanger waveform: 0x%04x", val};
break;
context->throw_error(AL_INVALID_VALUE, "Invalid flanger waveform: {:#04x}",
as_unsigned(val));
return;
case AL_FLANGER_PHASE:
if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE))
throw effect_exception{AL_INVALID_VALUE, "Flanger phase out of range: %d", val};
context->throw_error(AL_INVALID_VALUE, "Flanger phase out of range: {}", val);
props.Phase = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param};
return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid flanger integer property {:#04x}",
as_unsigned(param));
}
void FlangerEffectHandler::SetParamiv(ChorusProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void FlangerEffectHandler::SetParamf(ChorusProps &props, ALenum param, float val)
void FlangerEffectHandler::SetParamiv(ALCcontext *context, ChorusProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void FlangerEffectHandler::SetParamf(ALCcontext *context, ChorusProps &props, ALenum param, float val)
{
switch(param)
{
case AL_FLANGER_RATE:
if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE))
throw effect_exception{AL_INVALID_VALUE, "Flanger rate out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Flanger rate out of range: {:f}", val);
props.Rate = val;
break;
return;
case AL_FLANGER_DEPTH:
if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH))
throw effect_exception{AL_INVALID_VALUE, "Flanger depth out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Flanger depth out of range: {:f}", val);
props.Depth = val;
break;
return;
case AL_FLANGER_FEEDBACK:
if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK))
throw effect_exception{AL_INVALID_VALUE, "Flanger feedback out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Flanger feedback out of range: {:f}", val);
props.Feedback = val;
break;
return;
case AL_FLANGER_DELAY:
if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY))
throw effect_exception{AL_INVALID_VALUE, "Flanger delay out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Flanger delay out of range: {:f}", val);
props.Delay = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param};
return;
}
}
void FlangerEffectHandler::SetParamfv(ChorusProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void FlangerEffectHandler::GetParami(const ChorusProps &props, ALenum param, int *val)
context->throw_error(AL_INVALID_ENUM, "Invalid flanger float property {:#04x}",
as_unsigned(param));
}
void FlangerEffectHandler::SetParamfv(ALCcontext *context, ChorusProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void FlangerEffectHandler::GetParami(ALCcontext *context, const ChorusProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_FLANGER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); break;
case AL_FLANGER_PHASE: *val = props.Phase; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param};
case AL_FLANGER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return;
case AL_FLANGER_PHASE: *val = props.Phase; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid flanger integer property {:#04x}",
as_unsigned(param));
}
void FlangerEffectHandler::GetParamiv(const ChorusProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void FlangerEffectHandler::GetParamf(const ChorusProps &props, ALenum param, float *val)
void FlangerEffectHandler::GetParamiv(ALCcontext *context, const ChorusProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void FlangerEffectHandler::GetParamf(ALCcontext *context, const ChorusProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_FLANGER_RATE: *val = props.Rate; break;
case AL_FLANGER_DEPTH: *val = props.Depth; break;
case AL_FLANGER_FEEDBACK: *val = props.Feedback; break;
case AL_FLANGER_DELAY: *val = props.Delay; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param};
case AL_FLANGER_RATE: *val = props.Rate; return;
case AL_FLANGER_DEPTH: *val = props.Depth; return;
case AL_FLANGER_FEEDBACK: *val = props.Feedback; return;
case AL_FLANGER_DELAY: *val = props.Delay; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid flanger float property {:#04x}",
as_unsigned(param));
}
void FlangerEffectHandler::GetParamfv(const ChorusProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void FlangerEffectHandler::GetParamfv(ALCcontext *context, const ChorusProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
struct EaxChorusTraits {
@ -558,6 +564,17 @@ public:
al_props_.Depth = props.flDepth;
al_props_.Feedback = props.flFeedback;
al_props_.Delay = props.flDelay;
if(EaxTraceCommits) UNLIKELY
{
TRACE("Chorus/flanger commit:\n"
" Waveform: {}\n"
" Phase: {}\n"
" Rate: {:f}\n"
" Depth: {:f}\n"
" Feedback: {:f}\n"
" Delay: {:f}", al::to_underlying(al_props_.Waveform), al_props_.Phase,
al_props_.Rate, al_props_.Depth, al_props_.Feedback, al_props_.Delay);
}
return true;
}

View file

@ -4,11 +4,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -28,53 +28,46 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps CompressorEffectProps{genDefaultProps()};
void CompressorEffectHandler::SetParami(CompressorProps &props, ALenum param, int val)
void CompressorEffectHandler::SetParami(ALCcontext *context, CompressorProps &props, ALenum param, int val)
{
switch(param)
{
case AL_COMPRESSOR_ONOFF:
if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF))
throw effect_exception{AL_INVALID_VALUE, "Compressor state out of range"};
context->throw_error(AL_INVALID_VALUE, "Compressor state out of range");
props.OnOff = (val != AL_FALSE);
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
param};
return;
}
}
void CompressorEffectHandler::SetParamiv(CompressorProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void CompressorEffectHandler::SetParamf(CompressorProps&, ALenum param, float)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
void CompressorEffectHandler::SetParamfv(CompressorProps&, ALenum param, const float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
param};
}
void CompressorEffectHandler::GetParami(const CompressorProps &props, ALenum param, int *val)
context->throw_error(AL_INVALID_ENUM, "Invalid compressor integer property {:#04x}",
as_unsigned(param));
}
void CompressorEffectHandler::SetParamiv(ALCcontext *context, CompressorProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void CompressorEffectHandler::SetParamf(ALCcontext *context, CompressorProps&, ALenum param, float)
{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float property {:#04x}", as_unsigned(param)); }
void CompressorEffectHandler::SetParamfv(ALCcontext *context, CompressorProps&, ALenum param, const float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float-vector property {:#04x}", as_unsigned(param)); }
void CompressorEffectHandler::GetParami(ALCcontext *context, const CompressorProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_COMPRESSOR_ONOFF: *val = props.OnOff; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
param};
case AL_COMPRESSOR_ONOFF: *val = props.OnOff; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid compressor integer property {:#04x}",
as_unsigned(param));
}
void CompressorEffectHandler::GetParamiv(const CompressorProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void CompressorEffectHandler::GetParamf(const CompressorProps&, ALenum param, float*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
void CompressorEffectHandler::GetParamfv(const CompressorProps&, ALenum param, float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
param};
}
void CompressorEffectHandler::GetParamiv(ALCcontext *context, const CompressorProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void CompressorEffectHandler::GetParamf(ALCcontext *context, const CompressorProps&, ALenum param, float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float property {:#04x}", as_unsigned(param)); }
void CompressorEffectHandler::GetParamfv(ALCcontext *context, const CompressorProps&, ALenum param, float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float-vector property {:#04x}", as_unsigned(param)); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using CompressorCommitter = EaxCommitter<EaxCompressorCommitter>;

View file

@ -7,10 +7,10 @@
#include "AL/al.h"
#include "alc/context.h"
#include "alc/inprogext.h"
#include "alnumeric.h"
#include "alspan.h"
#include "core/effects/base.h"
#include "effects.h"
@ -28,90 +28,49 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps ConvolutionEffectProps{genDefaultProps()};
void ConvolutionEffectHandler::SetParami(ConvolutionProps& /*props*/, ALenum param, int /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid convolution effect integer property 0x%04x",
param};
}
}
void ConvolutionEffectHandler::SetParamiv(ConvolutionProps &props, ALenum param, const int *vals)
{
switch(param)
{
default:
SetParami(props, param, *vals);
}
}
void ConvolutionEffectHandler::SetParamf(ConvolutionProps& /*props*/, ALenum param, float /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid convolution effect float property 0x%04x",
param};
}
}
void ConvolutionEffectHandler::SetParamfv(ConvolutionProps &props, ALenum param, const float *values)
void ConvolutionEffectHandler::SetParami(ALCcontext *context, ConvolutionProps& /*props*/, ALenum param, int /*val*/)
{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect integer property {:#04x}", as_unsigned(param)); }
void ConvolutionEffectHandler::SetParamiv(ALCcontext *context, ConvolutionProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void ConvolutionEffectHandler::SetParamf(ALCcontext *context, ConvolutionProps& /*props*/, ALenum param, float /*val*/)
{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect float property {:#04x}", as_unsigned(param)); }
void ConvolutionEffectHandler::SetParamfv(ALCcontext *context, ConvolutionProps &props, ALenum param, const float *values)
{
static constexpr auto finite_checker = [](float val) -> bool { return std::isfinite(val); };
al::span<const float> vals;
switch(param)
{
case AL_CONVOLUTION_ORIENTATION_SOFT:
vals = {values, 6_uz};
auto vals = al::span{values, 6_uz};
if(!std::all_of(vals.cbegin(), vals.cend(), finite_checker))
throw effect_exception{AL_INVALID_VALUE, "Property 0x%04x value out of range", param};
context->throw_error(AL_INVALID_VALUE, "Convolution orientation out of range", param);
std::copy_n(vals.cbegin(), props.OrientAt.size(), props.OrientAt.begin());
std::copy_n(vals.cbegin()+3, props.OrientUp.size(), props.OrientUp.begin());
break;
default:
SetParamf(props, param, *values);
return;
}
SetParamf(context, props, param, *values);
}
void ConvolutionEffectHandler::GetParami(const ConvolutionProps& /*props*/, ALenum param, int* /*val*/)
void ConvolutionEffectHandler::GetParami(ALCcontext *context, const ConvolutionProps& /*props*/, ALenum param, int* /*val*/)
{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect integer property {:#04x}", as_unsigned(param)); }
void ConvolutionEffectHandler::GetParamiv(ALCcontext *context, const ConvolutionProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void ConvolutionEffectHandler::GetParamf(ALCcontext *context, const ConvolutionProps& /*props*/, ALenum param, float* /*val*/)
{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect float property {:#04x}", as_unsigned(param)); }
void ConvolutionEffectHandler::GetParamfv(ALCcontext *context, const ConvolutionProps &props, ALenum param, float *values)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid convolution effect integer property 0x%04x",
param};
}
}
void ConvolutionEffectHandler::GetParamiv(const ConvolutionProps &props, ALenum param, int *vals)
{
switch(param)
{
default:
GetParami(props, param, vals);
}
}
void ConvolutionEffectHandler::GetParamf(const ConvolutionProps& /*props*/, ALenum param, float* /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid convolution effect float property 0x%04x",
param};
}
}
void ConvolutionEffectHandler::GetParamfv(const ConvolutionProps &props, ALenum param, float *values)
{
al::span<float> vals;
switch(param)
{
case AL_CONVOLUTION_ORIENTATION_SOFT:
vals = {values, 6_uz};
auto vals = al::span{values, 6_uz};
std::copy(props.OrientAt.cbegin(), props.OrientAt.cend(), vals.begin());
std::copy(props.OrientUp.cbegin(), props.OrientUp.cend(), vals.begin()+3);
break;
default:
GetParamf(props, param, values);
return;
}
GetParamf(context, props, param, values);
}

View file

@ -6,7 +6,8 @@
#include "AL/al.h"
#include "AL/alext.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
@ -32,91 +33,81 @@ constexpr EffectProps genDefaultLfeProps() noexcept
const EffectProps DedicatedDialogEffectProps{genDefaultDialogProps()};
void DedicatedDialogEffectHandler::SetParami(DedicatedProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void DedicatedDialogEffectHandler::SetParamiv(DedicatedProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x",
param};
}
void DedicatedDialogEffectHandler::SetParamf(DedicatedProps &props, ALenum param, float val)
void DedicatedDialogEffectHandler::SetParami(ALCcontext *context, DedicatedProps&, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); }
void DedicatedDialogEffectHandler::SetParamiv(ALCcontext *context, DedicatedProps&, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); }
void DedicatedDialogEffectHandler::SetParamf(ALCcontext *context, DedicatedProps &props, ALenum param, float val)
{
switch(param)
{
case AL_DEDICATED_GAIN:
if(!(val >= 0.0f && std::isfinite(val)))
throw effect_exception{AL_INVALID_VALUE, "Dedicated gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Dedicated gain out of range");
props.Gain = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param};
return;
}
}
void DedicatedDialogEffectHandler::SetParamfv(DedicatedProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void DedicatedDialogEffectHandler::GetParami(const DedicatedProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void DedicatedDialogEffectHandler::GetParamiv(const DedicatedProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}",
as_unsigned(param));
}
void DedicatedDialogEffectHandler::GetParamf(const DedicatedProps &props, ALenum param, float *val)
void DedicatedDialogEffectHandler::SetParamfv(ALCcontext *context, DedicatedProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void DedicatedDialogEffectHandler::GetParami(ALCcontext *context, const DedicatedProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); }
void DedicatedDialogEffectHandler::GetParamiv(ALCcontext *context, const DedicatedProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); }
void DedicatedDialogEffectHandler::GetParamf(ALCcontext *context, const DedicatedProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_DEDICATED_GAIN: *val = props.Gain; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param};
case AL_DEDICATED_GAIN: *val = props.Gain; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}",
as_unsigned(param));
}
void DedicatedDialogEffectHandler::GetParamfv(const DedicatedProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void DedicatedDialogEffectHandler::GetParamfv(ALCcontext *context, const DedicatedProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
const EffectProps DedicatedLfeEffectProps{genDefaultLfeProps()};
void DedicatedLfeEffectHandler::SetParami(DedicatedProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void DedicatedLfeEffectHandler::SetParamiv(DedicatedProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x",
param};
}
void DedicatedLfeEffectHandler::SetParamf(DedicatedProps &props, ALenum param, float val)
void DedicatedLfeEffectHandler::SetParami(ALCcontext *context, DedicatedProps&, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); }
void DedicatedLfeEffectHandler::SetParamiv(ALCcontext *context, DedicatedProps&, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); }
void DedicatedLfeEffectHandler::SetParamf(ALCcontext *context, DedicatedProps &props, ALenum param, float val)
{
switch(param)
{
case AL_DEDICATED_GAIN:
if(!(val >= 0.0f && std::isfinite(val)))
throw effect_exception{AL_INVALID_VALUE, "Dedicated gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Dedicated gain out of range");
props.Gain = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param};
return;
}
}
void DedicatedLfeEffectHandler::SetParamfv(DedicatedProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void DedicatedLfeEffectHandler::GetParami(const DedicatedProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void DedicatedLfeEffectHandler::GetParamiv(const DedicatedProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}",
as_unsigned(param));
}
void DedicatedLfeEffectHandler::GetParamf(const DedicatedProps &props, ALenum param, float *val)
void DedicatedLfeEffectHandler::SetParamfv(ALCcontext *context, DedicatedProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void DedicatedLfeEffectHandler::GetParami(ALCcontext *context, const DedicatedProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); }
void DedicatedLfeEffectHandler::GetParamiv(ALCcontext *context, const DedicatedProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); }
void DedicatedLfeEffectHandler::GetParamf(ALCcontext *context, const DedicatedProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_DEDICATED_GAIN: *val = props.Gain; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param};
case AL_DEDICATED_GAIN: *val = props.Gain; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}",
as_unsigned(param));
}
void DedicatedLfeEffectHandler::GetParamfv(const DedicatedProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void DedicatedLfeEffectHandler::GetParamfv(ALCcontext *context, const DedicatedProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }

View file

@ -4,11 +4,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -32,80 +32,76 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps DistortionEffectProps{genDefaultProps()};
void DistortionEffectHandler::SetParami(DistortionProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; }
void DistortionEffectHandler::SetParamiv(DistortionProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x",
param};
}
void DistortionEffectHandler::SetParamf(DistortionProps &props, ALenum param, float val)
void DistortionEffectHandler::SetParami(ALCcontext *context, DistortionProps&, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer property {:#04x}", as_unsigned(param)); }
void DistortionEffectHandler::SetParamiv(ALCcontext *context, DistortionProps&, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer-vector property {:#04x}", as_unsigned(param)); }
void DistortionEffectHandler::SetParamf(ALCcontext *context, DistortionProps &props, ALenum param, float val)
{
switch(param)
{
case AL_DISTORTION_EDGE:
if(!(val >= AL_DISTORTION_MIN_EDGE && val <= AL_DISTORTION_MAX_EDGE))
throw effect_exception{AL_INVALID_VALUE, "Distortion edge out of range"};
context->throw_error(AL_INVALID_VALUE, "Distortion edge out of range");
props.Edge = val;
break;
return;
case AL_DISTORTION_GAIN:
if(!(val >= AL_DISTORTION_MIN_GAIN && val <= AL_DISTORTION_MAX_GAIN))
throw effect_exception{AL_INVALID_VALUE, "Distortion gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Distortion gain out of range");
props.Gain = val;
break;
return;
case AL_DISTORTION_LOWPASS_CUTOFF:
if(!(val >= AL_DISTORTION_MIN_LOWPASS_CUTOFF && val <= AL_DISTORTION_MAX_LOWPASS_CUTOFF))
throw effect_exception{AL_INVALID_VALUE, "Distortion low-pass cutoff out of range"};
context->throw_error(AL_INVALID_VALUE, "Distortion low-pass cutoff out of range");
props.LowpassCutoff = val;
break;
return;
case AL_DISTORTION_EQCENTER:
if(!(val >= AL_DISTORTION_MIN_EQCENTER && val <= AL_DISTORTION_MAX_EQCENTER))
throw effect_exception{AL_INVALID_VALUE, "Distortion EQ center out of range"};
context->throw_error(AL_INVALID_VALUE, "Distortion EQ center out of range");
props.EQCenter = val;
break;
return;
case AL_DISTORTION_EQBANDWIDTH:
if(!(val >= AL_DISTORTION_MIN_EQBANDWIDTH && val <= AL_DISTORTION_MAX_EQBANDWIDTH))
throw effect_exception{AL_INVALID_VALUE, "Distortion EQ bandwidth out of range"};
context->throw_error(AL_INVALID_VALUE, "Distortion EQ bandwidth out of range");
props.EQBandwidth = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param};
return;
}
}
void DistortionEffectHandler::SetParamfv(DistortionProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void DistortionEffectHandler::GetParami(const DistortionProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; }
void DistortionEffectHandler::GetParamiv(const DistortionProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid distortion float property {:#04x}",
as_unsigned(param));
}
void DistortionEffectHandler::GetParamf(const DistortionProps &props, ALenum param, float *val)
void DistortionEffectHandler::SetParamfv(ALCcontext *context, DistortionProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void DistortionEffectHandler::GetParami(ALCcontext *context, const DistortionProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer property {:#04x}", as_unsigned(param)); }
void DistortionEffectHandler::GetParamiv(ALCcontext *context, const DistortionProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer-vector property {:#04x}", as_unsigned(param)); }
void DistortionEffectHandler::GetParamf(ALCcontext *context, const DistortionProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_DISTORTION_EDGE: *val = props.Edge; break;
case AL_DISTORTION_GAIN: *val = props.Gain; break;
case AL_DISTORTION_LOWPASS_CUTOFF: *val = props.LowpassCutoff; break;
case AL_DISTORTION_EQCENTER: *val = props.EQCenter; break;
case AL_DISTORTION_EQBANDWIDTH: *val = props.EQBandwidth; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param};
case AL_DISTORTION_EDGE: *val = props.Edge; return;
case AL_DISTORTION_GAIN: *val = props.Gain; return;
case AL_DISTORTION_LOWPASS_CUTOFF: *val = props.LowpassCutoff; return;
case AL_DISTORTION_EQCENTER: *val = props.EQCenter; return;
case AL_DISTORTION_EQBANDWIDTH: *val = props.EQBandwidth; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid distortion float property {:#04x}",
as_unsigned(param));
}
void DistortionEffectHandler::GetParamfv(const DistortionProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void DistortionEffectHandler::GetParamfv(ALCcontext *context, const DistortionProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using DistortionCommitter = EaxCommitter<EaxDistortionCommitter>;

View file

@ -4,11 +4,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -35,74 +35,74 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps EchoEffectProps{genDefaultProps()};
void EchoEffectHandler::SetParami(EchoProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
void EchoEffectHandler::SetParamiv(EchoProps&, ALenum param, const int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; }
void EchoEffectHandler::SetParamf(EchoProps &props, ALenum param, float val)
void EchoEffectHandler::SetParami(ALCcontext *context, EchoProps&, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer property {:#04x}", as_unsigned(param)); }
void EchoEffectHandler::SetParamiv(ALCcontext *context, EchoProps&, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer-vector property {:#04x}", as_unsigned(param)); }
void EchoEffectHandler::SetParamf(ALCcontext *context, EchoProps &props, ALenum param, float val)
{
switch(param)
{
case AL_ECHO_DELAY:
if(!(val >= AL_ECHO_MIN_DELAY && val <= AL_ECHO_MAX_DELAY))
throw effect_exception{AL_INVALID_VALUE, "Echo delay out of range"};
context->throw_error(AL_INVALID_VALUE, "Echo delay out of range");
props.Delay = val;
break;
return;
case AL_ECHO_LRDELAY:
if(!(val >= AL_ECHO_MIN_LRDELAY && val <= AL_ECHO_MAX_LRDELAY))
throw effect_exception{AL_INVALID_VALUE, "Echo LR delay out of range"};
context->throw_error(AL_INVALID_VALUE, "Echo LR delay out of range");
props.LRDelay = val;
break;
return;
case AL_ECHO_DAMPING:
if(!(val >= AL_ECHO_MIN_DAMPING && val <= AL_ECHO_MAX_DAMPING))
throw effect_exception{AL_INVALID_VALUE, "Echo damping out of range"};
context->throw_error(AL_INVALID_VALUE, "Echo damping out of range");
props.Damping = val;
break;
return;
case AL_ECHO_FEEDBACK:
if(!(val >= AL_ECHO_MIN_FEEDBACK && val <= AL_ECHO_MAX_FEEDBACK))
throw effect_exception{AL_INVALID_VALUE, "Echo feedback out of range"};
context->throw_error(AL_INVALID_VALUE, "Echo feedback out of range");
props.Feedback = val;
break;
return;
case AL_ECHO_SPREAD:
if(!(val >= AL_ECHO_MIN_SPREAD && val <= AL_ECHO_MAX_SPREAD))
throw effect_exception{AL_INVALID_VALUE, "Echo spread out of range"};
context->throw_error(AL_INVALID_VALUE, "Echo spread out of range");
props.Spread = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param};
return;
}
}
void EchoEffectHandler::SetParamfv(EchoProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EchoEffectHandler::GetParami(const EchoProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
void EchoEffectHandler::GetParamiv(const EchoProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; }
void EchoEffectHandler::GetParamf(const EchoProps &props, ALenum param, float *val)
context->throw_error(AL_INVALID_ENUM, "Invalid echo float property {:#04x}",
as_unsigned(param));
}
void EchoEffectHandler::SetParamfv(ALCcontext *context, EchoProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void EchoEffectHandler::GetParami(ALCcontext *context, const EchoProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer property {:#04x}", as_unsigned(param)); }
void EchoEffectHandler::GetParamiv(ALCcontext *context, const EchoProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer-vector property {:#04x}", as_unsigned(param)); }
void EchoEffectHandler::GetParamf(ALCcontext *context, const EchoProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_ECHO_DELAY: *val = props.Delay; break;
case AL_ECHO_LRDELAY: *val = props.LRDelay; break;
case AL_ECHO_DAMPING: *val = props.Damping; break;
case AL_ECHO_FEEDBACK: *val = props.Feedback; break;
case AL_ECHO_SPREAD: *val = props.Spread; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param};
case AL_ECHO_DELAY: *val = props.Delay; return;
case AL_ECHO_LRDELAY: *val = props.LRDelay; return;
case AL_ECHO_DAMPING: *val = props.Damping; return;
case AL_ECHO_FEEDBACK: *val = props.Feedback; return;
case AL_ECHO_SPREAD: *val = props.Spread; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid echo float property {:#04x}",
as_unsigned(param));
}
void EchoEffectHandler::GetParamfv(const EchoProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void EchoEffectHandler::GetParamfv(ALCcontext *context, const EchoProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using EchoCommitter = EaxCommitter<EaxEchoCommitter>;

View file

@ -3,23 +3,24 @@
#include <variant>
#include "AL/alc.h"
#include "AL/al.h"
#include "al/error.h"
#include "core/effects/base.h"
#include "opthelpers.h"
#define DECL_HANDLER(N, T) \
struct N { \
using prop_type = T; \
\
static void SetParami(prop_type &props, ALenum param, int val); \
static void SetParamiv(prop_type &props, ALenum param, const int *vals); \
static void SetParamf(prop_type &props, ALenum param, float val); \
static void SetParamfv(prop_type &props, ALenum param, const float *vals);\
static void GetParami(const prop_type &props, ALenum param, int *val); \
static void GetParamiv(const prop_type &props, ALenum param, int *vals); \
static void GetParamf(const prop_type &props, ALenum param, float *val); \
static void GetParamfv(const prop_type &props, ALenum param, float *vals);\
static void SetParami(ALCcontext *context, prop_type &props, ALenum param, int val); \
static void SetParamiv(ALCcontext *context, prop_type &props, ALenum param, const int *vals); \
static void SetParamf(ALCcontext *context, prop_type &props, ALenum param, float val); \
static void SetParamfv(ALCcontext *context, prop_type &props, ALenum param, const float *vals);\
static void GetParami(ALCcontext *context, const prop_type &props, ALenum param, int *val); \
static void GetParamiv(ALCcontext *context, const prop_type &props, ALenum param, int *vals); \
static void GetParamf(ALCcontext *context, const prop_type &props, ALenum param, float *val); \
static void GetParamfv(ALCcontext *context, const prop_type &props, ALenum param, float *vals);\
};
DECL_HANDLER(NullEffectHandler, std::monostate)
DECL_HANDLER(ReverbEffectHandler, ReverbProps)
@ -41,26 +42,23 @@ DECL_HANDLER(ConvolutionEffectHandler, ConvolutionProps)
#undef DECL_HANDLER
using effect_exception = al::context_error;
/* Default properties for the given effect types. */
extern const EffectProps NullEffectProps;
extern const EffectProps ReverbEffectProps;
extern const EffectProps StdReverbEffectProps;
extern const EffectProps AutowahEffectProps;
extern const EffectProps ChorusEffectProps;
extern const EffectProps CompressorEffectProps;
extern const EffectProps DistortionEffectProps;
extern const EffectProps EchoEffectProps;
extern const EffectProps EqualizerEffectProps;
extern const EffectProps FlangerEffectProps;
extern const EffectProps FshifterEffectProps;
extern const EffectProps ModulatorEffectProps;
extern const EffectProps PshifterEffectProps;
extern const EffectProps VmorpherEffectProps;
extern const EffectProps DedicatedDialogEffectProps;
extern const EffectProps DedicatedLfeEffectProps;
extern const EffectProps ConvolutionEffectProps;
DECL_HIDDEN extern const EffectProps NullEffectProps;
DECL_HIDDEN extern const EffectProps ReverbEffectProps;
DECL_HIDDEN extern const EffectProps StdReverbEffectProps;
DECL_HIDDEN extern const EffectProps AutowahEffectProps;
DECL_HIDDEN extern const EffectProps ChorusEffectProps;
DECL_HIDDEN extern const EffectProps CompressorEffectProps;
DECL_HIDDEN extern const EffectProps DistortionEffectProps;
DECL_HIDDEN extern const EffectProps EchoEffectProps;
DECL_HIDDEN extern const EffectProps EqualizerEffectProps;
DECL_HIDDEN extern const EffectProps FlangerEffectProps;
DECL_HIDDEN extern const EffectProps FshifterEffectProps;
DECL_HIDDEN extern const EffectProps ModulatorEffectProps;
DECL_HIDDEN extern const EffectProps PshifterEffectProps;
DECL_HIDDEN extern const EffectProps VmorpherEffectProps;
DECL_HIDDEN extern const EffectProps DedicatedDialogEffectProps;
DECL_HIDDEN extern const EffectProps DedicatedLfeEffectProps;
DECL_HIDDEN extern const EffectProps ConvolutionEffectProps;
#endif /* AL_EFFECTS_EFFECTS_H */

View file

@ -4,11 +4,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -37,115 +37,109 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps EqualizerEffectProps{genDefaultProps()};
void EqualizerEffectHandler::SetParami(EqualizerProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
void EqualizerEffectHandler::SetParamiv(EqualizerProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
param};
}
void EqualizerEffectHandler::SetParamf(EqualizerProps &props, ALenum param, float val)
void EqualizerEffectHandler::SetParami(ALCcontext *context, EqualizerProps&, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer property {:#04x}", as_unsigned(param)); }
void EqualizerEffectHandler::SetParamiv(ALCcontext *context, EqualizerProps&, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer-vector property {:#04x}", as_unsigned(param)); }
void EqualizerEffectHandler::SetParamf(ALCcontext *context, EqualizerProps &props, ALenum param, float val)
{
switch(param)
{
case AL_EQUALIZER_LOW_GAIN:
if(!(val >= AL_EQUALIZER_MIN_LOW_GAIN && val <= AL_EQUALIZER_MAX_LOW_GAIN))
throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer low-band gain out of range");
props.LowGain = val;
break;
return;
case AL_EQUALIZER_LOW_CUTOFF:
if(!(val >= AL_EQUALIZER_MIN_LOW_CUTOFF && val <= AL_EQUALIZER_MAX_LOW_CUTOFF))
throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band cutoff out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer low-band cutoff out of range");
props.LowCutoff = val;
break;
return;
case AL_EQUALIZER_MID1_GAIN:
if(!(val >= AL_EQUALIZER_MIN_MID1_GAIN && val <= AL_EQUALIZER_MAX_MID1_GAIN))
throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer mid1-band gain out of range");
props.Mid1Gain = val;
break;
return;
case AL_EQUALIZER_MID1_CENTER:
if(!(val >= AL_EQUALIZER_MIN_MID1_CENTER && val <= AL_EQUALIZER_MAX_MID1_CENTER))
throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band center out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer mid1-band center out of range");
props.Mid1Center = val;
break;
return;
case AL_EQUALIZER_MID1_WIDTH:
if(!(val >= AL_EQUALIZER_MIN_MID1_WIDTH && val <= AL_EQUALIZER_MAX_MID1_WIDTH))
throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band width out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer mid1-band width out of range");
props.Mid1Width = val;
break;
return;
case AL_EQUALIZER_MID2_GAIN:
if(!(val >= AL_EQUALIZER_MIN_MID2_GAIN && val <= AL_EQUALIZER_MAX_MID2_GAIN))
throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer mid2-band gain out of range");
props.Mid2Gain = val;
break;
return;
case AL_EQUALIZER_MID2_CENTER:
if(!(val >= AL_EQUALIZER_MIN_MID2_CENTER && val <= AL_EQUALIZER_MAX_MID2_CENTER))
throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band center out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer mid2-band center out of range");
props.Mid2Center = val;
break;
return;
case AL_EQUALIZER_MID2_WIDTH:
if(!(val >= AL_EQUALIZER_MIN_MID2_WIDTH && val <= AL_EQUALIZER_MAX_MID2_WIDTH))
throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band width out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer mid2-band width out of range");
props.Mid2Width = val;
break;
return;
case AL_EQUALIZER_HIGH_GAIN:
if(!(val >= AL_EQUALIZER_MIN_HIGH_GAIN && val <= AL_EQUALIZER_MAX_HIGH_GAIN))
throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer high-band gain out of range");
props.HighGain = val;
break;
return;
case AL_EQUALIZER_HIGH_CUTOFF:
if(!(val >= AL_EQUALIZER_MIN_HIGH_CUTOFF && val <= AL_EQUALIZER_MAX_HIGH_CUTOFF))
throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band cutoff out of range"};
context->throw_error(AL_INVALID_VALUE, "Equalizer high-band cutoff out of range");
props.HighCutoff = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param};
return;
}
}
void EqualizerEffectHandler::SetParamfv(EqualizerProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EqualizerEffectHandler::GetParami(const EqualizerProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
void EqualizerEffectHandler::GetParamiv(const EqualizerProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid equalizer float property {:#04x}",
as_unsigned(param));
}
void EqualizerEffectHandler::GetParamf(const EqualizerProps &props, ALenum param, float *val)
void EqualizerEffectHandler::SetParamfv(ALCcontext *context, EqualizerProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void EqualizerEffectHandler::GetParami(ALCcontext *context, const EqualizerProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer property {:#04x}", as_unsigned(param)); }
void EqualizerEffectHandler::GetParamiv(ALCcontext *context, const EqualizerProps&, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer-vector property {:#04x}", as_unsigned(param)); }
void EqualizerEffectHandler::GetParamf(ALCcontext *context, const EqualizerProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_EQUALIZER_LOW_GAIN: *val = props.LowGain; break;
case AL_EQUALIZER_LOW_CUTOFF: *val = props.LowCutoff; break;
case AL_EQUALIZER_MID1_GAIN: *val = props.Mid1Gain; break;
case AL_EQUALIZER_MID1_CENTER: *val = props.Mid1Center; break;
case AL_EQUALIZER_MID1_WIDTH: *val = props.Mid1Width; break;
case AL_EQUALIZER_MID2_GAIN: *val = props.Mid2Gain; break;
case AL_EQUALIZER_MID2_CENTER: *val = props.Mid2Center; break;
case AL_EQUALIZER_MID2_WIDTH: *val = props.Mid2Width; break;
case AL_EQUALIZER_HIGH_GAIN: *val = props.HighGain; break;
case AL_EQUALIZER_HIGH_CUTOFF: *val = props.HighCutoff; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param};
case AL_EQUALIZER_LOW_GAIN: *val = props.LowGain; return;
case AL_EQUALIZER_LOW_CUTOFF: *val = props.LowCutoff; return;
case AL_EQUALIZER_MID1_GAIN: *val = props.Mid1Gain; return;
case AL_EQUALIZER_MID1_CENTER: *val = props.Mid1Center; return;
case AL_EQUALIZER_MID1_WIDTH: *val = props.Mid1Width; return;
case AL_EQUALIZER_MID2_GAIN: *val = props.Mid2Gain; return;
case AL_EQUALIZER_MID2_CENTER: *val = props.Mid2Center; return;
case AL_EQUALIZER_MID2_WIDTH: *val = props.Mid2Width; return;
case AL_EQUALIZER_HIGH_GAIN: *val = props.HighGain; return;
case AL_EQUALIZER_HIGH_CUTOFF: *val = props.HighCutoff; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid equalizer float property {:#04x}",
as_unsigned(param));
}
void EqualizerEffectHandler::GetParamfv(const EqualizerProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void EqualizerEffectHandler::GetParamfv(ALCcontext *context, const EqualizerProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using EqualizerCommitter = EaxCommitter<EaxEqualizerCommitter>;

View file

@ -7,12 +7,13 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include <cassert>
#include "alnumeric.h"
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -39,7 +40,7 @@ constexpr ALenum EnumFromDirection(FShifterDirection dir)
case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
}
throw std::runtime_error{"Invalid direction: "+std::to_string(static_cast<int>(dir))};
throw std::runtime_error{fmt::format("Invalid direction: {}", int{al::to_underlying(dir)})};
}
constexpr EffectProps genDefaultProps() noexcept
@ -55,7 +56,7 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps FshifterEffectProps{genDefaultProps()};
void FshifterEffectHandler::SetParami(FshifterProps &props, ALenum param, int val)
void FshifterEffectHandler::SetParami(ALCcontext *context, FshifterProps &props, ALenum param, int val)
{
switch(param)
{
@ -63,81 +64,75 @@ void FshifterEffectHandler::SetParami(FshifterProps &props, ALenum param, int va
if(auto diropt = DirectionFromEmum(val))
props.LeftDirection = *diropt;
else
throw effect_exception{AL_INVALID_VALUE,
"Unsupported frequency shifter left direction: 0x%04x", val};
break;
context->throw_error(AL_INVALID_VALUE,
"Unsupported frequency shifter left direction: {:#04x}", as_unsigned(val));
return;
case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
if(auto diropt = DirectionFromEmum(val))
props.RightDirection = *diropt;
else
throw effect_exception{AL_INVALID_VALUE,
"Unsupported frequency shifter right direction: 0x%04x", val};
break;
default:
throw effect_exception{AL_INVALID_ENUM,
"Invalid frequency shifter integer property 0x%04x", param};
context->throw_error(AL_INVALID_VALUE,
"Unsupported frequency shifter right direction: {:#04x}", as_unsigned(val));
return;
}
}
void FshifterEffectHandler::SetParamiv(FshifterProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void FshifterEffectHandler::SetParamf(FshifterProps &props, ALenum param, float val)
context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter integer property {:#04x}",
as_unsigned(param));
}
void FshifterEffectHandler::SetParamiv(ALCcontext *context, FshifterProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void FshifterEffectHandler::SetParamf(ALCcontext *context, FshifterProps &props, ALenum param, float val)
{
switch(param)
{
case AL_FREQUENCY_SHIFTER_FREQUENCY:
if(!(val >= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY && val <= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY))
throw effect_exception{AL_INVALID_VALUE, "Frequency shifter frequency out of range"};
context->throw_error(AL_INVALID_VALUE, "Frequency shifter frequency out of range");
props.Frequency = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
param};
return;
}
}
void FshifterEffectHandler::SetParamfv(FshifterProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void FshifterEffectHandler::GetParami(const FshifterProps &props, ALenum param, int *val)
context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter float property {:#04x}",
as_unsigned(param));
}
void FshifterEffectHandler::SetParamfv(ALCcontext *context, FshifterProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void FshifterEffectHandler::GetParami(ALCcontext *context, const FshifterProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
*val = EnumFromDirection(props.LeftDirection);
break;
return;
case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
*val = EnumFromDirection(props.RightDirection);
break;
default:
throw effect_exception{AL_INVALID_ENUM,
"Invalid frequency shifter integer property 0x%04x", param};
return;
}
}
void FshifterEffectHandler::GetParamiv(const FshifterProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void FshifterEffectHandler::GetParamf(const FshifterProps &props, ALenum param, float *val)
context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter integer property {:#04x}",
as_unsigned(param));
}
void FshifterEffectHandler::GetParamiv(ALCcontext *context, const FshifterProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void FshifterEffectHandler::GetParamf(ALCcontext *context, const FshifterProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_FREQUENCY_SHIFTER_FREQUENCY:
*val = props.Frequency;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x",
param};
case AL_FREQUENCY_SHIFTER_FREQUENCY: *val = props.Frequency; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter float property {:#04x}",
as_unsigned(param));
}
void FshifterEffectHandler::GetParamfv(const FshifterProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void FshifterEffectHandler::GetParamfv(ALCcontext *context, const FshifterProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using FrequencyShifterCommitter = EaxCommitter<EaxFrequencyShifterCommitter>;

View file

@ -7,12 +7,13 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include <cassert>
#include "alnumeric.h"
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -39,8 +40,8 @@ constexpr ALenum EnumFromWaveform(ModulatorWaveform type)
case ModulatorWaveform::Sawtooth: return AL_RING_MODULATOR_SAWTOOTH;
case ModulatorWaveform::Square: return AL_RING_MODULATOR_SQUARE;
}
throw std::runtime_error{"Invalid modulator waveform: " +
std::to_string(static_cast<int>(type))};
throw std::runtime_error{fmt::format("Invalid modulator waveform: {}",
int{al::to_underlying(type)})};
}
constexpr EffectProps genDefaultProps() noexcept
@ -56,84 +57,84 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps ModulatorEffectProps{genDefaultProps()};
void ModulatorEffectHandler::SetParami(ModulatorProps &props, ALenum param, int val)
void ModulatorEffectHandler::SetParami(ALCcontext *context, ModulatorProps &props, ALenum param, int val)
{
switch(param)
{
case AL_RING_MODULATOR_FREQUENCY:
case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
SetParamf(props, param, static_cast<float>(val));
break;
SetParamf(context, props, param, static_cast<float>(val));
return;
case AL_RING_MODULATOR_WAVEFORM:
if(auto formopt = WaveformFromEmum(val))
props.Waveform = *formopt;
else
throw effect_exception{AL_INVALID_VALUE, "Invalid modulator waveform: 0x%04x", val};
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x",
param};
context->throw_error(AL_INVALID_VALUE, "Invalid modulator waveform: {:#04x}",
as_unsigned(val));
return;
}
}
void ModulatorEffectHandler::SetParamiv(ModulatorProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void ModulatorEffectHandler::SetParamf(ModulatorProps &props, ALenum param, float val)
context->throw_error(AL_INVALID_ENUM, "Invalid modulator integer property {:#04x}",
as_unsigned(param));
}
void ModulatorEffectHandler::SetParamiv(ALCcontext *context, ModulatorProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void ModulatorEffectHandler::SetParamf(ALCcontext *context, ModulatorProps &props, ALenum param, float val)
{
switch(param)
{
case AL_RING_MODULATOR_FREQUENCY:
if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY))
throw effect_exception{AL_INVALID_VALUE, "Modulator frequency out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Modulator frequency out of range: {:f}", val);
props.Frequency = val;
break;
return;
case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF))
throw effect_exception{AL_INVALID_VALUE, "Modulator high-pass cutoff out of range: %f", val};
context->throw_error(AL_INVALID_VALUE, "Modulator high-pass cutoff out of range: {:f}",
val);
props.HighPassCutoff = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param};
return;
}
}
void ModulatorEffectHandler::SetParamfv(ModulatorProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void ModulatorEffectHandler::GetParami(const ModulatorProps &props, ALenum param, int *val)
context->throw_error(AL_INVALID_ENUM, "Invalid modulator float property {:#04x}",
as_unsigned(param));
}
void ModulatorEffectHandler::SetParamfv(ALCcontext *context, ModulatorProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void ModulatorEffectHandler::GetParami(ALCcontext *context, const ModulatorProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_RING_MODULATOR_FREQUENCY: *val = static_cast<int>(props.Frequency); break;
case AL_RING_MODULATOR_HIGHPASS_CUTOFF: *val = static_cast<int>(props.HighPassCutoff); break;
case AL_RING_MODULATOR_WAVEFORM: *val = EnumFromWaveform(props.Waveform); break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x",
param};
case AL_RING_MODULATOR_FREQUENCY: *val = static_cast<int>(props.Frequency); return;
case AL_RING_MODULATOR_HIGHPASS_CUTOFF: *val = static_cast<int>(props.HighPassCutoff); return;
case AL_RING_MODULATOR_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid modulator integer property {:#04x}",
as_unsigned(param));
}
void ModulatorEffectHandler::GetParamiv(const ModulatorProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void ModulatorEffectHandler::GetParamf(const ModulatorProps &props, ALenum param, float *val)
void ModulatorEffectHandler::GetParamiv(ALCcontext *context, const ModulatorProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void ModulatorEffectHandler::GetParamf(ALCcontext *context, const ModulatorProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_RING_MODULATOR_FREQUENCY: *val = props.Frequency; break;
case AL_RING_MODULATOR_HIGHPASS_CUTOFF: *val = props.HighPassCutoff; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param};
case AL_RING_MODULATOR_FREQUENCY: *val = props.Frequency; return;
case AL_RING_MODULATOR_HIGHPASS_CUTOFF: *val = props.HighPassCutoff; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid modulator float property {:#04x}",
as_unsigned(param));
}
void ModulatorEffectHandler::GetParamfv(const ModulatorProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void ModulatorEffectHandler::GetParamfv(ALCcontext *context, const ModulatorProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using ModulatorCommitter = EaxCommitter<EaxModulatorCommitter>;

View file

@ -4,10 +4,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#endif // ALSOFT_EAX
@ -24,78 +25,46 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps NullEffectProps{genDefaultProps()};
void NullEffectHandler::SetParami(std::monostate& /*props*/, ALenum param, int /*val*/)
void NullEffectHandler::SetParami(ALCcontext *context, std::monostate& /*props*/, ALenum param, int /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x",
param};
}
context->throw_error(AL_INVALID_ENUM, "Invalid null effect integer property {:#04x}",
as_unsigned(param));
}
void NullEffectHandler::SetParamiv(std::monostate &props, ALenum param, const int *vals)
void NullEffectHandler::SetParamiv(ALCcontext *context, std::monostate &props, ALenum param, const int *vals)
{
switch(param)
{
default:
SetParami(props, param, *vals);
}
SetParami(context, props, param, *vals);
}
void NullEffectHandler::SetParamf(std::monostate& /*props*/, ALenum param, float /*val*/)
void NullEffectHandler::SetParamf(ALCcontext *context, std::monostate& /*props*/, ALenum param, float /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid null effect float property 0x%04x",
param};
}
context->throw_error(AL_INVALID_ENUM, "Invalid null effect float property {:#04x}",
as_unsigned(param));
}
void NullEffectHandler::SetParamfv(std::monostate &props, ALenum param, const float *vals)
void NullEffectHandler::SetParamfv(ALCcontext *context, std::monostate &props, ALenum param, const float *vals)
{
switch(param)
{
default:
SetParamf(props, param, *vals);
}
SetParamf(context, props, param, *vals);
}
void NullEffectHandler::GetParami(const std::monostate& /*props*/, ALenum param, int* /*val*/)
void NullEffectHandler::GetParami(ALCcontext *context, const std::monostate& /*props*/, ALenum param, int* /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x",
param};
}
context->throw_error(AL_INVALID_ENUM, "Invalid null effect integer property {:#04x}",
as_unsigned(param));
}
void NullEffectHandler::GetParamiv(const std::monostate &props, ALenum param, int *vals)
void NullEffectHandler::GetParamiv(ALCcontext *context, const std::monostate &props, ALenum param, int *vals)
{
switch(param)
{
default:
GetParami(props, param, vals);
}
GetParami(context, props, param, vals);
}
void NullEffectHandler::GetParamf(const std::monostate& /*props*/, ALenum param, float* /*val*/)
void NullEffectHandler::GetParamf(ALCcontext *context, const std::monostate& /*props*/, ALenum param, float* /*val*/)
{
switch(param)
{
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid null effect float property 0x%04x",
param};
}
context->throw_error(AL_INVALID_ENUM, "Invalid null effect float property {:#04x}",
as_unsigned(param));
}
void NullEffectHandler::GetParamfv(const std::monostate &props, ALenum param, float *vals)
void NullEffectHandler::GetParamfv(ALCcontext *context, const std::monostate &props, ALenum param, float *vals)
{
switch(param)
{
default:
GetParamf(props, param, vals);
}
GetParamf(context, props, param, vals);
}
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using NullCommitter = EaxCommitter<EaxNullCommitter>;

View file

@ -4,11 +4,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#if ALSOFT_EAX
#include "al/eax/effect.h"
#include "al/eax/exception.h"
#include "al/eax/utils.h"
@ -29,63 +29,55 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps PshifterEffectProps{genDefaultProps()};
void PshifterEffectHandler::SetParami(PshifterProps &props, ALenum param, int val)
void PshifterEffectHandler::SetParami(ALCcontext *context, PshifterProps &props, ALenum param, int val)
{
switch(param)
{
case AL_PITCH_SHIFTER_COARSE_TUNE:
if(!(val >= AL_PITCH_SHIFTER_MIN_COARSE_TUNE && val <= AL_PITCH_SHIFTER_MAX_COARSE_TUNE))
throw effect_exception{AL_INVALID_VALUE, "Pitch shifter coarse tune out of range"};
context->throw_error(AL_INVALID_VALUE, "Pitch shifter coarse tune out of range");
props.CoarseTune = val;
break;
return;
case AL_PITCH_SHIFTER_FINE_TUNE:
if(!(val >= AL_PITCH_SHIFTER_MIN_FINE_TUNE && val <= AL_PITCH_SHIFTER_MAX_FINE_TUNE))
throw effect_exception{AL_INVALID_VALUE, "Pitch shifter fine tune out of range"};
context->throw_error(AL_INVALID_VALUE, "Pitch shifter fine tune out of range");
props.FineTune = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x",
param};
return;
}
}
void PshifterEffectHandler::SetParamiv(PshifterProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void PshifterEffectHandler::SetParamf(PshifterProps&, ALenum param, float)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; }
void PshifterEffectHandler::SetParamfv(PshifterProps&, ALenum param, const float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float-vector property 0x%04x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter integer property {:#04x}",
as_unsigned(param));
}
void PshifterEffectHandler::SetParamiv(ALCcontext *context, PshifterProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void PshifterEffectHandler::GetParami(const PshifterProps &props, ALenum param, int *val)
void PshifterEffectHandler::SetParamf(ALCcontext *context, PshifterProps&, ALenum param, float)
{ context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter float property {:#04x}", as_unsigned(param)); }
void PshifterEffectHandler::SetParamfv(ALCcontext *context, PshifterProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void PshifterEffectHandler::GetParami(ALCcontext *context, const PshifterProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_PITCH_SHIFTER_COARSE_TUNE: *val = props.CoarseTune; break;
case AL_PITCH_SHIFTER_FINE_TUNE: *val = props.FineTune; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x",
param};
case AL_PITCH_SHIFTER_COARSE_TUNE: *val = props.CoarseTune; return;
case AL_PITCH_SHIFTER_FINE_TUNE: *val = props.FineTune; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter integer property {:#04x}",
as_unsigned(param));
}
void PshifterEffectHandler::GetParamiv(const PshifterProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void PshifterEffectHandler::GetParamiv(ALCcontext *context, const PshifterProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void PshifterEffectHandler::GetParamf(const PshifterProps&, ALenum param, float*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; }
void PshifterEffectHandler::GetParamfv(const PshifterProps&, ALenum param, float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float vector-property 0x%04x",
param};
}
void PshifterEffectHandler::GetParamf(ALCcontext *context, const PshifterProps&, ALenum param, float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter float property {:#04x}", as_unsigned(param)); }
void PshifterEffectHandler::GetParamfv(ALCcontext *context, const PshifterProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using PitchShifterCommitter = EaxCommitter<EaxPitchShifterCommitter>;

View file

@ -9,13 +9,17 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "alspan.h"
#include "core/effects/base.h"
#include "core/logging.h"
#include "effects.h"
#include "fmt/ranges.h"
#include "opthelpers.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include <cassert>
#include "al/eax/api.h"
#include "al/eax/call.h"
#include "al/eax/effect.h"
@ -92,152 +96,149 @@ constexpr EffectProps genDefaultStdProps() noexcept
const EffectProps ReverbEffectProps{genDefaultProps()};
void ReverbEffectHandler::SetParami(ReverbProps &props, ALenum param, int val)
void ReverbEffectHandler::SetParami(ALCcontext *context, ReverbProps &props, ALenum param, int val)
{
switch(param)
{
case AL_EAXREVERB_DECAY_HFLIMIT:
if(!(val >= AL_EAXREVERB_MIN_DECAY_HFLIMIT && val <= AL_EAXREVERB_MAX_DECAY_HFLIMIT))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range");
props.DecayHFLimit = val != AL_FALSE;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x",
param};
return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}",
as_unsigned(param));
}
void ReverbEffectHandler::SetParamiv(ReverbProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void ReverbEffectHandler::SetParamf(ReverbProps &props, ALenum param, float val)
void ReverbEffectHandler::SetParamiv(ALCcontext *context, ReverbProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void ReverbEffectHandler::SetParamf(ALCcontext *context, ReverbProps &props, ALenum param, float val)
{
switch(param)
{
case AL_EAXREVERB_DENSITY:
if(!(val >= AL_EAXREVERB_MIN_DENSITY && val <= AL_EAXREVERB_MAX_DENSITY))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb density out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb density out of range");
props.Density = val;
break;
return;
case AL_EAXREVERB_DIFFUSION:
if(!(val >= AL_EAXREVERB_MIN_DIFFUSION && val <= AL_EAXREVERB_MAX_DIFFUSION))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb diffusion out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb diffusion out of range");
props.Diffusion = val;
break;
return;
case AL_EAXREVERB_GAIN:
if(!(val >= AL_EAXREVERB_MIN_GAIN && val <= AL_EAXREVERB_MAX_GAIN))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gain out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb gain out of range");
props.Gain = val;
break;
return;
case AL_EAXREVERB_GAINHF:
if(!(val >= AL_EAXREVERB_MIN_GAINHF && val <= AL_EAXREVERB_MAX_GAINHF))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainhf out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb gainhf out of range");
props.GainHF = val;
break;
return;
case AL_EAXREVERB_GAINLF:
if(!(val >= AL_EAXREVERB_MIN_GAINLF && val <= AL_EAXREVERB_MAX_GAINLF))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainlf out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb gainlf out of range");
props.GainLF = val;
break;
return;
case AL_EAXREVERB_DECAY_TIME:
if(!(val >= AL_EAXREVERB_MIN_DECAY_TIME && val <= AL_EAXREVERB_MAX_DECAY_TIME))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay time out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay time out of range");
props.DecayTime = val;
break;
return;
case AL_EAXREVERB_DECAY_HFRATIO:
if(!(val >= AL_EAXREVERB_MIN_DECAY_HFRATIO && val <= AL_EAXREVERB_MAX_DECAY_HFRATIO))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range");
props.DecayHFRatio = val;
break;
return;
case AL_EAXREVERB_DECAY_LFRATIO:
if(!(val >= AL_EAXREVERB_MIN_DECAY_LFRATIO && val <= AL_EAXREVERB_MAX_DECAY_LFRATIO))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay lfratio out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay lfratio out of range");
props.DecayLFRatio = val;
break;
return;
case AL_EAXREVERB_REFLECTIONS_GAIN:
if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN && val <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections gain out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections gain out of range");
props.ReflectionsGain = val;
break;
return;
case AL_EAXREVERB_REFLECTIONS_DELAY:
if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY && val <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections delay out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections delay out of range");
props.ReflectionsDelay = val;
break;
return;
case AL_EAXREVERB_LATE_REVERB_GAIN:
if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN && val <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range");
props.LateReverbGain = val;
break;
return;
case AL_EAXREVERB_LATE_REVERB_DELAY:
if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY && val <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range");
props.LateReverbDelay = val;
break;
return;
case AL_EAXREVERB_ECHO_TIME:
if(!(val >= AL_EAXREVERB_MIN_ECHO_TIME && val <= AL_EAXREVERB_MAX_ECHO_TIME))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb echo time out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb echo time out of range");
props.EchoTime = val;
break;
return;
case AL_EAXREVERB_ECHO_DEPTH:
if(!(val >= AL_EAXREVERB_MIN_ECHO_DEPTH && val <= AL_EAXREVERB_MAX_ECHO_DEPTH))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb echo depth out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb echo depth out of range");
props.EchoDepth = val;
break;
return;
case AL_EAXREVERB_MODULATION_TIME:
if(!(val >= AL_EAXREVERB_MIN_MODULATION_TIME && val <= AL_EAXREVERB_MAX_MODULATION_TIME))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb modulation time out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb modulation time out of range");
props.ModulationTime = val;
break;
return;
case AL_EAXREVERB_MODULATION_DEPTH:
if(!(val >= AL_EAXREVERB_MIN_MODULATION_DEPTH && val <= AL_EAXREVERB_MAX_MODULATION_DEPTH))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb modulation depth out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb modulation depth out of range");
props.ModulationDepth = val;
break;
return;
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
if(!(val >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range");
props.AirAbsorptionGainHF = val;
break;
return;
case AL_EAXREVERB_HFREFERENCE:
if(!(val >= AL_EAXREVERB_MIN_HFREFERENCE && val <= AL_EAXREVERB_MAX_HFREFERENCE))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb hfreference out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb hfreference out of range");
props.HFReference = val;
break;
return;
case AL_EAXREVERB_LFREFERENCE:
if(!(val >= AL_EAXREVERB_MIN_LFREFERENCE && val <= AL_EAXREVERB_MAX_LFREFERENCE))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb lfreference out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb lfreference out of range");
props.LFReference = val;
break;
return;
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
if(!(val >= AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range");
props.RoomRolloffFactor = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param};
return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}",
as_unsigned(param));
}
void ReverbEffectHandler::SetParamfv(ReverbProps &props, ALenum param, const float *vals)
void ReverbEffectHandler::SetParamfv(ALCcontext *context, ReverbProps &props, ALenum param, const float *vals)
{
static constexpr auto finite_checker = [](float f) -> bool { return std::isfinite(f); };
al::span<const float> values;
@ -246,64 +247,60 @@ void ReverbEffectHandler::SetParamfv(ReverbProps &props, ALenum param, const flo
case AL_EAXREVERB_REFLECTIONS_PAN:
values = {vals, 3_uz};
if(!std::all_of(values.cbegin(), values.cend(), finite_checker))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections pan out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections pan out of range");
std::copy(values.cbegin(), values.cend(), props.ReflectionsPan.begin());
break;
return;
case AL_EAXREVERB_LATE_REVERB_PAN:
values = {vals, 3_uz};
if(!std::all_of(values.cbegin(), values.cend(), finite_checker))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb pan out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb pan out of range");
std::copy(values.cbegin(), values.cend(), props.LateReverbPan.begin());
break;
default:
SetParamf(props, param, *vals);
break;
return;
}
SetParamf(context, props, param, *vals);
}
void ReverbEffectHandler::GetParami(const ReverbProps &props, ALenum param, int *val)
void ReverbEffectHandler::GetParami(ALCcontext *context, const ReverbProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_EAXREVERB_DECAY_HFLIMIT: *val = props.DecayHFLimit; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x",
param};
case AL_EAXREVERB_DECAY_HFLIMIT: *val = props.DecayHFLimit; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}",
as_unsigned(param));
}
void ReverbEffectHandler::GetParamiv(const ReverbProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void ReverbEffectHandler::GetParamf(const ReverbProps &props, ALenum param, float *val)
void ReverbEffectHandler::GetParamiv(ALCcontext *context, const ReverbProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void ReverbEffectHandler::GetParamf(ALCcontext *context, const ReverbProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_EAXREVERB_DENSITY: *val = props.Density; break;
case AL_EAXREVERB_DIFFUSION: *val = props.Diffusion; break;
case AL_EAXREVERB_GAIN: *val = props.Gain; break;
case AL_EAXREVERB_GAINHF: *val = props.GainHF; break;
case AL_EAXREVERB_GAINLF: *val = props.GainLF; break;
case AL_EAXREVERB_DECAY_TIME: *val = props.DecayTime; break;
case AL_EAXREVERB_DECAY_HFRATIO: *val = props.DecayHFRatio; break;
case AL_EAXREVERB_DECAY_LFRATIO: *val = props.DecayLFRatio; break;
case AL_EAXREVERB_REFLECTIONS_GAIN: *val = props.ReflectionsGain; break;
case AL_EAXREVERB_REFLECTIONS_DELAY: *val = props.ReflectionsDelay; break;
case AL_EAXREVERB_LATE_REVERB_GAIN: *val = props.LateReverbGain; break;
case AL_EAXREVERB_LATE_REVERB_DELAY: *val = props.LateReverbDelay; break;
case AL_EAXREVERB_ECHO_TIME: *val = props.EchoTime; break;
case AL_EAXREVERB_ECHO_DEPTH: *val = props.EchoDepth; break;
case AL_EAXREVERB_MODULATION_TIME: *val = props.ModulationTime; break;
case AL_EAXREVERB_MODULATION_DEPTH: *val = props.ModulationDepth; break;
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: *val = props.AirAbsorptionGainHF; break;
case AL_EAXREVERB_HFREFERENCE: *val = props.HFReference; break;
case AL_EAXREVERB_LFREFERENCE: *val = props.LFReference; break;
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: *val = props.RoomRolloffFactor; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param};
case AL_EAXREVERB_DENSITY: *val = props.Density; return;
case AL_EAXREVERB_DIFFUSION: *val = props.Diffusion; return;
case AL_EAXREVERB_GAIN: *val = props.Gain; return;
case AL_EAXREVERB_GAINHF: *val = props.GainHF; return;
case AL_EAXREVERB_GAINLF: *val = props.GainLF; return;
case AL_EAXREVERB_DECAY_TIME: *val = props.DecayTime; return;
case AL_EAXREVERB_DECAY_HFRATIO: *val = props.DecayHFRatio; return;
case AL_EAXREVERB_DECAY_LFRATIO: *val = props.DecayLFRatio; return;
case AL_EAXREVERB_REFLECTIONS_GAIN: *val = props.ReflectionsGain; return;
case AL_EAXREVERB_REFLECTIONS_DELAY: *val = props.ReflectionsDelay; return;
case AL_EAXREVERB_LATE_REVERB_GAIN: *val = props.LateReverbGain; return;
case AL_EAXREVERB_LATE_REVERB_DELAY: *val = props.LateReverbDelay; return;
case AL_EAXREVERB_ECHO_TIME: *val = props.EchoTime; return;
case AL_EAXREVERB_ECHO_DEPTH: *val = props.EchoDepth; return;
case AL_EAXREVERB_MODULATION_TIME: *val = props.ModulationTime; return;
case AL_EAXREVERB_MODULATION_DEPTH: *val = props.ModulationDepth; return;
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: *val = props.AirAbsorptionGainHF; return;
case AL_EAXREVERB_HFREFERENCE: *val = props.HFReference; return;
case AL_EAXREVERB_LFREFERENCE: *val = props.LFReference; return;
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: *val = props.RoomRolloffFactor; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}",
as_unsigned(param));
}
void ReverbEffectHandler::GetParamfv(const ReverbProps &props, ALenum param, float *vals)
void ReverbEffectHandler::GetParamfv(ALCcontext *context, const ReverbProps &props, ALenum param, float *vals)
{
al::span<float> values;
switch(param)
@ -311,159 +308,155 @@ void ReverbEffectHandler::GetParamfv(const ReverbProps &props, ALenum param, flo
case AL_EAXREVERB_REFLECTIONS_PAN:
values = {vals, 3_uz};
std::copy(props.ReflectionsPan.cbegin(), props.ReflectionsPan.cend(), values.begin());
break;
return;
case AL_EAXREVERB_LATE_REVERB_PAN:
values = {vals, 3_uz};
std::copy(props.LateReverbPan.cbegin(), props.LateReverbPan.cend(), values.begin());
break;
default:
GetParamf(props, param, vals);
break;
return;
}
GetParamf(context, props, param, vals);
}
const EffectProps StdReverbEffectProps{genDefaultStdProps()};
void StdReverbEffectHandler::SetParami(ReverbProps &props, ALenum param, int val)
void StdReverbEffectHandler::SetParami(ALCcontext *context, ReverbProps &props, ALenum param, int val)
{
switch(param)
{
case AL_REVERB_DECAY_HFLIMIT:
if(!(val >= AL_REVERB_MIN_DECAY_HFLIMIT && val <= AL_REVERB_MAX_DECAY_HFLIMIT))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range");
props.DecayHFLimit = val != AL_FALSE;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x",
param};
return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}",
as_unsigned(param));
}
void StdReverbEffectHandler::SetParamiv(ReverbProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void StdReverbEffectHandler::SetParamf(ReverbProps &props, ALenum param, float val)
void StdReverbEffectHandler::SetParamiv(ALCcontext *context, ReverbProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void StdReverbEffectHandler::SetParamf(ALCcontext *context, ReverbProps &props, ALenum param, float val)
{
switch(param)
{
case AL_REVERB_DENSITY:
if(!(val >= AL_REVERB_MIN_DENSITY && val <= AL_REVERB_MAX_DENSITY))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb density out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb density out of range");
props.Density = val;
break;
return;
case AL_REVERB_DIFFUSION:
if(!(val >= AL_REVERB_MIN_DIFFUSION && val <= AL_REVERB_MAX_DIFFUSION))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb diffusion out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb diffusion out of range");
props.Diffusion = val;
break;
return;
case AL_REVERB_GAIN:
if(!(val >= AL_REVERB_MIN_GAIN && val <= AL_REVERB_MAX_GAIN))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gain out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb gain out of range");
props.Gain = val;
break;
return;
case AL_REVERB_GAINHF:
if(!(val >= AL_REVERB_MIN_GAINHF && val <= AL_REVERB_MAX_GAINHF))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainhf out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb gainhf out of range");
props.GainHF = val;
break;
return;
case AL_REVERB_DECAY_TIME:
if(!(val >= AL_REVERB_MIN_DECAY_TIME && val <= AL_REVERB_MAX_DECAY_TIME))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay time out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay time out of range");
props.DecayTime = val;
break;
return;
case AL_REVERB_DECAY_HFRATIO:
if(!(val >= AL_REVERB_MIN_DECAY_HFRATIO && val <= AL_REVERB_MAX_DECAY_HFRATIO))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range");
props.DecayHFRatio = val;
break;
return;
case AL_REVERB_REFLECTIONS_GAIN:
if(!(val >= AL_REVERB_MIN_REFLECTIONS_GAIN && val <= AL_REVERB_MAX_REFLECTIONS_GAIN))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections gain out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections gain out of range");
props.ReflectionsGain = val;
break;
return;
case AL_REVERB_REFLECTIONS_DELAY:
if(!(val >= AL_REVERB_MIN_REFLECTIONS_DELAY && val <= AL_REVERB_MAX_REFLECTIONS_DELAY))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections delay out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections delay out of range");
props.ReflectionsDelay = val;
break;
return;
case AL_REVERB_LATE_REVERB_GAIN:
if(!(val >= AL_REVERB_MIN_LATE_REVERB_GAIN && val <= AL_REVERB_MAX_LATE_REVERB_GAIN))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range");
props.LateReverbGain = val;
break;
return;
case AL_REVERB_LATE_REVERB_DELAY:
if(!(val >= AL_REVERB_MIN_LATE_REVERB_DELAY && val <= AL_REVERB_MAX_LATE_REVERB_DELAY))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range");
props.LateReverbDelay = val;
break;
return;
case AL_REVERB_AIR_ABSORPTION_GAINHF:
if(!(val >= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range");
props.AirAbsorptionGainHF = val;
break;
return;
case AL_REVERB_ROOM_ROLLOFF_FACTOR:
if(!(val >= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR))
throw effect_exception{AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range"};
context->throw_error(AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range");
props.RoomRolloffFactor = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param};
return;
}
}
void StdReverbEffectHandler::SetParamfv(ReverbProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void StdReverbEffectHandler::GetParami(const ReverbProps &props, ALenum param, int *val)
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}",
as_unsigned(param));
}
void StdReverbEffectHandler::SetParamfv(ALCcontext *context, ReverbProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void StdReverbEffectHandler::GetParami(ALCcontext *context, const ReverbProps &props, ALenum param, int *val)
{
switch(param)
{
case AL_REVERB_DECAY_HFLIMIT: *val = props.DecayHFLimit; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x",
param};
case AL_REVERB_DECAY_HFLIMIT: *val = props.DecayHFLimit; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}",
as_unsigned(param));
}
void StdReverbEffectHandler::GetParamiv(const ReverbProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void StdReverbEffectHandler::GetParamf(const ReverbProps &props, ALenum param, float *val)
void StdReverbEffectHandler::GetParamiv(ALCcontext *context, const ReverbProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void StdReverbEffectHandler::GetParamf(ALCcontext *context, const ReverbProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_REVERB_DENSITY: *val = props.Density; break;
case AL_REVERB_DIFFUSION: *val = props.Diffusion; break;
case AL_REVERB_GAIN: *val = props.Gain; break;
case AL_REVERB_GAINHF: *val = props.GainHF; break;
case AL_REVERB_DECAY_TIME: *val = props.DecayTime; break;
case AL_REVERB_DECAY_HFRATIO: *val = props.DecayHFRatio; break;
case AL_REVERB_REFLECTIONS_GAIN: *val = props.ReflectionsGain; break;
case AL_REVERB_REFLECTIONS_DELAY: *val = props.ReflectionsDelay; break;
case AL_REVERB_LATE_REVERB_GAIN: *val = props.LateReverbGain; break;
case AL_REVERB_LATE_REVERB_DELAY: *val = props.LateReverbDelay; break;
case AL_REVERB_AIR_ABSORPTION_GAINHF: *val = props.AirAbsorptionGainHF; break;
case AL_REVERB_ROOM_ROLLOFF_FACTOR: *val = props.RoomRolloffFactor; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param};
case AL_REVERB_DENSITY: *val = props.Density; return;
case AL_REVERB_DIFFUSION: *val = props.Diffusion; return;
case AL_REVERB_GAIN: *val = props.Gain; return;
case AL_REVERB_GAINHF: *val = props.GainHF; return;
case AL_REVERB_DECAY_TIME: *val = props.DecayTime; return;
case AL_REVERB_DECAY_HFRATIO: *val = props.DecayHFRatio; return;
case AL_REVERB_REFLECTIONS_GAIN: *val = props.ReflectionsGain; return;
case AL_REVERB_REFLECTIONS_DELAY: *val = props.ReflectionsDelay; return;
case AL_REVERB_LATE_REVERB_GAIN: *val = props.LateReverbGain; return;
case AL_REVERB_LATE_REVERB_DELAY: *val = props.LateReverbDelay; return;
case AL_REVERB_AIR_ABSORPTION_GAINHF: *val = props.AirAbsorptionGainHF; return;
case AL_REVERB_ROOM_ROLLOFF_FACTOR: *val = props.RoomRolloffFactor; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}",
as_unsigned(param));
}
void StdReverbEffectHandler::GetParamfv(const ReverbProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void StdReverbEffectHandler::GetParamfv(ALCcontext *context, const ReverbProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
class EaxReverbEffectException : public EaxException
@ -1064,6 +1057,38 @@ bool EaxReverbCommitter::commit(const EAXREVERBPROPERTIES &props)
ret.LFReference = props.flLFReference;
ret.RoomRolloffFactor = props.flRoomRolloffFactor;
ret.DecayHFLimit = ((props.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
if(EaxTraceCommits) UNLIKELY
{
TRACE("Reverb commit:\n"
" Density: {:f}\n"
" Diffusion: {:f}\n"
" Gain: {:f}\n"
" GainHF: {:f}\n"
" GainLF: {:f}\n"
" DecayTime: {:f}\n"
" DecayHFRatio: {:f}\n"
" DecayLFRatio: {:f}\n"
" ReflectionsGain: {:f}\n"
" ReflectionsDelay: {:f}\n"
" ReflectionsPan: {}\n"
" LateReverbGain: {:f}\n"
" LateReverbDelay: {:f}\n"
" LateRevernPan: {}\n"
" EchoTime: {:f}\n"
" EchoDepth: {:f}\n"
" ModulationTime: {:f}\n"
" ModulationDepth: {:f}\n"
" AirAbsorptionGainHF: {:f}\n"
" HFReference: {:f}\n"
" LFReference: {:f}\n"
" RoomRolloffFactor: {:f}\n"
" DecayHFLimit: {}", ret.Density, ret.Diffusion, ret.Gain, ret.GainHF, ret.GainLF,
ret.DecayTime, ret.DecayHFRatio, ret.DecayLFRatio, ret.ReflectionsGain,
ret.ReflectionsDelay, ret.ReflectionsPan, ret.LateReverbGain, ret.LateReverbDelay,
ret.LateReverbPan, ret.EchoTime, ret.EchoDepth, ret.ModulationTime,
ret.ModulationDepth, ret.AirAbsorptionGainHF, ret.HFReference, ret.LFReference,
ret.RoomRolloffFactor, ret.DecayHFLimit ? "true" : "false");
}
return ret;
}();

View file

@ -7,10 +7,11 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "core/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include <cassert>
#include "al/eax/effect.h"
#include "al/eax/exception.h"
@ -96,7 +97,7 @@ constexpr ALenum EnumFromPhenome(VMorpherPhenome phenome)
HANDLE_PHENOME(V);
HANDLE_PHENOME(Z);
}
throw std::runtime_error{"Invalid phenome: "+std::to_string(static_cast<int>(phenome))};
throw std::runtime_error{fmt::format("Invalid phenome: {}", int{al::to_underlying(phenome)})};
#undef HANDLE_PHENOME
}
@ -118,8 +119,8 @@ constexpr ALenum EnumFromWaveform(VMorpherWaveform type)
case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
}
throw std::runtime_error{"Invalid vocal morpher waveform: " +
std::to_string(static_cast<int>(type))};
throw std::runtime_error{fmt::format("Invalid vocal morpher waveform: {}",
int{al::to_underlying(type)})};
}
constexpr EffectProps genDefaultProps() noexcept
@ -138,7 +139,7 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps VmorpherEffectProps{genDefaultProps()};
void VmorpherEffectHandler::SetParami(VmorpherProps &props, ALenum param, int val)
void VmorpherEffectHandler::SetParami(ALCcontext *context, VmorpherProps &props, ALenum param, int val)
{
switch(param)
{
@ -146,101 +147,94 @@ void VmorpherEffectHandler::SetParami(VmorpherProps &props, ALenum param, int va
if(auto phenomeopt = PhenomeFromEnum(val))
props.PhonemeA = *phenomeopt;
else
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a out of range: 0x%04x", val};
break;
context->throw_error(AL_INVALID_VALUE,
"Vocal morpher phoneme-a out of range: {:#04x}", as_unsigned(val));
return;
case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING))
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a coarse tuning out of range"};
context->throw_error(AL_INVALID_VALUE,
"Vocal morpher phoneme-a coarse tuning out of range");
props.PhonemeACoarseTuning = val;
break;
return;
case AL_VOCAL_MORPHER_PHONEMEB:
if(auto phenomeopt = PhenomeFromEnum(val))
props.PhonemeB = *phenomeopt;
else
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b out of range: 0x%04x", val};
break;
context->throw_error(AL_INVALID_VALUE,
"Vocal morpher phoneme-b out of range: {:#04x}", as_unsigned(val));
return;
case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING))
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b coarse tuning out of range"};
context->throw_error(AL_INVALID_VALUE,
"Vocal morpher phoneme-b coarse tuning out of range");
props.PhonemeBCoarseTuning = val;
break;
return;
case AL_VOCAL_MORPHER_WAVEFORM:
if(auto formopt = WaveformFromEmum(val))
props.Waveform = *formopt;
else
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher waveform out of range: 0x%04x", val};
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
param};
context->throw_error(AL_INVALID_VALUE, "Vocal morpher waveform out of range: {:#04x}",
as_unsigned(val));
return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher integer property {:#04x}",
as_unsigned(param));
}
void VmorpherEffectHandler::SetParamiv(VmorpherProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
param};
}
void VmorpherEffectHandler::SetParamf(VmorpherProps &props, ALenum param, float val)
void VmorpherEffectHandler::SetParamiv(ALCcontext *context, VmorpherProps &props, ALenum param, const int *vals)
{ SetParami(context, props, param, *vals); }
void VmorpherEffectHandler::SetParamf(ALCcontext *context, VmorpherProps &props, ALenum param, float val)
{
switch(param)
{
case AL_VOCAL_MORPHER_RATE:
if(!(val >= AL_VOCAL_MORPHER_MIN_RATE && val <= AL_VOCAL_MORPHER_MAX_RATE))
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher rate out of range"};
context->throw_error(AL_INVALID_VALUE, "Vocal morpher rate out of range");
props.Rate = val;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x",
param};
return;
}
}
void VmorpherEffectHandler::SetParamfv(VmorpherProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void VmorpherEffectHandler::GetParami(const VmorpherProps &props, ALenum param, int* val)
context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher float property {:#04x}",
as_unsigned(param));
}
void VmorpherEffectHandler::SetParamfv(ALCcontext *context, VmorpherProps &props, ALenum param, const float *vals)
{ SetParamf(context, props, param, *vals); }
void VmorpherEffectHandler::GetParami(ALCcontext *context, const VmorpherProps &props, ALenum param, int* val)
{
switch(param)
{
case AL_VOCAL_MORPHER_PHONEMEA: *val = EnumFromPhenome(props.PhonemeA); break;
case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING: *val = props.PhonemeACoarseTuning; break;
case AL_VOCAL_MORPHER_PHONEMEB: *val = EnumFromPhenome(props.PhonemeB); break;
case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING: *val = props.PhonemeBCoarseTuning; break;
case AL_VOCAL_MORPHER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
param};
case AL_VOCAL_MORPHER_PHONEMEA: *val = EnumFromPhenome(props.PhonemeA); return;
case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING: *val = props.PhonemeACoarseTuning; return;
case AL_VOCAL_MORPHER_PHONEMEB: *val = EnumFromPhenome(props.PhonemeB); return;
case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING: *val = props.PhonemeBCoarseTuning; return;
case AL_VOCAL_MORPHER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher integer property {:#04x}",
as_unsigned(param));
}
void VmorpherEffectHandler::GetParamiv(const VmorpherProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
param};
}
void VmorpherEffectHandler::GetParamf(const VmorpherProps &props, ALenum param, float *val)
void VmorpherEffectHandler::GetParamiv(ALCcontext *context, const VmorpherProps &props, ALenum param, int *vals)
{ GetParami(context, props, param, vals); }
void VmorpherEffectHandler::GetParamf(ALCcontext *context, const VmorpherProps &props, ALenum param, float *val)
{
switch(param)
{
case AL_VOCAL_MORPHER_RATE:
*val = props.Rate;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x",
param};
case AL_VOCAL_MORPHER_RATE: *val = props.Rate; return;
}
context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher float property {:#04x}",
as_unsigned(param));
}
void VmorpherEffectHandler::GetParamfv(const VmorpherProps &props, ALenum param, float *vals)
{ GetParamf(props, param, vals); }
void VmorpherEffectHandler::GetParamfv(ALCcontext *context, const VmorpherProps &props, ALenum param, float *vals)
{ GetParamf(context, props, param, vals); }
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
namespace {
using VocalMorpherCommitter = EaxCommitter<EaxVocalMorpherCommitter>;

View file

@ -20,24 +20,19 @@
#include "config.h"
#include "error.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <atomic>
#include <csignal>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
@ -45,53 +40,19 @@
#include "al/debug.h"
#include "alc/alconfig.h"
#include "alc/context.h"
#include "alc/inprogext.h"
#include "alnumeric.h"
#include "core/except.h"
#include "core/logging.h"
#include "opthelpers.h"
#include "strutils.h"
namespace al {
context_error::context_error(ALenum code, const char *msg, ...) : mErrorCode{code}
void ALCcontext::setErrorImpl(ALenum errorCode, const fmt::string_view fmt, fmt::format_args args)
{
/* NOLINTBEGIN(*-array-to-pointer-decay) */
std::va_list args;
va_start(args, msg);
setMessage(msg, args);
va_end(args);
/* NOLINTEND(*-array-to-pointer-decay) */
}
context_error::~context_error() = default;
} /* namespace al */
const auto msg = fmt::vformat(fmt, std::move(args));
void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
{
auto message = std::vector<char>(256);
/* NOLINTBEGIN(*-array-to-pointer-decay) */
std::va_list args, args2;
va_start(args, msg);
va_copy(args2, args);
int msglen{std::vsnprintf(message.data(), message.size(), msg, args)};
if(msglen >= 0 && static_cast<size_t>(msglen) >= message.size())
{
message.resize(static_cast<size_t>(msglen) + 1u);
msglen = std::vsnprintf(message.data(), message.size(), msg, args2);
}
va_end(args2);
va_end(args);
/* NOLINTEND(*-array-to-pointer-decay) */
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);
WARN("Error generated on context {}, code {:#04x}, \"{}\"",
decltype(std::declval<void*>()){this}, as_unsigned(errorCode), msg);
if(TrapALError)
{
#ifdef _WIN32
@ -106,10 +67,18 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
if(mLastThreadError.get() == AL_NO_ERROR)
mLastThreadError.set(errorCode);
debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High,
{msg, static_cast<uint>(msglen)});
debugMessage(DebugSource::API, DebugType::Error, static_cast<ALuint>(errorCode),
DebugSeverity::High, msg);
}
void ALCcontext::throw_error_impl(ALenum errorCode, const fmt::string_view fmt,
fmt::format_args args)
{
setErrorImpl(errorCode, fmt, std::move(args));
throw al::base_exception{};
}
/* Special-case alGetError since it (potentially) raises a debug signal and
* returns a non-default value for a null context.
*/
@ -125,17 +94,20 @@ AL_API auto AL_APIENTRY alGetError() noexcept -> ALenum
optstr = ConfigValueStr({}, "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());
try {
auto idx = 0_uz;
auto value = std::stoi(*optstr, &idx, 0);
if(idx >= optstr->size() || std::isspace(optstr->at(idx)))
return static_cast<ALenum>(value);
} catch(...) {
}
ERR("Invalid default error value: \"{}\"", *optstr);
}
return AL_INVALID_OPERATION;
};
static const ALenum deferror{get_value("__ALSOFT_DEFAULT_ERROR", "default-error")};
WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
WARN("Querying error state on null context (implicitly {:#04x})", as_unsigned(deferror));
if(TrapALError)
{
#ifdef _WIN32

View file

@ -1,27 +0,0 @@
#ifndef AL_ERROR_H
#define AL_ERROR_H
#include "AL/al.h"
#include "core/except.h"
namespace al {
class context_error final : public al::base_exception {
ALenum mErrorCode{};
public:
#ifdef __MINGW32__
[[gnu::format(__MINGW_PRINTF_FORMAT, 3, 4)]]
#else
[[gnu::format(printf, 3, 4)]]
#endif
context_error(ALenum code, const char *msg, ...);
~context_error() final;
[[nodiscard]] auto errorCode() const noexcept -> ALenum { return mErrorCode; }
};
} /* namespace al */
#endif /* AL_ERROR_H */

View file

@ -3,7 +3,6 @@
#include "event.h"
#include <array>
#include <atomic>
#include <bitset>
#include <exception>
@ -12,10 +11,8 @@
#include <new>
#include <optional>
#include <string>
#include <string_view>
#include <thread>
#include <tuple>
#include <utility>
#include <variant>
#include "AL/al.h"
@ -23,15 +20,17 @@
#include "AL/alext.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "alsem.h"
#include "alspan.h"
#include "alstring.h"
#include "core/async_event.h"
#include "core/context.h"
#include "core/effects/base.h"
#include "core/except.h"
#include "core/logging.h"
#include "debug.h"
#include "direct_defs.h"
#include "error.h"
#include "intrusive_ptr.h"
#include "opthelpers.h"
#include "ringbuffer.h"
@ -51,14 +50,15 @@ int EventThread(ALCcontext *context)
bool quitnow{false};
while(!quitnow)
{
auto evt_data = ring->getReadVector().first;
auto evt_data = ring->getReadVector()[0];
if(evt_data.len == 0)
{
context->mEventSem.wait();
continue;
}
std::lock_guard<std::mutex> eventlock{context->mEventCbLock};
auto eventlock = std::lock_guard{context->mEventCbLock};
const auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire);
auto evt_span = al::span{std::launder(reinterpret_cast<AsyncEvent*>(evt_data.buf)),
evt_data.len};
for(auto &event : evt_span)
@ -66,7 +66,6 @@ int EventThread(ALCcontext *context)
quitnow = std::holds_alternative<AsyncKillThread>(event);
if(quitnow) UNLIKELY break;
auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire);
auto proc_killthread = [](AsyncKillThread&) { };
auto proc_release = [](AsyncEffectReleaseEvent &evt)
{
@ -101,7 +100,7 @@ int EventThread(ALCcontext *context)
break;
}
context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.mId, state,
static_cast<ALsizei>(msg.length()), msg.c_str(), context->mEventParam);
al::sizei(msg), msg.c_str(), context->mEventParam);
};
auto proc_buffercomp = [context,enabledevts](AsyncBufferCompleteEvent &evt)
{
@ -113,18 +112,16 @@ int EventThread(ALCcontext *context)
if(evt.mCount == 1) msg += " buffer completed";
else msg += " buffers completed";
context->mEventCb(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, evt.mId, evt.mCount,
static_cast<ALsizei>(msg.length()), msg.c_str(), context->mEventParam);
al::sizei(msg), msg.c_str(), context->mEventParam);
};
auto proc_disconnect = [context,enabledevts](AsyncDisconnectEvent &evt)
{
context->debugMessage(DebugSource::System, DebugType::Error, 0,
DebugSeverity::High, evt.msg);
if(!context->mEventCb
|| !enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected)))
return;
if(context->mEventCb
&& enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected)))
context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0,
static_cast<ALsizei>(evt.msg.length()), evt.msg.c_str(),
context->mEventParam);
context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, al::sizei(evt.msg),
evt.msg.c_str(), context->mEventParam);
};
std::visit(overloaded{proc_srcstate, proc_buffercomp, proc_release, proc_disconnect,
@ -156,22 +153,22 @@ void StartEventThrd(ALCcontext *ctx)
ctx->mEventThread = std::thread{EventThread, ctx};
}
catch(std::exception& e) {
ERR("Failed to start event thread: %s\n", e.what());
ERR("Failed to start event thread: {}", e.what());
}
catch(...) {
ERR("Failed to start event thread! Expect problems.\n");
ERR("Failed to start event thread! Expect problems.");
}
}
void StopEventThrd(ALCcontext *ctx)
{
RingBuffer *ring{ctx->mAsyncEvents.get()};
auto evt_data = ring->getWriteVector().first;
auto evt_data = ring->getWriteVector()[0];
if(evt_data.len == 0)
{
do {
std::this_thread::yield();
evt_data = ring->getWriteVector().first;
evt_data = ring->getWriteVector()[0];
} while(evt_data.len == 0);
}
std::ignore = InitAsyncEvent<AsyncKillThread>(evt_data.buf);
@ -187,18 +184,19 @@ FORCE_ALIGN void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsiz
const ALenum *types, ALboolean enable) noexcept
try {
if(count < 0)
throw al::context_error{AL_INVALID_VALUE, "Controlling %d events", count};
context->throw_error(AL_INVALID_VALUE, "Controlling {} events", count);
if(count <= 0) UNLIKELY return;
if(!types)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
ContextBase::AsyncEventBitset flags{};
for(ALenum evttype : al::span{types, static_cast<uint>(count)})
{
auto etype = GetEventType(evttype);
if(!etype)
throw al::context_error{AL_INVALID_ENUM, "Invalid event type 0x%04x", evttype};
context->throw_error(AL_INVALID_ENUM, "Invalid event type {:#04x}",
as_unsigned(evttype));
flags.set(al::to_underlying(*etype));
}
@ -226,15 +224,22 @@ try {
std::lock_guard<std::mutex> eventlock{context->mEventCbLock};
}
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNCEXT2(void, alEventCallback,SOFT, ALEVENTPROCSOFT,callback, void*,userParam)
FORCE_ALIGN void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context,
ALEVENTPROCSOFT callback, void *userParam) noexcept
{
try {
std::lock_guard<std::mutex> eventlock{context->mEventCbLock};
context->mEventCb = callback;
context->mEventParam = userParam;
}
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}

View file

@ -21,13 +21,11 @@
#include "config.h"
#include <string_view>
#include <vector>
#include "AL/al.h"
#include "AL/alc.h"
#include "alc/context.h"
#include "alc/inprogext.h"
#include "alstring.h"
#include "direct_defs.h"
#include "opthelpers.h"

View file

@ -30,7 +30,6 @@
#include <memory>
#include <mutex>
#include <numeric>
#include <string>
#include <unordered_map>
#include <vector>
@ -41,12 +40,12 @@
#include "albit.h"
#include "alc/context.h"
#include "alc/device.h"
#include "alc/inprogext.h"
#include "almalloc.h"
#include "alnumeric.h"
#include "alspan.h"
#include "core/except.h"
#include "core/logging.h"
#include "direct_defs.h"
#include "error.h"
#include "intrusive_ptr.h"
#include "opthelpers.h"
@ -97,7 +96,8 @@ void InitFilterParams(ALfilter *filter, ALenum type)
filter->type = type;
}
auto EnsureFilters(ALCdevice *device, size_t needed) noexcept -> bool
[[nodiscard]]
auto EnsureFilters(al::Device *device, size_t needed) noexcept -> bool
try {
size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), 0_uz,
[](size_t cur, const FilterSubList &sublist) noexcept -> size_t
@ -121,7 +121,8 @@ catch(...) {
}
ALfilter *AllocFilter(ALCdevice *device) noexcept
[[nodiscard]]
auto AllocFilter(al::Device *device) noexcept -> ALfilter*
{
auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(),
[](const FilterSubList &entry) noexcept -> bool
@ -141,7 +142,7 @@ ALfilter *AllocFilter(ALCdevice *device) noexcept
return filter;
}
void FreeFilter(ALCdevice *device, ALfilter *filter)
void FreeFilter(al::Device *device, ALfilter *filter)
{
device->mFilterNames.erase(filter->id);
@ -155,7 +156,8 @@ void FreeFilter(ALCdevice *device, ALfilter *filter)
}
auto LookupFilter(ALCdevice *device, ALuint id) noexcept -> ALfilter*
[[nodiscard]]
auto LookupFilter(al::Device *device, ALuint id) noexcept -> ALfilter*
{
const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f};
@ -172,171 +174,176 @@ auto LookupFilter(ALCdevice *device, ALuint id) noexcept -> ALfilter*
/* Null filter parameter handlers */
template<>
void FilterTable<NullFilterTable>::setParami(ALfilter*, ALenum param, int)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::setParami(ALCcontext *context, ALfilter*, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::setParamiv(ALfilter*, ALenum param, const int*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::setParamiv(ALCcontext *context, ALfilter*, ALenum param, const int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::setParamf(ALfilter*, ALenum param, float)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::setParamf(ALCcontext *context, ALfilter*, ALenum param, float)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::setParamfv(ALfilter*, ALenum param, const float*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::setParamfv(ALCcontext *context, ALfilter*, ALenum param, const float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::getParami(const ALfilter*, ALenum param, int*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::getParamiv(const ALfilter*, ALenum param, int*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::getParamiv(ALCcontext *context, const ALfilter*, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::getParamf(const ALfilter*, ALenum param, float*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::getParamf(ALCcontext *context, const ALfilter*, ALenum param, float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<NullFilterTable>::getParamfv(const ALfilter*, ALenum param, float*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; }
void FilterTable<NullFilterTable>::getParamfv(ALCcontext *context, const ALfilter*, ALenum param, float*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); }
/* Lowpass parameter handlers */
template<>
void FilterTable<LowpassFilterTable>::setParami(ALfilter*, ALenum param, int)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; }
void FilterTable<LowpassFilterTable>::setParami(ALCcontext *context, ALfilter*, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid low-pass integer property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<LowpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
{ setParami(filter, param, *values); }
void FilterTable<LowpassFilterTable>::setParamiv(ALCcontext *context, ALfilter *filter, ALenum param, const int *values)
{ setParami(context, filter, param, *values); }
template<>
void FilterTable<LowpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
void FilterTable<LowpassFilterTable>::setParamf(ALCcontext *context, ALfilter *filter, ALenum param, float val)
{
switch(param)
{
case AL_LOWPASS_GAIN:
if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
throw al::context_error{AL_INVALID_VALUE, "Low-pass gain %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "Low-pass gain {:f} out of range", val);
filter->Gain = val;
return;
case AL_LOWPASS_GAINHF:
if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF))
throw al::context_error{AL_INVALID_VALUE, "Low-pass gainhf %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "Low-pass gainhf {:f} out of range", val);
filter->GainHF = val;
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid low-pass float property {:#04x}",
as_unsigned(param));
}
template<>
void FilterTable<LowpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
{ setParamf(filter, param, *vals); }
void FilterTable<LowpassFilterTable>::setParamfv(ALCcontext *context, ALfilter *filter, ALenum param, const float *vals)
{ setParamf(context, filter, param, *vals); }
template<>
void FilterTable<LowpassFilterTable>::getParami(const ALfilter*, ALenum param, int*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; }
void FilterTable<LowpassFilterTable>::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid low-pass integer property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<LowpassFilterTable>::getParamiv(const ALfilter *filter, ALenum param, int *values)
{ getParami(filter, param, values); }
void FilterTable<LowpassFilterTable>::getParamiv(ALCcontext *context, const ALfilter *filter, ALenum param, int *values)
{ getParami(context, filter, param, values); }
template<>
void FilterTable<LowpassFilterTable>::getParamf(const ALfilter *filter, ALenum param, float *val)
void FilterTable<LowpassFilterTable>::getParamf(ALCcontext *context, const ALfilter *filter, ALenum param, float *val)
{
switch(param)
{
case AL_LOWPASS_GAIN: *val = filter->Gain; return;
case AL_LOWPASS_GAINHF: *val = filter->GainHF; return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid low-pass float property {:#04x}",
as_unsigned(param));
}
template<>
void FilterTable<LowpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
{ getParamf(filter, param, vals); }
void FilterTable<LowpassFilterTable>::getParamfv(ALCcontext *context, const ALfilter *filter, ALenum param, float *vals)
{ getParamf(context, filter, param, vals); }
/* Highpass parameter handlers */
template<>
void FilterTable<HighpassFilterTable>::setParami(ALfilter*, ALenum param, int)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; }
void FilterTable<HighpassFilterTable>::setParami(ALCcontext *context, ALfilter*, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid high-pass integer property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<HighpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
{ setParami(filter, param, *values); }
void FilterTable<HighpassFilterTable>::setParamiv(ALCcontext *context, ALfilter *filter, ALenum param, const int *values)
{ setParami(context, filter, param, *values); }
template<>
void FilterTable<HighpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
void FilterTable<HighpassFilterTable>::setParamf(ALCcontext *context, ALfilter *filter, ALenum param, float val)
{
switch(param)
{
case AL_HIGHPASS_GAIN:
if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
throw al::context_error{AL_INVALID_VALUE, "High-pass gain %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "High-pass gain {:f} out of range", val);
filter->Gain = val;
return;
case AL_HIGHPASS_GAINLF:
if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF))
throw al::context_error{AL_INVALID_VALUE, "High-pass gainlf %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "High-pass gainlf {:f} out of range", val);
filter->GainLF = val;
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid high-pass float property {:#04x}",
as_unsigned(param));
}
template<>
void FilterTable<HighpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
{ setParamf(filter, param, *vals); }
void FilterTable<HighpassFilterTable>::setParamfv(ALCcontext *context, ALfilter *filter, ALenum param, const float *vals)
{ setParamf(context, filter, param, *vals); }
template<>
void FilterTable<HighpassFilterTable>::getParami(const ALfilter*, ALenum param, int*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; }
void FilterTable<HighpassFilterTable>::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid high-pass integer property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<HighpassFilterTable>::getParamiv(const ALfilter *filter, ALenum param, int *values)
{ getParami(filter, param, values); }
void FilterTable<HighpassFilterTable>::getParamiv(ALCcontext *context, const ALfilter *filter, ALenum param, int *values)
{ getParami(context, filter, param, values); }
template<>
void FilterTable<HighpassFilterTable>::getParamf(const ALfilter *filter, ALenum param, float *val)
void FilterTable<HighpassFilterTable>::getParamf(ALCcontext *context, const ALfilter *filter, ALenum param, float *val)
{
switch(param)
{
case AL_HIGHPASS_GAIN: *val = filter->Gain; return;
case AL_HIGHPASS_GAINLF: *val = filter->GainLF; return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid high-pass float property {:#04x}",
as_unsigned(param));
}
template<>
void FilterTable<HighpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
{ getParamf(filter, param, vals); }
void FilterTable<HighpassFilterTable>::getParamfv(ALCcontext *context, const ALfilter *filter, ALenum param, float *vals)
{ getParamf(context, filter, param, vals); }
/* Bandpass parameter handlers */
template<>
void FilterTable<BandpassFilterTable>::setParami(ALfilter*, ALenum param, int)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; }
void FilterTable<BandpassFilterTable>::setParami(ALCcontext *context, ALfilter*, ALenum param, int)
{ context->throw_error(AL_INVALID_ENUM, "Invalid band-pass integer property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<BandpassFilterTable>::setParamiv(ALfilter *filter, ALenum param, const int *values)
{ setParami(filter, param, *values); }
void FilterTable<BandpassFilterTable>::setParamiv(ALCcontext *context, ALfilter *filter, ALenum param, const int *values)
{ setParami(context, filter, param, *values); }
template<>
void FilterTable<BandpassFilterTable>::setParamf(ALfilter *filter, ALenum param, float val)
void FilterTable<BandpassFilterTable>::setParamf(ALCcontext *context, ALfilter *filter, ALenum param, float val)
{
switch(param)
{
case AL_BANDPASS_GAIN:
if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
throw al::context_error{AL_INVALID_VALUE, "Band-pass gain %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "Band-pass gain {:f} out of range", val);
filter->Gain = val;
return;
case AL_BANDPASS_GAINHF:
if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF))
throw al::context_error{AL_INVALID_VALUE, "Band-pass gainhf %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "Band-pass gainhf {:f} out of range", val);
filter->GainHF = val;
return;
case AL_BANDPASS_GAINLF:
if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF))
throw al::context_error{AL_INVALID_VALUE, "Band-pass gainlf %f out of range", val};
context->throw_error(AL_INVALID_VALUE, "Band-pass gainlf {:f} out of range", val);
filter->GainLF = val;
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid band-pass float property {:#04x}",
as_unsigned(param));
}
template<>
void FilterTable<BandpassFilterTable>::setParamfv(ALfilter *filter, ALenum param, const float *vals)
{ setParamf(filter, param, *vals); }
void FilterTable<BandpassFilterTable>::setParamfv(ALCcontext *context, ALfilter *filter, ALenum param, const float *vals)
{ setParamf(context, filter, param, *vals); }
template<>
void FilterTable<BandpassFilterTable>::getParami(const ALfilter*, ALenum param, int*)
{ throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; }
void FilterTable<BandpassFilterTable>::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*)
{ context->throw_error(AL_INVALID_ENUM, "Invalid band-pass integer property {:#04x}", as_unsigned(param)); }
template<>
void FilterTable<BandpassFilterTable>::getParamiv(const ALfilter *filter, ALenum param, int *values)
{ getParami(filter, param, values); }
void FilterTable<BandpassFilterTable>::getParamiv(ALCcontext *context, const ALfilter *filter, ALenum param, int *values)
{ getParami(context, filter, param, values); }
template<>
void FilterTable<BandpassFilterTable>::getParamf(const ALfilter *filter, ALenum param, float *val)
void FilterTable<BandpassFilterTable>::getParamf(ALCcontext *context, const ALfilter *filter, ALenum param, float *val)
{
switch(param)
{
@ -344,32 +351,35 @@ void FilterTable<BandpassFilterTable>::getParamf(const ALfilter *filter, ALenum
case AL_BANDPASS_GAINHF: *val = filter->GainHF; return;
case AL_BANDPASS_GAINLF: *val = filter->GainLF; return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid band-pass float property {:#04x}",
as_unsigned(param));
}
template<>
void FilterTable<BandpassFilterTable>::getParamfv(const ALfilter *filter, ALenum param, float *vals)
{ getParamf(filter, param, vals); }
void FilterTable<BandpassFilterTable>::getParamfv(ALCcontext *context, const ALfilter *filter, ALenum param, float *vals)
{ getParamf(context, filter, param, vals); }
AL_API DECL_FUNC2(void, alGenFilters, ALsizei,n, ALuint*,filters)
FORCE_ALIGN void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept
try {
if(n < 0)
throw al::context_error{AL_INVALID_VALUE, "Generating %d filters", n};
context->throw_error(AL_INVALID_VALUE, "Generating {} filters", n);
if(n <= 0) UNLIKELY return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
const al::span fids{filters, static_cast<ALuint>(n)};
if(!EnsureFilters(device, fids.size()))
throw al::context_error{AL_OUT_OF_MEMORY, "Failed to allocate %d filter%s", n,
(n == 1) ? "" : "s"};
context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} filter{}", n,
(n==1) ? "" : "s");
std::generate(fids.begin(), fids.end(), [device]{ return AllocFilter(device)->id; });
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alDeleteFilters, ALsizei,n, const ALuint*,filters)
@ -377,11 +387,11 @@ FORCE_ALIGN void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei
const ALuint *filters) noexcept
try {
if(n < 0)
throw al::context_error{AL_INVALID_VALUE, "Deleting %d filters", n};
context->throw_error(AL_INVALID_VALUE, "Deleting {} filters", n);
if(n <= 0) UNLIKELY return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
/* First try to find any filters that are invalid. */
auto validate_filter = [device](const ALuint fid) -> bool
@ -390,7 +400,7 @@ try {
const al::span fids{filters, static_cast<ALuint>(n)};
auto invflt = std::find_if_not(fids.begin(), fids.end(), validate_filter);
if(invflt != fids.end())
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", *invflt};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", *invflt);
/* All good. Delete non-0 filter IDs. */
auto delete_filter = [device](const ALuint fid) -> void
@ -400,15 +410,17 @@ try {
};
std::for_each(fids.begin(), fids.end(), delete_filter);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC1(ALboolean, alIsFilter, ALuint,filter)
FORCE_ALIGN ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) noexcept
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
if(!filter || LookupFilter(device, filter))
return AL_TRUE;
return AL_FALSE;
@ -419,29 +431,32 @@ AL_API DECL_FUNC3(void, alFilteri, ALuint,filter, ALenum,param, ALint,value)
FORCE_ALIGN void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param,
ALint value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
switch(param)
{
case AL_FILTER_TYPE:
if(!(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS
|| value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS))
throw al::context_error{AL_INVALID_VALUE, "Invalid filter type 0x%04x", value};
context->throw_error(AL_INVALID_VALUE, "Invalid filter type {:#04x}",
as_unsigned(value));
InitFilterParams(alfilt, value);
return;
}
/* Call the appropriate handler */
std::visit([alfilt,param,value](auto&& thunk){thunk.setParami(alfilt, param, value);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,value](auto&& thunk)
{ thunk.setParami(context, alfilt, param, value); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alFilteriv, ALuint,filter, ALenum,param, const ALint*,values)
@ -455,83 +470,89 @@ try {
return;
}
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
/* Call the appropriate handler */
std::visit([alfilt,param,values](auto&& thunk){thunk.setParamiv(alfilt, param, values);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,values](auto&& thunk)
{ thunk.setParamiv(context, alfilt, param, values); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alFilterf, ALuint,filter, ALenum,param, ALfloat,value)
FORCE_ALIGN void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param,
ALfloat value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
/* Call the appropriate handler */
std::visit([alfilt,param,value](auto&& thunk){thunk.setParamf(alfilt, param, value);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,value](auto&& thunk)
{ thunk.setParamf(context, alfilt, param, value); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alFilterfv, ALuint,filter, ALenum,param, const ALfloat*,values)
FORCE_ALIGN void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param,
const ALfloat *values) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
/* Call the appropriate handler */
std::visit([alfilt,param,values](auto&& thunk){thunk.setParamfv(alfilt, param, values);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,values](auto&& thunk)
{ thunk.setParamfv(context, alfilt, param, values); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetFilteri, ALuint,filter, ALenum,param, ALint*,value)
FORCE_ALIGN void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param,
ALint *value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
const ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
switch(param)
{
case AL_FILTER_TYPE:
*value = alfilt->type;
return;
case AL_FILTER_TYPE: *value = alfilt->type; return;
}
/* Call the appropriate handler */
std::visit([alfilt,param,value](auto&& thunk){thunk.getParami(alfilt, param, value);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,value](auto&& thunk)
{ thunk.getParami(context, alfilt, param, value); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetFilteriv, ALuint,filter, ALenum,param, ALint*,values)
@ -545,68 +566,74 @@ try {
return;
}
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
const ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
/* Call the appropriate handler */
std::visit([alfilt,param,values](auto&& thunk){thunk.getParamiv(alfilt, param, values);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,values](auto&& thunk)
{ thunk.getParamiv(context, alfilt, param, values); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetFilterf, ALuint,filter, ALenum,param, ALfloat*,value)
FORCE_ALIGN void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param,
ALfloat *value) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
const ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt) UNLIKELY
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
if(!alfilt)
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
/* Call the appropriate handler */
std::visit([alfilt,param,value](auto&& thunk){thunk.getParamf(alfilt, param, value);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,value](auto&& thunk)
{ thunk.getParamf(context, alfilt, param, value); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC3(void, alGetFilterfv, ALuint,filter, ALenum,param, ALfloat*,values)
FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param,
ALfloat *values) noexcept
try {
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
const ALfilter *alfilt{LookupFilter(device, filter)};
if(!alfilt) UNLIKELY
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", filter};
if(!alfilt)
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter);
/* Call the appropriate handler */
std::visit([alfilt,param,values](auto&& thunk){thunk.getParamfv(alfilt, param, values);},
alfilt->mTypeVariant);
std::visit([context,alfilt,param,values](auto&& thunk)
{ thunk.getParamfv(context, alfilt, param, values); }, alfilt->mTypeVariant);
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
void ALfilter::SetName(ALCcontext *context, ALuint id, std::string_view name)
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> filterlock{device->FilterLock};
auto *device = context->mALDevice.get();
auto filterlock = std::lock_guard{device->FilterLock};
auto filter = LookupFilter(device, id);
if(!filter)
throw al::context_error{AL_INVALID_NAME, "Invalid filter ID %u", id};
context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", id);
device->mFilterNames.insert_or_assign(id, name);
}

View file

@ -14,21 +14,27 @@
#include "almalloc.h"
#include "alnumeric.h"
struct ALfilter;
inline constexpr float LowPassFreqRef{5000.0f};
inline constexpr float 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 setParami(ALCcontext*, ALfilter*, ALenum, int);
static void setParamiv(ALCcontext*, ALfilter*, ALenum, const int*);
static void setParamf(ALCcontext*, ALfilter*, ALenum, float);
static void setParamfv(ALCcontext*, 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*);
static void getParami(ALCcontext*, const ALfilter*, ALenum, int*);
static void getParamiv(ALCcontext*, const ALfilter*, ALenum, int*);
static void getParamf(ALCcontext*, const ALfilter*, ALenum, float*);
static void getParamfv(ALCcontext*, const ALfilter*, ALenum, float*);
private:
FilterTable() = default;
friend T;
};
struct NullFilterTable : public FilterTable<NullFilterTable> { };

View file

@ -31,11 +31,11 @@
#include "AL/efx.h"
#include "alc/context.h"
#include "alc/inprogext.h"
#include "alnumeric.h"
#include "alspan.h"
#include "core/except.h"
#include "core/logging.h"
#include "direct_defs.h"
#include "error.h"
#include "opthelpers.h"
namespace {
@ -54,7 +54,7 @@ inline void CommitAndUpdateProps(ALCcontext *context)
{
if(!context->mDeferUpdates)
{
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
if(context->eaxNeedsCommit())
{
context->mPropsDirty = true;
@ -79,22 +79,26 @@ try {
{
case AL_GAIN:
if(!(value >= 0.0f && std::isfinite(value)))
throw al::context_error{AL_INVALID_VALUE, "Listener gain out of range"};
context->throw_error(AL_INVALID_VALUE, "Listener gain {:f} out of range", value);
listener.Gain = value;
UpdateProps(context);
return;
case AL_METERS_PER_UNIT:
if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
throw al::context_error{AL_INVALID_VALUE, "Listener meters per unit out of range"};
context->throw_error(AL_INVALID_VALUE, "Listener meters per unit {:f} out of range",
value);
listener.mMetersPerUnit = value;
UpdateProps(context);
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener float property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener float property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC4(void, alListener3f, ALenum,param, ALfloat,value1, ALfloat,value2, ALfloat,value3)
@ -107,7 +111,7 @@ try {
{
case AL_POSITION:
if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
throw al::context_error{AL_INVALID_VALUE, "Listener position out of range"};
context->throw_error(AL_INVALID_VALUE, "Listener position out of range");
listener.Position[0] = value1;
listener.Position[1] = value2;
listener.Position[2] = value3;
@ -116,17 +120,20 @@ try {
case AL_VELOCITY:
if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
throw al::context_error{AL_INVALID_VALUE, "Listener velocity out of range"};
context->throw_error(AL_INVALID_VALUE, "Listener velocity out of range");
listener.Velocity[0] = value1;
listener.Velocity[1] = value2;
listener.Velocity[2] = value3;
CommitAndUpdateProps(context);
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener 3-float property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-float property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alListenerfv, ALenum,param, const ALfloat*,values)
@ -134,7 +141,7 @@ FORCE_ALIGN void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum para
const ALfloat *values) noexcept
try {
if(!values)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
switch(param)
{
@ -157,17 +164,20 @@ try {
case AL_ORIENTATION:
auto vals = al::span<const float,6>{values, 6_uz};
if(!std::all_of(vals.cbegin(), vals.cend(), [](float f) { return std::isfinite(f); }))
return context->setError(AL_INVALID_VALUE, "Listener orientation out of range");
context->throw_error(AL_INVALID_VALUE, "Listener orientation out of range");
/* AT then UP */
std::copy_n(vals.cbegin(), 3, listener.OrientAt.begin());
std::copy_n(vals.cbegin()+3, 3, listener.OrientUp.begin());
CommitAndUpdateProps(context);
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener float-vector property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener float-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -175,10 +185,13 @@ AL_API DECL_FUNC2(void, alListeneri, ALenum,param, ALint,value)
FORCE_ALIGN void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint /*value*/) noexcept
try {
std::lock_guard<std::mutex> proplock{context->mPropLock};
throw al::context_error{AL_INVALID_ENUM, "Invalid listener integer property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener integer property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC4(void, alListener3i, ALenum,param, ALint,value1, ALint,value2, ALint,value3)
@ -195,10 +208,13 @@ try {
}
std::lock_guard<std::mutex> proplock{context->mPropLock};
throw al::context_error{AL_INVALID_ENUM, "Invalid listener 3-integer property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-integer property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alListeneriv, ALenum,param, const ALint*,values)
@ -206,7 +222,7 @@ FORCE_ALIGN void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum para
const ALint *values) noexcept
try {
if(!values)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
al::span<const ALint> vals;
switch(param)
@ -229,11 +245,13 @@ try {
}
std::lock_guard<std::mutex> proplock{context->mPropLock};
throw al::context_error{AL_INVALID_ENUM, "Invalid listener integer-vector property 0x%x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener integer-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
@ -242,7 +260,7 @@ FORCE_ALIGN void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum pa
ALfloat *value) noexcept
try {
if(!value)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> proplock{context->mPropLock};
@ -251,10 +269,13 @@ try {
case AL_GAIN: *value = listener.Gain; return;
case AL_METERS_PER_UNIT: *value = listener.mMetersPerUnit; return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener float property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener float property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC4(void, alGetListener3f, ALenum,param, ALfloat*,value1, ALfloat*,value2, ALfloat*,value3)
@ -262,7 +283,7 @@ FORCE_ALIGN void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum p
ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept
try {
if(!value1 || !value2 || !value3)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> proplock{context->mPropLock};
@ -280,10 +301,13 @@ try {
*value3 = listener.Velocity[2];
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener 3-float property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-float property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alGetListenerfv, ALenum,param, ALfloat*,values)
@ -291,7 +315,7 @@ FORCE_ALIGN void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum p
ALfloat *values) noexcept
try {
if(!values)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
switch(param)
{
@ -318,22 +342,28 @@ try {
std::copy_n(listener.OrientUp.cbegin(), 3, vals.begin()+3);
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener float-vector property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener float-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alGetListeneri, ALenum,param, ALint*,value)
FORCE_ALIGN void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) noexcept
try {
if(!value) throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
if(!value) context->throw_error(AL_INVALID_VALUE, "NULL pointer");
std::lock_guard<std::mutex> proplock{context->mPropLock};
throw al::context_error{AL_INVALID_ENUM, "Invalid listener integer property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener integer property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC4(void, alGetListener3i, ALenum,param, ALint*,value1, ALint*,value2, ALint*,value3)
@ -341,7 +371,7 @@ FORCE_ALIGN void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum p
ALint *value1, ALint *value2, ALint *value3) noexcept
try {
if(!value1 || !value2 || !value3)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
ALlistener &listener = context->mListener;
std::lock_guard<std::mutex> proplock{context->mPropLock};
@ -359,10 +389,13 @@ try {
*value3 = static_cast<ALint>(listener.Velocity[2]);
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener 3-integer property 0x%x", param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-integer property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}
AL_API DECL_FUNC2(void, alGetListeneriv, ALenum,param, ALint*,values)
@ -370,7 +403,7 @@ FORCE_ALIGN void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum p
ALint *values) noexcept
try {
if(!values)
throw al::context_error{AL_INVALID_VALUE, "NULL pointer"};
context->throw_error(AL_INVALID_VALUE, "NULL pointer");
switch(param)
{
@ -394,9 +427,11 @@ try {
std::transform(listener.OrientUp.cbegin(), listener.OrientUp.cend(), vals.begin()+3, f2i);
return;
}
throw al::context_error{AL_INVALID_ENUM, "Invalid listener integer-vector property 0x%x",
param};
context->throw_error(AL_INVALID_ENUM, "Invalid listener integer-vector property {:#04x}",
as_unsigned(param));
}
catch(al::context_error& e) {
context->setError(e.errorCode(), "%s", e.what());
catch(al::base_exception&) {
}
catch(std::exception &e) {
ERR("Caught exception: {}", e.what());
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,8 @@
#ifndef AL_SOURCE_H
#define AL_SOURCE_H
#include "config.h"
#include <array>
#include <cstddef>
#include <cstdint>
@ -20,7 +22,7 @@
#include "core/context.h"
#include "core/voice.h"
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#include "eax/api.h"
#include "eax/call.h"
#include "eax/exception.h"
@ -45,12 +47,10 @@ inline bool sBufferSubDataCompat{false};
struct ALbufferQueueItem : public VoiceBufferItem {
ALbuffer *mBuffer{nullptr};
DISABLE_ALLOC
};
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
class EaxSourceException : public EaxException {
public:
explicit EaxSourceException(const char* message)
@ -71,7 +71,7 @@ struct ALsource {
float RefDistance{1.0f};
float MaxDistance{std::numeric_limits<float>::max()};
float RolloffFactor{1.0f};
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
// For EAXSOURCE_ROLLOFFFACTOR, which is distinct from and added to
// AL_ROLLOFF_FACTOR
float RolloffFactor2{0.0f};
@ -165,10 +165,10 @@ struct ALsource {
DISABLE_ALLOC
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
public:
void eaxInitialize(ALCcontext *context) noexcept;
void eaxDispatch(const EaxCall& call);
void eaxDispatch(const EaxCall& call) { call.is_get() ? eax_get(call) : eax_set(call); }
void eaxCommit();
void eaxMarkAsChanged() noexcept { mEaxChanged = true; }
@ -199,26 +199,23 @@ private:
using EaxSpeakerLevels = std::array<EAXSPEAKERLEVELPROPERTIES, eax_max_speakers>;
using EaxSends = std::array<EAXSOURCEALLSENDPROPERTIES, EAX_MAX_FXSLOTS>;
using Eax1Props = EAXBUFFER_REVERBPROPERTIES;
struct Eax1State {
Eax1Props i; // Immediate.
Eax1Props d; // Deferred.
EAXBUFFER_REVERBPROPERTIES i; // Immediate.
EAXBUFFER_REVERBPROPERTIES d; // Deferred.
};
using Eax2Props = EAX20BUFFERPROPERTIES;
struct Eax2State {
Eax2Props i; // Immediate.
Eax2Props d; // Deferred.
EAX20BUFFERPROPERTIES i; // Immediate.
EAX20BUFFERPROPERTIES d; // Deferred.
};
using Eax3Props = EAX30SOURCEPROPERTIES;
struct Eax3State {
Eax3Props i; // Immediate.
Eax3Props d; // Deferred.
EAX30SOURCEPROPERTIES i; // Immediate.
EAX30SOURCEPROPERTIES d; // Deferred.
};
struct Eax4Props {
Eax3Props source;
EAX30SOURCEPROPERTIES source;
EaxSends sends;
EAX40ACTIVEFXSLOTS active_fx_slots;
};
@ -490,14 +487,14 @@ private:
};
struct Eax1SourceAllValidator {
void operator()(const Eax1Props& props) const
void operator()(const EAXBUFFER_REVERBPROPERTIES& props) const
{
Eax1SourceReverbMixValidator{}(props.fMix);
}
};
struct Eax2SourceAllValidator {
void operator()(const Eax2Props& props) const
void operator()(const EAX20BUFFERPROPERTIES& props) const
{
Eax2SourceDirectValidator{}(props.lDirect);
Eax2SourceDirectHfValidator{}(props.lDirectHF);
@ -516,7 +513,7 @@ private:
};
struct Eax3SourceAllValidator {
void operator()(const Eax3Props& props) const
void operator()(const EAX30SOURCEPROPERTIES& props) const
{
Eax2SourceDirectValidator{}(props.lDirect);
Eax2SourceDirectHfValidator{}(props.lDirectHF);
@ -823,11 +820,11 @@ private:
[[noreturn]] static void eax_fail_unknown_receiving_fx_slot_id();
static void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept;
static void eax1_set_defaults(Eax1Props& props) noexcept;
static void eax1_set_defaults(EAXBUFFER_REVERBPROPERTIES& props) noexcept;
void eax1_set_defaults() noexcept;
static void eax2_set_defaults(Eax2Props& props) noexcept;
static void eax2_set_defaults(EAX20BUFFERPROPERTIES& props) noexcept;
void eax2_set_defaults() noexcept;
static void eax3_set_defaults(Eax3Props& props) noexcept;
static void eax3_set_defaults(EAX30SOURCEPROPERTIES& props) noexcept;
void eax3_set_defaults() noexcept;
static void eax4_set_sends_defaults(EaxSends& sends) noexcept;
static void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept;
@ -840,9 +837,9 @@ private:
void eax5_set_defaults() noexcept;
void eax_set_defaults() noexcept;
static void eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept;
static void eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept;
static void eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept;
static void eax1_translate(const EAXBUFFER_REVERBPROPERTIES& src, Eax5Props& dst) noexcept;
static void eax2_translate(const EAX20BUFFERPROPERTIES& src, Eax5Props& dst) noexcept;
static void eax3_translate(const EAX30SOURCEPROPERTIES& src, Eax5Props& dst) noexcept;
static void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept;
static float eax_calculate_dst_occlusion_mb(
@ -907,12 +904,12 @@ private:
}
static void eax_get_active_fx_slot_id(const EaxCall& call, const al::span<const GUID> src_ids);
static void eax1_get(const EaxCall& call, const Eax1Props& props);
static void eax2_get(const EaxCall& call, const Eax2Props& props);
static void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props);
static void eax3_get_occlusion(const EaxCall& call, const Eax3Props& props);
static void eax3_get_exclusion(const EaxCall& call, const Eax3Props& props);
static void eax3_get(const EaxCall& call, const Eax3Props& props);
static void eax1_get(const EaxCall& call, const EAXBUFFER_REVERBPROPERTIES& props);
static void eax2_get(const EaxCall& call, const EAX20BUFFERPROPERTIES& props);
static void eax3_get_obstruction(const EaxCall& call, const EAX30SOURCEPROPERTIES& props);
static void eax3_get_occlusion(const EaxCall& call, const EAX30SOURCEPROPERTIES& props);
static void eax3_get_exclusion(const EaxCall& call, const EAX30SOURCEPROPERTIES& props);
static void eax3_get(const EaxCall& call, const EAX30SOURCEPROPERTIES& props);
void eax4_get(const EaxCall& call, const Eax4Props& props);
static void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props);
static void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props);
@ -1034,9 +1031,9 @@ private:
void eax_set_efx_wet_gain_auto();
void eax_set_efx_wet_gain_hf_auto();
static void eax1_set(const EaxCall& call, Eax1Props& props);
static void eax2_set(const EaxCall& call, Eax2Props& props);
void eax3_set(const EaxCall& call, Eax3Props& props);
static void eax1_set(const EaxCall& call, EAXBUFFER_REVERBPROPERTIES& props);
static void eax2_set(const EaxCall& call, EAX20BUFFERPROPERTIES& props);
void eax3_set(const EaxCall& call, EAX30SOURCEPROPERTIES& props);
void eax4_set(const EaxCall& call, Eax4Props& props);
static void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props);
static void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props);

View file

@ -40,6 +40,7 @@
#include "al/listener.h"
#include "alc/alu.h"
#include "alc/context.h"
#include "alc/device.h"
#include "alc/inprogext.h"
#include "alnumeric.h"
#include "atomic.h"
@ -52,9 +53,7 @@
#include "opthelpers.h"
#include "strutils.h"
#ifdef ALSOFT_EAX
#include "alc/device.h"
#if ALSOFT_EAX
#include "eax/globals.h"
#include "eax/x_ram.h"
#endif // ALSOFT_EAX
@ -62,6 +61,8 @@
namespace {
using ALvoidptr = ALvoid*;
[[nodiscard]] constexpr auto GetVendorString() noexcept { return "OpenAL Community"; }
[[nodiscard]] constexpr auto GetVersionString() noexcept { return "1.1 ALSOFT " ALSOFT_VERSION; }
[[nodiscard]] constexpr auto GetRendererString() noexcept { return "OpenAL Soft"; }
@ -94,6 +95,10 @@ template<> struct ResamplerName<Resampler::FastBSinc24>
{ static constexpr const ALchar *Get() noexcept { return "23rd order Sinc (fast)"; } };
template<> struct ResamplerName<Resampler::BSinc24>
{ static constexpr const ALchar *Get() noexcept { return "23rd order Sinc"; } };
template<> struct ResamplerName<Resampler::FastBSinc48>
{ static constexpr const ALchar *Get() noexcept { return "47th order Sinc (fast)"; } };
template<> struct ResamplerName<Resampler::BSinc48>
{ static constexpr const ALchar *Get() noexcept { return "47th order Sinc"; } };
const ALchar *GetResamplerName(const Resampler rtype)
{
@ -108,6 +113,8 @@ const ALchar *GetResamplerName(const Resampler rtype)
HANDLE_RESAMPLER(Resampler::BSinc12);
HANDLE_RESAMPLER(Resampler::FastBSinc24);
HANDLE_RESAMPLER(Resampler::BSinc24);
HANDLE_RESAMPLER(Resampler::FastBSinc48);
HANDLE_RESAMPLER(Resampler::BSinc48);
}
#undef HANDLE_RESAMPLER
/* Should never get here. */
@ -144,24 +151,24 @@ constexpr auto ALenumFromDistanceModel(DistanceModel model) -> ALenum
}
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,
DopplerFactorProp = AL_DOPPLER_FACTOR,
DopplerVelocityProp = AL_DOPPLER_VELOCITY,
DistanceModelProp = AL_DISTANCE_MODEL,
SpeedOfSoundProp = AL_SPEED_OF_SOUND,
DeferredUpdatesProp = AL_DEFERRED_UPDATES_SOFT,
GainLimitProp = AL_GAIN_LIMIT_SOFT,
NumResamplersProp = AL_NUM_RESAMPLERS_SOFT,
DefaultResamplerProp = AL_DEFAULT_RESAMPLER_SOFT,
DebugLoggedMessagesProp = AL_DEBUG_LOGGED_MESSAGES_EXT,
DebugNextLoggedMessageLengthProp = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT,
MaxDebugMessageLengthProp = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT,
MaxDebugLoggedMessagesProp = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT,
MaxDebugGroupDepthProp = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT,
MaxLabelLengthProp = AL_MAX_LABEL_LENGTH_EXT,
ContextFlagsProp = AL_CONTEXT_FLAGS_EXT,
#if ALSOFT_EAX
EaxRamSizeProp = AL_EAX_RAM_SIZE,
EaxRamFreeProp = AL_EAX_RAM_FREE,
#endif
};
@ -259,7 +266,7 @@ void GetValue(ALCcontext *context, ALenum pname, T *values)
*values = cast_value(context->mContextFlags.to_ulong());
return;
#ifdef ALSOFT_EAX
#if ALSOFT_EAX
#define EAX_ERROR "[alGetInteger] EAX not enabled"
case AL_EAX_RAM_SIZE:
@ -268,7 +275,7 @@ void GetValue(ALCcontext *context, ALenum pname, T *values)
*values = cast_value(eax_x_ram_max_size);
return;
}
ERR(EAX_ERROR "\n");
ERR(EAX_ERROR);
break;
case AL_EAX_RAM_FREE:
@ -279,13 +286,13 @@ void GetValue(ALCcontext *context, ALenum pname, T *values)
*values = cast_value(device->eax_x_ram_free_size);
return;
}
ERR(EAX_ERROR "\n");
ERR(EAX_ERROR);
break;
#undef EAX_ERROR
#endif // ALSOFT_EAX
}
context->setError(AL_INVALID_ENUM, "Invalid context property 0x%04x", pname);
context->setError(AL_INVALID_ENUM, "Invalid context property {:#04x}", as_unsigned(pname));
}
@ -331,7 +338,8 @@ FORCE_ALIGN void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capabili
context->setError(AL_INVALID_OPERATION, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported");
return;
}
context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
context->setError(AL_INVALID_VALUE, "Invalid enable property {:#04x}",
as_unsigned(capability));
}
AL_API DECL_FUNC1(void, alDisable, ALenum,capability)
@ -355,7 +363,8 @@ FORCE_ALIGN void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capabil
context->mStopVoicesOnDisconnect.store(false);
return;
}
context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
context->setError(AL_INVALID_VALUE, "Invalid disable property {:#04x}",
as_unsigned(capability));
}
AL_API DECL_FUNC1(ALboolean, alIsEnabled, ALenum,capability)
@ -369,14 +378,15 @@ FORCE_ALIGN ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum
case AL_STOP_SOURCES_ON_DISCONNECT_SOFT:
return context->mStopVoicesOnDisconnect.load() ? AL_TRUE : AL_FALSE;
}
context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
context->setError(AL_INVALID_VALUE, "Invalid is enabled property {:#04x}",
as_unsigned(capability));
return AL_FALSE;
}
#define DECL_GETFUNC(R, Name, Ext) \
AL_API auto AL_APIENTRY Name##Ext(ALenum pname) noexcept -> R \
auto AL_APIENTRY Name##Ext(ALenum pname) noexcept -> R \
{ \
R value{}; \
auto value = R{}; \
auto context = GetContextRef(); \
if(!context) UNLIKELY return value; \
Name##vDirect##Ext(GetContextRef().get(), pname, &value); \
@ -384,18 +394,19 @@ AL_API auto AL_APIENTRY Name##Ext(ALenum pname) noexcept -> R \
} \
FORCE_ALIGN auto AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept -> R \
{ \
R value{}; \
auto value = R{}; \
Name##vDirect##Ext(context, pname, &value); \
return value; \
}
DECL_GETFUNC(ALboolean, alGetBoolean,)
DECL_GETFUNC(ALdouble, alGetDouble,)
DECL_GETFUNC(ALfloat, alGetFloat,)
DECL_GETFUNC(ALint, alGetInteger,)
AL_API DECL_GETFUNC(ALboolean, alGetBoolean,)
AL_API DECL_GETFUNC(ALdouble, alGetDouble,)
AL_API DECL_GETFUNC(ALfloat, alGetFloat,)
AL_API DECL_GETFUNC(ALint, alGetInteger,)
DECL_GETFUNC(ALint64SOFT, alGetInteger64,SOFT)
DECL_GETFUNC(ALvoid*, alGetPointer,SOFT)
DECL_GETFUNC(ALvoidptr, alGetPointer,EXT)
AL_API DECL_GETFUNC(ALint64SOFT, alGetInteger64,SOFT)
AL_API DECL_GETFUNC(ALvoidptr, alGetPointer,SOFT)
#undef DECL_GETFUNC
@ -442,6 +453,10 @@ FORCE_ALIGN void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALen
AL_API DECL_FUNCEXT2(void, alGetPointerv,SOFT, ALenum,pname, ALvoid**,values)
FORCE_ALIGN void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, ALvoid **values) noexcept
{ return alGetPointervDirectEXT(context, pname, values); }
FORCE_ALIGN DECL_FUNCEXT2(void, alGetPointerv,EXT, ALenum,pname, ALvoid**,values)
FORCE_ALIGN void AL_APIENTRY alGetPointervDirectEXT(ALCcontext *context, ALenum pname, ALvoid **values) noexcept
{
if(!values) UNLIKELY
return context->setError(AL_INVALID_VALUE, "NULL pointer");
@ -464,7 +479,8 @@ FORCE_ALIGN void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum
*values = context->mDebugParam;
return;
}
context->setError(AL_INVALID_ENUM, "Invalid context pointer property 0x%04x", pname);
context->setError(AL_INVALID_ENUM, "Invalid context pointer property {:#04x}",
as_unsigned(pname));
}
AL_API DECL_FUNC1(const ALchar*, alGetString, ALenum,pname)
@ -472,9 +488,18 @@ FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALe
{
switch(pname)
{
case AL_VENDOR: return GetVendorString();
case AL_VERSION: return GetVersionString();
case AL_RENDERER: return GetRendererString();
case AL_VENDOR:
if(auto device = context->mALDevice.get(); !device->mVendorOverride.empty())
return device->mVendorOverride.c_str();
return GetVendorString();
case AL_VERSION:
if(auto device = context->mALDevice.get(); !device->mVersionOverride.empty())
return device->mVersionOverride.c_str();
return GetVersionString();
case AL_RENDERER:
if(auto device = context->mALDevice.get(); !device->mRendererOverride.empty())
return device->mRendererOverride.c_str();
return GetRendererString();
case AL_EXTENSIONS: return context->mExtensionsString.c_str();
case AL_NO_ERROR: return GetNoErrorString();
case AL_INVALID_NAME: return GetInvalidNameString();
@ -485,7 +510,7 @@ FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALe
case AL_STACK_OVERFLOW_EXT: return GetStackOverflowString();
case AL_STACK_UNDERFLOW_EXT: return GetStackUnderflowString();
}
context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
context->setError(AL_INVALID_VALUE, "Invalid string property {:#04x}", as_unsigned(pname));
return nullptr;
}
@ -493,7 +518,7 @@ AL_API DECL_FUNC1(void, alDopplerFactor, ALfloat,value)
FORCE_ALIGN void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) noexcept
{
if(!(value >= 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
context->setError(AL_INVALID_VALUE, "Doppler factor {:f} out of range", value);
else
{
std::lock_guard<std::mutex> proplock{context->mPropLock};
@ -506,7 +531,7 @@ AL_API DECL_FUNC1(void, alSpeedOfSound, ALfloat,value)
FORCE_ALIGN void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) noexcept
{
if(!(value > 0.0f && std::isfinite(value)))
context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
context->setError(AL_INVALID_VALUE, "Speed of sound {:f} out of range", value);
else
{
std::lock_guard<std::mutex> proplock{context->mPropLock};
@ -526,7 +551,8 @@ FORCE_ALIGN void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum v
UpdateProps(context);
}
else
context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
context->setError(AL_INVALID_VALUE, "Distance model {:#04x} out of range",
as_unsigned(value));
}
@ -551,12 +577,13 @@ FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context
switch(pname)
{
case AL_RESAMPLER_NAME_SOFT:
if(index >= 0 && index <= static_cast<ALint>(Resampler::Max))
if(index >= 0 && index <= al::to_underlying(Resampler::Max))
return GetResamplerName(static_cast<Resampler>(index));
context->setError(AL_INVALID_VALUE, "Resampler name index %d out of range", index);
context->setError(AL_INVALID_VALUE, "Resampler name index {} out of range", index);
return nullptr;
}
context->setError(AL_INVALID_VALUE, "Invalid string indexed property");
context->setError(AL_INVALID_VALUE, "Invalid string indexed property {:#04x}",
as_unsigned(pname));
return nullptr;
}
@ -567,13 +594,13 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept
if(!context) UNLIKELY return;
if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY
context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0,
context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 1,
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);
context->setError(AL_INVALID_VALUE, "Doppler velocity {:f} out of range", value);
else
{
std::lock_guard<std::mutex> proplock{context->mPropLock};
@ -611,6 +638,9 @@ void UpdateContextProps(ALCcontext *context)
props->DopplerFactor = context->mDopplerFactor;
props->DopplerVelocity = context->mDopplerVelocity;
props->SpeedOfSound = context->mSpeedOfSound;
#if ALSOFT_EAX
props->DistanceFactor = context->eaxGetDistanceFactor();
#endif
props->SourceDistanceModel = context->mSourceDistanceModel;
props->mDistanceModel = context->mDistanceModel;