Decompiled source of SentinelaFuracao v1.0.0
plugins/SentrySound/NLayer.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using NLayer.Decoder; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Mark Heath, Andrew Ward")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Fully Managed MPEG 1 & 2 Decoder for Layers 1, 2, & 3")] [assembly: AssemblyFileVersion("1.16.0.0")] [assembly: AssemblyInformationalVersion("1.16.0+c88b0d8abfa15c1e506106931ea8410170dc6326")] [assembly: AssemblyProduct("NLayer")] [assembly: AssemblyTitle("NLayer")] [assembly: AssemblyVersion("1.16.0.0")] namespace NLayer { public enum MpegVersion { Unknown = 0, Version1 = 10, Version2 = 20, Version25 = 25 } public enum MpegLayer { Unknown, LayerI, LayerII, LayerIII } public enum MpegChannelMode { Stereo, JointStereo, DualChannel, Mono } public enum StereoMode { Both, LeftOnly, RightOnly, DownmixToMono } public interface IMpegFrame { int SampleRate { get; } int SampleRateIndex { get; } int FrameLength { get; } int BitRate { get; } MpegVersion Version { get; } MpegLayer Layer { get; } MpegChannelMode ChannelMode { get; } int ChannelModeExtension { get; } int SampleCount { get; } int BitRateIndex { get; } bool IsCopyrighted { get; } bool HasCrc { get; } bool IsCorrupted { get; } void Reset(); int ReadBits(int bitCount); } public class MpegFile : IDisposable { private Stream _stream; private bool _closeStream; private bool _eofFound; private MpegStreamReader _reader; private MpegFrameDecoder _decoder; private object _seekLock = new object(); private long _position; private float[] _readBuf = new float[2304]; private int _readBufLen; private int _readBufOfs; public int SampleRate => _reader.SampleRate; public int Channels => _reader.Channels; public bool CanSeek => _reader.CanSeek; public long Length => _reader.SampleCount * _reader.Channels * 4; public TimeSpan Duration { get { long sampleCount = _reader.SampleCount; if (sampleCount == -1) { return TimeSpan.Zero; } return TimeSpan.FromSeconds((double)sampleCount / (double)_reader.SampleRate); } } public long Position { get { return _position; } set { if (!_reader.CanSeek) { throw new InvalidOperationException("Cannot Seek!"); } if (value < 0) { throw new ArgumentOutOfRangeException("value"); } long num = value / 4 / _reader.Channels; int num2 = 0; if (num >= _reader.FirstFrameSampleCount) { num2 = _reader.FirstFrameSampleCount; num -= num2; } lock (_seekLock) { long num3 = _reader.SeekTo(num); if (num3 == -1) { throw new ArgumentOutOfRangeException("value"); } _decoder.Reset(); if (num2 != 0) { _decoder.DecodeFrame(_reader.NextFrame(), _readBuf, 0); num3 += num2; } _position = num3 * 4 * _reader.Channels; _eofFound = false; _readBufOfs = (_readBufLen = 0); } } } public TimeSpan Time { get { return TimeSpan.FromSeconds((double)_position / 4.0 / (double)_reader.Channels / (double)_reader.SampleRate); } set { Position = (long)(value.TotalSeconds * (double)_reader.SampleRate * (double)_reader.Channels * 4.0); } } public StereoMode StereoMode { get { return _decoder.StereoMode; } set { _decoder.StereoMode = value; } } public MpegFile(string fileName) { Init(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), closeStream: true); } public MpegFile(Stream stream) { Init(stream, closeStream: false); } private void Init(Stream stream, bool closeStream) { _stream = stream; _closeStream = closeStream; _reader = new MpegStreamReader(_stream); _decoder = new MpegFrameDecoder(); } public void Dispose() { if (_closeStream) { _stream.Dispose(); _closeStream = false; } } public void SetEQ(float[] eq) { _decoder.SetEQ(eq); } public int ReadSamples(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } count -= count % 4; return ReadSamplesImpl(buffer, index, count, 32); } public int ReadSamples(float[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } return ReadSamplesImpl(buffer, index * 4, count * 4, 32) / 4; } public int ReadSamplesInt16(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length * 2) { throw new ArgumentOutOfRangeException("index"); } return ReadSamplesImpl(buffer, index, count, 16) * 2 / 4; } public int ReadSamplesInt8(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length * 4) { throw new ArgumentOutOfRangeException("index"); } return ReadSamplesImpl(buffer, index, count, 8) / 4; } private int ReadSamplesImpl(Array buffer, int index, int count, int bitDepth) { int num = 0; lock (_seekLock) { while (count > 0) { if (_readBufLen > _readBufOfs) { int num2 = _readBufLen - _readBufOfs; if (num2 > count) { num2 = count; } if (bitDepth == 32) { Buffer.BlockCopy(_readBuf, _readBufOfs, buffer, index, num2); } else { for (int i = 0; i < num2 / 4; i++) { switch (bitDepth) { case 8: buffer.SetValue((byte)Math.Round(127.5f * _readBuf[_readBufOfs / 4 + i] + 127.5f), index / 4 + i); break; case 16: { int num3 = (int)Math.Round(32767.5f * _readBuf[_readBufOfs / 4 + i] - 0.5f); if (num3 < 0) { num3 += 65536; } buffer.SetValue((byte)(num3 % 256), 2 * (index / 4 + i)); buffer.SetValue((byte)(num3 / 256), 2 * (index / 4 + i) + 1); break; } } } } num += num2; count -= num2; index += num2; _position += num2; _readBufOfs += num2; if (_readBufOfs == _readBufLen) { _readBufLen = 0; } } if (_readBufLen != 0) { continue; } if (_eofFound) { break; } MpegFrame mpegFrame = _reader.NextFrame(); if (mpegFrame == null) { _eofFound = true; break; } try { _readBufLen = _decoder.DecodeFrame(mpegFrame, _readBuf, 0) * 4; _readBufOfs = 0; } catch (InvalidDataException) { _decoder.Reset(); _readBufOfs = (_readBufLen = 0); } catch (EndOfStreamException) { _eofFound = true; break; } finally { mpegFrame.ClearBuffer(); } } } return num; } } public class MpegFrameDecoder { private LayerIDecoder _layerIDecoder; private LayerIIDecoder _layerIIDecoder; private LayerIIIDecoder _layerIIIDecoder; private float[] _eqFactors; private float[] _ch0; private float[] _ch1; public StereoMode StereoMode { get; set; } public MpegFrameDecoder() { _ch0 = new float[1152]; _ch1 = new float[1152]; } public void SetEQ(float[] eq) { if (eq != null) { float[] array = new float[32]; for (int i = 0; i < eq.Length; i++) { array[i] = (float)Math.Pow(2.0, eq[i] / 6f); } _eqFactors = array; } else { _eqFactors = null; } } public int DecodeFrame(IMpegFrame frame, byte[] dest, int destOffset) { if (frame == null) { throw new ArgumentNullException("frame"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (destOffset % 4 != 0) { throw new ArgumentException("Must be an even multiple of 4", "destOffset"); } if ((dest.Length - destOffset) / 4 < ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) * frame.SampleCount) { throw new ArgumentException("Buffer not large enough! Must be big enough to hold the frame's entire output. This is up to 9,216 bytes.", "dest"); } return DecodeFrameImpl(frame, dest, destOffset / 4) * 4; } public int DecodeFrame(IMpegFrame frame, float[] dest, int destOffset) { if (frame == null) { throw new ArgumentNullException("frame"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (dest.Length - destOffset < ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) * frame.SampleCount) { throw new ArgumentException("Buffer not large enough! Must be big enough to hold the frame's entire output. This is up to 2,304 elements.", "dest"); } return DecodeFrameImpl(frame, dest, destOffset); } private int DecodeFrameImpl(IMpegFrame frame, Array dest, int destOffset) { frame.Reset(); LayerDecoderBase layerDecoderBase = null; switch (frame.Layer) { case MpegLayer.LayerI: if (_layerIDecoder == null) { _layerIDecoder = new LayerIDecoder(); } layerDecoderBase = _layerIDecoder; break; case MpegLayer.LayerII: if (_layerIIDecoder == null) { _layerIIDecoder = new LayerIIDecoder(); } layerDecoderBase = _layerIIDecoder; break; case MpegLayer.LayerIII: if (_layerIIIDecoder == null) { _layerIIIDecoder = new LayerIIIDecoder(); } layerDecoderBase = _layerIIIDecoder; break; } if (layerDecoderBase != null) { layerDecoderBase.SetEQ(_eqFactors); layerDecoderBase.StereoMode = StereoMode; int num = layerDecoderBase.DecodeFrame(frame, _ch0, _ch1); if (frame.ChannelMode == MpegChannelMode.Mono) { Buffer.BlockCopy(_ch0, 0, dest, destOffset * 4, num * 4); } else { for (int i = 0; i < num; i++) { Buffer.BlockCopy(_ch0, i * 4, dest, destOffset * 4, 4); destOffset++; Buffer.BlockCopy(_ch1, i * 4, dest, destOffset * 4, 4); destOffset++; } num *= 2; } return num; } return 0; } public void Reset() { if (_layerIDecoder != null) { _layerIDecoder.ResetForSeek(); } if (_layerIIDecoder != null) { _layerIIDecoder.ResetForSeek(); } if (_layerIIIDecoder != null) { _layerIIIDecoder.ResetForSeek(); } } } } namespace NLayer.Decoder { internal class BitReservoir { private byte[] _buf = new byte[8192]; private int _start; private int _end = -1; private int _bitsLeft; private long _bitsRead; public int BitsAvailable { get { if (_bitsLeft > 0) { return (_end + _buf.Length - _start) % _buf.Length * 8 + _bitsLeft; } return 0; } } public long BitsRead => _bitsRead; private static int GetSlots(IMpegFrame frame) { int num = frame.FrameLength - 4; if (frame.HasCrc) { num -= 2; } if (frame.Version == MpegVersion.Version1 && frame.ChannelMode != MpegChannelMode.Mono) { return num - 32; } if (frame.Version > MpegVersion.Version1 && frame.ChannelMode == MpegChannelMode.Mono) { return num - 9; } return num - 17; } public bool AddBits(IMpegFrame frame, int overlap) { int end = _end; int num = GetSlots(frame); while (--num >= 0) { int num2 = frame.ReadBits(8); if (num2 == -1) { throw new InvalidDataException("Frame did not have enough bytes!"); } _buf[++_end] = (byte)num2; if (_end == _buf.Length - 1) { _end = -1; } } _bitsLeft = 8; if (end == -1) { return overlap == 0; } if ((end + 1 - _start + _buf.Length) % _buf.Length >= overlap) { _start = (end + 1 - overlap + _buf.Length) % _buf.Length; return true; } _start = end + overlap; return false; } public int GetBits(int count) { int readCount; int result = TryPeekBits(count, out readCount); if (readCount < count) { throw new InvalidDataException("Reservoir did not have enough bytes!"); } SkipBits(count); return result; } public int Get1Bit() { if (_bitsLeft == 0) { throw new InvalidDataException("Reservoir did not have enough bytes!"); } _bitsLeft--; _bitsRead++; int result = (_buf[_start] >> _bitsLeft) & 1; if (_bitsLeft == 0 && (_start = (_start + 1) % _buf.Length) != _end + 1) { _bitsLeft = 8; } return result; } public int TryPeekBits(int count, out int readCount) { if (count < 0 || count > 32) { throw new ArgumentOutOfRangeException("count", "Must return between 0 and 32 bits!"); } if (_bitsLeft == 0 || count == 0) { readCount = 0; return 0; } int num = _buf[_start]; if (count < _bitsLeft) { num >>= _bitsLeft - count; num &= (1 << count) - 1; readCount = count; return num; } num &= (1 << _bitsLeft) - 1; count -= _bitsLeft; readCount = _bitsLeft; int num2 = _start; while (count > 0 && (num2 = (num2 + 1) % _buf.Length) != _end + 1) { int num3 = Math.Min(count, 8); num <<= num3; num |= _buf[num2] >> (8 - num3) % 8; count -= num3; readCount += num3; } return num; } public void SkipBits(int count) { if (count > 0) { if (count > BitsAvailable) { throw new ArgumentOutOfRangeException("count"); } int num = 8 - _bitsLeft + count; _start = (num / 8 + _start) % _buf.Length; _bitsLeft = 8 - num % 8; _bitsRead += count; } } public void RewindBits(int count) { _bitsLeft += count; _bitsRead -= count; while (_bitsLeft > 8) { _start--; _bitsLeft -= 8; } while (_start < 0) { _start += _buf.Length; } } public void FlushBits() { if (_bitsLeft < 8) { SkipBits(_bitsLeft); } } public void Reset() { _start = 0; _end = -1; _bitsLeft = 0; } } internal abstract class FrameBase { private static int _totalAllocation; private MpegStreamReader _reader; private byte[] _savedBuffer; internal static int TotalAllocation => Interlocked.CompareExchange(ref _totalAllocation, 0, 0); internal long Offset { get; private set; } internal int Length { get; set; } internal bool Validate(long offset, MpegStreamReader reader) { Offset = offset; _reader = reader; int num = Validate(); if (num > 0) { Length = num; return true; } return false; } protected int Read(int offset, byte[] buffer) { return Read(offset, buffer, 0, buffer.Length); } protected int Read(int offset, byte[] buffer, int index, int count) { if (_savedBuffer != null) { if (index < 0 || index + count > buffer.Length) { return 0; } if (offset < 0 || offset >= _savedBuffer.Length) { return 0; } if (offset + count > _savedBuffer.Length) { count = _savedBuffer.Length - index; } Array.Copy(_savedBuffer, offset, buffer, index, count); return count; } return _reader.Read(Offset + offset, buffer, index, count); } protected int ReadByte(int offset) { if (_savedBuffer != null) { if (offset < 0) { throw new ArgumentOutOfRangeException(); } if (offset >= _savedBuffer.Length) { return -1; } return _savedBuffer[offset]; } return _reader.ReadByte(Offset + offset); } protected abstract int Validate(); internal void SaveBuffer() { _savedBuffer = new byte[Length]; _reader.Read(Offset, _savedBuffer, 0, Length); Interlocked.Add(ref _totalAllocation, Length); } internal void ClearBuffer() { Interlocked.Add(ref _totalAllocation, -Length); _savedBuffer = null; } internal virtual void Parse() { } } internal class Huffman { private class HuffmanListNode { internal byte Value; internal int Length; internal int Bits; internal int Mask; internal HuffmanListNode Next; } private static readonly byte[][,] _codeTables; private static readonly float[] _floatLookup; private static HuffmanListNode[] _llCache; private static int[] _llCacheMaxBits; private static readonly int[] LIN_BITS; static Huffman() { _codeTables = new byte[17][,] { new byte[7, 2] { { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 } }, new byte[17, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 } }, new byte[17, 2] { { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 2, 1 }, { 0, 16 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 } }, new byte[31, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 2, 1 }, { 0, 3 }, { 0, 19 }, { 2, 1 }, { 0, 49 }, { 2, 1 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 0, 51 } }, new byte[31, 2] { { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 16 }, { 0, 17 }, { 6, 1 }, { 2, 1 }, { 0, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 6, 1 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 48 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 2, 1 }, { 0, 3 }, { 0, 51 } }, new byte[71, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 8, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 0, 33 }, { 18, 1 }, { 6, 1 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 3 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 0, 4 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 65 }, { 2, 1 }, { 0, 20 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 51 }, { 0, 67 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 52 }, { 0, 5 }, { 0, 81 }, { 6, 1 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 53 }, { 4, 1 }, { 2, 1 }, { 0, 83 }, { 0, 84 }, { 2, 1 }, { 0, 69 }, { 0, 85 } }, new byte[71, 2] { { 6, 1 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 34 }, { 4, 1 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 2, 1 }, { 0, 65 }, { 2, 1 }, { 0, 20 }, { 0, 66 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 36 }, { 2, 1 }, { 0, 51 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 0, 81 }, { 6, 1 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 5 }, { 0, 82 }, { 6, 1 }, { 2, 1 }, { 0, 37 }, { 2, 1 }, { 0, 68 }, { 0, 53 }, { 2, 1 }, { 0, 83 }, { 2, 1 }, { 0, 69 }, { 2, 1 }, { 0, 84 }, { 0, 85 } }, new byte[71, 2] { { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 2 }, { 0, 34 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 0, 49 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 65 }, { 0, 20 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 51 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 80 }, { 0, 67 }, { 2, 1 }, { 0, 52 }, { 0, 81 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 21 }, { 0, 82 }, { 2, 1 }, { 0, 37 }, { 0, 68 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 84 }, { 0, 83 }, { 2, 1 }, { 0, 53 }, { 2, 1 }, { 0, 69 }, { 0, 85 } }, new byte[127, 2] { { 2, 1 }, { 0, 0 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 10, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 28, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 3 }, { 0, 50 }, { 2, 1 }, { 0, 35 }, { 0, 64 }, { 4, 1 }, { 2, 1 }, { 0, 65 }, { 0, 20 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 51 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 28, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 80 }, { 0, 5 }, { 0, 96 }, { 2, 1 }, { 0, 97 }, { 0, 22 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 0, 81 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 38 }, { 0, 54 }, { 0, 113 }, { 20, 1 }, { 8, 1 }, { 2, 1 }, { 0, 23 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 0, 6 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 53 }, { 0, 69 }, { 0, 98 }, { 2, 1 }, { 0, 112 }, { 2, 1 }, { 0, 7 }, { 0, 100 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 114 }, { 0, 39 }, { 6, 1 }, { 2, 1 }, { 0, 99 }, { 2, 1 }, { 0, 84 }, { 0, 85 }, { 2, 1 }, { 0, 70 }, { 0, 115 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 55 }, { 0, 101 }, { 2, 1 }, { 0, 86 }, { 0, 116 }, { 6, 1 }, { 2, 1 }, { 0, 71 }, { 2, 1 }, { 0, 102 }, { 0, 117 }, { 4, 1 }, { 2, 1 }, { 0, 87 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 119 } }, new byte[127, 2] { { 6, 1 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 8, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 0, 18 }, { 24, 1 }, { 8, 1 }, { 2, 1 }, { 0, 33 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 2, 1 }, { 0, 65 }, { 0, 20 }, { 30, 1 }, { 16, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 4, 1 }, { 2, 1 }, { 0, 51 }, { 0, 67 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 52 }, { 0, 81 }, { 0, 97 }, { 6, 1 }, { 2, 1 }, { 0, 22 }, { 2, 1 }, { 0, 6 }, { 0, 38 }, { 2, 1 }, { 0, 98 }, { 2, 1 }, { 0, 21 }, { 2, 1 }, { 0, 5 }, { 0, 82 }, { 16, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 37 }, { 0, 68 }, { 0, 96 }, { 2, 1 }, { 0, 99 }, { 0, 54 }, { 4, 1 }, { 2, 1 }, { 0, 112 }, { 0, 23 }, { 0, 113 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 7 }, { 0, 100 }, { 0, 114 }, { 2, 1 }, { 0, 39 }, { 4, 1 }, { 2, 1 }, { 0, 83 }, { 0, 53 }, { 2, 1 }, { 0, 84 }, { 0, 69 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 70 }, { 0, 115 }, { 2, 1 }, { 0, 55 }, { 2, 1 }, { 0, 101 }, { 0, 86 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 85 }, { 0, 87 }, { 0, 116 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 119 } }, new byte[127, 2] { { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 16, 1 }, { 4, 1 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 49 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 48 }, { 2, 1 }, { 0, 3 }, { 0, 64 }, { 26, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 2, 1 }, { 0, 65 }, { 0, 51 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 20 }, { 0, 66 }, { 2, 1 }, { 0, 36 }, { 2, 1 }, { 0, 4 }, { 0, 80 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 2, 1 }, { 0, 81 }, { 0, 21 }, { 28, 1 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 2, 1 }, { 0, 83 }, { 0, 53 }, { 4, 1 }, { 2, 1 }, { 0, 96 }, { 0, 22 }, { 0, 97 }, { 4, 1 }, { 2, 1 }, { 0, 98 }, { 0, 38 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 6 }, { 0, 68 }, { 2, 1 }, { 0, 84 }, { 0, 69 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 99 }, { 0, 54 }, { 4, 1 }, { 2, 1 }, { 0, 112 }, { 0, 7 }, { 0, 113 }, { 4, 1 }, { 2, 1 }, { 0, 23 }, { 0, 100 }, { 2, 1 }, { 0, 70 }, { 0, 114 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 39 }, { 2, 1 }, { 0, 85 }, { 0, 115 }, { 2, 1 }, { 0, 55 }, { 0, 86 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 101 }, { 0, 116 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 119 } }, new byte[511, 2] { { 2, 1 }, { 0, 0 }, { 6, 1 }, { 2, 1 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 28, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 34 }, { 0, 48 }, { 2, 1 }, { 0, 3 }, { 0, 49 }, { 6, 1 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 0, 65 }, { 70, 1 }, { 28, 1 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 20 }, { 2, 1 }, { 0, 51 }, { 0, 66 }, { 4, 1 }, { 2, 1 }, { 0, 36 }, { 0, 80 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 4, 1 }, { 2, 1 }, { 0, 81 }, { 0, 21 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 82 }, { 2, 1 }, { 0, 37 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 2, 1 }, { 0, 97 }, { 0, 22 }, { 4, 1 }, { 2, 1 }, { 0, 128 }, { 0, 8 }, { 0, 129 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 53 }, { 0, 98 }, { 2, 1 }, { 0, 38 }, { 0, 84 }, { 4, 1 }, { 2, 1 }, { 0, 69 }, { 0, 99 }, { 2, 1 }, { 0, 54 }, { 0, 112 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 7 }, { 0, 85 }, { 0, 113 }, { 2, 1 }, { 0, 23 }, { 2, 1 }, { 0, 39 }, { 0, 55 }, { 72, 1 }, { 24, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 24 }, { 0, 130 }, { 2, 1 }, { 0, 40 }, { 4, 1 }, { 2, 1 }, { 0, 100 }, { 0, 70 }, { 0, 114 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 132 }, { 0, 72 }, { 2, 1 }, { 0, 144 }, { 0, 9 }, { 2, 1 }, { 0, 145 }, { 0, 25 }, { 24, 1 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 115 }, { 0, 101 }, { 2, 1 }, { 0, 86 }, { 0, 116 }, { 4, 1 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 0, 131 }, { 6, 1 }, { 2, 1 }, { 0, 56 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 146 }, { 0, 41 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 103 }, { 0, 133 }, { 2, 1 }, { 0, 88 }, { 0, 57 }, { 2, 1 }, { 0, 147 }, { 2, 1 }, { 0, 73 }, { 0, 134 }, { 6, 1 }, { 2, 1 }, { 0, 160 }, { 2, 1 }, { 0, 104 }, { 0, 10 }, { 2, 1 }, { 0, 161 }, { 0, 26 }, { 68, 1 }, { 24, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 162 }, { 0, 42 }, { 4, 1 }, { 2, 1 }, { 0, 149 }, { 0, 89 }, { 2, 1 }, { 0, 163 }, { 0, 58 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 74 }, { 0, 150 }, { 2, 1 }, { 0, 176 }, { 0, 11 }, { 2, 1 }, { 0, 177 }, { 0, 27 }, { 20, 1 }, { 8, 1 }, { 2, 1 }, { 0, 178 }, { 4, 1 }, { 2, 1 }, { 0, 118 }, { 0, 119 }, { 0, 148 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 135 }, { 0, 120 }, { 0, 164 }, { 4, 1 }, { 2, 1 }, { 0, 105 }, { 0, 165 }, { 0, 43 }, { 12, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 90 }, { 0, 136 }, { 0, 179 }, { 2, 1 }, { 0, 59 }, { 2, 1 }, { 0, 121 }, { 0, 166 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 106 }, { 0, 180 }, { 0, 192 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 152 }, { 0, 193 }, { 60, 1 }, { 22, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 28 }, { 2, 1 }, { 0, 137 }, { 0, 181 }, { 2, 1 }, { 0, 91 }, { 0, 194 }, { 4, 1 }, { 2, 1 }, { 0, 44 }, { 0, 60 }, { 4, 1 }, { 2, 1 }, { 0, 182 }, { 0, 107 }, { 2, 1 }, { 0, 196 }, { 0, 76 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 168 }, { 0, 138 }, { 2, 1 }, { 0, 208 }, { 0, 13 }, { 2, 1 }, { 0, 209 }, { 2, 1 }, { 0, 75 }, { 2, 1 }, { 0, 151 }, { 0, 167 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 195 }, { 2, 1 }, { 0, 122 }, { 0, 153 }, { 4, 1 }, { 2, 1 }, { 0, 197 }, { 0, 92 }, { 0, 183 }, { 4, 1 }, { 2, 1 }, { 0, 29 }, { 0, 210 }, { 2, 1 }, { 0, 45 }, { 2, 1 }, { 0, 123 }, { 0, 211 }, { 52, 1 }, { 28, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 4, 1 }, { 2, 1 }, { 0, 108 }, { 0, 169 }, { 2, 1 }, { 0, 154 }, { 0, 212 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 184 }, { 0, 139 }, { 2, 1 }, { 0, 77 }, { 0, 199 }, { 4, 1 }, { 2, 1 }, { 0, 124 }, { 0, 213 }, { 2, 1 }, { 0, 93 }, { 0, 224 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 225 }, { 0, 30 }, { 4, 1 }, { 2, 1 }, { 0, 14 }, { 0, 46 }, { 0, 226 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 227 }, { 0, 109 }, { 2, 1 }, { 0, 140 }, { 0, 228 }, { 4, 1 }, { 2, 1 }, { 0, 229 }, { 0, 186 }, { 0, 240 }, { 38, 1 }, { 16, 1 }, { 4, 1 }, { 2, 1 }, { 0, 241 }, { 0, 31 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 170 }, { 0, 155 }, { 0, 185 }, { 2, 1 }, { 0, 62 }, { 2, 1 }, { 0, 214 }, { 0, 200 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 78 }, { 2, 1 }, { 0, 215 }, { 0, 125 }, { 2, 1 }, { 0, 171 }, { 2, 1 }, { 0, 94 }, { 0, 201 }, { 6, 1 }, { 2, 1 }, { 0, 15 }, { 2, 1 }, { 0, 156 }, { 0, 110 }, { 2, 1 }, { 0, 242 }, { 0, 47 }, { 32, 1 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 216 }, { 0, 141 }, { 0, 63 }, { 6, 1 }, { 2, 1 }, { 0, 243 }, { 2, 1 }, { 0, 230 }, { 0, 202 }, { 2, 1 }, { 0, 244 }, { 0, 79 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 187 }, { 0, 172 }, { 2, 1 }, { 0, 231 }, { 0, 245 }, { 4, 1 }, { 2, 1 }, { 0, 217 }, { 0, 157 }, { 2, 1 }, { 0, 95 }, { 0, 232 }, { 30, 1 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 111 }, { 2, 1 }, { 0, 246 }, { 0, 203 }, { 4, 1 }, { 2, 1 }, { 0, 188 }, { 0, 173 }, { 0, 218 }, { 8, 1 }, { 2, 1 }, { 0, 247 }, { 4, 1 }, { 2, 1 }, { 0, 126 }, { 0, 127 }, { 0, 142 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 158 }, { 0, 174 }, { 0, 204 }, { 2, 1 }, { 0, 248 }, { 0, 143 }, { 18, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 219 }, { 0, 189 }, { 2, 1 }, { 0, 234 }, { 0, 249 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 235 }, { 2, 1 }, { 0, 190 }, { 2, 1 }, { 0, 205 }, { 0, 250 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 221 }, { 0, 236 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 233 }, { 0, 175 }, { 0, 220 }, { 2, 1 }, { 0, 206 }, { 0, 251 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 191 }, { 0, 222 }, { 2, 1 }, { 0, 207 }, { 0, 238 }, { 4, 1 }, { 2, 1 }, { 0, 223 }, { 0, 239 }, { 2, 1 }, { 0, 255 }, { 2, 1 }, { 0, 237 }, { 2, 1 }, { 0, 253 }, { 2, 1 }, { 0, 252 }, { 0, 254 } }, new byte[511, 2] { { 16, 1 }, { 6, 1 }, { 2, 1 }, { 0, 0 }, { 2, 1 }, { 0, 16 }, { 0, 1 }, { 2, 1 }, { 0, 17 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 50, 1 }, { 16, 1 }, { 6, 1 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 49 }, { 6, 1 }, { 2, 1 }, { 0, 19 }, { 2, 1 }, { 0, 3 }, { 0, 64 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 20 }, { 0, 65 }, { 4, 1 }, { 2, 1 }, { 0, 51 }, { 0, 66 }, { 2, 1 }, { 0, 36 }, { 0, 67 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 52 }, { 2, 1 }, { 0, 80 }, { 0, 5 }, { 2, 1 }, { 0, 81 }, { 0, 21 }, { 4, 1 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 0, 97 }, { 90, 1 }, { 36, 1 }, { 18, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 53 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 2, 1 }, { 0, 22 }, { 0, 98 }, { 4, 1 }, { 2, 1 }, { 0, 38 }, { 0, 84 }, { 2, 1 }, { 0, 69 }, { 0, 99 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 54 }, { 2, 1 }, { 0, 112 }, { 0, 7 }, { 2, 1 }, { 0, 113 }, { 0, 85 }, { 4, 1 }, { 2, 1 }, { 0, 23 }, { 0, 100 }, { 2, 1 }, { 0, 114 }, { 0, 39 }, { 24, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 70 }, { 0, 115 }, { 2, 1 }, { 0, 55 }, { 0, 101 }, { 4, 1 }, { 2, 1 }, { 0, 86 }, { 0, 128 }, { 2, 1 }, { 0, 8 }, { 0, 116 }, { 4, 1 }, { 2, 1 }, { 0, 129 }, { 0, 24 }, { 2, 1 }, { 0, 130 }, { 0, 40 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 71 }, { 0, 102 }, { 2, 1 }, { 0, 131 }, { 0, 56 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 132 }, { 0, 72 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 144 }, { 0, 25 }, { 0, 145 }, { 4, 1 }, { 2, 1 }, { 0, 146 }, { 0, 118 }, { 2, 1 }, { 0, 103 }, { 0, 41 }, { 92, 1 }, { 36, 1 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 133 }, { 0, 88 }, { 4, 1 }, { 2, 1 }, { 0, 9 }, { 0, 119 }, { 0, 147 }, { 4, 1 }, { 2, 1 }, { 0, 57 }, { 0, 148 }, { 2, 1 }, { 0, 73 }, { 0, 134 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 104 }, { 2, 1 }, { 0, 160 }, { 0, 10 }, { 2, 1 }, { 0, 161 }, { 0, 26 }, { 4, 1 }, { 2, 1 }, { 0, 162 }, { 0, 42 }, { 2, 1 }, { 0, 149 }, { 0, 89 }, { 26, 1 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 163 }, { 2, 1 }, { 0, 58 }, { 0, 135 }, { 4, 1 }, { 2, 1 }, { 0, 120 }, { 0, 164 }, { 2, 1 }, { 0, 74 }, { 0, 150 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 105 }, { 0, 176 }, { 0, 177 }, { 4, 1 }, { 2, 1 }, { 0, 27 }, { 0, 165 }, { 0, 178 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 90 }, { 0, 43 }, { 2, 1 }, { 0, 136 }, { 0, 151 }, { 2, 1 }, { 0, 179 }, { 2, 1 }, { 0, 121 }, { 0, 59 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 106 }, { 0, 180 }, { 2, 1 }, { 0, 75 }, { 0, 193 }, { 4, 1 }, { 2, 1 }, { 0, 152 }, { 0, 137 }, { 2, 1 }, { 0, 28 }, { 0, 181 }, { 80, 1 }, { 34, 1 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 91 }, { 0, 44 }, { 0, 194 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 11 }, { 0, 192 }, { 0, 166 }, { 2, 1 }, { 0, 167 }, { 0, 122 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 195 }, { 0, 60 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 153 }, { 0, 182 }, { 4, 1 }, { 2, 1 }, { 0, 107 }, { 0, 196 }, { 2, 1 }, { 0, 76 }, { 0, 168 }, { 20, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 138 }, { 0, 197 }, { 4, 1 }, { 2, 1 }, { 0, 208 }, { 0, 92 }, { 0, 209 }, { 4, 1 }, { 2, 1 }, { 0, 183 }, { 0, 123 }, { 2, 1 }, { 0, 29 }, { 2, 1 }, { 0, 13 }, { 0, 45 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 210 }, { 0, 211 }, { 4, 1 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 2, 1 }, { 0, 108 }, { 0, 169 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 154 }, { 0, 184 }, { 0, 212 }, { 4, 1 }, { 2, 1 }, { 0, 139 }, { 0, 77 }, { 2, 1 }, { 0, 199 }, { 0, 124 }, { 68, 1 }, { 34, 1 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 213 }, { 0, 93 }, { 4, 1 }, { 2, 1 }, { 0, 224 }, { 0, 14 }, { 0, 225 }, { 4, 1 }, { 2, 1 }, { 0, 30 }, { 0, 226 }, { 2, 1 }, { 0, 170 }, { 0, 46 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 185 }, { 0, 155 }, { 2, 1 }, { 0, 227 }, { 0, 214 }, { 4, 1 }, { 2, 1 }, { 0, 109 }, { 0, 62 }, { 2, 1 }, { 0, 200 }, { 0, 140 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 228 }, { 0, 78 }, { 2, 1 }, { 0, 215 }, { 0, 125 }, { 4, 1 }, { 2, 1 }, { 0, 229 }, { 0, 186 }, { 2, 1 }, { 0, 171 }, { 0, 94 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 201 }, { 0, 156 }, { 2, 1 }, { 0, 241 }, { 0, 31 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 240 }, { 0, 110 }, { 0, 242 }, { 2, 1 }, { 0, 47 }, { 0, 230 }, { 38, 1 }, { 18, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 216 }, { 0, 243 }, { 2, 1 }, { 0, 63 }, { 0, 244 }, { 6, 1 }, { 2, 1 }, { 0, 79 }, { 2, 1 }, { 0, 141 }, { 0, 217 }, { 2, 1 }, { 0, 187 }, { 0, 202 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 172 }, { 0, 231 }, { 2, 1 }, { 0, 126 }, { 0, 245 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 157 }, { 0, 95 }, { 2, 1 }, { 0, 232 }, { 0, 142 }, { 2, 1 }, { 0, 246 }, { 0, 203 }, { 34, 1 }, { 18, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 15 }, { 0, 174 }, { 0, 111 }, { 2, 1 }, { 0, 188 }, { 0, 218 }, { 4, 1 }, { 2, 1 }, { 0, 173 }, { 0, 247 }, { 2, 1 }, { 0, 127 }, { 0, 233 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 158 }, { 0, 204 }, { 2, 1 }, { 0, 248 }, { 0, 143 }, { 4, 1 }, { 2, 1 }, { 0, 219 }, { 0, 189 }, { 2, 1 }, { 0, 234 }, { 0, 249 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 220 }, { 2, 1 }, { 0, 205 }, { 0, 235 }, { 4, 1 }, { 2, 1 }, { 0, 190 }, { 0, 250 }, { 2, 1 }, { 0, 175 }, { 0, 221 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 236 }, { 0, 206 }, { 0, 251 }, { 4, 1 }, { 2, 1 }, { 0, 191 }, { 0, 237 }, { 2, 1 }, { 0, 222 }, { 0, 252 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 207 }, { 0, 253 }, { 0, 238 }, { 4, 1 }, { 2, 1 }, { 0, 223 }, { 0, 254 }, { 2, 1 }, { 0, 239 }, { 0, 255 } }, new byte[511, 2] { { 2, 1 }, { 0, 0 }, { 6, 1 }, { 2, 1 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 42, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 2, 1 }, { 0, 33 }, { 0, 18 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 0, 65 }, { 6, 1 }, { 2, 1 }, { 0, 20 }, { 2, 1 }, { 0, 51 }, { 0, 66 }, { 4, 1 }, { 2, 1 }, { 0, 36 }, { 0, 80 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 138, 1 }, { 40, 1 }, { 16, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 5 }, { 0, 21 }, { 0, 81 }, { 4, 1 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 53 }, { 0, 83 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 0, 97 }, { 2, 1 }, { 0, 22 }, { 0, 98 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 38 }, { 0, 84 }, { 2, 1 }, { 0, 69 }, { 0, 99 }, { 4, 1 }, { 2, 1 }, { 0, 54 }, { 0, 112 }, { 0, 113 }, { 40, 1 }, { 18, 1 }, { 8, 1 }, { 2, 1 }, { 0, 23 }, { 2, 1 }, { 0, 7 }, { 2, 1 }, { 0, 85 }, { 0, 100 }, { 4, 1 }, { 2, 1 }, { 0, 114 }, { 0, 39 }, { 4, 1 }, { 2, 1 }, { 0, 70 }, { 0, 101 }, { 0, 115 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 55 }, { 2, 1 }, { 0, 86 }, { 0, 8 }, { 2, 1 }, { 0, 128 }, { 0, 129 }, { 6, 1 }, { 2, 1 }, { 0, 24 }, { 2, 1 }, { 0, 116 }, { 0, 71 }, { 2, 1 }, { 0, 130 }, { 2, 1 }, { 0, 40 }, { 0, 102 }, { 24, 1 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 131 }, { 0, 56 }, { 2, 1 }, { 0, 117 }, { 0, 132 }, { 4, 1 }, { 2, 1 }, { 0, 72 }, { 0, 144 }, { 0, 145 }, { 6, 1 }, { 2, 1 }, { 0, 25 }, { 2, 1 }, { 0, 9 }, { 0, 118 }, { 2, 1 }, { 0, 146 }, { 0, 41 }, { 14, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 133 }, { 0, 88 }, { 2, 1 }, { 0, 147 }, { 0, 57 }, { 4, 1 }, { 2, 1 }, { 0, 160 }, { 0, 10 }, { 0, 26 }, { 8, 1 }, { 2, 1 }, { 0, 162 }, { 2, 1 }, { 0, 103 }, { 2, 1 }, { 0, 87 }, { 0, 73 }, { 6, 1 }, { 2, 1 }, { 0, 148 }, { 2, 1 }, { 0, 119 }, { 0, 134 }, { 2, 1 }, { 0, 161 }, { 2, 1 }, { 0, 104 }, { 0, 149 }, { 220, 1 }, { 126, 1 }, { 50, 1 }, { 26, 1 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 42 }, { 2, 1 }, { 0, 89 }, { 0, 58 }, { 2, 1 }, { 0, 163 }, { 2, 1 }, { 0, 135 }, { 0, 120 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 164 }, { 0, 74 }, { 2, 1 }, { 0, 150 }, { 0, 105 }, { 4, 1 }, { 2, 1 }, { 0, 176 }, { 0, 11 }, { 0, 177 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 27 }, { 0, 178 }, { 2, 1 }, { 0, 43 }, { 2, 1 }, { 0, 165 }, { 0, 90 }, { 6, 1 }, { 2, 1 }, { 0, 179 }, { 2, 1 }, { 0, 166 }, { 0, 106 }, { 4, 1 }, { 2, 1 }, { 0, 180 }, { 0, 75 }, { 2, 1 }, { 0, 12 }, { 0, 193 }, { 30, 1 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 181 }, { 0, 194 }, { 0, 44 }, { 4, 1 }, { 2, 1 }, { 0, 167 }, { 0, 195 }, { 2, 1 }, { 0, 107 }, { 0, 196 }, { 8, 1 }, { 2, 1 }, { 0, 29 }, { 4, 1 }, { 2, 1 }, { 0, 136 }, { 0, 151 }, { 0, 59 }, { 4, 1 }, { 2, 1 }, { 0, 209 }, { 0, 210 }, { 2, 1 }, { 0, 45 }, { 0, 211 }, { 18, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 30 }, { 0, 46 }, { 0, 226 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 121 }, { 0, 152 }, { 0, 192 }, { 2, 1 }, { 0, 28 }, { 2, 1 }, { 0, 137 }, { 0, 91 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 60 }, { 2, 1 }, { 0, 122 }, { 0, 182 }, { 4, 1 }, { 2, 1 }, { 0, 76 }, { 0, 153 }, { 2, 1 }, { 0, 168 }, { 0, 138 }, { 6, 1 }, { 2, 1 }, { 0, 13 }, { 2, 1 }, { 0, 197 }, { 0, 92 }, { 4, 1 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 2, 1 }, { 0, 108 }, { 0, 154 }, { 88, 1 }, { 86, 1 }, { 36, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 139 }, { 0, 77 }, { 2, 1 }, { 0, 199 }, { 0, 124 }, { 4, 1 }, { 2, 1 }, { 0, 213 }, { 0, 93 }, { 2, 1 }, { 0, 224 }, { 0, 14 }, { 8, 1 }, { 2, 1 }, { 0, 227 }, { 4, 1 }, { 2, 1 }, { 0, 208 }, { 0, 183 }, { 0, 123 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 169 }, { 0, 184 }, { 0, 212 }, { 2, 1 }, { 0, 225 }, { 2, 1 }, { 0, 170 }, { 0, 185 }, { 24, 1 }, { 10, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 155 }, { 0, 214 }, { 0, 109 }, { 2, 1 }, { 0, 62 }, { 0, 200 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 140 }, { 0, 228 }, { 0, 78 }, { 4, 1 }, { 2, 1 }, { 0, 215 }, { 0, 229 }, { 2, 1 }, { 0, 186 }, { 0, 171 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 156 }, { 0, 230 }, { 4, 1 }, { 2, 1 }, { 0, 110 }, { 0, 216 }, { 2, 1 }, { 0, 141 }, { 0, 187 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 231 }, { 0, 157 }, { 2, 1 }, { 0, 232 }, { 0, 142 }, { 4, 1 }, { 2, 1 }, { 0, 203 }, { 0, 188 }, { 0, 158 }, { 0, 241 }, { 2, 1 }, { 0, 31 }, { 2, 1 }, { 0, 15 }, { 0, 47 }, { 66, 1 }, { 56, 1 }, { 2, 1 }, { 0, 242 }, { 52, 1 }, { 50, 1 }, { 20, 1 }, { 8, 1 }, { 2, 1 }, { 0, 189 }, { 2, 1 }, { 0, 94 }, { 2, 1 }, { 0, 125 }, { 0, 201 }, { 6, 1 }, { 2, 1 }, { 0, 202 }, { 2, 1 }, { 0, 172 }, { 0, 126 }, { 4, 1 }, { 2, 1 }, { 0, 218 }, { 0, 173 }, { 0, 204 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 174 }, { 2, 1 }, { 0, 219 }, { 0, 220 }, { 2, 1 }, { 0, 205 }, { 0, 190 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 235 }, { 0, 237 }, { 0, 238 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 217 }, { 0, 234 }, { 0, 233 }, { 2, 1 }, { 0, 222 }, { 4, 1 }, { 2, 1 }, { 0, 221 }, { 0, 236 }, { 0, 206 }, { 0, 63 }, { 0, 240 }, { 4, 1 }, { 2, 1 }, { 0, 243 }, { 0, 244 }, { 2, 1 }, { 0, 79 }, { 2, 1 }, { 0, 245 }, { 0, 95 }, { 10, 1 }, { 2, 1 }, { 0, 255 }, { 4, 1 }, { 2, 1 }, { 0, 246 }, { 0, 111 }, { 2, 1 }, { 0, 247 }, { 0, 127 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 143 }, { 2, 1 }, { 0, 248 }, { 0, 249 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 250 }, { 0, 175 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 251 }, { 0, 191 }, { 2, 1 }, { 0, 252 }, { 0, 207 }, { 4, 1 }, { 2, 1 }, { 0, 253 }, { 0, 223 }, { 2, 1 }, { 0, 254 }, { 0, 239 } }, new byte[512, 2] { { 60, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 16 }, { 2, 1 }, { 0, 1 }, { 0, 17 }, { 14, 1 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 32 }, { 0, 2 }, { 0, 33 }, { 2, 1 }, { 0, 18 }, { 2, 1 }, { 0, 34 }, { 2, 1 }, { 0, 48 }, { 0, 3 }, { 14, 1 }, { 4, 1 }, { 2, 1 }, { 0, 49 }, { 0, 19 }, { 4, 1 }, { 2, 1 }, { 0, 50 }, { 0, 35 }, { 4, 1 }, { 2, 1 }, { 0, 64 }, { 0, 4 }, { 0, 65 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 20 }, { 0, 51 }, { 2, 1 }, { 0, 66 }, { 0, 36 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 67 }, { 0, 52 }, { 0, 81 }, { 6, 1 }, { 4, 1 }, { 2, 1 }, { 0, 80 }, { 0, 5 }, { 0, 21 }, { 2, 1 }, { 0, 82 }, { 0, 37 }, { 250, 1 }, { 98, 1 }, { 34, 1 }, { 18, 1 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 68 }, { 0, 83 }, { 2, 1 }, { 0, 53 }, { 2, 1 }, { 0, 96 }, { 0, 6 }, { 4, 1 }, { 2, 1 }, { 0, 97 }, { 0, 22 }, { 2, 1 }, { 0, 98 }, { 0, 38 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 84 }, { 0, 69 }, { 2, 1 }, { 0, 99 }, { 0, 54 }, { 4, 1 }, { 2, 1 }, { 0, 113 }, { 0, 85 }, { 2, 1 }, { 0, 100 }, { 0, 70 }, { 32, 1 }, { 14, 1 }, { 6, 1 }, { 2, 1 }, { 0, 114 }, { 2, 1 }, { 0, 39 }, { 0, 55 }, { 2, 1 }, { 0, 115 }, { 4, 1 }, { 2, 1 }, { 0, 112 }, { 0, 7 }, { 0, 23 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 101 }, { 0, 86 }, { 4, 1 }, { 2, 1 }, { 0, 128 }, { 0, 8 }, { 0, 129 }, { 4, 1 }, { 2, 1 }, { 0, 116 }, { 0, 71 }, { 2, 1 }, { 0, 24 }, { 0, 130 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 40 }, { 0, 102 }, { 2, 1 }, { 0, 131 }, { 0, 56 }, { 4, 1 }, { 2, 1 }, { 0, 117 }, { 0, 87 }, { 2, 1 }, { 0, 132 }, { 0, 72 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 145 }, { 0, 25 }, { 2, 1 }, { 0, 146 }, { 0, 118 }, { 4, 1 }, { 2, 1 }, { 0, 103 }, { 0, 41 }, { 2, 1 }, { 0, 133 }, { 0, 88 }, { 92, 1 }, { 34, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 147 }, { 0, 57 }, { 2, 1 }, { 0, 148 }, { 0, 73 }, { 4, 1 }, { 2, 1 }, { 0, 119 }, { 0, 134 }, { 2, 1 }, { 0, 104 }, { 0, 161 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 162 }, { 0, 42 }, { 2, 1 }, { 0, 149 }, { 0, 89 }, { 4, 1 }, { 2, 1 }, { 0, 163 }, { 0, 58 }, { 2, 1 }, { 0, 135 }, { 2, 1 }, { 0, 120 }, { 0, 74 }, { 22, 1 }, { 12, 1 }, { 4, 1 }, { 2, 1 }, { 0, 164 }, { 0, 150 }, { 4, 1 }, { 2, 1 }, { 0, 105 }, { 0, 177 }, { 2, 1 }, { 0, 27 }, { 0, 165 }, { 6, 1 }, { 2, 1 }, { 0, 178 }, { 2, 1 }, { 0, 90 }, { 0, 43 }, { 2, 1 }, { 0, 136 }, { 0, 179 }, { 16, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 144 }, { 2, 1 }, { 0, 9 }, { 0, 160 }, { 2, 1 }, { 0, 151 }, { 0, 121 }, { 4, 1 }, { 2, 1 }, { 0, 166 }, { 0, 106 }, { 0, 180 }, { 12, 1 }, { 6, 1 }, { 2, 1 }, { 0, 26 }, { 2, 1 }, { 0, 10 }, { 0, 176 }, { 2, 1 }, { 0, 59 }, { 2, 1 }, { 0, 11 }, { 0, 192 }, { 4, 1 }, { 2, 1 }, { 0, 75 }, { 0, 193 }, { 2, 1 }, { 0, 152 }, { 0, 137 }, { 67, 1 }, { 34, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 28 }, { 0, 181 }, { 2, 1 }, { 0, 91 }, { 0, 194 }, { 4, 1 }, { 2, 1 }, { 0, 44 }, { 0, 167 }, { 2, 1 }, { 0, 122 }, { 0, 195 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 60 }, { 2, 1 }, { 0, 12 }, { 0, 208 }, { 2, 1 }, { 0, 182 }, { 0, 107 }, { 4, 1 }, { 2, 1 }, { 0, 196 }, { 0, 76 }, { 2, 1 }, { 0, 153 }, { 0, 168 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 138 }, { 0, 197 }, { 2, 1 }, { 0, 92 }, { 0, 209 }, { 4, 1 }, { 2, 1 }, { 0, 183 }, { 0, 123 }, { 2, 1 }, { 0, 29 }, { 0, 210 }, { 9, 1 }, { 4, 1 }, { 2, 1 }, { 0, 45 }, { 0, 211 }, { 2, 1 }, { 0, 61 }, { 0, 198 }, { 85, 250 }, { 4, 1 }, { 2, 1 }, { 0, 108 }, { 0, 169 }, { 2, 1 }, { 0, 154 }, { 0, 212 }, { 32, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 184 }, { 0, 139 }, { 2, 1 }, { 0, 77 }, { 0, 199 }, { 4, 1 }, { 2, 1 }, { 0, 124 }, { 0, 213 }, { 2, 1 }, { 0, 93 }, { 0, 225 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 30 }, { 0, 226 }, { 2, 1 }, { 0, 170 }, { 0, 185 }, { 4, 1 }, { 2, 1 }, { 0, 155 }, { 0, 227 }, { 2, 1 }, { 0, 214 }, { 0, 109 }, { 20, 1 }, { 10, 1 }, { 6, 1 }, { 2, 1 }, { 0, 62 }, { 2, 1 }, { 0, 46 }, { 0, 78 }, { 2, 1 }, { 0, 200 }, { 0, 140 }, { 4, 1 }, { 2, 1 }, { 0, 228 }, { 0, 215 }, { 4, 1 }, { 2, 1 }, { 0, 125 }, { 0, 171 }, { 0, 229 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 186 }, { 0, 94 }, { 2, 1 }, { 0, 201 }, { 2, 1 }, { 0, 156 }, { 0, 110 }, { 8, 1 }, { 2, 1 }, { 0, 230 }, { 2, 1 }, { 0, 13 }, { 2, 1 }, { 0, 224 }, { 0, 14 }, { 4, 1 }, { 2, 1 }, { 0, 216 }, { 0, 141 }, { 2, 1 }, { 0, 187 }, { 0, 202 }, { 74, 1 }, { 2, 1 }, { 0, 255 }, { 64, 1 }, { 58, 1 }, { 32, 1 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 172 }, { 0, 231 }, { 2, 1 }, { 0, 126 }, { 0, 217 }, { 4, 1 }, { 2, 1 }, { 0, 157 }, { 0, 232 }, { 2, 1 }, { 0, 142 }, { 0, 203 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 188 }, { 0, 218 }, { 2, 1 }, { 0, 173 }, { 0, 233 }, { 4, 1 }, { 2, 1 }, { 0, 158 }, { 0, 204 }, { 2, 1 }, { 0, 219 }, { 0, 189 }, { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 234 }, { 0, 174 }, { 2, 1 }, { 0, 220 }, { 0, 205 }, { 4, 1 }, { 2, 1 }, { 0, 235 }, { 0, 190 }, { 2, 1 }, { 0, 221 }, { 0, 236 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 206 }, { 0, 237 }, { 2, 1 }, { 0, 222 }, { 0, 238 }, { 0, 15 }, { 4, 1 }, { 2, 1 }, { 0, 240 }, { 0, 31 }, { 0, 241 }, { 4, 1 }, { 2, 1 }, { 0, 242 }, { 0, 47 }, { 2, 1 }, { 0, 243 }, { 0, 63 }, { 18, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 244 }, { 0, 79 }, { 2, 1 }, { 0, 245 }, { 0, 95 }, { 4, 1 }, { 2, 1 }, { 0, 246 }, { 0, 111 }, { 2, 1 }, { 0, 247 }, { 2, 1 }, { 0, 127 }, { 0, 143 }, { 10, 1 }, { 4, 1 }, { 2, 1 }, { 0, 248 }, { 0, 249 }, { 4, 1 }, { 2, 1 }, { 0, 159 }, { 0, 175 }, { 0, 250 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 251 }, { 0, 191 }, { 2, 1 }, { 0, 252 }, { 0, 207 }, { 4, 1 }, { 2, 1 }, { 0, 253 }, { 0, 223 }, { 2, 1 }, { 0, 254 }, { 0, 239 } }, new byte[31, 2] { { 2, 1 }, { 0, 0 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 8 }, { 0, 4 }, { 2, 1 }, { 0, 1 }, { 0, 2 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 10 }, { 2, 1 }, { 0, 3 }, { 0, 6 }, { 6, 1 }, { 2, 1 }, { 0, 9 }, { 2, 1 }, { 0, 5 }, { 0, 7 }, { 4, 1 }, { 2, 1 }, { 0, 14 }, { 0, 13 }, { 2, 1 }, { 0, 15 }, { 0, 11 } }, new byte[31, 2] { { 16, 1 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 0 }, { 0, 1 }, { 2, 1 }, { 0, 2 }, { 0, 3 }, { 4, 1 }, { 2, 1 }, { 0, 4 }, { 0, 5 }, { 2, 1 }, { 0, 6 }, { 0, 7 }, { 8, 1 }, { 4, 1 }, { 2, 1 }, { 0, 8 }, { 0, 9 }, { 2, 1 }, { 0, 10 }, { 0, 11 }, { 4, 1 }, { 2, 1 }, { 0, 12 }, { 0, 13 }, { 2, 1 }, { 0, 14 }, { 0, 15 } } }; _llCache = new HuffmanListNode[_codeTables.Length]; _llCacheMaxBits = new int[_codeTables.Length]; LIN_BITS = new int[32] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13 }; _floatLookup = new float[8207]; for (int i = 0; i < 8207; i++) { _floatLookup[i] = (float)Math.Pow(i, 1.3333333333333333); } } internal static void Decode(BitReservoir br, int table, out float x, out float y) { if (table == 0 || table == 4 || table == 14) { x = (y = 0f); return; } byte num = DecodeSymbol(br, table); int num2 = num >> 4; int num3 = num & 0xF; int num4 = LIN_BITS[table]; if (num4 > 0 && num2 == 15) { num2 += br.GetBits(num4); } if (num2 != 0 && br.Get1Bit() != 0) { x = 0f - _floatLookup[num2]; } else { x = _floatLookup[num2]; } if (num4 > 0 && num3 == 15) { num3 += br.GetBits(num4); } if (num3 != 0 && br.Get1Bit() != 0) { y = 0f - _floatLookup[num3]; } else { y = _floatLookup[num3]; } } internal static void Decode(BitReservoir br, int table, out float x, out float y, out float v, out float w) { byte num = DecodeSymbol(br, table); v = (w = (x = (y = 0f))); if ((num & 8u) != 0) { if (br.Get1Bit() == 1) { v = 0f - _floatLookup[1]; } else { v = _floatLookup[1]; } } if ((num & 4u) != 0) { if (br.Get1Bit() == 1) { w = 0f - _floatLookup[1]; } else { w = _floatLookup[1]; } } if ((num & 2u) != 0) { if (br.Get1Bit() == 1) { x = 0f - _floatLookup[1]; } else { x = _floatLookup[1]; } } if (((uint)num & (true ? 1u : 0u)) != 0) { if (br.Get1Bit() == 1) { y = 0f - _floatLookup[1]; } else { y = _floatLookup[1]; } } } private static byte DecodeSymbol(BitReservoir br, int table) { int maxBits; HuffmanListNode huffmanListNode = GetNode(table, out maxBits); int readCount; int num = br.TryPeekBits(maxBits, out readCount); if (readCount < maxBits) { num <<= maxBits - readCount; } while (huffmanListNode != null && huffmanListNode.Length <= readCount) { if ((num & huffmanListNode.Mask) == huffmanListNode.Bits) { br.SkipBits(huffmanListNode.Length); break; } huffmanListNode = huffmanListNode.Next; } if (huffmanListNode != null && huffmanListNode.Length <= readCount) { return huffmanListNode.Value; } return 0; } private static HuffmanListNode GetNode(int table, out int maxBits) { int num = table; if (num > 16) { num = ((num > 31) ? (num - 17) : ((num < 24) ? 13 : 14)); } else { if (num > 13) { num--; } if (num > 3) { num--; } num--; } if (_llCache[num] == null) { _llCache[num] = InitTable(_codeTables[num], out maxBits); _llCacheMaxBits[num] = maxBits; } else { maxBits = _llCacheMaxBits[num]; } return _llCache[num]; } private static HuffmanListNode InitTable(byte[,] tree, out int maxBits) { List<byte> list = new List<byte>(); List<int> list2 = new List<int>(); List<int> list3 = new List<int>(); int length = tree.GetLength(0); for (int i = 0; i < length; i++) { if (tree[i, 0] == 0) { int num = 0; int item = 0; int num2 = i; do { num2 = FindPreviousNode(tree, num2, out var bit); num |= bit << item++; } while (num2 > 0); list.Add(tree[i, 1]); list2.Add(item); list3.Add(num); } } return BuildLinkedList(list, list2, list3, out maxBits); } private static int FindPreviousNode(byte[,] tree, int idx, out int bit) { for (int num = idx - 1; num >= 0; num--) { if (tree[num, 0] != 0) { for (int i = 0; i < 2; i++) { if (num + tree[num, i] != idx) { continue; } if (tree[num, i] >= 250) { int result = FindPreviousNode(tree, num, out bit); if (bit != i) { throw new InvalidOperationException(); } return result; } bit = i; return num; } } } throw new InvalidOperationException(); } private static HuffmanListNode BuildLinkedList(List<byte> values, List<int> lengthList, List<int> codeList, out int maxBits) { HuffmanListNode[] array = new HuffmanListNode[lengthList.Count]; maxBits = lengthList.Max(); for (int j = 0; j < array.Length; j++) { int num = maxBits - lengthList[j]; array[j] = new HuffmanListNode { Value = values[j], Length = lengthList[j], Bits = codeList[j] << num, Mask = (1 << lengthList[j]) - 1 << num }; } Array.Sort(array, (HuffmanListNode i1, HuffmanListNode i2) => i1.Length - i2.Length); for (int k = 1; k < array.Length && array[k].Length < 99999; k++) { array[k - 1].Next = array[k]; } return array[0]; } } internal class ID3Frame : FrameBase { private int _version; internal int Version { get { if (_version == 0) { return 1; } return _version; } } internal static ID3Frame TrySync(uint syncMark) { if ((syncMark & 0xFFFFFF00u) == 1229206272) { return new ID3Frame { _version = 2 }; } if ((syncMark & 0xFFFFFF00u) == 1413564160) { if ((syncMark & 0xFF) == 43) { return new ID3Frame { _version = 1 }; } return new ID3Frame { _version = 0 }; } return null; } private ID3Frame() { } protected override int Validate() { switch (_version) { case 2: { byte[] array = new byte[7]; if (Read(3, array) == 7) { byte b; switch (array[0]) { case 2: b = 63; break; case 3: b = 31; break; case 4: b = 15; break; default: return -1; } int num = (array[3] << 21) | (array[4] << 14) | (array[5] << 7) | array[6]; if (((array[2] & b) | (array[3] & 0x80) | (array[4] & 0x80) | (array[5] & 0x80) | (array[6] & 0x80)) == 0 && array[1] != byte.MaxValue) { return num + 10; } } break; } case 1: return 355; case 0: return 128; } return -1; } internal override void Parse() { switch (_version) { case 2: ParseV2(); break; case 1: ParseV1Enh(); break; case 0: ParseV1(3); break; } } private void ParseV1(int offset) { } private void ParseV1Enh() { ParseV1(230); } private void ParseV2() { } internal void Merge(ID3Frame newFrame) { } } internal abstract class LayerDecoderBase { protected const int SBLIMIT = 32; private const float INV_SQRT_2 = 0.70710677f; private static float[] DEWINDOW_TABLE = new float[512] { 0f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -3.0518E-05f, -3.0518E-05f, -3.0518E-05f, -3.0518E-05f, -4.5776E-05f, -4.5776E-05f, -6.1035E-05f, -6.1035E-05f, -7.6294E-05f, -7.6294E-05f, -9.1553E-05f, -0.000106812f, -0.000106812f, -0.00012207f, -0.000137329f, -0.000152588f, -0.000167847f, -0.000198364f, -0.000213623f, -0.000244141f, -0.000259399f, -0.000289917f, -0.000320435f, -0.000366211f, -0.000396729f, -0.000442505f, -0.000473022f, -0.000534058f, -0.000579834f, -0.00062561f, -0.000686646f, -0.000747681f, -0.000808716f, -0.00088501f, -0.000961304f, -0.001037598f, -0.001113892f, -0.001205444f, -0.001296997f, -0.00138855f, -0.001480103f, -0.001586914f, -0.001693726f, -0.001785278f, -0.001907349f, -0.00201416f, -0.002120972f, -0.002243042f, -0.002349854f, -0.002456665f, -0.002578735f, -0.002685547f, -0.002792358f, -0.00289917f, -0.002990723f, -0.003082275f, -0.003173828f, 0.003250122f, 0.003326416f, 0.003387451f, 0.003433228f, 0.003463745f, 0.003479004f, 0.003479004f, 0.003463745f, 0.003417969f, 0.003372192f, 0.00328064f, 0.003173828f, 0.003051758f, 0.002883911f, 0.002700806f, 0.002487183f, 0.002227783f, 0.001937866f, 0.001617432f, 0.001266479f, 0.000869751f, 0.000442505f, -3.0518E-05f, -0.000549316f, -0.001098633f, -0.001693726f, -0.002334595f, -0.003005981f, -0.003723145f, -0.004486084f, -0.0052948f, -0.006118774f, -0.007003784f, -0.007919312f, -0.008865356f, -0.009841919f, -0.010848999f, -0.011886597f, -0.012939453f, -0.014022827f, -0.01512146f, -0.016235352f, -0.017349243f, -0.018463135f, -0.019577026f, -0.020690918f, -0.02178955f, -0.022857666f, -0.023910522f, -0.024932861f, -0.025909424f, -0.02684021f, -0.02772522f, -0.028533936f, -0.029281616f, -0.029937744f, -0.030532837f, -0.03100586f, -0.03138733f, -0.031661987f, -0.031814575f, -0.031845093f, -0.03173828f, -0.03147888f, 0.031082153f, 0.030517578f, 0.029785156f, 0.028884888f, 0.027801514f, 0.026535034f, 0.02508545f, 0.023422241f, 0.021575928f, 0.01953125f, 0.01725769f, 0.014801025f, 0.012115479f, 0.009231567f, 0.006134033f, 0.002822876f, -0.000686646f, -0.004394531f, -0.00831604f, -0.012420654f, -0.016708374f, -0.0211792f, -0.025817871f, -0.03060913f, -0.03555298f, -0.040634155f, -0.045837402f, -0.051132202f, -0.056533813f, -0.06199646f, -0.06752014f, -0.07305908f, -0.07862854f, -0.08418274f, -0.08970642f, -0.09516907f, -0.10054016f, -0.1058197f, -0.110946655f, -0.11592102f, -0.12069702f, -0.1252594f, -0.12956238f, -0.1335907f, -0.13729858f, -0.14067078f, -0.14367676f, -0.1462555f, -0.14842224f, -0.15011597f, -0.15130615f, -0.15196228f, -0.15206909f, -0.15159607f, -0.15049744f, -0.1487732f, -0.1463623f, -0.14326477f, -0.13945007f, -0.1348877f, -0.12957764f, -0.12347412f, -0.11657715f, -0.1088562f, 0.10031128f, 0.090927124f, 0.08068848f, 0.06959534f, 0.057617188f, 0.044784546f, 0.031082153f, 0.01651001f, 0.001068115f, -0.015228271f, -0.03237915f, -0.050354004f, -0.06916809f, -0.088775635f, -0.10916138f, -0.13031006f, -0.15220642f, -0.17478943f, -0.19805908f, -0.22198486f, -0.24650574f, -0.2715912f, -0.2972107f, -0.32331848f, -0.34986877f, -0.37680054f, -0.40408325f, -0.43165588f, -0.45947266f, -0.48747253f, -0.51560974f, -0.54382324f, -0.57203674f, -0.6002197f, -0.6282959f, -0.6562195f, -0.6839142f, -0.71131897f, -0.7383728f, -0.7650299f, -0.791214f, -0.816864f, -0.84194946f, -0.8663635f, -0.89009094f, -0.9130554f, -0.9351959f, -0.95648193f, -0.9768524f, -0.99624634f, -1.0146179f, -1.0319366f, -1.0481567f, -1.0632172f, -1.0771179f, -1.0897827f, -1.1012115f, -1.1113739f, -1.120224f, -1.1277466f, -1.1339264f, -1.1387634f, -1.1422119f, -1.1442871f, 1.144989f, 1.1442871f, 1.1422119f, 1.1387634f, 1.1339264f, 1.1277466f, 1.120224f, 1.1113739f, 1.1012115f, 1.0897827f, 1.0771179f, 1.0632172f, 1.0481567f, 1.0319366f, 1.0146179f, 0.99624634f, 0.9768524f, 0.95648193f, 0.9351959f, 0.9130554f, 0.89009094f, 0.8663635f, 0.84194946f, 0.816864f, 0.791214f, 0.7650299f, 0.7383728f, 0.71131897f, 0.6839142f, 0.6562195f, 0.6282959f, 0.6002197f, 0.57203674f, 0.54382324f, 0.51560974f, 0.48747253f, 0.45947266f, 0.43165588f, 0.40408325f, 0.37680054f, 0.34986877f, 0.32331848f, 0.2972107f, 0.2715912f, 0.24650574f, 0.22198486f, 0.19805908f, 0.17478943f, 0.15220642f, 0.13031006f, 0.10916138f, 0.088775635f, 0.06916809f, 0.050354004f, 0.03237915f, 0.015228271f, -0.001068115f, -0.01651001f, -0.031082153f, -0.044784546f, -0.057617188f, -0.06959534f, -0.08068848f, -0.090927124f, 0.10031128f, 0.1088562f, 0.11657715f, 0.12347412f, 0.12957764f, 0.1348877f, 0.13945007f, 0.14326477f, 0.1463623f, 0.1487732f, 0.15049744f, 0.15159607f, 0.15206909f, 0.15196228f, 0.15130615f, 0.15011597f, 0.14842224f, 0.1462555f, 0.14367676f, 0.14067078f, 0.13729858f, 0.1335907f, 0.12956238f, 0.1252594f, 0.12069702f, 0.11592102f, 0.110946655f, 0.1058197f, 0.10054016f, 0.09516907f, 0.08970642f, 0.08418274f, 0.07862854f, 0.07305908f, 0.06752014f, 0.06199646f, 0.056533813f, 0.051132202f, 0.045837402f, 0.040634155f, 0.03555298f, 0.03060913f, 0.025817871f, 0.0211792f, 0.016708374f, 0.012420654f, 0.00831604f, 0.004394531f, 0.000686646f, -0.002822876f, -0.006134033f, -0.009231567f, -0.012115479f, -0.014801025f, -0.01725769f, -0.01953125f, -0.021575928f, -0.023422241f, -0.02508545f, -0.026535034f, -0.027801514f, -0.028884888f, -0.029785156f, -0.030517578f, 0.031082153f, 0.03147888f, 0.03173828f, 0.031845093f, 0.031814575f, 0.031661987f, 0.03138733f, 0.03100586f, 0.030532837f, 0.029937744f, 0.029281616f, 0.028533936f, 0.02772522f, 0.02684021f, 0.025909424f, 0.024932861f, 0.023910522f, 0.022857666f, 0.02178955f, 0.020690918f, 0.019577026f, 0.018463135f, 0.017349243f, 0.016235352f, 0.01512146f, 0.014022827f, 0.012939453f, 0.011886597f, 0.010848999f, 0.009841919f, 0.008865356f, 0.007919312f, 0.007003784f, 0.006118774f, 0.0052948f, 0.004486084f, 0.003723145f, 0.003005981f, 0.002334595f, 0.001693726f, 0.001098633f, 0.000549316f, 3.0518E-05f, -0.000442505f, -0.000869751f, -0.001266479f, -0.001617432f, -0.001937866f, -0.002227783f, -0.002487183f, -0.002700806f, -0.002883911f, -0.003051758f, -0.003173828f, -0.00328064f, -0.003372192f, -0.003417969f, -0.003463745f, -0.003479004f, -0.003479004f, -0.003463745f, -0.003433228f, -0.003387451f, -0.003326416f, 0.003250122f, 0.003173828f, 0.003082275f, 0.002990723f, 0.00289917f, 0.002792358f, 0.002685547f, 0.002578735f, 0.002456665f, 0.002349854f, 0.002243042f, 0.002120972f, 0.00201416f, 0.001907349f, 0.001785278f, 0.001693726f, 0.001586914f, 0.001480103f, 0.00138855f, 0.001296997f, 0.001205444f, 0.001113892f, 0.001037598f, 0.000961304f, 0.00088501f, 0.000808716f, 0.000747681f, 0.000686646f, 0.00062561f, 0.000579834f, 0.000534058f, 0.000473022f, 0.000442505f, 0.000396729f, 0.000366211f, 0.000320435f, 0.000289917f, 0.000259399f, 0.000244141f, 0.000213623f, 0.000198364f, 0.000167847f, 0.000152588f, 0.000137329f, 0.00012207f, 0.000106812f, 0.000106812f, 9.1553E-05f, 7.6294E-05f, 7.6294E-05f, 6.1035E-05f, 6.1035E-05f, 4.5776E-05f, 4.5776E-05f, 3.0518E-05f, 3.0518E-05f, 3.0518E-05f, 3.0518E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f }; private static float[] SYNTH_COS64_TABLE = new float[31] { 0.500603f, 0.5024193f, 0.50547093f, 0.5097956f, 0.5154473f, 0.5224986f, 0.5310426f, 0.5411961f, 0.5531039f, 0.56694406f, 0.582935f, 0.6013449f, 0.6225041f, 0.6468218f, 0.6748083f, 0.70710677f, 0.7445363f, 0.7881546f, 0.8393496f, 0.8999762f, 0.9725682f, 1.0606776f, 1.1694399f, 1.306563f, 1.4841646f, 1.7224472f, 2.057781f, 2.5629156f, 3.4076085f, 5.1011486f, 10.190008f }; private List<float[]> _synBuf = new List<float[]>(2); private List<int> _bufOffset = new List<int>(2); private float[] _eq; private float[] ippuv = new float[512]; private float[] ei32 = new float[16]; private float[] eo32 = new float[16]; private float[] oi32 = new float[16]; private float[] oo32 = new float[16]; private float[] ei16 = new float[8]; private float[] eo16 = new float[8]; private float[] oi16 = new float[8]; private float[] oo16 = new float[8]; private float[] ei8 = new float[4]; private float[] tmp8 = new float[6]; private float[] oi8 = new float[4]; private float[] oo8 = new float[4]; internal StereoMode StereoMode { get; set; } internal LayerDecoderBase() { StereoMode = StereoMode.Both; } internal abstract int DecodeFrame(IMpegFrame frame, float[] ch0, float[] ch1); internal void SetEQ(float[] eq) { if (eq == null || eq.Length == 32) { _eq = eq; } } internal virtual void ResetForSeek() { _synBuf.Clear(); _bufOffset.Clear(); } protected void InversePolyPhase(int channel, float[] data) { GetBufAndOffset(channel, out var synBuf, out var k); if (_eq != null) { for (int i = 0; i < 32; i++) { data[i] *= _eq[i]; } } DCT32(data, synBuf, k); BuildUVec(ippuv, synBuf, k); DewindowOutput(ippuv, data); } private void GetBufAndOffset(int channel, out float[] synBuf, out int k) { while (_synBuf.Count <= channel) { _synBuf.Add(new float[1024]); } while (_bufOffset.Count <= channel) { _bufOffset.Add(0); } synBuf = _synBuf[channel]; k = _bufOffset[channel]; k = (k - 32) & 0x1FF; _bufOffset[channel] = k; } private void DCT32(float[] _in, float[] _out, int k) { for (int i = 0; i < 16; i++) { ei32[i] = _in[i] + _in[31 - i]; oi32[i] = (_in[i] - _in[31 - i]) * SYNTH_COS64_TABLE[2 * i]; } DCT16(ei32, eo32); DCT16(oi32, oo32); for (int i = 0; i < 15; i++) { _out[2 * i + k] = eo32[i]; _out[2 * i + 1 + k] = oo32[i] + oo32[i + 1]; } _out[30 + k] = eo32[15]; _out[31 + k] = oo32[15]; } private void DCT16(float[] _in, float[] _out) { float num = _in[0]; float num2 = _in[15]; ei16[0] = num + num2; oi16[0] = (num - num2) * SYNTH_COS64_TABLE[1]; num = _in[1]; num2 = _in[14]; ei16[1] = num + num2; oi16[1] = (num - num2) * SYNTH_COS64_TABLE[5]; num = _in[2]; num2 = _in[13]; ei16[2] = num + num2; oi16[2] = (num - num2) * SYNTH_COS64_TABLE[9]; num = _in[3]; num2 = _in[12]; ei16[3] = num + num2; oi16[3] = (num - num2) * SYNTH_COS64_TABLE[13]; num = _in[4]; num2 = _in[11]; ei16[4] = num + num2; oi16[4] = (num - num2) * SYNTH_COS64_TABLE[17]; num = _in[5]; num2 = _in[10]; ei16[5] = num + num2; oi16[5] = (num - num2) * SYNTH_COS64_TABLE[21]; num = _in[6]; num2 = _in[9]; ei16[6] = num + num2; oi16[6] = (num - num2) * SYNTH_COS64_TABLE[25]; num = _in[7]; num2 = _in[8]; ei16[7] = num + num2; oi16[7] = (num - num2) * SYNTH_COS64_TABLE[29]; DCT8(ei16, eo16); DCT8(oi16, oo16); _out[0] = eo16[0]; _out[1] = oo16[0] + oo16[1]; _out[2] = eo16[1]; _out[3] = oo16[1] + oo16[2]; _out[4] = eo16[2]; _out[5] = oo16[2] + oo16[3]; _out[6] = eo16[3]; _out[7] = oo16[3] + oo16[4]; _out[8] = eo16[4]; _out[9] = oo16[4] + oo16[5]; _out[10] = eo16[5]; _out[11] = oo16[5] + oo16[6]; _out[12] = eo16[6]; _out[13] = oo16[6] + oo16[7]; _out[14] = eo16[7]; _out[15] = oo16[7]; } private void DCT8(float[] _in, float[] _out) { ei8[0] = _in[0] + _in[7]; ei8[1] = _in[3] + _in[4]; ei8[2] = _in[1] + _in[6]; ei8[3] = _in[2] + _in[5]; tmp8[0] = ei8[0] + ei8[1]; tmp8[1] = ei8[2] + ei8[3]; tmp8[2] = (ei8[0] - ei8[1]) * SYNTH_COS64_TABLE[7]; tmp8[3] = (ei8[2] - ei8[3]) * SYNTH_COS64_TABLE[23]; tmp8[4] = (tmp8[2] - tmp8[3]) * 0.70710677f; _out[0] = tmp8[0] + tmp8[1]; _out[2] = tmp8[2] + tmp8[3] + tmp8[4]; _out[4] = (tmp8[0] - tmp8[1]) * 0.70710677f; _out[6] = tmp8[4]; oi8[0] = (_in[0] - _in[7]) * SYNTH_COS64_TABLE[3]; oi8[1] = (_in[1] - _in[6]) * SYNTH_COS64_TABLE[11]; oi8[2] = (_in[2] - _in[5]) * SYNTH_COS64_TABLE[19]; oi8[3] = (_in[3] - _in[4]) * SYNTH_COS64_TABLE[27]; tmp8[0] = oi8[0] + oi8[3]; tmp8[1] = oi8[1] + oi8[2]; tmp8[2] = (oi8[0] - oi8[3]) * SYNTH_COS64_TABLE[7]; tmp8[3] = (oi8[1] - oi8[2]) * SYNTH_COS64_TABLE[23]; tmp8[4] = tmp8[2] + tmp8[3]; tmp8[5] = (tmp8[2] - tmp8[3]) * 0.70710677f; oo8[0] = tmp8[0] + tmp8[1]; oo8[1] = tmp8[4] + tmp8[5]; oo8[2] = (tmp8[0] - tmp8[1]) * 0.70710677f; oo8[3] = tmp8[5]; _out[1] = oo8[0] + oo8[1]; _out[3] = oo8[1] + oo8[2]; _out[5] = oo8[2] + oo8[3]; _out[7] = oo8[3]; } private void BuildUVec(float[] u_vec, float[] cur_synbuf, int k) { int num = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 16; j++) { u_vec[num + j] = cur_synbuf[k + j + 16]; u_vec[num + j + 17] = 0f - cur_synbuf[k + 31 - j]; } k = (k + 32) & 0x1FF; for (int j = 0; j < 16; j++) { u_vec[num + j + 32] = 0f - cur_synbuf[k + 16 - j]; u_vec[num + j + 48] = 0f - cur_synbuf[k + j]; } u_vec[num + 16] = 0f; k = (k + 32) & 0x1FF; num += 64; } } private void DewindowOutput(float[] u_vec, float[] samples) { for (int i = 0; i < 512; i++) { u_vec[i] *= DEWINDOW_TABLE[i]; } for (int j = 0; j < 32; j++) { float num = u_vec[j]; num += u_vec[j + 32]; num += u_vec[j + 64]; num += u_vec[j + 96]; num += u_vec[j + 128]; num += u_vec[j + 160]; num += u_vec[j + 192]; num += u_vec[j + 224]; num += u_vec[j + 256]; num += u_vec[j + 288]; num += u_vec[j + 320]; num += u_vec[j + 352]; num += u_vec[j + 384]; num += u_vec[j + 416]; num += u_vec[j + 448]; num += u_vec[j + 480]; u_vec[j] = num; } for (int k = 0; k < 32; k++) { samples[k] = u_vec[k]; } } } internal class LayerIDecoder : LayerIIDecoderBase { private static readonly int[] _rateTable = new int[32]; private static readonly int[][] _allocLookupTable = new int[1][] { new int[17] { 4, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } }; internal static bool GetCRC(MpegFrame frame, ref uint crc) { return LayerIIDecoderBase.GetCRC(frame, _rateTable, _allocLookupTable, readScfsiBits: false, ref crc); } internal LayerIDecoder() : base(_allocLookupTable, 1) { } protected override int[] GetRateTable(IMpegFrame frame) { return _rateTable; } protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels) { } } internal class LayerIIDecoder : LayerIIDecoderBase { private static readonly int[][] _rateLookupTable = new int[5][] { new int[27] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, new int[30] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, new int[8] { 4, 4, 5, 5, 5, 5, 5, 5 }, new int[12] { 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, new int[30] { 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 } }; private static readonly int[][] _allocLookupTable = new int[8][] { new int[5] { 2, 0, -5, -7, 16 }, new int[9] { 3, 0, -5, -7, 3, -10, 4, 5, 16 }, new int[17] { 4, 0, -5, -7, 3, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, new int[17] { 4, 0, -5, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, new int[17] { 4, 0, -5, -7, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, new int[9] { 3, 0, -5, -7, -10, 4, 5, 6, 9 }, new int[17] { 4, 0, -5, -7, 3, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, new int[5] { 2, 0, -5, -7, 3 } }; internal static bool GetCRC(MpegFrame frame, ref uint crc) { return LayerIIDecoderBase.GetCRC(frame, SelectTable(frame), _allocLookupTable, readScfsiBits: true, ref crc); } private static int[] SelectTable(IMpegFrame frame) { int num = frame.BitRate / ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) / 1000; if (frame.Version == MpegVersion.Version1) { if ((num >= 56 && num <= 80) || (frame.SampleRate == 48000 && num >= 56)) { return _rateLookupTable[0]; } if (frame.SampleRate != 48000 && num >= 96) { return _rateLookupTable[1]; } if (frame.SampleRate != 32000 && num <= 48) { return _rateLookupTable[2]; } return _rateLookupTable[3]; } return _rateLookupTable[4]; } internal LayerIIDecoder() : base(_allocLookupTable, 3) { } protected override int[] GetRateTable(IMpegFrame frame) { return SelectTable(frame); } protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels) { for (int i = 0; i < 30; i++) { for (int j = 0; j < channels; j++) { if (scfsi[j][i] == 2) { scfsi[j][i] = frame.ReadBits(2); } } } } } internal abstract class LayerIIDecoderBase : LayerDecoderBase { protected const int SSLIMIT = 12; private static readonly float[] _groupedC = new float[5] { 0f, 0f, 1.3333334f, 1.6f, 1.7777778f }; private static readonly float[] _groupedD = new float[5] { 0f, 0f, -0.5f, -0.5f, -0.5f }; private static readonly float[] _C = new float[17] { 0f, 0f, 1.3333334f, 1.1428572f, 1.0666667f, 1.032258f, 1.0158731f, 1.007874f, 1.0039216f, 1.0019569f, 1.0009775f, 1.0004885f, 1.0002443f, 1.0001221f, 1.000061f, 1.0000305f, 1.0000153f }; private static readonly float[] _D = new float[17] { 0f, 0f, -0.5f, -0.75f, -0.875f, -0.9375f, -31f / 32f, -63f / 64f, -127f / 128f, -0.99609375f, -0.9980469f, -0.99902344f, -0.9995117f, -0.99975586f, -0.9998779f, -0.99993896f, -0.9999695f }; private static readonly float[] _denormalMultiplier = new float[64] { 2f, 1.587401f, 1.2599211f, 1f, 0.7937005f, 0.62996054f, 0.5f, 0.39685026f, 0.31498027f, 0.25f, 0.19842513f, 0.15749013f, 0.125f, 0.099212565f, 0.07874507f, 0.0625f, 0.049606282f, 0.039372534f, 1f / 32f, 0.024803141f, 0.019686267f, 1f / 64f, 0.012401571f, 0.009843133f, 1f / 128f, 0.0062007853f, 0.0049215667f, 0.00390625f, 0.0031003926f, 0.0024607833f, 0.001953125f, 0.0015501963f, 0.0012303917f, 0.0009765625f, 0.00077509816f, 0.00061519584f, 0.00048828125f, 0.00038754908f, 0.00030759792f, 0.00024414062f, 0.00019377454f, 0.00015379896f, 0.00012207031f, 9.688727E-05f, 7.689948E-05f, 6.1035156E-05f, 4.8443635E-05f, 3.844974E-05f, 3.0517578E-05f, 2.4221818E-05f, 1.922487E-05f, 1.5258789E-05f, 1.2110909E-05f, 9.612435E-06f, 7.6293945E-06f, 6.0554544E-06f, 4.8062175E-06f, 3.8146973E-06f, 3.0277272E-06f, 2.4031087E-06f, 1.9073486E-06f, 1.5138636E-06f, 1.2015544E-06f, 9.536743E-07f }; private int _channels; private int _jsbound; private int _granuleCount; private int[][] _allocLookupTable; private int[][] _scfsi; private int[][] _samples; private int[][][] _scalefac; private float[] _polyPhaseBuf; private int[][] _allocation; protected static bool GetCRC(MpegFrame frame, int[] rateTable, int[][] allocLookupTable, bool readScfsiBits, ref uint crc) { int num = 0; int num2 = rateTable.Length; int num3 = num2; if (frame.ChannelMode == MpegChannelMode.JointStereo) { num3 = frame.ChannelModeExtension * 4 + 4; } int num4 = ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2); int i; for (i = 0; i < num3; i++) { int num5 = allocLookupTable[rateTable[i]][0]; for (int j = 0; j < num4; j++) { int num6 = frame.ReadBits(num5); if (num6 > 0) { num += 2; } MpegFrame.UpdateCRC(num6, num5, ref crc); } } for (; i < num2; i++) { int num7 = allocLookupTable[rateTable[i]][0]; int num8 = frame.ReadBits(num7); if (num8 > 0) { num += num4 * 2; } MpegFrame.UpdateCRC(num8, num7, ref crc); } if (readScfsiBits) { while (num >= 2) { MpegFrame.UpdateCRC(frame.ReadBits(2), 2, ref crc); num -= 2; } } return true; } protected LayerIIDecoderBase(int[][] allocLookupTable, int granuleCount) { _allocLookupTable = allocLookupTable; _granuleCount = granuleCount; _allocation = new int[2][] { new int[32], new int[32] }; _scfsi = new int[2][] { new int[32], new int[32] }; _samples = new int[2][] { new int[384 * _granuleCount], new int[384 * _granuleCount] }; _scalefac = new int[2][][] { new int[3][], new int[3][] }; for (int i = 0; i < 3; i++) { _scalefac[0][i] = new int[32]; _scalefac[1][i] = new int[32]; } _polyPhaseBuf = new float[32]; } internal override int DecodeFrame(IMpegFrame frame, float[] ch0, float[] ch1) { InitFrame(frame); int[] rateTable = GetRateTable(frame); ReadAllocation(frame, rateTable); for (int i = 0; i < _scfsi[0].Length; i++) { _scfsi[0][i] = ((_allocation[0][i] != 0) ? 2 : (-1)); _scfsi[1][i] = ((_allocation[1][i] != 0) ? 2 : (-1)); } ReadScaleFactorSelection(frame, _scfsi, _channels); ReadScaleFactors(frame); ReadSamples(frame); return DecodeSamples(ch0, ch1); } private void InitFrame(IMpegFrame frame) { switch (frame.ChannelMode) { case MpegChannelMode.Mono: _channels = 1; _jsbound = 32; break; case MpegChannelMode.JointStereo: _channels = 2; _jsbound = frame.ChannelModeExtension * 4 + 4; break; default: _channels = 2; _jsbound = 32; break; } } protected abstract int[] GetRateTable(IMpegFrame frame); private void ReadAllocation(IMpegFrame frame, int[] rateTable) { int num = rateTable.Length; if (_jsbound > num) { _jsbound = num; } Array.Clear(_allocation[0], 0, 32); Array.Clear(_allocation[1], 0, 32); int i; for (i = 0; i < _jsbound; i++) { int[] array = _allocLookupTable[rateTable[i]]; int bitCount = array[0]; for (int j = 0; j < _channels; j++) { _allocation[j][i] = array[frame.ReadBits(bitCount) + 1]; } } for (; i < num; i++) { int[] array2 = _allocLookupTable[rateTable[i]]; _allocation[0][i] = (_allocation[1][i] = array2[frame.ReadBits(array2[0]) + 1]); } } protected abstract void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels); private void ReadScaleFactors(IMpegFrame frame) { for (int i = 0; i < 32; i++) { for (int j = 0; j < _channels; j++) { switch (_scfsi[j][i]) { case 0: _scalefac[j][0][i] = frame.ReadBits(6); _scalefac[j][1][i] = frame.ReadBits(6); _scalefac[j][2][i] = frame.ReadBits(6); break; case 1: _scalefac[j][0][i] = (_scalefac[j][1][i] = frame.ReadBits(6)); _scalefac[j][2][i] = frame.ReadBits(6); break; case 2: _scalefac[j][0][i] = (_scalefac[j][1][i] = (_scalefac[j][2][i] = frame.ReadBits(6))); break; case 3: _scalefac[j][0][i] = frame.ReadBits(6); _scalefac[j][1][i] = (_scalefac[j][2][i] = frame.ReadBits(6)); break; default: _scalefac[j][0][i] = 63; _scalefac[j][1][i] = 63; _scalefac[j][2][i] = 63; break; } } } } private void ReadSamples(IMpegFrame frame) { int num = 0; int num2 = 0; while (num < 12) { int num3 = 0; while (num3 < 32) { for (int i = 0; i < _channels; i++) { if (i == 0 || num3 < _jsbound) { int num4 = _allocation[i][num3]; if (num4 != 0) { if (num4 < 0) { int num5 = frame.ReadBits(-num4); int num6 = (1 << -num4 / 2 + -num4 % 2 - 1) + 1; _samples[i][num2] = num5 % num6; num5 /= num6; _samples[i][num2 + 32] = num5 % num6; _samples[i][num2 + 64] = num5 / num6; } else { for (int j = 0; j < _granuleCount; j++) { _samples[i][num2 + 32 * j] = frame.ReadBits(num4); } } } else { for (int k = 0; k < _granuleCount; k++) { _samples[i][num2 + 32 * k] = 0; } } } else { for (int l = 0; l < _granuleCount; l++) { _samples[1][num2 + 32 * l] = _samples[0][num2 + 32 * l]; } } } num3++; num2++; } num++; num2 += 32 * (_granuleCount - 1); } } private int DecodeSamples(float[] ch0, float[] ch1) { float[][] array = new float[2][]; int num = 0; int num2 = _channels - 1; if (_channels == 1 || base.StereoMode == StereoMode.LeftOnly) { array[0] = ch0; num2 = 0; } else if (base.StereoMode == StereoMode.RightOnly) { array[1] = ch0; num = 1; } else { array[0] = ch0; array[1] = ch1; } int num3 = 0; for (int i = num; i <= num2; i++) { num3 = 0; for (int j = 0; j < _granuleCount; j++) { for (int k = 0; k < 12; k++) { int num4 = 0; while (num4 < 32) { int num5 = _allocation[i][num4]; if (num5 != 0) { float[] array2; float[] array3; if (num5 < 0) { num5 = -num5 / 2 + -num5 % 2 - 1; array2 = _groupedC; array3 = _groupedD; } else { array2 = _C; array3 = _D; } _polyPhaseBuf[num4] = array2[num5] * ((float)(_samples[i][num3] << 16 - num5) / 32768f + array3[num5]) * _denormalMultiplier[_scalefac[i][j][num4]]; } else { _polyPhaseBuf[num4] = 0f; } num4++; num3++; } InversePolyPhase(i, _polyPhaseBuf); Array.Copy(_polyPhaseBuf, 0, array[i], num3 - 32, 32); } } } if (_channels == 2 && base.StereoMode == StereoMode.DownmixToMono) { for (int l = 0; l < num3; l++) { ch0[l] = (ch0[l] + ch1[l]) / 2f; } } return num3; } } internal sealed class LayerIIIDecoder : LayerDecoderBase { private class HybridMDCT { private const float PI = MathF.PI; private static float[][] _swin; private static float[] icos72_table; private List<float[]> _prevBlock; private List<float[]> _nextBlock; private float[] _imdctTemp = new float[18]; private float[] _imdctResult = new float[36]; private const float sqrt32 = 0.8660254f; static HybridMDCT() { icos72_table = new float[35] { 0.50047636f, 0.5019099f, 0.5043145f, 0.5077133f, 0.51213974f, 0.5176381f, 0.5242646f, 0.5320889f, 0.5411961f, 0.55168897f, 0.56369096f, 0.57735026f, 0.59284455f, 0.61038727f, 0.6302362f, 0.65270364f, 0.67817086f, 0.70710677f, 0.7400936f, 0.7778619f, 0.8213398f, 0.8717234f, 0.9305795f, 1f, 1.0828403f, 1.1831008f, 1.306563f, 1.4619021f, 1.6627548f, 1.9318516f, 2.3101132f, 2.8793852f, 3.830649f, 5.7368565f, 11.462792f }; _swin = new float[4][] { new float[36], new float[36], new float[36], new float[36] }; for (int i = 0; i < 36; i++) { _swin[0][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5)); } for (int i = 0; i < 18; i++) { _swin[1][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5)); } for (int i = 18; i < 24; i++) { _swin[1][i] = 1f; } for (int i = 24; i < 30; i++) { _swin[1][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5 - 18.0)); } for (int i = 30; i < 36; i++) { _swin[1][i] = 0f; } for (int i = 0; i < 6; i++) { _swin[3][i] = 0f; } for (int i = 6; i < 12; i++) { _swin[3][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5 - 6.0)); } for (int i = 12; i < 18; i++) { _swin[3][i] = 1f; } for (int i = 18; i < 36; i++) { _swin[3][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5)); } for (int i = 0; i < 12; i++) { _swin[2][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5)); } for (int i = 12; i < 36; i++) { _swin[2][i] = 0f; } } internal HybridMDCT() { _prevBlock = new List<float[]>(); _nextBlock = new List<float[]>(); } internal void Reset() { _prevBlock.Clear(); _nextBlock.Clear(); } private void GetPrevBlock(int channel, out float[] prevBlock, out float[] nextBlock) { while (_prevBlock.Count <= channel) { _prevBlock.Add(new float[576]); } while (_nextBlock.Count <= channel) { _nextBlock.Add(new float[576]); } prevBlock = _prevBlock[channel]; nextBlock = _nextBlock[channel]; _nextBlock[channel] = prevBlock; _prevBlock[channel] = nextBlock; } internal void Apply(float[] fsIn, int channel, int blockType, bool doMixed) { GetPrevBlock(channel, out var prevBlock, out var nextBlock); int sbStart = 0; if (doMixed) { LongImpl(fsIn, 0, 2, nextBlock, 0); sbStart = 2; } if (blockType == 2) { ShortImpl(fsIn, sbStart, nextBlock); } else { LongImpl(fsIn, sbStart, 32, nextBlock, blockType); } for (int i = 0; i < 576; i++) { fsIn[i] += prevBlock[i]; } } private void LongImpl(float[] fsIn, int sbStart, int sbLimit, float[] nextblck, int blockType) { int i = sbStart; int num = sbStart * 18; for (; i < sbLimit; i++) { Array.Copy(fsIn, num, _imdctTemp, 0, 18); LongIMDCT(_imdctTemp, _imdctResult); float[] array = _swin[blockType]; int j; for (j = 0; j < 18; j++) { fsIn[num++] = _imdctResult[j] * array[j]; } num -= 18; for (; j < 36; j++) { nextblck[num++] = _imdctResult[j] * array[j]; } } } private static void LongIMDCT(float[] invec, float[] outvec) { float[] array = new float[17]; float[] array2 = new float[18]; float[] array3 = new float[9]; float[] array4 = new float[9]; float[] array5 = new float[9]; float[] array6 = new float[9]; int i; for (i = 0; i < 17; i++) { array[i] = invec[i] + invec[i + 1]; } array3[0] = invec[0]; array4[0] = array[0]; int num = 0; i = 1; while (i < 9) { array3[i] = array[num + 1]; array4[i] = array[num] + array[num + 2]; i++; num += 2; } imdct_9pt(array3, array5); imdct_9pt(array4, array6); for (i = 0; i < 9; i++) { array6[i] *= ICOS36_A(i); array2[i] = (array5[i] + array6[i]) * ICOS72_A(i); } for (; i < 18; i++) { array2[i] = (array5[17 - i] - array6[17 - i]) * ICOS72_A(i); } outvec[0] = array2[9]; outvec[1] = array2[10]; outvec[2] = array2[11]; outvec[3] = array2[12]; outvec[4] = array2[13]; outvec[5] = array2[14]; outvec[6] = array2[15]; outvec[7] = array2[16]; outvec[8] = array2[17]; outvec[9] = 0f - array2[17]; outvec[10] = 0f - array2[16]; outvec[11] = 0f - array2[15]; outvec[12] = 0f - array2[14]; outvec[13] = 0f - array2[13]; outvec[14] = 0f - array2[12]; outvec[15] = 0f - array2[11]; outvec[16] = 0f - array2[10]; outvec[17] = 0f - array2[9]; outvec[35] = (outvec[18] = 0f - array2[8]); outvec[34] = (outvec[19] = 0f - array2[7]); outvec[33] = (outvec[20] = 0f - array2[6]); outvec[32] = (outvec[21] = 0f - array2[5]); outvec[31] = (outvec[22] = 0f - array2[4]); outvec[30] = (outvec[23] = 0f - array2[3]); outvec[29] = (outvec[24] = 0f - array2[2]); outvec[28] = (outvec[25] = 0f - array2[1]); outvec[27] = (outvec[26] = 0f - array2[0]); } private static float ICOS72_A(int i) { return icos72_table[2 * i]; } private static float ICOS36_A(int i) { return icos72_table[4 * i + 1]; } private static void imdct_9pt(float[] invec, float[] outvec) { float[] array = new float[5]; float[] array2 = new float[4]; float num = invec[6] / 2f + invec[0]; float num2 = invec[0] - invec[6]; float num3 = invec[2] - invec[4] - invec[8]; array[0] = num + invec[2] * 0.9396926f + invec[4] * 0.76604444f + invec[8] * 0.17364818f; array[1] = num3 / 2f + num2; array[2] = num - invec[2] * 0.17364818f - invec[4] * 0.9396926f + invec[8] * 0.76604444f; array[3] = num - invec[2] * 0.76604444f + invec[4] * 0.17364818f - invec[8] * 0.9396926f; array[4] = num2 - num3; float num4 = invec[1] + invec[3]; float num5 = invec[3] + invec[5]; num = (invec[5] + invec[7]) * 0.5f + invec[1]; array2[0] = num + num4 * 0.9396926f + num5 * 0.76604444f; array2[1] = (invec[1] - invec[5]) * 1.5f - invec[7]; array2[2] = num - num4 * 0.17364818f - num5 * 0.9396926f; array2[3] = num - num4 * 0.76604444f + num5 * 0.17364818f; array2[0] += invec[7] * 0.17364818f; array2[1] -= invec[7] * 0.5f; array2[2] += invec[7] * 0.76604444f; array2[3] -= invec[7] * 0.9396926f; array2[0] *= 0.5077133f; array2[1] *= 0.57735026f; array2[2] *= 0.7778619f; array2[3] *= 1.4619021f; for (int i = 0; i < 4; i++) { outvec[i] = array[i] + array2[i]; } outvec[4] = array[4]; for (int i = 5; i < 9; i++) { outvec[i] = array[8 - i] - array2[8 - i]; } } private void ShortImpl(float[] fsIn, int sbStart, float[] nextblck) { _ = _swin[2]; int num = sbStart; int num2 = sbStart * 18; while (num < 32) { int i = 0; int num3 = 0; for (; i < 3; i++) { int num4 = num2 + i; for (int j = 0; j < 6; j++) { _imdctTemp[num3 + j] = fsIn[num4]; num4 += 3; } num3 += 6; } Array.Clear(fsIn, num2, 6); ShortIMDCT(_imdctTemp, 0, _imdctResult); Array.Copy(_imdctResult, 0, fsIn, num2 + 6, 12); ShortIMDCT(_imdct
plugins/SentrySound/SentrySound.Core.dll
Decompiled 2 weeks agousing System; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using NLayer; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("SentrySound.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SentrySound.Core")] [assembly: AssemblyTitle("SentrySound.Core")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SentrySound.Core { public sealed record DecodedTrack(TrackInfo Info, float[] Samples, int PeakIndex = 0); public static class AudioDecoder { public const int MaxFrames = 16000000; public static string[] Discover(string directory) { return (from g in (from p in Directory.EnumerateFiles(directory) where Path.GetExtension(p).Equals(".mp3", StringComparison.OrdinalIgnoreCase) || Path.GetExtension(p).Equals(".wav", StringComparison.OrdinalIgnoreCase) select p).GroupBy<string, string>(Path.GetFileNameWithoutExtension, StringComparer.OrdinalIgnoreCase) select g.OrderBy((string p) => (!Path.GetExtension(p).Equals(".mp3", StringComparison.OrdinalIgnoreCase)) ? 1 : 0).ThenBy<string, string>((string p) => p, StringComparer.Ordinal).First()).OrderBy<string, string>((string p) => Path.GetFileName(p), StringComparer.OrdinalIgnoreCase).ToArray(); } public static DecodedTrack Decode(string path, CancellationToken cancellation = default(CancellationToken)) { return DecodeInternal(path, retainSamples: true, cancellation); } public static TrackInfo Inspect(string path, CancellationToken cancellation = default(CancellationToken)) { return DecodeInternal(path, retainSamples: false, cancellation).Info; } private static DecodedTrack DecodeInternal(string path, bool retainSamples, CancellationToken cancellation) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (new FileInfo(path).Length > 67108864) { throw new InvalidDataException("Encoded file exceeds 64 MiB limit."); } byte[] array = File.ReadAllBytes(path); cancellation.ThrowIfCancellationRequested(); using MemoryStream memoryStream = new MemoryStream(array, writable: false); int rate; int num; float[] array3; BinaryReader reader; if (Path.GetExtension(path).Equals(".mp3", StringComparison.OrdinalIgnoreCase)) { MpegFile val = new MpegFile((Stream)memoryStream); try { rate = val.SampleRate; int channels = val.Channels; ValidateFormat(channels, rate); float[] array2 = new float[4096 * channels]; List<float> list = (retainSamples ? new List<float>() : null); num = 0; int num2; while ((num2 = val.ReadSamples(array2, 0, array2.Length)) > 0) { cancellation.ThrowIfCancellationRequested(); if (num2 % channels != 0) { throw new InvalidDataException("Incomplete MP3 sample frame."); } num += num2 / channels; if (num > 16000000) { throw new InvalidDataException("Decoded track exceeds memory limit."); } for (int i = 0; i < num2; i += channels) { float num3 = ((channels == 1) ? array2[i] : ((array2[i] + array2[i + 1]) * 0.5f)); if (!float.IsFinite(num3)) { throw new InvalidDataException("Invalid MP3 sample."); } list?.Add(Math.Clamp(num3, -1f, 1f)); } } array3 = list?.ToArray() ?? Array.Empty<float>(); } finally { ((IDisposable)val)?.Dispose(); } } else { reader = new BinaryReader(memoryStream, Encoding.ASCII, leaveOpen: true); try { if (Four() != "RIFF") { throw new InvalidDataException("Expected RIFF."); } reader.ReadUInt32(); if (Four() != "WAVE") { throw new InvalidDataException("Expected WAVE."); } int num4 = 0; int num5 = 0; int num6 = 0; rate = 0; long num7 = -1L; uint num8 = 0u; while (memoryStream.Position + 8 <= memoryStream.Length) { string text = Four(); uint num9 = reader.ReadUInt32(); long position = memoryStream.Position; long num10 = position + num9 + (num9 & 1); if (num10 > memoryStream.Length) { throw new InvalidDataException("Truncated WAV chunk."); } if (text == "fmt ") { if (num9 < 16) { throw new InvalidDataException("Short WAV fmt chunk."); } num6 = reader.ReadUInt16(); num4 = reader.ReadUInt16(); rate = reader.ReadInt32(); reader.ReadUInt32(); reader.ReadUInt16(); num5 = reader.ReadUInt16(); } else if (text == "data") { num7 = position; num8 = num9; } memoryStream.Position = num10; } ValidateFormat(num4, rate); if (num6 != 1 || num5 != 16 || num7 < 0 || num8 % (num4 * 2) != 0L) { throw new InvalidDataException("Expected complete 16-bit PCM WAV frames."); } int num11; checked { num11 = (int)unchecked(num8 / checked(num4 * 2)); num = num11; if (num11 > 16000000) { throw new InvalidDataException("Decoded track exceeds memory limit."); } array3 = (retainSamples ? new float[num11] : Array.Empty<float>()); memoryStream.Position = num7; } for (int j = 0; j < num11; j++) { if (j % 4096 == 0) { cancellation.ThrowIfCancellationRequested(); } float num12 = (float)reader.ReadInt16() / 32768f; if (num4 == 2) { num12 = (num12 + (float)reader.ReadInt16() / 32768f) * 0.5f; } if (retainSamples) { array3[j] = num12; } } } finally { if (reader != null) { ((IDisposable)reader).Dispose(); } } } if (num == 0) { throw new InvalidDataException("Empty audio track."); } int num13 = 0; for (int k = 1; k < array3.Length; k++) { if (Math.Abs(array3[k]) > Math.Abs(array3[num13])) { num13 = k; } } return new DecodedTrack(new TrackInfo(Path.GetFileName(path), Convert.ToHexString(SHA256.HashData(array)), num, rate), array3, num13); string Four() { return Encoding.ASCII.GetString(reader.ReadBytes(4)); } } private static void ValidateFormat(int channels, int rate) { if (channels < 1 || channels > 2 || rate < 8000 || rate > 96000) { throw new InvalidDataException("Supported audio: mono/stereo, 8–96 kHz."); } } } public static class AudioPathResolver { public static string Resolve(string configuredPath, string assemblyLocation, string fallbackDirectory) { if (string.IsNullOrWhiteSpace(configuredPath)) { throw new ArgumentException("Audio path cannot be empty.", "configuredPath"); } if (Path.IsPathRooted(configuredPath)) { return Path.GetFullPath(configuredPath); } string text = (string.IsNullOrWhiteSpace(assemblyLocation) ? null : Path.GetDirectoryName(Path.GetFullPath(assemblyLocation))); return Path.GetFullPath(Path.Combine(string.IsNullOrWhiteSpace(text) ? Path.GetFullPath(fallbackDirectory) : text, configuredPath)); } } public static class DistanceGain { public static float Evaluate(float distance, float radius) { if (!float.IsFinite(distance) || !float.IsFinite(radius) || radius <= 0f) { return 0f; } return Math.Clamp(1f - Math.Max(0f, distance) / radius, 0f, 1f); } } public sealed record TrackInfo(string Name, string ContentHash, int Frames, int Rate) { public double Duration => (double)Frames / (double)Rate; } public sealed class Playlist { private readonly TrackInfo[] _tracks; private readonly int[] _order; public ulong Fingerprint { get; } public double Duration { get; } public IReadOnlyList<int> Order => Array.AsReadOnly(_order); public Playlist(IEnumerable<TrackInfo> tracks, uint seed) { _tracks = tracks.ToArray(); if (_tracks.Length == 0 || _tracks.Any((TrackInfo t) => t.Frames <= 0 || t.Rate <= 0)) { throw new ArgumentException("Playlist requires valid tracks."); } string s = string.Join("\n", _tracks.Select((TrackInfo t) => $"{t.Name.ToLowerInvariant()}|{t.ContentHash}|{t.Frames}|{t.Rate}")); Fingerprint = BinaryPrimitives.ReadUInt64LittleEndian(SHA256.HashData(Encoding.UTF8.GetBytes(s))); Duration = _tracks.Sum((TrackInfo t) => t.Duration); _order = Enumerable.Range(0, _tracks.Length).ToArray(); uint state = ((seed == 0) ? 2654435769u : seed); for (int num = _order.Length - 1; num > 0; num--) { uint num2 = (uint)(num + 1); uint num3 = (0 - num2) % num2; uint num4; do { num4 = Next(); } while (num4 < num3); int num5 = (int)(num4 % num2); ref int reference = ref _order[num]; ref int reference2 = ref _order[num5]; int num6 = _order[num5]; int num7 = _order[num]; reference = num6; reference2 = num7; } uint Next() { state ^= state << 13; state ^= state >> 17; state ^= state << 5; return state; } } public (int Index, double Position) Locate(double elapsed) { if (!double.IsFinite(elapsed) || elapsed < 0.0) { throw new ArgumentOutOfRangeException("elapsed"); } double num = elapsed % Duration; int[] order = _order; foreach (int num2 in order) { if (num < _tracks[num2].Duration) { return (Index: num2, Position: num); } num -= _tracks[num2].Duration; } return (Index: _order[0], Position: 0.0); } public int NextIndex(int index) { int num = Array.IndexOf(_order, index); if (num < 0) { throw new ArgumentOutOfRangeException("index"); } return _order[(num + 1) % _order.Length]; } } public sealed class SessionTimeline { private double _anchorClock; private double _anchorPosition; public bool IsPlaying { get; private set; } public long Revision { get; private set; } public void Play(double clock, double positionSeconds = 0.0) { ValidateClock(clock); ValidatePosition(positionSeconds); _anchorClock = clock; _anchorPosition = positionSeconds; IsPlaying = true; Revision++; } public void Pause(double clock, double durationSeconds) { if (IsPlaying) { _anchorPosition = GetPosition(clock, durationSeconds); _anchorClock = clock; IsPlaying = false; Revision++; } } public void Resume(double clock) { ValidateClock(clock); if (!IsPlaying) { _anchorClock = clock; IsPlaying = true; Revision++; } } public void Seek(double clock, double positionSeconds) { ValidateClock(clock); ValidatePosition(positionSeconds); _anchorClock = clock; _anchorPosition = positionSeconds; Revision++; } public double GetPosition(double clock, double durationSeconds) { ValidateClock(clock); if (!double.IsFinite(durationSeconds) || durationSeconds <= 0.0) { return 0.0; } double val = (IsPlaying ? (clock - _anchorClock) : 0.0); double num = (_anchorPosition + Math.Max(0.0, val)) % durationSeconds; if (!(num < 0.0)) { return num; } return num + durationSeconds; } private static void ValidateClock(double value) { if (!double.IsFinite(value) || value < 0.0) { throw new ArgumentOutOfRangeException("value", "Clock must be finite and non-negative."); } } private static void ValidatePosition(double value) { if (!double.IsFinite(value) || value < 0.0) { throw new ArgumentOutOfRangeException("value", "Position must be finite and non-negative."); } } } public static class SyncRules { public static bool AcceptEnvelope(ulong sender, ulong master, int protocol, ulong session, double elapsed, ulong sequence, ulong currentSession, ulong lastSequence) { if (master != 0L && sender == master && protocol == 2 && session != 0L && double.IsFinite(elapsed) && elapsed >= 0.0 && elapsed <= 2592000.0) { if (session == currentSession) { return sequence > lastSequence; } return true; } return false; } } }
plugins/SentrySound/SentrySound.dll
Decompiled 2 weeks agousing System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using GTFO.API; using HarmonyLib; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Microsoft.CodeAnalysis; using Player; using SNetwork; using SentrySound.Core; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("SentrySound")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SentrySound")] [assembly: AssemblyTitle("SentrySound")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SentrySound { internal sealed class AudioLibrary : IDisposable { private readonly CancellationTokenSource _cancel = new CancellationTokenSource(); private readonly ManualLogSource _log; private readonly string _folder; private readonly Task<TrackInfo[]> _indexWorker; private readonly Dictionary<int, AudioClip> _clips = new Dictionary<int, AudioClip>(); private readonly HashSet<int> _failed = new HashSet<int>(); private readonly HashSet<int> _wanted = new HashSet<int>(); private Task<DecodedTrack>? _decoder; private DecodedTrack? _pending; private AudioClip? _upload; private Il2CppStructArray<float>? _buffer; private int _decodeIndex = -1; private int _offset; private int _probeIndex; private float _probeValue; private bool _disposed; private int _wantedCurrent = -2; private int _wantedNext = -2; public List<TrackInfo> Tracks { get; } = new List<TrackInfo>(); public bool Ready { get; private set; } public AudioLibrary(string folder, ManualLogSource log) { AudioLibrary audioLibrary = this; _folder = folder; _log = log; _indexWorker = Task.Run(delegate { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown List<TrackInfo> list = new List<TrackInfo>(); string[] array = AudioDecoder.Discover(folder); if (array.Length > 256) { throw new InvalidDataException("Maximum 256 tracks per library."); } string[] array2 = array; bool flag = default(bool); foreach (string text in array2) { audioLibrary._cancel.Token.ThrowIfCancellationRequested(); try { Stopwatch stopwatch = Stopwatch.StartNew(); TrackInfo val = AudioDecoder.Inspect(text, audioLibrary._cancel.Token); list.Add(val); ManualLogSource log2 = audioLibrary._log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(23, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Indexed "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(val.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(val.Duration, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s; workerMs="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(stopwatch.Elapsed.TotalMilliseconds, "0.0"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log2.LogInfo(val2); } catch (OperationCanceledException) { throw; } catch (Exception ex2) { ManualLogSource log3 = audioLibrary._log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(10, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Skipped "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(Path.GetFileName(text)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex2.Message); } log3.LogError(val3); } } return list.ToArray(); }); } public AudioClip? GetClip(int index) { if (!_clips.TryGetValue(index, out AudioClip value)) { return null; } return value; } public void EnsureTracks(int current, int next) { if (_disposed || !Ready) { return; } if (_wantedCurrent != current || _wantedNext != next) { _wantedCurrent = current; _wantedNext = next; _wanted.Clear(); if (current >= 0) { _wanted.Add(current); } if (next >= 0) { _wanted.Add(next); } int[] array = _clips.Keys.Where((int i) => !_wanted.Contains(i)).ToArray(); foreach (int key in array) { Object.Destroy((Object)(object)_clips[key]); _clips.Remove(key); } } if (_pending != (DecodedTrack)null && !_wanted.Contains(_decodeIndex)) { DiscardUpload(); } if (_decoder != null || _pending != (DecodedTrack)null) { return; } for (int num2 = 0; num2 < 2; num2++) { int num3 = ((num2 == 0) ? current : next); if (num3 < 0 || _clips.ContainsKey(num3) || _failed.Contains(num3)) { continue; } TrackInfo expected = Tracks[num3]; _decodeIndex = num3; _decoder = Task.Run(delegate { DecodedTrack obj = AudioDecoder.Decode(Path.Combine(_folder, expected.Name), _cancel.Token); if (obj.Info != expected) { throw new InvalidDataException("Audio changed after indexing. Restart the game on all clients."); } return obj; }); break; } } public void Tick() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (_disposed) { return; } bool flag = default(bool); if (!Ready) { if (!_indexWorker.IsCompleted) { return; } try { Tracks.AddRange(_indexWorker.GetAwaiter().GetResult()); } catch (Exception ex) { ManualLogSource log = _log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio catalog failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } Ready = true; ManualLogSource log2 = _log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(64, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Audio library ready: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Tracks.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" tracks; two-track cache; total duration="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(Tracks.Sum((TrackInfo t) => t.Duration), "0.0"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s."); } log2.LogInfo(val2); } Task<DecodedTrack>? decoder = _decoder; if (decoder != null && decoder.IsCompleted) { try { DecodedTrack result = _decoder.GetAwaiter().GetResult(); if (_wanted.Contains(_decodeIndex)) { _pending = result; } else { _decodeIndex = -1; } } catch (Exception ex2) { _failed.Add(_decodeIndex); ManualLogSource log3 = _log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio decode failed for index "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_decodeIndex); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2); } log3.LogError(val); _decodeIndex = -1; } _decoder = null; } Stopwatch stopwatch = Stopwatch.StartNew(); for (int num = 0; num < 16; num++) { if (!(stopwatch.Elapsed.TotalMilliseconds < 2.0)) { break; } if (!(_pending != (DecodedTrack)null)) { break; } UploadSlice(); } } private void UploadSlice() { //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Expected O, but got Unknown //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Expected O, but got Unknown Stopwatch stopwatch = Stopwatch.StartNew(); bool flag = default(bool); try { if ((Object)(object)_upload == (Object)null) { _upload = AudioClip.Create(_pending.Info.Name, _pending.Info.Frames, 1, _pending.Info.Rate, false); ((Object)_upload).hideFlags = (HideFlags)32; _offset = 0; _probeIndex = _pending.PeakIndex; _probeValue = _pending.Samples[_probeIndex]; return; } int num = Math.Min(32768, _pending.Samples.Length - _offset); if (_buffer == null) { _buffer = new Il2CppStructArray<float>(32768L); } Marshal.Copy(_pending.Samples, _offset, IntPtr.Add(((Il2CppObjectBase)_buffer).Pointer, 4 * IntPtr.Size), num); if (((Il2CppArrayBase<float>)(object)_buffer)[0] != _pending.Samples[_offset] || ((Il2CppArrayBase<float>)(object)_buffer)[num - 1] != _pending.Samples[_offset + num - 1]) { throw new InvalidOperationException("Native PCM buffer copy failed."); } if (!AudioClip.SetData(_upload, _buffer, num, _offset)) { throw new InvalidOperationException("PCM upload rejected."); } _offset += num; if (_offset >= _pending.Samples.Length) { Il2CppStructArray<float> val = new Il2CppStructArray<float>(1L); if (!_upload.GetData(val, _probeIndex) || Math.Abs(((Il2CppArrayBase<float>)(object)val)[0] - _probeValue) > 0.0001f) { throw new InvalidOperationException("PCM upload read-back mismatch."); } _clips.Add(_decodeIndex, _upload); ManualLogSource log = _log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(45, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("PCM transfer verified: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(_pending.Info.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; cachedClips="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_clips.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; peak="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(Math.Abs(_probeValue), "0.000000"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); _pending = null; _upload = null; _decodeIndex = -1; } } catch (Exception ex) { _failed.Add(_decodeIndex); ManualLogSource log2 = _log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(21, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Track upload failed: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex); } log2.LogError(val3); DiscardUpload(); } finally { if (stopwatch.Elapsed.TotalMilliseconds > 15.0) { ManualLogSource log3 = _log; BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(36, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Performance: audio upload slice "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<double>(stopwatch.Elapsed.TotalMilliseconds, "0.0"); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ms."); } log3.LogWarning(val4); } } } private void DiscardUpload() { if ((Object)(object)_upload != (Object)null) { Object.Destroy((Object)(object)_upload); } _upload = null; _pending = null; _decodeIndex = -1; } public void Dispose() { if (_disposed) { return; } _disposed = true; _cancel.Cancel(); DiscardUpload(); foreach (AudioClip value in _clips.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } _clips.Clear(); Task.WhenAll((_decoder != null) ? new Task[2] { _indexWorker, _decoder } : new Task[1] { _indexWorker }).ContinueWith(delegate(Task task) { _ = task.Exception; _cancel.Dispose(); }, TaskScheduler.Default); } } internal static class AudioSignalDiagnostics { public static string Levels(Il2CppStructArray<float> data) { double num = 0.0; double num2 = 0.0; int num3 = 0; for (int i = 0; i < ((Il2CppArrayBase<float>)(object)data).Length; i++) { float num4 = ((Il2CppArrayBase<float>)(object)data)[i]; if (!float.IsFinite(num4)) { num3++; continue; } num2 = Math.Max(num2, Math.Abs(num4)); num += (double)num4 * (double)num4; } return FormattableString.Invariant($"peak={num2:0.000000}; rms={Math.Sqrt(num / (double)Math.Max(1, ((Il2CppArrayBase<float>)(object)data).Length)):0.000000}; invalid={num3}"); } public static void Clip(ManualLogSource? log, AudioClip clip, string phase) { //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown bool flag = default(bool); try { Stopwatch stopwatch = Stopwatch.StartNew(); int num = Math.Min(256, clip.samples); Il2CppStructArray<float> val = new Il2CppStructArray<float>((long)(num * clip.channels)); double num2 = 0.0; double num3 = 0.0; long num4 = 0L; for (int i = 0; i < 3; i++) { int num5 = (int)((long)(clip.samples - num) * (long)i / 2); if (!clip.GetData(val, num5)) { ManualLogSource val2 = log; if (val2 != null) { BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(48, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Signal PCM ["); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("]: GetData returned false at frame "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num5); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } val2.LogWarning(val3); } return; } int length = ((Il2CppArrayBase<float>)(object)val).Length; for (int j = 0; j < length; j++) { float num6 = ((Il2CppArrayBase<float>)(object)val)[j]; if (!float.IsFinite(num6)) { throw new InvalidDataException("Non-finite PCM sample."); } num2 = Math.Max(num2, Math.Abs(num6)); num3 += (double)num6 * (double)num6; num4++; } } if (log != null) { log.LogInfo((object)FormattableString.Invariant($"Signal PCM windows [{phase}]: sampledValues={num4}; peak={num2:0.000000}; rms={Math.Sqrt(num3 / (double)Math.Max(1L, num4)):0.000000}; elapsedMs={stopwatch.Elapsed.TotalMilliseconds:0.00}. Quiet windows alone do not imply a silent track.")); } } catch (Exception ex) { ManualLogSource val2 = log; if (val2 != null) { BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(27, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Signal PCM ["); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(phase); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("] unavailable: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex); } val2.LogWarning(val3); } } } public static void Output(ManualLogSource? log, AudioSource? source, string label) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown bool flag = default(bool); try { Il2CppStructArray<float> val = new Il2CppStructArray<float>(1024L); if ((Object)(object)source != (Object)null) { source.GetOutputData(val, 0); } else { AudioListener.GetOutputData(val, 0); } ManualLogSource val2 = log; if (val2 != null) { BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(30, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Signal output ["); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(label); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("; channel=0]: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(Levels(val)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } val2.LogInfo(val3); } } catch (Exception ex) { ManualLogSource val2 = log; if (val2 != null) { BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(30, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Signal output ["); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(label); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("] unavailable: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Exception>(ex); } val2.LogWarning(val4); } } } } internal sealed class LocalAudioListener : IDisposable { private readonly ManualLogSource _log; private GameObject? _holder; private AudioListener? _owned; private AudioListener? _active; private float _nextScan; private int _lastListenerId; public AudioListener? Active => _active; public LocalAudioListener(ManualLogSource log) { _log = log; } public void Refresh(bool hasSpeakers, bool forceScan = false) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Expected O, but got Unknown if (!hasSpeakers || !PlayerManager.HasLocalPlayerAgent()) { if ((Object)(object)_owned != (Object)null) { ((Behaviour)_owned).enabled = false; } _active = null; return; } PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); LocalPlayerAgent val = ((localPlayerAgent != null) ? ((Il2CppObjectBase)localPlayerAgent).TryCast<LocalPlayerAgent>() : null); FPSCamera val2 = (((Object)(object)val != (Object)null) ? ((PlayerAgent)val).FPSCamera : null); if ((Object)(object)val2 == (Object)null) { if ((Object)(object)_owned != (Object)null) { ((Behaviour)_owned).enabled = false; } _active = null; return; } if ((Object)(object)_holder != (Object)null) { _holder.transform.position = val2.Position; _holder.transform.rotation = val2.Rotation; } if (!forceScan && (Object)(object)_active != (Object)null && ((Behaviour)_active).isActiveAndEnabled && ((Object)(object)_active != (Object)(object)_owned || Time.unscaledTime < _nextScan)) { return; } _nextScan = Time.unscaledTime + 1f; AudioListener val3 = null; foreach (AudioListener item in Object.FindObjectsOfType<AudioListener>()) { if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)_owned && ((Behaviour)item).isActiveAndEnabled) { val3 = item; break; } } if ((Object)(object)val3 != (Object)null) { if ((Object)(object)_owned != (Object)null) { ((Behaviour)_owned).enabled = false; } _active = val3; } else { if ((Object)(object)_owned == (Object)null) { _holder = new GameObject("SentrySound.LocalListener"); ((Object)_holder).hideFlags = (HideFlags)61; _holder.transform.position = val2.Position; _holder.transform.rotation = val2.Rotation; Object.DontDestroyOnLoad((Object)(object)_holder); _owned = _holder.AddComponent<AudioListener>(); _log.LogInfo((object)"No active Unity AudioListener found. Created listener following the local player's camera."); } ((Behaviour)_owned).enabled = true; _active = _owned; } int instanceID = ((Object)_active).GetInstanceID(); if (instanceID != _lastListenerId) { _lastListenerId = instanceID; ManualLogSource log = _log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(43, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Audio listener: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)((Component)_active).gameObject).name); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("; owned="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>((Object)(object)_active == (Object)(object)_owned); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("; volume="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(AudioListener.volume, "0.00"); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("; paused="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(AudioListener.pause); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("."); } log.LogInfo(val4); } } public void Dispose() { if ((Object)(object)_owned != (Object)null) { ((Behaviour)_owned).enabled = false; } if ((Object)(object)_holder != (Object)null) { Object.Destroy((Object)(object)_holder); } _owned = null; _holder = null; _active = null; } } [BepInPlugin("dev.lucas.sentrysound", "SentinelaFuracao", "1.0.0")] [BepInProcess("GTFO.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BasePlugin { private Harmony? _harmony; private SentryAudioHost? _host; internal static ManualLogSource? DiagnosticLog { get; private set; } public override void Load() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) DiagnosticLog = ((BasePlugin)this).Log; SentrySoundSettings settings = SentrySoundSettings.Bind(((BasePlugin)this).Config); _host = ((BasePlugin)this).AddComponent<SentryAudioHost>(); _host.Initialize(settings, ((BasePlugin)this).Log); ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(66, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio host attached to BepInEx manager; flags="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<HideFlags>(((Object)((Component)_host).gameObject).hideFlags); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; active="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(((Component)_host).gameObject.activeInHierarchy); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; enabled="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(((Behaviour)_host).enabled); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogInfo(val); _harmony = new Harmony("dev.lucas.sentrysound"); _harmony.PatchAll(typeof(Plugin).Assembly); ManualLogSource log2 = ((BasePlugin)this).Log; val = new BepInExInfoLogInterpolatedStringHandler(31, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("SentinelaFuracao"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded. Waiting for sentries."); } log2.LogInfo(val); } public override bool Unload() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)_host != (Object)null) { _host.Shutdown(); Object.Destroy((Object)(object)_host); _host = null; } return true; } } internal static class PluginInfo { public const string Guid = "dev.lucas.sentrysound"; public const string Name = "SentinelaFuracao"; public const string FolderName = "SentrySound"; public const string Version = "1.0.0"; } internal sealed class SentryAudioHost : MonoBehaviour { private sealed class Speaker { public GameObject Target { get; } public AudioSource Source { get; } public float CameraDistance { get; set; } = -1f; public Speaker(GameObject target, AudioSource source) { Target = target; Source = source; } } private readonly Dictionary<int, Speaker> _speakers = new Dictionary<int, Speaker>(); private AudioLibrary? _library; private SessionSync? _sync; private bool _libraryRegistered; private int _trackIndex = -1; private double _trackPosition; private float _nextDriftCheck; private double _lastFrameStart; private double _lastUpdateMs; private double _lastLateUpdateMs; private double _nextGapLog; private SentrySoundSettings? _settings; private ManualLogSource? _log; private AudioClip? _clip; private LocalAudioListener? _listener; private float _nextDiagnostic; private int _diagnosticsRemaining; private double _previousDspTime; private bool _updateErrorReported; private bool _updateLoopReported; private bool _shutdown; private VolumePanel? _panel; private bool _panelErrorReported; public static SentryAudioHost? Instance { get; private set; } public SentryAudioHost(IntPtr pointer) : base(pointer) { } [HideFromIl2Cpp] public void Initialize(SentrySoundSettings settings, ManualLogSource log) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown Instance = this; _settings = settings; _panel = new VolumePanel(settings); _log = log; _listener = new LocalAudioListener(log); if (!settings.Enabled.Value) { log.LogInfo((object)"Audio is disabled in configuration."); return; } _sync = new SessionSync(log); string text = ResolveAudioPath(settings.AudioFolder.Value); bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio folder resolved to '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'."); } log.LogInfo(val); _library = new AudioLibrary(text, log); log.LogInfo((object)"Preparing MP3/WAV playlist asynchronously; sentry audio waits until the library and host session are ready."); } [HideFromIl2Cpp] public void Attach(GameObject sentry) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown if (_settings == null || !_settings.Enabled.Value || (Object)(object)sentry == (Object)null) { return; } int instanceID = ((Object)sentry).GetInstanceID(); if (_speakers.ContainsKey(instanceID)) { return; } GameObject val = new GameObject($"SentrySound.Speaker.{instanceID}") { hideFlags = (HideFlags)61 }; val.transform.SetParent(((Component)this).transform, false); AudioSource val2 = val.AddComponent<AudioSource>(); val2.playOnAwake = false; val2.loop = false; val2.spatialBlend = 1f; val2.rolloffMode = (AudioRolloffMode)1; val2.dopplerLevel = 0f; val2.minDistance = 2f; val2.maxDistance = 3f; val2.volume = 0f; _speakers.Add(instanceID, new Speaker(sentry, val2)); _listener?.Refresh(hasSpeakers: true, forceScan: true); RefreshSpatialSpeakers(); StartSpeaker(val2); _diagnosticsRemaining = 2; _nextDiagnostic = Time.unscaledTime + 1f; _previousDspTime = AudioSettings.dspTime; ManualLogSource log = _log; if (log != null) { bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(39, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Attached positional speaker to sentry "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(instanceID); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("."); } log.LogInfo(val3); } } [HideFromIl2Cpp] public void Detach(GameObject sentry) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown if ((Object)(object)sentry == (Object)null) { return; } int instanceID = ((Object)sentry).GetInstanceID(); if (!_speakers.Remove(instanceID, out Speaker value)) { return; } _panel?.CloseForTarget(sentry); if ((Object)(object)value.Source != (Object)null) { value.Source.Stop(); Object.Destroy((Object)(object)((Component)value.Source).gameObject); } if (_speakers.Count == 0) { _listener?.Refresh(hasSpeakers: false); } ManualLogSource log = _log; if (log != null) { bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(40, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Removed positional speaker from sentry "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(instanceID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogInfo(val); } } [HideFromIl2Cpp] public void Shutdown() { if (_shutdown) { return; } _shutdown = true; _panel?.Shutdown(); foreach (Speaker value in _speakers.Values) { if ((Object)(object)value.Source != (Object)null) { value.Source.Stop(); Object.Destroy((Object)(object)((Component)value.Source).gameObject); } } _speakers.Clear(); _listener?.Dispose(); _listener = null; _sync?.Dispose(); _library?.Dispose(); _clip = null; if (Instance == this) { Instance = null; } } private void Update() { //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if (_shutdown || _settings == null) { return; } Stopwatch stopwatch = Stopwatch.StartNew(); double num = (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; bool flag = default(bool); if (_lastFrameStart > 0.0 && num - _lastFrameStart > 0.25 && num >= _nextGapLog) { _nextGapLog = num + 2.0; ManualLogSource log = _log; if (log != null) { BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(107, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Frame gap="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<double>((num - _lastFrameStart) * 1000.0, "0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ms; previous SentrySound Update="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<double>(_lastUpdateMs, "0.00"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ms; LateUpdate="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<double>(_lastLateUpdateMs, "0.00"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ms; state="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<eGameStateName>(GameStateManager.CurrentStateName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Gap alone does not identify the cause."); } log.LogWarning(val); } } _lastFrameStart = num; try { if (!_updateLoopReported) { _updateLoopReported = true; ManualLogSource? log2 = _log; if (log2 != null) { log2.LogInfo((object)"Audio host update loop active. Deploy a sentry to start positional playback."); } } _library?.Tick(); if (!_libraryRegistered) { AudioLibrary? library = _library; if (library != null && library.Ready) { _sync?.SetLibrary(_library.Tracks); _libraryRegistered = true; } } _sync?.Tick(); RefreshPlaylist(); _panel?.Tick(FindPanelTarget); RemoveDestroyedSentries(); LogPlaybackDiagnostics(); } catch (Exception ex) { _panel?.Close(); if (!_updateErrorReported) { ManualLogSource log = _log; if (log != null) { BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(21, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Audio update failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex); } log.LogError(val2); } } _updateErrorReported = true; } finally { _lastUpdateMs = stopwatch.Elapsed.TotalMilliseconds; if (_lastUpdateMs > 15.0) { ManualLogSource log = _log; if (log != null) { BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Performance: SentrySound Update="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<double>(_lastUpdateMs, "0.00"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ms."); } log.LogWarning(val); } } } } private void LateUpdate() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown if (_shutdown) { return; } Stopwatch stopwatch = Stopwatch.StartNew(); bool flag = default(bool); try { _listener?.Refresh(_speakers.Count > 0); RefreshSpatialSpeakers(); } catch (Exception ex) { if (!_updateErrorReported) { ManualLogSource log = _log; if (log != null) { BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio listener update failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } _updateErrorReported = true; } finally { _lastLateUpdateMs = stopwatch.Elapsed.TotalMilliseconds; if (_lastLateUpdateMs > 15.0) { ManualLogSource log = _log; if (log != null) { BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(39, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Performance: SentrySound LateUpdate="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(_lastLateUpdateMs, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("ms."); } log.LogWarning(val2); } } } } private void OnDestroy() { if (!_shutdown) { ManualLogSource? log = _log; if (log != null) { log.LogWarning((object)"Audio host destroyed unexpectedly. Automatic speaker updates are no longer available on this host."); } } Shutdown(); } private void OnGUI() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (_shutdown || _panelErrorReported) { return; } try { _panel?.Draw(); } catch (Exception ex) { _panelErrorReported = true; _panel?.Close(); ManualLogSource log = _log; if (log != null) { bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Volume panel rendering failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } } private GameObject? FindPanelTarget() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (_panelErrorReported || !PlayerManager.HasLocalPlayerAgent()) { return null; } PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); LocalPlayerAgent val = ((localPlayerAgent != null) ? ((Il2CppObjectBase)localPlayerAgent).TryCast<LocalPlayerAgent>() : null); FPSCamera val2 = (((Object)(object)val != (Object)null) ? ((PlayerAgent)val).FPSCamera : null); if ((Object)(object)val2 == (Object)null) { return null; } GameObject result = null; float num = 0.8f; Vector3 val3 = val2.Rotation * Vector3.forward; foreach (Speaker value in _speakers.Values) { if ((Object)(object)value.Target == (Object)null) { continue; } Vector3 val4 = value.Target.transform.position - val2.Position; if (!(((Vector3)(ref val4)).magnitude > 4f)) { float num2 = Vector3.Dot(val3, ((Vector3)(ref val4)).normalized); if (!(num2 <= num)) { result = value.Target; num = num2; } } } return result; } private void RefreshPlaylist() { //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown if (_sync?.Playlist == null || _library == null) { _library?.EnsureTracks(-1, -1); if (_trackIndex < 0) { return; } foreach (Speaker value in _speakers.Values) { if ((Object)(object)value.Source != (Object)null) { value.Source.Stop(); } } _trackIndex = -1; _clip = null; _panel?.Close(); return; } (int, double) tuple = _sync.Playlist.Locate(_sync.Elapsed); _library.EnsureTracks(tuple.Item1, _sync.Playlist.NextIndex(tuple.Item1)); _trackPosition = tuple.Item2; AudioClip clip = _library.GetClip(tuple.Item1); if ((Object)(object)clip == (Object)null) { if (_trackIndex >= 0) { foreach (Speaker value2 in _speakers.Values) { if ((Object)(object)value2.Source != (Object)null) { value2.Source.Stop(); } } } _trackIndex = -1; _clip = null; return; } bool flag = _trackIndex != tuple.Item1 || (Object)(object)_clip != (Object)(object)clip; if (flag) { _trackIndex = tuple.Item1; _clip = clip; ManualLogSource log = _log; if (log != null) { bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(24, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Now playing: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(_library.Tracks[_trackIndex].Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; offset="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<double>(_trackPosition, "0.000"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s."); } log.LogInfo(val); } } bool flag3 = Time.unscaledTime >= _nextDriftCheck; if (flag3) { _nextDriftCheck = Time.unscaledTime + 2f; } foreach (Speaker value3 in _speakers.Values) { AudioSource source = value3.Source; if (!((Object)(object)source == (Object)null) && (flag || !source.isPlaying || (flag3 && (Object)(object)_clip != (Object)null && Math.Abs((double)source.timeSamples / (double)_clip.frequency - _trackPosition) > 0.2))) { StartSpeaker(source); } } } private void StartSpeaker(AudioSource source) { if (!((Object)(object)_clip == (Object)null) && !((Object)(object)source == (Object)null)) { source.clip = _clip; int timeSamples = Math.Clamp((int)Math.Floor(_trackPosition * (double)_clip.frequency), 0, Math.Max(0, _clip.samples - 1)); source.timeSamples = timeSamples; source.Play(); } } private void LogPlaybackDiagnostics() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown //IL_02de: Unknown result type (might be due to invalid IL or missing references) if (_diagnosticsRemaining <= 0 || Time.unscaledTime < _nextDiagnostic) { return; } _diagnosticsRemaining--; _nextDiagnostic = Time.unscaledTime + 2f; AudioListener val = _listener?.Active; double dspTime = AudioSettings.dspTime; ManualLogSource log = _log; bool flag = default(bool); if (log != null) { BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(94, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Audio diagnostics: listener="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)(object)val != (Object)null) ? ((Object)((Component)val).gameObject).name : "NONE"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; listenerVolume="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(AudioListener.volume, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; paused="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(AudioListener.pause); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; dspAdvance="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(dspTime - _previousDspTime, "0.000"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s; outputRate="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(AudioSettings.outputSampleRate); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; clipAlive="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>((Object)(object)_clip != (Object)null); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); } _previousDspTime = dspTime; AudioSignalDiagnostics.Output(_log, null, "Unity listener master"); foreach (KeyValuePair<int, Speaker> speaker in _speakers) { AudioSource source = speaker.Value.Source; if ((Object)(object)source == (Object)null) { continue; } AudioSignalDiagnostics.Output(_log, source, $"sentry {speaker.Key}"); float num = (((Object)(object)val != (Object)null) ? Vector3.Distance(((Component)source).transform.position, ((Component)val).transform.position) : (-1f)); log = _log; if (log != null) { BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(99, 9, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Speaker "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(speaker.Key); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": playing="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(source.isPlaying); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; active="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(((Behaviour)source).isActiveAndEnabled); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; sample="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(source.timeSamples); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; volume="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(source.volume, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; mute="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(source.mute); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; cameraDistance="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(speaker.Value.CameraDistance, "0.0"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("m; mappedDistance="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(num, "0.0"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("m; rolloff="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<AudioRolloffMode>(source.rolloffMode); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); } } } private void RemoveDestroyedSentries() { if (_speakers.Count == 0) { return; } List<int> list = null; foreach (KeyValuePair<int, Speaker> speaker in _speakers) { if (!((Object)(object)speaker.Value.Target != (Object)null) || !((Object)(object)speaker.Value.Source != (Object)null)) { if (list == null) { list = new List<int>(); } list.Add(speaker.Key); } } if (list == null) { return; } foreach (int item in list) { AudioSource source = _speakers[item].Source; if ((Object)(object)source != (Object)null) { source.Stop(); Object.Destroy((Object)(object)((Component)source).gameObject); } _speakers.Remove(item); } } private void RefreshSpatialSpeakers() { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) if (_settings == null || _speakers.Count == 0) { return; } float value = _settings.Volume.Value; AudioListener val = _listener?.Active; object obj; if (!PlayerManager.HasLocalPlayerAgent()) { obj = null; } else { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); obj = ((localPlayerAgent != null) ? ((Il2CppObjectBase)localPlayerAgent).TryCast<LocalPlayerAgent>() : null); } LocalPlayerAgent val2 = (LocalPlayerAgent)obj; FPSCamera val3 = (((Object)(object)val2 != (Object)null) ? ((PlayerAgent)val2).FPSCamera : null); foreach (Speaker value2 in _speakers.Values) { AudioSource source = value2.Source; if (!((Object)(object)source == (Object)null)) { if ((Object)(object)value2.Target == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled) { source.volume = 0f; value2.CameraDistance = -1f; continue; } Vector3 val4 = Quaternion.Inverse(val3.Rotation) * (value2.Target.transform.position - val3.Position); Transform transform = ((Component)val).transform; ((Component)source).transform.position = transform.position + transform.rotation * ((Vector3)(ref val4)).normalized; value2.CameraDistance = ((Vector3)(ref val4)).magnitude; source.volume = value * DistanceGain.Evaluate(value2.CameraDistance, _settings.MaximumDistance.Value); } } } private static string ResolveAudioPath(string configuredPath) { return AudioPathResolver.Resolve(configuredPath, typeof(Plugin).Assembly.Location, Path.Combine(Paths.PluginPath, "SentrySound")); } } [HarmonyPatch(typeof(SentryGunInstance), "OnGearSpawnComplete")] internal static class SentryDeployedPatch { [HarmonyWrapSafe] [HarmonyPostfix] private static void Postfix(SentryGunInstance __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown ManualLogSource diagnosticLog = Plugin.DiagnosticLog; if (diagnosticLog != null) { bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Sentry spawn callback received; audioHostAvailable="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>((Object)(object)SentryAudioHost.Instance != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } diagnosticLog.LogInfo(val); } SentryAudioHost.Instance?.Attach(((Component)__instance).gameObject); } } [HarmonyPatch(typeof(SentryGunInstance), "SyncedPickup")] internal static class SentryPickedUpPatch { [HarmonyWrapSafe] [HarmonyPrefix] private static void Prefix(SentryGunInstance __instance) { SentryAudioHost.Instance?.Detach(((Component)__instance).gameObject); } } internal sealed class SentrySoundSettings { private readonly ConfigFile _config; public ConfigEntry<bool> Enabled { get; } public ConfigEntry<string> AudioFolder { get; } public ConfigEntry<float> Volume { get; } public ConfigEntry<float> MaximumDistance { get; } public ConfigEntry<KeyCode> PanelKey { get; } private SentrySoundSettings(ConfigFile config) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown _config = config; config.SaveOnConfigSet = false; float value = config.Bind<float>("Audio", "MasterVolume", 0.18f, (ConfigDescription)null).Value; float value2 = config.Bind<float>("Audio", "PersonalVolume", 1f, (ConfigDescription)null).Value; config.Bind<float>("Spatial", "MinimumDistance", 2f, (ConfigDescription)null); Enabled = config.Bind<bool>("General", "Enabled", true, "Play music from deployed sentries."); string value3 = config.Bind<string>("Audio", "File", "test-tone.wav", (ConfigDescription)null).Value; AudioFolder = config.Bind<string>("Audio", "Folder", Path.IsPathRooted(value3) ? Path.GetDirectoryName(value3) : Path.Combine("audio", Path.GetDirectoryName(value3) ?? ""), "Folder containing MP3 and 16-bit PCM WAV tracks. Relative to the folder containing SentrySound.dll, or absolute. Restart after changes."); Volume = config.Bind<float>("Audio", "Volume", Mathf.Clamp01(value * value2), new ConfigDescription("Local volume only. Never synchronized with other players.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); MaximumDistance = config.Bind<float>("Spatial", "MaximumDistance", 28f, new ConfigDescription("Fade from the sentry center to silence at this distance in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>())); PanelKey = config.Bind<KeyCode>("Controls", "PanelKey", (KeyCode)121, "Open Volume while looking at a nearby sentry."); config.Remove(new ConfigDefinition("Audio", "MasterVolume")); config.Remove(new ConfigDefinition("Audio", "PersonalVolume")); config.Remove(new ConfigDefinition("Spatial", "MinimumDistance")); config.Remove(new ConfigDefinition("Audio", "File")); config.Save(); } public void Save() { _config.Save(); } public static SentrySoundSettings Bind(ConfigFile config) { return new SentrySoundSettings(config); } } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct SyncRequest { public ulong Nonce; } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct SyncSnapshot { public int Protocol; public ulong Session; public ulong Catalog; public ulong Sequence; public ulong Echo; public uint Seed; public double Elapsed; } internal sealed class SessionSync : IDisposable { private const string RequestEvent = "SentrySound.v2.request"; private const string SnapshotEvent = "SentrySound.v2.snapshot"; private static SessionSync? _active; private static bool _eventsRegistered; private readonly ConcurrentQueue<(ulong Sender, SyncSnapshot Snapshot)> _snapshots = new ConcurrentQueue<(ulong, SyncSnapshot)>(); private readonly ConcurrentQueue<(ulong Sender, SyncRequest Request)> _requests = new ConcurrentQueue<(ulong, SyncRequest)>(); private readonly Dictionary<ulong, double> _responseTimes = new Dictionary<ulong, double>(); private readonly ManualLogSource _log; private TrackInfo[]? _tracks; private ulong _catalog; private ulong _session; private ulong _master; private ulong _sequence; private ulong _lastSequence; private ulong _nonce; private uint _seed; private double _anchor; private double _elapsed; private double _nextRequest; private double _requestTime; private bool _inLevel; private bool _mismatchReported; public Playlist? Playlist { get; private set; } public double Elapsed => _elapsed + Math.Max(0.0, Now - _anchor); private static double Now => (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; public SessionSync(ManualLogSource log) { _log = log; _active = this; if (_eventsRegistered) { return; } NetworkAPI.RegisterEvent<SyncRequest>("SentrySound.v2.request", (Action<ulong, SyncRequest>)delegate(ulong sender, SyncRequest payload) { SessionSync active = _active; if (active != null && active._requests.Count < 32) { active._requests.Enqueue((sender, payload)); } }); NetworkAPI.RegisterEvent<SyncSnapshot>("SentrySound.v2.snapshot", (Action<ulong, SyncSnapshot>)delegate(ulong sender, SyncSnapshot payload) { SessionSync active = _active; if (active != null && active._snapshots.Count < 32) { active._snapshots.Enqueue((sender, payload)); } }); _eventsRegistered = true; } public void SetLibrary(IEnumerable<TrackInfo> tracks) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) _tracks = tracks.ToArray(); if (_tracks.Length != 0) { _catalog = new Playlist((IEnumerable<TrackInfo>)_tracks, 1u).Fingerprint; } } public void Tick() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Expected O, but got Unknown eGameStateName currentStateName = GameStateManager.CurrentStateName; bool flag = (int)currentStateName == 10; if (!flag && (int)currentStateName != 13) { if (_inLevel) { Reset(); } _requests.Clear(); _snapshots.Clear(); } else { if (!flag) { return; } _inLevel = true; if (_tracks == null || _tracks.Length == 0 || !SNet.HasMaster) { _requests.Clear(); _snapshots.Clear(); return; } ulong lookup = SNet.Master.Lookup; if (_master != lookup) { _master = lookup; _lastSequence = 0uL; _nextRequest = 0.0; _responseTimes.Clear(); ManualLogSource log = _log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Session authority: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(lookup); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; localMaster="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(SNet.IsMaster); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogInfo(val); } if (SNet.IsMaster) { if (Playlist == null) { _seed = BitConverter.ToUInt32(RandomNumberGenerator.GetBytes(4)); _session = BitConverter.ToUInt64(RandomNumberGenerator.GetBytes(8)); if (_session == 0L) { _session = 1uL; } _anchor = Now; _elapsed = 0.0; Playlist = new Playlist((IEnumerable<TrackInfo>)_tracks, _seed); LogOrder("New expedition"); } (ulong, SyncRequest) result; SNet_Player val2 = default(SNet_Player); while (_requests.TryDequeue(out result)) { if ((!_responseTimes.TryGetValue(result.Item1, out var value) || !(Now - value < 1.0)) && SNet.TryGetPlayer(result.Item1, ref val2) && !val2.IsLocal) { _responseTimes[result.Item1] = Now; NetworkAPI.InvokeEvent<SyncSnapshot>("SentrySound.v2.snapshot", Snapshot(result.Item2.Nonce), val2, (SNet_ChannelType)2); } } _snapshots.Clear(); return; } _requests.Clear(); if (Now >= _nextRequest) { _nextRequest = Now + 3.0; _nonce++; _requestTime = Now; NetworkAPI.InvokeEvent<SyncRequest>("SentrySound.v2.request", new SyncRequest { Nonce = _nonce }, SNet.Master, (SNet_ChannelType)2); } (ulong, SyncSnapshot) result2; while (_snapshots.TryDequeue(out result2)) { SyncSnapshot item = result2.Item2; if (item.Echo == 0L || item.Echo != _nonce || Now - _requestTime > 2.0 || !SyncRules.AcceptEnvelope(result2.Item1, lookup, item.Protocol, item.Session, item.Elapsed, item.Sequence, _session, _lastSequence)) { continue; } if (item.Catalog != _catalog) { Playlist = null; if (!_mismatchReported) { _log.LogError((object)"Playlist mismatch with host. Use identical MP3/WAV files and names on every client. Sentry music muted."); } _mismatchReported = true; continue; } double num = (Now - _requestTime) / 2.0; bool num2 = Playlist == null || _session != item.Session || _seed != item.Seed; _lastSequence = item.Sequence; _session = item.Session; _seed = item.Seed; double num3 = item.Elapsed + num; if (num2 || Math.Abs(Elapsed - num3) > 0.08) { _elapsed = num3; _anchor = Now; } if (num2) { Playlist = new Playlist((IEnumerable<TrackInfo>)_tracks, _seed); LogOrder("Synchronized expedition"); } _mismatchReported = false; } } } private SyncSnapshot Snapshot(ulong echo) { return new SyncSnapshot { Protocol = 2, Session = _session, Seed = _seed, Catalog = _catalog, Sequence = ++_sequence, Echo = echo, Elapsed = Elapsed }; } private void LogOrder(string label) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ManualLogSource log = _log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(label); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": session="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(_session); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; seed="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<uint>(_seed); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; catalog="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(_catalog, "X16"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; order="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(" -> ", Playlist.Order.Select((int i) => _tracks[i].Name))); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogInfo(val); } private void Reset() { _inLevel = false; Playlist = null; _session = (_master = (_lastSequence = 0uL)); _nextRequest = 0.0; _mismatchReported = false; _responseTimes.Clear(); _log.LogInfo((object)"Expedition playlist reset."); } public void Dispose() { if (_active == this) { _active = null; } Reset(); } } internal sealed class VolumePanel { private readonly SentrySoundSettings _settings; private GameObject? _target; private CursorLockMode _previousLock; private bool _previousVisible; private bool _dirty; private static int _blockThroughFrame = -1; private static bool _waitingForRelease; public static bool IsOpen { get; private set; } public static bool BlocksInput { get { if (!IsOpen && !_waitingForRelease) { return Time.frameCount <= _blockThroughFrame; } return true; } } public VolumePanel(SentrySoundSettings settings) { _settings = settings; } public void Tick(Func<GameObject?> findTarget) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Invalid comparison between Unknown and I4 //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Invalid comparison between Unknown and I4 //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen && _waitingForRelease && !Input.GetMouseButton(0) && !Input.GetMouseButton(1)) { _waitingForRelease = false; _blockThroughFrame = Time.frameCount + 1; } if (IsOpen) { object obj; if (!PlayerManager.HasLocalPlayerAgent()) { obj = null; } else { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); obj = ((localPlayerAgent != null) ? ((Il2CppObjectBase)localPlayerAgent).TryCast<LocalPlayerAgent>() : null); } LocalPlayerAgent val = (LocalPlayerAgent)obj; FPSCamera val2 = (((Object)(object)val != (Object)null) ? ((PlayerAgent)val).FPSCamera : null); if ((Object)(object)_target == (Object)null || (Object)(object)val2 == (Object)null || !Application.isFocused || (int)FocusStateManager.CurrentState != 4 || Vector3.Distance(val2.Position, _target.transform.position) > 5f || Input.GetKeyDown(_settings.PanelKey.Value) || Input.GetKeyDown((KeyCode)27)) { Close(); } else { UnlockCursor(); } } else { if (!_settings.Enabled.Value || !Application.isFocused || (int)FocusStateManager.CurrentState != 4 || !Input.GetKeyDown(_settings.PanelKey.Value)) { return; } _target = findTarget(); if (!((Object)(object)_target == (Object)null)) { _previousLock = Cursor.lockState; _previousVisible = Cursor.visible; IsOpen = true; UnlockCursor(); ManualLogSource? diagnosticLog = Plugin.DiagnosticLog; if (diagnosticLog != null) { diagnosticLog.LogInfo((object)"Local Volume panel opened."); } } } } public static void UnlockCursor() { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } public void Close() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown if (!IsOpen) { return; } IsOpen = false; _target = null; _waitingForRelease = true; _blockThroughFrame = Time.frameCount + 1; if ((int)FocusStateManager.CurrentState == 4) { Cursor.lockState = _previousLock; Cursor.visible = _previousVisible; } bool flag = default(bool); ManualLogSource diagnosticLog; if (_dirty) { try { _settings.Save(); _dirty = false; } catch (Exception ex) { diagnosticLog = Plugin.DiagnosticLog; if (diagnosticLog != null) { BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(29, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not save local Volume: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } diagnosticLog.LogError(val); } } } diagnosticLog = Plugin.DiagnosticLog; if (diagnosticLog != null) { BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Local Volume panel closed; volume="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(_settings.Volume.Value, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } diagnosticLog.LogInfo(val2); } } public void CloseForTarget(GameObject target) { if (IsOpen && (Object)(object)_target == (Object)(object)target) { Close(); } } public void Shutdown() { Close(); _waitingForRelease = false; _blockThroughFrame = -1; } public void Draw() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) if (IsOpen) { float num = Math.Min(380f, (float)Screen.width - 20f); float num2 = ((float)Screen.width - num) / 2f; float num3 = ((float)Screen.height - 190f) / 2f; GUI.Box(new Rect(num2, num3, num, 190f), "SentinelaFuracao"); GUI.Label(new Rect(num2 + 24f, num3 + 34f, num - 48f, 26f), $"Volume {Mathf.RoundToInt(_settings.Volume.Value * 100f)}%"); float num4 = GUI.HorizontalSlider(new Rect(num2 + 24f, num3 + 72f, num - 48f, 24f), _settings.Volume.Value, 0f, 1f); if (Math.Abs(num4 - _settings.Volume.Value) > 0.0001f) { _settings.Volume.Value = Mathf.Clamp01(num4); _dirty = true; } GUI.Label(new Rect(num2 + 24f, num3 + 101f, num - 48f, 25f), "Altera somente o som para você."); if (GUI.Button(new Rect(num2 + num - 124f, num3 + 140f, 100f, 28f), "Fechar")) { Close(); } } } } [HarmonyPatch(typeof(InputMapper), "FocusStateFilterPass")] internal static class VolumePanelInputPatch { [HarmonyPrefix] private static bool Prefix(ref bool __result) { if (!VolumePanel.BlocksInput) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(InputMapper), "get_PlayerHasFocus")] internal static class VolumePanelFocusPatch { [HarmonyPostfix] private static void Postfix(ref bool __result) { if (VolumePanel.BlocksInput) { __result = false; } } } [HarmonyPatch(typeof(InputMapper), "CheckLockMouse")] internal static class VolumePanelCursorPatch { [HarmonyPrefix] private static bool Prefix() { if (!VolumePanel.IsOpen) { return true; } VolumePanel.UnlockCursor(); return false; } } }