Decompiled source of Weak Kingsley v1.0.1

NVorbis.dll

Decompiled 12 hours ago
using System;
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(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Andrew Ward")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © Andrew Ward 2018")]
[assembly: AssemblyDescription("A fully managed implementation of a Xiph.org Foundation Ogg Vorbis decoder.")]
[assembly: AssemblyFileVersion("0.8.6.0")]
[assembly: AssemblyInformationalVersion("0.8.6.0")]
[assembly: AssemblyProduct("NVorbis")]
[assembly: AssemblyTitle("NVorbis")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: AssemblyVersion("0.8.6.0")]
namespace NVorbis
{
	internal class BufferedReadStream : Stream
	{
		private const int DEFAULT_INITIAL_SIZE = 32768;

		private const int DEFAULT_MAX_SIZE = 262144;

		private Stream _baseStream;

		private StreamReadBuffer _buffer;

		private long _readPosition;

		private object _localLock = new object();

		private Thread _owningThread;

		private int _lockCount;

		public bool CloseBaseStream { get; set; }

		public bool MinimalRead
		{
			get
			{
				return _buffer.MinimalRead;
			}
			set
			{
				_buffer.MinimalRead = value;
			}
		}

		public int MaxBufferSize
		{
			get
			{
				return _buffer.MaxSize;
			}
			set
			{
				CheckLock();
				_buffer.MaxSize = value;
			}
		}

		public long BufferBaseOffset => _buffer.BaseOffset;

		public int BufferBytesFilled => _buffer.BytesFilled;

		public override bool CanRead => true;

		public override bool CanSeek => true;

		public override bool CanWrite => false;

		public override long Length => _baseStream.Length;

		public override long Position
		{
			get
			{
				return _readPosition;
			}
			set
			{
				Seek(value, SeekOrigin.Begin);
			}
		}

		public BufferedReadStream(Stream baseStream)
			: this(baseStream, 32768, 262144, minimalRead: false)
		{
		}

		public BufferedReadStream(Stream baseStream, bool minimalRead)
			: this(baseStream, 32768, 262144, minimalRead)
		{
		}

		public BufferedReadStream(Stream baseStream, int initialSize, int maxSize)
			: this(baseStream, initialSize, maxSize, minimalRead: false)
		{
		}

		public BufferedReadStream(Stream baseStream, int initialSize, int maxBufferSize, bool minimalRead)
		{
			if (baseStream == null)
			{
				throw new ArgumentNullException("baseStream");
			}
			if (!baseStream.CanRead)
			{
				throw new ArgumentException("baseStream");
			}
			if (maxBufferSize < 1)
			{
				maxBufferSize = 1;
			}
			if (initialSize < 1)
			{
				initialSize = 1;
			}
			if (initialSize > maxBufferSize)
			{
				initialSize = maxBufferSize;
			}
			_baseStream = baseStream;
			_buffer = new StreamReadBuffer(baseStream, initialSize, maxBufferSize, minimalRead);
			_buffer.MaxSize = maxBufferSize;
			_buffer.MinimalRead = minimalRead;
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			if (disposing)
			{
				if (_buffer != null)
				{
					_buffer.Dispose();
					_buffer = null;
				}
				if (CloseBaseStream)
				{
					_baseStream.Close();
				}
			}
		}

		public void TakeLock()
		{
			Monitor.Enter(_localLock);
			if (++_lockCount == 1)
			{
				_owningThread = Thread.CurrentThread;
			}
		}

		private void CheckLock()
		{
			if (_owningThread != Thread.CurrentThread)
			{
				throw new SynchronizationLockException();
			}
		}

		public void ReleaseLock()
		{
			CheckLock();
			if (--_lockCount == 0)
			{
				_owningThread = null;
			}
			Monitor.Exit(_localLock);
		}

		public void Discard(int bytes)
		{
			CheckLock();
			_buffer.DiscardThrough(_buffer.BaseOffset + bytes);
		}

		public void DiscardThrough(long offset)
		{
			CheckLock();
			_buffer.DiscardThrough(offset);
		}

		public override void Flush()
		{
		}

