From c147dacbc29b2d634db43894e5da791ab5fc771b Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 18 Sep 2014 11:43:26 +1000 Subject: [PATCH] Queue up sfx instead of starting them immediately. Preparation for threading the sfx manager. --- src/audio/sfx_base.hpp | 32 +++++++++++------------ src/audio/sfx_manager.cpp | 53 +++++++++++++++++++++++++++++++-------- src/audio/sfx_manager.hpp | 14 ++++++++--- src/audio/sfx_openal.cpp | 48 ++++++++++++++++++++++------------- src/audio/sfx_openal.hpp | 3 ++- src/graphics/hit_sfx.cpp | 4 ++- src/main_loop.cpp | 3 ++- 7 files changed, 105 insertions(+), 52 deletions(-) diff --git a/src/audio/sfx_base.hpp b/src/audio/sfx_base.hpp index 39229fd3f..033d57c05 100644 --- a/src/audio/sfx_base.hpp +++ b/src/audio/sfx_base.hpp @@ -42,26 +42,24 @@ class Vec3; class SFXBase : public NoCopy { public: - virtual ~SFXBase() {} + virtual ~SFXBase() {} /** Late creation, if SFX was initially disabled */ - virtual bool init() = 0; - + virtual bool init() = 0; virtual void position(const Vec3 &position) = 0; - virtual void setLoop(bool status) = 0; - virtual void play() = 0; - virtual void stop() = 0; - virtual void pause() = 0; - virtual void resume() = 0; - virtual void speed(float factor) = 0; - virtual void volume(float gain) = 0; - virtual void masterVolume(float gain) = 0; - virtual SFXManager::SFXStatus - getStatus() = 0; - virtual void onSoundEnabledBack() = 0; - virtual void setRolloff(float rolloff) = 0; - - virtual const SFXBuffer* getBuffer() const = 0; + virtual void setLoop(bool status) = 0; + virtual void play() = 0; + virtual void reallyPlayNow() = 0; + virtual void stop() = 0; + virtual void pause() = 0; + virtual void resume() = 0; + virtual void speed(float factor) = 0; + virtual void volume(float gain) = 0; + virtual void setMasterVolume(float gain) = 0; + virtual void onSoundEnabledBack() = 0; + virtual void setRolloff(float rolloff) = 0; + virtual const SFXBuffer* getBuffer() const = 0; + virtual SFXManager::SFXStatus getStatus() = 0; }; // SfxBase diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp index ca1f14e8c..115addf3b 100644 --- a/src/audio/sfx_manager.cpp +++ b/src/audio/sfx_manager.cpp @@ -18,8 +18,11 @@ #include "audio/dummy_sfx.hpp" #include "audio/music_manager.hpp" +#include "audio/sfx_openal.hpp" #include "audio/sfx_buffer.hpp" +#include "config/user_config.hpp" #include "io/file_manager.hpp" +#include "race/race_manager.hpp" #include #include @@ -39,12 +42,6 @@ # endif #endif -#include "audio/sfx_openal.hpp" -#include "config/user_config.hpp" -#include "io/file_manager.hpp" -#include "race/race_manager.hpp" -#include "utils/constants.hpp" - SFXManager *SFXManager::m_sfx_manager; // ---------------------------------------------------------------------------- @@ -80,7 +77,9 @@ SFXManager::SFXManager() loadSfx(); if (!sfxAllowed()) return; setMasterSFXVolume( UserConfigParams::m_sfx_volume ); - + m_sfx_to_play.lock(); + m_sfx_to_play.getData().clear(); + m_sfx_to_play.unlock(); } // SoundManager //----------------------------------------------------------------------------- @@ -122,6 +121,40 @@ SFXManager::~SFXManager() } // ~SFXManager +//---------------------------------------------------------------------------- +/** Adds a sound effect to the queue of sfx to be started by the sfx manager. + * Starting a sfx can sometimes cause a 5ms delay, so it is done in a + * separate thread. + * \param sfx The sound effect to be started. + */ +void SFXManager::queue(SFXBase *sfx) +{ + // Don't add sfx that are either not working correctly (e.g. because sfx + // are disabled); + if(sfx->getStatus()==SFX_UNKNOWN ) return; + + m_sfx_to_play.lock(); + m_sfx_to_play.getData().push_back(sfx); + m_sfx_to_play.unlock(); +} // playSFX + +//---------------------------------------------------------------------------- +/** Starts all sfx that are queues to be started. Called once per frame. + */ +void SFXManager::update() +{ + m_sfx_to_play.lock(); + while(!m_sfx_to_play.getData().empty()) + { + SFXBase *sfx = m_sfx_to_play.getData().front(); + m_sfx_to_play.getData().erase(m_sfx_to_play.getData().begin()); + m_sfx_to_play.unlock(); + sfx->reallyPlayNow(); + m_sfx_to_play.lock(); + } // while !empty + m_sfx_to_play.unlock(); +} // update + //---------------------------------------------------------------------------- /** Called then sound is globally switched on or off. It either pauses or * resumes all sound effects. @@ -327,7 +360,7 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer, SFXBase* sfx = new DummySFX(buffer, positional, buffer->getGain(), owns_buffer); #endif - sfx->masterVolume(m_master_gain); + sfx->setMasterVolume(m_master_gain); if (add_to_SFX_list) m_all_sfx.push_back(sfx); @@ -475,7 +508,7 @@ void SFXManager::setMasterSFXVolume(float gain) for (std::vector::iterator i=m_all_sfx.begin(); i!=m_all_sfx.end(); i++) { - (*i)->masterVolume(m_master_gain); + (*i)->setMasterVolume(m_master_gain); } // for i in m_all_sfx } @@ -484,7 +517,7 @@ void SFXManager::setMasterSFXVolume(float gain) std::map::iterator i = m_quick_sounds.begin(); for (; i != m_quick_sounds.end(); i++) { - (*i).second->masterVolume(m_master_gain); + (*i).second->setMasterVolume(m_master_gain); } } diff --git a/src/audio/sfx_manager.hpp b/src/audio/sfx_manager.hpp index 0a859a486..e3aacaaba 100644 --- a/src/audio/sfx_manager.hpp +++ b/src/audio/sfx_manager.hpp @@ -19,10 +19,13 @@ #ifndef HEADER_SFX_MANAGER_HPP #define HEADER_SFX_MANAGER_HPP +#include "utils/no_copy.hpp" +#include "utils/synchronised.hpp" +#include "utils/vec3.hpp" +#include #include #include -#include #if HAVE_OGGVORBIS # ifdef __APPLE__ @@ -31,11 +34,9 @@ # include # endif #else -typedef unsigned int ALuint; + typedef unsigned int ALuint; #endif -#include "utils/no_copy.hpp" -#include "utils/vec3.hpp" class SFXBase; class SFXBuffer; @@ -94,6 +95,9 @@ private: /** The actual instances (sound sources) */ std::vector m_all_sfx; + /** The list of sound effects to be played in the next update. */ + Synchronised< std::vector > m_sfx_to_play; + /** To play non-positional sounds without having to create a new object for each */ std::map m_quick_sounds; @@ -113,6 +117,8 @@ private: public: static void create(); static void destroy(); + void queue(SFXBase *sfx); + void update(); // ------------------------------------------------------------------------ /** Static function to get the singleton sfx manager. */ static SFXManager *get() diff --git a/src/audio/sfx_openal.cpp b/src/audio/sfx_openal.cpp index 5b9e0412d..83c503ca6 100644 --- a/src/audio/sfx_openal.cpp +++ b/src/audio/sfx_openal.cpp @@ -85,28 +85,30 @@ bool SFXOpenAL::init() assert( alIsBuffer(m_soundBuffer->getBufferID()) ); assert( alIsSource(m_soundSource) ); - //std::cout << "Setting a source with buffer " << m_soundBuffer << ", rolloff " << rolloff - // << ", gain=" << m_defaultGain << ", positional=" << (positional ? "true" : "false") << std::endl; + //std::cout << "Setting a source with buffer " << m_soundBuffer + // << ", rolloff " << rolloff + // << ", gain=" << m_defaultGain << ", positional=" + // << (positional ? "true" : "false") << std::endl; - alSourcei (m_soundSource, AL_BUFFER, m_soundBuffer->getBufferID()); + alSourcei (m_soundSource, AL_BUFFER, m_soundBuffer->getBufferID()); - if (!SFXManager::checkError("attaching the buffer to the source")) return false; + if (!SFXManager::checkError("attaching the buffer to the source")) + return false; - alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0); - alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0); + alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0); + alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0); - alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, m_soundBuffer->getRolloff()); - - alSourcef (m_soundSource, AL_MAX_DISTANCE, m_soundBuffer->getMaxDist()); + alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, m_soundBuffer->getRolloff()); + alSourcef (m_soundSource, AL_MAX_DISTANCE, m_soundBuffer->getMaxDist()); if (m_gain < 0.0f) { - alSourcef (m_soundSource, AL_GAIN, m_defaultGain * m_master_gain); + alSourcef (m_soundSource, AL_GAIN, m_defaultGain * m_master_gain); } else { - alSourcef (m_soundSource, AL_GAIN, m_gain * m_master_gain); + alSourcef (m_soundSource, AL_GAIN, m_gain * m_master_gain); } if (m_positional) alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE); @@ -117,7 +119,7 @@ bool SFXOpenAL::init() m_ok = SFXManager::checkError("setting up the source"); return m_ok; -} +} // init //----------------------------------------------------------------------------- /** Changes the pitch of a sound effect. @@ -156,15 +158,16 @@ void SFXOpenAL::volume(float gain) //----------------------------------------------------------------------------- -void SFXOpenAL::masterVolume(float gain) +void SFXOpenAL::setMasterVolume(float gain) { m_master_gain = gain; if(!m_ok) return; - alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain); + alSourcef(m_soundSource, AL_GAIN, + (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain); SFXManager::checkError("setting volume"); -} +} //setMasterVolume //----------------------------------------------------------------------------- /** Loops this sound effect. @@ -222,9 +225,18 @@ void SFXOpenAL::resume() } // resume //----------------------------------------------------------------------------- -/** Plays this sound effect. +/** This actually queues up the sfx in the sfx manager. It will be started + * from a separate thread later (in this frame). */ void SFXOpenAL::play() +{ + SFXManager::get()->queue(this); +} // play + +//----------------------------------------------------------------------------- +/** Plays this sound effect. + */ +void SFXOpenAL::reallyPlayNow() { if (!SFXManager::get()->sfxAllowed()) return; if (!m_ok) @@ -238,7 +250,7 @@ void SFXOpenAL::play() alSourcePlay(m_soundSource); SFXManager::checkError("playing"); -} // play +} // reallyPlayNow //----------------------------------------------------------------------------- /** Sets the position where this sound effects is played. diff --git a/src/audio/sfx_openal.hpp b/src/audio/sfx_openal.hpp index 5ba26e8e0..58a93eafb 100644 --- a/src/audio/sfx_openal.hpp +++ b/src/audio/sfx_openal.hpp @@ -70,6 +70,7 @@ public: virtual bool init(); virtual void play(); + virtual void reallyPlayNow(); virtual void setLoop(bool status); virtual void stop(); virtual void pause(); @@ -77,7 +78,7 @@ public: virtual void speed(float factor); virtual void position(const Vec3 &position); virtual void volume(float gain); - virtual void masterVolume(float gain); + virtual void setMasterVolume(float gain); virtual SFXManager::SFXStatus getStatus(); virtual void onSoundEnabledBack(); virtual void setRolloff(float rolloff); diff --git a/src/graphics/hit_sfx.cpp b/src/graphics/hit_sfx.cpp index 71095979a..53800b28c 100644 --- a/src/graphics/hit_sfx.cpp +++ b/src/graphics/hit_sfx.cpp @@ -67,5 +67,7 @@ void HitSFX::setPlayerKartHit() */ bool HitSFX::updateAndDelete(float dt) { - return m_sfx->getStatus() != SFXManager::SFX_PLAYING; + SFXManager::SFXStatus status = m_sfx->getStatus(); + if(status==SFXManager::SFX_INITIAL) return false; + return status!= SFXManager::SFX_PLAYING; } // updateAndDelete diff --git a/src/main_loop.cpp b/src/main_loop.cpp index 3052c9ed8..2ea4be613 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -22,6 +22,7 @@ #include #include "audio/music_manager.hpp" +#include "audio/sfx_manager.hpp" #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" #include "graphics/material_manager.hpp" @@ -139,7 +140,7 @@ void MainLoop::run() { PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00); music_manager->update(dt); - + SFXManager::get()->update(); input_manager->update(dt); #ifdef ENABLE_WIIUSE