sound_bank.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdsound.h"
00025 
00026 #include "sound_bank.h"
00027 #include "simple_sound.h"
00028 #include "complex_sound.h"
00029 #include "context_sound.h"
00030 #include "background_sound.h"
00031 #include "music_sound.h"
00032 
00033 #include "nel/georges/u_form_loader.h"
00034 #include "nel/georges/u_form_elm.h"
00035 #include "nel/georges/u_form.h"
00036 #include "nel/misc/path.h"
00037 #include "driver/buffer.h"
00038 
00039 #include "nel/georges/load_form.h"
00040 
00041 #include <limits>
00042 
00043 using namespace std;
00044 using namespace NLMISC;
00045 using namespace NLGEORGES;
00046 
00047 
00048 namespace NLSOUND {
00049 
00050 CSoundBank      *CSoundBank::_Instance;
00051 
00052 
00053 
00054 CSoundBank  *CSoundBank::instance()
00055 {
00056     if (_Instance == 0)
00057         _Instance = new CSoundBank();
00058     return _Instance;
00059 }
00060 
00061 void CSoundBank::release()
00062 {
00063     if (_Instance != 0)
00064         delete _Instance;
00065     _Instance = 0;
00066 }
00067 
00068 
00069 void CSoundBank::bufferUnloaded(const NLMISC::TStringId  &bufferName)
00070 {
00071     TBufferAssocContainer::iterator it(_BufferAssoc.find(bufferName));
00072 
00073     if (it != _BufferAssoc.end())
00074     {
00075         // ok, found some sound associated with this buffer.
00076         // update all sounds.
00077         TSimpleSoundContainer::iterator first(it->second.begin()), last(it->second.end());
00078         for (; first != last; ++first)
00079         {
00080             // remove the associated buffer.
00081             CSimpleSound *ss = const_cast<CSimpleSound*>(*(first));
00082             ss->setBuffer(NULL);
00083         }
00084     }
00085 }
00086 
00087 //void CSoundBank::bufferLoaded(const std::string bufferName, IBuffer *buffer)
00088 void CSoundBank::bufferLoaded(const NLMISC::TStringId &/* bufferName */, IBuffer *buffer)
00089 {
00090 //  std::map<std::string, std::vector<TBufferAssoc> >::iterator it(_BufferAssoc.find(buffer->getName()));
00091     TBufferAssocContainer::iterator it(_BufferAssoc.find(buffer->getName()));
00092 
00093     if (it != _BufferAssoc.end())
00094     {
00095         // ok, found some sound associated with this buffer.
00096         // update all sounds.
00097         TSimpleSoundContainer::iterator first(it->second.begin()), last(it->second.end());
00098         for (; first != last; ++first)
00099         {
00100             CSimpleSound *ss = const_cast<CSimpleSound*>(*(it->second.begin()));
00101             // restore the associated buffer.
00102             ss->setBuffer(buffer);
00103         }
00104     }
00105 
00106 }
00107 
00108 void CSoundBank::registerBufferAssoc(CSimpleSound *sound, IBuffer *buffer)
00109 {
00110     if (buffer != NULL)
00111     {
00112         const NLMISC::TStringId &bufferName = buffer->getName();
00113         _BufferAssoc[bufferName].insert(sound);
00114     }
00115 }
00116 
00117 void CSoundBank::unregisterBufferAssoc(CSimpleSound *sound, IBuffer * buffer)
00118 {
00119     if (buffer != NULL)
00120     {
00121         const TStringId &bufferName = buffer->getName();
00122         TBufferAssocContainer::iterator it(_BufferAssoc.find(bufferName));
00123 
00124         if (it != _BufferAssoc.end())
00125         {
00126             TSimpleSoundContainer::iterator it2(it->second.find(sound));
00127 
00128             nlassert(it2 != it->second.end());
00129             it->second.erase(it2);
00130 
00131             if (it->second.empty())
00132             {
00133                 // last sound refenrecing this buffer
00134                 _BufferAssoc.erase(it);
00135             }
00136 
00137         }
00138     }
00139 }
00140 
00141 
00142 /*
00143  * Destructor
00144  */
00145 CSoundBank::~CSoundBank()
00146 {
00147     unload();
00148 }
00149 
00150 void CSoundBank::addSound(CSound *sound)
00151 {
00152     std::pair<TSoundTable::iterator, bool> ret;
00153     ret = _Sounds.insert(make_pair(sound->getName(), sound));
00154     nlassert(ret.second);
00155 }
00156 
00157 void CSoundBank::removeSound(const NLMISC::TStringId &name)
00158 {
00159     _Sounds.erase(name);
00160 }
00161 
00162 
00169 class CSoundSerializer
00170 {
00171 public:
00173     CSound *Sound;
00174 
00176     CSoundSerializer()
00177         : Sound(0)
00178     {}
00179 
00180     // load the values using the george sheet (called by GEORGE::loadForm)
00181     void readGeorges (const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const std::string &name)
00182     {
00183         // just call the sound creation method with the xml form.
00184         Sound = CSound::createSound(name, form->getRootNode());
00185 
00186         // success ?
00187 //      if (_Sound != 0)
00188 //          CSoundBank::instance()->addSound(_Sound);
00189     }
00190 
00191     // load/save the values using the serial system (called by GEORGE::loadForm)
00192     void serial (NLMISC::IStream &s)
00193     {
00194         if (s.isReading())
00195         {
00196             // read the first item to find the type
00197             CSound::TSOUND_TYPE type = CSound::SOUND_SIMPLE;
00198             s.serialEnum(type);
00199             // read the sound name
00200 //          std::string name;
00201 //          s.serial(name);
00202 
00203             // Instantiate the corresponding sound.
00204             switch(CSound::TSOUND_TYPE(type))
00205             {
00206             case CSound::SOUND_SIMPLE:
00207                 Sound = new CSimpleSound();
00208                 break;
00209             case CSound::SOUND_COMPLEX:
00210                 Sound = new CComplexSound();
00211                 break;
00212             case CSound::SOUND_CONTEXT:
00213                 Sound = new CContextSound();
00214                 break;
00215             case CSound::SOUND_BACKGROUND:
00216                 Sound = new CBackgroundSound();
00217                 break;
00218             case CSound::SOUND_MUSIC:
00219                 Sound = new CMusicSound();
00220                 break;
00221             default:
00222                 Sound = 0;
00223             }
00224 
00225 //          nlassert(_Sound != 0);
00226             if (Sound)
00227             {
00228                 // read the sound data
00229                 Sound->serial(s);
00230 //              CSoundBank::instance()->addSound(_Sound);
00231             }
00232         }
00233         else
00234         {
00235             if (Sound == 0)
00236             {
00237                 // the sound doesn't exist
00238                 uint32 i = std::numeric_limits<uint32>::max();
00239                 s.serialEnum(i);
00240 //              s.serial(std::string("bad sound"));
00241             }
00242             else
00243             {
00244                 // write the sound type.
00245                 CSound::TSOUND_TYPE type = Sound->getSoundType();
00246                 s.serialEnum(type);
00247                 // write the sound name
00248 //              s.serial(const_cast<std::string&>(_Sound->getName()));
00249 
00250                 // and write the sound data
00251                 Sound->serial(s);
00252             }
00253         }
00254     }
00255 
00259     void removed()
00260     {
00261         if (Sound != 0)
00262         {
00263             // we remove the sound from the bank and delete it.
00264 //          CSoundBank::instance()->removeSound(_Sound->getName());
00265             delete Sound;
00266         }
00267     }
00268 
00269     // return the version of this class, increments this value when the content of this class changed
00270     static uint getVersion () { return 3; }
00271 };
00272 
00273 
00278 void                CSoundBank::load()
00279 {
00280     // this structure is fill by the loadForm() function and will contain all you need
00281     std::map<std::string, CSoundSerializer> Container;
00282     nlassert(!_Loaded);
00283     // Just call the GEORGE::loadFrom method to read all available sounds
00284 	::loadForm("sound", CAudioMixerUser::instance()->getPackedSheetPath()+"sounds.packed_sheets", Container, CAudioMixerUser::instance()->getPackedSheetUpdate(), false);
00285     _Loaded = true;
00286 
00287     // add all the loaded sound in the sound banks
00288     std::map<std::string, CSoundSerializer>::iterator first(Container.begin()), last(Container.end());
00289     for (; first != last; ++first)
00290     {
00291         if (first->second.Sound != 0)
00292             addSound(first->second.Sound);
00293     }
00294 
00295     Container.clear();
00296 }
00297 
00298 
00299 /*
00300  * Unload all the sound samples in this bank.
00301  */
00302 void                CSoundBank::unload()
00303 {
00304     nlassert(_Loaded);
00305 
00306     TSoundTable::iterator first(_Sounds.begin()), last(_Sounds.end());
00307     for (; first != last; ++first)
00308     {
00309         delete first->second;
00310     }
00311 
00312     _Sounds.clear();
00313     _Loaded = false;
00314 
00315 /*  vector<CSound*> vec;
00316 
00317 
00318     TSoundTable::iterator map_iter;
00319 
00320     for (map_iter = _Sounds.begin(); map_iter != _Sounds.end(); ++map_iter)
00321     {
00322         // We can't delete directly second because the map is based on second->getName()
00323         vec.push_back( (*map_iter).second );
00324     }
00325 
00326     _Sounds.clear();
00327 
00328     vector<CSound*>::iterator vec_iter;
00329 
00330     for (vec_iter = vec.begin(); vec_iter != vec.end(); ++vec_iter)
00331     {
00332         CSound *sound = *vec_iter;
00333         delete sound;
00334     }
00335 
00336     _Loaded = false;
00337 */
00338 }
00339 
00340 /*
00341  * Returns true if the samples in this bank have been loaded.
00342  */
00343 bool                CSoundBank::isLoaded()
00344 {
00345     return _Loaded;
00346 }
00347 
00348 /*
00349  * Return a sound sample corresponding to a name.
00350  */
00351 CSound*         CSoundBank::getSound(const NLMISC::TStringId &name)
00352 {
00353     // Find sound
00354     TSoundTable::iterator iter = _Sounds.find(name);
00355     if ( iter == _Sounds.end() )
00356     {
00357         return 0;
00358     }
00359     else
00360     {
00361         return (*iter).second;
00362     }
00363 }
00364 
00368 void                CSoundBank::getNames( std::vector<NLMISC::TStringId> &names )
00369 {
00370     TSoundTable::const_iterator iter;
00371     for (iter = _Sounds.begin(); iter != _Sounds.end(); ++iter)
00372     {
00373         names.push_back((*iter).first);
00374         //nlwarning("getting sound %s", (*iter).first);
00375     }
00376 }
00377 
00378 /*
00379  * Return the number of buffers in this bank.
00380  */
00381 uint                CSoundBank::countSounds()
00382 {
00383     return _Sounds.size();
00384 }
00385 
00386 
00387 } // namespace NLSOUND
00388 

Generated on Thu Jan 7 08:26:38 2010 for NeL by  doxygen 1.6.1