OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_AudioFormatReader.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30 : input (in), formatName (name)
31{
32}
33
38
39static void convertFixedToFloat (int* const* channels, int numChannels, int numSamples)
40{
41 constexpr auto scaleFactor = 1.0f / static_cast<float> (0x7fffffff);
42
43 for (int i = 0; i < numChannels; ++i)
44 if (auto d = channels[i])
45 FloatVectorOperations::convertFixedToFloat (reinterpret_cast<float*> (d), d, scaleFactor, numSamples);
46}
47
48bool AudioFormatReader::read (float* const* destChannels, int numDestChannels,
50{
51 auto channelsAsInt = reinterpret_cast<int* const*> (destChannels);
52
54 return false;
55
57 convertFixedToFloat (channelsAsInt, numDestChannels, numSamplesToRead);
58
59 return true;
60}
61
62bool AudioFormatReader::read (int* const* destChannels,
67{
68 jassert (numDestChannels > 0); // you have to actually give this some channels to work with!
69
72
73 if (startSampleInSource < 0)
74 {
75 auto silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
76
77 for (int i = numDestChannels; --i >= 0;)
78 if (auto d = destChannels[i])
79 zeromem (d, (size_t) silence * sizeof (int));
80
84 }
85
86 if (numSamplesToRead <= 0)
87 return true;
88
89 if (! readSamples (destChannels,
92 return false;
93
94 if (numDestChannels > (int) numChannels)
95 {
97 {
98 auto lastFullChannel = destChannels[0];
99
100 for (int i = (int) numChannels; --i > 0;)
101 {
102 if (destChannels[i] != nullptr)
103 {
104 lastFullChannel = destChannels[i];
105 break;
106 }
107 }
108
109 if (lastFullChannel != nullptr)
110 for (int i = (int) numChannels; i < numDestChannels; ++i)
111 if (auto d = destChannels[i])
113 }
114 else
115 {
116 for (int i = (int) numChannels; i < numDestChannels; ++i)
117 if (auto d = destChannels[i])
118 zeromem (d, sizeof (int) * originalNumSamplesToRead);
119 }
120 }
121
122 return true;
123}
124
125static bool readChannels (AudioFormatReader& reader, int** chans, AudioBuffer<float>* buffer,
126 int startSample, int numSamples, int64 readerStartSample, int numTargetChannels,
127 bool convertToFloat)
128{
129 for (int j = 0; j < numTargetChannels; ++j)
130 chans[j] = reinterpret_cast<int*> (buffer->getWritePointer (j, startSample));
131
132 chans[numTargetChannels] = nullptr;
133
134 const bool success = reader.read (chans, numTargetChannels, readerStartSample, numSamples, true);
135
136 if (convertToFloat)
137 convertFixedToFloat (chans, numTargetChannels, numSamples);
138
139 return success;
140}
141
143 int startSample,
144 int numSamples,
145 int64 readerStartSample,
148{
149 jassert (buffer != nullptr);
150 jassert (startSample >= 0 && startSample + numSamples <= buffer->getNumSamples());
151
152 if (numSamples <= 0)
153 return true;
154
155 auto numTargetChannels = buffer->getNumChannels();
156
157 if (numTargetChannels <= 2)
158 {
159 int* dests[2] = { reinterpret_cast<int*> (buffer->getWritePointer (0, startSample)),
160 reinterpret_cast<int*> (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr) };
161 int* chans[3] = {};
162
164 {
165 chans[0] = dests[0];
166
167 if (numChannels > 1)
168 chans[1] = dests[1];
169 }
170 else if (useReaderLeftChan || (numChannels == 1))
171 {
172 chans[0] = dests[0];
173 }
174 else if (useReaderRightChan)
175 {
176 chans[1] = dests[0];
177 }
178
179 if (! read (chans, 2, readerStartSample, numSamples, true))
180 return false;
181
182 // if the target's stereo and the source is mono, dupe the first channel..
183 if (numTargetChannels > 1
184 && (chans[0] == nullptr || chans[1] == nullptr)
185 && (dests[0] != nullptr && dests[1] != nullptr))
186 {
187 memcpy (dests[1], dests[0], (size_t) numSamples * sizeof (float));
188 }
189
191 convertFixedToFloat (dests, 2, numSamples);
192
193 return true;
194 }
195
196 if (numTargetChannels <= 64)
197 {
198 int* chans[65];
199 return readChannels (*this, chans, buffer, startSample, numSamples,
201 }
202
203 HeapBlock<int*> chans (numTargetChannels + 1);
204
205 return readChannels (*this, chans, buffer, startSample, numSamples,
206 readerStartSample, numTargetChannels, ! usesFloatingPointData);
207}
208
210 Range<float>* const results, const int channelsToRead)
211{
212 jassert (channelsToRead > 0 && channelsToRead <= (int) numChannels);
213
214 if (numSamples <= 0)
215 {
216 for (int i = 0; i < channelsToRead; ++i)
217 results[i] = Range<float>();
218
219 return;
220 }
221
222 auto bufferSize = (int) jmin (numSamples, (int64) 4096);
224
225 auto floatBuffer = tempSampleBuffer.getArrayOfWritePointers();
226 auto intBuffer = reinterpret_cast<int* const*> (floatBuffer);
227 bool isFirstBlock = true;
228
229 while (numSamples > 0)
230 {
231 auto numToDo = (int) jmin (numSamples, (int64) bufferSize);
232
234 break;
235
236 for (int i = 0; i < channelsToRead; ++i)
237 {
238 Range<float> r;
239
241 {
242 r = FloatVectorOperations::findMinAndMax (floatBuffer[i], numToDo);
243 }
244 else
245 {
247
248 r = Range<float> ((float) intRange.getStart() / (float) std::numeric_limits<int>::max(),
249 (float) intRange.getEnd() / (float) std::numeric_limits<int>::max());
250 }
251
252 results[i] = isFirstBlock ? r : results[i].getUnionWith (r);
253 }
254
255 isFirstBlock = false;
256 numSamples -= numToDo;
258 }
259}
260
262 float& lowestLeft, float& highestLeft,
263 float& lowestRight, float& highestRight)
264{
266
267 if (numChannels < 2)
268 {
270 levels[1] = levels[0];
271 }
272 else
273 {
274 readMaxLevels (startSampleInFile, numSamples, levels, 2);
275 }
276
277 lowestLeft = levels[0].getStart();
278 highestLeft = levels[0].getEnd();
279 lowestRight = levels[1].getStart();
280 highestRight = levels[1].getEnd();
281}
282
283int64 AudioFormatReader::searchForLevel (int64 startSample,
284 int64 numSamplesToSearch,
288{
289 if (numSamplesToSearch == 0)
290 return -1;
291
292 const int bufferSize = 4096;
293 HeapBlock<int> tempSpace (bufferSize * 2 + 64);
294
295 int* tempBuffer[3] = { tempSpace.get(),
296 tempSpace.get() + bufferSize,
297 nullptr };
298
299 int consecutive = 0;
300 int64 firstMatchPos = -1;
301
303
304 auto doubleMin = jlimit (0.0, (double) std::numeric_limits<int>::max(), magnitudeRangeMinimum * std::numeric_limits<int>::max());
305 auto doubleMax = jlimit (doubleMin, (double) std::numeric_limits<int>::max(), magnitudeRangeMaximum * std::numeric_limits<int>::max());
306 auto intMagnitudeRangeMinimum = roundToInt (doubleMin);
307 auto intMagnitudeRangeMaximum = roundToInt (doubleMax);
308
309 while (numSamplesToSearch != 0)
310 {
311 auto numThisTime = (int) jmin (std::abs (numSamplesToSearch), (int64) bufferSize);
312 int64 bufferStart = startSample;
313
314 if (numSamplesToSearch < 0)
316
318 break;
319
320 read (tempBuffer, 2, bufferStart, numThisTime, false);
321 auto num = numThisTime;
322
323 while (--num >= 0)
324 {
325 if (numSamplesToSearch < 0)
326 --startSample;
327
328 bool matches = false;
329 auto index = (int) (startSample - bufferStart);
330
332 {
333 const float sample1 = std::abs (((float*) tempBuffer[0]) [index]);
334
337 {
338 matches = true;
339 }
340 else if (numChannels > 1)
341 {
342 const float sample2 = std::abs (((float*) tempBuffer[1]) [index]);
343
344 matches = (sample2 >= magnitudeRangeMinimum
346 }
347 }
348 else
349 {
350 const int sample1 = std::abs (tempBuffer[0] [index]);
351
354 {
355 matches = true;
356 }
357 else if (numChannels > 1)
358 {
359 const int sample2 = std::abs (tempBuffer[1][index]);
360
363 }
364 }
365
366 if (matches)
367 {
368 if (firstMatchPos < 0)
369 firstMatchPos = startSample;
370
372 {
374 return -1;
375
376 return firstMatchPos;
377 }
378 }
379 else
380 {
381 consecutive = 0;
382 firstMatchPos = -1;
383 }
384
385 if (numSamplesToSearch > 0)
386 ++startSample;
387 }
388
389 if (numSamplesToSearch > 0)
391 else
393 }
394
395 return -1;
396}
397
402
403//==============================================================================
405 int64 start, int64 length, int frameSize)
406 : AudioFormatReader (nullptr, reader.getFormatName()), file (f),
407 dataChunkStart (start), dataLength (length), bytesPerFrame (frameSize)
408{
409 sampleRate = reader.sampleRate;
412 numChannels = reader.numChannels;
415}
416
421
423{
424 if (map == nullptr || samplesToMap != mappedSection)
425 {
426 map.reset();
427
429 sampleToFilePos (samplesToMap.getEnd()));
430
432
433 if (map->getData() == nullptr)
434 map.reset();
435 else
436 mappedSection = Range<int64> (jmax ((int64) 0, filePosToSample (map->getRange().getStart() + (bytesPerFrame - 1))),
437 jmin (lengthInSamples, filePosToSample (map->getRange().getEnd())));
438 }
439
440 return map != nullptr;
441}
442
443static int memoryReadDummyVariable; // used to force the compiler not to optimise-away the read operation
444
446{
447 if (map != nullptr && mappedSection.contains (sample))
448 memoryReadDummyVariable += *(char*) sampleToPointer (sample);
449 else
450 jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read.
451}
452
453} // 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 bool readSamples(int *const *destChannels, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples)=0
virtual void readMaxLevels(int64 startSample, int64 numSamples, Range< float > *results, int numChannelsToRead)
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, Integral numValues) noexcept
Definition juce_Range.h:279