mirror of
https://github.com/halpz/re3.git
synced 2025-06-28 22:06:28 +00:00
Multi-threaded audio fixes
This commit is contained in:
@ -1089,42 +1089,23 @@ CStream::FlagAsToBeProcessed(bool close)
|
||||
gAudioThreadCv.notify_one();
|
||||
}
|
||||
|
||||
extern CStream *aStream[];
|
||||
void audioFileOpsThread()
|
||||
{
|
||||
std::queue<CStream*> m_streamsToDelete;
|
||||
|
||||
do
|
||||
{
|
||||
CStream *stream;
|
||||
{
|
||||
// Just a semaphore
|
||||
std::unique_lock<std::mutex> queueMutex(gAudioThreadQueueMutex);
|
||||
gAudioThreadCv.wait(queueMutex, [m_streamsToDelete] { return gStreamsToProcess.size() > 0 || m_streamsToDelete.size() > 0 || gAudioThreadTerm; });
|
||||
gAudioThreadCv.wait(queueMutex, [] { return gStreamsToProcess.size() > 0 || gAudioThreadTerm; });
|
||||
if (gAudioThreadTerm)
|
||||
return;
|
||||
|
||||
if (!gStreamsToProcess.empty()) {
|
||||
stream = gStreamsToProcess.front();
|
||||
gStreamsToProcess.pop();
|
||||
} else {
|
||||
// End of streams. Perform deleting streams
|
||||
while(!m_streamsToDelete.empty()) {
|
||||
CStream *stream = m_streamsToDelete.front();
|
||||
m_streamsToDelete.pop();
|
||||
if (stream->m_pSoundFile) {
|
||||
delete stream->m_pSoundFile;
|
||||
stream->m_pSoundFile = nil;
|
||||
}
|
||||
|
||||
if (stream->m_pBuffer) {
|
||||
free(stream->m_pBuffer);
|
||||
stream->m_pBuffer = nil;
|
||||
}
|
||||
delete stream;
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(stream->m_mutex);
|
||||
@ -1133,17 +1114,22 @@ void audioFileOpsThread()
|
||||
bool insertBufsAfterCheck = false;
|
||||
|
||||
do {
|
||||
if (stream->m_nDeleteMe == 1) {
|
||||
m_streamsToDelete.push(stream);
|
||||
stream->m_nDeleteMe = 2;
|
||||
break;
|
||||
} else if (stream->m_nDeleteMe == 2) {
|
||||
if (!stream->IsOpened()) {
|
||||
// We MUST do that here, because we release mutex for m_pSoundFile->Seek() and m_pSoundFile->Decode() since they're costly
|
||||
if (stream->m_pSoundFile) {
|
||||
delete stream->m_pSoundFile;
|
||||
stream->m_pSoundFile = nil;
|
||||
}
|
||||
|
||||
if (stream->m_pBuffer) {
|
||||
free(stream->m_pBuffer);
|
||||
stream->m_pBuffer = nil;
|
||||
}
|
||||
lock.unlock();
|
||||
stream->m_closeCv.notify_one();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!stream->IsOpened())
|
||||
break;
|
||||
|
||||
if (stream->m_bReset)
|
||||
break;
|
||||
|
||||
@ -1223,14 +1209,14 @@ void CStream::Terminate()
|
||||
#endif
|
||||
}
|
||||
|
||||
CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate) :
|
||||
CStream::CStream(ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS]) :
|
||||
m_pAlSources(sources),
|
||||
m_alBuffers(buffers),
|
||||
m_pBuffer(nil),
|
||||
m_bPaused(false),
|
||||
m_bActive(false),
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
m_nDeleteMe(false),
|
||||
m_bIExist(false),
|
||||
m_bDoSeek(false),
|
||||
m_SeekPos(0),
|
||||
#endif
|
||||
@ -1242,6 +1228,31 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
|
||||
m_nLoopCount(1)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
bool CStream::Open(const char* filename, uint32 overrideSampleRate)
|
||||
{
|
||||
if (IsOpened()) return false;
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
CStream *stream = this;
|
||||
// Wait for thread to close old one. We can't close it here, because the thread might be running Decode() or Seek(), while mutex is released
|
||||
m_closeCv.wait(lock, [this] { return m_pSoundFile == nil && m_pBuffer == nil; });
|
||||
|
||||
m_bDoSeek = false;
|
||||
m_SeekPos = 0;
|
||||
#endif
|
||||
|
||||
m_bPaused = false;
|
||||
m_bActive = false;
|
||||
m_bReset = false;
|
||||
m_nVolume = 0;
|
||||
m_nPan = 0;
|
||||
m_nPosBeforeReset = 0;
|
||||
m_nLoopCount = 1;
|
||||
|
||||
// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)
|
||||
#if !defined(_WIN32)
|
||||
char *real = casepath(filename);
|
||||
@ -1278,7 +1289,7 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
|
||||
else
|
||||
m_pSoundFile = nil;
|
||||
|
||||
if ( IsOpened() )
|
||||
if ( m_pSoundFile && m_pSoundFile->IsOpened() )
|
||||
{
|
||||
uint32 bufSize = m_pSoundFile->GetBufferSize();
|
||||
if(bufSize != 0) { // Otherwise it's deferred
|
||||
@ -1293,8 +1304,12 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
|
||||
DEV("Buffer sec: %f\n", (float(m_pSoundFile->GetBufferSamples()) / float(m_pSoundFile->GetChannels())/ float(m_pSoundFile->GetSampleRate())));
|
||||
DEV("Length MS: %02d:%02d\n", (m_pSoundFile->GetLength() / 1000) / 60, (m_pSoundFile->GetLength() / 1000) % 60);
|
||||
}
|
||||
return;
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
m_bIExist = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CStream::~CStream()
|
||||
@ -1304,18 +1319,21 @@ CStream::~CStream()
|
||||
|
||||
void CStream::Close()
|
||||
{
|
||||
if(!IsOpened()) return;
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
m_nDeleteMe = true;
|
||||
// clearing buffer queues are not needed. after m_nDeleteMe set, this stream is ded
|
||||
m_bIExist = false;
|
||||
// clearing buffer queues are not needed. after m_bIExist is cleared, this stream is ded
|
||||
}
|
||||
|
||||
FlagAsToBeProcessed(true);
|
||||
#else
|
||||
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
|
||||
@ -1338,9 +1356,14 @@ bool CStream::HasSource()
|
||||
return (m_pAlSources[0] != AL_NONE) && (m_pAlSources[1] != AL_NONE);
|
||||
}
|
||||
|
||||
// m_bIExist only written in main thread, thus mutex is not needed on main thread
|
||||
bool CStream::IsOpened()
|
||||
{
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
return m_bIExist;
|
||||
#else
|
||||
return m_pSoundFile && m_pSoundFile->IsOpened();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CStream::IsPlaying()
|
||||
|
@ -127,9 +127,10 @@ public:
|
||||
std::mutex m_mutex;
|
||||
std::queue<std::pair<ALuint, ALuint>> m_fillBuffers; // left and right buffer
|
||||
tsQueue<std::pair<ALuint, ALuint>> m_queueBuffers;
|
||||
std::condition_variable m_closeCv;
|
||||
bool m_bDoSeek;
|
||||
uint32 m_SeekPos;
|
||||
uint8 m_nDeleteMe; // 1: add to delete list 2: already on delete list
|
||||
bool m_bIExist;
|
||||
#endif
|
||||
|
||||
void *m_pBuffer;
|
||||
@ -163,8 +164,10 @@ public:
|
||||
static void Initialise();
|
||||
static void Terminate();
|
||||
|
||||
CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate = 32000);
|
||||
CStream(ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS]);
|
||||
~CStream();
|
||||
void Delete();
|
||||
bool Open(const char *filename, uint32 overrideSampleRate = 32000);
|
||||
void Close();
|
||||
|
||||
bool IsOpened();
|
||||
|
Reference in New Issue
Block a user