mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(audio): add audio fade in/out and fix delta time naming
This commit is contained in:
@@ -38,7 +38,7 @@ public:
|
||||
static int start_cubed_application(int argc, char** argv);
|
||||
|
||||
static unsigned int seed();
|
||||
static float delte_time();
|
||||
static float delta_time();
|
||||
static float get_fps();
|
||||
|
||||
Camera& camera();
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
|
||||
inline static double last_time = glfwGetTime();
|
||||
inline static double current_time = glfwGetTime();
|
||||
inline static double delta_time = 0.0f;
|
||||
inline static double dt = 0.0f;
|
||||
inline static double fps_time_count = 0.0f;
|
||||
inline static int frame_count = 0;
|
||||
inline static int fps = 0;
|
||||
|
||||
@@ -12,9 +12,11 @@ public:
|
||||
AudioBuffer& operator=(AudioBuffer&&) = delete;
|
||||
~AudioBuffer();
|
||||
ALuint buffer() const;
|
||||
float duration() const;
|
||||
|
||||
private:
|
||||
ALuint m_buffer = 0;
|
||||
float m_duration = 0.0f;
|
||||
void set_data(const AudioData& data);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/audio/audio_fade.hpp"
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
#include "Cubed/audio/sound_manager.hpp"
|
||||
|
||||
@@ -24,15 +25,18 @@ public:
|
||||
|
||||
void init();
|
||||
void play_bgm();
|
||||
void update(glm::vec3 listener_pos);
|
||||
void update_listener(glm::vec3 listener_pos);
|
||||
void update(float dt);
|
||||
|
||||
private:
|
||||
using SourcePool = std::unordered_map<std::string, ALuint>;
|
||||
using FadeMap = std::unordered_map<std::string, AudioFade>;
|
||||
bool m_init{false};
|
||||
ALCdevice* device{nullptr};
|
||||
ALCcontext* context{nullptr};
|
||||
glm::vec3 listener_pos;
|
||||
std::unique_ptr<AudioSource> m_bgm;
|
||||
FadeMap m_fade_map;
|
||||
SoundManager m_sounds;
|
||||
};
|
||||
} // namespace Cubed
|
||||
19
include/Cubed/audio/audio_fade.hpp
Normal file
19
include/Cubed/audio/audio_fade.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
namespace Cubed {
|
||||
class AudioFade {
|
||||
public:
|
||||
AudioFade(AudioSource* source, float fade_in = 0.0f, float fade_out = 0.0f);
|
||||
~AudioFade();
|
||||
void update();
|
||||
|
||||
private:
|
||||
AudioSource* m_source = nullptr;
|
||||
float m_in_duration = 0.0f;
|
||||
float m_out_duration = 0.0f;
|
||||
float m_start_gain = 0.0f;
|
||||
float m_end_gain = 0.0f;
|
||||
bool m_fade_in = true;
|
||||
bool m_active = true;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -11,16 +11,20 @@ public:
|
||||
AudioSource();
|
||||
~AudioSource();
|
||||
|
||||
void set_buffer(const AudioBuffer& buffer);
|
||||
void set_buffer_2d(const AudioBuffer& buffer);
|
||||
void set_loop(bool on = true);
|
||||
|
||||
void set_volume(float volume);
|
||||
void play();
|
||||
void stop();
|
||||
void pause();
|
||||
|
||||
float duration() const;
|
||||
float current_time() const;
|
||||
float volume() const;
|
||||
AudioState state();
|
||||
|
||||
private:
|
||||
ALuint m_source = 0;
|
||||
float m_volume = 1.0f;
|
||||
float m_duration = 0.0f;
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
0
include/Cubed/audio/source_pool.hpp
Normal file
0
include/Cubed/audio/source_pool.hpp
Normal file
@@ -104,6 +104,8 @@ inline float distance2(const glm::vec3& a, const glm::vec3& b) {
|
||||
return glm::dot(diff, diff);
|
||||
}
|
||||
|
||||
inline float lerp(float a, float b, float t) { return a + t * (b - a); }
|
||||
|
||||
} // namespace Math
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -50,4 +50,5 @@ target_sources(${PROJECT_NAME}
|
||||
audio/audio_buffer.cpp
|
||||
audio/sound_manager.cpp
|
||||
audio/source_pool.cpp
|
||||
audio/audio_fade.cpp
|
||||
)
|
||||
13
src/app.cpp
13
src/app.cpp
@@ -329,9 +329,9 @@ static Gait player_gait = Gait::WALK;
|
||||
void App::update() {
|
||||
glfwPollEvents();
|
||||
current_time = glfwGetTime();
|
||||
delta_time = current_time - last_time;
|
||||
dt = current_time - last_time;
|
||||
last_time = current_time;
|
||||
fps_time_count += delta_time;
|
||||
fps_time_count += dt;
|
||||
frame_count++;
|
||||
if (fps_time_count >= 1.0f) {
|
||||
fps = static_cast<int>(frame_count / fps_time_count);
|
||||
@@ -346,7 +346,7 @@ void App::update() {
|
||||
std::format("RSS: {}mb", Tools::get_current_rss() / (1024 * 1024)));
|
||||
}
|
||||
m_texture_manager.update();
|
||||
m_client_world.update(delta_time);
|
||||
m_client_world.update(dt);
|
||||
m_camera.update_move_camera();
|
||||
const auto& player = m_client_world.get_player();
|
||||
if (player_gait != player.get_gait()) {
|
||||
@@ -359,8 +359,9 @@ void App::update() {
|
||||
m_renderer.update_fov(fov + 5.0f);
|
||||
}
|
||||
}
|
||||
m_audio.update(m_camera.get_camera_pos());
|
||||
m_renderer.update(delta_time);
|
||||
m_audio.update_listener(m_camera.get_camera_pos());
|
||||
m_audio.update(dt);
|
||||
m_renderer.update(dt);
|
||||
}
|
||||
|
||||
int App::start_cubed_application(int argc, char** argv) {
|
||||
@@ -382,7 +383,7 @@ int App::start_cubed_application(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
float App::delte_time() { return delta_time; }
|
||||
float App::delta_time() { return dt; }
|
||||
|
||||
float App::get_fps() { return fps; }
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ AudioBuffer::AudioBuffer(const AudioData& data) {
|
||||
AudioBuffer::~AudioBuffer() { alDeleteBuffers(1, &m_buffer); }
|
||||
|
||||
ALuint AudioBuffer::buffer() const { return m_buffer; }
|
||||
float AudioBuffer::duration() const { return m_duration; }
|
||||
|
||||
void AudioBuffer::set_data(const AudioData& data) {
|
||||
ALenum format;
|
||||
if (data.channels == 1) {
|
||||
@@ -17,6 +19,8 @@ void AudioBuffer::set_data(const AudioData& data) {
|
||||
}
|
||||
alBufferData(m_buffer, format, data.pcm.data(), data.pcm.size(),
|
||||
data.sample_rate);
|
||||
m_duration = static_cast<float>(data.pcm.size()) /
|
||||
(data.channels * data.sample_rate);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -33,7 +33,10 @@ void AudioEngine::init() {
|
||||
|
||||
m_sounds.init();
|
||||
m_bgm = std::make_unique<AudioSource>();
|
||||
m_bgm->set_buffer(m_sounds.get_buffer("bgm/bgm001.mp3"));
|
||||
m_bgm->set_buffer_2d(m_sounds.get_buffer("bgm/bgm001.mp3"));
|
||||
|
||||
m_fade_map.try_emplace("bgm", m_bgm.get(), 5.0f, 2.0f);
|
||||
|
||||
Logger::info("Audio Engine Init Success");
|
||||
|
||||
m_init = true;
|
||||
@@ -41,6 +44,11 @@ void AudioEngine::init() {
|
||||
|
||||
void AudioEngine::play_bgm() { m_bgm->play(); }
|
||||
|
||||
void AudioEngine::update(glm::vec3 listener_pos) {}
|
||||
void AudioEngine::update_listener(glm::vec3 listener_pos) {}
|
||||
void AudioEngine::update(float dt) {
|
||||
|
||||
for (auto& [key, fade] : m_fade_map) {
|
||||
fade.update();
|
||||
}
|
||||
}
|
||||
} // namespace Cubed
|
||||
62
src/audio/audio_fade.cpp
Normal file
62
src/audio/audio_fade.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "Cubed/audio/audio_fade.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace Cubed {
|
||||
AudioFade::AudioFade(AudioSource* source, float fade_in, float fade_out)
|
||||
: m_source(source), m_in_duration(fade_in), m_out_duration(fade_out) {
|
||||
if (!m_source) {
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
m_start_gain = 0.0f;
|
||||
m_end_gain = m_source->volume();
|
||||
m_source->set_volume(0.0f);
|
||||
}
|
||||
AudioFade::~AudioFade() {}
|
||||
void AudioFade::update() {
|
||||
if (!m_active || !m_source) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_fade_in) {
|
||||
float t =
|
||||
std::clamp(m_source->current_time() / m_in_duration, 0.0f, 1.0f);
|
||||
|
||||
// Ease Out Sine
|
||||
t = std::sin(t * std::numbers::pi_v<float> * 0.5f);
|
||||
|
||||
float gain = std::lerp(m_start_gain, m_end_gain, t);
|
||||
m_source->set_volume(gain);
|
||||
if (t >= 1.0f) {
|
||||
m_source->set_volume(m_end_gain);
|
||||
m_fade_in = false;
|
||||
m_start_gain = m_end_gain;
|
||||
m_end_gain = 0.0f;
|
||||
}
|
||||
} else {
|
||||
float start_time =
|
||||
std::max(0.0f, m_source->duration() - m_out_duration);
|
||||
|
||||
if (m_source->current_time() < start_time) {
|
||||
return;
|
||||
}
|
||||
|
||||
float elapsed = m_source->current_time() - start_time;
|
||||
|
||||
float t = std::clamp(elapsed / m_out_duration, 0.0f, 1.0f);
|
||||
|
||||
// Smoothstep
|
||||
t = t * t * (3.0f - 2.0f * t);
|
||||
|
||||
float gain = std::lerp(m_start_gain, m_end_gain, t);
|
||||
m_source->set_volume(gain);
|
||||
|
||||
if (t >= 1.0f) {
|
||||
m_source->set_volume(m_end_gain);
|
||||
m_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Cubed
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Cubed {
|
||||
@@ -11,11 +13,14 @@ AudioSource::~AudioSource() {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSource::set_buffer(const AudioBuffer& buffer) {
|
||||
void AudioSource::set_buffer_2d(const AudioBuffer& buffer) {
|
||||
if (state() == AudioState::PLAYING) {
|
||||
stop();
|
||||
}
|
||||
m_duration = buffer.duration();
|
||||
alSourcei(m_source, AL_BUFFER, buffer.buffer());
|
||||
alSourcei(m_source, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSource3f(m_source, AL_POSITION, 0, 0, 0);
|
||||
}
|
||||
|
||||
void AudioSource::set_loop(bool on) {
|
||||
@@ -26,11 +31,28 @@ void AudioSource::set_loop(bool on) {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSource::set_volume(float volume) {
|
||||
if (volume > 1.0f) {
|
||||
Logger::error("Volume {} is too large", volume);
|
||||
return;
|
||||
}
|
||||
m_volume = volume;
|
||||
alSourcef(m_source, AL_GAIN, volume);
|
||||
}
|
||||
|
||||
void AudioSource::play() { alSourcePlay(m_source); }
|
||||
|
||||
void AudioSource::stop() { alSourceStop(m_source); }
|
||||
void AudioSource::pause() { alSourcePause(m_source); }
|
||||
|
||||
float AudioSource::duration() const { return m_duration; }
|
||||
float AudioSource::current_time() const {
|
||||
ALfloat sec = 0.0f;
|
||||
alGetSourcef(m_source, AL_SEC_OFFSET, &sec);
|
||||
return static_cast<float>(sec);
|
||||
}
|
||||
float AudioSource::volume() const { return m_volume; }
|
||||
|
||||
AudioState AudioSource::state() {
|
||||
ALint state;
|
||||
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
|
||||
|
||||
0
src/audio/source_pool.cpp
Normal file
0
src/audio/source_pool.cpp
Normal file
Reference in New Issue
Block a user