mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +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_music_volume = 1.0f;
|
||||||
float m_sfx_volume = 1.0f;
|
float m_sfx_volume = 1.0f;
|
||||||
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
||||||
|
std::unique_ptr<AudioEffect> m_underwater_effect;
|
||||||
|
std::unique_ptr<AudioEffectSlot> m_underwater_slot;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Cubed/audio/audio_buffer.hpp"
|
#include "Cubed/audio/audio_buffer.hpp"
|
||||||
|
#include "Cubed/audio/audio_effect_slot.hpp"
|
||||||
#include "Cubed/audio/audio_filter.hpp"
|
#include "Cubed/audio/audio_filter.hpp"
|
||||||
|
|
||||||
#include <AL/al.h>
|
#include <AL/al.h>
|
||||||
@@ -37,6 +38,8 @@ public:
|
|||||||
|
|
||||||
void set_filter(const AudioFilter& filter);
|
void set_filter(const AudioFilter& filter);
|
||||||
void clear_filter();
|
void clear_filter();
|
||||||
|
void set_effect_slot(const AudioEffectSlot& slot);
|
||||||
|
void clear_effect_slot();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ALuint m_source = 0;
|
ALuint m_source = 0;
|
||||||
|
|||||||
@@ -52,4 +52,6 @@ target_sources(${PROJECT_NAME}
|
|||||||
audio/source_pool.cpp
|
audio/source_pool.cpp
|
||||||
audio/audio_fade.cpp
|
audio/audio_fade.cpp
|
||||||
audio/audio_filter.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_pool.reset();
|
||||||
m_sounds.clear();
|
m_sounds.clear();
|
||||||
|
|
||||||
|
m_low_pass_filter.reset();
|
||||||
|
m_underwater_effect.reset();
|
||||||
|
m_underwater_slot.reset();
|
||||||
|
|
||||||
alcMakeContextCurrent(nullptr);
|
alcMakeContextCurrent(nullptr);
|
||||||
alcDestroyContext(context);
|
alcDestroyContext(context);
|
||||||
alcCloseDevice(device);
|
alcCloseDevice(device);
|
||||||
@@ -49,6 +53,12 @@ void AudioEngine::init() {
|
|||||||
m_low_pass_filter = std::make_unique<AudioFilter>();
|
m_low_pass_filter = std::make_unique<AudioFilter>();
|
||||||
|
|
||||||
m_low_pass_filter->set_lowpass(1.0f, 0.15f);
|
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);
|
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);
|
auto& buffer = m_sounds.get_buffer(sound);
|
||||||
if (m_efx_supported && m_underwater) {
|
if (m_efx_supported && m_underwater) {
|
||||||
source->set_filter(*m_low_pass_filter);
|
source->set_filter(*m_low_pass_filter);
|
||||||
|
source->set_effect_slot(*m_underwater_slot);
|
||||||
}
|
}
|
||||||
source->play_3d(buffer, pos);
|
source->play_3d(buffer, pos);
|
||||||
} catch (const std::exception& e) {
|
} 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);
|
auto& buffer = m_sounds.get_buffer(sound);
|
||||||
if (m_efx_supported && m_underwater) {
|
if (m_efx_supported && m_underwater) {
|
||||||
source->set_filter(*m_low_pass_filter);
|
source->set_filter(*m_low_pass_filter);
|
||||||
|
source->set_effect_slot(*m_underwater_slot);
|
||||||
}
|
}
|
||||||
source->play_2d(buffer);
|
source->play_2d(buffer);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
@@ -195,9 +207,10 @@ void AudioEngine::underwater_change(bool underwater) {
|
|||||||
for (auto& source : m_pool->sources()) {
|
for (auto& source : m_pool->sources()) {
|
||||||
if (m_underwater) {
|
if (m_underwater) {
|
||||||
source.set_filter(*m_low_pass_filter);
|
source.set_filter(*m_low_pass_filter);
|
||||||
|
source.set_effect_slot(*m_underwater_slot);
|
||||||
} else {
|
} else {
|
||||||
source.clear_filter();
|
source.clear_filter();
|
||||||
|
source.clear_effect_slot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (underwater) {
|
if (underwater) {
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ void AudioSource::reset() {
|
|||||||
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
||||||
|
|
||||||
clear_filter();
|
clear_filter();
|
||||||
|
clear_effect_slot();
|
||||||
|
|
||||||
m_duration = 0.0f;
|
m_duration = 0.0f;
|
||||||
m_target_volume = 1.0f;
|
m_target_volume = 1.0f;
|
||||||
@@ -168,4 +169,15 @@ void AudioSource::set_filter(const AudioFilter& filter) {
|
|||||||
void AudioSource::clear_filter() {
|
void AudioSource::clear_filter() {
|
||||||
alSourcei(m_source, AL_DIRECT_FILTER, AL_FILTER_NULL);
|
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
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user