OpenShot Library | libopenshot-audio 0.2.0
juce_AudioDataConverters.h
1
2/** @weakgroup juce_audio_basics-buffers
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
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
30//==============================================================================
31/**
32 This class a container which holds all the classes pertaining to the AudioData::Pointer
33 audio sample format class.
34
35 @see AudioData::Pointer.
36
37 @tags{Audio}
38*/
40{
41public:
42 //==============================================================================
43 // These types can be used as the SampleFormat template parameter for the AudioData::Pointer class.
44
45 class Int8; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit integer packed data format. */
46 class UInt8; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit unsigned integer packed data format. */
47 class Int16; /**< Used as a template parameter for AudioData::Pointer. Indicates an 16-bit integer packed data format. */
48 class Int24; /**< Used as a template parameter for AudioData::Pointer. Indicates an 24-bit integer packed data format. */
49 class Int32; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit integer packed data format. */
50 class Float32; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit float data format. */
51
52 //==============================================================================
53 // These types can be used as the Endianness template parameter for the AudioData::Pointer class.
54
55 class BigEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in big-endian order. */
56 class LittleEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in little-endian order. */
57 class NativeEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in the CPU's native endianness. */
58
59 //==============================================================================
60 // These types can be used as the InterleavingType template parameter for the AudioData::Pointer class.
61
62 class NonInterleaved; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored contiguously. */
63 class Interleaved; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are interleaved with a number of other channels. */
64
65 //==============================================================================
66 // These types can be used as the Constness template parameter for the AudioData::Pointer class.
67
68 class NonConst; /**< Used as a template parameter for AudioData::Pointer. Indicates that the pointer can be used for non-const data. */
69 class Const; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples can only be used for const data.. */
70
71 #ifndef DOXYGEN
72 //==============================================================================
73 class BigEndian
74 {
75 public:
76 template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatBE(); }
77 template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatBE (newValue); }
78 template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32BE(); }
79 template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32BE (newValue); }
80 template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromBE (source); }
81 enum { isBigEndian = 1 };
82 };
83
84 class LittleEndian
85 {
86 public:
87 template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatLE(); }
88 template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatLE (newValue); }
89 template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32LE(); }
90 template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32LE (newValue); }
91 template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromLE (source); }
92 enum { isBigEndian = 0 };
93 };
94
95 #if JUCE_BIG_ENDIAN
96 class NativeEndian : public BigEndian {};
97 #else
98 class NativeEndian : public LittleEndian {};
99 #endif
100
101 //==============================================================================
102 class Int8
103 {
104 public:
105 inline Int8 (void* d) noexcept : data (static_cast<int8*> (d)) {}
106
107 inline void advance() noexcept { ++data; }
108 inline void skip (int numSamples) noexcept { data += numSamples; }
109 inline float getAsFloatLE() const noexcept { return (float) (*data * (1.0 / (1.0 + maxValue))); }
110 inline float getAsFloatBE() const noexcept { return getAsFloatLE(); }
111 inline void setAsFloatLE (float newValue) noexcept { *data = (int8) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))); }
112 inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); }
113 inline int32 getAsInt32LE() const noexcept { return (int) (*((uint8*) data) << 24); }
114 inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); }
115 inline void setAsInt32LE (int newValue) noexcept { *data = (int8) (newValue >> 24); }
116 inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); }
117 inline void clear() noexcept { *data = 0; }
118 inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
119 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
120 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
121 inline void copyFromSameType (Int8& source) noexcept { *data = *source.data; }
122
123 int8* data;
124 enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
125 };
126
127 class UInt8
128 {
129 public:
130 inline UInt8 (void* d) noexcept : data (static_cast<uint8*> (d)) {}
131
132 inline void advance() noexcept { ++data; }
133 inline void skip (int numSamples) noexcept { data += numSamples; }
134 inline float getAsFloatLE() const noexcept { return (float) ((*data - 128) * (1.0 / (1.0 + maxValue))); }
135 inline float getAsFloatBE() const noexcept { return getAsFloatLE(); }
136 inline void setAsFloatLE (float newValue) noexcept { *data = (uint8) jlimit (0, 255, 128 + roundToInt (newValue * (1.0 + maxValue))); }
137 inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); }
138 inline int32 getAsInt32LE() const noexcept { return (int) (((uint8) (*data - 128)) << 24); }
139 inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); }
140 inline void setAsInt32LE (int newValue) noexcept { *data = (uint8) (128 + (newValue >> 24)); }
141 inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); }
142 inline void clear() noexcept { *data = 128; }
143 inline void clearMultiple (int num) noexcept { memset (data, 128, (size_t) num) ;}
144 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
145 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
146 inline void copyFromSameType (UInt8& source) noexcept { *data = *source.data; }
147
148 uint8* data;
149 enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
150 };
151
152 class Int16
153 {
154 public:
155 inline Int16 (void* d) noexcept : data (static_cast<uint16*> (d)) {}
156
157 inline void advance() noexcept { ++data; }
158 inline void skip (int numSamples) noexcept { data += numSamples; }
159 inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfBigEndian (*data)); }
160 inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfLittleEndian (*data)); }
161 inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); }
162 inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); }
163 inline int32 getAsInt32LE() const noexcept { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); }
164 inline int32 getAsInt32BE() const noexcept { return (int32) (ByteOrder::swapIfLittleEndian ((uint16) *data) << 16); }
165 inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); }
166 inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); }
167 inline void clear() noexcept { *data = 0; }
168 inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
169 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
170 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
171 inline void copyFromSameType (Int16& source) noexcept { *data = *source.data; }
172
173 uint16* data;
174 enum { bytesPerSample = 2, maxValue = 0x7fff, resolution = (1 << 16), isFloat = 0 };
175 };
176
177 class Int24
178 {
179 public:
180 inline Int24 (void* d) noexcept : data (static_cast<char*> (d)) {}
181
182 inline void advance() noexcept { data += 3; }
183 inline void skip (int numSamples) noexcept { data += 3 * numSamples; }
184 inline float getAsFloatLE() const noexcept { return (float) (ByteOrder::littleEndian24Bit (data) * (1.0 / (1.0 + maxValue))); }
185 inline float getAsFloatBE() const noexcept { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / (1.0 + maxValue))); }
186 inline void setAsFloatLE (float newValue) noexcept { ByteOrder::littleEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); }
187 inline void setAsFloatBE (float newValue) noexcept { ByteOrder::bigEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); }
188 inline int32 getAsInt32LE() const noexcept { return (int32) (((unsigned int) ByteOrder::littleEndian24Bit (data)) << 8); }
189 inline int32 getAsInt32BE() const noexcept { return (int32) (((unsigned int) ByteOrder::bigEndian24Bit (data)) << 8); }
190 inline void setAsInt32LE (int32 newValue) noexcept { ByteOrder::littleEndian24BitToChars (newValue >> 8, data); }
191 inline void setAsInt32BE (int32 newValue) noexcept { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); }
192 inline void clear() noexcept { data[0] = 0; data[1] = 0; data[2] = 0; }
193 inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
194 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
195 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
196 inline void copyFromSameType (Int24& source) noexcept { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; }
197
198 char* data;
199 enum { bytesPerSample = 3, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
200 };
201
202 class Int32
203 {
204 public:
205 inline Int32 (void* d) noexcept : data (static_cast<uint32*> (d)) {}
206
207 inline void advance() noexcept { ++data; }
208 inline void skip (int numSamples) noexcept { data += numSamples; }
209 inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); }
210 inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); }
211 inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (int32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); }
212 inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (int32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); }
213 inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); }
214 inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); }
215 inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); }
216 inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue); }
217 inline void clear() noexcept { *data = 0; }
218 inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
219 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
220 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
221 inline void copyFromSameType (Int32& source) noexcept { *data = *source.data; }
222
223 uint32* data;
224 enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = 1, isFloat = 0 };
225 };
226
227 /** A 32-bit integer type, of which only the bottom 24 bits are used. */
228 class Int24in32 : public Int32
229 {
230 public:
231 inline Int24in32 (void* d) noexcept : Int32 (d) {}
232
233 inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); }
234 inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); }
235 inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); }
236 inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); }
237 inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data) << 8; }
238 inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data) << 8; }
239 inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue >> 8); }
240 inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue >> 8); }
241 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
242 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
243 inline void copyFromSameType (Int24in32& source) noexcept { *data = *source.data; }
244
245 enum { bytesPerSample = 4, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
246 };
247
248 class Float32
249 {
250 public:
251 inline Float32 (void* d) noexcept : data (static_cast<float*> (d)) {}
252
253 inline void advance() noexcept { ++data; }
254 inline void skip (int numSamples) noexcept { data += numSamples; }
255 #if JUCE_BIG_ENDIAN
256 inline float getAsFloatBE() const noexcept { return *data; }
257 inline void setAsFloatBE (float newValue) noexcept { *data = newValue; }
258 inline float getAsFloatLE() const noexcept { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
259 inline void setAsFloatLE (float newValue) noexcept { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
260 #else
261 inline float getAsFloatLE() const noexcept { return *data; }
262 inline void setAsFloatLE (float newValue) noexcept { *data = newValue; }
263 inline float getAsFloatBE() const noexcept { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
264 inline void setAsFloatBE (float newValue) noexcept { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
265 #endif
266 inline int32 getAsInt32LE() const noexcept { return (int32) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatLE()) * (double) maxValue); }
267 inline int32 getAsInt32BE() const noexcept { return (int32) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatBE()) * (double) maxValue); }
268 inline void setAsInt32LE (int32 newValue) noexcept { setAsFloatLE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
269 inline void setAsInt32BE (int32 newValue) noexcept { setAsFloatBE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
270 inline void clear() noexcept { *data = 0; }
271 inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
272 template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsFloatLE (source.getAsFloat()); }
273 template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsFloatBE (source.getAsFloat()); }
274 inline void copyFromSameType (Float32& source) noexcept { *data = *source.data; }
275
276 float* data;
277 enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = (1 << 8), isFloat = 1 };
278 };
279
280 //==============================================================================
281 class NonInterleaved
282 {
283 public:
284 inline NonInterleaved() = default;
285 inline NonInterleaved (const NonInterleaved&) = default;
286 inline NonInterleaved (const int) noexcept {}
287 inline void copyFrom (const NonInterleaved&) noexcept {}
288 template <class SampleFormatType> inline void advanceData (SampleFormatType& s) noexcept { s.advance(); }
289 template <class SampleFormatType> inline void advanceDataBy (SampleFormatType& s, int numSamples) noexcept { s.skip (numSamples); }
290 template <class SampleFormatType> inline void clear (SampleFormatType& s, int numSamples) noexcept { s.clearMultiple (numSamples); }
291 template <class SampleFormatType> inline static int getNumBytesBetweenSamples (const SampleFormatType&) noexcept { return SampleFormatType::bytesPerSample; }
292
293 enum { isInterleavedType = 0, numInterleavedChannels = 1 };
294 };
295
296 class Interleaved
297 {
298 public:
299 inline Interleaved() noexcept {}
300 inline Interleaved (const Interleaved& other) = default;
301 inline Interleaved (const int numInterleavedChans) noexcept : numInterleavedChannels (numInterleavedChans) {}
302 inline void copyFrom (const Interleaved& other) noexcept { numInterleavedChannels = other.numInterleavedChannels; }
303 template <class SampleFormatType> inline void advanceData (SampleFormatType& s) noexcept { s.skip (numInterleavedChannels); }
304 template <class SampleFormatType> inline void advanceDataBy (SampleFormatType& s, int numSamples) noexcept { s.skip (numInterleavedChannels * numSamples); }
305 template <class SampleFormatType> inline void clear (SampleFormatType& s, int numSamples) noexcept { while (--numSamples >= 0) { s.clear(); s.skip (numInterleavedChannels); } }
306 template <class SampleFormatType> inline int getNumBytesBetweenSamples (const SampleFormatType&) const noexcept { return numInterleavedChannels * SampleFormatType::bytesPerSample; }
307 int numInterleavedChannels = 1;
308 enum { isInterleavedType = 1 };
309 };
310
311 //==============================================================================
312 class NonConst
313 {
314 public:
315 using VoidType = void;
316 static inline void* toVoidPtr (VoidType* v) noexcept { return v; }
317 enum { isConst = 0 };
318 };
319
320 class Const
321 {
322 public:
323 using VoidType = const void;
324 static inline void* toVoidPtr (VoidType* v) noexcept { return const_cast<void*> (v); }
325 enum { isConst = 1 };
326 };
327 #endif
328
329 //==============================================================================
330 /**
331 A pointer to a block of audio data with a particular encoding.
332
333 This object can be used to read and write from blocks of encoded audio samples. To create one, you specify
334 the audio format as a series of template parameters, e.g.
335 @code
336 // this creates a pointer for reading from a const array of 16-bit little-endian packed samples.
337 AudioData::Pointer <AudioData::Int16,
338 AudioData::LittleEndian,
339 AudioData::NonInterleaved,
340 AudioData::Const> pointer (someRawAudioData);
341
342 // These methods read the sample that is being pointed to
343 float firstSampleAsFloat = pointer.getAsFloat();
344 int32 firstSampleAsInt = pointer.getAsInt32();
345 ++pointer; // moves the pointer to the next sample.
346 pointer += 3; // skips the next 3 samples.
347 @endcode
348
349 The convertSamples() method lets you copy a range of samples from one format to another, automatically
350 converting its format.
351
352 @see AudioData::Converter
353 */
354 template <typename SampleFormat,
355 typename Endianness,
356 typename InterleavingType,
357 typename Constness>
358 class Pointer : private InterleavingType // (inherited for EBCO)
359 {
360 public:
361 //==============================================================================
362 /** Creates a non-interleaved pointer from some raw data in the appropriate format.
363 This constructor is only used if you've specified the AudioData::NonInterleaved option -
364 for interleaved formats, use the constructor that also takes a number of channels.
365 */
366 Pointer (typename Constness::VoidType* sourceData) noexcept
367 : data (Constness::toVoidPtr (sourceData))
368 {
369 // If you're using interleaved data, call the other constructor! If you're using non-interleaved data,
370 // you should pass NonInterleaved as the template parameter for the interleaving type!
371 static_assert (InterleavingType::isInterleavedType == 0, "Incorrect constructor for interleaved data");
372 }
373
374 /** Creates a pointer from some raw data in the appropriate format with the specified number of interleaved channels.
375 For non-interleaved data, use the other constructor.
376 */
377 Pointer (typename Constness::VoidType* sourceData, int numInterleaved) noexcept
378 : InterleavingType (numInterleaved), data (Constness::toVoidPtr (sourceData))
379 {
380 }
381
382 /** Creates a copy of another pointer. */
383 Pointer (const Pointer& other) noexcept
384 : InterleavingType (other), data (other.data)
385 {
386 }
387
388 Pointer& operator= (const Pointer& other) noexcept
389 {
390 InterleavingType::operator= (other);
391 data = other.data;
392 return *this;
393 }
394
395 //==============================================================================
396 /** Returns the value of the first sample as a floating point value.
397 The value will be in the range -1.0 to 1.0 for integer formats. For floating point
398 formats, the value could be outside that range, although -1 to 1 is the standard range.
399 */
400 inline float getAsFloat() const noexcept { return Endianness::getAsFloat (data); }
401
402 /** Sets the value of the first sample as a floating point value.
403
404 (This method can only be used if the AudioData::NonConst option was used).
405 The value should be in the range -1.0 to 1.0 - for integer formats, values outside that
406 range will be clipped. For floating point formats, any value passed in here will be
407 written directly, although -1 to 1 is the standard range.
408 */
409 inline void setAsFloat (float newValue) noexcept
410 {
411 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
412 static_assert (Constness::isConst == 0, "Attempt to write to a const pointer");
413 Endianness::setAsFloat (data, newValue);
414 }
415
416 /** Returns the value of the first sample as a 32-bit integer.
417 The value returned will be in the range 0x80000000 to 0x7fffffff, and shorter values will be
418 shifted to fill this range (e.g. if you're reading from 24-bit data, the values will be shifted up
419 by 8 bits when returned here). If the source data is floating point, values beyond -1.0 to 1.0 will
420 be clipped so that -1.0 maps onto -0x7fffffff and 1.0 maps to 0x7fffffff.
421 */
422 inline int32 getAsInt32() const noexcept { return Endianness::getAsInt32 (data); }
423
424 /** Sets the value of the first sample as a 32-bit integer.
425 This will be mapped to the range of the format that is being written - see getAsInt32().
426 */
427 inline void setAsInt32 (int32 newValue) noexcept
428 {
429 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
430 static_assert (Constness::isConst == 0, "Attempt to write to a const pointer");
431 Endianness::setAsInt32 (data, newValue);
432 }
433
434 /** Moves the pointer along to the next sample. */
435 inline Pointer& operator++() noexcept { advance(); return *this; }
436
437 /** Moves the pointer back to the previous sample. */
438 inline Pointer& operator--() noexcept { this->advanceDataBy (data, -1); return *this; }
439
440 /** Adds a number of samples to the pointer's position. */
441 Pointer& operator+= (int samplesToJump) noexcept { this->advanceDataBy (data, samplesToJump); return *this; }
442
443 /** Writes a stream of samples into this pointer from another pointer.
444 This will copy the specified number of samples, converting between formats appropriately.
445 */
446 void convertSamples (Pointer source, int numSamples) const noexcept
447 {
448 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
449 static_assert (Constness::isConst == 0, "Attempt to write to a const pointer");
450
451 for (Pointer dest (*this); --numSamples >= 0;)
452 {
453 dest.data.copyFromSameType (source.data);
454 dest.advance();
455 source.advance();
456 }
457 }
458
459 /** Writes a stream of samples into this pointer from another pointer.
460 This will copy the specified number of samples, converting between formats appropriately.
461 */
462 template <class OtherPointerType>
463 void convertSamples (OtherPointerType source, int numSamples) const noexcept
464 {
465 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
466 static_assert (Constness::isConst == 0, "Attempt to write to a const pointer");
467
468 Pointer dest (*this);
469
470 if (source.getRawData() != getRawData() || source.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples())
471 {
472 while (--numSamples >= 0)
473 {
474 Endianness::copyFrom (dest.data, source);
475 dest.advance();
476 ++source;
477 }
478 }
479 else // copy backwards if we're increasing the sample width..
480 {
481 dest += numSamples;
482 source += numSamples;
483
484 while (--numSamples >= 0)
485 Endianness::copyFrom ((--dest).data, --source);
486 }
487 }
488
489 /** Sets a number of samples to zero. */
490 void clearSamples (int numSamples) const noexcept
491 {
492 Pointer dest (*this);
493 dest.clear (dest.data, numSamples);
494 }
495
496 /** Scans a block of data, returning the lowest and highest levels as floats */
497 Range<float> findMinAndMax (size_t numSamples) const noexcept
498 {
499 if (numSamples == 0)
500 return Range<float>();
501
502 Pointer dest (*this);
503
504 if (isFloatingPoint())
505 {
506 float mn = dest.getAsFloat();
507 dest.advance();
508 float mx = mn;
509
510 while (--numSamples > 0)
511 {
512 const float v = dest.getAsFloat();
513 dest.advance();
514
515 if (mx < v) mx = v;
516 if (v < mn) mn = v;
517 }
518
519 return Range<float> (mn, mx);
520 }
521
522 int32 mn = dest.getAsInt32();
523 dest.advance();
524 int32 mx = mn;
525
526 while (--numSamples > 0)
527 {
528 const int v = dest.getAsInt32();
529 dest.advance();
530
531 if (mx < v) mx = v;
532 if (v < mn) mn = v;
533 }
534
535 return Range<float> (mn * (float) (1.0 / (1.0 + Int32::maxValue)),
536 mx * (float) (1.0 / (1.0 + Int32::maxValue)));
537 }
538
539 /** Scans a block of data, returning the lowest and highest levels as floats */
540 void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept
541 {
542 Range<float> r (findMinAndMax (numSamples));
543 minValue = r.getStart();
544 maxValue = r.getEnd();
545 }
546
547 /** Returns true if the pointer is using a floating-point format. */
548 static bool isFloatingPoint() noexcept { return (bool) SampleFormat::isFloat; }
549
550 /** Returns true if the format is big-endian. */
551 static bool isBigEndian() noexcept { return (bool) Endianness::isBigEndian; }
552
553 /** Returns the number of bytes in each sample (ignoring the number of interleaved channels). */
554 static int getBytesPerSample() noexcept { return (int) SampleFormat::bytesPerSample; }
555
556 /** Returns the number of interleaved channels in the format. */
557 int getNumInterleavedChannels() const noexcept { return (int) this->numInterleavedChannels; }
558
559 /** Returns the number of bytes between the start address of each sample. */
560 int getNumBytesBetweenSamples() const noexcept { return InterleavingType::getNumBytesBetweenSamples (data); }
561
562 /** Returns the accuracy of this format when represented as a 32-bit integer.
563 This is the smallest number above 0 that can be represented in the sample format, converted to
564 a 32-bit range. E,g. if the format is 8-bit, its resolution is 0x01000000; if the format is 24-bit,
565 its resolution is 0x100.
566 */
567 static int get32BitResolution() noexcept { return (int) SampleFormat::resolution; }
568
569 /** Returns a pointer to the underlying data. */
570 const void* getRawData() const noexcept { return data.data; }
571
572 private:
573 //==============================================================================
574 SampleFormat data;
575
576 inline void advance() noexcept { this->advanceData (data); }
577
578 Pointer operator++ (int); // private to force you to use the more efficient pre-increment!
579 Pointer operator-- (int);
580 };
581
582 //==============================================================================
583 /** A base class for objects that are used to convert between two different sample formats.
584
585 The AudioData::ConverterInstance implements this base class and can be templated, so
586 you can create an instance that converts between two particular formats, and then
587 store this in the abstract base class.
588
589 @see AudioData::ConverterInstance
590 */
592 {
593 public:
594 virtual ~Converter() = default;
595
596 /** Converts a sequence of samples from the converter's source format into the dest format. */
597 virtual void convertSamples (void* destSamples, const void* sourceSamples, int numSamples) const = 0;
598
599 /** Converts a sequence of samples from the converter's source format into the dest format.
600 This method takes sub-channel indexes, which can be used with interleaved formats in order to choose a
601 particular sub-channel of the data to be used.
602 */
603 virtual void convertSamples (void* destSamples, int destSubChannel,
604 const void* sourceSamples, int sourceSubChannel, int numSamples) const = 0;
605 };
606
607 //==============================================================================
608 /**
609 A class that converts between two templated AudioData::Pointer types, and which
610 implements the AudioData::Converter interface.
611
612 This can be used as a concrete instance of the AudioData::Converter abstract class.
613
614 @see AudioData::Converter
615 */
616 template <class SourceSampleType, class DestSampleType>
618 {
619 public:
620 ConverterInstance (int numSourceChannels = 1, int numDestChannels = 1)
621 : sourceChannels (numSourceChannels), destChannels (numDestChannels)
622 {}
623
624 void convertSamples (void* dest, const void* source, int numSamples) const override
625 {
626 SourceSampleType s (source, sourceChannels);
627 DestSampleType d (dest, destChannels);
628 d.convertSamples (s, numSamples);
629 }
630
631 void convertSamples (void* dest, int destSubChannel,
632 const void* source, int sourceSubChannel, int numSamples) const override
633 {
634 jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels);
635
636 SourceSampleType s (addBytesToPointer (source, sourceSubChannel * SourceSampleType::getBytesPerSample()), sourceChannels);
637 DestSampleType d (addBytesToPointer (dest, destSubChannel * DestSampleType::getBytesPerSample()), destChannels);
638 d.convertSamples (s, numSamples);
639 }
640
641 private:
642 JUCE_DECLARE_NON_COPYABLE (ConverterInstance)
643
644 const int sourceChannels, destChannels;
645 };
646};
647
648
649
650//==============================================================================
651/**
652 A set of routines to convert buffers of 32-bit floating point data to and from
653 various integer formats.
654
655 Note that these functions are deprecated - the AudioData class provides a much more
656 flexible set of conversion classes now.
657
658 @tags{Audio}
659*/
661{
662public:
663 //==============================================================================
664 static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
665 static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
666
667 static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
668 static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
669
670 static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
671 static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
672
673 static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
674 static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
675
676 //==============================================================================
677 static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
678 static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
679
680 static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
681 static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
682
683 static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
684 static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
685
686 static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
687 static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
688
689 //==============================================================================
690 enum DataFormat
691 {
692 int16LE,
693 int16BE,
694 int24LE,
695 int24BE,
696 int32LE,
697 int32BE,
698 float32LE,
699 float32BE,
700 };
701
702 static void convertFloatToFormat (DataFormat destFormat,
703 const float* source, void* dest, int numSamples);
704
705 static void convertFormatToFloat (DataFormat sourceFormat,
706 const void* source, float* dest, int numSamples);
707
708 //==============================================================================
709 static void interleaveSamples (const float** source, float* dest,
710 int numSamples, int numChannels);
711
712 static void deinterleaveSamples (const float* source, float** dest,
713 int numSamples, int numChannels);
714
715private:
717 JUCE_DECLARE_NON_COPYABLE (AudioDataConverters)
718};
719
720} // namespace juce
721
722/** @}*/
A set of routines to convert buffers of 32-bit floating point data to and from various integer format...
A class that converts between two templated AudioData::Pointer types, and which implements the AudioD...
void convertSamples(void *dest, const void *source, int numSamples) const override
Converts a sequence of samples from the converter's source format into the dest format.
void convertSamples(void *dest, int destSubChannel, const void *source, int sourceSubChannel, int numSamples) const override
Converts a sequence of samples from the converter's source format into the dest format.
A base class for objects that are used to convert between two different sample formats.
virtual void convertSamples(void *destSamples, int destSubChannel, const void *sourceSamples, int sourceSubChannel, int numSamples) const =0
Converts a sequence of samples from the converter's source format into the dest format.
virtual void convertSamples(void *destSamples, const void *sourceSamples, int numSamples) const =0
Converts a sequence of samples from the converter's source format into the dest format.
Used as a template parameter for AudioData::Pointer.
int getNumBytesBetweenSamples() const noexcept
Returns the number of bytes between the start address of each sample.
void setAsInt32(int32 newValue) noexcept
Sets the value of the first sample as a 32-bit integer.
void clearSamples(int numSamples) const noexcept
Sets a number of samples to zero.
static int getBytesPerSample() noexcept
Returns the number of bytes in each sample (ignoring the number of interleaved channels).
const void * getRawData() const noexcept
Returns a pointer to the underlying data.
void convertSamples(OtherPointerType source, int numSamples) const noexcept
Writes a stream of samples into this pointer from another pointer.
int getNumInterleavedChannels() const noexcept
Returns the number of interleaved channels in the format.
Pointer(const Pointer &other) noexcept
Creates a copy of another pointer.
void convertSamples(Pointer source, int numSamples) const noexcept
Writes a stream of samples into this pointer from another pointer.
int32 getAsInt32() const noexcept
Returns the value of the first sample as a 32-bit integer.
void setAsFloat(float newValue) noexcept
Sets the value of the first sample as a floating point value.
Range< float > findMinAndMax(size_t numSamples) const noexcept
Scans a block of data, returning the lowest and highest levels as floats.
Pointer & operator--() noexcept
Moves the pointer back to the previous sample.
Pointer(typename Constness::VoidType *sourceData, int numInterleaved) noexcept
Creates a pointer from some raw data in the appropriate format with the specified number of interleav...
Pointer & operator++() noexcept
Moves the pointer along to the next sample.
static bool isFloatingPoint() noexcept
Returns true if the pointer is using a floating-point format.
float getAsFloat() const noexcept
Returns the value of the first sample as a floating point value.
Pointer(typename Constness::VoidType *sourceData) noexcept
Creates a non-interleaved pointer from some raw data in the appropriate format.
void findMinAndMax(size_t numSamples, float &minValue, float &maxValue) const noexcept
Scans a block of data, returning the lowest and highest levels as floats.
static int get32BitResolution() noexcept
Returns the accuracy of this format when represented as a 32-bit integer.
static bool isBigEndian() noexcept
Returns true if the format is big-endian.
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition juce_Range.h:44
JUCE_CONSTEXPR ValueType getStart() const noexcept
Returns the start of the range.
Definition juce_Range.h:84
JUCE_CONSTEXPR ValueType getEnd() const noexcept
Returns the end of the range.
Definition juce_Range.h:90
This class a container which holds all the classes pertaining to the AudioData::Pointer audio sample ...
#define JUCE_API
This macro is added to all JUCE public class declarations.