Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_AudioDataConverters.cpp 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
  20. JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
  21. void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  22. {
  23. auto maxVal = (double) 0x7fff;
  24. auto intData = static_cast<char*> (dest);
  25. if (dest != (void*) source || destBytesPerSample <= 4)
  26. {
  27. for (int i = 0; i < numSamples; ++i)
  28. {
  29. *unalignedPointerCast<uint16*> (intData) = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  30. intData += destBytesPerSample;
  31. }
  32. }
  33. else
  34. {
  35. intData += destBytesPerSample * numSamples;
  36. for (int i = numSamples; --i >= 0;)
  37. {
  38. intData -= destBytesPerSample;
  39. *unalignedPointerCast<uint16*> (intData) = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  40. }
  41. }
  42. }
  43. void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  44. {
  45. auto maxVal = (double) 0x7fff;
  46. auto intData = static_cast<char*> (dest);
  47. if (dest != (void*) source || destBytesPerSample <= 4)
  48. {
  49. for (int i = 0; i < numSamples; ++i)
  50. {
  51. *unalignedPointerCast<uint16*> (intData) = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  52. intData += destBytesPerSample;
  53. }
  54. }
  55. else
  56. {
  57. intData += destBytesPerSample * numSamples;
  58. for (int i = numSamples; --i >= 0;)
  59. {
  60. intData -= destBytesPerSample;
  61. *unalignedPointerCast<uint16*> (intData) = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  62. }
  63. }
  64. }
  65. void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  66. {
  67. auto maxVal = (double) 0x7fffff;
  68. auto intData = static_cast<char*> (dest);
  69. if (dest != (void*) source || destBytesPerSample <= 4)
  70. {
  71. for (int i = 0; i < numSamples; ++i)
  72. {
  73. ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
  74. intData += destBytesPerSample;
  75. }
  76. }
  77. else
  78. {
  79. intData += destBytesPerSample * numSamples;
  80. for (int i = numSamples; --i >= 0;)
  81. {
  82. intData -= destBytesPerSample;
  83. ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
  84. }
  85. }
  86. }
  87. void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  88. {
  89. auto maxVal = (double) 0x7fffff;
  90. auto intData = static_cast<char*> (dest);
  91. if (dest != (void*) source || destBytesPerSample <= 4)
  92. {
  93. for (int i = 0; i < numSamples; ++i)
  94. {
  95. ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
  96. intData += destBytesPerSample;
  97. }
  98. }
  99. else
  100. {
  101. intData += destBytesPerSample * numSamples;
  102. for (int i = numSamples; --i >= 0;)
  103. {
  104. intData -= destBytesPerSample;
  105. ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
  106. }
  107. }
  108. }
  109. void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  110. {
  111. auto maxVal = (double) 0x7fffffff;
  112. auto intData = static_cast<char*> (dest);
  113. if (dest != (void*) source || destBytesPerSample <= 4)
  114. {
  115. for (int i = 0; i < numSamples; ++i)
  116. {
  117. *unalignedPointerCast<uint32*> (intData) = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  118. intData += destBytesPerSample;
  119. }
  120. }
  121. else
  122. {
  123. intData += destBytesPerSample * numSamples;
  124. for (int i = numSamples; --i >= 0;)
  125. {
  126. intData -= destBytesPerSample;
  127. *unalignedPointerCast<uint32*> (intData) = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  128. }
  129. }
  130. }
  131. void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  132. {
  133. auto maxVal = (double) 0x7fffffff;
  134. auto intData = static_cast<char*> (dest);
  135. if (dest != (void*) source || destBytesPerSample <= 4)
  136. {
  137. for (int i = 0; i < numSamples; ++i)
  138. {
  139. *unalignedPointerCast<uint32*> (intData) = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  140. intData += destBytesPerSample;
  141. }
  142. }
  143. else
  144. {
  145. intData += destBytesPerSample * numSamples;
  146. for (int i = numSamples; --i >= 0;)
  147. {
  148. intData -= destBytesPerSample;
  149. *unalignedPointerCast<uint32*> (intData) = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
  150. }
  151. }
  152. }
  153. void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  154. {
  155. jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
  156. char* d = static_cast<char*> (dest);
  157. for (int i = 0; i < numSamples; ++i)
  158. {
  159. *unalignedPointerCast<float*> (d) = source[i];
  160. #if JUCE_BIG_ENDIAN
  161. *unalignedPointerCast<uint32*> (d) = ByteOrder::swap (*unalignedPointerCast<uint32*> (d));
  162. #endif
  163. d += destBytesPerSample;
  164. }
  165. }
  166. void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample)
  167. {
  168. jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
  169. auto d = static_cast<char*> (dest);
  170. for (int i = 0; i < numSamples; ++i)
  171. {
  172. *unalignedPointerCast<float*> (d) = source[i];
  173. #if JUCE_LITTLE_ENDIAN
  174. *unalignedPointerCast<uint32*> (d) = ByteOrder::swap (*unalignedPointerCast<uint32*> (d));
  175. #endif
  176. d += destBytesPerSample;
  177. }
  178. }
  179. //==============================================================================
  180. void AudioDataConverters::convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  181. {
  182. const float scale = 1.0f / 0x7fff;
  183. auto intData = static_cast<const char*> (source);
  184. if (source != (void*) dest || srcBytesPerSample >= 4)
  185. {
  186. for (int i = 0; i < numSamples; ++i)
  187. {
  188. dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*unalignedPointerCast<const uint16*> (intData));
  189. intData += srcBytesPerSample;
  190. }
  191. }
  192. else
  193. {
  194. intData += srcBytesPerSample * numSamples;
  195. for (int i = numSamples; --i >= 0;)
  196. {
  197. intData -= srcBytesPerSample;
  198. dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*unalignedPointerCast<const uint16*> (intData));
  199. }
  200. }
  201. }
  202. void AudioDataConverters::convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  203. {
  204. const float scale = 1.0f / 0x7fff;
  205. auto intData = static_cast<const char*> (source);
  206. if (source != (void*) dest || srcBytesPerSample >= 4)
  207. {
  208. for (int i = 0; i < numSamples; ++i)
  209. {
  210. dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*unalignedPointerCast<const uint16*> (intData));
  211. intData += srcBytesPerSample;
  212. }
  213. }
  214. else
  215. {
  216. intData += srcBytesPerSample * numSamples;
  217. for (int i = numSamples; --i >= 0;)
  218. {
  219. intData -= srcBytesPerSample;
  220. dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*unalignedPointerCast<const uint16*> (intData));
  221. }
  222. }
  223. }
  224. void AudioDataConverters::convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  225. {
  226. const float scale = 1.0f / 0x7fffff;
  227. auto intData = static_cast<const char*> (source);
  228. if (source != (void*) dest || srcBytesPerSample >= 4)
  229. {
  230. for (int i = 0; i < numSamples; ++i)
  231. {
  232. dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData);
  233. intData += srcBytesPerSample;
  234. }
  235. }
  236. else
  237. {
  238. intData += srcBytesPerSample * numSamples;
  239. for (int i = numSamples; --i >= 0;)
  240. {
  241. intData -= srcBytesPerSample;
  242. dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData);
  243. }
  244. }
  245. }
  246. void AudioDataConverters::convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  247. {
  248. const float scale = 1.0f / 0x7fffff;
  249. auto intData = static_cast<const char*> (source);
  250. if (source != (void*) dest || srcBytesPerSample >= 4)
  251. {
  252. for (int i = 0; i < numSamples; ++i)
  253. {
  254. dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData);
  255. intData += srcBytesPerSample;
  256. }
  257. }
  258. else
  259. {
  260. intData += srcBytesPerSample * numSamples;
  261. for (int i = numSamples; --i >= 0;)
  262. {
  263. intData -= srcBytesPerSample;
  264. dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData);
  265. }
  266. }
  267. }
  268. void AudioDataConverters::convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  269. {
  270. const float scale = 1.0f / (float) 0x7fffffff;
  271. auto intData = static_cast<const char*> (source);
  272. if (source != (void*) dest || srcBytesPerSample >= 4)
  273. {
  274. for (int i = 0; i < numSamples; ++i)
  275. {
  276. dest[i] = scale * (float) ByteOrder::swapIfBigEndian (*unalignedPointerCast<const uint32*> (intData));
  277. intData += srcBytesPerSample;
  278. }
  279. }
  280. else
  281. {
  282. intData += srcBytesPerSample * numSamples;
  283. for (int i = numSamples; --i >= 0;)
  284. {
  285. intData -= srcBytesPerSample;
  286. dest[i] = scale * (float) ByteOrder::swapIfBigEndian (*unalignedPointerCast<const uint32*> (intData));
  287. }
  288. }
  289. }
  290. void AudioDataConverters::convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  291. {
  292. const float scale = 1.0f / (float) 0x7fffffff;
  293. auto intData = static_cast<const char*> (source);
  294. if (source != (void*) dest || srcBytesPerSample >= 4)
  295. {
  296. for (int i = 0; i < numSamples; ++i)
  297. {
  298. dest[i] = scale * (float) ByteOrder::swapIfLittleEndian (*unalignedPointerCast<const uint32*> (intData));
  299. intData += srcBytesPerSample;
  300. }
  301. }
  302. else
  303. {
  304. intData += srcBytesPerSample * numSamples;
  305. for (int i = numSamples; --i >= 0;)
  306. {
  307. intData -= srcBytesPerSample;
  308. dest[i] = scale * (float) ByteOrder::swapIfLittleEndian (*unalignedPointerCast<const uint32*> (intData));
  309. }
  310. }
  311. }
  312. void AudioDataConverters::convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  313. {
  314. auto s = static_cast<const char*> (source);
  315. for (int i = 0; i < numSamples; ++i)
  316. {
  317. dest[i] = *unalignedPointerCast<const float*> (s);
  318. #if JUCE_BIG_ENDIAN
  319. auto d = unalignedPointerCast<uint32*> (dest + i);
  320. *d = ByteOrder::swap (*d);
  321. #endif
  322. s += srcBytesPerSample;
  323. }
  324. }
  325. void AudioDataConverters::convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample)
  326. {
  327. auto s = static_cast<const char*> (source);
  328. for (int i = 0; i < numSamples; ++i)
  329. {
  330. dest[i] = *unalignedPointerCast<const float*> (s);
  331. #if JUCE_LITTLE_ENDIAN
  332. auto d = unalignedPointerCast<uint32*> (dest + i);
  333. *d = ByteOrder::swap (*d);
  334. #endif
  335. s += srcBytesPerSample;
  336. }
  337. }
  338. //==============================================================================
  339. void AudioDataConverters::convertFloatToFormat (DataFormat destFormat, const float* source, void* dest, int numSamples)
  340. {
  341. switch (destFormat)
  342. {
  343. case int16LE: convertFloatToInt16LE (source, dest, numSamples); break;
  344. case int16BE: convertFloatToInt16BE (source, dest, numSamples); break;
  345. case int24LE: convertFloatToInt24LE (source, dest, numSamples); break;
  346. case int24BE: convertFloatToInt24BE (source, dest, numSamples); break;
  347. case int32LE: convertFloatToInt32LE (source, dest, numSamples); break;
  348. case int32BE: convertFloatToInt32BE (source, dest, numSamples); break;
  349. case float32LE: convertFloatToFloat32LE (source, dest, numSamples); break;
  350. case float32BE: convertFloatToFloat32BE (source, dest, numSamples); break;
  351. default: jassertfalse; break;
  352. }
  353. }
  354. void AudioDataConverters::convertFormatToFloat (DataFormat sourceFormat, const void* source, float* dest, int numSamples)
  355. {
  356. switch (sourceFormat)
  357. {
  358. case int16LE: convertInt16LEToFloat (source, dest, numSamples); break;
  359. case int16BE: convertInt16BEToFloat (source, dest, numSamples); break;
  360. case int24LE: convertInt24LEToFloat (source, dest, numSamples); break;
  361. case int24BE: convertInt24BEToFloat (source, dest, numSamples); break;
  362. case int32LE: convertInt32LEToFloat (source, dest, numSamples); break;
  363. case int32BE: convertInt32BEToFloat (source, dest, numSamples); break;
  364. case float32LE: convertFloat32LEToFloat (source, dest, numSamples); break;
  365. case float32BE: convertFloat32BEToFloat (source, dest, numSamples); break;
  366. default: jassertfalse; break;
  367. }
  368. }
  369. //==============================================================================
  370. void AudioDataConverters::interleaveSamples (const float** source, float* dest, int numSamples, int numChannels)
  371. {
  372. using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>;
  373. AudioData::interleaveSamples (AudioData::NonInterleavedSource<Format> { source, numChannels },
  374. AudioData::InterleavedDest<Format> { dest, numChannels },
  375. numSamples);
  376. }
  377. void AudioDataConverters::deinterleaveSamples (const float* source, float** dest, int numSamples, int numChannels)
  378. {
  379. using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>;
  380. AudioData::deinterleaveSamples (AudioData::InterleavedSource<Format> { source, numChannels },
  381. AudioData::NonInterleavedDest<Format> { dest, numChannels },
  382. numSamples);
  383. }
  384. //==============================================================================
  385. //==============================================================================
  386. #if JUCE_UNIT_TESTS
  387. class AudioConversionTests : public UnitTest
  388. {
  389. public:
  390. AudioConversionTests()
  391. : UnitTest ("Audio data conversion", UnitTestCategories::audio)
  392. {}
  393. template <class F1, class E1, class F2, class E2>
  394. struct Test5
  395. {
  396. static void test (UnitTest& unitTest, Random& r)
  397. {
  398. test (unitTest, false, r);
  399. test (unitTest, true, r);
  400. }
  401. JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6262)
  402. static void test (UnitTest& unitTest, bool inPlace, Random& r)
  403. {
  404. const int numSamples = 2048;
  405. int32 original [(size_t) numSamples],
  406. converted[(size_t) numSamples],
  407. reversed [(size_t) numSamples];
  408. {
  409. AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
  410. bool clippingFailed = false;
  411. for (int i = 0; i < numSamples / 2; ++i)
  412. {
  413. d.setAsFloat (r.nextFloat() * 2.2f - 1.1f);
  414. if (! d.isFloatingPoint())
  415. clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed;
  416. ++d;
  417. d.setAsInt32 (r.nextInt());
  418. ++d;
  419. }
  420. unitTest.expect (! clippingFailed);
  421. }
  422. // convert data from the source to dest format..
  423. std::unique_ptr<AudioData::Converter> conv (new AudioData::ConverterInstance<AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const>,
  424. AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::NonConst>>());
  425. conv->convertSamples (inPlace ? reversed : converted, original, numSamples);
  426. // ..and back again..
  427. conv.reset (new AudioData::ConverterInstance<AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>,
  428. AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst>>());
  429. if (! inPlace)
  430. zeromem (reversed, sizeof (reversed));
  431. conv->convertSamples (reversed, inPlace ? reversed : converted, numSamples);
  432. {
  433. int biggestDiff = 0;
  434. AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d1 (original);
  435. AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d2 (reversed);
  436. const int errorMargin = 2 * AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const>::get32BitResolution()
  437. + AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>::get32BitResolution();
  438. for (int i = 0; i < numSamples; ++i)
  439. {
  440. biggestDiff = jmax (biggestDiff, std::abs (d1.getAsInt32() - d2.getAsInt32()));
  441. ++d1;
  442. ++d2;
  443. }
  444. unitTest.expect (biggestDiff <= errorMargin);
  445. }
  446. }
  447. JUCE_END_IGNORE_WARNINGS_MSVC
  448. };
  449. template <class F1, class E1, class FormatType>
  450. struct Test3
  451. {
  452. static void test (UnitTest& unitTest, Random& r)
  453. {
  454. Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest, r);
  455. Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest, r);
  456. }
  457. };
  458. template <class FormatType, class Endianness>
  459. struct Test2
  460. {
  461. static void test (UnitTest& unitTest, Random& r)
  462. {
  463. Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest, r);
  464. Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest, r);
  465. Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest, r);
  466. Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest, r);
  467. Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest, r);
  468. Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest, r);
  469. }
  470. };
  471. template <class FormatType>
  472. struct Test1
  473. {
  474. static void test (UnitTest& unitTest, Random& r)
  475. {
  476. Test2 <FormatType, AudioData::BigEndian>::test (unitTest, r);
  477. Test2 <FormatType, AudioData::LittleEndian>::test (unitTest, r);
  478. }
  479. };
  480. void runTest() override
  481. {
  482. auto r = getRandom();
  483. beginTest ("Round-trip conversion: Int8");
  484. Test1 <AudioData::Int8>::test (*this, r);
  485. beginTest ("Round-trip conversion: Int16");
  486. Test1 <AudioData::Int16>::test (*this, r);
  487. beginTest ("Round-trip conversion: Int24");
  488. Test1 <AudioData::Int24>::test (*this, r);
  489. beginTest ("Round-trip conversion: Int32");
  490. Test1 <AudioData::Int32>::test (*this, r);
  491. beginTest ("Round-trip conversion: Float32");
  492. Test1 <AudioData::Float32>::test (*this, r);
  493. using Format = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>;
  494. beginTest ("Interleaving");
  495. {
  496. constexpr auto numChannels = 4;
  497. constexpr auto numSamples = 512;
  498. AudioBuffer<float> sourceBuffer { numChannels, numSamples },
  499. destBuffer { 1, numChannels * numSamples };
  500. for (int ch = 0; ch < numChannels; ++ch)
  501. for (int i = 0; i < numSamples; ++i)
  502. sourceBuffer.setSample (ch, i, r.nextFloat());
  503. AudioData::interleaveSamples (AudioData::NonInterleavedSource<Format> { sourceBuffer.getArrayOfReadPointers(), numChannels },
  504. AudioData::InterleavedDest<Format> { destBuffer.getWritePointer (0), numChannels },
  505. numSamples);
  506. for (int ch = 0; ch < numChannels; ++ch)
  507. for (int i = 0; i < numSamples; ++i)
  508. expect (destBuffer.getSample (0, ch + (i * numChannels)) == sourceBuffer.getSample (ch, i));
  509. }
  510. beginTest ("Deinterleaving");
  511. {
  512. constexpr auto numChannels = 4;
  513. constexpr auto numSamples = 512;
  514. AudioBuffer<float> sourceBuffer { 1, numChannels * numSamples },
  515. destBuffer { numChannels, numSamples };
  516. for (int ch = 0; ch < numChannels; ++ch)
  517. for (int i = 0; i < numSamples; ++i)
  518. sourceBuffer.setSample (0, ch + (i * numChannels), r.nextFloat());
  519. AudioData::deinterleaveSamples (AudioData::InterleavedSource<Format> { sourceBuffer.getReadPointer (0), numChannels },
  520. AudioData::NonInterleavedDest<Format> { destBuffer.getArrayOfWritePointers(), numChannels },
  521. numSamples);
  522. for (int ch = 0; ch < numChannels; ++ch)
  523. for (int i = 0; i < numSamples; ++i)
  524. expect (sourceBuffer.getSample (0, ch + (i * numChannels)) == destBuffer.getSample (ch, i));
  525. }
  526. }
  527. };
  528. static AudioConversionTests audioConversionUnitTests;
  529. #endif
  530. JUCE_END_IGNORE_WARNINGS_MSVC
  531. JUCE_END_IGNORE_WARNINGS_GCC_LIKE
  532. } // namespace juce