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;
Holds a resizable array of primitive or copy-by-value objects.
void clear()
Removes all elements from the array.
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Changes the buffer's size or number of channels.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.
void clear() noexcept
Clears all the samples in all channels.
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Implementation of the AudioSource method.
void setNextReadPosition(int64 newPosition) override
Implements the PositionableAudioSource method.
int64 getTotalLength() const override
Implements the PositionableAudioSource method.
~BufferingAudioSource() override
Destructor.
BufferingAudioSource(PositionableAudioSource *source, TimeSliceThread &backgroundThread, bool deleteSourceWhenDeleted, int numberOfSamplesToBuffer, int numberOfChannels=2, bool prefillBufferOnPrepareToPlay=true)
Creates a BufferingAudioSource.
bool isLooping() const override
Implements the PositionableAudioSource method.
void releaseResources() override
Implementation of the AudioSource method.
bool waitForNextAudioBlockReady(const AudioSourceChannelInfo &info, const uint32 timeout)
A useful function to block until the next the buffer info can be filled.
int64 getNextReadPosition() const override
Implements the PositionableAudioSource method.
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Implementation of the AudioSource method.
A type of AudioSource which can be repositioned.
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
A thread that keeps a list of clients, and calls each one in turn, giving them all a chance to run so...
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
Removes a client from the list.
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
Adds a client to the list.
void moveToFrontOfQueue(TimeSliceClient *clientToMove)
If the given client is waiting in the queue, it will be moved to the front and given a time-slice as ...
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
bool wait(int timeOutMilliseconds=-1) const noexcept
Suspends the calling thread until the event has been signalled.
void signal() const noexcept
Wakes up any threads that are currently waiting on this object.
Used by AudioSource::getNextAudioBlock().