mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(audio): implement reverb effect and integrate into underwater system
This commit is contained in:
19
include/Cubed/audio/audio_effect.hpp
Normal file
19
include/Cubed/audio/audio_effect.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <AL/al.h>
|
||||
namespace Cubed {
|
||||
class AudioEffect {
|
||||
public:
|
||||
AudioEffect();
|
||||
AudioEffect(const AudioEffect&) = delete;
|
||||
AudioEffect(AudioEffect&&) = delete;
|
||||
AudioEffect& operator=(const AudioEffect&) = default;
|
||||
AudioEffect& operator=(AudioEffect&&) = delete;
|
||||
~AudioEffect();
|
||||
void set_reverb(float decay_time, float reverb_gain, float gain_hf,
|
||||
float density = 1.0f, float diffusion = 1.0f);
|
||||
ALuint effect() const;
|
||||
|
||||
private:
|
||||
ALuint m_effect = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
18
include/Cubed/audio/audio_effect_slot.hpp
Normal file
18
include/Cubed/audio/audio_effect_slot.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_effect.hpp"
|
||||
namespace Cubed {
|
||||
class AudioEffectSlot {
|
||||
public:
|
||||
AudioEffectSlot();
|
||||
AudioEffectSlot(const AudioEffectSlot&) = delete;
|
||||
AudioEffectSlot(AudioEffectSlot&&) = delete;
|
||||
AudioEffectSlot& operator=(const AudioEffectSlot&) = delete;
|
||||
AudioEffectSlot& operator=(AudioEffectSlot&&) = delete;
|
||||
~AudioEffectSlot();
|
||||
void set_effect(const AudioEffect& effect);
|
||||
ALuint slot() const;
|
||||
|
||||
private:
|
||||
ALuint m_slot = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -54,5 +54,7 @@ private:
|
||||
float m_music_volume = 1.0f;
|
||||
float m_sfx_volume = 1.0f;
|
||||
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
||||
std::unique_ptr<AudioEffect> m_underwater_effect;
|
||||
std::unique_ptr<AudioEffectSlot> m_underwater_slot;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_buffer.hpp"
|
||||
#include "Cubed/audio/audio_effect_slot.hpp"
|
||||
#include "Cubed/audio/audio_filter.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
@@ -37,6 +38,8 @@ public:
|
||||
|
||||
void set_filter(const AudioFilter& filter);
|
||||
void clear_filter();
|
||||
void set_effect_slot(const AudioEffectSlot& slot);
|
||||
void clear_effect_slot();
|
||||
|
||||
private:
|
||||
ALuint m_source = 0;
|
||||
|
||||
@@ -52,4 +52,6 @@ target_sources(${PROJECT_NAME}
|
||||
audio/source_pool.cpp
|
||||
audio/audio_fade.cpp
|
||||
audio/audio_filter.cpp
|
||||
audio/audio_effect.cpp
|
||||
audio/audio_effect_slot.cpp
|
||||
)
|
||||
26
src/audio/audio_effect.cpp
Normal file
26
src/audio/audio_effect.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "Cubed/audio/audio_effect.hpp"
|
||||
#ifndef AL_ALEXT_PROTOTYPES
|
||||
#define AL_ALEXT_PROTOTYPES
|
||||
#endif
|
||||
#include <AL/efx.h>
|
||||
|
||||
namespace Cubed {
|
||||
AudioEffect::AudioEffect() { alGenEffects(1, &m_effect); }
|
||||
|
||||
AudioEffect::~AudioEffect() {
|
||||
if (m_effect) {
|
||||
alDeleteEffects(1, &m_effect);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioEffect::set_reverb(float decay_time, float reverb_gain, float gain_hf,
|
||||
float density, float diffusion) {
|
||||
alEffecti(m_effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
|
||||
alEffectf(m_effect, AL_REVERB_DECAY_TIME, decay_time);
|
||||
alEffectf(m_effect, AL_REVERB_GAIN, reverb_gain);
|
||||
alEffectf(m_effect, AL_REVERB_GAINHF, gain_hf);
|
||||
alEffectf(m_effect, AL_REVERB_DENSITY, density);
|
||||
alEffectf(m_effect, AL_REVERB_DIFFUSION, diffusion);
|
||||
}
|
||||
ALuint AudioEffect::effect() const { return m_effect; }
|
||||
} // namespace Cubed
|
||||
19
src/audio/audio_effect_slot.cpp
Normal file
19
src/audio/audio_effect_slot.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "Cubed/audio/audio_effect_slot.hpp"
|
||||
#ifndef AL_ALEXT_PROTOTYPES
|
||||
#define AL_ALEXT_PROTOTYPES
|
||||
#endif
|
||||
#include <AL/efx.h>
|
||||
namespace Cubed {
|
||||
AudioEffectSlot::AudioEffectSlot() { alGenAuxiliaryEffectSlots(1, &m_slot); }
|
||||
|
||||
AudioEffectSlot::~AudioEffectSlot() {
|
||||
if (m_slot) {
|
||||
alDeleteAuxiliaryEffectSlots(1, &m_slot);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioEffectSlot::set_effect(const AudioEffect& effect) {
|
||||
alAuxiliaryEffectSloti(m_slot, AL_EFFECTSLOT_EFFECT, effect.effect());
|
||||
}
|
||||
ALuint AudioEffectSlot::slot() const { return m_slot; }
|
||||
} // namespace Cubed
|
||||
@@ -19,6 +19,10 @@ AudioEngine::~AudioEngine() {
|
||||
m_pool.reset();
|
||||
m_sounds.clear();
|
||||
|
||||
m_low_pass_filter.reset();
|
||||
m_underwater_effect.reset();
|
||||
m_underwater_slot.reset();
|
||||
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
@@ -49,6 +53,12 @@ void AudioEngine::init() {
|
||||
m_low_pass_filter = std::make_unique<AudioFilter>();
|
||||
|
||||
m_low_pass_filter->set_lowpass(1.0f, 0.15f);
|
||||
|
||||
m_underwater_effect = std::make_unique<AudioEffect>();
|
||||
m_underwater_effect->set_reverb(0.8f, 0.3162f, 0.01f);
|
||||
// m_underwater_effect->set_reverb(20.0f, 1.0f, 1.0f);
|
||||
m_underwater_slot = std::make_unique<AudioEffectSlot>();
|
||||
m_underwater_slot->set_effect(*m_underwater_effect);
|
||||
}
|
||||
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
@@ -120,6 +130,7 @@ void AudioEngine::play_3d(const std::string& sound, const glm::vec3& pos,
|
||||
auto& buffer = m_sounds.get_buffer(sound);
|
||||
if (m_efx_supported && m_underwater) {
|
||||
source->set_filter(*m_low_pass_filter);
|
||||
source->set_effect_slot(*m_underwater_slot);
|
||||
}
|
||||
source->play_3d(buffer, pos);
|
||||
} catch (const std::exception& e) {
|
||||
@@ -145,6 +156,7 @@ void AudioEngine::play_2d(const std::string& sound, bool check) {
|
||||
auto& buffer = m_sounds.get_buffer(sound);
|
||||
if (m_efx_supported && m_underwater) {
|
||||
source->set_filter(*m_low_pass_filter);
|
||||
source->set_effect_slot(*m_underwater_slot);
|
||||
}
|
||||
source->play_2d(buffer);
|
||||
} catch (const std::exception& e) {
|
||||
@@ -195,9 +207,10 @@ void AudioEngine::underwater_change(bool underwater) {
|
||||
for (auto& source : m_pool->sources()) {
|
||||
if (m_underwater) {
|
||||
source.set_filter(*m_low_pass_filter);
|
||||
|
||||
source.set_effect_slot(*m_underwater_slot);
|
||||
} else {
|
||||
source.clear_filter();
|
||||
source.clear_effect_slot();
|
||||
}
|
||||
}
|
||||
if (underwater) {
|
||||
|
||||
@@ -156,6 +156,7 @@ void AudioSource::reset() {
|
||||
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
||||
|
||||
clear_filter();
|
||||
clear_effect_slot();
|
||||
|
||||
m_duration = 0.0f;
|
||||
m_target_volume = 1.0f;
|
||||
@@ -168,4 +169,15 @@ void AudioSource::set_filter(const AudioFilter& filter) {
|
||||
void AudioSource::clear_filter() {
|
||||
alSourcei(m_source, AL_DIRECT_FILTER, AL_FILTER_NULL);
|
||||
}
|
||||
|
||||
void AudioSource::set_effect_slot(const AudioEffectSlot& slot) {
|
||||
alSource3i(m_source, AL_AUXILIARY_SEND_FILTER, slot.slot(), 0,
|
||||
AL_FILTER_NULL);
|
||||
}
|
||||
|
||||
void AudioSource::clear_effect_slot() {
|
||||
alSource3i(m_source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0,
|
||||
AL_FILTER_NULL);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user