Changed: Improve performance of ryzom client CSoundManager. Strange code, though.

--HG--
branch : sound_dev
This commit is contained in:
kaetemi 2012-04-11 00:48:47 +02:00
parent a346ab59ad
commit 7a95fae1f9
4 changed files with 276 additions and 143 deletions

View file

@ -0,0 +1,151 @@
/**
* \file fast_id_map.h
* \brief CFastIdMap
* \date 2012-04-10 19:28GMT
* \author Jan Boon (Kaetemi)
* CFastIdMap
*/
/*
* Copyright (C) 2012 by authors
*
* This file is part of RYZOM CORE.
* RYZOM CORE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* RYZOM CORE is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with RYZOM CORE. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef NLMISC_FAST_ID_MAP_H
#define NLMISC_FAST_ID_MAP_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/debug.h>
// Project includes
namespace NLMISC {
/**
* \brief CFastIdMap
* \date 2012-04-10 19:28GMT
* \author Jan Boon (Kaetemi)
* This template allows for assigning unique uint32 identifiers to pointers.
* Useful when externally only exposing an identifier, when pointers may have been deleted.
* The identifier is made from two uint16's, one being the direct index in the identifier vector,
* and the other being a verification value that is increased when the identifier index is re-used.
* TId must be a typedef of uint32.
* TValue should be a pointer.
*/
template<typename TId, class TValue>
class CFastIdMap
{
protected:
struct CIdInfo
{
CIdInfo() { }
CIdInfo(uint16 verification, uint16 next, TValue value) :
Verification(verification), Next(next), Value(value) { }
uint16 Verification;
uint16 Next;
TValue Value;
};
/// ID memory
std::vector<CIdInfo> m_Ids;
/// Nb of assigned IDs
uint m_Size;
/// Assigned IDs
uint16 m_Next;
public:
CFastIdMap(TValue defaultValue) : m_Size(0), m_Next(0)
{
// Id 0 will contain the last available unused id, and be 0 if no more unused id's are available
// defaultValue will be returned when the ID is not found
m_Ids.push_back(CIdInfo(0, 0, defaultValue));
}
virtual ~CFastIdMap() { }
void clear()
{
m_Ids.resize(1);
m_Ids[0].Next = 0;
}
TId insert(TValue value)
{
// get next unused index
uint16 idx = m_Ids[0].Next;
if (idx == 0)
{
// size of used elements must be equal to the vector size minus one, when everything is allocated
nlassert((m_Ids.size() - 1) == m_Size);
idx = m_Ids.size();
uint16 verification = rand();
m_Ids.push_back(CIdInfo(verification, m_Next, value));
m_Next = idx;
return (TId)(((uint32)verification) << 16) & idx;
}
else
{
m_Ids[0].Next = m_Ids[idx].Next; // restore the last unused id
m_Ids[idx].Value = value;
return (TId)(((uint32)m_Ids[idx].Verification) << 16) & idx;
}
}
void erase(TId id)
{
uint32 idx = ((uint32)id) & 0xFFFF;
uint16 verification = (uint16)(((uint32)id) >> 16);
if (m_Ids[idx].Verification == verification)
{
m_Ids[idx].Value = m_Ids[0].Value; // clean value for safety
m_Ids[idx].Verification = (uint16)(((uint32)m_Ids[idx].Verification + 1) & 0xFFFF); // change verification value, allow overflow :)
m_Ids[idx].Next = m_Ids[0].Next; // store the last unused id
m_Ids[0].Next = (uint16)idx; // set this as last unused id
}
else
{
nlwarning("Invalid ID");
}
}
TValue get(TId id)
{
uint32 idx = ((uint32)id) & 0xFFFF;
uint16 verification = (uint16)(((uint32)id) >> 16);
if (m_Ids[idx].Verification == verification)
{
return m_Ids[idx].Value;
}
else
{
nldebug("Invalid ID");
return m_Ids[0].Value;
}
}
inline uint size() { return m_Size; }
}; /* class CFastIdMap */
} /* namespace NLMISC */
#endif /* #ifndef NLMISC_FAST_ID_MAP_H */
/* end of file */

