1 /* 2 * ITCompression.h 3 * --------------- 4 * Purpose: Code for IT sample compression and decompression. 5 * Notes : The original Python compression code was written by GreaseMonkey and has been released into the public domain. 6 * Authors: OpenMPT Devs 7 * Ben "GreaseMonkey" Russell 8 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. 9 */ 10 11 #pragma once 12 13 #include "openmpt/all/BuildSettings.hpp" 14 15 #include <vector> 16 #include <iosfwd> 17 #include "Snd_defs.h" 18 #include "BitReader.h" 19 20 21 OPENMPT_NAMESPACE_BEGIN 22 23 struct ModSample; 24 25 class ITCompression 26 { 27 public: 28 ITCompression(const ModSample &sample, bool it215, std::ostream *f, SmpLength maxLength = 0); GetCompressedSize()29 size_t GetCompressedSize() const { return packedTotalLength; } 30 31 static constexpr size_t bufferSize = 2 + 0xFFFF; // Our output buffer can't be longer than this. 32 static constexpr size_t blockSize = 0x8000; // Block size (in bytes) in which samples are being processed 33 34 protected: 35 std::vector<int8> bwt; // Bit width table for each sampling point 36 std::vector<uint8> packedData; // Compressed data for current sample block 37 std::ostream *file = nullptr; // File to which compressed data will be written (can be nullptr if you only want to find out the sample size) 38 std::vector<int8> sampleData8; // Pre-processed sample data for currently compressed sample block 39 std::vector<int16> sampleData16; // Pre-processed sample data for currently compressed sample block 40 const ModSample &mptSample; // Sample that is being processed 41 size_t packedLength = 0; // Size of currently compressed sample block 42 size_t packedTotalLength = 0; // Size of all compressed data so far 43 SmpLength baseLength = 0; // Length of the currently compressed sample block (in samples) 44 45 // Bit writer 46 int8 bitPos = 0; // Current bit position in this byte 47 int8 remBits = 0; // Remaining bits in this byte 48 uint8 byteVal = 0; // Current byte value to be written 49 50 const bool is215; // Use IT2.15 compression (double deltas) 51 52 template<typename Properties> 53 void Compress(const typename Properties::sample_t *mptSampleData, SmpLength maxLength); 54 55 template<typename T> 56 static void CopySample(T *target, const T *source, SmpLength offset, SmpLength length, SmpLength skip); 57 58 template<typename T> 59 void Deltafy(T *sampleData); 60 61 template<typename Properties> 62 void CompressBlock(const typename Properties::sample_t *data, SmpLength offset, SmpLength actualLength, typename Properties::sample_t *sampleData); 63 64 static int8 GetWidthChangeSize(int8 w, bool is16); 65 66 template<typename Properties> 67 void SquishRecurse(int8 sWidth, int8 lWidth, int8 rWidth, int8 width, SmpLength offset, SmpLength length, const typename Properties::sample_t *sampleData); 68 69 static int8 ConvertWidth(int8 curWidth, int8 newWidth); 70 void WriteBits(int8 width, int v); 71 72 void WriteByte(uint8 v); 73 }; 74 75 76 class ITDecompression 77 { 78 public: 79 ITDecompression(FileReader &file, ModSample &sample, bool it215); 80 81 protected: 82 BitReader bitFile; 83 ModSample &mptSample; // Sample that is being processed 84 85 SmpLength writtenSamples = 0; // Number of samples so far written on this channel 86 SmpLength writePos = 0; // Absolut write position in sample (for stereo samples) 87 SmpLength curLength = 0; // Length of currently processed block 88 unsigned int mem1 = 0, mem2 = 0; // Integrator memory 89 90 const bool is215; // Use IT2.15 compression (double deltas) 91 92 template<typename Properties> 93 void Uncompress(typename Properties::sample_t *target); 94 static void ChangeWidth(int &curWidth, int width); 95 96 template<typename Properties> 97 void Write(int v, int topbit, typename Properties::sample_t *target); 98 }; 99 100 101 OPENMPT_NAMESPACE_END 102