2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
20 ==============================================================================
26 //==============================================================================
28 This class a container which holds all the classes pertaining to the AudioData::Pointer
29 audio sample format class.
31 @see AudioData::Pointer.
35 class JUCE_API AudioData
38 //==============================================================================
39 // These types can be used as the SampleFormat template parameter for the AudioData::Pointer class.
41 class Int8
; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit integer packed data format. */
42 class UInt8
; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit unsigned integer packed data format. */
43 class Int16
; /**< Used as a template parameter for AudioData::Pointer. Indicates an 16-bit integer packed data format. */
44 class Int24
; /**< Used as a template parameter for AudioData::Pointer. Indicates an 24-bit integer packed data format. */
45 class Int32
; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit integer packed data format. */
46 class Float32
; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit float data format. */
48 //==============================================================================
49 // These types can be used as the Endianness template parameter for the AudioData::Pointer class.
51 class BigEndian
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in big-endian order. */
52 class LittleEndian
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in little-endian order. */
53 class NativeEndian
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in the CPU's native endianness. */
55 //==============================================================================
56 // These types can be used as the InterleavingType template parameter for the AudioData::Pointer class.
58 class NonInterleaved
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored contiguously. */
59 class Interleaved
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are interleaved with a number of other channels. */
61 //==============================================================================
62 // These types can be used as the Constness template parameter for the AudioData::Pointer class.
64 class NonConst
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the pointer can be used for non-const data. */
65 class Const
; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples can only be used for const data.. */
68 //==============================================================================
72 template <class SampleFormatType
> static float getAsFloat (SampleFormatType
& s
) noexcept
{ return s
.getAsFloatBE(); }
73 template <class SampleFormatType
> static void setAsFloat (SampleFormatType
& s
, float newValue
) noexcept
{ s
.setAsFloatBE (newValue
); }
74 template <class SampleFormatType
> static int32
getAsInt32 (SampleFormatType
& s
) noexcept
{ return s
.getAsInt32BE(); }
75 template <class SampleFormatType
> static void setAsInt32 (SampleFormatType
& s
, int32 newValue
) noexcept
{ s
.setAsInt32BE (newValue
); }
76 template <class SourceType
, class DestType
> static void copyFrom (DestType
& dest
, SourceType
& source
) noexcept
{ dest
.copyFromBE (source
); }
77 enum { isBigEndian
= 1 };
83 template <class SampleFormatType
> static float getAsFloat (SampleFormatType
& s
) noexcept
{ return s
.getAsFloatLE(); }
84 template <class SampleFormatType
> static void setAsFloat (SampleFormatType
& s
, float newValue
) noexcept
{ s
.setAsFloatLE (newValue
); }
85 template <class SampleFormatType
> static int32
getAsInt32 (SampleFormatType
& s
) noexcept
{ return s
.getAsInt32LE(); }
86 template <class SampleFormatType
> static void setAsInt32 (SampleFormatType
& s
, int32 newValue
) noexcept
{ s
.setAsInt32LE (newValue
); }
87 template <class SourceType
, class DestType
> static void copyFrom (DestType
& dest
, SourceType
& source
) noexcept
{ dest
.copyFromLE (source
); }
88 enum { isBigEndian
= 0 };
92 class NativeEndian
: public BigEndian
{};
94 class NativeEndian
: public LittleEndian
{};
97 //==============================================================================
101 inline Int8 (void* d
) noexcept
: data (static_cast<int8
*> (d
)) {}
103 inline void advance() noexcept
{ ++data
; }
104 inline void skip (int numSamples
) noexcept
{ data
+= numSamples
; }
105 inline float getAsFloatLE() const noexcept
{ return (float) (*data
* (1.0 / (1.0 + (double) maxValue
))); }
106 inline float getAsFloatBE() const noexcept
{ return getAsFloatLE(); }
107 inline void setAsFloatLE (float newValue
) noexcept
{ *data
= (int8
) jlimit ((int) -maxValue
, (int) maxValue
, roundToInt (newValue
* (1.0 + (double) maxValue
))); }
108 inline void setAsFloatBE (float newValue
) noexcept
{ setAsFloatLE (newValue
); }
109 inline int32
getAsInt32LE() const noexcept
{ return (int) (*((uint8
*) data
) << 24); }
110 inline int32
getAsInt32BE() const noexcept
{ return getAsInt32LE(); }
111 inline void setAsInt32LE (int newValue
) noexcept
{ *data
= (int8
) (newValue
>> 24); }
112 inline void setAsInt32BE (int newValue
) noexcept
{ setAsInt32LE (newValue
); }
113 inline void clear() noexcept
{ *data
= 0; }
114 inline void clearMultiple (int num
) noexcept
{ zeromem (data
, (size_t) (num
* bytesPerSample
)) ;}
115 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsInt32LE (source
.getAsInt32()); }
116 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsInt32BE (source
.getAsInt32()); }
117 inline void copyFromSameType (Int8
& source
) noexcept
{ *data
= *source
.data
; }
120 enum { bytesPerSample
= 1, maxValue
= 0x7f, resolution
= (1 << 24), isFloat
= 0 };
126 inline UInt8 (void* d
) noexcept
: data (static_cast<uint8
*> (d
)) {}
128 inline void advance() noexcept
{ ++data
; }
129 inline void skip (int numSamples
) noexcept
{ data
+= numSamples
; }
130 inline float getAsFloatLE() const noexcept
{ return (float) ((*data
- 128) * (1.0 / (1.0 + (double) maxValue
))); }
131 inline float getAsFloatBE() const noexcept
{ return getAsFloatLE(); }
132 inline void setAsFloatLE (float newValue
) noexcept
{ *data
= (uint8
) jlimit (0, 255, 128 + roundToInt (newValue
* (1.0 + (double) maxValue
))); }
133 inline void setAsFloatBE (float newValue
) noexcept
{ setAsFloatLE (newValue
); }
134 inline int32
getAsInt32LE() const noexcept
{ return (int) (((uint8
) (*data
- 128)) << 24); }
135 inline int32
getAsInt32BE() const noexcept
{ return getAsInt32LE(); }
136 inline void setAsInt32LE (int newValue
) noexcept
{ *data
= (uint8
) (128 + (newValue
>> 24)); }
137 inline void setAsInt32BE (int newValue
) noexcept
{ setAsInt32LE (newValue
); }
138 inline void clear() noexcept
{ *data
= 128; }
139 inline void clearMultiple (int num
) noexcept
{ memset (data
, 128, (size_t) num
) ;}
140 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsInt32LE (source
.getAsInt32()); }
141 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsInt32BE (source
.getAsInt32()); }
142 inline void copyFromSameType (UInt8
& source
) noexcept
{ *data
= *source
.data
; }
145 enum { bytesPerSample
= 1, maxValue
= 0x7f, resolution
= (1 << 24), isFloat
= 0 };
151 inline Int16 (void* d
) noexcept
: data (static_cast<uint16
*> (d
)) {}
153 inline void advance() noexcept
{ ++data
; }
154 inline void skip (int numSamples
) noexcept
{ data
+= numSamples
; }
155 inline float getAsFloatLE() const noexcept
{ return (float) ((1.0 / (1.0 + (double) maxValue
)) * (int16
) ByteOrder::swapIfBigEndian (*data
)); }
156 inline float getAsFloatBE() const noexcept
{ return (float) ((1.0 / (1.0 + (double) maxValue
)) * (int16
) ByteOrder::swapIfLittleEndian (*data
)); }
157 inline void setAsFloatLE (float newValue
) noexcept
{ *data
= ByteOrder::swapIfBigEndian ((uint16
) jlimit ((int) -maxValue
, (int) maxValue
, roundToInt (newValue
* (1.0 + (double) maxValue
)))); }
158 inline void setAsFloatBE (float newValue
) noexcept
{ *data
= ByteOrder::swapIfLittleEndian ((uint16
) jlimit ((int) -maxValue
, (int) maxValue
, roundToInt (newValue
* (1.0 + (double) maxValue
)))); }
159 inline int32
getAsInt32LE() const noexcept
{ return (int32
) (ByteOrder::swapIfBigEndian ((uint16
) *data
) << 16); }
160 inline int32
getAsInt32BE() const noexcept
{ return (int32
) (ByteOrder::swapIfLittleEndian ((uint16
) *data
) << 16); }
161 inline void setAsInt32LE (int32 newValue
) noexcept
{ *data
= ByteOrder::swapIfBigEndian ((uint16
) (newValue
>> 16)); }
162 inline void setAsInt32BE (int32 newValue
) noexcept
{ *data
= ByteOrder::swapIfLittleEndian ((uint16
) (newValue
>> 16)); }
163 inline void clear() noexcept
{ *data
= 0; }
164 inline void clearMultiple (int num
) noexcept
{ zeromem (data
, (size_t) (num
* bytesPerSample
)) ;}
165 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsInt32LE (source
.getAsInt32()); }
166 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsInt32BE (source
.getAsInt32()); }
167 inline void copyFromSameType (Int16
& source
) noexcept
{ *data
= *source
.data
; }
170 enum { bytesPerSample
= 2, maxValue
= 0x7fff, resolution
= (1 << 16), isFloat
= 0 };
176 inline Int24 (void* d
) noexcept
: data (static_cast<char*> (d
)) {}
178 inline void advance() noexcept
{ data
+= 3; }
179 inline void skip (int numSamples
) noexcept
{ data
+= 3 * numSamples
; }
180 inline float getAsFloatLE() const noexcept
{ return (float) (ByteOrder::littleEndian24Bit (data
) * (1.0 / (1.0 + (double) maxValue
))); }
181 inline float getAsFloatBE() const noexcept
{ return (float) (ByteOrder::bigEndian24Bit (data
) * (1.0 / (1.0 + (double) maxValue
))); }
182 inline void setAsFloatLE (float newValue
) noexcept
{ ByteOrder::littleEndian24BitToChars (jlimit ((int) -maxValue
, (int) maxValue
, roundToInt (newValue
* (1.0 + (double) maxValue
))), data
); }
183 inline void setAsFloatBE (float newValue
) noexcept
{ ByteOrder::bigEndian24BitToChars (jlimit ((int) -maxValue
, (int) maxValue
, roundToInt (newValue
* (1.0 + (double) maxValue
))), data
); }
184 inline int32
getAsInt32LE() const noexcept
{ return (int32
) (((unsigned int) ByteOrder::littleEndian24Bit (data
)) << 8); }
185 inline int32
getAsInt32BE() const noexcept
{ return (int32
) (((unsigned int) ByteOrder::bigEndian24Bit (data
)) << 8); }
186 inline void setAsInt32LE (int32 newValue
) noexcept
{ ByteOrder::littleEndian24BitToChars (newValue
>> 8, data
); }
187 inline void setAsInt32BE (int32 newValue
) noexcept
{ ByteOrder::bigEndian24BitToChars (newValue
>> 8, data
); }
188 inline void clear() noexcept
{ data
[0] = 0; data
[1] = 0; data
[2] = 0; }
189 inline void clearMultiple (int num
) noexcept
{ zeromem (data
, (size_t) (num
* bytesPerSample
)) ;}
190 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsInt32LE (source
.getAsInt32()); }
191 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsInt32BE (source
.getAsInt32()); }
192 inline void copyFromSameType (Int24
& source
) noexcept
{ data
[0] = source
.data
[0]; data
[1] = source
.data
[1]; data
[2] = source
.data
[2]; }
195 enum { bytesPerSample
= 3, maxValue
= 0x7fffff, resolution
= (1 << 8), isFloat
= 0 };
201 inline Int32 (void* d
) noexcept
: data (static_cast<uint32
*> (d
)) {}
203 inline void advance() noexcept
{ ++data
; }
204 inline void skip (int numSamples
) noexcept
{ data
+= numSamples
; }
205 inline float getAsFloatLE() const noexcept
{ return (float) ((1.0 / (1.0 + (double) maxValue
)) * (int32
) ByteOrder::swapIfBigEndian (*data
)); }
206 inline float getAsFloatBE() const noexcept
{ return (float) ((1.0 / (1.0 + (double) maxValue
)) * (int32
) ByteOrder::swapIfLittleEndian (*data
)); }
207 inline void setAsFloatLE (float newValue
) noexcept
{ *data
= ByteOrder::swapIfBigEndian ((uint32
) (int32
) ((double) maxValue
* jlimit (-1.0, 1.0, (double) newValue
))); }
208 inline void setAsFloatBE (float newValue
) noexcept
{ *data
= ByteOrder::swapIfLittleEndian ((uint32
) (int32
) ((double) maxValue
* jlimit (-1.0, 1.0, (double) newValue
))); }
209 inline int32
getAsInt32LE() const noexcept
{ return (int32
) ByteOrder::swapIfBigEndian (*data
); }
210 inline int32
getAsInt32BE() const noexcept
{ return (int32
) ByteOrder::swapIfLittleEndian (*data
); }
211 inline void setAsInt32LE (int32 newValue
) noexcept
{ *data
= ByteOrder::swapIfBigEndian ((uint32
) newValue
); }
212 inline void setAsInt32BE (int32 newValue
) noexcept
{ *data
= ByteOrder::swapIfLittleEndian ((uint32
) newValue
); }
213 inline void clear() noexcept
{ *data
= 0; }
214 inline void clearMultiple (int num
) noexcept
{ zeromem (data
, (size_t) (num
* bytesPerSample
)) ;}
215 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsInt32LE (source
.getAsInt32()); }
216 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsInt32BE (source
.getAsInt32()); }
217 inline void copyFromSameType (Int32
& source
) noexcept
{ *data
= *source
.data
; }
220 enum { bytesPerSample
= 4, maxValue
= 0x7fffffff, resolution
= 1, isFloat
= 0 };
223 /** A 32-bit integer type, of which only the bottom 24 bits are used. */
224 class Int24in32
: public Int32
227 inline Int24in32 (void* d
) noexcept
: Int32 (d
) {}
229 inline float getAsFloatLE() const noexcept
{ return (float) ((1.0 / (1.0 + (double) maxValue
)) * (int32
) ByteOrder::swapIfBigEndian (*data
)); }
230 inline float getAsFloatBE() const noexcept
{ return (float) ((1.0 / (1.0 + (double) maxValue
)) * (int32
) ByteOrder::swapIfLittleEndian (*data
)); }
231 inline void setAsFloatLE (float newValue
) noexcept
{ *data
= ByteOrder::swapIfBigEndian ((uint32
) ((double) maxValue
* jlimit (-1.0, 1.0, (double) newValue
))); }
232 inline void setAsFloatBE (float newValue
) noexcept
{ *data
= ByteOrder::swapIfLittleEndian ((uint32
) ((double) maxValue
* jlimit (-1.0, 1.0, (double) newValue
))); }
233 inline int32
getAsInt32LE() const noexcept
{ return (int32
) ByteOrder::swapIfBigEndian (*data
) << 8; }
234 inline int32
getAsInt32BE() const noexcept
{ return (int32
) ByteOrder::swapIfLittleEndian (*data
) << 8; }
235 inline void setAsInt32LE (int32 newValue
) noexcept
{ *data
= ByteOrder::swapIfBigEndian ((uint32
) newValue
>> 8); }
236 inline void setAsInt32BE (int32 newValue
) noexcept
{ *data
= ByteOrder::swapIfLittleEndian ((uint32
) newValue
>> 8); }
237 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsInt32LE (source
.getAsInt32()); }
238 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsInt32BE (source
.getAsInt32()); }
239 inline void copyFromSameType (Int24in32
& source
) noexcept
{ *data
= *source
.data
; }
241 enum { bytesPerSample
= 4, maxValue
= 0x7fffff, resolution
= (1 << 8), isFloat
= 0 };
247 inline Float32 (void* d
) noexcept
: data (static_cast<float*> (d
)) {}
249 inline void advance() noexcept
{ ++data
; }
250 inline void skip (int numSamples
) noexcept
{ data
+= numSamples
; }
252 inline float getAsFloatBE() const noexcept
{ return *data
; }
253 inline void setAsFloatBE (float newValue
) noexcept
{ *data
= newValue
; }
254 inline float getAsFloatLE() const noexcept
{ union { uint32 asInt
; float asFloat
; } n
; n
.asInt
= ByteOrder::swap (*(uint32
*) data
); return n
.asFloat
; }
255 inline void setAsFloatLE (float newValue
) noexcept
{ union { uint32 asInt
; float asFloat
; } n
; n
.asFloat
= newValue
; *(uint32
*) data
= ByteOrder::swap (n
.asInt
); }
257 inline float getAsFloatLE() const noexcept
{ return *data
; }
258 inline void setAsFloatLE (float newValue
) noexcept
{ *data
= newValue
; }
259 inline float getAsFloatBE() const noexcept
{ union { uint32 asInt
; float asFloat
; } n
; n
.asInt
= ByteOrder::swap (*(uint32
*) data
); return n
.asFloat
; }
260 inline void setAsFloatBE (float newValue
) noexcept
{ union { uint32 asInt
; float asFloat
; } n
; n
.asFloat
= newValue
; *(uint32
*) data
= ByteOrder::swap (n
.asInt
); }
262 inline int32
getAsInt32LE() const noexcept
{ return (int32
) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatLE()) * (double) maxValue
); }
263 inline int32
getAsInt32BE() const noexcept
{ return (int32
) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatBE()) * (double) maxValue
); }
264 inline void setAsInt32LE (int32 newValue
) noexcept
{ setAsFloatLE ((float) (newValue
* (1.0 / (1.0 + (double) maxValue
)))); }
265 inline void setAsInt32BE (int32 newValue
) noexcept
{ setAsFloatBE ((float) (newValue
* (1.0 / (1.0 + (double) maxValue
)))); }
266 inline void clear() noexcept
{ *data
= 0; }
267 inline void clearMultiple (int num
) noexcept
{ zeromem (data
, (size_t) (num
* bytesPerSample
)) ;}
268 template <class SourceType
> inline void copyFromLE (SourceType
& source
) noexcept
{ setAsFloatLE (source
.getAsFloat()); }
269 template <class SourceType
> inline void copyFromBE (SourceType
& source
) noexcept
{ setAsFloatBE (source
.getAsFloat()); }
270 inline void copyFromSameType (Float32
& source
) noexcept
{ *data
= *source
.data
; }
273 enum { bytesPerSample
= 4, maxValue
= 0x7fffffff, resolution
= (1 << 8), isFloat
= 1 };
276 //==============================================================================
280 inline NonInterleaved() = default;
281 inline NonInterleaved (const NonInterleaved
&) = default;
282 inline NonInterleaved (const int) noexcept
{}
283 inline void copyFrom (const NonInterleaved
&) noexcept
{}
284 template <class SampleFormatType
> inline void advanceData (SampleFormatType
& s
) noexcept
{ s
.advance(); }
285 template <class SampleFormatType
> inline void advanceDataBy (SampleFormatType
& s
, int numSamples
) noexcept
{ s
.skip (numSamples
); }
286 template <class SampleFormatType
> inline void clear (SampleFormatType
& s
, int numSamples
) noexcept
{ s
.clearMultiple (numSamples
); }
287 template <class SampleFormatType
> static int getNumBytesBetweenSamples (const SampleFormatType
&) noexcept
{ return SampleFormatType::bytesPerSample
; }
289 enum { isInterleavedType
= 0, numInterleavedChannels
= 1 };
295 inline Interleaved() noexcept
{}
296 inline Interleaved (const Interleaved
& other
) = default;
297 inline Interleaved (const int numInterleavedChans
) noexcept
: numInterleavedChannels (numInterleavedChans
) {}
298 inline void copyFrom (const Interleaved
& other
) noexcept
{ numInterleavedChannels
= other
.numInterleavedChannels
; }
299 template <class SampleFormatType
> inline void advanceData (SampleFormatType
& s
) noexcept
{ s
.skip (numInterleavedChannels
); }
300 template <class SampleFormatType
> inline void advanceDataBy (SampleFormatType
& s
, int numSamples
) noexcept
{ s
.skip (numInterleavedChannels
* numSamples
); }
301 template <class SampleFormatType
> inline void clear (SampleFormatType
& s
, int numSamples
) noexcept
{ while (--numSamples
>= 0) { s
.clear(); s
.skip (numInterleavedChannels
); } }
302 template <class SampleFormatType
> inline int getNumBytesBetweenSamples (const SampleFormatType
&) const noexcept
{ return numInterleavedChannels
* SampleFormatType::bytesPerSample
; }
303 int numInterleavedChannels
= 1;
304 enum { isInterleavedType
= 1 };
307 //==============================================================================
311 using VoidType
= void;
312 static void* toVoidPtr (VoidType
* v
) noexcept
{ return v
; }
313 enum { isConst
= 0 };
319 using VoidType
= const void;
320 static void* toVoidPtr (VoidType
* v
) noexcept
{ return const_cast<void*> (v
); }
321 enum { isConst
= 1 };
325 //==============================================================================
327 A pointer to a block of audio data with a particular encoding.
329 This object can be used to read and write from blocks of encoded audio samples. To create one, you specify
330 the audio format as a series of template parameters, e.g.
332 // this creates a pointer for reading from a const array of 16-bit little-endian packed samples.
333 AudioData::Pointer <AudioData::Int16,
334 AudioData::LittleEndian,
335 AudioData::NonInterleaved,
336 AudioData::Const> pointer (someRawAudioData);
338 // These methods read the sample that is being pointed to
339 float firstSampleAsFloat = pointer.getAsFloat();
340 int32 firstSampleAsInt = pointer.getAsInt32();
341 ++pointer; // moves the pointer to the next sample.
342 pointer += 3; // skips the next 3 samples.
345 The convertSamples() method lets you copy a range of samples from one format to another, automatically
346 converting its format.
348 @see AudioData::Converter
350 template <typename SampleFormat
,
352 typename InterleavingType
,
354 class Pointer
: private InterleavingType
// (inherited for EBCO)
357 //==============================================================================
358 /** Creates a non-interleaved pointer from some raw data in the appropriate format.
359 This constructor is only used if you've specified the AudioData::NonInterleaved option -
360 for interleaved formats, use the constructor that also takes a number of channels.
362 Pointer (typename
Constness::VoidType
* sourceData
) noexcept
363 : data (Constness::toVoidPtr (sourceData
))
365 // If you're using interleaved data, call the other constructor! If you're using non-interleaved data,
366 // you should pass NonInterleaved as the template parameter for the interleaving type!
367 static_assert (InterleavingType::isInterleavedType
== 0, "Incorrect constructor for interleaved data");
370 /** Creates a pointer from some raw data in the appropriate format with the specified number of interleaved channels.
371 For non-interleaved data, use the other constructor.
373 Pointer (typename
Constness::VoidType
* sourceData
, int numInterleaved
) noexcept
374 : InterleavingType (numInterleaved
), data (Constness::toVoidPtr (sourceData
))
378 /** Creates a copy of another pointer. */
379 Pointer (const Pointer
& other
) noexcept
380 : InterleavingType (other
), data (other
.data
)
384 Pointer
& operator= (const Pointer
& other
) noexcept
386 InterleavingType::operator= (other
);
391 //==============================================================================
392 /** Returns the value of the first sample as a floating point value.
393 The value will be in the range -1.0 to 1.0 for integer formats. For floating point
394 formats, the value could be outside that range, although -1 to 1 is the standard range.
396 inline float getAsFloat() const noexcept
{ return Endianness::getAsFloat (data
); }
398 /** Sets the value of the first sample as a floating point value.
400 (This method can only be used if the AudioData::NonConst option was used).
401 The value should be in the range -1.0 to 1.0 - for integer formats, values outside that
402 range will be clipped. For floating point formats, any value passed in here will be
403 written directly, although -1 to 1 is the standard range.
405 inline void setAsFloat (float newValue
) noexcept
407 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
408 static_assert (Constness::isConst
== 0, "Attempt to write to a const pointer");
409 Endianness::setAsFloat (data
, newValue
);
412 /** Returns the value of the first sample as a 32-bit integer.
413 The value returned will be in the range 0x80000000 to 0x7fffffff, and shorter values will be
414 shifted to fill this range (e.g. if you're reading from 24-bit data, the values will be shifted up
415 by 8 bits when returned here). If the source data is floating point, values beyond -1.0 to 1.0 will
416 be clipped so that -1.0 maps onto -0x7fffffff and 1.0 maps to 0x7fffffff.
418 inline int32
getAsInt32() const noexcept
{ return Endianness::getAsInt32 (data
); }
420 /** Sets the value of the first sample as a 32-bit integer.
421 This will be mapped to the range of the format that is being written - see getAsInt32().
423 inline void setAsInt32 (int32 newValue
) noexcept
425 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
426 static_assert (Constness::isConst
== 0, "Attempt to write to a const pointer");
427 Endianness::setAsInt32 (data
, newValue
);
430 /** Moves the pointer along to the next sample. */
431 inline Pointer
& operator++() noexcept
{ advance(); return *this; }
433 /** Moves the pointer back to the previous sample. */
434 inline Pointer
& operator--() noexcept
{ this->advanceDataBy (data
, -1); return *this; }
436 /** Adds a number of samples to the pointer's position. */
437 Pointer
& operator+= (int samplesToJump
) noexcept
{ this->advanceDataBy (data
, samplesToJump
); return *this; }
439 /** Writes a stream of samples into this pointer from another pointer.
440 This will copy the specified number of samples, converting between formats appropriately.
442 void convertSamples (Pointer source
, int numSamples
) const noexcept
444 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
445 static_assert (Constness::isConst
== 0, "Attempt to write to a const pointer");
447 for (Pointer
dest (*this); --numSamples
>= 0;)
449 dest
.data
.copyFromSameType (source
.data
);
455 /** Writes a stream of samples into this pointer from another pointer.
456 This will copy the specified number of samples, converting between formats appropriately.
458 template <class OtherPointerType
>
459 void convertSamples (OtherPointerType source
, int numSamples
) const noexcept
461 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
462 static_assert (Constness::isConst
== 0, "Attempt to write to a const pointer");
464 Pointer
dest (*this);
466 if (source
.getRawData() != getRawData() || source
.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples())
468 while (--numSamples
>= 0)
470 Endianness::copyFrom (dest
.data
, source
);
475 else // copy backwards if we're increasing the sample width..
478 source
+= numSamples
;
480 while (--numSamples
>= 0)
481 Endianness::copyFrom ((--dest
).data
, --source
);
485 /** Sets a number of samples to zero. */
486 void clearSamples (int numSamples
) const noexcept
488 Pointer
dest (*this);
489 dest
.clear (dest
.data
, numSamples
);
492 /** Scans a block of data, returning the lowest and highest levels as floats */
493 Range
<float> findMinAndMax (size_t numSamples
) const noexcept
496 return Range
<float>();
498 Pointer
dest (*this);
500 if (isFloatingPoint())
502 float mn
= dest
.getAsFloat();
506 while (--numSamples
> 0)
508 const float v
= dest
.getAsFloat();
515 return Range
<float> (mn
, mx
);
518 int32 mn
= dest
.getAsInt32();
522 while (--numSamples
> 0)
524 const int v
= dest
.getAsInt32();
531 return Range
<float> ((float) mn
* (float) (1.0 / (1.0 + (double) Int32::maxValue
)),
532 (float) mx
* (float) (1.0 / (1.0 + (double) Int32::maxValue
)));
535 /** Scans a block of data, returning the lowest and highest levels as floats */
536 void findMinAndMax (size_t numSamples
, float& minValue
, float& maxValue
) const noexcept
538 Range
<float> r (findMinAndMax (numSamples
));
539 minValue
= r
.getStart();
540 maxValue
= r
.getEnd();
543 /** Returns true if the pointer is using a floating-point format. */
544 static bool isFloatingPoint() noexcept
{ return (bool) SampleFormat::isFloat
; }
546 /** Returns true if the format is big-endian. */
547 static bool isBigEndian() noexcept
{ return (bool) Endianness::isBigEndian
; }
549 /** Returns the number of bytes in each sample (ignoring the number of interleaved channels). */
550 static int getBytesPerSample() noexcept
{ return (int) SampleFormat::bytesPerSample
; }
552 /** Returns the number of interleaved channels in the format. */
553 int getNumInterleavedChannels() const noexcept
{ return (int) this->numInterleavedChannels
; }
555 /** Returns the number of bytes between the start address of each sample. */
556 int getNumBytesBetweenSamples() const noexcept
{ return InterleavingType::getNumBytesBetweenSamples (data
); }
558 /** Returns the accuracy of this format when represented as a 32-bit integer.
559 This is the smallest number above 0 that can be represented in the sample format, converted to
560 a 32-bit range. E,g. if the format is 8-bit, its resolution is 0x01000000; if the format is 24-bit,
561 its resolution is 0x100.
563 static int get32BitResolution() noexcept
{ return (int) SampleFormat::resolution
; }
565 /** Returns a pointer to the underlying data. */
566 const void* getRawData() const noexcept
{ return data
.data
; }
569 //==============================================================================
572 inline void advance() noexcept
{ this->advanceData (data
); }
574 Pointer
operator++ (int); // private to force you to use the more efficient pre-increment!
575 Pointer
operator-- (int);
578 //==============================================================================
579 /** A base class for objects that are used to convert between two different sample formats.
581 The AudioData::ConverterInstance implements this base class and can be templated, so
582 you can create an instance that converts between two particular formats, and then
583 store this in the abstract base class.
585 @see AudioData::ConverterInstance
590 virtual ~Converter() = default;
592 /** Converts a sequence of samples from the converter's source format into the dest format. */
593 virtual void convertSamples (void* destSamples
, const void* sourceSamples
, int numSamples
) const = 0;
595 /** Converts a sequence of samples from the converter's source format into the dest format.
596 This method takes sub-channel indexes, which can be used with interleaved formats in order to choose a
597 particular sub-channel of the data to be used.
599 virtual void convertSamples (void* destSamples
, int destSubChannel
,
600 const void* sourceSamples
, int sourceSubChannel
, int numSamples
) const = 0;
603 //==============================================================================
605 A class that converts between two templated AudioData::Pointer types, and which
606 implements the AudioData::Converter interface.
608 This can be used as a concrete instance of the AudioData::Converter abstract class.
610 @see AudioData::Converter
612 template <class SourceSampleType
, class DestSampleType
>
613 class ConverterInstance
: public Converter
616 ConverterInstance (int numSourceChannels
= 1, int numDestChannels
= 1)
617 : sourceChannels (numSourceChannels
), destChannels (numDestChannels
)
620 void convertSamples (void* dest
, const void* source
, int numSamples
) const override
622 SourceSampleType
s (source
, sourceChannels
);
623 DestSampleType
d (dest
, destChannels
);
624 d
.convertSamples (s
, numSamples
);
627 void convertSamples (void* dest
, int destSubChannel
,
628 const void* source
, int sourceSubChannel
, int numSamples
) const override
630 jassert (destSubChannel
< destChannels
&& sourceSubChannel
< sourceChannels
);
632 SourceSampleType
s (addBytesToPointer (source
, sourceSubChannel
* SourceSampleType::getBytesPerSample()), sourceChannels
);
633 DestSampleType
d (addBytesToPointer (dest
, destSubChannel
* DestSampleType::getBytesPerSample()), destChannels
);
634 d
.convertSamples (s
, numSamples
);
638 JUCE_DECLARE_NON_COPYABLE (ConverterInstance
)
640 const int sourceChannels
, destChannels
;
643 //==============================================================================
644 /** A struct that contains a SampleFormat and Endianness to be used with the source and
645 destination types when calling the interleaveSamples() and deinterleaveSamples() helpers.
647 @see interleaveSamples, deinterleaveSamples
649 template <typename DataFormatIn
, typename EndiannessIn
>
652 using DataFormat
= DataFormatIn
;
653 using Endianness
= EndiannessIn
;
657 template <bool IsInterleaved
, bool IsConst
, typename
...>
658 struct ChannelDataSubtypes
;
660 template <bool IsInterleaved
, bool IsConst
, typename DataFormat
, typename Endianness
>
661 struct ChannelDataSubtypes
<IsInterleaved
, IsConst
, DataFormat
, Endianness
>
663 using ElementType
= std::remove_pointer_t
<decltype (DataFormat::data
)>;
664 using ChannelType
= std::conditional_t
<IsConst
, const ElementType
*, ElementType
*>;
665 using DataType
= std::conditional_t
<IsInterleaved
, ChannelType
, ChannelType
*>;
666 using PointerType
= Pointer
<DataFormat
,
668 std::conditional_t
<IsInterleaved
, Interleaved
, NonInterleaved
>,
669 std::conditional_t
<IsConst
, Const
, NonConst
>>;
672 template <bool IsInterleaved
, bool IsConst
, typename DataFormat
, typename Endianness
>
673 struct ChannelDataSubtypes
<IsInterleaved
, IsConst
, Format
<DataFormat
, Endianness
>>
675 using Subtypes
= ChannelDataSubtypes
<IsInterleaved
, IsConst
, DataFormat
, Endianness
>;
676 using DataType
= typename
Subtypes::DataType
;
677 using PointerType
= typename
Subtypes::PointerType
;
680 template <bool IsInterleaved
, bool IsConst
, typename
... Format
>
683 using Subtypes
= ChannelDataSubtypes
<IsInterleaved
, IsConst
, Format
...>;
684 using DataType
= typename
Subtypes::DataType
;
685 using PointerType
= typename
Subtypes::PointerType
;
692 //==============================================================================
693 /** A sequence of interleaved samples used as the source for the deinterleaveSamples() method. */
694 template <typename
... Format
> using InterleavedSource
= ChannelData
<true, true, Format
...>;
695 /** A sequence of interleaved samples used as the destination for the interleaveSamples() method. */
696 template <typename
... Format
> using InterleavedDest
= ChannelData
<true, false, Format
...>;
697 /** A sequence of non-interleaved samples used as the source for the interleaveSamples() method. */
698 template <typename
... Format
> using NonInterleavedSource
= ChannelData
<false, true, Format
...>;
699 /** A sequence of non-interleaved samples used as the destination for the deinterleaveSamples() method. */
700 template <typename
... Format
> using NonInterleavedDest
= ChannelData
<false, false, Format
...>;
702 /** A helper function for converting a sequence of samples from a non-interleaved source
703 to an interleaved destination.
705 When calling this method you need to specify the source and destination data format and endianness
706 from the AudioData SampleFormat and Endianness types and provide the data and number of channels
707 for each. For example, to convert a floating-point stream of big endian samples to an interleaved,
708 native endian stream of 16-bit integer samples you would do the following:
711 using SourceFormat = AudioData::Format<AudioData::Float32, AudioData::BigEndian>;
712 using DestFormat = AudioData::Format<AudioData::Int16, AudioData::NativeEndian>;
714 AudioData::interleaveSamples (AudioData::NonInterleavedSource<SourceFormat> { sourceData, numSourceChannels },
715 AudioData::InterleavedDest<DestFormat> { destData, numDestChannels },
719 template <typename
... SourceFormat
, typename
... DestFormat
>
720 static void interleaveSamples (NonInterleavedSource
<SourceFormat
...> source
,
721 InterleavedDest
<DestFormat
...> dest
,
724 using SourceType
= typename
decltype (source
)::PointerType
;
725 using DestType
= typename
decltype (dest
) ::PointerType
;
727 for (int i
= 0; i
< dest
.channels
; ++i
)
729 const DestType
destType (addBytesToPointer (dest
.data
, i
* DestType::getBytesPerSample()), dest
.channels
);
731 if (i
< source
.channels
)
733 if (*source
.data
!= nullptr)
735 destType
.convertSamples (SourceType
{ *source
.data
}, numSamples
);
741 destType
.clearSamples (numSamples
);
746 /** A helper function for converting a sequence of samples from an interleaved source
747 to a non-interleaved destination.
749 When calling this method you need to specify the source and destination data format and endianness
750 from the AudioData SampleFormat and Endianness types and provide the data and number of channels
751 for each. For example, to convert a floating-point stream of big endian samples to an non-interleaved,
752 native endian stream of 16-bit integer samples you would do the following:
755 using SourceFormat = AudioData::Format<AudioData::Float32, AudioData::BigEndian>;
756 using DestFormat = AudioData::Format<AudioData::Int16, AudioData::NativeEndian>;
758 AudioData::deinterleaveSamples (AudioData::InterleavedSource<SourceFormat> { sourceData, numSourceChannels },
759 AudioData::NonInterleavedDest<DestFormat> { destData, numDestChannels },
763 template <typename
... SourceFormat
, typename
... DestFormat
>
764 static void deinterleaveSamples (InterleavedSource
<SourceFormat
...> source
,
765 NonInterleavedDest
<DestFormat
...> dest
,
768 using SourceType
= typename
decltype (source
)::PointerType
;
769 using DestType
= typename
decltype (dest
) ::PointerType
;
771 for (int i
= 0; i
< dest
.channels
; ++i
)
773 if (auto* targetChan
= dest
.data
[i
])
775 const DestType
destType (targetChan
);
777 if (i
< source
.channels
)
778 destType
.convertSamples (SourceType (addBytesToPointer (source
.data
, i
* SourceType::getBytesPerSample()), source
.channels
), numSamples
);
780 destType
.clearSamples (numSamples
);
786 //==============================================================================
789 A set of routines to convert buffers of 32-bit floating point data to and from
790 various integer formats.
792 Note that these functions are deprecated - the AudioData class provides a much more
793 flexible set of conversion classes now.
797 class [[deprecated
]] JUCE_API AudioDataConverters
800 //==============================================================================
801 static void convertFloatToInt16LE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 2);
802 static void convertFloatToInt16BE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 2);
804 static void convertFloatToInt24LE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 3);
805 static void convertFloatToInt24BE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 3);
807 static void convertFloatToInt32LE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 4);
808 static void convertFloatToInt32BE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 4);
810 static void convertFloatToFloat32LE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 4);
811 static void convertFloatToFloat32BE (const float* source
, void* dest
, int numSamples
, int destBytesPerSample
= 4);
813 //==============================================================================
814 static void convertInt16LEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 2);
815 static void convertInt16BEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 2);
817 static void convertInt24LEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 3);
818 static void convertInt24BEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 3);
820 static void convertInt32LEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 4);
821 static void convertInt32BEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 4);
823 static void convertFloat32LEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 4);
824 static void convertFloat32BEToFloat (const void* source
, float* dest
, int numSamples
, int srcBytesPerSample
= 4);
826 //==============================================================================
839 static void convertFloatToFormat (DataFormat destFormat
,
840 const float* source
, void* dest
, int numSamples
);
842 static void convertFormatToFloat (DataFormat sourceFormat
,
843 const void* source
, float* dest
, int numSamples
);
845 //==============================================================================
846 static void interleaveSamples (const float** source
, float* dest
,
847 int numSamples
, int numChannels
);
849 static void deinterleaveSamples (const float* source
, float** dest
,
850 int numSamples
, int numChannels
);
853 AudioDataConverters();