aboutsummaryrefslogtreecommitdiffstats
path: root/al/effect.cpp
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-01-30 14:47:32 +0200
committerGitHub <[email protected]>2022-01-30 04:47:32 -0800
commit19ed994dc30ed84ea7cbbb5152577669fc25caf6 (patch)
treef68933bf8f778806618bd6c0b1bf9ced1b0ccf08 /al/effect.cpp
parent619249371a40f03cf988d1f5750d643df797c485 (diff)
Add EAX extensions (EAX 2.0-5.0, X-RAM) (#632)
* Add EAX extensions (EAX 2.0-5.0, X-RAM) * Comment out C++17 leftovers * Remove everything related to patching * Update alsoftrc.sample * Rewrite integration * Fix GCC compilation under Linux * Always reset EAX effect properties when loading it into FX slot
Diffstat (limited to 'al/effect.cpp')
-rw-r--r--al/effect.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/al/effect.cpp b/al/effect.cpp
index 217cc1c2..79cd7fab 100644
--- a/al/effect.cpp
+++ b/al/effect.cpp
@@ -51,6 +51,11 @@
#include "opthelpers.h"
#include "vector.h"
+#if ALSOFT_EAX
+#include <cassert>
+
+#include "eax_exception.h"
+#endif // ALSOFT_EAX
const EffectList gEffectList[16]{
{ "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB },
@@ -745,3 +750,141 @@ void LoadReverbPreset(const char *name, ALeffect *effect)
WARN("Reverb preset '%s' not found\n", name);
}
+
+#if ALSOFT_EAX
+namespace
+{
+
+class EaxAlEffectException :
+ public EaxException
+{
+public:
+ explicit EaxAlEffectException(
+ const char* message)
+ :
+ EaxException{"[EAX_AL_EFFECT]", message}
+ {
+ }
+}; // EaxAlEffectException
+
+
+} // namespace
+
+
+void ALeffect::eax_initialize()
+{
+ eax_effect = nullptr;
+ eax_effect = eax_create_eax_effect(type, Props);
+}
+
+void ALeffect::eax_al_set_effect(
+ ALenum al_effect_type)
+{
+ if (al_effect_type != AL_EFFECT_NULL)
+ {
+ auto has_effect = false;
+
+ for (const auto &effect_item : gEffectList)
+ {
+ if (al_effect_type == effect_item.val && !DisabledEffects[effect_item.type])
+ {
+ has_effect = true;
+ break;
+ }
+ }
+
+ if (!has_effect)
+ {
+ eax_fail("Effect not available.");
+ }
+ }
+
+ InitEffectParams(this, al_effect_type);
+}
+
+[[noreturn]]
+void ALeffect::eax_fail(
+ const char* message)
+{
+ throw EaxAlEffectException{message};
+}
+
+EaxAlEffectDeleter::EaxAlEffectDeleter(
+ ALCcontext& context) noexcept
+ :
+ context_{&context}
+{
+}
+
+void EaxAlEffectDeleter::operator()(
+ ALeffect* effect) const
+{
+ assert(effect);
+
+ eax_al_delete_effect(*context_, *effect);
+}
+
+EaxAlEffectUPtr eax_create_al_effect(
+ ALCcontext& context,
+ ALenum effect_type)
+{
+#define EAX_PREFIX "[EAX_MAKE_EFFECT] "
+
+ auto& device = *context.mALDevice;
+ std::lock_guard<std::mutex> effect_lock{device.EffectLock};
+
+ // Allocate.
+ //
+ if (!EnsureEffects(&device, 1))
+ {
+ ERR(EAX_PREFIX "%s\n", "Failed to ensure.");
+ return nullptr;
+ }
+
+ auto effect = EaxAlEffectUPtr{AllocEffect(&device), EaxAlEffectDeleter{context}};
+
+ if (!effect)
+ {
+ ERR(EAX_PREFIX "%s\n", "Failed to allocate.");
+ return nullptr;
+ }
+
+ // Set the type.
+ //
+ auto is_supported = (effect_type == AL_EFFECT_NULL);
+
+ if (!is_supported)
+ {
+ for (const auto& effect_item : gEffectList)
+ {
+ if(effect_type == effect_item.val && !DisabledEffects[effect_item.type])
+ {
+ is_supported = true;
+ break;
+ }
+ }
+ }
+
+ if (!is_supported)
+ {
+ ERR(EAX_PREFIX "Effect type 0x%04x not supported.\n", effect_type);
+ return nullptr;
+ }
+
+ InitEffectParams(effect.get(), effect_type);
+
+ return effect;
+
+#undef EAX_PREFIX
+}
+
+void eax_al_delete_effect(
+ ALCcontext& context,
+ ALeffect& effect)
+{
+ auto& device = *context.mALDevice;
+ std::lock_guard<std::mutex> effect_lock{device.EffectLock};
+
+ FreeEffect(&device, &effect);
+}
+#endif // ALSOFT_EAX