diff --git a/rwengine/CMakeLists.txt b/rwengine/CMakeLists.txt index cddfe5f9e..b2a22c53a 100644 --- a/rwengine/CMakeLists.txt +++ b/rwengine/CMakeLists.txt @@ -24,6 +24,14 @@ set(RWENGINE_SOURCES src/audio/SoundManager.hpp src/audio/SoundSource.cpp src/audio/SoundSource.hpp + src/audio/EffectSlot.hpp + src/audio/EffectSlot.cpp + src/audio/SoundEffect.cpp + src/audio/SoundEffect.hpp + src/audio/ReverbEffect.cpp + src/audio/ReverbEffect.hpp + src/audio/OpenAlExtensions.hpp + src/audio/OpenAlExtensions.cpp src/core/Logger.cpp src/core/Logger.hpp diff --git a/rwengine/src/audio/EffectSlot.cpp b/rwengine/src/audio/EffectSlot.cpp new file mode 100644 index 000000000..18ef435ff --- /dev/null +++ b/rwengine/src/audio/EffectSlot.cpp @@ -0,0 +1,37 @@ +#include "EffectSlot.hpp" +#include "SoundEffect.hpp" +#include "OpenAlExtensions.hpp" + +EffectSlot::EffectSlot() { + alGenAuxiliaryEffectSlots(1, &slotId); + + created = alGetError() == AL_NO_ERROR; +} + +EffectSlot::~EffectSlot() { + alDeleteAuxiliaryEffectSlots(1, &slotId); +} + +bool EffectSlot::attachEffect(std::shared_ptr effect) { + alAuxiliaryEffectSloti(slotId, AL_EFFECTSLOT_EFFECT, effect->getId()); + + if (alGetError() != AL_NO_ERROR) { + return false; + } + + this->effect = std::move(effect); + + return true; +} + +bool EffectSlot::detachEffect() { + alAuxiliaryEffectSloti(slotId, AL_EFFECTSLOT_EFFECT, 0); + this->effect = nullptr; + + return alGetError() == AL_NO_ERROR; +} + +void EffectSlot::setGain(float gain) { + this->gain = gain; + alAuxiliaryEffectSlotf(slotId, AL_EFFECTSLOT_GAIN, gain); +} diff --git a/rwengine/src/audio/EffectSlot.hpp b/rwengine/src/audio/EffectSlot.hpp new file mode 100644 index 000000000..0f02a50f7 --- /dev/null +++ b/rwengine/src/audio/EffectSlot.hpp @@ -0,0 +1,62 @@ +#ifndef EFFECTSLOT_H +#define EFFECTSLOT_H + +#include + +#include + +class SoundEffect; + +/** + * Effect slot. + * + * Many sound sources can be attached to one slot. + * Different effects can be binded to this (e.g reverb, delay). + */ +class EffectSlot { +public: + EffectSlot(); + ~EffectSlot(); + + /** + * Attach effect to this slot. + * + * @param sound effect (e.g reverb, delay) + * @return true if effect attached successfully, false otherwise + */ + bool attachEffect(std::shared_ptr effect); + + /** + * Detach current effect from this slot. + * @return true if effect detached successfully, false otherwise + */ + bool detachEffect(); + + void setGain(float gain); + + ALuint getSlotId() const { + return slotId; + } + + int getSlotNumber() const { + return slotNumber; + } + +private: + /** + * Effect binded to this slot + */ + std::shared_ptr effect; + + ALuint slotId; + /** + * This is flag of successfull slot creation + */ + bool created; + float gain = 1.0f; + + /// OpenAL aux slot + int slotNumber = 0; +}; + +#endif // EFFECTSLOT_H diff --git a/rwengine/src/audio/OpenAlExtensions.cpp b/rwengine/src/audio/OpenAlExtensions.cpp new file mode 100644 index 000000000..ead6089bc --- /dev/null +++ b/rwengine/src/audio/OpenAlExtensions.cpp @@ -0,0 +1,25 @@ +#include "OpenAlExtensions.hpp" + +LPALGENEFFECTS alGenEffects = nullptr; +LPALDELETEEFFECTS alDeleteEffects = nullptr; +LPALEFFECTI alEffecti = nullptr; +LPALEFFECTF alEffectf = nullptr; + +// Auxiliary slot object +LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots = nullptr; +LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots = nullptr; +LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti = nullptr; +LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf = nullptr; + +void initEfxFunctionPointers() { + alGenEffects = reinterpret_cast(alGetProcAddress("alGenEffects")); + alDeleteEffects = reinterpret_cast(alGetProcAddress("alDeleteEffects")); + alEffecti = reinterpret_cast(alGetProcAddress("alEffecti")); + alEffectf = reinterpret_cast(alGetProcAddress("alEffectf")); + + // aux slot + alGenAuxiliaryEffectSlots = reinterpret_cast(alGetProcAddress("alGenAuxiliaryEffectSlots")); + alDeleteAuxiliaryEffectSlots = reinterpret_cast(alGetProcAddress("alDeleteAuxiliaryEffectSlots")); + alAuxiliaryEffectSloti = reinterpret_cast(alGetProcAddress("alAuxiliaryEffectSloti")); + alAuxiliaryEffectSlotf = reinterpret_cast(alGetProcAddress("alAuxiliaryEffectSlotf")); +} diff --git a/rwengine/src/audio/OpenAlExtensions.hpp b/rwengine/src/audio/OpenAlExtensions.hpp new file mode 100644 index 000000000..ee700f3ad --- /dev/null +++ b/rwengine/src/audio/OpenAlExtensions.hpp @@ -0,0 +1,26 @@ +#ifndef OPENALEXTENSIONS_HPP +#define OPENALEXTENSIONS_HPP + +#include + +/** + * Functions to access OpenAL EFX extension + */ + +extern LPALGENEFFECTS alGenEffects; +extern LPALDELETEEFFECTS alDeleteEffects; +extern LPALEFFECTI alEffecti; +extern LPALEFFECTF alEffectf; + +// Aux slot +extern LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots; +extern LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots; +extern LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti; +extern LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf; + +/** + * Initialize function pointers + */ +void initEfxFunctionPointers(); + +#endif // OPENALEXTENSIONS_HPP diff --git a/rwengine/src/audio/ReverbEffect.cpp b/rwengine/src/audio/ReverbEffect.cpp new file mode 100644 index 000000000..e48b43736 --- /dev/null +++ b/rwengine/src/audio/ReverbEffect.cpp @@ -0,0 +1,44 @@ +#include "ReverbEffect.hpp" +#include "OpenAlExtensions.hpp" +#include + +ReverbEffect::ReverbEffect() : SoundEffect (AL_EFFECT_REVERB) { + +} + + +void ReverbEffect::setDensity(float d) { + alEffectf(id, AL_REVERB_DENSITY, d); +} + +void ReverbEffect::setDiffusion(float d) { + alEffectf(id, AL_REVERB_DIFFUSION, d); +} + +void ReverbEffect::setGain(float g) { + alEffectf(id, AL_REVERB_GAIN, g); +} + +void ReverbEffect::setGainHf(float g) { + alEffectf(id, AL_REVERB_GAINHF, g); +} + +void ReverbEffect::setDecayTime(float t) { + alEffectf(id, AL_REVERB_DECAY_TIME, t); +} + +void ReverbEffect::setLateReverbGain(float g) { + alEffectf(id, AL_REVERB_LATE_REVERB_GAIN, g); +} + +void ReverbEffect::setLateReverbDelay(float t) { + alEffectf(id, AL_REVERB_LATE_REVERB_DELAY, t); +} + +void ReverbEffect::setAirAbsorptionGainHf(float g) { + alEffectf(id, AL_REVERB_AIR_ABSORPTION_GAINHF, g); +} + +void ReverbEffect::setDecayHfLimit(bool flag) { + alEffecti(id, AL_REVERB_DECAY_HFLIMIT, flag ? AL_TRUE : AL_FALSE); +} diff --git a/rwengine/src/audio/ReverbEffect.hpp b/rwengine/src/audio/ReverbEffect.hpp new file mode 100644 index 000000000..6a1f46b92 --- /dev/null +++ b/rwengine/src/audio/ReverbEffect.hpp @@ -0,0 +1,22 @@ +#ifndef REVERBEFFECT_H +#define REVERBEFFECT_H + +#include "SoundEffect.hpp" + +class ReverbEffect : public SoundEffect { + +public: + ReverbEffect(); + + void setDensity(float density = 1.0f); + void setDiffusion(float diffusion = 0.3f); + void setGain(float gain = 0.92f); + void setGainHf(float gainHf = 0.89f); + void setDecayTime(float decayTime = 5.49f); + void setLateReverbGain(float lateReverbGain = 1.26f ); + void setLateReverbDelay(float lateReverbDelay = 0.011f); + void setAirAbsorptionGainHf(float absorptionGainHf = 0.994f); + void setDecayHfLimit(bool decayHfLimit = true); +}; + +#endif // REVERBEFFECT_H diff --git a/rwengine/src/audio/Sound.cpp b/rwengine/src/audio/Sound.cpp index df934cd78..d186fd975 100644 --- a/rwengine/src/audio/Sound.cpp +++ b/rwengine/src/audio/Sound.cpp @@ -2,6 +2,13 @@ #include "audio/SoundBuffer.hpp" +Sound::~Sound() +{ + if (effect != nullptr) { + buffer->disableEffect(effect); + } +} + bool Sound::isPlaying() const { return buffer->isPlaying(); } @@ -46,6 +53,12 @@ void Sound::setMaxDistance(float maxDist) { buffer->setMaxDistance(maxDist); } +void Sound::enableEffect(std::shared_ptr effect) +{ + this->effect = std::move(effect); + buffer->enableEffect(this->effect); +} + size_t Sound::getScriptObjectID() const { return id; } diff --git a/rwengine/src/audio/Sound.hpp b/rwengine/src/audio/Sound.hpp index fbb29122b..6eb857cbf 100644 --- a/rwengine/src/audio/Sound.hpp +++ b/rwengine/src/audio/Sound.hpp @@ -1,9 +1,12 @@ #ifndef _RWENGINE_SOUND_HPP_ #define _RWENGINE_SOUND_HPP_ +#include