1
0
forked from 0ad/0ad

new threaded soundmanager and proper distance roll off

This was SVN commit r12709.
This commit is contained in:
stwf 2012-09-27 02:42:03 +00:00
parent e72b603cce
commit 44821da620
4 changed files with 238 additions and 66 deletions

View File

@ -28,10 +28,212 @@
#include "soundmanager/js/MusicSound.h" #include "soundmanager/js/MusicSound.h"
#include "soundmanager/js/Sound.h" #include "soundmanager/js/Sound.h"
#include "ps/CLogger.h" #include "ps/CLogger.h"
#include "ps/Profiler2.h"
CSoundManager* g_SoundManager = NULL; 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<CSoundManagerWorker*>(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() void CSoundManager::ScriptingInit()
{ {
JAmbientSound::ScriptingInit(); JAmbientSound::ScriptingInit();
@ -76,7 +278,6 @@ void CSoundManager::al_check(const char* caller, int line)
CSoundManager::CSoundManager() CSoundManager::CSoundManager()
{ {
m_Items = new ItemsList;
m_CurrentEnvirons = 0; m_CurrentEnvirons = 0;
m_CurrentTune = 0; m_CurrentTune = 0;
m_Gain = 1; m_Gain = 1;
@ -87,23 +288,20 @@ CSoundManager::CSoundManager()
m_BufferSize = 65536; m_BufferSize = 65536;
m_MusicEnabled = true; m_MusicEnabled = true;
m_Enabled = AlcInit() == INFO::OK; m_Enabled = AlcInit() == INFO::OK;
InitListener();
m_Worker = new CSoundManagerWorker();
m_Worker->SetEnabled( true );
} }
CSoundManager::~CSoundManager() CSoundManager::~CSoundManager()
{ {
ItemsList::iterator lstr = m_Items->begin(); m_Worker->Shutdown();
while (lstr != m_Items->end()) m_Worker = 0L;
{
(*lstr)->Stop();
delete *lstr;
lstr++;
}
alcDestroyContext(m_Context); alcDestroyContext(m_Context);
alcCloseDevice(m_Device); alcCloseDevice(m_Device);
delete m_Items;
m_Items = 0L;
m_CurrentEnvirons = 0; m_CurrentEnvirons = 0;
m_CurrentTune = 0; m_CurrentTune = 0;
} }
@ -156,11 +354,13 @@ long CSoundManager::GetBufferSize()
return m_BufferSize; return m_BufferSize;
} }
void CSoundManager::SetMasterGain(float gain) void CSoundManager::SetMasterGain(float gain)
{ {
m_Gain = gain; m_Gain = gain;
alListenerf( AL_GAIN, m_Gain);
AL_CHECK
} }
void CSoundManager::SetMusicGain(float gain) void CSoundManager::SetMusicGain(float gain)
{ {
m_MusicGain = gain; m_MusicGain = gain;
@ -198,67 +398,32 @@ ISoundItem* CSoundManager::LoadItem(const VfsPath& itemPath)
answer = new CStreamItem(itemData); answer = new CStreamItem(itemData);
} }
if (answer != NULL) if ( answer && m_Worker )
m_Items->push_back(answer); m_Worker->addItem( answer );
} }
return answer; return answer;
} }
unsigned long CSoundManager::Count()
{
return m_Items->size();
}
void CSoundManager::IdleTask() 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 AL_CHECK
if (m_CurrentTune) if (m_CurrentTune)
m_CurrentTune->EnsurePlay(); m_CurrentTune->EnsurePlay();
if (m_CurrentEnvirons) if (m_CurrentEnvirons)
m_CurrentEnvirons->EnsurePlay(); m_CurrentEnvirons->EnsurePlay();
AL_CHECK AL_CHECK
if (m_Worker)
m_Worker->CleanupItems();
} }
void CSoundManager::DeleteItem(long itemNum) void CSoundManager::DeleteItem(long itemNum)
{ {
ItemsList::iterator lstr = m_Items->begin(); if (m_Worker)
lstr += itemNum; m_Worker->DeleteItem(itemNum);
delete *lstr;
m_Items->erase(lstr);
} }
ISoundItem* CSoundManager::GetSoundItem(unsigned long itemRow)
{
return (*m_Items)[itemRow];
}
void CSoundManager::InitListener() void CSoundManager::InitListener()
{ {
@ -270,7 +435,7 @@ void CSoundManager::InitListener()
alListenerfv(AL_VELOCITY,listenerVel); alListenerfv(AL_VELOCITY,listenerVel);
alListenerfv(AL_ORIENTATION,listenerOri); alListenerfv(AL_ORIENTATION,listenerOri);
alDistanceModel(AL_EXPONENT_DISTANCE); alDistanceModel(AL_LINEAR_DISTANCE);
} }
void CSoundManager::PlayActionItem(ISoundItem* anItem) void CSoundManager::PlayActionItem(ISoundItem* anItem)
@ -279,7 +444,7 @@ void CSoundManager::PlayActionItem(ISoundItem* anItem)
{ {
if (m_Enabled && (m_ActionGain > 0)) if (m_Enabled && (m_ActionGain > 0))
{ {
anItem->SetGain(m_Gain * m_ActionGain); anItem->SetGain( m_ActionGain );
anItem->Play(); anItem->Play();
AL_CHECK AL_CHECK
} }
@ -290,7 +455,7 @@ void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain)
if (anItem) if (anItem)
{ {
if (m_Enabled && (m_ActionGain > 0)) { if (m_Enabled && (m_ActionGain > 0)) {
anItem->SetGain(m_Gain * groupGain); anItem->SetGain(m_ActionGain * groupGain);
anItem->Play(); anItem->Play();
AL_CHECK AL_CHECK
} }
@ -312,10 +477,12 @@ void CSoundManager::SetMusicItem(ISoundItem* anItem)
AL_CHECK AL_CHECK
if (m_CurrentTune) if (m_CurrentTune)
{ {
m_CurrentTune->FadeAndDelete(3.00); m_CurrentTune->FadeAndDelete(2.00);
m_CurrentTune = 0L; m_CurrentTune = 0L;
} }
IdleTask(); IdleTask();
if (anItem) if (anItem)
{ {
if (m_MusicEnabled && m_Enabled) if (m_MusicEnabled && m_Enabled)
@ -323,7 +490,7 @@ void CSoundManager::SetMusicItem(ISoundItem* anItem)
m_CurrentTune = anItem; m_CurrentTune = anItem;
m_CurrentTune->SetGain(0); m_CurrentTune->SetGain(0);
m_CurrentTune->PlayLoop(); m_CurrentTune->PlayLoop();
m_CurrentTune->FadeToIn(m_Gain * m_MusicGain, 2.00); m_CurrentTune->FadeToIn( m_MusicGain, 1.00);
} }
else else
{ {
@ -349,7 +516,7 @@ void CSoundManager::SetAmbientItem(ISoundItem* anItem)
m_CurrentEnvirons = anItem; m_CurrentEnvirons = anItem;
m_CurrentEnvirons->SetGain(0); m_CurrentEnvirons->SetGain(0);
m_CurrentEnvirons->PlayLoop(); m_CurrentEnvirons->PlayLoop();
m_CurrentEnvirons->FadeToIn(m_Gain * m_AmbientGain, 2.00); m_CurrentEnvirons->FadeToIn( m_AmbientGain, 2.00);
} }
} }
AL_CHECK AL_CHECK

View File

@ -32,6 +32,7 @@
typedef std::vector<ISoundItem*> ItemsList; typedef std::vector<ISoundItem*> ItemsList;
class CSoundManagerWorker;
class CSoundManager class CSoundManager
{ {
@ -42,7 +43,7 @@ protected:
ALCdevice* m_Device; ALCdevice* m_Device;
ISoundItem* m_CurrentTune; ISoundItem* m_CurrentTune;
ISoundItem* m_CurrentEnvirons; ISoundItem* m_CurrentEnvirons;
ItemsList* m_Items; CSoundManagerWorker* m_Worker;
float m_Gain; float m_Gain;
float m_MusicGain; float m_MusicGain;
float m_AmbientGain; float m_AmbientGain;

View File

@ -142,7 +142,7 @@ bool CSoundBase::InitOpenAL()
if (anErr == AL_NO_ERROR) 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}; ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
alSourcef(m_ALSource,AL_PITCH,1.0f); alSourcef(m_ALSource,AL_PITCH,1.0f);
@ -151,6 +151,12 @@ bool CSoundBase::InitOpenAL()
alSourcefv(m_ALSource,AL_VELOCITY,source0Vel); alSourcefv(m_ALSource,AL_VELOCITY,source0Vel);
alSourcei(m_ALSource,AL_LOOPING,AL_FALSE); alSourcei(m_ALSource,AL_LOOPING,AL_FALSE);
AL_CHECK 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; return true;
} }

