# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

context_sound.h

Go to the documentation of this file.
00001 
00006 /* Copyright, 2001 Nevrax Ltd.
00007  *
00008  * This file is part of NEVRAX NEL.
00009  * NEVRAX NEL is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2, or (at your option)
00012  * any later version.
00013 
00014  * NEVRAX NEL is distributed in the hope that it will be useful, but
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00017  * General Public License for more details.
00018 
00019  * You should have received a copy of the GNU General Public License
00020  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00021  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00022  * MA 02111-1307, USA.
00023  */
00024 
00025 #ifndef NL_CONTEXT_SOUND_H
00026 #define NL_CONTEXT_SOUND_H
00027 
00028 #include "sound.h"
00029 #include <hash_map>
00030 #include <nel/misc/fast_mem.h>
00031 
00032 namespace NLSOUND {
00033 
00034 class ISoundDriver;
00035 class IBuffer;
00036 class CSound;
00037 
00038 
00039 template <uint NbJoker, bool UseRandom, uint Shift = 5>
00040 struct CContextMatcher
00041 {
00042         CContextMatcher(uint32 *jokersValues, uint32 randomValue)
00043                 : HashValue(0)
00044         {
00045                 for (uint i=0; i<NbJoker; ++i)
00046                 {
00047                         JokersValues[i] = jokersValues[i];
00048                         
00049                         uint leftShift = (5*i)&0x1f;
00050                         HashValue ^= JokersValues[i] << leftShift;
00051                         HashValue ^= JokersValues[i] >> (32-leftShift);
00052                 }
00053                 if (UseRandom)
00054                 {
00055                         RandomValue = randomValue;
00056                         uint leftShift = (5*i)&0x1f;
00057                         HashValue ^= randomValue << leftShift;
00058                         HashValue ^= randomValue >> (32-leftShift);
00059                 }
00060                 else
00061                         RandomValue = 0;
00062         }
00063 
00064         bool operator ==(const CContextMatcher &other) const
00065         {
00066                 if (HashValue != other.HashValue)
00067                         return false;
00068                 else if (UseRandom)
00069                         return RandomValue == other.RandomValue && memcmp(JokersValues, other.JokersValues, sizeof(uint32)*NbJoker) == 0;
00070                 else
00071                         return memcmp(JokersValues, other.JokersValues, sizeof(uint32)*NbJoker) == 0;
00072         }
00073 
00074         size_t getHashValue() const
00075         {
00076                 return size_t(HashValue);
00077         }
00078 
00079         uint32  HashValue;
00080         uint32  JokersValues[NbJoker];
00081         uint32  RandomValue;
00082 
00083         struct CHash : public std::unary_function<CContextMatcher, size_t>
00084         {
00085                 size_t operator () (const CContextMatcher &patternMatcher) const
00086                 {
00087                         return patternMatcher.getHashValue();
00088                 }
00089         };
00090 
00091 };
00092 
00093 
00094 class IContextSoundContainer
00095 {
00096 public:
00097         virtual                         ~IContextSoundContainer() {};
00098         virtual void            init(uint *contextArgsIndex) =0;
00099         virtual void            addSound(CSound *sound, const std::string &baseName) =0;
00100         virtual CSound          *getSound(const CSoundContext &context, uint32 randomValue) =0;
00101         virtual void            getSoundList(std::vector<std::pair<std::string, CSound*> > &subsounds) const =0;
00102 };
00103 
00104 template <uint NbJoker, bool UseRandom, uint Shift = 5>
00105 class CContextSoundContainer : public IContextSoundContainer
00106 {
00107 
00108         typedef std::hash_map<CContextMatcher<NbJoker, UseRandom, Shift>, CSound *, CContextMatcher<NbJoker, UseRandom, Shift>::CHash>  THashContextSound;
00109 
00110         virtual void            init(uint *contextArgsIndex)
00111         {
00112                 NLMISC::CFastMem::memcpy(_ContextArgsIndex, contextArgsIndex, sizeof(uint) * NbJoker);
00113         }
00114 
00115         virtual void            addSound(CSound *sound, const std::string &baseName)
00116         {
00117                 const std::string &patternName = sound->getName();
00118                 nlassert(patternName.size() >= baseName.size());
00119 
00120                 std::string arg;
00121                 uint32          args[NbJoker];
00122 
00123                 // extract the context values
00124                 std::string::const_iterator     first(patternName.begin() + baseName.size()), last(patternName.end());
00125 //              std::string::const_iterator     first2(baseName.begin()), last2(baseName.end());
00126                 // 1st, skip the base name 
00127 //              for (; first == first2; ++first, ++first2);
00128 
00129                 // 2nd, read all the joker values
00130                 for (uint i=0; i<NbJoker && first != last; ++first)
00131                 {
00132                         if (isdigit(int(*first)))
00133                         {
00134                                 arg += *first;
00135                         }
00136                         else if (!arg.empty())
00137                         {
00138                                 // end of the argument.
00139                                 args[i++] = atoi(arg.c_str());
00140                                 arg = "";
00141                         }
00142                 }
00143                 // read the potential last arg.
00144                 if (!arg.empty())
00145                 {
00146                         // end of the argument.
00147                         args[i++] = atoi(arg.c_str());
00148                         arg = "";
00149                 }
00150 
00151                 if (i != NbJoker)
00152                         return;
00153                 nlassert(i==NbJoker);
00154 
00155                 int randomValue;
00156                 if (UseRandom)
00157                 {
00158                         bool ok = false;
00159                         // 3rd, read the random value (if any)
00160                         for (uint i=0; first != last; ++first)
00161                         {
00162                                 if (isdigit(int(*first)))
00163                                 {
00164                                         arg += *first;
00165                                 }
00166                                 else if (!arg.empty())
00167                                 {
00168                                         nlassert (ok == false);
00169                                         // end of the argument.
00170                                         randomValue = atoi(arg.c_str());
00171                                         arg = "";
00172                                         ok = true;
00173                                 }
00174                         }
00175                         // read the potential last arg.
00176                         if (!arg.empty())
00177                         {
00178                                 nlassert (ok == false);
00179                                 // end of the argument.
00180                                 randomValue = atoi(arg.c_str());
00181                                 arg = "";
00182                                 ok = true;
00183                         }
00184                         nlassert (ok == true);
00185 
00186                 }
00187                 else
00188                 {
00189                         randomValue = 0;
00190                 }
00191                         
00192                 // ok, now create the key and storea the sound.
00193                 CContextMatcher<NbJoker, UseRandom, Shift>      cm(args, randomValue);
00194 
00195 #ifdef _DEBUG
00196                 char tmp[1024];
00197                 char tmp2[1024];
00198 
00199                 smprintf(tmp, 1024, "Adding sound : %s, args = ", patternName.c_str());
00200 
00201                 for (uint k=0; k<NbJoker; ++k)
00202                 {
00203                         sprintf(tmp2, "%u", args[k]);
00204                         strcat(tmp, tmp2);
00205                 }
00206 
00207                 nldebug(tmp);
00208 
00209 #endif
00210 
00211                 std::pair<THashContextSound::iterator, bool>    ret;
00212                 ret = _ContextSounds.insert(std::make_pair(cm, sound));
00213                 if (!ret.second)
00214                 {
00215                         THashContextSound::iterator it = _ContextSounds.find(cm);
00216                         nlassert(it != _ContextSounds.end());
00217 
00218                         nlwarning("Sound %s has the same context matcher as the sound %s", sound->getName().c_str(), it->second->getName().c_str());
00219                 }
00220         }
00221 
00222         virtual CSound          *getSound(const CSoundContext &context, uint32 randomValue)
00223         {
00224                 // create a key
00225                 uint32          args[NbJoker];
00226                 for (uint i=0; i<NbJoker; ++i)
00227                         args[i] = context.Args[_ContextArgsIndex[i]];
00228 
00229                 CContextMatcher<NbJoker, UseRandom, Shift>      cm(args, randomValue);
00230 
00231                 THashContextSound::iterator it = _ContextSounds.find(cm);
00232 
00233                 if (it != _ContextSounds.end())
00234                         return it->second;
00235                 else
00236                         return 0;
00237         }
00238 
00239         void getSoundList(std::vector<std::pair<std::string, CSound*> > &subsounds) const
00240         {
00241                 THashContextSound::const_iterator first(_ContextSounds.begin()), last(_ContextSounds.end());
00242                 for (; first != last; ++first)
00243                 {
00244                         subsounds.push_back(std::make_pair(first->second->getName(), first->second));
00245                 }
00246         }
00247 
00248 private:
00249         uint32                          _ContextArgsIndex[NbJoker];
00250         THashContextSound       _ContextSounds;
00251 };
00252 
00253 class CContextSound : public CSound
00254 {
00255 public:
00257         CContextSound();
00259         ~CContextSound();
00260 
00261 
00262         TSOUND_TYPE                     getSoundType()                                  { return CSound::SOUND_CONTEXT; };
00263 
00265         virtual void            importForm(const std::string& filename, NLGEORGES::UFormElm& formRoot);
00266 
00268         virtual bool            isDetailed() const;
00270         virtual uint32          getDuration();
00272         virtual void            getSubSoundList(std::vector<std::pair<std::string, CSound*> > &subsounds) const;
00273 
00274 
00275         CSound                          *getContextSound(CSoundContext &context);
00276 
00277         void                            init();
00278 
00279         void                            serial(NLMISC::IStream &s);
00280 
00281 
00282 private:
00283         
00285         std::string                                     _PatternName;
00287         std::string                                     _BaseName;
00288 
00290         uint32                                          _Random;
00291 
00292         
00293 
00295         IContextSoundContainer          *_ContextSounds;
00296         
00297 };
00298 
00299 } // NLSOUND
00300 
00301 #endif //NL_CONTEXT_SOUND_H