update OpenAL-Soft to 1.24.3.

This commit is contained in:
Sasha Szpakowski
2025-05-03 12:51:37 -03:00
parent 375c6f88cd
commit 5e4f3241ac
322 changed files with 54386 additions and 12885 deletions
File diff suppressed because it is too large Load Diff
+72 -66
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)
@@ -37,10 +40,8 @@ public:
};
#endif // ALSOFT_EAX
enum class SlotState : ALenum {
Initial = AL_INITIAL,
Playing = AL_PLAYING,
Stopped = AL_STOPPED,
enum class SlotState : bool {
Initial, Playing,
};
struct ALeffectslot {
@@ -52,7 +53,7 @@ struct ALeffectslot {
struct EffectData {
EffectSlotType Type{EffectSlotType::None};
EffectProps Props{};
EffectProps Props;
al::intrusive_ptr<EffectState> State;
};
@@ -69,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();
@@ -81,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
@@ -96,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 {
@@ -194,6 +195,17 @@ private:
}
};
struct Eax5FlagsValidator {
void operator()(unsigned long ulFlags) const
{
EaxRangeValidator{}(
"Flags",
ulFlags,
0UL,
~EAX50FXSLOTFLAGS_RESERVED);
}
};
struct Eax5OcclusionValidator {
void operator()(long lOcclusion) const
{
@@ -216,35 +228,27 @@ private:
}
};
struct Eax5FlagsValidator {
void operator()(unsigned long ulFlags) const
{
EaxRangeValidator{}(
"Flags",
ulFlags,
0UL,
~EAX50FXSLOTFLAGS_RESERVED);
}
};
struct Eax5AllValidator {
void operator()(const EAX50FXSLOTPROPERTIES& all) const
{
Eax4AllValidator{}(static_cast<const EAX40FXSLOTPROPERTIES&>(all));
Eax4GuidLoadEffectValidator{}(all.guidLoadEffect);
Eax4VolumeValidator{}(all.lVolume);
Eax4LockValidator{}(all.lLock);
Eax5FlagsValidator{}(all.ulFlags);
Eax5OcclusionValidator{}(all.lOcclusion);
Eax5OcclusionLfRatioValidator{}(all.flOcclusionLFRatio);
}
};
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();
@@ -255,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;
}
@@ -268,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;
@@ -287,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);
@@ -320,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);
@@ -359,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
+4 -2
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
+157 -143
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,29 +536,30 @@ 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);
if(identifier == AL_SOURCE_EXT)
return ALsource::SetName(context, name, objname);
if(identifier == AL_BUFFER)
return ALbuffer::SetName(context, name, objname);
if(identifier == AL_FILTER_EXT)
return ALfilter::SetName(context, name, objname);
if(identifier == AL_EFFECT_EXT)
return ALeffect::SetName(context, name, objname);
if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT)
return ALeffectslot::SetName(context, name, objname);
switch(identifier)
{
case AL_SOURCE_EXT: ALsource::SetName(context, name, objname); return;
case AL_BUFFER: ALbuffer::SetName(context, name, objname); return;
case AL_FILTER_EXT: ALfilter::SetName(context, name, objname); return;
case AL_EFFECT_EXT: ALeffect::SetName(context, name, objname); return;
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)
@@ -556,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)
@@ -591,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)
@@ -613,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());
}
+49 -47
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,
+29 -23
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)
+35 -20
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_{};
+7 -2
View File
@@ -10,9 +10,14 @@ class EaxException : public std::runtime_error {
static std::string make_message(std::string_view context, std::string_view message);
public:
EaxException() = delete;
EaxException(const EaxException&) = default;
EaxException(EaxException&&) = default;
EaxException(std::string_view context, std::string_view message);
~EaxException() override;
}; // EaxException
auto operator=(const EaxException&) -> EaxException& = default;
auto operator=(EaxException&&) -> EaxException& = default;
};
#endif // !EAX_EXCEPTION_INCLUDED
#endif /* EAX_EXCEPTION_INCLUDED */
+1 -4
View File
@@ -6,13 +6,10 @@
#include "al/auxeffectslot.h"
#include "api.h"
#include "call.h"
#include "fx_slot_index.h"
class EaxFxSlots
{
class EaxFxSlots {
public:
void initialize(ALCcontext& al_context);
+2 -3
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.");
}
}
+3 -69
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
-5
View File
@@ -24,12 +24,7 @@ constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC";
constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE";
constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE";
/* NOLINTBEGIN(readability-inconsistent-declaration-parameter-name)
* These functions are defined using macros to forward them in a generic way to
* implementation functions, which gives the parameters generic names.
*/
ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buffers, ALint value) noexcept;
ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint *pReserved) noexcept;
/* NOLINTEND(readability-inconsistent-declaration-parameter-name) */
#endif // !EAX_X_RAM_INCLUDED
+150 -133
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"
@@ -109,11 +109,38 @@ constexpr auto GetDefaultProps(ALenum type) noexcept -> const EffectProps&
void InitEffectParams(ALeffect *effect, ALenum type) noexcept
{
switch(type)
{
case AL_EFFECT_NULL: effect->PropsVariant.emplace<NullEffectHandler>(); break;
case AL_EFFECT_EAXREVERB: effect->PropsVariant.emplace<ReverbEffectHandler>(); break;
case AL_EFFECT_REVERB: effect->PropsVariant.emplace<StdReverbEffectHandler>(); break;
case AL_EFFECT_AUTOWAH: effect->PropsVariant.emplace<AutowahEffectHandler>(); break;
case AL_EFFECT_CHORUS: effect->PropsVariant.emplace<ChorusEffectHandler>(); break;
case AL_EFFECT_COMPRESSOR: effect->PropsVariant.emplace<CompressorEffectHandler>(); break;
case AL_EFFECT_DISTORTION: effect->PropsVariant.emplace<DistortionEffectHandler>(); break;
case AL_EFFECT_ECHO: effect->PropsVariant.emplace<EchoEffectHandler>(); break;
case AL_EFFECT_EQUALIZER: effect->PropsVariant.emplace<EqualizerEffectHandler>(); break;
case AL_EFFECT_FLANGER: effect->PropsVariant.emplace<ChorusEffectHandler>(); break;
case AL_EFFECT_FREQUENCY_SHIFTER: effect->PropsVariant.emplace<FshifterEffectHandler>(); break;
case AL_EFFECT_RING_MODULATOR: effect->PropsVariant.emplace<ModulatorEffectHandler>(); break;
case AL_EFFECT_PITCH_SHIFTER: effect->PropsVariant.emplace<PshifterEffectHandler>(); break;
case AL_EFFECT_VOCAL_MORPHER: effect->PropsVariant.emplace<VmorpherEffectHandler>(); break;
case AL_EFFECT_DEDICATED_DIALOGUE:
effect->PropsVariant.emplace<DedicatedDialogEffectHandler>();
break;
case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT:
effect->PropsVariant.emplace<DedicatedLfeEffectHandler>();
break;
case AL_EFFECT_CONVOLUTION_SOFT:
effect->PropsVariant.emplace<ConvolutionEffectHandler>();
break;
}
effect->Props = GetDefaultProps(type);
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
@@ -136,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
@@ -156,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);
@@ -169,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};
@@ -188,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)
@@ -210,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
@@ -223,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
@@ -233,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;
@@ -251,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)
{
@@ -266,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);
@@ -275,19 +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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbSetParami(arg, param, value);
}
return EffectHandler::SetParami(arg, param, value);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)
@@ -301,93 +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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbSetParamiv(arg, param, values);
}
return EffectHandler::SetParamiv(arg, param, values);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbSetParamf(arg, param, value);
}
return EffectHandler::SetParamf(arg, param, value);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbSetParamfv(arg, param, values);
}
return EffectHandler::SetParamfv(arg, param, values);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)
{
@@ -397,19 +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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbGetParami(arg, param, value);
}
return EffectHandler::GetParami(arg, param, value);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)
@@ -423,81 +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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbGetParamiv(arg, param, values);
}
return EffectHandler::GetParamiv(arg, param, values);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbGetParamf(arg, param, value);
}
return EffectHandler::GetParamf(arg, param, value);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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)>>;
if constexpr(std::is_same_v<Type,ReverbProps>)
{
if(aleffect->type == AL_EFFECT_REVERB)
return EffectHandler::StdReverbGetParamfv(arg, param, values);
}
return EffectHandler::GetParamfv(arg, param, values);
}, aleffect->Props);
using PropType = typename Type::prop_type;
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());
}
@@ -508,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);
}
@@ -679,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;
}
@@ -694,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;
@@ -727,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
+10 -2
View File
@@ -6,6 +6,7 @@
#include <cstdint>
#include <string_view>
#include <utility>
#include <variant>
#include "AL/al.h"
#include "AL/alc.h"
@@ -14,6 +15,7 @@
#include "almalloc.h"
#include "alnumeric.h"
#include "core/effects/base.h"
#include "effects/effects.h"
enum {
@@ -42,14 +44,20 @@ 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,
DistortionEffectHandler,EchoEffectHandler,EqualizerEffectHandler,FlangerEffectHandler,
FshifterEffectHandler,ModulatorEffectHandler,PshifterEffectHandler,VmorpherEffectHandler,
DedicatedDialogEffectHandler,DedicatedLfeEffectHandler,ConvolutionEffectHandler>;
struct ALeffect {
// Effect type (AL_EFFECT_NULL, ...)
ALenum type{AL_EFFECT_NULL};
EffectProps Props{};
EffectHandlerVariant PropsVariant;
EffectProps Props;
/* Self ID */
ALuint id{0u};
+35 -44
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 EffectHandler::SetParami(AutowahProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::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 EffectHandler::SetParamfv(AutowahProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const AutowahProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::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 EffectHandler::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>;
+108 -97
View File
@@ -7,13 +7,13 @@
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "alc/context.h"
#include "alnumeric.h"
#include "core/logging.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"
@@ -44,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
@@ -61,7 +62,7 @@ constexpr EffectProps genDefaultChorusProps() noexcept
constexpr EffectProps genDefaultFlangerProps() noexcept
{
FlangerProps props{};
ChorusProps props{};
props.Waveform = WaveformFromEnum(AL_FLANGER_DEFAULT_WAVEFORM).value();
props.Phase = AL_FLANGER_DEFAULT_PHASE;
props.Rate = AL_FLANGER_DEFAULT_RATE;
@@ -75,7 +76,7 @@ constexpr EffectProps genDefaultFlangerProps() noexcept
const EffectProps ChorusEffectProps{genDefaultChorusProps()};
void EffectHandler::SetParami(ChorusProps &props, ALenum param, int val)
void ChorusEffectHandler::SetParami(ALCcontext *context, ChorusProps &props, ALenum param, int val)
{
switch(param)
{
@@ -83,89 +84,90 @@ void EffectHandler::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 EffectHandler::SetParamiv(ChorusProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::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 EffectHandler::SetParamfv(ChorusProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::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 EffectHandler::GetParamiv(const ChorusProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void EffectHandler::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 EffectHandler::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 EffectHandler::SetParami(FlangerProps &props, ALenum param, int val)
void FlangerEffectHandler::SetParami(ALCcontext *context, ChorusProps &props, ALenum param, int val)
{
switch(param)
{
@@ -173,93 +175,93 @@ void EffectHandler::SetParami(FlangerProps &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 EffectHandler::SetParamiv(FlangerProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::SetParamf(FlangerProps &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 EffectHandler::SetParamfv(FlangerProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const FlangerProps &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 EffectHandler::GetParamiv(const FlangerProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void EffectHandler::GetParamf(const FlangerProps &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 EffectHandler::GetParamfv(const FlangerProps &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 {
using EaxProps = EAXCHORUSPROPERTIES;
using Committer = EaxChorusCommitter;
using AlProps = ChorusProps;
static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; }
@@ -325,7 +327,6 @@ struct EaxChorusTraits {
struct EaxFlangerTraits {
using EaxProps = EAXFLANGERPROPERTIES;
using Committer = EaxFlangerCommitter;
using AlProps = FlangerProps;
static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; }
@@ -393,7 +394,6 @@ struct ChorusFlangerEffect {
using Traits = TTraits;
using EaxProps = typename Traits::EaxProps;
using Committer = typename Traits::Committer;
using AlProps = typename Traits::AlProps;
using Exception = typename Committer::Exception;
struct WaveformValidator {
@@ -551,7 +551,7 @@ public:
}
}
static bool Commit(const EaxProps &props, EaxEffectProps &props_, AlProps &al_props_)
static bool Commit(const EaxProps &props, EaxEffectProps &props_, ChorusProps &al_props_)
{
if(auto *cur = std::get_if<EaxProps>(&props_); cur && *cur == props)
return false;
@@ -564,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;
}
@@ -628,7 +639,7 @@ template<>
bool EaxFlangerCommitter::commit(const EAXFLANGERPROPERTIES &props)
{
using Committer = ChorusFlangerEffect<EaxFlangerTraits>;
return Committer::Commit(props, mEaxProps, mAlProps.emplace<FlangerProps>());
return Committer::Commit(props, mEaxProps, mAlProps.emplace<ChorusProps>());
}
void EaxFlangerCommitter::SetDefaults(EaxEffectProps &props)
+28 -38
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,56 +28,46 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps CompressorEffectProps{genDefaultProps()};
void EffectHandler::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 EffectHandler::SetParamiv(CompressorProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::SetParamf(CompressorProps&, ALenum param, float)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
void EffectHandler::SetParamfv(CompressorProps&, ALenum param, const float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
param};
}
void EffectHandler::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 EffectHandler::GetParamiv(const CompressorProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void EffectHandler::GetParamf(const CompressorProps&, ALenum param, float*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
void EffectHandler::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>;
+27 -68
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 EffectHandler::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 EffectHandler::SetParamiv(ConvolutionProps &props, ALenum param, const int *vals)
{
switch(param)
{
default:
SetParami(props, param, *vals);
}
}
void EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::GetParamiv(const ConvolutionProps &props, ALenum param, int *vals)
{
switch(param)
{
default:
GetParami(props, param, vals);
}
}
void EffectHandler::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 EffectHandler::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);
}
+52 -59
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"
@@ -14,14 +15,16 @@ namespace {
constexpr EffectProps genDefaultDialogProps() noexcept
{
DedicatedDialogProps props{};
DedicatedProps props{};
props.Target = DedicatedProps::Dialog;
props.Gain = 1.0f;
return props;
}
constexpr EffectProps genDefaultLfeProps() noexcept
{
DedicatedLfeProps props{};
DedicatedProps props{};
props.Target = DedicatedProps::Lfe;
props.Gain = 1.0f;
return props;
}
@@ -30,91 +33,81 @@ constexpr EffectProps genDefaultLfeProps() noexcept
const EffectProps DedicatedDialogEffectProps{genDefaultDialogProps()};
void EffectHandler::SetParami(DedicatedDialogProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void EffectHandler::SetParamiv(DedicatedDialogProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x",
param};
}
void EffectHandler::SetParamf(DedicatedDialogProps &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 EffectHandler::SetParamfv(DedicatedDialogProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const DedicatedDialogProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void EffectHandler::GetParamiv(const DedicatedDialogProps&, 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 EffectHandler::GetParamf(const DedicatedDialogProps &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 EffectHandler::GetParamfv(const DedicatedDialogProps &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 EffectHandler::SetParami(DedicatedLfeProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void EffectHandler::SetParamiv(DedicatedLfeProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x",
param};
}
void EffectHandler::SetParamf(DedicatedLfeProps &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 EffectHandler::SetParamfv(DedicatedLfeProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const DedicatedLfeProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; }
void EffectHandler::GetParamiv(const DedicatedLfeProps&, 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 EffectHandler::GetParamf(const DedicatedLfeProps &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 EffectHandler::GetParamfv(const DedicatedLfeProps &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); }
+41 -45
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 EffectHandler::SetParami(DistortionProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; }
void EffectHandler::SetParamiv(DistortionProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x",
param};
}
void EffectHandler::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 EffectHandler::SetParamfv(DistortionProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const DistortionProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::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 EffectHandler::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>;
+40 -40
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 EffectHandler::SetParami(EchoProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
void EffectHandler::SetParamiv(EchoProps&, ALenum param, const int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::SetParamfv(EchoProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const EchoProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
void EffectHandler::GetParamiv(const EchoProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::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>;
+49 -58
View File
@@ -3,71 +3,62 @@
#include <variant>
#include "AL/alc.h"
#include "AL/al.h"
#include "al/error.h"
#include "core/effects/base.h"
#include "opthelpers.h"
struct EffectHandler {
#define DECL_HANDLER(T) \
static void SetParami(T &props, ALenum param, int val); \
static void SetParamiv(T &props, ALenum param, const int *vals); \
static void SetParamf(T &props, ALenum param, float val); \
static void SetParamfv(T &props, ALenum param, const float *vals); \
static void GetParami(const T &props, ALenum param, int *val); \
static void GetParamiv(const T &props, ALenum param, int *vals); \
static void GetParamf(const T &props, ALenum param, float *val); \
static void GetParamfv(const T &props, ALenum param, float *vals);
DECL_HANDLER(std::monostate)
DECL_HANDLER(ReverbProps)
DECL_HANDLER(ChorusProps)
DECL_HANDLER(AutowahProps)
DECL_HANDLER(CompressorProps)
DECL_HANDLER(ConvolutionProps)
DECL_HANDLER(DedicatedDialogProps)
DECL_HANDLER(DedicatedLfeProps)
DECL_HANDLER(DistortionProps)
DECL_HANDLER(EchoProps)
DECL_HANDLER(EqualizerProps)
DECL_HANDLER(FlangerProps)
DECL_HANDLER(FshifterProps)
DECL_HANDLER(ModulatorProps)
DECL_HANDLER(PshifterProps)
DECL_HANDLER(VmorpherProps)
#undef DECL_HANDLER
static void StdReverbSetParami(ReverbProps &props, ALenum param, int val);
static void StdReverbSetParamiv(ReverbProps &props, ALenum param, const int *vals);
static void StdReverbSetParamf(ReverbProps &props, ALenum param, float val);
static void StdReverbSetParamfv(ReverbProps &props, ALenum param, const float *vals);
static void StdReverbGetParami(const ReverbProps &props, ALenum param, int *val);
static void StdReverbGetParamiv(const ReverbProps &props, ALenum param, int *vals);
static void StdReverbGetParamf(const ReverbProps &props, ALenum param, float *val);
static void StdReverbGetParamfv(const ReverbProps &props, ALenum param, float *vals);
#define DECL_HANDLER(N, T) \
struct N { \
using prop_type = T; \
\
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);\
};
using effect_exception = al::context_error;
DECL_HANDLER(NullEffectHandler, std::monostate)
DECL_HANDLER(ReverbEffectHandler, ReverbProps)
DECL_HANDLER(StdReverbEffectHandler, ReverbProps)
DECL_HANDLER(AutowahEffectHandler, AutowahProps)
DECL_HANDLER(ChorusEffectHandler, ChorusProps)
DECL_HANDLER(CompressorEffectHandler, CompressorProps)
DECL_HANDLER(DistortionEffectHandler, DistortionProps)
DECL_HANDLER(EchoEffectHandler, EchoProps)
DECL_HANDLER(EqualizerEffectHandler, EqualizerProps)
DECL_HANDLER(FlangerEffectHandler, ChorusProps)
DECL_HANDLER(FshifterEffectHandler, FshifterProps)
DECL_HANDLER(ModulatorEffectHandler, ModulatorProps)
DECL_HANDLER(PshifterEffectHandler, PshifterProps)
DECL_HANDLER(VmorpherEffectHandler, VmorpherProps)
DECL_HANDLER(DedicatedDialogEffectHandler, DedicatedProps)
DECL_HANDLER(DedicatedLfeEffectHandler, DedicatedProps)
DECL_HANDLER(ConvolutionEffectHandler, ConvolutionProps)
#undef DECL_HANDLER
/* 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 */
+54 -60
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 EffectHandler::SetParami(EqualizerProps&, ALenum param, int)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
void EffectHandler::SetParamiv(EqualizerProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
param};
}
void EffectHandler::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 EffectHandler::SetParamfv(EqualizerProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::GetParami(const EqualizerProps&, ALenum param, int*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::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 EffectHandler::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>;
+44 -49
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 EffectHandler::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 EffectHandler::SetParami(FshifterProps &props, ALenum param, int val)
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 EffectHandler::SetParamiv(FshifterProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::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 EffectHandler::SetParamfv(FshifterProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::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 EffectHandler::GetParamiv(const FshifterProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void EffectHandler::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 EffectHandler::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>;
+48 -47
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 EffectHandler::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 EffectHandler::SetParamiv(ModulatorProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::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 EffectHandler::SetParamfv(ModulatorProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::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 EffectHandler::GetParamiv(const ModulatorProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void EffectHandler::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 EffectHandler::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>;
+24 -55
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 EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::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>;
+30 -38
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 EffectHandler::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 EffectHandler::SetParamiv(PshifterProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::SetParamf(PshifterProps&, ALenum param, float)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; }
void EffectHandler::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 EffectHandler::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 EffectHandler::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 EffectHandler::GetParamf(const PshifterProps&, ALenum param, float*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; }
void EffectHandler::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>;
+192 -181
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 EffectHandler::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 EffectHandler::SetParamiv(ReverbProps &props, ALenum param, const int *vals)
{ SetParami(props, param, *vals); }
void EffectHandler::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 EffectHandler::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 EffectHandler::SetParamfv(ReverbProps &props, ALenum param, const float *va
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 EffectHandler::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 EffectHandler::GetParamiv(const ReverbProps &props, ALenum param, int *vals)
{ GetParami(props, param, vals); }
void EffectHandler::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 EffectHandler::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,173 +308,155 @@ void EffectHandler::GetParamfv(const ReverbProps &props, ALenum param, float *va
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 EffectHandler::StdReverbSetParami(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 EffectHandler::StdReverbSetParamiv(ReverbProps &props, ALenum param, const int *vals)
{ StdReverbSetParami(props, param, *vals); }
void EffectHandler::StdReverbSetParamf(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;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}",
as_unsigned(param));
}
void EffectHandler::StdReverbSetParamfv(ReverbProps &props, ALenum param, const float *vals)
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)
{
default:
StdReverbSetParamf(props, param, *vals);
break;
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 EffectHandler::StdReverbGetParami(const ReverbProps &props, ALenum param, int *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_DECAY_HFLIMIT: *val = props.DecayHFLimit; break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer 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;
}
}
void EffectHandler::StdReverbGetParamiv(const ReverbProps &props, ALenum param, int *vals)
{ StdReverbGetParami(props, param, vals); }
void EffectHandler::StdReverbGetParamf(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};
}
}
void EffectHandler::StdReverbGetParamfv(const ReverbProps &props, ALenum param, float *vals)
{
switch(param)
{
default:
StdReverbGetParamf(props, param, vals);
break;
}
context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}",
as_unsigned(param));
}
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
@@ -1078,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;
}();
+55 -62
View File
@@ -7,12 +7,12 @@
#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"
@@ -97,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
}
@@ -119,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
@@ -139,7 +139,7 @@ constexpr EffectProps genDefaultProps() noexcept
const EffectProps VmorpherEffectProps{genDefaultProps()};
void EffectHandler::SetParami(VmorpherProps &props, ALenum param, int val)
void VmorpherEffectHandler::SetParami(ALCcontext *context, VmorpherProps &props, ALenum param, int val)
{
switch(param)
{
@@ -147,101 +147,94 @@ void EffectHandler::SetParami(VmorpherProps &props, ALenum param, int val)
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 EffectHandler::SetParamiv(VmorpherProps&, ALenum param, const int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
param};
}
void EffectHandler::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 EffectHandler::SetParamfv(VmorpherProps &props, ALenum param, const float *vals)
{ SetParamf(props, param, *vals); }
void EffectHandler::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 EffectHandler::GetParamiv(const VmorpherProps&, ALenum param, int*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
param};
}
void EffectHandler::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 EffectHandler::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>;
+25 -53
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
-27
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 */
+31 -29
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,16 +20,17 @@
#include "AL/alext.h"
#include "alc/context.h"
#include "alc/inprogext.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"
@@ -52,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)
@@ -67,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)
{
@@ -102,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)
{
@@ -114,20 +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)
{
const std::string_view message{evt.msg.data()};
if(!context->mEventCb
|| !enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected)))
return;
context->debugMessage(DebugSource::System, DebugType::Error, 0,
DebugSeverity::High, message);
if(context->mEventCb
&& enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected)))
context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0,
static_cast<ALsizei>(message.length()), message.data(),
context->mEventParam);
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,
@@ -159,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);
@@ -190,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));
}
@@ -229,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());
}
-2
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"
+185 -158
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)
}
inline 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 @@ inline 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);
}
+14 -8
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> { };
+90 -55
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
+51 -37
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);
@@ -542,7 +539,24 @@ private:
struct Eax5SourceAllValidator {
void operator()(const EAX50SOURCEPROPERTIES& props) const
{
Eax3SourceAllValidator{}(static_cast<const Eax3Props&>(props));
Eax2SourceDirectValidator{}(props.lDirect);
Eax2SourceDirectHfValidator{}(props.lDirectHF);
Eax2SourceRoomValidator{}(props.lRoom);
Eax2SourceRoomHfValidator{}(props.lRoomHF);
Eax2SourceObstructionValidator{}(props.lObstruction);
Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
Eax2SourceOcclusionValidator{}(props.lOcclusion);
Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
Eax3SourceExclusionValidator{}(props.lExclusion);
Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor);
Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor);
Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
Eax5SourceFlagsValidator{}(props.ulFlags);
Eax5SourceMacroFXFactorValidator{}(props.flMacroFXFactor);
}
};
@@ -806,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;
@@ -823,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(
@@ -889,13 +903,13 @@ private:
}
}
static void eax_get_active_fx_slot_id(const EaxCall& call, const GUID* ids, size_t max_count);
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 eax_get_active_fx_slot_id(const EaxCall& call, const al::span<const GUID> src_ids);
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);
@@ -1017,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);
+86 -53
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"; }
@@ -82,8 +83,10 @@ template<> struct ResamplerName<Resampler::Point>
{ static constexpr const ALchar *Get() noexcept { return "Nearest"; } };
template<> struct ResamplerName<Resampler::Linear>
{ static constexpr const ALchar *Get() noexcept { return "Linear"; } };
template<> struct ResamplerName<Resampler::Cubic>
{ static constexpr const ALchar *Get() noexcept { return "Cubic"; } };
template<> struct ResamplerName<Resampler::Spline>
{ static constexpr const ALchar *Get() noexcept { return "Cubic Spline"; } };
template<> struct ResamplerName<Resampler::Gaussian>
{ static constexpr const ALchar *Get() noexcept { return "4-point Gaussian"; } };
template<> struct ResamplerName<Resampler::FastBSinc12>
{ static constexpr const ALchar *Get() noexcept { return "11th order Sinc (fast)"; } };
template<> struct ResamplerName<Resampler::BSinc12>
@@ -92,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)
{
@@ -100,11 +107,14 @@ const ALchar *GetResamplerName(const Resampler rtype)
{
HANDLE_RESAMPLER(Resampler::Point);
HANDLE_RESAMPLER(Resampler::Linear);
HANDLE_RESAMPLER(Resampler::Cubic);
HANDLE_RESAMPLER(Resampler::Spline);
HANDLE_RESAMPLER(Resampler::Gaussian);
HANDLE_RESAMPLER(Resampler::FastBSinc12);
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. */
@@ -141,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
};
@@ -256,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:
@@ -265,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:
@@ -276,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));
}
@@ -328,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)
@@ -352,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)
@@ -366,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); \
@@ -381,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
@@ -439,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");
@@ -461,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)
@@ -469,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();
@@ -482,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;
}
@@ -490,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};
@@ -503,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};
@@ -523,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));
}
@@ -548,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;
}
@@ -564,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};
@@ -608,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;