Audio: Add dummy device (in case OpenAL fails to load) and unifiate unit tests

This commit is contained in:
Jérôme Leclercq
2022-03-18 19:03:57 +01:00
parent efa2c0a253
commit 82641c6653
30 changed files with 809 additions and 107 deletions

View File

@@ -133,7 +133,6 @@ namespace Nz
std::lock_guard<std::mutex> lock(m_bufferLock);
UInt32 sampleOffset = m_source->GetSampleOffset();
return static_cast<UInt32>((1000ULL * (sampleOffset + (m_processedSamples / GetChannelCount(m_stream->GetFormat())))) / m_sampleRate);
}
@@ -173,6 +172,8 @@ namespace Nz
{
NazaraAssert(m_stream, "Music not created");
std::lock_guard<std::mutex> lock(m_bufferLock);
SoundStatus status = m_source->GetStatus();
// To compensate any delays (or the timelaps between Play() and the thread startup)
@@ -250,6 +251,8 @@ namespace Nz
*/
void Music::Pause()
{
std::lock_guard<std::mutex> lock(m_bufferLock);
m_source->Pause();
}
@@ -285,24 +288,7 @@ namespace Nz
}
}
else
{
std::mutex mutex;
std::condition_variable cv;
// Starting streaming thread
m_streaming = true;
std::exception_ptr exceptionPtr;
std::unique_lock<std::mutex> lock(mutex);
m_thread = std::thread(&Music::MusicThread, this, std::ref(cv), std::ref(mutex), std::ref(exceptionPtr));
// Wait until thread signal it has properly started (or an error occurred)
cv.wait(lock);
if (exceptionPtr)
std::rethrow_exception(exceptionPtr);
}
StartThread(false);
}
/*!
@@ -319,9 +305,10 @@ namespace Nz
NazaraAssert(m_stream, "Music not created");
bool isPlaying = m_streaming;
bool isPaused = GetStatus() == SoundStatus::Paused;
if (isPlaying)
Stop();
StopThread();
UInt64 sampleOffset = UInt64(offset) * m_sampleRate * GetChannelCount(m_stream->GetFormat()) / 1000ULL;
@@ -329,7 +316,7 @@ namespace Nz
m_streamOffset = sampleOffset;
if (isPlaying)
Play();
StartThread(isPaused);
}
/*!
@@ -380,7 +367,7 @@ namespace Nz
return sampleRead != sampleCount; // End of stream (Does not happen when looping)
}
void Music::MusicThread(std::condition_variable& cv, std::mutex& m, std::exception_ptr& err)
void Music::MusicThread(std::condition_variable& cv, std::mutex& m, std::exception_ptr& err, bool startPaused)
{
// Allocation of streaming buffers
CallOnExit unqueueBuffers([&]
@@ -406,8 +393,14 @@ namespace Nz
cv.notify_all();
return;
}
m_source->Play();
if (startPaused)
{
// little hack to start paused (required by SetPlayingOffset)
m_source->Pause();
m_source->SetSampleOffset(0);
}
CallOnExit stopSource([&]
{
@@ -424,6 +417,11 @@ namespace Nz
// Reading loop (Filling new buffers as playing)
while (m_streaming)
{
// Wait until buffers are processed
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::lock_guard<std::mutex> lock(m_bufferLock);
SoundStatus status = m_source->GetStatus();
if (status == SoundStatus::Stopped)
{
@@ -432,24 +430,37 @@ namespace Nz
break;
}
// We treat read buffers
while (std::shared_ptr<AudioBuffer> buffer = m_source->TryUnqueueProcessedBuffer())
{
std::lock_guard<std::mutex> lock(m_bufferLock);
m_processedSamples += buffer->GetSampleCount();
// We treat read buffers
while (std::shared_ptr<AudioBuffer> buffer = m_source->TryUnqueueProcessedBuffer())
{
m_processedSamples += buffer->GetSampleCount();
if (FillAndQueueBuffer(std::move(buffer)))
break;
}
if (FillAndQueueBuffer(std::move(buffer)))
break;
}
// We go back to sleep
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
void Music::StartThread(bool startPaused)
{
std::mutex mutex;
std::condition_variable cv;
// Starting streaming thread
m_streaming = true;
std::exception_ptr exceptionPtr;
std::unique_lock<std::mutex> lock(mutex);
m_thread = std::thread(&Music::MusicThread, this, std::ref(cv), std::ref(mutex), std::ref(exceptionPtr), startPaused);
// Wait until thread signal it has properly started (or an error occurred)
cv.wait(lock);
if (exceptionPtr)
std::rethrow_exception(exceptionPtr);
}
void Music::StopThread()
{
if (m_streaming)