OpenShot Audio Library | OpenShotAudio  0.6.0
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 
23 namespace juce
24 {
25 
26 //==============================================================================
35 class JUCE_API AudioData
36 {
37 public:
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;
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;
55  //==============================================================================
56  // These types can be used as the InterleavingType template parameter for the AudioData::Pointer class.
57 
58  class NonInterleaved;
59  class Interleaved;
61  //==============================================================================
62  // These types can be used as the Constness template parameter for the AudioData::Pointer class.
63 
64  class NonConst;
65  class Const;
67  #ifndef DOXYGEN
68  //==============================================================================
69  class BigEndian
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  //==============================================================================
590  class Converter
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>
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 
659 private:
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 
694 public:
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
800 class [[deprecated]] JUCE_API AudioDataConverters
801 {
802 public:
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 
855 private:
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
int getNumBytesBetweenSamples() const noexcept
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
Pointer(typename Constness::VoidType *sourceData, int numInterleaved) noexcept
Range< float > findMinAndMax(size_t numSamples) const noexcept
static bool isFloatingPoint() noexcept
float getAsFloat() const noexcept
const void * getRawData() 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< false, false, Format... > NonInterleavedDest
ChannelData< true, true, Format... > InterleavedSource
ChannelData< true, false, Format... > InterleavedDest
ChannelData< false, true, Format... > NonInterleavedSource
static void deinterleaveSamples(InterleavedSource< SourceFormat... > source, NonInterleavedDest< DestFormat... > dest, int numSamples)
static Type swapIfLittleEndian(Type value) noexcept
static void littleEndian24BitToChars(int32 value, void *destBytes) noexcept
constexpr static uint16 swap(uint16 value) noexcept
static void bigEndian24BitToChars(int32 value, void *destBytes) noexcept
constexpr static int littleEndian24Bit(const void *bytes) noexcept
static Type swapIfBigEndian(Type value) noexcept
constexpr static int bigEndian24Bit(const void *bytes) noexcept
constexpr ValueType getStart() const noexcept
Definition: juce_Range.h:80
constexpr ValueType getEnd() const noexcept
Definition: juce_Range.h:86