public ImuseDigiSndMgr(ScummEngine scumm) { _vm = scumm; _disk = 0; _cacheBundleDir = new BundleDirCache(); BundleCodecs.InitializeImcTables(); }
public int DecompressSampleByIndex(int index, int offset, int size, out byte[] compFinal, int headerSize, bool headerOutside) { int finalSize, outputSize; int skip, firstBlock, lastBlock; Debug.Assert(0 <= index && index < _numFiles); if (_curSampleId == -1) { _curSampleId = index; } Debug.Assert(_curSampleId == index); if (!_compTableLoaded) { _compTableLoaded = LoadCompTable(index); if (!_compTableLoaded) { compFinal = null; return(0); } } firstBlock = (offset + headerSize) / 0x2000; lastBlock = (offset + headerSize + size - 1) / 0x2000; // Clip last_block by the total number of blocks (= "comp items") if ((lastBlock >= _numCompItems) && (_numCompItems > 0)) { lastBlock = _numCompItems - 1; } int blocksFinalSize = 0x2000 * (1 + lastBlock - firstBlock); compFinal = new byte[blocksFinalSize]; finalSize = 0; skip = (offset + headerSize) % 0x2000; for (var i = firstBlock; i <= lastBlock; i++) { if (_lastBlock != i) { // CMI hack: one more zero byte at the end of input buffer _compInputBuff[_compTable[i].Size] = 0; _file.BaseStream.Seek(_bundleTable[index].Offset + _compTable[i].Offset, SeekOrigin.Begin); _file.BaseStream.Read(_compInputBuff, 0, _compTable[i].Size); _outputSize = BundleCodecs.DecompressCodec(_compTable[i].Codec, _compInputBuff, _compOutputBuff, _compTable[i].Size); if (_outputSize > 0x2000) { // Console.Error.WriteLine("_outputSize: {0}", _outputSize); } _lastBlock = i; } outputSize = _outputSize; if (headerOutside) { outputSize -= skip; } else { if ((headerSize != 0) && (skip >= headerSize)) { outputSize -= skip; } } if ((outputSize + skip) > 0x2000) // workaround { outputSize -= (outputSize + skip) - 0x2000; } if (outputSize > size) { outputSize = size; } Debug.Assert(finalSize + outputSize <= blocksFinalSize); Array.Copy(_compOutputBuff, skip, compFinal, finalSize, outputSize); finalSize += outputSize; size -= outputSize; Debug.Assert(size >= 0); if (size == 0) { break; } skip = 0; } return(finalSize); }
void Callback() { lock (_mutex) { for (int l = 0; l < MaxDigitalTracks + MaxDigitalFadeTracks; l++) { var track = _track[l]; if (track.Used) { // Ignore tracks which are about to finish. Also, if it did finish in the meantime, // mark it as unused. if (track.Stream == null) { if (!_mixer.IsSoundHandleActive(track.MixChanHandle)) { _track[l].Clear(); } continue; } if (_pause) { return; } if (track.VolFadeUsed) { if (track.VolFadeStep < 0) { if (track.vol > track.VolFadeDest) { track.vol += track.VolFadeStep; if (track.vol < track.VolFadeDest) { track.vol = track.VolFadeDest; track.VolFadeUsed = false; } if (track.vol == 0) { // Fade out complete . remove this track FlushTrack(track); continue; } } } else if (track.VolFadeStep > 0) { if (track.vol < track.VolFadeDest) { track.vol += track.VolFadeStep; if (track.vol > track.VolFadeDest) { track.vol = track.VolFadeDest; track.VolFadeUsed = false; } } } // Debug.WriteLine("Fade: sound({0}), Vol({1})", track.SoundId, track.vol / 1000); } if (!track.SouStreamUsed) { Debug.Assert(track.Stream != null); byte[] tmpSndBufferPtr = null; int curFeedSize = 0; if (track.CurRegion == -1) { SwitchToNextRegion(track); if (track.Stream == null) // Seems we reached the end of the stream { continue; } } int bits = _sound.GetBits(track.SoundDesc); int channels = _sound.GetChannels(track.SoundDesc); int feedSize = track.FeedSize / _callbackFps; if (track.Stream.IsEndOfData) { feedSize *= 2; } if ((bits == 12) || (bits == 16)) { if (channels == 1) { feedSize &= ~1; } if (channels == 2) { feedSize &= ~3; } } else if (bits == 8) { if (channels == 2) { feedSize &= ~1; } } else { // Console.Error.WriteLine("IMuseDigita::callback: Unexpected sample width, {0} bits", bits); continue; } if (feedSize == 0) { continue; } do { switch (bits) { case 12: byte[] tmpPtr; feedSize += track.DataMod12Bit; int tmpFeedSize12Bits = (feedSize * 3) / 4; int tmpLength12Bits = (tmpFeedSize12Bits / 3) * 4; track.DataMod12Bit = feedSize - tmpLength12Bits; int tmpOffset = (track.RegionOffset * 3) / 4; int tmpFeedSize = _sound.GetDataFromRegion(track.SoundDesc, track.CurRegion, out tmpPtr, tmpOffset, tmpFeedSize12Bits); curFeedSize = BundleCodecs.Decode12BitsSample(tmpPtr, out tmpSndBufferPtr, tmpFeedSize); break; case 16: curFeedSize = _sound.GetDataFromRegion(track.SoundDesc, track.CurRegion, out tmpSndBufferPtr, track.RegionOffset, feedSize); if (channels == 1) { curFeedSize &= ~1; } if (channels == 2) { curFeedSize &= ~3; } break; case 8: curFeedSize = _sound.GetDataFromRegion(track.SoundDesc, track.CurRegion, out tmpSndBufferPtr, track.RegionOffset, feedSize); if (RadioChatterSFX && track.SoundId == 10000) { if (curFeedSize > feedSize) { curFeedSize = feedSize; } var buf = new byte[curFeedSize]; int index = 0; int count = curFeedSize - 4; var ptr_1 = 0; var ptr_2 = 4; int value = tmpSndBufferPtr[ptr_1 + 0] - 0x80; value += tmpSndBufferPtr[ptr_1 + 1] - 0x80; value += tmpSndBufferPtr[ptr_1 + 2] - 0x80; value += tmpSndBufferPtr[ptr_1 + 3] - 0x80; do { int t = tmpSndBufferPtr[ptr_1++]; int v = t - (value / 4); value = tmpSndBufferPtr[ptr_2++] - 0x80 + (value - t + 0x80); buf[index++] = (byte)(v * 2 + 0x80); }while ((--count) != 0); buf[curFeedSize - 1] = 0x80; buf[curFeedSize - 2] = 0x80; buf[curFeedSize - 3] = 0x80; buf[curFeedSize - 4] = 0x80; tmpSndBufferPtr = buf; } if (channels == 2) { curFeedSize &= ~1; } break; } if (curFeedSize > feedSize) { curFeedSize = feedSize; } if (_mixer.IsReady) { track.Stream.QueueBuffer(tmpSndBufferPtr, curFeedSize, true, MakeMixerFlags(track)); track.RegionOffset += curFeedSize; } else { tmpSndBufferPtr = null; } if (_sound.IsEndOfRegion(track.SoundDesc, track.CurRegion)) { SwitchToNextRegion(track); if (track.Stream == null) // Seems we reached the end of the stream { break; } } feedSize -= curFeedSize; Debug.Assert(feedSize >= 0); } while (feedSize != 0); } if (_mixer.IsReady) { _mixer.SetChannelVolume(track.MixChanHandle, track.Volume); _mixer.SetChannelBalance(track.MixChanHandle, track.Pan); } } } } }