		public override int ReadByte()
		{
			CheckLock();
			int num = _buffer.ReadByte(Position);
			if (num > -1)
			{
				Seek(1L, SeekOrigin.Current);
			}
			return num;
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			CheckLock();
			int num = _buffer.Read(Position, buffer, offset, count);
			Seek(num, SeekOrigin.Current);
			return num;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			CheckLock();
			switch (origin)
			{
			case SeekOrigin.Current:
				offset += Position;
				break;
			case SeekOrigin.End:
				offset += _baseStream.Length;
				break;
			}
			if (!_baseStream.CanSeek)
			{
				if (offset < _buffer.BaseOffset)
				{
					throw new InvalidOperationException("Cannot seek to before the start of the buffer!");
				}
				if (offset >= _buffer.BufferEndOffset)
				{
					throw new InvalidOperationException("Cannot seek to beyond the end of the buffer!  Discard some bytes.");
				}
			}
			return _readPosition = offset;
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException();
		}
	}
	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)
		{
			List<byte> list = new List<byte>(count);
			while (list.Count < count)
			{
				list.Add(ReadByte());
			}
			return list.ToArray();
		}

		public int Read(byte[] buffer, int index, int count)
		{
			if (index < 0 || index + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			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(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, SortCallback);
			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;
		}

		private static int SortCallback(HuffmanListNode i1, HuffmanListNode i2)
		{
			int num = i1.Length - i2.Length;
			if (num == 0)
			{
				return i1.Bits - i2.Bits;
			}
			return num;
		}
	}
	internal class HuffmanListNode
	{
		internal int Value;

		internal int Length;

		internal int Bits;

		internal int Mask;

		internal HuffmanListNode Next;
	}
	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 = MathF.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) * MathF.PI / (float)n);
				_A[num2 + 1] = (float)(0.0 - Math.Sin((float)(4 * num) * MathF.PI / (float)n));
				_B[num2] = (float)Math.Cos((float)(num2 + 1) * MathF.PI / (float)n / 2f) * 0.5f;
				_B[num2 + 1] = (float)Math.Sin((float)(num2 + 1) * MathF.PI / (float)n / 2f) * 0.5f;
				num++;
				num2 += 2;
			}
			num = (num2 = 0);
			while (num < _n8)
			{
				_C[num2] = (float)Math.Cos((float)(2 * (num2 + 1)) * MathF.PI / (float)n);
				_C[num2 + 1] = (float)(0.0 - Math.Sin((float)(2 * (num2 + 1)) * MathF.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 class StreamReadBuffer : IDisposable
	{
		private class StreamWrapper
		{
			internal Stream Source;

			internal object LockObject = new object();

			internal long EofOffset = long.MaxValue;

			internal int RefCount = 1;
		}

		private class SavedBuffer
		{
			public byte[] Buffer;

			public long BaseOffset;

			public int End;

			public int DiscardCount;

			public long VersionSaved;
		}

		private static Dictionary<Stream, StreamWrapper> _lockObjects = new Dictionary<Stream, StreamWrapper>();

		private StreamWrapper _wrapper;

		private int _maxSize;

		private byte[] _data;

		private long _baseOffset;

		private int _end;

		private int _discardCount;

		private bool _minimalRead;

		private long _versionCounter;

		private List<SavedBuffer> _savedBuffers;

		public bool MinimalRead
		{
			get
			{
				return _minimalRead;
			}
			set
			{
				_minimalRead = value;
			}
		}

		public int MaxSize
		{
			get
			{
				return _maxSize;
			}
			set
			{
				if (value < 1)
				{
					throw new ArgumentOutOfRangeException("Must be greater than zero.");
				}
				int num = 1 << (int)Math.Ceiling(Math.Log(value, 2.0));
				if (num < _end)
				{
					if (num < _end - _discardCount)
					{
						throw new ArgumentOutOfRangeException("Must be greater than or equal to the number of bytes currently buffered.");
					}
					CommitDiscard();
					byte[] array = new byte[num];
					Buffer.BlockCopy(_data, 0, array, 0, _end);
					_data = array;
				}
				_maxSize = num;
			}
		}

		public long BaseOffset => _baseOffset + _discardCount;

		public int BytesFilled => _end - _discardCount;

		public int Length => _data.Length;

		internal long BufferEndOffset
		{
			get
			{
				if (_end - _discardCount > 0)
				{
					return _baseOffset + _discardCount + _maxSize;
				}
				return _wrapper.Source.Length;
			}
		}

		internal StreamReadBuffer(Stream source, int initialSize, int maxSize, bool minimalRead)
		{
			StreamWrapper value;
			lock (_lockObjects)
			{
				if (!_lockObjects.TryGetValue(source, out value))
				{
					_lockObjects.Add(source, new StreamWrapper
					{
						Source = source
					});
					value = _lockObjects[source];
					if (source.CanSeek)
					{
						value.EofOffset = source.Length;
					}
				}
				else
				{
					value.RefCount++;
				}
			}
			initialSize = 2 << (int)Math.Log(initialSize - 1, 2.0);
			maxSize = 1 << (int)Math.Log(maxSize, 2.0);
			_wrapper = value;
			_data = new byte[initialSize];
			_maxSize = maxSize;
			_minimalRead = minimalRead;
			_savedBuffers = new List<SavedBuffer>();
		}

		public void Dispose()
		{
			lock (_lockObjects)
			{
				if (--_wrapper.RefCount == 0)
				{
					_lockObjects.Remove(_wrapper.Source);
				}
			}
		}

		public int Read(long offset, byte[] buffer, int index, int count)
		{
			if (offset < 0)
			{
				throw new ArgumentOutOfRangeException("offset");
			}
			if (buffer == null)
			{
				throw new ArgumentNullException("buffer");
			}
			if (index < 0 || index + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			if (count < 0)
			{
				throw new ArgumentOutOfRangeException("count");
			}
			if (offset >= _wrapper.EofOffset)
			{
				return 0;
			}
			int srcOffset = EnsureAvailable(offset, ref count, isRecursion: false);
			Buffer.BlockCopy(_data, srcOffset, buffer, index, count);
			return count;
		}

		internal int ReadByte(long offset)
		{
			if (offset < 0)
			{
				throw new ArgumentOutOfRangeException("offset");
			}
			if (offset >= _wrapper.EofOffset)
			{
				return -1;
			}
			int count = 1;
			int num = EnsureAvailable(offset, ref count, isRecursion: false);
			if (count == 1)
			{
				return _data[num];
			}
			return -1;
		}

		private int EnsureAvailable(long offset, ref int count, bool isRecursion)
		{
			if (offset >= _baseOffset && offset + count < _baseOffset + _end)
			{
				return (int)(offset - _baseOffset);
			}
			if (count > _maxSize)
			{
				throw new InvalidOperationException("Not enough room in the buffer!  Increase the maximum size and try again.");
			}
			_versionCounter++;
			if (!isRecursion)
			{
				for (int i = 0; i < _savedBuffers.Count; i++)
				{
					long num = _savedBuffers[i].BaseOffset - offset;
					if ((num < 0 && _savedBuffers[i].End + num > 0) || (num > 0 && count - num > 0))
					{
						SwapBuffers(_savedBuffers[i]);
						return EnsureAvailable(offset, ref count, isRecursion: true);
					}
				}
			}
			while (_savedBuffers.Count > 0 && _savedBuffers[0].VersionSaved + 25 < _versionCounter)
			{
				_savedBuffers[0].Buffer = null;
				_savedBuffers.RemoveAt(0);
			}
			if (offset < _baseOffset && !_wrapper.Source.CanSeek)
			{
				throw new InvalidOperationException("Cannot seek before buffer on forward-only streams!");
			}
			CalcBuffer(offset, count, out var readStart, out var readEnd);
			count = FillBuffer(offset, count, readStart, readEnd);
			return (int)(offset - _baseOffset);
		}

		private void SaveBuffer()
		{
			_savedBuffers.Add(new SavedBuffer
			{
				Buffer = _data,
				BaseOffset = _baseOffset,
				End = _end,
				DiscardCount = _discardCount,
				VersionSaved = _versionCounter
			});
			_data = null;
			_end = 0;
			_discardCount = 0;
		}

		private void CreateNewBuffer(long offset, int count)
		{
			SaveBuffer();
			_data = new byte[Math.Min(2 << (int)Math.Log(count - 1, 2.0), _maxSize)];
			_baseOffset = offset;
		}

		private void SwapBuffers(SavedBuffer savedBuffer)
		{
			_savedBuffers.Remove(savedBuffer);
			SaveBuffer();
			_data = savedBuffer.Buffer;
			_baseOffset = savedBuffer.BaseOffset;
			_end = savedBuffer.End;
			_discardCount = savedBuffer.DiscardCount;
		}

		private void CalcBuffer(long offset, int count, out int readStart, out int readEnd)
		{
			readStart = 0;
			readEnd = 0;
			if (offset < _baseOffset)
			{
				if (offset + _maxSize <= _baseOffset)
				{
					if (_baseOffset - (offset + _maxSize) > _maxSize)
					{
						CreateNewBuffer(offset, count);
					}
					else
					{
						EnsureBufferSize(count, copyContents: false, 0);
					}
					_baseOffset = offset;
					readEnd = count;
				}
				else
				{
					readEnd = (int)(offset - _baseOffset);
					EnsureBufferSize(Math.Min((int)(offset + _maxSize - _baseOffset), _end) - readEnd, copyContents: true, readEnd);
					readEnd = (int)(offset - _baseOffset) - readEnd;
				}
			}
			else if (offset >= _baseOffset + _maxSize)
			{
				if (offset - (_baseOffset + _maxSize) > _maxSize)
				{
					CreateNewBuffer(offset, count);
				}
				else
				{
					EnsureBufferSize(count, copyContents: false, 0);
				}
				_baseOffset = offset;
				readEnd = count;
			}
			else
			{
				readEnd = (int)(offset + count - _baseOffset);
				int num = Math.Max(readEnd - _maxSize, 0);
				EnsureBufferSize(readEnd - num, copyContents: true, num);
				readStart = _end;
				readEnd = (int)(offset + count - _baseOffset);
			}
		}

		private void EnsureBufferSize(int reqSize, bool copyContents, int copyOffset)
		{
			byte[] array = _data;
			if (reqSize > _data.Length)
			{
				if (reqSize > _maxSize)
				{
					if (!_wrapper.Source.CanSeek && reqSize - _discardCount > _maxSize)
					{
						throw new InvalidOperationException("Not enough room in the buffer!  Increase the maximum size and try again.");
					}
					int num = reqSize - _maxSize;
					copyOffset += num;
					reqSize = _maxSize;
				}
				else
				{
					int num2;
					for (num2 = _data.Length; num2 < reqSize; num2 *= 2)
					{
					}
					reqSize = num2;
				}
				if (reqSize > _data.Length)
				{
					array = new byte[reqSize];
				}
			}
			if (copyContents)
			{
				if ((copyOffset > 0 && copyOffset < _end) || (copyOffset == 0 && array != _data))
				{
					Buffer.BlockCopy(_data, copyOffset, array, 0, _end - copyOffset);
					if ((_discardCount -= copyOffset) < 0)
					{
						_discardCount = 0;
					}
				}
				else if (copyOffset < 0 && -copyOffset < _end)
				{
					if (array != _data || _end <= -copyOffset)
					{
						Buffer.BlockCopy(_data, 0, array, -copyOffset, Math.Max(_end, Math.Min(_end, _data.Length + copyOffset)));
					}
					else
					{
						_end = copyOffset;
					}
					_discardCount = 0;
				}
				else
				{
					_end = copyOffset;
					_discardCount = 0;
				}
				_baseOffset += copyOffset;
				_end -= copyOffset;
				if (_end > array.Length)
				{
					_end = array.Length;
				}
			}
			else
			{
				_discardCount = 0;
				_end = 0;
			}
			_data = array;
		}

		private int FillBuffer(long offset, int count, int readStart, int readEnd)
		{
			long readOffset = _baseOffset + readStart;
			int readCount = readEnd - readStart;
			lock (_wrapper.LockObject)
			{
				readCount = PrepareStreamForRead(readCount, readOffset);
				ReadStream(readStart, readCount, readOffset);
				if (_end < readStart + readCount)
				{
					count = Math.Max(0, (int)(_baseOffset + _end - offset));
				}
				else if (!_minimalRead && _end < _data.Length)
				{
					readCount = _data.Length - _end;
					readCount = PrepareStreamForRead(readCount, _baseOffset + _end);
					_end += _wrapper.Source.Read(_data, _end, readCount);
				}
			}
			return count;
		}

		private int PrepareStreamForRead(int readCount, long readOffset)
		{
			if (readCount > 0 && _wrapper.Source.Position != readOffset)
			{
				if (readOffset < _wrapper.EofOffset)
				{
					if (_wrapper.Source.CanSeek)
					{
						_wrapper.Source.Position = readOffset;
					}
					else
					{
						long num = readOffset - _wrapper.Source.Position;
						if (num < 0)
						{
							readCount = 0;
						}
						else
						{
							while (--num >= 0)
							{
								if (_wrapper.Source.ReadByte() == -1)
								{
									_wrapper.EofOffset = _wrapper.Source.Position;
									readCount = 0;
									break;
								}
							}
						}
					}
				}
				else
				{
					readCount = 0;
				}
			}
			return readCount;
		}

		private void ReadStream(int readStart, int readCount, long readOffset)
		{
			while (readCount > 0 && readOffset < _wrapper.EofOffset)
			{
				int num = _wrapper.Source.Read(_data, readStart, readCount);
				if (num == 0)
				{
					break;
				}
				readStart += num;
				readOffset += num;
				readCount -= num;
			}
			if (readStart > _end)
			{
				_end = readStart;
			}
		}

		public void DiscardThrough(long offset)
		{
			int val = (int)(offset - _baseOffset);
			_discardCount = Math.Max(val, _discardCount);
			if (_discardCount >= _data.Length)
			{
				CommitDiscard();
			}
		}

		private void CommitDiscard()
		{
			if (_discardCount >= _data.Length || _discardCount >= _end)
			{
				_baseOffset += _discardCount;
				_end = 0;
			}
			else
			{
				Buffer.BlockCopy(_data, _discardCount, _data, 0, _end - _discardCount);
				_baseOffset += _discardCount;
				_end -= _discardCount;
			}
			_discardCount = 0;
		}
	}
	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
	{
		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)
		{
			VorbisCodebook vorbisCodebook = new VorbisCodebook();
			vorbisCodebook.BookNum = number;
			vorbisCodebook.Init(packet);
			return vorbisCodebook;
		}

		private VorbisCodebook()
		{
		}

		internal void Init(DataPacket packet)
		{
			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();
				}
				PrefixList = Huffman.BuildPrefixedLinkedList(array2 ?? Enumerable.Range(0, array3.Length).ToArray(), 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 = MathF.PI;

		private const float M_PI2 = MathF.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 * (MathF.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 * (MathF.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()
		{
			BufferedReadStream bufferedReadStream = new BufferedReadStream(stream)
			{
				CloseBaseStream = closeStreamOnDispose
			};
			ContainerReader containerReader = new ContainerReader(bufferedReadStream, closeStreamOnDispose);
			if (!LoadContainer(containerReader))
			{
				bufferedReadStream.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 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 bool ProcessStreamHeader(DataPacket packet)
		{
			if (!packet.ReadBytes(7).SequenceEqual(new byte[7] { 1, 118, 111, 114, 98, 105, 115 }))
			{
				_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 (!packet.ReadBytes(7).SequenceEqual(new byte[7] { 3, 118, 111, 114, 98, 105, 115 }))
			{
				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 (!packet.ReadBytes(7).SequenceEqual(new byte[7] { 5, 118, 111, 114, 98, 105, 115 }))
			{
				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[] array

WeakKingsley.dll

Decompiled 12 hours ago
using System;
using System.Collections;
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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.AI.Walker;
using EntityStates.Commando;
using EntityStates.Commando.CommandoWeapon;
using EntityStates.TitanMonster;
using HG;
using HG.BlendableTypes;
using HenryMod.Modules;
using HenryMod.Modules.Achievements;
using HenryMod.Modules.BaseStates;
using HenryMod.Modules.Characters;
using HenryMod.Radioport;
using HenryMod.Survivors.Henry;
using HenryMod.Survivors.Henry.Components;
using HenryMod.Survivors.Henry.SkillStates;
using NVorbis;
using On.EntityStates.TitanMonster;
using On.RoR2;
using On.RoR2.CharacterAI;
using R2API;
using R2API.Utils;
using Rewired;
using RoR2;
using RoR2.Achievements;
using RoR2.Audio;
using RoR2.CharacterAI;
using RoR2.ConVar;
using RoR2.ContentManagement;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HenryMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9ed4904769a158cdcd4285d4bb7955c441e46c94")]
[assembly: AssemblyProduct("HenryMod")]
[assembly: AssemblyTitle("HenryMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace HenryMod
{
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.weakkingsley.king", "WeakKingsley", "1.0.1")]
	public class HenryPlugin : BaseUnityPlugin
	{
		public const string MODUID = "com.weakkingsley.king";

		public const string MODNAME = "WeakKingsley";

		public const string MODVERSION = "1.0.1";

		public const string DEVELOPER_PREFIX = "WEAKKINGSLEY";

		public static HenryPlugin instance;

		private void Awake()
		{
			instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			Language.Init();
			Stopwatch stopwatch = Stopwatch.StartNew();
			new HenrySurvivor().Initialize();
			Log.Info("[King] startup survivor total: " + stopwatch.ElapsedMilliseconds + " ms");
			new ContentPacks().Initialize();
			Log.Info("[King] startup plugin total: " + stopwatch.ElapsedMilliseconds + " ms");
		}
	}
	internal static class Log
	{
		internal static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void ErrorAssetBundle(string assetName, string bundleName)
		{
			Error("failed to load asset, " + assetName + ", because it does not exist in asset bundle, " + bundleName);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
}
namespace HenryMod.Radioport
{
	public interface IRadioDecoder : IDisposable
	{
		int Channels { get; }

		int SampleRate { get; }

		double Length { get; }

		double Position { get; }

		int Read(float[] interleaved, int frames);

		void Seek(double seconds);
	}
	public static class RadioDecoders
	{
		public static IRadioDecoder Open(string path)
		{
			string text = Path.GetExtension(path).ToLowerInvariant();
			if (text == ".wav")
			{
				return new WavDecoder(path);
			}
			if (text == ".ogg")
			{
				return new OggDecoder(path);
			}
			throw new NotSupportedException("unsupported file type " + text);
		}
	}
	public class WavDecoder : IRadioDecoder, IDisposable
	{
		private readonly FileStream fs;

		private readonly int ch;

		private readonly int rate;

		private readonly int bits;

		private readonly bool isFloat;

		private readonly long dataStart;

		private readonly long totalFrames;

		private long frame;

		private byte[] tmp = new byte[0];

		public int Channels => ch;

		public int SampleRate => rate;

		public double Length => (double)totalFrames / (double)rate;

		public double Position => (double)frame / (double)rate;

		public WavDecoder(string path)
		{
			fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 65536);
			try
			{
				BinaryReader binaryReader = new BinaryReader(fs);
				if (new string(binaryReader.ReadChars(4)) != "RIFF")
				{
					throw new InvalidDataException("not RIFF");
				}
				binaryReader.ReadInt32();
				if (new string(binaryReader.ReadChars(4)) != "WAVE")
				{
					throw new InvalidDataException("not WAVE");
				}
				int num = 0;
				long num2 = -1L;
				while (fs.Position + 8 <= fs.Length)
				{
					string text = new string(binaryReader.ReadChars(4));
					uint num3 = binaryReader.ReadUInt32();
					long position = fs.Position + num3 + (num3 & 1);
					if (text == "fmt ")
					{
						num = binaryReader.ReadUInt16();
						ch = binaryReader.ReadUInt16();
						rate = binaryReader.ReadInt32();
						binaryReader.ReadInt32();
						binaryReader.ReadUInt16();
						bits = binaryReader.ReadUInt16();
						if (num == 65534 && num3 >= 26)
						{
							binaryReader.ReadUInt16();
							binaryReader.ReadUInt16();
							binaryReader.ReadUInt32();
							num = binaryReader.ReadUInt16();
						}
					}
					else if (text == "data")
					{
						dataStart = fs.Position;
						num2 = Math.Min(num3, fs.Length - fs.Position);
						break;
					}
					fs.Position = position;
				}
				if (num2 < 0)
				{
					throw new InvalidDataException("no data chunk");
				}
				if (ch < 1 || ch > 8 || rate < 8000 || rate > 384000)
				{
					throw new InvalidDataException("bad format " + ch + "ch " + rate + "Hz");
				}
				isFloat = num == 3;
				if ((num != 1 || (bits != 8 && bits != 16 && bits != 24 && bits != 32)) && (!isFloat || bits != 32))
				{
					throw new InvalidDataException("unsupported encoding (tag " + num + ", " + bits + " bit)");
				}
				totalFrames = num2 / (ch * bits / 8);
				if (totalFrames <= 0)
				{
					throw new InvalidDataException("no audio");
				}
				fs.Position = dataStart;
			}
			catch
			{
				fs.Dispose();
				throw;
			}
		}

		public int Read(float[] buf, int frames)
		{
			int num = (int)Math.Min(frames, totalFrames - frame);
			if (num <= 0)
			{
				return 0;
			}
			int num2 = ch * bits / 8;
			int num3 = num * num2;
			if (tmp.Length < num3)
			{
				tmp = new byte[num3];
			}
			int i;
			int num4;
			for (i = 0; i < num3; i += num4)
			{
				num4 = fs.Read(tmp, i, num3 - i);
				if (num4 <= 0)
				{
					break;
				}
			}
			num = i / num2;
			int num5 = num * ch;
			for (int j = 0; j < num5; j++)
			{
				int num6 = j * bits / 8;
				float num7 = ((!isFloat) ? ((bits != 16) ? ((bits != 24) ? ((bits != 32) ? ((float)(tmp[num6] - 128) / 128f) : ((float)BitConverter.ToInt32(tmp, num6) / 2.1474836E+09f)) : ((float)(((tmp[num6] << 8) | (tmp[num6 + 1] << 16) | (tmp[num6 + 2] << 24)) >> 8) / 8388608f)) : ((float)(short)(tmp[num6] | (tmp[num6 + 1] << 8)) / 32768f)) : BitConverter.ToSingle(tmp, num6));
				buf[j] = (float.IsNaN(num7) ? 0f : num7);
			}
			frame += num;
			return num;
		}

		public void Seek(double seconds)
		{
			frame = Math.Max(0L, Math.Min(totalFrames - 1, (long)(seconds * (double)rate)));
			fs.Position = dataStart + frame * (ch * bits / 8);
		}

		public void Dispose()
		{
			fs.Dispose();
		}
	}
	public class OggDecoder : IRadioDecoder, IDisposable
	{
		private readonly VorbisReader r;

		public int Channels => r.Channels;

		public int SampleRate => r.SampleRate;

		public double Length
		{
			get
			{
				try
				{
					return r.TotalTime.TotalSeconds;
				}
				catch
				{
					return 0.0;
				}
			}
		}

		public double Position
		{
			get
			{
				try
				{
					return r.DecodedTime.TotalSeconds;
				}
				catch
				{
					return 0.0;
				}
			}
		}

		public OggDecoder(string path)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			r = new VorbisReader(path);
			if (r.Channels < 1 || r.SampleRate < 8000)
			{
				r.Dispose();
				throw new InvalidDataException("not a Vorbis stream");
			}
		}

		public int Read(float[] buf, int frames)
		{
			return r.ReadSamples(buf, 0, frames * r.Channels) / r.Channels;
		}

		public void Seek(double seconds)
		{
			r.DecodedTime = TimeSpan.FromSeconds(Math.Max(0.0, Math.Min(Length - 0.05, seconds)));
		}

		public void Dispose()
		{
			r.Dispose();
		}
	}
	public class RadioportAudio
	{
		private class Deck
		{
			public IRadioDecoder dec;

			public RadioTrack track;

			public float gain;

			public float target = 1f;

			public float step;

			public float[] src = new float[0];

			public int srcCount;

			public int srcIdx;

			public double frac;

			public float l0;

			public float r0;

			public float l1;

			public float r1;

			public bool primed;

			public bool ended;
		}

		private struct WaveFormat
		{
			public short wFormatTag;

			public short nChannels;

			public int nSamplesPerSec;

			public int nAvgBytesPerSec;

			public short nBlockAlign;

			public short wBitsPerSample;

			public short cbSize;
		}

		public const int RATE = 48000;

		public const int FRAMES = 1024;

		public const int BUFFERS = 6;

		public float fadeIn = 0.25f;

		public float fadeOut = 0.35f;

		private readonly object gate = new object();

		private Deck current;

		private readonly List<Deck> fading = new List<Deck>();

		private int request;

		private float vol = 0.8f;

		private float volNow = 0.8f;

		private volatile bool running;

		private Thread thread;

		public volatile RadioTrack finished;

		public volatile RadioTrack failed;

		public volatile string failReason;

		public volatile bool loading;

		public double Position;

		public double Length;

		public float Master = 1f;

		public float Peak;

		private const int WAVE_MAPPER = -1;

		private const int WHDR_DONE = 1;

		private static readonly int HDR = ((IntPtr.Size == 8) ? 48 : 32);

		private static readonly int FLAGS = ((IntPtr.Size == 8) ? 24 : 16);

		public RadioTrack Playing
		{
			get
			{
				lock (gate)
				{
					return (current != null) ? current.track : null;
				}
			}
		}

		public float Volume
		{
			get
			{
				return vol;
			}
			set
			{
				vol = Math.Max(0f, Math.Min(1f, value));
			}
		}

		public void Play(RadioTrack t)
		{
			int id;
			lock (gate)
			{
				id = ++request;
				FadeCurrentOut();
				loading = true;
			}
			ThreadPool.QueueUserWorkItem(delegate
			{
				Load(t, id);
			});
		}

		public void PlayNow(RadioTrack t)
		{
			int id;
			lock (gate)
			{
				id = ++request;
				FadeCurrentOut();
				loading = true;
			}
			Load(t, id);
		}

		public void Seek(double seconds)
		{
			lock (gate)
			{
				if (current != null)
				{
					try
					{
						current.dec.Seek(seconds);
					}
					catch (Exception ex)
					{
						failReason = ex.Message;
						return;
					}
					current.srcCount = (current.srcIdx = 0);
					current.primed = false;
					current.frac = 0.0;
					current.gain = Math.Min(current.gain, 0.15f);
					current.step = 0.00034722223f;
				}
			}
		}

		public void Stop()
		{
			lock (gate)
			{
				request++;
				FadeCurrentOut();
				loading = false;
			}
		}

		private void FadeCurrentOut()
		{
			if (current != null)
			{
				current.target = 0f;
				current.step = 1f / (Math.Max(0.02f, fadeOut) * 48000f);
				fading.Add(current);
				current = null;
			}
		}

		private void Load(RadioTrack t, int id)
		{
			IRadioDecoder radioDecoder = null;
			try
			{
				radioDecoder = RadioDecoders.Open(t.path);
				float[] interleaved = new float[256 * Math.Max(1, radioDecoder.Channels)];
				if (radioDecoder.Read(interleaved, 256) <= 0)
				{
					throw new InvalidDataException("no audio frames");
				}
				radioDecoder.Dispose();
				radioDecoder = RadioDecoders.Open(t.path);
				lock (gate)
				{
					if (id != request)
					{
						radioDecoder.Dispose();
						return;
					}
					current = new Deck
					{
						dec = radioDecoder,
						track = t,
						gain = 0f,
						target = 1f,
						step = 1f / (Math.Max(0.02f, fadeIn) * 48000f)
					};
					loading = false;
				}
			}
			catch (Exception ex)
			{
				if (radioDecoder != null)
				{
					try
					{
						radioDecoder.Dispose();
					}
					catch
					{
					}
				}
				lock (gate)
				{
					if (id == request)
					{
						loading = false;
						failReason = ex.Message;
						failed = t;
					}
				}
			}
		}

		public void StartOutput()
		{
			if (!running)
			{
				running = true;
				thread = new Thread(Output)
				{
					IsBackground = true,
					Name = "Radioport",
					Priority = ThreadPriority.AboveNormal
				};
				thread.Start();
			}
		}

		public void Shutdown()
		{
			running = false;
		}

		public void Render(float[] mix, int frames)
		{
			Array.Clear(mix, 0, frames * 2);
			lock (gate)
			{
				if (current != null)
				{
					MixDeck(current, mix, frames, isCurrent: true);
				}
				for (int i = 0; i < fading.Count; i++)
				{
					MixDeck(fading[i], mix, frames, isCurrent: false);
				}
				for (int num = fading.Count - 1; num >= 0; num--)
				{
					if (fading[num].gain <= 0f || fading[num].ended)
					{
						try
						{
							fading[num].dec.Dispose();
						}
						catch
						{
						}
						fading.RemoveAt(num);
					}
				}
				if (current != null && current.ended)
				{
					try
					{
						current.dec.Dispose();
					}
					catch
					{
					}
					finished = current.track;
					current = null;
				}
				if (current != null)
				{
					try
					{
						Position = current.dec.Position;
						Length = current.dec.Length;
					}
					catch
					{
					}
				}
				else
				{
					Position = 0.0;
					Length = 0.0;
				}
			}
			float num2 = vol * Master;
			float num3 = 0f;
			for (int j = 0; j < frames * 2; j++)
			{
				if ((j & 1) == 0)
				{
					volNow += (num2 - volNow) * 0.0015f;
				}
				float num4 = mix[j] * volNow * 0.9f;
				float num5 = Math.Abs(num4);
				if (num5 > 0.8f)
				{
					num4 = (float)Math.Sign(num4) * (0.8f + 0.2f * (float)Math.Tanh((num5 - 0.8f) / 0.2f));
				}
				mix[j] = num4;
				if (num5 > num3)
				{
					num3 = Math.Abs(num4);
				}
			}
			Peak = num3;
		}

		private void MixDeck(Deck d, float[] mix, int frames, bool isCurrent)
		{
			if (d.ended)
			{
				return;
			}
			double num = (double)d.dec.SampleRate / 48000.0;
			int channels = d.dec.Channels;
			for (int i = 0; i < frames; i++)
			{
				if (!d.primed)
				{
					if (!NextSrc(d, channels, out d.l0, out d.r0) || !NextSrc(d, channels, out d.l1, out d.r1))
					{
						d.ended = true;
						break;
					}
					d.primed = true;
				}
				d.frac += num;
				while (d.frac >= 1.0)
				{
					d.frac -= 1.0;
					d.l0 = d.l1;
					d.r0 = d.r1;
					if (!NextSrc(d, channels, out d.l1, out d.r1))
					{
						d.ended = true;
						return;
					}
				}
				float num2 = (float)d.frac;
				float num3 = d.l0 + (d.l1 - d.l0) * num2;
				float num4 = d.r0 + (d.r1 - d.r0) * num2;
				if (d.gain < d.target)
				{
					d.gain = Math.Min(d.target, d.gain + d.step);
				}
				else if (d.gain > d.target)
				{
					d.gain = Math.Max(d.target, d.gain - d.step);
				}
				float num5 = d.gain * d.gain;
				mix[i * 2] += num3 * num5;
				mix[i * 2 + 1] += num4 * num5;
				if (!isCurrent && d.gain <= 0f)
				{
					break;
				}
			}
		}

		private bool NextSrc(Deck d, int ch, out float l, out float r)
		{
			if (d.srcIdx >= d.srcCount)
			{
				int num = 2048;
				if (d.src.Length < num * ch)
				{
					d.src = new float[num * ch];
				}
				int num2;
				try
				{
					num2 = d.dec.Read(d.src, num);
				}
				catch (Exception ex)
				{
					failReason = ex.Message;
					failed = d.track;
					num2 = 0;
				}
				d.srcCount = num2;
				d.srcIdx = 0;
				if (num2 <= 0)
				{
					l = (r = 0f);
					return false;
				}
			}
			int num3 = d.srcIdx * ch;
			l = d.src[num3];
			r = ((ch > 1) ? d.src[num3 + 1] : l);
			d.srcIdx++;
			return true;
		}

		private void Output()
		{
			IntPtr hwo = IntPtr.Zero;
			IntPtr[] array = new IntPtr[6];
			IntPtr[] array2 = new IntPtr[6];
			try
			{
				WaveFormat fmt = new WaveFormat
				{
					wFormatTag = 1,
					nChannels = 2,
					nSamplesPerSec = 48000,
					nAvgBytesPerSec = 192000,
					nBlockAlign = 4,
					wBitsPerSample = 16,
					cbSize = 0
				};
				int num = waveOutOpen(out hwo, -1, ref fmt, IntPtr.Zero, IntPtr.Zero, 0);
				if (num != 0)
				{
					failReason = "audio output unavailable (" + num + ")";
					running = false;
					return;
				}
				int num2 = 4096;
				for (int i = 0; i < 6; i++)
				{
					array2[i] = Marshal.AllocHGlobal(num2);
					array[i] = Marshal.AllocHGlobal(HDR);
					for (int j = 0; j < HDR; j += 4)
					{
						Marshal.WriteInt32(array[i], j, 0);
					}
					Marshal.WriteIntPtr(array[i], 0, array2[i]);
					Marshal.WriteInt32(array[i], IntPtr.Size, num2);
					waveOutPrepareHeader(hwo, array[i], HDR);
				}
				float[] array3 = new float[2048];
				short[] array4 = new short[2048];
				bool[] array5 = new bool[6];
				while (running)
				{
					bool flag = false;
					for (int k = 0; k < 6; k++)
					{
						if (!array5[k] || (Marshal.ReadInt32(array[k], FLAGS) & 1) != 0)
						{
							Render(array3, 1024);
							for (int l = 0; l < array3.Length; l++)
							{
								array4[l] = (short)Math.Max(-32768f, Math.Min(32767f, array3[l] * 32767f));
							}
							Marshal.Copy(array4, 0, array2[k], array4.Length);
							waveOutWrite(hwo, array[k], HDR);
							array5[k] = true;
							flag = true;
						}
					}
					if (!flag)
					{
						Thread.Sleep(3);
					}
				}
			}
			catch (Exception ex)
			{
				failReason = "audio thread: " + ex.Message;
			}
			finally
			{
				if (hwo != IntPtr.Zero)
				{
					waveOutReset(hwo);
					for (int m = 0; m < 6; m++)
					{
						if (array[m] != IntPtr.Zero)
						{
							waveOutUnprepareHeader(hwo, array[m], HDR);
						}
					}
					waveOutClose(hwo);
				}
				for (int n = 0; n < 6; n++)
				{
					if (array[n] != IntPtr.Zero)
					{
						Marshal.FreeHGlobal(array[n]);
					}
					if (array2[n] != IntPtr.Zero)
					{
						Marshal.FreeHGlobal(array2[n]);
					}
				}
				lock (gate)
				{
					if (current != null)
					{
						current.dec.Dispose();
					}
					foreach (Deck item in fading)
					{
						item.dec.Dispose();
					}
					current = null;
					fading.Clear();
				}
			}
		}

		[DllImport("winmm.dll")]
		private static extern int waveOutOpen(out IntPtr hwo, int uDeviceID, ref WaveFormat fmt, IntPtr cb, IntPtr inst, int flags);

		[DllImport("winmm.dll")]
		private static extern int waveOutPrepareHeader(IntPtr hwo, IntPtr hdr, int size);

		[DllImport("winmm.dll")]
		private static extern int waveOutUnprepareHeader(IntPtr hwo, IntPtr hdr, int size);

		[DllImport("winmm.dll")]
		private static extern int waveOutWrite(IntPtr hwo, IntPtr hdr, int size);

		[DllImport("winmm.dll")]
		private static extern int waveOutReset(IntPtr hwo);

		[DllImport("winmm.dll")]
		private static extern int waveOutClose(IntPtr hwo);
	}
	public class Glide
	{
		public float value;

		public float target;

		private float from;

		private float t = 1f;

		private float dur = 0.3f;

		public Glide(float v)
		{
			value = (target = (from = v));
		}

		public void To(float v, float seconds)
		{
			if (!(Math.Abs(v - target) < 0.0001f))
			{
				from = value;
				target = v;
				dur = Math.Max(0.001f, seconds);
				t = 0f;
			}
		}

		public bool Tick(float dt)
		{
			if (t >= 1f)
			{
				return false;
			}
			t = Math.Min(1f, t + dt / dur);
			float num = t * t * (3f - 2f * t);
			value = from + (target - from) * num;
			return true;
		}
	}
	public class RadioportController : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static hook_TogglePauseScreen <>9__39_0;

			public static Action<string> <>9__40_0;

			internal void <Init>b__39_0(orig_TogglePauseScreen orig)
			{
				if (Time.frameCount > blockPauseUntilFrame)
				{
					orig.Invoke();
				}
			}

			internal void <Awake>b__40_0(string s)
			{
				Log.Warning(s);
			}
		}

		public static RadioportController instance;

		private static ConfigEntry<bool> cfgEnabled;

		private static ConfigEntry<bool> cfgPauseSolo;

		private static ConfigEntry<bool> cfgMultiplayer;

		private static ConfigEntry<KeyCode> cfgKey;

		private static ConfigEntry<float> cfgHold;

		private static ConfigEntry<float> cfgDuck;

		private static ConfigEntry<float> cfgDuckTime;

		private static ConfigEntry<float> cfgVolume;

		private static ConfigEntry<string> cfgExtraFolder;

		private static ConfigEntry<string> cfgDefaultStation;

		private static ConfigEntry<bool> cfgShuffle;

		private static Font fontRegular;

		private static Font fontBold;

		private static int blockPauseUntilFrame;

		public RadioportUI ui;

		public RadioportAudio audio;

		public RadioportLibrary library;

		public RadioportModel model = new RadioportModel();

		private readonly HoldTrigger hold = new HoldTrigger();

		private readonly Glide duck = new Glide(1f);

		private string musicFolder;

		private bool menuOpen;

		private bool pausedGame;

		private bool pausedWwise;

		private float oldTimeScale = 1f;

		private MPEventSystem cursorSystem;

		private GameObject focus;

		private float repeatT;

		private int repeatDir;

		private float masterTimer;

		private Vector3 lastMouse;

		private string nowError;

		private float nowErrorT;

		private int duckErrors;

		private ulong musicOutput = ulong.MaxValue;

		private MusicController musicFor;

		private static FieldInfo musicListenerField = typeof(MusicController).GetField("musicListenerId", BindingFlags.Instance | BindingFlags.NonPublic);

		private readonly Dictionary<string, Texture2D> logos = new Dictionary<string, Texture2D>();

		private float volRepeat;

		private float seekT;

		private int seekDir;

		public static void Init(AssetBundle bundle)
		{
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			ConfigFile config = ((BaseUnityPlugin)HenryPlugin.instance).Config;
			cfgEnabled = config.Bind<bool>("Radioport", "Enabled", true, "Cyberpunk-style radio for your own music (hold the key in a run).");
			cfgKey = config.Bind<KeyCode>("Radioport", "Key", (KeyCode)122, "Hold this key to open the Radioport.");
			cfgHold = config.Bind<float>("Radioport", "HoldSeconds", 0.4f, "How long the key has to be held (0.35 - 0.5 recommended). A tap does nothing.");
			cfgPauseSolo = config.Bind<bool>("Radioport", "PauseInSingleplayer", true, "Pause the game while the Radioport is open (singleplayer only).");
			cfgMultiplayer = config.Bind<bool>("Radioport", "AllowInMultiplayer", true, "Allow the menu in multiplayer as a local menu. It never pauses a multiplayer game.");
			cfgDuck = config.Bind<float>("Radioport", "GameMusicWhilePlaying", 0.25f, "Game music level while a Radioport song plays (0 = silent, 1 = untouched).");
			cfgDuckTime = config.Bind<float>("Radioport", "DuckFadeSeconds", 0.3f, "How long the game music takes to fade down / back up.");
			cfgVolume = config.Bind<float>("Radioport", "Volume", 0.8f, "Radioport volume (also changed in the menu with A/D or Left/Right).");
			cfgExtraFolder = config.Bind<string>("Radioport", "ExtraMusicFolder", "", "Optional extra folder to scan for music.");
			cfgDefaultStation = config.Bind<string>("Radioport", "DefaultStation", "Growl FM", "Station for songs that are not in a station folder (Edgerunners' songs are on 89.7 Growl FM in the game).");
			cfgShuffle = config.Bind<bool>("Radioport", "Shuffle", false, "Shuffle the station's tracks (R in the menu).");
			if (!string.IsNullOrEmpty(cfgDefaultStation.Value))
			{
				RadioportLibrary.DefaultStation = cfgDefaultStation.Value.Trim();
			}
			if (!cfgEnabled.Value)
			{
				return;
			}
			try
			{
				if (Object.op_Implicit((Object)(object)bundle))
				{
					fontRegular = bundle.LoadAsset<Font>("Rajdhani-Medium");
					fontBold = bundle.LoadAsset<Font>("Rajdhani-SemiBold");
				}
			}
			catch (Exception ex)
			{
				Log.Warning("[Radioport] font: " + ex.Message);
			}
			object obj = <>c.<>9__39_0;
			if (obj == null)
			{
				hook_TogglePauseScreen val = delegate(orig_TogglePauseScreen orig)
				{
					if (Time.frameCount > blockPauseUntilFrame)
					{
						orig.Invoke();
					}
				};
				<>c.<>9__39_0 = val;
				obj = (object)val;
			}
			PauseManager.TogglePauseScreen += (hook_TogglePauseScreen)obj;
			GameObject val2 = new GameObject("Radioport");
			Object.DontDestroyOnLoad((Object)val2);
			val2.AddComponent<RadioportController>();
		}

		private void Awake()
		{
			instance = this;
			string directoryName = Path.GetDirectoryName(typeof(HenryPlugin).Assembly.Location);
			musicFolder = Path.Combine(directoryName, "RadioportMusic");
			try
			{
				Directory.CreateDirectory(musicFolder);
				WriteReadme();
			}
			catch (Exception ex)
			{
				Log.Warning("[Radioport] " + ex.Message);
			}
			library = new RadioportLibrary
			{
				log = delegate(string s)
				{
					Log.Warning(s);
				}
			};
			library.roots.Add(musicFolder);
			library.roots.Add(Path.Combine(Paths.PluginPath, "KingMod", "RadioportMusic"));
			if (!string.IsNullOrEmpty(cfgExtraFolder.Value))
			{
				library.roots.Add(cfgExtraFolder.Value);
			}
			audio = new RadioportAudio
			{
				Volume = Mathf.Clamp01(cfgVolume.Value)
			};
			ui = new RadioportUI(fontRegular, fontBold, ((Component)this).transform);
			ui.SetVolume(audio.Volume);
			model.shuffle = cfgShuffle.Value;
			ui.SetShuffle(model.shuffle);
			focus = ((Component)ui.panel).gameObject;
			Rescan();
			Application.quitting += OnQuit;
		}

		private void Rescan()
		{
			string keepPlayingPath = ((audio.Playing != null) ? audio.Playing.path : null);
			try
			{
				library.Scan();
			}
			catch (Exception ex)
			{
				Log.Warning("[Radioport] scan failed: " + ex);
			}
			model.SetStations(library.stations, keepPlayingPath);
			Log.Info("[Radioport] " + library.found + " tracks in " + library.stations.Count + " stations" + ((library.skipped > 0) ? (" (" + library.skipped + " skipped, see warnings)") : ""));
		}

		private void Update()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			try
			{
				bool num = Object.op_Implicit((Object)(object)Run.instance) && LocalUserManager.GetFirstLocalUser() != null;
				bool flag = !RoR2Application.isInSinglePlayer;
				bool flag2 = num && (!flag || cfgMultiplayer.Value);
				if (menuOpen && !flag2)
				{
					CloseMenu();
				}
				bool flag3 = Input.GetKey(cfgKey.Value) && !TypingSomewhere();
				hold.holdTime = Mathf.Clamp(cfgHold.Value, 0.1f, 2f);
				if (flag2 && hold.Tick(flag3 && (menuOpen || !BlockedByOtherUI()), menuOpen, unscaledDeltaTime))
				{
					if (menuOpen)
					{
						CloseMenu();
					}
					else
					{
						OpenMenu();
					}
				}
				ui.SetHold(menuOpen ? 0f : hold.Progress);
				ui.SetHud(flag2 && !PauseScreenUp());
				if (menuOpen)
				{
					MenuInput(unscaledDeltaTime);
				}
				RadioTrack failed = audio.failed;
				if (failed != null)
				{
					audio.failed = null;
					failed.broken = true;
					Log.Warning("[Radioport] cannot play " + failed.path + ": " + audio.failReason);
					nowError = "UNREADABLE FILE";
					nowErrorT = 4f;
					if (model.playStation >= 0 && model.Track(model.playStation, model.playTrack) == failed)
					{
						int num2 = model.Step(1);
						if (num2 >= 0)
						{
							PlayTrack(model.playStation, num2, fromUser: false);
						}
						else
						{
							StopRadio();
						}
					}
					Refresh();
				}
				RadioTrack finished = audio.finished;
				if (finished != null)
				{
					audio.finished = null;
					if (!finished.broken && model.playStation >= 0)
					{
						int num3 = model.Step(1);
						if (num3 >= 0)
						{
							PlayTrack(model.playStation, num3, fromUser: false);
						}
						else
						{
							StopRadio();
						}
					}
				}
				masterTimer -= unscaledDeltaTime;
				if (masterTimer <= 0f)
				{
					masterTimer = 0.5f;
					audio.Master = ConVar("volume_master");
				}
				UpdateDuck(unscaledDeltaTime);
				if (nowErrorT > 0f)
				{
					nowErrorT -= unscaledDeltaTime;
				}
				ui.SetPlaying(audio.Playing != null);
				UpdateNow();
				ui.Tick(unscaledDeltaTime);
			}
			catch (Exception ex)
			{
				Log.Warning("[Radioport] " + ex);
			}
		}

		private void LateUpdate()
		{
			if (!menuOpen)
			{
				return;
			}
			try
			{
				MPEventSystem val = cursorSystem;
				if (Object.op_Implicit((Object)(object)val) && (Object)(object)((EventSystem)val).currentSelectedGameObject != (Object)(object)focus)
				{
					((EventSystem)val).SetSelectedGameObject(focus);
				}
			}
			catch
			{
			}
		}

		private void OpenMenu()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Rescan();
			model.CursorToPlaying();
			menuOpen = true;
			ui.Open();
			Refresh();
			lastMouse = Input.mousePosition;
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			cursorSystem = ((firstLocalUser != null) ? firstLocalUser.eventSystem : null);
			if (Object.op_Implicit((Object)(object)cursorSystem))
			{
				MPEventSystem obj = cursorSystem;
				int cursorOpenerCount = obj.cursorOpenerCount;
				obj.cursorOpenerCount = cursorOpenerCount + 1;
				MPEventSystem obj2 = cursorSystem;
				cursorOpenerCount = obj2.cursorOpenerForGamepadCount;
				obj2.cursorOpenerForGamepadCount = cursorOpenerCount + 1;
			}
			if (RoR2Application.isInSinglePlayer && cfgPauseSolo.Value && NetworkServer.active)
			{
				oldTimeScale = Time.timeScale;
				Time.timeScale = 0f;
				pausedGame = true;
				try
				{
					AkSoundEngine.PostEvent("Pause_All", ulong.MaxValue);
					pausedWwise = true;
				}
				catch
				{
				}
			}
			Click(1.15f);
		}

		private void CloseMenu()
		{
			if (!menuOpen)
			{
				return;
			}
			menuOpen = false;
			ui.Close();
			blockPauseUntilFrame = Time.frameCount + 2;
			if (Object.op_Implicit((Object)(object)cursorSystem))
			{
				cursorSystem.cursorOpenerCount = Mathf.Max(0, cursorSystem.cursorOpenerCount - 1);
				cursorSystem.cursorOpenerForGamepadCount = Mathf.Max(0, cursorSystem.cursorOpenerForGamepadCount - 1);
				if ((Object)(object)((EventSystem)cursorSystem).currentSelectedGameObject == (Object)(object)focus)
				{
					((EventSystem)cursorSystem).SetSelectedGameObject((GameObject)null);
				}
			}
			cursorSystem = null;
			if (pausedGame)
			{
				Time.timeScale = oldTimeScale;
				pausedGame = false;
			}
			if (pausedWwise)
			{
				try
				{
					AkSoundEngine.PostEvent("Unpause_All", ulong.MaxValue);
				}
				catch
				{
				}
				pausedWwise = false;
			}
			hold.Reset();
			cfgVolume.Value = audio.Volume;
			Click(0.85f);
		}

		private void MenuInput(float dt)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)27))
			{
				CloseMenu();
				return;
			}
			Player val = null;
			try
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				val = ((firstLocalUser != null) ? firstLocalUser.inputPlayer : null);
			}
			catch
			{
			}
			if (val != null && val.GetButtonDown(15) && !Input.GetKey((KeyCode)27))
			{
				CloseMenu();
				return;
			}
			int num = 0;
			if (Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273))
			{
				num = -1;
			}
			else if (Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274))
			{
				num = 1;
			}
			else if (val != null)
			{
				float axis = val.GetAxis(13);
				if (axis > 0.5f)
				{
					num = -1;
				}
				else if (axis < -0.5f)
				{
					num = 1;
				}
			}
			if (num != 0)
			{
				if (num != repeatDir)
				{
					repeatDir = num;
					repeatT = 0.35f;
					Move(num);
				}
				else
				{
					repeatT -= dt;
					if (repeatT <= 0f)
					{
						repeatT = 0.075f;
						Move(num);
					}
				}
			}
			else
			{
				repeatDir = 0;
			}
			float y = Input.mouseScrollDelta.y;
			if (y > 0.1f)
			{
				Move(-1);
			}
			else if (y < -0.1f)
			{
				Move(1);
			}
			if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271) || (val != null && val.GetButtonDown(14)))
			{
				Select();
			}
			int num2 = 0;
			if (Input.GetKeyDown((KeyCode)97))
			{
				num2 = -1;
			}
			if (Input.GetKeyDown((KeyCode)100))
			{
				num2 = 1;
			}
			int num3 = (Input.GetKey((KeyCode)276) ? (-1) : (Input.GetKey((KeyCode)275) ? 1 : 0));
			if (num3 != 0 && audio.Playing != null && !audio.loading)
			{
				if (num3 != seekDir)
				{
					seekDir = num3;
					seekT = 0.4f;
					Seek((double)num3 * 10.0);
				}
				else
				{
					seekT -= dt;
					if (seekT <= 0f)
					{
						seekT = 0.18f;
						Seek((double)num3 * 10.0);
					}
				}
			}
			else
			{
				seekDir = 0;
			}
			if (Input.GetMouseButtonDown(0))
			{
				float num4 = ui.ProgressAt(Vector2.op_Implicit(Input.mousePosition));
				if (num4 >= 0f && audio.Length > 0.5)
				{
					audio.Seek((double)num4 * audio.Length);
					Click(1f);
				}
			}
			if (Input.GetKeyDown((KeyCode)114))
			{
				model.shuffle = !model.shuffle;
				cfgShuffle.Value = model.shuffle;
				ui.SetShuffle(model.shuffle);
				Click(1.6f);
			}
			if (val != null && num2 == 0)
			{
				float axis2 = val.GetAxis(12);
				if (Mathf.Abs(axis2) > 0.5f)
				{
					if (volRepeat <= 0f)
					{
						num2 = ((axis2 > 0f) ? 1 : (-1));
						volRepeat = 0.15f;
					}
					volRepeat -= dt;
				}
				else
				{
					volRepeat = 0f;
				}
			}
			if (num2 != 0)
			{
				audio.Volume = Mathf.Round((audio.Volume + (float)num2 * 0.05f) * 20f) / 20f;
				ui.SetVolume(audio.Volume);
				Click(1.3f);
			}
			if (Input.GetKeyDown((KeyCode)113) || (val != null && val.GetButtonDown(29)))
			{
				Skip(-1);
			}
			if (Input.GetKeyDown((KeyCode)101) || (val != null && val.GetButtonDown(30)))
			{
				Skip(1);
			}
			Vector3 mousePosition = Input.mousePosition;
			int num5 = ui.RowAt(Vector2.op_Implicit(mousePosition));
			Vector3 val2 = mousePosition - lastMouse;
			if (((Vector3)(ref val2)).sqrMagnitude > 1f && num5 >= 0)
			{
				lastMouse = mousePosition;
				model.Build();
				int num6 = SelectedRow();
				if (num5 != num6)
				{
					model.Pick(num5);
					Refresh(num5);
				}
			}
			if (Input.GetMouseButtonDown(0) && num5 >= 0)
			{
				model.Build();
				model.Pick(num5);
				Select();
			}
		}

		private void Seek(double delta)
		{
			double num = audio.Position + delta;
			if (num >= audio.Length - 0.5)
			{
				Skip(1);
				return;
			}
			audio.Seek(Math.Max(0.0, num));
			Click(1f);
		}

		private int SelectedRow()
		{
			return model.Build();
		}

		private void Move(int dir)
		{
			model.Move(dir);
			Refresh();
			Click(1f);
		}

		private void Select()
		{
			model.Activate(out var station, out var track);
			if (station < 0)
			{
				StopRadio();
			}
			else if (track < 0)
			{
				if (model.playStation == station)
				{
					Refresh();
					return;
				}
				int num = (model.shuffle ? (-1) : FirstPlayable(station));
				if (num < 0)
				{
					List<RadioTrack> tracks = model.stations[station].tracks;
					List<int> list = new List<int>();
					for (int i = 0; i < tracks.Count; i++)
					{
						if (!tracks[i].broken)
						{
							list.Add(i);
						}
					}
					if (list.Count > 0)
					{
						num = list[Random.Range(0, list.Count)];
					}
				}
				if (num >= 0)
				{
					PlayTrack(station, num, fromUser: true);
				}
			}
			else if (!model.stations[station].tracks[track].broken)
			{
				PlayTrack(station, track, fromUser: true);
			}
			Refresh();
			Click(1.6f);
		}

		private void Skip(int dir)
		{
			int num = model.Step(dir);
			if (num >= 0)
			{
				PlayTrack(model.playStation, num, fromUser: true, dir < 0);
				Refresh();
			}
		}

		private int FirstPlayable(int s)
		{
			List<RadioTrack> tracks = model.stations[s].tracks;
			for (int i = 0; i < tracks.Count; i++)
			{
				if (!tracks[i].broken)
				{
					return i;
				}
			}
			return -1;
		}

		private void PlayTrack(int s, int t, bool fromUser, bool back = false)
		{
			RadioTrack radioTrack = model.Track(s, t);
			if (radioTrack != null)
			{
				model.Played(s, t, !back);
				audio.StartOutput();
				audio.Play(radioTrack);
				model.playStation = s;
				model.playTrack = t;
				if (!menuOpen)
				{
					ui.Toast("NOW PLAYING  " + radioTrack.Display);
				}
			}
		}

		private void StopRadio()
		{
			audio.Stop();
			model.playStation = (model.playTrack = -1);
		}

		private void Refresh(int scrollTo = -1)
		{
			int num = model.Build();
			ui.SetRows(model.rows, num, (scrollTo >= 0) ? scrollTo : num);
			bool empty = model.stations.Count == 0;
			ui.SetEmpty(empty, "Add .ogg or .wav files to\n" + musicFolder + "\n(sub folders become stations)");
		}

		private void UpdateNow()
		{
			RadioTrack radioTrack = ((model.playStation >= 0) ? model.Track(model.playStation, model.playTrack) : null);
			RadioStation radioStation = ((model.playStation >= 0) ? model.stations[model.playStation] : null);
			string track = radioTrack?.Display;
			string sub = null;
			string timeLine = null;
			float progress = 0f;
			if (nowErrorT > 0f && radioTrack == null)
			{
				track = nowError;
			}
			if (radioTrack != null)
			{
				sub = radioStation.Display + "   //   TRACK " + (model.playTrack + 1) + "/" + radioStation.tracks.Count;
				double length = audio.Length;
				double position = audio.Position;
				if (audio.loading)
				{
					timeLine = "TUNING...";
				}
				else if (length > 0.5)
				{
					progress = (float)(position / length);
					timeLine = Clock(position) + " / " + Clock(length);
				}
				if (nowErrorT > 0f)
				{
					timeLine = nowError;
				}
			}
			Texture logo = (Texture)(object)((radioStation != null) ? Logo(radioStation) : null);
			string info = ((radioStation != null) ? ("FREQ " + radioStation.frequency + " MHZ\nTRACKS: " + radioStation.tracks.Count + "\nSRC: LOCAL") : "SIGNAL: NONE\nSRC: -");
			ui.SetNow(track, sub, progress, timeLine, radioStation == null, radioStation?.frequency, radioStation?.name, logo, info);
		}

		private static string Clock(double s)
		{
			int num = (int)s;
			return num / 60 + ":" + (num % 60).ToString("00");
		}

		private Texture2D Logo(RadioStation st)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if (st.logoPath == null)
			{
				return null;
			}
			if (logos.TryGetValue(st.logoPath, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				Texture2D val = new Texture2D(2, 2);
				if (ImageConversion.LoadImage(val, File.ReadAllBytes(st.logoPath)))
				{
					value = val;
				}
			}
			catch (Exception ex)
			{
				Log.Warning("[Radioport] logo " + st.logoPath + ": " + ex.Message);
			}
			logos[st.logoPath] = value;
			return value;
		}

		private void UpdateDuck(float dt)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			bool flag = audio.Playing != null || audio.loading;
			duck.To(flag ? Mathf.Clamp01(cfgDuck.Value) : 1f, Mathf.Clamp(cfgDuckTime.Value, 0.05f, 2f));
			bool flag2 = duck.Tick(dt);
			MusicController val = MusicController.Instance;
			if ((Object)(object)val != (Object)(object)musicFor)
			{
				musicFor = val;
				musicOutput = ulong.MaxValue;
				flag2 = true;
				if (Object.op_Implicit((Object)(object)val) && musicListenerField != null)
				{
					try
					{
						musicOutput = (ulong)musicListenerField.GetValue(val);
					}
					catch
					{
					}
				}
			}
			if (!flag2 || musicOutput == ulong.MaxValue)
			{
				return;
			}
			try
			{
				AkSoundEngine.SetOutputVolume(musicOutput, duck.value);
			}
			catch (Exception ex)
			{
				if (duckErrors++ < 3)
				{
					Log.Warning("[Radioport] ducking: " + ex.Message);
				}
			}
		}

		private void OnQuit()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (musicOutput != ulong.MaxValue)
				{
					AkSoundEngine.SetOutputVolume(musicOutput, 1f);
				}
			}
			catch
			{
			}
			audio.Shutdown();
		}

		private void OnDestroy()
		{
			OnQuit();
		}

		private static bool TypingSomewhere()
		{
			try
			{
				if (Object.op_Implicit((Object)(object)ConsoleWindow.instance))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private bool BlockedByOtherUI()
		{
			try
			{
				if (PauseScreenUp())
				{
					return true;
				}
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				if (firstLocalUser != null && Object.op_Implicit((Object)(object)firstLocalUser.eventSystem) && Object.op_Implicit((Object)(object)((EventSystem)firstLocalUser.eventSystem).currentSelectedGameObject) && (Object)(object)((EventSystem)firstLocalUser.eventSystem).currentSelectedGameObject != (Object)(object)focus)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool PauseScreenUp()
		{
			try
			{
				return Object.op_Implicit((Object)(object)PauseManager.pauseScreenInstance);
			}
			catch
			{
				return false;
			}
		}

		private static float ConVar(string name)
		{
			try
			{
				BaseConVar val = (Object.op_Implicit((Object)(object)Console.instance) ? Console.instance.FindConVar(name) : null);
				if (val != null && float.TryParse(val.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					return Mathf.Clamp01(result / 100f);
				}
			}
			catch
			{
			}
			return 1f;
		}

		private static void Click(float kind)
		{
			try
			{
				GameObject val = (Object.op_Implicit((Object)(object)RoR2Application.instance) ? ((Component)RoR2Application.instance).gameObject : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					Util.PlaySound((kind >= 1.5f) ? "Play_UI_menuClick" : "Play_UI_menuHover", val);
				}
			}
			catch
			{
			}
		}

		private void WriteReadme()
		{
			string path = Path.Combine(musicFolder, "README.txt");
			if (!File.Exists(path))
			{
				File.WriteAllText(path, "RADIOPORT - put your own music here (.ogg or .wav).\r\n\r\nFiles in this folder play on 89.7 GROWL FM (config: DefaultStation). Every sub folder becomes its own station,\r\nnamed after the folder - name it after a Night City station (Night FM, The Dirge...) and it gets that frequency.\r\nnamed after the folder. Add logo.png to a station folder to give it a logo.\r\n\r\nOptional metadata: a .json file next to the songs, either one object per song\r\n  { \"title\": \"Song Name\", \"artist\": \"Artist Name\", \"station\": \"My Radio\", \"file\": \"song01.ogg\" }\r\nor a list of them [ {...}, {...} ]. Without metadata the file name is the title, the artist is \"Unknown Artist\".\r\n\r\nIn a run: hold Z to open. W/S or Up/Down move, Enter (or click) selects, A/D change the volume,\r\nLeft/Right arrows seek 10 s (or click the progress bar), Q/E previous/next track, R shuffle,\r\nZ or Escape closes. NO STATION stops the radio and brings the game music back.\r\n");
			}
		}
	}
	public class HoldTrigger
	{
		public float holdTime = 0.4f;

		public float held;

		private bool armed = true;

		private bool waitRelease;

		public float Progress
		{
			get
			{
				if (!(holdTime > 0f))
				{
					return 0f;
				}
				return Math.Min(1f, held / holdTime);
			}
		}

		public bool Tick(bool keyDown, bool menuOpen, float dt)
		{
			if (menuOpen)
			{
				held = 0f;
				if (waitRelease)
				{
					if (!keyDown)
					{
						waitRelease = false;
					}
					return false;
				}
				if (keyDown && armed)
				{
					armed = false;
					return true;
				}
				if (!keyDown)
				{
					armed = true;
				}
				return false;
			}
			if (!keyDown)
			{
				held = 0f;
				armed = true;
				waitRelease = false;
				return false;
			}
			if (!armed)
			{
				return false;
			}
			held += dt;
			if (held >= holdTime)
			{
				held = 0f;
				armed = false;
				waitRelease = true;
				return true;
			}
			return false;
		}

		public void Reset()
		{
			held = 0f;
			armed = false;
			waitRelease = true;
		}
	}
	public class RadioportModel
	{
		public readonly List<RadioStation> stations = new List<RadioStation>();

		public int curStation = -1;

		public int curTrack = -1;

		public int playStation = -1;

		public int playTrack = -1;

		public bool shuffle;

		private readonly List<int> history = new List<int>();

		private readonly Random rng = new Random();

		public readonly List<RadioRow> rows = new List<RadioRow>();

		private readonly List<int[]> ids = new List<int[]>();

		public void SetStations(List<RadioStation> list, string keepPlayingPath)
		{
			stations.Clear();
			stations.AddRange(list);
			playStation = (playTrack = -1);
			if (keepPlayingPath != null)
			{
				for (int i = 0; i < stations.Count; i++)
				{
					for (int j = 0; j < stations[i].tracks.Count; j++)
					{
						if (string.Equals(stations[i].tracks[j].path, keepPlayingPath, StringComparison.OrdinalIgnoreCase))
						{
							playStation = i;
							playTrack = j;
						}
					}
				}
			}
			if (curStation >= stations.Count)
			{
				curStation = -1;
				curTrack = -1;
			}
			if (curStation >= 0 && curTrack >= stations[curStation].tracks.Count)
			{
				curTrack = -1;
			}
		}

		public void CursorToPlaying()
		{
			curStation = playStation;
			curTrack = ((playStation >= 0) ? playTrack : (-1));
		}

		public int Build()
		{
			rows.Clear();
			ids.Clear();
			int result = 0;
			rows.Add(new RadioRow
			{
				text = "NO STATION",
				playing = (playStation < 0)
			});
			ids.Add(new int[2] { -1, -1 });
			for (int i = 0; i < stations.Count; i++)
			{
				if (curStation == i && curTrack < 0)
				{
					result = rows.Count;
				}
				rows.Add(new RadioRow
				{
					text = stations[i].Display,
					playing = (playStation == i && curStation != i)
				});
				ids.Add(new int[2] { i, -1 });
				if (curStation != i)
				{
					continue;
				}
				for (int j = 0; j < stations[i].tracks.Count; j++)
				{
					RadioTrack radioTrack = stations[i].tracks[j];
					if (curTrack == j)
					{
						result = rows.Count;
					}
					rows.Add(new RadioRow
					{
						text = radioTrack.title,
						sub = ((radioTrack.artist == "Unknown Artist") ? null : radioTrack.artist),
						isTrack = true,
						playing = (playStation == i && playTrack == j),
						broken = radioTrack.broken
					});
					ids.Add(new int[2] { i, j });
				}
			}
			if (curStation >= 0 && playStation == curStation)
			{
				for (int k = 0; k < ids.Count; k++)
				{
					if (ids[k][0] == curStation && ids[k][1] < 0)
					{
						RadioRow value = rows[k];
						value.playing = false;
						rows[k] = value;
					}
				}
			}
			return result;
		}

		public void Move(int dir)
		{
			int num = Build();
			int rowIndex = Math.Max(0, Math.Min(rows.Count - 1, num + dir));
			Pick(rowIndex);
		}

		public void Pick(int rowIndex)
		{
			if (rowIndex >= 0 && rowIndex < ids.Count)
			{
				curStation = ids[rowIndex][0];
				curTrack = ids[rowIndex][1];
			}
		}

		public void Activate(out int station, out int track)
		{
			station = curStation;
			track = curTrack;
		}

		public RadioTrack Track(int s, int t)
		{
			if (s < 0 || s >= stations.Count || t < 0 || t >= stations[s].tracks.Count)
			{
				return null;
			}
			return stations[s].tracks[t];
		}

		public void Played(int station, int track, bool remember)
		{
			if (station != playStation)
			{
				history.Clear();
			}
			else if (remember && playTrack >= 0 && playTrack != track)
			{
				history.Add(playTrack);
				if (history.Count > 64)
				{
					history.RemoveAt(0);
				}
			}
		}

		public int Step(int dir)
		{
			if (playStation < 0)
			{
				return -1;
			}
			List<RadioTrack> tracks = stations[playStation].tracks;
			if (shuffle && tracks.Count > 1)
			{
				if (dir < 0)
				{
					while (history.Count > 0)
					{
						int num = history[history.Count - 1];
						history.RemoveAt(history.Count - 1);
						if (num < tracks.Count && !tracks[num].broken)
						{
							return num;
						}
					}
				}
				List<int> list = new List<int>();
				for (int i = 0; i < tracks.Count; i++)
				{
					if (i != playTrack && !tracks[i].broken)
					{
						list.Add(i);
					}
				}
				if (list.Count > 0)
				{
					return list[rng.Next(list.Count)];
				}
			}
			for (int j = 1; j <= tracks.Count; j++)
			{
				int num2 = ((playTrack + dir * j) % tracks.Count + tracks.Count) % tracks.Count;
				if (!tracks[num2].broken)
				{
					return num2;
				}
			}
			return -1;
		}
	}
	public class RadioTrack
	{
		public string path;

		public string title;

		public string artist;

		public string station;

		public bool broken;

		public string Display => ((artist == "Unknown Artist") ? title : (artist + " - " + title)).ToUpperInvariant();
	}
	public class RadioStation
	{
		public string name;

		public string frequency;

		public string logoPath;

		public readonly List<RadioTrack> tracks = new List<RadioTrack>();

		public string Display => (frequency + " " + name).ToUpperInvariant();
	}
	[Serializable]
	public class RadioTrackMeta
	{
		public string title;

		public string artist;

		public string station;

		public string file;
	}
	[Serializable]
	public class RadioTrackMetaList
	{
		public RadioTrackMeta[] tracks;
	}
	public class RadioportLibrary
	{
		public const string UnknownArtist = "Unknown Artist";

		public static string DefaultStation = "Growl FM";

		public static readonly Dictionary<string, string> Known = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "Pacific Dreams", "88.9" },
			{ "Radio Vexelstrom", "89.3" },
			{ "Growl FM", "89.7" },
			{ "Royal Blue Radio", "91.9" },
			{ "Night FM", "92.9" },
			{ "Samizdat Radio", "95.2" },
			{ "Night City Talk Radio", "95.5" },
			{ "Ritual FM", "96.1" },
			{ "Body Heat Radio", "98.7" },
			{ "The Diamond Hour", "99.7" },
			{ "Impulse", "99.9" },
			{ "The Dirge", "101.9" },
			{ "Radio Pebkac", "103.5" },
			{ "Pebkac", "103.5" },
			{ "30 Principales", "106.9" },
			{ "Morro Rock Radio", "107.3" },
			{ "Morro Rock", "107.3" }
		};

		public readonly List<string> roots = new List<string>();

		public readonly List<RadioStation> stations = new List<RadioStation>();

		public Action<string> log = delegate
		{
		};

		public int skipped;

		public int found;

		public void Scan()
		{
			Dictionary<string, RadioStation> dictionary = new Dictionary<string, RadioStation>(StringComparer.OrdinalIgnoreCase);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			skipped = 0;
			found = 0;
			foreach (string root in roots)
			{
				string fullPath;
				try
				{
					fullPath = Path.GetFullPath(root);
				}
				catch
				{
					continue;
				}
				if (hashSet.Add(fullPath) && Directory.Exists(fullPath))
				{
					try
					{
						ScanFolder(fullPath, null, dictionary);
					}
					catch (Exception ex)
					{
						log("[Radioport] could not scan " + fullPath + ": " + ex.Message);
					}
				}
			}
			List<RadioStation> list = new List<RadioStation>(dictionary.Values);
			list.RemoveAll((RadioStation s) => s.tracks.Count == 0);
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (RadioStation item in list)
			{
				if (Known.TryGetValue(item.name, out var value) && hashSet2.Add(value))
				{
					item.frequency = value;
				}
			}
			float num = 88.1f;
			list.Sort((RadioStation a, RadioStation b) => string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase));
			foreach (RadioStation item2 in list)
			{
				if (item2.frequency != null)
				{
					continue;
				}
				string text;
				do
				{
					text = num.ToString("0.0", CultureInfo.InvariantCulture);
					num += 0.2f;
					if (num > 107.9f)
					{
						num = 87.5f;
					}
				}
				while (hashSet2.Contains(text));
				hashSet2.Add(text);
				item2.frequency = text;
			}
			list.Sort((RadioStation a, RadioStation b) => float.Parse(a.frequency, CultureInfo.InvariantCulture).CompareTo(float.Parse(b.frequency, CultureInfo.InvariantCulture)));
			stations.Clear();
			stations.AddRange(list);
		}

		private void ScanFolder(string dir, string folderStation, Dictionary<string, RadioStation> byName)
		{
			Dictionary<string, RadioTrackMeta> dictionary = LoadMeta(dir);
			string[] files;
			try
			{
				files = Directory.GetFiles(dir);
			}
			catch (Exception ex)
			{
				log("[Radioport] " + dir + ": " + ex.Message);
				return;
			}
			Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
			string[] array = files;
			foreach (string text in array)
			{
				string text2 = Path.GetExtension(text).ToLowerInvariant();
				if (text2 != ".wav" && text2 != ".ogg")
				{
					continue;
				}
				try
				{
					string text3 = CheckHeader(text, text2);
					if (text3 != null)
					{
						skipped++;
						log("[Radioport] skipped " + text + ": " + text3);
						continue;
					}
					string key = Path.GetFileName(text).ToLowerInvariant();
					string text4 = Path.GetFileNameWithoutExtension(text).ToLowerInvariant();
					if (!dictionary.TryGetValue(key, out var value))
					{
						dictionary.TryGetValue("stem:" + text4, out value);
					}
					RadioTrack radioTrack = new RadioTrack
					{
						path = text,
						title = ((value != null && !string.IsNullOrEmpty(value.title)) ? value.title.Trim() : Path.GetFileNameWithoutExtension(text)),
						artist = ((value != null && !string.IsNullOrEmpty(value.artist)) ? value.artist.Trim() : "Unknown Artist"),
						station = ((value != null && !string.IsNullOrEmpty(value.station)) ? value.station.Trim() : (folderStation ?? DefaultStation))
					};
					if (!byName.TryGetValue(radioTrack.station, out var value2))
					{
						string station = radioTrack.station;
						RadioStation obj = new RadioStation
						{
							name = radioTrack.station
						};
						value2 = obj;
						byName[station] = obj;
					}
					value2.tracks.Add(radioTrack);
					found++;
				}
				catch (Exception ex2)
				{
					skipped++;
					log("[Radioport] skipped " + text + ": " + ex2.Message);
				}
			}
			if (folderStation != null)
			{
				array = new string[3] { "logo.png", "logo.jpg", "logo.jpeg" };
				foreach (string path in array)
				{
					string text5 = Path.Combine(dir, path);
					if (File.Exists(text5) && byName.TryGetValue(folderStation, out var value3) && value3.logoPath == null)
					{
						value3.logoPath = text5;
						break;
					}
				}
			}
			string[] directories;
			try
			{
				directories = Directory.GetDirectories(dir);
			}
			catch
			{
				return;
			}
			Array.Sort(directories, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
			array = directories;
			foreach (string text6 in array)
			{
				ScanFolder(text6, folderStation ?? Path.GetFileName(text6), byName);
			}
		}

		private Dictionary<string, RadioTrackMeta> LoadMeta(string dir)
		{
			Dictionary<string, RadioTrackMeta> dictionary = new Dictionary<string, RadioTrackMeta>(StringComparer.OrdinalIgnoreCase);
			string[] files;
			try
			{
				files = Directory.GetFiles(dir, "*.json");
			}
			catch
			{
				return dictionary;
			}
			string[] array = files;
			foreach (string text in array)
			{
				try
				{
					string text2 = File.ReadAllText(text).Trim();
					if (text2.Length == 0)
					{
						continue;
					}
					RadioTrackMeta[] array2 = ((text2[0] == '[') ? JsonUtility.FromJson<RadioTrackMetaList>("{\"tracks\":" + text2 + "}").tracks : ((!text2.Contains("\"tracks\"")) ? new RadioTrackMeta[1] { JsonUtility.FromJson<RadioTrackMeta>(text2) } : JsonUtility.FromJson<RadioTrackMetaList>(text2).tracks));
					if (array2 == null)
					{
						continue;
					}
					RadioTrackMeta[] array3 = array2;
					foreach (RadioTrackMeta radioTrackMeta in array3)
					{
						if (radioTrackMeta != null)
						{
							if (!string.IsNullOrEmpty(radioTrackMeta.file))
							{
								dictionary[Path.GetFileName(radioTrackMeta.file.Trim())] = radioTrackMeta;
							}
							else if (array2.Length == 1)
							{
								dictionary["stem:" + Path.GetFileNameWithoutExtension(text)] = radioTrackMeta;
							}
						}
					}
				}
				catch (Exception ex)
				{
					log("[Radioport] bad metadata " + text + ": " + ex.Message);
				}
			}
			return dictionary;
		}

		public static string CheckHeader(string file, string ext)
		{
			if (new FileInfo(file).Length < 64)
			{
				return "empty or too small";
			}
			byte[] array = new byte[12];
			using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
			{
				if (fileStream.Read(array, 0, 12) < 12)
				{
					return "too small";
				}
			}
			if (ext == ".wav")
			{
				if (array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70 || array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69)
				{
					return "not a RIFF/WAVE file";
				}
				return null;
			}
			if (array[0] != 79 || array[1] != 103 || array[2] != 103 || array[3] != 83)
			{
				return "not an Ogg file";
			}
			return null;
		}
	}
	public struct RadioRow
	{
		public string text;

		public string sub;

		public bool isTrack;

		public bool playing;

		public bool broken;
	}
	public class RadioportUI
	{
		private class Row
		{
			public RectTransform rt;

			public GameObject selGroup;

			public Image selFill;

			public Text text;

			public GameObject listIcon;

			public GameObject barsIcon;

			public Image[] bars = (Image[])(object)new Image[3];

			public RectTransform clip;

			public float textW;

			public float clipW;
		}

		public static readonly Color Red = new Color(1f, 0.33f, 0.29f);

		public static readonly Color RedLine = new Color(0.86f, 0.22f, 0.2f, 0.95f);

		public static readonly Color RedDim = new Color(0.62f, 0.16f, 0.15f, 0.75f);

		public static readonly Color Cyan = new Color(0.37f, 0.96f, 1f);

		public static readonly Color CyanDim = new Color(0.37f, 0.96f, 1f, 0.35f);

		public static readonly Color Teal = new Color(0.55f, 0.8f, 0.8f);

		public static readonly Color Yellow = new Color(0.95f, 0.86f, 0.42f);

		public static readonly Color Grey = new Color(0.72f, 0.72f, 0.72f);

		public static readonly Color SelFill = new Color(0.06f, 0.27f, 0.3f, 0.62f);

		public const float W = 600f;

		public const float H = 822f;

		public const int VisibleRows = 9;

		private const float ListY = 284f;

		private const float RowH = 48f;

		private const float ListW = 582f;

		private const int RowFont = 20;

		private int lastSel = -2;

		private float marquee;

		private float nowMarquee;

		private RectTransform nowClip;

		private float nowClipW = 364f;

		private Text shuffleText;

		private RectTransform progHit;

		public readonly GameObject root;

		public readonly RectTransform panel;

		private readonly Font font;

		private readonly Font bold;

		private readonly CanvasGroup panelGroup;

		private readonly CanvasGroup dimGroup;

		private readonly CanvasGroup hudGroup;

		private readonly RectTransform hudRect;

		private readonly Image holdFill;

		private readonly Image[] hudBars = (Image[])(object)new Image[4];

		private readonly Text toast;

		private float toastT;

		private readonly Text nowLabel;

		private readonly Text trackText;

		private readonly Text subText;

		private readonly Text timeText;

		private readonly Text volText;

		private readonly Image progFill;

		private readonly Image[] volTicks = (Image[])(object)new Image[20];

		private readonly GameObject emblemGroup;

		private readonly GameObject noStationGroup;

		private readonly Text emblemFreq;

		private readonly Text emblemName;

		private readonly RawImage logoImage;

		private readonly Text logoInfo;

		private readonly RectTransform scrollThumb;

		private readonly GameObject scrollGroup;

		private readonly GameObject emptyGroup;

		private readonly Text emptyHint;

		private readonly Row[] rows = new Row[9];

		private int rowCount;

		private int firstRow;

		private int selected = -1;

		private int playingRow = -1;

		private bool playing;

		private float open;

		private float openTarget;

		private float openSpeed;

		private float time;

		private static Texture2D white;

		private static Texture2D ring;

		private static Texture2D scan;

		private bool hudShow = true;

		private float hold;

		private const float MarqueeHold = 1.4f;

		private const float MarqueeSpeed = 45f;

		public bool IsOpen => openTarget > 0.5f;

		public bool IsVisible => open > 0.001f;

		public float OpenAmount => open;

		public RadioportUI(Font regular, Font semiBold, Transform parent)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Expected O, but got Unknown
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0516: Expected O, but got Unknown
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05df: Unknown result type (might be due to invalid IL or missing references)
			//IL_061f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Expected O, but got Unknown
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_0658: Expected O, but got Unknown
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_0686: Unknown result type (might be due to invalid IL or missing references)
			//IL_06df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0707: Unknown result type (might be due to invalid IL or missing references)
			//IL_0740: Unknown result type (might be due to invalid IL or missing references)
			//IL_0774: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0811: Unknown result type (might be due to invalid IL or missing references)
			//IL_0869: Unknown result type (might be due to invalid IL or missing references)
			//IL_088f: Unknown result type (might be due to invalid IL or missing references)
			//IL_08bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0929: Unknown result type (might be due to invalid IL or missing references)
			//IL_097a: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aa1: Expected O, but got Unknown
			//IL_0aac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad0: Expected O, but got Unknown
			//IL_0b12: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b3d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b74: Expected O, but got Unknown
			//IL_0b7f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba3: Expected O, but got Unknown
			//IL_0bc5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c4c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c73: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dc3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e0c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e13: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e15: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e16: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e1c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e32: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e4c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eb2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0efb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f56: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f9b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fff: Unknown result type (might be due to invalid IL or missing references)
			//IL_103a: Unknown result type (might be due to invalid IL or missing references)
			font = (Object.op_Implicit((Object)(object)regular) ? regular : Resources.GetBuiltinResource<Font>("Arial.ttf"));
			bold = (Object.op_Implicit((Object)(object)semiBold) ? semiBold : font);
			MakeTextures();
			root = new GameObject("RadioportCanvas", new Type[1] { typeof(RectTransform) });
			if (Object.op_Implicit((Object)(object)parent))
			{
				root.transform.SetParent(parent, false);
			}
			Canvas obj = root.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 30000;
			CanvasScaler obj2 = root.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 1f;
			root.AddComponent<GraphicRaycaster>();
			RectTransform val = Stretch(root.transform, "Dim");
			dimGroup = ((Component)val).gameObject.AddComponent<CanvasGroup>();
			Image obj3 = ((Component)val).gameObject.AddComponent<Image>();
			((Graphic)obj3).color = new Color(0.03f, 0.004f, 0.008f, 0.68f);
			((Graphic)obj3).raycastTarget = true;
			RawImage obj4 = ((Component)Stretch((Transform)(object)val, "Tint")).gameObject.AddComponent<RawImage>();
			obj4.texture = (Texture)(object)white;
			((Graphic)obj4).color = new Color(0.45f, 0.03f, 0.04f, 0.16f);
			((Graphic)obj4).raycastTarget = false;
			RawImage obj5 = ((Component)Stretch((Transform)(object)val, "Scan")).gameObject.AddComponent<RawImage>();
			obj5.texture = (Texture)(object)scan;
			((Graphic)obj5).color = new Color(1f, 0.3f, 0.3f, 0.05f);
			obj5.uvRect = new Rect(0f, 0f, 1f, 360f);
			((Graphic)obj5).raycastTarget = false;
			panel = new GameObject("Panel", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)panel).SetParent(root.transform, false);
			RectTransform obj6 = panel;
			RectTransform obj7 = panel;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			obj7.anchorMax = val2;
			obj6.anchorMin = val2;
			panel.pivot = new Vector2(0.5f, 0.5f);
			panel.sizeDelta = new Vector2(600f, 822f);
			panelGroup = ((Component)panel).gameObject.AddComponent<CanvasGroup>();
			T((Transform)(object)panel, 2f, 0f, 300f, 12f, 10, RedDim, font, (TextAnchor)0, "SYS_TCLAS_K1NG // RADIOPORT_V2");
			Img((Transform)(object)panel, 0f, 14f, 600f, 36f, new Color(0.08f, 0.01f, 0.01f, 0.55f));
			Frame((Transform)(object)panel, 0f, 14f, 600f, 36f, 12f, 1.5f, RedLine);
			Img((Transform)(object)panel, 0f, 14f, 5f, 36f, Red);
			T((Transform)(object)panel, 18f, 14f, 400f, 36f, 24, Red, bold, (TextAnchor)3, "RADIOPORT");
			Img((Transform)(object)panel, 0f, 62f, 220f, 202f, new Color(0.04f, 0f, 0f, 0.6f));
			Frame((Transform)(object)panel, 0f, 62f, 220f, 202f, 14f, 1.2f, RedDim, cutTopLeft: true);
			Img((Transform)(object)panel, 0f, 62f, 3f, 202f, RedLine);
			logoImage = new GameObject("Logo", new Type[1] { typeof(RectTransform) }).AddComponent<RawImage>();
			Place(((Graphic)logoImage).rectTransform, (Transform)(object)panel, 30f, 74f, 160f, 150f);
			((Graphic)logoImage).raycastTarget = false;
			((Component)logoImage).gameObject.SetActive(false);
			emblemGroup = new GameObject("Emblem", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)emblemGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f);
			Frame(emblemGroup.transform, 34f, 84f, 152f, 118f, 10f, 1.5f, Cyan);
			Frame(emblemGroup.transform, 40f, 90f, 140f, 106f, 6f, 1f, CyanDim);
			emblemFreq = T(emblemGroup.transform, 34f, 92f, 152f, 56f, 46, Cyan, bold, (TextAnchor)4, "88.9");
			emblemName = T(emblemGroup.transform, 40f, 148f, 140f, 46f, 17, Cyan, bold, (TextAnchor)1, "KING RADIO");
			emblemName.horizontalOverflow = (HorizontalWrapMode)0;
			noStationGroup = new GameObject("NoStation", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)noStationGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f);
			RawImage obj8 = new GameObject("Ring", new Type[1] { typeof(RectTransform) }).AddComponent<RawImage>();
			obj8.texture = (Texture)(object)ring;
			((Graphic)obj8).color = Cyan;
			((Graphic)obj8).raycastTarget = false;
			Place(((Graphic)obj8).rectTransform, noStationGroup.transform, 70f, 98f, 80f, 80f);
			Img(noStationGroup.transform, 86f, 135f, 48f, 6f, Cyan);
			logoInfo = T((Transform)(object)panel, 10f, 226f, 200f, 36f, 8, RedDim, font, (TextAnchor)6, "");
			nowLabel = T((Transform)(object)panel, 236f, 62f, 300f, 14f, 10, RedDim, font, (TextAnchor)0, "NOW PLAYING");
			nowClip = new GameObject("NowClip", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			Place(nowClip, (Transform)(object)panel, 236f, 82f, nowClipW, 34f);
			((Component)nowClip).gameObject.AddComponent<RectMask2D>();
			trackText = T((Transform)(object)nowClip, 0f, 0f, 3000f, 34f, 24, Red, bold, (TextAnchor)3, "NO TRACK");
			subText = T((Transform)(object)panel, 236f, 138f, 364f, 18f, 14, Yellow, font, (TextAnchor)0, "");
			Img((Transform)(object)panel, 236f, 166f, 364f, 2f, new Color(RedDim.r, RedDim.g, RedDim.b, 0.45f));
			progFill = Img((Transform)(object)panel, 236f, 165.5f, 0f, 3f, Red);
			timeText = T((Transform)(object)panel, 236f, 172f, 364f, 16f, 13, Grey, font, (TextAnchor)0, "");
			shuffleText = T((Transform)(object)panel, 236f, 172f, 364f, 16f, 13, CyanDim, bold, (TextAnchor)2, "SHUFFLE");
			progHit = new GameObject("ProgressHit", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			Place(progHit, (Transform)(object)panel, 236f, 156f, 364f, 22f);
			T((Transform)(object)panel, 236f, 214f, 140f, 32f, 19, Red, bold, (TextAnchor)3, "VOLUME");
			Key((Transform)(object)panel, 470f, 216f, 28f, "A");
			volText = T((Transform)(object)panel, 500f, 214f, 64f, 32f, 22, Cyan, bold, (TextAnchor)4, "80%");
			Key((Transform)(object)panel, 568f, 216f, 28f, "D");
			for (int i = 0; i < volTicks.Length; i++)
			{
				volTicks[i] = Img((Transform)(object)panel, 236f + (float)i * 18.2f, 254f, 14f, 4f, CyanDim);
			}
			for (int j = 0; j < 9; j++)
			{
				rows[j] = MakeRow(j);
			}
			scrollGroup = new GameObject("Scroll", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)scrollGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f);
			Img(scrollGroup.transform, 594f, 284f, 2f, 432f, new Color(RedDim.r, RedDim.g, RedDim.b, 0.4f));
			scrollThumb = ((Graphic)Img(scrollGroup.transform, 593f, 284f, 4f, 80f, Red)).rectTransform;
			emptyGroup = new GameObject("Empty", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)emptyGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f);
			T(emptyGroup.transform, 0f, 362f, 600f, 40f, 30, Red, bold, (TextAnchor)4, "NO TRACKS FOUND");
			emptyHint = T(emptyGroup.transform, 40f, 410f, 520f, 120f, 15, Grey, font, (TextAnchor)1, "");
			emptyHint.horizontalOverflow = (HorizontalWrapMode)0;
			emptyGroup.SetActive(false);
			Img((Transform)(object)panel, 0f, 740f, 600f, 1.5f, RedLine);
			T((Transform)(object)panel, 2f, 748f, 96f, 30f, 8, RedDim, font, (TextAnchor)0, "K1NG-OS // RADIOPORT\nLOCAL LIBRARY\nSIGNAL: OWNED");
			float right = 600f;
			right = Hint((Transform)(object)panel, right, 750f, "PREV/NEXT", "Q", "E");
			right = Hint((Transform)(object)panel, right - 14f, 750f, "SHUFFLE", "R");
			Hint((Transform)(object)panel, right - 14f, 750f, "SEEK", "←", "→");
			right = 600f;
			right = Hint((Transform)(object)panel, right, 782f, "CLOSE", "Z");
			right = Hint((Transform)(object)panel, right - 14f, 782f, "SELECT", "ENTER");
			Hint((Transform)(object)panel, right - 14f, 782f, "VOLUME", "A", "D");
			hudRect = new GameObject("HudHint", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)hudRect).SetParent(root.transform, false);
			RectTransform obj9 = hudRect;
			RectTransform obj10 = hudRect;
			RectTransform obj11 = hudRect;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 0f);
			obj11.pivot = val3;
			val2 = (obj9.anchorMin = (obj10.anchorMax = val3));
			hudRect.anchoredPosition = new Vector2(38f, 36f);
			hudRect.sizeDelta = new Vector2(400f, 34f);
			hudGroup = ((Component)hudRect).gameObject.AddComponent<CanvasGroup>();
			hudGroup.blocksRaycasts = false;
			hudGroup.interactable = false;
			Img((Transform)(object)hudRect, 0f, 0f, 30f, 30f, new Color(0f, 0f, 0f, 0.35f));
			holdFill = Img((Transform)(object)hudRect, 0f, 30f, 30f, 0f, new Color(Cyan.r, Cyan.g, Cyan.b, 0.4f));
			Frame((Transform)(object)hudRect, 0f, 0f, 30f, 30f, 0f, 1.5f, Cyan);
			T((Transform)(object)hudRect, 0f, 0f, 30f, 30f, 19, Cyan, bold, (TextAnchor)4, "Z");
			Img((Transform)(object)hudRect, 34f, 0f, 30f, 30f, new Color(0f, 0f, 0f, 0.35f));
			Frame((Transform)(object)hudRect, 34f, 0f, 30f, 30f, 6f, 1.5f, Cyan);
			for (int k = 0; k < hudBars.Length; k++)
			{
				hudBars[k] = Img((Transform)(object)hudRect, 41 + k * 5, 24f, 3f, 8f, Cyan);
			}
			toast = T((Transform)(object)hudRect, 74f, 0f, 520f, 30f, 16, Cyan, bold, (TextAnchor)3, "");
			toast.horizontalOverflow = (HorizontalWrapMode)1;
			open = 0f;
			Apply();
		}

		public void Open()
		{
			openTarget = 1f;
			openSpeed = 4.5454545f;
		}

		public void Close()
		{
			openTarget = 0f;
			openSpeed = 5.5555553f;
		}

		public void SetHud(bool show)
		{
			hudShow = show;
		}

		public void SetHold(float p)
		{
			hold = Mathf.Clamp01(p);
		}

		public void Toast(string s)
		{
			toast.text = s;
			toastT = 4.5f;
		}

		public void SetPlaying(bool isPlaying)
		{
			playing = isPlaying;
		}

		public void SetRows(List<RadioRow> data, int sel, int scrollTo)
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			rowCount = data.Count;
			selected = sel;
			if (scrollTo >= 0)
			{
				if (scrollTo < firstRow)
				{
					firstRow = scrollTo;
				}
				if (scrollTo >= firstRow + 9)
				{
					firstRow = scrollTo - 9 + 1;
				}
			}
			firstRow = Mathf.Clamp(firstRow, 0, Mathf.Max(0, rowCount - 9));
			playingRow = -1;
			for (int i = 0; i < 9; i++)
			{
				int num = firstRow + i;
				Row row = rows[i];
				bool flag = num < rowCount;
				((Component)row.rt).gameObject.SetActive(flag);
				if (flag)
				{
					RadioRow radioRow = data[num];
					bool flag2 = num == sel;
					row.selGroup.SetActive(flag2);
					row.listIcon.SetActive(!radioRow.playing);
					row.barsIcon.SetActive(radioRow.playing);
					if (radioRow.playing)
					{
						playingRow = i;
					}
					float num2 = (radioRow.isTrack ? 26f : 0f);
					row.clipW = 498f - num2;
					row.clip.anchoredPosition = new Vector2(40f + num2, 0f);
					row.clip.sizeDelta = new Vector2(row.clipW, 42f);
					((Graphic)row.text).rectTransform.anchoredPosition = Vector2.zero;
					row.listIcon.GetComponent<RectTransform>().anchoredPosition = new Vector2(12f + num2, -17f);
					row.barsIcon.GetComponent<RectTransform>().anchoredPosition = new Vector2(12f + num2, -17f);
					row.text.fontSize = 20;
					Color color = (Color)(radioRow.broken ? new Color(0.5f, 0.5f, 0.5f) : (flag2 ? Cyan : (radioRow.isTrack ? Grey : Teal)));
					((Graphic)row.text).color = color;
					string text = radioRow.text.ToUpperInvariant();
					if (radioRow.broken)
					{
						text += "  <color=#ff5a4e>[UNREADABLE]</color>";
					}
					else if (radioRow.isTrack && !string.IsNullOrEmpty(radioRow.sub))
					{
						text = text + "  <color=#" + ColorUtility.ToHtmlStringRGB(flag2 ? Yellow : (Yellow * 0.85f)) + ">// " + radioRow.sub.ToUpperInvariant() + "</color>";
					}
					row.text.text = text;
					row.textW = row.text.preferredWidth;
				}
			}
			if (sel != lastSel)
			{
				lastSel = sel;
				marquee = 0f;
			}
			bool num3 = rowCount > 9;
			scrollGroup.SetActive(true);
			float num4 = 432f;
			float num5 = (num3 ? Mathf.Max(30f, num4 * 9f / (float)rowCount) : num4);
			float num6 = (num3 ? ((num4 - num5) * (float)firstRow / (float)Mathf.Max(1, rowCount - 9)) : 0f);
			scrollThumb.sizeDelta = new Vector2(4f, num5);
			scrollThumb.anchoredPosition = new Vector2(593f, 0f - (284f + num6));
		}

		public void SetShuffle(bool on)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)shuffleText).color = (Color)(on ? Cyan : new Color(Cyan.r, Cyan.g, Cyan.b, 0.22f));
			shuffleText.text = (on ? "SHUFFLE ON" : "SHUFFLE OFF");
		}

		public float ProgressAt(Vector2 screen)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen || !RectTransformUtility.RectangleContainsScreenPoint(progHit, screen, (Camera)null))
			{
				return -1f;
			}
			Vector2 val = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(progHit, screen, (Camera)null, ref val);
			float x = val.x;
			Rect rect = progHit.rect;
			return Mathf.Clamp01(x / ((Rect)(ref rect)).width);
		}

		public void SetEmpty(bool empty, string hint)
		{
			emptyGroup.SetActive(empty);
			emptyHint.text = hint;
		}

		public void SetNow(string track, string sub, float progress, string timeLine, bool noStation, string freq, string stationName, Texture logo, string info)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			string text = (string.IsNullOrEmpty(track) ? "NO TRACK" : track);
			if (trackText.text != text)
			{
				trackText.text = text;
				nowMarquee = 0f;
			}
			subText.text = sub ?? "";
			((Graphic)progFill).rectTransform.sizeDelta = new Vector2(364f * Mathf.Clamp01(progress), 3f);
			timeText.text = timeLine ?? "";
			noStationGroup.SetActive(noStation);
			((Component)logoImage).gameObject.SetActive(!noStation && Object.op_Implicit((Object)(object)logo));
			if (Object.op_Implicit((Object)(object)logo))
			{
				logoImage.texture = logo;
			}
			emblemGroup.SetActive(!noStation && !Object.op_Implicit((Object)(object)logo));
			emblemFreq.text = freq ?? "";
			emblemName.text = (stationName ?? "").ToUpperInvariant();
			logoInfo.text = info ?? "";
		}

		public void SetVolume(float v)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			volText.text = Mathf.RoundToInt(v * 100f) + "%";
			int num = Mathf.RoundToInt(v * (float)volTicks.Length);
			for (int i = 0; i < volTicks.Length; i++)
			{
				((Graphic)volTicks[i]).color = (Color)((i < num) ? Cyan : new Color(Cyan.r, Cyan.g, Cyan.b, 0.16f));
			}
		}

		public int RowAt(Vector2 screen)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				return -1;
			}
			for (int i = 0; i < 9; i++)
			{
				if (((Component)rows[i].rt).gameObject.activeSelf && RectTransformUtility.RectangleContainsScreenPoint(rows[i].rt, screen, (Camera)null))
				{
					return firstRow + i;
				}
			}
			return -1;
		}

		public bool OverPanel(Vector2 screen)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return RectTransformUtility.RectangleContainsScreenPoint(panel, screen, (Camera)null);
		}

		public void Tick(float dt)
		{
			time += dt;
			if (open != openTarget)
			{
				open = Mathf.MoveTowards(open, openTarget, dt * openSpeed);
			}
			if (toastT > 0f)
			{
				toastT -= dt;
			}
			marquee += dt;
			nowMarquee += dt;
			Apply();
		}

		private void Apply()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			float num = ((openTarget > 0.5f) ? (1f - Mathf.Pow(1f - open, 3f)) : (open * open * (3f - 2f * open)));
			panelGroup.alpha = num;
			dimGroup.alpha = num;
			CanvasGroup obj = panelGroup;
			bool blocksRaycasts = (dimGroup.blocksRaycasts = open > 0.5f);
			obj.blocksRaycasts = blocksRaycasts;
			panel.anchoredPosition = new Vector2(70f * (1f - num), 0f);
			((Component)panel).gameObject.SetActive(open > 0.001f);
			((Component)dimGroup).gameObject.SetActive(open > 0.001f);
			float num2 = (hudShow ? (1f - Mathf.Clamp01(open * 3f)) : 0f);
			hudGroup.alpha = Mathf.MoveTowards(hudGroup.alpha, num2, 0.15f);
			((Graphic)holdFill).rectTransform.sizeDelta = new Vector2(30f, 30f * hold);
			((Graphic)holdFill).rectTransform.anchoredPosition = new Vector2(0f, 0f - (30f - 30f * hold));
			for (int i = 0; i < hudBars.Length; i++)
			{
				float num3 = (playing ? (6f + 14f * (0.5f + 0.5f * Mathf.Sin(time * (5.3f + (float)i * 1.7f) + (float)i * 1.3f)) * (0.6f + 0.4f * Mathf.Sin(time * 2.1f + (float)i))) : (4f + (float)i * 4f));
				((Graphic)hudBars[i]).rectTransform.sizeDelta = new Vector2(3f, num3);
				((Graphic)hudBars[i]).rectTransform.anchoredPosition = new Vector2((float)(41 + i * 5), 0f - (24f - num3 + 0f) + 0f - 0f);
				((Graphic)hudBars[i]).rectTransform.anchoredPosition = new Vector2((float)(41 + i * 5), 0f - (25f - num3));
				((Graphic)hudBars[i]).color = (playing ? Cyan : CyanDim);
			}
			((Graphic)toast).color = new Color(Cyan.r, Cyan.g, Cyan.b, Mathf.Clamp01(toastT) * (1f - Mathf.Clamp01(open * 3f)));
			if (playingRow >= 0)
			{
				for (int j = 0; j < 3; j++)
				{
					float num4 = (playing ? (4f + 10f * (0.5f + 0.5f * Mathf.Sin(time * (6f + (float)j * 2.3f) + (float)j))) : (6f + (float)j * 3f));
					RectTransform rectTransform = ((Graphic)rows[playingRow].bars[j]).rectTransform;
					rectTransform.sizeDelta = new Vector2(3f, num4);
					rectTransform.anchoredPosition = new Vector2((float)j * 5f, 0f - (14f - num4));
				}
			}
			for (int k = 0; k < 9; k++)
			{
				Row row = rows[k];
				if (((Component)row.rt).gameObject.activeSelf)
				{
					float num5 = 0f;
					if (firstRow + k == selected)
					{
						num5 = 0f - Scroll(marquee, row.textW - row.clipW + 8f);
					}
					((Graphic)row.text).rectTransform.anchoredPosition = new Vector2(num5, 0f);
				}
			}
			((Graphic)trackText).rectTransform.anchoredPosition = new Vector2(0f - Scroll(nowMarquee, trackText.preferredWidth - nowClipW + 8f), 0f);
			if (selected >= firstRow && selected < firstRow + 9)
			{
				((Graphic)rows[selected - firstRow].selFill).color = new Color(SelFill.r, SelFill.g, SelFill.b, SelFill.a * (0.85f + 0.15f * Mathf.Sin(time * 4f)));
			}
		}

		private static float Scroll(float t, float over)
		{
			if (over <= 0f)
			{
				return 0f;
			}
			float num = over / 45f;
			float num2 = 1.4f + num + 1.4f;
			t %= num2;
			if (t < 1.4f)
			{
				return 0f;
			}
			if (t < 1.4f + num)
			{
				float num3 = (t - 1.4f) / num;
				return over * (num3 * num3 * (3f - 2f * num3) * 0.25f + num3 * 0.75f);
			}
			return over;
		}

		private Row MakeRow(int i)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Expected O, but got Unknown
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Expected O, but got Unknown
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			Row row = new Row();
			row.rt = new GameObject("Row" + i, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			Place(row.rt, (Transform)(object)panel, 0f, 284f + (float)i * 48f, 582f, 42f);
			row.selGroup = new GameObject("Sel", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)row.selGroup.transform, (Transform)(object)row.rt, 0f, 0f, 582f, 42f);
			row.selFill = Img(row.selGroup.transform, 1f, 1f, 570f, 40f, SelFill);
			Frame(row.selGroup.transform, 0f, 0f, 582f, 42f, 12f, 1.5f, Cyan);
			Img(row.selGroup.transform, 0f, 0f, 3f, 42f, Cyan);
			Line(row.selGroup.transform, new Vector2(552f, 13f), new Vector2(560f, 21f), 2f, Cyan);
			Line(row.selGroup.transform, new Vector2(560f, 21f), new Vector2(552f, 29f), 2f, Cyan);
			row.listIcon = new GameObject("List", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)row.listIcon.transform, (Transform)(object)row.rt, 12f, 17f, 16f, 12f);
			for (int j = 0; j < 3; j++)
			{
				Img(row.listIcon.transform, 0f, j * 5, 3f, 2f, new Color(Teal.r, Teal.g, Teal.b, 0.55f));
				Img(row.listIcon.transform, 5f, j * 5, 11f, 2f, new Color(Teal.r, Teal.g, Teal.b, 0.55f));
			}
			row.barsIcon = new GameObject("Bars", new Type[1] { typeof(RectTransform) });
			Place((RectTransform)row.barsIcon.transform, (Transform)(object)row.rt, 12f, 17f, 16f, 14f);
			for (int k = 0; k < 3; k++)
			{
				row.bars[k] = Img(row.barsIcon.transform, k * 5, 6f, 3f, 8f, Cyan);
			}
			row.clip = new GameObject("Clip", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			Place(row.clip, (Transform)(object)row.rt, 40f, 0f, 498f, 42f);
			((Component)row.clip).gameObject.AddComponent<RectMask2D>();
			row.text = T((Transform)(object)row.clip, 0f, 0f, 3000f, 42f, 20, Teal, bold, (TextAnchor)3, "");
			row.text.supportRichText = true;
			Shadow obj = ((Component)row.text).gameObject.AddComponent<Shadow>();
			obj.effectColor = new Color(0f, 0f, 0f, 0.6f);
			obj.effectDistance = new Vector2(1f, -1f);
			return row;
		}

		private float Hint(Transform p, float right, float y, string label, params string[] keys)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Text obj = T(p, 0f, y, 200f, 24f, 16, Red, bold, (TextAnchor)3, label);
			float num = obj.preferredWidth + 2f;
			float num2 = right - num;
			((Graphic)obj).rectTransform.anchoredPosition = new Vector2(num2, 0f - y);
			((Graphic)obj).rectTransform.sizeDelta = new Vector2(num, 24f);
			for (int num3 = keys.Length - 1; num3 >= 0; num3--)
			{
				float num4 = ((keys[num3].Length > 1) ? (14f + (float)keys[num3].Length * 9f) : 24f);
				num2 -= num4 + 5f;
				Key(p, num2, y, num4, keys[num3], 24f);
			}
			return num2;
		}

		private void Key(Transform p, float x, float y, float w, string k, float h = -1f)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (h < 0f)
			{
				h = w;
			}
			Img(p, x, y, w, h, new Color(0f, 0.08f, 0.09f, 0.6f));
			Frame(p, x, y, w, h, 0f, 1.4f, Cyan);
			T(p, x, y, w, h, (k.Length > 1) ? 13 : ((int)(h * 0.62f)), Cyan, bold, (TextAnchor)4, k);
		}

		private static void MakeTextures()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)white))
			{
				return;
			}
			white = new Texture2D(1, 1);
			white.SetPixel(0, 0, Color.white);
			white.Apply();
			((Object)white).hideFlags = (HideFlags)61;
			ring = new Texture2D(128, 128, (TextureFormat)4, false);
			((Object)ring).hideFlags = (HideFlags)61;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(64f, 64f));
					float num2 = Mathf.Clamp01(1f - Mathf.Abs(num - 54f) / 2.2f) + Mathf.Clamp01(1f - Mathf.Abs(num - 46f) / 1.2f) * 0.45f;
					ring.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Clamp01(num2)));
				}
			}
			ring.Apply();
			scan = new Texture2D(1, 3, (TextureFormat)4, false);
			((Object)scan).hideFlags = (HideFlags)61;
			scan.SetPixel(0, 0, Color.white);
			scan.SetPixel(0, 1, new Color(1f, 1f, 1f, 0f));
			scan.SetPixel(0, 2, new Color(1f, 1f, 1f, 0f));
			((Texture)scan).wrapMode = (TextureWrapMode)0;
			((Texture)scan).filterMode = (FilterMode)0;
			scan.Apply();
		}

		private static RectTransform Stretch(Transform p, string name)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)component).SetParent(p, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			return component;
		}

		private static void Place(RectTransform rt, Transform p, float x, float y, float w, float h)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			((Transform)rt).SetParent(p, false);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rt.anchorMax = val;
			rt.anchorMin = val;
			rt.pivot = new Vector2(0f, 1f);
			rt.anchoredPosition = new Vector2(x, 0f - y);
			rt.sizeDelta = new Vector2(w, h);
		}

		private static Image Img(Transform p, float x, float y, float w, float h, Color c)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Image obj = new GameObject("I", new Type[1] { typeof(RectTransform) }).AddComponent<Image>();
			Place(((Graphic)obj).rectTransform, p, x, y, w, h);
			((Graphic)obj).color = c;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private Text T(Transform p, float x, float y, float w, float h, int size, Color c, Font f, TextAnchor a, string s)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			Text obj = new GameObject("T", new Type[1] { typeof(RectTransform) }).AddComponent<Text>();
			Place(((Graphic)obj).rectTransform, p, x, y, w, h);
			obj.font = f;
			obj.fontSize = size;
			((Graphic)obj).color = c;
			obj.alignment = a;
			obj.text = s;
			((Graphic)obj).raycastTarget = false;
			obj.horizontalOverflow = (HorizontalWrapMode)1;
			obj.verticalOverflow = (VerticalWrapMode)1;
			obj.supportRichText = true;
			return obj;
		}

		private static void Line(Transform p, Vector2 a, Vector2 b, float th, Color c)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: U