Browse Source

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

tags/1.2.0
xenakios 7 years ago
parent
commit
9afca36d64
2 changed files with 66 additions and 63 deletions
  1. +43
    -42
      Source/ps3_BufferingAudioSource.cpp
  2. +23
    -21
      Source/ps3_BufferingAudioSource.h

+ 43
- 42
Source/ps3_BufferingAudioSource.cpp View File

@@ -24,20 +24,14 @@


MyBufferingAudioSource::MyBufferingAudioSource(PositionableAudioSource* s, MyBufferingAudioSource::MyBufferingAudioSource(PositionableAudioSource* s,
TimeSliceThread& thread, TimeSliceThread& thread,
const bool deleteSourceWhenDeleted,
const int bufferSizeSamples,
const int numChannels,
bool deleteSourceWhenDeleted,
int bufferSizeSamples,
int numChannels,
bool prefillBufferOnPrepareToPlay) bool prefillBufferOnPrepareToPlay)
: source (s, deleteSourceWhenDeleted), : source (s, deleteSourceWhenDeleted),
backgroundThread (thread), backgroundThread (thread),
numberOfSamplesToBuffer (jmax (1024, bufferSizeSamples)), numberOfSamplesToBuffer (jmax (1024, bufferSizeSamples)),
numberOfChannels (numChannels), numberOfChannels (numChannels),
bufferValidStart (0),
bufferValidEnd (0),
nextPlayPos (0),
sampleRate (0),
wasSourceLooping (false),
isPrepared (false),
prefillBuffer (prefillBufferOnPrepareToPlay) prefillBuffer (prefillBufferOnPrepareToPlay)
{ {
jassert (source != nullptr); jassert (source != nullptr);
@@ -54,7 +48,7 @@ MyBufferingAudioSource::~MyBufferingAudioSource()
//============================================================================== //==============================================================================
void MyBufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double newSampleRate) void MyBufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double newSampleRate)
{ {
const int bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer);
auto bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer);


if (newSampleRate != sampleRate if (newSampleRate != sampleRate
|| bufferSizeNeeded != buffer.getNumSamples() || bufferSizeNeeded != buffer.getNumSamples()
@@ -103,8 +97,12 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in
{ {
const ScopedLock sl (bufferStartPosLock); 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) if (validStart == validEnd)
{ {
@@ -125,8 +123,8 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in
for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;) for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;)
{ {
jassert (buffer.getNumSamples() > 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) if (startBufferIndex < endBufferIndex)
{ {
@@ -137,7 +135,7 @@ void MyBufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& in
} }
else else
{ {
const int initialSize = buffer.getNumSamples() - startBufferIndex;
auto initialSize = buffer.getNumSamples() - startBufferIndex;


info.buffer->copyFrom (chan, info.startSample + validStart, info.buffer->copyFrom (chan, info.startSample + validStart,
buffer, 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) if (!source || source->getTotalLength() <= 0)
return false; return false;
@@ -167,26 +165,28 @@ bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChanne
if (! isLooping() && nextPlayPos > getTotalLength()) if (! isLooping() && nextPlayPos > getTotalLength())
return true; 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) while (elapsed <= timeout)
{ {
{ {
const ScopedLock sl (bufferStartPosLock); 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) if (validStart <= 0 && validStart < validEnd && validEnd >= info.numSamples)
return true; return true;
} }




if (elapsed < timeout && (! bufferReadyEvent.wait (static_cast<int> (timeout - elapsed)))) if (elapsed < timeout && (! bufferReadyEvent.wait (static_cast<int> (timeout - elapsed))))
return false; return false;


@@ -198,21 +198,14 @@ bool MyBufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChanne
return false; 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 int64 MyBufferingAudioSource::getNextReadPosition() const
{ {
jassert (source->getTotalLength() > 0); jassert (source->getTotalLength() > 0);
auto pos = nextPlayPos.load();

return (source->isLooping() && nextPlayPos > 0) return (source->isLooping() && nextPlayPos > 0)
? nextPlayPos % source->getTotalLength()
: nextPlayPos;
? pos % source->getTotalLength()
: pos;
} }


void MyBufferingAudioSource::setNextReadPosition (int64 newPosition) void MyBufferingAudioSource::setNextReadPosition (int64 newPosition)
@@ -237,7 +230,7 @@ bool MyBufferingAudioSource::readNextBufferChunk()
bufferValidEnd = 0; bufferValidEnd = 0;
} }


newBVS = jmax ((int64) 0, nextPlayPos);
newBVS = jmax ((int64) 0, nextPlayPos.load());
newBVE = newBVS + buffer.getNumSamples() - 4; newBVE = newBVS + buffer.getNumSamples() - 4;
sectionToReadStart = 0; sectionToReadStart = 0;
sectionToReadEnd = 0; sectionToReadEnd = 0;
@@ -263,7 +256,7 @@ bool MyBufferingAudioSource::readNextBufferChunk()
sectionToReadEnd = newBVE; sectionToReadEnd = newBVE;


bufferValidStart = newBVS; bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
bufferValidEnd = jmin (bufferValidEnd.load(), newBVE);
} }
} }


@@ -271,8 +264,8 @@ bool MyBufferingAudioSource::readNextBufferChunk()
return false; return false;


jassert (buffer.getNumSamples() > 0); 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) if (bufferIndexStart < bufferIndexEnd)
{ {
@@ -282,7 +275,7 @@ bool MyBufferingAudioSource::readNextBufferChunk()
} }
else else
{ {
const int initialSize = buffer.getNumSamples() - bufferIndexStart;
auto initialSize = buffer.getNumSamples() - bufferIndexStart;


readBufferSection (sectionToReadStart, readBufferSection (sectionToReadStart,
initialSize, initialSize,
@@ -301,11 +294,10 @@ bool MyBufferingAudioSource::readNextBufferChunk()
} }


bufferReadyEvent.signal(); bufferReadyEvent.signal();

return true; 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) if (source->getNextReadPosition() != start)
source->setNextReadPosition (start); source->setNextReadPosition (start);
@@ -319,4 +311,13 @@ int MyBufferingAudioSource::useTimeSlice()
return readNextBufferChunk() ? 1 : 100; 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);
}




+ 23
- 21
Source/ps3_BufferingAudioSource.h 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. 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. directly, or use it indirectly using an AudioTransportSource.


@see PositionableAudioSource, AudioTransportSource @see PositionableAudioSource, AudioTransportSource
*/


#include "../JuceLibraryCode/JuceHeader.h"
class MyBufferingAudioSource : public PositionableAudioSource,
@tags{Audio}
*/
class JUCE_API MyBufferingAudioSource : public PositionableAudioSource,
private TimeSliceClient private TimeSliceClient
{ {
public: public:
@@ -104,9 +106,9 @@ private:
AudioBuffer<float> buffer; AudioBuffer<float> buffer;
CriticalSection bufferStartPosLock; CriticalSection bufferStartPosLock;
WaitableEvent bufferReadyEvent; 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(); bool readNextBufferChunk();
void readBufferSection (int64 start, int length, int bufferOffset); void readBufferSection (int64 start, int length, int bufferOffset);


Loading…
Cancel
Save