26void AudioDataConverters::convertFloatToInt16LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
28 auto maxVal = (double) 0x7fff;
29 auto intData =
static_cast<char*
> (dest);
31 if (dest != (
void*) source || destBytesPerSample <= 4)
33 for (
int i = 0; i < numSamples; ++i)
35 *
reinterpret_cast<uint16*
> (intData) =
ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
36 intData += destBytesPerSample;
41 intData += destBytesPerSample * numSamples;
43 for (
int i = numSamples; --i >= 0;)
45 intData -= destBytesPerSample;
46 *
reinterpret_cast<uint16*
> (intData) =
ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
51void AudioDataConverters::convertFloatToInt16BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
53 auto maxVal = (double) 0x7fff;
54 auto intData =
static_cast<char*
> (dest);
56 if (dest != (
void*) source || destBytesPerSample <= 4)
58 for (
int i = 0; i < numSamples; ++i)
60 *
reinterpret_cast<uint16*
> (intData) =
ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
61 intData += destBytesPerSample;
66 intData += destBytesPerSample * numSamples;
68 for (
int i = numSamples; --i >= 0;)
70 intData -= destBytesPerSample;
71 *
reinterpret_cast<uint16*
> (intData) =
ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
76void AudioDataConverters::convertFloatToInt24LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
78 auto maxVal = (double) 0x7fffff;
79 auto intData =
static_cast<char*
> (dest);
81 if (dest != (
void*) source || destBytesPerSample <= 4)
83 for (
int i = 0; i < numSamples; ++i)
86 intData += destBytesPerSample;
91 intData += destBytesPerSample * numSamples;
93 for (
int i = numSamples; --i >= 0;)
95 intData -= destBytesPerSample;
101void AudioDataConverters::convertFloatToInt24BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
103 auto maxVal = (double) 0x7fffff;
104 auto intData =
static_cast<char*
> (dest);
106 if (dest != (
void*) source || destBytesPerSample <= 4)
108 for (
int i = 0; i < numSamples; ++i)
111 intData += destBytesPerSample;
116 intData += destBytesPerSample * numSamples;
118 for (
int i = numSamples; --i >= 0;)
120 intData -= destBytesPerSample;
126void AudioDataConverters::convertFloatToInt32LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
128 auto maxVal = (double) 0x7fffffff;
129 auto intData =
static_cast<char*
> (dest);
131 if (dest != (
void*) source || destBytesPerSample <= 4)
133 for (
int i = 0; i < numSamples; ++i)
135 *
reinterpret_cast<uint32*
> (intData) =
ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
136 intData += destBytesPerSample;
141 intData += destBytesPerSample * numSamples;
143 for (
int i = numSamples; --i >= 0;)
145 intData -= destBytesPerSample;
146 *
reinterpret_cast<uint32*
> (intData) =
ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
151void AudioDataConverters::convertFloatToInt32BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
153 auto maxVal = (double) 0x7fffffff;
154 auto intData =
static_cast<char*
> (dest);
156 if (dest != (
void*) source || destBytesPerSample <= 4)
158 for (
int i = 0; i < numSamples; ++i)
161 intData += destBytesPerSample;
166 intData += destBytesPerSample * numSamples;
168 for (
int i = numSamples; --i >= 0;)
170 intData -= destBytesPerSample;
176void AudioDataConverters::convertFloatToFloat32LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
178 jassert (dest != (
void*) source || destBytesPerSample <= 4);
180 char* d =
static_cast<char*
> (dest);
182 for (
int i = 0; i < numSamples; ++i)
184 *
reinterpret_cast<float*
> (d) = source[i];
187 *
reinterpret_cast<uint32*
> (d) =
ByteOrder::swap (*
reinterpret_cast<uint32*
> (d));
190 d += destBytesPerSample;
194void AudioDataConverters::convertFloatToFloat32BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample)
196 jassert (dest != (
void*) source || destBytesPerSample <= 4);
198 auto d =
static_cast<char*
> (dest);
200 for (
int i = 0; i < numSamples; ++i)
202 *
reinterpret_cast<float*
> (d) = source[i];
204 #if JUCE_LITTLE_ENDIAN
205 *
reinterpret_cast<uint32*
> (d) =
ByteOrder::swap (*
reinterpret_cast<uint32*
> (d));
208 d += destBytesPerSample;
213void AudioDataConverters::convertInt16LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
215 const float scale = 1.0f / 0x7fff;
216 auto intData =
static_cast<const char*
> (source);
218 if (source != (
void*) dest || srcBytesPerSample >= 4)
220 for (
int i = 0; i < numSamples; ++i)
223 intData += srcBytesPerSample;
228 intData += srcBytesPerSample * numSamples;
230 for (
int i = numSamples; --i >= 0;)
232 intData -= srcBytesPerSample;
238void AudioDataConverters::convertInt16BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
240 const float scale = 1.0f / 0x7fff;
241 auto intData =
static_cast<const char*
> (source);
243 if (source != (
void*) dest || srcBytesPerSample >= 4)
245 for (
int i = 0; i < numSamples; ++i)
248 intData += srcBytesPerSample;
253 intData += srcBytesPerSample * numSamples;
255 for (
int i = numSamples; --i >= 0;)
257 intData -= srcBytesPerSample;
263void AudioDataConverters::convertInt24LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
265 const float scale = 1.0f / 0x7fffff;
266 auto intData =
static_cast<const char*
> (source);
268 if (source != (
void*) dest || srcBytesPerSample >= 4)
270 for (
int i = 0; i < numSamples; ++i)
273 intData += srcBytesPerSample;
278 intData += srcBytesPerSample * numSamples;
280 for (
int i = numSamples; --i >= 0;)
282 intData -= srcBytesPerSample;
288void AudioDataConverters::convertInt24BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
290 const float scale = 1.0f / 0x7fffff;
291 auto intData =
static_cast<const char*
> (source);
293 if (source != (
void*) dest || srcBytesPerSample >= 4)
295 for (
int i = 0; i < numSamples; ++i)
298 intData += srcBytesPerSample;
303 intData += srcBytesPerSample * numSamples;
305 for (
int i = numSamples; --i >= 0;)
307 intData -= srcBytesPerSample;
313void AudioDataConverters::convertInt32LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
315 const float scale = 1.0f / (float) 0x7fffffff;
316 auto intData =
static_cast<const char*
> (source);
318 if (source != (
void*) dest || srcBytesPerSample >= 4)
320 for (
int i = 0; i < numSamples; ++i)
323 intData += srcBytesPerSample;
328 intData += srcBytesPerSample * numSamples;
330 for (
int i = numSamples; --i >= 0;)
332 intData -= srcBytesPerSample;
338void AudioDataConverters::convertInt32BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
340 const float scale = 1.0f / (float) 0x7fffffff;
341 auto intData =
static_cast<const char*
> (source);
343 if (source != (
void*) dest || srcBytesPerSample >= 4)
345 for (
int i = 0; i < numSamples; ++i)
348 intData += srcBytesPerSample;
353 intData += srcBytesPerSample * numSamples;
355 for (
int i = numSamples; --i >= 0;)
357 intData -= srcBytesPerSample;
363void AudioDataConverters::convertFloat32LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
365 auto s =
static_cast<const char*
> (source);
367 for (
int i = 0; i < numSamples; ++i)
369 dest[i] = *
reinterpret_cast<const float*
> (s);
372 auto d =
reinterpret_cast<uint32*
> (dest + i);
376 s += srcBytesPerSample;
380void AudioDataConverters::convertFloat32BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample)
382 auto s =
static_cast<const char*
> (source);
384 for (
int i = 0; i < numSamples; ++i)
386 dest[i] = *
reinterpret_cast<const float*
> (s);
388 #if JUCE_LITTLE_ENDIAN
389 auto d =
reinterpret_cast<uint32*
> (dest + i);
393 s += srcBytesPerSample;
399void AudioDataConverters::convertFloatToFormat (DataFormat destFormat,
const float* source,
void* dest,
int numSamples)
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;
415void AudioDataConverters::convertFormatToFloat (DataFormat sourceFormat,
const void* source,
float* dest,
int numSamples)
417 switch (sourceFormat)
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;
432void AudioDataConverters::interleaveSamples (
const float** source,
float* dest,
int numSamples,
int numChannels)
434 for (
int chan = 0; chan < numChannels; ++chan)
437 auto src = source [chan];
439 for (
int j = 0; j < numSamples; ++j)
447void AudioDataConverters::deinterleaveSamples (
const float* source,
float** dest,
int numSamples,
int numChannels)
449 for (
int chan = 0; chan < numChannels; ++chan)
452 auto dst = dest [chan];
454 for (
int j = 0; j < numSamples; ++j)
456 dst [j] = source [i];
467class AudioConversionTests :
public UnitTest
471 : UnitTest (
"Audio data conversion", UnitTestCategories::audio)
474 template <
class F1,
class E1,
class F2,
class E2>
477 static void test (UnitTest& unitTest, Random& r)
479 test (unitTest,
false, r);
480 test (unitTest,
true, r);
483 static void test (UnitTest& unitTest,
bool inPlace, Random& r)
485 const int numSamples = 2048;
486 int32 original [(size_t) numSamples],
487 converted[(
size_t) numSamples],
488 reversed [(size_t) numSamples];
491 AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
492 bool clippingFailed =
false;
494 for (
int i = 0; i < numSamples / 2; ++i)
496 d.setAsFloat (r.nextFloat() * 2.2f - 1.1f);
498 if (! d.isFloatingPoint())
499 clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed;
502 d.setAsInt32 (r.nextInt());
506 unitTest.expect (! clippingFailed);
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);
515 conv.reset (
new AudioData::ConverterInstance<AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>,
516 AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst>>());
518 zeromem (reversed,
sizeof (reversed));
520 conv->convertSamples (reversed, inPlace ? reversed : converted, numSamples);
524 AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d1 (original);
525 AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d2 (reversed);
527 const int errorMargin = 2 * AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const>::get32BitResolution()
528 + AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>::get32BitResolution();
530 for (
int i = 0; i < numSamples; ++i)
532 biggestDiff = jmax (biggestDiff, std::abs (d1.getAsInt32() - d2.getAsInt32()));
537 unitTest.expect (biggestDiff <= errorMargin);
542 template <
class F1,
class E1,
class FormatType>
545 static void test (UnitTest& unitTest, Random& r)
547 Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest, r);
548 Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest, r);
552 template <
class FormatType,
class Endianness>
555 static void test (UnitTest& unitTest, Random& r)
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);
566 template <
class FormatType>
569 static void test (UnitTest& unitTest, Random& r)
571 Test2 <FormatType, AudioData::BigEndian>::test (unitTest, r);
572 Test2 <FormatType, AudioData::LittleEndian>::test (unitTest, r);
576 void runTest()
override
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);
592static AudioConversionTests audioConversionUnitTests;
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