28 bool deleteSourceWhenDeleted,
32 : source (s, deleteSourceWhenDeleted),
33 backgroundThread (thread),
35 numberOfChannels (numChannels),
38 jassert (source !=
nullptr);
40 jassert (numberOfSamplesToBuffer > 1024);
88 buffer.
setSize (numberOfChannels, 0);
94 source->releaseResources();
101 auto start = bufferValidStart.load();
102 auto end = bufferValidEnd.load();
103 auto pos = nextPlayPos.load();
105 auto validStart = (
int) (jlimit (start, end, pos) - pos);
106 auto validEnd = (
int) (jlimit (start, end, pos +
info.numSamples) - pos);
108 if (validStart == validEnd)
111 info.clearActiveBufferRegion();
118 if (validEnd <
info.numSamples)
120 info.numSamples - validEnd);
122 if (validStart < validEnd)
124 for (
int chan = jmin (numberOfChannels,
info.buffer->getNumChannels()); --
chan >= 0;)
132 info.buffer->copyFrom (
chan,
info.startSample + validStart,
135 validEnd - validStart);
141 info.buffer->copyFrom (
chan,
info.startSample + validStart,
154 nextPlayPos +=
info.numSamples;
160 if (!source || source->getTotalLength() <= 0)
163 if (nextPlayPos +
info.numSamples < 0)
170 auto startTime =
now;
173 : (std::numeric_limits<uint32>::max() - startTime) +
now);
180 auto start = bufferValidStart.load();
181 auto end = bufferValidEnd.load();
182 auto pos = nextPlayPos.load();
184 auto validStart =
static_cast<int> (jlimit (start, end, pos) - pos);
185 auto validEnd =
static_cast<int> (jlimit (start, end, pos +
info.numSamples) - pos);
191 if (
elapsed < timeout && (! bufferReadyEvent.
wait (
static_cast<int> (timeout -
elapsed))))
196 : (std::numeric_limits<uint32>::max() - startTime) +
now);
204 jassert (source->getTotalLength() > 0);
205 auto pos = nextPlayPos.load();
207 return (source->isLooping() && nextPlayPos > 0)
208 ? pos % source->getTotalLength()
220bool BufferingAudioSource::readNextBufferChunk()
230 bufferValidStart = 0;
234 newBVS = jmax ((int64) 0, nextPlayPos.load());
236 sectionToReadStart = 0;
237 sectionToReadEnd = 0;
239 const int maxChunkSize = 2048;
241 if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
243 newBVE = jmin (newBVE, newBVS + maxChunkSize);
245 sectionToReadStart = newBVS;
246 sectionToReadEnd = newBVE;
248 bufferValidStart = 0;
251 else if (std::abs ((
int) (newBVS - bufferValidStart)) > 512
252 || std::abs ((
int) (newBVE - bufferValidEnd)) > 512)
254 newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);
256 sectionToReadStart = bufferValidEnd;
257 sectionToReadEnd = newBVE;
259 bufferValidStart = newBVS;
260 bufferValidEnd = jmin (bufferValidEnd.load(), newBVE);
264 if (sectionToReadStart == sectionToReadEnd)
268 auto bufferIndexStart = (int) (sectionToReadStart % buffer.
getNumSamples());
269 auto bufferIndexEnd = (int) (sectionToReadEnd % buffer.
getNumSamples());
271 if (bufferIndexStart < bufferIndexEnd)
273 readBufferSection (sectionToReadStart,
274 (
int) (sectionToReadEnd - sectionToReadStart),
279 auto initialSize = buffer.
getNumSamples() - bufferIndexStart;
281 readBufferSection (sectionToReadStart,
285 readBufferSection (sectionToReadStart + initialSize,
286 (
int) (sectionToReadEnd - sectionToReadStart) - initialSize,
291 const ScopedLock sl2 (bufferStartPosLock);
293 bufferValidStart = newBVS;
294 bufferValidEnd = newBVE;
297 bufferReadyEvent.
signal();
301void BufferingAudioSource::readBufferSection (int64 start,
int length,
int bufferOffset)
303 if (source->getNextReadPosition() != start)
304 source->setNextReadPosition (start);
306 AudioSourceChannelInfo info (&buffer, bufferOffset, length);
307 source->getNextAudioBlock (info);
310int BufferingAudioSource::useTimeSlice()
312 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 isLooping() const override
void releaseResources() override
bool waitForNextAudioBlockReady(const AudioSourceChannelInfo &info, const uint32 timeout)
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(int timeOutMilliseconds=-1) const