View File

@ -130,7 +130,7 @@ float CSoundGroup::RadiansOffCenter(const CVector3D& position, bool& onScreen, f
else { else {
if ((x < 0) || (x > screenWidth)) if ((x < 0) || (x > screenWidth))
{ {
itemRollOff = 0.5; itemRollOff = 5.0;
} }
float pixPerRadian = audioWidth / (radianCap * 2); float pixPerRadian = audioWidth / (radianCap * 2);
answer = (x - (screenWidth/2)) / pixPerRadian; answer = (x - (screenWidth/2)) / pixPerRadian;
@ -147,7 +147,7 @@ float CSoundGroup::RadiansOffCenter(const CVector3D& position, bool& onScreen, f
else { else {
if ((y < 0) || (y > screenHeight)) 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 CONFIG2_AUDIO
if ( g_SoundManager ) { if ( g_SoundManager ) {
bool isOnscreen; bool isOnscreen;
ALfloat initialRolllOff = 0.02f; ALfloat initialRolllOff = 1.0f;
ALfloat itemRollOff = initialRolllOff; ALfloat itemRollOff = initialRolllOff;
float offSet = RadiansOffCenter(position, isOnscreen, itemRollOff); float offSet = RadiansOffCenter(position, isOnscreen, itemRollOff);
@ -178,7 +178,7 @@ void CSoundGroup::UploadPropertiesAndPlay(int theIndex, const CVector3D& positio
if (!TestFlag(eOmnipresent)) 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)) if (TestFlag(eDistanceless))
hSound->SetRollOff(initialRolllOff); hSound->SetRollOff(initialRolllOff);
else else
@ -265,8 +265,6 @@ void CSoundGroup::Update(float UNUSED(TimeSinceLastFrame))
bool CSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML) bool CSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML)
{ {
// LOGERROR(L"loading new sound group '%ls'", pathnameXML.string().c_str());
CXeromyces XeroFile; CXeromyces XeroFile;
if (XeroFile.Load(g_VFS, pathnameXML) != PSRETURN_OK) if (XeroFile.Load(g_VFS, pathnameXML) != PSRETURN_OK)
{ {