background_sound_manager.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 
00025 #include "stdsound.h"
00026 
00027 #include "nel/misc/file.h"
00028 #include "nel/misc/i_xml.h"
00029 #include "nel/misc/path.h"
00030 #include "nel/misc/hierarchical_timer.h"
00031 
00032 #include "nel/ligo/primitive.h"
00033 #include "nel/3d/cluster.h"
00034 
00035 #include "nel/sound/u_source.h"
00036 #include "clustered_sound.h"
00037 #include "sample_bank.h"
00038 
00039 #include "background_sound_manager.h"
00040 #include "source_common.h"
00041 #include "clustered_sound.h"
00042 #include <algorithm>
00043 #include "background_source.h"
00044 #include <list>
00045 
00046 using namespace std;
00047 using namespace NLMISC;
00048 using namespace NLLIGO;
00049 
00050 
00051 namespace NLSOUND {
00052 
00053 // external sound are cliping after 10 meter inside the inner patate
00054 const float INSIDE_FALLOF = 10.0f;
00055 const float BACKGROUND_SOUND_ALTITUDE = 5.0f;
00056 
00057 
00058 
00059 CBackgroundSoundManager::CBackgroundSoundManager()
00060 : _Playing(false), _DoFade(false), _LastPosition(0,0,0)
00061 {
00062     for (uint i=0; i<UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS; ++i)
00063     {
00064         _BackgroundFlags.Flags[i] = false;
00065         _FilterFadesStart[i] = 0;
00066         _FilterFadeValues[i] = 1.0f;
00067     }
00068 }
00069 
00070 CBackgroundSoundManager::~CBackgroundSoundManager()
00071 {
00072     unload();
00073 }
00074 
00075 const UAudioMixer::TBackgroundFlags &CBackgroundSoundManager::getBackgroundFlags()
00076 {
00077     return  _BackgroundFlags;
00078 }
00079 
00080 
00081 void CBackgroundSoundManager::setBackgroundFilterFades(const UAudioMixer::TBackgroundFilterFades &backgroundFilterFades)
00082 {
00083     _BackgroundFilterFades = backgroundFilterFades;
00084 }
00085 
00086 const UAudioMixer::TBackgroundFilterFades &CBackgroundSoundManager::getBackgroundFilterFades()
00087 {
00088     return _BackgroundFilterFades;
00089 }
00090 
00091 
00092 void CBackgroundSoundManager::addSound(const std::string &soundName, uint layerId, const std::vector<NLLIGO::CPrimVector> &points, bool isPath)
00093 {
00094     CAudioMixerUser *mixer = CAudioMixerUser::instance();
00095     TSoundData  sd;
00096 
00097     sd.SoundName = CStringMapper::map(soundName);
00098     sd.Sound = mixer->getSoundId(sd.SoundName);
00099     sd.Source = 0;
00100 
00101     // Copy the points
00102     sd.Points.resize (points.size ());
00103     for (uint i=0; i<points.size (); i++)
00104         sd.Points[i] = points[i];
00105 
00106     sd.Selected = false;
00107     sd.IsPath = isPath;
00108 
00109     if (sd.Sound != 0)
00110     {
00111         // the sound is available !
00112         // compute bouding box/
00113         CVector vmin(FLT_MAX, FLT_MAX, 0), vmax(-FLT_MAX, -FLT_MAX, 0);
00114 
00115         vector<CVector>::iterator first(sd.Points.begin()), last(sd.Points.end());
00116         for (; first != last; ++first)
00117         {
00118             vmin.x = min(first->x, vmin.x);
00119             vmin.y = min(first->y, vmin.y);
00120             vmax.x = max(first->x, vmax.x);
00121             vmax.y = max(first->y, vmax.y);
00122         }
00123         sd.MaxBox = vmax;
00124         sd.MinBox = vmin;
00125 
00126         // compute the surface without the sound distance
00127         sd.Surface = (vmax.x - vmin.x) * (vmax.y - vmin.y);
00128 
00129         // add the eard distance of the sound.
00130         float   dist = sd.Sound->getMaxDistance();
00131         sd.MaxBox.x += dist;
00132         sd.MaxBox.y += dist;
00133         sd.MinBox.x -= dist;
00134         sd.MinBox.y -= dist;
00135 
00136         sd.MaxDist = dist;
00137 
00138         // store the sound.
00139         // TODO : handle the three layer.
00140         _Layers[layerId].push_back(sd);
00141     }
00142     else
00143     {
00144         nlwarning ("The sound '%s' can't be loaded", CStringMapper::unmap(sd.SoundName).c_str());
00145     }
00146 }
00147 
00148 void CBackgroundSoundManager::addSound(const std::string &rawSoundName, const std::vector<NLLIGO::CPrimVector> &points, bool isPath)
00149 {
00150     uint layerId = 0;
00151     uint n = 0;
00152     string name;
00153     // count the number of '-' in the string.
00154     n = std::count(rawSoundName.begin(), rawSoundName.end(), '-');
00155 
00156     if (n == 2)
00157     {
00158         // no layer spec, default to layer A
00159         string::size_type pos1 = rawSoundName.find ("-");
00160         if(pos1 == string::npos)
00161         {
00162             nlwarning ("zone have the malformated name '%s' missing -name-", rawSoundName.c_str());
00163             return;
00164         }
00165         pos1++;
00166 
00167         string::size_type pos2 = rawSoundName.find ("-", pos1);
00168         if(pos2 == string::npos)
00169         {
00170             nlwarning ("zone have the malformated name '%s' missing -name-", rawSoundName.c_str());
00171             return;
00172         }
00173 
00174         name = rawSoundName.substr(pos1, pos2-pos1);
00175     }
00176     else if (n == 3)
00177     {
00178         // layer spec !
00179         string::size_type pos1 = rawSoundName.find ("-");
00180         string::size_type pos2 = rawSoundName.find ("-", pos1+1);
00181         if(pos1 == string::npos || pos2 == string::npos)
00182         {
00183             nlwarning ("zone have the malformated name '%s' missing -layerId- or -name-", rawSoundName.c_str());
00184             return;
00185         }
00186         pos1++;
00187 
00188         string::size_type pos3 = rawSoundName.find ("-", pos2+1);
00189         if(pos3 == string::npos)
00190         {
00191             nlwarning ("zone have the malformated name '%s' missing -name-", rawSoundName.c_str());
00192             return;
00193         }
00194 
00195         char id = rawSoundName[pos1];
00196 
00197         // check caps
00198         if (id < 'a')
00199             id = id + ('a' - 'A');
00200 
00201         layerId = id - 'a';
00202 
00203         NLMISC::clamp(layerId, 0u, BACKGROUND_LAYER-1);
00204         pos2++;
00205 
00206         name = rawSoundName.substr(pos2, pos3-pos2);
00207     }
00208     else
00209     {
00210         nlwarning ("zone have the malformated name '%s",  rawSoundName.c_str());
00211         return;
00212     }
00213 
00214     addSound(name, layerId, points, isPath);
00215 /*
00216     TSoundData  sd;
00217 
00218     sd.SoundName = name;
00219     sd.Sound = mixer->getSoundId(sd.SoundName);
00220     sd.Source = 0;
00221 
00222     // Copy the points
00223     sd.Points.resize (points.size ());
00224     for (uint i=0; i<points.size (); i++)
00225         sd.Points[i] = points[i];
00226 
00227     sd.Selected = false;
00228     sd.IsPath = isPath;
00229 
00230     if (sd.Sound != 0)
00231     {
00232         // the sound is available !
00233         // compute bouding box/
00234         CVector vmin(FLT_MAX, FLT_MAX, 0), vmax(-FLT_MAX, -FLT_MAX, 0);
00235 
00236         vector<CVector>::iterator first(sd.Points.begin()), last(sd.Points.end());
00237         for (; first != last; ++first)
00238         {
00239             vmin.x = min(first->x, vmin.x);
00240             vmin.y = min(first->y, vmin.y);
00241             vmax.x = max(first->x, vmax.x);
00242             vmax.y = max(first->y, vmax.y);
00243         }
00244         sd.MaxBox = vmax;
00245         sd.MinBox = vmin;
00246 
00247         // compute the surface without the sound distance
00248         sd.Surface = (vmax.x - vmin.x) * (vmax.y - vmin.y);
00249 
00250         // add the eard distance of the sound.
00251         float   dist = sd.Sound->getMaxDistance();
00252         sd.MaxBox.x += dist;
00253         sd.MaxBox.y += dist;
00254         sd.MinBox.x -= dist;
00255         sd.MinBox.y -= dist;
00256 
00257         sd.MaxDist = dist;
00258 
00259         // store the sound.
00260         // TODO : handle the three layer.
00261         _Layers[layerId].push_back(sd);
00262     }
00263     else
00264     {
00265         nlwarning ("The sound '%s' can't be loaded", sd.SoundName.c_str());
00266     }
00267 */
00268 }
00269 
00270 
00271 void CBackgroundSoundManager::loadAudioFromPrimitives(const NLLIGO::IPrimitive &audioRoot)
00272 {
00273     std::string className;
00274     if(audioRoot.getPropertyByName("class", className))
00275     {
00276         if (className == "audio")
00277         {
00278             // ok, it a root of the audio primitives
00279 
00280             // remember playing state
00281             bool oldState = _Playing;
00282             unload();
00283 
00284             for (uint i=0; i<audioRoot.getNumChildren(); ++i)
00285             {
00286                 const NLLIGO::IPrimitive *child;
00287 
00288                 audioRoot.getChild(child, i);
00289 
00290                 if (child->getPropertyByName("class", className))
00291                 {
00292                     if (className == "sounds")
00293                     {
00294                         loadSoundsFromPrimitives(*child);
00295                     }
00296                     else if (className == "sample_banks")
00297                     {
00298                         loadSamplesFromPrimitives(*child);
00299                     }
00300                     else if (className == "env_fx")
00301                     {
00302                         loadEffectsFromPrimitives(*child);
00303                     }
00304                 }
00305             }
00306 
00307             if (oldState)
00308                 play();
00309         }
00310     }
00311     else
00312     {
00313         // try to look in the first child level
00314         for (uint i=0; i<audioRoot.getNumChildren(); ++i)
00315         {
00316             const NLLIGO::IPrimitive *child;
00317             audioRoot.getChild(child, i);
00318 
00319             if (child->getPropertyByName("class", className))
00320             {
00321                 if (className == "audio")
00322                 {
00323                     // recurse in this node
00324                     loadAudioFromPrimitives(*child);
00325                     // don't look any other primitives
00326                     break;
00327                 }
00328             }
00329         }
00330     }
00331 }
00332 
00333 void CBackgroundSoundManager::loadSoundsFromPrimitives(const NLLIGO::IPrimitive &soundRoot)
00334 {
00335     std::string className;
00336     if (soundRoot.getPropertyByName("class", className))
00337     {
00338         if (className == "sounds" || className == "sound_folder")
00339         {
00340             // ok, it sounds or a sounds foilder
00341             for (uint i=0; i<soundRoot.getNumChildren(); ++i)
00342             {
00343                 const NLLIGO::IPrimitive *child;
00344                 std::string primName;
00345                 soundRoot.getChild(child, i);
00346 
00347 
00348                 if (child->getPropertyByName("class", className))
00349                 {
00350                     uint layerId = 0;
00351                     std::string layerString;
00352                     std::string soundName;
00353                     if (child->getPropertyByName("layer", layerString))
00354                     {
00355                         // extract layer number.
00356                         if (!layerString.empty())
00357                         {
00358                             // TODO : handle special case for weather layer
00359                             layerId = layerString[layerString.size()-1] - '0';
00360                         }
00361                         clamp(layerId, 0u, BACKGROUND_LAYER-1);
00362                     }
00363 
00364                     child->getPropertyByName("name", primName);
00365                     child->getPropertyByName("sound", soundName);
00366                     // compatibility with older primitive
00367                     if (soundName.empty())
00368                         soundName = primName;
00369 
00370                     if (className == "sound_zone")
00371                     {
00372                         if(child->getNumVector()>2)
00373                         {
00374                             addSound(soundName, layerId, static_cast<const CPrimZone*>(child)->VPoints, false);
00375                         }
00376                         else
00377                         {
00378                             nlwarning ("A background sound patatoid have less than 3 points '%s'", primName.c_str());
00379                         }
00380                     }
00381                     else if (className == "sound_path")
00382                     {
00383                         if(child->getNumVector() > 1)
00384                         {
00385                             addSound(soundName, layerId, static_cast<const CPrimPath*>(child)->VPoints, true);
00386                         }
00387                         else
00388                         {
00389                             nlwarning ("A background sound path have less than 2 points '%s'", primName.c_str());
00390                         }
00391                     }
00392                     else if (className == "sound_point")
00393                     {
00394                         std::vector<NLLIGO::CPrimVector>    points;
00395                         points.push_back(static_cast<const CPrimPoint*>(child)->Point);
00396 
00397                         addSound(soundName, layerId, points, false);
00398                     }
00399                     else if (className == "sound_folder")
00400                     {
00401                         loadSoundsFromPrimitives(*child);
00402                     }
00403                 }
00404             }
00405         }
00406     }
00407 }
00408 
00409 void CBackgroundSoundManager::loadSamplesFromPrimitives(const NLLIGO::IPrimitive &sampleRoot)
00410 {
00411     std::string className;
00412     _Banks.clear();
00413     if (sampleRoot.getPropertyByName("class", className))
00414     {
00415         if (className == "sample_banks")
00416         {
00417             for (uint i=0; i<sampleRoot.getNumChildren(); ++i)
00418             {
00419                 const NLLIGO::IPrimitive *child;
00420                 std::string primName;
00421                 sampleRoot.getChild(child, i);
00422 
00423                 if (child->getPropertyByName("class", className))
00424                 {
00425                     child->getPropertyByName("name", primName);
00426                     if (className == "sample_bank_zone")
00427                     {
00428                         const std::vector<std::string> *names;
00429                         if (child->getPropertyByName("bank_names", names))
00430                         {
00431                             addSampleBank(*names, static_cast<const CPrimZone*>(child)->VPoints);
00432                         }
00433                     }
00434                 }
00435             }
00436         }
00437     }
00438 }
00439 
00440 void CBackgroundSoundManager::loadEffectsFromPrimitives(const NLLIGO::IPrimitive &fxRoot)
00441 {
00442     std::string className;
00443     _FxZones.clear();
00444 
00445     if (fxRoot.getPropertyByName("class", className))
00446     {
00447         if (className == "env_fx")
00448         {
00449             for (uint i=0; i<fxRoot.getNumChildren(); ++i)
00450             {
00451                 const NLLIGO::IPrimitive *child;
00452                 std::string primName;
00453                 fxRoot.getChild(child, i);
00454 
00455                 if (child->getPropertyByName("class", className))
00456                 {
00457                     child->getPropertyByName("name", primName);
00458                     if (className == "env_fx_zone")
00459                     {
00460                         std::string fxName;
00461                         if (child->getPropertyByName("fx_name", fxName))
00462                         {
00463                             addFxZone(fxName, static_cast<const CPrimZone*>(child)->VPoints);
00464                         }
00465                     }
00466                 }
00467             }
00468         }
00469     }
00470 }
00471 
00472 void CBackgroundSoundManager::addFxZone(const std::string &fxName, const std::vector<NLLIGO::CPrimVector> &points)
00473 {
00474     TFxZone fxZone;
00475 
00476     fxZone.FxName = CStringMapper::map(fxName);
00477     fxZone.Points.resize (points.size());
00478     for (uint j=0; j<points.size(); j++)
00479     {
00480         fxZone.Points[j] = points[j];
00481     }
00482 
00483     // compute bouding box.
00484     CVector vmin(FLT_MAX, FLT_MAX, 0), vmax(-FLT_MAX, -FLT_MAX, 0);
00485 
00486     vector<CVector>::iterator first(fxZone.Points.begin()), last(fxZone.Points.end());
00487     for (; first != last; ++first)
00488     {
00489         vmin.x = min(first->x, vmin.x);
00490         vmin.y = min(first->y, vmin.y);
00491         vmax.x = max(first->x, vmax.x);
00492         vmax.y = max(first->y, vmax.y);
00493     }
00494     fxZone.MaxBox = vmax;
00495     fxZone.MinBox = vmin;
00496 
00497     _FxZones.push_back(fxZone);
00498 }
00499 
00500 
00501 void CBackgroundSoundManager::addSampleBank(const std::vector<std::string> &bankNames, const std::vector<CPrimVector> &points)
00502 {
00503     TBanksData  bd;
00504 //  uint pointCount = points.size ();
00505     bd.Points.resize (points.size());
00506     for (uint j=0; j<points.size(); j++)
00507     {
00508         bd.Points[j] = points[j];
00509     }
00510 
00511     // compute bouding box.
00512     CVector vmin(FLT_MAX, FLT_MAX, 0), vmax(-FLT_MAX, -FLT_MAX, 0);
00513 
00514     vector<CVector>::iterator first(bd.Points.begin()), last(bd.Points.end());
00515     for (; first != last; ++first)
00516     {
00517         vmin.x = min(first->x, vmin.x);
00518         vmin.y = min(first->y, vmin.y);
00519         vmax.x = max(first->x, vmax.x);
00520         vmax.y = max(first->y, vmax.y);
00521     }
00522     bd.MaxBox = vmax;
00523     bd.MinBox = vmin;
00524 
00525     for(uint i=0; i<bankNames.size(); ++i)
00526     {
00527         if (!bankNames[i].empty())
00528             bd.Banks.push_back(bankNames[i]);
00529     }
00530 
00531     // ok, store it in the container.
00532     _Banks.push_back(bd);
00533 }
00534 
00535 
00536 //void CBackgroundSoundManager::loadSamplesFromRegion(const NLLIGO::CPrimRegion &region)
00537 //{
00538 //  _Banks.clear();
00539 //
00540 //  for (uint i=0; i< region.VZones.size(); ++i)
00541 //  {
00542 //      if (region.VZones[i].VPoints.size() > 2)
00543 //      {
00544 //          // parse the zone name to find the samples name.
00545 //          std::vector<std::string>    splitted = split(region.VZones[i].Name, '-');
00546 //          std::vector<std::string>    bankNames;
00547 //
00548 //          if (splitted.size() > 2)
00549 //          {
00550 //              for (uint j=1; j<splitted.size()-1; ++j)
00551 //              {
00552 //                  bankNames.push_back(splitted[j]);
00553 //              }
00554 //
00555 //              addSampleBank(bankNames, region.VZones[i].VPoints);
00556 //          }
00557 //          else
00558 //          {
00559 //              nlwarning ("A sample bank patatoid name did'nt contains banks name '%s'", region.VZones[i].Name.c_str());
00560 //          }
00561 //      }
00562 //      else
00563 //      {
00564 //          nlwarning ("A sample bank patatoid have less than 3 points '%s'", region.VZones[i].Name.c_str());
00565 //      }
00566 //  }
00567 //}
00568 
00569 //void CBackgroundSoundManager::loadEffecsFromRegion(const NLLIGO::CPrimRegion &region)
00570 //{
00571 //}
00572 
00573 //void CBackgroundSoundManager::loadSoundsFromRegion(const CPrimRegion &region)
00574 //{
00575 //  uint i;
00576 //  // remember playing state
00577 //  bool oldState = _Playing;
00578 //  unload();
00579 //
00580 //  for (i = 0; i < region.VZones.size(); i++)
00581 //  {
00582 //      if(region.VZones[i].VPoints.size()>2)
00583 //      {
00584 //          addSound(region.VZones[i].Name, region.VZones[i].VPoints, false);
00585 //      }
00586 //      else
00587 //      {
00588 //          nlwarning ("A background sound patatoid have less than 3 points '%s'", region.VZones[i].Name.c_str());
00589 //      }
00590 //  }
00591 //
00592 //  for (i = 0; i < region.VPaths.size(); i++)
00593 //  {
00594 //      if(region.VPaths[i].VPoints.size() > 1)
00595 //      {
00596 //          addSound(region.VPaths[i].Name, region.VPaths[i].VPoints, true);
00597 //      }
00598 //      else
00599 //      {
00600 //          nlwarning ("A background sound path have less than 2 points '%s'", region.VPaths[i].Name.c_str());
00601 //      }
00602 //  }
00603 //  for (i = 0; i < region.VPoints.size(); i++)
00604 //  {
00605 //      std::vector<CPrimVector>    points;
00606 //      points.push_back(region.VPoints[i].Point);
00607 //
00608 //      addSound(region.VPoints[i].Name, points, false);
00609 //  }
00610 //
00611 //
00612 //  // restart playing ?
00613 //  if (oldState)
00614 //      play();
00615 //}
00616 
00617 void CBackgroundSoundManager::load (const string &continent, NLLIGO::CLigoConfig &config)
00618 {
00619     uint32  PACKED_VERSION = 1;
00620     // First, try to load from a .primitive file (contain everythink)
00621     {
00622         CIFile file;
00623 //      CPrimRegion region;
00624         CPrimitives primitives;
00625         primitives.RootNode = new CPrimNode;
00626         string fn = continent+"_audio.primitive";
00627 
00628         string path = CPath::lookup(fn, false);
00629 
00630         if(!path.empty() && file.open (path))
00631         {
00632             // first, try to load the binary version (if up to date)
00633             {
00634                 uint32 version;
00635                 string filename = continent+".background_primitive";
00636                 string binPath = CPath::lookup(filename, false, false, false);
00637                 if (!binPath.empty()
00638                     && (CFile::getFileModificationDate(binPath) > CFile::getFileModificationDate(path)))
00639                 {
00640                     CIFile binFile(binPath);
00641                     binFile.serial(version);
00642 
00643                     if (version == PACKED_VERSION)
00644                     {
00645                         nlinfo ("loading '%s'", filename.c_str());
00646                         _Banks.clear();
00647                         binFile.serialCont(_Banks);
00648                         for (uint i=0; i<BACKGROUND_LAYER; ++i)
00649                         {
00650                             _Layers[i].clear();
00651                             binFile.serialCont(_Layers[i]);
00652                         }
00653                         _FxZones.clear();
00654                         binFile.serialCont(_FxZones);
00655 
00656                         // jobs done !
00657                         return;
00658                     }
00659                 }
00660             }
00661 
00662             nlinfo ("loading '%s'", fn.c_str());
00663 
00664             CIXml xml;
00665             {
00666                 H_AUTO(BackgroundSoundMangerLoad_xml_init);
00667                 xml.init (file);
00668             }
00669 
00670             {
00671                 H_AUTO(BackgroundSoundMangerLoad_primitive_read);
00672                 primitives.read(xml.getRootNode(), fn.c_str(), config);
00673             }
00674 //          region.serial(xml);
00675             file.close ();
00676 
00677             {
00678                 H_AUTO(BackgroundSoundMangerLoad_loadAudioFromPrimitive);
00679                 loadAudioFromPrimitives(*primitives.RootNode);
00680             }
00681 
00682             // store the binary version of the audio primitive for later use
00683             CAudioMixerUser *mixer = CAudioMixerUser::instance();
00684             if (mixer->getPackedSheetUpdate())
00685             {
00686                 // need to update packed sheet, so write the binary primitive version
00687                 string filename = mixer->getPackedSheetPath()+"/"+continent+".background_primitive";
00688                 COFile file(filename);
00689 
00690                 file.serial(PACKED_VERSION);
00691                 file.serialCont(_Banks);
00692                 for (uint i=0; i<BACKGROUND_LAYER; ++i)
00693                     file.serialCont(_Layers[i]);
00694                 file.serialCont(_FxZones);
00695             }
00696 
00698             // Jobs done !
00699             return;
00700         }
00701 
00702     }
00703 
00704     // We reach this only if the new .primitive file format is not found
00705     // then, we try to load separate .prim file for sound, samples and fx
00706 
00707     // load the sound.
00708 //  {
00709 //      CIFile file;
00710 //      CPrimRegion region;
00711 //      string fn = continent+"_audio.prim";
00712 //
00713 //      nlinfo ("loading '%s'", fn.c_str());
00714 //
00715 //      string path = CPath::lookup(fn, false);
00716 //
00717 //      if(!path.empty() && file.open (path))
00718 //      {
00719 //          CIXml xml;
00720 //          xml.init (file);
00721 //          region.serial(xml);
00722 //          file.close ();
00723 //
00724 //          nlinfo ("Region '%s' contains %d zones for the background sounds", continent.c_str(), region.VZones.size());
00725 //
00726 //          loadSoundsFromRegion(region);
00727 //      }
00728 //  }
00729 //  // load the effect.
00730 //  {
00731 //      CIFile file;
00732 //      CPrimRegion region;
00733 //      string fn = continent+"_effects.prim";
00734 //
00735 //      nlinfo ("loading '%s'", fn.c_str());
00736 //
00737 //      string path = CPath::lookup(fn, false);
00738 //
00739 //      if(!path.empty() && file.open (path))
00740 //      {
00741 //          CIXml xml;
00742 //          xml.init (file);
00743 //          region.serial(xml);
00744 //          file.close ();
00745 //
00746 //          nlinfo ("Region '%s' contains %d zones for the background effetcs", continent.c_str(), region.VZones.size());
00747 //
00748 //          loadEffecsFromRegion(region);
00749 //      }
00750 //  }
00751 //  // load the samples banks.
00752 //  {
00753 //      CIFile file;
00754 //      CPrimRegion region;
00755 //      string fn = continent+"_samples.prim";
00756 //
00757 //      nlinfo ("loading '%s'", fn.c_str());
00758 //
00759 //      string path = CPath::lookup(fn, false);
00760 //
00761 //      if(!path.empty() && file.open (path))
00762 //      {
00763 //          CIXml xml;
00764 //          xml.init (file);
00765 //          region.serial(xml);
00766 //          file.close ();
00767 //
00768 //          nlinfo ("Region '%s' contains %d zones for the background samples banks", continent.c_str(), region.VZones.size());
00769 //
00770 //          loadSamplesFromRegion(region);
00771 //      }
00772 //  }
00773 }
00774 
00775 
00776 void CBackgroundSoundManager::play ()
00777 {
00778     if (_Playing)
00779         return;
00780 
00781     _Playing = true;
00782 
00783     CAudioMixerUser::instance()->registerUpdate(this);
00784 
00785     // init the filter value and filter start time
00786     for (uint i =0; i<UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS; ++i)
00787     {
00788         _FilterFadesStart[i] = 0;
00789         _FilterFadeValues[i] = 1.0f * !_BackgroundFlags.Flags[i];
00790     }
00791     // force an initial filtering
00792     _DoFade = true;
00793     updateBackgroundStatus();
00794 
00795 
00796 }
00797 
00798 
00799 void CBackgroundSoundManager::stop ()
00800 {
00801     if(!_Playing)
00802         return;
00803 
00804     for (uint i=0; i<BACKGROUND_LAYER; ++i)
00805     {
00806         // stop all playing source
00807         std::vector<TSoundData>::iterator first(_Layers[i].begin()), last(_Layers[i].end());
00808         for (; first != last; ++first)
00809         {
00810             if (first->Source != 0 && first->Source->isPlaying())
00811                 first->Source->stop();
00812         }
00813     }
00814 
00815     CAudioMixerUser::instance()->unregisterUpdate(this);
00816 
00817     _Playing = false;
00818 }
00819 
00820 void CBackgroundSoundManager::unload ()
00821 {
00822     stop();
00823 
00824     for (uint i=0; i<BACKGROUND_LAYER; ++i)
00825     {
00826         // delete all created source
00827         std::vector<TSoundData>::iterator first(_Layers[i].begin()), last(_Layers[i].end());
00828         for (; first != last; ++first)
00829         {
00830             if (first->Source)
00831 //              mixer->removeSource(first->Source);
00832                 delete first->Source;
00833         }
00834 
00835         // and free the layer.
00836         _Layers[i].clear();
00837     }
00838 
00839     // erase the sample banks zone
00840     _Banks.clear();
00841 
00842     // TODO : erase the fx zones
00843 }
00844 
00845 void CBackgroundSoundManager::setListenerPosition (const CVector &listenerPosition)
00846 {
00847     if (_LastPosition == listenerPosition)
00848     {
00849         return;
00850     }
00851     _LastPosition = listenerPosition;
00852 
00853     updateBackgroundStatus();
00854 }
00855 
00856 void CBackgroundSoundManager::updateBackgroundStatus()
00857 {
00858     H_AUTO(NLSOUND_UpdateBackgroundSound)
00859     if (!_Playing)
00860         return;
00861 
00862     CAudioMixerUser *mixer = CAudioMixerUser::instance();
00863 
00864 
00865     // it s on 2d so we don't have z
00866     CVector listener = _LastPosition;
00867     listener.z = 0.0f;
00868 
00869     // special case for clustered sound management. If the listener is not
00870     // in the global cluster, it's background listening place could be different
00871     CClusteredSound *clusteredSound = mixer->getClusteredSound();
00872     if (clusteredSound != 0)
00873     {
00874         const CClusteredSound::CClusterSoundStatus *css = clusteredSound->getClusterSoundStatus(clusteredSound->getRootCluster());
00875         if (css != 0)
00876         {
00877             listener = css->Position;
00878             listener.z = 0.0f;
00879         }
00880     }
00881 
00882     // evalutate the current env fx
00883     if (mixer->useEnvironmentEffects())
00884     {
00885         H_AUTO(NLSOUND_EvaluateEnvFx)
00886         NL3D::CCluster *rootCluster = 0;
00887         if (mixer->getClusteredSound())
00888             rootCluster = mixer->getClusteredSound()->getRootCluster();
00889 
00890         std::vector<TFxZone>::iterator first(_FxZones.begin()), last(_FxZones.end());
00891         for (; first != last; ++first)
00892         {
00893             if (listener.x >= first->MinBox.x && listener.x <= first->MaxBox.x
00894                 && listener.y >= first->MinBox.y && listener.y <= first->MaxBox.y
00895                 )
00896             {
00897                 // bounding box ok,
00898                 if (CPrimZone::contains(listener, first->Points))
00899                 {
00900                     // stop at the first zone !
00901                     if (rootCluster)
00902                     {
00903                         // use the cluster system
00904                         rootCluster->setEnvironmentFx(first->FxName);
00905                     }
00906                     else
00907                     {
00908                         // no cluster system, set the env 'manualy'
00909                         if (_LastEnv != first->FxName)
00910                         {
00911                             // set an env with size 10.f
00912                             _LastEnv = first->FxName;
00913                             mixer->setEnvironment(first->FxName, 10.f);
00914                         }
00915                     }
00916                     break;
00917                 }
00918             }
00919         }
00920     }
00921 
00922 
00923     // compute the list of load/unload banks.
00924     {
00925         H_AUTO(NLSOUND_LoadUnloadSampleBank)
00926         // set of bank that must be in ram.
00927         std::set<std::string>   newBanks;
00928 
00929         std::vector<TBanksData>::iterator first(_Banks.begin()), last(_Banks.end());
00930         for (; first != last; ++first)
00931         {
00932             if (listener.x >= first->MinBox.x && listener.x <= first->MaxBox.x
00933                 && listener.y >= first->MinBox.y && listener.y <= first->MaxBox.y
00934                 )
00935             {
00936                 // bounding box ok,
00937                 if (CPrimZone::contains(listener, first->Points))
00938                 {
00939                     // add the banks of this zone in the n
00940                     newBanks.insert(first->Banks.begin(), first->Banks.end());
00941                 }
00942             }
00943         }
00944 
00945 /*      {
00946             nldebug("-----------------------------");
00947             nldebug("Loaded sample banks (%u elements):", _LoadedBanks.size());
00948             set<string>::iterator first(_LoadedBanks.begin()), last(_LoadedBanks.end());
00949             for (; first != last; ++first)
00950             {
00951                 const string &str = *first;
00952                 nldebug("  %s", first->c_str());
00953             }
00954         }
00955         {
00956             nldebug("New Sample bank list (%u elements):", newBanks.size());
00957             set<string>::iterator first(newBanks.begin()), last(newBanks.end());
00958             for (; first != last; ++first)
00959             {
00960                 const string &str = *first;
00961                 nldebug("  %s", first->c_str());
00962             }
00963         }
00964 */
00965         // ok, now compute to set : the set of bank to load, and the set of banks to unload.
00966         std::set<std::string>   noChange;
00967         std::set_intersection(_LoadedBanks.begin(), _LoadedBanks.end(), newBanks.begin(), newBanks.end(), std::inserter(noChange, noChange.end()));
00968 
00969         std::set<std::string>   loadList;
00970         std::set_difference(newBanks.begin(), newBanks.end(), noChange.begin(), noChange.end(), std::inserter(loadList, loadList.end()));
00971 
00972         std::set<std::string>   unloadList;
00973         std::set_difference(_LoadedBanks.begin(), _LoadedBanks.end(), newBanks.begin(), newBanks.end(), std::inserter(unloadList, unloadList.end()));
00974 
00975         // and now, load and unload....
00976         {
00977             std::set<std::string>::iterator first(loadList.begin()), last(loadList.end());
00978             for (; first != last; ++first)
00979             {
00980 //              nldebug("Trying to load sample bank %s", first->c_str());
00981                 mixer->loadSampleBank(true, *first);
00982             }
00983             _LoadedBanks.insert(loadList.begin(), loadList.end());
00984         }
00985         {
00986             std::set<std::string>::iterator first(unloadList.begin()), last(unloadList.end());
00987             for (; first != last; ++first)
00988             {
00989 //              nldebug("Trying to unload sample bank %s", first->c_str());
00990                 if (mixer->unloadSampleBank(*first))
00991                 {
00992                     // ok, the bank is unloaded
00993                     _LoadedBanks.erase(*first);
00994                 }
00995                 else if (CSampleBank::findSampleBank(CStringMapper::map(*first)) == 0)
00996                 {
00997                     // ok, the bank is unavailable !
00998                     _LoadedBanks.erase(*first);
00999                 }
01000             }
01001         }
01002     }
01003 
01004     H_BEFORE(NLSOUND_UpdateSoundLayer)
01005     // retreive the root cluster...
01006     NL3D::CCluster *rootCluster = 0;
01007     if (mixer->getClusteredSound() != 0)
01008         rootCluster = mixer->getClusteredSound()->getRootCluster();
01009 
01010     // Apply the same algo for each sound layer.
01011     for (uint i=0; i<BACKGROUND_LAYER; ++i)
01012     {
01013         vector<TSoundData> &layer = _Layers[i];
01014         vector<uint> selectedIndex;
01015         vector<uint> leaveIndex;
01016 
01017         selectedIndex.reserve(layer.size());
01018         leaveIndex.reserve(layer.size());
01019 
01020         // extract the list of selected/unselected box
01021         vector<TSoundData>::iterator first(layer.begin()), last(layer.end());
01022         for (uint count = 0; first != last; ++first, ++count)
01023         {
01024             if (listener.x >= first->MinBox.x && listener.x <= first->MaxBox.x
01025                 && listener.y >= first->MinBox.y && listener.y <= first->MaxBox.y
01026 //              && listener.z >= first->MinBox.z && listener.z <= first->MaxBox.z
01027                 )
01028             {
01029 //              nldebug("patat %u is selected by box (%s)", count, first->SoundName.c_str());
01030                 selectedIndex.push_back(count);
01031             }
01032             else
01033             {
01034 //              nldebug("patat %u is rejected  by box (%s)", count, first->SoundName.c_str());
01035                 // listener out of this box.
01036                 if (first->Selected && first->Source != 0)
01037                 {
01038                     // we leave this box.
01039                     leaveIndex.push_back(count);
01040                 }
01041             }
01042         }
01043 
01044         // stop all the sound that are leaved.
01045         {
01046             vector<uint>::iterator first(leaveIndex.begin()), last(leaveIndex.end());
01047             for (; first != last; ++first)
01048             {
01049                 TSoundData &sd = layer[*first];
01050                 sd.Selected = false;
01051                 if (sd.Source->isPlaying())
01052                     sd.Source->stop();
01053             }
01054         }
01055         // Compute new source mixing in this layer
01056         {
01058             list<pair<float, TSoundStatus> > status;
01059 
01060             // first loop to compute selected sound gain and position and order the result by surface..
01061             {
01062                 vector<uint>::iterator first(selectedIndex.begin()), last(selectedIndex.end());
01063                 for (; first != last; ++first)
01064                 {
01065                     TSoundData &sd = layer[*first];
01066                     CVector pos;
01067                     float   gain = 1.0f;
01068                     float   distance;
01069                     bool    inside = false;
01070 
01071                     // inside the patat ?
01072 
01073                     if(CPrimZone::contains(listener, sd.Points, distance, pos, sd.IsPath))
01074                     {
01075                         inside = true;
01076                         pos = _LastPosition;    // use the real listener position, not the 0 z centered
01077                         gain = 1.0f;
01078 //                      nlinfo ("inside patate %d name '%s' ", *first, sd.SoundName.c_str());
01079                     }
01080                     else
01081                     {
01082                         if (sd.MaxDist>0 && distance < sd.MaxDist)
01083                         {
01084                             // compute the gain.
01085 //                          gain = (sd.MaxDist - distance) / sd.MaxDist;
01086                         }
01087                         else
01088                         {
01089                             // too far
01090                             gain = 0;
01091                         }
01092                         //nlinfo ("near patate %d name '%s' from %f ", *first, sd.SoundName.c_str(), distance);
01093                     }
01094 
01095                     // store the status.
01096                     status.push_back(make_pair(sd.Surface, TSoundStatus(sd, pos, gain, distance, inside)));
01097                 }
01098             }
01099             // second loop thrue the surface ordered selected sound.
01100             {
01101                 // Sound mixing strategie :
01102                 // The smallest zone sound mask bigger one
01103 
01104                 float   maskFactor = 1.0f;
01105 
01106                 list<pair<float, TSoundStatus> >::iterator first(status.begin()), last(status.end());
01107                 for (; first != last; ++first)
01108                 {
01109                     TSoundStatus &ss = first->second;
01110 
01111                     // special algo for music sound (don't influence / use maskFactor strategy)
01112                     bool    musicSound= ss.SoundData.Sound && ss.SoundData.Sound->getSoundType()==CSound::SOUND_MUSIC;
01113 
01114                     // ---- music sound special case (music competition is managed specially in the CMusicSoundManager)
01115                     if(musicSound)
01116                     {
01117                         if (ss.Gain > 0)
01118                         {
01119                             ss.SoundData.Selected = true;
01120 
01121                             // start the sound (if needed) and update the volume.
01122                             if (ss.SoundData.Source == 0)
01123                             {
01124                                 // try to create the source.
01125                                 ss.SoundData.Source = static_cast<CSourceCommon*>(mixer->createSource(ss.SoundData.Sound, false, 0, 0, rootCluster));
01126                             }
01127                             if (ss.SoundData.Source != 0)
01128                             {
01129                                 // update the position (not used I think, but maybe important...)
01130                                 ss.Position.z = _LastPosition.z + BACKGROUND_SOUND_ALTITUDE;
01131                                 ss.SoundData.Source->setPos(ss.Position);
01132 
01133                                 if (!ss.SoundData.Source->isPlaying())
01134                                 {
01135                                     // start the sound is needed.
01136                                     ss.SoundData.Source->play();
01137                                 }
01138                             }
01139                         }
01140                         else if (ss.SoundData.Source != 0 && ss.SoundData.Source->isPlaying())
01141                         {
01142                             // stop this too far source.
01143                             ss.SoundData.Source->stop();
01144                         }
01145                     }
01146                     // ---- standard sound case
01147                     else
01148                     {
01149                         if (maskFactor > 0.0f && ss.Gain > 0)
01150                         {
01151                             float gain;
01152 
01153                             if (!ss.SoundData.IsPath && ss.SoundData.Points.size() > 1)
01154                                 gain = maskFactor * ss.Gain;
01155                             else
01156                                 gain = ss.Gain;
01157 
01158 //                          maskFactor -= ss.Gain;
01159 
01160                             ss.SoundData.Selected = true;
01161 
01162 //                          if (ss.Gain == 1)
01163 //                          if (ss.Distance == 0)
01164                             if (ss.Inside)
01165                             {
01166                                 // inside a pattate, then decrease the mask factor will we are more inside the patate
01167                                 maskFactor -= first->second.Distance / INSIDE_FALLOF;
01168                                 clamp(maskFactor, 0.0f, 1.0f);
01169                             }
01170 
01171                             // start the sound (if needed) and update the volume.
01172 
01173                             if (ss.SoundData.Source == 0)
01174                             {
01175                                 // try to create the source.
01176                                 ss.SoundData.Source = static_cast<CSourceCommon*>(mixer->createSource(ss.SoundData.Sound, false, 0, 0, rootCluster));
01177                             }
01178                             if (ss.SoundData.Source != 0)
01179                             {
01180                                 // set the volume
01181                                 ss.SoundData.Source->setRelativeGain(gain);
01182                                 // and the position
01183                                 ss.Position.z = _LastPosition.z + BACKGROUND_SOUND_ALTITUDE;
01184                                 ss.SoundData.Source->setPos(ss.Position);
01185 
01186 //                              nldebug("Setting source %s at %f", ss.SoundData.SoundName.c_str(), gain);
01187                                 if (!ss.SoundData.Source->isPlaying())
01188                                 {
01189                                     // start the sound is needed.
01190                                     ss.SoundData.Source->play();
01191                                 }
01192                                 else if (ss.SoundData.Source->getType() != CSourceCommon::SOURCE_SIMPLE)
01193                                     ss.SoundData.Source->checkup();
01194                             }
01195                         }
01196                         else if (ss.SoundData.Source != 0 && ss.SoundData.Source->isPlaying())
01197                         {
01198                             // stop this too far source.
01199                             ss.SoundData.Source->stop();
01200                         }
01201                     }
01202                 }
01203             }
01204         } // compute source mixing
01205     } // for each layer
01206 
01207     H_AFTER(NLSOUND_UpdateSoundLayer)
01208 
01209 
01210     H_BEFORE(NLSOUND_DoFadeInOut)
01211     // update the fade in / out
01212     if (_DoFade)
01213     {
01214         TTime now = NLMISC::CTime::getLocalTime();
01215         _DoFade = false;
01216         uint i;
01217 
01218         //for each filter
01219         for (i=0; i< UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS; ++i)
01220         {
01221             if (_FilterFadesStart[i] != 0)
01222             {
01223                 // this filter is fading
01224                 if (_BackgroundFlags.Flags[i])
01225                 {
01226                     // fading out
01227                     TTime delta = now - _FilterFadesStart[i];
01228                     if (delta > _BackgroundFilterFades.FadeOuts[i])
01229                     {
01230                         // the fade is terminated
01231                         _FilterFadeValues[i] = 0;
01232                         // stop the fade for this filter
01233                         _FilterFadesStart[i] = 0;
01234                     }
01235                     else
01236                     {
01237                         _FilterFadeValues[i] = 1 - (float(delta) / _BackgroundFilterFades.FadeOuts[i]);
01238                         // continue to fade (at least for this filter.
01239                         _DoFade |= true;
01240                     }
01241                 }
01242                 else
01243                 {
01244                     // fading in
01245                     TTime delta = now - _FilterFadesStart[i];
01246                     if (delta > _BackgroundFilterFades.FadeIns[i])
01247                     {
01248                         // the fade is terminated
01249                         _FilterFadeValues[i] = 1;
01250                         // stop the fade for this filter
01251                         _FilterFadesStart[i] = 0;
01252                     }
01253                     else
01254                     {
01255                         _FilterFadeValues[i] = float(delta) / _BackgroundFilterFades.FadeIns[i];
01256                         // continue to fade (at least for this filter.
01257                         _DoFade |= true;
01258                     }
01259                 }
01260             }
01261         }
01262 
01263         // update all playing background source that filter value has changed
01264         // for each layer
01265         for (i=0; i<BACKGROUND_LAYER; ++i)
01266         {
01267             // for each patat
01268             std::vector<TSoundData>::iterator first(_Layers[i].begin()), last(_Layers[i].end());
01269             for (; first != last; ++first)
01270             {
01271                 if (first->Selected)
01272                 {
01273                     // update this playing sound
01274                     if (first->Source != 0 && first->Source->getType() == CSourceCommon::SOURCE_BACKGROUND)
01275                         static_cast<CBackgroundSource*>(first->Source)->updateFilterValues(_FilterFadeValues);
01276                 }
01277             }
01278 
01279         }
01280 
01281         if (!_DoFade)
01282         {
01283             // we can remove the update.
01284             mixer->unregisterUpdate(this);
01285         }
01286     }
01287     H_AFTER(NLSOUND_DoFadeInOut)
01288 }
01289 
01290 void CBackgroundSoundManager::setBackgroundFlags(const UAudioMixer::TBackgroundFlags &backgroundFlags)
01291 {
01292     for (uint i=0; i<UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS; ++i)
01293     {
01294         if (_BackgroundFlags.Flags[i] != backgroundFlags.Flags[i])
01295         {
01296             // the filter flags has changed !
01297             if (backgroundFlags.Flags[i])
01298             {
01299                 // the filter is activated, to a fade out
01300                 _FilterFadesStart[i] = uint64(NLMISC::CTime::getLocalTime() - (1-_FilterFadeValues[i]) * _BackgroundFilterFades.FadeOuts[i]);
01301                 _DoFade = true;
01302             }
01303             else
01304             {
01305                 // the filter is cleared, do a fade in
01306                 _FilterFadesStart[i] = uint64(NLMISC::CTime::getLocalTime() - (_FilterFadeValues[i]) * _BackgroundFilterFades.FadeIns[i]);
01307                 _DoFade = true;
01308             }
01309         }
01310 
01311         _BackgroundFlags.Flags[i] = backgroundFlags.Flags[i];
01312     }
01313 
01314     if (_DoFade)
01315         CAudioMixerUser::instance()->registerUpdate(this);
01316 }
01317 
01318 
01319 void CBackgroundSoundManager::onUpdate()
01320 {
01321     updateBackgroundStatus();
01322 }
01323 
01324 
01325 /*
01326 void CBackgroundSoundManager::update ()
01327 {
01328 
01329 }
01330 */
01331 /*
01332 uint32 CBackgroundSoundManager::getZoneNumber ()
01333 {
01334 //  return BackgroundSounds.size();
01335     return 0;
01336 }
01337 */
01338 /*
01339 const vector<CVector> &CBackgroundSoundManager::getZone(uint32 zone)
01340 {
01341 //  nlassert (zone< BackgroundSounds.size());
01342 //  return BackgroundSounds[zone].Points;
01343     static vector<CVector> v;
01344     return v;
01345 }
01346 */
01347 CVector CBackgroundSoundManager::getZoneSourcePos(uint32 /* zone */)
01348 {
01349 /*  nlassert (zone< BackgroundSounds.size());
01350     CVector pos;
01351     if (BackgroundSounds[zone].SourceDay != NULL)
01352         BackgroundSounds[zone].SourceDay->getPos(pos);
01353     return pos;
01354 */
01355     return CVector();
01356 }
01357 
01358 
01359 /*
01360 void CBackgroundSoundManager::setDayNightRatio(float ratio)
01361 {
01362     // 0 is day
01363     // 1 is night
01364 
01365     nlassert (ratio>=0.0f && ratio<=1.0f);
01366 
01367     if (OldRatio == ratio)
01368         return;
01369     else
01370         OldRatio = ratio;
01371 
01372 
01373     // recompute all source volume
01374 
01375     for (uint i = 0; i < BackgroundSounds.size(); i++)
01376     {
01377         if(ratio == 0.0f)
01378         {
01379             if(BackgroundSounds[i].SourceDay != NULL)
01380             {
01381                 BackgroundSounds[i].SourceDay->setRelativeGain(1.0f);
01382 
01383                 if (!BackgroundSounds[i].SourceDay->isPlaying())
01384                     BackgroundSounds[i].SourceDay->play();
01385             }
01386 
01387             if(BackgroundSounds[i].SourceNight != NULL)
01388             {
01389                 if (BackgroundSounds[i].SourceNight->isPlaying())
01390                     BackgroundSounds[i].SourceNight->stop();
01391             }
01392         }
01393         else if (ratio == 1.0f)
01394         {
01395             if(BackgroundSounds[i].SourceDay != NULL)
01396             {
01397                 if (BackgroundSounds[i].SourceDay->isPlaying())
01398                     BackgroundSounds[i].SourceDay->stop();
01399             }
01400 
01401             if(BackgroundSounds[i].SourceNight != NULL)
01402             {
01403                 BackgroundSounds[i].SourceNight->setRelativeGain(1.0f);
01404 
01405                 if (!BackgroundSounds[i].SourceNight->isPlaying())
01406                     BackgroundSounds[i].SourceNight->play();
01407             }
01408         }
01409         else
01410         {
01411             if(BackgroundSounds[i].SourceDay != NULL)
01412             {
01413                 BackgroundSounds[i].SourceDay->setRelativeGain((1.0f-ratio));
01414 
01415                 if (!BackgroundSounds[i].SourceDay->isPlaying())
01416                     BackgroundSounds[i].SourceDay->play();
01417             }
01418 
01419             if(BackgroundSounds[i].SourceNight != NULL)
01420             {
01421                 BackgroundSounds[i].SourceNight->setRelativeGain(ratio);
01422 
01423                 if (!BackgroundSounds[i].SourceNight->isPlaying())
01424                     BackgroundSounds[i].SourceNight->play();
01425             }
01426         }
01427     }
01428 
01429 }
01430 */
01431 
01432 void CBackgroundSoundManager::TBanksData::serial(NLMISC::IStream &s)
01433 {
01434     s.serialCont(Banks);
01435     s.serial(MinBox);
01436     s.serial(MaxBox);
01437     s.serialCont(Points);
01438 }
01439 
01440 void CBackgroundSoundManager::TSoundData::serial(NLMISC::IStream &s)
01441 {
01442     std::string str;
01443 
01444     if (s.isReading())
01445     {
01446         CAudioMixerUser *mixer = CAudioMixerUser::instance();
01447         s.serial(str);
01448         SoundName = NLMISC::CStringMapper::map(str);
01449         Sound = mixer->getSoundId(SoundName);
01450         Source = NULL;
01451         Selected = false;
01452     }
01453     else
01454     {
01455         s.serial(const_cast<std::string&>(NLMISC::CStringMapper::unmap(SoundName)));
01456     }
01457     s.serial(MinBox);
01458     s.serial(MaxBox);
01459     s.serial(Surface);
01460     s.serial(MaxDist);
01461     s.serial(IsPath);
01462     s.serialCont(Points);
01463 }
01464 
01465 void CBackgroundSoundManager::TFxZone::serial(NLMISC::IStream &s)
01466 {
01467     std::string str;
01468 
01469     if (s.isReading())
01470     {
01471         s.serial(str);
01472         FxName= NLMISC::CStringMapper::map(str);
01473     }
01474     else
01475     {
01476         s.serial(const_cast<std::string&>(NLMISC::CStringMapper::unmap(FxName)));
01477     }
01478 
01479     s.serialCont(Points);
01480     s.serial(MinBox);
01481     s.serial(MaxBox);
01482 }
01483 
01484 
01485 } // NLSOUND
01486 

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