OpenShot Audio Library | OpenShotAudio  0.3.3
juce_AudioDataConverters.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
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 inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatBE(); }
73  template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatBE (newValue); }
74  template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32BE(); }
75  template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32BE (newValue); }
76  template <class SourceType, class DestType> static inline 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 inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatLE(); }
84  template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatLE (newValue); }
85  template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32LE(); }
86  template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32LE (newValue); }
87  template <class SourceType, class DestType> static inline 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 (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> inline 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 inline 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 inline 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 
442  void convertSamples (Pointer source, int numSamples) const noexcept
443  {
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");
446 
447  for (Pointer dest (*this); --numSamples >= 0;)
448  {
449  dest.data.copyFromSameType (source.data);
450  dest.advance();
451  source.advance();
452  }
453  }
454 
458  template <class OtherPointerType>
459  void convertSamples (OtherPointerType source, int numSamples) const noexcept
460  {
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");
463 
464  Pointer dest (*this);
465 
466  if (source.getRawData() != getRawData() || source.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples())
467  {
468  while (--numSamples >= 0)
469  {
470  Endianness::copyFrom (dest.data, source);
471  dest.advance();
472  ++source;
473  }
474  }
475  else // copy backwards if we're increasing the sample width..
476  {
477  dest += numSamples;
478  source += numSamples;
479 
480  while (--numSamples >= 0)
481  Endianness::copyFrom ((--dest).data, --source);
482  }
483  }
484 
486  void clearSamples (int numSamples) const noexcept
487  {
488  Pointer dest (*this);
489  dest.clear (dest.data, numSamples);
490  }
491 
493  Range<float> findMinAndMax (size_t numSamples) const noexcept
494  {
495  if (numSamples == 0)
496  return Range<float>();
497 
498  Pointer dest (*this);
499 
500  if (isFloatingPoint())
501  {
502  float mn = dest.getAsFloat();
503  dest.advance();
504  float mx = mn;
505 
506  while (--numSamples > 0)
507  {
508  const float v = dest.getAsFloat();
509  dest.advance();
510 
511  if (mx < v) mx = v;
512  if (v < mn) mn = v;
513  }
514 
515  return Range<float> (mn, mx);
516  }
517 
518  int32 mn = dest.getAsInt32();
519  dest.advance();
520  int32 mx = mn;
521 
522  while (--numSamples > 0)
523  {
524  const int v = dest.getAsInt32();
525  dest.advance();
526 
527  if (mx < v) mx = v;
528  if (v < mn) mn = v;
529  }
530 
531  return Range<float> (mn * (float) (1.0 / (1.0 + (double) Int32::maxValue)),
532  mx * (float) (1.0 / (1.0 + (double) Int32::maxValue)));
533  }
534 
536  void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept
537  {
538  Range<float> r (findMinAndMax (numSamples));
539  minValue = r.getStart();
540  maxValue = r.getEnd();
541  }
542 
544  static bool isFloatingPoint() noexcept { return (bool) SampleFormat::isFloat; }
545 
547  static bool isBigEndian() noexcept { return (bool) Endianness::isBigEndian; }
548 
550  static int getBytesPerSample() noexcept { return (int) SampleFormat::bytesPerSample; }
551 
553  int getNumInterleavedChannels() const noexcept { return (int) this->numInterleavedChannels; }
554 
556  int getNumBytesBetweenSamples() const noexcept { return InterleavingType::getNumBytesBetweenSamples (data); }
557 
563  static int get32BitResolution() noexcept { return (int) SampleFormat::resolution; }
564 
566  const void* getRawData() const noexcept { return data.data; }
567 
568  private:
569  //==============================================================================
570  SampleFormat data;
571 
572  inline void advance() noexcept { this->advanceData (data); }
573 
574  Pointer operator++ (int); // private to force you to use the more efficient pre-increment!
575  Pointer operator-- (int);
576  };
577 
578  //==============================================================================
587  class Converter
588  {
589  public:
590  virtual ~Converter() = default;
591 
593  virtual void convertSamples (void* destSamples, const void* sourceSamples, int numSamples) const = 0;
594 
599  virtual void convertSamples (void* destSamples, int destSubChannel,
600  const void* sourceSamples, int sourceSubChannel, int numSamples) const = 0;
601  };
602 
603  //==============================================================================
612  template <class SourceSampleType, class DestSampleType>
614  {
615  public:
616  ConverterInstance (int numSourceChannels = 1, int numDestChannels = 1)
617  : sourceChannels (numSourceChannels), destChannels (numDestChannels)
618  {}
619 
620  void convertSamples (void* dest, const void* source, int numSamples) const override
621  {
622  SourceSampleType s (source, sourceChannels);
623  DestSampleType d (dest, destChannels);
624  d.convertSamples (s, numSamples);
625  }
626 
627  void convertSamples (void* dest, int destSubChannel,
628  const void* source, int sourceSubChannel, int numSamples) const override
629  {
630  jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels);
631 
632  SourceSampleType s (addBytesToPointer (source, sourceSubChannel * SourceSampleType::getBytesPerSample()), sourceChannels);
633  DestSampleType d (addBytesToPointer (dest, destSubChannel * DestSampleType::getBytesPerSample()), destChannels);
634  d.convertSamples (s, numSamples);
635  }
636 
637  private:
638  JUCE_DECLARE_NON_COPYABLE (ConverterInstance)
639 
640  const int sourceChannels, destChannels;
641  };
642 };
643 
644 
645 
646 //==============================================================================
656 class JUCE_API AudioDataConverters
657 {
658 public:
659  //==============================================================================
660  static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
661  static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
662 
663  static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
664  static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
665 
666  static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
667  static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
668 
669  static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
670  static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
671 
672  //==============================================================================
673  static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
674  static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
675 
676  static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
677  static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
678 
679  static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
680  static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
681 
682  static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
683  static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
684 
685  //==============================================================================
686  enum DataFormat
687  {
688  int16LE,
689  int16BE,
690  int24LE,
691  int24BE,
692  int32LE,
693  int32BE,
694  float32LE,
695  float32BE,
696  };
697 
698  static void convertFloatToFormat (DataFormat destFormat,
699  const float* source, void* dest, int numSamples);
700 
701  static void convertFormatToFloat (DataFormat sourceFormat,
702  const void* source, float* dest, int numSamples);
703 
704  //==============================================================================
705  static void interleaveSamples (const float** source, float* dest,
706  int numSamples, int numChannels);
707 
708  static void deinterleaveSamples (const float* source, float** dest,
709  int numSamples, int numChannels);
710 
711 private:
713  JUCE_DECLARE_NON_COPYABLE (AudioDataConverters)
714 };
715 
716 } // 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 JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
static Type swapIfLittleEndian(Type value) noexcept
static void littleEndian24BitToChars(int32 value, void *destBytes) noexcept
static JUCE_CONSTEXPR int bigEndian24Bit(const void *bytes) noexcept
static void bigEndian24BitToChars(int32 value, void *destBytes) noexcept
static Type swapIfBigEndian(Type value) noexcept
static JUCE_CONSTEXPR int littleEndian24Bit(const void *bytes) noexcept
JUCE_CONSTEXPR ValueType getStart() const noexcept
Definition: juce_Range.h:80
JUCE_CONSTEXPR ValueType getEnd() const noexcept
Definition: juce_Range.h:86