diff --git a/code/nel/include/nel/sound/audio_mixer_user.h b/code/nel/include/nel/sound/audio_mixer_user.h index eded75fc6..c060edd48 100644 --- a/code/nel/include/nel/sound/audio_mixer_user.h +++ b/code/nel/include/nel/sound/audio_mixer_user.h @@ -34,6 +34,14 @@ #include "nel/sound/mixing_track.h" #include "nel/sound/sound.h" #include "nel/sound/music_channel_fader.h" +#include "nel/sound/group_controller_root.h" + +// Current version is 2, Ryzom Live uses 1 +// Provided to allow compatibility with old binary files +#define NLSOUND_SHEET_VERSION_BUILT 1 +#define NLSOUND_SHEET_V1_DEFAULT_SOUND_GROUP_CONTROLLER "effects" +#define NLSOUND_SHEET_V1_DEFAULT_SOUND_MUSIC_GROUP_CONTROLLER "music" +#define NLSOUND_SHEET_V1_DEFAULT_SOUND_STREAM_GROUP_CONTROLLER "dialog" namespace NLLIGO { class CLigoConfig; @@ -51,26 +59,6 @@ namespace NLSOUND { class CMusicSoundManager; class IReverbEffect; -/// Hasher functor for hashed container with pointer key. -template -struct THashPtr : public std::unary_function -{ - static const size_t bucket_size = 4; - static const size_t min_buckets = 8; - size_t operator () (const Pointer &ptr) const - { - //CHashSet::hasher h; - // transtype the pointer into int then hash it - //return h.operator()(uint(uintptr_t(ptr))); - return (size_t)(uintptr_t)ptr; - } - inline bool operator() (const Pointer &ptr1, const Pointer &ptr2) const - { - // delegate the work to someone else as well? - return (uintptr_t)ptr1 < (uintptr_t)ptr2; - } -}; - /** * Implementation of UAudioMixer * @@ -197,6 +185,9 @@ public: /// Get a TSoundId from a name (returns NULL if not found) virtual TSoundId getSoundId( const NLMISC::TStringId &name ); + /// Gets the group controller for the given group tree path with separator '/', if it doesn't exist yet it will be created. + /// Examples: "music", "effects", "dialog", "music/background", "music/loading", "music/player", etcetera + virtual UGroupController *getGroupController(const std::string &path); /** Add a logical sound source (returns NULL if name not found). * If spawn is true, the source will auto-delete after playing. If so, the return USource* pointer @@ -431,9 +422,6 @@ 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; @@ -566,6 +554,9 @@ private: // Instance of the background music manager CMusicSoundManager *_BackgroundMusicManager; + /// Group controller + CGroupControllerRoot _GroupController; + public: struct TSampleBankHeader { diff --git a/code/nel/include/nel/sound/containers.h b/code/nel/include/nel/sound/containers.h new file mode 100644 index 000000000..bd4fe7fb9 --- /dev/null +++ b/code/nel/include/nel/sound/containers.h @@ -0,0 +1,67 @@ +/** + * \file containers.h + * \brief CContainers + * \date 2012-04-10 13:57GMT + * \author Unknown (Unknown) + * CContainers + */ + +/* + * 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_CONTAINERS_H +#define NLSOUND_CONTAINERS_H +#include + +// STL includes + +// NeL includes + +// Project includes + +namespace NLSOUND { + class CSourceCommon; + +/// Hasher functor for hashed container with pointer key. +template +struct THashPtr : public std::unary_function +{ + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + size_t operator () (const Pointer &ptr) const + { + //CHashSet::hasher h; + // transtype the pointer into int then hash it + //return h.operator()(uint(uintptr_t(ptr))); + return (size_t)(uintptr_t)ptr; + } + inline bool operator() (const Pointer &ptr1, const Pointer &ptr2) const + { + // delegate the work to someone else as well? + return (uintptr_t)ptr1 < (uintptr_t)ptr2; + } +}; + +typedef CHashSet > TSourceContainer; + +} /* namespace NLSOUND */ + +#endif /* #ifndef NLSOUND_CONTAINERS_H */ + +/* end of file */ diff --git a/code/nel/include/nel/sound/group_controller.h b/code/nel/include/nel/sound/group_controller.h index 4c443a52d..d93fb8683 100644 --- a/code/nel/include/nel/sound/group_controller.h +++ b/code/nel/include/nel/sound/group_controller.h @@ -35,13 +35,12 @@ // NeL includes #include -#include #include +#include // Project includes namespace NLSOUND { - class CSourceCommon; class CGroupControllerRoot; /** @@ -64,7 +63,7 @@ private: float m_FinalGain; int m_NbSourcesInclChild; - CAudioMixerUser::TSourceContainer m_Sources; + TSourceContainer m_Sources; public: CGroupController(CGroupController *parent); @@ -83,8 +82,12 @@ public: void addSource(CSourceCommon *source); void removeSource(CSourceCommon *source); -private: + virtual std::string getPath(); + +protected: virtual ~CGroupController(); // subnodes can only be deleted by the root + +private: inline float calculateTotalGain() { return m_DevGain * m_UserGain; } virtual void calculateFinalGain(); virtual void increaseSources(); diff --git a/code/nel/include/nel/sound/group_controller_root.h b/code/nel/include/nel/sound/group_controller_root.h index 82c3af849..5d47ff50a 100644 --- a/code/nel/include/nel/sound/group_controller_root.h +++ b/code/nel/include/nel/sound/group_controller_root.h @@ -54,6 +54,7 @@ public: CGroupController *getGroupController(const std::string &path); protected: + virtual std::string getPath(); virtual void calculateFinalGain(); virtual void increaseSources(); virtual void decreaseSources(); diff --git a/code/nel/include/nel/sound/sound.h b/code/nel/include/nel/sound/sound.h index ef0e62f72..7d7542fc9 100644 --- a/code/nel/include/nel/sound/sound.h +++ b/code/nel/include/nel/sound/sound.h @@ -105,7 +105,7 @@ public: /// Return the max distance (if detailed()) virtual float getMaxDistance() const { return _MaxDist; } - inline CGroupController *getGroupController() const { return NULL; } // TODO, RETURN THE GROUP CONTROLLER + inline CGroupController *getGroupController() const { return _GroupController; } /// Set looping void setLooping( bool looping ) { _Looping = looping; } @@ -145,6 +145,9 @@ protected: /// An optional user var controler. NLMISC::TStringId _UserVarControler; + /// The group controller, always exists, owned by the audio mixer + CGroupController *_GroupController; + }; diff --git a/code/nel/include/nel/sound/u_audio_mixer.h b/code/nel/include/nel/sound/u_audio_mixer.h index b6016d079..c4702c3f8 100644 --- a/code/nel/include/nel/sound/u_audio_mixer.h +++ b/code/nel/include/nel/sound/u_audio_mixer.h @@ -286,6 +286,10 @@ public: /// Get a TSoundId from a name (returns NULL if not found) virtual TSoundId getSoundId( const NLMISC::TStringId &name ) = 0; + /// Gets the group controller for the given group tree path with separator '/', if it doesn't exist yet it will be created. + /// Examples: "music", "effects", "dialog", "music/background", "music/loading", "music/player", etcetera + virtual UGroupController *getGroupController(const std::string &path) = 0; + /** Add a logical sound source (returns NULL if name not found). * If spawn is true, the source will auto-delete after playing. If so, the return USource* pointer * is valid only before the time when calling play() plus the duration of the sound. You can diff --git a/code/nel/include/nel/sound/u_group_controller.h b/code/nel/include/nel/sound/u_group_controller.h index 0e8eeed47..a74e9da73 100644 --- a/code/nel/include/nel/sound/u_group_controller.h +++ b/code/nel/include/nel/sound/u_group_controller.h @@ -52,7 +52,7 @@ class UGroupController virtual float getUserGain() = 0; protected: - virtual ~UGroupController(); + virtual ~UGroupController() { } }; /* class UGroupController */ diff --git a/code/nel/src/sound/audio_mixer_user.cpp b/code/nel/src/sound/audio_mixer_user.cpp index 5ee4907c5..e03b1ae00 100644 --- a/code/nel/src/sound/audio_mixer_user.cpp +++ b/code/nel/src/sound/audio_mixer_user.cpp @@ -52,6 +52,7 @@ #include "nel/sound/sample_bank.h" #include "nel/sound/sound_bank.h" #include "nel/sound/group_controller.h" +#include "nel/sound/containers.h" using namespace std; using namespace NLMISC; @@ -1827,6 +1828,10 @@ bool CAudioMixerUser::tryToLoadSampleBank(const std::string &sampleName) } } +UGroupController *CAudioMixerUser::getGroupController(const std::string &path) +{ + return static_cast(_GroupController.getGroupController(path)); +} // ****************************************************************** diff --git a/code/nel/src/sound/group_controller.cpp b/code/nel/src/sound/group_controller.cpp index 405be5d4e..86f46301e 100644 --- a/code/nel/src/sound/group_controller.cpp +++ b/code/nel/src/sound/group_controller.cpp @@ -72,6 +72,22 @@ void CGroupController::removeSource(CSourceCommon *source) m_Sources.erase(source); } +std::string CGroupController::getPath() // overridden by root +{ + for (std::map::iterator it(m_Parent->m_Children.begin()), end(m_Parent->m_Children.end()); it != end; ++it) + { + if (it->second == this) + { + const std::string &name = it->first; + std::string returnPath = m_Parent->getPath() + "/" + name; + if (returnPath[0] == '/') + returnPath = returnPath.substr(1); + return returnPath; + } + } + +} + void CGroupController::calculateFinalGain() // overridden by root { m_FinalGain = calculateTotalGain() * m_Parent->getFinalGain(); @@ -83,7 +99,7 @@ void CGroupController::updateSourceGain() if (m_NbSourcesInclChild) { calculateFinalGain(); - for (CAudioMixerUser::TSourceContainer::iterator it(m_Sources.begin()), end(m_Sources.end()); it != end; ++it) + for (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(); diff --git a/code/nel/src/sound/group_controller_root.cpp b/code/nel/src/sound/group_controller_root.cpp index c5305e061..f49a40fff 100644 --- a/code/nel/src/sound/group_controller_root.cpp +++ b/code/nel/src/sound/group_controller_root.cpp @@ -51,12 +51,17 @@ CGroupControllerRoot::~CGroupControllerRoot() } +std::string CGroupControllerRoot::getPath() +{ + return ""; +} + void CGroupControllerRoot::calculateFinalGain() { m_FinalGain = calculateTotalGain(); } -void CGroupController::increaseSources() +void CGroupControllerRoot::increaseSources() { ++m_NbSourcesInclChild; @@ -65,7 +70,7 @@ void CGroupController::increaseSources() updateSourceGain(); } -void CGroupController::decreaseSources() +void CGroupControllerRoot::decreaseSources() { --m_NbSourcesInclChild; } diff --git a/code/nel/src/sound/music_sound.cpp b/code/nel/src/sound/music_sound.cpp index 2b192c3c6..f95edfb26 100644 --- a/code/nel/src/sound/music_sound.cpp +++ b/code/nel/src/sound/music_sound.cpp @@ -20,6 +20,9 @@ #include "nel/misc/path.h" #include "nel/georges/u_form_elm.h" +#if NLSOUND_SHEET_VERSION_BUILT < 2 +# include "nel/sound/audio_mixer_user.h" +#endif using namespace std; using namespace NLMISC; @@ -72,6 +75,10 @@ void CMusicSound::importForm(const std::string& filename, NLGEORGES::UFormElm& root.getValueByName(_MinimumPlayTime, ".SoundType.MinimumPlayTime"); root.getValueByName(_TimeBeforeCanReplay, ".SoundType.TimeBeforeCanReplay"); +#if NLSOUND_SHEET_VERSION_BUILT < 2 + _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(NLSOUND_SHEET_V1_DEFAULT_SOUND_MUSIC_GROUP_CONTROLLER)); +#endif + } // *************************************************************************** @@ -97,6 +104,11 @@ void CMusicSound::serial(NLMISC::IStream &s) CStringMapper::serialString(s, _FileName); s.serial(_FadeInLength, _FadeOutLength); s.serial(_MinimumPlayTime, _TimeBeforeCanReplay); + +#if NLSOUND_SHEET_VERSION_BUILT < 2 + if (s.isReading()) _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(NLSOUND_SHEET_V1_DEFAULT_SOUND_MUSIC_GROUP_CONTROLLER)); +#endif + } // *************************************************************************** diff --git a/code/nel/src/sound/sound.cpp b/code/nel/src/sound/sound.cpp index eed318cca..a943fa543 100644 --- a/code/nel/src/sound/sound.cpp +++ b/code/nel/src/sound/sound.cpp @@ -27,6 +27,8 @@ #include "nel/sound/music_sound.h" #include "nel/sound/stream_sound.h" +#include "nel/sound/group_controller.h" + using namespace std; using namespace NLMISC; @@ -134,6 +136,23 @@ void CSound::serial(NLMISC::IStream &s) std::string name = CStringMapper::unmap(_Name); s.serial(name); } + + nlassert(CAudioMixerUser::instance()); // not sure +#if NLSOUND_SHEET_VERSION_BUILT < 2 + if (s.isReading()) _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(NLSOUND_SHEET_V1_DEFAULT_SOUND_GROUP_CONTROLLER)); +#else + if (s.isReading()) + { + std::string groupControllerPath; + s.serial(groupControllerPath); + _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(groupControllerPath)); + } + else + { + std::string groupControllerPath = _GroupController->getPath(); + s.serial(groupControllerPath); + } +#endif } @@ -225,6 +244,15 @@ void CSound::importForm(const std::string& filename, NLGEORGES::UFormElm& roo default: _Priority = MidPri; } + +#if NLSOUND_SHEET_VERSION_BUILT < 2 + _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(NLSOUND_SHEET_V1_DEFAULT_SOUND_GROUP_CONTROLLER)); +#else + std::string groupControllerPath; + root.getValueByName(groupControllerPath, ".GroupControllerPath"); + _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(groupControllerPath)); +#endif + } diff --git a/code/nel/src/sound/stream_sound.cpp b/code/nel/src/sound/stream_sound.cpp index 347fae987..7addbbe0a 100644 --- a/code/nel/src/sound/stream_sound.cpp +++ b/code/nel/src/sound/stream_sound.cpp @@ -17,6 +17,10 @@ #include "stdsound.h" #include "nel/sound/stream_sound.h" +#if NLSOUND_SHEET_VERSION_BUILT < 2 +# include "nel/sound/audio_mixer_user.h" +#endif + namespace NLSOUND { CStreamSound::CStreamSound() @@ -51,6 +55,11 @@ void CStreamSound::importForm(const std::string &filename, NLGEORGES::UFormElm & // Alpha root.getValueByName(m_Alpha, ".SoundType.Alpha"); + +#if NLSOUND_SHEET_VERSION_BUILT < 2 + _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(NLSOUND_SHEET_V1_DEFAULT_SOUND_STREAM_GROUP_CONTROLLER)); +#endif + } void CStreamSound::serial(NLMISC::IStream &s) @@ -59,6 +68,11 @@ void CStreamSound::serial(NLMISC::IStream &s) s.serial(_MinDist); s.serial(m_Alpha); + +#if NLSOUND_SHEET_VERSION_BUILT < 2 + if (s.isReading()) _GroupController = static_cast(CAudioMixerUser::instance()->getGroupController(NLSOUND_SHEET_V1_DEFAULT_SOUND_STREAM_GROUP_CONTROLLER)); +#endif + } } /* namespace NLSOUND */