SampleIO.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /*
  2. * SampleIO.cpp
  3. * ------------
  4. * Purpose: Central code for reading and writing samples. Create your SampleIO object and have a go at the ReadSample and WriteSample functions!
  5. * Notes : Not all combinations of possible sample format combinations are implemented, especially for WriteSample.
  6. * Using the existing generic functions, it should be quite easy to extend the code, though.
  7. * Authors: Olivier Lapicque
  8. * OpenMPT Devs
  9. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  10. */
  11. #include "stdafx.h"
  12. #include "Loaders.h"
  13. #include "SampleIO.h"
  14. #include "openmpt/soundbase/SampleDecode.hpp"
  15. #include "SampleCopy.h"
  16. #include "SampleNormalize.h"
  17. #include "ModSampleCopy.h"
  18. #include "ITCompression.h"
  19. #ifndef MODPLUG_NO_FILESAVE
  20. #include "../common/mptFileIO.h"
  21. #include "mpt/io/base.hpp"
  22. #include "mpt/io/io.hpp"
  23. #include "mpt/io/io_stdstream.hpp"
  24. #include "mpt/io_write/buffer.hpp"
  25. #endif
  26. #include "BitReader.h"
  27. OPENMPT_NAMESPACE_BEGIN
  28. // Read a sample from memory
  29. size_t SampleIO::ReadSample(ModSample &sample, FileReader &file) const
  30. {
  31. if(!file.IsValid())
  32. {
  33. return 0;
  34. }
  35. LimitMax(sample.nLength, MAX_SAMPLE_LENGTH);
  36. FileReader::off_t bytesRead = 0; // Amount of memory that has been read from file
  37. FileReader::off_t filePosition = file.GetPosition();
  38. const std::byte * sourceBuf = nullptr;
  39. FileReader::PinnedView restrictedSampleDataView;
  40. FileReader::off_t fileSize = 0;
  41. if(UsesFileReaderForDecoding())
  42. {
  43. sourceBuf = nullptr;
  44. fileSize = file.BytesLeft();
  45. } else if(!IsVariableLengthEncoded())
  46. {
  47. restrictedSampleDataView = file.GetPinnedView(CalculateEncodedSize(sample.nLength));
  48. sourceBuf = restrictedSampleDataView.data();
  49. fileSize = restrictedSampleDataView.size();
  50. if(sourceBuf == nullptr)
  51. return 0;
  52. } else
  53. {
  54. MPT_ASSERT_NOTREACHED();
  55. }
  56. if(!IsVariableLengthEncoded() && sample.nLength > 0x40000)
  57. {
  58. // Limit sample length to available bytes in file to avoid excessive memory allocation.
  59. // However, for ProTracker MODs we need to support samples exceeding the end of file
  60. // (see the comment about MOD.shorttune2 in Load_mod.cpp), so as a semi-arbitrary threshold,
  61. // we do not apply this limit to samples shorter than 256K.
  62. size_t maxLength = fileSize - std::min(GetEncodedHeaderSize(), fileSize);
  63. uint8 bps = GetEncodedBitsPerSample();
  64. if(bps % 8u != 0)
  65. {
  66. MPT_ASSERT(GetEncoding() == ADPCM && bps == 4);
  67. if(Util::MaxValueOfType(maxLength) / 2u >= maxLength)
  68. maxLength *= 2;
  69. else
  70. maxLength = Util::MaxValueOfType(maxLength);
  71. } else
  72. {
  73. size_t encodedBytesPerSample = GetNumChannels() * GetEncodedBitsPerSample() / 8u;
  74. // Check if we can round up without overflowing
  75. if(Util::MaxValueOfType(maxLength) - maxLength >= (encodedBytesPerSample - 1u))
  76. maxLength += encodedBytesPerSample - 1u;
  77. else
  78. maxLength = Util::MaxValueOfType(maxLength);
  79. maxLength /= encodedBytesPerSample;
  80. }
  81. LimitMax(sample.nLength, mpt::saturate_cast<SmpLength>(maxLength));
  82. } else if(GetEncoding() == IT214 || GetEncoding() == IT215 || GetEncoding() == MDL || GetEncoding() == DMF)
  83. {
  84. // In the best case, IT compression represents each sample point as a single bit.
  85. // In practice, there is of course the two-byte header per compressed block and the initial bit width change.
  86. // As a result, if we have a file length of n, we know that the sample can be at most n*8 sample points long.
  87. // For DMF, there are at least two bits per sample, and for MDL at least 5 (so both are worse than IT).
  88. size_t maxLength = fileSize;
  89. uint8 maxSamplesPerByte = 8 / GetNumChannels();
  90. if(Util::MaxValueOfType(maxLength) / maxSamplesPerByte >= maxLength)
  91. maxLength *= maxSamplesPerByte;
  92. else
  93. maxLength = Util::MaxValueOfType(maxLength);
  94. LimitMax(sample.nLength, mpt::saturate_cast<SmpLength>(maxLength));
  95. } else if(GetEncoding() == AMS)
  96. {
  97. if(fileSize <= 9)
  98. return 0;
  99. file.Skip(4); // Target sample size (we already know this)
  100. SmpLength maxLength = std::min(file.ReadUint32LE(), mpt::saturate_cast<uint32>(fileSize));
  101. file.SkipBack(8);
  102. // In the best case, every byte triplet can decode to 255 bytes, which is a ratio of exactly 1:85
  103. if(Util::MaxValueOfType(maxLength) / 85 >= maxLength)
  104. maxLength *= 85;
  105. else
  106. maxLength = Util::MaxValueOfType(maxLength);
  107. LimitMax(sample.nLength, maxLength / (m_bitdepth / 8u));
  108. }
  109. if(sample.nLength < 1)
  110. {
  111. return 0;
  112. }
  113. sample.uFlags.set(CHN_16BIT, GetBitDepth() >= 16);
  114. sample.uFlags.set(CHN_STEREO, GetChannelFormat() != mono);
  115. size_t sampleSize = sample.AllocateSample(); // Target sample size in bytes
  116. if(sampleSize == 0)
  117. {
  118. sample.nLength = 0;
  119. return 0;
  120. }
  121. MPT_ASSERT(sampleSize >= sample.GetSampleSizeInBytes());
  122. //////////////////////////////////////////////////////
  123. // Compressed samples
  124. if(*this == SampleIO(_8bit, mono, littleEndian, ADPCM))
  125. {
  126. // 4-Bit ADPCM data
  127. int8 compressionTable[16]; // ADPCM Compression LUT
  128. if(file.ReadArray(compressionTable))
  129. {
  130. size_t readLength = (sample.nLength + 1) / 2;
  131. LimitMax(readLength, file.BytesLeft());
  132. const uint8 *inBuf = mpt::byte_cast<const uint8*>(sourceBuf) + sizeof(compressionTable);
  133. int8 *outBuf = sample.sample8();
  134. int8 delta = 0;
  135. for(size_t i = readLength; i != 0; i--)
  136. {
  137. delta += compressionTable[*inBuf & 0x0F];
  138. *(outBuf++) = delta;
  139. delta += compressionTable[(*inBuf >> 4) & 0x0F];
  140. *(outBuf++) = delta;
  141. inBuf++;
  142. }
  143. bytesRead = sizeof(compressionTable) + readLength;
  144. }
  145. } else if(GetEncoding() == IT214 || GetEncoding() == IT215)
  146. {
  147. // IT 2.14 / 2.15 compressed samples
  148. ITDecompression(file, sample, GetEncoding() == IT215);
  149. bytesRead = file.GetPosition() - filePosition;
  150. } else if(GetEncoding() == AMS && GetChannelFormat() == mono)
  151. {
  152. // AMS compressed samples
  153. file.Skip(4); // Target sample size (we already know this)
  154. uint32 sourceSize = file.ReadUint32LE();
  155. int8 packCharacter = file.ReadUint8();
  156. bytesRead += 9;
  157. FileReader::PinnedView packedDataView = file.ReadPinnedView(sourceSize);
  158. LimitMax(sourceSize, mpt::saturate_cast<uint32>(packedDataView.size()));
  159. bytesRead += sourceSize;
  160. AMSUnpack(reinterpret_cast<const int8 *>(packedDataView.data()), packedDataView.size(), sample.samplev(), sample.GetSampleSizeInBytes(), packCharacter);
  161. if(sample.uFlags[CHN_16BIT] && !mpt::endian_is_little())
  162. {
  163. auto p = sample.sample16();
  164. for(SmpLength length = sample.nLength; length != 0; length--, p++)
  165. {
  166. *p = mpt::bit_cast<int16le>(*p);
  167. }
  168. }
  169. } else if(GetEncoding() == PTM8Dto16 && GetChannelFormat() == mono && GetBitDepth() == 16)
  170. {
  171. // PTM 8-Bit delta to 16-Bit sample
  172. bytesRead = CopyMonoSample<SC::DecodeInt16Delta8>(sample, sourceBuf, fileSize);
  173. } else if(GetEncoding() == MDL && GetChannelFormat() == mono && GetBitDepth() <= 16)
  174. {
  175. // Huffman MDL compressed samples
  176. if(file.CanRead(8) && (fileSize = file.ReadUint32LE()) >= 4)
  177. {
  178. BitReader chunk = file.ReadChunk(fileSize);
  179. bytesRead = chunk.GetLength() + 4;
  180. uint8 dlt = 0, lowbyte = 0;
  181. const bool is16bit = GetBitDepth() == 16;
  182. try
  183. {
  184. for(SmpLength j = 0; j < sample.nLength; j++)
  185. {
  186. uint8 hibyte;
  187. if(is16bit)
  188. {
  189. lowbyte = static_cast<uint8>(chunk.ReadBits(8));
  190. }
  191. bool sign = chunk.ReadBits(1) != 0;
  192. if(chunk.ReadBits(1))
  193. {
  194. hibyte = static_cast<uint8>(chunk.ReadBits(3));
  195. } else
  196. {
  197. hibyte = 8;
  198. while(!chunk.ReadBits(1))
  199. {
  200. hibyte += 0x10;
  201. }
  202. hibyte += static_cast<uint8>(chunk.ReadBits(4));
  203. }
  204. if(sign)
  205. {
  206. hibyte = ~hibyte;
  207. }
  208. dlt += hibyte;
  209. if(!is16bit)
  210. {
  211. sample.sample8()[j] = dlt;
  212. } else
  213. {
  214. sample.sample16()[j] = lowbyte | (dlt << 8);
  215. }
  216. }
  217. } catch(const BitReader::eof &)
  218. {
  219. // Data is not sufficient to decode the whole sample
  220. //AddToLog(LogWarning, "Truncated MDL sample block");
  221. }
  222. }
  223. } else if(GetEncoding() == DMF && GetChannelFormat() == mono && GetBitDepth() <= 16)
  224. {
  225. // DMF Huffman compression
  226. if(fileSize > 4)
  227. {
  228. bytesRead = DMFUnpack(file, mpt::byte_cast<uint8 *>(sample.sampleb()), sample.GetSampleSizeInBytes());
  229. }
  230. } else if((GetEncoding() == uLaw || GetEncoding() == aLaw) && GetBitDepth() == 16 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved))
  231. {
  232. SmpLength readLength = sample.nLength * GetNumChannels();
  233. LimitMax(readLength, mpt::saturate_cast<SmpLength>(fileSize));
  234. bytesRead = readLength;
  235. const std::byte *inBuf = sourceBuf;
  236. int16 *outBuf = sample.sample16();
  237. if(GetEncoding() == uLaw)
  238. {
  239. SC::DecodeInt16uLaw conv;
  240. while(readLength--)
  241. {
  242. *(outBuf++) = conv(inBuf++);
  243. }
  244. } else
  245. {
  246. SC::DecodeInt16ALaw conv;
  247. while(readLength--)
  248. {
  249. *(outBuf++) = conv(inBuf++);
  250. }
  251. }
  252. }
  253. /////////////////////////
  254. // Uncompressed samples
  255. //////////////////////////////////////////////////////
  256. // 8-Bit / Mono / PCM
  257. else if(GetBitDepth() == 8 && GetChannelFormat() == mono)
  258. {
  259. switch(GetEncoding())
  260. {
  261. case signedPCM: // 8-Bit / Mono / Signed / PCM
  262. bytesRead = CopyMonoSample<SC::DecodeInt8>(sample, sourceBuf, fileSize);
  263. break;
  264. case unsignedPCM: // 8-Bit / Mono / Unsigned / PCM
  265. bytesRead = CopyMonoSample<SC::DecodeUint8>(sample, sourceBuf, fileSize);
  266. break;
  267. case deltaPCM: // 8-Bit / Mono / Delta / PCM
  268. case MT2:
  269. bytesRead = CopyMonoSample<SC::DecodeInt8Delta>(sample, sourceBuf, fileSize);
  270. break;
  271. default:
  272. MPT_ASSERT_NOTREACHED();
  273. break;
  274. }
  275. }
  276. //////////////////////////////////////////////////////
  277. // 8-Bit / Stereo Split / PCM
  278. else if(GetBitDepth() == 8 && GetChannelFormat() == stereoSplit)
  279. {
  280. switch(GetEncoding())
  281. {
  282. case signedPCM: // 8-Bit / Stereo Split / Signed / PCM
  283. bytesRead = CopyStereoSplitSample<SC::DecodeInt8>(sample, sourceBuf, fileSize);
  284. break;
  285. case unsignedPCM: // 8-Bit / Stereo Split / Unsigned / PCM
  286. bytesRead = CopyStereoSplitSample<SC::DecodeUint8>(sample, sourceBuf, fileSize);
  287. break;
  288. case deltaPCM: // 8-Bit / Stereo Split / Delta / PCM
  289. case MT2: // same as deltaPCM, but right channel is stored as a difference from the left channel
  290. bytesRead = CopyStereoSplitSample<SC::DecodeInt8Delta>(sample, sourceBuf, fileSize);
  291. if(GetEncoding() == MT2)
  292. {
  293. for(int8 *p = sample.sample8(), *pEnd = p + sample.nLength * 2; p < pEnd; p += 2)
  294. {
  295. p[1] = static_cast<int8>(static_cast<uint8>(p[0]) + static_cast<uint8>(p[1]));
  296. }
  297. }
  298. break;
  299. default:
  300. MPT_ASSERT_NOTREACHED();
  301. break;
  302. }
  303. }
  304. //////////////////////////////////////////////////////
  305. // 8-Bit / Stereo Interleaved / PCM
  306. else if(GetBitDepth() == 8 && GetChannelFormat() == stereoInterleaved)
  307. {
  308. switch(GetEncoding())
  309. {
  310. case signedPCM: // 8-Bit / Stereo Interleaved / Signed / PCM
  311. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt8>(sample, sourceBuf, fileSize);
  312. break;
  313. case unsignedPCM: // 8-Bit / Stereo Interleaved / Unsigned / PCM
  314. bytesRead = CopyStereoInterleavedSample<SC::DecodeUint8>(sample, sourceBuf, fileSize);
  315. break;
  316. case deltaPCM: // 8-Bit / Stereo Interleaved / Delta / PCM
  317. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt8Delta>(sample, sourceBuf, fileSize);
  318. break;
  319. default:
  320. MPT_ASSERT_NOTREACHED();
  321. break;
  322. }
  323. }
  324. //////////////////////////////////////////////////////
  325. // 16-Bit / Mono / Little Endian / PCM
  326. else if(GetBitDepth() == 16 && GetChannelFormat() == mono && GetEndianness() == littleEndian)
  327. {
  328. switch(GetEncoding())
  329. {
  330. case signedPCM: // 16-Bit / Stereo Interleaved / Signed / PCM
  331. bytesRead = CopyMonoSample<SC::DecodeInt16<0, littleEndian16> >(sample, sourceBuf, fileSize);
  332. break;
  333. case unsignedPCM: // 16-Bit / Stereo Interleaved / Unsigned / PCM
  334. bytesRead = CopyMonoSample<SC::DecodeInt16<0x8000u, littleEndian16> >(sample, sourceBuf, fileSize);
  335. break;
  336. case deltaPCM: // 16-Bit / Stereo Interleaved / Delta / PCM
  337. case MT2:
  338. bytesRead = CopyMonoSample<SC::DecodeInt16Delta<littleEndian16> >(sample, sourceBuf, fileSize);
  339. break;
  340. default:
  341. MPT_ASSERT_NOTREACHED();
  342. break;
  343. }
  344. }
  345. //////////////////////////////////////////////////////
  346. // 16-Bit / Mono / Big Endian / PCM
  347. else if(GetBitDepth() == 16 && GetChannelFormat() == mono && GetEndianness() == bigEndian)
  348. {
  349. switch(GetEncoding())
  350. {
  351. case signedPCM: // 16-Bit / Mono / Signed / PCM
  352. bytesRead = CopyMonoSample<SC::DecodeInt16<0, bigEndian16> >(sample, sourceBuf, fileSize);
  353. break;
  354. case unsignedPCM: // 16-Bit / Mono / Unsigned / PCM
  355. bytesRead = CopyMonoSample<SC::DecodeInt16<0x8000u, bigEndian16> >(sample, sourceBuf, fileSize);
  356. break;
  357. case deltaPCM: // 16-Bit / Mono / Delta / PCM
  358. bytesRead = CopyMonoSample<SC::DecodeInt16Delta<bigEndian16> >(sample, sourceBuf, fileSize);
  359. break;
  360. default:
  361. MPT_ASSERT_NOTREACHED();
  362. break;
  363. }
  364. }
  365. //////////////////////////////////////////////////////
  366. // 16-Bit / Stereo Split / Little Endian / PCM
  367. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoSplit && GetEndianness() == littleEndian)
  368. {
  369. switch(GetEncoding())
  370. {
  371. case signedPCM: // 16-Bit / Stereo Split / Signed / PCM
  372. bytesRead = CopyStereoSplitSample<SC::DecodeInt16<0, littleEndian16> >(sample, sourceBuf, fileSize);
  373. break;
  374. case unsignedPCM: // 16-Bit / Stereo Split / Unsigned / PCM
  375. bytesRead = CopyStereoSplitSample<SC::DecodeInt16<0x8000u, littleEndian16> >(sample, sourceBuf, fileSize);
  376. break;
  377. case deltaPCM: // 16-Bit / Stereo Split / Delta / PCM
  378. case MT2: // same as deltaPCM, but right channel is stored as a difference from the left channel
  379. bytesRead = CopyStereoSplitSample<SC::DecodeInt16Delta<littleEndian16> >(sample, sourceBuf, fileSize);
  380. if(GetEncoding() == MT2)
  381. {
  382. for(int16 *p = sample.sample16(), *pEnd = p + sample.nLength * 2; p < pEnd; p += 2)
  383. {
  384. p[1] = static_cast<int16>(static_cast<uint16>(p[0]) + static_cast<uint16>(p[1]));
  385. }
  386. }
  387. break;
  388. default:
  389. MPT_ASSERT_NOTREACHED();
  390. break;
  391. }
  392. }
  393. //////////////////////////////////////////////////////
  394. // 16-Bit / Stereo Split / Big Endian / PCM
  395. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoSplit && GetEndianness() == bigEndian)
  396. {
  397. switch(GetEncoding())
  398. {
  399. case signedPCM: // 16-Bit / Stereo Split / Signed / PCM
  400. bytesRead = CopyStereoSplitSample<SC::DecodeInt16<0, bigEndian16> >(sample, sourceBuf, fileSize);
  401. break;
  402. case unsignedPCM: // 16-Bit / Stereo Split / Unsigned / PCM
  403. bytesRead = CopyStereoSplitSample<SC::DecodeInt16<0x8000u, bigEndian16> >(sample, sourceBuf, fileSize);
  404. break;
  405. case deltaPCM: // 16-Bit / Stereo Split / Delta / PCM
  406. bytesRead = CopyStereoSplitSample<SC::DecodeInt16Delta<bigEndian16> >(sample, sourceBuf, fileSize);
  407. break;
  408. default:
  409. MPT_ASSERT_NOTREACHED();
  410. break;
  411. }
  412. }
  413. //////////////////////////////////////////////////////
  414. // 16-Bit / Stereo Interleaved / Little Endian / PCM
  415. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoInterleaved && GetEndianness() == littleEndian)
  416. {
  417. switch(GetEncoding())
  418. {
  419. case signedPCM: // 16-Bit / Stereo Interleaved / Signed / PCM
  420. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt16<0, littleEndian16> >(sample, sourceBuf, fileSize);
  421. break;
  422. case unsignedPCM: // 16-Bit / Stereo Interleaved / Unsigned / PCM
  423. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt16<0x8000u, littleEndian16> >(sample, sourceBuf, fileSize);
  424. break;
  425. case deltaPCM: // 16-Bit / Stereo Interleaved / Delta / PCM
  426. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt16Delta<littleEndian16> >(sample, sourceBuf, fileSize);
  427. break;
  428. default:
  429. MPT_ASSERT_NOTREACHED();
  430. break;
  431. }
  432. }
  433. //////////////////////////////////////////////////////
  434. // 16-Bit / Stereo Interleaved / Big Endian / PCM
  435. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoInterleaved && GetEndianness() == bigEndian)
  436. {
  437. switch(GetEncoding())
  438. {
  439. case signedPCM: // 16-Bit / Stereo Interleaved / Signed / PCM
  440. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt16<0, bigEndian16> >(sample, sourceBuf, fileSize);
  441. break;
  442. case unsignedPCM: // 16-Bit / Stereo Interleaved / Unsigned / PCM
  443. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt16<0x8000u, bigEndian16> >(sample, sourceBuf, fileSize);
  444. break;
  445. case deltaPCM: // 16-Bit / Stereo Interleaved / Delta / PCM
  446. bytesRead = CopyStereoInterleavedSample<SC::DecodeInt16Delta<bigEndian16> >(sample, sourceBuf, fileSize);
  447. break;
  448. default:
  449. MPT_ASSERT_NOTREACHED();
  450. break;
  451. }
  452. }
  453. //////////////////////////////////////////////////////
  454. // 24-Bit / Signed / Mono / PCM
  455. else if(GetBitDepth() == 24 && GetChannelFormat() == mono && GetEncoding() == signedPCM)
  456. {
  457. if(GetEndianness() == littleEndian)
  458. {
  459. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt24<0, littleEndian24> > >(sample, sourceBuf, fileSize);
  460. } else
  461. {
  462. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt24<0, bigEndian24> > >(sample, sourceBuf, fileSize);
  463. }
  464. }
  465. //////////////////////////////////////////////////////
  466. // 24-Bit / Signed / Stereo Interleaved / PCM
  467. else if(GetBitDepth() == 24 && GetChannelFormat() == stereoInterleaved && GetEncoding() == signedPCM)
  468. {
  469. if(GetEndianness() == littleEndian)
  470. {
  471. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt24<0, littleEndian24> > >(sample, sourceBuf, fileSize);
  472. } else
  473. {
  474. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt24<0, bigEndian24> > >(sample, sourceBuf, fileSize);
  475. }
  476. }
  477. //////////////////////////////////////////////////////
  478. // 32-Bit / Signed / Mono / PCM
  479. else if(GetBitDepth() == 32 && GetChannelFormat() == mono && GetEncoding() == signedPCM)
  480. {
  481. if(GetEndianness() == littleEndian)
  482. {
  483. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt32<0, littleEndian32> > >(sample, sourceBuf, fileSize);
  484. } else
  485. {
  486. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt32<0, bigEndian32> > >(sample, sourceBuf, fileSize);
  487. }
  488. }
  489. //////////////////////////////////////////////////////
  490. // 32-Bit / Signed / Stereo Interleaved / PCM
  491. else if(GetBitDepth() == 32 && GetChannelFormat() == stereoInterleaved && GetEncoding() == signedPCM)
  492. {
  493. if(GetEndianness() == littleEndian)
  494. {
  495. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt32<0, littleEndian32> > >(sample, sourceBuf, fileSize);
  496. } else
  497. {
  498. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, int32>, SC::DecodeInt32<0, bigEndian32> > >(sample, sourceBuf, fileSize);
  499. }
  500. }
  501. //////////////////////////////////////////////////////
  502. // 64-Bit / Signed / Mono / PCM
  503. else if(GetBitDepth() == 64 && GetChannelFormat() == mono && GetEncoding() == signedPCM)
  504. {
  505. if(GetEndianness() == littleEndian)
  506. {
  507. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, int64>, SC::DecodeInt64<0, littleEndian64> > >(sample, sourceBuf, fileSize);
  508. } else
  509. {
  510. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, int64>, SC::DecodeInt64<0, bigEndian64> > >(sample, sourceBuf, fileSize);
  511. }
  512. }
  513. //////////////////////////////////////////////////////
  514. // 64-Bit / Signed / Stereo Interleaved / PCM
  515. else if(GetBitDepth() == 64 && GetChannelFormat() == stereoInterleaved && GetEncoding() == signedPCM)
  516. {
  517. if(GetEndianness() == littleEndian)
  518. {
  519. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, int64>, SC::DecodeInt64<0, littleEndian64> > >(sample, sourceBuf, fileSize);
  520. } else
  521. {
  522. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, int64>, SC::DecodeInt64<0, bigEndian64> > >(sample, sourceBuf, fileSize);
  523. }
  524. }
  525. //////////////////////////////////////////////////////
  526. // 32-Bit / Float / Mono / PCM
  527. else if(GetBitDepth() == 32 && GetChannelFormat() == mono && GetEncoding() == floatPCM)
  528. {
  529. if(GetEndianness() == littleEndian)
  530. {
  531. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeFloat32<littleEndian32> > >(sample, sourceBuf, fileSize);
  532. } else
  533. {
  534. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeFloat32<bigEndian32> > >(sample, sourceBuf, fileSize);
  535. }
  536. }
  537. //////////////////////////////////////////////////////
  538. // 32-Bit / Float / Stereo Interleaved / PCM
  539. else if(GetBitDepth() == 32 && GetChannelFormat() == stereoInterleaved && GetEncoding() == floatPCM)
  540. {
  541. if(GetEndianness() == littleEndian)
  542. {
  543. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeFloat32<littleEndian32> > >(sample, sourceBuf, fileSize);
  544. } else
  545. {
  546. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeFloat32<bigEndian32> > >(sample, sourceBuf, fileSize);
  547. }
  548. }
  549. //////////////////////////////////////////////////////
  550. // 64-Bit / Float / Mono / PCM
  551. else if(GetBitDepth() == 64 && GetChannelFormat() == mono && GetEncoding() == floatPCM)
  552. {
  553. if(GetEndianness() == littleEndian)
  554. {
  555. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, float64>, SC::DecodeFloat64<littleEndian64> > >(sample, sourceBuf, fileSize);
  556. } else
  557. {
  558. bytesRead = CopyMonoSample<SC::ConversionChain<SC::Convert<int16, float64>, SC::DecodeFloat64<bigEndian64> > >(sample, sourceBuf, fileSize);
  559. }
  560. }
  561. //////////////////////////////////////////////////////
  562. // 64-Bit / Float / Stereo Interleaved / PCM
  563. else if(GetBitDepth() == 64 && GetChannelFormat() == stereoInterleaved && GetEncoding() == floatPCM)
  564. {
  565. if(GetEndianness() == littleEndian)
  566. {
  567. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, float64>, SC::DecodeFloat64<littleEndian64> > >(sample, sourceBuf, fileSize);
  568. } else
  569. {
  570. bytesRead = CopyStereoInterleavedSample<SC::ConversionChain<SC::Convert<int16, float64>, SC::DecodeFloat64<bigEndian64> > >(sample, sourceBuf, fileSize);
  571. }
  572. }
  573. //////////////////////////////////////////////////////
  574. // 24-Bit / Signed / Mono, Stereo Interleaved / PCM
  575. else if(GetBitDepth() == 24 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved) && GetEncoding() == signedPCMnormalize)
  576. {
  577. // Normalize to 16-Bit
  578. uint32 srcPeak = uint32(1)<<31;
  579. if(GetEndianness() == littleEndian)
  580. {
  581. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, int32>, SC::DecodeInt24<0, littleEndian24> > >(sample, sourceBuf, fileSize, &srcPeak);
  582. } else
  583. {
  584. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, int32>, SC::DecodeInt24<0, bigEndian24> > >(sample, sourceBuf, fileSize, &srcPeak);
  585. }
  586. if(bytesRead && srcPeak != uint32(1)<<31)
  587. {
  588. // Adjust sample volume so we do not affect relative volume of the sample. Normalizing is only done to increase precision.
  589. sample.nGlobalVol = static_cast<uint16>(Clamp(Util::muldivr_unsigned(sample.nGlobalVol, srcPeak, uint32(1)<<31), uint32(1), uint32(64)));
  590. sample.uFlags.set(SMP_MODIFIED);
  591. }
  592. }
  593. //////////////////////////////////////////////////////
  594. // 32-Bit / Signed / Mono, Stereo Interleaved / PCM
  595. else if(GetBitDepth() == 32 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved) && GetEncoding() == signedPCMnormalize)
  596. {
  597. // Normalize to 16-Bit
  598. uint32 srcPeak = uint32(1)<<31;
  599. if(GetEndianness() == littleEndian)
  600. {
  601. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, int32>, SC::DecodeInt32<0, littleEndian32> > >(sample, sourceBuf, fileSize, &srcPeak);
  602. } else
  603. {
  604. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, int32>, SC::DecodeInt32<0, bigEndian32> > >(sample, sourceBuf, fileSize, &srcPeak);
  605. }
  606. if(bytesRead && srcPeak != uint32(1)<<31)
  607. {
  608. // Adjust sample volume so we do not affect relative volume of the sample. Normalizing is only done to increase precision.
  609. sample.nGlobalVol = static_cast<uint16>(Clamp(Util::muldivr_unsigned(sample.nGlobalVol, srcPeak, uint32(1)<<31), uint32(1), uint32(64)));
  610. sample.uFlags.set(SMP_MODIFIED);
  611. }
  612. }
  613. //////////////////////////////////////////////////////
  614. // 32-Bit / Float / Mono, Stereo Interleaved / PCM
  615. else if(GetBitDepth() == 32 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved) && GetEncoding() == floatPCMnormalize)
  616. {
  617. // Normalize to 16-Bit
  618. float32 srcPeak = 1.0f;
  619. if(GetEndianness() == littleEndian)
  620. {
  621. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, float32>, SC::DecodeFloat32<littleEndian32> > >(sample, sourceBuf, fileSize, &srcPeak);
  622. } else
  623. {
  624. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, float32>, SC::DecodeFloat32<bigEndian32> > >(sample, sourceBuf, fileSize, &srcPeak);
  625. }
  626. if(bytesRead && srcPeak != 1.0f)
  627. {
  628. // Adjust sample volume so we do not affect relative volume of the sample. Normalizing is only done to increase precision.
  629. sample.nGlobalVol = mpt::saturate_round<uint16>(Clamp(sample.nGlobalVol * srcPeak, 1.0f, 64.0f));
  630. sample.uFlags.set(SMP_MODIFIED);
  631. }
  632. }
  633. //////////////////////////////////////////////////////
  634. // 64-Bit / Float / Mono, Stereo Interleaved / PCM
  635. else if(GetBitDepth() == 64 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved) && GetEncoding() == floatPCMnormalize)
  636. {
  637. // Normalize to 16-Bit
  638. float64 srcPeak = 1.0;
  639. if(GetEndianness() == littleEndian)
  640. {
  641. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, float64>, SC::DecodeFloat64<littleEndian64> > >(sample, sourceBuf, fileSize, &srcPeak);
  642. } else
  643. {
  644. bytesRead = CopyAndNormalizeSample<SC::NormalizationChain<SC::Convert<int16, float64>, SC::DecodeFloat64<bigEndian64> > >(sample, sourceBuf, fileSize, &srcPeak);
  645. }
  646. if(bytesRead && srcPeak != 1.0)
  647. {
  648. // Adjust sample volume so we do not affect relative volume of the sample. Normalizing is only done to increase precision.
  649. sample.nGlobalVol = mpt::saturate_round<uint16>(Clamp(sample.nGlobalVol * srcPeak, 1.0, 64.0));
  650. sample.uFlags.set(SMP_MODIFIED);
  651. }
  652. }
  653. //////////////////////////////////////////////////////
  654. // 32-Bit / Float / Mono / PCM / full scale 2^15
  655. else if(GetBitDepth() == 32 && GetChannelFormat() == mono && GetEncoding() == floatPCM15)
  656. {
  657. if(GetEndianness() == littleEndian)
  658. {
  659. bytesRead = CopyMonoSample
  660. (sample, sourceBuf, fileSize,
  661. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<littleEndian32> >
  662. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<littleEndian32>(1.0f / static_cast<float>(1<<15)))
  663. );
  664. } else
  665. {
  666. bytesRead = CopyMonoSample
  667. (sample, sourceBuf, fileSize,
  668. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<bigEndian32> >
  669. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<bigEndian32>(1.0f / static_cast<float>(1<<15)))
  670. );
  671. }
  672. }
  673. //////////////////////////////////////////////////////
  674. // 32-Bit / Float / Stereo Interleaved / PCM / full scale 2^15
  675. else if(GetBitDepth() == 32 && GetChannelFormat() == stereoInterleaved && GetEncoding() == floatPCM15)
  676. {
  677. if(GetEndianness() == littleEndian)
  678. {
  679. bytesRead = CopyStereoInterleavedSample
  680. (sample, sourceBuf, fileSize,
  681. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<littleEndian32> >
  682. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<littleEndian32>(1.0f / static_cast<float>(1<<15)))
  683. );
  684. } else
  685. {
  686. bytesRead = CopyStereoInterleavedSample
  687. (sample, sourceBuf, fileSize,
  688. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<bigEndian32> >
  689. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<bigEndian32>(1.0f / static_cast<float>(1<<15)))
  690. );
  691. }
  692. }
  693. //////////////////////////////////////////////////////
  694. // 32-Bit / Float / Stereo Interleaved / PCM / full scale 2^23
  695. else if(GetBitDepth() == 32 && GetChannelFormat() == mono && GetEncoding() == floatPCM23)
  696. {
  697. if(GetEndianness() == littleEndian)
  698. {
  699. bytesRead = CopyMonoSample
  700. (sample, sourceBuf, fileSize,
  701. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<littleEndian32> >
  702. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<littleEndian32>(1.0f / static_cast<float>(1<<23)))
  703. );
  704. } else
  705. {
  706. bytesRead = CopyMonoSample
  707. (sample, sourceBuf, fileSize,
  708. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<bigEndian32> >
  709. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<bigEndian32>(1.0f / static_cast<float>(1<<23)))
  710. );
  711. }
  712. }
  713. //////////////////////////////////////////////////////
  714. // 32-Bit / Float / Stereo Interleaved / PCM / full scale 2^23
  715. else if(GetBitDepth() == 32 && GetChannelFormat() == stereoInterleaved && GetEncoding() == floatPCM23)
  716. {
  717. if(GetEndianness() == littleEndian)
  718. {
  719. bytesRead = CopyStereoInterleavedSample
  720. (sample, sourceBuf, fileSize,
  721. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<littleEndian32> >
  722. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<littleEndian32>(1.0f / static_cast<float>(1<<23)))
  723. );
  724. } else
  725. {
  726. bytesRead = CopyStereoInterleavedSample
  727. (sample, sourceBuf, fileSize,
  728. SC::ConversionChain<SC::Convert<int16, float32>, SC::DecodeScaledFloat32<bigEndian32> >
  729. (SC::Convert<int16, float32>(), SC::DecodeScaledFloat32<bigEndian32>(1.0f / static_cast<float>(1<<23)))
  730. );
  731. }
  732. }
  733. ////////////////
  734. // Unsupported
  735. else
  736. {
  737. MPT_ASSERT_NOTREACHED();
  738. }
  739. MPT_ASSERT(filePosition + bytesRead <= file.GetLength());
  740. file.Seek(filePosition + bytesRead);
  741. return bytesRead;
  742. }
  743. #ifndef MODPLUG_NO_FILESAVE
  744. // Write a sample to file
  745. size_t SampleIO::WriteSample(std::ostream &f, const ModSample &sample, SmpLength maxSamples) const
  746. {
  747. if(sample.uFlags[CHN_ADLIB])
  748. {
  749. mpt::IO::Write(f, sample.adlib);
  750. return sizeof(sample.adlib);
  751. }
  752. if(!sample.HasSampleData())
  753. {
  754. return 0;
  755. }
  756. std::array<std::byte, mpt::IO::BUFFERSIZE_TINY> writeBuffer;
  757. mpt::IO::WriteBuffer<std::ostream> fb{f, mpt::as_span(writeBuffer)};
  758. SmpLength numSamples = sample.nLength;
  759. if(maxSamples && numSamples > maxSamples)
  760. {
  761. numSamples = maxSamples;
  762. }
  763. std::size_t len = CalculateEncodedSize(numSamples);
  764. if(GetBitDepth() == 16 && GetChannelFormat() == mono && GetEndianness() == littleEndian &&
  765. (GetEncoding() == signedPCM || GetEncoding() == unsignedPCM || GetEncoding() == deltaPCM))
  766. {
  767. // 16-bit little-endian mono samples
  768. MPT_ASSERT(len == numSamples * 2);
  769. const int16 *const pSample16 = sample.sample16();
  770. const int16 *p = pSample16;
  771. int s_old = 0;
  772. const int s_ofs = (GetEncoding() == unsignedPCM) ? 0x8000 : 0;
  773. for(SmpLength j = 0; j < numSamples; j++)
  774. {
  775. int s_new = *p;
  776. p++;
  777. if(sample.uFlags[CHN_STEREO])
  778. {
  779. // Downmix stereo
  780. s_new = (s_new + (*p) + 1) / 2;
  781. p++;
  782. }
  783. if(GetEncoding() == deltaPCM)
  784. {
  785. mpt::IO::Write(fb, mpt::as_le(static_cast<int16>(s_new - s_old)));
  786. s_old = s_new;
  787. } else
  788. {
  789. mpt::IO::Write(fb, mpt::as_le(static_cast<int16>(s_new + s_ofs)));
  790. }
  791. }
  792. }
  793. else if(GetBitDepth() == 8 && GetChannelFormat() == stereoSplit &&
  794. (GetEncoding() == signedPCM || GetEncoding() == unsignedPCM || GetEncoding() == deltaPCM))
  795. {
  796. // 8-bit Stereo samples (not interleaved)
  797. MPT_ASSERT(len == numSamples * 2);
  798. const int8 *const pSample8 = sample.sample8();
  799. const int s_ofs = (GetEncoding() == unsignedPCM) ? 0x80 : 0;
  800. for (uint32 iCh=0; iCh<2; iCh++)
  801. {
  802. const int8 *p = pSample8 + iCh;
  803. int s_old = 0;
  804. for (SmpLength j = 0; j < numSamples; j++)
  805. {
  806. int s_new = *p;
  807. p += 2;
  808. if (GetEncoding() == deltaPCM)
  809. {
  810. mpt::IO::Write(fb, static_cast<int8>(s_new - s_old));
  811. s_old = s_new;
  812. } else
  813. {
  814. mpt::IO::Write(fb, static_cast<int8>(s_new + s_ofs));
  815. }
  816. }
  817. }
  818. }
  819. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoSplit && GetEndianness() == littleEndian &&
  820. (GetEncoding() == signedPCM || GetEncoding() == unsignedPCM || GetEncoding() == deltaPCM))
  821. {
  822. // 16-bit little-endian Stereo samples (not interleaved)
  823. MPT_ASSERT(len == numSamples * 4);
  824. const int16 *const pSample16 = sample.sample16();
  825. const int s_ofs = (GetEncoding() == unsignedPCM) ? 0x8000 : 0;
  826. for (uint32 iCh=0; iCh<2; iCh++)
  827. {
  828. const int16 *p = pSample16 + iCh;
  829. int s_old = 0;
  830. for (SmpLength j = 0; j < numSamples; j++)
  831. {
  832. int s_new = *p;
  833. p += 2;
  834. if (GetEncoding() == deltaPCM)
  835. {
  836. mpt::IO::Write(fb, mpt::as_le(static_cast<int16>(s_new - s_old)));
  837. s_old = s_new;
  838. } else
  839. {
  840. mpt::IO::Write(fb, mpt::as_le(static_cast<int16>(s_new + s_ofs)));
  841. }
  842. }
  843. }
  844. }
  845. else if(GetBitDepth() == 8 && GetChannelFormat() == stereoInterleaved && GetEncoding() == signedPCM)
  846. {
  847. // Stereo signed interleaved
  848. MPT_ASSERT(len == numSamples * 2);
  849. const int8 *const pSample8 = sample.sample8();
  850. mpt::IO::WriteRaw(f, reinterpret_cast<const std::byte*>(pSample8), len);
  851. }
  852. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoInterleaved && GetEncoding() == signedPCM && GetEndianness() == littleEndian)
  853. {
  854. // Stereo signed interleaved
  855. MPT_ASSERT(len == numSamples * 4);
  856. const int16 *const pSample16 = sample.sample16();
  857. const int16 *p = pSample16;
  858. for(SmpLength j = 0; j < numSamples; j++)
  859. {
  860. mpt::IO::Write(fb, mpt::as_le(p[0]));
  861. mpt::IO::Write(fb, mpt::as_le(p[1]));
  862. p += 2;
  863. }
  864. }
  865. else if(GetBitDepth() == 16 && GetChannelFormat() == stereoInterleaved && GetEncoding() == signedPCM && GetEndianness() == bigEndian)
  866. {
  867. // Stereo signed interleaved
  868. MPT_ASSERT(len == numSamples * 4);
  869. const int16 *const pSample16 = sample.sample16();
  870. const int16 *p = pSample16;
  871. for(SmpLength j = 0; j < numSamples; j++)
  872. {
  873. mpt::IO::Write(fb, mpt::as_be(p[0]));
  874. mpt::IO::Write(fb, mpt::as_be(p[1]));
  875. p += 2;
  876. }
  877. }
  878. else if(GetBitDepth() == 8 && GetChannelFormat() == stereoInterleaved && GetEncoding() == unsignedPCM)
  879. {
  880. // Stereo unsigned interleaved
  881. MPT_ASSERT(len == numSamples * 2);
  882. const int8 *const pSample8 = sample.sample8();
  883. for(SmpLength j = 0; j < numSamples * 2; j++)
  884. {
  885. mpt::IO::Write(fb, static_cast<int8>(static_cast<uint8>(pSample8[j]) + 0x80));
  886. }
  887. }
  888. else if(GetEncoding() == IT214 || GetEncoding() == IT215)
  889. {
  890. // IT2.14-encoded samples
  891. ITCompression its(sample, GetEncoding() == IT215, &f, numSamples);
  892. len = its.GetCompressedSize();
  893. }
  894. // Default: assume 8-bit PCM data
  895. else
  896. {
  897. MPT_ASSERT(GetBitDepth() == 8);
  898. MPT_ASSERT(len == numSamples);
  899. if(sample.uFlags[CHN_16BIT])
  900. {
  901. const int16 *p = sample.sample16();
  902. int s_old = 0;
  903. const int s_ofs = (GetEncoding() == unsignedPCM) ? 0x80 : 0;
  904. for(SmpLength j = 0; j < numSamples; j++)
  905. {
  906. int s_new = mpt::rshift_signed(*p, 8);
  907. p++;
  908. if(sample.uFlags[CHN_STEREO])
  909. {
  910. s_new = (s_new + mpt::rshift_signed(*p, 8) + 1) / 2;
  911. p++;
  912. }
  913. if(GetEncoding() == deltaPCM)
  914. {
  915. mpt::IO::Write(fb, static_cast<int8>(s_new - s_old));
  916. s_old = s_new;
  917. } else
  918. {
  919. mpt::IO::Write(fb, static_cast<int8>(s_new + s_ofs));
  920. }
  921. }
  922. } else
  923. {
  924. const int8 *const pSample8 = sample.sample8();
  925. const int8 *p = pSample8;
  926. int s_old = 0;
  927. const int s_ofs = (GetEncoding() == unsignedPCM) ? 0x80 : 0;
  928. for(SmpLength j = 0; j < numSamples; j++)
  929. {
  930. int s_new = *p;
  931. p++;
  932. if(sample.uFlags[CHN_STEREO])
  933. {
  934. s_new = (s_new + (static_cast<int>(*p)) + 1) / 2;
  935. p++;
  936. }
  937. if(GetEncoding() == deltaPCM)
  938. {
  939. mpt::IO::Write(fb, static_cast<int8>(s_new - s_old));
  940. s_old = s_new;
  941. } else
  942. {
  943. mpt::IO::Write(fb, static_cast<int8>(s_new + s_ofs));
  944. }
  945. }
  946. }
  947. }
  948. return len;
  949. }
  950. #endif // MODPLUG_NO_FILESAVE
  951. OPENMPT_NAMESPACE_END