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"
30 #include "juce_AudioFormat.h"
31 #include "../dsp/juce_AudioSampleBuffer.h"
34 //==============================================================================
35 AudioFormatReader::AudioFormatReader (InputStream
* const in
,
36 const String
& formatName_
)
41 usesFloatingPointData (false),
43 formatName (formatName_
)
47 AudioFormatReader::~AudioFormatReader()
52 bool AudioFormatReader::read (int* const* destSamples
,
54 int64 startSampleInSource
,
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)
78 if (! readSamples (const_cast<int**> (destSamples
),
79 jmin ((int) numChannels
, numDestChannels
), startOffsetInDestBuffer
,
80 startSampleInSource
, numSamplesToRead
))
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
];
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
);
105 for (int i
= numChannels
; i
< numDestChannels
; ++i
)
106 if (destSamples
[i
] != nullptr)
107 zeromem (destSamples
[i
], sizeof (int) * numSamplesToRead
);
114 void AudioFormatReader::readMaxLevels (int64 startSampleInFile
,
116 float& lowestLeft
, float& highestLeft
,
117 float& lowestRight
, float& highestRight
)
128 const int bufferSize
= (int) jmin (numSamples
, (int64
) 4096);
129 HeapBlock
<int> tempSpace (bufferSize
* 2 + 64);
132 tempBuffer
[0] = tempSpace
.getData();
133 tempBuffer
[1] = tempSpace
.getData() + bufferSize
;
136 if (usesFloatingPointData
)
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
);
158 findMinAndMax (reinterpret_cast<float*> (tempBuffer
[1]), numToDo
, bufMin
, bufMax
);
159 rmin
= jmin (rmin
, bufMin
);
160 rmax
= jmax (rmax
, bufMax
);
164 if (numChannels
<= 1)
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))
188 numSamples
-= numToDo
;
189 startSampleInFile
+= numToDo
;
191 for (int j
= numChannels
; --j
>= 0;)
194 findMinAndMax (tempBuffer
[j
], numToDo
, bufMin
, bufMax
);
198 lmax
= jmax (lmax
, bufMax
);
199 lmin
= jmin (lmin
, bufMin
);
203 rmax
= jmax (rmax
, bufMax
);
204 rmin
= jmin (rmin
, bufMin
);
209 if (numChannels
<= 1)
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)
231 const int bufferSize
= 4096;
232 HeapBlock
<int> tempSpace (bufferSize
* 2 + 64);
235 tempBuffer
[0] = tempSpace
.getData();
236 tempBuffer
[1] = tempSpace
.getData() + bufferSize
;
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
)
260 read (tempBuffer
, 2, bufferStart
, numThisTime
, false);
262 int num
= numThisTime
;
265 if (numSamplesToSearch
< 0)
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
)
280 else if (numChannels
> 1)
282 const float sample2
= std::abs (((float*) tempBuffer
[1]) [index
]);
284 matches
= (sample2
>= magnitudeRangeMinimum
285 && sample2
<= magnitudeRangeMaximum
);
290 const int sample1
= abs (tempBuffer
[0] [index
]);
292 if (sample1
>= intMagnitudeRangeMinimum
293 && sample1
<= intMagnitudeRangeMaximum
)
297 else if (numChannels
> 1)
299 const int sample2
= abs (tempBuffer
[1][index
]);
301 matches
= (sample2
>= intMagnitudeRangeMinimum
302 && sample2
<= intMagnitudeRangeMaximum
);
308 if (firstMatchPos
< 0)
309 firstMatchPos
= startSample
;
311 if (++consecutive
>= minimumConsecutiveSamples
)
313 if (firstMatchPos
< 0 || firstMatchPos
>= lengthInSamples
)
316 return firstMatchPos
;
325 if (numSamplesToSearch
> 0)
329 if (numSamplesToSearch
> 0)
330 numSamplesToSearch
-= numThisTime
;
332 numSamplesToSearch
+= numThisTime
;