From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/a06346.html | 628 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 628 insertions(+) create mode 100644 docs/doxygen/nel/a06346.html (limited to 'docs/doxygen/nel/a06346.html') diff --git a/docs/doxygen/nel/a06346.html b/docs/doxygen/nel/a06346.html new file mode 100644 index 00000000..62e499dd --- /dev/null +++ b/docs/doxygen/nel/a06346.html @@ -0,0 +1,628 @@ + + +NeL: sample_bank.cpp Source File + + + +
+

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 "nel/misc/file.h"
+00033 #include "async_file_manager_sound.h"
+00034 #include "background_sound_manager.h"
+00035 #include "sound_bank.h"
+00036 
+00037 
+00038 using namespace std;
+00039 using namespace NLMISC;
+00040 
+00041 
+00042 namespace NLSOUND {
+00043 
+00045 uint32          ASYNC_LOADING_SPLIT = 10;               // 10 file by 10 file
+00046 
+00047 CSampleBank::TSampleBankContainer       CSampleBank::_Banks;
+00048 uint    CSampleBank::_LoadedSize = 0;
+00049 
+00050 CSampleBank::TVirtualBankCont           CSampleBank::_VirtualBanks;
+00051 
+00052 
+00053 
+00054 
+00055 void                            CSampleBank::init(NLGEORGES::UFormElm *mixerConfig)
+00056 {
+00057         NL_ALLOC_CONTEXT(NLSOUND_CSampleBank);
+00058         if (mixerConfig == 0)
+00059                 return;
+00060 
+00061         NLGEORGES::UFormElm     *virtualBanks;
+00062         mixerConfig->getNodeByName(&virtualBanks, ".VirtualBanks");
+00063         if (virtualBanks == 0)
+00064                 return;
+00065 
+00066         uint size;
+00067         virtualBanks->getArraySize(size);
+00068 
+00069         for (uint i=0; i<size; ++i)
+00070         {
+00071                 NLGEORGES::UFormElm     *virtualBank;
+00072                 virtualBanks->getArrayNode(&virtualBank, i);
+00073 
+00074                 if (virtualBank != 0)
+00075                 {
+00076                         std::vector<TFilteredBank> vfb;
+00077                         std::string virtualName;
+00078                         virtualBank->getValueByName(virtualName, ".VirtualName");
+00079                         NLGEORGES::UFormElm     *realBanks;
+00080                         virtualBank->getNodeByName(&realBanks, ".FilteredBank");
+00081                         if (realBanks != 0)
+00082                         {
+00083                                 uint size2;
+00084                                 realBanks->getArraySize(size2);
+00085 
+00086                                 for (uint j=0; j<size2; ++j)
+00087                                 {
+00088                                         TFilteredBank fb;
+00089                                         std::string     bankName;
+00090                                         NLGEORGES::UFormElm     *realBank;
+00091                                         realBank->getArrayNode(&realBank, j);
+00092 
+00093                                         realBank->getValueByName(bankName, ".SampleBank");
+00094                                         fb.BankName = CStringMapper::map(bankName);
+00095                                         realBank->getValueByName(fb.Filter, ".Filter");
+00096 
+00097                                         vfb.push_back(fb);
+00098                                 }
+00099                         }
+00100 
+00101                         if (!vfb.empty())
+00102                         {
+00103                                 _VirtualBanks.insert(std::make_pair(NLMISC::CStringMapper::map(virtualName), vfb));
+00104                                 // create the sample bank
+00105                                 new CSampleBank(virtualName, NULL);
+00106                         }
+00107                 }
+00108         }
+00109 }
+00110 
+00111 
+00112 
+00113 
+00114 // ********************************************************
+00115 CSampleBank *CSampleBank::findSampleBank(const NLMISC::TStringId &filename)
+00116 {
+00117         TSampleBankContainer::iterator  it(_Banks.find(filename));
+00118 
+00119         if (it != _Banks.end())
+00120                 return it->second;
+00121 
+00122         return NULL;
+00123 }
+00124 
+00125 // ********************************************************
+00126 
+00127 IBuffer*                CSampleBank::get(const NLMISC::TStringId &name)
+00128 {
+00129         IBuffer* buffer;
+00130         TSampleBankContainer::iterator iter;
+00131 
+00132         for (iter = _Banks.begin(); iter != _Banks.end(); ++iter)
+00133         {
+00134                 buffer = iter->second->getSample(name);
+00135                 if (buffer != 0)
+00136                 {
+00137                         return buffer;
+00138                 }
+00139         }
+00140         
+00141         //nlwarning ("Try to get an unknown sample '%s'", name);
+00142         return 0;
+00143 }
+00144 
+00145 void     CSampleBank::reload(bool async)
+00146 {
+00147         TSampleBankContainer::iterator first(_Banks.begin()), last(_Banks.end());
+00148 
+00149         for (; first != last; ++first)
+00150         {
+00151                 first->second->unload();
+00152                 first->second->load(async);
+00153         }
+00154 }
+00155 
+00156 
+00157 void CSampleBank::getLoadedSampleBankInfo(std::vector<std::pair<std::string, uint> > &result)
+00158 {
+00159         result.clear();
+00160 
+00161         TSampleBankContainer::iterator first(_Banks.begin()), last(_Banks.end());
+00162         for (; first != last; ++first)
+00163         {
+00164                 std::pair<std::string, uint> p;
+00165                 if (first->second->isLoaded())
+00166                 {
+00167                         p.first = NLMISC::CStringMapper::unmap(first->first);
+00168                         p.second = first->second->getSize();
+00169                         result.push_back(p);
+00170                 }
+00171         }
+00172 }
+00173 
+00174 
+00175 
+00176 
+00177 
+00178 // ********************************************************
+00179 
+00180 CSampleBank::CSampleBank(const std::string& name, ISoundDriver *sd) 
+00181 : _SoundDriver(sd), _Name(CStringMapper::map(name)), _Loaded(false), _LoadingDone(true), _ByteSize(0)
+00182 {
+00183 //      _Name = CFile::getFilenameWithoutExtension(_Path);
+00184         _Banks.insert(make_pair(_Name, this));
+00185 }
+00186 
+00187 
+00188 // ********************************************************
+00189 
+00190 CSampleBank::~CSampleBank()
+00191 {
+00192         CAudioMixerUser::instance()->unregisterUpdate(this);
+00193         while (!_LoadingDone)
+00194         {
+00195                 // need to wait for loading end.
+00196                 nlSleep(100);
+00197         }
+00198 
+00199         if (_Loaded)
+00200                 unload();
+00201 
+00202         // remove the bank from the list of known banks
+00203         TSampleBankContainer::iterator iter(_Banks.begin()), end(_Banks.end());
+00204 
+00205         for (; iter != end; ++iter)
+00206         {
+00207                 if (iter->second == this)
+00208                 {
+00209                         _Banks.erase(iter);
+00210                         break;
+00211                 }
+00212         }
+00213 
+00214 
+00215         // delete all the samples.
+00216         while (!_Samples.empty())
+00217         {
+00218                 delete _Samples.begin()->second;
+00219                 _Samples.erase(_Samples.begin());
+00220         }
+00221 
+00222         _Samples.clear();
+00223 }
+00224 
+00225 
+00226 // ********************************************************
+00227 
+00228 void                            CSampleBank::load(bool async)
+00229 {
+00230         // TODO : add async loading support !
+00231 
+00232         TVirtualBankCont::iterator it(_VirtualBanks.find(_Name));
+00233         if (it != _VirtualBanks.end())
+00234         {
+00235                 // this is a virtual sample bank !
+00236                 nlinfo("Loading virtual sample bank %s", CStringMapper::unmap(_Name).c_str());
+00237 
+00238                 CAudioMixerUser *mixer = CAudioMixerUser::instance();
+00239                 const CAudioMixerUser::TBackgroundFlags &flags = mixer->getBackgroundFlags();
+00240 
+00241                 for (uint i=0; i<it->second.size(); ++i)
+00242                 {
+00243                         if (flags.Flags[it->second[i].Filter])
+00244                         {
+00245                                 CSampleBank *bank = findSampleBank(it->second[i].BankName);
+00246                                 if (bank)
+00247                                         bank->load(async);
+00248                         }
+00249                 }
+00250         }
+00251 
+00252         nlinfo("Loading sample bank %s %", CStringMapper::unmap(_Name).c_str(), async?"":"Asynchronously");
+00253 
+00254         vector<string> filenames;
+00255 //      vector<string>::iterator iter;
+00256 
+00257         if (_Loaded)
+00258         {
+00259                 nlwarning("Trying to load an already loaded bank : %s", CStringMapper::unmap(_Name).c_str ());
+00260                 return;
+00261         }
+00262 
+00263 
+00264         // Load the sample bank from the builded sample_bank file.
+00265         string bankName(CStringMapper::unmap(_Name)+".sample_bank");
+00266         string filename = CPath::lookup(bankName);
+00267         if (filename.empty())
+00268         {
+00269                 nlwarning("Trying to load an unknown sample bank [%s]", bankName.c_str());
+00270                 return;
+00271         }
+00272 
+00273         try
+00274         {
+00275 
+00276                 CIFile  sampleBank(filename);
+00277 
+00278                 CAudioMixerUser::TSampleBankHeader sbh;
+00279                 sampleBank.serial(sbh);
+00280                 _LoadingDone = false;
+00281 
+00282                 sint32 seekStart = sampleBank.getPos();
+00283 
+00284 
+00285                 uint8   *data = 0;
+00286                 uint    i;
+00287                 for (i=0; i<sbh.Name.size(); ++i)
+00288                 {
+00289                         IBuffer *ibuffer = _SoundDriver->createBuffer();
+00290                         nlassert(ibuffer);
+00291 
+00292                         TStringId       nameId = CStringMapper::map(CFile::getFilenameWithoutExtension(sbh.Name[i]));
+00293                         ibuffer->presetName(nameId);
+00294                         
+00295         /*              {
+00296                                 sint16 *data16 = new sint16[sbh.NbSample[i]];
+00297                                 IBuffer::TADPCMState    state;
+00298                                 state.PreviousSample = 0;
+00299                                 state.StepIndex = 0;
+00300                                 uint count =0;
+00301                                 for (count=0; count+1024<sbh.NbSample[i]; count+=1024)
+00302                                 {
+00303                                         IBuffer::decodeADPCM(data+count/2, data16+count, 1024, state);
+00304                                 }
+00305                                 IBuffer::decodeADPCM(data+count/2, data16+count, sbh.NbSample[i]-count, state);
+00306 
+00307                                 state.PreviousSample = 0;
+00308                                 state.StepIndex = 0;
+00309                                 sint16  *data16_2 = new sint16[sbh.NbSample[i]];
+00310                                 IBuffer::decodeADPCM(data, data16_2, sbh.NbSample[i], state);
+00311 
+00312                                 for (uint j=0; j<sbh.NbSample[i]; ++j)
+00313                                 {
+00314                                         if (data16[j] != data16_2[j])
+00315                                         {
+00316                                                 nlwarning("Sample differ at %u", j);
+00317                                         }
+00318                                 }
+00319 
+00320                                 _SoundDriver->readRawBuffer(ibuffer, sbh.Name[i], (uint8*)data16, sbh.NbSample[i]*2, Mono16, sbh.Freq[i]);
+00321                                 delete [] data16;
+00322                                 delete [] data16_2;
+00323                         }
+00324         */
+00325 
+00326                         if (CAudioMixerUser::instance()->useAPDCM())
+00327                         {
+00328                                 data = (uint8*) realloc(data, sbh.SizeAdpcm[i]);
+00329                                 sampleBank.seek(seekStart + sbh.OffsetAdpcm[i], CIFile::begin);
+00330                                 sampleBank.serialBuffer(data, sbh.SizeAdpcm[i]);
+00331                                 _SoundDriver->readRawBuffer(ibuffer, sbh.Name[i], data, sbh.SizeAdpcm[i], Mono16ADPCM, sbh.Freq[i]);
+00332                         }
+00333                         else
+00334                         {
+00335                                 data = (uint8*) realloc(data, sbh.SizeMono16[i]);
+00336                                 sampleBank.seek(seekStart + sbh.OffsetMono16[i], CIFile::begin);
+00337                                 sampleBank.serialBuffer(data, sbh.SizeMono16[i]);
+00338                                 _SoundDriver->readRawBuffer(ibuffer, sbh.Name[i], data, sbh.SizeMono16[i], Mono16, sbh.Freq[i]);
+00339                         }
+00340                         
+00341                         _ByteSize += ibuffer->getSize();
+00342 
+00343                         _Samples[nameId] = ibuffer;
+00344 
+00345                         // Warn the sound bank that the sample are available.
+00346                         CSoundBank::instance()->bufferLoaded(nameId, ibuffer);
+00347                 }
+00348                 free(data);
+00349 
+00350                 _LoadedSize += _ByteSize;
+00351         }
+00352         catch(Exception &e)
+00353         {
+00354                 // loading failed !
+00355                 nlwarning("Exception %s during loading of sample bank %s", e.what(), filename.c_str());
+00356                 CAudioMixerUser *mixer = CAudioMixerUser::instance();
+00357 
+00358                 if (mixer->getPackedSheetUpdate())
+00359                 {
+00360                         nlinfo("Deleting offending sound bank, you need to restart to recreate it!");
+00361                         CFile::deleteFile(filename);
+00362                 }
+00363         }
+00364 
+00365         _Loaded = true;
+00366         _LoadingDone = true;
+00367 
+00368 
+00369 
+00371 /*
+00372 
+00373         std::string list = CPath::lookup(CStringMapper::unmap(_Name)+CAudioMixerUser::SampleBankListExt, false);
+00374         if (list.empty())
+00375         {
+00376                 nlwarning("File %s not found to load sample bank %s", (CStringMapper::unmap(_Name)+CAudioMixerUser::SampleBankListExt).c_str(), CStringMapper::unmap(_Name).c_str());
+00377                 return;
+00378         }
+00379 
+00380 
+00381         NLMISC::CIFile sampleBankList(list);
+00382         sampleBankList.serialCont(filenames);
+00383 
+00384         for (iter = filenames.begin(); iter != filenames.end(); iter++)
+00385         {
+00386                 IBuffer* ibuffer = NULL;
+00387                 try
+00388                 {
+00389                         ibuffer = _SoundDriver->createBuffer();
+00390                         nlassert(ibuffer);
+00391 
+00392 //                      std::string sampleName(CFile::getFilenameWithoutExtension(*iter));
+00393                         NLMISC::TStringId sampleName(CStringMapper::map(CFile::getFilenameWithoutExtension(*iter)));
+00394 
+00395                         if (async)
+00396                         {
+00397                                 ibuffer->presetName(sampleName);
+00398                                 nldebug("Preloading sample [%s]", CStringMapper::unmap(sampleName).c_str());
+00399                         }
+00400                         else
+00401                         {
+00402                                 std::string fullName = NLMISC::CPath::lookup(*iter, false);
+00403                                 if (!fullName.empty())
+00404                                 {
+00405                                         NLMISC::CIFile  ifile(fullName);
+00406                                         uint size = ifile.getFileSize();
+00407                                         uint8 *buffer = new uint8[ifile.getFileSize()];
+00408                                         ifile.serialBuffer(buffer, size);
+00409 
+00410                                         _SoundDriver->readWavBuffer(ibuffer, fullName, buffer, size);
+00411                                         _ByteSize += ibuffer->getSize();
+00412 
+00413                                         delete [] buffer;
+00414                                 }
+00415                         }
+00416                         _Samples[sampleName] = ibuffer ;
+00417 
+00418                         // Warn the sound bank that the sample are available.
+00419                         CSoundBank::instance()->bufferLoaded(sampleName, ibuffer);
+00420                 }
+00421                 catch (ESoundDriver &e)
+00422                 {
+00423                         if (ibuffer != NULL) {
+00424                                 delete ibuffer;
+00425                                 ibuffer = NULL;
+00426                         }
+00427                         nlwarning("Problem with file '%s': %s", (*iter).c_str(), e.what());
+00428                 }
+00429         }
+00430 
+00431         _Loaded = true;
+00432 
+00433         if (!async)
+00434         {
+00435                 _LoadingDone = true;
+00436                 // compute the sample bank size.
+00437                 _LoadedSize += _ByteSize;
+00438         }
+00439         else
+00440         {
+00441                 // fill the loading list.
+00442                 TSampleTable::iterator first(_Samples.begin()), last(_Samples.end());
+00443                 for (; first != last; ++first)
+00444                 {
+00445                         _LoadList.push_back(make_pair(first->second, first->first));
+00446                 }
+00447                 _SplitLoadDone = false;
+00448                 // send the first files
+00449                 for (uint i=0; i<ASYNC_LOADING_SPLIT && !_LoadList.empty(); ++i)
+00450                 {
+00451                         CAsyncFileManagerSound::getInstance().loadWavFile(_LoadList.front().first, CStringMapper::unmap(_LoadList.front().second)+".wav");
+00452                         _LoadList.pop_front();
+00453                 }
+00454                 // add a end loading event...
+00455                 CAsyncFileManagerSound::getInstance().signal(&_SplitLoadDone);
+00456                 // and register for update on the mixer
+00457                 CAudioMixerUser::instance()->registerUpdate(this);
+00458         }
+00459         */
+00460 }
+00461 
+00462 void CSampleBank::onUpdate()
+00463 {
+00464         if (_SplitLoadDone)
+00465         {
+00466                 nldebug("Some samples have been loaded");
+00467                 if (_LoadList.empty())
+00468                 {
+00469                         // all the samples are loaded, we can compute the bank size.
+00470                         TSampleTable::iterator  first(_Samples.begin()), last(_Samples.end());
+00471                         for (; first != last; ++first)
+00472                         {
+00473                                 _ByteSize += first->second->getSize();
+00474                         }
+00475                 
+00476                         _LoadedSize += _ByteSize;
+00477 
+00478                         // stop the update.
+00479                         CAudioMixerUser::instance()->unregisterUpdate(this);
+00480                         _LoadingDone = true;
+00481 
+00482                         // Force an update in the background manager (can restar stoped sound).
+00483                         CAudioMixerUser::instance()->getBackgroundSoundManager()->updateBackgroundStatus();
+00484 
+00485                         nlinfo("Sample bank %s loaded.", CStringMapper::unmap(_Name).c_str());
+00486                 }
+00487                 else
+00488                 {
+00489                         _SplitLoadDone = false;
+00490                         for (uint i=0; i<ASYNC_LOADING_SPLIT && !_LoadList.empty(); ++i)
+00491                         {
+00492                                 CAsyncFileManagerSound::getInstance().loadWavFile(_LoadList.front().first, CStringMapper::unmap(_LoadList.front().second)+".wav");
+00493                                 _LoadList.pop_front();
+00494                         }
+00495                         // add a end loading event...
+00496                         CAsyncFileManagerSound::getInstance().signal(&_SplitLoadDone);
+00497                 }
+00498         }
+00499 }
+00500 
+00501 // ********************************************************
+00502 
+00503 bool                            CSampleBank::unload()
+00504 {
+00505         vector<IBuffer*> vec;
+00506         TSampleTable::iterator it;
+00507 
+00508         if (!_Loaded)
+00509         {
+00510                 nlwarning("Trying to unload an already unloaded bank : %s", CStringMapper::unmap(_Name).c_str ());
+00511                 return  true;
+00512         }
+00513 
+00514         // need to wait end of load ?
+00515         if (!_LoadingDone)
+00516                 return false;
+00517 
+00518         nlinfo("Unloading sample bank %s", CStringMapper::unmap(_Name).c_str());
+00519 
+00520         for (it = _Samples.begin(); it != _Samples.end(); ++it)
+00521         {
+00522                 IBuffer *buffer = it->second;
+00523                 if (buffer)
+00524                 {
+00525                         const NLMISC::TStringId & bufferName = buffer->getName();
+00526 
+00527                         // Warn the mixer to stop any track playing this buffer.
+00528                         CAudioMixerUser::instance()->bufferUnloaded(buffer);
+00529                         // Warn the sound banks abount this buffer.
+00530                         CSoundBank::instance()->bufferUnloaded(bufferName);
+00531 
+00532                         // delete
+00533                         it->second = NULL;
+00534                         delete buffer;
+00535                 }
+00536         }
+00537 
+00538         _Loaded = false;
+00539 
+00540         _LoadedSize -= _ByteSize;
+00541         _ByteSize = 0;
+00542 
+00543         return true;
+00544 }
+00545 
+00546 // ********************************************************
+00547 
+00548 bool                            CSampleBank::isLoaded()
+00549 {
+00550         return _Loaded;
+00551 }
+00552 
+00553 // ********************************************************
+00554 
+00555 IBuffer*                        CSampleBank::getSample(const NLMISC::TStringId &name)
+00556 {
+00557         {
+00558 /*              // dump the sample list.
+00559                 TSampleTable::iterator it (_Samples.begin()), last(_Samples.end());
+00560                 std::string s;
+00561 
+00562 //              while (first != last)
+00563                 for (it = _Samples.begin(); it != _Samples.end(); ++it)
+00564                 {
+00565                         s += std::string(" [")+it->first+"] ";
+00566                         //first++;
+00567                 }
+00568 
+00569                 nldebug("getSample(%s) : sample list = [%s]", name, s.c_str());
+00570 */
+00571         }
+00572 
+00573         // Find sound
+00574         TSampleTable::iterator iter = _Samples.find(name);
+00575         if ( iter == _Samples.end() )
+00576         {
+00577                 return 0;
+00578         }
+00579         else
+00580         {
+00581                 return (*iter).second;
+00582         }
+00583 }
+00584 
+00585 // ********************************************************
+00586 
+00587 uint                            CSampleBank::countSamples()
+00588 {
+00589         return _Samples.size();
+00590 }
+00591 
+00592 // ********************************************************
+00593 
+00594 uint                            CSampleBank::getSize()
+00595 {
+00596         uint size = 0;
+00597 
+00598         TSampleTable::const_iterator iter;
+00599         for (iter = _Samples.begin(); iter != _Samples.end(); iter++)
+00600         {
+00601                 size += (*iter).second->getSize();
+00602         }
+00603 
+00604         return size;
+00605 }
+00606 
+00607 void                            CSampleBank::releaseAll()
+00608 {
+00609         nldebug( "SampleBanks: Releasing..." );
+00610 
+00611         while (!_Banks.empty())
+00612         {
+00613                 delete _Banks.begin()->second;
+00614         }
+00615         nldebug( "SampleBanks: Released" );
+00616 }
+00617 
+00618 
+00619 
+00620 } // namespace NLSOUND
+00621 
+

Generated on Tue Mar 16 06:35:55 2004 for NeL by + +doxygen +1.3.6
+ + -- cgit v1.2.1