00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
00112
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
00127 sd.Surface = (vmax.x - vmin.x) * (vmax.y - vmin.y);
00128
00129
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
00139
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
00154 n = std::count(rawSoundName.begin(), rawSoundName.end(), '-');
00155
00156 if (n == 2)
00157 {
00158
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
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
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
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
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
00279
00280
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
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
00324 loadAudioFromPrimitives(*child);
00325
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
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
00356 if (!layerString.empty())
00357 {
00358
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
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
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
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
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
00532 _Banks.push_back(bd);
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 void CBackgroundSoundManager::load (const string &continent, NLLIGO::CLigoConfig &config)
00618 {
00619 uint32 PACKED_VERSION = 1;
00620
00621 {
00622 CIFile file;
00623
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
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
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
00675 file.close ();
00676
00677 {
00678 H_AUTO(BackgroundSoundMangerLoad_loadAudioFromPrimitive);
00679 loadAudioFromPrimitives(*primitives.RootNode);
00680 }
00681
00682
00683 CAudioMixerUser *mixer = CAudioMixerUser::instance();
00684 if (mixer->getPackedSheetUpdate())
00685 {
00686
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
00699 return;
00700 }
00701
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
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
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
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
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
00827 std::vector<TSoundData>::iterator first(_Layers[i].begin()), last(_Layers[i].end());
00828 for (; first != last; ++first)
00829 {
00830 if (first->Source)
00831
00832 delete first->Source;
00833 }
00834
00835
00836 _Layers[i].clear();
00837 }
00838
00839
00840 _Banks.clear();
00841
00842
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
00866 CVector listener = _LastPosition;
00867 listener.z = 0.0f;
00868
00869
00870
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
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
00898 if (CPrimZone::contains(listener, first->Points))
00899 {
00900
00901 if (rootCluster)
00902 {
00903
00904 rootCluster->setEnvironmentFx(first->FxName);
00905 }
00906 else
00907 {
00908
00909 if (_LastEnv != first->FxName)
00910 {
00911
00912 _LastEnv = first->FxName;
00913 mixer->setEnvironment(first->FxName, 10.f);
00914 }
00915 }
00916 break;
00917 }
00918 }
00919 }
00920 }
00921
00922
00923
00924 {
00925 H_AUTO(NLSOUND_LoadUnloadSampleBank)
00926
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
00937 if (CPrimZone::contains(listener, first->Points))
00938 {
00939
00940 newBanks.insert(first->Banks.begin(), first->Banks.end());
00941 }
00942 }
00943 }
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
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
00976 {
00977 std::set<std::string>::iterator first(loadList.begin()), last(loadList.end());
00978 for (; first != last; ++first)
00979 {
00980
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
00990 if (mixer->unloadSampleBank(*first))
00991 {
00992
00993 _LoadedBanks.erase(*first);
00994 }
00995 else if (CSampleBank::findSampleBank(CStringMapper::map(*first)) == 0)
00996 {
00997
00998 _LoadedBanks.erase(*first);
00999 }
01000 }
01001 }
01002 }
01003
01004 H_BEFORE(NLSOUND_UpdateSoundLayer)
01005
01006 NL3D::CCluster *rootCluster = 0;
01007 if (mixer->getClusteredSound() != 0)
01008 rootCluster = mixer->getClusteredSound()->getRootCluster();
01009
01010
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
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
01027 )
01028 {
01029
01030 selectedIndex.push_back(count);
01031 }
01032 else
01033 {
01034
01035
01036 if (first->Selected && first->Source != 0)
01037 {
01038
01039 leaveIndex.push_back(count);
01040 }
01041 }
01042 }
01043
01044
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
01056 {
01058 list<pair<float, TSoundStatus> > status;
01059
01060
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
01072
01073 if(CPrimZone::contains(listener, sd.Points, distance, pos, sd.IsPath))
01074 {
01075 inside = true;
01076 pos = _LastPosition;
01077 gain = 1.0f;
01078
01079 }
01080 else
01081 {
01082 if (sd.MaxDist>0 && distance < sd.MaxDist)
01083 {
01084
01085
01086 }
01087 else
01088 {
01089
01090 gain = 0;
01091 }
01092
01093 }
01094
01095
01096 status.push_back(make_pair(sd.Surface, TSoundStatus(sd, pos, gain, distance, inside)));
01097 }
01098 }
01099
01100 {
01101
01102
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
01112 bool musicSound= ss.SoundData.Sound && ss.SoundData.Sound->getSoundType()==CSound::SOUND_MUSIC;
01113
01114
01115 if(musicSound)
01116 {
01117 if (ss.Gain > 0)
01118 {
01119 ss.SoundData.Selected = true;
01120
01121
01122 if (ss.SoundData.Source == 0)
01123 {
01124
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
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
01136 ss.SoundData.Source->play();
01137 }
01138 }
01139 }
01140 else if (ss.SoundData.Source != 0 && ss.SoundData.Source->isPlaying())
01141 {
01142
01143 ss.SoundData.Source->stop();
01144 }
01145 }
01146
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
01159
01160 ss.SoundData.Selected = true;
01161
01162
01163
01164 if (ss.Inside)
01165 {
01166
01167 maskFactor -= first->second.Distance / INSIDE_FALLOF;
01168 clamp(maskFactor, 0.0f, 1.0f);
01169 }
01170
01171
01172
01173 if (ss.SoundData.Source == 0)
01174 {
01175
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
01181 ss.SoundData.Source->setRelativeGain(gain);
01182
01183 ss.Position.z = _LastPosition.z + BACKGROUND_SOUND_ALTITUDE;
01184 ss.SoundData.Source->setPos(ss.Position);
01185
01186
01187 if (!ss.SoundData.Source->isPlaying())
01188 {
01189
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
01199 ss.SoundData.Source->stop();
01200 }
01201 }
01202 }
01203 }
01204 }
01205 }
01206
01207 H_AFTER(NLSOUND_UpdateSoundLayer)
01208
01209
01210 H_BEFORE(NLSOUND_DoFadeInOut)
01211
01212 if (_DoFade)
01213 {
01214 TTime now = NLMISC::CTime::getLocalTime();
01215 _DoFade = false;
01216 uint i;
01217
01218
01219 for (i=0; i< UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS; ++i)
01220 {
01221 if (_FilterFadesStart[i] != 0)
01222 {
01223
01224 if (_BackgroundFlags.Flags[i])
01225 {
01226
01227 TTime delta = now - _FilterFadesStart[i];
01228 if (delta > _BackgroundFilterFades.FadeOuts[i])
01229 {
01230
01231 _FilterFadeValues[i] = 0;
01232
01233 _FilterFadesStart[i] = 0;
01234 }
01235 else
01236 {
01237 _FilterFadeValues[i] = 1 - (float(delta) / _BackgroundFilterFades.FadeOuts[i]);
01238
01239 _DoFade |= true;
01240 }
01241 }
01242 else
01243 {
01244
01245 TTime delta = now - _FilterFadesStart[i];
01246 if (delta > _BackgroundFilterFades.FadeIns[i])
01247 {
01248
01249 _FilterFadeValues[i] = 1;
01250
01251 _FilterFadesStart[i] = 0;
01252 }
01253 else
01254 {
01255 _FilterFadeValues[i] = float(delta) / _BackgroundFilterFades.FadeIns[i];
01256
01257 _DoFade |= true;
01258 }
01259 }
01260 }
01261 }
01262
01263
01264
01265 for (i=0; i<BACKGROUND_LAYER; ++i)
01266 {
01267
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
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
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
01297 if (backgroundFlags.Flags[i])
01298 {
01299
01300 _FilterFadesStart[i] = uint64(NLMISC::CTime::getLocalTime() - (1-_FilterFadeValues[i]) * _BackgroundFilterFades.FadeOuts[i]);
01301 _DoFade = true;
01302 }
01303 else
01304 {
01305
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
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 CVector CBackgroundSoundManager::getZoneSourcePos(uint32 )
01348 {
01349
01350
01351
01352
01353
01354
01355 return CVector();
01356 }
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
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 }
01486