View file

@ -0,0 +1,44 @@
/**
* \file fast_id_map.cpp
* \brief CFastIdMap
* \date 2012-04-10 19:28GMT
* \author Jan Boon (Kaetemi)
* CFastIdMap
*/
/*
* Copyright (C) 2012 by authors
*
* This file is part of RYZOM CORE.
* RYZOM CORE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* RYZOM CORE is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with RYZOM CORE. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include <nel/misc/fast_id_map.h>
// STL includes
// NeL includes
// #include <nel/misc/debug.h>
// Project includes
namespace NLMISC {
void dummytoavoidthecompilerwarningfastidmap() { }
} /* namespace NLMISC */
/* end of file */

View file

@ -108,7 +108,8 @@ enum TFilterMapping
CSoundManager::CSoundManager(IProgressCallback * /* progressCallBack */)
: _AudioMixer(NULL),
_EnvSoundRoot(NULL),
_UserEntitySoundLevel(1.0f)
_UserEntitySoundLevel(1.0f),
_Sources(NULL)
{
_EnableBackgroundMusicAtTime= 0;
_GameMusicVolume= 1.f;
@ -421,7 +422,6 @@ void CSoundManager::reset ()
//---------------------------------------------------
void CSoundManager::init(IProgressCallback *progressCallBack)
{
_NextId = 1;
_EnvSoundRoot = NULL;
_PlaySound = true;
@ -612,7 +612,7 @@ void CSoundManager::init(IProgressCallback *progressCallBack)
// add a new source to the world, attached to the specified entity
// return 0 if creation failed, sound id if creation was successful
//-----------------------------------------------
uint32 CSoundManager::addSource( const NLMISC::TStringId &soundName, const NLMISC::CVector &position, bool play, bool loop, const CEntityId &id)
CSoundManager::TSourceId CSoundManager::addSource( const NLMISC::TStringId &soundName, const NLMISC::CVector &position, bool play, bool loop, const CEntityId &id)
{
uint32 retValue = 0;
@ -642,22 +642,16 @@ uint32 CSoundManager::addSource( const NLMISC::TStringId &soundName, const NLMIS
pSource->play();
}
TSourceId sourceId = _Sources.insert(pSource);
// attach the source to the entity, if specified
if (id != CEntityId::Unknown )
{
_AttachedSources.insert( TMultiMapEntityToSource::value_type( id, pSource ) );
_AttachedSources.insert( TMultiMapEntityToSource::value_type( id, sourceId ) );
}
// set source id
retValue = _NextId;
// add the new source
_Sources.insert( TMapIdToSource::value_type( _NextId, pSource ) );
++_NextId;
// return the id of the source
return retValue;
return sourceId;
} // addSource //
@ -726,24 +720,20 @@ bool CSoundManager::spawnSource(const NLMISC::TStringId &soundName, const NLMISC
// removeSource:
// remove a source
//---------------------------------------------------
void CSoundManager::removeSource( uint32 sourceId )
void CSoundManager::removeSource(CSoundManager::TSourceId sourceId)
{
nldebug("remove the source : %d", sourceId);
/// \todo Malkav : optimize speed
nldebug("nb sources = %d", _Sources.size() );
TMapIdToSource::iterator itS = _Sources.find( sourceId );
if (itS != _Sources.end() )
USource *pSource = _Sources.get(sourceId);
if (pSource)
{
USource *pSource = (*itS).second;
if ( pSource == NULL )
return;
TMultiMapEntityToSource::iterator it = _AttachedSources.begin();//, itOld;
for ( ; it != _AttachedSources.end() ; ++it)
{
if ( (*it).second == pSource )
if ( (*it).second == sourceId )
{
(*it).second = NULL;
// itOld = it;
@ -759,8 +749,9 @@ nldebug("nb sources = %d", _Sources.size() );
}
// delete the source
// _AudioMixer->removeSource (pSource);
delete pSource;
// i think there was something going on here
_Sources.erase(sourceId);
}
} // removeSource //
@ -789,7 +780,7 @@ void CSoundManager::updateEntityPos( const CEntityId &id, const NLMISC::CVector
for ( it = range.first; it != range.second ; ++it)
{
(*it).second->setPos( pos );
_Sources.get((*it).second)->setPos( pos );
}
} // updateEntityPos //
@ -805,7 +796,7 @@ void CSoundManager::updateEntityVelocity( const CEntityId &id, const NLMISC::CVe
for ( it = range.first; it != range.second ; ++it)
{
(*it).second->setVelocity( velocity );
_Sources.get((*it).second)->setVelocity( velocity );
}
} // updateEntityVelocity //
@ -822,7 +813,7 @@ void CSoundManager::updateEntityDirection( const CEntityId &id, const NLMISC::CV
for ( it = range.first; it != range.second ; ++it)
{
(*it).second->setDirection( dir );
_Sources.get((*it).second)->setDirection( dir );
}
} // updateEntityOrientation //
@ -838,25 +829,14 @@ void CSoundManager::removeEntity( const CEntityId &id)
TMultiMapEntityToSource::iterator it;
const std::pair<TMultiMapEntityToSource::iterator, TMultiMapEntityToSource::iterator> range = _AttachedSources.equal_range( id );
USource *pSource;
for ( it = range.first; it != range.second ; ++it)
{
pSource = (*it).second;
if ( pSource != NULL)
TSourceId sourceId = (*it).second;
if (sourceId)
{
TMapIdToSource::iterator itS = _Sources.begin();//, itOld;
for ( ; itS != _Sources.end() ; ++itS)
{
if ( (*itS).second == pSource )
{
(*itS).second = NULL;
_Sources.erase( itS );
break;
}
}
// delete the source
delete (*it).second;
USource *pSource = _Sources.get(sourceId);
delete pSource;
_Sources.erase(sourceId);
}
}
@ -869,34 +849,24 @@ void CSoundManager::removeEntity( const CEntityId &id)
//---------------------------------------------------
// setSoundPosition :
//---------------------------------------------------
void CSoundManager::setSoundPosition( uint32 soundId, const NLMISC::CVector &position)
void CSoundManager::setSoundPosition(TSourceId sourceId, const NLMISC::CVector &position)
{
if (!_PlaySound) return;
TMapIdToSource::iterator it = _Sources.find( soundId );
if (it != _Sources.end() )
{
nlassert( (*it).second );
(*it).second->setPos( position );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) pSource->setPos(position);
} // setSoundPosition //
//---------------------------------------------------
// loopSound :
//---------------------------------------------------
void CSoundManager::loopSound( uint32 soundId, bool loop)
void CSoundManager::loopSound(TSourceId sourceId, bool loop)
{
if (!_PlaySound) return;
TMapIdToSource::iterator it = _Sources.find( soundId );
if (it != _Sources.end() )
{
nlassert( (*it).second );
(*it).second->setLooping( loop );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) pSource->setLooping(loop);
} // loopSound //
@ -904,19 +874,17 @@ void CSoundManager::loopSound( uint32 soundId, bool loop)
// playSound :
// start or stop playing sound
//---------------------------------------------------
void CSoundManager::playSound( uint32 soundId, bool play)
void CSoundManager::playSound(TSourceId sourceId, bool play)
{
if (!_PlaySound) return;
TMapIdToSource::iterator it = _Sources.find( soundId );
if (it != _Sources.end() )
USource *pSource = _Sources.get(sourceId);
if (pSource)
{
nlassert( (*it).second );
if (play)
(*it).second->play();
pSource->play();
else
(*it).second->stop();
pSource->stop();
}
} // loopSound //
@ -926,16 +894,10 @@ void CSoundManager::playSound( uint32 soundId, bool play)
// isPlaying :
// return true if the source is playing
//---------------------------------------------------
bool CSoundManager::isPlaying( uint32 sourceId )
bool CSoundManager::isPlaying(TSourceId sourceId)
{
TMapIdToSource::iterator it = _Sources.find( sourceId );
if (it != _Sources.end() )
{
nlassert( (*it).second );
return ( (*it).second->isPlaying() );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) return pSource->isPlaying();
return false;
} // isPlaying //
@ -999,16 +961,10 @@ bool CSoundManager::setSoundForSource( uint32 sourceId, TSound sound, const CVec
// setSourceGain :
// set the gain of the specified source
//---------------------------------------------------
void CSoundManager::setSourceGain( uint32 sourceId, float gain)
void CSoundManager::setSourceGain(TSourceId sourceId, float gain)
{
TMapIdToSource::const_iterator it = _Sources.find( sourceId );
if (it != _Sources.end() )
{
USource *pSource = (*it).second;
nlassert( pSource );
pSource->setGain( gain );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) pSource->setGain( gain );
} // setSourceGain //
@ -1016,17 +972,10 @@ void CSoundManager::setSourceGain( uint32 sourceId, float gain)
// getSourceGain :
// get the gain of the specified source (-1 if source not found)
//---------------------------------------------------
float CSoundManager::getSourceGain( uint32 sourceId )
float CSoundManager::getSourceGain(TSourceId sourceId)
{
TMapIdToSource::const_iterator it = _Sources.find( sourceId );
if (it != _Sources.end() )
{
USource *pSource = (*it).second;
nlassert( pSource );
return ( pSource->getGain() );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) return pSource->getGain();
return -1;
} // getSourceGain //
@ -1035,16 +984,10 @@ float CSoundManager::getSourceGain( uint32 sourceId )
// setSourcePitch :
// set the Pitch of the specified source
//---------------------------------------------------
void CSoundManager::setSourcePitch( uint32 sourceId, float Pitch)
void CSoundManager::setSourcePitch(TSourceId sourceId, float Pitch)
{
TMapIdToSource::const_iterator it = _Sources.find( sourceId );
if (it != _Sources.end() )
{
USource *pSource = (*it).second;
nlassert( pSource );
pSource->setPitch( Pitch );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) pSource->setPitch(Pitch);
} // setSourcePitch //
@ -1052,17 +995,10 @@ void CSoundManager::setSourcePitch( uint32 sourceId, float Pitch)
// getSourcePitch :
// get the Pitch of the specified source (-1 if source not found)
//---------------------------------------------------
float CSoundManager::getSourcePitch( uint32 sourceId )
float CSoundManager::getSourcePitch(TSourceId sourceId)
{
TMapIdToSource::const_iterator it = _Sources.find( sourceId );
if (it != _Sources.end() )
{
USource *pSource = (*it).second;
nlassert( pSource );
return ( pSource->getPitch() );
}
USource *pSource = _Sources.get(sourceId);
if (pSource) return pSource->getPitch();
return -1;
} // getSourcePitch //
@ -1204,11 +1140,13 @@ void CSoundManager::playPositionedSounds( const CVector& /* pos */ )
list<uint32>::iterator itPSnd;
for( itPSnd = _PositionedSounds.begin(); itPSnd != _PositionedSounds.end(); ++itPSnd )
{
TMapIdToSource::const_iterator itSrc = _Sources.find( *itPSnd );
if( itSrc == _Sources.end() )
USource *pSource = _Sources.get(*itPSnd);
if (!pSource)
{
nlwarning("<CSoundManager::playPositionedSounds> : The source %d is unknown",*itPSnd);
}
else
{
/*
if( (pos - (*itSrc).second.getPos()).norm() < ...)
{
@ -1218,9 +1156,10 @@ void CSoundManager::playPositionedSounds( const CVector& /* pos */ )
}
}
*/
if( (*itSrc).second->isPlaying() == false )
if (!pSource->isPlaying())
{
(*itSrc).second->play();
pSource->play();
}
}
}

View file

@ -26,6 +26,7 @@
#include "nel/misc/types_nl.h"
#include "nel/misc/vector.h"
#include "nel/misc/config_file.h"
#include "nel/misc/fast_id_map.h"
// game_share
#include "nel/misc/entity_id.h"
// sound
@ -45,8 +46,6 @@ namespace NLMISC
class IProgressCallback;
}
/**
* class managing all the sounds for the client
* \author David Fleury
@ -55,9 +54,12 @@ namespace NLMISC
*/
class CSoundManager
{
public:
typedef uint32 TSourceId;
typedef CHashMultiMap<NLMISC::CEntityId , NLSOUND::USource*, NLMISC::CEntityIdHashMapTraits > TMultiMapEntityToSource;
typedef std::map<uint32, NLSOUND::USource*> TMapIdToSource;
private:
typedef CHashMultiMap<NLMISC::CEntityId, TSourceId, NLMISC::CEntityIdHashMapTraits> TMultiMapEntityToSource;
typedef NLMISC::CFastIdMap<TSourceId, NLSOUND::USource *> TMapIdToSource;
/// Load the properties for this sound and aplly them.
void loadProperties(const string &soundName, USource *source);
@ -86,7 +88,7 @@ public:
/// Return the audio mixer instance pointer.
NLSOUND::UAudioMixer *getMixer();
uint32 addSource( const NLMISC::TStringId &soundName, const NLMISC::CVector &position, bool play = true , bool loop = false, const NLMISC::CEntityId &id = NLMISC::CEntityId::Unknown );
TSourceId addSource( const NLMISC::TStringId &soundName, const NLMISC::CVector &position, bool play = true , bool loop = false, const NLMISC::CEntityId &id = NLMISC::CEntityId::Unknown );
/// spawn a new source to the world but sound manager don't keep any link and the sound will be automatically deleted when finnished
bool spawnSource (const NLMISC::TStringId &soundName, NLSOUND::CSoundContext &context);
@ -98,7 +100,7 @@ public:
* remove a source
* \param uint32 source id
*/
void removeSource( uint32 sourceId );
void removeSource( TSourceId sourceId );
/**
@ -190,28 +192,28 @@ public:
* \param uint32 source id
* \param CVector& new position
*/
void setSoundPosition( uint32 sourceId, const NLMISC::CVector &position);
void setSoundPosition( TSourceId sourceId, const NLMISC::CVector &position);
/**
* loop a sound (or stop looping)
* \param uint32 source id
* \param bool loop (true = loop)
*/
void loopSound( uint32 sourceId, bool loop);
void loopSound( TSourceId sourceId, bool loop);
/**
* play or stop a sound
* \param uint32 source id
* \param bool play (true = play, false = stop)
*/
void playSound( uint32 sourceId, bool play);
void playSound( TSourceId sourceId, bool play);
/**
* test whether the sepcified source is playing or not
* \param uint32 source id
* \return bool true if the source is playing
*/
bool isPlaying( uint32 sourceId );
bool isPlaying( TSourceId sourceId );
/**
* select the env effect corresponding to tag
@ -236,14 +238,14 @@ public:
* \param uint32 sourceId
* \param float new gain (0-1)
*/
void setSourceGain( uint32 sourceId, float gain);
void setSourceGain( TSourceId sourceId, float gain);
/**
* get source Gain
* \param uint32 sourceId
* \return float new gain (0-1) (-1 if source not found)
*/
float getSourceGain( uint32 sourceId );
float getSourceGain( TSourceId sourceId );
/**
* set source Pitch
@ -251,14 +253,14 @@ public:
* \param uint32 sourceId
* \param float new Pitch (0-1)
*/
void setSourcePitch( uint32 sourceId, float gain);
void setSourcePitch( TSourceId sourceId, float gain);
/**
* get source Pitch
* \param uint32 sourceId
* \return float new Pitch (0-1) (>0) (-1 if source not found)
*/
float getSourcePitch( uint32 sourceId );
float getSourcePitch( TSourceId sourceId );
/**
* Play all the positioned sounds which are near the given position
@ -346,10 +348,7 @@ private:
//CStepSounds _StepSounds;
/// list of positioned sounds
std::list<uint32> _PositionedSounds;
/// the next value that will be used as id for the next sound to be created
uint32 _NextId;
std::list<TSourceId> _PositionedSounds;
/// Gain value for user entity sound.
float _UserEntitySoundLevel;