OpenShot Library | OpenShotAudio  0.2.2
juce_AudioDataConverters.cpp
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 void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
27 {
28  auto maxVal = (double) 0x7fff;
29  auto intData = static_cast<char*> (dest);
30 
31  if (dest != (void*) source || destBytesPerSample <= 4)
32  {
33  for (int i = 0; i < numSamples; ++i)
34  {
35  *reinterpret_cast<uint16*> (intData) = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
36  intData += destBytesPerSample;
37  }
38  }
39  else
40  {
41  intData += destBytesPerSample * numSamples;
42 
43  for (int i = numSamples; --i >= 0;)
44  {
45  intData -= destBytesPerSample;
46  *reinterpret_cast<uint16*> (intData) = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
47  }
48  }
49 }
50 
51 void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
52 {
53  auto maxVal = (double) 0x7fff;
54  auto intData = static_cast<char*> (dest);
55 
56  if (dest != (void*) source || destBytesPerSample <= 4)
57  {
58  for (int i = 0; i < numSamples; ++i)
59  {
60  *reinterpret_cast<uint16*> (intData) = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
61  intData += destBytesPerSample;
62  }
63  }
64  else
65  {
66  intData += destBytesPerSample * numSamples;
67 
68  for (int i = numSamples; --i >= 0;)
69  {
70  intData -= destBytesPerSample;
71  *reinterpret_cast<uint16*> (intData) = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
72  }
73  }
74 }
75 
76 void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
77 {
78  auto maxVal = (double) 0x7fffff;
79  auto intData = static_cast<char*> (dest);
80 
81  if (dest != (void*) source || destBytesPerSample <= 4)
82  {
83  for (int i = 0; i < numSamples; ++i)
84  {
85  ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
86  intData += destBytesPerSample;
87  }
88  }
89  else
90  {
91  intData += destBytesPerSample * numSamples;
92 
93  for (int i = numSamples; --i >= 0;)
94  {
95  intData -= destBytesPerSample;
96  ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
97  }
98  }
99 }
100 
101 void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
102 {
103  auto maxVal = (double) 0x7fffff;
104  auto intData = static_cast<char*> (dest);
105 
106  if (dest != (void*) source || destBytesPerSample <= 4)
107  {
108  for (int i = 0; i < numSamples; ++i)
109  {
110  ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
111  intData += destBytesPerSample;
112  }
113  }
114  else
115  {
116  intData += destBytesPerSample * numSamples;
117 
118  for (int i = numSamples; --i >= 0;)
119  {
120  intData -= destBytesPerSample;
121  ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
122  }
123  }
124 }
125 
126 void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
127 {
128  auto maxVal = (double) 0x7fffffff;
129  auto intData = static_cast<char*> (dest);
130 
131  if (dest != (void*) source || destBytesPerSample <= 4)
132  {
133  for (int i = 0; i < numSamples; ++i)
134  {
135  *reinterpret_cast<uint32*> (intData) = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
136  intData += destBytesPerSample;
137  }
138  }
139  else
140  {
141  intData += destBytesPerSample * numSamples;
142 
143  for (int i = numSamples; --i >= 0;)
144  {
145  intData -= destBytesPerSample;
146  *reinterpret_cast<uint32*> (intData) = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
147  }
148  }
149 }
150 
151 void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
152 {
153  auto maxVal = (double) 0x7fffffff;
154  auto intData = static_cast<char*> (dest);
155 
156  if (dest != (void*) source || destBytesPerSample <= 4)
157  {
158  for (int i = 0; i < numSamples; ++i)
159  {
160  *reinterpret_cast<uint32*> (intData) = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
161  intData += destBytesPerSample;
162  }
163  }
164  else
165  {
166  intData += destBytesPerSample * numSamples;
167 
168  for (int i = numSamples; --i >= 0;)
169  {
170  intData -= destBytesPerSample;
171  *reinterpret_cast<uint32*> (intData) = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
172  }
173  }
174 }
175 
176 void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
177 {
178  jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
179 
180  char* d = static_cast<char*> (dest);
181 
182  for (int i = 0; i < numSamples; ++i)
183  {
184  *reinterpret_cast<float*> (d) = source[i];
185 
186  #if JUCE_BIG_ENDIAN
187  *reinterpret_cast<uint32*> (d) = ByteOrder::swap (*reinterpret_cast<uint32*> (d));
188  #endif
189 
190  d += destBytesPerSample;
191  }
192 }
193 
194 void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
195 {
196  jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
197 
198  auto d = static_cast<char*> (dest);
199 
200  for (int i = 0; i < numSamples; ++i)
201  {
202  *reinterpret_cast<float*> (d) = source[i];
203 
204  #if JUCE_LITTLE_ENDIAN
205  *reinterpret_cast<uint32*> (d) = ByteOrder::swap (*reinterpret_cast<uint32*> (d));
206  #endif
207 
208  d += destBytesPerSample;
209  }
210 }
211 
212 //==============================================================================
213 void AudioDataConverters::convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
214 {
215  const float scale = 1.0f / 0x7fff;
216  auto intData = static_cast<const char*> (source);
217 
218  if (source != (void*) dest || srcBytesPerSample >= 4)
219  {
220  for (int i = 0; i < numSamples; ++i)
221  {
222  dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*reinterpret_cast<const uint16*> (intData));
223  intData += srcBytesPerSample;
224  }
225  }
226  else
227  {
228  intData += srcBytesPerSample * numSamples;
229 
230  for (int i = numSamples; --i >= 0;)
231  {
232  intData -= srcBytesPerSample;
233  dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*reinterpret_cast<const uint16*> (intData));
234  }
235  }
236 }
237 
238 void AudioDataConverters::convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
239 {
240  const float scale = 1.0f / 0x7fff;
241  auto intData = static_cast<const char*> (source);
242 
243  if (source != (void*) dest || srcBytesPerSample >= 4)
244  {
245  for (int i = 0; i < numSamples; ++i)
246  {
247  dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*reinterpret_cast<const uint16*> (intData));
248  intData += srcBytesPerSample;
249  }
250  }
251  else
252  {
253  intData += srcBytesPerSample * numSamples;
254 
255  for (int i = numSamples; --i >= 0;)
256  {
257  intData -= srcBytesPerSample;
258  dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*reinterpret_cast<const uint16*> (intData));
259  }
260  }
261 }
262 
263 void AudioDataConverters::convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
264 {
265  const float scale = 1.0f / 0x7fffff;
266  auto intData = static_cast<const char*> (source);
267 
268  if (source != (void*) dest || srcBytesPerSample >= 4)
269  {
270  for (int i = 0; i < numSamples; ++i)
271  {
272  dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData);
273  intData += srcBytesPerSample;
274  }
275  }
276  else
277  {
278  intData += srcBytesPerSample * numSamples;
279 
280  for (int i = numSamples; --i >= 0;)
281  {
282  intData -= srcBytesPerSample;
283  dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData);
284  }
285  }
286 }
287 
288 void AudioDataConverters::convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
289 {
290  const float scale = 1.0f / 0x7fffff;
291  auto intData = static_cast<const char*> (source);
292 
293  if (source != (void*) dest || srcBytesPerSample >= 4)
294  {
295  for (int i = 0; i < numSamples; ++i)
296  {
297  dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData);
298  intData += srcBytesPerSample;
299  }
300  }
301  else
302  {
303  intData += srcBytesPerSample * numSamples;
304 
305  for (int i = numSamples; --i >= 0;)
306  {
307  intData -= srcBytesPerSample;
308  dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData);
309  }
310  }
311 }
312 
313 void AudioDataConverters::convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
314 {
315  const float scale = 1.0f / (float) 0x7fffffff;
316  auto intData = static_cast<const char*> (source);
317 
318  if (source != (void*) dest || srcBytesPerSample >= 4)
319  {
320  for (int i = 0; i < numSamples; ++i)
321  {
322  dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*reinterpret_cast<const uint32*> (intData));
323  intData += srcBytesPerSample;
324  }
325  }
326  else
327  {
328  intData += srcBytesPerSample * numSamples;
329 
330  for (int i = numSamples; --i >= 0;)
331  {
332  intData -= srcBytesPerSample;
333  dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*reinterpret_cast<const uint32*> (intData));
334  }
335  }
336 }
337 
338 void AudioDataConverters::convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
339 {
340  const float scale = 1.0f / (float) 0x7fffffff;
341  auto intData = static_cast<const char*> (source);
342 
343  if (source != (void*) dest || srcBytesPerSample >= 4)
344  {
345  for (int i = 0; i < numSamples; ++i)
346  {
347  dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*reinterpret_cast<const uint32*> (intData));
348  intData += srcBytesPerSample;
349  }
350  }
351  else
352  {
353  intData += srcBytesPerSample * numSamples;
354 
355  for (int i = numSamples; --i >= 0;)
356  {
357  intData -= srcBytesPerSample;
358  dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*reinterpret_cast<const uint32*> (intData));
359  }
360  }
361 }
362 
363 void AudioDataConverters::convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
364 {
365  auto s = static_cast<const char*> (source);
366 
367  for (int i = 0; i < numSamples; ++i)
368  {
369  dest[i] = *reinterpret_cast<const float*> (s);
370 
371  #if JUCE_BIG_ENDIAN
372  auto d = reinterpret_cast<uint32*> (dest + i);
373  *d = ByteOrder::swap (*d);
374  #endif
375 
376  s += srcBytesPerSample;
377  }
378 }
379 
380 void AudioDataConverters::convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
381 {
382  auto s = static_cast<const char*> (source);
383 
384  for (int i = 0; i < numSamples; ++i)
385  {
386  dest[i] = *reinterpret_cast<const float*> (s);
387 
388  #if JUCE_LITTLE_ENDIAN
389  auto d = reinterpret_cast<uint32*> (dest + i);
390  *d = ByteOrder::swap (*d);
391  #endif
392 
393  s += srcBytesPerSample;
394  }
395 }
396 
397 
398 //==============================================================================
399 void AudioDataConverters::convertFloatToFormat (DataFormat destFormat, const float* source, void* dest, int numSamples)
400 {
401  switch (destFormat)
402  {
403  case int16LE: convertFloatToInt16LE (source, dest, numSamples); break;
404  case int16BE: convertFloatToInt16BE (source, dest, numSamples); break;
405  case int24LE: convertFloatToInt24LE (source, dest, numSamples); break;
406  case int24BE: convertFloatToInt24BE (source, dest, numSamples); break;
407  case int32LE: convertFloatToInt32LE (source, dest, numSamples); break;
408  case int32BE: convertFloatToInt32BE (source, dest, numSamples); break;
409  case float32LE: convertFloatToFloat32LE (source, dest, numSamples); break;
410  case float32BE: convertFloatToFloat32BE (source, dest, numSamples); break;
411  default: jassertfalse; break;
412  }
413 }
414 
415 void AudioDataConverters::convertFormatToFloat (DataFormat sourceFormat, const void* source, float* dest, int numSamples)
416 {
417  switch (sourceFormat)
418  {
419  case int16LE: convertInt16LEToFloat (source, dest, numSamples); break;
420  case int16BE: convertInt16BEToFloat (source, dest, numSamples); break;
421  case int24LE: convertInt24LEToFloat (source, dest, numSamples); break;
422  case int24BE: convertInt24BEToFloat (source, dest, numSamples); break;
423  case int32LE: convertInt32LEToFloat (source, dest, numSamples); break;
424  case int32BE: convertInt32BEToFloat (source, dest, numSamples); break;
425  case float32LE: convertFloat32LEToFloat (source, dest, numSamples); break;
426  case float32BE: convertFloat32BEToFloat (source, dest, numSamples); break;
427  default: jassertfalse; break;
428  }
429 }
430 
431 //==============================================================================
432 void AudioDataConverters::interleaveSamples (const float** source, float* dest, int numSamples, int numChannels)
433 {
434  for (int chan = 0; chan < numChannels; ++chan)
435  {
436  auto i = chan;
437  auto src = source [chan];
438 
439  for (int j = 0; j < numSamples; ++j)
440  {
441  dest [i] = src [j];
442  i += numChannels;
443  }
444  }
445 }
446 
447 void AudioDataConverters::deinterleaveSamples (const float* source, float** dest, int numSamples, int numChannels)
448 {
449  for (int chan = 0; chan < numChannels; ++chan)
450  {
451  auto i = chan;
452  auto dst = dest [chan];
453 
454  for (int j = 0; j < numSamples; ++j)
455  {
456  dst [j] = source [i];
457  i += numChannels;
458  }
459  }
460 }
461 
462 
463 //==============================================================================
464 //==============================================================================
465 #if JUCE_UNIT_TESTS
466 
467 class AudioConversionTests : public UnitTest
468 {
469 public:
470  AudioConversionTests()
471  : UnitTest ("Audio data conversion", UnitTestCategories::audio)
472  {}
473 
474  template <class F1, class E1, class F2, class E2>
475  struct Test5
476  {
477  static void test (UnitTest& unitTest, Random& r)
478  {
479  test (unitTest, false, r);
480  test (unitTest, true, r);
481  }
482 
483  static void test (UnitTest& unitTest, bool inPlace, Random& r)
484  {
485  const int numSamples = 2048;
486  int32 original [(size_t) numSamples],
487  converted[(size_t) numSamples],
488  reversed [(size_t) numSamples];
489 
490  {
491  AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
492  bool clippingFailed = false;
493 
494  for (int i = 0; i < numSamples / 2; ++i)
495  {
496  d.setAsFloat (r.nextFloat() * 2.2f - 1.1f);
497 
498  if (! d.isFloatingPoint())
499  clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed;
500 
501  ++d;
502  d.setAsInt32 (r.nextInt());
503  ++d;
504  }
505 
506  unitTest.expect (! clippingFailed);
507  }
508 
509  // convert data from the source to dest format..
510  std::unique_ptr<AudioData::Converter> conv (new AudioData::ConverterInstance<AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const>,
511  AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::NonConst>>());
512  conv->convertSamples (inPlace ? reversed : converted, original, numSamples);
513 
514  // ..and back again..
515  conv.reset (new AudioData::ConverterInstance<AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>,
516  AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst>>());
517  if (! inPlace)
518  zeromem (reversed, sizeof (reversed));
519 
520  conv->convertSamples (reversed, inPlace ? reversed : converted, numSamples);
521 
522  {
523  int biggestDiff = 0;
524  AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d1 (original);
525  AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d2 (reversed);
526 
529 
530  for (int i = 0; i < numSamples; ++i)
531  {
532  biggestDiff = jmax (biggestDiff, std::abs (d1.getAsInt32() - d2.getAsInt32()));
533  ++d1;
534  ++d2;
535  }
536 
537  unitTest.expect (biggestDiff <= errorMargin);
538  }
539  }
540  };
541 
542  template <class F1, class E1, class FormatType>
543  struct Test3
544  {
545  static void test (UnitTest& unitTest, Random& r)
546  {
547  Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest, r);
548  Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest, r);
549  }
550  };
551 
552  template <class FormatType, class Endianness>
553  struct Test2
554  {
555  static void test (UnitTest& unitTest, Random& r)
556  {
557  Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest, r);
558  Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest, r);
559  Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest, r);
560  Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest, r);
561  Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest, r);
562  Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest, r);
563  }
564  };
565 
566  template <class FormatType>
567  struct Test1
568  {
569  static void test (UnitTest& unitTest, Random& r)
570  {
571  Test2 <FormatType, AudioData::BigEndian>::test (unitTest, r);
572  Test2 <FormatType, AudioData::LittleEndian>::test (unitTest, r);
573  }
574  };
575 
576  void runTest() override
577  {
578  auto r = getRandom();
579  beginTest ("Round-trip conversion: Int8");
580  Test1 <AudioData::Int8>::test (*this, r);
581  beginTest ("Round-trip conversion: Int16");
582  Test1 <AudioData::Int16>::test (*this, r);
583  beginTest ("Round-trip conversion: Int24");
584  Test1 <AudioData::Int24>::test (*this, r);
585  beginTest ("Round-trip conversion: Int32");
586  Test1 <AudioData::Int32>::test (*this, r);
587  beginTest ("Round-trip conversion: Float32");
588  Test1 <AudioData::Float32>::test (*this, r);
589  }
590 };
591 
592 static AudioConversionTests audioConversionUnitTests;
593 
594 #endif
595 
596 } // namespace juce
static int get32BitResolution() noexcept
Returns the accuracy of this format when represented as a 32-bit integer.
static JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
Swaps the upper and lower bytes of a 16-bit integer.
static Type swapIfLittleEndian(Type value) noexcept
Swaps the byte order of a signed or unsigned integer if the CPU is little-endian.
static void littleEndian24BitToChars(int32 value, void *destBytes) noexcept
Copies a 24-bit number to 3 little-endian bytes.
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).
static void bigEndian24BitToChars(int32 value, void *destBytes) noexcept
Copies a 24-bit number to 3 big-endian bytes.
static Type swapIfBigEndian(Type value) noexcept
Swaps the byte order of a signed or unsigned integer if the CPU is big-endian.
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).