diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index c990332a0..0f8f7d32e 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -428,23 +428,23 @@ void AudioSource::Update() // 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) { + // Clear flag + _needToUpdateStreamingBuffers = false; + // Get buffers in a queue count int32 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; - 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 if (!_isActuallyPlayingSth) @@ -469,18 +469,25 @@ void AudioSource::Update() // Move the chunk pointer (AudioStreamingHandler will request new chunks streaming) _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 if (_streamingFirstChunk >= clip->Buffers.Count()) { // Loop over the clip or end play if (GetIsLooping()) { - // Move to the begin + // Move to the beginning _streamingFirstChunk = 0; - - // Stop audio and request buffers re-sync and then play continue - Stop(); - Play(); } else { diff --git a/Source/Engine/Streaming/StreamingHandlers.cpp b/Source/Engine/Streaming/StreamingHandlers.cpp index 0b10fba1b..73c23a60c 100644 --- a/Source/Engine/Streaming/StreamingHandlers.cpp +++ b/Source/Engine/Streaming/StreamingHandlers.cpp @@ -195,14 +195,15 @@ int32 AudioStreamingHandler::CalculateResidency(StreamableResource* resource, fl if (src->Clip == clip && src->GetState() != AudioSource::States::Stopped) { // 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 - 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; } } }