Decompiled source of Audio Formats v1.0.1

NLayer.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
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: AssemblyCopyright("© Mark Heath 2026")]
[assembly: AssemblyDescription("Fully Managed MPEG 1 & 2 Decoder for Layers 1, 2, & 3")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: AssemblyInformationalVersion("3.0.0+046c7ce422970f8f0f0bc205d6c6341bcb7debf1")]
[assembly: AssemblyProduct("NLayer")]
[assembly: AssemblyTitle("NLayer")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NLayer")]
[assembly: AssemblyVersion("3.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_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 int _encoderDelay;

		private int _encoderPadding;

		private bool _decoderDelaySkipped;

		private float[] _readBuf = new float[2304];

		private int _readBufLen;

		private int _readBufOfs;

		public int SampleRate => _reader.SampleRate;

		public int Channels => OutputChannels;

		private int OutputChannels
		{
			get
			{
				if (StereoMode != StereoMode.Both)
				{
					return 1;
				}
				return _reader.Channels;
			}
		}

		public bool CanSeek => _reader.CanSeek;

		public long Length
		{
			get
			{
				long sampleCount = _reader.SampleCount;
				if (sampleCount < 0)
				{
					return -1L;
				}
				return (sampleCount - _encoderDelay - _encoderPadding) * OutputChannels * 4;
			}
		}

		public TimeSpan Duration
		{
			get
			{
				long sampleCount = _reader.SampleCount;
				if (sampleCount == -1)
				{
					return TimeSpan.Zero;
				}
				return TimeSpan.FromSeconds((double)(sampleCount - _encoderDelay - _encoderPadding) / (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 / OutputChannels;
				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 * OutputChannels;
					_eofFound = false;
					_decoderDelaySkipped = num3 > 0 || _encoderDelay == 0;
					_readBufOfs = (_readBufLen = 0);
				}
			}
		}

		public TimeSpan Time
		{
			get
			{
				return TimeSpan.FromSeconds((double)_position / 4.0 / (double)OutputChannels / (double)_reader.SampleRate);
			}
			set
			{
				Position = (long)(value.TotalSeconds * (double)_reader.SampleRate * (double)OutputChannels * 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();
			_encoderDelay = _reader.EncoderDelay;
			_encoderPadding = _reader.EncoderPadding;
		}

		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 long GetTotalBytes()
		{
			long sampleCount = _reader.SampleCount;
			if (sampleCount < 0)
			{
				return long.MaxValue;
			}
			return (sampleCount - _encoderDelay - _encoderPadding) * OutputChannels * 4;
		}

		private bool TryFillReadBuffer()
		{
			while (true)
			{
				if (_eofFound)
				{
					return false;
				}
				MpegFrame mpegFrame = _reader.NextFrame();
				if (mpegFrame == null)
				{
					_eofFound = true;
					return false;
				}
				try
				{
					_readBufLen = _decoder.DecodeFrame(mpegFrame, _readBuf, 0) * 4;
					_readBufOfs = 0;
					if (!_decoderDelaySkipped)
					{
						int num = _encoderDelay * OutputChannels * 4;
						if (num > 0 && num <= _readBufLen)
						{
							_readBufOfs = num;
						}
						_decoderDelaySkipped = true;
						if (_readBufOfs >= _readBufLen)
						{
							_readBufLen = (_readBufOfs = 0);
						}
					}
				}
				catch (InvalidDataException)
				{
					_decoder.Reset();
					_readBufOfs = (_readBufLen = 0);
					continue;
				}
				catch (EndOfStreamException)
				{
					_eofFound = true;
					return false;
				}
				finally
				{
					mpegFrame.ClearBuffer();
				}
				break;
			}
			return true;
		}

		private int AvailableBytes(long totalBytes, int count)
		{
			if (_readBufLen <= _readBufOfs)
			{
				return 0;
			}
			int num = _readBufLen - _readBufOfs;
			if (num > count)
			{
				num = count;
			}
			long num2 = totalBytes - _position;
			if (num > num2)
			{
				num = (int)num2;
			}
			return num;
		}

		private void AdvanceReadBuffer(int temp)
		{
			_position += temp;
			_readBufOfs += temp;
			if (_readBufOfs == _readBufLen)
			{
				_readBufLen = 0;
			}
		}

		private int ReadSamplesImpl(Array buffer, int index, int count, int bitDepth)
		{
			int num = 0;
			long totalBytes = GetTotalBytes();
			lock (_seekLock)
			{
				while (count > 0)
				{
					if (_position >= totalBytes)
					{
						_eofFound = true;
						break;
					}
					int num2 = AvailableBytes(totalBytes, count);
					if (num2 > 0)
					{
						if (bitDepth == 32)
						{
							Buffer.BlockCopy(_readBuf, _readBufOfs, buffer, index, num2);
						}
						else
						{
							byte[] array = (byte[])buffer;
							int num3 = _readBufOfs / 4;
							int num4 = index / 4;
							int num5 = num2 / 4;
							if (bitDepth == 8)
							{
								for (int i = 0; i < num5; i++)
								{
									array[num4 + i] = (byte)Math.Round(127.5f * _readBuf[num3 + i] + 127.5f);
								}
							}
							else
							{
								for (int j = 0; j < num5; j++)
								{
									int num6 = (int)Math.Round(32767.5f * _readBuf[num3 + j] - 0.5f);
									if (num6 < 0)
									{
										num6 += 65536;
									}
									array[2 * (num4 + j)] = (byte)(num6 % 256);
									array[2 * (num4 + j) + 1] = (byte)(num6 / 256);
								}
							}
						}
						num += num2;
						count -= num2;
						index += num2;
						AdvanceReadBuffer(num2);
					}
					if (_readBufLen == 0 && !TryFillReadBuffer())
					{
						break;
					}
				}
			}
			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 < RequiredSampleCount(frame))
			{
				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 < RequiredSampleCount(frame))
			{
				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 DecodeToChannels(IMpegFrame frame)
		{
			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)
			{
				return 0;
			}
			layerDecoderBase.SetEQ(_eqFactors);
			layerDecoderBase.StereoMode = StereoMode;
			return layerDecoderBase.DecodeFrame(frame, _ch0, _ch1);
		}

		private bool IsSingleChannel(IMpegFrame frame)
		{
			if (frame.ChannelMode != MpegChannelMode.Mono)
			{
				return StereoMode != StereoMode.Both;
			}
			return true;
		}

		private int DecodeFrameImpl(IMpegFrame frame, Array dest, int destOffset)
		{
			int num = DecodeToChannels(frame);
			if (num > 0)
			{
				if (IsSingleChannel(frame))
				{
					Buffer.BlockCopy(_ch0, 0, dest, destOffset * 4, num * 4);
				}
				else if (dest is float[] array)
				{
					for (int i = 0; i < num; i++)
					{
						array[destOffset++] = _ch0[i];
						array[destOffset++] = _ch1[i];
					}
					num *= 2;
				}
				else
				{
					for (int j = 0; j < num; j++)
					{
						Buffer.BlockCopy(_ch0, j * 4, dest, destOffset * 4, 4);
						destOffset++;
						Buffer.BlockCopy(_ch1, j * 4, dest, destOffset * 4, 4);
						destOffset++;
					}
					num *= 2;
				}
				return num;
			}
			return 0;
		}

		private static int RequiredSampleCount(IMpegFrame frame)
		{
			return ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) * frame.SampleCount;
		}

		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 & 8) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					v = 0f - _floatLookup[1];
				}
				else
				{
					v = _floatLookup[1];
				}
			}
			if ((num & 4) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					w = 0f - _floatLookup[1];
				}
				else
				{
					w = _floatLookup[1];
				}
			}
			if ((num & 2) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					x = 0f - _floatLookup[1];
				}
				else
				{
					x = _floatLookup[1];
				}
			}
			if ((num & 1) != 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 i = 0; i < array.Length; i++)
			{
				int num = maxBits - lengthList[i];
				array[i] = new HuffmanListNode
				{
					Value = values[i],
					Length = lengthList[i],
					Bits = codeList[i] << num,
					Mask = (1 << lengthList[i]) - 1 << num
				};
			}
			Array.Sort(array, (HuffmanListNode huffmanListNode, HuffmanListNode huffmanListNode2) => huffmanListNode.Length - huffmanListNode2.Length);
			for (int num2 = 1; num2 < array.Length && array[num2].Length < 99999; num2++)
			{
				array[num2 - 1].Next = array[num2];
			}
			return array[0];
		}
	}
	internal class ID3Frame : FrameBase
	{
		private int _version;

		private int _encoderDelay = -1;

		private int _encoderPadding = -1;

		private bool _v2Parsed;

		internal int EncoderDelay
		{
			get
			{
				if (_encoderDelay >= 0)
				{
					return _encoderDelay;
				}
				return 0;
			}
		}

		internal int EncoderPadding
		{
			get
			{
				if (_encoderPadding >= 0)
				{
					return _encoderPadding;
				}
				return 0;
			}
		}

		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()
		{
			_v2Parsed = true;
			_encoderDelay = 0;
			_encoderPadding = 0;
			byte[] array = new byte[7];
			if (Read(3, array) != 7)
			{
				return;
			}
			int num = array[0];
			if (num != 3 && num != 4)
			{
				return;
			}
			int num2 = (array[3] << 21) | (array[4] << 14) | (array[5] << 7) | array[6];
			int i = 10;
			int num3;
			for (byte[] array2 = new byte[10]; i < num2 + 10 && Read(i, array2, 0, 10) >= 10; i += 10 + num3)
			{
				if (array2[0] == 0)
				{
					break;
				}
				num3 = ((num != 4) ? ((array2[4] << 24) | (array2[5] << 16) | (array2[6] << 8) | array2[7]) : ((array2[4] << 21) | (array2[5] << 14) | (array2[6] << 7) | array2[7]));
				if (num3 <= 0)
				{
					break;
				}
				if (array2[0] == 84 && array2[1] == 88 && array2[2] == 88 && array2[3] == 88 && num3 < 4096)
				{
					byte[] array3 = new byte[num3];
					if (Read(i + 10, array3, 0, num3) == num3)
					{
						TryParseITunSMPB(array3, num3);
					}
				}
				if (_encoderDelay > 0 || _encoderPadding > 0)
				{
					break;
				}
			}
		}

		private void TryParseITunSMPB(byte[] data, int length)
		{
			if (length < 2)
			{
				return;
			}
			int num = data[0];
			string text;
			try
			{
				text = ((num == 1 || num == 2) ? Encoding.Unicode : Encoding.UTF8).GetString(data, 1, length - 1);
			}
			catch
			{
				return;
			}
			if (text.Length > 0 && text[0] == '\ufeff')
			{
				text = text.Substring(1);
			}
			int num2 = text.IndexOf('\0');
			if (num2 >= 0 && !(text.Substring(0, num2) != "iTunSMPB"))
			{
				string text2 = text.Substring(num2 + 1).Trim(new char[1]);
				if (text2.Length > 0 && text2[0] == '\ufeff')
				{
					text2 = text2.Substring(1);
				}
				string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length >= 3 && int.TryParse(array[1], NumberStyles.HexNumber, null, out var result) && int.TryParse(array[2], NumberStyles.HexNumber, null, out var result2))
				{
					_encoderDelay = result;
					_encoderPadding = result2;
				}
			}
		}

		internal void ParseEagerIfNeeded()
		{
			if (_version == 2 && !_v2Parsed)
			{
				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, 7 },
			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, -10 }
		};

		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 float[][] _chanBufs = new float[2][];

		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 - 2) + 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[][] chanBufs = _chanBufs;
			int num = 0;
			int num2 = _channels - 1;
			if (_channels == 1 || base.StereoMode == StereoMode.LeftOnly)
			{
				chanBufs[0] = ch0;
				num2 = 0;
			}
			else if (base.StereoMode == StereoMode.RightOnly)
			{
				chanBufs[1] = ch0;
				num = 1;
			}
			else
			{
				chanBufs[0] = ch0;
				chanBufs[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[] array;
								float[] array2;
								if (num5 < 0)
								{
									num5 = -num5 / 2 + -num5 % 2 - 1;
									array = _groupedC;
									array2 = _groupedD;
								}
								else
								{
									array = _C;
									array2 = _D;
								}
								_polyPhaseBuf[num4] = array[num5] * ((float)(_samples[i][num3] << 16 - num5) / 32768f + array2[num5]) * _denormalMultiplier[_scalefac[i][j][num4]];
							}
							else
							{
								_polyPhaseBuf[num4] = 0f;
							}
							num4++;
							num3++;
						}
						InversePolyPhase(i, _polyPhaseBuf);
						Array.Copy(_polyPhaseBuf, 0, chanBufs[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 float[] _longImdct_H = new float[17];

			private float[] _longImdct_h = new float[18];

			private float[] _longImdct_even = new float[9];

			private float[] _longImdct_odd = new float[9];

			private float[] _longImdct_evenIdct = new float[9];

			private float[] _longImdct_oddIdct = new float[9];

			private float[] _imdct9pt_even_idct = new float[5];

			private float[] _imdct9pt_odd_idct = new float[4];

			private float[] _shortImdct_H = new float[6];

			private float[] _shortImdct_h = new float[6];

			private float[] _shortImdct_evenIdct = new float[3];

			private float[] _shortImdct_oddIdct = new float[3];

			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 <

NVorbis.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using NVorbis.Ogg;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("Andrew Ward")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © Andrew Ward 2019")]
[assembly: AssemblyDescription("A fully managed implementation of a Xiph.org Foundation Ogg Vorbis decoder.")]
[assembly: AssemblyFileVersion("0.9.0.0")]
[assembly: AssemblyInformationalVersion("0.9.0.0")]
[assembly: AssemblyProduct("NVorbis")]
[assembly: AssemblyTitle("NVorbis")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: AssemblyVersion("0.9.0.0")]
namespace NVorbis
{
	public abstract class DataPacket
	{
		[Flags]
		protected enum PacketFlags : byte
		{
			IsResync = 1,
			IsEndOfStream = 2,
			IsShort = 4,
			HasGranuleCount = 8,
			User1 = 0x10,
			User2 = 0x20,
			User3 = 0x40,
			User4 = 0x80
		}

		private ulong _bitBucket;

		private int _bitCount;

		private int _readBits;

		private byte _overflowBits;

		private PacketFlags _packetFlags;

		private long _granulePosition;

		private long _pageGranulePosition;

		private int _length;

		private int _granuleCount;

		private int _pageSequenceNumber;

		public bool IsResync
		{
			get
			{
				return GetFlag(PacketFlags.IsResync);
			}
			internal set
			{
				SetFlag(PacketFlags.IsResync, value);
			}
		}

		public long GranulePosition
		{
			get
			{
				return _granulePosition;
			}
			set
			{
				_granulePosition = value;
			}
		}

		public long PageGranulePosition
		{
			get
			{
				return _pageGranulePosition;
			}
			internal set
			{
				_pageGranulePosition = value;
			}
		}

		public int Length
		{
			get
			{
				return _length;
			}
			protected set
			{
				_length = value;
			}
		}

		public bool IsEndOfStream
		{
			get
			{
				return GetFlag(PacketFlags.IsEndOfStream);
			}
			internal set
			{
				SetFlag(PacketFlags.IsEndOfStream, value);
			}
		}

		public long BitsRead => _readBits;

		public int? GranuleCount
		{
			get
			{
				if (GetFlag(PacketFlags.HasGranuleCount))
				{
					return _granuleCount;
				}
				return null;
			}
			set
			{
				if (value.HasValue)
				{
					_granuleCount = value.Value;
					SetFlag(PacketFlags.HasGranuleCount, value: true);
				}
				else
				{
					SetFlag(PacketFlags.HasGranuleCount, value: false);
				}
			}
		}

		internal int PageSequenceNumber
		{
			get
			{
				return _pageSequenceNumber;
			}
			set
			{
				_pageSequenceNumber = value;
			}
		}

		internal bool IsShort
		{
			get
			{
				return GetFlag(PacketFlags.IsShort);
			}
			private set
			{
				SetFlag(PacketFlags.IsShort, value);
			}
		}

		protected bool GetFlag(PacketFlags flag)
		{
			return (_packetFlags & flag) == flag;
		}

		protected void SetFlag(PacketFlags flag, bool value)
		{
			if (value)
			{
				_packetFlags |= flag;
			}
			else
			{
				_packetFlags &= (PacketFlags)(byte)(~(int)flag);
			}
		}

		protected DataPacket(int length)
		{
			Length = length;
		}

		protected abstract int ReadNextByte();

		public virtual void Done()
		{
		}

		public ulong TryPeekBits(int count, out int bitsRead)
		{
			ulong num = 0uL;
			switch (count)
			{
			default:
				throw new ArgumentOutOfRangeException("count");
			case 0:
				bitsRead = 0;
				return 0uL;
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
			case 10:
			case 11:
			case 12:
			case 13:
			case 14:
			case 15:
			case 16:
			case 17:
			case 18:
			case 19:
			case 20:
			case 21:
			case 22:
			case 23:
			case 24:
			case 25:
			case 26:
			case 27:
			case 28:
			case 29:
			case 30:
			case 31:
			case 32:
			case 33:
			case 34:
			case 35:
			case 36:
			case 37:
			case 38:
			case 39:
			case 40:
			case 41:
			case 42:
			case 43:
			case 44:
			case 45:
			case 46:
			case 47:
			case 48:
			case 49:
			case 50:
			case 51:
			case 52:
			case 53:
			case 54:
			case 55:
			case 56:
			case 57:
			case 58:
			case 59:
			case 60:
			case 61:
			case 62:
			case 63:
			case 64:
				break;
			}
			while (_bitCount < count)
			{
				int num2 = ReadNextByte();
				if (num2 == -1)
				{
					bitsRead = _bitCount;
					num = _bitBucket;
					_bitBucket = 0uL;
					_bitCount = 0;
					IsShort = true;
					return num;
				}
				_bitBucket = (ulong)((long)(num2 & 0xFF) << _bitCount) | _bitBucket;
				_bitCount += 8;
				if (_bitCount > 64)
				{
					_overflowBits = (byte)(num2 >> 72 - _bitCount);
				}
			}
			num = _bitBucket;
			if (count < 64)
			{
				num &= (ulong)((1L << count) - 1);
			}
			bitsRead = count;
			return num;
		}

		public void SkipBits(int count)
		{
			if (count == 0)
			{
				return;
			}
			if (_bitCount > count)
			{
				if (count > 63)
				{
					_bitBucket = 0uL;
				}
				else
				{
					_bitBucket >>= count;
				}
				if (_bitCount > 64)
				{
					int num = _bitCount - 64;
					_bitBucket |= (ulong)_overflowBits << _bitCount - count - num;
					if (num > count)
					{
						_overflowBits = (byte)(_overflowBits >> count);
					}
				}
				_bitCount -= count;
				_readBits += count;
				return;
			}
			if (_bitCount == count)
			{
				_bitBucket = 0uL;
				_bitCount = 0;
				_readBits += count;
				return;
			}
			count -= _bitCount;
			_readBits += _bitCount;
			_bitCount = 0;
			_bitBucket = 0uL;
			while (count > 8)
			{
				if (ReadNextByte() == -1)
				{
					count = 0;
					IsShort = true;
					break;
				}
				count -= 8;
				_readBits += 8;
			}
			if (count > 0)
			{
				int num2 = ReadNextByte();
				if (num2 == -1)
				{
					IsShort = true;
					return;
				}
				_bitBucket = (ulong)(num2 >> count);
				_bitCount = 8 - count;
				_readBits += count;
			}
		}

		protected void ResetBitReader()
		{
			_bitBucket = 0uL;
			_bitCount = 0;
			_readBits = 0;
			IsShort = false;
		}

		public ulong ReadBits(int count)
		{
			if (count == 0)
			{
				return 0uL;
			}
			int bitsRead;
			ulong result = TryPeekBits(count, out bitsRead);
			SkipBits(count);
			return result;
		}

		public byte PeekByte()
		{
			int bitsRead;
			return (byte)TryPeekBits(8, out bitsRead);
		}

		public byte ReadByte()
		{
			return (byte)ReadBits(8);
		}

		public byte[] ReadBytes(int count)
		{
			byte[] array = new byte[count];
			for (int i = 0; i < count; i++)
			{
				array[i] = ReadByte();
			}
			return array;
		}

		public int Read(byte[] buffer, int index, int count)
		{
			if (index < 0 || index >= buffer.Length)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			if (count < 0 || index + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("count");
			}
			for (int i = 0; i < count; i++)
			{
				int bitsRead;
				byte b = (byte)TryPeekBits(8, out bitsRead);
				if (bitsRead == 0)
				{
					return i;
				}
				buffer[index++] = b;
				SkipBits(8);
			}
			return count;
		}

		public bool ReadBit()
		{
			return ReadBits(1) == 1;
		}

		public short ReadInt16()
		{
			return (short)ReadBits(16);
		}

		public int ReadInt32()
		{
			return (int)ReadBits(32);
		}

		public long ReadInt64()
		{
			return (long)ReadBits(64);
		}

		public ushort ReadUInt16()
		{
			return (ushort)ReadBits(16);
		}

		public uint ReadUInt32()
		{
			return (uint)ReadBits(32);
		}

		public ulong ReadUInt64()
		{
			return ReadBits(64);
		}

		public void SkipBytes(int count)
		{
			SkipBits(count * 8);
		}
	}
	internal static class Huffman
	{
		private const int MAX_TABLE_BITS = 10;

		internal static List<HuffmanListNode> BuildPrefixedLinkedList(IReadOnlyList<int> values, int[] lengthList, int[] codeList, out int tableBits, out HuffmanListNode firstOverflowNode)
		{
			HuffmanListNode[] array = new HuffmanListNode[lengthList.Length];
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new HuffmanListNode
				{
					Value = values[i],
					Length = ((lengthList[i] <= 0) ? 99999 : lengthList[i]),
					Bits = codeList[i],
					Mask = (1 << lengthList[i]) - 1
				};
				if (lengthList[i] > 0 && num < lengthList[i])
				{
					num = lengthList[i];
				}
			}
			Array.Sort(array, 0, array.Length);
			tableBits = ((num > 10) ? 10 : num);
			List<HuffmanListNode> list = new List<HuffmanListNode>(1 << tableBits);
			firstOverflowNode = null;
			for (int j = 0; j < array.Length && array[j].Length < 99999; j++)
			{
				if (firstOverflowNode == null)
				{
					int length = array[j].Length;
					if (length > tableBits)
					{
						firstOverflowNode = array[j];
						continue;
					}
					int num2 = 1 << tableBits - length;
					HuffmanListNode huffmanListNode = array[j];
					for (int k = 0; k < num2; k++)
					{
						int num3 = (k << length) | huffmanListNode.Bits;
						while (list.Count <= num3)
						{
							list.Add(null);
						}
						list[num3] = huffmanListNode;
					}
				}
				else
				{
					array[j - 1].Next = array[j];
				}
			}
			while (list.Count < 1 << tableBits)
			{
				list.Add(null);
			}
			return list;
		}
	}
	internal class HuffmanListNode : IComparable<HuffmanListNode>
	{
		internal int Value;

		internal int Length;

		internal int Bits;

		internal int Mask;

		internal HuffmanListNode Next;

		int IComparable<HuffmanListNode>.CompareTo(HuffmanListNode other)
		{
			int num = Length - other.Length;
			if (num == 0)
			{
				return Bits - other.Bits;
			}
			return num;
		}
	}
	public interface IContainerReader : IDisposable
	{
		int[] StreamSerials { get; }

		bool CanSeek { get; }

		long WasteBits { get; }

		int PagesRead { get; }

		event EventHandler<NewStreamEventArgs> NewStream;

		bool Init();

		bool FindNextStream();

		int GetTotalPageCount();
	}
	public interface IPacketProvider : IDisposable
	{
		int StreamSerial { get; }

		bool CanSeek { get; }

		long ContainerBits { get; }

		event EventHandler<ParameterChangeEventArgs> ParameterChange;

		int GetTotalPageCount();

		DataPacket GetNextPacket();

		DataPacket PeekNextPacket();

		DataPacket GetPacket(int packetIndex);

		long GetGranuleCount();

		DataPacket FindPacket(long granulePos, Func<DataPacket, DataPacket, int> packetGranuleCountCallback);

		void SeekToPacket(DataPacket packet, int preRoll);
	}
	public interface IVorbisStreamStatus
	{
		int EffectiveBitRate { get; }

		int InstantBitRate { get; }

		TimeSpan PageLatency { get; }

		TimeSpan PacketLatency { get; }

		TimeSpan SecondLatency { get; }

		long OverheadBits { get; }

		long AudioBits { get; }

		int PagesRead { get; }

		int TotalPages { get; }

		bool Clipped { get; }

		void ResetStats();
	}
	internal class Mdct
	{
		private const float M_PI = (float)Math.PI;

		private static Dictionary<int, Mdct> _setupCache = new Dictionary<int, Mdct>(2);

		private int _n;

		private int _n2;

		private int _n4;

		private int _n8;

		private int _ld;

		private float[] _A;

		private float[] _B;

		private float[] _C;

		private ushort[] _bitrev;

		private Dictionary<int, float[]> _threadLocalBuffers = new Dictionary<int, float[]>(1);

		public static void Reverse(float[] samples, int sampleCount)
		{
			GetSetup(sampleCount).CalcReverse(samples);
		}

		private static Mdct GetSetup(int n)
		{
			lock (_setupCache)
			{
				if (!_setupCache.ContainsKey(n))
				{
					_setupCache[n] = new Mdct(n);
				}
				return _setupCache[n];
			}
		}

		private Mdct(int n)
		{
			_n = n;
			_n2 = n >> 1;
			_n4 = _n2 >> 1;
			_n8 = _n4 >> 1;
			_ld = Utils.ilog(n) - 1;
			_A = new float[_n2];
			_B = new float[_n2];
			_C = new float[_n4];
			int num2;
			int num = (num2 = 0);
			while (num < _n4)
			{
				_A[num2] = (float)Math.Cos((float)(4 * num) * (float)Math.PI / (float)n);
				_A[num2 + 1] = (float)(0.0 - Math.Sin((float)(4 * num) * (float)Math.PI / (float)n));
				_B[num2] = (float)Math.Cos((float)(num2 + 1) * (float)Math.PI / (float)n / 2f) * 0.5f;
				_B[num2 + 1] = (float)Math.Sin((float)(num2 + 1) * (float)Math.PI / (float)n / 2f) * 0.5f;
				num++;
				num2 += 2;
			}
			num = (num2 = 0);
			while (num < _n8)
			{
				_C[num2] = (float)Math.Cos((float)(2 * (num2 + 1)) * (float)Math.PI / (float)n);
				_C[num2 + 1] = (float)(0.0 - Math.Sin((float)(2 * (num2 + 1)) * (float)Math.PI / (float)n));
				num++;
				num2 += 2;
			}
			_bitrev = new ushort[_n8];
			for (int i = 0; i < _n8; i++)
			{
				_bitrev[i] = (ushort)(Utils.BitReverse((uint)i, _ld - 3) << 2);
			}
		}

		private float[] GetBuffer()
		{
			lock (_threadLocalBuffers)
			{
				if (!_threadLocalBuffers.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var value))
				{
					value = (_threadLocalBuffers[Thread.CurrentThread.ManagedThreadId] = new float[_n2]);
				}
				return value;
			}
		}

		private void CalcReverse(float[] buffer)
		{
			float[] buffer2 = GetBuffer();
			int num = _n2 - 2;
			int num2 = 0;
			int i = 0;
			for (int n = _n2; i != n; i += 4)
			{
				buffer2[num + 1] = buffer[i] * _A[num2] - buffer[i + 2] * _A[num2 + 1];
				buffer2[num] = buffer[i] * _A[num2 + 1] + buffer[i + 2] * _A[num2];
				num -= 2;
				num2 += 2;
			}
			i = _n2 - 3;
			while (num >= 0)
			{
				buffer2[num + 1] = (0f - buffer[i + 2]) * _A[num2] - (0f - buffer[i]) * _A[num2 + 1];
				buffer2[num] = (0f - buffer[i + 2]) * _A[num2 + 1] + (0f - buffer[i]) * _A[num2];
				num -= 2;
				num2 += 2;
				i -= 4;
			}
			float[] array = buffer2;
			int num3 = _n2 - 8;
			int num4 = _n4;
			int num5 = 0;
			int num6 = _n4;
			int num7 = 0;
			while (num3 >= 0)
			{
				float num8 = array[num4 + 1] - array[num5 + 1];
				float num9 = array[num4] - array[num5];
				buffer[num6 + 1] = array[num4 + 1] + array[num5 + 1];
				buffer[num6] = array[num4] + array[num5];
				buffer[num7 + 1] = num8 * _A[num3 + 4] - num9 * _A[num3 + 5];
				buffer[num7] = num9 * _A[num3 + 4] + num8 * _A[num3 + 5];
				num8 = array[num4 + 3] - array[num5 + 3];
				num9 = array[num4 + 2] - array[num5 + 2];
				buffer[num6 + 3] = array[num4 + 3] + array[num5 + 3];
				buffer[num6 + 2] = array[num4 + 2] + array[num5 + 2];
				buffer[num7 + 3] = num8 * _A[num3] - num9 * _A[num3 + 1];
				buffer[num7 + 2] = num9 * _A[num3] + num8 * _A[num3 + 1];
				num3 -= 8;
				num6 += 4;
				num7 += 4;
				num4 += 4;
				num5 += 4;
			}
			int n2 = _n >> 4;
			int num10 = _n2 - 1;
			_ = _n4;
			step3_iter0_loop(n2, buffer, num10 - 0, -_n8);
			step3_iter0_loop(_n >> 4, buffer, _n2 - 1 - _n4, -_n8);
			int lim = _n >> 5;
			int num11 = _n2 - 1;
			_ = _n8;
			step3_inner_r_loop(lim, buffer, num11 - 0, -(_n >> 4), 16);
			step3_inner_r_loop(_n >> 5, buffer, _n2 - 1 - _n8, -(_n >> 4), 16);
			step3_inner_r_loop(_n >> 5, buffer, _n2 - 1 - _n8 * 2, -(_n >> 4), 16);
			step3_inner_r_loop(_n >> 5, buffer, _n2 - 1 - _n8 * 3, -(_n >> 4), 16);
			int j;
			for (j = 2; j < _ld - 3 >> 1; j++)
			{
				int num12 = _n >> j + 2;
				int num13 = num12 >> 1;
				int num14 = 1 << j + 1;
				for (int k = 0; k < num14; k++)
				{
					step3_inner_r_loop(_n >> j + 4, buffer, _n2 - 1 - num12 * k, -num13, 1 << j + 3);
				}
			}
			for (; j < _ld - 6; j++)
			{
				int num15 = _n >> j + 2;
				int num16 = 1 << j + 3;
				int num17 = num15 >> 1;
				int num18 = _n >> j + 6;
				int n3 = 1 << j + 1;
				int num19 = _n2 - 1;
				int num20 = 0;
				for (int num21 = num18; num21 > 0; num21--)
				{
					step3_inner_s_loop(n3, buffer, num19, -num17, num20, num16, num15);
					num20 += num16 * 4;
					num19 -= 8;
				}
			}
			step3_inner_s_loop_ld654(_n >> 5, buffer, _n2 - 1, _n);
			int num22 = 0;
			int num23 = _n4 - 4;
			int num24 = _n2 - 4;
			while (num23 >= 0)
			{
				int num25 = _bitrev[num22];
				array[num24 + 3] = buffer[num25];
				array[num24 + 2] = buffer[num25 + 1];
				array[num23 + 3] = buffer[num25 + 2];
				array[num23 + 2] = buffer[num25 + 3];
				num25 = _bitrev[num22 + 1];
				array[num24 + 1] = buffer[num25];
				array[num24] = buffer[num25 + 1];
				array[num23 + 1] = buffer[num25 + 2];
				array[num23] = buffer[num25 + 3];
				num23 -= 4;
				num24 -= 4;
				num22 += 2;
			}
			int num26 = 0;
			int num27 = 0;
			int num28 = _n2 - 4;
			while (num27 < num28)
			{
				float num29 = array[num27] - array[num28 + 2];
				float num30 = array[num27 + 1] + array[num28 + 3];
				float num31 = _C[num26 + 1] * num29 + _C[num26] * num30;
				float num32 = _C[num26 + 1] * num30 - _C[num26] * num29;
				float num33 = array[num27] + array[num28 + 2];
				float num34 = array[num27 + 1] - array[num28 + 3];
				array[num27] = num33 + num31;
				array[num27 + 1] = num34 + num32;
				array[num28 + 2] = num33 - num31;
				array[num28 + 3] = num32 - num34;
				num29 = array[num27 + 2] - array[num28];
				num30 = array[num27 + 3] + array[num28 + 1];
				num31 = _C[num26 + 3] * num29 + _C[num26 + 2] * num30;
				num32 = _C[num26 + 3] * num30 - _C[num26 + 2] * num29;
				num33 = array[num27 + 2] + array[num28];
				num34 = array[num27 + 3] - array[num28 + 1];
				array[num27 + 2] = num33 + num31;
				array[num27 + 3] = num34 + num32;
				array[num28] = num33 - num31;
				array[num28 + 1] = num32 - num34;
				num26 += 4;
				num27 += 4;
				num28 -= 4;
			}
			int num35 = _n2 - 8;
			int num36 = _n2 - 8;
			int num37 = 0;
			int num38 = _n2 - 4;
			int num39 = _n2;
			int num40 = _n - 4;
			while (num36 >= 0)
			{
				float num41 = buffer2[num36 + 6] * _B[num35 + 7] - buffer2[num36 + 7] * _B[num35 + 6];
				float num42 = (0f - buffer2[num36 + 6]) * _B[num35 + 6] - buffer2[num36 + 7] * _B[num35 + 7];
				buffer[num37] = num41;
				buffer[num38 + 3] = 0f - num41;
				buffer[num39] = num42;
				buffer[num40 + 3] = num42;
				float num43 = buffer2[num36 + 4] * _B[num35 + 5] - buffer2[num36 + 5] * _B[num35 + 4];
				float num44 = (0f - buffer2[num36 + 4]) * _B[num35 + 4] - buffer2[num36 + 5] * _B[num35 + 5];
				buffer[num37 + 1] = num43;
				buffer[num38 + 2] = 0f - num43;
				buffer[num39 + 1] = num44;
				buffer[num40 + 2] = num44;
				num41 = buffer2[num36 + 2] * _B[num35 + 3] - buffer2[num36 + 3] * _B[num35 + 2];
				num42 = (0f - buffer2[num36 + 2]) * _B[num35 + 2] - buffer2[num36 + 3] * _B[num35 + 3];
				buffer[num37 + 2] = num41;
				buffer[num38 + 1] = 0f - num41;
				buffer[num39 + 2] = num42;
				buffer[num40 + 1] = num42;
				num43 = buffer2[num36] * _B[num35 + 1] - buffer2[num36 + 1] * _B[num35];
				num44 = (0f - buffer2[num36]) * _B[num35] - buffer2[num36 + 1] * _B[num35 + 1];
				buffer[num37 + 3] = num43;
				buffer[num38] = 0f - num43;
				buffer[num39 + 3] = num44;
				buffer[num40] = num44;
				num35 -= 8;
				num36 -= 8;
				num37 += 4;
				num39 += 4;
				num38 -= 4;
				num40 -= 4;
			}
		}

		private void step3_iter0_loop(int n, float[] e, int i_off, int k_off)
		{
			int num = i_off;
			int num2 = num + k_off;
			int num3 = 0;
			for (int num4 = n >> 2; num4 > 0; num4--)
			{
				float num5 = e[num] - e[num2];
				float num6 = e[num - 1] - e[num2 - 1];
				e[num] += e[num2];
				e[num - 1] += e[num2 - 1];
				e[num2] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 1] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += 8;
				num5 = e[num - 2] - e[num2 - 2];
				num6 = e[num - 3] - e[num2 - 3];
				e[num - 2] += e[num2 - 2];
				e[num - 3] += e[num2 - 3];
				e[num2 - 2] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 3] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += 8;
				num5 = e[num - 4] - e[num2 - 4];
				num6 = e[num - 5] - e[num2 - 5];
				e[num - 4] += e[num2 - 4];
				e[num - 5] += e[num2 - 5];
				e[num2 - 4] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 5] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += 8;
				num5 = e[num - 6] - e[num2 - 6];
				num6 = e[num - 7] - e[num2 - 7];
				e[num - 6] += e[num2 - 6];
				e[num - 7] += e[num2 - 7];
				e[num2 - 6] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 7] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += 8;
				num -= 8;
				num2 -= 8;
			}
		}

		private void step3_inner_r_loop(int lim, float[] e, int d0, int k_off, int k1)
		{
			int num = d0;
			int num2 = num + k_off;
			int num3 = 0;
			for (int num4 = lim >> 2; num4 > 0; num4--)
			{
				float num5 = e[num] - e[num2];
				float num6 = e[num - 1] - e[num2 - 1];
				e[num] += e[num2];
				e[num - 1] += e[num2 - 1];
				e[num2] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 1] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += k1;
				num5 = e[num - 2] - e[num2 - 2];
				num6 = e[num - 3] - e[num2 - 3];
				e[num - 2] += e[num2 - 2];
				e[num - 3] += e[num2 - 3];
				e[num2 - 2] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 3] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += k1;
				num5 = e[num - 4] - e[num2 - 4];
				num6 = e[num - 5] - e[num2 - 5];
				e[num - 4] += e[num2 - 4];
				e[num - 5] += e[num2 - 5];
				e[num2 - 4] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 5] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += k1;
				num5 = e[num - 6] - e[num2 - 6];
				num6 = e[num - 7] - e[num2 - 7];
				e[num - 6] += e[num2 - 6];
				e[num - 7] += e[num2 - 7];
				e[num2 - 6] = num5 * _A[num3] - num6 * _A[num3 + 1];
				e[num2 - 7] = num6 * _A[num3] + num5 * _A[num3 + 1];
				num3 += k1;
				num -= 8;
				num2 -= 8;
			}
		}

		private void step3_inner_s_loop(int n, float[] e, int i_off, int k_off, int a, int a_off, int k0)
		{
			float num = _A[a];
			float num2 = _A[a + 1];
			float num3 = _A[a + a_off];
			float num4 = _A[a + a_off + 1];
			float num5 = _A[a + a_off * 2];
			float num6 = _A[a + a_off * 2 + 1];
			float num7 = _A[a + a_off * 3];
			float num8 = _A[a + a_off * 3 + 1];
			int num9 = i_off;
			int num10 = num9 + k_off;
			for (int num11 = n; num11 > 0; num11--)
			{
				float num12 = e[num9] - e[num10];
				float num13 = e[num9 - 1] - e[num10 - 1];
				e[num9] += e[num10];
				e[num9 - 1] += e[num10 - 1];
				e[num10] = num12 * num - num13 * num2;
				e[num10 - 1] = num13 * num + num12 * num2;
				num12 = e[num9 - 2] - e[num10 - 2];
				num13 = e[num9 - 3] - e[num10 - 3];
				e[num9 - 2] += e[num10 - 2];
				e[num9 - 3] += e[num10 - 3];
				e[num10 - 2] = num12 * num3 - num13 * num4;
				e[num10 - 3] = num13 * num3 + num12 * num4;
				num12 = e[num9 - 4] - e[num10 - 4];
				num13 = e[num9 - 5] - e[num10 - 5];
				e[num9 - 4] += e[num10 - 4];
				e[num9 - 5] += e[num10 - 5];
				e[num10 - 4] = num12 * num5 - num13 * num6;
				e[num10 - 5] = num13 * num5 + num12 * num6;
				num12 = e[num9 - 6] - e[num10 - 6];
				num13 = e[num9 - 7] - e[num10 - 7];
				e[num9 - 6] += e[num10 - 6];
				e[num9 - 7] += e[num10 - 7];
				e[num10 - 6] = num12 * num7 - num13 * num8;
				e[num10 - 7] = num13 * num7 + num12 * num8;
				num9 -= k0;
				num10 -= k0;
			}
		}

		private void step3_inner_s_loop_ld654(int n, float[] e, int i_off, int base_n)
		{
			int num = base_n >> 3;
			float num2 = _A[num];
			int num3 = i_off;
			int num4 = num3 - 16 * n;
			while (num3 > num4)
			{
				float num5 = e[num3] - e[num3 - 8];
				float num6 = e[num3 - 1] - e[num3 - 9];
				e[num3] += e[num3 - 8];
				e[num3 - 1] += e[num3 - 9];
				e[num3 - 8] = num5;
				e[num3 - 9] = num6;
				num5 = e[num3 - 2] - e[num3 - 10];
				num6 = e[num3 - 3] - e[num3 - 11];
				e[num3 - 2] += e[num3 - 10];
				e[num3 - 3] += e[num3 - 11];
				e[num3 - 10] = (num5 + num6) * num2;
				e[num3 - 11] = (num6 - num5) * num2;
				num5 = e[num3 - 12] - e[num3 - 4];
				num6 = e[num3 - 5] - e[num3 - 13];
				e[num3 - 4] += e[num3 - 12];
				e[num3 - 5] += e[num3 - 13];
				e[num3 - 12] = num6;
				e[num3 - 13] = num5;
				num5 = e[num3 - 14] - e[num3 - 6];
				num6 = e[num3 - 7] - e[num3 - 15];
				e[num3 - 6] += e[num3 - 14];
				e[num3 - 7] += e[num3 - 15];
				e[num3 - 14] = (num5 + num6) * num2;
				e[num3 - 15] = (num5 - num6) * num2;
				iter_54(e, num3);
				iter_54(e, num3 - 8);
				num3 -= 16;
			}
		}

		private void iter_54(float[] e, int z)
		{
			float num = e[z] - e[z - 4];
			float num2 = e[z] + e[z - 4];
			float num3 = e[z - 2] + e[z - 6];
			float num4 = e[z - 2] - e[z - 6];
			e[z] = num2 + num3;
			e[z - 2] = num2 - num3;
			float num5 = e[z - 3] - e[z - 7];
			e[z - 4] = num + num5;
			e[z - 6] = num - num5;
			float num6 = e[z - 1] - e[z - 5];
			float num7 = e[z - 1] + e[z - 5];
			float num8 = e[z - 3] + e[z - 7];
			e[z - 1] = num7 + num8;
			e[z - 3] = num7 - num8;
			e[z - 5] = num6 - num4;
			e[z - 7] = num6 + num4;
		}
	}
	[Serializable]
	public class NewStreamEventArgs : EventArgs
	{
		public IPacketProvider PacketProvider { get; private set; }

		public bool IgnoreStream { get; set; }

		public NewStreamEventArgs(IPacketProvider packetProvider)
		{
			if (packetProvider == null)
			{
				throw new ArgumentNullException("packetProvider");
			}
			PacketProvider = packetProvider;
		}
	}
	[Serializable]
	public class ParameterChangeEventArgs : EventArgs
	{
		public DataPacket FirstPacket { get; private set; }

		public ParameterChangeEventArgs(DataPacket firstPacket)
		{
			FirstPacket = firstPacket;
		}
	}
	internal class RingBuffer
	{
		private float[] _buffer;

		private int _start;

		private int _end;

		private int _bufLen;

		internal int Channels;

		internal int Length
		{
			get
			{
				int num = _end - _start;
				if (num < 0)
				{
					num += _bufLen;
				}
				return num;
			}
		}

		internal RingBuffer(int size)
		{
			_buffer = new float[size];
			_start = (_end = 0);
			_bufLen = size;
		}

		internal void EnsureSize(int size)
		{
			size += Channels;
			if (_bufLen < size)
			{
				float[] array = new float[size];
				Array.Copy(_buffer, _start, array, 0, _bufLen - _start);
				if (_end < _start)
				{
					Array.Copy(_buffer, 0, array, _bufLen - _start, _end);
				}
				int length = Length;
				_start = 0;
				_end = length;
				_buffer = array;
				_bufLen = size;
			}
		}

		internal void CopyTo(float[] buffer, int index, int count)
		{
			if (index < 0 || index + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			int start = _start;
			RemoveItems(count);
			int num = (_end - start + _bufLen) % _bufLen;
			if (count > num)
			{
				throw new ArgumentOutOfRangeException("count");
			}
			int num2 = Math.Min(count, _bufLen - start);
			Buffer.BlockCopy(_buffer, start * 4, buffer, index * 4, num2 * 4);
			if (num2 < count)
			{
				Buffer.BlockCopy(_buffer, 0, buffer, (index + num2) * 4, (count - num2) * 4);
			}
		}

		internal void RemoveItems(int count)
		{
			int num = (count + _start) % _bufLen;
			if (_end > _start)
			{
				if (num > _end || num < _start)
				{
					throw new ArgumentOutOfRangeException();
				}
			}
			else if (num < _start && num > _end)
			{
				throw new ArgumentOutOfRangeException();
			}
			_start = num;
		}

		internal void Clear()
		{
			_start = (_end = 0);
		}

		internal void Write(int channel, int index, int start, int switchPoint, int end, float[] pcm, float[] window)
		{
			int num;
			for (num = (index + start) * Channels + channel + _start; num >= _bufLen; num -= _bufLen)
			{
			}
			if (num < 0)
			{
				start -= index;
				num = channel;
			}
			while (num < _bufLen && start < switchPoint)
			{
				_buffer[num] += pcm[start] * window[start];
				num += Channels;
				start++;
			}
			if (num >= _bufLen)
			{
				num -= _bufLen;
				while (start < switchPoint)
				{
					_buffer[num] += pcm[start] * window[start];
					num += Channels;
					start++;
				}
			}
			while (num < _bufLen && start < end)
			{
				_buffer[num] = pcm[start] * window[start];
				num += Channels;
				start++;
			}
			if (num >= _bufLen)
			{
				num -= _bufLen;
				while (start < end)
				{
					_buffer[num] = pcm[start] * window[start];
					num += Channels;
					start++;
				}
			}
			_end = num;
		}
	}
	internal static class Utils
	{
		[StructLayout(LayoutKind.Explicit)]
		private struct FloatBits
		{
			[FieldOffset(0)]
			public float Float;

			[FieldOffset(0)]
			public uint Bits;
		}

		internal static int ilog(int x)
		{
			int num = 0;
			while (x > 0)
			{
				num++;
				x >>= 1;
			}
			return num;
		}

		internal static uint BitReverse(uint n)
		{
			return BitReverse(n, 32);
		}

		internal static uint BitReverse(uint n, int bits)
		{
			n = ((n & 0xAAAAAAAAu) >> 1) | ((n & 0x55555555) << 1);
			n = ((n & 0xCCCCCCCCu) >> 2) | ((n & 0x33333333) << 2);
			n = ((n & 0xF0F0F0F0u) >> 4) | ((n & 0xF0F0F0F) << 4);
			n = ((n & 0xFF00FF00u) >> 8) | ((n & 0xFF00FF) << 8);
			return ((n >> 16) | (n << 16)) >> 32 - bits;
		}

		internal static float ClipValue(float value, ref bool clipped)
		{
			FloatBits floatBits = default(FloatBits);
			floatBits.Bits = 0u;
			floatBits.Float = value;
			if ((floatBits.Bits & 0x7FFFFFFF) > 1065353215)
			{
				clipped = true;
				floatBits.Bits = 0x3F7FFFFF | (floatBits.Bits & 0x80000000u);
			}
			return floatBits.Float;
		}

		internal static float ConvertFromVorbisFloat32(uint bits)
		{
			int num = (int)bits >> 31;
			double y = (int)(((bits & 0x7FE00000) >> 21) - 788);
			return (float)(((bits & 0x1FFFFF) ^ num) + (num & 1)) * (float)Math.Pow(2.0, y);
		}

		internal static int Sum(Queue<int> queue)
		{
			int num = 0;
			for (int i = 0; i < queue.Count; i++)
			{
				int num2 = queue.Dequeue();
				num += num2;
				queue.Enqueue(num2);
			}
			return num;
		}
	}
	internal class VorbisCodebook
	{
		private class FastRange : IReadOnlyList<int>, IReadOnlyCollection<int>, IEnumerable<int>, IEnumerable
		{
			[ThreadStatic]
			private static FastRange _cachedRange;

			private int _start;

			private int _count;

			public int this[int index]
			{
				get
				{
					if (index > _count)
					{
						throw new ArgumentOutOfRangeException();
					}
					return _start + index;
				}
			}

			public int Count => _count;

			internal static FastRange Get(int start, int count)
			{
				FastRange obj = _cachedRange ?? (_cachedRange = new FastRange());
				obj._start = start;
				obj._count = count;
				return obj;
			}

			private FastRange()
			{
			}

			public IEnumerator<int> GetEnumerator()
			{
				throw new NotSupportedException();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		internal int BookNum;

		internal int Dimensions;

		internal int Entries;

		private int[] Lengths;

		private float[] LookupTable;

		internal int MapType;

		private HuffmanListNode PrefixOverflowTree;

		private List<HuffmanListNode> PrefixList;

		private int PrefixBitLength;

		private int MaxBits;

		internal float this[int entry, int dim] => LookupTable[entry * Dimensions + dim];

		internal static VorbisCodebook Init(VorbisStreamDecoder vorbis, DataPacket packet, int number)
		{
			return new VorbisCodebook(packet, number);
		}

		private VorbisCodebook(DataPacket packet, int number)
		{
			BookNum = number;
			if (packet.ReadBits(24) != 5653314)
			{
				throw new InvalidDataException();
			}
			Dimensions = (int)packet.ReadBits(16);
			Entries = (int)packet.ReadBits(24);
			Lengths = new int[Entries];
			InitTree(packet);
			InitLookupTable(packet);
		}

		private void InitTree(DataPacket packet)
		{
			int num = 0;
			bool flag;
			if (packet.ReadBit())
			{
				int num2 = (int)packet.ReadBits(5) + 1;
				int num3 = 0;
				while (num3 < Entries)
				{
					int num4 = (int)packet.ReadBits(Utils.ilog(Entries - num3));
					while (--num4 >= 0)
					{
						Lengths[num3++] = num2;
					}
					num2++;
				}
				num = 0;
				flag = false;
			}
			else
			{
				flag = packet.ReadBit();
				for (int i = 0; i < Entries; i++)
				{
					if (!flag || packet.ReadBit())
					{
						Lengths[i] = (int)packet.ReadBits(5) + 1;
						num++;
					}
					else
					{
						Lengths[i] = -1;
					}
				}
			}
			if ((MaxBits = Lengths.Max()) > -1)
			{
				int num5 = 0;
				int[] array = null;
				if (flag && num >= Entries >> 2)
				{
					array = new int[Entries];
					Array.Copy(Lengths, array, Entries);
					flag = false;
				}
				num5 = (flag ? num : 0);
				int num6 = num5;
				int[] array2 = null;
				int[] array3 = null;
				if (!flag)
				{
					array3 = new int[Entries];
				}
				else if (num6 != 0)
				{
					array = new int[num6];
					array3 = new int[num6];
					array2 = new int[num6];
				}
				if (!ComputeCodewords(flag, num6, array3, array, Lengths, Entries, array2))
				{
					throw new InvalidDataException();
				}
				IReadOnlyList<int> readOnlyList = array2;
				IReadOnlyList<int> values = readOnlyList ?? FastRange.Get(0, array3.Length);
				PrefixList = Huffman.BuildPrefixedLinkedList(values, array ?? Lengths, array3, out PrefixBitLength, out PrefixOverflowTree);
			}
		}

		private bool ComputeCodewords(bool sparse, int sortedEntries, int[] codewords, int[] codewordLengths, int[] len, int n, int[] values)
		{
			int num = 0;
			uint[] array = new uint[32];
			int i;
			for (i = 0; i < n && len[i] <= 0; i++)
			{
			}
			if (i == n)
			{
				return true;
			}
			AddEntry(sparse, codewords, codewordLengths, 0u, i, num++, len[i], values);
			for (int j = 1; j <= len[i]; j++)
			{
				array[j] = (uint)(1 << 32 - j);
			}
			for (int j = i + 1; j < n; j++)
			{
				int num2 = len[j];
				if (num2 <= 0)
				{
					continue;
				}
				while (num2 > 0 && array[num2] == 0)
				{
					num2--;
				}
				if (num2 == 0)
				{
					return false;
				}
				uint num3 = array[num2];
				array[num2] = 0u;
				AddEntry(sparse, codewords, codewordLengths, Utils.BitReverse(num3), j, num++, len[j], values);
				if (num2 != len[j])
				{
					for (int num4 = len[j]; num4 > num2; num4--)
					{
						array[num4] = num3 + (uint)(1 << 32 - num4);
					}
				}
			}
			return true;
		}

		private void AddEntry(bool sparse, int[] codewords, int[] codewordLengths, uint huffCode, int symbol, int count, int len, int[] values)
		{
			if (sparse)
			{
				codewords[count] = (int)huffCode;
				codewordLengths[count] = len;
				values[count] = symbol;
			}
			else
			{
				codewords[symbol] = (int)huffCode;
			}
		}

		private void InitLookupTable(DataPacket packet)
		{
			MapType = (int)packet.ReadBits(4);
			if (MapType == 0)
			{
				return;
			}
			float num = Utils.ConvertFromVorbisFloat32(packet.ReadUInt32());
			float num2 = Utils.ConvertFromVorbisFloat32(packet.ReadUInt32());
			int count = (int)packet.ReadBits(4) + 1;
			bool flag = packet.ReadBit();
			int num3 = Entries * Dimensions;
			float[] array = new float[num3];
			if (MapType == 1)
			{
				num3 = lookup1_values();
			}
			uint[] array2 = new uint[num3];
			for (int i = 0; i < num3; i++)
			{
				array2[i] = (uint)packet.ReadBits(count);
			}
			if (MapType == 1)
			{
				for (int j = 0; j < Entries; j++)
				{
					double num4 = 0.0;
					int num5 = 1;
					for (int k = 0; k < Dimensions; k++)
					{
						int num6 = j / num5 % num3;
						double num7 = (double)((float)array2[num6] * num2 + num) + num4;
						array[j * Dimensions + k] = (float)num7;
						if (flag)
						{
							num4 = num7;
						}
						num5 *= num3;
					}
				}
			}
			else
			{
				for (int l = 0; l < Entries; l++)
				{
					double num8 = 0.0;
					int num9 = l * Dimensions;
					for (int m = 0; m < Dimensions; m++)
					{
						double num10 = (double)((float)array2[num9] * num2 + num) + num8;
						array[l * Dimensions + m] = (float)num10;
						if (flag)
						{
							num8 = num10;
						}
						num9++;
					}
				}
			}
			LookupTable = array;
		}

		private int lookup1_values()
		{
			int num = (int)Math.Floor(Math.Exp(Math.Log(Entries) / (double)Dimensions));
			if (Math.Floor(Math.Pow(num + 1, Dimensions)) <= (double)Entries)
			{
				num++;
			}
			return num;
		}

		internal int DecodeScalar(DataPacket packet)
		{
			int index = (int)packet.TryPeekBits(PrefixBitLength, out var bitsRead);
			if (bitsRead == 0)
			{
				return -1;
			}
			HuffmanListNode huffmanListNode = PrefixList[index];
			if (huffmanListNode != null)
			{
				packet.SkipBits(huffmanListNode.Length);
				return huffmanListNode.Value;
			}
			index = (int)packet.TryPeekBits(MaxBits, out bitsRead);
			huffmanListNode = PrefixOverflowTree;
			do
			{
				if (huffmanListNode.Bits == (index & huffmanListNode.Mask))
				{
					packet.SkipBits(huffmanListNode.Length);
					return huffmanListNode.Value;
				}
			}
			while ((huffmanListNode = huffmanListNode.Next) != null);
			return -1;
		}
	}
	internal abstract class VorbisFloor
	{
		internal abstract class PacketData
		{
			internal int BlockSize;

			protected abstract bool HasEnergy { get; }

			internal bool ForceEnergy { get; set; }

			internal bool ForceNoEnergy { get; set; }

			internal bool ExecuteChannel => (ForceEnergy | HasEnergy) & !ForceNoEnergy;
		}

		private class Floor0 : VorbisFloor
		{
			private class PacketData0 : PacketData
			{
				internal float[] Coeff;

				internal float Amp;

				protected override bool HasEnergy => Amp > 0f;
			}

			private int _order;

			private int _rate;

			private int _bark_map_size;

			private int _ampBits;

			private int _ampOfs;

			private int _ampDiv;

			private VorbisCodebook[] _books;

			private int _bookBits;

			private Dictionary<int, float[]> _wMap;

			private Dictionary<int, int[]> _barkMaps;

			private PacketData0[] _reusablePacketData;

			internal Floor0(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			protected override void Init(DataPacket packet)
			{
				_order = (int)packet.ReadBits(8);
				_rate = (int)packet.ReadBits(16);
				_bark_map_size = (int)packet.ReadBits(16);
				_ampBits = (int)packet.ReadBits(6);
				_ampOfs = (int)packet.ReadBits(8);
				_books = new VorbisCodebook[(int)packet.ReadBits(4) + 1];
				if (_order < 1 || _rate < 1 || _bark_map_size < 1 || _books.Length == 0)
				{
					throw new InvalidDataException();
				}
				_ampDiv = (1 << _ampBits) - 1;
				for (int i = 0; i < _books.Length; i++)
				{
					int num = (int)packet.ReadBits(8);
					if (num < 0 || num >= _vorbis.Books.Length)
					{
						throw new InvalidDataException();
					}
					VorbisCodebook vorbisCodebook = _vorbis.Books[num];
					if (vorbisCodebook.MapType == 0 || vorbisCodebook.Dimensions < 1)
					{
						throw new InvalidDataException();
					}
					_books[i] = vorbisCodebook;
				}
				_bookBits = Utils.ilog(_books.Length);
				_barkMaps = new Dictionary<int, int[]>();
				_barkMaps[_vorbis.Block0Size] = SynthesizeBarkCurve(_vorbis.Block0Size / 2);
				_barkMaps[_vorbis.Block1Size] = SynthesizeBarkCurve(_vorbis.Block1Size / 2);
				_wMap = new Dictionary<int, float[]>();
				_wMap[_vorbis.Block0Size] = SynthesizeWDelMap(_vorbis.Block0Size / 2);
				_wMap[_vorbis.Block1Size] = SynthesizeWDelMap(_vorbis.Block1Size / 2);
				_reusablePacketData = new PacketData0[_vorbis._channels];
				for (int j = 0; j < _reusablePacketData.Length; j++)
				{
					_reusablePacketData[j] = new PacketData0
					{
						Coeff = new float[_order + 1]
					};
				}
			}

			private int[] SynthesizeBarkCurve(int n)
			{
				float num = (float)_bark_map_size / toBARK(_rate / 2);
				int[] array = new int[n + 1];
				for (int i = 0; i < n - 1; i++)
				{
					array[i] = Math.Min(_bark_map_size - 1, (int)Math.Floor(toBARK((float)_rate / 2f / (float)n * (float)i) * num));
				}
				array[n] = -1;
				return array;
			}

			private static float toBARK(double lsp)
			{
				return (float)(13.1 * Math.Atan(0.00074 * lsp) + 2.24 * Math.Atan(1.85E-08 * lsp * lsp) + 0.0001 * lsp);
			}

			private float[] SynthesizeWDelMap(int n)
			{
				float num = (float)(Math.PI / (double)_bark_map_size);
				float[] array = new float[n];
				for (int i = 0; i < n; i++)
				{
					array[i] = 2f * (float)Math.Cos(num * (float)i);
				}
				return array;
			}

			internal override PacketData UnpackPacket(DataPacket packet, int blockSize, int channel)
			{
				PacketData0 packetData = _reusablePacketData[channel];
				packetData.BlockSize = blockSize;
				packetData.ForceEnergy = false;
				packetData.ForceNoEnergy = false;
				packetData.Amp = packet.ReadBits(_ampBits);
				if (packetData.Amp > 0f)
				{
					Array.Clear(packetData.Coeff, 0, packetData.Coeff.Length);
					packetData.Amp = packetData.Amp / (float)_ampDiv * (float)_ampOfs;
					uint num = (uint)packet.ReadBits(_bookBits);
					if (num >= _books.Length)
					{
						packetData.Amp = 0f;
						return packetData;
					}
					VorbisCodebook vorbisCodebook = _books[num];
					int i = 0;
					while (i < _order)
					{
						int num2 = vorbisCodebook.DecodeScalar(packet);
						if (num2 == -1)
						{
							packetData.Amp = 0f;
							return packetData;
						}
						int num3 = 0;
						for (; i < _order; i++)
						{
							if (num3 >= vorbisCodebook.Dimensions)
							{
								break;
							}
							packetData.Coeff[i] = vorbisCodebook[num2, num3];
							num3++;
						}
					}
					float num4 = 0f;
					int num5 = 0;
					while (num5 < _order)
					{
						int num6 = 0;
						while (num5 < _order && num6 < vorbisCodebook.Dimensions)
						{
							packetData.Coeff[num5] += num4;
							num5++;
							num6++;
						}
						num4 = packetData.Coeff[num5 - 1];
					}
				}
				return packetData;
			}

			internal override void Apply(PacketData packetData, float[] residue)
			{
				if (!(packetData is PacketData0 packetData2))
				{
					throw new ArgumentException("Incorrect packet data!");
				}
				int num = packetData2.BlockSize / 2;
				if (packetData2.Amp > 0f)
				{
					int[] array = _barkMaps[packetData2.BlockSize];
					float[] array2 = _wMap[packetData2.BlockSize];
					int num2 = 0;
					for (num2 = 0; num2 < _order; num2++)
					{
						packetData2.Coeff[num2] = 2f * (float)Math.Cos(packetData2.Coeff[num2]);
					}
					num2 = 0;
					while (num2 < num)
					{
						int num3 = array[num2];
						float num4 = 0.5f;
						float num5 = 0.5f;
						float num6 = array2[num3];
						int i;
						for (i = 1; i < _order; i += 2)
						{
							num5 *= num6 - packetData2.Coeff[i - 1];
							num4 *= num6 - packetData2.Coeff[i];
						}
						if (i == _order)
						{
							num5 *= num6 - packetData2.Coeff[i - 1];
							num4 *= num4 * (4f - num6 * num6);
							num5 *= num5;
						}
						else
						{
							num4 *= num4 * (2f - num6);
							num5 *= num5 * (2f + num6);
						}
						num5 = packetData2.Amp / (float)Math.Sqrt(num4 + num5) - (float)_ampOfs;
						num5 = (float)Math.Exp(num5 * 0.11512925f);
						residue[num2] *= num5;
						while (array[++num2] == num3)
						{
							residue[num2] *= num5;
						}
					}
				}
				else
				{
					Array.Clear(residue, 0, num);
				}
			}
		}

		private class Floor1 : VorbisFloor
		{
			private class PacketData1 : PacketData
			{
				public int[] Posts = new int[64];

				public int PostCount;

				protected override bool HasEnergy => PostCount > 0;
			}

			private int[] _partitionClass;

			private int[] _classDimensions;

			private int[] _classSubclasses;

			private int[] _xList;

			private int[] _classMasterBookIndex;

			private int[] _hNeigh;

			private int[] _lNeigh;

			private int[] _sortIdx;

			private int _multiplier;

			private int _range;

			private int _yBits;

			private VorbisCodebook[] _classMasterbooks;

			private VorbisCodebook[][] _subclassBooks;

			private int[][] _subclassBookIndex;

			private static int[] _rangeLookup = new int[4] { 256, 128, 86, 64 };

			private static int[] _yBitsLookup = new int[4] { 8, 7, 7, 6 };

			private PacketData1[] _reusablePacketData;

			private bool[] _stepFlags = new bool[64];

			private int[] _finalY = new int[64];

			private static readonly float[] inverse_dB_table = new float[256]
			{
				1.0649863E-07f, 1.1341951E-07f, 1.2079015E-07f, 1.2863978E-07f, 1.369995E-07f, 1.459025E-07f, 1.5538409E-07f, 1.6548181E-07f, 1.7623574E-07f, 1.8768856E-07f,
				1.998856E-07f, 2.128753E-07f, 2.2670913E-07f, 2.4144197E-07f, 2.5713223E-07f, 2.7384212E-07f, 2.9163792E-07f, 3.1059022E-07f, 3.307741E-07f, 3.5226967E-07f,
				3.7516213E-07f, 3.995423E-07f, 4.255068E-07f, 4.5315863E-07f, 4.8260745E-07f, 5.1397E-07f, 5.4737063E-07f, 5.829419E-07f, 6.208247E-07f, 6.611694E-07f,
				7.041359E-07f, 7.4989464E-07f, 7.98627E-07f, 8.505263E-07f, 9.057983E-07f, 9.646621E-07f, 1.0273513E-06f, 1.0941144E-06f, 1.1652161E-06f, 1.2409384E-06f,
				1.3215816E-06f, 1.4074654E-06f, 1.4989305E-06f, 1.5963394E-06f, 1.7000785E-06f, 1.8105592E-06f, 1.9282195E-06f, 2.053526E-06f, 2.1869757E-06f, 2.3290977E-06f,
				2.4804558E-06f, 2.6416496E-06f, 2.813319E-06f, 2.9961443E-06f, 3.1908505E-06f, 3.39821E-06f, 3.619045E-06f, 3.8542307E-06f, 4.1047006E-06f, 4.371447E-06f,
				4.6555283E-06f, 4.958071E-06f, 5.280274E-06f, 5.623416E-06f, 5.988857E-06f, 6.3780467E-06f, 6.7925284E-06f, 7.2339453E-06f, 7.704048E-06f, 8.2047E-06f,
				8.737888E-06f, 9.305725E-06f, 9.910464E-06f, 1.0554501E-05f, 1.1240392E-05f, 1.1970856E-05f, 1.2748789E-05f, 1.3577278E-05f, 1.4459606E-05f, 1.5399271E-05f,
				1.6400005E-05f, 1.7465769E-05f, 1.8600793E-05f, 1.9809577E-05f, 2.1096914E-05f, 2.2467912E-05f, 2.3928002E-05f, 2.5482977E-05f, 2.7139005E-05f, 2.890265E-05f,
				3.078091E-05f, 3.2781227E-05f, 3.4911533E-05f, 3.718028E-05f, 3.9596467E-05f, 4.2169668E-05f, 4.491009E-05f, 4.7828602E-05f, 5.0936775E-05f, 5.424693E-05f,
				5.7772202E-05f, 6.152657E-05f, 6.552491E-05f, 6.9783084E-05f, 7.4317984E-05f, 7.914758E-05f, 8.429104E-05f, 8.976875E-05f, 9.560242E-05f, 0.00010181521f,
				0.00010843174f, 0.00011547824f, 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, 0.00015820454f, 0.00016848555f, 0.00017943469f, 0.00019109536f,
				0.00020351382f, 0.0002167393f, 0.00023082423f, 0.00024582449f, 0.00026179955f, 0.00027881275f, 0.00029693157f, 0.00031622787f, 0.00033677815f, 0.00035866388f,
				0.00038197188f, 0.00040679457f, 0.00043323037f, 0.0004613841f, 0.0004913675f, 0.00052329927f, 0.0005573062f, 0.0005935231f, 0.0006320936f, 0.0006731706f,
				0.000716917f, 0.0007635063f, 0.00081312325f, 0.00086596457f, 0.00092223985f, 0.0009821722f, 0.0010459992f, 0.0011139743f, 0.0011863665f, 0.0012634633f,
				0.0013455702f, 0.0014330129f, 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, 0.0019632196f, 0.0020908006f, 0.0022266726f, 0.0023713743f,
				0.0025254795f, 0.0026895993f, 0.0028643848f, 0.0030505287f, 0.003248769f, 0.0034598925f, 0.0036847359f, 0.0039241905f, 0.0041792067f, 0.004450795f,
				0.004740033f, 0.005048067f, 0.0053761187f, 0.005725489f, 0.0060975635f, 0.0064938175f, 0.0069158226f, 0.0073652514f, 0.007843887f, 0.008353627f,
				0.008896492f, 0.009474637f, 0.010090352f, 0.01074608f, 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, 0.014722068f, 0.015678791f,
				0.016697686f, 0.017782796f, 0.018938422f, 0.020169148f, 0.021479854f, 0.022875736f, 0.02436233f, 0.025945531f, 0.027631618f, 0.029427277f,
				0.031339627f, 0.03337625f, 0.035545226f, 0.037855156f, 0.0403152f, 0.042935107f, 0.045725275f, 0.048696756f, 0.05186135f, 0.05523159f,
				0.05882085f, 0.062643364f, 0.06671428f, 0.07104975f, 0.075666964f, 0.08058423f, 0.08582105f, 0.09139818f, 0.097337745f, 0.1036633f,
				0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, 0.14201812f, 0.15124726f, 0.16107617f, 0.1715438f, 0.18269168f, 0.19456401f,
				0.20720787f, 0.22067343f, 0.23501402f, 0.25028655f, 0.26655158f, 0.28387362f, 0.3023213f, 0.32196787f, 0.34289113f, 0.36517414f,
				0.3889052f, 0.41417846f, 0.44109413f, 0.4697589f, 0.50028646f, 0.53279793f, 0.5674221f, 0.6042964f, 0.64356697f, 0.6853896f,
				0.72993004f, 0.777365f, 0.8278826f, 0.88168305f, 0.9389798f, 1f
			};

			internal Floor1(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			protected override void Init(DataPacket packet)
			{
				_partitionClass = new int[(uint)packet.ReadBits(5)];
				for (int i = 0; i < _partitionClass.Length; i++)
				{
					_partitionClass[i] = (int)packet.ReadBits(4);
				}
				int num = _partitionClass.Max();
				_classDimensions = new int[num + 1];
				_classSubclasses = new int[num + 1];
				_classMasterbooks = new VorbisCodebook[num + 1];
				_classMasterBookIndex = new int[num + 1];
				_subclassBooks = new VorbisCodebook[num + 1][];
				_subclassBookIndex = new int[num + 1][];
				for (int j = 0; j <= num; j++)
				{
					_classDimensions[j] = (int)packet.ReadBits(3) + 1;
					_classSubclasses[j] = (int)packet.ReadBits(2);
					if (_classSubclasses[j] > 0)
					{
						_classMasterBookIndex[j] = (int)packet.ReadBits(8);
						_classMasterbooks[j] = _vorbis.Books[_classMasterBookIndex[j]];
					}
					_subclassBooks[j] = new VorbisCodebook[1 << _classSubclasses[j]];
					_subclassBookIndex[j] = new int[_subclassBooks[j].Length];
					for (int k = 0; k < _subclassBooks[j].Length; k++)
					{
						int num2 = (int)packet.ReadBits(8) - 1;
						if (num2 >= 0)
						{
							_subclassBooks[j][k] = _vorbis.Books[num2];
						}
						_subclassBookIndex[j][k] = num2;
					}
				}
				_multiplier = (int)packet.ReadBits(2);
				_range = _rangeLookup[_multiplier];
				_yBits = _yBitsLookup[_multiplier];
				_multiplier++;
				int num3 = (int)packet.ReadBits(4);
				List<int> list = new List<int>();
				list.Add(0);
				list.Add(1 << num3);
				for (int l = 0; l < _partitionClass.Length; l++)
				{
					int num4 = _partitionClass[l];
					for (int m = 0; m < _classDimensions[num4]; m++)
					{
						list.Add((int)packet.ReadBits(num3));
					}
				}
				_xList = list.ToArray();
				_lNeigh = new int[list.Count];
				_hNeigh = new int[list.Count];
				_sortIdx = new int[list.Count];
				_sortIdx[0] = 0;
				_sortIdx[1] = 1;
				for (int n = 2; n < _lNeigh.Length; n++)
				{
					_lNeigh[n] = 0;
					_hNeigh[n] = 1;
					_sortIdx[n] = n;
					for (int num5 = 2; num5 < n; num5++)
					{
						int num6 = _xList[num5];
						if (num6 < _xList[n])
						{
							if (num6 > _xList[_lNeigh[n]])
							{
								_lNeigh[n] = num5;
							}
						}
						else if (num6 < _xList[_hNeigh[n]])
						{
							_hNeigh[n] = num5;
						}
					}
				}
				for (int num7 = 0; num7 < _sortIdx.Length - 1; num7++)
				{
					for (int num8 = num7 + 1; num8 < _sortIdx.Length; num8++)
					{
						if (_xList[num7] == _xList[num8])
						{
							throw new InvalidDataException();
						}
						if (_xList[_sortIdx[num7]] > _xList[_sortIdx[num8]])
						{
							int num9 = _sortIdx[num7];
							_sortIdx[num7] = _sortIdx[num8];
							_sortIdx[num8] = num9;
						}
					}
				}
				_reusablePacketData = new PacketData1[_vorbis._channels];
				for (int num10 = 0; num10 < _reusablePacketData.Length; num10++)
				{
					_reusablePacketData[num10] = new PacketData1();
				}
			}

			internal override PacketData UnpackPacket(DataPacket packet, int blockSize, int channel)
			{
				PacketData1 packetData = _reusablePacketData[channel];
				packetData.BlockSize = blockSize;
				packetData.ForceEnergy = false;
				packetData.ForceNoEnergy = false;
				packetData.PostCount = 0;
				Array.Clear(packetData.Posts, 0, 64);
				if (packet.ReadBit())
				{
					int num = 2;
					packetData.Posts[0] = (int)packet.ReadBits(_yBits);
					packetData.Posts[1] = (int)packet.ReadBits(_yBits);
					for (int i = 0; i < _partitionClass.Length; i++)
					{
						int num2 = _partitionClass[i];
						int num3 = _classDimensions[num2];
						int num4 = _classSubclasses[num2];
						int num5 = (1 << num4) - 1;
						uint num6 = 0u;
						if (num4 > 0 && (num6 = (uint)_classMasterbooks[num2].DecodeScalar(packet)) == uint.MaxValue)
						{
							num = 0;
							break;
						}
						for (int j = 0; j < num3; j++)
						{
							VorbisCodebook vorbisCodebook = _subclassBooks[num2][num6 & num5];
							num6 >>= num4;
							if (vorbisCodebook != null && (packetData.Posts[num] = vorbisCodebook.DecodeScalar(packet)) == -1)
							{
								num = 0;
								i = _partitionClass.Length;
								break;
							}
							num++;
						}
					}
					packetData.PostCount = num;
				}
				return packetData;
			}

			internal override void Apply(PacketData packetData, float[] residue)
			{
				if (!(packetData is PacketData1 packetData2))
				{
					throw new ArgumentException("Incorrect packet data!", "packetData");
				}
				int num = packetData2.BlockSize / 2;
				if (packetData2.PostCount > 0)
				{
					bool[] array = UnwrapPosts(packetData2);
					int num2 = 0;
					int num3 = packetData2.Posts[0] * _multiplier;
					for (int i = 1; i < packetData2.PostCount; i++)
					{
						int num4 = _sortIdx[i];
						if (array[num4])
						{
							int num5 = _xList[num4];
							int num6 = packetData2.Posts[num4] * _multiplier;
							if (num2 < num)
							{
								RenderLineMulti(num2, num3, Math.Min(num5, num), num6, residue);
							}
							num2 = num5;
							num3 = num6;
						}
						if (num2 >= num)
						{
							break;
						}
					}
					if (num2 < num)
					{
						RenderLineMulti(num2, num3, num, num3, residue);
					}
				}
				else
				{
					Array.Clear(residue, 0, num);
				}
			}

			private bool[] UnwrapPosts(PacketData1 data)
			{
				Array.Clear(_stepFlags, 2, 62);
				_stepFlags[0] = true;
				_stepFlags[1] = true;
				Array.Clear(_finalY, 2, 62);
				_finalY[0] = data.Posts[0];
				_finalY[1] = data.Posts[1];
				for (int i = 2; i < data.PostCount; i++)
				{
					int num = _lNeigh[i];
					int num2 = _hNeigh[i];
					int num3 = RenderPoint(_xList[num], _finalY[num], _xList[num2], _finalY[num2], _xList[i]);
					int num4 = data.Posts[i];
					int num5 = _range - num3;
					int num6 = num3;
					int num7 = ((num5 >= num6) ? (num6 * 2) : (num5 * 2));
					if (num4 != 0)
					{
						_stepFlags[num] = true;
						_stepFlags[num2] = true;
						_stepFlags[i] = true;
						if (num4 >= num7)
						{
							if (num5 > num6)
							{
								_finalY[i] = num4 - num6 + num3;
							}
							else
							{
								_finalY[i] = num3 - num4 + num5 - 1;
							}
						}
						else if (num4 % 2 == 1)
						{
							_finalY[i] = num3 - (num4 + 1) / 2;
						}
						else
						{
							_finalY[i] = num3 + num4 / 2;
						}
					}
					else
					{
						_stepFlags[i] = false;
						_finalY[i] = num3;
					}
				}
				for (int j = 0; j < data.PostCount; j++)
				{
					data.Posts[j] = _finalY[j];
				}
				return _stepFlags;
			}

			private int RenderPoint(int x0, int y0, int x1, int y1, int X)
			{
				int num = y1 - y0;
				int num2 = x1 - x0;
				int num3 = Math.Abs(num) * (X - x0) / num2;
				if (num < 0)
				{
					return y0 - num3;
				}
				return y0 + num3;
			}

			private void RenderLineMulti(int x0, int y0, int x1, int y1, float[] v)
			{
				int num = y1 - y0;
				int num2 = x1 - x0;
				int num3 = Math.Abs(num);
				int num4 = 1 - ((num >> 31) & 1) * 2;
				int num5 = num / num2;
				int num6 = x0;
				int num7 = y0;
				int num8 = -num2;
				v[x0] *= inverse_dB_table[y0];
				num3 -= Math.Abs(num5) * num2;
				while (++num6 < x1)
				{
					num7 += num5;
					num8 += num3;
					if (num8 >= 0)
					{
						num8 -= num2;
						num7 += num4;
					}
					v[num6] *= inverse_dB_table[num7];
				}
			}
		}

		private VorbisStreamDecoder _vorbis;

		internal static VorbisFloor Init(VorbisStreamDecoder vorbis, DataPacket packet)
		{
			int num = (int)packet.ReadBits(16);
			VorbisFloor vorbisFloor = null;
			switch (num)
			{
			case 0:
				vorbisFloor = new Floor0(vorbis);
				break;
			case 1:
				vorbisFloor = new Floor1(vorbis);
				break;
			}
			if (vorbisFloor == null)
			{
				throw new InvalidDataException();
			}
			vorbisFloor.Init(packet);
			return vorbisFloor;
		}

		protected VorbisFloor(VorbisStreamDecoder vorbis)
		{
			_vorbis = vorbis;
		}

		protected abstract void Init(DataPacket packet);

		internal abstract PacketData UnpackPacket(DataPacket packet, int blockSize, int channel);

		internal abstract void Apply(PacketData packetData, float[] residue);
	}
	internal abstract class VorbisMapping
	{
		private class Mapping0 : VorbisMapping
		{
			internal Mapping0(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			protected override void Init(DataPacket packet)
			{
				int num = 1;
				if (packet.ReadBit())
				{
					num += (int)packet.ReadBits(4);
				}
				int num2 = 0;
				if (packet.ReadBit())
				{
					num2 = (int)packet.ReadBits(8) + 1;
				}
				int count = Utils.ilog(_vorbis._channels - 1);
				CouplingSteps = new CouplingStep[num2];
				for (int i = 0; i < num2; i++)
				{
					int num3 = (int)packet.ReadBits(count);
					int num4 = (int)packet.ReadBits(count);
					if (num3 == num4 || num3 > _vorbis._channels - 1 || num4 > _vorbis._channels - 1)
					{
						throw new InvalidDataException();
					}
					CouplingSteps[i] = new CouplingStep
					{
						Angle = num4,
						Magnitude = num3
					};
				}
				if (packet.ReadBits(2) != 0L)
				{
					throw new InvalidDataException();
				}
				int[] array = new int[_vorbis._channels];
				if (num > 1)
				{
					for (int j = 0; j < ChannelSubmap.Length; j++)
					{
						array[j] = (int)packet.ReadBits(4);
						if (array[j] >= num)
						{
							throw new InvalidDataException();
						}
					}
				}
				Submaps = new Submap[num];
				for (int k = 0; k < num; k++)
				{
					packet.ReadBits(8);
					int num5 = (int)packet.ReadBits(8);
					if (num5 >= _vorbis.Floors.Length)
					{
						throw new InvalidDataException();
					}
					if ((int)packet.ReadBits(8) >= _vorbis.Residues.Length)
					{
						throw new InvalidDataException();
					}
					Submaps[k] = new Submap
					{
						Floor = _vorbis.Floors[num5],
						Residue = _vorbis.Residues[num5]
					};
				}
				ChannelSubmap = new Submap[_vorbis._channels];
				for (int l = 0; l < ChannelSubmap.Length; l++)
				{
					ChannelSubmap[l] = Submaps[array[l]];
				}
			}
		}

		internal class Submap
		{
			internal VorbisFloor Floor;

			internal VorbisResidue Residue;

			internal Submap()
			{
			}
		}

		internal class CouplingStep
		{
			internal int Magnitude;

			internal int Angle;

			internal CouplingStep()
			{
			}
		}

		private VorbisStreamDecoder _vorbis;

		internal Submap[] Submaps;

		internal Submap[] ChannelSubmap;

		internal CouplingStep[] CouplingSteps;

		internal static VorbisMapping Init(VorbisStreamDecoder vorbis, DataPacket packet)
		{
			int num = (int)packet.ReadBits(16);
			VorbisMapping vorbisMapping = null;
			if (num == 0)
			{
				vorbisMapping = new Mapping0(vorbis);
			}
			if (vorbisMapping == null)
			{
				throw new InvalidDataException();
			}
			vorbisMapping.Init(packet);
			return vorbisMapping;
		}

		protected VorbisMapping(VorbisStreamDecoder vorbis)
		{
			_vorbis = vorbis;
		}

		protected abstract void Init(DataPacket packet);
	}
	internal class VorbisMode
	{
		private const float M_PI = (float)Math.PI;

		private const float M_PI2 = (float)Math.PI / 2f;

		private VorbisStreamDecoder _vorbis;

		private float[][] _windows;

		internal bool BlockFlag;

		internal int WindowType;

		internal int TransformType;

		internal VorbisMapping Mapping;

		internal int BlockSize;

		internal static VorbisMode Init(VorbisStreamDecoder vorbis, DataPacket packet)
		{
			VorbisMode vorbisMode = new VorbisMode(vorbis);
			vorbisMode.BlockFlag = packet.ReadBit();
			vorbisMode.WindowType = (int)packet.ReadBits(16);
			vorbisMode.TransformType = (int)packet.ReadBits(16);
			int num = (int)packet.ReadBits(8);
			if (vorbisMode.WindowType != 0 || vorbisMode.TransformType != 0 || num >= vorbis.Maps.Length)
			{
				throw new InvalidDataException();
			}
			vorbisMode.Mapping = vorbis.Maps[num];
			vorbisMode.BlockSize = (vorbisMode.BlockFlag ? vorbis.Block1Size : vorbis.Block0Size);
			if (vorbisMode.BlockFlag)
			{
				vorbisMode._windows = new float[4][];
				vorbisMode._windows[0] = new float[vorbis.Block1Size];
				vorbisMode._windows[1] = new float[vorbis.Block1Size];
				vorbisMode._windows[2] = new float[vorbis.Block1Size];
				vorbisMode._windows[3] = new float[vorbis.Block1Size];
			}
			else
			{
				vorbisMode._windows = new float[1][];
				vorbisMode._windows[0] = new float[vorbis.Block0Size];
			}
			vorbisMode.CalcWindows();
			return vorbisMode;
		}

		private VorbisMode(VorbisStreamDecoder vorbis)
		{
			_vorbis = vorbis;
		}

		private void CalcWindows()
		{
			for (int i = 0; i < _windows.Length; i++)
			{
				float[] array = _windows[i];
				int num = (((i & 1) == 0) ? _vorbis.Block0Size : _vorbis.Block1Size) / 2;
				int blockSize = BlockSize;
				int num2 = (((i & 2) == 0) ? _vorbis.Block0Size : _vorbis.Block1Size) / 2;
				int num3 = blockSize / 4 - num / 2;
				int num4 = blockSize - blockSize / 4 - num2 / 2;
				for (int j = 0; j < num; j++)
				{
					float num5 = (float)Math.Sin(((double)j + 0.5) / (double)num * 1.5707963705062866);
					num5 *= num5;
					array[num3 + j] = (float)Math.Sin(num5 * ((float)Math.PI / 2f));
				}
				for (int k = num3 + num; k < num4; k++)
				{
					array[k] = 1f;
				}
				for (int l = 0; l < num2; l++)
				{
					float num6 = (float)Math.Sin(((double)(num2 - l) - 0.5) / (double)num2 * 1.5707963705062866);
					num6 *= num6;
					array[num4 + l] = (float)Math.Sin(num6 * ((float)Math.PI / 2f));
				}
			}
		}

		internal float[] GetWindow(bool prev, bool next)
		{
			if (BlockFlag)
			{
				if (next)
				{
					if (prev)
					{
						return _windows[3];
					}
					return _windows[2];
				}
				if (prev)
				{
					return _windows[1];
				}
			}
			return _windows[0];
		}
	}
	public class VorbisReader : IDisposable
	{
		private int _streamIdx;

		private IContainerReader _containerReader;

		private List<VorbisStreamDecoder> _decoders;

		private List<int> _serials;

		private VorbisStreamDecoder ActiveDecoder
		{
			get
			{
				if (_decoders == null)
				{
					throw new ObjectDisposedException("VorbisReader");
				}
				return _decoders[_streamIdx];
			}
		}

		public int Channels => ActiveDecoder._channels;

		public int SampleRate => ActiveDecoder._sampleRate;

		public int UpperBitrate => ActiveDecoder._upperBitrate;

		public int NominalBitrate => ActiveDecoder._nominalBitrate;

		public int LowerBitrate => ActiveDecoder._lowerBitrate;

		public string Vendor => ActiveDecoder._vendor;

		public string[] Comments => ActiveDecoder._comments;

		public bool IsParameterChange => ActiveDecoder.IsParameterChange;

		public long ContainerOverheadBits => ActiveDecoder.ContainerBits;

		public bool ClipSamples { get; set; }

		public IVorbisStreamStatus[] Stats => _decoders.Select((VorbisStreamDecoder d) => d).Cast<IVorbisStreamStatus>().ToArray();

		public int StreamIndex => _streamIdx;

		public int StreamCount => _decoders.Count;

		public TimeSpan DecodedTime
		{
			get
			{
				return TimeSpan.FromSeconds((double)ActiveDecoder.CurrentPosition / (double)SampleRate);
			}
			set
			{
				ActiveDecoder.SeekTo((long)(value.TotalSeconds * (double)SampleRate));
			}
		}

		public long DecodedPosition
		{
			get
			{
				return ActiveDecoder.CurrentPosition;
			}
			set
			{
				ActiveDecoder.SeekTo(value);
			}
		}

		public TimeSpan TotalTime
		{
			get
			{
				VorbisStreamDecoder activeDecoder = ActiveDecoder;
				if (activeDecoder.CanSeek)
				{
					return TimeSpan.FromSeconds((double)activeDecoder.GetLastGranulePos() / (double)activeDecoder._sampleRate);
				}
				return TimeSpan.MaxValue;
			}
		}

		public long TotalSamples
		{
			get
			{
				VorbisStreamDecoder activeDecoder = ActiveDecoder;
				if (activeDecoder.CanSeek)
				{
					return activeDecoder.GetLastGranulePos();
				}
				return long.MaxValue;
			}
		}

		private VorbisReader()
		{
			ClipSamples = true;
			_decoders = new List<VorbisStreamDecoder>();
			_serials = new List<int>();
		}

		public VorbisReader(string fileName)
			: this(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), closeStreamOnDispose: true)
		{
		}

		public VorbisReader(Stream stream, bool closeStreamOnDispose)
			: this()
		{
			ContainerReader containerReader = new ContainerReader(stream, closeStreamOnDispose);
			if (!LoadContainer(containerReader))
			{
				if (closeStreamOnDispose)
				{
					stream.Close();
				}
				throw new InvalidDataException("Could not determine container type!");
			}
			_containerReader = containerReader;
			if (_decoders.Count == 0)
			{
				throw new InvalidDataException("No Vorbis data found!");
			}
		}

		public VorbisReader(IContainerReader containerReader)
			: this()
		{
			if (!LoadContainer(containerReader))
			{
				throw new InvalidDataException("Container did not initialize!");
			}
			_containerReader = containerReader;
			if (_decoders.Count == 0)
			{
				throw new InvalidDataException("No Vorbis data found!");
			}
		}

		public VorbisReader(IPacketProvider packetProvider)
			: this()
		{
			NewStreamEventArgs e = new NewStreamEventArgs(packetProvider);
			NewStream(this, e);
			if (e.IgnoreStream)
			{
				throw new InvalidDataException("No Vorbis data found!");
			}
		}

		private bool LoadContainer(IContainerReader containerReader)
		{
			containerReader.NewStream += NewStream;
			if (!containerReader.Init())
			{
				containerReader.NewStream -= NewStream;
				return false;
			}
			return true;
		}

		private void NewStream(object sender, NewStreamEventArgs ea)
		{
			IPacketProvider packetProvider = ea.PacketProvider;
			VorbisStreamDecoder vorbisStreamDecoder = new VorbisStreamDecoder(packetProvider);
			if (vorbisStreamDecoder.TryInit())
			{
				_decoders.Add(vorbisStreamDecoder);
				_serials.Add(packetProvider.StreamSerial);
			}
			else
			{
				ea.IgnoreStream = true;
			}
		}

		public void Dispose()
		{
			if (_decoders != null)
			{
				foreach (VorbisStreamDecoder decoder in _decoders)
				{
					decoder.Dispose();
				}
				_decoders.Clear();
				_decoders = null;
			}
			if (_containerReader != null)
			{
				_containerReader.NewStream -= NewStream;
				_containerReader.Dispose();
				_containerReader = null;
			}
		}

		public int ReadSamples(float[] buffer, int offset, int count)
		{
			if (offset < 0)
			{
				throw new ArgumentOutOfRangeException("offset");
			}
			if (count < 0 || offset + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("count");
			}
			count = ActiveDecoder.ReadSamples(buffer, offset, count);
			if (ClipSamples)
			{
				VorbisStreamDecoder vorbisStreamDecoder = _decoders[_streamIdx];
				int num = 0;
				while (num < count)
				{
					buffer[offset] = Utils.ClipValue(buffer[offset], ref vorbisStreamDecoder._clipped);
					num++;
					offset++;
				}
			}
			return count;
		}

		public void ClearParameterChange()
		{
			ActiveDecoder.IsParameterChange = false;
		}

		public bool FindNextStream()
		{
			if (_containerReader == null)
			{
				return false;
			}
			return _containerReader.FindNextStream();
		}

		public bool SwitchStreams(int index)
		{
			if (index < 0 || index >= StreamCount)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			if (_decoders == null)
			{
				throw new ObjectDisposedException("VorbisReader");
			}
			if (_streamIdx == index)
			{
				return false;
			}
			VorbisStreamDecoder vorbisStreamDecoder = _decoders[_streamIdx];
			_streamIdx = index;
			VorbisStreamDecoder vorbisStreamDecoder2 = _decoders[_streamIdx];
			if (vorbisStreamDecoder._channels == vorbisStreamDecoder2._channels)
			{
				return vorbisStreamDecoder._sampleRate != vorbisStreamDecoder2._sampleRate;
			}
			return true;
		}
	}
	internal abstract class VorbisResidue
	{
		private class Residue0 : VorbisResidue
		{
			private int _begin;

			private int _end;

			private int _partitionSize;

			private int _classifications;

			private int _maxStages;

			private VorbisCodebook[][] _books;

			private VorbisCodebook _classBook;

			private int[] _cascade;

			private int[] _entryCache;

			private int[][] _decodeMap;

			private int[][][] _partWordCache;

			internal Residue0(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			protected override void Init(DataPacket packet)
			{
				_begin = (int)packet.ReadBits(24);
				_end = (int)packet.ReadBits(24);
				_partitionSize = (int)packet.ReadBits(24) + 1;
				_classifications = (int)packet.ReadBits(6) + 1;
				_classBook = _vorbis.Books[(uint)packet.ReadBits(8)];
				_cascade = new int[_classifications];
				int num = 0;
				for (int i = 0; i < _classifications; i++)
				{
					int num2 = (int)packet.ReadBits(3);
					if (packet.ReadBit())
					{
						_cascade[i] = ((int)packet.ReadBits(5) << 3) | num2;
					}
					else
					{
						_cascade[i] = num2;
					}
					num += icount(_cascade[i]);
				}
				int[] array = new int[num];
				for (int j = 0; j < num; j++)
				{
					array[j] = (int)packet.ReadBits(8);
					if (_vorbis.Books[array[j]].MapType == 0)
					{
						throw new InvalidDataException();
					}
				}
				int entries = _classBook.Entries;
				int num3 = _classBook.Dimensions;
				int num4 = 1;
				while (num3 > 0)
				{
					num4 *= _classifications;
					if (num4 > entries)
					{
						throw new InvalidDataException();
					}
					num3--;
				}
				num3 = _classBook.Dimensions;
				_books = new VorbisCodebook[_classifications][];
				num = 0;
				int num5 = 0;
				for (int k = 0; k < _classifications; k++)
				{
					int num6 = Utils.ilog(_cascade[k]);
					_books[k] = new VorbisCodebook[num6];
					if (num6 <= 0)
					{
						continue;
					}
					num5 = Math.Max(num5, num6);
					for (int l = 0; l < num6; l++)
					{
						if ((_cascade[k] & (1 << l)) > 0)
						{
							_books[k][l] = _vorbis.Books[array[num++]];
						}
					}
				}
				_maxStages = num5;
				_decodeMap = new int[num4][];
				for (int m = 0; m < num4; m++)
				{
					int num7 = m;
					int num8 = num4 / _classifications;
					_decodeMap[m] = new int[_classBook.Dimensions];
					for (int n = 0; n < _classBook.Dimensions; n++)
					{
						int num9 = num7 / num8;
						num7 -= num9 * num8;
						num8 /= _classifications;
						_decodeMap[m][n] = num9;
					}
				}
				_entryCache = new int[_partitionSize];
				_partWordCache = new int[_vorbis._channels][][];
				int num10 = ((_end - _begin) / _partitionSize + _classBook.Dimensions - 1) / _classBook.Dimensions;
				for (int num11 = 0; num11 < _vorbis._channels; num11++)
				{
					_partWordCache[num11] = new int[num10][];
				}
			}

			internal override float[][] Decode(DataPacket packet, bool[] doNotDecode, int channels, int blockSize)
			{
				float[][] residueBuffer = GetResidueBuffer(doNotDecode.Length);
				int num = ((_end < blockSize / 2) ? _end : (blockSize / 2)) - _begin;
				if (num > 0 && doNotDecode.Contains(value: false))
				{
					int num2 = num / _partitionSize;
					int length = (num2 + _classBook.Dimensions - 1) / _classBook.Dimensions;
					for (int i = 0; i < channels; i++)
					{
						Array.Clear(_partWordCache[i], 0, length);
					}
					for (int j = 0; j < _maxStages; j++)
					{
						int k = 0;
						int num3 = 0;
						while (k < num2)
						{
							if (j == 0)
							{
								for (int l = 0; l < channels; l++)
								{
									int num4 = _classBook.DecodeScalar(packet);
									if (num4 >= 0 && num4 < _decodeMap.Length)
									{
										_partWordCache[l][num3] = _decodeMap[num4];
										continue;
									}
									k = num2;
									j = _maxStages;
									break;
								}
							}
							int num5 = 0;
							for (; k < num2; k++)
							{
								if (num5 >= _classBook.Dimensions)
								{
									break;
								}
								int offset = _begin + k * _partitionSize;
								for (int m = 0; m < channels; m++)
								{
									int num6 = _partWordCache[m][num3][num5];
									if ((_cascade[num6] & (1 << j)) != 0)
									{
										VorbisCodebook vorbisCodebook = _books[num6][j];
										if (vorbisCodebook != null && WriteVectors(vorbisCodebook, packet, residueBuffer, m, offset, _partitionSize))
										{
											k = num2;
											j = _maxStages;
											break;
										}
									}
								}
								num5++;
							}
							num3++;
						}
					}
				}
				return residueBuffer;
			}

			protected virtual bool WriteVectors(VorbisCodebook codebook, DataPacket packet, float[][] residue, int channel, int offset, int partitionSize)
			{
				float[] array = residue[channel];
				int num = partitionSize / codebook.Dimensions;
				for (int i = 0; i < num; i++)
				{
					if ((_entryCache[i] = codebook.DecodeScalar(packet)) == -1)
					{
						return true;
					}
				}
				for (int j = 0; j < codebook.Dimensions; j++)
				{
					int num2 = 0;
					while (num2 < num)
					{
						array[offset] += codebook[_entryCache[num2], j];
						num2++;
						offset++;
					}
				}
				return false;
			}
		}

		private class Residue1 : Residue0
		{
			internal Residue1(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			protected override bool WriteVectors(VorbisCodebook codebook, DataPacket packet, float[][] residue, int channel, int offset, int partitionSize)
			{
				float[] array = residue[channel];
				int num = 0;
				while (num < partitionSize)
				{
					int num2 = codebook.DecodeScalar(packet);
					if (num2 == -1)
					{
						return true;
					}
					for (int i = 0; i < codebook.Dimensions; i++)
					{
						array[offset + num] += codebook[num2, i];
						num++;
					}
				}
				return false;
			}
		}

		private class Residue2 : Residue0
		{
			private int _channels;

			internal Residue2(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			internal override float[][] Decode(DataPacket packet, bool[] doNotDecode, int channels, int blockSize)
			{
				_channels = channels;
				return base.Decode(packet, doNotDecode, 1, blockSize * channels);
			}

			protected override bool WriteVectors(VorbisCodebook codebook, DataPacket packet, float[][] residue, int channel, int offset, int partitionSize)
			{
				int num = 0;
				offset /= _channels;
				int num2 = 0;
				while (num2 < partitionSize)
				{
					int num3 = codebook.DecodeScalar(packet);
					if (num3 == -1)
					{
						return true;
					}
					int num4 = 0;
					while (num4 < codebook.Dimensions)
					{
						residue[num][offset] += codebook[num3, num4];
						if (++num == _channels)
						{
							num = 0;
							offset++;
						}
						num4++;
						num2++;
					}
				}
				return false;
			}
		}

		private VorbisStreamDecoder _vorbis;

		private float[][] _residue;

		internal static VorbisResidue Init(VorbisStreamDecoder vorbis, DataPacket packet)
		{
			int num = (int)packet.ReadBits(16);
			VorbisResidue vorbisResidue = null;
			switch (num)
			{
			case 0:
				vorbisResidue = new Residue0(vorbis);
				break;
			case 1:
				vorbisResidue = new Residue1(vorbis);
				break;
			case 2:
				vorbisResidue = new Residue2(vorbis);
				break;
			}
			if (vorbisResidue == null)
			{
				throw new InvalidDataException();
			}
			vorbisResidue.Init(packet);
			return vorbisResidue;
		}

		private static int icount(int v)
		{
			int num = 0;
			while (v != 0)
			{
				num += v & 1;
				v >>= 1;
			}
			return num;
		}

		protected VorbisResidue(VorbisStreamDecoder vorbis)
		{
			_vorbis = vorbis;
			_residue = new float[_vorbis._channels][];
			for (int i = 0; i < _vorbis._channels; i++)
			{
				_residue[i] = new float[_vorbis.Block1Size];
			}
		}

		protected float[][] GetResidueBuffer(int channels)
		{
			float[][] array = _residue;
			if (channels < _vorbis._channels)
			{
				array = new float[channels][];
				Array.Copy(_residue, array, channels);
			}
			for (int i = 0; i < channels; i++)
			{
				Array.Clear(array[i], 0, array[i].Length);
			}
			return array;
		}

		internal abstract float[][] Decode(DataPacket packet, bool[] doNotDecode, int channels, int blockSize);

		protected abstract void Init(DataPacket packet);
	}
	internal class VorbisStreamDecoder : IVorbisStreamStatus, IDisposable
	{
		internal int _upperBitrate;

		internal int _nominalBitrate;

		internal int _lowerBitrate;

		internal string _vendor;

		internal string[] _comments;

		internal int _channels;

		internal int _sampleRate;

		internal int Block0Size;

		internal int Block1Size;

		internal VorbisCodebook[] Books;

		internal VorbisTime[] Times;

		internal VorbisFloor[] Floors;

		internal VorbisResidue[] Residues;

		internal VorbisMapping[] Maps;

		internal VorbisMode[] Modes;

		private int _modeFieldBits;

		internal long _glueBits;

		internal long _metaBits;

		internal long _bookBits;

		internal long _timeHdrBits;

		internal long _floorHdrBits;

		internal long _resHdrBits;

		internal long _mapHdrBits;

		internal long _modeHdrBits;

		internal long _wasteHdrBits;

		internal long _modeBits;

		internal long _floorBits;

		internal long _resBits;

		internal long _wasteBits;

		internal long _samples;

		internal int _packetCount;

		internal Stopwatch _sw = new Stopwatch();

		private IPacketProvider _packetProvider;

		private DataPacket _parameterChangePacket;

		private List<int> _pagesSeen;

		private int _lastPageSeen;

		private bool _eosFound;

		private object _seekLock = new object();

		private static readonly byte[] PacketSignatureStream = new byte[7] { 1, 118, 111, 114, 98, 105, 115 };

		private static readonly byte[] PacketSignatureComments = new byte[7] { 3, 118, 111, 114, 98, 105, 115 };

		private static readonly byte[] PacketSignatureBooks = new byte[7] { 5, 118, 111, 114, 98, 105, 115 };

		private float[] _prevBuffer;

		private RingBuffer _outputBuffer;

		private Queue<int> _bitsPerPacketHistory;

		private Queue<int> _sampleCountHistory;

		private int _preparedLength;

		internal bool _clipped;

		private Stack<DataPacket> _resyncQueue;

		private long _currentPosition;

		private long _reportedPosition;

		private VorbisMode _mode;

		private bool _prevFlag;

		private bool _nextFlag;

		private bool[] _noExecuteChannel;

		private VorbisFloor.PacketData[] _floorData;

		private float[][] _residue;

		private bool _isParameterChange;

		internal bool IsParameterChange
		{
			get
			{
				return _isParameterChange;
			}
			set
			{
				if (value)
				{
					throw new InvalidOperationException("Only clearing is supported!");
				}
				_isParameterChange = value;
			}
		}

		internal bool CanSeek => _packetProvider.CanSeek;

		internal long CurrentPosition
		{
			get
			{
				return _reportedPosition;
			}
			private set
			{
				_reportedPosition = value;
				_currentPosition = value;
				_preparedLength = 0;
				_eosFound = false;
				ResetDecoder(isFullReset: false);
				_prevBuffer = null;
			}
		}

		internal long ContainerBits => _packetProvider.ContainerBits;

		public int EffectiveBitRate
		{
			get
			{
				if (_samples == 0L)
				{
					return 0;
				}
				double num = (double)(_currentPosition - _preparedLength) / (double)_sampleRate;
				return (int)((double)AudioBits / num);
			}
		}

		public int InstantBitRate
		{
			get
			{
				int num = _sampleCountHistory.Sum();
				if (num > 0)
				{
					return (int)((long)_bitsPerPacketHistory.Sum() * (long)_sampleRate / num);
				}
				return -1;
			}
		}

		public TimeSpan PageLatency => TimeSpan.FromTicks(_sw.ElapsedTicks / PagesRead);

		public TimeSpan PacketLatency => TimeSpan.FromTicks(_sw.ElapsedTicks / _packetCount);

		public TimeSpan SecondLatency => TimeSpan.FromTicks(_sw.ElapsedTicks / _samples * _sampleRate);

		public long OverheadBits => _glueBits + _metaBits + _timeHdrBits + _wasteHdrBits + _wasteBits + _packetProvider.ContainerBits;

		public long AudioBits => _bookBits + _floorHdrBits + _resHdrBits + _mapHdrBits + _modeHdrBits + _modeBits + _floorBits + _resBits;

		public int PagesRead => _pagesSeen.IndexOf(_lastPageSeen) + 1;

		public int TotalPages => _packetProvider.GetTotalPageCount();

		public bool Clipped => _clipped;

		internal VorbisStreamDecoder(IPacketProvider packetProvider)
		{
			_packetProvider = packetProvider;
			_packetProvider.ParameterChange += SetParametersChanging;
			_pagesSeen = new List<int>();
			_lastPageSeen = -1;
		}

		internal bool TryInit()
		{
			if (!ProcessStreamHeader(_packetProvider.PeekNextPacket()))
			{
				return false;
			}
			_packetProvider.GetNextPacket().Done();
			DataPacket nextPacket = _packetProvider.GetNextPacket();
			if (!LoadComments(nextPacket))
			{
				throw new InvalidDataException("Comment header was not readable!");
			}
			nextPacket.Done();
			nextPacket = _packetProvider.GetNextPacket();
			if (!LoadBooks(nextPacket))
			{
				throw new InvalidDataException("Book header was not readable!");
			}
			nextPacket.Done();
			InitDecoder();
			return true;
		}

		private void SetParametersChanging(object sender, ParameterChangeEventArgs e)
		{
			_parameterChangePacket = e.FirstPacket;
		}

		public void Dispose()
		{
			if (_packetProvider != null)
			{
				IPacketProvider packetProvider = _packetProvider;
				_packetProvider = null;
				packetProvider.ParameterChange -= SetParametersChanging;
				packetProvider.Dispose();
			}
		}

		private void ProcessParameterChange(DataPacket packet)
		{
			_parameterChangePacket = null;
			bool flag = false;
			bool isFullReset = false;
			if (ProcessStreamHeader(packet))
			{
				packet.Done();
				flag = true;
				isFullReset = true;
				packet = _packetProvider.PeekNextPacket();
				if (packet == null)
				{
					throw new InvalidDataException("Couldn't get next packet!");
				}
			}
			if (LoadComments(packet))
			{
				if (flag)
				{
					_packetProvider.GetNextPacket().Done();
				}
				else
				{
					packet.Done();
				}
				flag = true;
				packet = _packetProvider.PeekNextPacket();
				if (packet == null)
				{
					throw new InvalidDataException("Couldn't get next packet!");
				}
			}
			if (LoadBooks(packet))
			{
				if (flag)
				{
					_packetProvider.GetNextPacket().Done();
				}
				else
				{
					packet.Done();
				}
			}
			ResetDecoder(isFullReset);
		}

		private static bool ValidateHeader(DataPacket packet, byte[] expected)
		{
			for (int i = 0; i < expected.Length; i++)
			{
				if (expected[i] != packet.ReadByte())
				{
					return false;
				}
			}
			return true;
		}

		private bool ProcessStreamHeader(DataPacket packet)
		{
			if (!ValidateHeader(packet, PacketSignatureStream))
			{
				_glueBits += packet.Length * 8;
				return false;
			}
			if (!_pagesSeen.Contains(_lastPageSeen = packet.PageSequenceNumber))
			{
				_pagesSeen.Add(_lastPageSeen);
			}
			_glueBits += 56L;
			long bitsRead = packet.BitsRead;
			if (packet.ReadInt32() != 0)
			{
				throw new InvalidDataException("Only Vorbis stream version 0 is supported.");
			}
			_channels = packet.ReadByte();
			_sampleRate = packet.ReadInt32();
			_upperBitrate = packet.ReadInt32();
			_nominalBitrate = packet.ReadInt32();
			_lowerBitrate = packet.ReadInt32();
			Block0Size = 1 << (int)packet.ReadBits(4);
			Block1Size = 1 << (int)packet.ReadBits(4);
			if (_nominalBitrate == 0 && _upperBitrate > 0 && _lowerBitrate > 0)
			{
				_nominalBitrate = (_upperBitrate + _lowerBitrate) / 2;
			}
			_metaBits += packet.BitsRead - bitsRead + 8;
			_wasteHdrBits += 8 * packet.Length - packet.BitsRead;
			return true;
		}

		private bool LoadComments(DataPacket packet)
		{
			if (!ValidateHeader(packet, PacketSignatureComments))
			{
				_glueBits += packet.Length * 8;
				return false;
			}
			if (!_pagesSeen.Contains(_lastPageSeen = packet.PageSequenceNumber))
			{
				_pagesSeen.Add(_lastPageSeen);
			}
			_glueBits += 56L;
			_vendor = Encoding.UTF8.GetString(packet.ReadBytes(packet.ReadInt32()));
			_comments = new string[packet.ReadInt32()];
			for (int i = 0; i < _comments.Length; i++)
			{
				_comments[i] = Encoding.UTF8.GetString(packet.ReadBytes(packet.ReadInt32()));
			}
			_metaBits += packet.BitsRead - 56;
			_wasteHdrBits += 8 * packet.Length - packet.BitsRead;
			return true;
		}

		private bool LoadBooks(DataPacket packet)
		{
			if (!ValidateHeader(packet, PacketSignatureBooks))
			{
				_glueBits += packet.Length * 8;
				return false;
			}
			if (!_pagesSeen.Contains(_lastPageSeen = packet.PageSequenceNumber))
			{
				_pagesSeen.Add(_lastPageSeen);
			}
			long bitsRead = packet.BitsRead;
			_glueBits += packet.BitsRead;
			Books = new VorbisCodebook[packet.ReadByte() + 1];
			for (int i = 0; i < Books.Length; i++)
			{
				Books[i] = VorbisCodebook.Init(this, packet, i);
			}
			_bookBits += packet.BitsRead - bitsRead;
			bitsRead = packet.BitsRead;
			Times = new VorbisTime[(int)packet.ReadBits(6) + 1];
			for (int j = 0; j < Times.Length; j++)
			{
				Times[j] = VorbisTime.Init(this, packet);
			}
			_timeHdrBits += packet.BitsRead - bitsRead;
			bitsRead = packet.BitsRead;
			Floors = new VorbisFloor[(int)packet.ReadBits(6) + 1];
			for (int k = 0; k < Floors.Length; k++)
			{
				Floors[k] = VorbisFloor.Init(this, packet);
			}
			_floorHdrBits += packet.BitsRead - bitsRead;
			bitsRead = packet.BitsRead;
			Residues = new VorbisResidue[(int)packet.ReadBits(6) + 1];
			for (int l = 0; l < Residues.Length; l++)
			{
				Residues[l] = VorbisResidue.Init(this, packet);
			}
			_resHdrBits += packet.BitsRead - bitsRead;
			bitsRead = packet.BitsRead;
			Maps = new VorbisMapping[(int)packet.ReadBits(6) + 1];
			for (int m = 0; m < Maps.Length; m++)
			{
				Maps[m] = VorbisMapping.Init(this, packet);
			}
			_mapHdrBits += packet.BitsRead - bitsRead;
			bitsRead = packet.BitsRead;
			Modes = new VorbisMode[(int)packet.ReadBits(6) + 1];
			for (int n = 0; n < Modes.Length; n++)
			{
				Modes[n] = VorbisMode.Init(this, packet);
			}
			_modeHdrBits += packet.BitsRead - bitsRead;
			if (!packet.ReadBit())
			{
				throw new InvalidDataException();
			}
			_glueBits++;
			_wasteHdrBits += 8 * packet.Length - packet.BitsRead;
			_modeFieldBits = Utils.ilog(Modes.Length - 1);
			return true;
		}

		private void InitDecoder()
		{
			_currentPosition = 0L;
			_resyncQueue = new Stack<DataPacket>();
			_bitsPerPacketHistory = new Queue<int>();
			_sampleCountHistory = new Queue<int>();
			ResetDecoder(isFullReset: true);
		}

		private void ResetDecoder(bool isFullReset)
		{
			if (_preparedLength > 0)
			{
				SaveBuffer();
			}
			if (isFullReset)
			{
				_noExecuteChannel = new bool[_channels];
				_floorData = new VorbisFloor.PacketData[_channels];
				_residue = new float[_channels][];
				for (int i = 0; i < _channels; i++)
				{
					_residue[i] = new float[Block1Size];
				}
				_outputBuffer = new RingBuffer(Block1Size * 2 * _channels);
				_outputBuffer.Channels = _channels;
			}
			else
			{
				_outputBuffer.Clear();
			}
			_preparedLength = 0;
		}

		private void SaveBuffer()
		{
			float[] array = new float[_preparedLength * _channels];
			ReadSamples(array, 0, array.Length);
			_prevBuffer = array;
		}

		private bool UnpackPacket(DataPacket packet)
		{
			if (packet.ReadBit())
			{
				return false;
			}
			int num = _modeFieldBits;
			_mode = Modes[(uint)packet.ReadBits(_modeFieldBits)];
			if (_mode.BlockFlag)
			{
				_prevFlag = packet.ReadBit();
				_nextFlag = packet.ReadBit();
				num += 2;
			}
			else
			{
				_prevFlag = (_nextFlag = false);
			}
			if (packet.IsShort)
			{
				return false;
			}
			long bitsRead = packet.BitsRead;
			int num2 = _mode.BlockSize / 2;
			for (int i = 0; i < _channels; i++)
			{
				_floorData[i] = _mode.Mapping.ChannelSubmap[i].Floor.UnpackPacket(packet, _mode.BlockSize, i);
				_noExecuteChannel[i] = !_floorData[i].ExecuteChannel;
				Array.Clear(_residue[i], 0, num2);
			}
			VorbisMapping.CouplingStep[] couplingSteps = _mode.Mapping.CouplingSteps;
			foreach (VorbisMapping.CouplingStep couplingStep in couplingSteps)
			{
				if (_floorData[couplingStep.Angle].ExecuteChannel || _floorData[couplingStep.Magnitude].ExecuteChannel)
				{
					_floorData[couplingStep.Angle].ForceEnergy = true;
					_floorData[couplingStep.Magnitude].ForceEnergy = true;
				}
			}
			long num3 = packet.BitsRead - bitsRead;
			bitsRead = packet.BitsRead;
			VorbisMapping.Submap[] submaps = _mode.Mapping.Submaps;
			foreach (VorbisMapping.Submap submap in submaps)
			{
				for (int k = 0; k < _channels; k++)
				{
					if (_mode.Mapping.ChannelSubmap[k] != submap)
					{
						_floorData[k].ForceNoEnergy = true;
					}
				}
				float[][] array = submap.Residue.Decode(packet, _noExecuteChannel, _channels, _mode.BlockSize);
				for (int l = 0; l < _channels; l++)
				{
					float[] array2 = _residue[l];
					float[] array3 = array[l];
					for (int m = 0; m < num2; m++)
					{
						array2[m] += array3[m];
					}
				}
			}
			_glueBits++;
			_modeBits += num;
			_floorBits += num3;
			_resBits += packet.BitsRead - bitsRead;
			_wasteBits += 8 * packet.Length - packet.BitsRead;
			_packetCount++;
			return true;
		}

		private void DecodePacket()
		{
			VorbisMapping.CouplingStep[] couplingSteps = _mode.Mapping.CouplingSteps;
			int num = _mode.BlockSize / 2;
			for (int num2 = couplingSteps.Length - 1; num2 >= 0; num2--)
			{
				if (_floorData[couplingSteps[num2].Angle].ExecuteChannel || _floorData[couplingSteps[num2].Magnitude].ExecuteChannel)
				{
					float[] array = _residue[couplingSteps[num2].Magnitude];
					float[] array2 = _residue[couplingSteps[num2].Angle];
					for (int i = 0; i < num; i++)
					{
						float num3;
						float num4;
						if (array[i] > 0f)
						{
							if (array2[i] > 0f)
							{
								num3 = array[i];
								num4 = array[i] - array2[i];
							}
							else
							{
								num4 = array[i];
								num3 = array[i] + array2[i];
							}
						}
						else if (array2[i] > 0f)
						{
							num3 = array[i];
							num4 = array[i] + array2[i];
						}
						else
						{
							num4 = array[i];
							num3 = array[i] - array2[i];
						}
						array[i] = num3;
						array2[i] = num4;
					}
				}
			}
			for (int j = 0; j < _channels; j++)
			{
				VorbisFloor.PacketData packetData = _floorData[j];
				float[] array3 = _residue[j];
				if (packetData.ExecuteChannel)
				{
					_mode.Mapping.ChannelSubmap[j].Floor.Apply(packetData, array3);
					Mdct.Reverse(array3, _mode.BlockSize);
				}
				else
				{
					Array.Clear(array3, num, num);
				}
			}
		}

		private int OverlapSamples()
		{
			float[] window = _mode.GetWindow(_prevFlag, _nextFlag);
			int blockSize = _mode.BlockSize;
			int num = blockSize;
			int num2 = num >> 1;
			int num3 = 0;
			int num4 = -num2;
			int num5 = num2;
			if (_mode.BlockFlag)
			{
				if (!_prevFlag)
				{
					num3 = Block1Size / 4 - Block0Size / 4;
					num2 = num3 + Block0Size / 2;
					num4 = Block0Size / -2 - num3;
				}
				if (!_nextFlag)
				{
					num -= blockSize / 4 - Block0Size / 4;
					num5 = blockSize / 4 + Block0Size / 4;
				}
			}
			int index = _outputBuffer.Length / _channels + num4;
			for (int i = 0; i < _channels; i++)
			{
				_outputBuffer.Write(i, index, num3, num2, num, _residue[i], window);
			}
			int num6 = _outputBuffer.Length / _channels - num5;
			int result = num6 - _preparedLength;
			_preparedLength = num6;
			return result;
		}

		private void UpdatePosition(int samplesDecoded, DataPacket packet)
		{
			_samples += samplesDecoded;
			if (packet.IsResync)
			{
				_currentPosition = -packet.PageGranulePosition;
				_resyncQueue.Push(packet);
			}
			else
			{
				if (samplesDecoded <= 0)
				{
					return;
				}
				_currentPosition += samplesDecoded;
				packet.GranulePosition = _currentPosition;
				if (_currentPosition < 0)
				{
					if (packet.PageGranulePosition > -_currentPosition)
					{
						long num = _currentPosition - samplesDecoded;
						while (_resyncQueue.Count > 0)
						{
							DataPacket dataPacket = _resyncQueue.Pop();
							long num2 = dataPacket.GranulePosition + num;
							dataPacket.GranulePosition = num;
							num = num2;
						}
					}
					else
					{
						packet.GranulePosition = -samplesDecoded;
						_resyncQueue.Push(packet);
					}
				}
				else if (packet.IsEndOfStream && _currentPosition > packet.PageGranulePosition)
				{
					int num3 = (int)(_currentPosition - packet.PageGranulePosition);
					if (num3 >= 0)
					{
						_preparedLength -= num3;
						_currentPosition -= num3;
					}
					else
					{
						_preparedLength = 0;
					}
					packet.GranulePosition = packet.PageGranulePosition;
					_eosFound = true;
				}
			}
		}

		private void DecodeNextPacket()
		{
			_sw.Start();
			DataPacket dataPacket = null;
			try
			{
				IPacketProvider packetProvider = _packetProvider;
				if (packetProvider != null)
				{
					dataPacket = packetProvider.GetNextPacket();
				}
				if (dataPacket == null)
				{
					_eosFound = true;
					return;
				}
				if (!_pagesSeen.Contains(_lastPageSeen = dataPacket.PageSequenceNumber))
				{
					_pagesSeen.Add(_lastPageSeen);
				}
				if (dataPacket.IsResync)
				{
					ResetDecoder(isFullReset: false);
				}
				if (dataPacket == _parameterChangePacket)
				{
					_isParameterChange = true;
					ProcessParameterChange(dataPacket);
					return;
				}
				if (!UnpackPacket(dataPacket))
				{
					dataPacket.Done();
					_wasteBits += 8 * dataPacket.Length;
					return;
				}
				dataPacket.Done();
				DecodePacket();
				int num = OverlapSamples();
				if (!dataPacket.GranuleCount.HasValue)
				{
					dataPacket.GranuleCount = num;
				}
				UpdatePosition(num, dataPacket);
				int num2 = Utils.Sum(_sampleCountHistory) + num;
				_bitsPerPacketHistory.Enqueue((int)dataPacket.BitsRead);
				_sampleCountHistory.Enqueue(num);
				while (num2 > _sampleRate)
				{
					_bitsPerPacketHistory.Dequeue();
					num2 -= _sampleCountHistory.Dequeue();
				}
			}
			catch
			{
				dataPacket?.Done();
				throw;
			}
			finally
			{
				_sw.Stop();
			}
		}

		internal int GetPacketLength(DataPacket curPacket, DataPacket lastPacket)
		{
			if (lastPacket == null || curPacket.IsResync)
			{
				return 0;
			}
			if (curPacket.ReadBit())
			{
				return 0;
			}
			if (lastPacket.ReadBit())
			{
				return 0;
			}
			int num = (int)curPacket.ReadBits(_modeFieldBits);
			if (num < 0 || num >= Modes.Length)
			{
				return 0;
			}
			VorbisMode vorbisMode = Modes[num];
			num = (int)lastPacket.ReadBits(_modeFieldBits);
			if (num < 0 || num >= Modes.Length)
			{
				return 0;
			}
			VorbisMode vorbisMode2 = Modes[num];
			return vorbisMode.BlockSize / 4 + vorbisMode2.BlockSize / 4;
		}

		internal int ReadSamples(float[] buffer, int offset, int count)
		{
			int num = 0;
			lock (_seekLock)
			{
				if (_prevBuffer != null)
				{
					int num2 = Math.Min(count, _prevBuffer.Length);
					Buffer.BlockCopy(_prevBuffer, 0, buffer, offset, num2 * 4);
					if (num2 < _prevBuffer.Length)
					{
						float[] array = new float[_prevBuffer.Length - num2];
						Buffer.BlockCopy(_prevBuffer, num2 * 4, array, 0, (_prevBuffer.Length - num2) * 4);
						_prevBuffer = array;
					}
					else
					{
						_prevBuffer = null;
					}
					count -= num2;
					offset += num2;
					num = num2;
				}
				else if (_isParameterChange)
				{
					throw new InvalidOperationException("Currently pending a parameter change.  Read new parameters before requesting further samples!");
				}
				int size = count + Block1Size * _channels;
				_outputBuffer.EnsureSize(size);
				while (_preparedLength * _channels < count && !_eosFound && !_isParameterChange)
				{
					DecodeNextPacket();
					if (_prevBuffer != null)
					{
						return ReadSamples(buffer, offset, _prevBuffer.Length);
					}
				}
				if (_preparedLength * _channels < count)
				{
					count = _preparedLength * _channels;
				}
				_outputBuffer.CopyTo(buffer, offset, count);
				_preparedLength -= count / _channels;
				_reportedPosition = _currentPosition - _preparedLength;
			}
			return num + count;
		}

		internal void SeekTo(long granulePos)
		{
			if (!_packetProvider.CanSeek)
			{
				throw new NotSupportedException();
			}
			if (granulePos < 0)
			{
				throw new ArgumentOutOfRangeException("granulePos");
			}
			DataPacket dataPacket;
			if (granulePos > 0)
			{
				dataPacket = _packetProvider.FindPacket(granulePos, GetPacketLength);
				if (dataPacket == null)
				{
					throw new ArgumentOutOfRangeException("granulePos");
				}
			}
			else
			{
				dataPacket = _packetProvider.GetPacket(4);
			}
			lock (_seekLock)
			{
				_packetProvider.SeekToPacket(dataPacket, 1);
				DataPacket dataPacket2 = _packetProvider.PeekNextPacket();
				CurrentPosition = dataPacket2.GranulePosition;
				int num = (int)((granulePos - CurrentPosition) * _channels);
				if (num <= 0)
				{
					return;
				}
				float[] buffer = new float[num];
				while (num > 0)
				{
					int num2 = ReadSamples(buffer, 0, num);
					if (num2 == 0)
					{
						break;
					}
					num -= num2;
				}
			}
		}

		internal long GetLastGranulePos()
		{
			return _packetProvider.GetGranuleCount();
		}

		public void ResetStats()
		{
			_clipped = false;
			_packetCount = 0;
			_floorBits = 0L;
			_glueBits = 0L;
			_modeBits = 0L;
			_resBits = 0L;
			_wasteBits = 0L;
			_samples = 0L;
			_sw.Reset();
		}
	}
	internal abstract class VorbisTime
	{
		private class Time0 : VorbisTime
		{
			internal Time0(VorbisStreamDecoder vorbis)
				: base(vorbis)
			{
			}

			protected override void Init(DataPacket packet)
			{
			}
		}

		private VorbisStreamDecoder _vorbis;

		internal static VorbisTime Init(VorbisStreamDecoder vorbis, DataPacket packet)
		{
			int num = (int)packet.ReadBits(16);
			VorbisTime vorbisTime = null;
			if (num == 0)
			{
				vorbisTime = new Time0(vorbis);
			}
			if (vorbisTime == null)
			{
				throw new InvalidDataException();
			}
			vorbisTime.Init(packet);
			return vorbisTime;
		}

		protected VorbisTime(VorbisStreamDecoder vorbis)
		{
			_vorbis = vorbis;
		}

		protected abstract void Init(DataPacket packet);
	}
}
namespace NVorbis.Ogg
{
	public class ContainerReader : IContainerReader, IDisposable
	{
		private class PageHeader
		{
			public int StreamSerial { get; set; }

			public PageFlags Flags { get; set; }

			public long GranulePosition { get; set; }

			public int SequenceNumber { get; set; }

			public long DataOffset { get; set; }

			public int[] PacketSizes { get; set; }

			public bool LastPacketContinues { get; set; }

			public bool IsResync { get; set; }
		}

		private Crc _crc = new Crc();

		private Stream _stream;

		private bool _closeOnDispose;

		private Dictionary<int, PacketReader> _packetReaders;

		private List<int> _disposedStreamSerials;

		private long _nextPageOffset;

		private int _pageCount;

		private byte[] _readBuffer = new byte[65025];

		private long _containerBits;

		private long _wasteBits;

		public int[] StreamSerials => _packetReaders.Keys.ToArray();

		public int PagesRead => _pageCount;

		public bool CanSeek => true;

		public long WasteBits => _wasteBits;

		public event EventHandler<NewStreamEventArgs> NewStream;

		public ContainerReader(string path)
			: this(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), closeOnDispose: true)
		{
		}

		public ContainerReader(Stream stream, bool closeOnDispose)
		{
			_packetReaders = new Dictionary<int, PacketReader>();
			_disposedStreamSerials = new List<int>();
			_stream = stream ?? throw new ArgumentNullException("stream");
			_closeOnDispose = closeOnDispose;
			if (!_stream.CanSeek)
			{
				throw new ArgumentException("The specified stream must be seek-able!", "stream");
			}
		}

		public bool Init()
		{
			return GatherNextPage() != -1;
		}

		public void Dispose()
		{
			int[] streamSerials = StreamSerials;
			foreach (int key in streamSerials)
			{
				_packetReaders[key].Dispose();
			}
			_nextPageOffset = 0L;
			_containerBits = 0L;
			_wasteBits = 0L;
			_stream.Dispose();
		}

		public IPacketProvider GetStream(int streamSerial)
		{
			if (!_packetReaders.TryGetValue(streamSerial, out var value))
			{
				throw new ArgumentOutOfRangeException("streamSerial");
			}
			return value;
		}

		public bool FindNextStream()
		{
			int count = _packetReaders.Count;
			while (_packetReaders.Count == count && GatherNextPage() != -1)
			{
			}
			return count > _packetReaders.Count;
		}

		public int GetTotalPageCount()
		{
			while (GatherNextPage() != -1)
			{
			}
			return _pageCount;
		}

		private PageHeader ReadPageHeader(long position)
		{
			_stream.Seek(position, SeekOrigin.Begin);
			if (_stream.Read(_readBuffer, 0, 27) != 27)
			{
				return null;
			}
			if (_readBuffer[0] != 79 || _readBuffer[1] != 103 || _readBuffer[2] != 103 || _readBuffer[3] != 83)
			{
				return null;
			}
			if (_readBuffer[4] != 0)
			{
				return null;
			}
			PageHeader pageHeader = new PageHeader();
			pageHeader.Flags = (PageFlags)_readBuffer[5];
			pageHeader.GranulePosition = BitConverter.ToInt64(_readBuffer, 6);
			pageHeader.StreamSerial = BitConverter.ToInt32(_readBuffer, 14);
			pageHeader.SequenceNumber = BitConverter.ToInt32(_readBuffer, 18);
			uint checkCrc = BitConverter.ToUInt32(_readBuffer, 22);
			_crc.Reset();
			for (int i = 0; i < 22; i++)
			{
				_crc.Update(_readBuffer[i]);
			}
			_crc.Update(0);
			_crc.Update(0);
			_crc.Update(0);
			_crc.Update(0);
			_crc.Update(_readBuffer[26]);
			int num = _readBuffer[26];
			if (_stream.Read(_readBuffer, 0, num) != num)
			{
				return null;
			}
			List<int> list = new List<int>(num);
			int num2 = 0;
			int num3 = 0;
			for (int j = 0; j < num; j++)
			{
				byte b = _readBuffer[j];
				_crc.Update(b);
				if (num3 == list.Count)
				{
					list.Add(0);
				}
				list[num3] += b;
				if (b < byte.MaxValue)
				{
					num3++;
					pageHeader.LastPacketContinues = false;
				}
				else
				{
					pageHeader.LastPacketContinues = true;
				}
				num2 += b;
			}
			pageHeader.PacketSizes = list.ToArray();
			pageHeader.DataOffset = position + 27 + num;
			if (_stream.Read(_readBuffer, 0, num2) != num2)
			{
				return null;
			}
			for (int k = 0; k < num2; k++)
			{
				_crc.Update(_readBuffer[k]);
			}
			if (_crc.Test(checkCrc))
			{
				_containerBits += 8 * (27 + num);
				_pageCount++;
				return pageHeader;
			}
			return null;
		}

		private PageHeader FindNextPageHeader()
		{
			long num = _nextPageOffset;
			bool isResync = false;
			PageHeader pageHeader;
			while ((pageHeader = ReadPageHeader(num)) == null)
			{
				isResync = true;
				_wasteBits += 8L;
				num = (_stream.Position = num + 1);
				int num3 = 0;
				do
				{
					switch (_stream.ReadByte())
					{
					case 79:
						if (_stream.ReadByte() == 103)
						{
							if (_stream.ReadByte() == 103)
							{
								if (_stream.ReadByte() == 83)
								{
									num += num3;
									goto end_IL_0032;
								}
								_stream.Seek(-1L, SeekOrigin.Current);
							}
							_stream.Seek(-1L, SeekOrigin.Current);
						}
						_stream.Seek(-1L, SeekOrigin.Current);
						break;
					case -1:
						return null;
					}
					_wasteBits += 8L;
					cont

AudioFormats.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using NLayer;
using NVorbis;
using SideLoader;
using SideLoader.SLPacks.Categories;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AudioFormats")]
[assembly: AssemblyDescription("Adds .ogg and .mp3 support to SideLoader's audio loading.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AudioFormats")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c4688ed5-9644-4f6d-a9b6-1cce1f1d9015")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Tchernobill.AudioFormats
{
	public static class AudioFormatsConfig
	{
		public static ConfigEntry<bool> PreferManagedDecoders;

		public static ConfigEntry<bool> VerboseLogging;

		public static void Bind(ConfigFile config)
		{
			PreferManagedDecoders = config.Bind<bool>("Decoding", "PreferManagedDecoders", false, "If active, .ogg and .mp3 files are always decoded by the bundled NVorbis / NLayer decoders instead of Unity's built-in one. Slower and uses more memory, but gives identical results on every machine. Leave this off unless a file that plays fine elsewhere is refused by the game.");
			VerboseLogging = config.Bind<bool>("Debug", "VerboseLogging", false, "If active, log the sample rate, channel count and decoder used for each loaded clip.");
		}
	}
	[BepInPlugin("Tchernobill.AudioFormats", "Audio Formats", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class AudioFormatsPlugin : BaseUnityPlugin
	{
		public const string GUID = "Tchernobill.AudioFormats";

		public const string NAME = "Audio Formats";

		public const string VERSION = "1.0.0";

		public static AudioFormatsPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			AudioFormatsConfig.Bind(((BaseUnityPlugin)this).Config);
			AppDomain.CurrentDomain.AssemblyResolve += ResolveBundledDecoder;
			new Harmony("Tchernobill.AudioFormats").PatchAll();
		}

		private static Assembly ResolveBundledDecoder(object sender, ResolveEventArgs args)
		{
			string name = new AssemblyName(args.Name).Name;
			if (name != "NVorbis" && name != "NLayer")
			{
				return null;
			}
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				string text = Path.Combine(directoryName, name + ".dll");
				if (!File.Exists(text))
				{
					Log.Warning("'" + name + ".dll' is missing from '" + directoryName + "'. Reinstall AudioFormats to get the fallback decoders back.");
					return null;
				}
				return Assembly.LoadFrom(text);
			}
			catch (Exception ex)
			{
				Log.Warning("Could not load '" + name + ".dll': " + ex.Message);
				return null;
			}
		}
	}
	public static class AudioClipLoader
	{
		public static void LoadFromFile(string filePath, SLPack pack = null, Action<AudioClip> onClipLoaded = null)
		{
			if (!File.Exists(filePath))
			{
				Log.Warning("No such audio file: '" + filePath + "'.");
				return;
			}
			AudioFileFormat format = AudioFileFormats.FromExtension(filePath);
			if (!AudioFileFormats.IsAdded(format))
			{
				Log.Warning("'" + Path.GetFileName(filePath) + "' is not an .ogg or .mp3 file.");
				return;
			}
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
			if (AudioFormatsConfig.PreferManagedDecoders.Value)
			{
				Complete(ManagedAudioDecoder.DecodeFile(filePath, format, fileNameWithoutExtension), fileNameWithoutExtension, filePath, pack, onClipLoaded);
				return;
			}
			AudioFormatsPlugin instance = AudioFormatsPlugin.Instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				Complete(ManagedAudioDecoder.DecodeFile(filePath, format, fileNameWithoutExtension), fileNameWithoutExtension, filePath, pack, onClipLoaded);
			}
			else
			{
				((MonoBehaviour)instance).StartCoroutine(LoadWithFallbackCoroutine(filePath, format, fileNameWithoutExtension, pack, onClipLoaded));
			}
		}

		public static AudioClip LoadFromBytes(byte[] data, string clipName, SLPack pack = null)
		{
			AudioFileFormat format = AudioFileFormats.FromHeader(data);
			if (!AudioFileFormats.IsAdded(format))
			{
				Log.Warning("'" + clipName + "' is not ogg or mp3 data.");
				return null;
			}
			AudioClip val = ManagedAudioDecoder.Decode(data, format, clipName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return SideLoaderBridge.FinalizeAudioClip(val, clipName, pack);
		}

		private static IEnumerator LoadWithFallbackCoroutine(string filePath, AudioFileFormat format, string clipName, SLPack pack, Action<AudioClip> onClipLoaded)
		{
			AudioClip clip = null;
			string failure = null;
			yield return UnityAudioDecoder.LoadCoroutine(filePath, format, clipName, delegate(AudioClip result)
			{
				clip = result;
			}, delegate(string error)
			{
				failure = error;
			});
			if (!Object.op_Implicit((Object)(object)clip))
			{
				Log.Message("Unity could not decode '" + Path.GetFileName(filePath) + "' (" + failure + "), retrying with the managed decoder.");
				clip = ManagedAudioDecoder.DecodeFile(filePath, format, clipName);
			}
			Complete(clip, clipName, filePath, pack, onClipLoaded);
		}

		private static void Complete(AudioClip clip, string clipName, string filePath, SLPack pack, Action<AudioClip> onClipLoaded)
		{
			if (!Object.op_Implicit((Object)(object)clip))
			{
				Log.Warning("Could not load audio clip '" + Path.GetFileName(filePath) + "'.");
				return;
			}
			SideLoaderBridge.FinalizeAudioClip(clip, clipName, pack);
			Log.Message("Loaded audio clip: " + Path.GetFileName(filePath));
			onClipLoaded?.Invoke(clip);
		}
	}
	public enum AudioFileFormat
	{
		Unknown,
		Wav,
		Ogg,
		Mp3
	}
	public static class AudioFileFormats
	{
		public static readonly string[] AddedExtensions = new string[2] { ".ogg", ".mp3" };

		public static bool IsAdded(AudioFileFormat format)
		{
			if (format != AudioFileFormat.Ogg)
			{
				return format == AudioFileFormat.Mp3;
			}
			return true;
		}

		public static AudioFileFormat FromExtension(string filePath)
		{
			if (string.IsNullOrEmpty(filePath))
			{
				return AudioFileFormat.Unknown;
			}
			string extension = Path.GetExtension(filePath);
			if (string.Equals(extension, ".ogg", StringComparison.OrdinalIgnoreCase))
			{
				return AudioFileFormat.Ogg;
			}
			if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
			{
				return AudioFileFormat.Mp3;
			}
			if (string.Equals(extension, ".wav", StringComparison.OrdinalIgnoreCase))
			{
				return AudioFileFormat.Wav;
			}
			return AudioFileFormat.Unknown;
		}

		public static AudioFileFormat FromHeader(byte[] data)
		{
			if (data == null || data.Length < 4)
			{
				return AudioFileFormat.Unknown;
			}
			if (data[0] == 79 && data[1] == 103 && data[2] == 103 && data[3] == 83)
			{
				return AudioFileFormat.Ogg;
			}
			if (data[0] == 82 && data[1] == 73 && data[2] == 70 && data[3] == 70)
			{
				return AudioFileFormat.Wav;
			}
			if (data[0] == 73 && data[1] == 68 && data[2] == 51)
			{
				return AudioFileFormat.Mp3;
			}
			if (data[0] == byte.MaxValue && (data[1] & 0xE0) == 224)
			{
				return AudioFileFormat.Mp3;
			}
			return AudioFileFormat.Unknown;
		}

		public static AudioType ToUnityAudioType(AudioFileFormat format)
		{
			return (AudioType)(format switch
			{
				AudioFileFormat.Ogg => 14, 
				AudioFileFormat.Mp3 => 13, 
				AudioFileFormat.Wav => 20, 
				_ => 0, 
			});
		}
	}
	public static class ManagedAudioDecoder
	{
		private const int ReadChunkFloats = 16384;

		private static bool? s_oggAvailable;

		private static bool? s_mp3Available;

		public static bool OggAvailable => (s_oggAvailable ?? (s_oggAvailable = Type.GetType("NVorbis.VorbisReader, NVorbis") != null)).Value;

		public static bool Mp3Available => (s_mp3Available ?? (s_mp3Available = Type.GetType("NLayer.MpegFile, NLayer") != null)).Value;

		public static bool IsAvailable(AudioFileFormat format)
		{
			return format switch
			{
				AudioFileFormat.Ogg => OggAvailable, 
				AudioFileFormat.Mp3 => Mp3Available, 
				_ => false, 
			};
		}

		public static AudioClip DecodeFile(string filePath, AudioFileFormat format, string clipName)
		{
			try
			{
				using FileStream stream = File.OpenRead(filePath);
				return Decode(stream, format, clipName);
			}
			catch (Exception ex)
			{
				Log.Warning("Managed decoding of '" + filePath + "' failed: " + ex.Message);
				return null;
			}
		}

		public static AudioClip Decode(byte[] data, AudioFileFormat format, string clipName)
		{
			try
			{
				using MemoryStream stream = new MemoryStream(data, writable: false);
				return Decode(stream, format, clipName);
			}
			catch (Exception ex)
			{
				Log.Warning("Managed decoding of '" + clipName + "' failed: " + ex.Message);
				return null;
			}
		}

		public static AudioClip Decode(Stream stream, AudioFileFormat format, string clipName)
		{
			if (!IsAvailable(format))
			{
				Log.Warning("Cannot decode '" + clipName + "': the " + ((format == AudioFileFormat.Ogg) ? "NVorbis" : "NLayer") + ".dll shipped with AudioFormats was not found next to the plugin.");
				return null;
			}
			try
			{
				switch (format)
				{
				case AudioFileFormat.Ogg:
					return DecodeOgg(stream, clipName);
				case AudioFileFormat.Mp3:
					return DecodeMp3(stream, clipName);
				default:
					Log.Warning($"Cannot decode '{clipName}': unsupported format '{format}'.");
					return null;
				}
			}
			catch (Exception ex)
			{
				Log.Warning("Managed decoding of '" + clipName + "' failed: " + ex.Message);
				return null;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static AudioClip DecodeOgg(Stream stream, string clipName)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			VorbisReader val = new VorbisReader(stream, false);
			try
			{
				long num = val.TotalSamples * val.Channels;
				bool flag = num > 0 && num < int.MaxValue;
				PcmBuffer pcmBuffer = new PcmBuffer((int)(flag ? num : 16384));
				float[] array = new float[16384];
				int num2;
				while ((num2 = val.ReadSamples(array, 0, array.Length)) > 0)
				{
					if (flag && pcmBuffer.Count + num2 > num)
					{
						num2 = (int)(num - pcmBuffer.Count);
					}
					if (num2 <= 0)
					{
						break;
					}
					pcmBuffer.Append(array, num2);
				}
				return BuildClip(clipName, pcmBuffer, val.Channels, val.SampleRate);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static AudioClip DecodeMp3(Stream stream, string clipName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			MpegFile val = new MpegFile(stream);
			try
			{
				PcmBuffer pcmBuffer = new PcmBuffer(16384);
				float[] array = new float[16384];
				int count;
				while ((count = val.ReadSamples(array, 0, array.Length)) > 0)
				{
					pcmBuffer.Append(array, count);
				}
				return BuildClip(clipName, pcmBuffer, val.Channels, val.SampleRate);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static AudioClip BuildClip(string clipName, PcmBuffer pcm, int channels, int sampleRate)
		{
			if (channels <= 0 || sampleRate <= 0)
			{
				Log.Warning($"Cannot build '{clipName}': invalid channels ({channels}) or sample rate ({sampleRate}).");
				return null;
			}
			float[] array = pcm.ToInterleavedArray(channels);
			int num = array.Length / channels;
			if (num <= 0)
			{
				Log.Warning("Cannot build '" + clipName + "': the file decoded to 0 sample.");
				return null;
			}
			AudioClip val = AudioClip.Create(clipName, num, channels, sampleRate, false);
			val.SetData(array, 0);
			Log.Debug($"Decoded '{clipName}' with the managed decoder: {num} samples, {channels} ch, {sampleRate} Hz.");
			return val;
		}
	}
	internal class PcmBuffer
	{
		private float[] m_data;

		private int m_count;

		public int Count => m_count;

		public PcmBuffer(int initialCapacity)
		{
			m_data = new float[Math.Max(initialCapacity, 4096)];
		}

		public void Append(float[] source, int count)
		{
			EnsureCapacity(m_count + count);
			Buffer.BlockCopy(source, 0, m_data, m_count * 4, count * 4);
			m_count += count;
		}

		public float[] ToInterleavedArray(int channels)
		{
			int num = m_count - m_count % channels;
			if (num == m_data.Length)
			{
				return m_data;
			}
			float[] array = new float[num];
			Buffer.BlockCopy(m_data, 0, array, 0, num * 4);
			return array;
		}

		private void EnsureCapacity(int required)
		{
			if (required > m_data.Length)
			{
				long num;
				for (num = m_data.Length; num < required; num *= 2)
				{
				}
				Array.Resize(ref m_data, (int)Math.Min(num, 2147483647L));
			}
		}
	}
	internal static class SideLoaderBridge
	{
		private static readonly MethodInfo s_finalizeAudioClip = AccessTools.Method(typeof(CustomAudio), "FinalizeAudioClip", new Type[3]
		{
			typeof(AudioClip),
			typeof(string),
			typeof(SLPack)
		}, (Type[])null);

		private static readonly MethodInfo s_packLoadAudioClip = AccessTools.Method(typeof(SLPack), "LoadAudioClip", new Type[3]
		{
			typeof(string),
			typeof(string),
			typeof(Action<AudioClip>)
		}, (Type[])null);

		public static AudioClip FinalizeAudioClip(AudioClip clip, string name, SLPack pack)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if (s_finalizeAudioClip == null)
			{
				Log.Warning("CustomAudio.FinalizeAudioClip was not found - is SideLoader up to date?");
				return clip;
			}
			try
			{
				return (AudioClip)s_finalizeAudioClip.Invoke(null, new object[3] { clip, name, pack });
			}
			catch (Exception ex)
			{
				Log.Warning("Could not finalize clip '" + name + "': " + (ex.InnerException?.Message ?? ex.Message));
				return clip;
			}
		}

		public static void PackLoadAudioClip(SLPack pack, string relativeDirectory, string file, Action<AudioClip> onClipLoaded)
		{
			if (s_packLoadAudioClip == null)
			{
				Log.Warning("SLPack.LoadAudioClip was not found - is SideLoader up to date?");
				return;
			}
			try
			{
				s_packLoadAudioClip.Invoke(pack, new object[3] { relativeDirectory, file, onClipLoaded });
			}
			catch (Exception ex)
			{
				Log.Warning("Could not load '" + file + "' from pack '" + ((pack != null) ? pack.Name : null) + "': " + (ex.InnerException?.Message ?? ex.Message));
			}
		}
	}
	internal static class UnityAudioDecoder
	{
		public static IEnumerator LoadCoroutine(string filePath, AudioFileFormat format, string clipName, Action<AudioClip> onSuccess, Action<string> onFailure)
		{
			string absoluteUri;
			try
			{
				absoluteUri = new Uri(Path.GetFullPath(filePath)).AbsoluteUri;
			}
			catch (Exception ex)
			{
				onFailure("could not build a file:// url (" + ex.Message + ")");
				yield break;
			}
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, AudioFileFormats.ToUnityAudioType(format));
			yield return request.SendWebRequest();
			while (!request.isDone)
			{
				yield return null;
			}
			if (!string.IsNullOrEmpty(request.error))
			{
				onFailure(request.error);
				yield break;
			}
			AudioClip content;
			try
			{
				content = DownloadHandlerAudioClip.GetContent(request);
			}
			catch (Exception ex2)
			{
				onFailure(ex2.Message);
				yield break;
			}
			if (!Object.op_Implicit((Object)(object)content) || (int)content.loadState == 3 || content.samples <= 0)
			{
				onFailure("Unity could not decode the file");
				yield break;
			}
			((Object)content).name = clipName;
			Log.Debug($"Decoded '{clipName}' with Unity's decoder: {content.samples} samples, {content.channels} ch, {content.frequency} Hz.");
			onSuccess(content);
		}
	}
	internal static class Log
	{
		private static ManualLogSource s_source;

		public static void Init(ManualLogSource source)
		{
			s_source = source;
		}

		public static void Message(string message)
		{
			ManualLogSource obj = s_source;
			if (obj != null)
			{
				obj.LogMessage((object)message);
			}
		}

		public static void Warning(string message)
		{
			ManualLogSource obj = s_source;
			if (obj != null)
			{
				obj.LogWarning((object)message);
			}
		}

		public static void Debug(string message)
		{
			if (AudioFormatsConfig.VerboseLogging != null && AudioFormatsConfig.VerboseLogging.Value)
			{
				ManualLogSource obj = s_source;
				if (obj != null)
				{
					obj.LogInfo((object)message);
				}
			}
		}
	}
}
namespace Tchernobill.AudioFormats.Patches
{
	[HarmonyPatch(typeof(AudioClipCategory), "LoadContent")]
	internal static class Patch_AudioClipCategory_LoadContent
	{
		[HarmonyPostfix]
		public static void Postfix(SLPack pack, Dictionary<string, object> __result)
		{
			if (pack == null || __result == null)
			{
				return;
			}
			string pathForCategory = pack.GetPathForCategory<AudioClipCategory>();
			if (!pack.DirectoryExists(pathForCategory))
			{
				return;
			}
			string[] addedExtensions = AudioFileFormats.AddedExtensions;
			foreach (string text in addedExtensions)
			{
				string[] files = pack.GetFiles(pathForCategory, text);
				foreach (string text2 in files)
				{
					string key = text2;
					SideLoaderBridge.PackLoadAudioClip(pack, pathForCategory, Path.GetFileName(text2), delegate(AudioClip clip)
					{
						if (Object.op_Implicit((Object)(object)clip))
						{
							__result[key] = clip;
						}
					});
				}
			}
		}
	}
	[HarmonyPatch(typeof(CustomAudio), "ConvertByteArrayToAudioClip")]
	internal static class Patch_CustomAudio_ConvertByteArrayToAudioClip
	{
		[HarmonyPrefix]
		public static bool Prefix(byte[] sourceData, string name, ref AudioClip __result)
		{
			AudioFileFormat format = AudioFileFormats.FromHeader(sourceData);
			if (!AudioFileFormats.IsAdded(format))
			{
				return true;
			}
			__result = ManagedAudioDecoder.Decode(sourceData, format, name);
			return false;
		}
	}
	[HarmonyPatch(typeof(CustomAudio), "LoadAudioClip", new Type[]
	{
		typeof(byte[]),
		typeof(string),
		typeof(SLPack)
	})]
	internal static class Patch_CustomAudio_LoadAudioClip_Bytes
	{
		[HarmonyPrefix]
		public static bool Prefix(byte[] data, string name, SLPack pack, ref AudioClip __result)
		{
			if (!AudioFileFormats.IsAdded(AudioFileFormats.FromHeader(data)))
			{
				return true;
			}
			__result = AudioClipLoader.LoadFromBytes(data, name, pack);
			return false;
		}
	}
	[HarmonyPatch(typeof(CustomAudio), "LoadAudioClip", new Type[]
	{
		typeof(string),
		typeof(SLPack),
		typeof(Action<AudioClip>)
	})]
	internal static class Patch_CustomAudio_LoadAudioClip_File
	{
		[HarmonyPrefix]
		public static bool Prefix(string filePath, SLPack pack, Action<AudioClip> onClipLoaded)
		{
			if (!AudioFileFormats.IsAdded(AudioFileFormats.FromExtension(filePath)))
			{
				return true;
			}
			AudioClipLoader.LoadFromFile(filePath, pack, onClipLoaded);
			return false;
		}
	}
}