Updated the buffering audio source from the new JUCE code that removed the use of volatile
This commit is contained in:
		@@ -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,10 +165,10 @@ 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
 | 
			
		||||
    auto elapsed = (now >= startTime ? now - startTime
 | 
			
		||||
                                     : (std::numeric_limits<uint32>::max() - startTime) + now);
 | 
			
		||||
 | 
			
		||||
    while (elapsed <= timeout)
 | 
			
		||||
@@ -178,15 +176,17 @@ bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChanne
 | 
			
		||||
        {
 | 
			
		||||
            const ScopedLock sl (bufferStartPosLock);
 | 
			
		||||
 | 
			
		||||
            const int validStart = static_cast<int> (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos);
 | 
			
		||||
            const int validEnd   = static_cast<int> (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos);
 | 
			
		||||
            auto start = bufferValidStart.load();
 | 
			
		||||
            auto end   = bufferValidEnd.load();
 | 
			
		||||
            auto pos   = nextPlayPos.load();
 | 
			
		||||
 | 
			
		||||
            auto validStart = static_cast<int> (jlimit (start, end, pos) - pos);
 | 
			
		||||
            auto validEnd   = static_cast<int> (jlimit (start, end, pos + info.numSamples) - pos);
 | 
			
		||||
 | 
			
		||||
            if (validStart <= 0 && validStart < validEnd && validEnd >= info.numSamples)
 | 
			
		||||
                return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (elapsed < timeout  && (! bufferReadyEvent.wait (static_cast<int> (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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,9 @@
 | 
			
		||||
==============================================================================
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#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<float> buffer;
 | 
			
		||||
    CriticalSection bufferStartPosLock;
 | 
			
		||||
    WaitableEvent bufferReadyEvent;
 | 
			
		||||
    int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos;
 | 
			
		||||
    double volatile sampleRate;
 | 
			
		||||
    bool wasSourceLooping, isPrepared, prefillBuffer;
 | 
			
		||||
    std::atomic<int64> 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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user