Fix looping audio sources not looping seamlessly
This commit is contained in:
@@ -428,23 +428,23 @@ void AudioSource::Update()
|
|||||||
// Handle streaming buffers queue submit (ensure that clip has loaded the first chunk with audio data)
|
// Handle streaming buffers queue submit (ensure that clip has loaded the first chunk with audio data)
|
||||||
if (_needToUpdateStreamingBuffers && clip->Buffers[_streamingFirstChunk] != AUDIO_BUFFER_ID_INVALID)
|
if (_needToUpdateStreamingBuffers && clip->Buffers[_streamingFirstChunk] != AUDIO_BUFFER_ID_INVALID)
|
||||||
{
|
{
|
||||||
|
// Clear flag
|
||||||
|
_needToUpdateStreamingBuffers = false;
|
||||||
|
|
||||||
// Get buffers in a queue count
|
// Get buffers in a queue count
|
||||||
int32 numQueuedBuffers;
|
int32 numQueuedBuffers;
|
||||||
AudioBackend::Source::GetQueuedBuffersCount(this, numQueuedBuffers);
|
AudioBackend::Source::GetQueuedBuffersCount(this, numQueuedBuffers);
|
||||||
|
|
||||||
// Queue missing buffers
|
// Queue missing buffers, make sure there is at least two buffers in queue to avoid gaps in playback
|
||||||
uint32 bufferId;
|
uint32 bufferId;
|
||||||
if (numQueuedBuffers < 1 && (bufferId = clip->Buffers[_streamingFirstChunk]) != AUDIO_BUFFER_ID_INVALID)
|
for (int i = numQueuedBuffers; i < 2; i++)
|
||||||
{
|
{
|
||||||
AudioBackend::Source::QueueBuffer(this, bufferId);
|
int bufferIndex = (_streamingFirstChunk + i) % clip->Buffers.Count();
|
||||||
|
if ((bufferId = clip->Buffers[bufferIndex]) != AUDIO_BUFFER_ID_INVALID)
|
||||||
|
AudioBackend::Source::QueueBuffer(this, bufferId);
|
||||||
|
else
|
||||||
|
_needToUpdateStreamingBuffers = true; // The buffer has not been streamed yet, try again later
|
||||||
}
|
}
|
||||||
if (numQueuedBuffers < 2 && _streamingFirstChunk + 1 < clip->Buffers.Count() && (bufferId = clip->Buffers[_streamingFirstChunk + 1]) != AUDIO_BUFFER_ID_INVALID)
|
|
||||||
{
|
|
||||||
AudioBackend::Source::QueueBuffer(this, bufferId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear flag
|
|
||||||
_needToUpdateStreamingBuffers = false;
|
|
||||||
|
|
||||||
// Play it if need to
|
// Play it if need to
|
||||||
if (!_isActuallyPlayingSth)
|
if (!_isActuallyPlayingSth)
|
||||||
@@ -469,18 +469,25 @@ void AudioSource::Update()
|
|||||||
// Move the chunk pointer (AudioStreamingHandler will request new chunks streaming)
|
// Move the chunk pointer (AudioStreamingHandler will request new chunks streaming)
|
||||||
_streamingFirstChunk += numProcessedBuffers;
|
_streamingFirstChunk += numProcessedBuffers;
|
||||||
|
|
||||||
|
if (GetIsLooping())
|
||||||
|
{
|
||||||
|
int32 numQueuedBuffers;
|
||||||
|
AudioBackend::Source::GetQueuedBuffersCount(this, numQueuedBuffers);
|
||||||
|
if (numQueuedBuffers < 1)
|
||||||
|
{
|
||||||
|
// Audio engine unexpectedly stopped playing the clip after queue emptied, restart the clip
|
||||||
|
_isActuallyPlayingSth = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if reached the end
|
// Check if reached the end
|
||||||
if (_streamingFirstChunk >= clip->Buffers.Count())
|
if (_streamingFirstChunk >= clip->Buffers.Count())
|
||||||
{
|
{
|
||||||
// Loop over the clip or end play
|
// Loop over the clip or end play
|
||||||
if (GetIsLooping())
|
if (GetIsLooping())
|
||||||
{
|
{
|
||||||
// Move to the begin
|
// Move to the beginning
|
||||||
_streamingFirstChunk = 0;
|
_streamingFirstChunk = 0;
|
||||||
|
|
||||||
// Stop audio and request buffers re-sync and then play continue
|
|
||||||
Stop();
|
|
||||||
Play();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -195,14 +195,15 @@ int32 AudioStreamingHandler::CalculateResidency(StreamableResource* resource, fl
|
|||||||
if (src->Clip == clip && src->GetState() != AudioSource::States::Stopped)
|
if (src->Clip == clip && src->GetState() != AudioSource::States::Stopped)
|
||||||
{
|
{
|
||||||
// Stream the current and the next chunk if could be used in a while
|
// Stream the current and the next chunk if could be used in a while
|
||||||
const int32 chunk = src->_streamingFirstChunk;
|
|
||||||
ASSERT(Math::IsInRange(chunk, 0, chunksCount));
|
|
||||||
chunksMask[chunk] = true;
|
|
||||||
|
|
||||||
const float StreamingDstSec = 2.0f; // TODO: make it configurable via StreamingSettings
|
const float StreamingDstSec = 2.0f; // TODO: make it configurable via StreamingSettings
|
||||||
if (chunk + 1 < chunksCount && src->GetTime() + StreamingDstSec >= clip->GetBufferStartTime(src->_streamingFirstChunk))
|
const int32 firstChunk = src->_streamingFirstChunk;
|
||||||
|
const int32 nextChunk = (firstChunk + 1) % chunksCount;
|
||||||
|
ASSERT(Math::IsInRange(firstChunk, 0, chunksCount));
|
||||||
|
chunksMask[firstChunk] = true;
|
||||||
|
|
||||||
|
if (firstChunk != nextChunk && src->GetTime() + StreamingDstSec >= clip->GetBufferStartTime(firstChunk))
|
||||||
{
|
{
|
||||||
chunksMask[chunk + 1] = true;
|
chunksMask[nextChunk] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user