18
18
#include "precompiled.h"
20
#include "ISoundManager.h"
20
21
#include "SoundManager.h"
22
23
#include "soundmanager/data/SoundData.h"
23
24
#include "soundmanager/items/CSoundItem.h"
24
25
#include "soundmanager/items/CBufferItem.h"
25
26
#include "soundmanager/items/CStreamItem.h"
26
#include "soundmanager/js/SoundPlayer.h"
27
#include "soundmanager/js/AmbientSound.h"
28
#include "soundmanager/js/MusicSound.h"
29
#include "soundmanager/js/Sound.h"
30
27
#include "lib/external_libraries/libsdl.h"
31
28
#include "ps/CLogger.h"
32
29
#include "ps/CStr.h"
33
30
#include "ps/Profiler2.h"
35
CSoundManager* g_SoundManager = NULL;
32
ISoundManager* g_SoundManager = NULL;
37
34
#define SOURCE_NUM 64
75
* Called by main thread to request shutdown.
76
* Returns true if we've shut down successfully.
77
* Returns false if shutdown is taking too long (we might be blocked on a
78
* sync network operation) - you mustn't destroy this object, just leak it
84
73
CScopeLock lock(m_WorkerMutex);
207
196
CMutex m_DeadItemsMutex;
209
198
// Shared by main thread and worker thread:
210
// These variables are all protected by m_WorkerMutex
199
// These variables are all protected by a mutexes
211
200
ItemsList* m_Items;
212
201
ItemsList* m_DeadItems;
206
CSoundManagerWorker(ISoundManager* UNUSED(other)){};
219
void CSoundManager::ScriptingInit()
221
JAmbientSound::ScriptingInit();
222
JMusicSound::ScriptingInit();
223
JSound::ScriptingInit();
224
JSoundPlayer::ScriptingInit();
231
void CSoundManager::CreateSoundManager()
209
void ISoundManager::CreateSoundManager()
233
211
g_SoundManager = new CSoundManager();
236
void CSoundManager::SetEnabled(bool doEnable)
214
void ISoundManager::SetEnabled(bool doEnable)
238
216
if ( g_SoundManager && !doEnable )
242
220
else if ( ! g_SoundManager && doEnable )
244
CSoundManager::CreateSoundManager();
222
ISoundManager::CreateSoundManager();
225
void ISoundManager::CloseGame()
227
if ( CSoundManager* aSndMgr = (CSoundManager*)g_SoundManager )
228
aSndMgr->SetAmbientItem( NULL );
248
231
void CSoundManager::al_ReportError(ALenum err, const char* caller, int line)
262
245
m_CurrentEnvirons = 0;
263
246
m_ALSourceBuffer = NULL;
250
m_PlayListItems = NULL;
264
251
m_CurrentTune = 0;
268
254
m_AmbientGain = 1;
269
255
m_ActionGain = 1;
270
257
m_BufferCount = 50;
271
m_BufferSize = 65536;
258
m_BufferSize = 98304;
259
m_SoundEnabled = true;
272
260
m_MusicEnabled = true;
261
m_MusicPaused = false;
262
m_AmbientPaused = false;
263
m_ActionPaused = false;
273
265
m_DistressTime = 0;
274
266
m_DistressErrCount = 0;
276
m_Enabled = AlcInit() == INFO::OK;
277
m_ItemsMap = new ItemsMap;
280
m_Worker = new CSoundManagerWorker();
281
m_Worker->SetEnabled( true );
268
m_PlayingPlaylist = false;
269
m_LoopingPlaylist = false;
270
m_RunningPlaylist = false;
280
m_PlayListItems = new PlayList;
282
m_Worker = new CSoundManagerWorker();
283
m_Worker->SetEnabled( true );
284
287
CSoundManager::~CSoundManager()
286
if (m_Worker->Shutdown())
292
m_Worker->Shutdown();
294
m_Worker->CleanupItems();
301
for (std::map<std::wstring, CSoundGroup*>::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
303
m_SoundGroups.clear();
305
if ( m_PlayListItems )
306
delete m_PlayListItems;
291
308
if ( m_ALSourceBuffer != NULL )
292
309
delete[] m_ALSourceBuffer;
294
alcDestroyContext(m_Context);
295
alcCloseDevice(m_Device);
312
alcDestroyContext(m_Context);
315
alcCloseDevice(m_Device);
302
322
Status ret = INFO::OK;
304
324
m_Device = alcOpenDevice(NULL);
307
327
ALCint attribs[] = {ALC_STEREO_SOURCES, 16, 0};
308
328
m_Context = alcCreateContext(m_Device, &attribs[0]);
312
332
alcMakeContextCurrent(m_Context);
313
333
m_ALSourceBuffer = new ALSourceHolder[SOURCE_NUM];
419
439
if ( m_ALSourceBuffer[x].ALSource == theSource )
422
441
m_ALSourceBuffer[x].SourceItem = NULL;
428
void CSoundManager::SetMemoryUsage(long bufferSize, int bufferCount)
430
m_BufferCount = bufferCount;
431
m_BufferSize = bufferSize;
433
447
long CSoundManager::GetBufferCount()
435
449
return m_BufferCount;
439
453
return m_BufferSize;
456
void CSoundManager::AddPlayListItem( const VfsPath* itemPath)
458
m_PlayListItems->push_back( *itemPath );
461
void CSoundManager::ClearPlayListItems()
463
if ( m_PlayingPlaylist )
464
SetMusicItem( NULL );
466
m_PlayingPlaylist = false;
467
m_LoopingPlaylist = false;
468
m_RunningPlaylist = false;
470
m_PlayListItems->clear();
473
void CSoundManager::StartPlayList( bool doLoop )
475
if ( m_MusicEnabled )
477
if ( m_PlayListItems->size() > 0 )
479
m_PlayingPlaylist = true;
480
m_LoopingPlaylist = doLoop;
481
m_RunningPlaylist = false;
483
ISoundItem* aSnd = LoadItem( (m_PlayListItems->at( 0 )) );
485
SetMusicItem( aSnd );
488
SetMusicItem( NULL );
442
494
void CSoundManager::SetMasterGain(float gain)
445
alListenerf( AL_GAIN, m_Gain);
499
alListenerf( AL_GAIN, m_Gain);
449
504
void CSoundManager::SetMusicGain(float gain)
459
514
m_ActionGain = gain;
516
void CSoundManager::SetUIGain(float gain)
463
522
ISoundItem* CSoundManager::LoadItem(const VfsPath& itemPath)
467
CSoundData* itemData = CSoundData::SoundDataFromFile(itemPath);
528
CSoundData* itemData = CSoundData::SoundDataFromFile(itemPath);
471
return CSoundManager::ItemForData( itemData );
532
return CSoundManager::ItemForData( itemData );
505
567
void CSoundManager::IdleTask()
509
m_CurrentTune->EnsurePlay();
511
if (m_CurrentEnvirons)
512
m_CurrentEnvirons->EnsurePlay();
515
m_Worker->CleanupItems();
519
ISoundItem* CSoundManager::ItemForEntity( entity_id_t source, CSoundData* sndData)
521
ISoundItem* currentItem = NULL;
524
ItemsMap::iterator itemFound = m_ItemsMap->find( source );
525
if ( itemFound != m_ItemsMap->end() )
527
currentItem = itemFound->second;
528
if ( currentItem->CanAttach( sndData ) )
530
currentItem->Attach( sndData );
531
LOGERROR(L"did REUSE items source = %d", m_SourceCOunt);
535
m_ItemsMap->erase( itemFound );
536
currentItem->StopAndDelete();
537
LOGERROR(L"item UNREUSABLE for data = %d", m_SourceCOunt);
573
m_CurrentTune->EnsurePlay();
574
if ( m_PlayingPlaylist && m_RunningPlaylist )
576
if ( m_CurrentTune->Finished() )
578
if ( m_PlaylistGap == 0 )
580
m_PlaylistGap = timer_Time() + 15;
582
else if ( m_PlaylistGap < timer_Time() )
585
PlayList::iterator it = find (m_PlayListItems->begin(), m_PlayListItems->end(), *(m_CurrentTune->GetName()) );
586
if ( it != m_PlayListItems->end() )
591
if ( it == m_PlayListItems->end() )
592
nextPath = m_PlayListItems->at( 0 );
596
ISoundItem* aSnd = LoadItem( nextPath );
598
SetMusicItem( aSnd );
605
if (m_CurrentEnvirons)
606
m_CurrentEnvirons->EnsurePlay();
609
m_Worker->CleanupItems();
542
if ( currentItem == NULL )
614
ISoundItem* CSoundManager::ItemForEntity( entity_id_t UNUSED(source), CSoundData* sndData)
616
ISoundItem* currentItem = NULL;
544
619
currentItem = ItemForData( sndData );
546
m_ItemsMap->insert(std::make_pair( source, currentItem));
549
621
return currentItem;
563
635
alDistanceModel(AL_LINEAR_DISTANCE);
566
void CSoundManager::PlayActionItem(ISoundItem* anItem)
570
if (m_Enabled && (m_ActionGain > 0))
572
anItem->SetGain( m_ActionGain );
578
638
void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain )
597
657
m_MusicEnabled = isEnabled;
660
void CSoundManager::PlayAsGroup(const VfsPath& groupPath, CVector3D sourcePos, entity_id_t source, bool ownedSound)
662
// Make sure the sound group is loaded
664
if (m_SoundGroups.find(groupPath.string()) == m_SoundGroups.end())
666
group = new CSoundGroup();
667
if (!group->LoadSoundGroup(L"audio/" + groupPath.string() ))
669
LOGERROR(L"Failed to load sound group '%ls'", groupPath.string().c_str());
673
// Cache the sound group (or the null, if it failed)
674
m_SoundGroups[groupPath.string()] = group;
678
group = m_SoundGroups[groupPath.string()];
681
// Failed to load group -> do nothing
682
if ( group && ( ownedSound || !group->TestFlag( eOwnerOnly ) ) )
683
group->PlayNext(sourcePos, source);
686
void CSoundManager::PlayAsMusic( const VfsPath& itemPath, bool looping )
690
ISoundItem* aSnd = LoadItem(itemPath);
692
SetMusicItem( aSnd );
695
void CSoundManager::PlayAsAmbient( const VfsPath& itemPath, bool looping )
698
ISoundItem* aSnd = LoadItem(itemPath);
700
SetAmbientItem( aSnd );
704
void CSoundManager::PlayAsUI(const VfsPath& itemPath, bool looping)
708
if ( ISoundItem* anItem = LoadItem(itemPath) )
710
if (m_Enabled && (m_UIGain > 0))
712
anItem->SetGain(m_UIGain);
713
anItem->SetLooping( looping );
714
anItem->PlayAndDelete();
721
void CSoundManager::Pause(bool pauseIt)
724
PauseAmbient(pauseIt);
725
PauseAction(pauseIt);
728
void CSoundManager::PauseMusic (bool pauseIt)
730
if (m_CurrentTune && pauseIt && !m_MusicPaused )
732
m_CurrentTune->FadeAndPause( 1.0 );
734
else if ( m_CurrentTune && m_MusicPaused && !pauseIt && m_MusicEnabled )
736
m_CurrentTune->SetGain(0);
737
m_CurrentTune->Resume();
738
m_CurrentTune->FadeToIn( m_MusicGain, 1.0);
740
m_MusicPaused = pauseIt;
743
void CSoundManager::PauseAmbient (bool pauseIt)
745
if (m_CurrentEnvirons && pauseIt)
746
m_CurrentEnvirons->Pause();
747
else if ( m_CurrentEnvirons )
748
m_CurrentEnvirons->Resume();
750
m_AmbientPaused = pauseIt;
753
void CSoundManager::PauseAction (bool pauseIt)
755
m_ActionPaused = pauseIt;
600
758
void CSoundManager::SetMusicItem(ISoundItem* anItem)
613
771
if (m_MusicEnabled && m_Enabled)
615
773
m_CurrentTune = anItem;
616
m_CurrentTune->SetIsManaged( true );
617
774
m_CurrentTune->SetGain(0);
618
m_CurrentTune->PlayLoop();
776
if ( m_PlayingPlaylist )
778
m_RunningPlaylist = true;
779
m_CurrentTune->Play();
782
m_CurrentTune->PlayLoop();
619
784
m_CurrentTune->FadeToIn( m_MusicGain, 1.00);
640
805
if (m_Enabled && (m_AmbientGain > 0))
642
807
m_CurrentEnvirons = anItem;
643
m_CurrentEnvirons->SetIsManaged( true );
644
808
m_CurrentEnvirons->SetGain(0);
645
809
m_CurrentEnvirons->PlayLoop();
646
810
m_CurrentEnvirons->FadeToIn( m_AmbientGain, 2.00);