public BigHuffmanTree(BitStream bs, int allocSize) { _bs = bs; uint bit = _bs.GetBit(); if (bit == 0) { _tree = new uint[1]; _tree[0] = 0; _last[0] = _last[1] = _last[2] = 0; return; } for (uint i = 0; i < 256; ++i) { _prefixtree[i] = _prefixlength[i] = 0; } _loBytes = new SmallHuffmanTree(_bs); _hiBytes = new SmallHuffmanTree(_bs); _markers[0] = _bs.GetBits(16); _markers[1] = _bs.GetBits(16); _markers[2] = _bs.GetBits(16); _last[0] = _last[1] = _last[2] = 0xffffffff; _treeSize = 0; _tree = new uint[allocSize / 4]; DecodeTree(0, 0); bit = _bs.GetBit(); Debug.Assert(bit == 0); for (uint i = 0; i < 3; ++i) { if (_last[i] == 0xffffffff) { _last[i] = _treeSize; _tree[_treeSize++] = 0; } } }
public BigHuffmanTree(BitStream bs, int allocSize) { _bs = bs; uint bit = _bs.GetBit(); if (bit == 0) { _tree = new uint[1]; _tree[0] = 0; _last[0] = _last[1] = _last[2] = 0; return; } for (uint i = 0; i < 256; ++i) _prefixtree[i] = _prefixlength[i] = 0; _loBytes = new SmallHuffmanTree(_bs); _hiBytes = new SmallHuffmanTree(_bs); _markers[0] = _bs.GetBits(16); _markers[1] = _bs.GetBits(16); _markers[2] = _bs.GetBits(16); _last[0] = _last[1] = _last[2] = 0xffffffff; _treeSize = 0; _tree = new uint[allocSize / 4]; DecodeTree(0, 0); bit = _bs.GetBit(); Debug.Assert(bit == 0); for (uint i = 0; i < 3; ++i) { if (_last[i] == 0xffffffff) { _last[i] = _treeSize; _tree[_treeSize++] = 0; } } }
public void QueueCompressedBuffer(byte[] buffer, int bufferSize, int unpackedSize) { using (var ms = new MemoryStream(buffer, 0, bufferSize)) { var audioBS = BitStream.Create8Lsb(ms); bool dataPresent = audioBS.GetBit() != 0; if (!dataPresent) return; bool isStereo = audioBS.GetBit() != 0; Debug.Assert(isStereo == _audioInfo.isStereo); bool is16Bits = audioBS.GetBit() != 0; Debug.Assert(is16Bits == _audioInfo.is16Bits); int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1); byte[] unpackedBuffer = new byte[unpackedSize]; var curPointer = 0; var curPos = 0; SmallHuffmanTree[] audioTrees = new SmallHuffmanTree[4]; for (int k = 0; k < numBytes; k++) audioTrees[k] = new SmallHuffmanTree(audioBS); // Base values, stored as big endian int[] bases = new int[2]; if (isStereo) { if (is16Bits) { bases[1] = ScummHelper.SwapBytes((ushort)audioBS.GetBits(16)); } else { bases[1] = (int)audioBS.GetBits(8); } } if (is16Bits) { bases[0] = ScummHelper.SwapBytes((ushort)audioBS.GetBits(16)); } else { bases[0] = (int)audioBS.GetBits(8); } // The bases are the first samples, too for (int i = 0; i < (isStereo ? 2 : 1); i++, curPointer += (is16Bits ? 2 : 1), curPos += (is16Bits ? 2 : 1)) { if (is16Bits) unpackedBuffer.WriteUInt16BigEndian(curPointer, (ushort)bases[i]); else unpackedBuffer[curPointer] = (byte)((bases[i] & 0xFF) ^ 0x80); } // Next follow the deltas, which are added to the corresponding base values and // are stored as little endian // We store the unpacked bytes in big endian format while (curPos < unpackedSize) { // If the sample is stereo, the data is stored for the left and right channel, respectively // (the exact opposite to the base values) if (!is16Bits) { for (int k = 0; k < (isStereo ? 2 : 1); k++) { sbyte delta = (sbyte)((short)audioTrees[k].GetCode(audioBS)); bases[k] = (bases[k] + delta) & 0xFF; unpackedBuffer[curPointer++] = (byte)(bases[k] ^ 0x80); curPos++; } } else { for (int k = 0; k < (isStereo ? 2 : 1); k++) { byte lo = (byte)audioTrees[k * 2].GetCode(audioBS); byte hi = (byte)audioTrees[k * 2 + 1].GetCode(audioBS); bases[k] += (short)(lo | (hi << 8)); unpackedBuffer.WriteUInt16BigEndian(curPointer, (ushort)bases[k]); curPointer += 2; curPos += 2; } } } QueuePCM(unpackedBuffer, unpackedSize); } }
public void QueueCompressedBuffer(byte[] buffer, int bufferSize, int unpackedSize) { using (var ms = new MemoryStream(buffer, 0, bufferSize)) { var audioBS = BitStream.Create8Lsb(ms); bool dataPresent = audioBS.GetBit() != 0; if (!dataPresent) { return; } bool isStereo = audioBS.GetBit() != 0; Debug.Assert(isStereo == _audioInfo.isStereo); bool is16Bits = audioBS.GetBit() != 0; Debug.Assert(is16Bits == _audioInfo.is16Bits); int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1); byte[] unpackedBuffer = new byte[unpackedSize]; var curPointer = 0; var curPos = 0; SmallHuffmanTree[] audioTrees = new SmallHuffmanTree[4]; for (int k = 0; k < numBytes; k++) { audioTrees[k] = new SmallHuffmanTree(audioBS); } // Base values, stored as big endian int[] bases = new int[2]; if (isStereo) { if (is16Bits) { bases[1] = ScummHelper.SwapBytes((ushort)audioBS.GetBits(16)); } else { bases[1] = (int)audioBS.GetBits(8); } } if (is16Bits) { bases[0] = ScummHelper.SwapBytes((ushort)audioBS.GetBits(16)); } else { bases[0] = (int)audioBS.GetBits(8); } // The bases are the first samples, too for (int i = 0; i < (isStereo ? 2 : 1); i++, curPointer += (is16Bits ? 2 : 1), curPos += (is16Bits ? 2 : 1)) { if (is16Bits) { unpackedBuffer.WriteUInt16BigEndian(curPointer, (ushort)bases[i]); } else { unpackedBuffer[curPointer] = (byte)((bases[i] & 0xFF) ^ 0x80); } } // Next follow the deltas, which are added to the corresponding base values and // are stored as little endian // We store the unpacked bytes in big endian format while (curPos < unpackedSize) { // If the sample is stereo, the data is stored for the left and right channel, respectively // (the exact opposite to the base values) if (!is16Bits) { for (int k = 0; k < (isStereo ? 2 : 1); k++) { sbyte delta = (sbyte)((short)audioTrees[k].GetCode(audioBS)); bases[k] = (bases[k] + delta) & 0xFF; unpackedBuffer[curPointer++] = (byte)(bases[k] ^ 0x80); curPos++; } } else { for (int k = 0; k < (isStereo ? 2 : 1); k++) { byte lo = (byte)audioTrees[k * 2].GetCode(audioBS); byte hi = (byte)audioTrees[k * 2 + 1].GetCode(audioBS); bases[k] += (short)(lo | (hi << 8)); unpackedBuffer.WriteUInt16BigEndian(curPointer, (ushort)bases[k]); curPointer += 2; curPos += 2; } } } QueuePCM(unpackedBuffer, unpackedSize); } }