OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_AudioFormatReader.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 : input (in), formatName (name)
32{
33}
34
39
40static void convertFixedToFloat (int* const* channels, int numChannels, int numSamples)
41{
42 for (int i = 0; i < numChannels; ++i)
43 if (auto d = channels[i])
44 FloatVectorOperations::convertFixedToFloat (reinterpret_cast<float*> (d), d, 1.0f / 0x7fffffff, numSamples);
45}
46
47bool AudioFormatReader::read (float* const* destChannels, int numDestChannels,
49{
50 auto channelsAsInt = reinterpret_cast<int* const*> (destChannels);
51
53 return false;
54
56 convertFixedToFloat (channelsAsInt, numDestChannels, numSamplesToRead);
57
58 return true;
59}
60
61bool AudioFormatReader::read (int* const* destChannels,
66{
67 jassert (numDestChannels > 0); // you have to actually give this some channels to work with!
68
71
72 if (startSampleInSource < 0)
73 {
74 auto silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
75
76 for (int i = numDestChannels; --i >= 0;)
77 if (auto d = destChannels[i])
78 zeromem (d, (size_t) silence * sizeof (int));
79
83 }
84
85 if (numSamplesToRead <= 0)
86 return true;
87
88 if (! readSamples (const_cast<int**> (destChannels),
91 return false;
92
93 if (numDestChannels > (int) numChannels)
94 {
96 {
97 auto lastFullChannel = destChannels[0];
98
99 for (int i = (int) numChannels; --i > 0;)
100 {
101 if (destChannels[i] != nullptr)
102 {
103 lastFullChannel = destChannels[i];
104 break;
105 }
106 }
107
108 if (lastFullChannel != nullptr)
109 for (int i = (int) numChannels; i < numDestChannels; ++i)
110 if (auto d = destChannels[i])
112 }
113 else
114 {
115 for (int i = (int) numChannels; i < numDestChannels; ++i)
116 if (auto d = destChannels[i])
117 zeromem (d, sizeof (int) * originalNumSamplesToRead);
118 }
119 }
120
121 return true;
122}
123
124static void readChannels (AudioFormatReader& reader, int** chans, AudioBuffer<float>* buffer,
125 int startSample, int numSamples, int64 readerStartSample, int numTargetChannels,
126 bool convertToFloat)
127{
128 for (int j = 0; j < numTargetChannels; ++j)
129 chans[j] = reinterpret_cast<int*> (buffer->getWritePointer (j, startSample));
130
131 chans[numTargetChannels] = nullptr;
132 reader.read (chans, numTargetChannels, readerStartSample, numSamples, true);
133
134 if (convertToFloat)
135 convertFixedToFloat (chans, numTargetChannels, numSamples);
136}
137
139 int startSample,
140 int numSamples,
141 int64 readerStartSample,
144{
145 jassert (buffer != nullptr);
146 jassert (startSample >= 0 && startSample + numSamples <= buffer->getNumSamples());
147
148 if (numSamples > 0)
149 {
150 auto numTargetChannels = buffer->getNumChannels();
151
152 if (numTargetChannels <= 2)
153 {
154 int* dests[2] = { reinterpret_cast<int*> (buffer->getWritePointer (0, startSample)),
155 reinterpret_cast<int*> (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr) };
156 int* chans[3] = {};
157
159 {
160 chans[0] = dests[0];
161
162 if (numChannels > 1)
163 chans[1] = dests[1];
164 }
165 else if (useReaderLeftChan || (numChannels == 1))
166 {
167 chans[0] = dests[0];
168 }
169 else if (useReaderRightChan)
170 {
171 chans[1] = dests[0];
172 }
173
174 read (chans, 2, readerStartSample, numSamples, true);
175
176 // if the target's stereo and the source is mono, dupe the first channel..
177 if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr))
178 memcpy (dests[1], dests[0], (size_t) numSamples * sizeof (float));
179
181 convertFixedToFloat (dests, 2, numSamples);
182 }
183 else if (numTargetChannels <= 64)
184 {
185 int* chans[65];
186 readChannels (*this, chans, buffer, startSample, numSamples,
188 }
189 else
190 {
192 readChannels (*this, chans, buffer, startSample, numSamples,
194 }
195 }
196}
197
199 Range<float>* const results, const int channelsToRead)
200{
201 jassert (channelsToRead > 0 && channelsToRead <= (int) numChannels);
202
203 if (numSamples <= 0)
204 {
205 for (int i = 0; i < channelsToRead; ++i)
206 results[i] = Range<float>();
207
208 return;
209 }
210
211 auto bufferSize = (int) jmin (numSamples, (int64) 4096);
213
214 auto floatBuffer = tempSampleBuffer.getArrayOfWritePointers();
215 auto intBuffer = reinterpret_cast<int* const*> (floatBuffer);
216 bool isFirstBlock = true;
217
218 while (numSamples > 0)
219 {
220 auto numToDo = (int) jmin (numSamples, (int64) bufferSize);
221
223 break;
224
225 for (int i = 0; i < channelsToRead; ++i)
226 {
227 Range<float> r;
228
230 {
232 }
233 else
234 {
236
237 r = Range<float> (intRange.getStart() / (float) std::numeric_limits<int>::max(),
238 intRange.getEnd() / (float) std::numeric_limits<int>::max());
239 }
240
241 results[i] = isFirstBlock ? r : results[i].getUnionWith (r);
242 }
243
244 isFirstBlock = false;
245 numSamples -= numToDo;
247 }
248}
249
251 float& lowestLeft, float& highestLeft,
252 float& lowestRight, float& highestRight)
253{
255
256 if (numChannels < 2)
257 {
259 levels[1] = levels[0];
260 }
261 else
262 {
263 readMaxLevels (startSampleInFile, numSamples, levels, 2);
264 }
265
266 lowestLeft = levels[0].getStart();
267 highestLeft = levels[0].getEnd();
268 lowestRight = levels[1].getStart();
269 highestRight = levels[1].getEnd();
270}
271
272int64 AudioFormatReader::searchForLevel (int64 startSample,
273 int64 numSamplesToSearch,
277{
278 if (numSamplesToSearch == 0)
279 return -1;
280
281 const int bufferSize = 4096;
282 HeapBlock<int> tempSpace (bufferSize * 2 + 64);
283
284 int* tempBuffer[3] = { tempSpace.get(),
285 tempSpace.get() + bufferSize,
286 nullptr };
287
288 int consecutive = 0;
289 int64 firstMatchPos = -1;
290
292
293 auto doubleMin = jlimit (0.0, (double) std::numeric_limits<int>::max(), magnitudeRangeMinimum * std::numeric_limits<int>::max());
294 auto doubleMax = jlimit (doubleMin, (double) std::numeric_limits<int>::max(), magnitudeRangeMaximum * std::numeric_limits<int>::max());
295 auto intMagnitudeRangeMinimum = roundToInt (doubleMin);
296 auto intMagnitudeRangeMaximum = roundToInt (doubleMax);
297
298 while (numSamplesToSearch != 0)
299 {
300 auto numThisTime = (int) jmin (std::abs (numSamplesToSearch), (int64) bufferSize);
301 int64 bufferStart = startSample;
302
303 if (numSamplesToSearch < 0)
304 bufferStart -= numThisTime;
305
306 if (bufferStart >= lengthInSamples)
307 break;
308
309 read (tempBuffer, 2, bufferStart, numThisTime, false);
310 auto num = numThisTime;
311
312 while (--num >= 0)
313 {
314 if (numSamplesToSearch < 0)
315 --startSample;
316
317 bool matches = false;
318 auto index = (int) (startSample - bufferStart);
319
321 {
322 const float sample1 = std::abs (((float*) tempBuffer[0]) [index]);
323
326 {
327 matches = true;
328 }
329 else if (numChannels > 1)
330 {
331 const float sample2 = std::abs (((float*) tempBuffer[1]) [index]);
332
333 matches = (sample2 >= magnitudeRangeMinimum
335 }
336 }
337 else
338 {
339 const int sample1 = std::abs (tempBuffer[0] [index]);
340
343 {
344 matches = true;
345 }
346 else if (numChannels > 1)
347 {
348 const int sample2 = std::abs (tempBuffer[1][index]);
349
352 }
353 }
354
355 if (matches)
356 {
357 if (firstMatchPos < 0)
358 firstMatchPos = startSample;
359
361 {
363 return -1;
364
365 return firstMatchPos;
366 }
367 }
368 else
369 {
370 consecutive = 0;
371 firstMatchPos = -1;
372 }
373
374 if (numSamplesToSearch > 0)
375 ++startSample;
376 }
377
378 if (numSamplesToSearch > 0)
380 else
382 }
383
384 return -1;
385}
386
391
392//==============================================================================
394 int64 start, int64 length, int frameSize)
395 : AudioFormatReader (nullptr, reader.getFormatName()), file (f),
396 dataChunkStart (start), dataLength (length), bytesPerFrame (frameSize)
397{
398 sampleRate = reader.sampleRate;
401 numChannels = reader.numChannels;
404}
405
410
412{
413 if (map == nullptr || samplesToMap != mappedSection)
414 {
415 map.reset();
416
418 sampleToFilePos (samplesToMap.getEnd()));
419
421
422 if (map->getData() == nullptr)
423 map.reset();
424 else
425 mappedSection = Range<int64> (jmax ((int64) 0, filePosToSample (map->getRange().getStart() + (bytesPerFrame - 1))),
426 jmin (lengthInSamples, filePosToSample (map->getRange().getEnd())));
427 }
428
429 return map != nullptr;
430}
431
432static int memoryReadDummyVariable; // used to force the compiler not to optimise-away the read operation
433
435{
436 if (map != nullptr && mappedSection.contains (sample))
437 memoryReadDummyVariable += *(char*) sampleToPointer (sample);
438 else
439 jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read.
440}
441
442} // namespace juce
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
bool read(float *const *destChannels, int numDestChannels, int64 startSampleInSource, int numSamplesToRead)
int64 searchForLevel(int64 startSample, int64 numSamplesToSearch, double magnitudeRangeMinimum, double magnitudeRangeMaximum, int minimumConsecutiveSamples)
virtual AudioChannelSet getChannelLayout()
AudioFormatReader(InputStream *sourceStream, const String &formatName)
virtual void readMaxLevels(int64 startSample, int64 numSamples, Range< float > *results, int numChannelsToRead)
virtual bool readSamples(int **destChannels, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples)=0
static void JUCE_CALLTYPE convertFixedToFloat(float *dest, const int *src, float multiplier, int numValues) noexcept
static Range< float > JUCE_CALLTYPE findMinAndMax(const float *src, int numValues) noexcept
MemoryMappedAudioFormatReader(const File &file, const AudioFormatReader &details, int64 dataChunkStart, int64 dataChunkLength, int bytesPerFrame)
void touchSample(int64 sample) const noexcept
int64 sampleToFilePos(int64 sample) const noexcept
virtual bool mapSectionOfFile(Range< int64 > samplesToMap)
int64 filePosToSample(int64 filePos) const noexcept
static Range findMinAndMax(const ValueType *values, int numValues) noexcept
Definition juce_Range.h:273