1
0
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:
stwf 2013-03-01 14:22:28 +00:00
parent c16b93794a
commit e4a9312c46
18 changed files with 462 additions and 112 deletions

View File

@ -135,7 +135,7 @@ public:
sourcePos = CVector3D(cmpPosition->GetPosition());
}
group->PlayNext(sourcePos);
group->PlayNext(sourcePos, source);
}
#else // !CONFIG2_AUDIO
UNUSED2(name);

View File

@ -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);

View File

@ -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();

View File

@ -34,6 +34,8 @@ COggData::COggData()
COggData::~COggData()
{
ogg->Close();
alDeleteBuffers(m_BuffersUsed, m_Buffer);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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());

View File

@ -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

View File

@ -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);

View File

@ -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:

View File

@ -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());

View File

@ -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();
};

View File

@ -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());

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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.