34 source (sourceReader), thread (timeSliceThread),
35 numBlocks (1 + (samplesToBuffer / samplesPerBlock))
44 for (
int i = 3; --i >= 0;)
45 readNextBufferChunk();
50BufferingAudioReader::~BufferingAudioReader()
57 timeoutMs = timeoutMilliseconds;
61 int64 startSampleInFile,
int numSamples)
68 nextReadPosition = startSampleInFile;
70 while (numSamples > 0)
72 if (
auto block = getBlockContaining (startSampleInFile))
74 auto offset = (int) (startSampleInFile - block->range.getStart());
75 auto numToDo = jmin (numSamples, (
int) (block->range.getEnd() - startSampleInFile));
77 for (
int j = 0; j < numDestChannels; ++j)
79 if (
auto dest = (
float*) destSamples[j])
81 dest += startOffsetInDestBuffer;
90 startOffsetInDestBuffer += numToDo;
91 startSampleInFile += numToDo;
92 numSamples -= numToDo;
98 for (
int j = 0; j < numDestChannels; ++j)
99 if (
auto dest = (
float*) destSamples[j])
115BufferingAudioReader::BufferedBlock::BufferedBlock (
AudioFormatReader& reader, int64 pos,
int numSamples)
116 : range (pos, pos + numSamples),
117 buffer ((int) reader.numChannels, numSamples)
119 reader.
read (&buffer, 0, numSamples, pos,
true,
true);
122BufferingAudioReader::BufferedBlock* BufferingAudioReader::getBlockContaining (int64 pos)
const noexcept
124 for (
auto* b : blocks)
125 if (b->range.contains (pos))
131int BufferingAudioReader::useTimeSlice()
133 return readNextBufferChunk() ? 1 : 100;
136bool BufferingAudioReader::readNextBufferChunk()
138 auto pos = nextReadPosition.load();
139 auto startPos = ((pos - 1024) / samplesPerBlock) * samplesPerBlock;
140 auto endPos = startPos + numBlocks * samplesPerBlock;
142 OwnedArray<BufferedBlock> newBlocks;
144 for (
int i = blocks.
size(); --i >= 0;)
145 if (blocks.
getUnchecked(i)->range.intersects (Range<int64> (startPos, endPos)))
148 if (newBlocks.size() == numBlocks)
150 newBlocks.clear (
false);
154 for (
auto p = startPos; p < endPos; p += samplesPerBlock)
156 if (getBlockContaining (p) ==
nullptr)
158 newBlocks.add (
new BufferedBlock (*source, p, samplesPerBlock));
164 const ScopedLock sl (lock);
165 newBlocks.swapWith (blocks);
168 for (
int i = blocks.
size(); --i >= 0;)
bool readSamples(int **destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
Subclasses must implement this method to perform the low-level read operation.
BufferingAudioReader(AudioFormatReader *sourceReader, TimeSliceThread &timeSliceThread, int samplesToBuffer)
Creates a reader.
void setReadTimeout(int timeoutMilliseconds) noexcept
Sets a number of milliseconds that the reader can block for in its readSamples() method before giving...
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
Clears a vector of floats.
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
Copies a vector of floats.
Automatically locks and unlocks a mutex object.
Automatically unlocks and re-locks a mutex object.
int size() const noexcept
Returns the number of items currently in the array.
ObjectClass * getUnchecked(const int index) const noexcept
Returns a pointer to the object at this index in the array, without checking whether the index is in-...
static void JUCE_CALLTYPE yield()
Yields the current thread's CPU time-slot and allows a new thread to run.
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.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).