From 44821da620d569a6082c3232d04673cd0e05b788 Mon Sep 17 00:00:00 2001 From: stwf Date: Thu, 27 Sep 2012 02:42:03 +0000 Subject: [PATCH] new threaded soundmanager and proper distance roll off This was SVN commit r12709. --- source/soundmanager/SoundManager.cpp | 283 ++++++++++++++++++----- source/soundmanager/SoundManager.h | 3 +- source/soundmanager/items/CSoundBase.cpp | 8 +- source/soundmanager/js/SoundGroup.cpp | 10 +- 4 files changed, 238 insertions(+), 66 deletions(-) diff --git a/source/soundmanager/SoundManager.cpp b/source/soundmanager/SoundManager.cpp index d020f43fcb..40844cc571 100644 --- a/source/soundmanager/SoundManager.cpp +++ b/source/soundmanager/SoundManager.cpp @@ -28,10 +28,212 @@ #include "soundmanager/js/MusicSound.h" #include "soundmanager/js/Sound.h" #include "ps/CLogger.h" +#include "ps/Profiler2.h" CSoundManager* g_SoundManager = NULL; +class CSoundManagerWorker +{ +public: + CSoundManagerWorker() + { + m_Items = new ItemsList; + m_DeadItems = new ItemsList; + m_Shutdown = false; + m_Enabled = false; + m_PauseUntilTime = 0; + + int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this); + ENSURE(ret == 0); + } + + ~CSoundManagerWorker() + { + + } + + /** + * Called by main thread, when the online reporting is enabled/disabled. + */ + void SetEnabled(bool enabled) + { + CScopeLock lock(m_WorkerMutex); + if (enabled != m_Enabled) + { + m_Enabled = enabled; + } + } + + /** + * Called by main thread to request shutdown. + * Returns true if we've shut down successfully. + * Returns false if shutdown is taking too long (we might be blocked on a + * sync network operation) - you mustn't destroy this object, just leak it + * and terminate. + */ + bool Shutdown() + { + { + CScopeLock lock(m_WorkerMutex); + m_Shutdown = true; + m_Enabled = false; + + ItemsList::iterator lstr = m_Items->begin(); + while (lstr != m_Items->end()) + { + (*lstr)->Stop(); + delete *lstr; + lstr++; + } + + } + + pthread_join(m_WorkerThread, NULL); + + return true; + } + void addItem( ISoundItem* anItem ) + { + CScopeLock lock(m_WorkerMutex); + m_Items->push_back( anItem ); + } + + void CleanupItems() + { + CScopeLock lock(m_WorkerMutex); + AL_CHECK + ItemsList::iterator deadItems = m_DeadItems->begin(); + while (deadItems != m_DeadItems->end()) + { + delete *deadItems; + deadItems++; + + AL_CHECK + } + m_DeadItems->clear(); + } + void DeleteItem(long itemNum) + { + CScopeLock lock(m_WorkerMutex); + AL_CHECK + ItemsList::iterator lstr = m_Items->begin(); + lstr += itemNum; + + delete *lstr; + AL_CHECK + + m_Items->erase(lstr); + } + + +private: + static void* RunThread(void* data) + { + debug_SetThreadName("CSoundManagerWorker"); + g_Profiler2.RegisterCurrentThread("soundmanager"); + + static_cast(data)->Run(); + + return NULL; + } + + void Run() + { + + // Wait until the main thread wakes us up + while ( true ) + { + g_Profiler2.RecordRegionLeave("semaphore wait"); + + if (timer_Time() < m_PauseUntilTime) + continue; + + // Handle shutdown requests as soon as possible + if (GetShutdown()) + return; + + // If we're not enabled, ignore this wakeup + if (!GetEnabled()) + continue; + + { + CScopeLock lock(m_WorkerMutex); + + ItemsList::iterator lstr = m_Items->begin(); + ItemsList* nextItemList = new ItemsList; + + + while (lstr != m_Items->end()) { + + if ((*lstr)->IdleTask()) + nextItemList->push_back(*lstr); + else + m_DeadItems->push_back(*lstr); + lstr++; + + AL_CHECK + } + + delete m_Items; + m_Items = nextItemList; + + AL_CHECK + } + m_PauseUntilTime = timer_Time() + 0.1; + } + } + + bool GetEnabled() + { + CScopeLock lock(m_WorkerMutex); + return m_Enabled; + } + + bool GetShutdown() + { + CScopeLock lock(m_WorkerMutex); + return m_Shutdown; + } + + + +private: + // Thread-related members: + pthread_t m_WorkerThread; + CMutex m_WorkerMutex; + + // Shared by main thread and worker thread: + // These variables are all protected by m_WorkerMutex + ItemsList* m_Items; + ItemsList* m_DeadItems; + + bool m_Enabled; + bool m_Shutdown; + + // Initialised in constructor by main thread; otherwise used only by worker thread: + double m_PauseUntilTime; +}; + + + + + + + + + + + + + + + + + + + + void CSoundManager::ScriptingInit() { JAmbientSound::ScriptingInit(); @@ -76,7 +278,6 @@ void CSoundManager::al_check(const char* caller, int line) CSoundManager::CSoundManager() { - m_Items = new ItemsList; m_CurrentEnvirons = 0; m_CurrentTune = 0; m_Gain = 1; @@ -87,23 +288,20 @@ CSoundManager::CSoundManager() m_BufferSize = 65536; m_MusicEnabled = true; m_Enabled = AlcInit() == INFO::OK; + InitListener(); + + m_Worker = new CSoundManagerWorker(); + m_Worker->SetEnabled( true ); } CSoundManager::~CSoundManager() { - ItemsList::iterator lstr = m_Items->begin(); - while (lstr != m_Items->end()) - { - (*lstr)->Stop(); - delete *lstr; - lstr++; - } + m_Worker->Shutdown(); + m_Worker = 0L; alcDestroyContext(m_Context); alcCloseDevice(m_Device); - delete m_Items; - m_Items = 0L; m_CurrentEnvirons = 0; m_CurrentTune = 0; } @@ -156,11 +354,13 @@ long CSoundManager::GetBufferSize() return m_BufferSize; } - void CSoundManager::SetMasterGain(float gain) { m_Gain = gain; + alListenerf( AL_GAIN, m_Gain); + AL_CHECK } + void CSoundManager::SetMusicGain(float gain) { m_MusicGain = gain; @@ -198,67 +398,32 @@ ISoundItem* CSoundManager::LoadItem(const VfsPath& itemPath) answer = new CStreamItem(itemData); } - if (answer != NULL) - m_Items->push_back(answer); + if ( answer && m_Worker ) + m_Worker->addItem( answer ); } return answer; } -unsigned long CSoundManager::Count() -{ - return m_Items->size(); -} - void CSoundManager::IdleTask() { - if (m_Items) - { - ItemsList::iterator lstr = m_Items->begin(); - ItemsList deadItemList; - ItemsList* nextItemList = new ItemsList; - - - while (lstr != m_Items->end()) { - if ((*lstr)->IdleTask()) - nextItemList->push_back(*lstr); - else - deadItemList.push_back(*lstr); - lstr++; - } - delete m_Items; - m_Items = nextItemList; - - ItemsList::iterator deadItems = deadItemList.begin(); - while (deadItems != deadItemList.end()) - { - delete *deadItems; - deadItems++; - } - } AL_CHECK if (m_CurrentTune) m_CurrentTune->EnsurePlay(); if (m_CurrentEnvirons) m_CurrentEnvirons->EnsurePlay(); AL_CHECK + if (m_Worker) + m_Worker->CleanupItems(); } void CSoundManager::DeleteItem(long itemNum) { - ItemsList::iterator lstr = m_Items->begin(); - lstr += itemNum; - - delete *lstr; - - m_Items->erase(lstr); + if (m_Worker) + m_Worker->DeleteItem(itemNum); } -ISoundItem* CSoundManager::GetSoundItem(unsigned long itemRow) -{ - return (*m_Items)[itemRow]; -} void CSoundManager::InitListener() { @@ -270,7 +435,7 @@ void CSoundManager::InitListener() alListenerfv(AL_VELOCITY,listenerVel); alListenerfv(AL_ORIENTATION,listenerOri); - alDistanceModel(AL_EXPONENT_DISTANCE); + alDistanceModel(AL_LINEAR_DISTANCE); } void CSoundManager::PlayActionItem(ISoundItem* anItem) @@ -279,7 +444,7 @@ void CSoundManager::PlayActionItem(ISoundItem* anItem) { if (m_Enabled && (m_ActionGain > 0)) { - anItem->SetGain(m_Gain * m_ActionGain); + anItem->SetGain( m_ActionGain ); anItem->Play(); AL_CHECK } @@ -290,7 +455,7 @@ void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain) if (anItem) { if (m_Enabled && (m_ActionGain > 0)) { - anItem->SetGain(m_Gain * groupGain); + anItem->SetGain(m_ActionGain * groupGain); anItem->Play(); AL_CHECK } @@ -312,10 +477,12 @@ void CSoundManager::SetMusicItem(ISoundItem* anItem) AL_CHECK if (m_CurrentTune) { - m_CurrentTune->FadeAndDelete(3.00); + m_CurrentTune->FadeAndDelete(2.00); m_CurrentTune = 0L; } + IdleTask(); + if (anItem) { if (m_MusicEnabled && m_Enabled) @@ -323,7 +490,7 @@ void CSoundManager::SetMusicItem(ISoundItem* anItem) m_CurrentTune = anItem; m_CurrentTune->SetGain(0); m_CurrentTune->PlayLoop(); - m_CurrentTune->FadeToIn(m_Gain * m_MusicGain, 2.00); + m_CurrentTune->FadeToIn( m_MusicGain, 1.00); } else { @@ -349,7 +516,7 @@ void CSoundManager::SetAmbientItem(ISoundItem* anItem) m_CurrentEnvirons = anItem; m_CurrentEnvirons->SetGain(0); m_CurrentEnvirons->PlayLoop(); - m_CurrentEnvirons->FadeToIn(m_Gain * m_AmbientGain, 2.00); + m_CurrentEnvirons->FadeToIn( m_AmbientGain, 2.00); } } AL_CHECK diff --git a/source/soundmanager/SoundManager.h b/source/soundmanager/SoundManager.h index 521a69c5d7..b2dc4c55a3 100644 --- a/source/soundmanager/SoundManager.h +++ b/source/soundmanager/SoundManager.h @@ -32,6 +32,7 @@ typedef std::vector ItemsList; +class CSoundManagerWorker; class CSoundManager { @@ -42,7 +43,7 @@ protected: ALCdevice* m_Device; ISoundItem* m_CurrentTune; ISoundItem* m_CurrentEnvirons; - ItemsList* m_Items; + CSoundManagerWorker* m_Worker; float m_Gain; float m_MusicGain; float m_AmbientGain; diff --git a/source/soundmanager/items/CSoundBase.cpp b/source/soundmanager/items/CSoundBase.cpp index 94845fa636..d24488b59c 100644 --- a/source/soundmanager/items/CSoundBase.cpp +++ b/source/soundmanager/items/CSoundBase.cpp @@ -142,7 +142,7 @@ bool CSoundBase::InitOpenAL() if (anErr == AL_NO_ERROR) { - ALfloat source0Pos[]={ -2.0, 0.0, 0.0}; + ALfloat source0Pos[]={ 0.0, 0.0, -1.0}; ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; alSourcef(m_ALSource,AL_PITCH,1.0f); @@ -151,6 +151,12 @@ bool CSoundBase::InitOpenAL() alSourcefv(m_ALSource,AL_VELOCITY,source0Vel); alSourcei(m_ALSource,AL_LOOPING,AL_FALSE); AL_CHECK + alSourcef(m_ALSource, AL_REFERENCE_DISTANCE, 70.0f); + AL_CHECK + alSourcef(m_ALSource, AL_MAX_DISTANCE, 145.0); + AL_CHECK + alSourcef(m_ALSource, AL_ROLLOFF_FACTOR, 1.0); + AL_CHECK return true; } diff --git a/source/soundmanager/js/SoundGroup.cpp b/source/soundmanager/js/SoundGroup.cpp index eabd0767c3..8f7cfa5129 100644 --- a/source/soundmanager/js/SoundGroup.cpp +++ b/source/soundmanager/js/SoundGroup.cpp @@ -130,7 +130,7 @@ float CSoundGroup::RadiansOffCenter(const CVector3D& position, bool& onScreen, f else { if ((x < 0) || (x > screenWidth)) { - itemRollOff = 0.5; + itemRollOff = 5.0; } float pixPerRadian = audioWidth / (radianCap * 2); answer = (x - (screenWidth/2)) / pixPerRadian; @@ -147,7 +147,7 @@ float CSoundGroup::RadiansOffCenter(const CVector3D& position, bool& onScreen, f else { if ((y < 0) || (y > screenHeight)) { - itemRollOff = 0.5; + itemRollOff = 5.0; } } @@ -162,7 +162,7 @@ void CSoundGroup::UploadPropertiesAndPlay(int theIndex, const CVector3D& positio #if CONFIG2_AUDIO if ( g_SoundManager ) { bool isOnscreen; - ALfloat initialRolllOff = 0.02f; + ALfloat initialRolllOff = 1.0f; ALfloat itemRollOff = initialRolllOff; float offSet = RadiansOffCenter(position, isOnscreen, itemRollOff); @@ -178,7 +178,7 @@ void CSoundGroup::UploadPropertiesAndPlay(int theIndex, const CVector3D& positio if (!TestFlag(eOmnipresent)) { - hSound->SetLocation(CVector3D((sndDist * sin(offSet)), 0, sndDist * cos(offSet))); + hSound->SetLocation(CVector3D((sndDist * sin(offSet)), 0, - sndDist * cos(offSet))); if (TestFlag(eDistanceless)) hSound->SetRollOff(initialRolllOff); else @@ -265,8 +265,6 @@ void CSoundGroup::Update(float UNUSED(TimeSinceLastFrame)) bool CSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML) { -// LOGERROR(L"loading new sound group '%ls'", pathnameXML.string().c_str()); - CXeromyces XeroFile; if (XeroFile.Load(g_VFS, pathnameXML) != PSRETURN_OK) {