mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(audio): add spatial voice source with underwater effects
Update voice source to support spatial positioning, low-pass filter, and reverb effect for underwater immersion. Adjust source pool size and low-pass filter parameter. Correct receive_voice parameter type.
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -48,7 +48,7 @@ public:
|
|||||||
void set_client(std::weak_ptr<NetworkClient> client);
|
void set_client(std::weak_ptr<NetworkClient> client);
|
||||||
|
|
||||||
void send_voice(const std::array<int16_t, AudioRecording::FRAME_SAMPLES>&);
|
void send_voice(const std::array<int16_t, AudioRecording::FRAME_SAMPLES>&);
|
||||||
void receive_voice(std::span<char> opus, const glm::vec3& pos);
|
void receive_voice(std::span<const char> opus, const glm::vec3& pos);
|
||||||
|
|
||||||
AudioRecording& audio_recording();
|
AudioRecording& audio_recording();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cubed/audio/audio_effect_slot.hpp"
|
||||||
|
#include "Cubed/audio/audio_filter.hpp"
|
||||||
|
#include "glm/ext/vector_float3.hpp"
|
||||||
|
|
||||||
#include <al.h>
|
#include <al.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <span>
|
#include <span>
|
||||||
@@ -19,6 +23,15 @@ public:
|
|||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
bool is_playing() const;
|
bool is_playing() const;
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void set_volume(float volume);
|
||||||
|
void set_pitch(float pitch);
|
||||||
|
void set_pos(glm::vec3 pos);
|
||||||
|
void set_filter(const AudioFilter& 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;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ 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.1f);
|
||||||
|
|
||||||
m_underwater_effect = std::make_unique<AudioEffect>();
|
m_underwater_effect = std::make_unique<AudioEffect>();
|
||||||
m_underwater_effect->set_reverb(0.8f, 0.3162f, 0.01f);
|
m_underwater_effect->set_reverb(0.8f, 0.3162f, 0.01f);
|
||||||
@@ -102,7 +102,7 @@ void AudioEngine::init() {
|
|||||||
m_bgm->set_buffer_2d(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);
|
m_fade_map.try_emplace("bgm", m_bgm.get(), 5.0f, 2.0f);
|
||||||
|
m_voice_source = std::make_unique<AudioStreamSource>();
|
||||||
ALCint max_mono = 0;
|
ALCint max_mono = 0;
|
||||||
|
|
||||||
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, &max_mono);
|
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, &max_mono);
|
||||||
@@ -113,14 +113,12 @@ void AudioEngine::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Logger::info("Set Source Pool Size {}", static_cast<int>(max_mono));
|
Logger::info("Set Source Pool Size {}", static_cast<int>(max_mono));
|
||||||
// Reserve a source for BGM
|
// Reserve two sources for BGM and voice
|
||||||
m_pool = std::make_shared<SourcePool>(max_mono - 1);
|
m_pool = std::make_shared<SourcePool>(max_mono - 2);
|
||||||
|
|
||||||
Logger::info("Audio Engine Init Success");
|
Logger::info("Audio Engine Init Success");
|
||||||
|
|
||||||
m_init = true;
|
m_init = true;
|
||||||
|
|
||||||
m_voice_source = std::make_unique<AudioStreamSource>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEngine::play_bgm() { m_bgm->play(); }
|
void AudioEngine::play_bgm() { m_bgm->play(); }
|
||||||
@@ -242,9 +240,13 @@ void AudioEngine::underwater_change(bool underwater) {
|
|||||||
}
|
}
|
||||||
if (underwater) {
|
if (underwater) {
|
||||||
m_bgm->set_filter(*m_low_pass_filter);
|
m_bgm->set_filter(*m_low_pass_filter);
|
||||||
|
m_voice_source->set_filter(*m_low_pass_filter);
|
||||||
|
m_voice_source->set_effect_slot(*m_underwater_slot);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
m_bgm->clear_filter();
|
m_bgm->clear_filter();
|
||||||
|
m_voice_source->clear_filter();
|
||||||
|
m_voice_source->clear_effect_slot();
|
||||||
}
|
}
|
||||||
Logger::info("Under Water Change {}", m_underwater);
|
Logger::info("Under Water Change {}", m_underwater);
|
||||||
}
|
}
|
||||||
@@ -279,7 +281,8 @@ void AudioEngine::send_voice(
|
|||||||
c->send(make_packet(*msg));
|
c->send(make_packet(*msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void AudioEngine::receive_voice(std::span<char> opus, const glm::vec3& pos) {
|
void AudioEngine::receive_voice(std::span<const char> opus,
|
||||||
|
const glm::vec3& pos) {
|
||||||
std::array<int16_t, AudioRecording::FRAME_SAMPLES> pcm;
|
std::array<int16_t, AudioRecording::FRAME_SAMPLES> pcm;
|
||||||
int len =
|
int len =
|
||||||
opus_decode(m_decoder, reinterpret_cast<const uint8_t*>(opus.data()),
|
opus_decode(m_decoder, reinterpret_cast<const uint8_t*>(opus.data()),
|
||||||
@@ -288,6 +291,7 @@ void AudioEngine::receive_voice(std::span<char> opus, const glm::vec3& pos) {
|
|||||||
Logger::error("Opus decode failed: {}", opus_strerror(len));
|
Logger::error("Opus decode failed: {}", opus_strerror(len));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_voice_source->set_pos(pos);
|
||||||
m_voice_source->push_pcm(std::span(pcm.data(), len),
|
m_voice_source->push_pcm(std::span(pcm.data(), len),
|
||||||
AudioRecording::SAMPLE_RATE);
|
AudioRecording::SAMPLE_RATE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "Cubed/audio/audio_stream_source.hpp"
|
#include "Cubed/audio/audio_stream_source.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/audio/audio_error.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
#include <efx.h>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
AudioStreamSource::AudioStreamSource() {
|
AudioStreamSource::AudioStreamSource() {
|
||||||
alGenBuffers(NUM_BUFFERS, m_buffers.data());
|
alGenBuffers(NUM_BUFFERS, m_buffers.data());
|
||||||
@@ -68,4 +72,71 @@ void AudioStreamSource::unqueue_processed() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::set_volume(float volume) {
|
||||||
|
volume = std::clamp(volume, 0.0f, 1.0f);
|
||||||
|
alSourcef(m_source, AL_GAIN, volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::set_pitch(float pitch) {
|
||||||
|
pitch = std::clamp(pitch, 0.0f, 1.0f);
|
||||||
|
alSourcef(m_source, AL_PITCH, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::set_pos(glm::vec3 pos) {
|
||||||
|
alSourcei(m_source, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
alSource3f(m_source, AL_POSITION, pos.x, pos.y, pos.z);
|
||||||
|
check_al_error();
|
||||||
|
|
||||||
|
alSourcef(m_source, AL_REFERENCE_DISTANCE, 4.0f);
|
||||||
|
alSourcef(m_source, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
alSourcef(m_source, AL_MAX_DISTANCE, 48.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::reset() {
|
||||||
|
alSourceStop(m_source);
|
||||||
|
|
||||||
|
alSourcei(m_source, AL_BUFFER, 0);
|
||||||
|
|
||||||
|
alSourcef(m_source, AL_GAIN, 1.0f);
|
||||||
|
alSourcef(m_source, AL_PITCH, 1.0f);
|
||||||
|
|
||||||
|
alSource3f(m_source, AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(m_source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(m_source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
alSourcef(m_source, AL_REFERENCE_DISTANCE, 1.0f);
|
||||||
|
alSourcef(m_source, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
alSourcef(m_source, AL_MAX_DISTANCE, FLT_MAX);
|
||||||
|
|
||||||
|
alSourcef(m_source, AL_CONE_INNER_ANGLE, 360.0f);
|
||||||
|
alSourcef(m_source, AL_CONE_OUTER_ANGLE, 360.0f);
|
||||||
|
alSourcef(m_source, AL_CONE_OUTER_GAIN, 0.0f);
|
||||||
|
|
||||||
|
alSourcei(m_source, AL_LOOPING, AL_FALSE);
|
||||||
|
|
||||||
|
alSourcei(m_source, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
|
|
||||||
|
alSourcef(m_source, AL_SEC_OFFSET, 0.0f);
|
||||||
|
|
||||||
|
clear_filter();
|
||||||
|
clear_effect_slot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::set_filter(const AudioFilter& filter) {
|
||||||
|
alSourcei(m_source, AL_DIRECT_FILTER, filter.filter());
|
||||||
|
}
|
||||||
|
void AudioStreamSource::clear_filter() {
|
||||||
|
alSourcei(m_source, AL_DIRECT_FILTER, AL_FILTER_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::set_effect_slot(const AudioEffectSlot& slot) {
|
||||||
|
alSource3i(m_source, AL_AUXILIARY_SEND_FILTER, slot.slot(), 0,
|
||||||
|
AL_FILTER_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioStreamSource::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