From 663c7aacaf62586785c14602888c67ac95adfb09 Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Sat, 2 Sep 2017 22:00:37 -0400 Subject: [PATCH] Tweak kart audio code to use fewer OpenAL sources (see #2921). Seems to work well, though I need to take a closer look to make it thread-safe --- src/audio/sfx_base.hpp | 1 + src/audio/sfx_manager.cpp | 16 +++++++ src/audio/sfx_manager.hpp | 3 ++ src/audio/sfx_openal.cpp | 29 +++++++++++++ src/audio/sfx_openal.hpp | 4 ++ src/karts/kart.cpp | 90 ++++++++++++++++++++++----------------- src/karts/kart.hpp | 17 +++++--- 7 files changed, 114 insertions(+), 46 deletions(-) diff --git a/src/audio/sfx_base.hpp b/src/audio/sfx_base.hpp index f01479346..e0fff346d 100644 --- a/src/audio/sfx_base.hpp +++ b/src/audio/sfx_base.hpp @@ -83,6 +83,7 @@ public: virtual void onSoundEnabledBack() = 0; virtual void setRolloff(float rolloff) = 0; virtual const SFXBuffer* getBuffer() const = 0; + virtual void setBuffer(SFXBuffer* buffer, bool owns_buffer) = 0; virtual SFXStatus getStatus() = 0; }; // SFXBase diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp index 4761e2c47..12b24ba5d 100644 --- a/src/audio/sfx_manager.cpp +++ b/src/audio/sfx_manager.cpp @@ -675,6 +675,22 @@ SFXBase* SFXManager::createSoundSource(const std::string &name, return createSoundSource( i->second, add_to_SFXList ); } // createSoundSource +//---------------------------------------------------------------------------- + +SFXBuffer* SFXManager::getBuffer(const std::string &name) +{ + std::map::iterator i = m_all_sfx_types.find(name); + if (i == m_all_sfx_types.end()) + { + Log::error("SFXManager", + "SFXManager::getBuffer could not find the " + "requested sound effect : '%s'.", name.c_str()); + return NULL; + } + + return i->second; +} + //---------------------------------------------------------------------------- /** Returns true if a sfx with the given name exists. * \param name The internal name of the sfx (not the name of the ogg file) diff --git a/src/audio/sfx_manager.hpp b/src/audio/sfx_manager.hpp index d9bfbf515..8e0c701cc 100644 --- a/src/audio/sfx_manager.hpp +++ b/src/audio/sfx_manager.hpp @@ -296,6 +296,9 @@ public: /** Returns the current position of the listener. */ Vec3 getListenerPos() const { return m_listener_position.getData(); } + // ------------------------------------------------------------------------ + + SFXBuffer* getBuffer(const std::string &name); }; #endif // HEADER_SFX_MANAGER_HPP diff --git a/src/audio/sfx_openal.cpp b/src/audio/sfx_openal.cpp index 652fd56c6..61456e5a3 100644 --- a/src/audio/sfx_openal.cpp +++ b/src/audio/sfx_openal.cpp @@ -52,6 +52,7 @@ SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float volume, m_master_gain = 1.0f; m_owns_buffer = owns_buffer; m_play_time = 0.0f; + m_sound_buffer_changed = false; // Don't initialise anything else if the sfx manager was not correctly // initialised. First of all the initialisation will not work, and it @@ -377,6 +378,18 @@ void SFXOpenAL::reallyPlayNow() if (m_status==SFX_UNKNOWN) return; } + if (m_sound_buffer_changed) + { + if (m_status == SFX_PLAYING || m_status == SFX_PAUSED) + reallyStopNow(); + + alSourcei(m_sound_source, AL_BUFFER, m_sound_buffer->getBufferID()); + m_sound_buffer_changed = false; + + if (!SFXManager::checkError("attaching the buffer to the source")) + return; + } + alSourcePlay(m_sound_source); SFXManager::checkError("playing"); // Esp. with terrain sounds it can (very likely) happen that the status @@ -528,4 +541,20 @@ void SFXOpenAL::setRolloff(float rolloff) alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff); } +//----------------------------------------------------------------------------- + +// TODO: make this thread-safe +void SFXOpenAL::setBuffer(SFXBuffer* buffer, bool owns_buffer) +{ + if (m_owns_buffer && m_sound_buffer) + { + m_sound_buffer->unload(); + delete m_sound_buffer; + } + + m_sound_buffer = buffer; + m_owns_buffer = owns_buffer; + m_sound_buffer_changed = true; +} + #endif //if HAVE_OGGVORBIS diff --git a/src/audio/sfx_openal.hpp b/src/audio/sfx_openal.hpp index 10b1c0717..cd2d095b4 100644 --- a/src/audio/sfx_openal.hpp +++ b/src/audio/sfx_openal.hpp @@ -75,6 +75,8 @@ private: /** How long the sfx has been playing. */ float m_play_time; + bool m_sound_buffer_changed; + public: SFXOpenAL(SFXBuffer* buffer, bool positional, float volume, bool owns_buffer = false); @@ -117,6 +119,8 @@ public: // ------------------------------------------------------------------------ /** Returns the buffer associated with this sfx. */ virtual const SFXBuffer* getBuffer() const { return m_sound_buffer; } + // ------------------------------------------------------------------------ + virtual void setBuffer(SFXBuffer* buffer, bool owns_buffer); }; // SFXOpenAL diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 6379915c9..28a1c0855 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -171,12 +171,9 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, }*/ m_engine_sound = SFXManager::get()->createSoundSource(m_kart_properties->getEngineSfxType()); - m_beep_sound = SFXManager::get()->createSoundSource( "horn" ); - m_crash_sound = SFXManager::get()->createSoundSource( "crash" ); - m_crash_sound2 = SFXManager::get()->createSoundSource( "crash2"); - m_crash_sound3 = SFXManager::get()->createSoundSource( "crash3"); - m_boing_sound = SFXManager::get()->createSoundSource( "boing" ); - m_goo_sound = SFXManager::get()->createSoundSource( "goo" ); + m_emitter_1 = SFXManager::get()->createSoundSource("crash"); + m_emitter_2 = SFXManager::get()->createSoundSource("crash"); + m_emitter_3 = SFXManager::get()->createSoundSource("crash"); m_skid_sound = SFXManager::get()->createSoundSource( "skid" ); m_nitro_sound = SFXManager::get()->createSoundSource( "nitro" ); m_terrain_sound = NULL; @@ -201,13 +198,10 @@ void Kart::init(RaceManager::KartType type) if (type == RaceManager::KT_PLAYER) factor = std::min(1.0f, race_manager->getNumLocalPlayers()/2.0f); - m_goo_sound->setVolume(factor); + m_emitter_1->setVolume(factor); + m_emitter_2->setVolume(factor); + m_emitter_3->setVolume(factor); m_skid_sound->setVolume(factor); - m_crash_sound->setVolume(factor); - m_crash_sound2->setVolume(factor); - m_crash_sound3->setVolume(factor); - m_boing_sound->setVolume(factor); - m_beep_sound->setVolume(factor); m_nitro_sound->setVolume(factor); } // if getNumLocalPlayers > 1 @@ -257,13 +251,10 @@ Kart::~Kart() }*/ m_engine_sound->deleteSFX(); - m_crash_sound ->deleteSFX(); - m_crash_sound2->deleteSFX(); - m_crash_sound3->deleteSFX(); m_skid_sound ->deleteSFX(); - m_goo_sound ->deleteSFX(); - m_beep_sound ->deleteSFX(); - m_boing_sound ->deleteSFX(); + m_emitter_1->deleteSFX(); + m_emitter_2->deleteSFX(); + m_emitter_3->deleteSFX(); m_nitro_sound ->deleteSFX(); delete m_kart_gfx; if(m_terrain_sound) m_terrain_sound->deleteSFX(); @@ -1029,8 +1020,11 @@ void Kart::collectedItem(Item *item, int add_info) m_kart_properties->getBubblegumSpeedFraction() , m_kart_properties->getBubblegumFadeInTime(), m_bubblegum_time); - m_goo_sound->setPosition(getXYZ()); - m_goo_sound->play(); + { + SFXBase* emitter = getNextEmitter(); + emitter->setBuffer(SFXManager::get()->getBuffer("goo"), false); + emitter->play(getXYZ()); + } // Play appropriate custom character sound playCustomSFX(SFXManager::CUSTOM_GOO); break; @@ -1361,12 +1355,10 @@ void Kart::update(float dt) } */ - m_beep_sound->setPosition ( getXYZ() ); - m_crash_sound->setPosition ( getXYZ() ); - m_crash_sound2->setPosition ( getXYZ() ); - m_crash_sound3->setPosition ( getXYZ() ); + m_emitter_1->setPosition(getXYZ()); + m_emitter_2->setPosition(getXYZ()); + m_emitter_3->setPosition(getXYZ()); m_skid_sound->setPosition ( getXYZ() ); - m_boing_sound->setPosition ( getXYZ() ); m_nitro_sound->setPosition ( getXYZ() ); // Check if a kart is (nearly) upside down and not moving much --> @@ -2166,23 +2158,22 @@ void Kart::playCrashSFX(const Material* m, AbstractKart *k) // it's not already playing. if (isShielded() || (k != NULL && k->isShielded())) { - if (m_boing_sound->getStatus() != SFXBase::SFX_PLAYING) - m_boing_sound->play(getXYZ()); + SFXBase* emitter = getNextEmitter(); + emitter->setBuffer(SFXManager::get()->getBuffer("boing"), false); + emitter->play(getXYZ()); } else { - if (m_crash_sound->getStatus() != SFXBase::SFX_PLAYING - && m_crash_sound2->getStatus() != SFXBase::SFX_PLAYING - && m_crash_sound3->getStatus() != SFXBase::SFX_PLAYING) - { - int idx = rand() % 3; - if (idx == 0) - m_crash_sound->play(getXYZ()); - else if (idx == 1) - m_crash_sound2->play(getXYZ()); - else - m_crash_sound3->play(getXYZ()); - } + int idx = rand() % 3; + + SFXBase* emitter = getNextEmitter(); + if (idx == 0) + emitter->setBuffer(SFXManager::get()->getBuffer("crash"), false); + else if (idx == 1) + emitter->setBuffer(SFXManager::get()->getBuffer("crash2"), false); + else + emitter->setBuffer(SFXManager::get()->getBuffer("crash3"), false); + emitter->play(getXYZ()); } } // if lin_vel > 0.555 } // if m_bounce_back_time <= 0 @@ -2196,7 +2187,9 @@ void Kart::beep() // If the custom horn can't play (isn't defined) then play the default one if (!playCustomSFX(SFXManager::CUSTOM_HORN)) { - m_beep_sound->play(getXYZ()); + SFXBase* emitter = getNextEmitter(); + emitter->setBuffer(SFXManager::get()->getBuffer("horn"), false); + emitter->play(getXYZ()); } } // beep @@ -2690,6 +2683,23 @@ void Kart::kartIsInRestNow() m_kart_model->setDefaultSuspension(); } // kartIsInRestNow +//----------------------------------------------------------------------------- + +SFXBase* Kart::getNextEmitter() +{ + m_emitter_id = (m_emitter_id + 1) % 3; + + SFXBase* next_emitter; + if (m_emitter_id == 0) + next_emitter = m_emitter_1; + else if (m_emitter_id == 1) + next_emitter = m_emitter_2; + else + next_emitter = m_emitter_3; + + return next_emitter; +} + //----------------------------------------------------------------------------- /** Updates the graphics model. It is responsible for positioning the graphical * chasses at an 'appropriate' position: typically, the physical model has diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 9440130f1..3e2f7a307 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -206,19 +206,23 @@ protected: float m_last_factor_engine_sound; std::vector m_custom_sounds; - SFXBase *m_beep_sound; + int m_emitter_id = 0; + SFXBase *m_emitter_1; + SFXBase *m_emitter_2; + SFXBase *m_emitter_3; + //SFXBase *m_beep_sound; SFXBase *m_engine_sound; - SFXBase *m_crash_sound; - SFXBase *m_crash_sound2; - SFXBase *m_crash_sound3; + //SFXBase *m_crash_sound; + //SFXBase *m_crash_sound2; + //SFXBase *m_crash_sound3; SFXBase *m_terrain_sound; SFXBase *m_nitro_sound; /** A pointer to the previous terrain sound needs to be saved so that an * 'older' sfx can be finished and an abrupt end of the sfx is avoided. */ SFXBase *m_previous_terrain_sound; SFXBase *m_skid_sound; - SFXBase *m_goo_sound; - SFXBase *m_boing_sound; + //SFXBase *m_goo_sound; + //SFXBase *m_boing_sound; float m_time_last_crash; RaceManager::KartType m_type; @@ -237,6 +241,7 @@ protected: float getActualWheelForce(); void playCrashSFX(const Material* m, AbstractKart *k); void loadData(RaceManager::KartType type, bool animatedModel); + SFXBase* getNextEmitter(); public: Kart(const std::string& ident, unsigned int world_kart_id,