int32 McmpMgr::decompressSample(int32 offset, int32 size, byte **comp_final) { int32 i, final_size, output_size; int skip, first_block, last_block; if (!_file) { error("McmpMgr::decompressSampleByName() File is not open!"); return 0; } first_block = offset / 0x2000; last_block = (offset + size - 1) / 0x2000; skip = offset % 0x2000; // Clip last_block by the total number of blocks (= "comp items") if ((last_block >= _numCompItems) && (_numCompItems > 0)) last_block = _numCompItems - 1; int32 blocks_final_size = 0x2000 * (1 + last_block - first_block); *comp_final = (byte *)malloc(blocks_final_size * sizeof(byte)); final_size = 0; for (i = first_block; i <= last_block; i++) { if (_lastBlock != i) { // hack: two more zero bytes at the end of input buffer _compInput[_compTable[i].compSize] = 0; _compInput[_compTable[i].compSize + 1] = 0; _file->seek(_compTable[i].offset, SEEK_SET); _file->read(_compInput, _compTable[i].compSize); decompressVima(_compInput, (int16 *)_compOutput, _compTable[i].decompSize, imuseDestTable); _outputSize = _compTable[i].decompSize; if (_outputSize > 0x2000) { error("McmpMgr::decompressSample() _outputSize: %d", _outputSize); } _lastBlock = i; } output_size = _outputSize - skip; if ((output_size + skip) > 0x2000) // workaround output_size -= (output_size + skip) - 0x2000; if (output_size > size) output_size = size; assert(final_size + output_size <= blocks_final_size); memcpy(*comp_final + final_size, _compOutput + skip, output_size); final_size += output_size; size -= output_size; assert(size >= 0); if (size == 0) break; skip = 0; } return final_size; }
void SmushDecoder::handleWave(const byte *src, uint32 size) { int16 *dst = (int16 *) malloc(size * _channels * sizeof(int16)); decompressVima(src, dst, size * _channels * 2, smushDestTable); int flags = Audio::FLAG_16BITS; if (_channels == 2) flags |= Audio::FLAG_STEREO; if (!_stream) { _stream = Audio::makeQueuingAudioStream(_freq, (_channels == 2)); g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, _stream); } if (g_system->getMixer()->isReady()) { _stream->queueBuffer((byte *)dst, size * _channels * 2, DisposeAfterUse::YES, flags); } else { free(dst); } }