Updated the buffering audio source from the new JUCE code that removed the use of volatile

This commit is contained in:
xenakios 2018-05-01 15:11:45 +03:00
parent c4b2ead50d
commit 9afca36d64
2 changed files with 66 additions and 63 deletions

View File

@ -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<uint32>::max() - startTime) + now);
auto elapsed = (now >= startTime ? now - startTime
: (std::numeric_limits<uint32>::max() - startTime) + now);
while (elapsed <= timeout)
{
{
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);
}

View File

@ -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<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);