28 bool deleteSourceWhenDeleted,
32 : source (s, deleteSourceWhenDeleted),
33 backgroundThread (thread),
35 numberOfChannels (numChannels),
38 jassert (source !=
nullptr);
40 jassert (numberOfSamplesToBuffer > 1024);
92 buffer.
setSize (numberOfChannels, 0);
98 source->releaseResources();
108 info.clearActiveBufferRegion();
118 info.buffer->clear (
info.startSample, validStart);
120 if (validEnd <
info.numSamples)
121 info.buffer->clear (
info.startSample + validEnd,
122 info.numSamples - validEnd);
124 if (validStart < validEnd)
126 for (
int chan = jmin (numberOfChannels,
info.buffer->getNumChannels()); --
chan >= 0;)
135 info.buffer->copyFrom (
chan,
info.startSample + validStart,
138 validEnd - validStart);
144 info.buffer->copyFrom (
chan,
info.startSample + validStart,
157 nextPlayPos +=
info.numSamples;
162 if (source ==
nullptr || source->getTotalLength() <= 0)
165 if ((nextPlayPos +
info.numSamples < 0)
170 auto now = startTime;
173 : (std::numeric_limits<uint32>::max() - startTime) +
now);
183 && validStart < validEnd
184 && validEnd >=
info.numSamples)
190 && ! bufferReadyEvent.
wait (
static_cast<int> (timeout -
elapsed)))
197 : (std::numeric_limits<uint32>::max() - startTime) +
now);
205 jassert (source->getTotalLength() > 0);
206 const auto pos = nextPlayPos.load();
208 return (source->isLooping() && nextPlayPos > 0)
209 ? pos % source->getTotalLength()
221Range<int> BufferingAudioSource::getValidBufferRange (
int numSamples)
const
225 const auto pos = nextPlayPos.load();
227 return { (
int) (jlimit (bufferValidStart, bufferValidEnd, pos) - pos),
228 (
int) (jlimit (bufferValidStart, bufferValidEnd, pos + numSamples) - pos) };
231bool BufferingAudioSource::readNextBufferChunk()
233 int64 newBVS, newBVE, sectionToReadStart, sectionToReadEnd;
236 const ScopedLock sl (bufferRangeLock);
241 bufferValidStart = 0;
245 newBVS = jmax ((int64) 0, nextPlayPos.load());
247 sectionToReadStart = 0;
248 sectionToReadEnd = 0;
250 constexpr int maxChunkSize = 2048;
252 if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
254 newBVE = jmin (newBVE, newBVS + maxChunkSize);
256 sectionToReadStart = newBVS;
257 sectionToReadEnd = newBVE;
259 bufferValidStart = 0;
262 else if (std::abs ((
int) (newBVS - bufferValidStart)) > 512
263 || std::abs ((
int) (newBVE - bufferValidEnd)) > 512)
265 newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);
267 sectionToReadStart = bufferValidEnd;
268 sectionToReadEnd = newBVE;
270 bufferValidStart = newBVS;
271 bufferValidEnd = jmin (bufferValidEnd, newBVE);
275 if (sectionToReadStart == sectionToReadEnd)
280 const auto bufferIndexStart = (int) (sectionToReadStart % buffer.
getNumSamples());
281 const auto bufferIndexEnd = (int) (sectionToReadEnd % buffer.
getNumSamples());
283 if (bufferIndexStart < bufferIndexEnd)
285 readBufferSection (sectionToReadStart,
286 (
int) (sectionToReadEnd - sectionToReadStart),
291 const auto initialSize = buffer.
getNumSamples() - bufferIndexStart;
293 readBufferSection (sectionToReadStart,
297 readBufferSection (sectionToReadStart + initialSize,
298 (
int) (sectionToReadEnd - sectionToReadStart) - initialSize,
303 const ScopedLock sl2 (bufferRangeLock);
305 bufferValidStart = newBVS;
306 bufferValidEnd = newBVE;
309 bufferReadyEvent.
signal();
313void BufferingAudioSource::readBufferSection (int64 start,
int length,
int bufferOffset)
315 if (source->getNextReadPosition() != start)
316 source->setNextReadPosition (start);
318 AudioSourceChannelInfo info (&buffer, bufferOffset, length);
320 const ScopedLock sl (callbackLock);
321 source->getNextAudioBlock (info);
324int BufferingAudioSource::useTimeSlice()
326 return readNextBufferChunk() ? 1 : 100;
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
int getNumSamples() const noexcept
void getNextAudioBlock(const AudioSourceChannelInfo &) override
void setNextReadPosition(int64 newPosition) override
int64 getTotalLength() const override
~BufferingAudioSource() override
BufferingAudioSource(PositionableAudioSource *source, TimeSliceThread &backgroundThread, bool deleteSourceWhenDeleted, int numberOfSamplesToBuffer, int numberOfChannels=2, bool prefillBufferOnPrepareToPlay=true)
bool waitForNextAudioBlockReady(const AudioSourceChannelInfo &info, uint32 timeout)
bool isLooping() const override
void releaseResources() override
int64 getNextReadPosition() const override
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
static void JUCE_CALLTYPE sleep(int milliseconds)
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
void moveToFrontOfQueue(TimeSliceClient *clientToMove)
static uint32 getMillisecondCounter() noexcept
bool wait(double timeOutMilliseconds=-1.0) const