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 reload_config();
|
||||
|
||||
void underwater_change(bool underwater);
|
||||
|
||||
float& bgm_target_volume();
|
||||
|
||||
private:
|
||||
@@ -47,8 +49,10 @@ private:
|
||||
FadeMap m_fade_map;
|
||||
SoundManager m_sounds;
|
||||
std::shared_ptr<SourcePool> m_pool;
|
||||
|
||||
bool m_efx_supported = false;
|
||||
bool m_underwater = false;
|
||||
float m_music_volume = 1.0f;
|
||||
float m_sfx_volume = 1.0f;
|
||||
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
||||
};
|
||||
} // 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
|
||||
#include "Cubed/audio/audio_buffer.hpp"
|
||||
#include "Cubed/audio/audio_filter.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <glm/glm.hpp>
|
||||
@@ -34,6 +35,9 @@ public:
|
||||
bool in_use() const;
|
||||
void reset();
|
||||
|
||||
void set_filter(const AudioFilter& filter);
|
||||
void clear_filter();
|
||||
|
||||
private:
|
||||
ALuint m_source = 0;
|
||||
float m_target_volume = 1.0f;
|
||||
|
||||
@@ -16,6 +16,8 @@ public:
|
||||
|
||||
void update();
|
||||
AudioSource* acquire();
|
||||
|
||||
std::vector<AudioSource>& sources();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -51,4 +51,5 @@ target_sources(${PROJECT_NAME}
|
||||
audio/sound_manager.cpp
|
||||
audio/source_pool.cpp
|
||||
audio/audio_fade.cpp
|
||||
audio/audio_filter.cpp
|
||||
)
|
||||
@@ -35,6 +35,21 @@ void AudioEngine::init() {
|
||||
}
|
||||
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);
|
||||
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_target_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");
|
||||
if (it != m_fade_map.end()) {
|
||||
it->second.reset();
|
||||
@@ -99,6 +117,9 @@ void AudioEngine::play_3d(const std::string& sound, const glm::vec3& pos,
|
||||
|
||||
try {
|
||||
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);
|
||||
} catch (const std::exception& e) {
|
||||
if (check) {
|
||||
@@ -121,6 +142,9 @@ void AudioEngine::play_2d(const std::string& sound, bool check) {
|
||||
|
||||
try {
|
||||
auto& buffer = m_sounds.get_buffer(sound);
|
||||
if (m_efx_supported && m_underwater) {
|
||||
source->set_filter(*m_low_pass_filter);
|
||||
}
|
||||
source->play_2d(buffer);
|
||||
} catch (const std::exception& e) {
|
||||
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(); }
|
||||
|
||||
} // 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/tools/log.hpp"
|
||||
|
||||
#include <AL/efx.h>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -149,8 +150,17 @@ void AudioSource::reset() {
|
||||
|
||||
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
||||
|
||||
clear_filter();
|
||||
|
||||
m_duration = 0.0f;
|
||||
m_target_volume = 1.0f;
|
||||
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
|
||||
@@ -20,5 +20,5 @@ AudioSource* SourcePool::acquire() {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<AudioSource>& SourcePool::sources() { return m_sources; }
|
||||
} // namespace Cubed
|
||||
@@ -49,8 +49,9 @@ void Camera::update_move_camera() {
|
||||
if (m_under_water != change) {
|
||||
m_under_water = change;
|
||||
m_player->set_underwater(m_under_water);
|
||||
m_player->get_world().get_audio().play_2d(
|
||||
"ambient/water/in_and_out_of_water.flac", true);
|
||||
auto& audio = m_player->get_world().get_audio();
|
||||
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