forked from 0ad/0ad
newest soundmanager patch, should give better battle sequences, and handle low resource situations correctly.
This was SVN commit r13209.
This commit is contained in:
parent
c16b93794a
commit
e4a9312c46
@ -135,7 +135,7 @@ public:
|
||||
sourcePos = CVector3D(cmpPosition->GetPosition());
|
||||
}
|
||||
|
||||
group->PlayNext(sourcePos);
|
||||
group->PlayNext(sourcePos, source);
|
||||
}
|
||||
#else // !CONFIG2_AUDIO
|
||||
UNUSED2(name);
|
||||
|
@ -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<SOURCE_NUM;x++)
|
||||
{
|
||||
m_ALSourceBuffer[x].ALSource = sourceList[x];
|
||||
m_ALSourceBuffer[x].SourceItem = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR(L"error in gensource = %d", err);
|
||||
}
|
||||
delete[] sourceList;
|
||||
}
|
||||
}
|
||||
|
||||
// check if init succeeded.
|
||||
@ -311,6 +338,9 @@ Status CSoundManager::AlcInit()
|
||||
else
|
||||
{
|
||||
LOGERROR(L"Sound: AlcInit failed, m_Device=%p m_Context=%p dev_name=%hs err=%d\n", m_Device, m_Context, dev_name, err);
|
||||
|
||||
|
||||
|
||||
// FIXME Hack to get around exclusive access to the sound device
|
||||
#if OS_UNIX
|
||||
ret = INFO::OK;
|
||||
@ -321,6 +351,80 @@ Status CSoundManager::AlcInit()
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CSoundManager::InDistress()
|
||||
{
|
||||
CScopeLock lock(m_DistressMutex);
|
||||
|
||||
if ( m_DistressTime == 0 )
|
||||
return false;
|
||||
else if ( (timer_Time() - m_DistressTime) > 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; x<SOURCE_NUM;x++)
|
||||
{
|
||||
if ( ! m_ALSourceBuffer[x].SourceItem )
|
||||
{
|
||||
m_SourceCOunt++;
|
||||
m_ALSourceBuffer[x].SourceItem = anItem;
|
||||
return m_ALSourceBuffer[x].ALSource;
|
||||
}
|
||||
}
|
||||
SetDistressThroughShortage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSoundManager::ReleaseALSource(ALuint theSource)
|
||||
{
|
||||
for ( int x=0; x<SOURCE_NUM;x++)
|
||||
{
|
||||
if ( m_ALSourceBuffer[x].ALSource == theSource )
|
||||
{
|
||||
m_SourceCOunt--;
|
||||
m_ALSourceBuffer[x].SourceItem = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSoundManager::SetMemoryUsage(long bufferSize, int bufferCount)
|
||||
{
|
||||
m_BufferCount = bufferCount;
|
||||
@ -361,6 +465,17 @@ ISoundItem* CSoundManager::LoadItem(const VfsPath& itemPath)
|
||||
AL_CHECK
|
||||
|
||||
CSoundData* itemData = CSoundData::SoundDataFromFile(itemPath);
|
||||
|
||||
AL_CHECK
|
||||
if ( itemData )
|
||||
return CSoundManager::ItemForData( itemData );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISoundItem* CSoundManager::ItemForData(CSoundData* itemData)
|
||||
{
|
||||
AL_CHECK
|
||||
ISoundItem* answer = NULL;
|
||||
|
||||
AL_CHECK
|
||||
@ -392,17 +507,46 @@ void CSoundManager::IdleTask()
|
||||
AL_CHECK
|
||||
if (m_CurrentTune)
|
||||
m_CurrentTune->EnsurePlay();
|
||||
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);
|
||||
|
@ -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 <vector>
|
||||
#include <map>
|
||||
@ -31,9 +35,18 @@
|
||||
#define AL_CHECK CSoundManager::al_check(__func__, __LINE__);
|
||||
|
||||
typedef std::vector<ISoundItem*> ItemsList;
|
||||
typedef std::map<entity_id_t, ISoundItem*> 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();
|
||||
|
@ -34,6 +34,8 @@ COggData::COggData()
|
||||
|
||||
COggData::~COggData()
|
||||
{
|
||||
ogg->Close();
|
||||
|
||||
alDeleteBuffers(m_BuffersUsed, m_Buffer);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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();
|
||||
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 <vector>
|
||||
|
||||
@ -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<ISoundItem*> snd_group; // we store the handles so we can load now and play later
|
||||
std::vector<CSoundData*> snd_group; // we store the handles so we can load now and play later
|
||||
#endif
|
||||
std::vector<std::wstring> filenames; // we need the filenames so we can reload when necessary.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user