mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +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 int start_cubed_application(int argc, char** argv);
|
||||||
|
|
||||||
static unsigned int seed();
|
static unsigned int seed();
|
||||||
static float delte_time();
|
static float delta_time();
|
||||||
static float get_fps();
|
static float get_fps();
|
||||||
|
|
||||||
Camera& camera();
|
Camera& camera();
|
||||||
@@ -67,7 +67,7 @@ private:
|
|||||||
|
|
||||||
inline static double last_time = glfwGetTime();
|
inline static double last_time = glfwGetTime();
|
||||||
inline static double current_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 double fps_time_count = 0.0f;
|
||||||
inline static int frame_count = 0;
|
inline static int frame_count = 0;
|
||||||
inline static int fps = 0;
|
inline static int fps = 0;
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ public:
|
|||||||
AudioBuffer& operator=(AudioBuffer&&) = delete;
|
AudioBuffer& operator=(AudioBuffer&&) = delete;
|
||||||
~AudioBuffer();
|
~AudioBuffer();
|
||||||
ALuint buffer() const;
|
ALuint buffer() const;
|
||||||
|
float duration() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ALuint m_buffer = 0;
|
ALuint m_buffer = 0;
|
||||||
|
float m_duration = 0.0f;
|
||||||
void set_data(const AudioData& data);
|
void set_data(const AudioData& data);
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cubed/audio/audio_fade.hpp"
|
||||||
#include "Cubed/audio/audio_source.hpp"
|
#include "Cubed/audio/audio_source.hpp"
|
||||||
#include "Cubed/audio/sound_manager.hpp"
|
#include "Cubed/audio/sound_manager.hpp"
|
||||||
|
|
||||||
@@ -24,15 +25,18 @@ public:
|
|||||||
|
|
||||||
void init();
|
void init();
|
||||||
void play_bgm();
|
void play_bgm();
|
||||||
void update(glm::vec3 listener_pos);
|
void update_listener(glm::vec3 listener_pos);
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using SourcePool = std::unordered_map<std::string, ALuint>;
|
using SourcePool = std::unordered_map<std::string, ALuint>;
|
||||||
|
using FadeMap = std::unordered_map<std::string, AudioFade>;
|
||||||
bool m_init{false};
|
bool m_init{false};
|
||||||
ALCdevice* device{nullptr};
|
ALCdevice* device{nullptr};
|
||||||
ALCcontext* context{nullptr};
|
ALCcontext* context{nullptr};
|
||||||
glm::vec3 listener_pos;
|
glm::vec3 listener_pos;
|
||||||
std::unique_ptr<AudioSource> m_bgm;
|
std::unique_ptr<AudioSource> m_bgm;
|
||||||
|
FadeMap m_fade_map;
|
||||||
SoundManager m_sounds;
|
SoundManager m_sounds;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // 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();
|
||||||
~AudioSource();
|
~AudioSource();
|
||||||
|
|
||||||
void set_buffer(const AudioBuffer& buffer);
|
void set_buffer_2d(const AudioBuffer& buffer);
|
||||||
void set_loop(bool on = true);
|
void set_loop(bool on = true);
|
||||||
|
void set_volume(float volume);
|
||||||
void play();
|
void play();
|
||||||
void stop();
|
void stop();
|
||||||
void pause();
|
void pause();
|
||||||
|
float duration() const;
|
||||||
|
float current_time() const;
|
||||||
|
float volume() const;
|
||||||
AudioState state();
|
AudioState state();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ALuint m_source = 0;
|
ALuint m_source = 0;
|
||||||
|
float m_volume = 1.0f;
|
||||||
|
float m_duration = 0.0f;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // 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);
|
return glm::dot(diff, diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float lerp(float a, float b, float t) { return a + t * (b - a); }
|
||||||
|
|
||||||
} // namespace Math
|
} // namespace Math
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -50,4 +50,5 @@ target_sources(${PROJECT_NAME}
|
|||||||
audio/audio_buffer.cpp
|
audio/audio_buffer.cpp
|
||||||
audio/sound_manager.cpp
|
audio/sound_manager.cpp
|
||||||
audio/source_pool.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() {
|
void App::update() {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
current_time = glfwGetTime();
|
current_time = glfwGetTime();
|
||||||
delta_time = current_time - last_time;
|
dt = current_time - last_time;
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
fps_time_count += delta_time;
|
fps_time_count += dt;
|
||||||
frame_count++;
|
frame_count++;
|
||||||
if (fps_time_count >= 1.0f) {
|
if (fps_time_count >= 1.0f) {
|
||||||
fps = static_cast<int>(frame_count / fps_time_count);
|
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)));
|
std::format("RSS: {}mb", Tools::get_current_rss() / (1024 * 1024)));
|
||||||
}
|
}
|
||||||
m_texture_manager.update();
|
m_texture_manager.update();
|
||||||
m_client_world.update(delta_time);
|
m_client_world.update(dt);
|
||||||
m_camera.update_move_camera();
|
m_camera.update_move_camera();
|
||||||
const auto& player = m_client_world.get_player();
|
const auto& player = m_client_world.get_player();
|
||||||
if (player_gait != player.get_gait()) {
|
if (player_gait != player.get_gait()) {
|
||||||
@@ -359,8 +359,9 @@ void App::update() {
|
|||||||
m_renderer.update_fov(fov + 5.0f);
|
m_renderer.update_fov(fov + 5.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_audio.update(m_camera.get_camera_pos());
|
m_audio.update_listener(m_camera.get_camera_pos());
|
||||||
m_renderer.update(delta_time);
|
m_audio.update(dt);
|
||||||
|
m_renderer.update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int App::start_cubed_application(int argc, char** argv) {
|
int App::start_cubed_application(int argc, char** argv) {
|
||||||
@@ -382,7 +383,7 @@ int App::start_cubed_application(int argc, char** argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float App::delte_time() { return delta_time; }
|
float App::delta_time() { return dt; }
|
||||||
|
|
||||||
float App::get_fps() { return fps; }
|
float App::get_fps() { return fps; }
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ AudioBuffer::AudioBuffer(const AudioData& data) {
|
|||||||
AudioBuffer::~AudioBuffer() { alDeleteBuffers(1, &m_buffer); }
|
AudioBuffer::~AudioBuffer() { alDeleteBuffers(1, &m_buffer); }
|
||||||
|
|
||||||
ALuint AudioBuffer::buffer() const { return m_buffer; }
|
ALuint AudioBuffer::buffer() const { return m_buffer; }
|
||||||
|
float AudioBuffer::duration() const { return m_duration; }
|
||||||
|
|
||||||
void AudioBuffer::set_data(const AudioData& data) {
|
void AudioBuffer::set_data(const AudioData& data) {
|
||||||
ALenum format;
|
ALenum format;
|
||||||
if (data.channels == 1) {
|
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(),
|
alBufferData(m_buffer, format, data.pcm.data(), data.pcm.size(),
|
||||||
data.sample_rate);
|
data.sample_rate);
|
||||||
|
m_duration = static_cast<float>(data.pcm.size()) /
|
||||||
|
(data.channels * data.sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -33,7 +33,10 @@ void AudioEngine::init() {
|
|||||||
|
|
||||||
m_sounds.init();
|
m_sounds.init();
|
||||||
m_bgm = std::make_unique<AudioSource>();
|
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");
|
Logger::info("Audio Engine Init Success");
|
||||||
|
|
||||||
m_init = true;
|
m_init = true;
|
||||||
@@ -41,6 +44,11 @@ void AudioEngine::init() {
|
|||||||
|
|
||||||
void AudioEngine::play_bgm() { m_bgm->play(); }
|
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
|
} // 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/audio/audio_source.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/tools/log.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace Cubed {
|
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) {
|
if (state() == AudioState::PLAYING) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
m_duration = buffer.duration();
|
||||||
alSourcei(m_source, AL_BUFFER, buffer.buffer());
|
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) {
|
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::play() { alSourcePlay(m_source); }
|
||||||
|
|
||||||
void AudioSource::stop() { alSourceStop(m_source); }
|
void AudioSource::stop() { alSourceStop(m_source); }
|
||||||
void AudioSource::pause() { alSourcePause(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() {
|
AudioState AudioSource::state() {
|
||||||
ALint state;
|
ALint state;
|
||||||
alGetSourcei(m_source, AL_SOURCE_STATE, &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