mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(audio): add underwater low-pass filter effect
This commit is contained in:
@@ -35,6 +35,8 @@ public:
|
|||||||
void update();
|
void update();
|
||||||
void reload_config();
|
void reload_config();
|
||||||
|
|
||||||
|
void underwater_change(bool underwater);
|
||||||
|
|
||||||
float& bgm_target_volume();
|
float& bgm_target_volume();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -47,8 +49,10 @@ private:
|
|||||||
FadeMap m_fade_map;
|
FadeMap m_fade_map;
|
||||||
SoundManager m_sounds;
|
SoundManager m_sounds;
|
||||||
std::shared_ptr<SourcePool> m_pool;
|
std::shared_ptr<SourcePool> m_pool;
|
||||||
|
bool m_efx_supported = false;
|
||||||
|
bool m_underwater = false;
|
||||||
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;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
19
include/Cubed/audio/audio_filter.hpp
Normal file
19
include/Cubed/audio/audio_filter.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <AL/al.h>
|
||||||
|
namespace Cubed {
|
||||||
|
class AudioFilter {
|
||||||
|
public:
|
||||||
|
AudioFilter();
|
||||||
|
AudioFilter(const AudioFilter&) = delete;
|
||||||
|
AudioFilter(AudioFilter&&) = delete;
|
||||||
|
AudioFilter& operator=(const AudioFilter&) = delete;
|
||||||
|
AudioFilter& operator=(AudioFilter&&) = delete;
|
||||||
|
~AudioFilter();
|
||||||
|
|
||||||
|
void set_lowpass(float gain, float gain_hf);
|
||||||
|
ALuint filter() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ALuint m_filter = 0;
|
||||||
|
};
|
||||||
|
} // 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_filter.hpp"
|
||||||
|
|
||||||
#include <AL/al.h>
|
#include <AL/al.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
@@ -34,6 +35,9 @@ public:
|
|||||||
bool in_use() const;
|
bool in_use() const;
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void set_filter(const AudioFilter& filter);
|
||||||
|
void clear_filter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ALuint m_source = 0;
|
ALuint m_source = 0;
|
||||||
float m_target_volume = 1.0f;
|
float m_target_volume = 1.0f;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public:
|
|||||||
|
|
||||||
void update();
|
void update();
|
||||||
AudioSource* acquire();
|
AudioSource* acquire();
|
||||||
|
|
||||||
|
std::vector<AudioSource>& sources();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -51,4 +51,5 @@ target_sources(${PROJECT_NAME}
|
|||||||
audio/sound_manager.cpp
|
audio/sound_manager.cpp
|
||||||
audio/source_pool.cpp
|
audio/source_pool.cpp
|
||||||
audio/audio_fade.cpp
|
audio/audio_fade.cpp
|
||||||
|
audio/audio_filter.cpp
|
||||||
)
|
)
|
||||||
@@ -35,6 +35,21 @@ void AudioEngine::init() {
|
|||||||
}
|
}
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
|
|
||||||
|
if (!alcIsExtensionPresent(device, "ALC_EXT_EFX")) {
|
||||||
|
Logger::error("EFX not supported!");
|
||||||
|
m_efx_supported = false;
|
||||||
|
} else {
|
||||||
|
Logger::info("EFX supported!");
|
||||||
|
m_efx_supported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_efx_supported) {
|
||||||
|
|
||||||
|
m_low_pass_filter = std::make_unique<AudioFilter>();
|
||||||
|
|
||||||
|
m_low_pass_filter->set_lowpass(1.0f, 0.15f);
|
||||||
|
}
|
||||||
|
|
||||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||||
check_al_error();
|
check_al_error();
|
||||||
|
|
||||||
@@ -78,6 +93,9 @@ void AudioEngine::change_bgm(const std::string& sound) {
|
|||||||
m_bgm->set_buffer_2d(m_sounds.get_buffer(sound));
|
m_bgm->set_buffer_2d(m_sounds.get_buffer(sound));
|
||||||
m_bgm->set_target_volume(m_music_volume);
|
m_bgm->set_target_volume(m_music_volume);
|
||||||
m_bgm->set_volume(m_music_volume);
|
m_bgm->set_volume(m_music_volume);
|
||||||
|
if (m_efx_supported && m_underwater) {
|
||||||
|
m_bgm->set_filter(*m_low_pass_filter);
|
||||||
|
}
|
||||||
auto it = m_fade_map.find("bgm");
|
auto it = m_fade_map.find("bgm");
|
||||||
if (it != m_fade_map.end()) {
|
if (it != m_fade_map.end()) {
|
||||||
it->second.reset();
|
it->second.reset();
|
||||||
@@ -99,6 +117,9 @@ void AudioEngine::play_3d(const std::string& sound, const glm::vec3& pos,
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
auto& buffer = m_sounds.get_buffer(sound);
|
auto& buffer = m_sounds.get_buffer(sound);
|
||||||
|
if (m_efx_supported && m_underwater) {
|
||||||
|
source->set_filter(*m_low_pass_filter);
|
||||||
|
}
|
||||||
source->play_3d(buffer, pos);
|
source->play_3d(buffer, pos);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
if (check) {
|
if (check) {
|
||||||
@@ -121,6 +142,9 @@ void AudioEngine::play_2d(const std::string& sound, bool check) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
auto& buffer = m_sounds.get_buffer(sound);
|
auto& buffer = m_sounds.get_buffer(sound);
|
||||||
|
if (m_efx_supported && m_underwater) {
|
||||||
|
source->set_filter(*m_low_pass_filter);
|
||||||
|
}
|
||||||
source->play_2d(buffer);
|
source->play_2d(buffer);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
if (check) {
|
if (check) {
|
||||||
@@ -159,6 +183,29 @@ void AudioEngine::reload_config() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioEngine::underwater_change(bool underwater) {
|
||||||
|
m_underwater = underwater;
|
||||||
|
if (!m_efx_supported) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_pool) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto& source : m_pool->sources()) {
|
||||||
|
if (m_underwater) {
|
||||||
|
source.set_filter(*m_low_pass_filter);
|
||||||
|
} else {
|
||||||
|
source.clear_filter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (underwater) {
|
||||||
|
m_bgm->set_filter(*m_low_pass_filter);
|
||||||
|
} else {
|
||||||
|
m_bgm->clear_filter();
|
||||||
|
}
|
||||||
|
Logger::info("Under Water Change {}", m_underwater);
|
||||||
|
}
|
||||||
|
|
||||||
float& AudioEngine::bgm_target_volume() { return m_bgm->target_volume(); }
|
float& AudioEngine::bgm_target_volume() { return m_bgm->target_volume(); }
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
22
src/audio/audio_filter.cpp
Normal file
22
src/audio/audio_filter.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "Cubed/audio/audio_filter.hpp"
|
||||||
|
#ifndef AL_ALEXT_PROTOTYPES
|
||||||
|
#define AL_ALEXT_PROTOTYPES
|
||||||
|
#endif
|
||||||
|
#include <AL/alc.h>
|
||||||
|
#include <AL/efx.h>
|
||||||
|
namespace Cubed {
|
||||||
|
AudioFilter::AudioFilter() { alGenFilters(1, &m_filter); }
|
||||||
|
AudioFilter::~AudioFilter() {
|
||||||
|
if (m_filter != 0) {
|
||||||
|
alDeleteFilters(1, &m_filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void AudioFilter::set_lowpass(float gain, float gain_hf) {
|
||||||
|
alFilteri(m_filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
|
||||||
|
alFilterf(m_filter, AL_LOWPASS_GAIN, gain);
|
||||||
|
alFilterf(m_filter, AL_LOWPASS_GAINHF, gain_hf);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALuint AudioFilter::filter() const { return m_filter; }
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "Cubed/audio/audio_error.hpp"
|
#include "Cubed/audio/audio_error.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
|
||||||
|
#include <AL/efx.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@@ -149,8 +150,17 @@ void AudioSource::reset() {
|
|||||||
|
|
||||||
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
||||||
|
|
||||||
|
clear_filter();
|
||||||
|
|
||||||
m_duration = 0.0f;
|
m_duration = 0.0f;
|
||||||
m_target_volume = 1.0f;
|
m_target_volume = 1.0f;
|
||||||
m_using = false;
|
m_using = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioSource::set_filter(const AudioFilter& filter) {
|
||||||
|
alSourcei(m_source, AL_DIRECT_FILTER, filter.filter());
|
||||||
|
}
|
||||||
|
void AudioSource::clear_filter() {
|
||||||
|
alSourcei(m_source, AL_DIRECT_FILTER, AL_FILTER_NULL);
|
||||||
|
}
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -20,5 +20,5 @@ AudioSource* SourcePool::acquire() {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
std::vector<AudioSource>& SourcePool::sources() { return m_sources; }
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -49,8 +49,9 @@ void Camera::update_move_camera() {
|
|||||||
if (m_under_water != change) {
|
if (m_under_water != change) {
|
||||||
m_under_water = change;
|
m_under_water = change;
|
||||||
m_player->set_underwater(m_under_water);
|
m_player->set_underwater(m_under_water);
|
||||||
m_player->get_world().get_audio().play_2d(
|
auto& audio = m_player->get_world().get_audio();
|
||||||
"ambient/water/in_and_out_of_water.flac", true);
|
audio.play_2d("ambient/water/in_and_out_of_water.flac", true);
|
||||||
|
audio.underwater_change(m_under_water);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user