Esempio n. 1
0
void SmackerDecoder::SmackerAudioTrack::queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize) {
	Common::BitStream8LSB audioBS(new Common::MemoryReadStream(buffer, bufferSize), true);
	bool dataPresent = audioBS.getBit();

	if (!dataPresent)
		return;

	bool isStereo = audioBS.getBit();
	assert(isStereo == _audioInfo.isStereo);
	bool is16Bits = audioBS.getBit();
	assert(is16Bits == _audioInfo.is16Bits);

	int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1);

	byte *unpackedBuffer = (byte *)malloc(unpackedSize);
	byte *curPointer = unpackedBuffer;
	uint32 curPos = 0;

	SmallHuffmanTree *audioTrees[4];
	for (int k = 0; k < numBytes; k++)
		audioTrees[k] = new SmallHuffmanTree(audioBS);

	// Base values, stored as big endian

	int32 bases[2];

	if (isStereo) {
		if (is16Bits) {
			bases[1] = SWAP_BYTES_16(audioBS.getBits(16));
		} else {
			bases[1] = audioBS.getBits(8);
		}
	}

	if (is16Bits) {
		bases[0] = SWAP_BYTES_16(audioBS.getBits(16));
	} else {
		bases[0] = 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)
			WRITE_BE_UINT16(curPointer, bases[i]);
		else
			*curPointer = (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++) {
				bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS));
				*curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80;
				curPos++;
			}
		} else {
			for (int k = 0; k < (isStereo ? 2 : 1); k++) {
				byte lo = audioTrees[k * 2]->getCode(audioBS);
				byte hi = audioTrees[k * 2 + 1]->getCode(audioBS);
				bases[k] += (int16) (lo | (hi << 8));

				WRITE_BE_UINT16(curPointer, bases[k]);
				curPointer += 2;
				curPos += 2;
			}
		}

	}

	for (int k = 0; k < numBytes; k++)
		delete audioTrees[k];

	queuePCM(unpackedBuffer, unpackedSize);
}
Esempio n. 2
0
void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize,
		uint32 unpackedSize, int streamNum) {

	BitStream audioBS(buffer, bufferSize);
	bool dataPresent = audioBS.getBit();

	if (!dataPresent)
		return;

	bool isStereo = audioBS.getBit();
	assert(isStereo == _header.audioInfo[streamNum].isStereo);
	bool is16Bits = audioBS.getBit();
	assert(is16Bits == _header.audioInfo[streamNum].is16Bits);

	int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1);

	byte *unpackedBuffer = (byte *)malloc(unpackedSize);
	byte *curPointer = unpackedBuffer;
	uint32 curPos = 0;

	SmallHuffmanTree *audioTrees[4];
	for (int k = 0; k < numBytes; k++)
		audioTrees[k] = new SmallHuffmanTree(audioBS);

	// Base values, stored as big endian

	int32 bases[2];

	if (isStereo) {
		if (is16Bits) {
			byte hi = audioBS.getBits8();
			byte lo = audioBS.getBits8();
			bases[1] = (int16) ((hi << 8) | lo);
		} else {
			bases[1] = audioBS.getBits8();
		}
	}

	if (is16Bits) {
		byte hi = audioBS.getBits8();
		byte lo = audioBS.getBits8();
		bases[0] = (int16) ((hi << 8) | lo);
	} else {
		bases[0] = audioBS.getBits8();
	}

	// 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)
			WRITE_BE_UINT16(curPointer, bases[i]);
		else
			*curPointer = (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++) {
				bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS));
				*curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80;
				curPos++;
			}
		} else {
			for (int k = 0; k < (isStereo ? 2 : 1); k++) {
				byte lo = audioTrees[k * 2]->getCode(audioBS);
				byte hi = audioTrees[k * 2 + 1]->getCode(audioBS);
				bases[k] += (int16) (lo | (hi << 8));

				WRITE_BE_UINT16(curPointer, bases[k]);
				curPointer += 2;
				curPos += 2;
			}
		}

	}

	for (int k = 0; k < numBytes; k++)
		delete audioTrees[k];

	byte flags = 0;
	if (_header.audioInfo[0].is16Bits)
		flags = flags | Audio::FLAG_16BITS;
	if (_header.audioInfo[0].isStereo)
		flags = flags | Audio::FLAG_STEREO;
	_audioStream->queueBuffer(unpackedBuffer, unpackedSize, DisposeAfterUse::YES, flags);
	// unpackedBuffer will be deleted by QueuingAudioStream
}