Use both internal and external UIs
[juce-lv2.git] / juce / source / src / audio / audio_file_formats / juce_AudioFormatReader.cpp
blobb4f1296405068131f32fd4e4776f26103b5c55ba
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_AudioFormat.h"
31 #include "../dsp/juce_AudioSampleBuffer.h"
34 //==============================================================================
35 AudioFormatReader::AudioFormatReader (InputStream* const in,
36 const String& formatName_)
37 : sampleRate (0),
38 bitsPerSample (0),
39 lengthInSamples (0),
40 numChannels (0),
41 usesFloatingPointData (false),
42 input (in),
43 formatName (formatName_)
47 AudioFormatReader::~AudioFormatReader()
49 delete input;
52 bool AudioFormatReader::read (int* const* destSamples,
53 int numDestChannels,
54 int64 startSampleInSource,
55 int numSamplesToRead,
56 const bool fillLeftoverChannelsWithCopies)
58 jassert (numDestChannels > 0); // you have to actually give this some channels to work with!
60 int startOffsetInDestBuffer = 0;
62 if (startSampleInSource < 0)
64 const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
66 for (int i = numDestChannels; --i >= 0;)
67 if (destSamples[i] != nullptr)
68 zeromem (destSamples[i], sizeof (int) * silence);
70 startOffsetInDestBuffer += silence;
71 numSamplesToRead -= silence;
72 startSampleInSource = 0;
75 if (numSamplesToRead <= 0)
76 return true;
78 if (! readSamples (const_cast<int**> (destSamples),
79 jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer,
80 startSampleInSource, numSamplesToRead))
81 return false;
83 if (numDestChannels > (int) numChannels)
85 if (fillLeftoverChannelsWithCopies)
87 int* lastFullChannel = destSamples[0];
89 for (int i = (int) numChannels; --i > 0;)
91 if (destSamples[i] != nullptr)
93 lastFullChannel = destSamples[i];
94 break;
98 if (lastFullChannel != nullptr)
99 for (int i = numChannels; i < numDestChannels; ++i)
100 if (destSamples[i] != nullptr)
101 memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead);
103 else
105 for (int i = numChannels; i < numDestChannels; ++i)
106 if (destSamples[i] != nullptr)
107 zeromem (destSamples[i], sizeof (int) * numSamplesToRead);
111 return true;
114 void AudioFormatReader::readMaxLevels (int64 startSampleInFile,
115 int64 numSamples,
116 float& lowestLeft, float& highestLeft,
117 float& lowestRight, float& highestRight)
119 if (numSamples <= 0)
121 lowestLeft = 0;
122 lowestRight = 0;
123 highestLeft = 0;
124 highestRight = 0;
125 return;
128 const int bufferSize = (int) jmin (numSamples, (int64) 4096);
129 HeapBlock<int> tempSpace (bufferSize * 2 + 64);
131 int* tempBuffer[3];
132 tempBuffer[0] = tempSpace.getData();
133 tempBuffer[1] = tempSpace.getData() + bufferSize;
134 tempBuffer[2] = 0;
136 if (usesFloatingPointData)
138 float lmin = 1.0e6f;
139 float lmax = -lmin;
140 float rmin = lmin;
141 float rmax = lmax;
143 while (numSamples > 0)
145 const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
146 read (tempBuffer, 2, startSampleInFile, numToDo, false);
148 numSamples -= numToDo;
149 startSampleInFile += numToDo;
151 float bufMin, bufMax;
152 findMinAndMax (reinterpret_cast<float*> (tempBuffer[0]), numToDo, bufMin, bufMax);
153 lmin = jmin (lmin, bufMin);
154 lmax = jmax (lmax, bufMax);
156 if (numChannels > 1)
158 findMinAndMax (reinterpret_cast<float*> (tempBuffer[1]), numToDo, bufMin, bufMax);
159 rmin = jmin (rmin, bufMin);
160 rmax = jmax (rmax, bufMax);
164 if (numChannels <= 1)
166 rmax = lmax;
167 rmin = lmin;
170 lowestLeft = lmin;
171 highestLeft = lmax;
172 lowestRight = rmin;
173 highestRight = rmax;
175 else
177 int lmax = std::numeric_limits<int>::min();
178 int lmin = std::numeric_limits<int>::max();
179 int rmax = std::numeric_limits<int>::min();
180 int rmin = std::numeric_limits<int>::max();
182 while (numSamples > 0)
184 const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
185 if (! read (tempBuffer, 2, startSampleInFile, numToDo, false))
186 break;
188 numSamples -= numToDo;
189 startSampleInFile += numToDo;
191 for (int j = numChannels; --j >= 0;)
193 int bufMin, bufMax;
194 findMinAndMax (tempBuffer[j], numToDo, bufMin, bufMax);
196 if (j == 0)
198 lmax = jmax (lmax, bufMax);
199 lmin = jmin (lmin, bufMin);
201 else
203 rmax = jmax (rmax, bufMax);
204 rmin = jmin (rmin, bufMin);
209 if (numChannels <= 1)
211 rmax = lmax;
212 rmin = lmin;
215 lowestLeft = lmin / (float) std::numeric_limits<int>::max();
216 highestLeft = lmax / (float) std::numeric_limits<int>::max();
217 lowestRight = rmin / (float) std::numeric_limits<int>::max();
218 highestRight = rmax / (float) std::numeric_limits<int>::max();
222 int64 AudioFormatReader::searchForLevel (int64 startSample,
223 int64 numSamplesToSearch,
224 const double magnitudeRangeMinimum,
225 const double magnitudeRangeMaximum,
226 const int minimumConsecutiveSamples)
228 if (numSamplesToSearch == 0)
229 return -1;
231 const int bufferSize = 4096;
232 HeapBlock<int> tempSpace (bufferSize * 2 + 64);
234 int* tempBuffer[3];
235 tempBuffer[0] = tempSpace.getData();
236 tempBuffer[1] = tempSpace.getData() + bufferSize;
237 tempBuffer[2] = 0;
239 int consecutive = 0;
240 int64 firstMatchPos = -1;
242 jassert (magnitudeRangeMaximum > magnitudeRangeMinimum);
244 const double doubleMin = jlimit (0.0, (double) std::numeric_limits<int>::max(), magnitudeRangeMinimum * std::numeric_limits<int>::max());
245 const double doubleMax = jlimit (doubleMin, (double) std::numeric_limits<int>::max(), magnitudeRangeMaximum * std::numeric_limits<int>::max());
246 const int intMagnitudeRangeMinimum = roundToInt (doubleMin);
247 const int intMagnitudeRangeMaximum = roundToInt (doubleMax);
249 while (numSamplesToSearch != 0)
251 const int numThisTime = (int) jmin (abs64 (numSamplesToSearch), (int64) bufferSize);
252 int64 bufferStart = startSample;
254 if (numSamplesToSearch < 0)
255 bufferStart -= numThisTime;
257 if (bufferStart >= (int) lengthInSamples)
258 break;
260 read (tempBuffer, 2, bufferStart, numThisTime, false);
262 int num = numThisTime;
263 while (--num >= 0)
265 if (numSamplesToSearch < 0)
266 --startSample;
268 bool matches = false;
269 const int index = (int) (startSample - bufferStart);
271 if (usesFloatingPointData)
273 const float sample1 = std::abs (((float*) tempBuffer[0]) [index]);
275 if (sample1 >= magnitudeRangeMinimum
276 && sample1 <= magnitudeRangeMaximum)
278 matches = true;
280 else if (numChannels > 1)
282 const float sample2 = std::abs (((float*) tempBuffer[1]) [index]);
284 matches = (sample2 >= magnitudeRangeMinimum
285 && sample2 <= magnitudeRangeMaximum);
288 else
290 const int sample1 = abs (tempBuffer[0] [index]);
292 if (sample1 >= intMagnitudeRangeMinimum
293 && sample1 <= intMagnitudeRangeMaximum)
295 matches = true;
297 else if (numChannels > 1)
299 const int sample2 = abs (tempBuffer[1][index]);
301 matches = (sample2 >= intMagnitudeRangeMinimum
302 && sample2 <= intMagnitudeRangeMaximum);
306 if (matches)
308 if (firstMatchPos < 0)
309 firstMatchPos = startSample;
311 if (++consecutive >= minimumConsecutiveSamples)
313 if (firstMatchPos < 0 || firstMatchPos >= lengthInSamples)
314 return -1;
316 return firstMatchPos;
319 else
321 consecutive = 0;
322 firstMatchPos = -1;
325 if (numSamplesToSearch > 0)
326 ++startSample;
329 if (numSamplesToSearch > 0)
330 numSamplesToSearch -= numThisTime;
331 else
332 numSamplesToSearch += numThisTime;
335 return -1;
339 END_JUCE_NAMESPACE