mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
Move soundmanager into its own thread
Fixes sound queues running empty on client step hiccups.
This commit is contained in:
parent
591e45657f
commit
8fa2ea71ef
3 changed files with 384 additions and 12 deletions
|
@ -38,5 +38,5 @@ std::shared_ptr<SoundManagerSingleton> createSoundManagerSingleton()
|
||||||
std::unique_ptr<ISoundManager> createOpenALSoundManager(SoundManagerSingleton *smg,
|
std::unique_ptr<ISoundManager> createOpenALSoundManager(SoundManagerSingleton *smg,
|
||||||
std::unique_ptr<SoundFallbackPathProvider> fallback_path_provider)
|
std::unique_ptr<SoundFallbackPathProvider> fallback_path_provider)
|
||||||
{
|
{
|
||||||
return std::make_unique<OpenALSoundManager>(smg, std::move(fallback_path_provider));
|
return std::make_unique<ProxySoundManager>(smg, std::move(fallback_path_provider));
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,6 @@ with this program; ifnot, write to the Free Software Foundation, Inc.,
|
||||||
#include "sound_openal_internal.h"
|
#include "sound_openal_internal.h"
|
||||||
|
|
||||||
#include "util/numeric.h" // myrand()
|
#include "util/numeric.h" // myrand()
|
||||||
#include "../sound.h"
|
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -806,7 +805,7 @@ std::string OpenALSoundManager::getLoadedSoundNameFromGroup(const std::string &g
|
||||||
|
|
||||||
auto it_groups = m_sound_groups.find(group_name);
|
auto it_groups = m_sound_groups.find(group_name);
|
||||||
if (it_groups == m_sound_groups.end())
|
if (it_groups == m_sound_groups.end())
|
||||||
return chosen_sound_name;
|
return "";
|
||||||
|
|
||||||
std::vector<std::string> &group_sounds = it_groups->second;
|
std::vector<std::string> &group_sounds = it_groups->second;
|
||||||
while (!group_sounds.empty()) {
|
while (!group_sounds.empty()) {
|
||||||
|
@ -817,7 +816,7 @@ std::string OpenALSoundManager::getLoadedSoundNameFromGroup(const std::string &g
|
||||||
// find chosen one
|
// find chosen one
|
||||||
std::shared_ptr<ISoundDataOpen> snd = openSingleSound(chosen_sound_name);
|
std::shared_ptr<ISoundDataOpen> snd = openSingleSound(chosen_sound_name);
|
||||||
if (snd)
|
if (snd)
|
||||||
break;
|
return chosen_sound_name;
|
||||||
|
|
||||||
// it doesn't exist
|
// it doesn't exist
|
||||||
// remove it from the group and try again
|
// remove it from the group and try again
|
||||||
|
@ -825,7 +824,7 @@ std::string OpenALSoundManager::getLoadedSoundNameFromGroup(const std::string &g
|
||||||
group_sounds.pop_back();
|
group_sounds.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
return chosen_sound_name;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OpenALSoundManager::getOrLoadLoadedSoundNameFromGroup(const std::string &group_name)
|
std::string OpenALSoundManager::getOrLoadLoadedSoundNameFromGroup(const std::string &group_name)
|
||||||
|
@ -887,8 +886,7 @@ void OpenALSoundManager::playSoundGeneric(sound_handle_t id, const std::string &
|
||||||
bool loop, f32 volume, f32 fade, f32 pitch, bool use_local_fallback,
|
bool loop, f32 volume, f32 fade, f32 pitch, bool use_local_fallback,
|
||||||
f32 start_time, const std::optional<std::pair<v3f, v3f>> &pos_vel_opt)
|
f32 start_time, const std::optional<std::pair<v3f, v3f>> &pos_vel_opt)
|
||||||
{
|
{
|
||||||
if (id == 0)
|
assert(id != 0);
|
||||||
id = allocateId(1);
|
|
||||||
|
|
||||||
if (group_name.empty()) {
|
if (group_name.empty()) {
|
||||||
reportRemovedSound(id);
|
reportRemovedSound(id);
|
||||||
|
@ -963,6 +961,7 @@ int OpenALSoundManager::removeDeadSounds()
|
||||||
|
|
||||||
OpenALSoundManager::OpenALSoundManager(SoundManagerSingleton *smg,
|
OpenALSoundManager::OpenALSoundManager(SoundManagerSingleton *smg,
|
||||||
std::unique_ptr<SoundFallbackPathProvider> fallback_path_provider) :
|
std::unique_ptr<SoundFallbackPathProvider> fallback_path_provider) :
|
||||||
|
Thread("OpenALSoundManager"),
|
||||||
m_fallback_path_provider(std::move(fallback_path_provider)),
|
m_fallback_path_provider(std::move(fallback_path_provider)),
|
||||||
m_device(smg->m_device.get()),
|
m_device(smg->m_device.get()),
|
||||||
m_context(smg->m_context.get())
|
m_context(smg->m_context.get())
|
||||||
|
@ -1053,8 +1052,7 @@ bool OpenALSoundManager::loadSoundFile(const std::string &name, const std::strin
|
||||||
if (!fs::IsFile(filepath))
|
if (!fs::IsFile(filepath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// remember for lazy loading
|
loadSoundFileNoCheck(name, filepath);
|
||||||
m_sound_datas_unopen.emplace(name, std::make_unique<SoundDataUnopenFile>(filepath));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,9 +1062,20 @@ bool OpenALSoundManager::loadSoundData(const std::string &name, std::string &&fi
|
||||||
if (m_sound_datas_open.count(name) != 0 || m_sound_datas_unopen.count(name) != 0)
|
if (m_sound_datas_open.count(name) != 0 || m_sound_datas_unopen.count(name) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
loadSoundDataNoCheck(name, std::move(filedata));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenALSoundManager::loadSoundFileNoCheck(const std::string &name, const std::string &filepath)
|
||||||
|
{
|
||||||
|
// remember for lazy loading
|
||||||
|
m_sound_datas_unopen.emplace(name, std::make_unique<SoundDataUnopenFile>(filepath));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenALSoundManager::loadSoundDataNoCheck(const std::string &name, std::string &&filedata)
|
||||||
|
{
|
||||||
// remember for lazy loading
|
// remember for lazy loading
|
||||||
m_sound_datas_unopen.emplace(name, std::make_unique<SoundDataUnopenBuffer>(std::move(filedata)));
|
m_sound_datas_unopen.emplace(name, std::make_unique<SoundDataUnopenBuffer>(std::move(filedata)));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALSoundManager::addSoundToGroup(const std::string &sound_name, const std::string &group_name)
|
void OpenALSoundManager::addSoundToGroup(const std::string &sound_name, const std::string &group_name)
|
||||||
|
@ -1126,3 +1135,229 @@ void OpenALSoundManager::updateSoundPosVel(sound_handle_t id, const v3f &pos_,
|
||||||
return;
|
return;
|
||||||
i->second->updatePosVel(pos, vel);
|
i->second->updatePosVel(pos, vel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *OpenALSoundManager::run()
|
||||||
|
{
|
||||||
|
using namespace sound_manager_messages_to_mgr;
|
||||||
|
|
||||||
|
struct MsgVisitor {
|
||||||
|
enum class Result { Ok, Empty, StopRequested };
|
||||||
|
|
||||||
|
OpenALSoundManager &mgr;
|
||||||
|
|
||||||
|
Result operator()(std::monostate &&) {
|
||||||
|
return Result::Empty; }
|
||||||
|
|
||||||
|
Result operator()(PauseAll &&) {
|
||||||
|
mgr.pauseAll(); return Result::Ok; }
|
||||||
|
Result operator()(ResumeAll &&) {
|
||||||
|
mgr.resumeAll(); return Result::Ok; }
|
||||||
|
|
||||||
|
Result operator()(UpdateListener &&msg) {
|
||||||
|
mgr.updateListener(msg.pos_, msg.vel_, msg.at_, msg.up_); return Result::Ok; }
|
||||||
|
Result operator()(SetListenerGain &&msg) {
|
||||||
|
mgr.setListenerGain(msg.gain); return Result::Ok; }
|
||||||
|
|
||||||
|
Result operator()(LoadSoundFile &&msg) {
|
||||||
|
mgr.loadSoundFileNoCheck(msg.name, msg.filepath); return Result::Ok; }
|
||||||
|
Result operator()(LoadSoundData &&msg) {
|
||||||
|
mgr.loadSoundDataNoCheck(msg.name, std::move(msg.filedata)); return Result::Ok; }
|
||||||
|
Result operator()(AddSoundToGroup &&msg) {
|
||||||
|
mgr.addSoundToGroup(msg.sound_name, msg.group_name); return Result::Ok; }
|
||||||
|
|
||||||
|
Result operator()(PlaySound &&msg) {
|
||||||
|
mgr.playSound(msg.id, msg.spec); return Result::Ok; }
|
||||||
|
Result operator()(PlaySoundAt &&msg) {
|
||||||
|
mgr.playSoundAt(msg.id, msg.spec, msg.pos_, msg.vel_); return Result::Ok; }
|
||||||
|
Result operator()(StopSound &&msg) {
|
||||||
|
mgr.stopSound(msg.sound); return Result::Ok; }
|
||||||
|
Result operator()(FadeSound &&msg) {
|
||||||
|
mgr.fadeSound(msg.soundid, msg.step, msg.target_gain); return Result::Ok; }
|
||||||
|
Result operator()(UpdateSoundPosVel &&msg) {
|
||||||
|
mgr.updateSoundPosVel(msg.sound, msg.pos_, msg.vel_); return Result::Ok; }
|
||||||
|
|
||||||
|
Result operator()(PleaseStop &&msg) {
|
||||||
|
return Result::StopRequested; }
|
||||||
|
};
|
||||||
|
|
||||||
|
u64 t_step_start = porting::getTimeMs();
|
||||||
|
while (true) {
|
||||||
|
auto get_time_since_last_step = [&] {
|
||||||
|
return (f32)(porting::getTimeMs() - t_step_start);
|
||||||
|
};
|
||||||
|
auto get_remaining_timeout = [&] {
|
||||||
|
return (s32)((1.0e3f * PROXYSOUNDMGR_DTIME) - get_time_since_last_step());
|
||||||
|
};
|
||||||
|
|
||||||
|
bool stop_requested = false;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
SoundManagerMsgToMgr msg =
|
||||||
|
m_queue_to_mgr.pop_frontNoEx(std::max(get_remaining_timeout(), 0));
|
||||||
|
|
||||||
|
MsgVisitor::Result res = std::visit(MsgVisitor{*this}, std::move(msg));
|
||||||
|
|
||||||
|
if (res == MsgVisitor::Result::Empty && get_remaining_timeout() <= 0) {
|
||||||
|
break; // finished sleeping
|
||||||
|
} else if (res == MsgVisitor::Result::StopRequested) {
|
||||||
|
stop_requested = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stop_requested)
|
||||||
|
break;
|
||||||
|
|
||||||
|
f32 dtime = get_time_since_last_step();
|
||||||
|
t_step_start = porting::getTimeMs();
|
||||||
|
step(dtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(sound_manager_messages_to_proxy::Stopped{});
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ProxySoundManager class
|
||||||
|
*/
|
||||||
|
|
||||||
|
ProxySoundManager::MsgResult ProxySoundManager::handleMsg(SoundManagerMsgToProxy &&msg)
|
||||||
|
{
|
||||||
|
using namespace sound_manager_messages_to_proxy;
|
||||||
|
|
||||||
|
return std::visit([&](auto &&msg) {
|
||||||
|
using T = std::decay_t<decltype(msg)>;
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, std::monostate>)
|
||||||
|
return MsgResult::Empty;
|
||||||
|
else if constexpr (std::is_same_v<T, ReportRemovedSound>)
|
||||||
|
reportRemovedSound(msg.id);
|
||||||
|
else if constexpr (std::is_same_v<T, Stopped>)
|
||||||
|
return MsgResult::Stopped;
|
||||||
|
|
||||||
|
return MsgResult::Ok;
|
||||||
|
},
|
||||||
|
std::move(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxySoundManager::~ProxySoundManager()
|
||||||
|
{
|
||||||
|
if (m_sound_manager.isRunning()) {
|
||||||
|
send(sound_manager_messages_to_mgr::PleaseStop{});
|
||||||
|
|
||||||
|
// recv until it stopped
|
||||||
|
auto recv = [&] {
|
||||||
|
return m_sound_manager.m_queue_to_proxy.pop_frontNoEx();
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (handleMsg(recv()) == MsgResult::Stopped)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// join
|
||||||
|
m_sound_manager.stop();
|
||||||
|
SANITY_CHECK(m_sound_manager.wait());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::step(f32 dtime)
|
||||||
|
{
|
||||||
|
auto recv = [&] {
|
||||||
|
return m_sound_manager.m_queue_to_proxy.pop_frontNoEx(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
MsgResult res = handleMsg(recv());
|
||||||
|
if (res == MsgResult::Empty)
|
||||||
|
break;
|
||||||
|
else if (res == MsgResult::Stopped)
|
||||||
|
throw std::runtime_error("OpenALSoundManager stopped unexpectedly");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::pauseAll()
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::PauseAll{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::resumeAll()
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::ResumeAll{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::updateListener(const v3f &pos_, const v3f &vel_,
|
||||||
|
const v3f &at_, const v3f &up_)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::UpdateListener{pos_, vel_, at_, up_});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::setListenerGain(f32 gain)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::SetListenerGain{gain});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxySoundManager::loadSoundFile(const std::string &name,
|
||||||
|
const std::string &filepath)
|
||||||
|
{
|
||||||
|
// do not add twice
|
||||||
|
if (m_known_sound_names.count(name) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// coarse check
|
||||||
|
if (!fs::IsFile(filepath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
send(sound_manager_messages_to_mgr::LoadSoundFile{name, filepath});
|
||||||
|
|
||||||
|
m_known_sound_names.insert(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxySoundManager::loadSoundData(const std::string &name, std::string &&filedata)
|
||||||
|
{
|
||||||
|
// do not add twice
|
||||||
|
if (m_known_sound_names.count(name) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
send(sound_manager_messages_to_mgr::LoadSoundData{name, std::move(filedata)});
|
||||||
|
|
||||||
|
m_known_sound_names.insert(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::addSoundToGroup(const std::string &sound_name,
|
||||||
|
const std::string &group_name)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::AddSoundToGroup{sound_name, group_name});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::playSound(sound_handle_t id, const SoundSpec &spec)
|
||||||
|
{
|
||||||
|
if (id == 0)
|
||||||
|
id = allocateId(1);
|
||||||
|
send(sound_manager_messages_to_mgr::PlaySound{id, spec});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::playSoundAt(sound_handle_t id, const SoundSpec &spec, const v3f &pos_,
|
||||||
|
const v3f &vel_)
|
||||||
|
{
|
||||||
|
if (id == 0)
|
||||||
|
id = allocateId(1);
|
||||||
|
send(sound_manager_messages_to_mgr::PlaySoundAt{id, spec, pos_, vel_});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::stopSound(sound_handle_t sound)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::StopSound{sound});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::fadeSound(sound_handle_t soundid, f32 step, f32 target_gain)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::FadeSound{soundid, step, target_gain});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxySoundManager::updateSoundPosVel(sound_handle_t sound, const v3f &pos_, const v3f &vel_)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_mgr::UpdateSoundPosVel{sound, pos_, vel_});
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,10 @@ with this program; ifnot, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "sound_openal.h"
|
#include "sound_openal.h"
|
||||||
|
#include "../sound.h"
|
||||||
|
#include "threading/thread.h"
|
||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
|
#include "util/container.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <al.h>
|
#include <al.h>
|
||||||
|
@ -48,6 +51,7 @@ with this program; ifnot, write to the Free Software Foundation, Inc.,
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,6 +145,8 @@ constexpr f32 SOUND_DURATION_MAX_SINGLE = 3.0f;
|
||||||
constexpr f32 MIN_STREAM_BUFFER_LENGTH = 1.0f;
|
constexpr f32 MIN_STREAM_BUFFER_LENGTH = 1.0f;
|
||||||
// duration in seconds of one bigstep
|
// duration in seconds of one bigstep
|
||||||
constexpr f32 STREAM_BIGSTEP_TIME = 0.3f;
|
constexpr f32 STREAM_BIGSTEP_TIME = 0.3f;
|
||||||
|
// step duration for the ProxySoundManager, in seconds
|
||||||
|
constexpr f32 PROXYSOUNDMGR_DTIME = 0.016f;
|
||||||
|
|
||||||
static_assert(MIN_STREAM_BUFFER_LENGTH > STREAM_BIGSTEP_TIME * 2.0f,
|
static_assert(MIN_STREAM_BUFFER_LENGTH > STREAM_BIGSTEP_TIME * 2.0f,
|
||||||
"See [Streaming of sounds].");
|
"See [Streaming of sounds].");
|
||||||
|
@ -506,10 +512,67 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The public ISoundManager interface
|
* The SoundManager thread
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class OpenALSoundManager final : public ISoundManager
|
namespace sound_manager_messages_to_mgr {
|
||||||
|
struct PauseAll {};
|
||||||
|
struct ResumeAll {};
|
||||||
|
|
||||||
|
struct UpdateListener { v3f pos_; v3f vel_; v3f at_; v3f up_; };
|
||||||
|
struct SetListenerGain { f32 gain; };
|
||||||
|
|
||||||
|
struct LoadSoundFile { std::string name; std::string filepath; };
|
||||||
|
struct LoadSoundData { std::string name; std::string filedata; };
|
||||||
|
struct AddSoundToGroup { std::string sound_name; std::string group_name; };
|
||||||
|
|
||||||
|
struct PlaySound { sound_handle_t id; SoundSpec spec; };
|
||||||
|
struct PlaySoundAt { sound_handle_t id; SoundSpec spec; v3f pos_; v3f vel_; };
|
||||||
|
struct StopSound { sound_handle_t sound; };
|
||||||
|
struct FadeSound { sound_handle_t soundid; f32 step; f32 target_gain; };
|
||||||
|
struct UpdateSoundPosVel { sound_handle_t sound; v3f pos_; v3f vel_; };
|
||||||
|
|
||||||
|
struct PleaseStop {};
|
||||||
|
}
|
||||||
|
|
||||||
|
using SoundManagerMsgToMgr = std::variant<
|
||||||
|
std::monostate,
|
||||||
|
|
||||||
|
sound_manager_messages_to_mgr::PauseAll,
|
||||||
|
sound_manager_messages_to_mgr::ResumeAll,
|
||||||
|
|
||||||
|
sound_manager_messages_to_mgr::UpdateListener,
|
||||||
|
sound_manager_messages_to_mgr::SetListenerGain,
|
||||||
|
|
||||||
|
sound_manager_messages_to_mgr::LoadSoundFile,
|
||||||
|
sound_manager_messages_to_mgr::LoadSoundData,
|
||||||
|
sound_manager_messages_to_mgr::AddSoundToGroup,
|
||||||
|
|
||||||
|
sound_manager_messages_to_mgr::PlaySound,
|
||||||
|
sound_manager_messages_to_mgr::PlaySoundAt,
|
||||||
|
sound_manager_messages_to_mgr::StopSound,
|
||||||
|
sound_manager_messages_to_mgr::FadeSound,
|
||||||
|
sound_manager_messages_to_mgr::UpdateSoundPosVel,
|
||||||
|
|
||||||
|
sound_manager_messages_to_mgr::PleaseStop
|
||||||
|
>;
|
||||||
|
|
||||||
|
namespace sound_manager_messages_to_proxy {
|
||||||
|
struct ReportRemovedSound { sound_handle_t id; };
|
||||||
|
|
||||||
|
struct Stopped {};
|
||||||
|
}
|
||||||
|
|
||||||
|
using SoundManagerMsgToProxy = std::variant<
|
||||||
|
std::monostate,
|
||||||
|
|
||||||
|
sound_manager_messages_to_proxy::ReportRemovedSound,
|
||||||
|
|
||||||
|
sound_manager_messages_to_proxy::Stopped
|
||||||
|
>;
|
||||||
|
|
||||||
|
// not an ISoundManager. doesn't allocate ids, and doesn't accept id 0
|
||||||
|
class OpenALSoundManager final : public Thread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SoundFallbackPathProvider> m_fallback_path_provider;
|
std::unique_ptr<SoundFallbackPathProvider> m_fallback_path_provider;
|
||||||
|
@ -540,6 +603,11 @@ private:
|
||||||
// if true, all sounds will be directly paused after creation
|
// if true, all sounds will be directly paused after creation
|
||||||
bool m_is_paused = false;
|
bool m_is_paused = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// used for communication with ProxySoundManager
|
||||||
|
MutexedQueue<SoundManagerMsgToMgr> m_queue_to_mgr;
|
||||||
|
MutexedQueue<SoundManagerMsgToProxy> m_queue_to_proxy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void stepStreams(f32 dtime);
|
void stepStreams(f32 dtime);
|
||||||
void doFades(f32 dtime);
|
void doFades(f32 dtime);
|
||||||
|
@ -591,6 +659,75 @@ public:
|
||||||
|
|
||||||
DISABLE_CLASS_COPY(OpenALSoundManager)
|
DISABLE_CLASS_COPY(OpenALSoundManager)
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Similar to ISoundManager */
|
||||||
|
|
||||||
|
void step(f32 dtime);
|
||||||
|
void pauseAll();
|
||||||
|
void resumeAll();
|
||||||
|
|
||||||
|
void updateListener(const v3f &pos_, const v3f &vel_, const v3f &at_, const v3f &up_);
|
||||||
|
void setListenerGain(f32 gain);
|
||||||
|
|
||||||
|
bool loadSoundFile(const std::string &name, const std::string &filepath);
|
||||||
|
bool loadSoundData(const std::string &name, std::string &&filedata);
|
||||||
|
void loadSoundFileNoCheck(const std::string &name, const std::string &filepath);
|
||||||
|
void loadSoundDataNoCheck(const std::string &name, std::string &&filedata);
|
||||||
|
void addSoundToGroup(const std::string &sound_name, const std::string &group_name);
|
||||||
|
|
||||||
|
void playSound(sound_handle_t id, const SoundSpec &spec);
|
||||||
|
void playSoundAt(sound_handle_t id, const SoundSpec &spec, const v3f &pos_,
|
||||||
|
const v3f &vel_);
|
||||||
|
void stopSound(sound_handle_t sound);
|
||||||
|
void fadeSound(sound_handle_t soundid, f32 step, f32 target_gain);
|
||||||
|
void updateSoundPosVel(sound_handle_t sound, const v3f &pos_, const v3f &vel_);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Thread stuff */
|
||||||
|
|
||||||
|
void *run() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void send(SoundManagerMsgToProxy msg)
|
||||||
|
{
|
||||||
|
m_queue_to_proxy.push_back(std::move(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportRemovedSound(sound_handle_t id)
|
||||||
|
{
|
||||||
|
send(sound_manager_messages_to_proxy::ReportRemovedSound{id});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The public ISoundManager interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ProxySoundManager final : public ISoundManager
|
||||||
|
{
|
||||||
|
OpenALSoundManager m_sound_manager;
|
||||||
|
// sound names from loadSoundData and loadSoundFile
|
||||||
|
std::unordered_set<std::string> m_known_sound_names;
|
||||||
|
|
||||||
|
void send(SoundManagerMsgToMgr msg)
|
||||||
|
{
|
||||||
|
m_sound_manager.m_queue_to_mgr.push_back(std::move(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class MsgResult { Ok, Empty, Stopped};
|
||||||
|
MsgResult handleMsg(SoundManagerMsgToProxy &&msg);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProxySoundManager(SoundManagerSingleton *smg,
|
||||||
|
std::unique_ptr<SoundFallbackPathProvider> fallback_path_provider) :
|
||||||
|
m_sound_manager(smg, std::move(fallback_path_provider))
|
||||||
|
{
|
||||||
|
m_sound_manager.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProxySoundManager() override;
|
||||||
|
|
||||||
/* Interface */
|
/* Interface */
|
||||||
|
|
||||||
void step(f32 dtime) override;
|
void step(f32 dtime) override;
|
||||||
|
|
Loading…
Add table
Reference in a new issue