OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_BufferingAudioFormatReader.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12 27th April 2017).
13
14 End User License Agreement: www.juce.com/juce-5-licence
15 Privacy Policy: www.juce.com/juce-5-privacy-policy
16
17 Or: You may also use this code under the terms of the GPL v3 (see
18 www.gnu.org/licenses).
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
31 TimeSliceThread& timeSliceThread,
33 : AudioFormatReader (nullptr, sourceReader->getFormatName()),
34 source (sourceReader), thread (timeSliceThread),
35 numBlocks (1 + (samplesToBuffer / samplesPerBlock))
36{
37 sampleRate = source->sampleRate;
38 lengthInSamples = source->lengthInSamples;
39 numChannels = source->numChannels;
40 metadataValues = source->metadataValues;
41 bitsPerSample = 32;
43
44 for (int i = 3; --i >= 0;)
45 readNextBufferChunk();
46
47 timeSliceThread.addTimeSliceClient (this);
48}
49
50BufferingAudioReader::~BufferingAudioReader()
51{
52 thread.removeTimeSliceClient (this);
53}
54
59
61 int64 startSampleInFile, int numSamples)
62{
63 auto startTime = Time::getMillisecondCounter();
66
67 const ScopedLock sl (lock);
68 nextReadPosition = startSampleInFile;
69
70 while (numSamples > 0)
71 {
72 if (auto block = getBlockContaining (startSampleInFile))
73 {
74 auto offset = (int) (startSampleInFile - block->range.getStart());
75 auto numToDo = jmin (numSamples, (int) (block->range.getEnd() - startSampleInFile));
76
77 for (int j = 0; j < numDestChannels; ++j)
78 {
79 if (auto dest = (float*) destSamples[j])
80 {
82
83 if (j < (int) numChannels)
84 FloatVectorOperations::copy (dest, block->buffer.getReadPointer (j, offset), numToDo);
85 else
87 }
88 }
89
92 numSamples -= numToDo;
93 }
94 else
95 {
96 if (timeoutMs >= 0 && Time::getMillisecondCounter() >= startTime + (uint32) timeoutMs)
97 {
98 for (int j = 0; j < numDestChannels; ++j)
99 if (auto dest = (float*) destSamples[j])
101
102 break;
103 }
104 else
105 {
106 ScopedUnlock ul (lock);
108 }
109 }
110 }
111
112 return true;
113}
114
115BufferingAudioReader::BufferedBlock::BufferedBlock (AudioFormatReader& reader, int64 pos, int numSamples)
116 : range (pos, pos + numSamples),
117 buffer ((int) reader.numChannels, numSamples)
118{
119 reader.read (&buffer, 0, numSamples, pos, true, true);
120}
121
122BufferingAudioReader::BufferedBlock* BufferingAudioReader::getBlockContaining (int64 pos) const noexcept
123{
124 for (auto* b : blocks)
125 if (b->range.contains (pos))
126 return b;
127
128 return nullptr;
129}
130
131int BufferingAudioReader::useTimeSlice()
132{
133 return readNextBufferChunk() ? 1 : 100;
134}
135
136bool BufferingAudioReader::readNextBufferChunk()
137{
138 auto pos = nextReadPosition.load();
139 auto startPos = ((pos - 1024) / samplesPerBlock) * samplesPerBlock;
140 auto endPos = startPos + numBlocks * samplesPerBlock;
141
142 OwnedArray<BufferedBlock> newBlocks;
143
144 for (int i = blocks.size(); --i >= 0;)
145 if (blocks.getUnchecked(i)->range.intersects (Range<int64> (startPos, endPos)))
146 newBlocks.add (blocks.getUnchecked(i));
147
148 if (newBlocks.size() == numBlocks)
149 {
150 newBlocks.clear (false);
151 return false;
152 }
153
154 for (auto p = startPos; p < endPos; p += samplesPerBlock)
155 {
156 if (getBlockContaining (p) == nullptr)
157 {
158 newBlocks.add (new BufferedBlock (*source, p, samplesPerBlock));
159 break; // just do one block
160 }
161 }
162
163 {
164 const ScopedLock sl (lock);
165 newBlocks.swapWith (blocks);
166 }
167
168 for (int i = blocks.size(); --i >= 0;)
169 newBlocks.removeObject (blocks.getUnchecked(i), false);
170
171 return true;
172}
173
174} // namespace juce
bool read(float *const *destChannels, int numDestChannels, int64 startSampleInSource, int numSamplesToRead)
static void clearSamplesBeyondAvailableLength(int **destChannels, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int &numSamples, int64 fileLengthInSamples)
bool readSamples(int **destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
BufferingAudioReader(AudioFormatReader *sourceReader, TimeSliceThread &timeSliceThread, int samplesToBuffer)
void setReadTimeout(int timeoutMilliseconds) noexcept
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
int size() const noexcept
ObjectClass * getUnchecked(int index) const noexcept
static void JUCE_CALLTYPE yield()
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
static uint32 getMillisecondCounter() noexcept