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

This commit is contained in:
auria.mg 2017-09-02 22:00:37 -04:00
parent 590ec78640
commit 663c7aacaf
7 changed files with 114 additions and 46 deletions

View File

@ -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

View File

@ -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<std::string, SFXBuffer*>::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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
SFXBase* emitter = getNextEmitter();
if (idx == 0)
m_crash_sound->play(getXYZ());
emitter->setBuffer(SFXManager::get()->getBuffer("crash"), false);
else if (idx == 1)
m_crash_sound2->play(getXYZ());
emitter->setBuffer(SFXManager::get()->getBuffer("crash2"), false);
else
m_crash_sound3->play(getXYZ());
}
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

View File

@ -206,19 +206,23 @@ protected:
float m_last_factor_engine_sound;
std::vector<SFXBase*> 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,