# 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  

background_sound_manager.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 
00027 #include "stdsound.h"
00028 
00029 #include "nel/misc/file.h"
00030 #include "nel/misc/i_xml.h"
00031 #include "nel/misc/path.h"
00032 
00033 #include "nel/ligo/primitive.h"
00034 
00035 #include "nel/sound/u_source.h"
00036 
00037 #include "background_sound_manager.h"
00038 #include <algorithm>
00039 
00040 using namespace std;
00041 using namespace NLMISC;
00042 using namespace NLLIGO;
00043 
00044 
00045 namespace NLSOUND {
00046 
00047 // external sound are cliping after 10 meter inside the inner patate
00048 const float     INSIDE_FALLOF = 10.0f; 
00049 
00050 //UAudioMixer *CBackgroundSoundManager::_AudioMixer = NULL;
00051 
00052 
00053 CBackgroundSoundManager::CBackgroundSoundManager()
00054 : _LastPosition(0,0,0), _Playing(false)
00055 {
00056 }
00057 
00058 CBackgroundSoundManager::~CBackgroundSoundManager()
00059 {
00060         unload();
00061 }
00062 
00063 const UAudioMixer::TBackgroundFlags &CBackgroundSoundManager::getBackgroundFlags()
00064 {
00065         return  _BackgroundFlags;
00066 }
00067 
00068 void CBackgroundSoundManager::setBackgroundFlags(const UAudioMixer::TBackgroundFlags &backgroundFlags)
00069 {
00070         _BackgroundFlags = backgroundFlags;
00071 }
00072 
00073 void CBackgroundSoundManager::addSound(const std::string &soundName, const std::vector<NLLIGO::CPrimVector> &points, bool isPath)
00074 {
00075         CAudioMixerUser *mixer = CAudioMixerUser::instance();
00076         uint layerId = 0;
00077         uint n = 0;
00078         string name;
00079         // count the number of '-' in the sgtring.
00080         n = std::count(soundName.begin(), soundName.end(), '-');
00081 
00082         if (n == 2)
00083         {
00084                 // no layer spec, default to layer A
00085                 uint32 pos1 = soundName.find ("-");
00086                 if(pos1 == string::npos)
00087                 {
00088                         nlwarning ("zone have the malformated name '%s' missing -name-", soundName.c_str());
00089                         return;
00090                 }
00091                 pos1++;
00092 
00093                 uint32 pos2 = soundName.find ("-", pos1);
00094                 if(pos2 == string::npos)
00095                 {
00096                         nlwarning ("zone have the malformated name '%s' missing -name-", soundName.c_str());
00097                         return;
00098                 }
00099 
00100                 name = soundName.substr(pos1, pos2-pos1);
00101         }
00102         else if (n == 3)
00103         {
00104                 // layer spec !
00105                 uint32 pos1 = soundName.find ("-");
00106                 uint32 pos2 = soundName.find ("-", pos1+1);
00107                 if(pos1 == string::npos || pos2 == string::npos)
00108                 {
00109                         nlwarning ("zone have the malformated name '%s' missing -layerId- or -name-", soundName.c_str());
00110                         return;
00111                 }
00112                 pos1++;
00113 
00114                 uint32 pos3 = soundName.find ("-", pos2+1);
00115                 if(pos3 == string::npos)
00116                 {
00117                         nlwarning ("zone have the malformated name '%s' missing -name-", soundName.c_str());
00118                         return;
00119                 }
00120 
00121                 char id = soundName[pos1];
00122 
00123                 // check caps
00124                 if (id < 'a')
00125                         id = id + ('a' - 'A');
00126 
00127                 layerId = id - 'a';
00128 
00129                 NLMISC::clamp(layerId, 0u, BACKGROUND_LAYER-1);
00130                 pos2++;
00131 
00132                 name = soundName.substr(pos2, pos3-pos2);
00133         }
00134         else
00135         {
00136                 nlwarning ("zone have the malformated name '%s",  soundName.c_str());
00137                 return;
00138         }
00139                 
00140 
00141         TSoundData      sd;
00142 
00143         sd.SoundName = name;
00144         sd.Sound = mixer->getSoundId(sd.SoundName);
00145         sd.Source = 0;
00146 
00147         // Copy the points
00148         sd.Points.resize (points.size ());
00149         for (uint i=0; i<points.size (); i++)
00150                 sd.Points[i] = points[i];
00151 
00152         sd.Selected = false;
00153         sd.IsPath = isPath;
00154 
00155         if (sd.Sound != 0)
00156         {
00157                 // the sound is available !
00158                 // compute bouding box/
00159                 CVector vmin(FLT_MAX, FLT_MAX, 0), vmax(-FLT_MAX, -FLT_MAX, 0);
00160 
00161                 vector<CVector>::iterator first(sd.Points.begin()), last(sd.Points.end());
00162                 for (; first != last; ++first)
00163                 {
00164                         vmin.x = min(first->x, vmin.x);
00165                         vmin.y = min(first->y, vmin.y);
00166                         vmax.x = max(first->x, vmax.x);
00167                         vmax.y = max(first->y, vmax.y);
00168                 }
00169                 sd.MaxBox = vmax;
00170                 sd.MinBox = vmin;
00171 
00172                 // compute the surface without the sound distance
00173                 sd.Surface = (vmax.x - vmin.x) * (vmax.y - vmin.y);
00174 
00175                 // add the eard distance of the sound.
00176                 float   dist = sd.Sound->getMaxDistance();
00177                 sd.MaxBox.x += dist;
00178                 sd.MaxBox.y += dist;
00179                 sd.MinBox.x -= dist;
00180                 sd.MinBox.y -= dist;
00181 
00182                 sd.MaxDist = dist;
00183 
00184                 // store the sound. 
00185                 // TODO : handle the three layer.
00186                 _Layers[layerId].push_back(sd);
00187         }
00188         else
00189         {
00190                 nlwarning ("The sound '%s' can't be loaded", sd.SoundName.c_str());
00191         }
00192 }
00193 
00194 
00195 void CBackgroundSoundManager::loadSamplesFromRegion(const NLLIGO::CPrimRegion &region)
00196 {
00197         _Banks.clear();
00198 
00199         for (uint i=0; i< region.VZones.size(); ++i)
00200         {
00201                 if (region.VZones[i].VPoints.size() > 2)
00202                 {
00203                         TBanksData      bd;
00204                         uint pointCount = region.VZones[i].VPoints.size ();
00205                         bd.Points.resize (pointCount);
00206                         for (uint j=0; j<pointCount; j++)
00207                         {
00208                                 bd.Points[j] = region.VZones[i].VPoints[j];
00209                         }
00210 
00211                         // compute bouding box.
00212                         CVector vmin(FLT_MAX, FLT_MAX, 0), vmax(-FLT_MAX, -FLT_MAX, 0);
00213 
00214                         vector<CVector>::iterator first(bd.Points.begin()), last(bd.Points.end());
00215                         for (; first != last; ++first)
00216                         {
00217                                 vmin.x = min(first->x, vmin.x);
00218                                 vmin.y = min(first->y, vmin.y);
00219                                 vmax.x = max(first->x, vmax.x);
00220                                 vmax.y = max(first->y, vmax.y);
00221                         }
00222                         bd.MaxBox = vmax;
00223                         bd.MinBox = vmin;
00224 
00225                         // parse the zone name to find the samples name.
00226                         std::vector<std::string>        splitted = split(region.VZones[i].Name, '-');
00227 
00228                         if (splitted.size() > 2)
00229                         {
00230                                 for (uint j=1; j<splitted.size()-1; ++j)
00231                                 {
00232                                         bd.Banks.push_back(splitted[j]);
00233                                 }
00234 
00235                                 // ok, store it in the container.
00236                                 _Banks.push_back(bd);
00237                         }
00238                         else
00239                         {
00240                                 nlwarning ("A sample bank patatoid name did'nt contains banks name '%s'", region.VZones[i].Name.c_str());
00241                         }
00242                 }
00243                 else
00244                 {
00245                         nlwarning ("A sample bank patatoid have less than 3 points '%s'", region.VZones[i].Name.c_str());
00246                 }
00247         }
00248 }
00249 
00250 void CBackgroundSoundManager::loadEffecsFromRegion(const NLLIGO::CPrimRegion &region)
00251 {
00252 }
00253 
00254 void CBackgroundSoundManager::loadSoundsFromRegion(const CPrimRegion &region)
00255 {
00256         uint i;
00257         // remember playing state
00258         bool oldState = _Playing;
00259         unload();
00260 
00261         for (i = 0; i < region.VZones.size(); i++)
00262         {
00263                 if(region.VZones[i].VPoints.size()>2)
00264                 {
00265                         addSound(region.VZones[i].Name, region.VZones[i].VPoints, false);
00266                 }
00267                 else
00268                 {
00269                         nlwarning ("A background sound patatoid have less than 3 points '%s'", region.VZones[i].Name.c_str());
00270                 }
00271         }
00272 
00273         for (i = 0; i < region.VPaths.size(); i++)
00274         {
00275                 if(region.VPaths[i].VPoints.size() > 1)
00276                 {
00277                         addSound(region.VPaths[i].Name, region.VPaths[i].VPoints, true);
00278                 }
00279                 else
00280                 {
00281                         nlwarning ("A background sound path have less than 2 points '%s'", region.VPaths[i].Name.c_str());
00282                 }
00283         }
00284         for (i = 0; i < region.VPoints.size(); i++)
00285         {
00286                 std::vector<CPrimVector>        points;
00287                 points.push_back(region.VPoints[i].Point);
00288 
00289                 addSound(region.VPoints[i].Name, points, false);
00290         }
00291 
00292 
00293         // restart playing ?
00294         if (oldState)
00295                 play();
00296 }
00297 
00298 void CBackgroundSoundManager::load (const string &continent)
00299 {
00300         // load the sound.
00301         {
00302                 CIFile file;
00303                 CPrimRegion region;
00304                 string fn = continent+"_audio.prim";
00305 
00306                 nlinfo ("loading '%s'", fn.c_str());
00307 
00308                 string path = CPath::lookup(fn, false);
00309 
00310                 if(!path.empty() && file.open (path))
00311                 {
00312                         CIXml xml;
00313                         xml.init (file);
00314                         region.serial(xml);
00315                         file.close ();
00316 
00317                         nlinfo ("Region '%s' contains %d zones for the background sounds", continent.c_str(), region.VZones.size());
00318 
00319                         loadSoundsFromRegion(region);
00320                 }
00321         }
00322         // load the effect.
00323         {
00324                 CIFile file;
00325                 CPrimRegion region;
00326                 string fn = continent+"_effects.prim";
00327 
00328                 nlinfo ("loading '%s'", fn.c_str());
00329 
00330                 string path = CPath::lookup(fn, false);
00331 
00332                 if(!path.empty() && file.open (path))
00333                 {
00334                         CIXml xml;
00335                         xml.init (file);
00336                         region.serial(xml);
00337                         file.close ();
00338 
00339                         nlinfo ("Region '%s' contains %d zones for the background effetcs", continent.c_str(), region.VZones.size());
00340 
00341                         loadEffecsFromRegion(region);
00342                 }
00343         }
00344         // load the samples banks.
00345         {
00346                 CIFile file;
00347                 CPrimRegion region;
00348                 string fn = continent+"_samples.prim";
00349 
00350                 nlinfo ("loading '%s'", fn.c_str());
00351 
00352                 string path = CPath::lookup(fn, false);
00353 
00354                 if(!path.empty() && file.open (path))
00355                 {
00356                         CIXml xml;
00357                         xml.init (file);
00358                         region.serial(xml);
00359                         file.close ();
00360 
00361                         nlinfo ("Region '%s' contains %d zones for the background samples banks", continent.c_str(), region.VZones.size());
00362 
00363                         loadSamplesFromRegion(region);
00364                 }
00365         }
00366 }
00367 
00368 
00369 void CBackgroundSoundManager::play ()
00370 {
00371         if (_Playing)
00372                 return;
00373 
00374         _Playing = true;
00375 
00376         updateBackgroundStatus();
00377 }
00378 
00379 
00380 void CBackgroundSoundManager::stop ()
00381 {
00382         if(!_Playing)
00383                 return;
00384         CAudioMixerUser *mixer = CAudioMixerUser::instance();
00385         
00386         for (uint i=0; i<BACKGROUND_LAYER; ++i)
00387         {
00388                 // stop all playing source
00389                 std::vector<TSoundData>::iterator first(_Layers[i].begin()), last(_Layers[i].end());
00390                 for (; first != last; ++first)
00391                 {
00392                         if (first->Source != 0 && first->Source->isPlaying())
00393                                 first->Source->stop();
00394                 }
00395         }
00396 
00397         _Playing = false;
00398 }
00399 
00400 void CBackgroundSoundManager::unload ()
00401 {
00402         stop();
00403 
00404         CAudioMixerUser *mixer = CAudioMixerUser::instance();
00405         
00406         for (uint i=0; i<BACKGROUND_LAYER; ++i)
00407         {
00408                 // delete all created source
00409                 std::vector<TSoundData>::iterator first(_Layers[i].begin()), last(_Layers[i].end());
00410                 for (; first != last; ++first)
00411                 {
00412                         if (first->Source)
00413 //                              mixer->removeSource(first->Source);
00414                                 delete first->Source;
00415                 }
00416 
00417                 // and free the layer.
00418                 _Layers[i].clear();
00419         }
00420 }
00421 
00422 void CBackgroundSoundManager::setListenerPosition (const CVector &listenerPosition)
00423 {
00424         if (_LastPosition == listenerPosition)
00425         {
00426                 return;
00427         }
00428         _LastPosition = listenerPosition;
00429 
00430         updateBackgroundStatus();
00431 }
00432 
00433 void CBackgroundSoundManager::updateBackgroundStatus()
00434 {
00435         if (!_Playing)
00436                 return;
00437 
00438         CAudioMixerUser *mixer = CAudioMixerUser::instance();
00439 
00440         // it s on 2d so we don't have z
00441         CVector listener = _LastPosition;
00442         listener.z = 0.0f;
00443 
00444         // compute the list of load/unload banks.
00445         {
00446                 // set of bank that must be in ram.
00447                 std::set<std::string>   newBanks;
00448 
00449                 std::vector<TBanksData>::iterator first(_Banks.begin()), last(_Banks.end());
00450                 for (; first != last; ++first)
00451                 {
00452                         if (listener.x >= first->MinBox.x && listener.x <= first->MaxBox.x
00453                                 && listener.y >= first->MinBox.y && listener.y <= first->MaxBox.y
00454                                 )
00455                         {
00456                                 // bounding box ok, 
00457                                 if (CPrimZone::contains(listener, first->Points))
00458                                 {
00459                                         // add the banks of this zone in the n
00460                                         newBanks.insert(first->Banks.begin(), first->Banks.end());
00461                                 }
00462                         }
00463                 }
00464                 // ok, now compute to set : the set of bank to load, and the set of banks to unload.
00465                 std::set<std::string>   noChange;
00466                 std::set_intersection(_LoadedBanks.begin(), _LoadedBanks.end(), newBanks.begin(), newBanks.end(), std::inserter(noChange, noChange.end()));
00467 
00468                 std::set<std::string>   loadList; 
00469                 std::set_difference(newBanks.begin(), newBanks.end(), noChange.begin(), noChange.end(), std::inserter(loadList, loadList.end()));
00470 
00471                 std::set<std::string>   unloadList;
00472                 std::set_difference(_LoadedBanks.begin(), _LoadedBanks.end(), newBanks.begin(), newBanks.end(), std::inserter(unloadList, unloadList.end()));
00473 
00474                 // and now, load and unload....
00475                 {
00476                         std::set<std::string>::iterator first(loadList.begin()), last(loadList.end());
00477                         for (; first != last; ++first)
00478                         {
00479                                 mixer->loadSampleBank(true, *first);
00480                         }
00481                         _LoadedBanks.insert(loadList.begin(), loadList.end());
00482                 }
00483                 {
00484                         std::set<std::string>::iterator first(unloadList.begin()), last(unloadList.end());
00485                         for (; first != last; ++first)
00486                         {
00487                                 if (mixer->unloadSampleBank(*first))
00488                                 {
00489                                         // ok, the bank is unloaded
00490                                         _LoadedBanks.erase(*first);
00491                                 }
00492                         }
00493                 }
00494         }
00495 
00496         // Apply the same algo for each sound layer.
00497         for (uint i=0; i<BACKGROUND_LAYER; ++i)
00498         {
00499                 vector<TSoundData> &layer = _Layers[i];
00500                 vector<uint> selectedIndex;
00501                 vector<uint> leaveIndex;
00502 
00503                 selectedIndex.reserve(layer.size());
00504                 leaveIndex.reserve(layer.size());
00505 
00506                 // extract the list of selected/unselected box
00507                 vector<TSoundData>::iterator first(layer.begin()), last(layer.end());
00508                 for (uint count = 0; first != last; ++first, ++count)
00509                 {
00510                         if (listener.x >= first->MinBox.x && listener.x <= first->MaxBox.x
00511                                 && listener.y >= first->MinBox.y && listener.y <= first->MaxBox.y
00512 //                              && listener.z >= first->MinBox.z && listener.z <= first->MaxBox.z
00513                                 )
00514                         {
00515 //                              nldebug("patat %u is selected by box (%s)", count, first->SoundName.c_str());
00516                                 selectedIndex.push_back(count);
00517                         }
00518                         else
00519                         {
00520 //                              nldebug("patat %u is rejected  by box (%s)", count, first->SoundName.c_str());
00521                                 // listener out of this box.
00522                                 if (first->Selected && first->Source != 0)
00523                                 {
00524                                         // we leave this box.
00525                                         leaveIndex.push_back(count);
00526                                 }
00527                         }
00528                 }
00529 
00530                 // stop all the sound that are leaved.
00531                 {
00532                         vector<uint>::iterator first(leaveIndex.begin()), last(leaveIndex.end());
00533                         for (; first != last; ++first)
00534                         {
00535                                 TSoundData &sd = layer[*first];
00536                                 sd.Selected = false;
00537                                 if (sd.Source->isPlaying())
00538                                         sd.Source->stop();
00539                         }
00540                 }
00541                 // Compute new source mixing in this layer
00542                 {
00544                         map<float, TSoundStatus>        status;
00545 
00546                         // first loop to compute selected sound gain and position and order the result by surface..
00547                         {
00548                                 vector<uint>::iterator first(selectedIndex.begin()), last(selectedIndex.end());
00549                                 for (; first != last; ++first)
00550                                 {
00551                                         TSoundData &sd = layer[*first];
00552                                         CVector pos;
00553                                         float   gain;
00554                                         float   distance;
00555 
00556                                         // inside the patat ?
00557                                         
00558                                         if(CPrimZone::contains(listener, sd.Points, distance, pos, sd.IsPath))
00559                                         {
00560                                                 pos = _LastPosition;    // use the real listener position, not the 0 z centered
00561                                                 gain = 1.0f;
00562 //                                              nlinfo ("inside patate %d name '%s' ", *first, sd.SoundName.c_str());
00563                                         }
00564                                         else
00565                                         {
00566                                                 if (distance < sd.MaxDist)
00567                                                 {
00568                                                         // compute the gain.
00569                                                         gain = (sd.MaxDist - distance) / sd.MaxDist;
00570                                                 }
00571                                                 else
00572                                                 {
00573                                                         // too far
00574                                                         gain = 0;
00575                                                 }
00576                                                 //nlinfo ("near patate %d name '%s' from %f ", *first, sd.SoundName.c_str(), distance);
00577                                         }
00578 
00579                                         // store the status.
00580                                         status.insert(make_pair(sd.Surface, TSoundStatus(sd, pos, gain, distance)));
00581                                 }
00582                         }
00583                         // second loop thrue the surface ordered selected sound.
00584                         {
00585                                 // Sound mixing strategie :
00586                                 // The smallest zone sound mask bigger one
00587 
00588                                 float   maskFactor = 1.0f;
00589 
00590                                 map<float, TSoundStatus>::iterator first(status.begin()), last(status.end());
00591                                 for (; first != last; ++first)
00592                                 {
00593                                         TSoundStatus &ss = first->second;
00594 
00595                                         if (maskFactor > 0.0f && ss.Gain > 0)
00596                                         {
00597                                                 float gain = maskFactor * ss.Gain;
00598 //                                              maskFactor -= ss.Gain;
00599 
00600                                                 ss.SoundData.Selected = true;
00601 
00602                                                 if (ss.Gain == 1)
00603                                                 {
00604                                                         // inside a pattate, then decrease the mask factor will we are more inside the patate
00605                                                         maskFactor -= first->second.Distance / INSIDE_FALLOF;
00606                                                         clamp(maskFactor, 0.0f, 1.0f);
00607                                                 }
00608 
00609                                                 // start the soond (if needed) and update the volume.
00610 
00611                                                 if (ss.SoundData.Source == 0)
00612                                                 {
00613                                                         // try to create the source.
00614                                                         ss.SoundData.Source = mixer->createSource(ss.SoundData.Sound, false);
00615                                                 }
00616                                                 if (ss.SoundData.Source != 0)
00617                                                 {
00618                                                         // set the volume
00619                                                         ss.SoundData.Source->setRelativeGain(gain);
00620                                                         // and the position
00621                                                         ss.Position.z += 5.0f;
00622                                                         ss.SoundData.Source->setPos(ss.Position);
00623 
00624 //                                                      nldebug("Setting source %s at %f", ss.SoundData.SoundName.c_str(), gain);
00625                                                         if (!ss.SoundData.Source->isPlaying())
00626                                                         {
00627                                                                 // start the sound is needed.
00628                                                                 ss.SoundData.Source->play();
00629                                                         }
00630                                                 }
00631                                         }
00632                                         else if (ss.SoundData.Source != 0 && ss.SoundData.Source->isPlaying())
00633                                         {
00634                                                 // stop this too far source.
00635                                                 ss.SoundData.Source->stop();
00636                                         }
00637                                 }
00638                         } 
00639                 } // compute source mixing
00640         } // for each layer
00641 }
00642 
00643 /*
00644 void CBackgroundSoundManager::update ()
00645 {
00646 
00647 }
00648 */
00649 /*
00650 uint32 CBackgroundSoundManager::getZoneNumber ()
00651 {
00652 //      return BackgroundSounds.size();
00653         return 0;
00654 }
00655 */
00656 /*
00657 const vector<CVector> &CBackgroundSoundManager::getZone(uint32 zone)
00658 {
00659 //      nlassert (zone< BackgroundSounds.size());
00660 //      return BackgroundSounds[zone].Points;
00661         static vector<CVector> v;
00662         return v;
00663 }
00664 */
00665 CVector CBackgroundSoundManager::getZoneSourcePos(uint32 zone)
00666 {
00667 /*      nlassert (zone< BackgroundSounds.size());
00668         CVector pos;
00669         if (BackgroundSounds[zone].SourceDay != NULL)
00670                 BackgroundSounds[zone].SourceDay->getPos(pos);
00671         return pos;
00672 */
00673         return CVector();
00674 }
00675 
00676 
00677 /*
00678 void CBackgroundSoundManager::setDayNightRatio(float ratio)
00679 {
00680         // 0 is day
00681         // 1 is night
00682 
00683         nlassert (ratio>=0.0f && ratio<=1.0f);
00684 
00685         if (OldRatio == ratio)
00686                 return;
00687         else
00688                 OldRatio = ratio;
00689 
00690 
00691         // recompute all source volume
00692 
00693         for (uint i = 0; i < BackgroundSounds.size(); i++)
00694         {
00695                 if(ratio == 0.0f)
00696                 {
00697                         if(BackgroundSounds[i].SourceDay != NULL)
00698                         {
00699                                 BackgroundSounds[i].SourceDay->setRelativeGain(1.0f);
00700 
00701                                 if (!BackgroundSounds[i].SourceDay->isPlaying())
00702                                         BackgroundSounds[i].SourceDay->play();
00703                         }
00704                         
00705                         if(BackgroundSounds[i].SourceNight != NULL)
00706                         {
00707                                 if (BackgroundSounds[i].SourceNight->isPlaying())
00708                                         BackgroundSounds[i].SourceNight->stop();
00709                         }
00710                 }
00711                 else if (ratio == 1.0f)
00712                 {
00713                         if(BackgroundSounds[i].SourceDay != NULL)
00714                         {
00715                                 if (BackgroundSounds[i].SourceDay->isPlaying())
00716                                         BackgroundSounds[i].SourceDay->stop();
00717                         }
00718 
00719                         if(BackgroundSounds[i].SourceNight != NULL)
00720                         {
00721                                 BackgroundSounds[i].SourceNight->setRelativeGain(1.0f);
00722 
00723                                 if (!BackgroundSounds[i].SourceNight->isPlaying())
00724                                         BackgroundSounds[i].SourceNight->play();
00725                         }
00726                 }
00727                 else
00728                 {
00729                         if(BackgroundSounds[i].SourceDay != NULL)
00730                         {
00731                                 BackgroundSounds[i].SourceDay->setRelativeGain((1.0f-ratio));
00732 
00733                                 if (!BackgroundSounds[i].SourceDay->isPlaying())
00734                                         BackgroundSounds[i].SourceDay->play();
00735                         }
00736 
00737                         if(BackgroundSounds[i].SourceNight != NULL)
00738                         {
00739                                 BackgroundSounds[i].SourceNight->setRelativeGain(ratio);
00740 
00741                                 if (!BackgroundSounds[i].SourceNight->isPlaying())
00742                                         BackgroundSounds[i].SourceNight->play();
00743                         }
00744                 }
00745         }
00746 
00747 }
00748 */
00749 } // NLSOUND
00750