1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2012-2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #include "sound_manager.h"
30 #include "pacs_client.h"
31 #include "light_cycle_manager.h"
32 #include "weather_manager_client.h"
33 #include "user_entity.h"
35 #include "time_client.h"
39 #include "game_share/cst_loader.h"
41 // If you compile using the nel distrib and you don't have the source, you must undef this symbol
43 # define DEBUG_SOUND_IN_GAME
46 #if defined(DEBUG_SOUND_IN_GAME)
48 # include "nel/sound/clustered_sound.h"
49 # include "nel/sound/audio_mixer_user.h"
51 # include "nel/3d/cluster.h"
52 # include "nel/3d/portal.h"
53 # include "nel/3d/dru.h"
54 # include "nel/3d/material.h"
55 # include "nel/3d/driver.h"
56 # include "nel/3d/driver_user.h"
64 extern CLightCycleManager LightCycleManager
;
65 extern NL3D::UDriver
*Driver
;
66 extern NL3D::UCamera MainCam
;
67 extern NLLIGO::CLigoConfig LigoConfig
;
72 using namespace NLMISC
;
73 using namespace NLPACS
;
74 using namespace NLSOUND
;
79 extern NL3D::UScene
*Scene
;
81 // The interpolation distance for the portals : 1 m
82 const float PORTAL_INTERPOLATE
= 1.0f
;
113 //-----------------------------------------------
115 //-----------------------------------------------
116 CSoundManager::CSoundManager(IProgressCallback
* /* progressCallBack */)
118 _GroupControllerEffects(NULL
),
119 _GroupControllerEffectsGame(NULL
),
122 _UserEntitySoundLevel(1.0f
)
124 _EnableBackgroundMusicAtTime
= 0;
125 _GameMusicVolume
= 1.f
;
126 _UserMusicVolume
= 1.f
;
127 _FadeGameMusicVolume
= 1.f
;
129 _UseGameMusicVolume
= true;
130 _EventMusicEnabled
= true;
131 _EventMusicLoop
= false;
132 _FadeGameMusicVolumeDueToEvent
= 1.f
;
133 // init(progressCallBack);
139 //-----------------------------------------------
141 //-----------------------------------------------
142 CSoundManager::~CSoundManager()
146 _AttachedSources
.clear(); // attached sources already deleted (they are also in the _Sources map)
148 // detach the sound from the particule system
149 NL3D::UParticleSystemSound::setPSSound(NULL
);
151 _GroupControllerEffects
= NULL
;
152 _GroupControllerEffectsGame
= NULL
;
154 // free the audio mixer (and delete all sources)
158 // release sound anim properly
161 } // ~CSoundManager //
164 // ***************************************************************************
165 void CSoundManager::releaseSoundAnim()
167 // Parse all Entities to reset their current sound id
168 EntitiesMngr
.resetAllSoundAnimId();
170 // Parse all animation to reset their Id
172 EAM
->resetAllSoundAnimId();
174 // Delete the sound anim Singleton
175 CSoundAnimManager::release();
180 // ***************************************************************************
181 void CSoundManager::drawSounds(float camHeight
)
183 #if defined(DEBUG_SOUND_IN_GAME)
184 // prepare the cameras for cluster display
185 // draw the cluster bounding box on screen
190 CVector
pos(View
.viewPos());
191 pos
+= CVector(0,0,camHeight
);
193 // get the view vector ?
194 CVector
lookAt(View
.view());
200 newCam
.rotateZ(float(Pi
+/*-Pi/2+*/asin(lookAt
.x
)));
202 newCam
.rotateZ(float(Pi
+/*-Pi/2+*/Pi
-asin(lookAt
.x
)));
204 newCam
.rotateX(float(-Pi
/2));
210 Driver
->setMatrixMode3D(MainCam
);
211 Driver
->setViewMatrix(newCam
.inverted());
212 Driver
->clearZBuffer();
216 model
.translate(-pos
);
217 // model.rotateX(mapRX);
218 // model.rotateY(mapRY);
219 model
.translate(pos
);
222 Driver
->setModelMatrix(model
);
224 // UAudioMixer *amu = UAudioMixer::instance();
226 IDriver
*idriver
= static_cast<CDriverUser
*>(Driver
)->getDriver();
227 CClusteredSound
*cs
= static_cast<CAudioMixerUser
*>(_AudioMixer
)->getClusteredSound();
228 // Draw the audible clusters
233 CClusteredSound::TClusterStatusMap::const_iterator
first(cs
->getAudibleClusters().begin()), last(cs
->getAudibleClusters().end());
234 for (; first
!= last
; ++first
)
236 NL3D::CCluster
*cluster
= first
->first
;
238 const CAABBox
&box
= cluster
->getBBox();
239 CVector
center(box
.getCenter());
240 CVector
size(box
.getHalfSize());
242 CVector
a(center
+size
), b(center
-size
);
244 s
[0].set(a
.x
, a
.y
, a
.z
);
245 s
[1].set(a
.x
, b
.y
, a
.z
);
246 s
[2].set(b
.x
, b
.y
, a
.z
);
247 s
[3].set(b
.x
, a
.y
, a
.z
);
248 s
[4].set(a
.x
, a
.y
, b
.z
);
249 s
[5].set(a
.x
, b
.y
, b
.z
);
250 s
[6].set(b
.x
, b
.y
, b
.z
);
251 s
[7].set(b
.x
, a
.y
, b
.z
);
269 mat
.setColor(CRGBA(255,0,0,255));
270 mat
.setZFunc(CMaterial::less
);
271 NL3D::CDRU::drawLinesUnlit(lines
, 12, mat
, *idriver
);
272 mat
.setColor(CRGBA(80,0,0,255));
273 mat
.setZFunc(CMaterial::greater
);
274 NL3D::CDRU::drawLinesUnlit(lines
, 12, mat
, *idriver
);
277 mat2
.setColor(CRGBA(0,0,255,50));
278 mat2
.setZFunc(CMaterial:: always
);
279 mat2
.setSrcBlend(CMaterial::srcalpha
);
280 mat2
.setDstBlend(CMaterial::one
);
282 mat
.setColor(CRGBA(0,0,255,255));
283 mat
.setZFunc(CMaterial::always
);
286 for (uint k
= 0; k
<cluster
->getNbPortals(); ++k
)
288 CPortal
*portal
= cluster
->getPortal(k
);
289 std::vector
<NLMISC::CVector
> poly
;
290 portal
->getPoly(poly
);
294 for (uint i
=1; i
<poly
.size()-1; ++i
)
300 NL3D::CDRU::drawTrianglesUnlit(&tri
, 1, mat2
, *idriver
);
304 NL3D::CDRU::drawTrianglesUnlit(&tri
, 1, mat2
, *idriver
);
309 for (uint i
=0; i
<poly
.size(); ++i
)
311 CLine
line(poly
[i
], poly
[(i
+1)%poly
.size()]);
313 NL3D::CDRU::drawLinesUnlit(&line
, 1, mat
, *idriver
);
318 } // draw audible clusters
321 mat
.setColor(CRGBA(255,255,255,255));
323 /* float d = float(Pi/10);
324 for (float j=0; j<float(Pi*2); j+=d)
325 NL3D::CDRU::drawLine(pos+CVector(LISTEN_DISTANCE*float(sin(j)), LISTEN_DISTANCE*float(cos(j)), 0), pos+CVector(LISTEN_DISTANCE*float(sin(j+d)), LISTEN_DISTANCE*float(cos(j+d)),0), CRGBA(255,255,255,255), *idriver);
327 for (j=0; j<float(Pi*2); j+=d)
328 NL3D::CDRU::drawLine(pos+CVector(PORTAL_INTERPOLATE*float(sin(j)), PORTAL_INTERPOLATE*float(cos(j)), 0), pos+CVector(PORTAL_INTERPOLATE*float(sin(j+d)), PORTAL_INTERPOLATE*float(cos(j+d)),0), CRGBA(255,255,255,255), *idriver);
330 mat
.setColor(CRGBA(0,255,0,255));
331 mat
.setZFunc(CMaterial::always
);
332 /* for (uint k=0; k<debugLines.size(); ++k)
334 // CDRU::drawLinesUnlit(debugLines, mat, *idriver);
335 NL3D::CDRU::drawLine(debugLines[k].V0, debugLines[k].V1, CRGBA(0,255,0,255), *idriver);
337 */ // Draw listener pos
338 mat
.setColor(CRGBA(0,255,0,255));
340 NL3D::CDRU::drawLine(pos
+CVector(2,2,0), pos
+CVector(-2,-2,0), CRGBA(255,255,0,255), *idriver
);
341 NL3D::CDRU::drawLine(pos
+CVector(-2,2,0), pos
+CVector(2,-2,0), CRGBA(255,255,0,255), *idriver
);
343 // CVector front = Camera->getMatrix().getI();
344 // NL3D::CDRU::drawLine(pos, pos+front*4, CRGBA(255,255,0,255), *idriver);
346 // draw the virtual sound sound
348 CClusteredSound::TClusterStatusMap::const_iterator
first(cs
->getAudibleClusters().begin()), last(cs
->getAudibleClusters().end());
349 for (; first
!= last
; ++first
)
351 const CClusteredSound::CClusterSoundStatus
&css
= first
->second
;
352 if (css
.Direction
!= CVector::Null
)
354 CVector dest
= pos
+css
.Direction
*css
.Dist
;
356 NL3D::CDRU::drawLine(pos
, dest
, CRGBA(0,255,255,255), *idriver
);
357 NL3D::CDRU::drawLine(dest
+CVector(0.5f
,0.5f
,0), dest
+CVector(-0.5f
,-0.5f
,0), CRGBA(0, 255,255,255), *idriver
);
358 NL3D::CDRU::drawLine(dest
+CVector(-0.5f
,0.5f
,0), dest
+CVector(0.5f
,-0.5f
,0), CRGBA(0, 255,255,255), *idriver
);
362 // draw the audio path
364 idriver
->setupMaterial(mat
);
365 const std::vector
<std::pair
<NLMISC::CVector
, NLMISC::CVector
> > &lines
= cs
->getAudioPath();
366 std::vector
<std::pair
<NLMISC::CVector
, NLMISC::CVector
> >::const_iterator
first(lines
.begin()), last(lines
.end());
367 for (; first
!= last
; ++first
)
369 NL3D::CDRU::drawLine(first
->first
, first
->second
, CRGBA(0,255,0,255), *idriver
);
372 // draw the sound source position
374 std::vector
<std::pair
<bool, CVector
> > soundPos
;
375 _AudioMixer
->getPlayingSoundsPos(true, soundPos
);
377 std::vector
<std::pair
<bool, CVector
> >::iterator
first(soundPos
.begin()), last(soundPos
.end());
378 for (; first
!= last
; ++first
)
380 NL3D::CDRU::drawLine(first
->second
+ CVector(0.5f
,0.5f
,0), first
->second
+ CVector(-0.5f
,-0.5f
,0), CRGBA(255,0,255,255), *idriver
);
381 NL3D::CDRU::drawLine(first
->second
+ CVector(0.5f
,-0.5f
,0), first
->second
+ CVector(-0.5f
,0.5f
,0), CRGBA(255,0,255,255), *idriver
);
385 #endif // DEBUG_SOUND_IN_GAME
390 UAudioMixer
*CSoundManager::getMixer()
396 void CSoundManager::switchSoundState ()
398 _PlaySound
= !_PlaySound
;
399 _AudioMixer
->enable(_PlaySound
);
402 void CSoundManager::loadContinent(const string
&name
, const NLMISC::CVector
& pos
)
407 // load already stop all sound and unload them before loading new one
408 _AudioMixer
->loadBackgroundSound (name
, LigoConfig
);
409 _AudioMixer
->setListenerPos(pos
);
413 void CSoundManager::reset ()
418 NL3D::UParticleSystemSound::setPSSound(NULL
);
420 _GroupControllerEffects
= NULL
;
421 _GroupControllerEffectsGame
= NULL
;
426 // release sound anim properly
431 // _AudioMixer->reset ();
435 //---------------------------------------------------
437 // Initialize the audio mixer, load the sound banks
438 //---------------------------------------------------
439 void CSoundManager::init(IProgressCallback
*progressCallBack
)
441 _EnvSoundRoot
= NULL
;
444 _UserEntitySoundLevel
= ClientCfg
.UserEntitySoundLevel
;
446 const std::string
&packedSheetPath
= ClientCfg
.SoundPackedSheetPath
;
447 const std::string
&samplePath
= ClientCfg
.SampleBankDir
;
450 // reset particle sound
451 NL3D::UParticleSystemSound::setPSSound(NULL
);
453 * Create the audio mixer object and init it.
454 * If the sound driver cannot be loaded, an exception is thrown.
456 _AudioMixer
= UAudioMixer::createAudioMixer();
461 // Set the path to the sample directory
462 _AudioMixer
->setSamplePath(samplePath
);
463 // Set the path to the packed sheets
465 if (ClientCfg
.UpdatePackedSheet
)
466 _AudioMixer
->setPackedSheetOption(packedSheetPath
, true);
468 _AudioMixer
->setPackedSheetOption("", false);
470 UAudioMixer::TDriver driverType
= UAudioMixer::DriverAuto
;
471 if(ClientCfg
.DriverSound
==CClientConfig::SoundDrvOpenAL
)
472 driverType
= UAudioMixer::DriverOpenAl
;
473 else if(ClientCfg
.DriverSound
==CClientConfig::SoundDrvDirectSound
)
474 driverType
= UAudioMixer::DriverDSound
;
475 else if(ClientCfg
.DriverSound
==CClientConfig::SoundDrvXAudio2
)
476 driverType
= UAudioMixer::DriverXAudio2
;
477 _AudioMixer
->init(ClientCfg
.MaxTrack
, ClientCfg
.UseEax
, ClientCfg
.UseADPCM
, progressCallBack
, false, driverType
, ClientCfg
.SoundForceSoftwareBuffer
);
478 /* int nbVoice = _AudioMixer->getPolyphony();
479 _AudioMixer->setPriorityReserve(HighPri, max(1, nbVoice /2));
480 nbVoice -= nbVoice /2;
481 _AudioMixer->setPriorityReserve(MidPri, max(1, nbVoice /2));
482 nbVoice -= nbVoice /2;
483 _AudioMixer->setPriorityReserve(LowPri, max(1, nbVoice /2));
485 // when they are only 1 track available, enter in limiting mode.
486 _AudioMixer
->setLowWaterMark(1);
489 * Create the CSoundAnimManager. The CSoundAnimManager is a singleton.
490 * Access the singleton with CSoundAnimManager::instance().
492 new CSoundAnimManager(_AudioMixer
);
494 // get the controller group for effects
495 _GroupControllerEffects
= _AudioMixer
->getGroupController("sound:effects");
496 _GroupControllerEffectsGame
= _AudioMixer
->getGroupController("sound:effects:game");
498 // restore the volume
499 SoundMngr
->setSFXVolume(ClientCfg
.SoundSFXVolume
);
500 SoundMngr
->setGameMusicVolume(ClientCfg
.SoundGameMusicVolume
);
502 // Init clustered sound system
503 _AudioMixer
->initClusteredSound(Scene
, 0.01f
, 100.0f
, PORTAL_INTERPOLATE
);
505 // Init the background flags;
506 for (uint i
=0; i
<NLSOUND::UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS
; ++i
)
507 _BackgroundFlags
.Flags
[i
] = false;
508 _AudioMixer
->setBackgroundFlags(_BackgroundFlags
);
511 * Initialize listener's position
513 CVector
initpos ( 0.0f
, 0.0f
, 0.0f
);
514 //_AudioMixer->getListener()->setPos( initpos );
515 _AudioMixer
->setListenerPos(initpos
);
518 * Init the particule sound system
520 // attach the sound from the particule system
521 NL3D::UParticleSystemSound::setPSSound(_AudioMixer
);
523 //loadPositionedSounds();
525 // reload Sound Animation (if EAM already init)
527 EAM
->reloadAllSoundAnim();
529 // Special option for DEV (easier to test when disabled)
530 _AudioMixer
->enableBackgroundMusicTimeConstraint(ClientCfg
.EnableBackgroundMusicTimeConstraint
);
533 catch(const Exception &e)
535 nlwarning( "Error: %s", e.what() );
540 //---------------------------------------------------
542 //---------------------------------------------------
543 /*bool CSoundManager::getSoundName( TSound sound, std::string &name, const CVector& pos ) const
545 /// \todo Malkav: take ground type into account, and all the different sounds
551 UGlobalPosition globalPos = GR->retrievePosition( pos );
552 uint32 material = GR->getMaterial( globalPos );
580 //---------------------------------------------------
582 // add a new source to the world, attached to the specified entity
583 // return 0 if creation failed, sound id if creation was successful
584 //---------------------------------------------------
585 /*uint32 CSoundManager::addSource( TSound sound, const NLMISC::CVector &position, bool play, bool loop, const CEntityId &parentId )
587 static std::string name;
588 static TSource source;
592 if ( ! getSoundName ( sound, name, position ) )
595 USource *pSource = _AudioMixer->createSource( name );
597 if ( pSource != NULL )
599 pSource ->setPos( position );
601 pSource ->setLooping( loop );
606 //create the TSource object
607 source.sound = sound;
608 source.pSource = pSource;
610 // attach the source to the entity, if specified
611 if (parentId != CEntityId::Unknown)
612 _AttachedSources.insert( TMultiMapEntityToSource::value_type( parentId, source ) );
616 _Sources.insert( TMapIdToSource::value_type( _NextId, source ) );
621 nlwarning( "Sound '%s' not found", name );
628 //-----------------------------------------------
630 // add a new source to the world, attached to the specified entity
631 // return 0 if creation failed, sound id if creation was successful
632 //-----------------------------------------------
633 CSoundManager::TSourceId
CSoundManager::addSource(const NLMISC::TStringId
&soundName
, const NLMISC::CVector
&position
, bool play
, bool loop
, const CEntityId
&id
)
638 USource
*pSource
= _AudioMixer
->createSource(soundName
);
640 // If the source is valid.
643 nlwarning("Sound '%s' not found !", CStringMapper::unmap(soundName
).c_str());
647 // Load the properties for this sound.
648 // REMOVED because the pitch and the gain are now in the .nss (don't need .sdf anymore)
649 // loadProperties(soundName, pSource);
651 // Set the source position.
652 pSource
->setPos( position
);
654 // Is the source looping ?
655 pSource
->setLooping( loop
);
657 // Play the sound immedialty if asked.
663 TSourceId sourceId
= _Sources
.insert(pSource
);
665 // attach the source to the entity, if specified
666 if (id
!= CEntityId::Unknown
)
668 _AttachedSources
.insert( TMultiMapEntityToSource::value_type( id
, sourceId
) );
671 // return the id of the source
677 //-----------------------------------------------
678 // spawn a new source to the world
679 // return false if creation failed, true if creation was successful
680 //-----------------------------------------------
681 bool CSoundManager::spawnSource(const NLMISC::TStringId
&soundName
, CSoundContext
&context
)
683 if (!_PlaySound
) return false;
686 // TODO : find the correct cluster
687 USource
*pSource
= _AudioMixer
->createSource( soundName
, true, NULL
, NULL
, NULL
, &context
);
689 // If the source is valid.
692 nlwarning("Sound '%s' not found !", soundName
);
696 // Set the source position.
697 pSource
->setPos (context
.Position
);
700 ////nlinfo ("%.3f spawn source %p", (float)ryzomGetLocalTime ()/1000.0f, pSource);
707 //-----------------------------------------------
708 // spawn a new source to the world
709 // return false if creation failed, true if creation was successful
710 //-----------------------------------------------
711 bool CSoundManager::spawnSource(const NLMISC::TStringId
&soundName
, const NLMISC::CVector
&position
)
713 if (!_PlaySound
) return false;
716 USource
*pSource
= _AudioMixer
->createSource( soundName
, true);
718 // If the source is valid.
721 nlwarning("Sound '%s' not found !", CStringMapper::unmap(soundName
).c_str ());
725 // Set the source position.
726 pSource
->setPos (position
);
729 ////nlinfo ("%.3f spawn source %p", (float)ryzomGetLocalTime ()/1000.0f, pSource);
737 //---------------------------------------------------
740 //---------------------------------------------------
741 void CSoundManager::removeSource(CSoundManager::TSourceId sourceId
)
743 nldebug("remove the source : %d", sourceId
);
745 /// \todo Malkav : optimize speed
746 nldebug("nb sources = %d", _Sources
.size() );
747 USource
*pSource
= _Sources
.get(sourceId
);
750 TMultiMapEntityToSource::iterator it
= _AttachedSources
.begin();//, itOld;
752 for ( ; it
!= _AttachedSources
.end() ; ++it
)
754 if ( (*it
).second
== sourceId
)
760 _AttachedSources
.erase( it
/*Old*/ );
764 // if (it == _AttachedSources.end() )
771 // i think there was something going on here
772 _Sources
.erase(sourceId
);
778 //---------------------------------------------------
781 //---------------------------------------------------
782 /*bool CSoundManager::getSounds( uint32 material, TMoveType moveType, bool soft, std::vector<string>& sounds )
784 return _StepSounds.getSounds( material, moveType, soft, sounds );
790 //---------------------------------------------------
792 // update the pos of all the sounds attached to that entity
793 //---------------------------------------------------
794 void CSoundManager::updateEntityPos( const CEntityId
&id
, const NLMISC::CVector
&pos
)
796 TMultiMapEntityToSource::iterator it
;
797 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
799 for ( it
= range
.first
; it
!= range
.second
; ++it
)
801 _Sources
.get((*it
).second
)->setPos( pos
);
803 } // updateEntityPos //
806 //---------------------------------------------------
807 // updateEntityVelocity :
808 // update the velocity of all the sounds attached to that entity
809 //---------------------------------------------------
810 void CSoundManager::updateEntityVelocity( const CEntityId
&id
, const NLMISC::CVector
&velocity
)
812 TMultiMapEntityToSource::iterator it
;
813 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
815 for ( it
= range
.first
; it
!= range
.second
; ++it
)
817 _Sources
.get((*it
).second
)->setVelocity( velocity
);
820 } // updateEntityVelocity //
823 //---------------------------------------------------
824 // updateEntityDirection :
825 // update the direction of all the sounds attached to that entity
826 //---------------------------------------------------
827 void CSoundManager::updateEntityDirection( const CEntityId
&id
, const NLMISC::CVector
&dir
)
829 TMultiMapEntityToSource::iterator it
;
830 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
832 for ( it
= range
.first
; it
!= range
.second
; ++it
)
834 _Sources
.get((*it
).second
)->setDirection( dir
);
836 } // updateEntityOrientation //
839 //---------------------------------------------------
841 // remove an entity from the view : delete all the sources attached to that entity
842 //---------------------------------------------------
843 void CSoundManager::removeEntity( const CEntityId
&id
)
845 /// \todo Malkav : optimize speed
847 TMultiMapEntityToSource::iterator it
;
848 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
850 for ( it
= range
.first
; it
!= range
.second
; ++it
)
852 TSourceId sourceId
= (*it
).second
;
855 USource
*pSource
= _Sources
.get(sourceId
);
857 _Sources
.erase(sourceId
);
861 _AttachedSources
.erase( range
.first
, range
.second
);
867 //---------------------------------------------------
868 // setSoundPosition :
869 //---------------------------------------------------
870 void CSoundManager::setSoundPosition(TSourceId sourceId
, const NLMISC::CVector
&position
)
872 if (!_PlaySound
) return;
874 USource
*pSource
= _Sources
.get(sourceId
);
875 if (pSource
) pSource
->setPos(position
);
876 } // setSoundPosition //
879 //---------------------------------------------------
881 //---------------------------------------------------
882 void CSoundManager::loopSound(TSourceId sourceId
, bool loop
)
884 if (!_PlaySound
) return;
886 USource
*pSource
= _Sources
.get(sourceId
);
887 if (pSource
) pSource
->setLooping(loop
);
891 //---------------------------------------------------
893 // start or stop playing sound
894 //---------------------------------------------------
895 void CSoundManager::playSound(TSourceId sourceId
, bool play
)
897 if (!_PlaySound
) return;
899 USource
*pSource
= _Sources
.get(sourceId
);
911 //---------------------------------------------------
913 // return true if the source is playing
914 //---------------------------------------------------
915 bool CSoundManager::isPlaying(TSourceId sourceId
)
917 USource
*pSource
= _Sources
.get(sourceId
);
918 if (pSource
) return pSource
->isPlaying();
924 //---------------------------------------------------
925 // setSoundForSource :
926 // set the sound associated to the specified source
927 //---------------------------------------------------
929 bool CSoundManager::setSoundForSource( uint32 sourceId, TSound sound, const CVector& pos )
931 // find the sound name
932 static std::string soundName;
934 if ( ! getSoundName( sound , soundName, pos) )
937 TMapIdToSource::iterator it = _Sources.find( sourceId );
938 if (it != _Sources.end() )
940 nlassert( (*it).second.pSource );
943 TSoundId soundId = _AudioMixer->getSoundId( soundName.c_str() );
947 (*it).second.pSource->setSound( soundId );
948 (*it).second.sound = sound;
949 nlinfo("sound has been set to %d",sound);
954 } // setSoundForSource //
959 //---------------------------------------------------
960 // getSoundFromSource :
961 // get the sound type currently associated to a source
962 //---------------------------------------------------
963 /*CSoundManager::TSound CSoundManager::getSoundFromSource( uint32 sourceId ) const
965 TMapIdToSource::const_iterator it = _Sources.find( sourceId );
966 if (it != _Sources.end() )
968 nlassert( (*it).second.pSource );
970 return ( (*it).second.sound );
974 } // getSoundFromSource //
978 //---------------------------------------------------
980 // set the gain of the specified source
981 //---------------------------------------------------
982 void CSoundManager::setSourceGain(TSourceId sourceId
, float gain
)
984 USource
*pSource
= _Sources
.get(sourceId
);
985 if (pSource
) pSource
->setGain( gain
);
986 } // setSourceGain //
989 //---------------------------------------------------
991 // get the gain of the specified source (-1 if source not found)
992 //---------------------------------------------------
993 float CSoundManager::getSourceGain(TSourceId sourceId
)
995 USource
*pSource
= _Sources
.get(sourceId
);
996 if (pSource
) return pSource
->getGain();
998 } // getSourceGain //
1001 //---------------------------------------------------
1003 // set the Pitch of the specified source
1004 //---------------------------------------------------
1005 void CSoundManager::setSourcePitch(TSourceId sourceId
, float Pitch
)
1007 USource
*pSource
= _Sources
.get(sourceId
);
1008 if (pSource
) pSource
->setPitch(Pitch
);
1009 } // setSourcePitch //
1012 //---------------------------------------------------
1014 // get the Pitch of the specified source (-1 if source not found)
1015 //---------------------------------------------------
1016 float CSoundManager::getSourcePitch(TSourceId sourceId
)
1018 USource
*pSource
= _Sources
.get(sourceId
);
1019 if (pSource
) return pSource
->getPitch();
1021 } // getSourcePitch //
1025 //---------------------------------------------------
1027 // Load the properties for this sound and apply them.
1028 //---------------------------------------------------
1029 void CSoundManager::loadProperties(const string
&soundName
, USource
*source
)
1031 // If the source does not exist -> return nothing to do.
1035 // Search for the file.
1036 string filePath
= CPath::lookup(soundName
+".sdf");
1040 // Try to open the file.
1041 if (file
.open(filePath
))
1044 char delimiterBox
[] = "\t ";
1045 // While the end of the file is not reached.
1048 // Get a line (the line should not be more than _MAX_LINE_SIZE).
1049 file
.getline(tmpBuff
, 260);
1050 char *token
= strtok(tmpBuff
, delimiterBox
);
1051 while(token
!= NULL
)
1054 if(strcmp(token
, "Pitch:") == 0)
1056 token
= strtok(NULL
, delimiterBox
);
1060 fromString(token
, pitch
);
1061 nlinfo("Pitch: %f", pitch
);
1062 source
->setPitch(pitch
);
1066 else if(strcmp(token
, "Gain:") == 0)
1068 token
= strtok(NULL
, delimiterBox
);
1072 fromString(token
, gain
);
1073 nlinfo("Gain: %f", gain
);
1074 source
->setGain(gain
);
1079 token
= strtok(NULL
, delimiterBox
);
1085 }// loadProperties //
1090 //---------------------------------------------------
1091 // loadPositionedSounds :
1093 //---------------------------------------------------
1094 /*void CSoundManager::loadPositionedSounds()
1096 nlstopex(("class CStepSounds is not used anymore"));
1100 // build file format
1101 map<string,CSTLoader::TDataType> fileFormat;
1102 fileFormat.insert( make_pair( string( "sound name" ) , CSTLoader::STRING ));
1103 fileFormat.insert( make_pair( string( "x" ) , CSTLoader::FLOAT ));
1104 fileFormat.insert( make_pair( string( "y" ) , CSTLoader::FLOAT ));
1105 fileFormat.insert( make_pair( string( "z" ) , CSTLoader::FLOAT ));
1106 fileFormat.insert( make_pair( string( "loop" ) , CSTLoader::BOOL ));
1109 string str = CPath::lookup("positioned_sounds.txt", false);
1112 nlwarning ("cant load positioned_sounds");
1117 cstl.init( str, fileFormat );
1120 while( cstl.readLine() )
1123 cstl.getStringValue( "sound name", soundName );
1126 cstl.getValue( "x", sourcePos.x );
1127 cstl.getValue( "y", sourcePos.y );
1128 cstl.getValue( "z", sourcePos.z );
1131 cstl.getBoolValue( "loop", loop );
1133 uint32 sourceId = addSource( soundName, sourcePos, false , loop );
1137 _PositionedSounds.push_back( sourceId );
1141 nlwarning ("positioned sound: can't find sound: '%s'", soundName.c_str());
1147 } // chooseSoundOnMaterial //
1151 //---------------------------------------------------
1152 // playPositionedSounds :
1154 //---------------------------------------------------
1155 void CSoundManager::playPositionedSounds( const CVector
& /* pos */ )
1157 if (!_PlaySound
) return;
1159 list
<uint32
>::iterator itPSnd
;
1160 for( itPSnd
= _PositionedSounds
.begin(); itPSnd
!= _PositionedSounds
.end(); ++itPSnd
)
1162 USource
*pSource
= _Sources
.get(*itPSnd
);
1165 nlwarning("<CSoundManager::playPositionedSounds> : The source %d is unknown",*itPSnd
);
1170 if( (pos - (*itSrc).second.getPos()).norm() < ...)
1172 if( (*itSrc).second.pSource->isPlaying() == false )
1174 (*itSrc).second.pSource->play();
1178 if (!pSource
->isPlaying())
1185 } // playPositionedSounds //
1188 void CSoundManager::selectEnv( const std::string
&/* tag */)
1190 // TODO : boris : temporarily removed.
1191 /* if (_EnvSoundRoot==NULL)
1194 _EnvSoundRoot->selectEnv (tag.c_str(), true);
1198 void CSoundManager::setFilterState(uint filterId
, bool state
)
1200 nlassert(filterId
< NLSOUND::UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS
);
1201 _BackgroundFlags
.Flags
[filterId
] = state
;
1203 _AudioMixer
->setBackgroundFlags(_BackgroundFlags
);
1208 // ***************************************************************************
1209 void CSoundManager::update ()
1211 // Filters : day = 0, night = 1, morning = 2, Dusk = 3
1212 // update the filter state for day/night management.
1213 switch(LightCycleManager
.getState())
1215 case CLightCycleManager::Day
:
1216 _BackgroundFlags
.Flags
[DAY
] = true;
1217 _BackgroundFlags
.Flags
[NIGHT
] = false;
1218 _BackgroundFlags
.Flags
[MORNING
] = false;
1219 _BackgroundFlags
.Flags
[DUSK
] = false;
1221 case CLightCycleManager::Night
:
1222 _BackgroundFlags
.Flags
[DAY
] = false;
1223 _BackgroundFlags
.Flags
[NIGHT
] = true;
1224 _BackgroundFlags
.Flags
[MORNING
] = false;
1225 _BackgroundFlags
.Flags
[DUSK
] = false;
1227 case CLightCycleManager::DayToNight
:
1228 _BackgroundFlags
.Flags
[DAY
] = true;
1229 _BackgroundFlags
.Flags
[NIGHT
] = false;
1230 _BackgroundFlags
.Flags
[MORNING
] = true;
1231 _BackgroundFlags
.Flags
[DUSK
] = false;
1233 case CLightCycleManager::NightToDay
:
1234 _BackgroundFlags
.Flags
[DAY
] = false;
1235 _BackgroundFlags
.Flags
[NIGHT
] = false;
1236 _BackgroundFlags
.Flags
[MORNING
] = false;
1237 _BackgroundFlags
.Flags
[DUSK
] = true;
1239 case CLightCycleManager::StateUnknown
:
1240 //nlwarning("Unknown light cycle state reached.");
1244 // update the filter for season.
1245 EGSPD::CSeason::TSeason season
= CurrSeason
;
1248 case EGSPD::CSeason::Spring
:
1249 _BackgroundFlags
.Flags
[SPRING
] = true;
1250 _BackgroundFlags
.Flags
[SUMMER
] = false;
1251 _BackgroundFlags
.Flags
[AUTUMN
] = false;
1252 _BackgroundFlags
.Flags
[WINTER
] = false;
1254 case EGSPD::CSeason::Summer
:
1255 _BackgroundFlags
.Flags
[SPRING
] = false;
1256 _BackgroundFlags
.Flags
[SUMMER
] = true;
1257 _BackgroundFlags
.Flags
[AUTUMN
] = false;
1258 _BackgroundFlags
.Flags
[WINTER
] = false;
1260 case EGSPD::CSeason::Autumn
:
1261 _BackgroundFlags
.Flags
[SPRING
] = false;
1262 _BackgroundFlags
.Flags
[SUMMER
] = false;
1263 _BackgroundFlags
.Flags
[AUTUMN
] = true;
1264 _BackgroundFlags
.Flags
[WINTER
] = false;
1266 case EGSPD::CSeason::Winter
:
1267 _BackgroundFlags
.Flags
[SPRING
] = false;
1268 _BackgroundFlags
.Flags
[SUMMER
] = false;
1269 _BackgroundFlags
.Flags
[AUTUMN
] = false;
1270 _BackgroundFlags
.Flags
[WINTER
] = true;
1273 //nlwarning("Updating unknown season.");
1276 // TODO : update the filter state for weather effet
1277 CWeatherState weatherState
= WeatherManager
.getCurrWeatherState();
1281 enum TWeatherSoundEnv
1283 WSEMist
= 0, // not used
1293 WSEThunderSand1
, // not used
1294 WSEThunderSand2
, // not used
1295 WSEThunderSand3
, // not used
1299 // For each weather setup, gives the matching weather sound env to used, when there are precipitation or not
1300 class CWeatherSetupSoundEnv
1303 NLMISC::TStringId SetupName
; // setup nem as found is the .weather_setup sheets
1304 TWeatherSoundEnv Sound
;
1305 CWeatherSetupSoundEnv(const char *setupName
, TWeatherSoundEnv sound
)
1307 SetupName
= NLMISC::CStringMapper::map(setupName
);
1312 // association between weather setup names & sound env
1313 static const CWeatherSetupSoundEnv weatherSoundLUT
[] =
1315 CWeatherSetupSoundEnv("fair1", WSEFair1
),
1316 CWeatherSetupSoundEnv("fair2", WSEFair2
),
1317 CWeatherSetupSoundEnv("fair3", WSEFair3
),
1318 CWeatherSetupSoundEnv("wind1", WSEClouds
),
1319 CWeatherSetupSoundEnv("humidity1", WSERain1
),
1320 CWeatherSetupSoundEnv("humidity2", WSERain2
),
1321 CWeatherSetupSoundEnv("clouds1", WSERain1
),
1322 CWeatherSetupSoundEnv("clouds2", WSERain2
),
1323 CWeatherSetupSoundEnv("thunderseve", WSEThunderSeve
),
1324 CWeatherSetupSoundEnv("storm", WSEThunder1
),
1325 CWeatherSetupSoundEnv("snow", WSESnow1
),
1328 const CWeatherSetupSoundEnv
*weatherSetupSoundEnv
= NULL
;
1329 for(uint k
= 0; k
< sizeof(weatherSoundLUT
) / sizeof(weatherSoundLUT
[0]); ++k
)
1331 if (weatherSoundLUT
[k
].SetupName
== weatherState
.BestSetupName
)
1333 weatherSetupSoundEnv
= &weatherSoundLUT
[k
];
1338 // disable all weather setup sound flags except the current one
1339 for(uint k
= 0; k
< WSECount
; ++k
)
1341 _BackgroundFlags
.Flags
[MIST
+k
] = false;
1343 if (weatherSetupSoundEnv
)
1345 _BackgroundFlags
.Flags
[MIST
+ weatherSetupSoundEnv
->Sound
] = true;
1349 static bool bDisplayOnce
= false;
1352 nlinfo("The current weather setup '%s' is unknown !", CStringMapper::unmap(weatherState
.BestSetupName
).c_str());
1353 bDisplayOnce
= true;
1357 // update the background flags in the mixer.
1358 _AudioMixer
->setBackgroundFlags(_BackgroundFlags
);
1360 // update background music enabling
1361 if(_EnableBackgroundMusicAtTime
&& CTime::getLocalTime()>_EnableBackgroundMusicAtTime
)
1363 setGameMusicMode(true, true);
1366 // Special option for DEV (easier to test when disabled)
1367 _AudioMixer
->enableBackgroundMusicTimeConstraint(ClientCfg
.EnableBackgroundMusicTimeConstraint
);
1369 // update game music volume because of event played or not
1370 updateEventAndGameMusicVolume();
1372 // update audio mixer
1373 _AudioMixer
->update ();
1376 // ***************************************************************************
1377 void CSoundManager::updateAudioMixerOnly()
1381 _AudioMixer
->update ();
1384 // ***************************************************************************
1385 void CSoundManager::playBackgroundSound()
1387 _AudioMixer
->playBackgroundSound();
1390 // ***************************************************************************
1391 void CSoundManager::stopBackgroundSound()
1393 _AudioMixer
->stopBackgroundSound();
1396 // ***************************************************************************
1397 void CSoundManager::playMusic(const string
&fileName
, uint xFadeTime
, bool async
, bool loop
, bool forceGameMusicVolume
)
1399 if(fileName
.empty())
1401 stopMusic(xFadeTime
);
1407 // disable before the background music (before is important else may have bug)
1408 setGameMusicMode(false, forceGameMusicVolume
);
1410 _AudioMixer
->playMusic(fileName
, xFadeTime
, async
, loop
);
1415 // ***************************************************************************
1416 void CSoundManager::stopMusic(uint xFadeTime
)
1421 _AudioMixer
->stopMusic(xFadeTime
);
1422 // and reenable the background music system. after a delay if xFadeTime
1425 // enable background music later
1426 _EnableBackgroundMusicAtTime
= CTime::getLocalTime()+xFadeTime
;
1431 setGameMusicMode(true, true);
1436 // ***************************************************************************
1437 void CSoundManager::playEventMusic(const string
&fileName
, uint xFadeTime
, bool loop
)
1439 // if event music not enabled (mp3 player), abort
1440 if(!_EventMusicEnabled
)
1443 if(fileName
.empty())
1445 stopEventMusic("", xFadeTime
);
1451 // if the music is not already currently playing (with same loop state)
1452 if(_EventMusicPlayed
.empty() || nlstricmp(fileName
, _EventMusicPlayed
)!=0 || loop
!=_EventMusicLoop
)
1455 _AudioMixer
->playEventMusic(fileName
, xFadeTime
, true, loop
);
1456 _EventMusicPlayed
= fileName
;
1457 _EventMusicLoop
= loop
;
1463 // ***************************************************************************
1464 void CSoundManager::stopEventMusic(const string
&fileName
, uint xFadeTime
)
1468 // if the event music is the one currently played, or if empty fileName
1469 if(fileName
.empty() || nlstricmp(_EventMusicPlayed
,fileName
)==0)
1472 _AudioMixer
->stopEventMusic(xFadeTime
);
1473 // music no more played
1474 _EventMusicPlayed
.clear();
1479 // ***************************************************************************
1480 void CSoundManager::pauseMusic()
1483 _AudioMixer
->pauseMusic();
1486 // ***************************************************************************
1487 void CSoundManager::resumeMusic()
1490 _AudioMixer
->resumeMusic();
1493 // ***************************************************************************
1494 bool CSoundManager::isMusicEnded()
1497 return _AudioMixer
->isMusicEnded();
1501 // ***************************************************************************
1502 void CSoundManager::setGameMusicVolume(float val
)
1505 _GameMusicVolume
= val
;
1509 // ***************************************************************************
1510 void CSoundManager::setUserMusicVolume(float val
)
1513 _UserMusicVolume
= val
;
1517 // ***************************************************************************
1518 void CSoundManager::setSFXVolume(float val
)
1525 // ***************************************************************************
1526 void CSoundManager::setGameMusicMode(bool enableBackground
, bool useGameMusicVolume
)
1528 // update background music state
1529 _EnableBackgroundMusicAtTime
= 0;
1530 _AudioMixer
->enableBackgroundMusic(enableBackground
);
1531 _UseGameMusicVolume
= useGameMusicVolume
;
1532 // event music enabled if the background music is also enabled
1533 _EventMusicEnabled
= enableBackground
;
1534 // stop any event music if disabled
1535 if(!_EventMusicEnabled
)
1536 stopEventMusic("", 500);
1537 // update music volume state
1541 // ***************************************************************************
1542 void CSoundManager::updateVolume()
1546 // update music volume
1547 if(_UseGameMusicVolume
)
1548 // Game music (background music system)
1549 _AudioMixer
->setMusicVolume(_GameMusicVolume
*_FadeGameMusicVolume
*_FadeGameMusicVolumeDueToEvent
);
1551 // User music volume (mp3 player) is not affected by fadein/fadeout
1552 _AudioMixer
->setMusicVolume(_UserMusicVolume
);
1554 // The event music volume get the game music volume, but is not faded (want music during teleport)
1555 _AudioMixer
->setEventMusicVolume(_GameMusicVolume
);
1557 // update sfx volume
1558 _GroupControllerEffects
->setGain(_SFXVolume
);
1559 _GroupControllerEffectsGame
->setGain(_FadeSFXVolume
);
1563 // ***************************************************************************
1564 void CSoundManager::fadeInGameSound(sint32 timeFadeMs
)
1566 // if already at max, noop
1567 if(_FadeGameMusicVolume
==1.f
&& _FadeSFXVolume
==1.f
)
1570 fadeGameSound(true, timeFadeMs
);
1573 // ***************************************************************************
1574 void CSoundManager::fadeOutGameSound(sint32 timeFadeMs
)
1576 // if already at 0, noop
1577 if(_FadeGameMusicVolume
==0.f
&& _FadeSFXVolume
==0.f
)
1580 fadeGameSound(false, timeFadeMs
);
1583 // ***************************************************************************
1584 void CSoundManager::fadeGameSound(bool fadeIn
, sint32 timeFadeMs
)
1587 clamp(_FadeGameMusicVolume
, 0.f
, 1.f
);
1588 clamp(_FadeSFXVolume
, 0.f
, 1.f
);
1589 TTime t0
= CTime::getLocalTime();
1590 float dVolumeOverDt
= 1.f
/ (timeFadeMs
*0.001f
);
1593 while(fadeIn
?(_FadeGameMusicVolume
<1.f
|| _FadeSFXVolume
<1.f
):(_FadeGameMusicVolume
>0.f
|| _FadeSFXVolume
>0.f
))
1595 // update volume vars
1596 TTime t1
= CTime::getLocalTime();
1597 float dt
= (t1
-t0
)*0.001f
;
1599 _FadeGameMusicVolume
+= dVolumeOverDt
*dt
;
1600 _FadeSFXVolume
+= dVolumeOverDt
*dt
;
1601 clamp(_FadeGameMusicVolume
, 0.f
, 1.f
);
1602 clamp(_FadeSFXVolume
, 0.f
, 1.f
);
1603 // update volume and sound
1609 // ***************************************************************************
1610 void CSoundManager::setupFadeSound(float sfxFade
, float musicFade
)
1612 clamp(sfxFade
, 0.f
, 1.f
);
1613 clamp(musicFade
, 0.f
, 1.f
);
1614 _FadeGameMusicVolume
= musicFade
;
1615 _FadeSFXVolume
= sfxFade
;
1619 // ***************************************************************************
1620 void CSoundManager::updateEventAndGameMusicVolume()
1622 // update event music played state if not looping
1623 if(!_EventMusicPlayed
.empty() && !_EventMusicLoop
)
1626 _EventMusicPlayed
.clear();
1629 if(_AudioMixer
->isEventMusicEnded())
1630 _EventMusicPlayed
.clear();
1635 const sint32 timeFadeMs
= 500;
1636 static TTime t0
= CTime::getLocalTime();
1637 TTime t1
= CTime::getLocalTime();
1638 float dVolume
= (t1
-t0
) / (float)timeFadeMs
;
1641 // if event music is played, music lower the music
1642 if(!_EventMusicPlayed
.empty())
1644 float f
= _FadeGameMusicVolumeDueToEvent
+ dVolume
;
1647 // if faded, update the volume
1648 if(f
!=_FadeGameMusicVolumeDueToEvent
)
1650 _FadeGameMusicVolumeDueToEvent
= f
;
1656 //---------------------------------------------------
1659 //---------------------------------------------------
1660 /*CStepSounds::CStepSounds()
1662 nlstopex(("class CStepSounds is not used anymore"));
1663 //init( CPath::lookup("materials_for_step_sounds.txt", false).c_str() );
1668 //---------------------------------------------------
1671 //---------------------------------------------------
1672 /*void CStepSounds::init( const char * fileName )
1674 nlstopex(("class CStepSounds is not used anymore"));
1675 if(fileName==NULL || strlen(fileName)==0 || fileName[0]=='\0')
1677 nlwarning ("can't load step sound because no material step file");
1681 // get all the materials used for step sounds
1682 list<uint32> materials;
1686 cf.load( fileName );
1688 CConfigFile::CVar &cvMaterials = cf.getVar("Materials");
1689 for(sint i = 0; i < cvMaterials.size(); i++)
1691 materials.push_back( cvMaterials.asInt(i) );
1694 catch (const EConfigFile &e)
1696 nlerror("Problem in the file %s : %s", fileName,e.what ());
1699 // load all sounds for each of these material
1700 list<uint32>::const_iterator itMaterials;
1701 for( itMaterials = materials.begin(); itMaterials != materials.end(); ++itMaterials )
1703 CMaterialStepSounds materialStepSounds;
1704 materialStepSounds.load( CPath::lookup(string("sndmat_") + toString(*itMaterials) + string(".txt")) );
1705 _StepSoundsByMaterial.insert( make_pair(*itMaterials,materialStepSounds) );
1712 //---------------------------------------------------
1715 //---------------------------------------------------
1716 /*bool CStepSounds::getSounds( uint32 material, TMoveType moveType, bool soft, std::vector<string>& sounds )
1718 nlstopex(("class CStepSounds is not used anymore"));
1719 map<uint32,CMaterialStepSounds>::iterator itMatSounds = _StepSoundsByMaterial.find( material );
1720 if( itMatSounds == _StepSoundsByMaterial.end() )
1726 return (*itMatSounds).second.getSounds( moveType, soft, sounds );
1732 //---------------------------------------------------
1735 //---------------------------------------------------
1736 /*void CMaterialStepSounds::readVar( CConfigFile& cf, TMoveType moveType, bool soft, char * varName )
1740 vector<string> sounds;
1741 CConfigFile::CVar &cvSounds = cf.getVar( varName );
1742 for(sint i = 0; i < cvSounds.size(); i++)
1744 sounds.push_back( cvSounds.asString(i) );
1746 _Sounds.insert( make_pair( make_pair(moveType,soft), sounds) );
1748 catch (const EConfigFile &e)
1750 nlwarning("Problem in the sounds by material config file : %s", e.what ());
1757 //---------------------------------------------------
1760 //---------------------------------------------------
1761 /*void CMaterialStepSounds::load( string fileName )
1764 cf.load(CPath::lookup(fileName.c_str()));
1767 readVar(cf,WALK,true,"walk_sounds_soft");
1769 readVar(cf,WALK,false,"walk_sounds_hard");
1771 readVar(cf,RUN,true,"run_sounds_soft");
1773 readVar(cf,RUN,false,"run_sounds_hard");
1776 // user walk soft sounds
1777 readVar(cf,USER_WALK,true,"user_walk_sounds_soft");
1778 // user walk hard sounds
1779 readVar(cf,USER_WALK,false,"user_walk_sounds_hard");
1780 // user run soft sounds
1781 readVar(cf,USER_RUN,true,"user_run_sounds_soft");
1782 // user run hard sounds
1783 readVar(cf,USER_RUN,false,"user_run_sounds_hard");
1788 /*//---------------------------------------------------
1791 //---------------------------------------------------
1792 bool CMaterialStepSounds::getSounds( TMoveType moveType, bool soft, vector<string>& sounds )
1794 map<pair<TMoveType,bool>,vector<string> >::iterator itSounds = _Sounds.find( make_pair(moveType,soft) );
1795 if( itSounds == _Sounds.end() )
1801 uint sz = (*itSounds).second.size();
1803 sounds.resize( sz );
1804 for( i=0; i < sz; i++ )
1806 sounds[i] = (*itSounds).second[i];