JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_AudioFormatReader.cpp
Go to the documentation of this file.
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 {
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,
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
204
205 return readChannels (*this, chans, buffer, startSample, numSamples,
207}
208
210 Range<float>* const results, const int channelsToRead)
211{
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{
265 Range<float> levels[2];
266
267 if (numChannels < 2)
268 {
269 readMaxLevels (startSampleInFile, numSamples, levels, (int) numChannels);
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
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
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
A multi-channel buffer containing floating point audio samples.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
Represents a set of audio channel types.
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
Create a canonical channel set for a given number of channels.
Reads samples from an audio file stream.
InputStream * input
The input stream, for use by subclasses.
bool usesFloatingPointData
Indicates whether the data is floating-point or fixed.
bool read(float *const *destChannels, int numDestChannels, int64 startSampleInSource, int numSamplesToRead)
Reads samples from the stream.
int64 searchForLevel(int64 startSample, int64 numSamplesToSearch, double magnitudeRangeMinimum, double magnitudeRangeMaximum, int minimumConsecutiveSamples)
Scans the source looking for a sample whose magnitude is in a specified range.
StringPairArray metadataValues
A set of metadata values that the reader has pulled out of the stream.
virtual ~AudioFormatReader()
Destructor.
int64 lengthInSamples
The total number of samples in the audio stream.
double sampleRate
The sample-rate of the stream.
virtual AudioChannelSet getChannelLayout()
Get the channel layout of the audio stream.
AudioFormatReader(InputStream *sourceStream, const String &formatName)
Creates an AudioFormatReader object.
virtual bool readSamples(int *const *destChannels, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples)=0
Subclasses must implement this method to perform the low-level read operation.
unsigned int bitsPerSample
The number of bits per sample, e.g.
virtual void readMaxLevels(int64 startSample, int64 numSamples, Range< float > *results, int numChannelsToRead)
Finds the highest and lowest sample levels from a section of the audio stream.
unsigned int numChannels
The total number of channels in the audio stream.
Represents a local file or directory.
Definition juce_File.h:45
Very simple container class to hold a pointer to some data on the heap.
The base class for streams that read data.
MemoryMappedAudioFormatReader(const File &file, const AudioFormatReader &details, int64 dataChunkStart, int64 dataChunkLength, int bytesPerFrame)
Creates an MemoryMappedAudioFormatReader object.
void touchSample(int64 sample) const noexcept
Touches the memory for the given sample, to force it to be loaded into active memory.
bool mapEntireFile()
Attempts to map the entire file into memory.
int64 sampleToFilePos(int64 sample) const noexcept
Converts a sample index to a byte position in the file.
virtual bool mapSectionOfFile(Range< int64 > samplesToMap)
Attempts to map a section of the file into memory.
int64 filePosToSample(int64 filePos) const noexcept
Converts a byte position in the file to a sample index.
Maps a file into virtual memory for easy reading and/or writing.
@ readOnly
Indicates that the memory can only be read.
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition juce_Range.h:40
constexpr ValueType getStart() const noexcept
Returns the start of the range.
Definition juce_Range.h:80
constexpr ValueType getEnd() const noexcept
Returns the end of the range.
Definition juce_Range.h:86
constexpr Range getUnionWith(Range other) const noexcept
Returns the smallest range that contains both this one and the other one.
Definition juce_Range.h:246
static Range findMinAndMax(const ValueType *values, Integral numValues) noexcept
Scans an array of values for its min and max, and returns these as a Range.
Definition juce_Range.h:279
The JUCE String class!
Definition juce_String.h:53
#define jassert(expression)
Platform-independent assertion macro.
#define jassertfalse
This will always cause an assertion failure.
typedef int
memcpy
JUCE Namespace.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
long long int64
A platform-independent 64-bit integer type.
void zeromem(void *memory, size_t numBytes) noexcept
Fills a block of memory with zeros.
Definition juce_Memory.h:28
typedef size_t