diff --git a/code/nel/include/nel/misc/fast_id_map.h b/code/nel/include/nel/misc/fast_id_map.h
new file mode 100644
index 000000000..dbd05bc76
--- /dev/null
+++ b/code/nel/include/nel/misc/fast_id_map.h
@@ -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
+ * .
+ */
+
+#ifndef NLMISC_FAST_ID_MAP_H
+#define NLMISC_FAST_ID_MAP_H
+#include
+
+// STL includes
+
+// NeL includes
+#include
+
+// 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
+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 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 */
diff --git a/code/nel/src/misc/fast_id_map.cpp b/code/nel/src/misc/fast_id_map.cpp
new file mode 100644
index 000000000..f32d6edd8
--- /dev/null
+++ b/code/nel/src/misc/fast_id_map.cpp
@@ -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
+ * .
+ */
+
+#include
+#include
+
+// STL includes
+
+// NeL includes
+// #include
+
+// Project includes
+
+namespace NLMISC {
+
+void dummytoavoidthecompilerwarningfastidmap() { }
+
+} /* namespace NLMISC */
+
+/* end of file */
diff --git a/code/ryzom/client/src/sound_manager.cpp b/code/ryzom/client/src/sound_manager.cpp
index fb4b3708f..b15a5269b 100644
--- a/code/ryzom/client/src/sound_manager.cpp
+++ b/code/ryzom/client/src/sound_manager.cpp
@@ -106,9 +106,10 @@ enum TFilterMapping
// constructor
//-----------------------------------------------
CSoundManager::CSoundManager(IProgressCallback * /* progressCallBack */)
-: _AudioMixer(NULL),
- _EnvSoundRoot(NULL),
- _UserEntitySoundLevel(1.0f)
+: _AudioMixer(NULL),
+ _EnvSoundRoot(NULL),
+ _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 //
@@ -837,26 +828,15 @@ void CSoundManager::removeEntity( const CEntityId &id)
TMultiMapEntityToSource::iterator it;
const std::pair 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,23 +1140,26 @@ void CSoundManager::playPositionedSounds( const CVector& /* pos */ )
list::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(" : The source %d is unknown",*itPSnd);
}
- /*
- if( (pos - (*itSrc).second.getPos()).norm() < ...)
+ else
{
- if( (*itSrc).second.pSource->isPlaying() == false )
+ /*
+ if( (pos - (*itSrc).second.getPos()).norm() < ...)
{
- (*itSrc).second.pSource->play();
+ if( (*itSrc).second.pSource->isPlaying() == false )
+ {
+ (*itSrc).second.pSource->play();
+ }
+ }
+ */
+ if (!pSource->isPlaying())
+ {
+ pSource->play();
}
- }
- */
- if( (*itSrc).second->isPlaying() == false )
- {
- (*itSrc).second->play();
}
}
diff --git a/code/ryzom/client/src/sound_manager.h b/code/ryzom/client/src/sound_manager.h
index 629d9a957..260ab6e81 100644
--- a/code/ryzom/client/src/sound_manager.h
+++ b/code/ryzom/client/src/sound_manager.h
@@ -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 TMultiMapEntityToSource;
- typedef std::map TMapIdToSource;
+private:
+ typedef CHashMultiMap TMultiMapEntityToSource;
+ typedef NLMISC::CFastIdMap 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 _PositionedSounds;
-
- /// the next value that will be used as id for the next sound to be created
- uint32 _NextId;
+ std::list _PositionedSounds;
/// Gain value for user entity sound.
float _UserEntitySoundLevel;