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