2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_StandardHeader.h"
30 #include "juce_AudioDataConverters.h"
33 //==============================================================================
34 void AudioDataConverters::convertFloatToInt16LE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
36 const double maxVal
= (double) 0x7fff;
37 char* intData
= static_cast <char*> (dest
);
39 if (dest
!= (void*) source
|| destBytesPerSample
<= 4)
41 for (int i
= 0; i
< numSamples
; ++i
)
43 *(uint16
*) intData
= ByteOrder::swapIfBigEndian ((uint16
) (short) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
44 intData
+= destBytesPerSample
;
49 intData
+= destBytesPerSample
* numSamples
;
51 for (int i
= numSamples
; --i
>= 0;)
53 intData
-= destBytesPerSample
;
54 *(uint16
*) intData
= ByteOrder::swapIfBigEndian ((uint16
) (short) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
59 void AudioDataConverters::convertFloatToInt16BE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
61 const double maxVal
= (double) 0x7fff;
62 char* intData
= static_cast <char*> (dest
);
64 if (dest
!= (void*) source
|| destBytesPerSample
<= 4)
66 for (int i
= 0; i
< numSamples
; ++i
)
68 *(uint16
*) intData
= ByteOrder::swapIfLittleEndian ((uint16
) (short) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
69 intData
+= destBytesPerSample
;
74 intData
+= destBytesPerSample
* numSamples
;
76 for (int i
= numSamples
; --i
>= 0;)
78 intData
-= destBytesPerSample
;
79 *(uint16
*) intData
= ByteOrder::swapIfLittleEndian ((uint16
) (short) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
84 void AudioDataConverters::convertFloatToInt24LE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
86 const double maxVal
= (double) 0x7fffff;
87 char* intData
= static_cast <char*> (dest
);
89 if (dest
!= (void*) source
|| destBytesPerSample
<= 4)
91 for (int i
= 0; i
< numSamples
; ++i
)
93 ByteOrder::littleEndian24BitToChars ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])), intData
);
94 intData
+= destBytesPerSample
;
99 intData
+= destBytesPerSample
* numSamples
;
101 for (int i
= numSamples
; --i
>= 0;)
103 intData
-= destBytesPerSample
;
104 ByteOrder::littleEndian24BitToChars ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])), intData
);
109 void AudioDataConverters::convertFloatToInt24BE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
111 const double maxVal
= (double) 0x7fffff;
112 char* intData
= static_cast <char*> (dest
);
114 if (dest
!= (void*) source
|| destBytesPerSample
<= 4)
116 for (int i
= 0; i
< numSamples
; ++i
)
118 ByteOrder::bigEndian24BitToChars ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])), intData
);
119 intData
+= destBytesPerSample
;
124 intData
+= destBytesPerSample
* numSamples
;
126 for (int i
= numSamples
; --i
>= 0;)
128 intData
-= destBytesPerSample
;
129 ByteOrder::bigEndian24BitToChars ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])), intData
);
134 void AudioDataConverters::convertFloatToInt32LE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
136 const double maxVal
= (double) 0x7fffffff;
137 char* intData
= static_cast <char*> (dest
);
139 if (dest
!= (void*) source
|| destBytesPerSample
<= 4)
141 for (int i
= 0; i
< numSamples
; ++i
)
143 *(uint32
*)intData
= ByteOrder::swapIfBigEndian ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
144 intData
+= destBytesPerSample
;
149 intData
+= destBytesPerSample
* numSamples
;
151 for (int i
= numSamples
; --i
>= 0;)
153 intData
-= destBytesPerSample
;
154 *(uint32
*)intData
= ByteOrder::swapIfBigEndian ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
159 void AudioDataConverters::convertFloatToInt32BE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
161 const double maxVal
= (double) 0x7fffffff;
162 char* intData
= static_cast <char*> (dest
);
164 if (dest
!= (void*) source
|| destBytesPerSample
<= 4)
166 for (int i
= 0; i
< numSamples
; ++i
)
168 *(uint32
*)intData
= ByteOrder::swapIfLittleEndian ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
169 intData
+= destBytesPerSample
;
174 intData
+= destBytesPerSample
* numSamples
;
176 for (int i
= numSamples
; --i
>= 0;)
178 intData
-= destBytesPerSample
;
179 *(uint32
*)intData
= ByteOrder::swapIfLittleEndian ((uint32
) roundToInt (jlimit (-maxVal
, maxVal
, maxVal
* source
[i
])));
184 void AudioDataConverters::convertFloatToFloat32LE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
186 jassert (dest
!= (void*) source
|| destBytesPerSample
<= 4); // This op can't be performed on in-place data!
188 char* d
= static_cast <char*> (dest
);
190 for (int i
= 0; i
< numSamples
; ++i
)
192 *(float*) d
= source
[i
];
195 *(uint32
*) d
= ByteOrder::swap (*(uint32
*) d
);
198 d
+= destBytesPerSample
;
202 void AudioDataConverters::convertFloatToFloat32BE (const float* source
, void* dest
, int numSamples
, const int destBytesPerSample
)
204 jassert (dest
!= (void*) source
|| destBytesPerSample
<= 4); // This op can't be performed on in-place data!
206 char* d
= static_cast <char*> (dest
);
208 for (int i
= 0; i
< numSamples
; ++i
)
210 *(float*) d
= source
[i
];
212 #if JUCE_LITTLE_ENDIAN
213 *(uint32
*) d
= ByteOrder::swap (*(uint32
*) d
);
216 d
+= destBytesPerSample
;
220 //==============================================================================
221 void AudioDataConverters::convertInt16LEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
223 const float scale
= 1.0f
/ 0x7fff;
224 const char* intData
= static_cast <const char*> (source
);
226 if (source
!= (void*) dest
|| srcBytesPerSample
>= 4)
228 for (int i
= 0; i
< numSamples
; ++i
)
230 dest
[i
] = scale
* (short) ByteOrder::swapIfBigEndian (*(uint16
*)intData
);
231 intData
+= srcBytesPerSample
;
236 intData
+= srcBytesPerSample
* numSamples
;
238 for (int i
= numSamples
; --i
>= 0;)
240 intData
-= srcBytesPerSample
;
241 dest
[i
] = scale
* (short) ByteOrder::swapIfBigEndian (*(uint16
*)intData
);
246 void AudioDataConverters::convertInt16BEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
248 const float scale
= 1.0f
/ 0x7fff;
249 const char* intData
= static_cast <const char*> (source
);
251 if (source
!= (void*) dest
|| srcBytesPerSample
>= 4)
253 for (int i
= 0; i
< numSamples
; ++i
)
255 dest
[i
] = scale
* (short) ByteOrder::swapIfLittleEndian (*(uint16
*)intData
);
256 intData
+= srcBytesPerSample
;
261 intData
+= srcBytesPerSample
* numSamples
;
263 for (int i
= numSamples
; --i
>= 0;)
265 intData
-= srcBytesPerSample
;
266 dest
[i
] = scale
* (short) ByteOrder::swapIfLittleEndian (*(uint16
*)intData
);
271 void AudioDataConverters::convertInt24LEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
273 const float scale
= 1.0f
/ 0x7fffff;
274 const char* intData
= static_cast <const char*> (source
);
276 if (source
!= (void*) dest
|| srcBytesPerSample
>= 4)
278 for (int i
= 0; i
< numSamples
; ++i
)
280 dest
[i
] = scale
* (short) ByteOrder::littleEndian24Bit (intData
);
281 intData
+= srcBytesPerSample
;
286 intData
+= srcBytesPerSample
* numSamples
;
288 for (int i
= numSamples
; --i
>= 0;)
290 intData
-= srcBytesPerSample
;
291 dest
[i
] = scale
* (short) ByteOrder::littleEndian24Bit (intData
);
296 void AudioDataConverters::convertInt24BEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
298 const float scale
= 1.0f
/ 0x7fffff;
299 const char* intData
= static_cast <const char*> (source
);
301 if (source
!= (void*) dest
|| srcBytesPerSample
>= 4)
303 for (int i
= 0; i
< numSamples
; ++i
)
305 dest
[i
] = scale
* (short) ByteOrder::bigEndian24Bit (intData
);
306 intData
+= srcBytesPerSample
;
311 intData
+= srcBytesPerSample
* numSamples
;
313 for (int i
= numSamples
; --i
>= 0;)
315 intData
-= srcBytesPerSample
;
316 dest
[i
] = scale
* (short) ByteOrder::bigEndian24Bit (intData
);
321 void AudioDataConverters::convertInt32LEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
323 const float scale
= 1.0f
/ 0x7fffffff;
324 const char* intData
= static_cast <const char*> (source
);
326 if (source
!= (void*) dest
|| srcBytesPerSample
>= 4)
328 for (int i
= 0; i
< numSamples
; ++i
)
330 dest
[i
] = scale
* (int) ByteOrder::swapIfBigEndian (*(uint32
*) intData
);
331 intData
+= srcBytesPerSample
;
336 intData
+= srcBytesPerSample
* numSamples
;
338 for (int i
= numSamples
; --i
>= 0;)
340 intData
-= srcBytesPerSample
;
341 dest
[i
] = scale
* (int) ByteOrder::swapIfBigEndian (*(uint32
*) intData
);
346 void AudioDataConverters::convertInt32BEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
348 const float scale
= 1.0f
/ 0x7fffffff;
349 const char* intData
= static_cast <const char*> (source
);
351 if (source
!= (void*) dest
|| srcBytesPerSample
>= 4)
353 for (int i
= 0; i
< numSamples
; ++i
)
355 dest
[i
] = scale
* (int) ByteOrder::swapIfLittleEndian (*(uint32
*) intData
);
356 intData
+= srcBytesPerSample
;
361 intData
+= srcBytesPerSample
* numSamples
;
363 for (int i
= numSamples
; --i
>= 0;)
365 intData
-= srcBytesPerSample
;
366 dest
[i
] = scale
* (int) ByteOrder::swapIfLittleEndian (*(uint32
*) intData
);
371 void AudioDataConverters::convertFloat32LEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
373 const char* s
= static_cast <const char*> (source
);
375 for (int i
= 0; i
< numSamples
; ++i
)
377 dest
[i
] = *(float*)s
;
380 uint32
* const d
= (uint32
*) (dest
+ i
);
381 *d
= ByteOrder::swap (*d
);
384 s
+= srcBytesPerSample
;
388 void AudioDataConverters::convertFloat32BEToFloat (const void* const source
, float* const dest
, int numSamples
, const int srcBytesPerSample
)
390 const char* s
= static_cast <const char*> (source
);
392 for (int i
= 0; i
< numSamples
; ++i
)
394 dest
[i
] = *(float*)s
;
396 #if JUCE_LITTLE_ENDIAN
397 uint32
* const d
= (uint32
*) (dest
+ i
);
398 *d
= ByteOrder::swap (*d
);
401 s
+= srcBytesPerSample
;
406 //==============================================================================
407 void AudioDataConverters::convertFloatToFormat (const DataFormat destFormat
,
408 const float* const source
,
410 const int numSamples
)
414 case int16LE
: convertFloatToInt16LE (source
, dest
, numSamples
); break;
415 case int16BE
: convertFloatToInt16BE (source
, dest
, numSamples
); break;
416 case int24LE
: convertFloatToInt24LE (source
, dest
, numSamples
); break;
417 case int24BE
: convertFloatToInt24BE (source
, dest
, numSamples
); break;
418 case int32LE
: convertFloatToInt32LE (source
, dest
, numSamples
); break;
419 case int32BE
: convertFloatToInt32BE (source
, dest
, numSamples
); break;
420 case float32LE
: convertFloatToFloat32LE (source
, dest
, numSamples
); break;
421 case float32BE
: convertFloatToFloat32BE (source
, dest
, numSamples
); break;
422 default: jassertfalse
; break;
426 void AudioDataConverters::convertFormatToFloat (const DataFormat sourceFormat
,
427 const void* const source
,
429 const int numSamples
)
431 switch (sourceFormat
)
433 case int16LE
: convertInt16LEToFloat (source
, dest
, numSamples
); break;
434 case int16BE
: convertInt16BEToFloat (source
, dest
, numSamples
); break;
435 case int24LE
: convertInt24LEToFloat (source
, dest
, numSamples
); break;
436 case int24BE
: convertInt24BEToFloat (source
, dest
, numSamples
); break;
437 case int32LE
: convertInt32LEToFloat (source
, dest
, numSamples
); break;
438 case int32BE
: convertInt32BEToFloat (source
, dest
, numSamples
); break;
439 case float32LE
: convertFloat32LEToFloat (source
, dest
, numSamples
); break;
440 case float32BE
: convertFloat32BEToFloat (source
, dest
, numSamples
); break;
441 default: jassertfalse
; break;
445 //==============================================================================
446 void AudioDataConverters::interleaveSamples (const float** const source
,
448 const int numSamples
,
449 const int numChannels
)
451 for (int chan
= 0; chan
< numChannels
; ++chan
)
454 const float* src
= source
[chan
];
456 for (int j
= 0; j
< numSamples
; ++j
)
464 void AudioDataConverters::deinterleaveSamples (const float* const source
,
466 const int numSamples
,
467 const int numChannels
)
469 for (int chan
= 0; chan
< numChannels
; ++chan
)
472 float* dst
= dest
[chan
];
474 for (int j
= 0; j
< numSamples
; ++j
)
476 dst
[j
] = source
[i
];
483 //==============================================================================
486 #include "../../utilities/juce_UnitTest.h"
487 #include "../../maths/juce_Random.h"
489 class AudioConversionTests
: public UnitTest
492 AudioConversionTests() : UnitTest ("Audio data conversion") {}
494 template <class F1
, class E1
, class F2
, class E2
>
497 static void test (UnitTest
& unitTest
)
499 test (unitTest
, false);
500 test (unitTest
, true);
503 static void test (UnitTest
& unitTest
, bool inPlace
)
505 const int numSamples
= 2048;
506 int32 original
[numSamples
], converted
[numSamples
], reversed
[numSamples
];
509 AudioData::Pointer
<F1
, E1
, AudioData::NonInterleaved
, AudioData::NonConst
> d (original
);
510 bool clippingFailed
= false;
512 for (int i
= 0; i
< numSamples
/ 2; ++i
)
514 d
.setAsFloat (Random::getSystemRandom().nextFloat() * 2.2f
- 1.1f
);
516 if (! d
.isFloatingPoint())
517 clippingFailed
= d
.getAsFloat() > 1.0f
|| d
.getAsFloat() < -1.0f
|| clippingFailed
;
520 d
.setAsInt32 (Random::getSystemRandom().nextInt());
524 unitTest
.expect (! clippingFailed
);
527 // convert data from the source to dest format..
528 ScopedPointer
<AudioData::Converter
> conv (new AudioData::ConverterInstance
<AudioData::Pointer
<F1
, E1
, AudioData::NonInterleaved
, AudioData::Const
>,
529 AudioData::Pointer
<F2
, E2
, AudioData::NonInterleaved
, AudioData::NonConst
> >());
530 conv
->convertSamples (inPlace
? reversed
: converted
, original
, numSamples
);
532 // ..and back again..
533 conv
= new AudioData::ConverterInstance
<AudioData::Pointer
<F2
, E2
, AudioData::NonInterleaved
, AudioData::Const
>,
534 AudioData::Pointer
<F1
, E1
, AudioData::NonInterleaved
, AudioData::NonConst
> >();
536 zeromem (reversed
, sizeof (reversed
));
538 conv
->convertSamples (reversed
, inPlace
? reversed
: converted
, numSamples
);
542 AudioData::Pointer
<F1
, E1
, AudioData::NonInterleaved
, AudioData::Const
> d1 (original
);
543 AudioData::Pointer
<F1
, E1
, AudioData::NonInterleaved
, AudioData::Const
> d2 (reversed
);
545 const int errorMargin
= 2 * AudioData::Pointer
<F1
, E1
, AudioData::NonInterleaved
, AudioData::Const
>::get32BitResolution()
546 + AudioData::Pointer
<F2
, E2
, AudioData::NonInterleaved
, AudioData::Const
>::get32BitResolution();
548 for (int i
= 0; i
< numSamples
; ++i
)
550 biggestDiff
= jmax (biggestDiff
, std::abs (d1
.getAsInt32() - d2
.getAsInt32()));
555 unitTest
.expect (biggestDiff
<= errorMargin
);
560 template <class F1
, class E1
, class FormatType
>
563 static void test (UnitTest
& unitTest
)
565 Test5
<F1
, E1
, FormatType
, AudioData::BigEndian
>::test (unitTest
);
566 Test5
<F1
, E1
, FormatType
, AudioData::LittleEndian
>::test (unitTest
);
570 template <class FormatType
, class Endianness
>
573 static void test (UnitTest
& unitTest
)
575 Test3
<FormatType
, Endianness
, AudioData::Int8
>::test (unitTest
);
576 Test3
<FormatType
, Endianness
, AudioData::UInt8
>::test (unitTest
);
577 Test3
<FormatType
, Endianness
, AudioData::Int16
>::test (unitTest
);
578 Test3
<FormatType
, Endianness
, AudioData::Int24
>::test (unitTest
);
579 Test3
<FormatType
, Endianness
, AudioData::Int32
>::test (unitTest
);
580 Test3
<FormatType
, Endianness
, AudioData::Float32
>::test (unitTest
);
584 template <class FormatType
>
587 static void test (UnitTest
& unitTest
)
589 Test2
<FormatType
, AudioData::BigEndian
>::test (unitTest
);
590 Test2
<FormatType
, AudioData::LittleEndian
>::test (unitTest
);
596 beginTest ("Round-trip conversion: Int8");
597 Test1
<AudioData::Int8
>::test (*this);
598 beginTest ("Round-trip conversion: Int16");
599 Test1
<AudioData::Int16
>::test (*this);
600 beginTest ("Round-trip conversion: Int24");
601 Test1
<AudioData::Int24
>::test (*this);
602 beginTest ("Round-trip conversion: Int32");
603 Test1
<AudioData::Int32
>::test (*this);
604 beginTest ("Round-trip conversion: Float32");
605 Test1
<AudioData::Float32
>::test (*this);
609 static AudioConversionTests audioConversionUnitTests
;