00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdsound.h"
00027
00028
00029
00030 #include "simple_sound.h"
00031 #include "complex_sound.h"
00032
00033
00034
00035 #include "driver/buffer.h"
00036 #include "sample_bank.h"
00037 #include "sound_bank.h"
00038 #include "background_sound_manager.h"
00039 #include "simple_source.h"
00040 #include "complex_source.h"
00041 #include "background_source.h"
00042
00043
00044 #include "nel/misc/file.h"
00045 #include "nel/misc/path.h"
00046 #include "nel/misc/time_nl.h"
00047 #include "nel/misc/command.h"
00048
00049 #include "context_sound.h"
00050 #include <iomanip.h>
00051
00052
00053
00054 using namespace NLMISC;
00055
00056 using namespace std;
00057
00058
00059 namespace NLSOUND {
00060
00061
00062 #ifdef _DEBUG
00063 CAudioMixerUser::IMixerEvent *CurrentEvent = 0;
00064 #endif
00065
00066
00067 #define NL_TRACE_MIXER 0
00068
00069 #if NL_TRACE_MIXER
00070 #define _profile(_a) nldebug ## _a
00071 #else
00072 #define _profile(_a)
00073 #endif
00074
00075
00076 CAudioMixerUser *CAudioMixerUser::_Instance = NULL;
00077
00078
00079 const char *PriToCStr [NbSoundPriorities] = { "XH", "HI", "MD", "LO" };
00080
00081
00082
00083
00084 const char *getPriorityStr( TSoundPriority p )
00085 {
00086 nlassert( ((uint)p) < NbSoundPriorities );
00087 return PriToCStr[p];
00088 }
00089
00090
00091
00092
00093 UAudioMixer *UAudioMixer::createAudioMixer()
00094 {
00095 return new CAudioMixerUser();
00096 }
00097
00098
00099
00100
00101 CAudioMixerUser::CAudioMixerUser() : _SoundDriver(NULL),
00102 _ListenPosition(CVector::Null),
00103
00104
00105 _CurEnvEffect(NULL),
00106 _NbTracks(0),
00107 _MaxNbTracks(0),
00108 _Leaving(false),
00109 _BackgroundSoundManager(0),
00110 _PlayingSources(0)
00111 {
00112 if ( _Instance == NULL )
00113 {
00114 _Instance = this;
00115
00116 #if NL_PROFILE_MIXER
00117 _UpdateTime = 0.0;
00118 _CreateTime = 0.0;
00119 _UpdateCount = 0;
00120 _CreateCount = 0;
00121 #endif
00122
00123 }
00124 else
00125 {
00126 nlerror( "Audio mixer singleton instanciated twice" );
00127 }
00128 }
00129
00130
00131
00132
00133 CAudioMixerUser::~CAudioMixerUser()
00134 {
00135 nldebug( "AM: Releasing..." );
00136
00137 if (_BackgroundSoundManager != 0)
00138 delete _BackgroundSoundManager;
00139
00140
00141 reset();
00142
00143 _Leaving = true;
00144
00145
00146 CSoundBank::release();
00147
00148 CSampleBank::releaseAll();
00149
00150
00151 uint i;
00152 for ( i=0; i!=_NbTracks; i++ )
00153 {
00154 if ( _Tracks[i] )
00155 delete _Tracks[i];
00156 }
00157
00158
00159 if ( _SoundDriver != NULL )
00160 delete _SoundDriver;
00161
00162 _Instance = NULL;
00163
00164 nldebug( "AM: Released" );
00165 }
00166
00167
00168 void CAudioMixerUser::setPriorityReserve(TSoundPriority priorityChannel, uint reserve)
00169 {
00170 _PriorityReserve[priorityChannel] = min(_NbTracks, reserve);
00171 }
00172
00173 void CAudioMixerUser::setLowWaterMark(uint value)
00174 {
00175 _LowWaterMark = min(_NbTracks, value);
00176 }
00177
00178
00179
00180
00181 void CAudioMixerUser::writeProfile(std::ostream& out)
00182 {
00183
00184 uint nb = 0;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 out << "Mixer: \n";
00207 out << "Playing sources: " << getPlayingSourcesNumber() << " \n";
00208 out << "Available tracks: " << getNumberAvailableTracks() << " \n";
00209
00210
00211 out << "Muted sources: " << max(0, sint(_PlayingSources)-sint(_NbTracks)) << " \n";
00212 out << "Sources waiting for play: " << _SourceWaitingForPlay.size() << " \n";
00213 out << "HighestPri: " << _ReserveUsage[HighestPri] << " \n";
00214 out << "HighPri: " << _ReserveUsage[HighPri] << " \n";
00215 out << "MidPri: " << _ReserveUsage[MidPri] << " \n";
00216 out << "LowPri: " << _ReserveUsage[LowPri] << " \n";
00217 out << "Average update time: " << std::setw(10) << (1000.0 * _UpdateTime / _UpdateCount) << " msec\n";
00218 out << "Average create time: " << std::setw(10) <<(1000.0 * _CreateTime / _CreateCount) << " msec\n";
00219 out << "Estimated CPU: " << std::setiosflags(ios::right) << std::setprecision(6) << std::setw(10) << (100.0 * 1000.0 * (_UpdateTime + _CreateTime) / curTime()) << "%\n";
00220
00221 if (_SoundDriver)
00222 {
00223 out << "\n";
00224 out << "Driver: \n";
00225 _SoundDriver->writeProfile(out);
00226 }
00227 }
00228
00229
00230
00231 void CAudioMixerUser::addSourceWaitingForPlay(CSimpleSource *source)
00232 {
00233 _SourceWaitingForPlay.push_back(source);
00234 }
00235
00236
00237
00238
00239 void CAudioMixerUser::reset()
00240 {
00241 _Leaving = true;
00242
00243 _SourceWaitingForPlay.clear();
00244
00245
00246 uint i;
00247 for ( i=0; i!=_NbTracks; i++ )
00248 {
00249 if ( _Tracks[i] )
00250 {
00251 CSimpleSource* src = _Tracks[i]->getSource();
00252
00253 if (src && src->isPlaying())
00254 {
00255 src->stop();
00256 }
00257 }
00258 }
00259
00260
00261 while (!_Sources.empty())
00262 {
00263
00264 CSourceCommon *source = *(_Sources.begin());
00265 if (source->isPlaying())
00266 source->stop();
00267 else
00268 delete source;
00269 }
00270
00271 _Leaving = false;
00272 }
00273
00274
00275
00276 void CAudioMixerUser::init( )
00277 {
00278 nldebug( "AM: Init..." );
00279
00280 _profile(( "AM: ---------------------------------------------------------------" ));
00281 _profile(( "AM: DRIVER: %s", NLSOUND_DLL_NAME ));
00282
00283
00284 try
00285 {
00286 _SoundDriver = ISoundDriver::createDriver();
00287 }
00288 catch(...)
00289 {
00290 delete this;
00291 _Instance = NULL;
00292 throw;
00293 }
00294
00295 uint i;
00296
00297
00298
00299 static bool initialized = false;
00300 if (!initialized)
00301 {
00302
00303 initialized = true;
00304 }
00305
00306
00307 _Listener.init( _SoundDriver );
00308
00309
00310 _NbTracks = MAX_TRACKS;
00311 for ( i=0; i<MAX_TRACKS; i++ )
00312 {
00313 _Tracks[i] = NULL;
00314 }
00315 try
00316 {
00317 for ( i=0; i!=_NbTracks; i++ )
00318 {
00319 _Tracks[i] = new CTrack();
00320 _Tracks[i]->init( _SoundDriver );
00321 _FreeTracks.push_back(_Tracks[i]);
00322 }
00323 }
00324 catch ( ESoundDriver & )
00325 {
00326
00327 _NbTracks = i;
00328
00329 }
00330
00331 _MaxNbTracks = _NbTracks;
00332
00333
00334 _LowWaterMark = 0;
00335 for (i=0; i<NbSoundPriorities; ++i)
00336 {
00337 _PriorityReserve[i] = _NbTracks;
00338 _ReserveUsage[i] = 0;
00339 }
00340
00341 _StartTime = CTime::getLocalTime();
00342
00343
00344 _BackgroundSoundManager = new CBackgroundSoundManager();
00345
00346
00347 CSoundBank::instance()->load();
00348 nlinfo( "Initialized audio mixer with %u voices", _NbTracks );
00349 }
00350
00351
00352
00353 void CAudioMixerUser::bufferUnloaded(IBuffer *buffer)
00354 {
00355
00356 uint i;
00357 for ( i=0; i!=_NbTracks; ++i )
00358 {
00359 CTrack *track = _Tracks[i];
00360 if ( track && track->getSource())
00361 {
00362 if (track->getSource()->getBuffer() == buffer)
00363 {
00364 track->getSource()->stop();
00365 }
00366 }
00367 }
00368
00369 }
00370
00371
00372
00373
00374 void CAudioMixerUser::enable( bool b )
00375 {
00376
00377
00378 nlassert(false);
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 }
00401
00402
00403
00404 ISoundDriver* CAudioMixerUser::getSoundDriver()
00405 {
00406 return _SoundDriver;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 void CAudioMixerUser::getFreeTracks( uint nb, CTrack **tracks )
00445 {
00446 std::vector<CTrack*>::iterator first(_FreeTracks.begin()), last(_FreeTracks.end());
00447 for (nb =0; first != last; ++first, ++nb)
00448 {
00449 tracks[nb] = *first;
00450 }
00451 }
00452
00453
00454
00455
00456 void CAudioMixerUser::applyListenerMove( const NLMISC::CVector& listenerpos )
00457 {
00458
00459 _ListenPosition = listenerpos;
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 }
00471
00472
00473
00474 void CAudioMixerUser::reloadSampleBanks(bool async)
00475 {
00476 CSampleBank::reload(async);
00477 }
00478
00479
00480
00481 CTrack *CAudioMixerUser::getFreeTrack(CSimpleSource *source)
00482 {
00483
00484 if (!_FreeTracks.empty())
00485 {
00486
00487 if (_FreeTracks.size() > _LowWaterMark
00488 || _ReserveUsage[source->getPriority()] < _PriorityReserve[source->getPriority()] )
00489 {
00490
00491 if (source->getPriority() == HighestPri
00492 || _FreeTracks.size() > _SourceWaitingForPlay.size())
00493 {
00494 CTrack *ret = _FreeTracks.back();
00495 _FreeTracks.pop_back();
00496 ret->setSource(source);
00497 _ReserveUsage[source->getPriority()]++;
00498
00499 return ret;
00500 }
00501 }
00502 }
00503
00504 {
00505 float d1, d2, t1, t2;
00506 d1 = (source->getPos() - _ListenPosition).norm();
00507 t1 = max(0.0f, 1-((d1-source->getSimpleSound()->getMinDistance()) / (source->getSimpleSound()->getMaxDistance() - source->getSimpleSound()->getMinDistance())));
00508
00509 for (uint i=0; i<_NbTracks; ++i)
00510 {
00511 CSimpleSource *src2 = _Tracks[i]->getSource();
00512 if (src2 != 0)
00513 {
00514 d2 = (src2->getPos() - _ListenPosition).norm();
00515 t2 = max(0.0f, 1-((d2-src2->getSimpleSound()->getMinDistance()) / (src2->getSimpleSound()->getMaxDistance() - src2->getSimpleSound()->getMinDistance())));
00516
00517 const float tfactor = 1.3f;
00518 if (t1 > t2 * tfactor)
00519
00520 {
00521 nldebug("Cutting source %p with source %p (%f > %f*%f)", src2, source, t1, tfactor, t2);
00522
00523 src2->stop();
00524 if (_FreeTracks.empty())
00525 {
00526 nlwarning("No free track after cutting a playing sound source !");
00527 }
00528 else
00529 {
00530 CTrack *ret = _FreeTracks.back();
00531 _FreeTracks.pop_back();
00532 ret->setSource(source);
00533 nldebug("Track %p assign to source %p", ret, ret->getSource());
00534 return ret;
00535 }
00536 }
00537 }
00538 }
00539 }
00540
00541 return 0;
00542 }
00543
00544 void CAudioMixerUser::freeTrack(CTrack *track)
00545 {
00546 nlassert(track != 0);
00547 nlassert(track->getSource() != 0);
00548
00549
00550
00551 _ReserveUsage[track->getSource()->getPriority()]--;
00552 track->setSource(0);
00553 _FreeTracks.push_back(track);
00554 }
00555
00556
00557 void CAudioMixerUser::getPlayingSoundsPos(std::vector<std::pair<bool, NLMISC::CVector> > &pos)
00558 {
00559 int nbplay = 0;
00560 int nbmute = 0;
00561 int nbsrc = 0;
00562
00563 TSourceContainer::iterator first(_Sources.begin()), last(_Sources.end());
00564 for (; first != last; ++first)
00565 {
00566 CSourceCommon *ps = *first;
00567 if (ps->getType() == CSourceCommon::SOURCE_SIMPLE)
00568 {
00569 CSimpleSource *source = static_cast<CSimpleSource*>(*first);
00570 nbsrc++;
00571
00572 if (source->isPlaying())
00573 {
00574 pos.push_back(make_pair(source->getTrack() == 0, source->getPos()));
00575
00576 if (source->getTrack() == 0)
00577 nbmute++;
00578 else
00579 {
00580
00581 nbplay ++;
00582 }
00583 }
00584 }
00585 }
00586
00587
00588 }
00589
00590
00591
00592 void CAudioMixerUser::update()
00593 {
00594 #if NL_PROFILE_MIXER
00595 TTicks start = CTime::getPerformanceTime();
00596 #endif
00597
00598
00599 {
00600
00601 {
00602 std::vector<std::pair<IMixerUpdate*, bool> >::iterator first(_UpdateEventList.begin()), last(_UpdateEventList.end());
00603 for (; first != last; ++first)
00604 {
00605 if (first->second)
00606 _UpdateList.insert(first->first);
00607 else
00608 _UpdateList.erase(first->first);
00609 }
00610 _UpdateEventList.clear();
00611 }
00612
00613 {
00614 TMixerUpdateContainer::iterator first(_UpdateList.begin()), last(_UpdateList.end());
00615 for (; first != last; ++first)
00616 {
00617
00618 const_cast<IMixerUpdate*>(*first)->onUpdate();
00619 }
00620 }
00621 }
00622
00623 {
00624
00625 {
00626 std::vector<std::pair<NLMISC::TTime, IMixerEvent*> >::iterator first(_EventListUpdate.begin()), last(_EventListUpdate.end());
00627 for (; first != last; ++first)
00628 {
00629 if (first->first != 0)
00630 {
00631
00632
00633 TTimedEventContainer::iterator it(_EventList.insert(*first));
00634 _Events.insert(make_pair(first->second, it));
00635 }
00636 else
00637 {
00638
00639 pair<TEventContainer::iterator, TEventContainer::iterator> range = _Events.equal_range(first->second);
00640 TEventContainer::iterator first2(range.first), last2(range.second);
00641 for (; first2 != last2; ++first2)
00642 {
00643
00644 nldebug("Remove event %p", first2->second->second);
00645 _EventList.erase(first2->second);
00646 }
00647 _Events.erase(range.first, range.second);
00648 }
00649 }
00650
00651 _EventListUpdate.clear();
00652 }
00653
00654 TTime now = NLMISC::CTime::getLocalTime();
00655 while (!_EventList.empty() && _EventList.begin()->first <= now)
00656 {
00657 #ifdef _DEBUG
00658 CurrentEvent = _EventList.begin()->second;
00659 #endif
00660
00661 _EventList.begin()->second->onEvent();
00662 TEventContainer::iterator it(_Events.lower_bound(_EventList.begin()->second));
00663 while (it->first == _EventList.begin()->second)
00664 {
00665 if (it->second == _EventList.begin())
00666 {
00667 _Events.erase(it);
00668 break;
00669 }
00670 it++;
00671 }
00672 _EventList.erase(_EventList.begin());
00673 #ifdef _DEBUG
00674 CurrentEvent = 0;
00675 #endif
00676 }
00677 }
00678
00679
00680
00681
00682
00683 for (uint i=0; i<_NbTracks; ++i)
00684 {
00685 if (!_Tracks[i]->isPlaying())
00686 {
00687 if (_Tracks[i]->getSource() != 0)
00688 {
00689 CSimpleSource *source = _Tracks[i]->getSource();
00690 source->stop();
00691 }
00692
00693
00694 if (!_SourceWaitingForPlay.empty())
00695 {
00696
00697 if (_Sources.find(_SourceWaitingForPlay.front()) != _Sources.end())
00698 _SourceWaitingForPlay.front()->play();
00699 nldebug("Before POP Sources waiting : %u", _SourceWaitingForPlay.size());
00700 _SourceWaitingForPlay.pop_front();
00701 nldebug("After POP Sources waiting : %u", _SourceWaitingForPlay.size());
00702 }
00703 }
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 _SoundDriver->commit3DChanges();
00724
00725 #if NL_PROFILE_MIXER
00726 _UpdateTime = CTime::ticksToSecond(CTime::getPerformanceTime() - start);
00727 _UpdateCount++;
00728 #endif
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 TSoundId CAudioMixerUser::getSoundId( const std::string &name )
00756 {
00757 return CSoundBank::instance()->getSound(name);
00758 }
00759
00760
00761
00762 void CAudioMixerUser::addSource( CSourceCommon *source )
00763 {
00764 nlassert(_Sources.find(source) == _Sources.end());
00765 _Sources.insert( source );
00766
00767
00768
00769
00770 }
00771
00772
00773
00774
00775 USource *CAudioMixerUser::createSource( TSoundId id, bool spawn, TSpawnEndCallback cb, void *userParam, CSoundContext *context )
00776 {
00777 #if NL_PROFILE_MIXER
00778 TTicks start = CTime::getPerformanceTime();
00779 #endif
00780
00781 _profile(( "AM: [%u]---------------------------------------------------------------", curTime() ));
00782 _profile(( "AM: CREATESOURCE: SOUND=%p, NAME=%s, TIME=%d", id, id->getName().c_str(), curTime() ));
00783 _profile(( "AM: SOURCES: %d, PLAYING: %d, TRACKS: %d", getSourcesNumber(), getPlayingSourcesNumber(), getNumberAvailableTracks() ));
00784
00785 if ( id == NULL )
00786 {
00787 _profile(("AM: FAILED CREATESOURCE"));
00788 nldebug( "AM: Sound not created: invalid sound id" );
00789 return NULL;
00790 }
00791
00792 USource *ret = NULL;
00793
00794 if (id->getSoundType() == CSound::SOUND_SIMPLE)
00795 {
00796 CSimpleSound *simpleSound = static_cast<CSimpleSound *>(id);
00797
00798 if (simpleSound->getBuffer() == NULL)
00799 {
00800 nlwarning ("Can't create the sound '%s'", simpleSound->getBuffername().c_str());
00801 return NULL;
00802 }
00803
00804
00805 CSimpleSource *source = new CSimpleSource( simpleSound, spawn, cb, userParam);
00806
00807
00808
00809 if (source->getBuffer() != 0)
00810 {
00811
00812 if ( source->getBuffer()->isStereo() )
00813 {
00814 source->set3DPositionVector( &_ListenPosition );
00815 }
00816 }
00817 else
00818 {
00819 nlassert(false);
00820 }
00821 ret = source;
00822 }
00823 else if (id->getSoundType() == CSound::SOUND_COMPLEX)
00824 {
00825 CComplexSound *complexSound = static_cast<CComplexSound*>(id);
00826
00827 ret = new CComplexSource(complexSound, spawn, cb, userParam);
00828 }
00829 else if (id->getSoundType() == CSound::SOUND_BACKGROUND)
00830 {
00831
00832 CBackgroundSound *bgSound = static_cast<CBackgroundSound *>(id);
00833 ret = new CBackgroundSource(bgSound, spawn, cb, userParam);
00834 }
00835 else if (id->getSoundType() == CSound::SOUND_CONTEXT)
00836 {
00837
00838 if (context != 0)
00839 {
00840 CContextSound *ctxSound = static_cast<CContextSound *>(id);
00841
00842 CSound *sound = ctxSound->getContextSound(*context);
00843 if (sound != 0)
00844 {
00845 ret = createSource(sound, spawn, cb, userParam);
00846
00847 if (ret != 0)
00848 ret->setGain(ret->getGain() * ctxSound->getGain());
00849 }
00850 else
00851 ret = 0;
00852 }
00853 else
00854 ret = 0;
00855 }
00856 else
00857 {
00858
00859 nlwarning("Unknow sound class : %u", id->getSoundType());
00860 }
00861
00862 #if NL_PROFILE_MIXER
00863 _CreateTime = CTime::ticksToSecond(CTime::getPerformanceTime() - start);
00864 _CreateCount++;
00865 #endif
00866
00867
00868 return ret;
00869 }
00870
00871
00872
00873
00874 USource *CAudioMixerUser::createSource( const std::string &name, bool spawn, TSpawnEndCallback cb, void *userParam, CSoundContext *context)
00875 {
00876 return createSource( getSoundId( name ), spawn, cb, userParam, context );
00877 }
00878
00879
00880
00881
00882 void CAudioMixerUser::removeSource( CSourceCommon *source )
00883 {
00884 nlassert( source != NULL );
00885
00886 size_t n = _Sources.erase(source);
00887 nlassert(n == 1);
00888 }
00889
00890
00891
00892
00893 void CAudioMixerUser::selectEnvEffects( const std::string &tag )
00894 {
00895 nlassertex(false, ("Not implemented yet"));
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 }
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 uint32 CAudioMixerUser::loadSampleBank(bool async, const std::string &filename, std::vector<std::string> *notfoundfiles )
00946 {
00947
00948
00949 string path = _SamplePath;
00950 path.append("/").append(filename);
00951
00952 nldebug( "Loading samples from %s...", path.c_str() );
00953
00954 CSampleBank* bank = CSampleBank::findSampleBank(path);
00955 if (bank == NULL)
00956 {
00957
00958
00959 bank = new CSampleBank(path, _SoundDriver);
00960
00961 }
00962
00963 try
00964 {
00965 bank->load(async);
00966 }
00967 catch (Exception& e)
00968 {
00969 if (notfoundfiles) {
00970 notfoundfiles->push_back(path);
00971 }
00972 string reason = e.what();
00973 nlwarning( "AM: Failed to load the samples: %s", reason.c_str() );
00974 }
00975
00976
00977 return bank->countSamples();
00978 }
00979
00980 bool CAudioMixerUser::unloadSampleBank( const std::string &filename)
00981 {
00982 string path = _SamplePath;
00983 path.append("/").append(filename);
00984
00985 nldebug( "Unloading samples from %s...", path.c_str() );
00986 CSampleBank *pbank = CSampleBank::findSampleBank(path);
00987
00988 if (pbank != NULL)
00989 {
00990
00991 return pbank->unload();
00992 }
00993 else
00994 return false;
00995
00996 }
00997
00998
00999
01000 void CAudioMixerUser::getSoundNames( std::vector<std::string>& names ) const
01001 {
01002 CSoundBank::instance()->getNames(names);
01003 }
01004
01005
01006
01007
01008 uint CAudioMixerUser::getPlayingSourcesNumber() const
01009 {
01010 return _PlayingSources;
01011 }
01012
01013
01014
01015 uint CAudioMixerUser::getNumberAvailableTracks() const
01016 {
01017 return _FreeTracks.size();
01018 }
01019
01020
01021
01022
01023 string CAudioMixerUser::getSourcesStats() const
01024 {
01025
01026
01027 string s;
01028 TSourceContainer::iterator ips;
01029 for ( ips=_Sources.begin(); ips!=_Sources.end(); ++ips )
01030 {
01031 if ( (*ips)->isPlaying() )
01032 {
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042 }
01043 }
01044 return s;
01045
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 struct CompareSources : public binary_function<const CSimpleSource*, const CSimpleSource*, bool>
01077 {
01078
01079 CompareSources( const CVector &pos ) : _Pos(pos) {}
01080
01081
01082 bool operator()( const CSimpleSource *s1, const CSimpleSource *s2 )
01083 {
01084 if (s1->getPriority() < s2->getPriority())
01085 {
01086 return true;
01087 }
01088 else if (s1->getPriority() == s2->getPriority())
01089 {
01090
01091 const CVector &src1pos = s1->getPos();
01092 const CVector &src2pos = s2->getPos();;
01093 return ( (src1pos-_Pos).sqrnorm() < (src2pos-_Pos).sqrnorm() );
01094 }
01095 else
01096 {
01097 return false;
01098 }
01099 }
01100
01101
01102 const CVector &_Pos;
01103 };
01104
01105
01106
01107 uint32 CAudioMixerUser::getLoadedSampleSize()
01108 {
01109 return CSampleBank::getTotalByteSize();
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 void CAudioMixerUser::setListenerPos (const NLMISC::CVector &pos)
01217 {
01218 _Listener.setPos(pos);
01219 _BackgroundSoundManager->setListenerPosition(pos);
01220 }
01221
01222 NLMISC_COMMAND (displaySoundInfo, "Display information about the audio mixer", "")
01223 {
01224 if(args.size() != 0) return false;
01225
01226 if (CAudioMixerUser::instance() == NULL)
01227 {
01228 log.displayNL ("No audio mixer available");
01229 return true;
01230 }
01231
01232 log.displayNL ("%d tracks, MAX_TRACKS = %d, contains:", CAudioMixerUser::instance()->_NbTracks, MAX_TRACKS);
01233
01234 for (uint i = 0; i < CAudioMixerUser::instance()->_NbTracks; i++)
01235 {
01236 if (CAudioMixerUser::instance()->_Tracks[i] == NULL)
01237 {
01238 log.displayNL ("Track %d is NULL", i);
01239 }
01240 else
01241 {
01242 log.displayNL ("Track %d %s available and %s playing.", i, (CAudioMixerUser::instance()->_Tracks[i]->isAvailable()?"is":"is not"), (CAudioMixerUser::instance()->_Tracks[i]->isPlaying()?"is":"is not"));
01243 if (CAudioMixerUser::instance()->_Tracks[i]->getSource() == NULL)
01244 {
01245 log.displayNL (" CUserSource is NULL");
01246 }
01247 else
01248 {
01249 const CVector &pos = CAudioMixerUser::instance()->_Tracks[i]->getSource()->getPos();
01250 string bufname;
01251 if (CAudioMixerUser::instance()->_Tracks[i]->getSource()->getBuffer())
01252 bufname = CAudioMixerUser::instance()->_Tracks[i]->getSource()->getBuffer()->getName();
01253 log.displayNL (" CUserSource is id %d buffer name '%s' pos %f %f %f", CAudioMixerUser::instance()->_Tracks[i]->getSource()->getSound(), bufname.c_str(), pos.x, pos.y, pos.z);
01254 }
01255 }
01256 }
01257
01258 return true;
01259 }
01260
01261 void CAudioMixerUser::registerBufferAssoc(CSound *sound, IBuffer *buffer)
01262 {
01263 _BufferToSources[buffer].push_back(sound);
01264 }
01265
01266 void CAudioMixerUser::unregisterBufferAssoc(CSound *sound, IBuffer *buffer)
01267 {
01268 TBufferToSourceContainer::iterator it(_BufferToSources.find(buffer));
01269 if (it != _BufferToSources.end())
01270 {
01271 std::vector<CSound*>::iterator first(it->second.begin()), last(it->second.end());
01272
01273 for (; first != last; ++first)
01274 {
01275 if (*first == sound)
01276 {
01277 it->second.erase(first);
01278 break;
01279 }
01280 }
01281 }
01282 }
01283
01284
01286 void CAudioMixerUser::registerUpdate(CAudioMixerUser::IMixerUpdate *pmixerUpdate)
01287 {
01288 _UpdateEventList.push_back(make_pair(pmixerUpdate, true));
01289 }
01291 void CAudioMixerUser::unregisterUpdate(CAudioMixerUser::IMixerUpdate *pmixerUpdate)
01292 {
01293 _UpdateEventList.push_back(make_pair(pmixerUpdate, false));
01294 }
01295
01297 void CAudioMixerUser::addEvent( CAudioMixerUser::IMixerEvent *pmixerEvent, const NLMISC::TTime &date)
01298 {
01299
01300 _EventListUpdate.push_back(make_pair(date, pmixerEvent));
01301 }
01303 void CAudioMixerUser::removeEvents( CAudioMixerUser::IMixerEvent *pmixerEvent)
01304 {
01305
01306
01307 _EventListUpdate.push_back(make_pair(0, pmixerEvent));
01308 }
01309
01310 void CAudioMixerUser::setBackgroundFlags(const TBackgroundFlags &backgroundFlags)
01311 {
01312 _BackgroundSoundManager->setBackgroundFlags(backgroundFlags);
01313 }
01314
01315 void CAudioMixerUser::loadBackgroundSoundFromRegion (const NLLIGO::CPrimRegion ®ion)
01316 {
01317 _BackgroundSoundManager->loadSoundsFromRegion(region);
01318 }
01319
01320 void CAudioMixerUser::loadBackgroundEffectsFromRegion (const NLLIGO::CPrimRegion ®ion)
01321 {
01322 _BackgroundSoundManager->loadEffecsFromRegion(region);
01323 }
01324 void CAudioMixerUser::loadBackgroundSamplesFromRegion (const NLLIGO::CPrimRegion ®ion)
01325 {
01326 _BackgroundSoundManager->loadSamplesFromRegion(region);
01327 }
01328
01329
01330 void CAudioMixerUser::playBackgroundSound ()
01331 {
01332 _BackgroundSoundManager->play ();
01333 }
01334
01335 void CAudioMixerUser::stopBackgroundSound ()
01336 {
01337 _BackgroundSoundManager->stop ();
01338 }
01339
01340 void CAudioMixerUser::loadBackgroundSound (const std::string &continent)
01341 {
01342 _BackgroundSoundManager->load (continent);
01343 }
01344
01345 }