Audio: Add some fixes and tests
This commit is contained in:
parent
81085508ec
commit
21a38fb31b
|
|
@ -46,6 +46,9 @@ namespace Nz
|
|||
|
||||
UInt32 DummyAudioSource::GetSampleOffset() const
|
||||
{
|
||||
if (m_status == SoundStatus::Stopped)
|
||||
return 0; //< Always return 0 when stopped, to mimic OpenAL behavior
|
||||
|
||||
UInt64 bufferTime = UpdateTime();
|
||||
|
||||
UInt64 sampleOffset = 0;
|
||||
|
|
@ -114,7 +117,12 @@ namespace Nz
|
|||
{
|
||||
// playing or stopped, restart
|
||||
RequeueBuffers();
|
||||
m_playClock.Restart();
|
||||
|
||||
// special case, we are stopped but SetSampleOffset has been called
|
||||
if (m_status == SoundStatus::Stopped && m_playClock.GetMilliseconds() != 0)
|
||||
m_playClock.Unpause();
|
||||
else
|
||||
m_playClock.Restart(); //< already playing or stopped, restart from beginning
|
||||
}
|
||||
|
||||
m_status = SoundStatus::Playing;
|
||||
|
|
@ -168,10 +176,13 @@ namespace Nz
|
|||
}
|
||||
m_queuedBuffers.erase(m_queuedBuffers.begin(), m_queuedBuffers.begin() + processedBufferIndex);
|
||||
|
||||
assert(!m_queuedBuffers.empty());
|
||||
|
||||
UInt64 timeOffset = 1'000'000ULL * offset / m_queuedBuffers.front()->GetSampleRate();
|
||||
m_playClock.Restart(timeOffset, m_playClock.IsPaused());
|
||||
if (!m_queuedBuffers.empty())
|
||||
{
|
||||
UInt64 timeOffset = 1'000'000ULL * offset / m_queuedBuffers.front()->GetSampleRate();
|
||||
m_playClock.Restart(timeOffset, m_playClock.IsPaused());
|
||||
}
|
||||
else
|
||||
Stop();
|
||||
}
|
||||
|
||||
void DummyAudioSource::SetVelocity(const Vector3f& velocity)
|
||||
|
|
@ -216,7 +227,11 @@ namespace Nz
|
|||
if (!m_processedBuffers.empty())
|
||||
{
|
||||
m_queuedBuffers.resize(m_processedBuffers.size() + m_queuedBuffers.size());
|
||||
std::move(m_queuedBuffers.begin(), m_queuedBuffers.begin() + m_processedBuffers.size(), m_queuedBuffers.begin() + m_processedBuffers.size());
|
||||
|
||||
// Move currently queued buffers to the end of the queue
|
||||
if (m_queuedBuffers.size() > m_processedBuffers.size())
|
||||
std::move(m_queuedBuffers.begin(), m_queuedBuffers.begin() + m_processedBuffers.size(), m_queuedBuffers.begin() + m_processedBuffers.size());
|
||||
|
||||
std::move(m_processedBuffers.begin(), m_processedBuffers.end(), m_queuedBuffers.begin());
|
||||
m_processedBuffers.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ namespace Nz
|
|||
*/
|
||||
void Music::EnableLooping(bool loop)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_bufferLock);
|
||||
|
||||
m_looping = loop;
|
||||
}
|
||||
|
||||
|
|
@ -129,11 +131,24 @@ namespace Nz
|
|||
{
|
||||
NazaraAssert(m_stream, "Music not created");
|
||||
|
||||
if (!m_streaming)
|
||||
return 0;
|
||||
|
||||
// Prevent music thread from enqueuing new buffers while we're getting the count
|
||||
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);
|
||||
UInt32 playingOffset = SafeCast<UInt32>((1000ULL * (sampleOffset + (m_processedSamples / GetChannelCount(m_stream->GetFormat())))) / m_sampleRate);
|
||||
UInt32 duration = m_stream->GetDuration();
|
||||
if (playingOffset > duration)
|
||||
{
|
||||
if (m_looping)
|
||||
playingOffset %= duration;
|
||||
else
|
||||
playingOffset = 0; //< stopped
|
||||
}
|
||||
|
||||
return playingOffset;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -191,6 +206,8 @@ namespace Nz
|
|||
*/
|
||||
bool Music::IsLooping() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_bufferLock);
|
||||
|
||||
return m_looping;
|
||||
}
|
||||
|
||||
|
|
@ -290,7 +307,12 @@ namespace Nz
|
|||
else
|
||||
{
|
||||
// Ensure we're restarting
|
||||
Stop();
|
||||
StopThread();
|
||||
|
||||
// Special case of SetPlayingOffset(end) before Play(), restart from beginning
|
||||
if (m_streamOffset >= m_stream->GetSampleCount())
|
||||
m_streamOffset = 0;
|
||||
|
||||
StartThread(false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,12 +53,53 @@ SCENARIO("Music", "[AUDIO][MUSIC]")
|
|||
CHECK(music.GetStatus() == Nz::SoundStatus::Playing);
|
||||
|
||||
music.Pause();
|
||||
Nz::UInt32 playingOffset = music.GetPlayingOffset();
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Paused);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Paused);
|
||||
CHECK(music.GetPlayingOffset() == playingOffset);
|
||||
|
||||
music.SetPlayingOffset(3500);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
CHECK(music.GetPlayingOffset() == 3500);
|
||||
|
||||
music.Play();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
CHECK(music.GetPlayingOffset() >= 3650);
|
||||
|
||||
AND_WHEN("We let the sound stop by itself")
|
||||
{
|
||||
REQUIRE(music.GetDuration() == 63059);
|
||||
|
||||
music.SetPlayingOffset(62900);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Stopped);
|
||||
CHECK(music.GetPlayingOffset() == 0);
|
||||
|
||||
music.SetPlayingOffset(64000);
|
||||
music.Play();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Playing);
|
||||
CHECK(music.GetPlayingOffset() < 100);
|
||||
|
||||
music.Stop();
|
||||
music.SetPlayingOffset(62900);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Stopped);
|
||||
CHECK(music.GetPlayingOffset() == 0); //< playing offset has no effect until Play()
|
||||
|
||||
AND_WHEN("We enable looping")
|
||||
{
|
||||
music.EnableLooping(true);
|
||||
CHECK(music.IsLooping());
|
||||
music.Play();
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Playing);
|
||||
CHECK(music.GetPlayingOffset() >= 62900);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
CHECK(music.GetStatus() == Nz::SoundStatus::Playing);
|
||||
CHECK(music.GetPlayingOffset() < 300);
|
||||
}
|
||||
}
|
||||
Nz::Audio::Instance()->GetDefaultDevice()->SetGlobalVolume(100.f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,52 @@ SCENARIO("Sound", "[AUDIO][SOUND]")
|
|||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
CHECK(sound.GetPlayingOffset() <= 1500);
|
||||
sound.Pause();
|
||||
Nz::UInt32 playingOffset = sound.GetPlayingOffset();
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Paused);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Paused);
|
||||
CHECK(sound.GetPlayingOffset() == playingOffset);
|
||||
|
||||
sound.SetPlayingOffset(3500);
|
||||
CHECK(sound.GetPlayingOffset() == 3500);
|
||||
|
||||
sound.Play();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
CHECK(sound.GetPlayingOffset() >= 1650);
|
||||
|
||||
AND_WHEN("We let the sound stop by itself")
|
||||
{
|
||||
REQUIRE(sound.GetDuration() == 8192);
|
||||
|
||||
sound.SetPlayingOffset(8000);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Stopped);
|
||||
CHECK(sound.GetPlayingOffset() == 0);
|
||||
|
||||
sound.SetPlayingOffset(9000);
|
||||
sound.Play();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Playing);
|
||||
|
||||
sound.Stop();
|
||||
sound.SetPlayingOffset(8000);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Stopped);
|
||||
CHECK(sound.GetPlayingOffset() == 0); //< playing offset has no effect until Play()
|
||||
|
||||
AND_WHEN("We enable looping")
|
||||
{
|
||||
sound.EnableLooping(true);
|
||||
CHECK(sound.IsLooping());
|
||||
sound.Play();
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Playing);
|
||||
CHECK(sound.GetPlayingOffset() >= 8000);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||
CHECK(sound.GetStatus() == Nz::SoundStatus::Playing);
|
||||
CHECK(sound.GetPlayingOffset() < 300);
|
||||
}
|
||||
}
|
||||
|
||||
Nz::Audio::Instance()->GetDefaultDevice()->SetGlobalVolume(100.f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue