# 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  

sample_bank.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdsound.h"
00027 
00028 #include "sample_bank.h"
00029 #include "driver/sound_driver.h"
00030 #include "driver/buffer.h"
00031 #include "nel/misc/path.h"
00032 #include "async_file_manager_sound.h"
00033 #include "sound_bank.h"
00034 
00035 //#include <crtdbg.h>
00036 
00037 using namespace std;
00038 using namespace NLMISC;
00039 
00040 
00041 namespace NLSOUND {
00042 
00044 uint32          ASYNC_LOADING_SPLIT = 10;               // 10 file by 10 file
00045 
00046 CSampleBank::TSampleBankContainer CSampleBank::_Banks;
00047 uint    CSampleBank::_LoadedSize = 0;
00048 
00049 
00050 
00051 // ********************************************************
00052 CSampleBank *CSampleBank::findSampleBank(const std::string &filename)
00053 {
00054         TSampleBankContainer::iterator  it(_Banks.find(filename));
00055 
00056         if (it != _Banks.end())
00057                 return it->second;
00058 
00059         return NULL;
00060 }
00061 
00062 // ********************************************************
00063 
00064 IBuffer*                CSampleBank::get(const std::string &name)
00065 {
00066         IBuffer* buffer;
00067         TSampleBankContainer::iterator iter;
00068 
00069         for (iter = _Banks.begin(); iter != _Banks.end(); ++iter)
00070         {
00071                 buffer = iter->second->getSample(name);
00072                 if (buffer != 0)
00073                 {
00074                         return buffer;
00075                 }
00076         }
00077         
00078         //nlwarning ("Try to get an unknown sample '%s'", name);
00079         return 0;
00080 }
00081 
00082 void     CSampleBank::reload(bool async)
00083 {
00084         TSampleBankContainer::iterator first(_Banks.begin()), last(_Banks.end());
00085 
00086         for (; first != last; ++first)
00087         {
00088                 first->second->unload();
00089                 first->second->load(async);
00090         }
00091 }
00092 
00093 
00094 
00095 // ********************************************************
00096 
00097 CSampleBank::CSampleBank(const std::string& path, ISoundDriver *sd) 
00098         : _SoundDriver(sd), _Path(path), _Loaded(false), _LoadingDone(true), _ByteSize(0)
00099 {
00100 //_CrtCheckMemory();
00101         _Name = CFile::getFilenameWithoutExtension(_Path);
00102         _Banks.insert(make_pair(path, this));
00103 //_CrtCheckMemory();
00104 }
00105 
00106 
00107 // ********************************************************
00108 
00109 CSampleBank::~CSampleBank()
00110 {
00111 //_CrtCheckMemory();
00112         while (!_LoadingDone)
00113         {
00114                 // need to wait for loading end.
00115                 nlSleep(100);
00116         }
00117 //_CrtCheckMemory();
00118 
00119         // remove the bank from the list of known banks
00120         TSampleBankContainer::iterator iter(_Banks.begin()), end(_Banks.end());
00121 //_CrtCheckMemory();
00122 
00123         for (; iter != end; ++iter)
00124         {
00125                 if (iter->second == this)
00126                 {
00127                         _Banks.erase(iter);
00128                         break;
00129                 }
00130         }
00131 //_CrtCheckMemory();
00132 
00133 
00134         // delete all the samples.
00135         while (!_Samples.empty())
00136         {
00137 //_CrtCheckMemory();
00138                 delete _Samples.begin()->second;
00139                 _Samples.erase(_Samples.begin());
00140 //_CrtCheckMemory();
00141         }
00142 }
00143 
00144 
00145 // ********************************************************
00146 
00147 void                            CSampleBank::load(bool async)
00148 {
00149         nldebug("Loading sample bank %s %", _Name.c_str(), async?"":"Asynchronously");
00150 
00151         vector<string> filenames;
00152         vector<string>::iterator iter;
00153 
00154         if (_Loaded)
00155         {
00156                 nlwarning("Trying to load an already loaded bank : %s", _Path);
00157                 return;
00158         }
00159 
00160         _LoadingDone = false;
00161 
00162         CPath::getPathContent(_Path, true, false, true, filenames);
00163 
00164         for (iter = filenames.begin(); iter != filenames.end(); iter++)
00165         {
00166                 IBuffer* buffer = NULL;
00167                 try
00168                 {
00169                         buffer = _SoundDriver->createBuffer();
00170                         nlassert(buffer);
00171 
00172                         std::string sampleName(CFile::getFilenameWithoutExtension(*iter));
00173 
00174                         if (async)
00175                         {
00176                                 buffer->presetName(sampleName);
00177                                 nldebug("Preloading sample [%s]", sampleName.c_str());
00178                         }
00179                         else
00180                         {
00181                                 _SoundDriver->loadWavFile(buffer, (*iter).c_str());
00182                                 _ByteSize += buffer->getSize();
00183                         }
00184                         _Samples[sampleName] = buffer ;
00185 
00186                         // Warn the sound bank that the sample are available.
00187                         CSoundBank::instance()->bufferLoaded(sampleName, buffer);
00188                 }
00189                 catch (ESoundDriver &e)
00190                 {
00191                         if (buffer != NULL) {
00192                                 delete buffer;
00193                                 buffer = NULL;
00194                         }
00195                         nlwarning("Problem with file '%s': %s", (*iter).c_str(), e.what());
00196                 }
00197         }
00198 
00199         _Loaded = true;
00200 
00201         if (!async)
00202         {
00203                 _LoadingDone = true;
00204                 // compute the sample bank size.
00205                 _LoadedSize += _ByteSize;
00206         }
00207         else
00208         {
00209                 // fill the loading list.
00210                 TSampleTable::iterator first(_Samples.begin()), last(_Samples.end());
00211                 for (; first != last; ++first)
00212                 {
00213                         _LoadList.push_back(make_pair(first->second, first->first));
00214                 }
00215                 _SplitLoadDone = false;
00216                 // send the first files
00217                 for (uint i=0; i<ASYNC_LOADING_SPLIT && !_LoadList.empty(); ++i)
00218                 {
00219                         CAsyncFileManagerSound::getInstance().loadWavFile(_LoadList.front().first, _Path+"/"+_LoadList.front().second+".wav");
00220                         _LoadList.pop_front();
00221                 }
00222                 // add a end loading event...
00223                 CAsyncFileManagerSound::getInstance().signal(&_SplitLoadDone);
00224                 // and register for update on the mixer
00225                 CAudioMixerUser::instance()->registerUpdate(this);
00226         }
00227 //_CrtCheckMemory();
00228 }
00229 
00230 void CSampleBank::onUpdate()
00231 {
00232 //_CrtCheckMemory();
00233         if (_SplitLoadDone)
00234         {
00235                 nldebug("Some samples have been loaded");
00236                 if (_LoadList.empty())
00237                 {
00238                         // all the samples are loaded, we can compute the bank size.
00239                         TSampleTable::iterator  first(_Samples.begin()), last(_Samples.end());
00240                         for (; first != last; ++first)
00241                         {
00242                                 _ByteSize += first->second->getSize();
00243                         }
00244                 
00245                         _LoadedSize += _ByteSize;
00246 
00247                         // stop the update.
00248                         CAudioMixerUser::instance()->unregisterUpdate(this);
00249                         _LoadingDone = true;
00250 
00251                         // Force an update in the background manager (can restar stoped sound).
00252                         CAudioMixerUser::instance()->getBackgroundSoundManager()->updateBackgroundStatus();
00253 
00254                         nldebug("Sample bank %s loaded.", _Name.c_str());
00255                 }
00256                 else
00257                 {
00258                         _SplitLoadDone = false;
00259                         for (uint i=0; i<ASYNC_LOADING_SPLIT && !_LoadList.empty(); ++i)
00260                         {
00261                                 CAsyncFileManagerSound::getInstance().loadWavFile(_LoadList.front().first, _Path+"/"+_LoadList.front().second+".wav");
00262                                 _LoadList.pop_front();
00263                         }
00264                         // add a end loading event...
00265                         CAsyncFileManagerSound::getInstance().signal(&_SplitLoadDone);
00266                 }
00267         }
00268 //_CrtCheckMemory();
00269 }
00270 
00271 // ********************************************************
00272 
00273 bool                            CSampleBank::unload()
00274 {
00275 //_CrtCheckMemory();
00276         vector<IBuffer*> vec;
00277         TSampleTable::iterator it;
00278 
00279         if (!_Loaded)
00280         {
00281                 nlwarning("Trying to unload an already unloaded bank : %s", _Path);
00282         }
00283 
00284         // need to wait end of load ?
00285         if (!_LoadingDone)
00286                 return false;
00287 
00288         nldebug("Unloading sample bank %s", _Name.c_str());
00289 
00290         for (it = _Samples.begin(); it != _Samples.end(); ++it)
00291         {
00292                 IBuffer *buffer = it->second;
00293                 if (buffer)
00294                 {
00295                         const std::string & bufferName = buffer->getName();
00296 
00297                         // Warn the mixer to stop any track playing this buffer.
00298                         CAudioMixerUser::instance()->bufferUnloaded(buffer);
00299                         // Warn the sound banks abount this buffer.
00300                         CSoundBank::instance()->bufferUnloaded(bufferName);
00301 
00302                         // delete
00303                         it->second = NULL;
00304                         delete buffer;
00305                 }
00306         }
00307 //_CrtCheckMemory();
00308 
00309         _Loaded = false;
00310 
00311         _LoadedSize -= _ByteSize;
00312         _ByteSize = 0;
00313 
00314         return true;
00315 }
00316 
00317 // ********************************************************
00318 
00319 bool                            CSampleBank::isLoaded()
00320 {
00321         return _Loaded;
00322 }
00323 
00324 // ********************************************************
00325 
00326 IBuffer*                        CSampleBank::getSample(const std::string &name)
00327 {
00328         {
00329 /*              // dump the sample list.
00330                 TSampleTable::iterator it (_Samples.begin()), last(_Samples.end());
00331                 std::string s;
00332 
00333 //              while (first != last)
00334                 for (it = _Samples.begin(); it != _Samples.end(); ++it)
00335                 {
00336                         s += std::string(" [")+it->first+"] ";
00337                         //first++;
00338                 }
00339 
00340                 nldebug("getSample(%s) : sample list = [%s]", name, s.c_str());
00341 */
00342         }
00343 
00344         // Find sound
00345         TSampleTable::iterator iter = _Samples.find(name);
00346         if ( iter == _Samples.end() )
00347         {
00348                 return 0;
00349         }
00350         else
00351         {
00352                 return (*iter).second;
00353         }
00354 }
00355 
00356 // ********************************************************
00357 
00358 uint                            CSampleBank::countSamples()
00359 {
00360         return _Samples.size();
00361 }
00362 
00363 // ********************************************************
00364 
00365 uint                            CSampleBank::getSize()
00366 {
00367         uint size = 0;
00368 
00369         TSampleTable::const_iterator iter;
00370         for (iter = _Samples.begin(); iter != _Samples.end(); iter++)
00371         {
00372                 size += (*iter).second->getSize();
00373         }
00374 
00375         return size;
00376 }
00377 
00378 void                            CSampleBank::releaseAll()
00379 {
00380         nldebug( "SampleBanks: Releasing..." );
00381 
00382         while (!_Banks.empty())
00383         {
00384 //_CrtCheckMemory();
00385                 delete _Banks.begin()->second;
00386 //_CrtCheckMemory();
00387         }
00388         nldebug( "SampleBanks: Released" );
00389 }
00390 
00391 
00392 
00393 } // namespace NLSOUND
00394