OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_AudioDataConverters.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 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.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26//==============================================================================
35class JUCE_API AudioData
36{
37public:
38 //==============================================================================
39 // These types can be used as the SampleFormat template parameter for the AudioData::Pointer class.
40
41 class Int8;
42 class UInt8;
43 class Int16;
44 class Int24;
45 class Int32;
46 class Float32;
47
48 //==============================================================================
49 // These types can be used as the Endianness template parameter for the AudioData::Pointer class.
50
51 class BigEndian;
52 class LittleEndian;
53 class NativeEndian;
54
55 //==============================================================================
56 // These types can be used as the InterleavingType template parameter for the AudioData::Pointer class.
57
58 class NonInterleaved;
59 class Interleaved;
60
61 //==============================================================================
62 // These types can be used as the Constness template parameter for the AudioData::Pointer class.
63
64 class NonConst;
65 class Const;
66
67 #ifndef DOXYGEN
68 //==============================================================================
70 {
71 public:
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 };
78 };
79
80 class LittleEndian
81 {
82 public:
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 };
89 };
90
91 #if JUCE_BIG_ENDIAN
92 class NativeEndian : public BigEndian {};
93 #else
94 class NativeEndian : public LittleEndian {};
95 #endif
96
97 //==============================================================================
98 class Int8
99 {
100 public:
101 inline Int8 (void* d) noexcept : data (static_cast<int8*> (d)) {}
102
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; }
118
119 int8* data;
120 enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
121 };
122
123 class UInt8
124 {
125 public:
126 inline UInt8 (void* d) noexcept : data (static_cast<uint8*> (d)) {}
127
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; }
143
144 uint8* data;
145 enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
146 };
147
148 class Int16
149 {
150 public:
151 inline Int16 (void* d) noexcept : data (static_cast<uint16*> (d)) {}
152
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; }
168
169 uint16* data;
170 enum { bytesPerSample = 2, maxValue = 0x7fff, resolution = (1 << 16), isFloat = 0 };
171 };
172
173 class Int24
174 {
175 public:
176 inline Int24 (void* d) noexcept : data (static_cast<char*> (d)) {}
177
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]; }
193
194 char* data;
195 enum { bytesPerSample = 3, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
196 };
197
198 class Int32
199 {
200 public:
201 inline Int32 (void* d) noexcept : data (static_cast<uint32*> (d)) {}
202
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; }
218
219 uint32* data;
220 enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = 1, isFloat = 0 };
221 };
222
224 class Int24in32 : public Int32
225 {
226 public:
227 inline Int24in32 (void* d) noexcept : Int32 (d) {}
228
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; }
240
241 enum { bytesPerSample = 4, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
242 };
243
244 class Float32
245 {
246 public:
247 inline Float32 (void* d) noexcept : data (static_cast<float*> (d)) {}
248
249 inline void advance() noexcept { ++data; }
250 inline void skip (int numSamples) noexcept { data += numSamples; }
251 #if JUCE_BIG_ENDIAN
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); }
256 #else
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); }
261 #endif
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; }
271
272 float* data;
273 enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = (1 << 8), isFloat = 1 };
274 };
275
276 //==============================================================================
277 class NonInterleaved
278 {
279 public:
280 inline NonInterleaved() = default;
281 inline NonInterleaved (const NonInterleaved&) = default;
282 inline NonInterleaved (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; }
288
289 enum { isInterleavedType = 0, numInterleavedChannels = 1 };
290 };
291
292 class Interleaved
293 {
294 public:
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 };
305 };
306
307 //==============================================================================
308 class NonConst
309 {
310 public:
311 using VoidType = void;
312 static void* toVoidPtr (VoidType* v) noexcept { return v; }
313 enum { isConst = 0 };
314 };
315
316 class Const
317 {
318 public:
319 using VoidType = const void;
320 static void* toVoidPtr (VoidType* v) noexcept { return const_cast<void*> (v); }
321 enum { isConst = 1 };
322 };
323 #endif
324
325 //==============================================================================
350 template <typename SampleFormat,
351 typename Endianness,
352 typename InterleavingType,
353 typename Constness>
354 class Pointer : private InterleavingType // (inherited for EBCO)
355 {
356 public:
357 //==============================================================================
362 Pointer (typename Constness::VoidType* sourceData) noexcept
363 : data (Constness::toVoidPtr (sourceData))
364 {
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");
368 }
369
373 Pointer (typename Constness::VoidType* sourceData, int numInterleaved) noexcept
374 : InterleavingType (numInterleaved), data (Constness::toVoidPtr (sourceData))
375 {
376 }
377
379 Pointer (const Pointer& other) noexcept
380 : InterleavingType (other), data (other.data)
381 {
382 }
383
384 Pointer& operator= (const Pointer& other) noexcept
385 {
386 InterleavingType::operator= (other);
387 data = other.data;
388 return *this;
389 }
390
391 //==============================================================================
396 inline float getAsFloat() const noexcept { return Endianness::getAsFloat (data); }
397
405 inline void setAsFloat (float newValue) noexcept
406 {
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);
410 }
411
418 inline int32 getAsInt32() const noexcept { return Endianness::getAsInt32 (data); }
419
423 inline void setAsInt32 (int32 newValue) noexcept
424 {
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);
428 }
429
431 inline Pointer& operator++() noexcept { advance(); return *this; }
432
434 inline Pointer& operator--() noexcept { this->advanceDataBy (data, -1); return *this; }
435
437 Pointer& operator+= (int samplesToJump) noexcept { this->advanceDataBy (data, samplesToJump); return *this; }
438
440 Pointer operator+ (int samplesToJump) const { return Pointer { *this } += samplesToJump; }
441
445 void convertSamples (Pointer source, int numSamples) const noexcept
446 {
447 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
448 static_assert (Constness::isConst == 0, "Attempt to write to a const pointer");
449
450 for (Pointer dest (*this); --numSamples >= 0;)
451 {
452 dest.data.copyFromSameType (source.data);
453 dest.advance();
454 source.advance();
455 }
456 }
457
461 template <class OtherPointerType>
462 void convertSamples (OtherPointerType source, int numSamples) const noexcept
463 {
464 // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
465 static_assert (Constness::isConst == 0, "Attempt to write to a const pointer");
466
467 Pointer dest (*this);
468
469 if (source.getRawData() != getRawData() || source.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples())
470 {
471 while (--numSamples >= 0)
472 {
473 Endianness::copyFrom (dest.data, source);
474 dest.advance();
475 ++source;
476 }
477 }
478 else // copy backwards if we're increasing the sample width..
479 {
480 dest += numSamples;
481 source += numSamples;
482
483 while (--numSamples >= 0)
484 Endianness::copyFrom ((--dest).data, --source);
485 }
486 }
487
489 void clearSamples (int numSamples) const noexcept
490 {
491 Pointer dest (*this);
492 dest.clear (dest.data, numSamples);
493 }
494
496 Range<float> findMinAndMax (size_t numSamples) const noexcept
497 {
498 if (numSamples == 0)
499 return Range<float>();
500
501 Pointer dest (*this);
502
503 if (isFloatingPoint())
504 {
505 float mn = dest.getAsFloat();
506 dest.advance();
507 float mx = mn;
508
509 while (--numSamples > 0)
510 {
511 const float v = dest.getAsFloat();
512 dest.advance();
513
514 if (mx < v) mx = v;
515 if (v < mn) mn = v;
516 }
517
518 return Range<float> (mn, mx);
519 }
520
521 int32 mn = dest.getAsInt32();
522 dest.advance();
523 int32 mx = mn;
524
525 while (--numSamples > 0)
526 {
527 const int v = dest.getAsInt32();
528 dest.advance();
529
530 if (mx < v) mx = v;
531 if (v < mn) mn = v;
532 }
533
534 return Range<float> ((float) mn * (float) (1.0 / (1.0 + (double) Int32::maxValue)),
535 (float) mx * (float) (1.0 / (1.0 + (double) Int32::maxValue)));
536 }
537
539 void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept
540 {
541 Range<float> r (findMinAndMax (numSamples));
542 minValue = r.getStart();
543 maxValue = r.getEnd();
544 }
545
547 static bool isFloatingPoint() noexcept { return (bool) SampleFormat::isFloat; }
548
550 static bool isBigEndian() noexcept { return (bool) Endianness::isBigEndian; }
551
553 static int getBytesPerSample() noexcept { return (int) SampleFormat::bytesPerSample; }
554
556 int getNumInterleavedChannels() const noexcept { return (int) this->numInterleavedChannels; }
557
559 int getNumBytesBetweenSamples() const noexcept { return InterleavingType::getNumBytesBetweenSamples (data); }
560
566 static int get32BitResolution() noexcept { return (int) SampleFormat::resolution; }
567
569 const void* getRawData() const noexcept { return data.data; }
570
571 private:
572 //==============================================================================
573 SampleFormat data;
574
575 inline void advance() noexcept { this->advanceData (data); }
576
577 Pointer operator++ (int); // private to force you to use the more efficient pre-increment!
578 Pointer operator-- (int);
579 };
580
581 //==============================================================================
591 {
592 public:
593 virtual ~Converter() = default;
594
596 virtual void convertSamples (void* destSamples, const void* sourceSamples, int numSamples) const = 0;
597
602 virtual void convertSamples (void* destSamples, int destSubChannel,
603 const void* sourceSamples, int sourceSubChannel, int numSamples) const = 0;
604 };
605
606 //==============================================================================
615 template <class SourceSampleType, class DestSampleType>
616 class ConverterInstance : public Converter
617 {
618 public:
619 ConverterInstance (int numSourceChannels = 1, int numDestChannels = 1)
620 : sourceChannels (numSourceChannels), destChannels (numDestChannels)
621 {}
622
623 void convertSamples (void* dest, const void* source, int numSamples) const override
624 {
625 SourceSampleType s (source, sourceChannels);
626 DestSampleType d (dest, destChannels);
627 d.convertSamples (s, numSamples);
628 }
629
630 void convertSamples (void* dest, int destSubChannel,
631 const void* source, int sourceSubChannel, int numSamples) const override
632 {
633 jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels);
634
635 SourceSampleType s (addBytesToPointer (source, sourceSubChannel * SourceSampleType::getBytesPerSample()), sourceChannels);
636 DestSampleType d (addBytesToPointer (dest, destSubChannel * DestSampleType::getBytesPerSample()), destChannels);
637 d.convertSamples (s, numSamples);
638 }
639
640 private:
641 JUCE_DECLARE_NON_COPYABLE (ConverterInstance)
642
643 const int sourceChannels, destChannels;
644 };
645
646 //==============================================================================
652 template <typename DataFormatIn, typename EndiannessIn>
653 struct Format
654 {
655 using DataFormat = DataFormatIn;
656 using Endianness = EndiannessIn;
657 };
658
659private:
660 template <bool IsInterleaved, bool IsConst, typename...>
661 struct ChannelDataSubtypes;
662
663 template <bool IsInterleaved, bool IsConst, typename DataFormat, typename Endianness>
664 struct ChannelDataSubtypes<IsInterleaved, IsConst, DataFormat, Endianness>
665 {
666 using ElementType = std::remove_pointer_t<decltype (DataFormat::data)>;
667 using ChannelType = std::conditional_t<IsConst, const ElementType*, ElementType*>;
668 using DataType = std::conditional_t<IsInterleaved, ChannelType, ChannelType const*>;
669 using PointerType = Pointer<DataFormat,
670 Endianness,
671 std::conditional_t<IsInterleaved, Interleaved, NonInterleaved>,
672 std::conditional_t<IsConst, Const, NonConst>>;
673 };
674
675 template <bool IsInterleaved, bool IsConst, typename DataFormat, typename Endianness>
676 struct ChannelDataSubtypes<IsInterleaved, IsConst, Format<DataFormat, Endianness>>
677 {
678 using Subtypes = ChannelDataSubtypes<IsInterleaved, IsConst, DataFormat, Endianness>;
679 using DataType = typename Subtypes::DataType;
680 using PointerType = typename Subtypes::PointerType;
681 };
682
683 template <bool IsInterleaved, bool IsConst, typename... Format>
684 struct ChannelData
685 {
686 using Subtypes = ChannelDataSubtypes<IsInterleaved, IsConst, Format...>;
687 using DataType = typename Subtypes::DataType;
688 using PointerType = typename Subtypes::PointerType;
689
690 DataType data;
691 int channels;
692 };
693
694public:
695 //==============================================================================
697 template <typename... Format> using InterleavedSource = ChannelData<true, true, Format...>;
699 template <typename... Format> using InterleavedDest = ChannelData<true, false, Format...>;
701 template <typename... Format> using NonInterleavedSource = ChannelData<false, true, Format...>;
703 template <typename... Format> using NonInterleavedDest = ChannelData<false, false, Format...>;
704
722 template <typename... SourceFormat, typename... DestFormat>
725 int numSamples)
726 {
727 using SourceType = typename decltype (source)::PointerType;
728 using DestType = typename decltype (dest) ::PointerType;
729
730 for (int i = 0; i < dest.channels; ++i)
731 {
732 const DestType destType (addBytesToPointer (dest.data, i * DestType::getBytesPerSample()), dest.channels);
733
734 if (i < source.channels)
735 {
736 if (*source.data != nullptr)
737 {
738 destType.convertSamples (SourceType { *source.data }, numSamples);
739 ++source.data;
740 }
741 }
742 else
743 {
744 destType.clearSamples (numSamples);
745 }
746 }
747 }
748
766 template <typename... SourceFormat, typename... DestFormat>
769 int numSamples)
770 {
771 using SourceType = typename decltype (source)::PointerType;
772 using DestType = typename decltype (dest) ::PointerType;
773
774 for (int i = 0; i < dest.channels; ++i)
775 {
776 if (auto* targetChan = dest.data[i])
777 {
778 const DestType destType (targetChan);
779
780 if (i < source.channels)
781 destType.convertSamples (SourceType (addBytesToPointer (source.data, i * SourceType::getBytesPerSample()), source.channels), numSamples);
782 else
783 destType.clearSamples (numSamples);
784 }
785 }
786 }
787};
788
789//==============================================================================
790#ifndef DOXYGEN
800class [[deprecated]] JUCE_API AudioDataConverters
801{
802public:
803 //==============================================================================
804 static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
805 static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
806
807 static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
808 static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
809
810 static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
811 static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
812
813 static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
814 static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
815
816 //==============================================================================
817 static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
818 static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
819
820 static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
821 static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
822
823 static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
824 static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
825
826 static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
827 static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
828
829 //==============================================================================
830 enum DataFormat
831 {
832 int16LE,
833 int16BE,
834 int24LE,
835 int24BE,
836 int32LE,
837 int32BE,
838 float32LE,
839 float32BE,
840 };
841
842 static void convertFloatToFormat (DataFormat destFormat,
843 const float* source, void* dest, int numSamples);
844
845 static void convertFormatToFloat (DataFormat sourceFormat,
846 const void* source, float* dest, int numSamples);
847
848 //==============================================================================
849 static void interleaveSamples (const float** source, float* dest,
850 int numSamples, int numChannels);
851
852 static void deinterleaveSamples (const float* source, float** dest,
853 int numSamples, int numChannels);
854
855private:
856 AudioDataConverters();
857};
858#endif
859
860} // namespace juce
void convertSamples(void *dest, const void *source, int numSamples) const override
void convertSamples(void *dest, int destSubChannel, const void *source, int sourceSubChannel, int numSamples) const override
virtual void convertSamples(void *destSamples, int destSubChannel, const void *sourceSamples, int sourceSubChannel, int numSamples) const =0
virtual void convertSamples(void *destSamples, const void *sourceSamples, int numSamples) const =0
void setAsInt32(int32 newValue) noexcept
void clearSamples(int numSamples) const noexcept
static int getBytesPerSample() noexcept
void convertSamples(OtherPointerType source, int numSamples) const noexcept
int getNumInterleavedChannels() const noexcept
Pointer(const Pointer &other) noexcept
void convertSamples(Pointer source, int numSamples) const noexcept
int32 getAsInt32() const noexcept
void setAsFloat(float newValue) noexcept
Range< float > findMinAndMax(size_t numSamples) const noexcept
Pointer(typename Constness::VoidType *sourceData, int numInterleaved) noexcept
float getAsFloat() const noexcept
Pointer(typename Constness::VoidType *sourceData) noexcept
void findMinAndMax(size_t numSamples, float &minValue, float &maxValue) const noexcept
static int get32BitResolution() noexcept
static bool isBigEndian() noexcept
static void interleaveSamples(NonInterleavedSource< SourceFormat... > source, InterleavedDest< DestFormat... > dest, int numSamples)
ChannelData< true, true, Format... > InterleavedSource
ChannelData< true, false, Format... > InterleavedDest
ChannelData< false, true, Format... > NonInterleavedSource
ChannelData< false, false, Format... > NonInterleavedDest
static void deinterleaveSamples(InterleavedSource< SourceFormat... > source, NonInterleavedDest< DestFormat... > dest, int numSamples)
static Type swapIfLittleEndian(Type value) noexcept
static Type swapIfBigEndian(Type value) noexcept
constexpr ValueType getStart() const noexcept
Definition juce_Range.h:80
constexpr ValueType getEnd() const noexcept
Definition juce_Range.h:86