From e4a9312c469ae008787534c52888b626b65f1926 Mon Sep 17 00:00:00 2001 From: stwf Date: Fri, 1 Mar 2013 14:22:28 +0000 Subject: [PATCH] newest soundmanager patch, should give better battle sequences, and handle low resource situations correctly. This was SVN commit r13209. --- .../components/CCmpSoundManager.cpp | 2 +- source/soundmanager/SoundManager.cpp | 192 +++++++++++++++--- source/soundmanager/SoundManager.h | 34 +++- source/soundmanager/data/OggData.cpp | 2 + source/soundmanager/data/SoundData.cpp | 3 + source/soundmanager/data/ogg.cpp | 9 + source/soundmanager/data/ogg.h | 1 + source/soundmanager/items/CBufferItem.cpp | 52 ++++- source/soundmanager/items/CBufferItem.h | 19 +- source/soundmanager/items/CSoundBase.cpp | 120 ++++++++--- source/soundmanager/items/CSoundBase.h | 11 + source/soundmanager/items/CSoundItem.cpp | 38 +++- source/soundmanager/items/CSoundItem.h | 14 +- source/soundmanager/items/CStreamItem.cpp | 21 +- source/soundmanager/items/CStreamItem.h | 17 +- source/soundmanager/items/ISoundItem.h | 6 + source/soundmanager/js/SoundGroup.cpp | 21 +- source/soundmanager/js/SoundGroup.h | 12 +- 18 files changed, 462 insertions(+), 112 deletions(-) diff --git a/source/simulation2/components/CCmpSoundManager.cpp b/source/simulation2/components/CCmpSoundManager.cpp index d1160fa2c1..0ce1be3730 100644 --- a/source/simulation2/components/CCmpSoundManager.cpp +++ b/source/simulation2/components/CCmpSoundManager.cpp @@ -135,7 +135,7 @@ public: sourcePos = CVector3D(cmpPosition->GetPosition()); } - group->PlayNext(sourcePos); + group->PlayNext(sourcePos, source); } #else // !CONFIG2_AUDIO UNUSED2(name); diff --git a/source/soundmanager/SoundManager.cpp b/source/soundmanager/SoundManager.cpp index cbe72dfc89..5662df0ca7 100644 --- a/source/soundmanager/SoundManager.cpp +++ b/source/soundmanager/SoundManager.cpp @@ -34,6 +34,9 @@ CSoundManager* g_SoundManager = NULL; +#define SOURCE_NUM 64 + +#if CONFIG2_AUDIO class CSoundManagerWorker { @@ -83,7 +86,6 @@ public: ItemsList::iterator lstr = m_Items->begin(); while (lstr != m_Items->end()) { - (*lstr)->Stop(); delete *lstr; lstr++; } @@ -115,20 +117,6 @@ public: 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) { @@ -146,6 +134,8 @@ private: // Wait until the main thread wakes us up while ( true ) { + g_Profiler2.RecordRegionLeave("semaphore wait"); + // Handle shutdown requests as soon as possible if (GetShutdown()) return; @@ -155,6 +145,9 @@ private: continue; int pauseTime = 1000; + if ( g_SoundManager->InDistress() ) + pauseTime = 50; + { CScopeLock lock(m_WorkerMutex); @@ -164,10 +157,12 @@ private: while (lstr != m_Items->end()) { + AL_CHECK if ((*lstr)->IdleTask()) { - if ( (*lstr)->IsFading() ) + if ( (pauseTime == 1000) && (*lstr)->IsFading() ) pauseTime = 100; + nextItemList->push_back(*lstr); } else @@ -217,6 +212,7 @@ private: bool m_Enabled; bool m_Shutdown; }; +#endif void CSoundManager::ScriptingInit() { @@ -229,6 +225,7 @@ void CSoundManager::ScriptingInit() #if CONFIG2_AUDIO + void CSoundManager::CreateSoundManager() { g_SoundManager = new CSoundManager(); @@ -260,8 +257,10 @@ void CSoundManager::al_check(const char* caller, int line) CSoundManager::CSoundManager() { - m_CurrentEnvirons = NULL; - m_CurrentTune = NULL; + m_CurrentEnvirons = 0; + m_ALSourceBuffer = NULL; + m_CurrentTune = 0; + m_SourceCOunt = 0; m_Gain = 1; m_MusicGain = 1; m_AmbientGain = 1; @@ -269,7 +268,11 @@ CSoundManager::CSoundManager() m_BufferCount = 50; m_BufferSize = 65536; m_MusicEnabled = true; + m_DistressTime = 0; + m_DistressErrCount = 0; + m_Enabled = AlcInit() == INFO::OK; + m_ItemsMap = new ItemsMap; InitListener(); m_Worker = new CSoundManagerWorker(); @@ -286,6 +289,7 @@ CSoundManager::~CSoundManager() } + Status CSoundManager::AlcInit() { Status ret = INFO::OK; @@ -297,7 +301,30 @@ Status CSoundManager::AlcInit() m_Context = alcCreateContext(m_Device, &attribs[0]); if(m_Context) + { alcMakeContextCurrent(m_Context); + m_ALSourceBuffer = new ALSourceHolder[SOURCE_NUM]; + ALuint* sourceList = new ALuint[SOURCE_NUM]; + + alGenSources( SOURCE_NUM, sourceList); + ALCenum err = alcGetError(m_Device); + + + if ( err == ALC_NO_ERROR ) + { + for ( int x=0; x 10 ) + { + m_DistressTime = 0; + LOGERROR(L"Sound: Coming out of distress mode suffering %ld errors\n", m_DistressErrCount); + m_DistressErrCount = 0; + return false; + } + else + { +// LOGERROR(L"Sound: Still in distress mode suffering %ld errors at %ld time\n", m_DistressErrCount, m_DistressTime); + } + + + return true; +} + +void CSoundManager::SetDistressThroughShortage() +{ + CScopeLock lock(m_DistressMutex); + + if ( m_DistressTime == 0 ) + LOGERROR(L"Sound: Entering distress mode through shortage\n", 0); + + m_DistressTime = timer_Time(); +} + +void CSoundManager::SetDistressThroughError() +{ + CScopeLock lock(m_DistressMutex); + + if ( m_DistressTime == 0 ) + LOGERROR(L"Sound: Entering distress mode through error\n", 0); + + m_DistressTime = timer_Time(); + m_DistressErrCount++; +} + + + +ALuint CSoundManager::GetALSource( ISoundItem* anItem) +{ + for ( int x=0; xEnsurePlay(); + AL_CHECK if (m_CurrentEnvirons) m_CurrentEnvirons->EnsurePlay(); AL_CHECK if (m_Worker) m_Worker->CleanupItems(); + AL_CHECK } -void CSoundManager::DeleteItem(long itemNum) +ISoundItem* CSoundManager::ItemForEntity( entity_id_t source, CSoundData* sndData) { - if (m_Worker) - m_Worker->DeleteItem(itemNum); + ISoundItem* currentItem = NULL; + if ( false ) + { + ItemsMap::iterator itemFound = m_ItemsMap->find( source ); + if ( itemFound != m_ItemsMap->end() ) + { + currentItem = itemFound->second; + if ( currentItem->CanAttach( sndData ) ) + { + currentItem->Attach( sndData ); + LOGERROR(L"did REUSE items source = %d", m_SourceCOunt); + } + else + { + m_ItemsMap->erase( itemFound ); + currentItem->StopAndDelete(); + LOGERROR(L"item UNREUSABLE for data = %d", m_SourceCOunt); + currentItem = NULL; + } + } + } + if ( currentItem == NULL ) + { + currentItem = ItemForData( sndData ); + if ( currentItem ) + m_ItemsMap->insert(std::make_pair( source, currentItem)); + } + + return currentItem; } @@ -431,13 +575,13 @@ void CSoundManager::PlayActionItem(ISoundItem* anItem) } } } -void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain) +void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain ) { if (anItem) { if (m_Enabled && (m_ActionGain > 0)) { anItem->SetGain(m_ActionGain * groupGain); - anItem->Play(); + anItem->PlayAndDelete(); AL_CHECK } } @@ -469,6 +613,7 @@ void CSoundManager::SetMusicItem(ISoundItem* anItem) if (m_MusicEnabled && m_Enabled) { m_CurrentTune = anItem; + m_CurrentTune->SetIsManaged( true ); m_CurrentTune->SetGain(0); m_CurrentTune->PlayLoop(); m_CurrentTune->FadeToIn( m_MusicGain, 1.00); @@ -495,6 +640,7 @@ void CSoundManager::SetAmbientItem(ISoundItem* anItem) if (m_Enabled && (m_AmbientGain > 0)) { m_CurrentEnvirons = anItem; + m_CurrentEnvirons->SetIsManaged( true ); m_CurrentEnvirons->SetGain(0); m_CurrentEnvirons->PlayLoop(); m_CurrentEnvirons->FadeToIn( m_AmbientGain, 2.00); diff --git a/source/soundmanager/SoundManager.h b/source/soundmanager/SoundManager.h index b2dc4c55a3..f3518595cd 100644 --- a/source/soundmanager/SoundManager.h +++ b/source/soundmanager/SoundManager.h @@ -24,6 +24,10 @@ #include "lib/file/vfs/vfs_path.h" #include "soundmanager/items/ISoundItem.h" +#include "simulation2/system/Entity.h" +#include "soundmanager/data/SoundData.h" +#include "soundmanager/items/ISoundItem.h" +#include "ps/Profiler2.h" #include #include @@ -31,9 +35,18 @@ #define AL_CHECK CSoundManager::al_check(__func__, __LINE__); typedef std::vector ItemsList; +typedef std::map ItemsMap; class CSoundManagerWorker; + +struct ALSourceHolder +{ + /// Title of the column + ALuint ALSource; + ISoundItem* SourceItem; +}; + class CSoundManager { protected: @@ -44,21 +57,32 @@ protected: ISoundItem* m_CurrentTune; ISoundItem* m_CurrentEnvirons; CSoundManagerWorker* m_Worker; + ItemsMap* m_ItemsMap; + CMutex m_DistressMutex; + float m_Gain; float m_MusicGain; float m_AmbientGain; float m_ActionGain; bool m_Enabled; + long m_SourceCOunt; long m_BufferSize; int m_BufferCount; bool m_MusicEnabled; bool m_SoundEnabled; + long m_DistressErrCount; + long m_DistressTime; + + ALSourceHolder* m_ALSourceBuffer; + public: CSoundManager(); virtual ~CSoundManager(); ISoundItem* LoadItem(const VfsPath& itemPath); + ISoundItem* ItemForData(CSoundData* itemData); + ISoundItem* ItemForEntity( entity_id_t source, CSoundData* sndData); static void ScriptingInit(); static void CreateSoundManager(); @@ -70,13 +94,16 @@ public: void SetMusicEnabled (bool isEnabled); void setSoundEnabled( bool enabled ); + ALuint GetALSource(ISoundItem* anItem); + void ReleaseALSource(ALuint theSource); + ISoundItem* ItemFromData(CSoundData* itemData); + ISoundItem* ItemFromWAV(VfsPath& fname); ISoundItem* ItemFromOgg(VfsPath& fname); ISoundItem* GetSoundItem(unsigned long itemRow); unsigned long Count(); void IdleTask(); - void DeleteItem(long itemNum); void SetMemoryUsage(long bufferSize, int bufferCount); long GetBufferCount(); @@ -91,7 +118,10 @@ public: void SetMusicGain(float gain); void SetAmbientGain(float gain); void SetActionGain(float gain); - + bool InDistress(); + void SetDistressThroughShortage(); + void SetDistressThroughError(); + protected: void InitListener(); virtual Status AlcInit(); diff --git a/source/soundmanager/data/OggData.cpp b/source/soundmanager/data/OggData.cpp index 95d8bd6f53..80e367a6d2 100644 --- a/source/soundmanager/data/OggData.cpp +++ b/source/soundmanager/data/OggData.cpp @@ -34,6 +34,8 @@ COggData::COggData() COggData::~COggData() { + ogg->Close(); + alDeleteBuffers(m_BuffersUsed, m_Buffer); } diff --git a/source/soundmanager/data/SoundData.cpp b/source/soundmanager/data/SoundData.cpp index 00e9b35482..d18094a5ca 100644 --- a/source/soundmanager/data/SoundData.cpp +++ b/source/soundmanager/data/SoundData.cpp @@ -35,8 +35,11 @@ CSoundData::CSoundData() CSoundData::~CSoundData() { +// LOGERROR(L"Sound data deleted %ls\n", m_FileName->c_str() ); + if (m_ALBuffer != 0) alDeleteBuffers(1, &m_ALBuffer); + delete m_FileName; } diff --git a/source/soundmanager/data/ogg.cpp b/source/soundmanager/data/ogg.cpp index 7c692c3ae5..b63828f83a 100644 --- a/source/soundmanager/data/ogg.cpp +++ b/source/soundmanager/data/ogg.cpp @@ -28,6 +28,7 @@ #include "lib/file/file_system.h" #include "lib/file/vfs/vfs_util.h" +#include "ps/CLogger.h" #include "ps/Filesystem.h" @@ -219,6 +220,14 @@ public: m_fileEOF = false; } + Status Close() + { + ov_clear( &vf ); + LOGERROR(L"did clear ov\n", 0 ); + + return 0; + } + Status Open() { ov_callbacks callbacks; diff --git a/source/soundmanager/data/ogg.h b/source/soundmanager/data/ogg.h index c2e2e704d8..bff6bbc9fa 100644 --- a/source/soundmanager/data/ogg.h +++ b/source/soundmanager/data/ogg.h @@ -32,6 +32,7 @@ public: virtual ALsizei SamplingRate() = 0; virtual bool atFileEOF() = 0; virtual Status ResetFile() = 0; + virtual Status Close() = 0; /** * @return bytes read (<= size) or a (negative) Status diff --git a/source/soundmanager/items/CBufferItem.cpp b/source/soundmanager/items/CBufferItem.cpp index 3cf10d46ad..98af90f733 100644 --- a/source/soundmanager/items/CBufferItem.cpp +++ b/source/soundmanager/items/CBufferItem.cpp @@ -36,10 +36,15 @@ CBufferItem::CBufferItem(CSoundData* sndData) CBufferItem::~CBufferItem() { - AL_CHECK +} - Stop(); - if (m_ALSource != 0) + +void CBufferItem::ReleaseOpenAL() +{ + int num_processed; + alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed); + + if (num_processed > 0) { int num_processed; alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed); @@ -53,15 +58,34 @@ CBufferItem::~CBufferItem() delete[] al_buf; } } -} + CSoundBase::ReleaseOpenAL(); +} bool CBufferItem::IdleTask() { + if ( m_ALSource == 0 ) + return false; + HandleFade(); - if (m_ALSource != 0) + TouchTimer(); + + if (m_LastPlay) { - if (m_LastPlay) + CScopeLock lock(m_ItemMutex); + int proc_state; + alGetSourceiv(m_ALSource, AL_SOURCE_STATE, &proc_state); + AL_CHECK + return (proc_state != AL_STOPPED); + } + + if (GetLooping()) + { + CScopeLock lock(m_ItemMutex); + int num_processed; + alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed); + + for (int i = 0; i < num_processed; i++) { int proc_state; alGetSourceiv(m_ALSource, AL_SOURCE_STATE, &proc_state); @@ -88,11 +112,25 @@ bool CBufferItem::IdleTask() return true; } +bool CBufferItem::CanAttach(CSoundData* itemData) +{ + return itemData->IsOneShot() && (itemData->GetBufferCount() > 1); +} void CBufferItem::Attach(CSoundData* itemData) { +AL_CHECK + if ( m_ALSource == 0 ) + return; + AL_CHECK - if ( (itemData != NULL) && (m_ALSource != 0) ) + if (m_SoundData != NULL) + { + CSoundData::ReleaseSoundData(m_SoundData); + m_SoundData = 0; + } + AL_CHECK + if (itemData != NULL) { m_SoundData = itemData->IncrementCount(); alSourceQueueBuffers(m_ALSource, m_SoundData->GetBufferCount(),(const ALuint *) m_SoundData->GetBufferPtr()); diff --git a/source/soundmanager/items/CBufferItem.h b/source/soundmanager/items/CBufferItem.h index 9794130089..b19f72de09 100644 --- a/source/soundmanager/items/CBufferItem.h +++ b/source/soundmanager/items/CBufferItem.h @@ -27,16 +27,17 @@ class CBufferItem : public CSoundBase { public: - CBufferItem(CSoundData* sndData); - virtual ~CBufferItem(); - - virtual void SetLooping(bool loops); - virtual bool IdleTask(); - -protected: - virtual void Attach(CSoundData* itemData); + CBufferItem(CSoundData* sndData); + virtual ~CBufferItem(); + + virtual void SetLooping(bool loops); + virtual bool IdleTask(); + void Attach(CSoundData* itemData); + bool CanAttach(CSoundData* itemData); - +protected: + virtual void ReleaseOpenAL(); + }; #endif // CONFIG2_AUDIO diff --git a/source/soundmanager/items/CSoundBase.cpp b/source/soundmanager/items/CSoundBase.cpp index 63159060b6..99640ee03b 100644 --- a/source/soundmanager/items/CSoundBase.cpp +++ b/source/soundmanager/items/CSoundBase.cpp @@ -36,9 +36,15 @@ CSoundBase::CSoundBase() CSoundBase::~CSoundBase() { Stop(); + ReleaseOpenAL(); +} + +void CSoundBase::ReleaseOpenAL() +{ if (m_ALSource != 0) { - alDeleteSources(1, &m_ALSource); + alSourcei(m_ALSource, AL_BUFFER, 0); + g_SoundManager->ReleaseALSource(m_ALSource); m_ALSource = 0; } if (m_SoundData != 0) @@ -48,6 +54,15 @@ CSoundBase::~CSoundBase() } } +void CSoundBase::Attach(CSoundData* itemData) +{ + +} +bool CSoundBase::CanAttach(CSoundData* itemData) +{ + return false; +} + void CSoundBase::ResetVars() { m_ALSource = 0; @@ -58,7 +73,8 @@ void CSoundBase::ResetVars() m_EndFadeTime = 0; m_StartVolume = 0; m_EndVolume = 0; - + m_IsManaged = false; + m_TouchTime = timer_Time(); ResetFade(); } @@ -71,12 +87,44 @@ void CSoundBase::ResetFade() m_ShouldBePlaying = false; } + +bool CSoundBase::InitOpenAL() +{ + alGetError(); /* clear error */ + m_ALSource = g_SoundManager->GetALSource( this ); + + AL_CHECK + + if ( m_ALSource ) + { + alSourcef(m_ALSource,AL_PITCH,1.0f); + AL_CHECK + alSourcef(m_ALSource,AL_GAIN,1.0f); + AL_CHECK + alSourcei(m_ALSource,AL_LOOPING,AL_FALSE); + AL_CHECK + return true; + } + else + { +// LOGERROR(L"Source not allocated by SOundManager\n", 0); + } + return false; +} + + +void CSoundBase::SetIsManaged(bool manage) +{ + m_IsManaged = manage; +} + void CSoundBase::SetGain(ALfloat gain) { AL_CHECK if ( m_ALSource ) { + CScopeLock lock(m_ItemMutex); alSourcef(m_ALSource, AL_GAIN, gain); AL_CHECK } @@ -86,6 +134,7 @@ void CSoundBase::SetRollOff(ALfloat rolls) { if ( m_ALSource ) { + CScopeLock lock(m_ItemMutex); alSourcef(m_ALSource, AL_REFERENCE_DISTANCE, 70.0f); AL_CHECK alSourcef(m_ALSource, AL_MAX_DISTANCE, 200.0); @@ -105,6 +154,7 @@ void CSoundBase::SetCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain) { if ( m_ALSource ) { + CScopeLock lock(m_ItemMutex); AL_CHECK alSourcef(m_ALSource, AL_CONE_INNER_ANGLE, innerCone); AL_CHECK @@ -119,6 +169,7 @@ void CSoundBase::SetPitch(ALfloat pitch) { if ( m_ALSource ) { + CScopeLock lock(m_ItemMutex); alSourcef(m_ALSource, AL_PITCH, pitch); AL_CHECK } @@ -128,44 +179,25 @@ void CSoundBase::SetDirection(const CVector3D& direction) { if ( m_ALSource ) { + CScopeLock lock(m_ItemMutex); alSourcefv(m_ALSource, AL_DIRECTION, direction.GetFloatArray()); AL_CHECK } } -bool CSoundBase::InitOpenAL() -{ - alGetError(); /* clear error */ - alGenSources(1, &m_ALSource); - ALenum anErr = alGetError(); - - if (anErr == AL_NO_ERROR) - { - alSourcef(m_ALSource,AL_PITCH,1.0f); - AL_CHECK - alSourcef(m_ALSource,AL_GAIN,1.0f); - AL_CHECK - alSourcei(m_ALSource,AL_LOOPING,AL_FALSE); - AL_CHECK - return true; - } - else - { - CSoundManager::al_ReportError( anErr, __func__, __LINE__); - } - return false; -} bool CSoundBase::IsPlaying() { - ALenum proc_state = AL_STOPPED; - if ( m_ALSource != 0 ) + if ( m_ALSource ) { + CScopeLock lock(m_ItemMutex); + int proc_state; alGetSourceiv(m_ALSource, AL_SOURCE_STATE, &proc_state); AL_CHECK - } - return (proc_state == AL_PLAYING); + return (proc_state == AL_PLAYING); + } + return false; } void CSoundBase::SetLastPlay(bool last) @@ -178,10 +210,17 @@ bool CSoundBase::IdleTask() return true; } +void CSoundBase::TouchTimer() +{ + if ( IsPlaying() ) + m_TouchTime = timer_Time(); +} + void CSoundBase::SetLocation (const CVector3D& position) { if ( m_ALSource != 0 ) { + CScopeLock lock(m_ItemMutex); alSourcefv(m_ALSource,AL_POSITION, position.GetFloatArray()); AL_CHECK } @@ -224,6 +263,11 @@ bool CSoundBase::GetLooping() return m_Looping; } +bool CSoundBase::SoundStale() +{ + return !m_IsManaged && ( ( timer_Time() - m_TouchTime ) > 120 ); +} + void CSoundBase::SetLooping(bool loops) { m_Looping = loops; @@ -236,10 +280,23 @@ void CSoundBase::SetLooping(bool loops) void CSoundBase::Play() { + CScopeLock lock(m_ItemMutex); + + m_TouchTime = timer_Time(); m_ShouldBePlaying = true; - if (m_ALSource != 0) - alSourcePlay(m_ALSource); AL_CHECK + if (m_ALSource != 0) + { + alSourcePlay(m_ALSource); + ALenum err = alGetError(); + if (err != AL_NO_ERROR) + { + if (err == AL_INVALID) + g_SoundManager->SetDistressThroughError(); + else + g_SoundManager->al_ReportError(err, __func__, __LINE__); + } + } } void CSoundBase::PlayAndDelete() @@ -248,6 +305,7 @@ void CSoundBase::PlayAndDelete() Play(); } + void CSoundBase::FadeAndDelete(double fadeTime) { SetLastPlay(true); @@ -264,6 +322,7 @@ void CSoundBase::PlayLoop() { if (m_ALSource != 0) { + m_TouchTime = timer_Time(); SetLooping(true); Play(); AL_CHECK @@ -302,6 +361,7 @@ void CSoundBase::Stop() m_ShouldBePlaying = false; if (m_ALSource != 0) { + CScopeLock lock(m_ItemMutex); int proc_state; alSourcei(m_ALSource, AL_LOOPING, AL_FALSE); alGetSourceiv(m_ALSource, AL_SOURCE_STATE, &proc_state); diff --git a/source/soundmanager/items/CSoundBase.h b/source/soundmanager/items/CSoundBase.h index 10ffc1b229..46b26381f5 100644 --- a/source/soundmanager/items/CSoundBase.h +++ b/source/soundmanager/items/CSoundBase.h @@ -23,6 +23,7 @@ #if CONFIG2_AUDIO #include "lib/external_libraries/openal.h" +#include "ps/ThreadUtil.h" #include "soundmanager/items/ISoundItem.h" #include "soundmanager/data/SoundData.h" @@ -33,14 +34,17 @@ protected: ALuint m_ALSource; CSoundData* m_SoundData; + bool m_IsManaged; bool m_LastPlay; bool m_Looping; bool m_ShouldBePlaying; double m_StartFadeTime; double m_EndFadeTime; + double m_TouchTime; ALfloat m_StartVolume; ALfloat m_EndVolume; + CMutex m_ItemMutex; public: CSoundBase(); @@ -57,6 +61,10 @@ public: virtual void SetDirection(const CVector3D& direction); virtual void SetCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain); virtual void SetLastPlay(bool last); + virtual void ReleaseOpenAL(); + virtual void TouchTimer(); + virtual void SetIsManaged(bool manage); + virtual bool IsFading(); void Play(); @@ -66,6 +74,8 @@ public: void Stop(); void StopAndDelete(); void FadeToIn(ALfloat newVolume, double fadeDuration); + void Attach(CSoundData* itemData); + bool CanAttach(CSoundData* itemData); void PlayAsMusic(); void PlayAsAmbient(); @@ -77,6 +87,7 @@ public: virtual bool IsPlaying(); virtual void SetLocation(const CVector3D& position); virtual void FadeAndDelete(double fadeTime); + virtual bool SoundStale(); protected: diff --git a/source/soundmanager/items/CSoundItem.cpp b/source/soundmanager/items/CSoundItem.cpp index 346a443fde..e313b0865c 100644 --- a/source/soundmanager/items/CSoundItem.cpp +++ b/source/soundmanager/items/CSoundItem.cpp @@ -40,35 +40,51 @@ CSoundItem::CSoundItem(CSoundData* sndData) CSoundItem::~CSoundItem() { - AL_CHECK - - Stop(); +} - if (m_ALSource != 0) - { - alSourcei(m_ALSource, AL_BUFFER, 0); - AL_CHECK - } +void CSoundItem::ReleaseOpenAL() +{ + alSourcei(m_ALSource, AL_BUFFER, 0); + + CSoundBase::ReleaseOpenAL(); } bool CSoundItem::IdleTask() { + if ( m_ALSource == 0 ) + return false; + + TouchTimer(); HandleFade(); - if (m_LastPlay && (m_ALSource != 0) ) + if (m_LastPlay && m_ALSource) { + CScopeLock lock(m_ItemMutex); int proc_state; - alGetSourceiv(m_ALSource, AL_SOURCE_STATE, &proc_state); + alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state); AL_CHECK return (proc_state != AL_STOPPED); } return true; } +bool CSoundItem::CanAttach(CSoundData* itemData) +{ + return itemData->IsOneShot() && (itemData->GetBufferCount() == 1); +} void CSoundItem::Attach(CSoundData* itemData) { - if (itemData != NULL && (m_ALSource != 0) ) +AL_CHECK + if (m_SoundData != NULL) { + CSoundData::ReleaseSoundData(m_SoundData); + m_SoundData = 0; + } +AL_CHECK + if (itemData != NULL) + { + alSourcei(m_ALSource, AL_BUFFER, 0); + AL_CHECK m_SoundData = itemData->IncrementCount(); alSourcei(m_ALSource, AL_BUFFER, m_SoundData->GetBuffer()); diff --git a/source/soundmanager/items/CSoundItem.h b/source/soundmanager/items/CSoundItem.h index 2127edaf73..b510b9d7b5 100644 --- a/source/soundmanager/items/CSoundItem.h +++ b/source/soundmanager/items/CSoundItem.h @@ -28,12 +28,14 @@ class CSoundItem : public CSoundBase { public: - CSoundItem(); - CSoundItem(CSoundData* sndData); - - virtual ~CSoundItem(); - void Attach(CSoundData* itemData); - bool IdleTask(); + CSoundItem(); + CSoundItem(CSoundData* sndData); + + virtual ~CSoundItem(); + void Attach(CSoundData* itemData); + bool CanAttach(CSoundData* itemData); + bool IdleTask(); + void ReleaseOpenAL(); }; diff --git a/source/soundmanager/items/CStreamItem.cpp b/source/soundmanager/items/CStreamItem.cpp index 53b06742fb..7471ee547f 100644 --- a/source/soundmanager/items/CStreamItem.cpp +++ b/source/soundmanager/items/CStreamItem.cpp @@ -35,7 +35,12 @@ CStreamItem::CStreamItem(CSoundData* sndData) CStreamItem::~CStreamItem() { - Stop(); +} + +void CStreamItem::ReleaseOpenAL() +{ + int num_processed; + alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed); if (m_ALSource != 0) { @@ -50,11 +55,13 @@ CStreamItem::~CStreamItem() delete[] al_buf; } } + CSoundBase::ReleaseOpenAL(); } bool CStreamItem::IdleTask() { AL_CHECK + TouchTimer(); HandleFade(); AL_CHECK @@ -98,10 +105,20 @@ bool CStreamItem::IdleTask() } return true; } +bool CStreamItem::CanAttach(CSoundData* itemData) +{ + return ! itemData->IsOneShot(); +} void CStreamItem::Attach(CSoundData* itemData) { - if (itemData != NULL && (m_ALSource != 0) ) + if (m_SoundData != NULL) + { + CSoundData::ReleaseSoundData(m_SoundData); + m_SoundData = 0; + } + + if (itemData != NULL) { m_SoundData = itemData->IncrementCount(); alSourceQueueBuffers(m_ALSource, m_SoundData->GetBufferCount(), (const ALuint *)m_SoundData->GetBufferPtr()); diff --git a/source/soundmanager/items/CStreamItem.h b/source/soundmanager/items/CStreamItem.h index e5267ebe1e..6ca25b7345 100644 --- a/source/soundmanager/items/CStreamItem.h +++ b/source/soundmanager/items/CStreamItem.h @@ -28,15 +28,16 @@ class CStreamItem : public CSoundBase { public: - CStreamItem(CSoundData* sndData); - virtual ~CStreamItem(); - - virtual void SetLooping(bool loops); - virtual bool IdleTask(); - -protected: - virtual void Attach(CSoundData* itemData); + CStreamItem(CSoundData* sndData); + virtual ~CStreamItem(); + + virtual void SetLooping(bool loops); + virtual bool IdleTask(); + virtual bool CanAttach(CSoundData* itemData); + virtual void Attach(CSoundData* itemData); +protected: + virtual void ReleaseOpenAL(); }; #endif // CONFIG2_AUDIO diff --git a/source/soundmanager/items/ISoundItem.h b/source/soundmanager/items/ISoundItem.h index 33d975e314..2e59b7da37 100644 --- a/source/soundmanager/items/ISoundItem.h +++ b/source/soundmanager/items/ISoundItem.h @@ -25,6 +25,7 @@ #include "lib/external_libraries/openal.h" #include "maths/Vector3D.h" #include "ps/CStr.h" +#include "soundmanager/data/SoundData.h" class ISoundItem { @@ -42,10 +43,15 @@ public: virtual void Play() = 0; virtual void Stop() = 0; + virtual bool SoundStale() = 0; + virtual void TouchTimer() = 0; + virtual void Attach(CSoundData* itemData) = 0; + virtual bool CanAttach(CSoundData* itemData) = 0; virtual void EnsurePlay() = 0; virtual void PlayAsMusic() = 0; virtual void PlayAsAmbient() = 0; + virtual void SetIsManaged(bool manage) = 0; virtual void PlayAndDelete() = 0; virtual void StopAndDelete() = 0; diff --git a/source/soundmanager/js/SoundGroup.cpp b/source/soundmanager/js/SoundGroup.cpp index b3586b6898..7b191cb3bd 100644 --- a/source/soundmanager/js/SoundGroup.cpp +++ b/source/soundmanager/js/SoundGroup.cpp @@ -157,7 +157,7 @@ float CSoundGroup::RadiansOffCenter(const CVector3D& position, bool& onScreen, f return answer; } -void CSoundGroup::UploadPropertiesAndPlay(unsigned int theIndex, const CVector3D& position) +void CSoundGroup::UploadPropertiesAndPlay(int theIndex, const CVector3D& position, entity_id_t source) { #if CONFIG2_AUDIO if ( g_SoundManager ) @@ -175,11 +175,13 @@ void CSoundGroup::UploadPropertiesAndPlay(unsigned int theIndex, const CVector3D if ( snd_group.size() > theIndex ) { - if ( ISoundItem* hSound = snd_group[theIndex] ) + if ( CSoundData* sndData = snd_group[theIndex] ) { CVector3D origin = g_Game->GetView()->GetCamera()->GetOrientation().GetTranslation(); float sndDist = origin.Y; + ISoundItem* hSound = g_SoundManager->ItemForEntity( source, sndData); + if (!TestFlag(eOmnipresent)) { if (TestFlag(eDistanceless)) @@ -208,6 +210,7 @@ void CSoundGroup::UploadPropertiesAndPlay(unsigned int theIndex, const CVector3D #else // !CONFIG2_AUDIO UNUSED2(theIndex); UNUSED2(position); + UNUSED2(source); #endif // !CONFIG2_AUDIO } @@ -219,14 +222,14 @@ static void HandleError(const CStrW& message, const VfsPath& pathname, Status er LOGERROR(L"%ls: pathname=%ls, error=%ls", message.c_str(), pathname.string().c_str(), ErrorString(err)); } -void CSoundGroup::PlayNext(const CVector3D& position) +void CSoundGroup::PlayNext(const CVector3D& position, entity_id_t source) { // if no sounds, return if (filenames.size() == 0) return; m_index = (size_t)rand(0, (size_t)filenames.size()); - UploadPropertiesAndPlay(m_index, position); + UploadPropertiesAndPlay(m_index, position, source); } void CSoundGroup::Reload() @@ -234,18 +237,18 @@ void CSoundGroup::Reload() m_index = 0; // reset our index #if CONFIG2_AUDIO - snd_group.clear(); + ReleaseGroup(); if ( g_SoundManager ) { for (size_t i = 0; i < filenames.size(); i++) { VfsPath thePath = m_filepath/filenames[i]; - ISoundItem* temp = g_SoundManager->LoadItem(thePath); + CSoundData* itemData = CSoundData::SoundDataFromFile(thePath); - if (temp == NULL) + if (itemData == NULL) HandleError(L"error loading sound", thePath, ERR::FAIL); else - snd_group.push_back(temp); + snd_group.push_back(itemData->IncrementCount()); } if (TestFlag(eRandOrder)) @@ -259,7 +262,7 @@ void CSoundGroup::ReleaseGroup() #if CONFIG2_AUDIO for (size_t i = 0; i < snd_group.size(); i++) { - snd_group[i]->FadeAndDelete(0.2); + CSoundData::ReleaseSoundData( snd_group[i] ); } snd_group.clear(); #endif // CONFIG2_AUDIO diff --git a/source/soundmanager/js/SoundGroup.h b/source/soundmanager/js/SoundGroup.h index 70d8ca18ac..d19783a74c 100644 --- a/source/soundmanager/js/SoundGroup.h +++ b/source/soundmanager/js/SoundGroup.h @@ -54,6 +54,8 @@ Example SoundGroup.xml #include "lib/config2.h" #include "lib/file/vfs/vfs_path.h" +#include "simulation2/system/Entity.h" +#include "soundmanager/data/SoundData.h" #include @@ -82,7 +84,7 @@ public: // Play next sound in group // @param position world position of the entity generating the sound // (ignored if the eOmnipresent flag is set) - void PlayNext(const CVector3D& position); + void PlayNext(const CVector3D& position, entity_id_t source); float RadiansOffCenter(const CVector3D& position, bool& onScreen, float& itemRollOff); @@ -105,13 +107,15 @@ public: private: void SetGain(float gain); - void UploadPropertiesAndPlay(unsigned int theIndex, const CVector3D& position); + + void UploadPropertiesAndPlay(int theIndex, const CVector3D& position, entity_id_t source); + void SetDefaultValues(); - size_t m_index; // index of the next sound to play + int m_index; // index of the next sound to play #if CONFIG2_AUDIO - std::vector snd_group; // we store the handles so we can load now and play later + std::vector snd_group; // we store the handles so we can load now and play later #endif std::vector filenames; // we need the filenames so we can reload when necessary.