Skip to content

Commit

Permalink
Global initialization of sound using SoundManagerGlobal (#7063)
Browse files Browse the repository at this point in the history
* Global initialization of sound using SoundManagerGlobal
  • Loading branch information
nOOb3167 authored and nerzhul committed Mar 23, 2018
1 parent 9fcc0c1 commit 9293d8e
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 84 deletions.
9 changes: 9 additions & 0 deletions src/client/clientlauncher.cpp
Expand Up @@ -35,6 +35,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "renderingengine.h" #include "renderingengine.h"
#include "network/networkexceptions.h" #include "network/networkexceptions.h"


#if USE_SOUND
#include "sound_openal.h"
#endif

/* mainmenumanager.h /* mainmenumanager.h
*/ */
gui::IGUIEnvironment *guienv = nullptr; gui::IGUIEnvironment *guienv = nullptr;
Expand Down Expand Up @@ -71,6 +75,11 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
if (list_video_modes) if (list_video_modes)
return RenderingEngine::print_video_modes(); return RenderingEngine::print_video_modes();


#if USE_SOUND
if (g_settings->getBool("enable_sound"))
g_sound_manager_singleton = createSoundManagerSingleton();
#endif

if (!init_engine()) { if (!init_engine()) {
errorstream << "Could not initialize game engine." << std::endl; errorstream << "Could not initialize game engine." << std::endl;
return false; return false;
Expand Down
2 changes: 1 addition & 1 deletion src/game.cpp
Expand Up @@ -1219,7 +1219,7 @@ bool Game::initSound()
#if USE_SOUND #if USE_SOUND
if (g_settings->getBool("enable_sound")) { if (g_settings->getBool("enable_sound")) {
infostream << "Attempting to use OpenAL audio" << std::endl; infostream << "Attempting to use OpenAL audio" << std::endl;
sound = createOpenALSoundManager(&soundfetcher); sound = createOpenALSoundManager(g_sound_manager_singleton.get(), &soundfetcher);
if (!sound) if (!sound)
infostream << "Failed to initialize OpenAL audio" << std::endl; infostream << "Failed to initialize OpenAL audio" << std::endl;
} else } else
Expand Down
2 changes: 1 addition & 1 deletion src/gui/guiEngine.cpp
Expand Up @@ -137,7 +137,7 @@ GUIEngine::GUIEngine(JoystickController *joystick,
//create soundmanager //create soundmanager
MenuMusicFetcher soundfetcher; MenuMusicFetcher soundfetcher;
#if USE_SOUND #if USE_SOUND
m_sound_manager = createOpenALSoundManager(&soundfetcher); m_sound_manager = createOpenALSoundManager(g_sound_manager_singleton.get(), &soundfetcher);
#endif #endif
if(!m_sound_manager) if(!m_sound_manager)
m_sound_manager = &dummySoundManager; m_sound_manager = &dummySoundManager;
Expand Down
179 changes: 98 additions & 81 deletions src/sound_openal.cpp
Expand Up @@ -45,9 +45,29 @@ with this program; ifnot, write to the Free Software Foundation, Inc.,
#include <vector> #include <vector>
#include <fstream> #include <fstream>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>


#define BUFFER_SIZE 30000 #define BUFFER_SIZE 30000


std::shared_ptr<SoundManagerSingleton> g_sound_manager_singleton;

typedef std::unique_ptr<ALCdevice, void (*)(ALCdevice *p)> unique_ptr_alcdevice;
typedef std::unique_ptr<ALCcontext, void(*)(ALCcontext *p)> unique_ptr_alccontext;

static void delete_alcdevice(ALCdevice *p)
{
if (p)
alcCloseDevice(p);
}

static void delete_alccontext(ALCcontext *p)
{
if (p) {
alcMakeContextCurrent(nullptr);
alcDestroyContext(p);
}
}

static const char *alcErrorString(ALCenum err) static const char *alcErrorString(ALCenum err)
{ {
switch (err) { switch (err) {
Expand Down Expand Up @@ -146,7 +166,7 @@ SoundBuffer *load_opened_ogg_file(OggVorbis_File *oggFile,
infostream << "Audio: Error decoding " infostream << "Audio: Error decoding "
<< filename_for_logging << std::endl; << filename_for_logging << std::endl;
delete snd; delete snd;
return NULL; return nullptr;
} }


// Append to end of buffer // Append to end of buffer
Expand All @@ -161,8 +181,8 @@ SoundBuffer *load_opened_ogg_file(OggVorbis_File *oggFile,
ALenum error = alGetError(); ALenum error = alGetError();


if(error != AL_NO_ERROR){ if(error != AL_NO_ERROR){
infostream<<"Audio: OpenAL error: "<<alErrorString(error) infostream << "Audio: OpenAL error: " << alErrorString(error)
<<"preparing sound buffer"<<std::endl; << "preparing sound buffer" << std::endl;
} }


infostream << "Audio file " infostream << "Audio file "
Expand All @@ -184,7 +204,7 @@ SoundBuffer *load_ogg_from_file(const std::string &path)
if (ov_fopen(path.c_str(), &oggFile) != 0) { if (ov_fopen(path.c_str(), &oggFile) != 0) {
infostream << "Audio: Error opening " << path infostream << "Audio: Error opening " << path
<< " for decoding" << std::endl; << " for decoding" << std::endl;
return NULL; return nullptr;
} }


return load_opened_ogg_file(&oggFile, path); return load_opened_ogg_file(&oggFile, path);
Expand Down Expand Up @@ -237,7 +257,7 @@ long BufferSourceell_func(void *datasource)
static ov_callbacks g_buffer_ov_callbacks = { static ov_callbacks g_buffer_ov_callbacks = {
&buffer_sound_read_func, &buffer_sound_read_func,
&buffer_sound_seek_func, &buffer_sound_seek_func,
NULL, nullptr,
&BufferSourceell_func &BufferSourceell_func
}; };


Expand All @@ -250,10 +270,10 @@ SoundBuffer *load_ogg_from_buffer(const std::string &buf, const std::string &id_
s.cur_offset = 0; s.cur_offset = 0;
s.len = buf.size(); s.len = buf.size();


if (ov_open_callbacks(&s, &oggFile, NULL, 0, g_buffer_ov_callbacks) != 0) { if (ov_open_callbacks(&s, &oggFile, nullptr, 0, g_buffer_ov_callbacks) != 0) {
infostream << "Audio: Error opening " << id_for_log infostream << "Audio: Error opening " << id_for_log
<< " for decoding" << std::endl; << " for decoding" << std::endl;
return NULL; return nullptr;
} }


return load_opened_ogg_file(&oggFile, id_for_log); return load_opened_ogg_file(&oggFile, id_for_log);
Expand All @@ -265,6 +285,43 @@ struct PlayingSound
bool loop; bool loop;
}; };


class SoundManagerSingleton
{
public:
unique_ptr_alcdevice m_device;
unique_ptr_alccontext m_context;
public:
SoundManagerSingleton() :
m_device(nullptr, delete_alcdevice),
m_context(nullptr, delete_alccontext)
{
if (!(m_device = unique_ptr_alcdevice(alcOpenDevice(nullptr), delete_alcdevice)))
throw std::runtime_error("Audio: Global Initialization: Device Open");

if (!(m_context = unique_ptr_alccontext(
alcCreateContext(m_device.get(), nullptr), delete_alccontext))) {
throw std::runtime_error("Audio: Global Initialization: Context Create");
}

if (!alcMakeContextCurrent(m_context.get()))
throw std::runtime_error("Audio: Global Initialization: Context Current");

alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);

if (alGetError() != AL_NO_ERROR)
throw std::runtime_error("Audio: Global Initialization: OpenAL Error");

infostream << "Audio: Global Initialized: OpenAL " << alGetString(AL_VERSION)
<< ", using " << alcGetString(m_device.get(), ALC_DEVICE_SPECIFIER)
<< std::endl;
}

~SoundManagerSingleton()
{
infostream << "Audio: Global Deinitialized." << std::endl;
}
};

class OpenALSoundManager: public ISoundManager class OpenALSoundManager: public ISoundManager
{ {
private: private:
Expand All @@ -290,68 +347,27 @@ class OpenALSoundManager: public ISoundManager
std::unordered_map<int, FadeState> m_sounds_fading; std::unordered_map<int, FadeState> m_sounds_fading;
float m_fade_delay; float m_fade_delay;
public: public:
bool m_is_initialized; OpenALSoundManager(SoundManagerSingleton *smg, OnDemandSoundFetcher *fetcher):
OpenALSoundManager(OnDemandSoundFetcher *fetcher):
m_fetcher(fetcher), m_fetcher(fetcher),
m_device(NULL), m_device(smg->m_device.get()),
m_context(NULL), m_context(smg->m_context.get()),
m_next_id(1), m_next_id(1),
m_fade_delay(0), m_fade_delay(0)
m_is_initialized(false)
{ {
ALCenum error = ALC_NO_ERROR; infostream << "Audio: Initialized: OpenAL " << std::endl;

infostream<<"Audio: Initializing..."<<std::endl;

m_device = alcOpenDevice(NULL);
if(!m_device){
infostream<<"Audio: No audio device available, audio system "
<<"not initialized"<<std::endl;
return;
}

m_context = alcCreateContext(m_device, NULL);
if(!m_context){
error = alcGetError(m_device);
infostream<<"Audio: Unable to initialize audio context, "
<<"aborting audio initialization ("<<alcErrorString(error)
<<")"<<std::endl;
alcCloseDevice(m_device);
m_device = NULL;
return;
}

if(!alcMakeContextCurrent(m_context) ||
(error = alcGetError(m_device) != ALC_NO_ERROR))
{
infostream<<"Audio: Error setting audio context, aborting audio "
<<"initialization ("<<alcErrorString(error)<<")"<<std::endl;
alcDestroyContext(m_context);
m_context = NULL;
alcCloseDevice(m_device);
m_device = NULL;
return;
}

alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);

infostream<<"Audio: Initialized: OpenAL "<<alGetString(AL_VERSION)
<<", using "<<alcGetString(m_device, ALC_DEVICE_SPECIFIER)
<<std::endl;

m_is_initialized = true;
} }


~OpenALSoundManager() ~OpenALSoundManager()
{ {
infostream<<"Audio: Deinitializing..."<<std::endl; infostream << "Audio: Deinitializing..." << std::endl;
// KABOOM!
// TODO: Clear SoundBuffers std::unordered_set<int> source_del_list;
alcMakeContextCurrent(NULL);
alcDestroyContext(m_context); for (const auto &sp : m_sounds_playing)
m_context = NULL; source_del_list.insert(sp.second->source_id);
alcCloseDevice(m_device);
m_device = NULL; for (const auto &id : source_del_list)
deleteSound(id);


for (auto &buffer : m_buffers) { for (auto &buffer : m_buffers) {
for (SoundBuffer *sb : buffer.second) { for (SoundBuffer *sb : buffer.second) {
Expand All @@ -360,7 +376,8 @@ class OpenALSoundManager: public ISoundManager
buffer.second.clear(); buffer.second.clear();
} }
m_buffers.clear(); m_buffers.clear();
infostream<<"Audio: Deinitialized."<<std::endl;
infostream << "Audio: Deinitialized." << std::endl;
} }


void step(float dtime) void step(float dtime)
Expand All @@ -386,7 +403,7 @@ class OpenALSoundManager: public ISoundManager
std::unordered_map<std::string, std::vector<SoundBuffer*>>::iterator i = std::unordered_map<std::string, std::vector<SoundBuffer*>>::iterator i =
m_buffers.find(name); m_buffers.find(name);
if(i == m_buffers.end()) if(i == m_buffers.end())
return NULL; return nullptr;
std::vector<SoundBuffer*> &bufs = i->second; std::vector<SoundBuffer*> &bufs = i->second;
int j = myrand() % bufs.size(); int j = myrand() % bufs.size();
return bufs[j]; return bufs[j];
Expand All @@ -395,7 +412,7 @@ class OpenALSoundManager: public ISoundManager
PlayingSound* createPlayingSound(SoundBuffer *buf, bool loop, PlayingSound* createPlayingSound(SoundBuffer *buf, bool loop,
float volume, float pitch) float volume, float pitch)
{ {
infostream<<"OpenALSoundManager: Creating playing sound"<<std::endl; infostream << "OpenALSoundManager: Creating playing sound" << std::endl;
assert(buf); assert(buf);
PlayingSound *sound = new PlayingSound; PlayingSound *sound = new PlayingSound;
assert(sound); assert(sound);
Expand All @@ -417,8 +434,8 @@ class OpenALSoundManager: public ISoundManager
PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop, PlayingSound* createPlayingSoundAt(SoundBuffer *buf, bool loop,
float volume, v3f pos, float pitch) float volume, v3f pos, float pitch)
{ {
infostream<<"OpenALSoundManager: Creating positional playing sound" infostream << "OpenALSoundManager: Creating positional playing sound"
<<std::endl; << std::endl;
assert(buf); assert(buf);
PlayingSound *sound = new PlayingSound; PlayingSound *sound = new PlayingSound;
assert(sound); assert(sound);
Expand Down Expand Up @@ -486,7 +503,7 @@ class OpenALSoundManager: public ISoundManager
if(buf) if(buf)
return buf; return buf;
if(!m_fetcher) if(!m_fetcher)
return NULL; return nullptr;
std::set<std::string> paths; std::set<std::string> paths;
std::set<std::string> datas; std::set<std::string> datas;
m_fetcher->fetchSounds(name, paths, datas); m_fetcher->fetchSounds(name, paths, datas);
Expand All @@ -505,8 +522,8 @@ class OpenALSoundManager: public ISoundManager
verbosestream<<"OpenALSoundManager::maintain(): " verbosestream<<"OpenALSoundManager::maintain(): "
<<m_sounds_playing.size()<<" playing sounds, " <<m_sounds_playing.size()<<" playing sounds, "
<<m_buffers.size()<<" sound names loaded"<<std::endl; <<m_buffers.size()<<" sound names loaded"<<std::endl;
std::set<int> del_list; std::unordered_set<int> del_list;
for (auto &sp : m_sounds_playing) { for (const auto &sp : m_sounds_playing) {
int id = sp.first; int id = sp.first;
PlayingSound *sound = sp.second; PlayingSound *sound = sp.second;
// If not playing, remove it // If not playing, remove it
Expand Down Expand Up @@ -570,8 +587,8 @@ class OpenALSoundManager: public ISoundManager
return 0; return 0;
SoundBuffer *buf = getFetchBuffer(name); SoundBuffer *buf = getFetchBuffer(name);
if(!buf){ if(!buf){
infostream<<"OpenALSoundManager: \""<<name<<"\" not found." infostream << "OpenALSoundManager: \"" << name << "\" not found."
<<std::endl; << std::endl;
return -1; return -1;
} }
int handle = -1; int handle = -1;
Expand All @@ -591,8 +608,8 @@ class OpenALSoundManager: public ISoundManager
return 0; return 0;
SoundBuffer *buf = getFetchBuffer(name); SoundBuffer *buf = getFetchBuffer(name);
if(!buf){ if(!buf){
infostream<<"OpenALSoundManager: \""<<name<<"\" not found." infostream << "OpenALSoundManager: \"" << name << "\" not found."
<<std::endl; << std::endl;
return -1; return -1;
} }
return playSoundRawAt(buf, loop, volume, pos, pitch); return playSoundRawAt(buf, loop, volume, pos, pitch);
Expand Down Expand Up @@ -683,12 +700,12 @@ class OpenALSoundManager: public ISoundManager
} }
}; };


ISoundManager *createOpenALSoundManager(OnDemandSoundFetcher *fetcher) std::shared_ptr<SoundManagerSingleton> createSoundManagerSingleton()
{ {
OpenALSoundManager *m = new OpenALSoundManager(fetcher); return std::shared_ptr<SoundManagerSingleton>(new SoundManagerSingleton());
if(m->m_is_initialized) }
return m;
delete m;
return NULL;
};


ISoundManager *createOpenALSoundManager(SoundManagerSingleton *smg, OnDemandSoundFetcher *fetcher)
{
return new OpenALSoundManager(smg, fetcher);
};
8 changes: 7 additions & 1 deletion src/sound_openal.h
Expand Up @@ -19,6 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,


#pragma once #pragma once


#include <memory>

#include "sound.h" #include "sound.h"


ISoundManager *createOpenALSoundManager(OnDemandSoundFetcher *fetcher); class SoundManagerSingleton;
extern std::shared_ptr<SoundManagerSingleton> g_sound_manager_singleton;

std::shared_ptr<SoundManagerSingleton> createSoundManagerSingleton();
ISoundManager *createOpenALSoundManager(SoundManagerSingleton *smg, OnDemandSoundFetcher *fetcher);

0 comments on commit 9293d8e

Please sign in to comment.