diff options
Diffstat (limited to 'src/SFML/Audio/SoundStream.cpp')
-rw-r--r-- | src/SFML/Audio/SoundStream.cpp | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/src/SFML/Audio/SoundStream.cpp b/src/SFML/Audio/SoundStream.cpp index 9e147a5..0e40548 100644 --- a/src/SFML/Audio/SoundStream.cpp +++ b/src/SFML/Audio/SoundStream.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org) +// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -51,7 +51,7 @@ m_sampleRate (0), m_format (0), m_loop (false), m_samplesProcessed(0), -m_endBuffers () +m_bufferSeeks () { } @@ -77,7 +77,9 @@ SoundStream::~SoundStream() void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate) { m_channelCount = channelCount; - m_sampleRate = sampleRate; + m_sampleRate = sampleRate; + m_samplesProcessed = 0; + m_isStreaming = false; // Deduce the format from the number of channels m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount); @@ -127,11 +129,7 @@ void SoundStream::play() stop(); } - // Move to the beginning - onSeek(Time::Zero); - // Start updating the stream in a separate thread to avoid blocking the application - m_samplesProcessed = 0; m_isStreaming = true; m_threadStartState = Playing; m_thread.launch(); @@ -169,9 +167,6 @@ void SoundStream::stop() // Move to the beginning onSeek(Time::Zero); - - // Reset the playing position - m_samplesProcessed = 0; } @@ -263,6 +258,14 @@ bool SoundStream::getLoop() const //////////////////////////////////////////////////////////// +Int64 SoundStream::onLoop() +{ + onSeek(Time::Zero); + return 0; +} + + +//////////////////////////////////////////////////////////// void SoundStream::streamData() { bool requestStop = false; @@ -281,7 +284,7 @@ void SoundStream::streamData() // Create the buffers alCheck(alGenBuffers(BufferCount, m_buffers)); for (int i = 0; i < BufferCount; ++i) - m_endBuffers[i] = false; + m_bufferSeeks[i] = NoLoop; // Fill the queue requestStop = fillQueue(); @@ -341,11 +344,11 @@ void SoundStream::streamData() } // Retrieve its size and add it to the samples count - if (m_endBuffers[bufferNum]) + if (m_bufferSeeks[bufferNum] != NoLoop) { - // This was the last buffer: reset the sample count - m_samplesProcessed = 0; - m_endBuffers[bufferNum] = false; + // This was the last buffer before EOF or Loop End: reset the sample count + m_samplesProcessed = m_bufferSeeks[bufferNum]; + m_bufferSeeks[bufferNum] = NoLoop; } else { @@ -390,6 +393,9 @@ void SoundStream::streamData() // Dequeue any buffer left in the queue clearQueue(); + // Reset the playing position + m_samplesProcessed = 0; + // Delete the buffers alCheck(alSourcei(m_source, AL_BUFFER, 0)); alCheck(alDeleteBuffers(BufferCount, m_buffers)); @@ -397,34 +403,41 @@ void SoundStream::streamData() //////////////////////////////////////////////////////////// -bool SoundStream::fillAndPushBuffer(unsigned int bufferNum) +bool SoundStream::fillAndPushBuffer(unsigned int bufferNum, bool immediateLoop) { bool requestStop = false; - // Acquire audio data + // Acquire audio data, also address EOF and error cases if they occur Chunk data = {NULL, 0}; - if (!onGetData(data)) + for (Uint32 retryCount = 0; !onGetData(data) && (retryCount < BufferRetries); ++retryCount) { - // Mark the buffer as the last one (so that we know when to reset the playing position) - m_endBuffers[bufferNum] = true; - // Check if the stream must loop or stop - if (m_loop) + if (!m_loop) { - // Return to the beginning of the stream source - onSeek(Time::Zero); - - // If we previously had no data, try to fill the buffer once again - if (!data.samples || (data.sampleCount == 0)) - { - return fillAndPushBuffer(bufferNum); - } + // Not looping: Mark this buffer as ending with 0 and request stop + if (data.samples != NULL && data.sampleCount != 0) + m_bufferSeeks[bufferNum] = 0; + requestStop = true; + break; } - else + + // Return to the beginning or loop-start of the stream source using onLoop(), and store the result in the buffer seek array + // This marks the buffer as the "last" one (so that we know where to reset the playing position) + m_bufferSeeks[bufferNum] = onLoop(); + + // If we got data, break and process it, else try to fill the buffer once again + if (data.samples != NULL && data.sampleCount != 0) + break; + + // If immediateLoop is specified, we have to immediately adjust the sample count + if (immediateLoop && (m_bufferSeeks[bufferNum] != NoLoop)) { - // Not looping: request stop - requestStop = true; + // We just tried to begin preloading at EOF or Loop End: reset the sample count + m_samplesProcessed = m_bufferSeeks[bufferNum]; + m_bufferSeeks[bufferNum] = NoLoop; } + + // We're a looping sound that got no data, so we retry onGetData() } // Fill the buffer if some data was returned @@ -439,6 +452,11 @@ bool SoundStream::fillAndPushBuffer(unsigned int bufferNum) // Push it into the sound queue alCheck(alSourceQueueBuffers(m_source, 1, &buffer)); } + else + { + // If we get here, we most likely ran out of retries + requestStop = true; + } return requestStop; } @@ -451,7 +469,9 @@ bool SoundStream::fillQueue() bool requestStop = false; for (int i = 0; (i < BufferCount) && !requestStop; ++i) { - if (fillAndPushBuffer(i)) + // Since no sound has been loaded yet, we can't schedule loop seeks preemptively, + // So if we start on EOF or Loop End, we let fillAndPushBuffer() adjust the sample count + if (fillAndPushBuffer(i, (i == 0))) requestStop = true; } |