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::SoundDrvFMod
)
472 driverType
= UAudioMixer::DriverFMod
;
473 else if(ClientCfg
.DriverSound
==CClientConfig::SoundDrvOpenAL
)
474 driverType
= UAudioMixer::DriverOpenAl
;
475 else if(ClientCfg
.DriverSound
==CClientConfig::SoundDrvDirectSound
)
476 driverType
= UAudioMixer::DriverDSound
;
477 else if(ClientCfg
.DriverSound
==CClientConfig::SoundDrvXAudio2
)
478 driverType
= UAudioMixer::DriverXAudio2
;
479 _AudioMixer
->init(ClientCfg
.MaxTrack
, ClientCfg
.UseEax
, ClientCfg
.UseADPCM
, progressCallBack
, false, driverType
, ClientCfg
.SoundForceSoftwareBuffer
);
480 /* int nbVoice = _AudioMixer->getPolyphony();
481 _AudioMixer->setPriorityReserve(HighPri, max(1, nbVoice /2));
482 nbVoice -= nbVoice /2;
483 _AudioMixer->setPriorityReserve(MidPri, max(1, nbVoice /2));
484 nbVoice -= nbVoice /2;
485 _AudioMixer->setPriorityReserve(LowPri, max(1, nbVoice /2));
487 // when they are only 1 track available, enter in limiting mode.
488 _AudioMixer
->setLowWaterMark(1);
491 * Create the CSoundAnimManager. The CSoundAnimManager is a singleton.
492 * Access the singleton with CSoundAnimManager::instance().
494 new CSoundAnimManager(_AudioMixer
);
496 // get the controller group for effects
497 _GroupControllerEffects
= _AudioMixer
->getGroupController("sound:effects");
498 _GroupControllerEffectsGame
= _AudioMixer
->getGroupController("sound:effects:game");
500 // restore the volume
501 SoundMngr
->setSFXVolume(ClientCfg
.SoundSFXVolume
);
502 SoundMngr
->setGameMusicVolume(ClientCfg
.SoundGameMusicVolume
);
504 // Init clustered sound system
505 _AudioMixer
->initClusteredSound(Scene
, 0.01f
, 100.0f
, PORTAL_INTERPOLATE
);
507 // Init the background flags;
508 for (uint i
=0; i
<NLSOUND::UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS
; ++i
)
509 _BackgroundFlags
.Flags
[i
] = false;
510 _AudioMixer
->setBackgroundFlags(_BackgroundFlags
);
513 * Initialize listener's position
515 CVector
initpos ( 0.0f
, 0.0f
, 0.0f
);
516 //_AudioMixer->getListener()->setPos( initpos );
517 _AudioMixer
->setListenerPos(initpos
);
520 * Init the particule sound system
522 // attach the sound from the particule system
523 NL3D::UParticleSystemSound::setPSSound(_AudioMixer
);
525 //loadPositionedSounds();
527 // reload Sound Animation (if EAM already init)
529 EAM
->reloadAllSoundAnim();
531 // Special option for DEV (easier to test when disabled)
532 _AudioMixer
->enableBackgroundMusicTimeConstraint(ClientCfg
.EnableBackgroundMusicTimeConstraint
);
535 catch(const Exception &e)
537 nlwarning( "Error: %s", e.what() );
542 //---------------------------------------------------
544 //---------------------------------------------------
545 /*bool CSoundManager::getSoundName( TSound sound, std::string &name, const CVector& pos ) const
547 /// \todo Malkav: take ground type into account, and all the different sounds
553 UGlobalPosition globalPos = GR->retrievePosition( pos );
554 uint32 material = GR->getMaterial( globalPos );
582 //---------------------------------------------------
584 // add a new source to the world, attached to the specified entity
585 // return 0 if creation failed, sound id if creation was successful
586 //---------------------------------------------------
587 /*uint32 CSoundManager::addSource( TSound sound, const NLMISC::CVector &position, bool play, bool loop, const CEntityId &parentId )
589 static std::string name;
590 static TSource source;
594 if ( ! getSoundName ( sound, name, position ) )
597 USource *pSource = _AudioMixer->createSource( name );
599 if ( pSource != NULL )
601 pSource ->setPos( position );
603 pSource ->setLooping( loop );
608 //create the TSource object
609 source.sound = sound;
610 source.pSource = pSource;
612 // attach the source to the entity, if specified
613 if (parentId != CEntityId::Unknown)
614 _AttachedSources.insert( TMultiMapEntityToSource::value_type( parentId, source ) );
618 _Sources.insert( TMapIdToSource::value_type( _NextId, source ) );
623 nlwarning( "Sound '%s' not found", name );
630 //-----------------------------------------------
632 // add a new source to the world, attached to the specified entity
633 // return 0 if creation failed, sound id if creation was successful
634 //-----------------------------------------------
635 CSoundManager::TSourceId
CSoundManager::addSource(const NLMISC::TStringId
&soundName
, const NLMISC::CVector
&position
, bool play
, bool loop
, const CEntityId
&id
)
640 USource
*pSource
= _AudioMixer
->createSource(soundName
);
642 // If the source is valid.
645 nlwarning("Sound '%s' not found !", CStringMapper::unmap(soundName
).c_str());
649 // Load the properties for this sound.
650 // REMOVED because the pitch and the gain are now in the .nss (don't need .sdf anymore)
651 // loadProperties(soundName, pSource);
653 // Set the source position.
654 pSource
->setPos( position
);
656 // Is the source looping ?
657 pSource
->setLooping( loop
);
659 // Play the sound immedialty if asked.
665 TSourceId sourceId
= _Sources
.insert(pSource
);
667 // attach the source to the entity, if specified
668 if (id
!= CEntityId::Unknown
)
670 _AttachedSources
.insert( TMultiMapEntityToSource::value_type( id
, sourceId
) );
673 // return the id of the source
679 //-----------------------------------------------
680 // spawn a new source to the world
681 // return false if creation failed, true if creation was successful
682 //-----------------------------------------------
683 bool CSoundManager::spawnSource(const NLMISC::TStringId
&soundName
, CSoundContext
&context
)
685 if (!_PlaySound
) return false;
688 // TODO : find the correct cluster
689 USource
*pSource
= _AudioMixer
->createSource( soundName
, true, NULL
, NULL
, NULL
, &context
);
691 // If the source is valid.
694 nlwarning("Sound '%s' not found !", soundName
);
698 // Set the source position.
699 pSource
->setPos (context
.Position
);
702 ////nlinfo ("%.3f spawn source %p", (float)ryzomGetLocalTime ()/1000.0f, pSource);
709 //-----------------------------------------------
710 // spawn a new source to the world
711 // return false if creation failed, true if creation was successful
712 //-----------------------------------------------
713 bool CSoundManager::spawnSource(const NLMISC::TStringId
&soundName
, const NLMISC::CVector
&position
)
715 if (!_PlaySound
) return false;
718 USource
*pSource
= _AudioMixer
->createSource( soundName
, true);
720 // If the source is valid.
723 nlwarning("Sound '%s' not found !", CStringMapper::unmap(soundName
).c_str ());
727 // Set the source position.
728 pSource
->setPos (position
);
731 ////nlinfo ("%.3f spawn source %p", (float)ryzomGetLocalTime ()/1000.0f, pSource);
739 //---------------------------------------------------
742 //---------------------------------------------------
743 void CSoundManager::removeSource(CSoundManager::TSourceId sourceId
)
745 nldebug("remove the source : %d", sourceId
);
747 /// \todo Malkav : optimize speed
748 nldebug("nb sources = %d", _Sources
.size() );
749 USource
*pSource
= _Sources
.get(sourceId
);
752 TMultiMapEntityToSource::iterator it
= _AttachedSources
.begin();//, itOld;
754 for ( ; it
!= _AttachedSources
.end() ; ++it
)
756 if ( (*it
).second
== sourceId
)
762 _AttachedSources
.erase( it
/*Old*/ );
766 // if (it == _AttachedSources.end() )
773 // i think there was something going on here
774 _Sources
.erase(sourceId
);
780 //---------------------------------------------------
783 //---------------------------------------------------
784 /*bool CSoundManager::getSounds( uint32 material, TMoveType moveType, bool soft, std::vector<string>& sounds )
786 return _StepSounds.getSounds( material, moveType, soft, sounds );
792 //---------------------------------------------------
794 // update the pos of all the sounds attached to that entity
795 //---------------------------------------------------
796 void CSoundManager::updateEntityPos( const CEntityId
&id
, const NLMISC::CVector
&pos
)
798 TMultiMapEntityToSource::iterator it
;
799 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
801 for ( it
= range
.first
; it
!= range
.second
; ++it
)
803 _Sources
.get((*it
).second
)->setPos( pos
);
805 } // updateEntityPos //
808 //---------------------------------------------------
809 // updateEntityVelocity :
810 // update the velocity of all the sounds attached to that entity
811 //---------------------------------------------------
812 void CSoundManager::updateEntityVelocity( const CEntityId
&id
, const NLMISC::CVector
&velocity
)
814 TMultiMapEntityToSource::iterator it
;
815 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
817 for ( it
= range
.first
; it
!= range
.second
; ++it
)
819 _Sources
.get((*it
).second
)->setVelocity( velocity
);
822 } // updateEntityVelocity //
825 //---------------------------------------------------
826 // updateEntityDirection :
827 // update the direction of all the sounds attached to that entity
828 //---------------------------------------------------
829 void CSoundManager::updateEntityDirection( const CEntityId
&id
, const NLMISC::CVector
&dir
)
831 TMultiMapEntityToSource::iterator it
;
832 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
834 for ( it
= range
.first
; it
!= range
.second
; ++it
)
836 _Sources
.get((*it
).second
)->setDirection( dir
);
838 } // updateEntityOrientation //
841 //---------------------------------------------------
843 // remove an entity from the view : delete all the sources attached to that entity
844 //---------------------------------------------------
845 void CSoundManager::removeEntity( const CEntityId
&id
)
847 /// \todo Malkav : optimize speed
849 TMultiMapEntityToSource::iterator it
;
850 const std::pair
<TMultiMapEntityToSource::iterator
, TMultiMapEntityToSource::iterator
> range
= _AttachedSources
.equal_range( id
);
852 for ( it
= range
.first
; it
!= range
.second
; ++it
)
854 TSourceId sourceId
= (*it
).second
;
857 USource
*pSource
= _Sources
.get(sourceId
);
859 _Sources
.erase(sourceId
);
863 _AttachedSources
.erase( range
.first
, range
.second
);
869 //---------------------------------------------------
870 // setSoundPosition :
871 //---------------------------------------------------
872 void CSoundManager::setSoundPosition(TSourceId sourceId
, const NLMISC::CVector
&position
)
874 if (!_PlaySound
) return;
876 USource
*pSource
= _Sources
.get(sourceId
);
877 if (pSource
) pSource
->setPos(position
);
878 } // setSoundPosition //
881 //---------------------------------------------------
883 //---------------------------------------------------
884 void CSoundManager::loopSound(TSourceId sourceId
, bool loop
)
886 if (!_PlaySound
) return;
888 USource
*pSource
= _Sources
.get(sourceId
);
889 if (pSource
) pSource
->setLooping(loop
);
893 //---------------------------------------------------
895 // start or stop playing sound
896 //---------------------------------------------------
897 void CSoundManager::playSound(TSourceId sourceId
, bool play
)
899 if (!_PlaySound
) return;
901 USource
*pSource
= _Sources
.get(sourceId
);
913 //---------------------------------------------------
915 // return true if the source is playing
916 //---------------------------------------------------
917 bool CSoundManager::isPlaying(TSourceId sourceId
)
919 USource
*pSource
= _Sources
.get(sourceId
);
920 if (pSource
) return pSource
->isPlaying();
926 //---------------------------------------------------
927 // setSoundForSource :
928 // set the sound associated to the specified source
929 //---------------------------------------------------
931 bool CSoundManager::setSoundForSource( uint32 sourceId, TSound sound, const CVector& pos )
933 // find the sound name
934 static std::string soundName;
936 if ( ! getSoundName( sound , soundName, pos) )
939 TMapIdToSource::iterator it = _Sources.find( sourceId );
940 if (it != _Sources.end() )
942 nlassert( (*it).second.pSource );
945 TSoundId soundId = _AudioMixer->getSoundId( soundName.c_str() );
949 (*it).second.pSource->setSound( soundId );
950 (*it).second.sound = sound;
951 nlinfo("sound has been set to %d",sound);
956 } // setSoundForSource //
961 //---------------------------------------------------
962 // getSoundFromSource :
963 // get the sound type currently associated to a source
964 //---------------------------------------------------
965 /*CSoundManager::TSound CSoundManager::getSoundFromSource( uint32 sourceId ) const
967 TMapIdToSource::const_iterator it = _Sources.find( sourceId );
968 if (it != _Sources.end() )
970 nlassert( (*it).second.pSource );
972 return ( (*it).second.sound );
976 } // getSoundFromSource //
980 //---------------------------------------------------
982 // set the gain of the specified source
983 //---------------------------------------------------
984 void CSoundManager::setSourceGain(TSourceId sourceId
, float gain
)
986 USource
*pSource
= _Sources
.get(sourceId
);
987 if (pSource
) pSource
->setGain( gain
);
988 } // setSourceGain //
991 //---------------------------------------------------
993 // get the gain of the specified source (-1 if source not found)
994 //---------------------------------------------------
995 float CSoundManager::getSourceGain(TSourceId sourceId
)
997 USource
*pSource
= _Sources
.get(sourceId
);
998 if (pSource
) return pSource
->getGain();
1000 } // getSourceGain //
1003 //---------------------------------------------------
1005 // set the Pitch of the specified source
1006 //---------------------------------------------------
1007 void CSoundManager::setSourcePitch(TSourceId sourceId
, float Pitch
)
1009 USource
*pSource
= _Sources
.get(sourceId
);
1010 if (pSource
) pSource
->setPitch(Pitch
);
1011 } // setSourcePitch //
1014 //---------------------------------------------------
1016 // get the Pitch of the specified source (-1 if source not found)
1017 //---------------------------------------------------
1018 float CSoundManager::getSourcePitch(TSourceId sourceId
)
1020 USource
*pSource
= _Sources
.get(sourceId
);
1021 if (pSource
) return pSource
->getPitch();
1023 } // getSourcePitch //
1027 //---------------------------------------------------
1029 // Load the properties for this sound and apply them.
1030 //---------------------------------------------------
1031 void CSoundManager::loadProperties(const string
&soundName
, USource
*source
)
1033 // If the source does not exist -> return nothing to do.
1037 // Search for the file.
1038 string filePath
= CPath::lookup(soundName
+".sdf");
1042 // Try to open the file.
1043 if (file
.open(filePath
))
1046 char delimiterBox
[] = "\t ";
1047 // While the end of the file is not reached.
1050 // Get a line (the line should not be more than _MAX_LINE_SIZE).
1051 file
.getline(tmpBuff
, 260);
1052 char *token
= strtok(tmpBuff
, delimiterBox
);
1053 while(token
!= NULL
)
1056 if(strcmp(token
, "Pitch:") == 0)
1058 token
= strtok(NULL
, delimiterBox
);
1062 fromString(token
, pitch
);
1063 nlinfo("Pitch: %f", pitch
);
1064 source
->setPitch(pitch
);
1068 else if(strcmp(token
, "Gain:") == 0)
1070 token
= strtok(NULL
, delimiterBox
);
1074 fromString(token
, gain
);
1075 nlinfo("Gain: %f", gain
);
1076 source
->setGain(gain
);
1081 token
= strtok(NULL
, delimiterBox
);
1087 }// loadProperties //
1092 //---------------------------------------------------
1093 // loadPositionedSounds :
1095 //---------------------------------------------------
1096 /*void CSoundManager::loadPositionedSounds()
1098 nlstopex(("class CStepSounds is not used anymore"));
1102 // build file format
1103 map<string,CSTLoader::TDataType> fileFormat;
1104 fileFormat.insert( make_pair( string( "sound name" ) , CSTLoader::STRING ));
1105 fileFormat.insert( make_pair( string( "x" ) , CSTLoader::FLOAT ));
1106 fileFormat.insert( make_pair( string( "y" ) , CSTLoader::FLOAT ));
1107 fileFormat.insert( make_pair( string( "z" ) , CSTLoader::FLOAT ));
1108 fileFormat.insert( make_pair( string( "loop" ) , CSTLoader::BOOL ));
1111 string str = CPath::lookup("positioned_sounds.txt", false);
1114 nlwarning ("cant load positioned_sounds");
1119 cstl.init( str, fileFormat );
1122 while( cstl.readLine() )
1125 cstl.getStringValue( "sound name", soundName );
1128 cstl.getValue( "x", sourcePos.x );
1129 cstl.getValue( "y", sourcePos.y );
1130 cstl.getValue( "z", sourcePos.z );
1133 cstl.getBoolValue( "loop", loop );
1135 uint32 sourceId = addSource( soundName, sourcePos, false , loop );
1139 _PositionedSounds.push_back( sourceId );
1143 nlwarning ("positioned sound: can't find sound: '%s'", soundName.c_str());
1149 } // chooseSoundOnMaterial //
1153 //---------------------------------------------------
1154 // playPositionedSounds :
1156 //---------------------------------------------------
1157 void CSoundManager::playPositionedSounds( const CVector
& /* pos */ )
1159 if (!_PlaySound
) return;
1161 list
<uint32
>::iterator itPSnd
;
1162 for( itPSnd
= _PositionedSounds
.begin(); itPSnd
!= _PositionedSounds
.end(); ++itPSnd
)
1164 USource
*pSource
= _Sources
.get(*itPSnd
);
1167 nlwarning("<CSoundManager::playPositionedSounds> : The source %d is unknown",*itPSnd
);
1172 if( (pos - (*itSrc).second.getPos()).norm() < ...)
1174 if( (*itSrc).second.pSource->isPlaying() == false )
1176 (*itSrc).second.pSource->play();
1180 if (!pSource
->isPlaying())
1187 } // playPositionedSounds //
1190 void CSoundManager::selectEnv( const std::string
&/* tag */)
1192 // TODO : boris : temporarily removed.
1193 /* if (_EnvSoundRoot==NULL)
1196 _EnvSoundRoot->selectEnv (tag.c_str(), true);
1200 void CSoundManager::setFilterState(uint filterId
, bool state
)
1202 nlassert(filterId
< NLSOUND::UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS
);
1203 _BackgroundFlags
.Flags
[filterId
] = state
;
1205 _AudioMixer
->setBackgroundFlags(_BackgroundFlags
);
1210 // ***************************************************************************
1211 void CSoundManager::update ()
1213 // Filters : day = 0, night = 1, morning = 2, Dusk = 3
1214 // update the filter state for day/night management.
1215 switch(LightCycleManager
.getState())
1217 case CLightCycleManager::Day
:
1218 _BackgroundFlags
.Flags
[DAY
] = true;
1219 _BackgroundFlags
.Flags
[NIGHT
] = false;
1220 _BackgroundFlags
.Flags
[MORNING
] = false;
1221 _BackgroundFlags
.Flags
[DUSK
] = false;
1223 case CLightCycleManager::Night
:
1224 _BackgroundFlags
.Flags
[DAY
] = false;
1225 _BackgroundFlags
.Flags
[NIGHT
] = true;
1226 _BackgroundFlags
.Flags
[MORNING
] = false;
1227 _BackgroundFlags
.Flags
[DUSK
] = false;
1229 case CLightCycleManager::DayToNight
:
1230 _BackgroundFlags
.Flags
[DAY
] = true;
1231 _BackgroundFlags
.Flags
[NIGHT
] = false;
1232 _BackgroundFlags
.Flags
[MORNING
] = true;
1233 _BackgroundFlags
.Flags
[DUSK
] = false;
1235 case CLightCycleManager::NightToDay
:
1236 _BackgroundFlags
.Flags
[DAY
] = false;
1237 _BackgroundFlags
.Flags
[NIGHT
] = false;
1238 _BackgroundFlags
.Flags
[MORNING
] = false;
1239 _BackgroundFlags
.Flags
[DUSK
] = true;
1241 case CLightCycleManager::StateUnknown
:
1242 //nlwarning("Unknown light cycle state reached.");
1246 // update the filter for season.
1247 EGSPD::CSeason::TSeason season
= CurrSeason
;
1250 case EGSPD::CSeason::Spring
:
1251 _BackgroundFlags
.Flags
[SPRING
] = true;
1252 _BackgroundFlags
.Flags
[SUMMER
] = false;
1253 _BackgroundFlags
.Flags
[AUTUMN
] = false;
1254 _BackgroundFlags
.Flags
[WINTER
] = false;
1256 case EGSPD::CSeason::Summer
:
1257 _BackgroundFlags
.Flags
[SPRING
] = false;
1258 _BackgroundFlags
.Flags
[SUMMER
] = true;
1259 _BackgroundFlags
.Flags
[AUTUMN
] = false;
1260 _BackgroundFlags
.Flags
[WINTER
] = false;
1262 case EGSPD::CSeason::Autumn
:
1263 _BackgroundFlags
.Flags
[SPRING
] = false;
1264 _BackgroundFlags
.Flags
[SUMMER
] = false;
1265 _BackgroundFlags
.Flags
[AUTUMN
] = true;
1266 _BackgroundFlags
.Flags
[WINTER
] = false;
1268 case EGSPD::CSeason::Winter
:
1269 _BackgroundFlags
.Flags
[SPRING
] = false;
1270 _BackgroundFlags
.Flags
[SUMMER
] = false;
1271 _BackgroundFlags
.Flags
[AUTUMN
] = false;
1272 _BackgroundFlags
.Flags
[WINTER
] = true;
1275 //nlwarning("Updating unknown season.");
1278 // TODO : update the filter state for weather effet
1279 CWeatherState weatherState
= WeatherManager
.getCurrWeatherState();
1283 enum TWeatherSoundEnv
1285 WSEMist
= 0, // not used
1295 WSEThunderSand1
, // not used
1296 WSEThunderSand2
, // not used
1297 WSEThunderSand3
, // not used
1301 // For each weather setup, gives the matching weather sound env to used, when there are precipitation or not
1302 class CWeatherSetupSoundEnv
1305 NLMISC::TStringId SetupName
; // setup nem as found is the .weather_setup sheets
1306 TWeatherSoundEnv Sound
;
1307 CWeatherSetupSoundEnv(const char *setupName
, TWeatherSoundEnv sound
)
1309 SetupName
= NLMISC::CStringMapper::map(setupName
);
1314 // association between weather setup names & sound env
1315 static const CWeatherSetupSoundEnv weatherSoundLUT
[] =
1317 CWeatherSetupSoundEnv("fair1", WSEFair1
),
1318 CWeatherSetupSoundEnv("fair2", WSEFair2
),
1319 CWeatherSetupSoundEnv("fair3", WSEFair3
),
1320 CWeatherSetupSoundEnv("wind1", WSEClouds
),
1321 CWeatherSetupSoundEnv("humidity1", WSERain1
),
1322 CWeatherSetupSoundEnv("humidity2", WSERain2
),
1323 CWeatherSetupSoundEnv("clouds1", WSERain1
),
1324 CWeatherSetupSoundEnv("clouds2", WSERain2
),
1325 CWeatherSetupSoundEnv("thunderseve", WSEThunderSeve
),
1326 CWeatherSetupSoundEnv("storm", WSEThunder1
),
1327 CWeatherSetupSoundEnv("snow", WSESnow1
),
1330 const CWeatherSetupSoundEnv
*weatherSetupSoundEnv
= NULL
;
1331 for(uint k
= 0; k
< sizeof(weatherSoundLUT
) / sizeof(weatherSoundLUT
[0]); ++k
)
1333 if (weatherSoundLUT
[k
].SetupName
== weatherState
.BestSetupName
)
1335 weatherSetupSoundEnv
= &weatherSoundLUT
[k
];
1340 // disable all weather setup sound flags except the current one
1341 for(uint k
= 0; k
< WSECount
; ++k
)
1343 _BackgroundFlags
.Flags
[MIST
+k
] = false;
1345 if (weatherSetupSoundEnv
)
1347 _BackgroundFlags
.Flags
[MIST
+ weatherSetupSoundEnv
->Sound
] = true;
1351 static bool bDisplayOnce
= false;
1354 nlinfo("The current weather setup '%s' is unknown !", CStringMapper::unmap(weatherState
.BestSetupName
).c_str());
1355 bDisplayOnce
= true;
1359 // update the background flags in the mixer.
1360 _AudioMixer
->setBackgroundFlags(_BackgroundFlags
);
1362 // update background music enabling
1363 if(_EnableBackgroundMusicAtTime
&& CTime::getLocalTime()>_EnableBackgroundMusicAtTime
)
1365 setGameMusicMode(true, true);
1368 // Special option for DEV (easier to test when disabled)
1369 _AudioMixer
->enableBackgroundMusicTimeConstraint(ClientCfg
.EnableBackgroundMusicTimeConstraint
);
1371 // update game music volume because of event played or not
1372 updateEventAndGameMusicVolume();
1374 // update audio mixer
1375 _AudioMixer
->update ();
1378 // ***************************************************************************
1379 void CSoundManager::updateAudioMixerOnly()
1383 _AudioMixer
->update ();
1386 // ***************************************************************************
1387 void CSoundManager::playBackgroundSound()
1389 _AudioMixer
->playBackgroundSound();
1392 // ***************************************************************************
1393 void CSoundManager::stopBackgroundSound()
1395 _AudioMixer
->stopBackgroundSound();
1398 // ***************************************************************************
1399 void CSoundManager::playMusic(const string
&fileName
, uint xFadeTime
, bool async
, bool loop
, bool forceGameMusicVolume
)
1401 if(fileName
.empty())
1403 stopMusic(xFadeTime
);
1409 // disable before the background music (before is important else may have bug)
1410 setGameMusicMode(false, forceGameMusicVolume
);
1412 _AudioMixer
->playMusic(fileName
, xFadeTime
, async
, loop
);
1417 // ***************************************************************************
1418 void CSoundManager::stopMusic(uint xFadeTime
)
1423 _AudioMixer
->stopMusic(xFadeTime
);
1424 // and reenable the background music system. after a delay if xFadeTime
1427 // enable background music later
1428 _EnableBackgroundMusicAtTime
= CTime::getLocalTime()+xFadeTime
;
1433 setGameMusicMode(true, true);
1438 // ***************************************************************************
1439 void CSoundManager::playEventMusic(const string
&fileName
, uint xFadeTime
, bool loop
)
1441 // if event music not enabled (mp3 player), abort
1442 if(!_EventMusicEnabled
)
1445 if(fileName
.empty())
1447 stopEventMusic("", xFadeTime
);
1453 // if the music is not already currently playing (with same loop state)
1454 if(_EventMusicPlayed
.empty() || nlstricmp(fileName
, _EventMusicPlayed
)!=0 || loop
!=_EventMusicLoop
)
1457 _AudioMixer
->playEventMusic(fileName
, xFadeTime
, true, loop
);
1458 _EventMusicPlayed
= fileName
;
1459 _EventMusicLoop
= loop
;
1465 // ***************************************************************************
1466 void CSoundManager::stopEventMusic(const string
&fileName
, uint xFadeTime
)
1470 // if the event music is the one currently played, or if empty fileName
1471 if(fileName
.empty() || nlstricmp(_EventMusicPlayed
,fileName
)==0)
1474 _AudioMixer
->stopEventMusic(xFadeTime
);
1475 // music no more played
1476 _EventMusicPlayed
.clear();
1481 // ***************************************************************************
1482 void CSoundManager::pauseMusic()
1485 _AudioMixer
->pauseMusic();
1488 // ***************************************************************************
1489 void CSoundManager::resumeMusic()
1492 _AudioMixer
->resumeMusic();
1495 // ***************************************************************************
1496 bool CSoundManager::isMusicEnded()
1499 return _AudioMixer
->isMusicEnded();
1503 // ***************************************************************************
1504 void CSoundManager::setGameMusicVolume(float val
)
1507 _GameMusicVolume
= val
;
1511 // ***************************************************************************
1512 void CSoundManager::setUserMusicVolume(float val
)
1515 _UserMusicVolume
= val
;
1519 // ***************************************************************************
1520 void CSoundManager::setSFXVolume(float val
)
1527 // ***************************************************************************
1528 void CSoundManager::setGameMusicMode(bool enableBackground
, bool useGameMusicVolume
)
1530 // update background music state
1531 _EnableBackgroundMusicAtTime
= 0;
1532 _AudioMixer
->enableBackgroundMusic(enableBackground
);
1533 _UseGameMusicVolume
= useGameMusicVolume
;
1534 // event music enabled if the background music is also enabled
1535 _EventMusicEnabled
= enableBackground
;
1536 // stop any event music if disabled
1537 if(!_EventMusicEnabled
)
1538 stopEventMusic("", 500);
1539 // update music volume state
1543 // ***************************************************************************
1544 void CSoundManager::updateVolume()
1548 // update music volume
1549 if(_UseGameMusicVolume
)
1550 // Game music (background music system)
1551 _AudioMixer
->setMusicVolume(_GameMusicVolume
*_FadeGameMusicVolume
*_FadeGameMusicVolumeDueToEvent
);
1553 // User music volume (mp3 player) is not affected by fadein/fadeout
1554 _AudioMixer
->setMusicVolume(_UserMusicVolume
);
1556 // The event music volume get the game music volume, but is not faded (want music during teleport)
1557 _AudioMixer
->setEventMusicVolume(_GameMusicVolume
);
1559 // update sfx volume
1560 _GroupControllerEffects
->setGain(_SFXVolume
);
1561 _GroupControllerEffectsGame
->setGain(_FadeSFXVolume
);
1565 // ***************************************************************************
1566 void CSoundManager::fadeInGameSound(sint32 timeFadeMs
)
1568 // if already at max, noop
1569 if(_FadeGameMusicVolume
==1.f
&& _FadeSFXVolume
==1.f
)
1572 fadeGameSound(true, timeFadeMs
);
1575 // ***************************************************************************
1576 void CSoundManager::fadeOutGameSound(sint32 timeFadeMs
)
1578 // if already at 0, noop
1579 if(_FadeGameMusicVolume
==0.f
&& _FadeSFXVolume
==0.f
)
1582 fadeGameSound(false, timeFadeMs
);
1585 // ***************************************************************************
1586 void CSoundManager::fadeGameSound(bool fadeIn
, sint32 timeFadeMs
)
1589 clamp(_FadeGameMusicVolume
, 0.f
, 1.f
);
1590 clamp(_FadeSFXVolume
, 0.f
, 1.f
);
1591 TTime t0
= CTime::getLocalTime();
1592 float dVolumeOverDt
= 1.f
/ (timeFadeMs
*0.001f
);
1595 while(fadeIn
?(_FadeGameMusicVolume
<1.f
|| _FadeSFXVolume
<1.f
):(_FadeGameMusicVolume
>0.f
|| _FadeSFXVolume
>0.f
))
1597 // update volume vars
1598 TTime t1
= CTime::getLocalTime();
1599 float dt
= (t1
-t0
)*0.001f
;
1601 _FadeGameMusicVolume
+= dVolumeOverDt
*dt
;
1602 _FadeSFXVolume
+= dVolumeOverDt
*dt
;
1603 clamp(_FadeGameMusicVolume
, 0.f
, 1.f
);
1604 clamp(_FadeSFXVolume
, 0.f
, 1.f
);
1605 // update volume and sound
1611 // ***************************************************************************
1612 void CSoundManager::setupFadeSound(float sfxFade
, float musicFade
)
1614 clamp(sfxFade
, 0.f
, 1.f
);
1615 clamp(musicFade
, 0.f
, 1.f
);
1616 _FadeGameMusicVolume
= musicFade
;
1617 _FadeSFXVolume
= sfxFade
;
1621 // ***************************************************************************
1622 void CSoundManager::updateEventAndGameMusicVolume()
1624 // update event music played state if not looping
1625 if(!_EventMusicPlayed
.empty() && !_EventMusicLoop
)
1628 _EventMusicPlayed
.clear();
1631 if(_AudioMixer
->isEventMusicEnded())
1632 _EventMusicPlayed
.clear();
1637 const sint32 timeFadeMs
= 500;
1638 static TTime t0
= CTime::getLocalTime();
1639 TTime t1
= CTime::getLocalTime();
1640 float dVolume
= (t1
-t0
) / (float)timeFadeMs
;
1643 // if event music is played, music lower the music
1644 if(!_EventMusicPlayed
.empty())
1646 float f
= _FadeGameMusicVolumeDueToEvent
+ dVolume
;
1649 // if faded, update the volume
1650 if(f
!=_FadeGameMusicVolumeDueToEvent
)
1652 _FadeGameMusicVolumeDueToEvent
= f
;
1658 //---------------------------------------------------
1661 //---------------------------------------------------
1662 /*CStepSounds::CStepSounds()
1664 nlstopex(("class CStepSounds is not used anymore"));
1665 //init( CPath::lookup("materials_for_step_sounds.txt", false).c_str() );
1670 //---------------------------------------------------
1673 //---------------------------------------------------
1674 /*void CStepSounds::init( const char * fileName )
1676 nlstopex(("class CStepSounds is not used anymore"));
1677 if(fileName==NULL || strlen(fileName)==0 || fileName[0]=='\0')
1679 nlwarning ("can't load step sound because no material step file");
1683 // get all the materials used for step sounds
1684 list<uint32> materials;
1688 cf.load( fileName );
1690 CConfigFile::CVar &cvMaterials = cf.getVar("Materials");
1691 for(sint i = 0; i < cvMaterials.size(); i++)
1693 materials.push_back( cvMaterials.asInt(i) );
1696 catch (const EConfigFile &e)
1698 nlerror("Problem in the file %s : %s", fileName,e.what ());
1701 // load all sounds for each of these material
1702 list<uint32>::const_iterator itMaterials;
1703 for( itMaterials = materials.begin(); itMaterials != materials.end(); ++itMaterials )
1705 CMaterialStepSounds materialStepSounds;
1706 materialStepSounds.load( CPath::lookup(string("sndmat_") + toString(*itMaterials) + string(".txt")) );
1707 _StepSoundsByMaterial.insert( make_pair(*itMaterials,materialStepSounds) );
1714 //---------------------------------------------------
1717 //---------------------------------------------------
1718 /*bool CStepSounds::getSounds( uint32 material, TMoveType moveType, bool soft, std::vector<string>& sounds )
1720 nlstopex(("class CStepSounds is not used anymore"));
1721 map<uint32,CMaterialStepSounds>::iterator itMatSounds = _StepSoundsByMaterial.find( material );
1722 if( itMatSounds == _StepSoundsByMaterial.end() )
1728 return (*itMatSounds).second.getSounds( moveType, soft, sounds );
1734 //---------------------------------------------------
1737 //---------------------------------------------------
1738 /*void CMaterialStepSounds::readVar( CConfigFile& cf, TMoveType moveType, bool soft, char * varName )
1742 vector<string> sounds;
1743 CConfigFile::CVar &cvSounds = cf.getVar( varName );
1744 for(sint i = 0; i < cvSounds.size(); i++)
1746 sounds.push_back( cvSounds.asString(i) );
1748 _Sounds.insert( make_pair( make_pair(moveType,soft), sounds) );
1750 catch (const EConfigFile &e)
1752 nlwarning("Problem in the sounds by material config file : %s", e.what ());
1759 //---------------------------------------------------
1762 //---------------------------------------------------
1763 /*void CMaterialStepSounds::load( string fileName )
1766 cf.load(CPath::lookup(fileName.c_str()));
1769 readVar(cf,WALK,true,"walk_sounds_soft");
1771 readVar(cf,WALK,false,"walk_sounds_hard");
1773 readVar(cf,RUN,true,"run_sounds_soft");
1775 readVar(cf,RUN,false,"run_sounds_hard");
1778 // user walk soft sounds
1779 readVar(cf,USER_WALK,true,"user_walk_sounds_soft");
1780 // user walk hard sounds
1781 readVar(cf,USER_WALK,false,"user_walk_sounds_hard");
1782 // user run soft sounds
1783 readVar(cf,USER_RUN,true,"user_run_sounds_soft");
1784 // user run hard sounds
1785 readVar(cf,USER_RUN,false,"user_run_sounds_hard");
1790 /*//---------------------------------------------------
1793 //---------------------------------------------------
1794 bool CMaterialStepSounds::getSounds( TMoveType moveType, bool soft, vector<string>& sounds )
1796 map<pair<TMoveType,bool>,vector<string> >::iterator itSounds = _Sounds.find( make_pair(moveType,soft) );
1797 if( itSounds == _Sounds.end() )
1803 uint sz = (*itSounds).second.size();
1805 sounds.resize( sz );
1806 for( i=0; i < sz; i++ )
1808 sounds[i] = (*itSounds).second[i];