diff --git a/code/nel/include/nel/sound/audio_mixer_user.h b/code/nel/include/nel/sound/audio_mixer_user.h index 7cd0de051..eded75fc6 100644 --- a/code/nel/include/nel/sound/audio_mixer_user.h +++ b/code/nel/include/nel/sound/audio_mixer_user.h @@ -204,9 +204,9 @@ public: * pass a callback function that will be called (if not NULL) just before deleting the spawned * source. */ - virtual USource *createSource( const NLMISC::TStringId &name, bool spawn=false, TSpawnEndCallback cb=NULL, void *cbUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context = 0 ); + virtual USource *createSource( const NLMISC::TStringId &name, bool spawn=false, TSpawnEndCallback cb=NULL, void *cbUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context = 0, UGroupController *groupController = NULL); /// Add a logical sound source (by sound id). To remove a source, just delete it. See createSource(const char*) - virtual USource *createSource( TSoundId id, bool spawn=false, TSpawnEndCallback cb=NULL, void *cbUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context = 0 ); + virtual USource *createSource( TSoundId id, bool spawn=false, TSpawnEndCallback cb=NULL, void *cbUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context = 0, UGroupController *groupController = NULL); /// Add a source which was created by an EnvSound void addSource( CSourceCommon *source ); /** Delete a logical sound source. If you don't call it, the source will be auto-deleted @@ -431,8 +431,9 @@ private: // utility function for automatic sample bank loading. bool tryToLoadSampleBank(const std::string &sampleName); - +public: typedef CHashSet > TSourceContainer; +private: typedef CHashSet > TMixerUpdateContainer; typedef CHashMap, THashPtr > TBufferToSourceContainer; // typedef std::multimap TTimedEventContainer; diff --git a/code/nel/include/nel/sound/background_source.h b/code/nel/include/nel/sound/background_source.h index cdf044776..14ea1cf53 100644 --- a/code/nel/include/nel/sound/background_source.h +++ b/code/nel/include/nel/sound/background_source.h @@ -36,7 +36,7 @@ class CBackgroundSource : public CSourceCommon , public CAudioMixerUser::IMixerU { public: /// Constructor - CBackgroundSource (CBackgroundSound *backgroundSound=NULL, bool spawn=false, TSpawnEndCallback cb=0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0); + CBackgroundSource (CBackgroundSound *backgroundSound=NULL, bool spawn=false, TSpawnEndCallback cb=0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0, CGroupController *groupController = NULL); /// Destructor ~CBackgroundSource (); diff --git a/code/nel/include/nel/sound/complex_source.h b/code/nel/include/nel/sound/complex_source.h index d27b5af5b..d1135b1ad 100644 --- a/code/nel/include/nel/sound/complex_source.h +++ b/code/nel/include/nel/sound/complex_source.h @@ -34,7 +34,7 @@ class CComplexSource : public CSourceCommon, public CAudioMixerUser::IMixerEvent { public: /// Constructor - CComplexSource (CComplexSound *soundPattern=NULL, bool spawn=false, TSpawnEndCallback cb=0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0); + CComplexSource (CComplexSound *soundPattern=NULL, bool spawn=false, TSpawnEndCallback cb=0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0, CGroupController *groupController = NULL); /// Destructor ~CComplexSource (); diff --git a/code/nel/include/nel/sound/group_controller.h b/code/nel/include/nel/sound/group_controller.h new file mode 100644 index 000000000..4c443a52d --- /dev/null +++ b/code/nel/include/nel/sound/group_controller.h @@ -0,0 +1,100 @@ +/** + * \file group_controller.h + * \brief CGroupController + * \date 2012-04-10 09:29GMT + * \author Jan Boon (Kaetemi) + * CGroupController + */ + +/* + * 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 NLSOUND_GROUP_CONTROLLER_H +#define NLSOUND_GROUP_CONTROLLER_H +#include + +// STL includes +#include +#include + +// NeL includes +#include +#include +#include + +// Project includes + +namespace NLSOUND { + class CSourceCommon; + class CGroupControllerRoot; + +/** + * \brief CGroupController + * \date 2012-04-10 09:29GMT + * \author Jan Boon (Kaetemi) + * CGroupController + */ +class CGroupController : public UGroupController +{ +public: + friend CGroupControllerRoot; + +private: + CGroupController *m_Parent; + std::map m_Children; + + float m_DevGain; + float m_UserGain; + float m_FinalGain; + + int m_NbSourcesInclChild; + CAudioMixerUser::TSourceContainer m_Sources; + +public: + CGroupController(CGroupController *parent); + + /// \name UGroupController + //@{ + virtual void setDevGain(float gain) { NLMISC::clamp(gain, 0.0f, 1.0f); m_DevGain = gain; updateSourceGain(); } + virtual float getDevGain() { return m_DevGain; } + + virtual void setUserGain(float gain) { NLMISC::clamp(gain, 0.0f, 1.0f); m_UserGain = gain; updateSourceGain(); } + virtual float getUserGain() { return m_UserGain; } + //@} + + inline float getFinalGain() const { return m_FinalGain; } + + void addSource(CSourceCommon *source); + void removeSource(CSourceCommon *source); + +private: + virtual ~CGroupController(); // subnodes can only be deleted by the root + inline float calculateTotalGain() { return m_DevGain * m_UserGain; } + virtual void calculateFinalGain(); + virtual void increaseSources(); + virtual void decreaseSources(); + void updateSourceGain(); + +}; /* class CGroupController */ + +} /* namespace NLSOUND */ + +#endif /* #ifndef NLSOUND_GROUP_CONTROLLER_H */ + +/* end of file */ diff --git a/code/nel/include/nel/sound/group_controller_root.h b/code/nel/include/nel/sound/group_controller_root.h new file mode 100644 index 000000000..82c3af849 --- /dev/null +++ b/code/nel/include/nel/sound/group_controller_root.h @@ -0,0 +1,67 @@ +/** + * \file group_controller_root.h + * \brief CGroupControllerRoot + * \date 2012-04-10 09:44GMT + * \author Jan Boon (Kaetemi) + * CGroupControllerRoot + */ + +/* + * 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 NLSOUND_GROUP_CONTROLLER_ROOT_H +#define NLSOUND_GROUP_CONTROLLER_ROOT_H +#include + +// STL includes + +// NeL includes + +// Project includes +#include + +namespace NLSOUND { + +/** + * \brief CGroupControllerRoot + * \date 2012-04-10 09:44GMT + * \author Jan Boon (Kaetemi) + * CGroupControllerRoot + */ +class CGroupControllerRoot : public CGroupController +{ +public: + CGroupControllerRoot(); + virtual ~CGroupControllerRoot(); + + /// Gets the group controller in a certain path with separator '/', if it doesn't exist yet it will be created. + CGroupController *getGroupController(const std::string &path); + +protected: + virtual void calculateFinalGain(); + virtual void increaseSources(); + virtual void decreaseSources(); + +}; /* class CGroupControllerRoot */ + +} /* namespace NLSOUND */ + +#endif /* #ifndef NLSOUND_GROUP_CONTROLLER_ROOT_H */ + +/* end of file */ diff --git a/code/nel/include/nel/sound/music_source.h b/code/nel/include/nel/sound/music_source.h index a23547c6c..be09c1837 100644 --- a/code/nel/include/nel/sound/music_source.h +++ b/code/nel/include/nel/sound/music_source.h @@ -35,7 +35,7 @@ class CMusicSource : public CSourceCommon { public: /// Constructor - CMusicSource (class CMusicSound *sound=NULL, bool spawn=false, TSpawnEndCallback cb=0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0); + CMusicSource (class CMusicSound *sound=NULL, bool spawn=false, TSpawnEndCallback cb=0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0, CGroupController *groupController = NULL); /// Destructor ~CMusicSource (); diff --git a/code/nel/include/nel/sound/simple_source.h b/code/nel/include/nel/sound/simple_source.h index ac2af0099..9b21200c9 100644 --- a/code/nel/include/nel/sound/simple_source.h +++ b/code/nel/include/nel/sound/simple_source.h @@ -40,7 +40,7 @@ class CSimpleSource : public CSourceCommon, public CAudioMixerUser::IMixerEvent { public: /// Constructor - CSimpleSource(CSimpleSound *simpleSound = NULL, bool spawn = false, TSpawnEndCallback cb = 0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0); + CSimpleSource(CSimpleSound *simpleSound = NULL, bool spawn = false, TSpawnEndCallback cb = 0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0, CGroupController *groupController = NULL); /// Destructor virtual ~CSimpleSource(); @@ -97,14 +97,7 @@ public: * 1.0 -> no attenuation * values > 1 (amplification) not supported by most drivers */ - virtual void setGain( float gain ); - /** Set the gain amount (value inside [0, 1]) to map between 0 and the nominal gain - * (which is getSource()->getGain()). Does nothing if getSource() is null. - */ - virtual void setRelativeGain( float gain ); - /** Shift the frequency. 1.0f equals identity, each reduction of 50% equals a pitch shift - * of one octave. 0 is not a legal value. - */ + virtual void updateFinalGain(); virtual void setPitch( float pitch ); /// Set the source relative mode. If true, positions are interpreted relative to the listener position (default: false) virtual void setSourceRelativeMode( bool mode ); diff --git a/code/nel/include/nel/sound/sound.h b/code/nel/include/nel/sound/sound.h index 2112a0e73..ef0e62f72 100644 --- a/code/nel/include/nel/sound/sound.h +++ b/code/nel/include/nel/sound/sound.h @@ -30,6 +30,7 @@ namespace NLSOUND { class ISoundDriver; class IBuffer; class CSound; +class CGroupController; /// Sound names hash map @@ -104,6 +105,8 @@ public: /// Return the max distance (if detailed()) virtual float getMaxDistance() const { return _MaxDist; } + inline CGroupController *getGroupController() const { return NULL; } // TODO, RETURN THE GROUP CONTROLLER + /// Set looping void setLooping( bool looping ) { _Looping = looping; } diff --git a/code/nel/include/nel/sound/source_common.h b/code/nel/include/nel/sound/source_common.h index 34e3f084a..ca0a9a2b8 100644 --- a/code/nel/include/nel/sound/source_common.h +++ b/code/nel/include/nel/sound/source_common.h @@ -22,7 +22,7 @@ #include "nel/sound/u_stream_source.h" #include "nel/3d/cluster.h" #include "nel/sound/sound.h" - +#include "nel/sound/group_controller.h" namespace NLSOUND { @@ -36,11 +36,12 @@ public: SOURCE_SIMPLE, SOURCE_COMPLEX, SOURCE_BACKGROUND, - SOURCE_MUSIC, + SOURCE_MUSIC, // DEPRECATED SOURCE_STREAM }; - CSourceCommon(TSoundId id, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster); + /// When groupController is NULL it will use the groupcontroller specified in the TSoundId. You should manually specify the groupController if this source is a child of another source, so that the parent source controller of the user-specified .sound file is the one that will be used. + CSourceCommon(TSoundId id, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController); ~CSourceCommon(); @@ -63,6 +64,8 @@ public: void setGain( float gain ); void setRelativeGain( float gain ); float getRelativeGain() const; + /// Called whenever the gain is changed trough setGain, setRelativeGain or the group controller's gain settings change. + virtual void updateFinalGain() { } void setSourceRelativeMode( bool mode ); /// return the user param for the user callback void *getCallbackUserParam(void) const { return _CbUserParam; } @@ -74,6 +77,8 @@ public: virtual void getDirection( NLMISC::CVector& dir ) const { dir = _Direction; } /// Get the gain virtual float getGain() const { return _Gain; } + /// Get the final gain, including group controller changes. Use this when setting the physical source output gain. + inline float getFinalGain() const { return _Gain * _GroupController->getFinalGain(); } /// Get the pitch virtual float getPitch() const { return _Pitch; } /// Get the source relative mode @@ -145,6 +150,9 @@ protected: /// An optional user var controler. NLMISC::TStringId _UserVarControler; + /// Group controller for gain + CGroupController *_GroupController; + }; } // NLSOUND diff --git a/code/nel/include/nel/sound/stream_source.h b/code/nel/include/nel/sound/stream_source.h index a5ac7c9f8..702a26006 100644 --- a/code/nel/include/nel/sound/stream_source.h +++ b/code/nel/include/nel/sound/stream_source.h @@ -41,7 +41,7 @@ namespace NLSOUND { class CStreamSource : public CSourceCommon { public: - CStreamSource(CStreamSound *streamSound = NULL, bool spawn = false, TSpawnEndCallback cb = 0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0); + CStreamSource(CStreamSound *streamSound = NULL, bool spawn = false, TSpawnEndCallback cb = 0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0, CGroupController *groupController = NULL); virtual ~CStreamSource(); /// Return the sound binded to the source (or NULL if there is no sound) @@ -80,18 +80,7 @@ public: virtual void setVelocity(const NLMISC::CVector& vel); /// Set the direction vector (3D mode only, ignored in stereo mode) (default: (0,0,0) as non-directional) virtual void setDirection(const NLMISC::CVector& dir); - /** Set the gain (volume value inside [0 , 1]). (default: 1) - * 0.0 -> silence - * 0.5 -> -6dB - * 1.0 -> no attenuation - * values > 1 (amplification) not supported by most drivers - */ - virtual void setGain(float gain); - - /** Set the gain amount (value inside [0, 1]) to map between 0 and the nominal gain - * (which is getSource()->getGain()). Does nothing if getSource() is null. - */ - virtual void setRelativeGain(float gain); + virtual void updateFinalGain(); /** Shift the frequency. 1.0f equals identity, each reduction of 50% equals a pitch shift * of one octave. 0 is not a legal value. */ diff --git a/code/nel/include/nel/sound/u_audio_mixer.h b/code/nel/include/nel/sound/u_audio_mixer.h index e1c2a274e..b6016d079 100644 --- a/code/nel/include/nel/sound/u_audio_mixer.h +++ b/code/nel/include/nel/sound/u_audio_mixer.h @@ -20,6 +20,7 @@ #include "nel/misc/types_nl.h" #include "nel/misc/string_mapper.h" #include "nel/sound/u_source.h" +#include "nel/sound/u_group_controller.h" #include "nel/ligo/primitive.h" #include @@ -291,9 +292,9 @@ public: * pass a callback function that will be called (if not NULL) just before deleting the spawned * source. */ - virtual USource *createSource( const NLMISC::TStringId &name, bool spawn=false, TSpawnEndCallback cb=NULL, void *callbackUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context=0) = 0; + virtual USource *createSource(const NLMISC::TStringId &name, bool spawn=false, TSpawnEndCallback cb=NULL, void *callbackUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context = 0, UGroupController *groupController = NULL) = 0; /// Add a logical sound source (by sound id). To remove a source, just delete it. See createSource(const char*) - virtual USource *createSource( TSoundId id, bool spawn=false, TSpawnEndCallback cb=NULL, void *callbackUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context=0 ) = 0; + virtual USource *createSource(TSoundId id, bool spawn=false, TSpawnEndCallback cb=NULL, void *callbackUserParam = NULL, NL3D::CCluster *cluster = 0, CSoundContext *context = 0, UGroupController *groupController = NULL) = 0; /** Use this method to set the listener position instead of using getListener->setPos(); * It's because we have to update the background sounds in this case. diff --git a/code/nel/include/nel/sound/u_group_controller.h b/code/nel/include/nel/sound/u_group_controller.h new file mode 100644 index 000000000..0e8eeed47 --- /dev/null +++ b/code/nel/include/nel/sound/u_group_controller.h @@ -0,0 +1,63 @@ +/** + * \file u_group_controller.h + * \brief UGroupController + * \date 2012-04-10 12:49GMT + * \author Jan Boon (Kaetemi) + * UGroupController + */ + +/* + * 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 NLSOUND_U_GROUP_CONTROLLER_H +#define NLSOUND_U_GROUP_CONTROLLER_H +#include + +// STL includes + +// NeL includes + +// Project includes + +namespace NLSOUND { + +/** + * \brief UGroupController + * \date 2012-04-10 12:49GMT + * \author Jan Boon (Kaetemi) + * UGroupController + */ +class UGroupController +{ + virtual void setDevGain(float gain) = 0; + virtual float getDevGain() = 0; + + virtual void setUserGain(float gain) = 0; + virtual float getUserGain() = 0; + +protected: + virtual ~UGroupController(); + +}; /* class UGroupController */ + +} /* namespace NLSOUND */ + +#endif /* #ifndef NLSOUND_U_GROUP_CONTROLLER_H */ + +/* end of file */ diff --git a/code/nel/src/sound/audio_mixer_user.cpp b/code/nel/src/sound/audio_mixer_user.cpp index 367abd0e1..5ee4907c5 100644 --- a/code/nel/src/sound/audio_mixer_user.cpp +++ b/code/nel/src/sound/audio_mixer_user.cpp @@ -51,6 +51,7 @@ #include "nel/sound/sample_bank_manager.h" #include "nel/sound/sample_bank.h" #include "nel/sound/sound_bank.h" +#include "nel/sound/group_controller.h" using namespace std; using namespace NLMISC; @@ -1689,7 +1690,7 @@ void CAudioMixerUser::update() // _Tracks[i]->DrvSource->setPos(source->getPos() * (1-css->PosAlpha) + css->Position*(css->PosAlpha)); _Tracks[i]->getPhysicalSource()->setPos(source->getPos() * (1-css->PosAlpha) + vpos*(css->PosAlpha)); // update the relative gain - _Tracks[i]->getPhysicalSource()->setGain(source->getRelativeGain()*source->getGain()*css->Gain); + _Tracks[i]->getPhysicalSource()->setGain(source->getFinalGain() * css->Gain); #if EAX_AVAILABLE == 1 if (_UseEax) { @@ -1829,7 +1830,7 @@ bool CAudioMixerUser::tryToLoadSampleBank(const std::string &sampleName) // ****************************************************************** -USource *CAudioMixerUser::createSource( TSoundId id, bool spawn, TSpawnEndCallback cb, void *userParam, NL3D::CCluster *cluster, CSoundContext *context ) +USource *CAudioMixerUser::createSource( TSoundId id, bool spawn, TSpawnEndCallback cb, void *userParam, NL3D::CCluster *cluster, CSoundContext *context, UGroupController *groupController ) { #if NL_PROFILE_MIXER TTicks start = CTime::getPerformanceTime(); @@ -1915,7 +1916,7 @@ retrySound: } // Create source - CSimpleSource *source = new CSimpleSource( simpleSound, spawn, cb, userParam, cluster); + CSimpleSource *source = new CSimpleSource( simpleSound, spawn, cb, userParam, cluster, static_cast(groupController)); // nldebug("Mixer : source %p created", source); @@ -1939,28 +1940,28 @@ retrySound: { CStreamSound *streamSound = static_cast(id); // This is a stream thingy. - ret = new CStreamSource(streamSound, spawn, cb, userParam, cluster); + ret = new CStreamSource(streamSound, spawn, cb, userParam, cluster, static_cast(groupController)); } break; case CSound::SOUND_COMPLEX: { CComplexSound *complexSound = static_cast(id); // This is a pattern sound. - ret = new CComplexSource(complexSound, spawn, cb, userParam, cluster); + ret = new CComplexSource(complexSound, spawn, cb, userParam, cluster, static_cast(groupController)); } break; case CSound::SOUND_BACKGROUND: { // This is a background sound. CBackgroundSound *bgSound = static_cast(id); - ret = new CBackgroundSource(bgSound, spawn, cb, userParam, cluster); + ret = new CBackgroundSource(bgSound, spawn, cb, userParam, cluster, static_cast(groupController)); } break; case CSound::SOUND_MUSIC: { // This is a background music sound CMusicSound *music_sound= static_cast(id); - ret = new CMusicSource(music_sound, spawn, cb, userParam, cluster); + ret = new CMusicSource(music_sound, spawn, cb, userParam, cluster, static_cast(groupController)); } break; case CSound::SOUND_CONTEXT: @@ -1974,7 +1975,7 @@ retrySound: CSound *sound = ctxSound->getContextSound(*context); if (sound != 0) { - ret = createSource(sound, spawn, cb, userParam, cluster); + ret = createSource(sound, spawn, cb, userParam, cluster, NULL, static_cast(groupController)); // Set the volume of the source according to the context volume if (ret != 0) { @@ -2007,9 +2008,9 @@ retrySound: // ****************************************************************** -USource *CAudioMixerUser::createSource( const NLMISC::TStringId &name, bool spawn, TSpawnEndCallback cb, void *userParam, NL3D::CCluster *cluster, CSoundContext *context) +USource *CAudioMixerUser::createSource( const NLMISC::TStringId &name, bool spawn, TSpawnEndCallback cb, void *userParam, NL3D::CCluster *cluster, CSoundContext *context, UGroupController *groupController) { - return createSource( getSoundId( name ), spawn, cb, userParam, cluster, context); + return createSource( getSoundId( name ), spawn, cb, userParam, cluster, context, groupController); } diff --git a/code/nel/src/sound/background_source.cpp b/code/nel/src/sound/background_source.cpp index c2cb5206a..dbb14242a 100644 --- a/code/nel/src/sound/background_source.cpp +++ b/code/nel/src/sound/background_source.cpp @@ -26,8 +26,8 @@ namespace NLSOUND { -CBackgroundSource::CBackgroundSource(CBackgroundSound *backgroundSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster) -: CSourceCommon(backgroundSound, spawn, cb, cbUserParam, cluster) +CBackgroundSource::CBackgroundSource(CBackgroundSound *backgroundSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) +: CSourceCommon(backgroundSound, spawn, cb, cbUserParam, cluster, groupController) { _BackgroundSound = backgroundSound; } @@ -119,7 +119,7 @@ void CBackgroundSource::play() for (; first != last; ++first) { TSubSource subSource; - subSource.Source = mixer->createSource(first->SoundName, false, 0, 0, _Cluster, 0); + subSource.Source = mixer->createSource(first->SoundName, false, 0, 0, _Cluster, NULL, _GroupController); if (subSource.Source != NULL) subSource.Source->setPriority(_Priority); subSource.Filter = first->Filter; diff --git a/code/nel/src/sound/complex_source.cpp b/code/nel/src/sound/complex_source.cpp index cd3d2925d..8fad61a53 100644 --- a/code/nel/src/sound/complex_source.cpp +++ b/code/nel/src/sound/complex_source.cpp @@ -25,8 +25,8 @@ using namespace NLMISC; namespace NLSOUND { -CComplexSource::CComplexSource (CComplexSound *soundPattern, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster) -: CSourceCommon(soundPattern, spawn, cb, cbUserParam, cluster), +CComplexSource::CComplexSource (CComplexSound *soundPattern, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) +: CSourceCommon(soundPattern, spawn, cb, cbUserParam, cluster, groupController), _Source1(NULL), _Source2(NULL) { @@ -117,7 +117,7 @@ void CComplexSource::playStuf() else _FadeLength = 0; - _Source2 = mixer->createSource(sound, false, 0, 0, _Cluster); + _Source2 = mixer->createSource(sound, false, 0, 0, _Cluster, NULL, _GroupController); if (_Source2 == NULL) return; _Source2->setPriority(_Priority); @@ -155,7 +155,7 @@ void CComplexSource::playStuf() { CSound *sound = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++])); - _Source1 = mixer->createSource(sound, false, 0, 0, _Cluster); + _Source1 = mixer->createSource(sound, false, 0, 0, _Cluster, NULL, _GroupController); if (_Source1 == NULL) return; _Source1->setPriority(_Priority); @@ -202,7 +202,7 @@ void CComplexSource::playStuf() CSound *sound = mixer->getSoundId(*first); if (sound != NULL) { - USource *source = mixer->createSource(sound, false, 0, 0, _Cluster); + USource *source = mixer->createSource(sound, false, 0, 0, _Cluster, NULL, _GroupController); if (source != NULL) { source->setPriority(_Priority); @@ -512,7 +512,7 @@ void CComplexSource::onUpdate() // determine the XFade length (if next sound is too short. _FadeLength = minof(uint32(_PatternSound->getFadeLength()/_TickPerSecond), (sound2->getDuration()) / 2, (_Source1->getSound()->getDuration())/2); - _Source2 = mixer->createSource(sound2, false, 0, 0, _Cluster); + _Source2 = mixer->createSource(sound2, false, 0, 0, _Cluster, NULL, _GroupController); if (_Source2) { _Source2->setPriority(_Priority); @@ -641,7 +641,7 @@ void CComplexSource::onEvent() CSound *sound = mixer->getSoundId(_PatternSound->getSound(soundSeq[_SoundSeqIndex++])); - _Source1 = mixer->createSource(sound, false, 0, 0, _Cluster); + _Source1 = mixer->createSource(sound, false, 0, 0, _Cluster, NULL, _GroupController); if (_Source1 == NULL) { stop(); diff --git a/code/nel/src/sound/group_controller.cpp b/code/nel/src/sound/group_controller.cpp new file mode 100644 index 000000000..405be5d4e --- /dev/null +++ b/code/nel/src/sound/group_controller.cpp @@ -0,0 +1,112 @@ +/** + * \file group_controller.cpp + * \brief CGroupController + * \date 2012-04-10 09:29GMT + * \author Jan Boon (Kaetemi) + * CGroupController + */ + +/* + * 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 "stdsound.h" +#include + +// STL includes + +// NeL includes +// #include +#include + +// Project includes + +using namespace std; +// using namespace NLMISC; + +namespace NLSOUND { + +CGroupController::CGroupController(CGroupController *parent) : + m_Parent(parent), m_DevGain(1.0f), m_UserGain(1.0f), m_NbSourcesInclChild(0) +{ + +} + +CGroupController::~CGroupController() +{ + // If m_Sources is not empty, a crash is very likely. + nlassert(m_Sources.empty()); + + for (std::map::iterator it(m_Children.begin()), end(m_Children.end()); it != end; ++it) + { + delete it->second; + it->second = NULL; + } + m_Parent = NULL; +} + +void CGroupController::addSource(CSourceCommon *source) +{ + m_Sources.insert(source); + increaseSources(); +} + +void CGroupController::removeSource(CSourceCommon *source) +{ + decreaseSources(); + m_Sources.erase(source); +} + +void CGroupController::calculateFinalGain() // overridden by root +{ + m_FinalGain = calculateTotalGain() * m_Parent->getFinalGain(); +} + +void CGroupController::updateSourceGain() +{ + // Dont update source gain when this controller is inactive. + if (m_NbSourcesInclChild) + { + calculateFinalGain(); + for (CAudioMixerUser::TSourceContainer::iterator it(m_Sources.begin()), end(m_Sources.end()); it != end; ++it) + (*it)->updateFinalGain(); + for (std::map::iterator it(m_Children.begin()), end(m_Children.end()); it != end; ++it) + (*it).second->updateSourceGain(); + } +} + +void CGroupController::increaseSources() // overridden by root +{ + ++m_NbSourcesInclChild; + m_Parent->increaseSources(); + + // Update source gain when this controller was inactive before but the parent was active before. + // Thus, when this controller was the root of inactive controllers. + if (m_NbSourcesInclChild == 1 && m_Parent->m_NbSourcesInclChild > 1) + updateSourceGain(); +} + +void CGroupController::decreaseSources() // overridden by root +{ + --m_NbSourcesInclChild; + m_Parent->decreaseSources(); +} + +} /* namespace NLSOUND */ + +/* end of file */ diff --git a/code/nel/src/sound/group_controller_root.cpp b/code/nel/src/sound/group_controller_root.cpp new file mode 100644 index 000000000..c5305e061 --- /dev/null +++ b/code/nel/src/sound/group_controller_root.cpp @@ -0,0 +1,99 @@ +/** + * \file group_controller_root.cpp + * \brief CGroupControllerRoot + * \date 2012-04-10 09:44GMT + * \author Jan Boon (Kaetemi) + * CGroupControllerRoot + */ + +/* + * 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 "stdsound.h" +#include + +// STL includes + +// NeL includes +// #include +#include + +// Project includes + +using namespace std; +// using namespace NLMISC; + +namespace NLSOUND { + +CGroupControllerRoot::CGroupControllerRoot() : CGroupController(NULL) +{ + +} + +CGroupControllerRoot::~CGroupControllerRoot() +{ + +} + +void CGroupControllerRoot::calculateFinalGain() +{ + m_FinalGain = calculateTotalGain(); +} + +void CGroupController::increaseSources() +{ + ++m_NbSourcesInclChild; + + // Update source gain when this controller was inactive before. + if (m_NbSourcesInclChild == 1) + updateSourceGain(); +} + +void CGroupController::decreaseSources() +{ + --m_NbSourcesInclChild; +} + +CGroupController *CGroupControllerRoot::getGroupController(const std::string &path) +{ + std::vector pathNodes; + NLMISC::splitString(NLMISC::toLower(path), "/", pathNodes); + CGroupController *active = this; + for (std::vector::iterator it(pathNodes.begin()), end(pathNodes.end()); it != end; ++it) + { + if (!(*it).empty()) + { + std::map::iterator found = active->m_Children.find(*it); + if (found == active->m_Children.end()) + { + active = new CGroupController(active); + active->m_Parent->m_Children[*it] = active; + } + else + { + active = (*found).second; + } + } + } + return active; +} + +} /* namespace NLSOUND */ + +/* end of file */ diff --git a/code/nel/src/sound/music_source.cpp b/code/nel/src/sound/music_source.cpp index a47914dde..e5595d9f4 100644 --- a/code/nel/src/sound/music_source.cpp +++ b/code/nel/src/sound/music_source.cpp @@ -26,8 +26,8 @@ namespace NLSOUND { // *************************************************************************** -CMusicSource::CMusicSource(CMusicSound *musicSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster) - : CSourceCommon(musicSound, spawn, cb, cbUserParam, cluster) +CMusicSource::CMusicSource(CMusicSound *musicSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) + : CSourceCommon(musicSound, spawn, cb, cbUserParam, cluster, groupController) { _MusicSound= musicSound; } diff --git a/code/nel/src/sound/simple_source.cpp b/code/nel/src/sound/simple_source.cpp index fb0b7bc85..695619f91 100644 --- a/code/nel/src/sound/simple_source.cpp +++ b/code/nel/src/sound/simple_source.cpp @@ -28,8 +28,8 @@ using namespace NLMISC; namespace NLSOUND { -CSimpleSource::CSimpleSource(CSimpleSound *simpleSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster) - : CSourceCommon(simpleSound, spawn, cb, cbUserParam, cluster), +CSimpleSource::CSimpleSource(CSimpleSound *simpleSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) + : CSourceCommon(simpleSound, spawn, cb, cbUserParam, cluster, groupController), _SimpleSound(simpleSound), _Track(NULL), _PlayMuted(false) @@ -166,7 +166,7 @@ void CSimpleSource::play() setDirection(_Direction); // because there is a workaround inside pSource->setVelocity(_Velocity); } - pSource->setGain(_Gain); + pSource->setGain(getFinalGain()); pSource->setSourceRelativeMode(_RelativeMode); pSource->setLooping(_Looping); pSource->setPitch(_Pitch); @@ -312,36 +312,13 @@ void CSimpleSource::setDirection(const NLMISC::CVector& dir) } } - -/* Set the gain (volume value inside [0 , 1]). (default: 1) - * 0.0 -> silence - * 0.5 -> -6dB - * 1.0 -> no attenuation - * values > 1 (amplification) not supported by most drivers - */ -void CSimpleSource::setGain(float gain) +void CSimpleSource::updateFinalGain() { - CSourceCommon::setGain(gain); - // Set the gain if (hasPhysicalSource()) - { - getPhysicalSource()->setGain(gain); - } + getPhysicalSource()->setGain(getFinalGain()); } -void CSimpleSource::setRelativeGain(float gain) -{ - CSourceCommon::setRelativeGain(gain); - - // Set the gain - if (hasPhysicalSource()) - { - getPhysicalSource()->setGain(_Gain); - } -} - - /* Shift the frequency. 1.0f equals identity, each reduction of 50% equals a pitch shift * of one octave. 0 is not a legal value. */ diff --git a/code/nel/src/sound/source_common.cpp b/code/nel/src/sound/source_common.cpp index ce2b7e210..3af1eb6ae 100644 --- a/code/nel/src/sound/source_common.cpp +++ b/code/nel/src/sound/source_common.cpp @@ -25,7 +25,7 @@ using namespace NLMISC; namespace NLSOUND { -CSourceCommon::CSourceCommon(TSoundId id, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster) +CSourceCommon::CSourceCommon(TSoundId id, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) : _Priority(MidPri), _Playing(false), _Looping(false), @@ -41,9 +41,11 @@ CSourceCommon::CSourceCommon(TSoundId id, bool spawn, TSpawnEndCallback cb, void _SpawnEndCb(cb), _CbUserParam(cbUserParam), _Cluster(cluster), - _UserVarControler(id->getUserVarControler()) + _UserVarControler(id->getUserVarControler()), + _GroupController(groupController ? groupController : id->getGroupController()) { CAudioMixerUser::instance()->addSource(this); + groupController->addSource(this); // get a local copy of the sound parameter _InitialGain = _Gain = id->getGain(); @@ -51,11 +53,11 @@ CSourceCommon::CSourceCommon(TSoundId id, bool spawn, TSpawnEndCallback cb, void _Looping = id->getLooping(); _Priority = id->getPriority(); _Direction = id->getDirectionVector(); - } CSourceCommon::~CSourceCommon() { + _GroupController->removeSource(this); CAudioMixerUser::instance()->removeSource(this); } @@ -177,6 +179,7 @@ void CSourceCommon::setGain( float gain ) { clamp(gain, 0.0f, 1.0f); _InitialGain = _Gain = gain; + updateFinalGain(); } /* Set the gain amount (value inside [0, 1]) to map between 0 and the nominal gain @@ -185,8 +188,8 @@ void CSourceCommon::setGain( float gain ) void CSourceCommon::setRelativeGain( float gain ) { clamp(gain, 0.0f, 1.0f); - _Gain = _InitialGain * gain; + updateFinalGain(); } /* diff --git a/code/nel/src/sound/stream_source.cpp b/code/nel/src/sound/stream_source.cpp index a5b167c8f..2c3188454 100644 --- a/code/nel/src/sound/stream_source.cpp +++ b/code/nel/src/sound/stream_source.cpp @@ -28,8 +28,8 @@ using namespace NLMISC; namespace NLSOUND { -CStreamSource::CStreamSource(CStreamSound *streamSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster) - : CSourceCommon(streamSound, spawn, cb, cbUserParam, cluster), +CStreamSource::CStreamSource(CStreamSound *streamSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) + : CSourceCommon(streamSound, spawn, cb, cbUserParam, cluster, groupController), m_StreamSound(streamSound), m_Alpha(0.0f), m_Track(NULL), @@ -177,7 +177,7 @@ void CStreamSource::play() setDirection(_Direction); // because there is a workaround inside pSource->setVelocity(_Velocity); } - pSource->setGain(_Gain); + pSource->setGain(getFinalGain()); pSource->setSourceRelativeMode(_RelativeMode); // pSource->setLooping(_Looping); pSource->setPitch(_Pitch); @@ -294,22 +294,12 @@ void CStreamSource::setDirection(const NLMISC::CVector& dir) } } -void CStreamSource::setGain(float gain) +void CStreamSource::updateFinalGain() { CAutoMutex autoMutex(m_BufferMutex); - - CSourceCommon::setGain(gain); + if (hasPhysicalSource()) - getPhysicalSource()->setGain(gain); -} - -void CStreamSource::setRelativeGain(float gain) -{ - CAutoMutex autoMutex(m_BufferMutex); - - CSourceCommon::setRelativeGain(gain); - if (hasPhysicalSource()) - getPhysicalSource()->setGain(_Gain); + getPhysicalSource()->setGain(getFinalGain()); } void CStreamSource::setPitch(float pitch)