diff --git a/Source/ps3_BufferingAudioSource.cpp b/Source/ps3_BufferingAudioSource.cpp index 3d678f8..9bead08 100644 --- a/Source/ps3_BufferingAudioSource.cpp +++ b/Source/ps3_BufferingAudioSource.cpp @@ -24,20 +24,14 @@ MyBufferingAudioSource::MyBufferingAudioSource(PositionableAudioSource* s, TimeSliceThread& thread, - const bool deleteSourceWhenDeleted, - const int bufferSizeSamples, - const int numChannels, + bool deleteSourceWhenDeleted, + int bufferSizeSamples, + int numChannels, bool prefillBufferOnPrepareToPlay) : source (s, deleteSourceWhenDeleted), backgroundThread (thread), numberOfSamplesToBuffer (jmax (1024, bufferSizeSamples)), numberOfChannels (numChannels), - bufferValidStart (0), - bufferValidEnd (0), - nextPlayPos (0), - sampleRate (0), - wasSourceLooping (false), - isPrepared (false), prefillBuffer (prefillBufferOnPrepareToPlay) { jassert (source != nullptr); @@ -54,7 +48,7 @@ MyBufferingAudioSource::~MyBufferingAudioSource() //============================================================================== void MyBufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double newSampleRate) { - const int bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer); + auto bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer); if (newSampleRate != sampleRate || bufferSizeNeeded != buffer.getNumSamples() @@ -103,8 +97,12 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in { const ScopedLock sl (bufferStartPosLock); - const int validStart = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos); - const int validEnd = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos); + auto start = bufferValidStart.load(); + auto end = bufferValidEnd.load(); + auto pos = nextPlayPos.load(); + + auto validStart = (int) (jlimit (start, end, pos) - pos); + auto validEnd = (int) (jlimit (start, end, pos + info.numSamples) - pos); if (validStart == validEnd) { @@ -125,8 +123,8 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;) { jassert (buffer.getNumSamples() > 0); - const int startBufferIndex = (int) ((validStart + nextPlayPos) % buffer.getNumSamples()); - const int endBufferIndex = (int) ((validEnd + nextPlayPos) % buffer.getNumSamples()); + auto startBufferIndex = (int) ((validStart + nextPlayPos) % buffer.getNumSamples()); + auto endBufferIndex = (int) ((validEnd + nextPlayPos) % buffer.getNumSamples()); if (startBufferIndex < endBufferIndex) { @@ -137,7 +135,7 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in } else { - const int initialSize = buffer.getNumSamples() - startBufferIndex; + auto initialSize = buffer.getNumSamples() - startBufferIndex; info.buffer->copyFrom (chan, info.startSample + validStart, buffer, @@ -156,7 +154,7 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in } } -bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, const uint32 timeout) +bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, uint32 timeout) { if (!source || source->getTotalLength() <= 0) return false; @@ -167,26 +165,28 @@ bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChanne if (! isLooping() && nextPlayPos > getTotalLength()) return true; - uint32 now = Time::getMillisecondCounter(); - const uint32 startTime = now; + auto now = Time::getMillisecondCounter(); + auto startTime = now; - uint32 elapsed = (now >= startTime ? now - startTime - : (std::numeric_limits::max() - startTime) + now); + auto elapsed = (now >= startTime ? now - startTime + : (std::numeric_limits::max() - startTime) + now); while (elapsed <= timeout) { { const ScopedLock sl (bufferStartPosLock); - const int validStart = static_cast (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos); - const int validEnd = static_cast (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos); + auto start = bufferValidStart.load(); + auto end = bufferValidEnd.load(); + auto pos = nextPlayPos.load(); + + auto validStart = static_cast (jlimit (start, end, pos) - pos); + auto validEnd = static_cast (jlimit (start, end, pos + info.numSamples) - pos); if (validStart <= 0 && validStart < validEnd && validEnd >= info.numSamples) return true; } - - if (elapsed < timeout && (! bufferReadyEvent.wait (static_cast (timeout - elapsed)))) return false; @@ -198,21 +198,14 @@ bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChanne return false; } -double MyBufferingAudioSource::getPercentReady() -{ - if (bufferValidEnd == bufferValidStart) - return 0.0; - if (numberOfSamplesToBuffer == 0) - return 0.0; - return 1.0 / numberOfSamplesToBuffer * (bufferValidEnd - bufferValidStart); -} - int64 MyBufferingAudioSource::getNextReadPosition() const { jassert (source->getTotalLength() > 0); + auto pos = nextPlayPos.load(); + return (source->isLooping() && nextPlayPos > 0) - ? nextPlayPos % source->getTotalLength() - : nextPlayPos; + ? pos % source->getTotalLength() + : pos; } void MyBufferingAudioSource::setNextReadPosition (int64 newPosition) @@ -237,7 +230,7 @@ bool MyBufferingAudioSource::readNextBufferChunk() bufferValidEnd = 0; } - newBVS = jmax ((int64) 0, nextPlayPos); + newBVS = jmax ((int64) 0, nextPlayPos.load()); newBVE = newBVS + buffer.getNumSamples() - 4; sectionToReadStart = 0; sectionToReadEnd = 0; @@ -263,7 +256,7 @@ bool MyBufferingAudioSource::readNextBufferChunk() sectionToReadEnd = newBVE; bufferValidStart = newBVS; - bufferValidEnd = jmin (bufferValidEnd, newBVE); + bufferValidEnd = jmin (bufferValidEnd.load(), newBVE); } } @@ -271,8 +264,8 @@ bool MyBufferingAudioSource::readNextBufferChunk() return false; jassert (buffer.getNumSamples() > 0); - const int bufferIndexStart = (int) (sectionToReadStart % buffer.getNumSamples()); - const int bufferIndexEnd = (int) (sectionToReadEnd % buffer.getNumSamples()); + auto bufferIndexStart = (int) (sectionToReadStart % buffer.getNumSamples()); + auto bufferIndexEnd = (int) (sectionToReadEnd % buffer.getNumSamples()); if (bufferIndexStart < bufferIndexEnd) { @@ -282,7 +275,7 @@ bool MyBufferingAudioSource::readNextBufferChunk() } else { - const int initialSize = buffer.getNumSamples() - bufferIndexStart; + auto initialSize = buffer.getNumSamples() - bufferIndexStart; readBufferSection (sectionToReadStart, initialSize, @@ -301,11 +294,10 @@ bool MyBufferingAudioSource::readNextBufferChunk() } bufferReadyEvent.signal(); - return true; } -void MyBufferingAudioSource::readBufferSection (const int64 start, const int length, const int bufferOffset) +void MyBufferingAudioSource::readBufferSection (int64 start, int length, int bufferOffset) { if (source->getNextReadPosition() != start) source->setNextReadPosition (start); @@ -319,4 +311,13 @@ int MyBufferingAudioSource::useTimeSlice() return readNextBufferChunk() ? 1 : 100; } +double MyBufferingAudioSource::getPercentReady() +{ + if (bufferValidEnd == bufferValidStart) + return 0.0; + if (numberOfSamplesToBuffer == 0) + return 0.0; + return 1.0 / numberOfSamplesToBuffer * (bufferValidEnd - bufferValidStart); +} + diff --git a/Source/ps3_BufferingAudioSource.h b/Source/ps3_BufferingAudioSource.h index b2c4a22..6bedf91 100644 --- a/Source/ps3_BufferingAudioSource.h +++ b/Source/ps3_BufferingAudioSource.h @@ -1,25 +1,28 @@ /* - ============================================================================== +============================================================================== - This file is part of the JUCE library. - Copyright (c) 2017 - ROLI Ltd. +This file is part of the JUCE library. +Copyright (c) 2017 - ROLI Ltd. - JUCE is an open source library subject to commercial or open-source - licensing. +JUCE is an open source library subject to commercial or open-source +licensing. - The code included in this file is provided under the terms of the ISC license - http://www.isc.org/downloads/software-support-policy/isc-license. Permission - To use, copy, modify, and/or distribute this software for any purpose with or - without fee is hereby granted provided that the above copyright notice and - this permission notice appear in all copies. +The code included in this file is provided under the terms of the ISC license +http://www.isc.org/downloads/software-support-policy/isc-license. Permission +To use, copy, modify, and/or distribute this software for any purpose with or +without fee is hereby granted provided that the above copyright notice and +this permission notice appear in all copies. - JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER - EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE - DISCLAIMED. +JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +DISCLAIMED. - ============================================================================== +============================================================================== */ +#pragma once + +#include "../JuceLibraryCode/JuceHeader.h" //============================================================================== /** An AudioSource which takes another source as input, and buffers it using a thread. @@ -29,11 +32,10 @@ directly, or use it indirectly using an AudioTransportSource. @see PositionableAudioSource, AudioTransportSource + + @tags{Audio} */ - -#include "../JuceLibraryCode/JuceHeader.h" - -class MyBufferingAudioSource : public PositionableAudioSource, +class JUCE_API MyBufferingAudioSource : public PositionableAudioSource, private TimeSliceClient { public: @@ -104,9 +106,9 @@ private: AudioBuffer buffer; CriticalSection bufferStartPosLock; WaitableEvent bufferReadyEvent; - int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos; - double volatile sampleRate; - bool wasSourceLooping, isPrepared, prefillBuffer; + std::atomic bufferValidStart { 0 }, bufferValidEnd { 0 }, nextPlayPos { 0 }; + double sampleRate = 0; + bool wasSourceLooping = false, isPrepared = false, prefillBuffer; bool readNextBufferChunk(); void readBufferSection (int64 start, int length, int bufferOffset);