Updated the buffering audio source from the new JUCE code that removed the use of volatile
This commit is contained in:
parent
c4b2ead50d
commit
9afca36d64
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user