Decompiled source of Radio v0.4.2

BepInEx/patchers/SlipSkid.Radio.AudioBootstrap.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Preloader.Core.Patching;
using Microsoft.CodeAnalysis;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SlipSkid.Radio.AudioBootstrap
{
	[PatcherPluginInfo("slipskid.radio.audio", "Slip & Skid Radio Audio Bootstrap", "0.1.0")]
	public sealed class RadioAudioPatcher : BasePatcher
	{
		[TargetType("UnityEngine.AudioModule.dll", "UnityEngine.AudioClip")]
		public bool RestoreAudioClip(TypeDefinition clip)
		{
			return RestoreClipBindings(clip);
		}

		[TargetType("UnityEngine.AudioModule.dll", "UnityEngine.AudioSource")]
		public bool RestoreAudioSource(TypeDefinition source)
		{
			return RestoreSourceBindings(source);
		}

		public static bool RestoreSourceBindings(TypeDefinition source)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			if (((IEnumerable<MethodDefinition>)source.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == "UnPause" && !m.IsStatic && ((MethodReference)m).Parameters.Count == 0))
			{
				return false;
			}
			source.Methods.Add(new MethodDefinition("UnPause", (MethodAttributes)134, ((MemberReference)source).Module.TypeSystem.Void)
			{
				ImplAttributes = ((IEnumerable<MethodDefinition>)source.Methods).First((MethodDefinition m) => ((MemberReference)m).Name == "Pause").ImplAttributes
			});
			return true;
		}

		public static bool RestoreClipBindings(TypeDefinition clip)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			TypeSystem typeSystem = ((MemberReference)clip).Module.TypeSystem;
			return (byte)(0u | (Add(clip, "Construct_Internal", true, (TypeReference)(object)clip) ? 1u : 0u) | (Add(clip, "CreateUserSound", false, typeSystem.Void, typeSystem.String, typeSystem.Int32, typeSystem.Int32, typeSystem.Int32, typeSystem.Boolean) ? 1u : 0u) | (Add(clip, "SetData", true, typeSystem.Boolean, (TypeReference)clip, (TypeReference)new ArrayType(typeSystem.Single), typeSystem.Int32, typeSystem.Int32) ? 1u : 0u)) != 0;
		}

		private static bool Add(TypeDefinition type, string name, bool isStatic, TypeReference result, params TypeReference[] parameters)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			if (((IEnumerable<MethodDefinition>)type.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == name && m.IsStatic == isStatic && ((IEnumerable<ParameterDefinition>)((MethodReference)m).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName).SequenceEqual(parameters.Select((TypeReference p) => ((MemberReference)p).FullName))))
			{
				return false;
			}
			MethodDefinition val = new MethodDefinition(name, (MethodAttributes)(1 | (isStatic ? 16 : 0) | 0x80), result)
			{
				ImplAttributes = ((IEnumerable<MethodDefinition>)type.Methods).First((MethodDefinition m) => ((MemberReference)m).Name == "GetName").ImplAttributes
			};
			for (int num = 0; num < parameters.Length; num++)
			{
				((MethodReference)val).Parameters.Add(new ParameterDefinition("arg" + num, (ParameterAttributes)0, parameters[num]));
			}
			type.Methods.Add(val);
			return true;
		}
	}
}

BepInEx/plugins/SlipSkid.Radio/NLayer.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using NLayer.Decoder;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Mark Heath, Andrew Ward")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("© Mark Heath 2026")]
[assembly: AssemblyDescription("Fully Managed MPEG 1 & 2 Decoder for Layers 1, 2, & 3")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: AssemblyInformationalVersion("3.0.0+046c7ce422970f8f0f0bc205d6c6341bcb7debf1")]
[assembly: AssemblyProduct("NLayer")]
[assembly: AssemblyTitle("NLayer")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NLayer")]
[assembly: AssemblyVersion("3.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NLayer
{
	public enum MpegVersion
	{
		Unknown = 0,
		Version1 = 10,
		Version2 = 20,
		Version25 = 25
	}
	public enum MpegLayer
	{
		Unknown,
		LayerI,
		LayerII,
		LayerIII
	}
	public enum MpegChannelMode
	{
		Stereo,
		JointStereo,
		DualChannel,
		Mono
	}
	public enum StereoMode
	{
		Both,
		LeftOnly,
		RightOnly,
		DownmixToMono
	}
	public interface IMpegFrame
	{
		int SampleRate { get; }

		int SampleRateIndex { get; }

		int FrameLength { get; }

		int BitRate { get; }

		MpegVersion Version { get; }

		MpegLayer Layer { get; }

		MpegChannelMode ChannelMode { get; }

		int ChannelModeExtension { get; }

		int SampleCount { get; }

		int BitRateIndex { get; }

		bool IsCopyrighted { get; }

		bool HasCrc { get; }

		bool IsCorrupted { get; }

		void Reset();

		int ReadBits(int bitCount);
	}
	public class MpegFile : IDisposable
	{
		private Stream _stream;

		private bool _closeStream;

		private bool _eofFound;

		private MpegStreamReader _reader;

		private MpegFrameDecoder _decoder;

		private object _seekLock = new object();

		private long _position;

		private int _encoderDelay;

		private int _encoderPadding;

		private bool _decoderDelaySkipped;

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

		private int _readBufLen;

		private int _readBufOfs;

		public int SampleRate => _reader.SampleRate;

		public int Channels => OutputChannels;

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

		public bool CanSeek => _reader.CanSeek;

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

		public TimeSpan Duration
		{
			get
			{
				long sampleCount = _reader.SampleCount;
				if (sampleCount == -1)
				{
					return TimeSpan.Zero;
				}
				return TimeSpan.FromSeconds((double)(sampleCount - _encoderDelay - _encoderPadding) / (double)_reader.SampleRate);
			}
		}

		public long Position
		{
			get
			{
				return _position;
			}
			set
			{
				if (!_reader.CanSeek)
				{
					throw new InvalidOperationException("Cannot Seek!");
				}
				if (value < 0)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				long num = value / 4 / OutputChannels;
				int num2 = 0;
				if (num >= _reader.FirstFrameSampleCount)
				{
					num2 = _reader.FirstFrameSampleCount;
					num -= num2;
				}
				lock (_seekLock)
				{
					long num3 = _reader.SeekTo(num);
					if (num3 == -1)
					{
						throw new ArgumentOutOfRangeException("value");
					}
					_decoder.Reset();
					if (num2 != 0)
					{
						_decoder.DecodeFrame(_reader.NextFrame(), _readBuf, 0);
						num3 += num2;
					}
					_position = num3 * 4 * OutputChannels;
					_eofFound = false;
					_decoderDelaySkipped = num3 > 0 || _encoderDelay == 0;
					_readBufOfs = (_readBufLen = 0);
				}
			}
		}

		public TimeSpan Time
		{
			get
			{
				return TimeSpan.FromSeconds((double)_position / 4.0 / (double)OutputChannels / (double)_reader.SampleRate);
			}
			set
			{
				Position = (long)(value.TotalSeconds * (double)_reader.SampleRate * (double)OutputChannels * 4.0);
			}
		}

		public StereoMode StereoMode
		{
			get
			{
				return _decoder.StereoMode;
			}
			set
			{
				_decoder.StereoMode = value;
			}
		}

		public MpegFile(string fileName)
		{
			Init(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), closeStream: true);
		}

		public MpegFile(Stream stream)
		{
			Init(stream, closeStream: false);
		}

		private void Init(Stream stream, bool closeStream)
		{
			_stream = stream;
			_closeStream = closeStream;
			_reader = new MpegStreamReader(_stream);
			_decoder = new MpegFrameDecoder();
			_encoderDelay = _reader.EncoderDelay;
			_encoderPadding = _reader.EncoderPadding;
		}

		public void Dispose()
		{
			if (_closeStream)
			{
				_stream.Dispose();
				_closeStream = false;
			}
		}

		public void SetEQ(float[] eq)
		{
			_decoder.SetEQ(eq);
		}

		public int ReadSamples(byte[] buffer, int index, int count)
		{
			if (index < 0 || index + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			count -= count % 4;
			return ReadSamplesImpl(buffer, index, count, 32);
		}

		public int ReadSamples(float[] buffer, int index, int count)
		{
			if (index < 0 || index + count > buffer.Length)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			return ReadSamplesImpl(buffer, index * 4, count * 4, 32) / 4;
		}

		public int ReadSamplesInt16(byte[] buffer, int index, int count)
		{
			if (index < 0 || index + count > buffer.Length * 2)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			return ReadSamplesImpl(buffer, index, count, 16) * 2 / 4;
		}

		public int ReadSamplesInt8(byte[] buffer, int index, int count)
		{
			if (index < 0 || index + count > buffer.Length * 4)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			return ReadSamplesImpl(buffer, index, count, 8) / 4;
		}

		private long GetTotalBytes()
		{
			long sampleCount = _reader.SampleCount;
			if (sampleCount < 0)
			{
				return long.MaxValue;
			}
			return (sampleCount - _encoderDelay - _encoderPadding) * OutputChannels * 4;
		}

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

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

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

		private int ReadSamplesImpl(Array buffer, int index, int count, int bitDepth)
		{
			int num = 0;
			long totalBytes = GetTotalBytes();
			lock (_seekLock)
			{
				while (count > 0)
				{
					if (_position >= totalBytes)
					{
						_eofFound = true;
						break;
					}
					int num2 = AvailableBytes(totalBytes, count);
					if (num2 > 0)
					{
						if (bitDepth == 32)
						{
							Buffer.BlockCopy(_readBuf, _readBufOfs, buffer, index, num2);
						}
						else
						{
							byte[] array = (byte[])buffer;
							int num3 = _readBufOfs / 4;
							int num4 = index / 4;
							int num5 = num2 / 4;
							if (bitDepth == 8)
							{
								for (int i = 0; i < num5; i++)
								{
									array[num4 + i] = (byte)Math.Round(127.5f * _readBuf[num3 + i] + 127.5f);
								}
							}
							else
							{
								for (int j = 0; j < num5; j++)
								{
									int num6 = (int)Math.Round(32767.5f * _readBuf[num3 + j] - 0.5f);
									if (num6 < 0)
									{
										num6 += 65536;
									}
									array[2 * (num4 + j)] = (byte)(num6 % 256);
									array[2 * (num4 + j) + 1] = (byte)(num6 / 256);
								}
							}
						}
						num += num2;
						count -= num2;
						index += num2;
						AdvanceReadBuffer(num2);
					}
					if (_readBufLen == 0 && !TryFillReadBuffer())
					{
						break;
					}
				}
			}
			return num;
		}
	}
	public class MpegFrameDecoder
	{
		private LayerIDecoder _layerIDecoder;

		private LayerIIDecoder _layerIIDecoder;

		private LayerIIIDecoder _layerIIIDecoder;

		private float[] _eqFactors;

		private float[] _ch0;

		private float[] _ch1;

		public StereoMode StereoMode { get; set; }

		public MpegFrameDecoder()
		{
			_ch0 = new float[1152];
			_ch1 = new float[1152];
		}

		public void SetEQ(float[] eq)
		{
			if (eq != null)
			{
				float[] array = new float[32];
				for (int i = 0; i < eq.Length; i++)
				{
					array[i] = (float)Math.Pow(2.0, eq[i] / 6f);
				}
				_eqFactors = array;
			}
			else
			{
				_eqFactors = null;
			}
		}

		public int DecodeFrame(IMpegFrame frame, byte[] dest, int destOffset)
		{
			if (frame == null)
			{
				throw new ArgumentNullException("frame");
			}
			if (dest == null)
			{
				throw new ArgumentNullException("dest");
			}
			if (destOffset % 4 != 0)
			{
				throw new ArgumentException("Must be an even multiple of 4", "destOffset");
			}
			if ((dest.Length - destOffset) / 4 < RequiredSampleCount(frame))
			{
				throw new ArgumentException("Buffer not large enough!  Must be big enough to hold the frame's entire output.  This is up to 9,216 bytes.", "dest");
			}
			return DecodeFrameImpl(frame, dest, destOffset / 4) * 4;
		}

		public int DecodeFrame(IMpegFrame frame, float[] dest, int destOffset)
		{
			if (frame == null)
			{
				throw new ArgumentNullException("frame");
			}
			if (dest == null)
			{
				throw new ArgumentNullException("dest");
			}
			if (dest.Length - destOffset < RequiredSampleCount(frame))
			{
				throw new ArgumentException("Buffer not large enough!  Must be big enough to hold the frame's entire output.  This is up to 2,304 elements.", "dest");
			}
			return DecodeFrameImpl(frame, dest, destOffset);
		}

		private int DecodeToChannels(IMpegFrame frame)
		{
			frame.Reset();
			LayerDecoderBase layerDecoderBase = null;
			switch (frame.Layer)
			{
			case MpegLayer.LayerI:
				if (_layerIDecoder == null)
				{
					_layerIDecoder = new LayerIDecoder();
				}
				layerDecoderBase = _layerIDecoder;
				break;
			case MpegLayer.LayerII:
				if (_layerIIDecoder == null)
				{
					_layerIIDecoder = new LayerIIDecoder();
				}
				layerDecoderBase = _layerIIDecoder;
				break;
			case MpegLayer.LayerIII:
				if (_layerIIIDecoder == null)
				{
					_layerIIIDecoder = new LayerIIIDecoder();
				}
				layerDecoderBase = _layerIIIDecoder;
				break;
			}
			if (layerDecoderBase == null)
			{
				return 0;
			}
			layerDecoderBase.SetEQ(_eqFactors);
			layerDecoderBase.StereoMode = StereoMode;
			return layerDecoderBase.DecodeFrame(frame, _ch0, _ch1);
		}

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

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

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

		public void Reset()
		{
			if (_layerIDecoder != null)
			{
				_layerIDecoder.ResetForSeek();
			}
			if (_layerIIDecoder != null)
			{
				_layerIIDecoder.ResetForSeek();
			}
			if (_layerIIIDecoder != null)
			{
				_layerIIIDecoder.ResetForSeek();
			}
		}
	}
}
namespace NLayer.Decoder
{
	internal class BitReservoir
	{
		private byte[] _buf = new byte[8192];

		private int _start;

		private int _end = -1;

		private int _bitsLeft;

		private long _bitsRead;

		public int BitsAvailable
		{
			get
			{
				if (_bitsLeft > 0)
				{
					return (_end + _buf.Length - _start) % _buf.Length * 8 + _bitsLeft;
				}
				return 0;
			}
		}

		public long BitsRead => _bitsRead;

		private static int GetSlots(IMpegFrame frame)
		{
			int num = frame.FrameLength - 4;
			if (frame.HasCrc)
			{
				num -= 2;
			}
			if (frame.Version == MpegVersion.Version1 && frame.ChannelMode != MpegChannelMode.Mono)
			{
				return num - 32;
			}
			if (frame.Version > MpegVersion.Version1 && frame.ChannelMode == MpegChannelMode.Mono)
			{
				return num - 9;
			}
			return num - 17;
		}

		public bool AddBits(IMpegFrame frame, int overlap)
		{
			int end = _end;
			int num = GetSlots(frame);
			while (--num >= 0)
			{
				int num2 = frame.ReadBits(8);
				if (num2 == -1)
				{
					throw new InvalidDataException("Frame did not have enough bytes!");
				}
				_buf[++_end] = (byte)num2;
				if (_end == _buf.Length - 1)
				{
					_end = -1;
				}
			}
			_bitsLeft = 8;
			if (end == -1)
			{
				return overlap == 0;
			}
			if ((end + 1 - _start + _buf.Length) % _buf.Length >= overlap)
			{
				_start = (end + 1 - overlap + _buf.Length) % _buf.Length;
				return true;
			}
			_start = end + overlap;
			return false;
		}

		public int GetBits(int count)
		{
			int readCount;
			int result = TryPeekBits(count, out readCount);
			if (readCount < count)
			{
				throw new InvalidDataException("Reservoir did not have enough bytes!");
			}
			SkipBits(count);
			return result;
		}

		public int Get1Bit()
		{
			if (_bitsLeft == 0)
			{
				throw new InvalidDataException("Reservoir did not have enough bytes!");
			}
			_bitsLeft--;
			_bitsRead++;
			int result = (_buf[_start] >> _bitsLeft) & 1;
			if (_bitsLeft == 0 && (_start = (_start + 1) % _buf.Length) != _end + 1)
			{
				_bitsLeft = 8;
			}
			return result;
		}

		public int TryPeekBits(int count, out int readCount)
		{
			if (count < 0 || count > 32)
			{
				throw new ArgumentOutOfRangeException("count", "Must return between 0 and 32 bits!");
			}
			if (_bitsLeft == 0 || count == 0)
			{
				readCount = 0;
				return 0;
			}
			int num = _buf[_start];
			if (count < _bitsLeft)
			{
				num >>= _bitsLeft - count;
				num &= (1 << count) - 1;
				readCount = count;
				return num;
			}
			num &= (1 << _bitsLeft) - 1;
			count -= _bitsLeft;
			readCount = _bitsLeft;
			int num2 = _start;
			while (count > 0 && (num2 = (num2 + 1) % _buf.Length) != _end + 1)
			{
				int num3 = Math.Min(count, 8);
				num <<= num3;
				num |= _buf[num2] >> (8 - num3) % 8;
				count -= num3;
				readCount += num3;
			}
			return num;
		}

		public void SkipBits(int count)
		{
			if (count > 0)
			{
				if (count > BitsAvailable)
				{
					throw new ArgumentOutOfRangeException("count");
				}
				int num = 8 - _bitsLeft + count;
				_start = (num / 8 + _start) % _buf.Length;
				_bitsLeft = 8 - num % 8;
				_bitsRead += count;
			}
		}

		public void RewindBits(int count)
		{
			_bitsLeft += count;
			_bitsRead -= count;
			while (_bitsLeft > 8)
			{
				_start--;
				_bitsLeft -= 8;
			}
			while (_start < 0)
			{
				_start += _buf.Length;
			}
		}

		public void FlushBits()
		{
			if (_bitsLeft < 8)
			{
				SkipBits(_bitsLeft);
			}
		}

		public void Reset()
		{
			_start = 0;
			_end = -1;
			_bitsLeft = 0;
		}
	}
	internal abstract class FrameBase
	{
		private static int _totalAllocation;

		private MpegStreamReader _reader;

		private byte[] _savedBuffer;

		internal static int TotalAllocation => Interlocked.CompareExchange(ref _totalAllocation, 0, 0);

		internal long Offset { get; private set; }

		internal int Length { get; set; }

		internal bool Validate(long offset, MpegStreamReader reader)
		{
			Offset = offset;
			_reader = reader;
			int num = Validate();
			if (num > 0)
			{
				Length = num;
				return true;
			}
			return false;
		}

		protected int Read(int offset, byte[] buffer)
		{
			return Read(offset, buffer, 0, buffer.Length);
		}

		protected int Read(int offset, byte[] buffer, int index, int count)
		{
			if (_savedBuffer != null)
			{
				if (index < 0 || index + count > buffer.Length)
				{
					return 0;
				}
				if (offset < 0 || offset >= _savedBuffer.Length)
				{
					return 0;
				}
				if (offset + count > _savedBuffer.Length)
				{
					count = _savedBuffer.Length - index;
				}
				Array.Copy(_savedBuffer, offset, buffer, index, count);
				return count;
			}
			return _reader.Read(Offset + offset, buffer, index, count);
		}

		protected int ReadByte(int offset)
		{
			if (_savedBuffer != null)
			{
				if (offset < 0)
				{
					throw new ArgumentOutOfRangeException();
				}
				if (offset >= _savedBuffer.Length)
				{
					return -1;
				}
				return _savedBuffer[offset];
			}
			return _reader.ReadByte(Offset + offset);
		}

		protected abstract int Validate();

		internal void SaveBuffer()
		{
			_savedBuffer = new byte[Length];
			_reader.Read(Offset, _savedBuffer, 0, Length);
			Interlocked.Add(ref _totalAllocation, Length);
		}

		internal void ClearBuffer()
		{
			Interlocked.Add(ref _totalAllocation, -Length);
			_savedBuffer = null;
		}

		internal virtual void Parse()
		{
		}
	}
	internal class Huffman
	{
		private class HuffmanListNode
		{
			internal byte Value;

			internal int Length;

			internal int Bits;

			internal int Mask;

			internal HuffmanListNode Next;
		}

		private static readonly byte[][,] _codeTables;

		private static readonly float[] _floatLookup;

		private static HuffmanListNode[] _llCache;

		private static int[] _llCacheMaxBits;

		private static readonly int[] LIN_BITS;

		static Huffman()
		{
			_codeTables = new byte[17][,]
			{
				new byte[7, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 2, 1 },
					{ 0, 16 },
					{ 2, 1 },
					{ 0, 1 },
					{ 0, 17 }
				},
				new byte[17, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 33 },
					{ 2, 1 },
					{ 0, 18 },
					{ 2, 1 },
					{ 0, 2 },
					{ 0, 34 }
				},
				new byte[17, 2]
				{
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 2, 1 },
					{ 0, 16 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 33 },
					{ 2, 1 },
					{ 0, 18 },
					{ 2, 1 },
					{ 0, 2 },
					{ 0, 34 }
				},
				new byte[31, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 34 },
					{ 0, 48 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 19 },
					{ 2, 1 },
					{ 0, 49 },
					{ 2, 1 },
					{ 0, 50 },
					{ 2, 1 },
					{ 0, 35 },
					{ 0, 51 }
				},
				new byte[31, 2]
				{
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 0, 16 },
					{ 0, 17 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 33 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 18 },
					{ 2, 1 },
					{ 0, 2 },
					{ 0, 34 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 50 },
					{ 2, 1 },
					{ 0, 35 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 51 }
				},
				new byte[71, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 0, 33 },
					{ 18, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 18 },
					{ 2, 1 },
					{ 0, 34 },
					{ 0, 48 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 50 },
					{ 2, 1 },
					{ 0, 35 },
					{ 0, 4 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 65 },
					{ 2, 1 },
					{ 0, 20 },
					{ 2, 1 },
					{ 0, 66 },
					{ 0, 36 },
					{ 12, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 51 },
					{ 0, 67 },
					{ 0, 80 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 52 },
					{ 0, 5 },
					{ 0, 81 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 21 },
					{ 2, 1 },
					{ 0, 82 },
					{ 0, 37 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 53 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 83 },
					{ 0, 84 },
					{ 2, 1 },
					{ 0, 69 },
					{ 0, 85 }
				},
				new byte[71, 2]
				{
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 14, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 2, 1 },
					{ 0, 34 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 3 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 4 },
					{ 2, 1 },
					{ 0, 65 },
					{ 2, 1 },
					{ 0, 20 },
					{ 0, 66 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 36 },
					{ 2, 1 },
					{ 0, 51 },
					{ 0, 80 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 67 },
					{ 0, 52 },
					{ 0, 81 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 21 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 82 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 37 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 53 },
					{ 2, 1 },
					{ 0, 83 },
					{ 2, 1 },
					{ 0, 69 },
					{ 2, 1 },
					{ 0, 84 },
					{ 0, 85 }
				},
				new byte[71, 2]
				{
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 0, 16 },
					{ 2, 1 },
					{ 0, 1 },
					{ 0, 17 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 33 },
					{ 2, 1 },
					{ 0, 18 },
					{ 2, 1 },
					{ 0, 2 },
					{ 0, 34 },
					{ 12, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 3 },
					{ 0, 49 },
					{ 2, 1 },
					{ 0, 19 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 65 },
					{ 0, 20 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 51 },
					{ 2, 1 },
					{ 0, 66 },
					{ 0, 36 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 4 },
					{ 0, 80 },
					{ 0, 67 },
					{ 2, 1 },
					{ 0, 52 },
					{ 0, 81 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 21 },
					{ 0, 82 },
					{ 2, 1 },
					{ 0, 37 },
					{ 0, 68 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 84 },
					{ 0, 83 },
					{ 2, 1 },
					{ 0, 53 },
					{ 2, 1 },
					{ 0, 69 },
					{ 0, 85 }
				},
				new byte[127, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 10, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 28, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 34 },
					{ 0, 48 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 50 },
					{ 2, 1 },
					{ 0, 35 },
					{ 0, 64 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 65 },
					{ 0, 20 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 4 },
					{ 0, 51 },
					{ 2, 1 },
					{ 0, 66 },
					{ 0, 36 },
					{ 28, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 80 },
					{ 0, 5 },
					{ 0, 96 },
					{ 2, 1 },
					{ 0, 97 },
					{ 0, 22 },
					{ 12, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 67 },
					{ 0, 52 },
					{ 0, 81 },
					{ 2, 1 },
					{ 0, 21 },
					{ 2, 1 },
					{ 0, 82 },
					{ 0, 37 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 38 },
					{ 0, 54 },
					{ 0, 113 },
					{ 20, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 23 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 83 },
					{ 0, 6 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 53 },
					{ 0, 69 },
					{ 0, 98 },
					{ 2, 1 },
					{ 0, 112 },
					{ 2, 1 },
					{ 0, 7 },
					{ 0, 100 },
					{ 14, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 114 },
					{ 0, 39 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 99 },
					{ 2, 1 },
					{ 0, 84 },
					{ 0, 85 },
					{ 2, 1 },
					{ 0, 70 },
					{ 0, 115 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 55 },
					{ 0, 101 },
					{ 2, 1 },
					{ 0, 86 },
					{ 0, 116 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 71 },
					{ 2, 1 },
					{ 0, 102 },
					{ 0, 117 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 87 },
					{ 0, 118 },
					{ 2, 1 },
					{ 0, 103 },
					{ 0, 119 }
				},
				new byte[127, 2]
				{
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 0, 18 },
					{ 24, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 33 },
					{ 2, 1 },
					{ 0, 34 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 3 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 4 },
					{ 2, 1 },
					{ 0, 65 },
					{ 0, 20 },
					{ 30, 1 },
					{ 16, 1 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 66 },
					{ 0, 36 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 51 },
					{ 0, 67 },
					{ 0, 80 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 52 },
					{ 0, 81 },
					{ 0, 97 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 22 },
					{ 2, 1 },
					{ 0, 6 },
					{ 0, 38 },
					{ 2, 1 },
					{ 0, 98 },
					{ 2, 1 },
					{ 0, 21 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 82 },
					{ 16, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 37 },
					{ 0, 68 },
					{ 0, 96 },
					{ 2, 1 },
					{ 0, 99 },
					{ 0, 54 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 112 },
					{ 0, 23 },
					{ 0, 113 },
					{ 16, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 7 },
					{ 0, 100 },
					{ 0, 114 },
					{ 2, 1 },
					{ 0, 39 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 83 },
					{ 0, 53 },
					{ 2, 1 },
					{ 0, 84 },
					{ 0, 69 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 70 },
					{ 0, 115 },
					{ 2, 1 },
					{ 0, 55 },
					{ 2, 1 },
					{ 0, 101 },
					{ 0, 86 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 85 },
					{ 0, 87 },
					{ 0, 116 },
					{ 2, 1 },
					{ 0, 71 },
					{ 0, 102 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 117 },
					{ 0, 118 },
					{ 2, 1 },
					{ 0, 103 },
					{ 0, 119 }
				},
				new byte[127, 2]
				{
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 2, 1 },
					{ 0, 0 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 16, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 34 },
					{ 0, 49 },
					{ 2, 1 },
					{ 0, 19 },
					{ 2, 1 },
					{ 0, 48 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 64 },
					{ 26, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 2, 1 },
					{ 0, 65 },
					{ 0, 51 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 20 },
					{ 0, 66 },
					{ 2, 1 },
					{ 0, 36 },
					{ 2, 1 },
					{ 0, 4 },
					{ 0, 80 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 67 },
					{ 0, 52 },
					{ 2, 1 },
					{ 0, 81 },
					{ 0, 21 },
					{ 28, 1 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 82 },
					{ 0, 37 },
					{ 2, 1 },
					{ 0, 83 },
					{ 0, 53 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 96 },
					{ 0, 22 },
					{ 0, 97 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 98 },
					{ 0, 38 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 6 },
					{ 0, 68 },
					{ 2, 1 },
					{ 0, 84 },
					{ 0, 69 },
					{ 18, 1 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 99 },
					{ 0, 54 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 112 },
					{ 0, 7 },
					{ 0, 113 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 23 },
					{ 0, 100 },
					{ 2, 1 },
					{ 0, 70 },
					{ 0, 114 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 39 },
					{ 2, 1 },
					{ 0, 85 },
					{ 0, 115 },
					{ 2, 1 },
					{ 0, 55 },
					{ 0, 86 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 101 },
					{ 0, 116 },
					{ 2, 1 },
					{ 0, 71 },
					{ 0, 102 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 117 },
					{ 0, 87 },
					{ 2, 1 },
					{ 0, 118 },
					{ 2, 1 },
					{ 0, 103 },
					{ 0, 119 }
				},
				new byte[511, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 2, 1 },
					{ 0, 1 },
					{ 0, 17 },
					{ 28, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 34 },
					{ 0, 48 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 49 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 19 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 4 },
					{ 0, 65 },
					{ 70, 1 },
					{ 28, 1 },
					{ 14, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 20 },
					{ 2, 1 },
					{ 0, 51 },
					{ 0, 66 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 36 },
					{ 0, 80 },
					{ 2, 1 },
					{ 0, 67 },
					{ 0, 52 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 81 },
					{ 0, 21 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 82 },
					{ 2, 1 },
					{ 0, 37 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 83 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 96 },
					{ 0, 6 },
					{ 2, 1 },
					{ 0, 97 },
					{ 0, 22 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 128 },
					{ 0, 8 },
					{ 0, 129 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 53 },
					{ 0, 98 },
					{ 2, 1 },
					{ 0, 38 },
					{ 0, 84 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 69 },
					{ 0, 99 },
					{ 2, 1 },
					{ 0, 54 },
					{ 0, 112 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 7 },
					{ 0, 85 },
					{ 0, 113 },
					{ 2, 1 },
					{ 0, 23 },
					{ 2, 1 },
					{ 0, 39 },
					{ 0, 55 },
					{ 72, 1 },
					{ 24, 1 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 24 },
					{ 0, 130 },
					{ 2, 1 },
					{ 0, 40 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 100 },
					{ 0, 70 },
					{ 0, 114 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 132 },
					{ 0, 72 },
					{ 2, 1 },
					{ 0, 144 },
					{ 0, 9 },
					{ 2, 1 },
					{ 0, 145 },
					{ 0, 25 },
					{ 24, 1 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 115 },
					{ 0, 101 },
					{ 2, 1 },
					{ 0, 86 },
					{ 0, 116 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 71 },
					{ 0, 102 },
					{ 0, 131 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 56 },
					{ 2, 1 },
					{ 0, 117 },
					{ 0, 87 },
					{ 2, 1 },
					{ 0, 146 },
					{ 0, 41 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 103 },
					{ 0, 133 },
					{ 2, 1 },
					{ 0, 88 },
					{ 0, 57 },
					{ 2, 1 },
					{ 0, 147 },
					{ 2, 1 },
					{ 0, 73 },
					{ 0, 134 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 160 },
					{ 2, 1 },
					{ 0, 104 },
					{ 0, 10 },
					{ 2, 1 },
					{ 0, 161 },
					{ 0, 26 },
					{ 68, 1 },
					{ 24, 1 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 162 },
					{ 0, 42 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 149 },
					{ 0, 89 },
					{ 2, 1 },
					{ 0, 163 },
					{ 0, 58 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 74 },
					{ 0, 150 },
					{ 2, 1 },
					{ 0, 176 },
					{ 0, 11 },
					{ 2, 1 },
					{ 0, 177 },
					{ 0, 27 },
					{ 20, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 178 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 118 },
					{ 0, 119 },
					{ 0, 148 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 135 },
					{ 0, 120 },
					{ 0, 164 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 105 },
					{ 0, 165 },
					{ 0, 43 },
					{ 12, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 90 },
					{ 0, 136 },
					{ 0, 179 },
					{ 2, 1 },
					{ 0, 59 },
					{ 2, 1 },
					{ 0, 121 },
					{ 0, 166 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 106 },
					{ 0, 180 },
					{ 0, 192 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 12 },
					{ 0, 152 },
					{ 0, 193 },
					{ 60, 1 },
					{ 22, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 28 },
					{ 2, 1 },
					{ 0, 137 },
					{ 0, 181 },
					{ 2, 1 },
					{ 0, 91 },
					{ 0, 194 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 44 },
					{ 0, 60 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 182 },
					{ 0, 107 },
					{ 2, 1 },
					{ 0, 196 },
					{ 0, 76 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 168 },
					{ 0, 138 },
					{ 2, 1 },
					{ 0, 208 },
					{ 0, 13 },
					{ 2, 1 },
					{ 0, 209 },
					{ 2, 1 },
					{ 0, 75 },
					{ 2, 1 },
					{ 0, 151 },
					{ 0, 167 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 195 },
					{ 2, 1 },
					{ 0, 122 },
					{ 0, 153 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 197 },
					{ 0, 92 },
					{ 0, 183 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 29 },
					{ 0, 210 },
					{ 2, 1 },
					{ 0, 45 },
					{ 2, 1 },
					{ 0, 123 },
					{ 0, 211 },
					{ 52, 1 },
					{ 28, 1 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 61 },
					{ 0, 198 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 108 },
					{ 0, 169 },
					{ 2, 1 },
					{ 0, 154 },
					{ 0, 212 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 184 },
					{ 0, 139 },
					{ 2, 1 },
					{ 0, 77 },
					{ 0, 199 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 124 },
					{ 0, 213 },
					{ 2, 1 },
					{ 0, 93 },
					{ 0, 224 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 225 },
					{ 0, 30 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 14 },
					{ 0, 46 },
					{ 0, 226 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 227 },
					{ 0, 109 },
					{ 2, 1 },
					{ 0, 140 },
					{ 0, 228 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 229 },
					{ 0, 186 },
					{ 0, 240 },
					{ 38, 1 },
					{ 16, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 241 },
					{ 0, 31 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 170 },
					{ 0, 155 },
					{ 0, 185 },
					{ 2, 1 },
					{ 0, 62 },
					{ 2, 1 },
					{ 0, 214 },
					{ 0, 200 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 78 },
					{ 2, 1 },
					{ 0, 215 },
					{ 0, 125 },
					{ 2, 1 },
					{ 0, 171 },
					{ 2, 1 },
					{ 0, 94 },
					{ 0, 201 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 15 },
					{ 2, 1 },
					{ 0, 156 },
					{ 0, 110 },
					{ 2, 1 },
					{ 0, 242 },
					{ 0, 47 },
					{ 32, 1 },
					{ 16, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 216 },
					{ 0, 141 },
					{ 0, 63 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 243 },
					{ 2, 1 },
					{ 0, 230 },
					{ 0, 202 },
					{ 2, 1 },
					{ 0, 244 },
					{ 0, 79 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 187 },
					{ 0, 172 },
					{ 2, 1 },
					{ 0, 231 },
					{ 0, 245 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 217 },
					{ 0, 157 },
					{ 2, 1 },
					{ 0, 95 },
					{ 0, 232 },
					{ 30, 1 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 111 },
					{ 2, 1 },
					{ 0, 246 },
					{ 0, 203 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 188 },
					{ 0, 173 },
					{ 0, 218 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 247 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 126 },
					{ 0, 127 },
					{ 0, 142 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 158 },
					{ 0, 174 },
					{ 0, 204 },
					{ 2, 1 },
					{ 0, 248 },
					{ 0, 143 },
					{ 18, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 219 },
					{ 0, 189 },
					{ 2, 1 },
					{ 0, 234 },
					{ 0, 249 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 159 },
					{ 0, 235 },
					{ 2, 1 },
					{ 0, 190 },
					{ 2, 1 },
					{ 0, 205 },
					{ 0, 250 },
					{ 14, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 221 },
					{ 0, 236 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 233 },
					{ 0, 175 },
					{ 0, 220 },
					{ 2, 1 },
					{ 0, 206 },
					{ 0, 251 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 191 },
					{ 0, 222 },
					{ 2, 1 },
					{ 0, 207 },
					{ 0, 238 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 223 },
					{ 0, 239 },
					{ 2, 1 },
					{ 0, 255 },
					{ 2, 1 },
					{ 0, 237 },
					{ 2, 1 },
					{ 0, 253 },
					{ 2, 1 },
					{ 0, 252 },
					{ 0, 254 }
				},
				new byte[511, 2]
				{
					{ 16, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 2, 1 },
					{ 0, 16 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 17 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 50, 1 },
					{ 16, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 34 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 49 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 19 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 64 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 14, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 4 },
					{ 0, 20 },
					{ 0, 65 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 51 },
					{ 0, 66 },
					{ 2, 1 },
					{ 0, 36 },
					{ 0, 67 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 52 },
					{ 2, 1 },
					{ 0, 80 },
					{ 0, 5 },
					{ 2, 1 },
					{ 0, 81 },
					{ 0, 21 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 82 },
					{ 0, 37 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 83 },
					{ 0, 97 },
					{ 90, 1 },
					{ 36, 1 },
					{ 18, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 53 },
					{ 2, 1 },
					{ 0, 96 },
					{ 0, 6 },
					{ 2, 1 },
					{ 0, 22 },
					{ 0, 98 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 38 },
					{ 0, 84 },
					{ 2, 1 },
					{ 0, 69 },
					{ 0, 99 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 54 },
					{ 2, 1 },
					{ 0, 112 },
					{ 0, 7 },
					{ 2, 1 },
					{ 0, 113 },
					{ 0, 85 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 23 },
					{ 0, 100 },
					{ 2, 1 },
					{ 0, 114 },
					{ 0, 39 },
					{ 24, 1 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 70 },
					{ 0, 115 },
					{ 2, 1 },
					{ 0, 55 },
					{ 0, 101 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 86 },
					{ 0, 128 },
					{ 2, 1 },
					{ 0, 8 },
					{ 0, 116 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 129 },
					{ 0, 24 },
					{ 2, 1 },
					{ 0, 130 },
					{ 0, 40 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 71 },
					{ 0, 102 },
					{ 2, 1 },
					{ 0, 131 },
					{ 0, 56 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 117 },
					{ 0, 87 },
					{ 2, 1 },
					{ 0, 132 },
					{ 0, 72 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 144 },
					{ 0, 25 },
					{ 0, 145 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 146 },
					{ 0, 118 },
					{ 2, 1 },
					{ 0, 103 },
					{ 0, 41 },
					{ 92, 1 },
					{ 36, 1 },
					{ 18, 1 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 133 },
					{ 0, 88 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 9 },
					{ 0, 119 },
					{ 0, 147 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 57 },
					{ 0, 148 },
					{ 2, 1 },
					{ 0, 73 },
					{ 0, 134 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 104 },
					{ 2, 1 },
					{ 0, 160 },
					{ 0, 10 },
					{ 2, 1 },
					{ 0, 161 },
					{ 0, 26 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 162 },
					{ 0, 42 },
					{ 2, 1 },
					{ 0, 149 },
					{ 0, 89 },
					{ 26, 1 },
					{ 14, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 163 },
					{ 2, 1 },
					{ 0, 58 },
					{ 0, 135 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 120 },
					{ 0, 164 },
					{ 2, 1 },
					{ 0, 74 },
					{ 0, 150 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 105 },
					{ 0, 176 },
					{ 0, 177 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 27 },
					{ 0, 165 },
					{ 0, 178 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 90 },
					{ 0, 43 },
					{ 2, 1 },
					{ 0, 136 },
					{ 0, 151 },
					{ 2, 1 },
					{ 0, 179 },
					{ 2, 1 },
					{ 0, 121 },
					{ 0, 59 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 106 },
					{ 0, 180 },
					{ 2, 1 },
					{ 0, 75 },
					{ 0, 193 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 152 },
					{ 0, 137 },
					{ 2, 1 },
					{ 0, 28 },
					{ 0, 181 },
					{ 80, 1 },
					{ 34, 1 },
					{ 16, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 91 },
					{ 0, 44 },
					{ 0, 194 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 11 },
					{ 0, 192 },
					{ 0, 166 },
					{ 2, 1 },
					{ 0, 167 },
					{ 0, 122 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 195 },
					{ 0, 60 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 12 },
					{ 0, 153 },
					{ 0, 182 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 107 },
					{ 0, 196 },
					{ 2, 1 },
					{ 0, 76 },
					{ 0, 168 },
					{ 20, 1 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 138 },
					{ 0, 197 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 208 },
					{ 0, 92 },
					{ 0, 209 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 183 },
					{ 0, 123 },
					{ 2, 1 },
					{ 0, 29 },
					{ 2, 1 },
					{ 0, 13 },
					{ 0, 45 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 210 },
					{ 0, 211 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 61 },
					{ 0, 198 },
					{ 2, 1 },
					{ 0, 108 },
					{ 0, 169 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 154 },
					{ 0, 184 },
					{ 0, 212 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 139 },
					{ 0, 77 },
					{ 2, 1 },
					{ 0, 199 },
					{ 0, 124 },
					{ 68, 1 },
					{ 34, 1 },
					{ 18, 1 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 213 },
					{ 0, 93 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 224 },
					{ 0, 14 },
					{ 0, 225 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 30 },
					{ 0, 226 },
					{ 2, 1 },
					{ 0, 170 },
					{ 0, 46 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 185 },
					{ 0, 155 },
					{ 2, 1 },
					{ 0, 227 },
					{ 0, 214 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 109 },
					{ 0, 62 },
					{ 2, 1 },
					{ 0, 200 },
					{ 0, 140 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 228 },
					{ 0, 78 },
					{ 2, 1 },
					{ 0, 215 },
					{ 0, 125 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 229 },
					{ 0, 186 },
					{ 2, 1 },
					{ 0, 171 },
					{ 0, 94 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 201 },
					{ 0, 156 },
					{ 2, 1 },
					{ 0, 241 },
					{ 0, 31 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 240 },
					{ 0, 110 },
					{ 0, 242 },
					{ 2, 1 },
					{ 0, 47 },
					{ 0, 230 },
					{ 38, 1 },
					{ 18, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 216 },
					{ 0, 243 },
					{ 2, 1 },
					{ 0, 63 },
					{ 0, 244 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 79 },
					{ 2, 1 },
					{ 0, 141 },
					{ 0, 217 },
					{ 2, 1 },
					{ 0, 187 },
					{ 0, 202 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 172 },
					{ 0, 231 },
					{ 2, 1 },
					{ 0, 126 },
					{ 0, 245 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 157 },
					{ 0, 95 },
					{ 2, 1 },
					{ 0, 232 },
					{ 0, 142 },
					{ 2, 1 },
					{ 0, 246 },
					{ 0, 203 },
					{ 34, 1 },
					{ 18, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 15 },
					{ 0, 174 },
					{ 0, 111 },
					{ 2, 1 },
					{ 0, 188 },
					{ 0, 218 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 173 },
					{ 0, 247 },
					{ 2, 1 },
					{ 0, 127 },
					{ 0, 233 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 158 },
					{ 0, 204 },
					{ 2, 1 },
					{ 0, 248 },
					{ 0, 143 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 219 },
					{ 0, 189 },
					{ 2, 1 },
					{ 0, 234 },
					{ 0, 249 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 159 },
					{ 0, 220 },
					{ 2, 1 },
					{ 0, 205 },
					{ 0, 235 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 190 },
					{ 0, 250 },
					{ 2, 1 },
					{ 0, 175 },
					{ 0, 221 },
					{ 14, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 236 },
					{ 0, 206 },
					{ 0, 251 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 191 },
					{ 0, 237 },
					{ 2, 1 },
					{ 0, 222 },
					{ 0, 252 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 207 },
					{ 0, 253 },
					{ 0, 238 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 223 },
					{ 0, 254 },
					{ 2, 1 },
					{ 0, 239 },
					{ 0, 255 }
				},
				new byte[511, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 16 },
					{ 2, 1 },
					{ 0, 1 },
					{ 0, 17 },
					{ 42, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 2, 1 },
					{ 0, 33 },
					{ 0, 18 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 34 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 3 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 4 },
					{ 0, 65 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 20 },
					{ 2, 1 },
					{ 0, 51 },
					{ 0, 66 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 36 },
					{ 0, 80 },
					{ 2, 1 },
					{ 0, 67 },
					{ 0, 52 },
					{ 138, 1 },
					{ 40, 1 },
					{ 16, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 21 },
					{ 0, 81 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 82 },
					{ 0, 37 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 53 },
					{ 0, 83 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 96 },
					{ 0, 6 },
					{ 0, 97 },
					{ 2, 1 },
					{ 0, 22 },
					{ 0, 98 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 38 },
					{ 0, 84 },
					{ 2, 1 },
					{ 0, 69 },
					{ 0, 99 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 54 },
					{ 0, 112 },
					{ 0, 113 },
					{ 40, 1 },
					{ 18, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 23 },
					{ 2, 1 },
					{ 0, 7 },
					{ 2, 1 },
					{ 0, 85 },
					{ 0, 100 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 114 },
					{ 0, 39 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 70 },
					{ 0, 101 },
					{ 0, 115 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 55 },
					{ 2, 1 },
					{ 0, 86 },
					{ 0, 8 },
					{ 2, 1 },
					{ 0, 128 },
					{ 0, 129 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 24 },
					{ 2, 1 },
					{ 0, 116 },
					{ 0, 71 },
					{ 2, 1 },
					{ 0, 130 },
					{ 2, 1 },
					{ 0, 40 },
					{ 0, 102 },
					{ 24, 1 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 131 },
					{ 0, 56 },
					{ 2, 1 },
					{ 0, 117 },
					{ 0, 132 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 72 },
					{ 0, 144 },
					{ 0, 145 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 25 },
					{ 2, 1 },
					{ 0, 9 },
					{ 0, 118 },
					{ 2, 1 },
					{ 0, 146 },
					{ 0, 41 },
					{ 14, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 133 },
					{ 0, 88 },
					{ 2, 1 },
					{ 0, 147 },
					{ 0, 57 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 160 },
					{ 0, 10 },
					{ 0, 26 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 162 },
					{ 2, 1 },
					{ 0, 103 },
					{ 2, 1 },
					{ 0, 87 },
					{ 0, 73 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 148 },
					{ 2, 1 },
					{ 0, 119 },
					{ 0, 134 },
					{ 2, 1 },
					{ 0, 161 },
					{ 2, 1 },
					{ 0, 104 },
					{ 0, 149 },
					{ 220, 1 },
					{ 126, 1 },
					{ 50, 1 },
					{ 26, 1 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 42 },
					{ 2, 1 },
					{ 0, 89 },
					{ 0, 58 },
					{ 2, 1 },
					{ 0, 163 },
					{ 2, 1 },
					{ 0, 135 },
					{ 0, 120 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 164 },
					{ 0, 74 },
					{ 2, 1 },
					{ 0, 150 },
					{ 0, 105 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 176 },
					{ 0, 11 },
					{ 0, 177 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 27 },
					{ 0, 178 },
					{ 2, 1 },
					{ 0, 43 },
					{ 2, 1 },
					{ 0, 165 },
					{ 0, 90 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 179 },
					{ 2, 1 },
					{ 0, 166 },
					{ 0, 106 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 180 },
					{ 0, 75 },
					{ 2, 1 },
					{ 0, 12 },
					{ 0, 193 },
					{ 30, 1 },
					{ 14, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 181 },
					{ 0, 194 },
					{ 0, 44 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 167 },
					{ 0, 195 },
					{ 2, 1 },
					{ 0, 107 },
					{ 0, 196 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 29 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 136 },
					{ 0, 151 },
					{ 0, 59 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 209 },
					{ 0, 210 },
					{ 2, 1 },
					{ 0, 45 },
					{ 0, 211 },
					{ 18, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 30 },
					{ 0, 46 },
					{ 0, 226 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 121 },
					{ 0, 152 },
					{ 0, 192 },
					{ 2, 1 },
					{ 0, 28 },
					{ 2, 1 },
					{ 0, 137 },
					{ 0, 91 },
					{ 14, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 60 },
					{ 2, 1 },
					{ 0, 122 },
					{ 0, 182 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 76 },
					{ 0, 153 },
					{ 2, 1 },
					{ 0, 168 },
					{ 0, 138 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 13 },
					{ 2, 1 },
					{ 0, 197 },
					{ 0, 92 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 61 },
					{ 0, 198 },
					{ 2, 1 },
					{ 0, 108 },
					{ 0, 154 },
					{ 88, 1 },
					{ 86, 1 },
					{ 36, 1 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 139 },
					{ 0, 77 },
					{ 2, 1 },
					{ 0, 199 },
					{ 0, 124 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 213 },
					{ 0, 93 },
					{ 2, 1 },
					{ 0, 224 },
					{ 0, 14 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 227 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 208 },
					{ 0, 183 },
					{ 0, 123 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 169 },
					{ 0, 184 },
					{ 0, 212 },
					{ 2, 1 },
					{ 0, 225 },
					{ 2, 1 },
					{ 0, 170 },
					{ 0, 185 },
					{ 24, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 155 },
					{ 0, 214 },
					{ 0, 109 },
					{ 2, 1 },
					{ 0, 62 },
					{ 0, 200 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 140 },
					{ 0, 228 },
					{ 0, 78 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 215 },
					{ 0, 229 },
					{ 2, 1 },
					{ 0, 186 },
					{ 0, 171 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 156 },
					{ 0, 230 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 110 },
					{ 0, 216 },
					{ 2, 1 },
					{ 0, 141 },
					{ 0, 187 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 231 },
					{ 0, 157 },
					{ 2, 1 },
					{ 0, 232 },
					{ 0, 142 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 203 },
					{ 0, 188 },
					{ 0, 158 },
					{ 0, 241 },
					{ 2, 1 },
					{ 0, 31 },
					{ 2, 1 },
					{ 0, 15 },
					{ 0, 47 },
					{ 66, 1 },
					{ 56, 1 },
					{ 2, 1 },
					{ 0, 242 },
					{ 52, 1 },
					{ 50, 1 },
					{ 20, 1 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 189 },
					{ 2, 1 },
					{ 0, 94 },
					{ 2, 1 },
					{ 0, 125 },
					{ 0, 201 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 202 },
					{ 2, 1 },
					{ 0, 172 },
					{ 0, 126 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 218 },
					{ 0, 173 },
					{ 0, 204 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 174 },
					{ 2, 1 },
					{ 0, 219 },
					{ 0, 220 },
					{ 2, 1 },
					{ 0, 205 },
					{ 0, 190 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 235 },
					{ 0, 237 },
					{ 0, 238 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 217 },
					{ 0, 234 },
					{ 0, 233 },
					{ 2, 1 },
					{ 0, 222 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 221 },
					{ 0, 236 },
					{ 0, 206 },
					{ 0, 63 },
					{ 0, 240 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 243 },
					{ 0, 244 },
					{ 2, 1 },
					{ 0, 79 },
					{ 2, 1 },
					{ 0, 245 },
					{ 0, 95 },
					{ 10, 1 },
					{ 2, 1 },
					{ 0, 255 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 246 },
					{ 0, 111 },
					{ 2, 1 },
					{ 0, 247 },
					{ 0, 127 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 143 },
					{ 2, 1 },
					{ 0, 248 },
					{ 0, 249 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 159 },
					{ 0, 250 },
					{ 0, 175 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 251 },
					{ 0, 191 },
					{ 2, 1 },
					{ 0, 252 },
					{ 0, 207 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 253 },
					{ 0, 223 },
					{ 2, 1 },
					{ 0, 254 },
					{ 0, 239 }
				},
				new byte[512, 2]
				{
					{ 60, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 0, 16 },
					{ 2, 1 },
					{ 0, 1 },
					{ 0, 17 },
					{ 14, 1 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 32 },
					{ 0, 2 },
					{ 0, 33 },
					{ 2, 1 },
					{ 0, 18 },
					{ 2, 1 },
					{ 0, 34 },
					{ 2, 1 },
					{ 0, 48 },
					{ 0, 3 },
					{ 14, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 49 },
					{ 0, 19 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 50 },
					{ 0, 35 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 64 },
					{ 0, 4 },
					{ 0, 65 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 20 },
					{ 0, 51 },
					{ 2, 1 },
					{ 0, 66 },
					{ 0, 36 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 67 },
					{ 0, 52 },
					{ 0, 81 },
					{ 6, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 80 },
					{ 0, 5 },
					{ 0, 21 },
					{ 2, 1 },
					{ 0, 82 },
					{ 0, 37 },
					{ 250, 1 },
					{ 98, 1 },
					{ 34, 1 },
					{ 18, 1 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 68 },
					{ 0, 83 },
					{ 2, 1 },
					{ 0, 53 },
					{ 2, 1 },
					{ 0, 96 },
					{ 0, 6 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 97 },
					{ 0, 22 },
					{ 2, 1 },
					{ 0, 98 },
					{ 0, 38 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 84 },
					{ 0, 69 },
					{ 2, 1 },
					{ 0, 99 },
					{ 0, 54 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 113 },
					{ 0, 85 },
					{ 2, 1 },
					{ 0, 100 },
					{ 0, 70 },
					{ 32, 1 },
					{ 14, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 114 },
					{ 2, 1 },
					{ 0, 39 },
					{ 0, 55 },
					{ 2, 1 },
					{ 0, 115 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 112 },
					{ 0, 7 },
					{ 0, 23 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 101 },
					{ 0, 86 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 128 },
					{ 0, 8 },
					{ 0, 129 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 116 },
					{ 0, 71 },
					{ 2, 1 },
					{ 0, 24 },
					{ 0, 130 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 40 },
					{ 0, 102 },
					{ 2, 1 },
					{ 0, 131 },
					{ 0, 56 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 117 },
					{ 0, 87 },
					{ 2, 1 },
					{ 0, 132 },
					{ 0, 72 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 145 },
					{ 0, 25 },
					{ 2, 1 },
					{ 0, 146 },
					{ 0, 118 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 103 },
					{ 0, 41 },
					{ 2, 1 },
					{ 0, 133 },
					{ 0, 88 },
					{ 92, 1 },
					{ 34, 1 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 147 },
					{ 0, 57 },
					{ 2, 1 },
					{ 0, 148 },
					{ 0, 73 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 119 },
					{ 0, 134 },
					{ 2, 1 },
					{ 0, 104 },
					{ 0, 161 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 162 },
					{ 0, 42 },
					{ 2, 1 },
					{ 0, 149 },
					{ 0, 89 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 163 },
					{ 0, 58 },
					{ 2, 1 },
					{ 0, 135 },
					{ 2, 1 },
					{ 0, 120 },
					{ 0, 74 },
					{ 22, 1 },
					{ 12, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 164 },
					{ 0, 150 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 105 },
					{ 0, 177 },
					{ 2, 1 },
					{ 0, 27 },
					{ 0, 165 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 178 },
					{ 2, 1 },
					{ 0, 90 },
					{ 0, 43 },
					{ 2, 1 },
					{ 0, 136 },
					{ 0, 179 },
					{ 16, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 144 },
					{ 2, 1 },
					{ 0, 9 },
					{ 0, 160 },
					{ 2, 1 },
					{ 0, 151 },
					{ 0, 121 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 166 },
					{ 0, 106 },
					{ 0, 180 },
					{ 12, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 26 },
					{ 2, 1 },
					{ 0, 10 },
					{ 0, 176 },
					{ 2, 1 },
					{ 0, 59 },
					{ 2, 1 },
					{ 0, 11 },
					{ 0, 192 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 75 },
					{ 0, 193 },
					{ 2, 1 },
					{ 0, 152 },
					{ 0, 137 },
					{ 67, 1 },
					{ 34, 1 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 28 },
					{ 0, 181 },
					{ 2, 1 },
					{ 0, 91 },
					{ 0, 194 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 44 },
					{ 0, 167 },
					{ 2, 1 },
					{ 0, 122 },
					{ 0, 195 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 60 },
					{ 2, 1 },
					{ 0, 12 },
					{ 0, 208 },
					{ 2, 1 },
					{ 0, 182 },
					{ 0, 107 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 196 },
					{ 0, 76 },
					{ 2, 1 },
					{ 0, 153 },
					{ 0, 168 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 138 },
					{ 0, 197 },
					{ 2, 1 },
					{ 0, 92 },
					{ 0, 209 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 183 },
					{ 0, 123 },
					{ 2, 1 },
					{ 0, 29 },
					{ 0, 210 },
					{ 9, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 45 },
					{ 0, 211 },
					{ 2, 1 },
					{ 0, 61 },
					{ 0, 198 },
					{ 85, 250 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 108 },
					{ 0, 169 },
					{ 2, 1 },
					{ 0, 154 },
					{ 0, 212 },
					{ 32, 1 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 184 },
					{ 0, 139 },
					{ 2, 1 },
					{ 0, 77 },
					{ 0, 199 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 124 },
					{ 0, 213 },
					{ 2, 1 },
					{ 0, 93 },
					{ 0, 225 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 30 },
					{ 0, 226 },
					{ 2, 1 },
					{ 0, 170 },
					{ 0, 185 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 155 },
					{ 0, 227 },
					{ 2, 1 },
					{ 0, 214 },
					{ 0, 109 },
					{ 20, 1 },
					{ 10, 1 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 62 },
					{ 2, 1 },
					{ 0, 46 },
					{ 0, 78 },
					{ 2, 1 },
					{ 0, 200 },
					{ 0, 140 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 228 },
					{ 0, 215 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 125 },
					{ 0, 171 },
					{ 0, 229 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 186 },
					{ 0, 94 },
					{ 2, 1 },
					{ 0, 201 },
					{ 2, 1 },
					{ 0, 156 },
					{ 0, 110 },
					{ 8, 1 },
					{ 2, 1 },
					{ 0, 230 },
					{ 2, 1 },
					{ 0, 13 },
					{ 2, 1 },
					{ 0, 224 },
					{ 0, 14 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 216 },
					{ 0, 141 },
					{ 2, 1 },
					{ 0, 187 },
					{ 0, 202 },
					{ 74, 1 },
					{ 2, 1 },
					{ 0, 255 },
					{ 64, 1 },
					{ 58, 1 },
					{ 32, 1 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 172 },
					{ 0, 231 },
					{ 2, 1 },
					{ 0, 126 },
					{ 0, 217 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 157 },
					{ 0, 232 },
					{ 2, 1 },
					{ 0, 142 },
					{ 0, 203 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 188 },
					{ 0, 218 },
					{ 2, 1 },
					{ 0, 173 },
					{ 0, 233 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 158 },
					{ 0, 204 },
					{ 2, 1 },
					{ 0, 219 },
					{ 0, 189 },
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 234 },
					{ 0, 174 },
					{ 2, 1 },
					{ 0, 220 },
					{ 0, 205 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 235 },
					{ 0, 190 },
					{ 2, 1 },
					{ 0, 221 },
					{ 0, 236 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 206 },
					{ 0, 237 },
					{ 2, 1 },
					{ 0, 222 },
					{ 0, 238 },
					{ 0, 15 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 240 },
					{ 0, 31 },
					{ 0, 241 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 242 },
					{ 0, 47 },
					{ 2, 1 },
					{ 0, 243 },
					{ 0, 63 },
					{ 18, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 244 },
					{ 0, 79 },
					{ 2, 1 },
					{ 0, 245 },
					{ 0, 95 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 246 },
					{ 0, 111 },
					{ 2, 1 },
					{ 0, 247 },
					{ 2, 1 },
					{ 0, 127 },
					{ 0, 143 },
					{ 10, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 248 },
					{ 0, 249 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 159 },
					{ 0, 175 },
					{ 0, 250 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 251 },
					{ 0, 191 },
					{ 2, 1 },
					{ 0, 252 },
					{ 0, 207 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 253 },
					{ 0, 223 },
					{ 2, 1 },
					{ 0, 254 },
					{ 0, 239 }
				},
				new byte[31, 2]
				{
					{ 2, 1 },
					{ 0, 0 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 8 },
					{ 0, 4 },
					{ 2, 1 },
					{ 0, 1 },
					{ 0, 2 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 12 },
					{ 0, 10 },
					{ 2, 1 },
					{ 0, 3 },
					{ 0, 6 },
					{ 6, 1 },
					{ 2, 1 },
					{ 0, 9 },
					{ 2, 1 },
					{ 0, 5 },
					{ 0, 7 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 14 },
					{ 0, 13 },
					{ 2, 1 },
					{ 0, 15 },
					{ 0, 11 }
				},
				new byte[31, 2]
				{
					{ 16, 1 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 0 },
					{ 0, 1 },
					{ 2, 1 },
					{ 0, 2 },
					{ 0, 3 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 4 },
					{ 0, 5 },
					{ 2, 1 },
					{ 0, 6 },
					{ 0, 7 },
					{ 8, 1 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 8 },
					{ 0, 9 },
					{ 2, 1 },
					{ 0, 10 },
					{ 0, 11 },
					{ 4, 1 },
					{ 2, 1 },
					{ 0, 12 },
					{ 0, 13 },
					{ 2, 1 },
					{ 0, 14 },
					{ 0, 15 }
				}
			};
			_llCache = new HuffmanListNode[_codeTables.Length];
			_llCacheMaxBits = new int[_codeTables.Length];
			LIN_BITS = new int[32]
			{
				0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
				6, 8, 10, 13, 4, 5, 6, 7, 8, 9,
				11, 13
			};
			_floatLookup = new float[8207];
			for (int i = 0; i < 8207; i++)
			{
				_floatLookup[i] = (float)Math.Pow(i, 1.3333333333333333);
			}
		}

		internal static void Decode(BitReservoir br, int table, out float x, out float y)
		{
			if (table == 0 || table == 4 || table == 14)
			{
				x = (y = 0f);
				return;
			}
			byte num = DecodeSymbol(br, table);
			int num2 = num >> 4;
			int num3 = num & 0xF;
			int num4 = LIN_BITS[table];
			if (num4 > 0 && num2 == 15)
			{
				num2 += br.GetBits(num4);
			}
			if (num2 != 0 && br.Get1Bit() != 0)
			{
				x = 0f - _floatLookup[num2];
			}
			else
			{
				x = _floatLookup[num2];
			}
			if (num4 > 0 && num3 == 15)
			{
				num3 += br.GetBits(num4);
			}
			if (num3 != 0 && br.Get1Bit() != 0)
			{
				y = 0f - _floatLookup[num3];
			}
			else
			{
				y = _floatLookup[num3];
			}
		}

		internal static void Decode(BitReservoir br, int table, out float x, out float y, out float v, out float w)
		{
			byte num = DecodeSymbol(br, table);
			v = (w = (x = (y = 0f)));
			if ((num & 8) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					v = 0f - _floatLookup[1];
				}
				else
				{
					v = _floatLookup[1];
				}
			}
			if ((num & 4) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					w = 0f - _floatLookup[1];
				}
				else
				{
					w = _floatLookup[1];
				}
			}
			if ((num & 2) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					x = 0f - _floatLookup[1];
				}
				else
				{
					x = _floatLookup[1];
				}
			}
			if ((num & 1) != 0)
			{
				if (br.Get1Bit() == 1)
				{
					y = 0f - _floatLookup[1];
				}
				else
				{
					y = _floatLookup[1];
				}
			}
		}

		private static byte DecodeSymbol(BitReservoir br, int table)
		{
			int maxBits;
			HuffmanListNode huffmanListNode = GetNode(table, out maxBits);
			int readCount;
			int num = br.TryPeekBits(maxBits, out readCount);
			if (readCount < maxBits)
			{
				num <<= maxBits - readCount;
			}
			while (huffmanListNode != null && huffmanListNode.Length <= readCount)
			{
				if ((num & huffmanListNode.Mask) == huffmanListNode.Bits)
				{
					br.SkipBits(huffmanListNode.Length);
					break;
				}
				huffmanListNode = huffmanListNode.Next;
			}
			if (huffmanListNode != null && huffmanListNode.Length <= readCount)
			{
				return huffmanListNode.Value;
			}
			return 0;
		}

		private static HuffmanListNode GetNode(int table, out int maxBits)
		{
			int num = table;
			if (num > 16)
			{
				num = ((num > 31) ? (num - 17) : ((num < 24) ? 13 : 14));
			}
			else
			{
				if (num > 13)
				{
					num--;
				}
				if (num > 3)
				{
					num--;
				}
				num--;
			}
			if (_llCache[num] == null)
			{
				_llCache[num] = InitTable(_codeTables[num], out maxBits);
				_llCacheMaxBits[num] = maxBits;
			}
			else
			{
				maxBits = _llCacheMaxBits[num];
			}
			return _llCache[num];
		}

		private static HuffmanListNode InitTable(byte[,] tree, out int maxBits)
		{
			List<byte> list = new List<byte>();
			List<int> list2 = new List<int>();
			List<int> list3 = new List<int>();
			int length = tree.GetLength(0);
			for (int i = 0; i < length; i++)
			{
				if (tree[i, 0] == 0)
				{
					int num = 0;
					int item = 0;
					int num2 = i;
					do
					{
						num2 = FindPreviousNode(tree, num2, out var bit);
						num |= bit << item++;
					}
					while (num2 > 0);
					list.Add(tree[i, 1]);
					list2.Add(item);
					list3.Add(num);
				}
			}
			return BuildLinkedList(list, list2, list3, out maxBits);
		}

		private static int FindPreviousNode(byte[,] tree, int idx, out int bit)
		{
			for (int num = idx - 1; num >= 0; num--)
			{
				if (tree[num, 0] != 0)
				{
					for (int i = 0; i < 2; i++)
					{
						if (num + tree[num, i] != idx)
						{
							continue;
						}
						if (tree[num, i] >= 250)
						{
							int result = FindPreviousNode(tree, num, out bit);
							if (bit != i)
							{
								throw new InvalidOperationException();
							}
							return result;
						}
						bit = i;
						return num;
					}
				}
			}
			throw new InvalidOperationException();
		}

		private static HuffmanListNode BuildLinkedList(List<byte> values, List<int> lengthList, List<int> codeList, out int maxBits)
		{
			HuffmanListNode[] array = new HuffmanListNode[lengthList.Count];
			maxBits = lengthList.Max();
			for (int i = 0; i < array.Length; i++)
			{
				int num = maxBits - lengthList[i];
				array[i] = new HuffmanListNode
				{
					Value = values[i],
					Length = lengthList[i],
					Bits = codeList[i] << num,
					Mask = (1 << lengthList[i]) - 1 << num
				};
			}
			Array.Sort(array, (HuffmanListNode huffmanListNode, HuffmanListNode huffmanListNode2) => huffmanListNode.Length - huffmanListNode2.Length);
			for (int num2 = 1; num2 < array.Length && array[num2].Length < 99999; num2++)
			{
				array[num2 - 1].Next = array[num2];
			}
			return array[0];
		}
	}
	internal class ID3Frame : FrameBase
	{
		private int _version;

		private int _encoderDelay = -1;

		private int _encoderPadding = -1;

		private bool _v2Parsed;

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

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

		internal int Version
		{
			get
			{
				if (_version == 0)
				{
					return 1;
				}
				return _version;
			}
		}

		internal static ID3Frame TrySync(uint syncMark)
		{
			if ((syncMark & 0xFFFFFF00u) == 1229206272)
			{
				return new ID3Frame
				{
					_version = 2
				};
			}
			if ((syncMark & 0xFFFFFF00u) == 1413564160)
			{
				if ((syncMark & 0xFF) == 43)
				{
					return new ID3Frame
					{
						_version = 1
					};
				}
				return new ID3Frame
				{
					_version = 0
				};
			}
			return null;
		}

		private ID3Frame()
		{
		}

		protected override int Validate()
		{
			switch (_version)
			{
			case 2:
			{
				byte[] array = new byte[7];
				if (Read(3, array) == 7)
				{
					byte b;
					switch (array[0])
					{
					case 2:
						b = 63;
						break;
					case 3:
						b = 31;
						break;
					case 4:
						b = 15;
						break;
					default:
						return -1;
					}
					int num = (array[3] << 21) | (array[4] << 14) | (array[5] << 7) | array[6];
					if (((array[2] & b) | (array[3] & 0x80) | (array[4] & 0x80) | (array[5] & 0x80) | (array[6] & 0x80)) == 0 && array[1] != byte.MaxValue)
					{
						return num + 10;
					}
				}
				break;
			}
			case 1:
				return 355;
			case 0:
				return 128;
			}
			return -1;
		}

		internal override void Parse()
		{
			switch (_version)
			{
			case 2:
				ParseV2();
				break;
			case 1:
				ParseV1Enh();
				break;
			case 0:
				ParseV1(3);
				break;
			}
		}

		private void ParseV1(int offset)
		{
		}

		private void ParseV1Enh()
		{
			ParseV1(230);
		}

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

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

		internal void ParseEagerIfNeeded()
		{
			if (_version == 2 && !_v2Parsed)
			{
				ParseV2();
			}
		}

		internal void Merge(ID3Frame newFrame)
		{
		}
	}
	internal abstract class LayerDecoderBase
	{
		protected const int SBLIMIT = 32;

		private const float INV_SQRT_2 = 0.70710677f;

		private static float[] DEWINDOW_TABLE = new float[512]
		{
			0f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -1.5259E-05f, -3.0518E-05f, -3.0518E-05f, -3.0518E-05f,
			-3.0518E-05f, -4.5776E-05f, -4.5776E-05f, -6.1035E-05f, -6.1035E-05f, -7.6294E-05f, -7.6294E-05f, -9.1553E-05f, -0.000106812f, -0.000106812f,
			-0.00012207f, -0.000137329f, -0.000152588f, -0.000167847f, -0.000198364f, -0.000213623f, -0.000244141f, -0.000259399f, -0.000289917f, -0.000320435f,
			-0.000366211f, -0.000396729f, -0.000442505f, -0.000473022f, -0.000534058f, -0.000579834f, -0.00062561f, -0.000686646f, -0.000747681f, -0.000808716f,
			-0.00088501f, -0.000961304f, -0.001037598f, -0.001113892f, -0.001205444f, -0.001296997f, -0.00138855f, -0.001480103f, -0.001586914f, -0.001693726f,
			-0.001785278f, -0.001907349f, -0.00201416f, -0.002120972f, -0.002243042f, -0.002349854f, -0.002456665f, -0.002578735f, -0.002685547f, -0.002792358f,
			-0.00289917f, -0.002990723f, -0.003082275f, -0.003173828f, 0.003250122f, 0.003326416f, 0.003387451f, 0.003433228f, 0.003463745f, 0.003479004f,
			0.003479004f, 0.003463745f, 0.003417969f, 0.003372192f, 0.00328064f, 0.003173828f, 0.003051758f, 0.002883911f, 0.002700806f, 0.002487183f,
			0.002227783f, 0.001937866f, 0.001617432f, 0.001266479f, 0.000869751f, 0.000442505f, -3.0518E-05f, -0.000549316f, -0.001098633f, -0.001693726f,
			-0.002334595f, -0.003005981f, -0.003723145f, -0.004486084f, -0.0052948f, -0.006118774f, -0.007003784f, -0.007919312f, -0.008865356f, -0.009841919f,
			-0.010848999f, -0.011886597f, -0.012939453f, -0.014022827f, -0.01512146f, -0.016235352f, -0.017349243f, -0.018463135f, -0.019577026f, -0.020690918f,
			-0.02178955f, -0.022857666f, -0.023910522f, -0.024932861f, -0.025909424f, -0.02684021f, -0.02772522f, -0.028533936f, -0.029281616f, -0.029937744f,
			-0.030532837f, -0.03100586f, -0.03138733f, -0.031661987f, -0.031814575f, -0.031845093f, -0.03173828f, -0.03147888f, 0.031082153f, 0.030517578f,
			0.029785156f, 0.028884888f, 0.027801514f, 0.026535034f, 0.02508545f, 0.023422241f, 0.021575928f, 0.01953125f, 0.01725769f, 0.014801025f,
			0.012115479f, 0.009231567f, 0.006134033f, 0.002822876f, -0.000686646f, -0.004394531f, -0.00831604f, -0.012420654f, -0.016708374f, -0.0211792f,
			-0.025817871f, -0.03060913f, -0.03555298f, -0.040634155f, -0.045837402f, -0.051132202f, -0.056533813f, -0.06199646f, -0.06752014f, -0.07305908f,
			-0.07862854f, -0.08418274f, -0.08970642f, -0.09516907f, -0.10054016f, -0.1058197f, -0.110946655f, -0.11592102f, -0.12069702f, -0.1252594f,
			-0.12956238f, -0.1335907f, -0.13729858f, -0.14067078f, -0.14367676f, -0.1462555f, -0.14842224f, -0.15011597f, -0.15130615f, -0.15196228f,
			-0.15206909f, -0.15159607f, -0.15049744f, -0.1487732f, -0.1463623f, -0.14326477f, -0.13945007f, -0.1348877f, -0.12957764f, -0.12347412f,
			-0.11657715f, -0.1088562f, 0.10031128f, 0.090927124f, 0.08068848f, 0.06959534f, 0.057617188f, 0.044784546f, 0.031082153f, 0.01651001f,
			0.001068115f, -0.015228271f, -0.03237915f, -0.050354004f, -0.06916809f, -0.088775635f, -0.10916138f, -0.13031006f, -0.15220642f, -0.17478943f,
			-0.19805908f, -0.22198486f, -0.24650574f, -0.2715912f, -0.2972107f, -0.32331848f, -0.34986877f, -0.37680054f, -0.40408325f, -0.43165588f,
			-0.45947266f, -0.48747253f, -0.51560974f, -0.54382324f, -0.57203674f, -0.6002197f, -0.6282959f, -0.6562195f, -0.6839142f, -0.71131897f,
			-0.7383728f, -0.7650299f, -0.791214f, -0.816864f, -0.84194946f, -0.8663635f, -0.89009094f, -0.9130554f, -0.9351959f, -0.95648193f,
			-0.9768524f, -0.99624634f, -1.0146179f, -1.0319366f, -1.0481567f, -1.0632172f, -1.0771179f, -1.0897827f, -1.1012115f, -1.1113739f,
			-1.120224f, -1.1277466f, -1.1339264f, -1.1387634f, -1.1422119f, -1.1442871f, 1.144989f, 1.1442871f, 1.1422119f, 1.1387634f,
			1.1339264f, 1.1277466f, 1.120224f, 1.1113739f, 1.1012115f, 1.0897827f, 1.0771179f, 1.0632172f, 1.0481567f, 1.0319366f,
			1.0146179f, 0.99624634f, 0.9768524f, 0.95648193f, 0.9351959f, 0.9130554f, 0.89009094f, 0.8663635f, 0.84194946f, 0.816864f,
			0.791214f, 0.7650299f, 0.7383728f, 0.71131897f, 0.6839142f, 0.6562195f, 0.6282959f, 0.6002197f, 0.57203674f, 0.54382324f,
			0.51560974f, 0.48747253f, 0.45947266f, 0.43165588f, 0.40408325f, 0.37680054f, 0.34986877f, 0.32331848f, 0.2972107f, 0.2715912f,
			0.24650574f, 0.22198486f, 0.19805908f, 0.17478943f, 0.15220642f, 0.13031006f, 0.10916138f, 0.088775635f, 0.06916809f, 0.050354004f,
			0.03237915f, 0.015228271f, -0.001068115f, -0.01651001f, -0.031082153f, -0.044784546f, -0.057617188f, -0.06959534f, -0.08068848f, -0.090927124f,
			0.10031128f, 0.1088562f, 0.11657715f, 0.12347412f, 0.12957764f, 0.1348877f, 0.13945007f, 0.14326477f, 0.1463623f, 0.1487732f,
			0.15049744f, 0.15159607f, 0.15206909f, 0.15196228f, 0.15130615f, 0.15011597f, 0.14842224f, 0.1462555f, 0.14367676f, 0.14067078f,
			0.13729858f, 0.1335907f, 0.12956238f, 0.1252594f, 0.12069702f, 0.11592102f, 0.110946655f, 0.1058197f, 0.10054016f, 0.09516907f,
			0.08970642f, 0.08418274f, 0.07862854f, 0.07305908f, 0.06752014f, 0.06199646f, 0.056533813f, 0.051132202f, 0.045837402f, 0.040634155f,
			0.03555298f, 0.03060913f, 0.025817871f, 0.0211792f, 0.016708374f, 0.012420654f, 0.00831604f, 0.004394531f, 0.000686646f, -0.002822876f,
			-0.006134033f, -0.009231567f, -0.012115479f, -0.014801025f, -0.01725769f, -0.01953125f, -0.021575928f, -0.023422241f, -0.02508545f, -0.026535034f,
			-0.027801514f, -0.028884888f, -0.029785156f, -0.030517578f, 0.031082153f, 0.03147888f, 0.03173828f, 0.031845093f, 0.031814575f, 0.031661987f,
			0.03138733f, 0.03100586f, 0.030532837f, 0.029937744f, 0.029281616f, 0.028533936f, 0.02772522f, 0.02684021f, 0.025909424f, 0.024932861f,
			0.023910522f, 0.022857666f, 0.02178955f, 0.020690918f, 0.019577026f, 0.018463135f, 0.017349243f, 0.016235352f, 0.01512146f, 0.014022827f,
			0.012939453f, 0.011886597f, 0.010848999f, 0.009841919f, 0.008865356f, 0.007919312f, 0.007003784f, 0.006118774f, 0.0052948f, 0.004486084f,
			0.003723145f, 0.003005981f, 0.002334595f, 0.001693726f, 0.001098633f, 0.000549316f, 3.0518E-05f, -0.000442505f, -0.000869751f, -0.001266479f,
			-0.001617432f, -0.001937866f, -0.002227783f, -0.002487183f, -0.002700806f, -0.002883911f, -0.003051758f, -0.003173828f, -0.00328064f, -0.003372192f,
			-0.003417969f, -0.003463745f, -0.003479004f, -0.003479004f, -0.003463745f, -0.003433228f, -0.003387451f, -0.003326416f, 0.003250122f, 0.003173828f,
			0.003082275f, 0.002990723f, 0.00289917f, 0.002792358f, 0.002685547f, 0.002578735f, 0.002456665f, 0.002349854f, 0.002243042f, 0.002120972f,
			0.00201416f, 0.001907349f, 0.001785278f, 0.001693726f, 0.001586914f, 0.001480103f, 0.00138855f, 0.001296997f, 0.001205444f, 0.001113892f,
			0.001037598f, 0.000961304f, 0.00088501f, 0.000808716f, 0.000747681f, 0.000686646f, 0.00062561f, 0.000579834f, 0.000534058f, 0.000473022f,
			0.000442505f, 0.000396729f, 0.000366211f, 0.000320435f, 0.000289917f, 0.000259399f, 0.000244141f, 0.000213623f, 0.000198364f, 0.000167847f,
			0.000152588f, 0.000137329f, 0.00012207f, 0.000106812f, 0.000106812f, 9.1553E-05f, 7.6294E-05f, 7.6294E-05f, 6.1035E-05f, 6.1035E-05f,
			4.5776E-05f, 4.5776E-05f, 3.0518E-05f, 3.0518E-05f, 3.0518E-05f, 3.0518E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f, 1.5259E-05f,
			1.5259E-05f, 1.5259E-05f
		};

		private static float[] SYNTH_COS64_TABLE = new float[31]
		{
			0.500603f, 0.5024193f, 0.50547093f, 0.5097956f, 0.5154473f, 0.5224986f, 0.5310426f, 0.5411961f, 0.5531039f, 0.56694406f,
			0.582935f, 0.6013449f, 0.6225041f, 0.6468218f, 0.6748083f, 0.70710677f, 0.7445363f, 0.7881546f, 0.8393496f, 0.8999762f,
			0.9725682f, 1.0606776f, 1.1694399f, 1.306563f, 1.4841646f, 1.7224472f, 2.057781f, 2.5629156f, 3.4076085f, 5.1011486f,
			10.190008f
		};

		private List<float[]> _synBuf = new List<float[]>(2);

		private List<int> _bufOffset = new List<int>(2);

		private float[] _eq;

		private float[] ippuv = new float[512];

		private float[] ei32 = new float[16];

		private float[] eo32 = new float[16];

		private float[] oi32 = new float[16];

		private float[] oo32 = new float[16];

		private float[] ei16 = new float[8];

		private float[] eo16 = new float[8];

		private float[] oi16 = new float[8];

		private float[] oo16 = new float[8];

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

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

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

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

		internal StereoMode StereoMode { get; set; }

		internal LayerDecoderBase()
		{
			StereoMode = StereoMode.Both;
		}

		internal abstract int DecodeFrame(IMpegFrame frame, float[] ch0, float[] ch1);

		internal void SetEQ(float[] eq)
		{
			if (eq == null || eq.Length == 32)
			{
				_eq = eq;
			}
		}

		internal virtual void ResetForSeek()
		{
			_synBuf.Clear();
			_bufOffset.Clear();
		}

		protected void InversePolyPhase(int channel, float[] data)
		{
			GetBufAndOffset(channel, out var synBuf, out var k);
			if (_eq != null)
			{
				for (int i = 0; i < 32; i++)
				{
					data[i] *= _eq[i];
				}
			}
			DCT32(data, synBuf, k);
			BuildUVec(ippuv, synBuf, k);
			DewindowOutput(ippuv, data);
		}

		private void GetBufAndOffset(int channel, out float[] synBuf, out int k)
		{
			while (_synBuf.Count <= channel)
			{
				_synBuf.Add(new float[1024]);
			}
			while (_bufOffset.Count <= channel)
			{
				_bufOffset.Add(0);
			}
			synBuf = _synBuf[channel];
			k = _bufOffset[channel];
			k = (k - 32) & 0x1FF;
			_bufOffset[channel] = k;
		}

		private void DCT32(float[] _in, float[] _out, int k)
		{
			for (int i = 0; i < 16; i++)
			{
				ei32[i] = _in[i] + _in[31 - i];
				oi32[i] = (_in[i] - _in[31 - i]) * SYNTH_COS64_TABLE[2 * i];
			}
			DCT16(ei32, eo32);
			DCT16(oi32, oo32);
			for (int i = 0; i < 15; i++)
			{
				_out[2 * i + k] = eo32[i];
				_out[2 * i + 1 + k] = oo32[i] + oo32[i + 1];
			}
			_out[30 + k] = eo32[15];
			_out[31 + k] = oo32[15];
		}

		private void DCT16(float[] _in, float[] _out)
		{
			float num = _in[0];
			float num2 = _in[15];
			ei16[0] = num + num2;
			oi16[0] = (num - num2) * SYNTH_COS64_TABLE[1];
			num = _in[1];
			num2 = _in[14];
			ei16[1] = num + num2;
			oi16[1] = (num - num2) * SYNTH_COS64_TABLE[5];
			num = _in[2];
			num2 = _in[13];
			ei16[2] = num + num2;
			oi16[2] = (num - num2) * SYNTH_COS64_TABLE[9];
			num = _in[3];
			num2 = _in[12];
			ei16[3] = num + num2;
			oi16[3] = (num - num2) * SYNTH_COS64_TABLE[13];
			num = _in[4];
			num2 = _in[11];
			ei16[4] = num + num2;
			oi16[4] = (num - num2) * SYNTH_COS64_TABLE[17];
			num = _in[5];
			num2 = _in[10];
			ei16[5] = num + num2;
			oi16[5] = (num - num2) * SYNTH_COS64_TABLE[21];
			num = _in[6];
			num2 = _in[9];
			ei16[6] = num + num2;
			oi16[6] = (num - num2) * SYNTH_COS64_TABLE[25];
			num = _in[7];
			num2 = _in[8];
			ei16[7] = num + num2;
			oi16[7] = (num - num2) * SYNTH_COS64_TABLE[29];
			DCT8(ei16, eo16);
			DCT8(oi16, oo16);
			_out[0] = eo16[0];
			_out[1] = oo16[0] + oo16[1];
			_out[2] = eo16[1];
			_out[3] = oo16[1] + oo16[2];
			_out[4] = eo16[2];
			_out[5] = oo16[2] + oo16[3];
			_out[6] = eo16[3];
			_out[7] = oo16[3] + oo16[4];
			_out[8] = eo16[4];
			_out[9] = oo16[4] + oo16[5];
			_out[10] = eo16[5];
			_out[11] = oo16[5] + oo16[6];
			_out[12] = eo16[6];
			_out[13] = oo16[6] + oo16[7];
			_out[14] = eo16[7];
			_out[15] = oo16[7];
		}

		private void DCT8(float[] _in, float[] _out)
		{
			ei8[0] = _in[0] + _in[7];
			ei8[1] = _in[3] + _in[4];
			ei8[2] = _in[1] + _in[6];
			ei8[3] = _in[2] + _in[5];
			tmp8[0] = ei8[0] + ei8[1];
			tmp8[1] = ei8[2] + ei8[3];
			tmp8[2] = (ei8[0] - ei8[1]) * SYNTH_COS64_TABLE[7];
			tmp8[3] = (ei8[2] - ei8[3]) * SYNTH_COS64_TABLE[23];
			tmp8[4] = (tmp8[2] - tmp8[3]) * 0.70710677f;
			_out[0] = tmp8[0] + tmp8[1];
			_out[2] = tmp8[2] + tmp8[3] + tmp8[4];
			_out[4] = (tmp8[0] - tmp8[1]) * 0.70710677f;
			_out[6] = tmp8[4];
			oi8[0] = (_in[0] - _in[7]) * SYNTH_COS64_TABLE[3];
			oi8[1] = (_in[1] - _in[6]) * SYNTH_COS64_TABLE[11];
			oi8[2] = (_in[2] - _in[5]) * SYNTH_COS64_TABLE[19];
			oi8[3] = (_in[3] - _in[4]) * SYNTH_COS64_TABLE[27];
			tmp8[0] = oi8[0] + oi8[3];
			tmp8[1] = oi8[1] + oi8[2];
			tmp8[2] = (oi8[0] - oi8[3]) * SYNTH_COS64_TABLE[7];
			tmp8[3] = (oi8[1] - oi8[2]) * SYNTH_COS64_TABLE[23];
			tmp8[4] = tmp8[2] + tmp8[3];
			tmp8[5] = (tmp8[2] - tmp8[3]) * 0.70710677f;
			oo8[0] = tmp8[0] + tmp8[1];
			oo8[1] = tmp8[4] + tmp8[5];
			oo8[2] = (tmp8[0] - tmp8[1]) * 0.70710677f;
			oo8[3] = tmp8[5];
			_out[1] = oo8[0] + oo8[1];
			_out[3] = oo8[1] + oo8[2];
			_out[5] = oo8[2] + oo8[3];
			_out[7] = oo8[3];
		}

		private void BuildUVec(float[] u_vec, float[] cur_synbuf, int k)
		{
			int num = 0;
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					u_vec[num + j] = cur_synbuf[k + j + 16];
					u_vec[num + j + 17] = 0f - cur_synbuf[k + 31 - j];
				}
				k = (k + 32) & 0x1FF;
				for (int j = 0; j < 16; j++)
				{
					u_vec[num + j + 32] = 0f - cur_synbuf[k + 16 - j];
					u_vec[num + j + 48] = 0f - cur_synbuf[k + j];
				}
				u_vec[num + 16] = 0f;
				k = (k + 32) & 0x1FF;
				num += 64;
			}
		}

		private void DewindowOutput(float[] u_vec, float[] samples)
		{
			for (int i = 0; i < 512; i++)
			{
				u_vec[i] *= DEWINDOW_TABLE[i];
			}
			for (int j = 0; j < 32; j++)
			{
				float num = u_vec[j];
				num += u_vec[j + 32];
				num += u_vec[j + 64];
				num += u_vec[j + 96];
				num += u_vec[j + 128];
				num += u_vec[j + 160];
				num += u_vec[j + 192];
				num += u_vec[j + 224];
				num += u_vec[j + 256];
				num += u_vec[j + 288];
				num += u_vec[j + 320];
				num += u_vec[j + 352];
				num += u_vec[j + 384];
				num += u_vec[j + 416];
				num += u_vec[j + 448];
				num += u_vec[j + 480];
				u_vec[j] = num;
			}
			for (int k = 0; k < 32; k++)
			{
				samples[k] = u_vec[k];
			}
		}
	}
	internal class LayerIDecoder : LayerIIDecoderBase
	{
		private static readonly int[] _rateTable = new int[32];

		private static readonly int[][] _allocLookupTable = new int[1][] { new int[17]
		{
			4, 0, 2, 3, 4, 5, 6, 7, 8, 9,
			10, 11, 12, 13, 14, 15, 16
		} };

		internal static bool GetCRC(MpegFrame frame, ref uint crc)
		{
			return LayerIIDecoderBase.GetCRC(frame, _rateTable, _allocLookupTable, readScfsiBits: false, ref crc);
		}

		internal LayerIDecoder()
			: base(_allocLookupTable, 1)
		{
		}

		protected override int[] GetRateTable(IMpegFrame frame)
		{
			return _rateTable;
		}

		protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels)
		{
		}
	}
	internal class LayerIIDecoder : LayerIIDecoderBase
	{
		private static readonly int[][] _rateLookupTable = new int[5][]
		{
			new int[27]
			{
				3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
				2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
				1, 1, 1, 0, 0, 0, 0
			},
			new int[30]
			{
				3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
				2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
				1, 1, 1, 0, 0, 0, 0, 0, 0, 0
			},
			new int[8] { 4, 4, 5, 5, 5, 5, 5, 5 },
			new int[12]
			{
				4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
				5, 5
			},
			new int[30]
			{
				6, 6, 6, 6, 5, 5, 5, 5, 5, 5,
				5, 7, 7, 7, 7, 7, 7, 7, 7, 7,
				7, 7, 7, 7, 7, 7, 7, 7, 7, 7
			}
		};

		private static readonly int[][] _allocLookupTable = new int[8][]
		{
			new int[5] { 2, 0, -5, -7, 16 },
			new int[9] { 3, 0, -5, -7, 3, -10, 4, 5, 16 },
			new int[17]
			{
				4, 0, -5, -7, 3, -10, 4, 5, 6, 7,
				8, 9, 10, 11, 12, 13, 16
			},
			new int[17]
			{
				4, 0, -5, 3, 4, 5, 6, 7, 8, 9,
				10, 11, 12, 13, 14, 15, 16
			},
			new int[17]
			{
				4, 0, -5, -7, -10, 4, 5, 6, 7, 8,
				9, 10, 11, 12, 13, 14, 15
			},
			new int[9] { 3, 0, -5, -7, -10, 4, 5, 6, 7 },
			new int[17]
			{
				4, 0, -5, -7, 3, -10, 4, 5, 6, 7,
				8, 9, 10, 11, 12, 13, 14
			},
			new int[5] { 2, 0, -5, -7, -10 }
		};

		internal static bool GetCRC(MpegFrame frame, ref uint crc)
		{
			return LayerIIDecoderBase.GetCRC(frame, SelectTable(frame), _allocLookupTable, readScfsiBits: true, ref crc);
		}

		private static int[] SelectTable(IMpegFrame frame)
		{
			int num = frame.BitRate / ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2) / 1000;
			if (frame.Version == MpegVersion.Version1)
			{
				if ((num >= 56 && num <= 80) || (frame.SampleRate == 48000 && num >= 56))
				{
					return _rateLookupTable[0];
				}
				if (frame.SampleRate != 48000 && num >= 96)
				{
					return _rateLookupTable[1];
				}
				if (frame.SampleRate != 32000 && num <= 48)
				{
					return _rateLookupTable[2];
				}
				return _rateLookupTable[3];
			}
			return _rateLookupTable[4];
		}

		internal LayerIIDecoder()
			: base(_allocLookupTable, 3)
		{
		}

		protected override int[] GetRateTable(IMpegFrame frame)
		{
			return SelectTable(frame);
		}

		protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels)
		{
			for (int i = 0; i < 30; i++)
			{
				for (int j = 0; j < channels; j++)
				{
					if (scfsi[j][i] == 2)
					{
						scfsi[j][i] = frame.ReadBits(2);
					}
				}
			}
		}
	}
	internal abstract class LayerIIDecoderBase : LayerDecoderBase
	{
		protected const int SSLIMIT = 12;

		private static readonly float[] _groupedC = new float[5] { 0f, 0f, 1.3333334f, 1.6f, 1.7777778f };

		private static readonly float[] _groupedD = new float[5] { 0f, 0f, -0.5f, -0.5f, -0.5f };

		private static readonly float[] _C = new float[17]
		{
			0f, 0f, 1.3333334f, 1.1428572f, 1.0666667f, 1.032258f, 1.0158731f, 1.007874f, 1.0039216f, 1.0019569f,
			1.0009775f, 1.0004885f, 1.0002443f, 1.0001221f, 1.000061f, 1.0000305f, 1.0000153f
		};

		private static readonly float[] _D = new float[17]
		{
			0f,
			0f,
			-0.5f,
			-0.75f,
			-0.875f,
			-0.9375f,
			-31f / 32f,
			-63f / 64f,
			-127f / 128f,
			-0.99609375f,
			-0.9980469f,
			-0.99902344f,
			-0.9995117f,
			-0.99975586f,
			-0.9998779f,
			-0.99993896f,
			-0.9999695f
		};

		private static readonly float[] _denormalMultiplier = new float[64]
		{
			2f,
			1.587401f,
			1.2599211f,
			1f,
			0.7937005f,
			0.62996054f,
			0.5f,
			0.39685026f,
			0.31498027f,
			0.25f,
			0.19842513f,
			0.15749013f,
			0.125f,
			0.099212565f,
			0.07874507f,
			0.0625f,
			0.049606282f,
			0.039372534f,
			1f / 32f,
			0.024803141f,
			0.019686267f,
			1f / 64f,
			0.012401571f,
			0.009843133f,
			1f / 128f,
			0.0062007853f,
			0.0049215667f,
			0.00390625f,
			0.0031003926f,
			0.0024607833f,
			0.001953125f,
			0.0015501963f,
			0.0012303917f,
			0.0009765625f,
			0.00077509816f,
			0.00061519584f,
			0.00048828125f,
			0.00038754908f,
			0.00030759792f,
			0.00024414062f,
			0.00019377454f,
			0.00015379896f,
			0.00012207031f,
			9.688727E-05f,
			7.689948E-05f,
			6.1035156E-05f,
			4.8443635E-05f,
			3.844974E-05f,
			3.0517578E-05f,
			2.4221818E-05f,
			1.922487E-05f,
			1.5258789E-05f,
			1.2110909E-05f,
			9.612435E-06f,
			7.6293945E-06f,
			6.0554544E-06f,
			4.8062175E-06f,
			3.8146973E-06f,
			3.0277272E-06f,
			2.4031087E-06f,
			1.9073486E-06f,
			1.5138636E-06f,
			1.2015544E-06f,
			9.536743E-07f
		};

		private int _channels;

		private int _jsbound;

		private int _granuleCount;

		private int[][] _allocLookupTable;

		private int[][] _scfsi;

		private int[][] _samples;

		private int[][][] _scalefac;

		private float[] _polyPhaseBuf;

		private float[][] _chanBufs = new float[2][];

		private int[][] _allocation;

		protected static bool GetCRC(MpegFrame frame, int[] rateTable, int[][] allocLookupTable, bool readScfsiBits, ref uint crc)
		{
			int num = 0;
			int num2 = rateTable.Length;
			int num3 = num2;
			if (frame.ChannelMode == MpegChannelMode.JointStereo)
			{
				num3 = frame.ChannelModeExtension * 4 + 4;
			}
			int num4 = ((frame.ChannelMode == MpegChannelMode.Mono) ? 1 : 2);
			int i;
			for (i = 0; i < num3; i++)
			{
				int num5 = allocLookupTable[rateTable[i]][0];
				for (int j = 0; j < num4; j++)
				{
					int num6 = frame.ReadBits(num5);
					if (num6 > 0)
					{
						num += 2;
					}
					MpegFrame.UpdateCRC(num6, num5, ref crc);
				}
			}
			for (; i < num2; i++)
			{
				int num7 = allocLookupTable[rateTable[i]][0];
				int num8 = frame.ReadBits(num7);
				if (num8 > 0)
				{
					num += num4 * 2;
				}
				MpegFrame.UpdateCRC(num8, num7, ref crc);
			}
			if (readScfsiBits)
			{
				while (num >= 2)
				{
					MpegFrame.UpdateCRC(frame.ReadBits(2), 2, ref crc);
					num -= 2;
				}
			}
			return true;
		}

		protected LayerIIDecoderBase(int[][] allocLookupTable, int granuleCount)
		{
			_allocLookupTable = allocLookupTable;
			_granuleCount = granuleCount;
			_allocation = new int[2][]
			{
				new int[32],
				new int[32]
			};
			_scfsi = new int[2][]
			{
				new int[32],
				new int[32]
			};
			_samples = new int[2][]
			{
				new int[384 * _granuleCount],
				new int[384 * _granuleCount]
			};
			_scalefac = new int[2][][]
			{
				new int[3][],
				new int[3][]
			};
			for (int i = 0; i < 3; i++)
			{
				_scalefac[0][i] = new int[32];
				_scalefac[1][i] = new int[32];
			}
			_polyPhaseBuf = new float[32];
		}

		internal override int DecodeFrame(IMpegFrame frame, float[] ch0, float[] ch1)
		{
			InitFrame(frame);
			int[] rateTable = GetRateTable(frame);
			ReadAllocation(frame, rateTable);
			for (int i = 0; i < _scfsi[0].Length; i++)
			{
				_scfsi[0][i] = ((_allocation[0][i] != 0) ? 2 : (-1));
				_scfsi[1][i] = ((_allocation[1][i] != 0) ? 2 : (-1));
			}
			ReadScaleFactorSelection(frame, _scfsi, _channels);
			ReadScaleFactors(frame);
			ReadSamples(frame);
			return DecodeSamples(ch0, ch1);
		}

		private void InitFrame(IMpegFrame frame)
		{
			switch (frame.ChannelMode)
			{
			case MpegChannelMode.Mono:
				_channels = 1;
				_jsbound = 32;
				break;
			case MpegChannelMode.JointStereo:
				_channels = 2;
				_jsbound = frame.ChannelModeExtension * 4 + 4;
				break;
			default:
				_channels = 2;
				_jsbound = 32;
				break;
			}
		}

		protected abstract int[] GetRateTable(IMpegFrame frame);

		private void ReadAllocation(IMpegFrame frame, int[] rateTable)
		{
			int num = rateTable.Length;
			if (_jsbound > num)
			{
				_jsbound = num;
			}
			Array.Clear(_allocation[0], 0, 32);
			Array.Clear(_allocation[1], 0, 32);
			int i;
			for (i = 0; i < _jsbound; i++)
			{
				int[] array = _allocLookupTable[rateTable[i]];
				int bitCount = array[0];
				for (int j = 0; j < _channels; j++)
				{
					_allocation[j][i] = array[frame.ReadBits(bitCount) + 1];
				}
			}
			for (; i < num; i++)
			{
				int[] array2 = _allocLookupTable[rateTable[i]];
				_allocation[0][i] = (_allocation[1][i] = array2[frame.ReadBits(array2[0]) + 1]);
			}
		}

		protected abstract void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels);

		private void ReadScaleFactors(IMpegFrame frame)
		{
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < _channels; j++)
				{
					switch (_scfsi[j][i])
					{
					case 0:
						_scalefac[j][0][i] = frame.ReadBits(6);
						_scalefac[j][1][i] = frame.ReadBits(6);
						_scalefac[j][2][i] = frame.ReadBits(6);
						break;
					case 1:
						_scalefac[j][0][i] = (_scalefac[j][1][i] = frame.ReadBits(6));
						_scalefac[j][2][i] = frame.ReadBits(6);
						break;
					case 2:
						_scalefac[j][0][i] = (_scalefac[j][1][i] = (_scalefac[j][2][i] = frame.ReadBits(6)));
						break;
					case 3:
						_scalefac[j][0][i] = frame.ReadBits(6);
						_scalefac[j][1][i] = (_scalefac[j][2][i] = frame.ReadBits(6));
						break;
					default:
						_scalefac[j][0][i] = 63;
						_scalefac[j][1][i] = 63;
						_scalefac[j][2][i] = 63;
						break;
					}
				}
			}
		}

		private void ReadSamples(IMpegFrame frame)
		{
			int num = 0;
			int num2 = 0;
			while (num < 12)
			{
				int num3 = 0;
				while (num3 < 32)
				{
					for (int i = 0; i < _channels; i++)
					{
						if (i == 0 || num3 < _jsbound)
						{
							int num4 = _allocation[i][num3];
							if (num4 != 0)
							{
								if (num4 < 0)
								{
									int num5 = frame.ReadBits(-num4);
									int num6 = (1 << -num4 / 2 + -num4 % 2 - 2) + 1;
									_samples[i][num2] = num5 % num6;
									num5 /= num6;
									_samples[i][num2 + 32] = num5 % num6;
									_samples[i][num2 + 64] = num5 / num6;
								}
								else
								{
									for (int j = 0; j < _granuleCount; j++)
									{
										_samples[i][num2 + 32 * j] = frame.ReadBits(num4);
									}
								}
							}
							else
							{
								for (int k = 0; k < _granuleCount; k++)
								{
									_samples[i][num2 + 32 * k] = 0;
								}
							}
						}
						else
						{
							for (int l = 0; l < _granuleCount; l++)
							{
								_samples[1][num2 + 32 * l] = _samples[0][num2 + 32 * l];
							}
						}
					}
					num3++;
					num2++;
				}
				num++;
				num2 += 32 * (_granuleCount - 1);
			}
		}

		private int DecodeSamples(float[] ch0, float[] ch1)
		{
			float[][] chanBufs = _chanBufs;
			int num = 0;
			int num2 = _channels - 1;
			if (_channels == 1 || base.StereoMode == StereoMode.LeftOnly)
			{
				chanBufs[0] = ch0;
				num2 = 0;
			}
			else if (base.StereoMode == StereoMode.RightOnly)
			{
				chanBufs[1] = ch0;
				num = 1;
			}
			else
			{
				chanBufs[0] = ch0;
				chanBufs[1] = ch1;
			}
			int num3 = 0;
			for (int i = num; i <= num2; i++)
			{
				num3 = 0;
				for (int j = 0; j < _granuleCount; j++)
				{
					for (int k = 0; k < 12; k++)
					{
						int num4 = 0;
						while (num4 < 32)
						{
							int num5 = _allocation[i][num4];
							if (num5 != 0)
							{
								float[] array;
								float[] array2;
								if (num5 < 0)
								{
									num5 = -num5 / 2 + -num5 % 2 - 1;
									array = _groupedC;
									array2 = _groupedD;
								}
								else
								{
									array = _C;
									array2 = _D;
								}
								_polyPhaseBuf[num4] = array[num5] * ((float)(_samples[i][num3] << 16 - num5) / 32768f + array2[num5]) * _denormalMultiplier[_scalefac[i][j][num4]];
							}
							else
							{
								_polyPhaseBuf[num4] = 0f;
							}
							num4++;
							num3++;
						}
						InversePolyPhase(i, _polyPhaseBuf);
						Array.Copy(_polyPhaseBuf, 0, chanBufs[i], num3 - 32, 32);
					}
				}
			}
			if (_channels == 2 && base.StereoMode == StereoMode.DownmixToMono)
			{
				for (int l = 0; l < num3; l++)
				{
					ch0[l] = (ch0[l] + ch1[l]) / 2f;
				}
			}
			return num3;
		}
	}
	internal sealed class LayerIIIDecoder : LayerDecoderBase
	{
		private class HybridMDCT
		{
			private const float PI = MathF.PI;

			private static float[][] _swin;

			private static float[] icos72_table;

			private List<float[]> _prevBlock;

			private List<float[]> _nextBlock;

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

			private float[] _imdctResult = new float[36];

			private float[] _longImdct_H = new float[17];

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

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

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

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

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

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

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

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

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

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

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

			private const float sqrt32 = 0.8660254f;

			static HybridMDCT()
			{
				icos72_table = new float[35]
				{
					0.50047636f, 0.5019099f, 0.5043145f, 0.5077133f, 0.51213974f, 0.5176381f, 0.5242646f, 0.5320889f, 0.5411961f, 0.55168897f,
					0.56369096f, 0.57735026f, 0.59284455f, 0.61038727f, 0.6302362f, 0.65270364f, 0.67817086f, 0.70710677f, 0.7400936f, 0.7778619f,
					0.8213398f, 0.8717234f, 0.9305795f, 1f, 1.0828403f, 1.1831008f, 1.306563f, 1.4619021f, 1.6627548f, 1.9318516f,
					2.3101132f, 2.8793852f, 3.830649f, 5.7368565f, 11.462792f
				};
				_swin = new float[4][]
				{
					new float[36],
					new float[36],
					new float[36],
					new float[36]
				};
				for (int i = 0; i < 36; i++)
				{
					_swin[0][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5));
				}
				for (int i = 0; i < 18; i++)
				{
					_swin[1][i] = (float)Math.Sin(0.0872664675116539 * ((double)i + 0.5));
				}
				for (int i = 18; i < 24; i++)
				{
					_swin[1][i] = 1f;
				}
				for (int i = 24; i < 30; i++)
				{
					_swin[1][i] = (float)Math.Sin(0.2617993950843811 * ((double)i + 0.5 - 18.0));
				}
				for (int i = 30; i < 36; i++)
				{
					_swin[1][i] = 0f;
				}
				for (int i = 0; i < 6; i++)
				{
					_swin[3][i] = 0f;
				}
				for (int i = 6; i <

BepInEx/plugins/SlipSkid.Radio/SlipSkid.Radio.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.Mono;
using Game;
using Game.UnlockableContent;
using HarmonyLib;
using Menus;
using Menus.UI;
using Microsoft.CodeAnalysis;
using NLayer;
using Player;
using Sounds.SplitScreenAudio;
using TMPro;
using UI;
using UI.TabsSystem;
using UI.UnlockableContentGrid;
using UI.VectorGraphics;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.UI;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Slip & Skid Radio")]
[assembly: AssemblyDescription("Standalone accelerator radio and custom horns with native garage customisation tabs.")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.4.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SlipSkid.Radio
{
	internal sealed class RadioAudioFile
	{
		internal string file;

		internal string path;

		internal string hash;
	}
	internal static class RadioAudioFiles
	{
		internal const long MaxFileBytes = 33554432L;

		internal const int MaxDecodedSamples = 33554432;

		internal static bool Supported(string path)
		{
			string extension = Path.GetExtension(path);
			if (!string.Equals(extension, ".wav", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		internal static List<RadioAudioFile> Scan(string folder, Action<string> warn = null)
		{
			List<RadioAudioFile> list = new List<RadioAudioFile>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (string item in Directory.EnumerateFiles(folder).Where(Supported).OrderBy<string, string>((string p) => p, StringComparer.OrdinalIgnoreCase)
				.ThenBy<string, string>((string p) => p, StringComparer.Ordinal))
			{
				try
				{
					FileInfo fileInfo = new FileInfo(item);
					if (fileInfo.Length < 4 || fileInfo.Length > 33554432)
					{
						warn?.Invoke("Audio file skipped (empty or larger than 32 MiB): " + fileInfo.Name);
						continue;
					}
					string text;
					using (SHA256 sHA = SHA256.Create())
					{
						using FileStream inputStream = File.OpenRead(item);
						text = BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "");
					}
					if (hashSet.Add(text))
					{
						list.Add(new RadioAudioFile
						{
							file = fileInfo.Name,
							path = item,
							hash = text
						});
					}
				}
				catch (IOException ex)
				{
					warn?.Invoke("Audio file skipped: " + Path.GetFileName(item) + " — " + ex.Message);
				}
				catch (UnauthorizedAccessException ex2)
				{
					warn?.Invoke("Audio file skipped: " + Path.GetFileName(item) + " — " + ex2.Message);
				}
			}
			return list;
		}

		internal static PcmWave Decode(string path, int maxSamples = 33554432)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			if (maxSamples <= 0 || maxSamples > 33554432)
			{
				throw new ArgumentOutOfRangeException("maxSamples");
			}
			if (!Supported(path))
			{
				throw new InvalidDataException("Use MP3 or PCM 16-bit WAV audio.");
			}
			long length = new FileInfo(path).Length;
			if (length < 4 || length > 33554432)
			{
				throw new InvalidDataException("Audio files must be non-empty and no larger than 32 MiB.");
			}
			if (string.Equals(Path.GetExtension(path), ".wav", StringComparison.OrdinalIgnoreCase))
			{
				PcmWave pcmWave = PcmWave.Decode(File.ReadAllBytes(path));
				if (pcmWave.samples.Length > maxSamples)
				{
					throw new InvalidDataException("Audio exceeds the decoded sample limit.");
				}
				return pcmWave;
			}
			using FileStream fileStream = File.OpenRead(path);
			MpegFile val = new MpegFile((Stream)fileStream);
			try
			{
				if ((val.Channels != 1 && val.Channels != 2) || val.SampleRate < 8000 || val.SampleRate > 192000)
				{
					throw new InvalidDataException("Use a mono or stereo MP3 with a supported sample rate.");
				}
				List<float[]> list = new List<float[]>();
				int num = 0;
				while (true)
				{
					float[] array = new float[16384];
					int num2 = val.ReadSamples(array, 0, array.Length);
					if (num2 == 0)
					{
						break;
					}
					if (num2 < 0 || num2 > array.Length || num > maxSamples - num2)
					{
						throw new InvalidDataException("Audio exceeds the decoded sample limit (128 MiB maximum).");
					}
					for (int i = 0; i < num2; i++)
					{
						if (float.IsNaN(array[i]) || float.IsInfinity(array[i]))
						{
							throw new InvalidDataException("MP3 contains invalid decoded samples.");
						}
						array[i] = Math.Max(-1f, Math.Min(1f, array[i]));
					}
					if (num2 != array.Length)
					{
						Array.Resize(ref array, num2);
					}
					list.Add(array);
					num += num2;
				}
				if (num == 0 || num % val.Channels != 0)
				{
					throw new InvalidDataException("MP3 contains no complete audio samples.");
				}
				float[] array2 = new float[num];
				int num3 = 0;
				foreach (float[] item in list)
				{
					Array.Copy(item, 0, array2, num3, item.Length);
					num3 += item.Length;
				}
				return new PcmWave
				{
					samples = array2,
					channels = val.Channels,
					rate = val.SampleRate
				};
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
	public sealed class RadioAudioGrid : GridUI
	{
		private sealed class Item
		{
			internal string key;

			internal string label;

			internal Action action;

			internal bool selected;
		}

		private readonly List<Item> items = new List<Item>();

		private readonly List<UnlockableContentGridElementUi> nativeTiles = new List<UnlockableContentGridElementUi>();

		private readonly List<Image> fallbackTiles = new List<Image>();

		private UnlockableContentGridElementUi prefab;

		private PlayerData player;

		private bool horn;

		private bool settings;

		private int focused;

		private int lastSubmitFrame = -1;

		private ScrollRect scroll;

		private RectTransform viewport;

		private RectTransform content;

		private GridLayoutGroup layout;

		private TMP_Text heading;

		private TMP_Text hint;

		private static Sprite roundedBackground;

		internal bool Locked;

		private RadioAudioService Audio
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)RadioPlugin.Instance))
				{
					return null;
				}
				return RadioPlugin.Instance.Radio;
			}
		}

		internal void Initialize(PlayerData owner, bool isHorn, UnlockableContentGridElementUi template)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Expected O, but got Unknown
			player = owner;
			horn = isHorn;
			prefab = template;
			GameObject val = new GameObject("Garage-style rounded panel", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(((Component)this).transform, false);
			val.transform.SetAsFirstSibling();
			Place((RectTransform)val.transform, Vector2.zero, Vector2.one, new Vector2(-17f, -18f), new Vector2(17f, 16f));
			Image component = val.GetComponent<Image>();
			component.sprite = RoundedBackground();
			component.type = (Type)1;
			((Graphic)component).color = new Color(0.88f, 0.9f, 0.96f, 0.98f);
			((Graphic)component).raycastTarget = false;
			heading = Label(((Component)this).transform, "Selected sound", 22);
			Place(heading.rectTransform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(16f, -62f), new Vector2(-16f, -8f));
			hint = Label(((Component)this).transform, "Audio hint", 16);
			Place(hint.rectTransform, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(16f, 4f), new Vector2(-16f, 38f));
			GameObject val2 = new GameObject("Audio scroll", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(RectMask2D),
				typeof(ScrollRect)
			});
			val2.transform.SetParent(((Component)this).transform, false);
			viewport = (RectTransform)val2.transform;
			Place(viewport, Vector2.zero, Vector2.one, new Vector2(8f, 44f), new Vector2(-8f, -68f));
			((Graphic)val2.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0f);
			content = new GameObject("Audio tile content", new Type[2]
			{
				typeof(RectTransform),
				typeof(GridLayoutGroup)
			}).GetComponent<RectTransform>();
			((Transform)content).SetParent((Transform)(object)viewport, false);
			content.anchorMin = new Vector2(0f, 1f);
			content.anchorMax = Vector2.one;
			content.pivot = new Vector2(0.5f, 1f);
			content.anchoredPosition = Vector2.zero;
			layout = ((Component)content).GetComponent<GridLayoutGroup>();
			layout.constraint = (Constraint)1;
			layout.constraintCount = 3;
			layout.spacing = new Vector2(8f, 12f);
			((LayoutGroup)layout).padding = new RectOffset
			{
				left = 8,
				right = 8,
				top = 10,
				bottom = 10
			};
			((LayoutGroup)layout).childAlignment = (TextAnchor)1;
			scroll = val2.GetComponent<ScrollRect>();
			scroll.viewport = viewport;
			scroll.content = content;
			scroll.horizontal = false;
			scroll.vertical = true;
			scroll.scrollSensitivity = 25f;
			scroll.movementType = (MovementType)2;
			((GridUI)this).IsInit = true;
			Rebuild();
		}

		internal void Bind(PlayerData owner)
		{
			if ((Object)(object)player != (Object)(object)owner)
			{
				player = owner;
				focused = 0;
				settings = false;
				Rebuild();
			}
		}

		private void Add(string key, string text, Action action, bool selected = false)
		{
			items.Add(new Item
			{
				key = key,
				label = text,
				action = action,
				selected = selected
			});
		}

		private void Rebuild()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (!((GridUI)this).IsInit || !Object.op_Implicit((Object)(object)content))
			{
				return;
			}
			foreach (Transform item in (Transform)content)
			{
				((Component)item).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			nativeTiles.Clear();
			fallbackTiles.Clear();
			items.Clear();
			RadioAudioService audio = Audio;
			if (!Object.op_Implicit((Object)(object)player) || !((NetworkBehaviour)player).IsOwner || audio == null)
			{
				heading.text = "Join a lobby to choose your sounds";
				hint.text = "Radio and Horn tabs appear beside the car customisations.";
				return;
			}
			if (settings)
			{
				Add("back", "Back to sounds", delegate
				{
					settings = false;
					focused = 0;
				});
				if (horn)
				{
					Add("volume-", "Your horn −\n" + audio.OwnHornVolume(player) + "%", delegate
					{
						audio.SetOwnHornVolume(player, audio.OwnHornVolume(player) - 5);
					});
					Add("volume+", "Your horn +\n" + audio.OwnHornVolume(player) + "%", delegate
					{
						audio.SetOwnHornVolume(player, audio.OwnHornVolume(player) + 5);
					});
					Add("enabled", audio.HornsEnabled ? "Custom horns\nOn" : "Custom horns\nOff", delegate
					{
						audio.SetHornsEnabled(!audio.HornsEnabled);
					});
					Add("others-", "Others' horns −\n" + audio.OtherHornVolume + "%", delegate
					{
						audio.SetOtherHornVolume(audio.OtherHornVolume - 5);
					});
					Add("others+", "Others' horns +\n" + audio.OtherHornVolume + "%", delegate
					{
						audio.SetOtherHornVolume(audio.OtherHornVolume + 5);
					});
				}
				else
				{
					Add("volume-", "Your radio −\n" + Mathf.RoundToInt(audio.Volume(player) * 100f) + "%", delegate
					{
						audio.ChangeVolume(player, -5);
					});
					Add("volume+", "Your radio +\n" + Mathf.RoundToInt(audio.Volume(player) * 100f) + "%", delegate
					{
						audio.ChangeVolume(player, 5);
					});
					Add("enabled", audio.Enabled ? "Radio\nOn" : "Radio\nOff", delegate
					{
						audio.SetEnabled(!audio.Enabled);
					});
					Add("others-", "Others' radios −\n" + audio.OtherRadioVolume + "%", delegate
					{
						audio.SetOtherRadioVolume(audio.OtherRadioVolume - 5);
					});
					Add("others+", "Others' radios +\n" + audio.OtherRadioVolume + "%", delegate
					{
						audio.SetOtherRadioVolume(audio.OtherRadioVolume + 5);
					});
					Add("playback", "Playback mode\n" + audio.PlaybackModeName(player), delegate
					{
						audio.CyclePlaybackMode(player);
					});
					Add("playlist", "Playlist\n" + audio.PlaylistModeName(player), delegate
					{
						audio.CyclePlaylistMode(player);
					});
					Add("popup", audio.ShowNowPlaying ? "Now Playing\nPopup On" : "Now Playing\nPopup Off", delegate
					{
						audio.ToggleNowPlaying();
					});
					Add("mode", audio.Restart(player) ? "Restart on press" : "Resume on press", delegate
					{
						audio.ToggleResume(player);
					});
				}
				Add("preview", "Preview", delegate
				{
					Preview();
				});
				Add("stop", "Stop preview", delegate
				{
					audio.StopPreview();
				});
				Add("refresh", "Refresh audio files", delegate
				{
					audio.Refresh();
				});
			}
			else
			{
				string text = (horn ? audio.SelectedHornHash(player) : audio.Hash(player));
				Add("stock", horn ? "Normal game horn" : "Radio Off", delegate
				{
					audio.StopPreview();
					if (horn)
					{
						audio.ChooseHorn(player, "");
					}
					else
					{
						audio.Choose(player, "");
					}
				}, string.IsNullOrEmpty(text));
				foreach (RadioTrack item2 in horn ? audio.hornTracks : audio.tracks)
				{
					RadioTrack sound = item2;
					Add(sound.hash, Path.GetFileNameWithoutExtension(sound.file), delegate
					{
						if (horn)
						{
							audio.ChooseHorn(player, sound.hash);
						}
						else
						{
							audio.Choose(player, sound.hash);
						}
						Preview();
					}, sound.hash == text);
				}
				Add("settings", "Volume / settings", delegate
				{
					settings = true;
					focused = 0;
				});
				Add("preview", "Preview", delegate
				{
					Preview();
				});
				Add("refresh", "Refresh audio files", delegate
				{
					audio.Refresh();
				});
			}
			for (int num = 0; num < items.Count; num++)
			{
				BuildTile(num);
			}
			focused = Mathf.Clamp(focused, 0, Math.Max(0, items.Count - 1));
			Resize();
			RefreshStyles();
		}

		private void Preview()
		{
			RadioAudioService audio = Audio;
			if (audio != null && Object.op_Implicit((Object)(object)player))
			{
				if (horn)
				{
					audio.PreviewHorn(player);
				}
				else
				{
					audio.Preview(player);
				}
			}
		}

		private void BuildTile(int index)
		{
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Expected O, but got Unknown
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: 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_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: 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_017a: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			Item item = items[index];
			Navigation navigation;
			if (Object.op_Implicit((Object)(object)prefab))
			{
				UnlockableContentGridElementUi val = Object.Instantiate<UnlockableContentGridElementUi>(prefab, (Transform)(object)content, false);
				((Object)val).name = "Audio: " + item.key;
				((Component)val).gameObject.SetActive(true);
				val.Init(Color.white, index, false);
				val.previewImage.texture = (Texture)(object)RadioIcons.Texture(horn);
				((Graphic)val.previewImage).color = Color.white;
				val.indexLabel.richText = false;
				val.indexLabel.text = ((index == 0 && !settings) ? "Stock" : (index + 1).ToString());
				TMP_Text obj = Label(((Component)val).transform, item.label, 13);
				Place(obj.rectTransform, Vector2.zero, new Vector2(1f, 0f), new Vector2(5f, 1f), new Vector2(-5f, 35f));
				obj.alignment = (TextAlignmentOptions)514;
				CustomButton button = val.button;
				button.useLabel = false;
				button.useLocalizationString = false;
				button.useSounds = false;
				navigation = default(Navigation);
				((Navigation)(ref navigation)).mode = (Mode)0;
				((Selectable)button).navigation = navigation;
				button.onSubmit = new UnityEvent();
				button.onEnter = new UnityEvent();
				button.onExit = new UnityEvent();
				button.onDown = new UnityEvent();
				button.onUp = new UnityEvent();
				button.onEnter.AddListener((UnityAction)delegate
				{
					Hover(index, reveal: false);
				});
				button.onSubmit.AddListener((UnityAction)delegate
				{
					Activate(index);
				});
				nativeTiles.Add(val);
			}
			else
			{
				GameObject val2 = new GameObject("Audio: " + item.key, new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				val2.transform.SetParent((Transform)(object)content, false);
				Image component = val2.GetComponent<Image>();
				fallbackTiles.Add(component);
				GameObject val3 = new GameObject("Audio icon", new Type[2]
				{
					typeof(RectTransform),
					typeof(RawImage)
				});
				val3.transform.SetParent(val2.transform, false);
				val3.GetComponent<RawImage>().texture = (Texture)(object)RadioIcons.Texture(horn);
				Place((RectTransform)val3.transform, new Vector2(0f, 0.3f), Vector2.one, new Vector2(12f, 0f), new Vector2(-12f, -12f));
				((Graphic)val3.GetComponent<RawImage>()).raycastTarget = false;
				TMP_Text obj2 = Label(val2.transform, item.label, 18);
				Place(obj2.rectTransform, Vector2.zero, new Vector2(1f, 0.3f), new Vector2(6f, 3f), new Vector2(-6f, 0f));
				obj2.alignment = (TextAlignmentOptions)514;
				Button component2 = val2.GetComponent<Button>();
				navigation = default(Navigation);
				((Navigation)(ref navigation)).mode = (Mode)0;
				((Selectable)component2).navigation = navigation;
				((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
				{
					Activate(index);
				});
			}
		}

		private static Sprite RoundedBackground()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)roundedBackground))
			{
				return roundedBackground;
			}
			Texture2D val = new Texture2D(96, 96, (TextureFormat)4, false);
			((Object)val).name = "Radio garage-style panel";
			((Texture)val).wrapMode = (TextureWrapMode)1;
			for (int i = 0; i < 96; i++)
			{
				for (int j = 0; j < 96; j++)
				{
					float num = 1f;
					if (i < 35 && (j < 35 || j >= 61))
					{
						float num2 = ((j < 35) ? 34.5f : 60.5f);
						float num3 = 34.5f;
						float num4 = (float)j - num2;
						float num5 = (float)i - num3;
						num = Mathf.Clamp01(35.5f - Mathf.Sqrt(num4 * num4 + num5 * num5));
					}
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num));
				}
			}
			val.Apply();
			roundedBackground = Sprite.Create(val, new Rect(0f, 0f, 96f, 96f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(35f, 35f, 35f, 35f));
			return roundedBackground;
		}

		private TMP_Text Label(Transform parent, string value, int size)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text val = (TMP_Text)((!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.indexLabel)) ? ((object)new GameObject("Radio label", new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>()) : ((object)Object.Instantiate<TMP_Text>(prefab.indexLabel, parent, false)));
			val.transform.SetParent(parent, false);
			val.fontSize = size;
			((Graphic)val).color = new Color(0.3f, 0.34f, 0.48f);
			val.richText = false;
			((Graphic)val).raycastTarget = false;
			val.enableWordWrapping = true;
			val.text = value;
			if (!Object.op_Implicit((Object)(object)val.font))
			{
				val.font = TMP_Settings.defaultFontAsset;
			}
			return val;
		}

		private static void Place(RectTransform rect, Vector2 min, Vector2 max, Vector2 offsetMin, Vector2 offsetMax)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			rect.anchorMin = min;
			rect.anchorMax = max;
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.offsetMin = offsetMin;
			rect.offsetMax = offsetMax;
			((Transform)rect).localScale = Vector3.one;
			((Transform)rect).localRotation = Quaternion.identity;
		}

		private void Resize()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)layout) && Object.op_Implicit((Object)(object)viewport))
			{
				Rect rect = viewport.rect;
				float num = Mathf.Max(30f, (((Rect)(ref rect)).width - 48f) / 3f);
				layout.cellSize = new Vector2(num, num * 1.22f);
				content.sizeDelta = new Vector2(0f, 20f + (float)((items.Count + 2) / 3) * (layout.cellSize.y + 12f));
			}
		}

		private void OnRectTransformDimensionsChange()
		{
			if (((GridUI)this).IsInit)
			{
				Resize();
			}
		}

		private void Hover(int index, bool reveal)
		{
			if (!Locked && Object.op_Implicit((Object)(object)player))
			{
				focused = Mathf.Clamp(index, 0, Math.Max(0, items.Count - 1));
				RefreshStyles();
				if (reveal)
				{
					Reveal();
				}
			}
		}

		private void RefreshStyles()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < nativeTiles.Count; i++)
			{
				nativeTiles[i].ChangeStyle(i == focused, items[i].selected, true);
			}
			for (int j = 0; j < fallbackTiles.Count; j++)
			{
				((Graphic)fallbackTiles[j]).color = ((j == focused) ? new Color(0.7f, 0.79f, 1f) : (items[j].selected ? new Color(0.96f, 0.77f, 1f) : new Color(0.82f, 0.84f, 0.9f)));
			}
			if (Audio != null && Object.op_Implicit((Object)(object)player))
			{
				heading.text = (horn ? "HORN" : "RADIO") + (settings ? " / SETTINGS" : "") + "\n" + (horn ? Audio.SelectedHornName(player) : Audio.SelectedName(player));
				hint.text = ((items.Count > 0) ? (items[focused].label + "  ·  Confirm to select") : "Add MP3/WAV files, then refresh.");
				if (!settings && (horn ? Audio.hornTracks.Count : Audio.tracks.Count) == 0)
				{
					hint.text = "Add MP3/WAV files to " + (horn ? "horns/" : "music/") + ", then choose Refresh.";
				}
			}
		}

		private void Reveal()
		{
			//IL_003c: 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)
			//IL_0068: 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)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)scroll) && Object.op_Implicit((Object)(object)content) && Object.op_Implicit((Object)(object)viewport))
			{
				float num = 10f + (float)(focused / 3) * (layout.cellSize.y + 12f);
				float num2 = num + layout.cellSize.y;
				Rect rect = viewport.rect;
				float height = ((Rect)(ref rect)).height;
				float num3 = content.anchoredPosition.y;
				if (num < num3)
				{
					num3 = num;
				}
				else if (num2 > num3 + height)
				{
					num3 = num2 - height;
				}
				content.anchoredPosition = new Vector2(0f, Mathf.Clamp(num3, 0f, Mathf.Max(0f, content.sizeDelta.y - height)));
			}
		}

		internal void FocusSelected()
		{
			if (!((GridUI)this).IsInit)
			{
				return;
			}
			if (!settings)
			{
				int num = items.FindIndex((Item i) => i.selected);
				if (num >= 0)
				{
					focused = num;
				}
			}
			RefreshStyles();
			Reveal();
		}

		private void Activate(int index)
		{
			if (!Locked && Object.op_Implicit((Object)(object)player) && ((NetworkBehaviour)player).IsOwner && index >= 0 && index < items.Count && lastSubmitFrame != Time.frameCount)
			{
				lastSubmitFrame = Time.frameCount;
				focused = index;
				items[index].action();
				Rebuild();
				Reveal();
			}
		}

		private object Move(int x, int y)
		{
			Hover(RadioUiRules.Move(focused, items.Count, 3, x, y), reveal: true);
			return null;
		}

		public override object MoveRight()
		{
			return Move(1, 0);
		}

		public override object MoveLeft()
		{
			return Move(-1, 0);
		}

		public override object MoveUp()
		{
			return Move(0, -1);
		}

		public override object MoveDown()
		{
			return Move(0, 1);
		}

		public override object Select()
		{
			Activate(focused);
			return null;
		}

		private void OnEnable()
		{
			if (((GridUI)this).IsInit)
			{
				Rebuild();
				FocusSelected();
			}
		}

		private void OnDisable()
		{
			if (Audio != null)
			{
				Audio.StopPreview();
			}
		}
	}
	internal sealed class RadioTrack
	{
		internal string file;

		internal string path;

		internal string hash;

		internal AudioClip clip;
	}
	internal sealed class RadioPlayback
	{
		internal SplitScreenAudioPlayer player;

		internal string hash;

		internal bool held;

		internal bool localOwner;

		internal bool announced;

		internal float playedSeconds;

		internal AudioSource[] sources;
	}
	internal sealed class HornMuteState
	{
		internal bool mute;
	}
	internal sealed class RadioAudioService
	{
		private static readonly MethodInfo unpause = typeof(AudioSource).GetMethod("UnPause", BindingFlags.Instance | BindingFlags.Public);

		private readonly RadioPlugin p;

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

		internal readonly List<RadioTrack> hornTracks = new List<RadioTrack>();

		private readonly Dictionary<int, RadioPlayback> playback = new Dictionary<int, RadioPlayback>();

		private readonly Dictionary<int, RadioPlayback> hornPlayback = new Dictionary<int, RadioPlayback>();

		private readonly Dictionary<int, ConfigEntry<string>> selected = new Dictionary<int, ConfigEntry<string>>();

		private readonly Dictionary<int, ConfigEntry<int>> volumes = new Dictionary<int, ConfigEntry<int>>();

		private readonly Dictionary<int, ConfigEntry<int>> modes = new Dictionary<int, ConfigEntry<int>>();

		private readonly Dictionary<int, ConfigEntry<int>> playbackModes = new Dictionary<int, ConfigEntry<int>>();

		private readonly Dictionary<int, ConfigEntry<int>> playlistModes = new Dictionary<int, ConfigEntry<int>>();

		private readonly Dictionary<int, ConfigEntry<string>> selectedHorn = new Dictionary<int, ConfigEntry<string>>();

		private readonly Dictionary<int, ConfigEntry<int>> hornVolumes = new Dictionary<int, ConfigEntry<int>>();

		private readonly Dictionary<int, int> hornSequence = new Dictionary<int, int>();

		private readonly Dictionary<int, int> observedHornSequence = new Dictionary<int, int>();

		private readonly Dictionary<int, string> remoteHornHashes = new Dictionary<int, string>();

		private readonly Dictionary<AudioSource, HornMuteState> mutedHornSources = new Dictionary<AudioSource, HornMuteState>();

		private ConfigEntry<int> others;

		private ConfigEntry<int> otherHornVolume;

		private ConfigEntry<bool> enabled;

		private ConfigEntry<bool> hornsEnabled;

		private ConfigEntry<bool> showNowPlaying;

		private readonly Random shuffleRandom = new Random();

		internal string directory;

		internal string hornDirectory;

		private bool missingNotice;

		private bool missingHornNotice;

		private readonly HashSet<string> failed = new HashSet<string>();

		private readonly HashSet<string> failedHornNotices = new HashSet<string>();

		private readonly HashSet<int> loggedHornSourceControllers = new HashSet<int>();

		private GameObject preview;

		internal bool MenuOpen => RadioMenu.RadioOpen;

		internal bool Enabled => enabled.Value;

		internal bool HornsEnabled => hornsEnabled.Value;

		internal bool ShowNowPlaying => showNowPlaying.Value;

		internal int OtherRadioVolume => others.Value;

		internal string OtherMix
		{
			get
			{
				if (others.Value != 0)
				{
					return "Other radios audible";
				}
				return "Other radios muted";
			}
		}

		internal int OtherHornVolume => otherHornVolume.Value;

		internal RadioAudioService(RadioPlugin plugin)
		{
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Expected O, but got Unknown
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			p = plugin;
			enabled = ((BaseUnityPlugin)p).Config.Bind<bool>("Local Radio", "Enabled", true, "Play accelerator radio sounds on this computer.");
			showNowPlaying = ((BaseUnityPlugin)p).Config.Bind<bool>("Local Radio", "NowPlayingPopup", true, "Show a short popup when your radio starts a new track.");
			hornsEnabled = ((BaseUnityPlugin)p).Config.Bind<bool>("Custom Horns", "Enabled", true, "Enable custom horn sounds when a horn sound is selected.");
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)p).Info.Location);
			directory = Path.Combine(directoryName, "music");
			hornDirectory = Path.Combine(directoryName, "horns");
			Directory.CreateDirectory(directory);
			Directory.CreateDirectory(hornDirectory);
			others = ((BaseUnityPlugin)p).Config.Bind<int>("Local Radio", "OtherDriversVolume", 100, new ConfigDescription("Local mix for other drivers' accelerator radio", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			otherHornVolume = ((BaseUnityPlugin)p).Config.Bind<int>("Custom Horns", "OtherPlayersVolume", 70, new ConfigDescription("Local volume for other players' custom horns", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			Refresh();
		}

		internal void SetEnabled(bool value)
		{
			if (enabled.Value != value)
			{
				enabled.Value = value;
				((BaseUnityPlugin)p).Config.Save();
				if (!value)
				{
					StopRadio();
				}
			}
		}

		internal void SetHornsEnabled(bool value)
		{
			if (hornsEnabled.Value != value)
			{
				hornsEnabled.Value = value;
				((BaseUnityPlugin)p).Config.Save();
				if (!value)
				{
					StopHorns();
				}
			}
		}

		private void Ensure(PlayerData player)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Expected O, but got Unknown
			int localIndex = player.LocalIndex;
			if (!selected.ContainsKey(localIndex))
			{
				selected[localIndex] = ((BaseUnityPlugin)p).Config.Bind<string>("Local Radio", "Player" + localIndex + "Track", (tracks.Count > 0) ? tracks[0].hash : "", "Selected accelerator radio audio-file hash");
				volumes[localIndex] = ((BaseUnityPlugin)p).Config.Bind<int>("Local Radio", "Player" + localIndex + "Volume", 35, new ConfigDescription("Accelerator radio volume percent", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
				playbackModes[localIndex] = ((BaseUnityPlugin)p).Config.Bind<int>("Local Radio", "Player" + localIndex + "PlaybackMode", 0, new ConfigDescription("0 = accelerator, 1 = always on, 2 = off", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
				playlistModes[localIndex] = ((BaseUnityPlugin)p).Config.Bind<int>("Local Radio", "Player" + localIndex + "PlaylistMode", 0, new ConfigDescription("0 = repeat current song; 1 = shuffle; 2 = next file in folder order", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
				modes[localIndex] = ((BaseUnityPlugin)p).Config.Bind<int>("Local Radio", "Player" + localIndex + "Resume", 1, new ConfigDescription("1 resume; 0 restart each accelerator press", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1), Array.Empty<object>()));
				selectedHorn[localIndex] = ((BaseUnityPlugin)p).Config.Bind<string>("Custom Horns", "Player" + localIndex + "Horn", "", "Selected custom horn audio-file hash. Empty uses the game's normal horn.");
				hornVolumes[localIndex] = ((BaseUnityPlugin)p).Config.Bind<int>("Custom Horns", "Player" + localIndex + "Volume", 65, new ConfigDescription("Your own custom horn volume on this computer", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			}
		}

		internal void Refresh()
		{
			RefreshList(directory, tracks, "music");
			RefreshList(hornDirectory, hornTracks, "horn");
			missingNotice = false;
			missingHornNotice = false;
			failed.Clear();
			failedHornNotices.Clear();
		}

		private void RefreshList(string folder, List<RadioTrack> destination, string kind)
		{
			Dictionary<string, RadioTrack> dictionary = (from t in destination
				group t by t.hash).ToDictionary((IGrouping<string, RadioTrack> g) => g.Key, (IGrouping<string, RadioTrack> g) => g.First());
			destination.Clear();
			foreach (RadioAudioFile item in RadioAudioFiles.Scan(folder, p.Note))
			{
				if (dictionary.TryGetValue(item.hash, out var value))
				{
					value.file = item.file;
					value.path = item.path;
					destination.Add(value);
				}
				else
				{
					destination.Add(new RadioTrack
					{
						file = item.file,
						path = item.path,
						hash = item.hash
					});
				}
			}
			foreach (RadioTrack item2 in dictionary.Values.Where((RadioTrack t) => !destination.Contains(t)))
			{
				if (Object.op_Implicit((Object)(object)item2.clip))
				{
					Object.Destroy((Object)(object)item2.clip);
				}
			}
			p.Note("Radio menu found " + destination.Count + " " + kind + " MP3/WAV files in " + folder);
		}

		internal string Hash(PlayerData player)
		{
			Ensure(player);
			return selected[player.LocalIndex].Value;
		}

		internal float Volume(PlayerData player)
		{
			Ensure(player);
			return (float)volumes[player.LocalIndex].Value / 100f;
		}

		internal int PlaybackMode(PlayerData player)
		{
			Ensure(player);
			return playbackModes[player.LocalIndex].Value;
		}

		internal string PlaybackModeName(PlayerData player)
		{
			return PlaybackMode(player) switch
			{
				2 => "Off", 
				1 => "Always On", 
				_ => "Accelerator", 
			};
		}

		internal void CyclePlaybackMode(PlayerData player)
		{
			Ensure(player);
			ConfigEntry<int> obj = playbackModes[player.LocalIndex];
			obj.Value = (obj.Value + 1) % 3;
			((BaseUnityPlugin)p).Config.Save();
		}

		internal int PlaylistMode(PlayerData player)
		{
			Ensure(player);
			return playlistModes[player.LocalIndex].Value;
		}

		internal string PlaylistModeName(PlayerData player)
		{
			return PlaylistMode(player) switch
			{
				2 => "Next File", 
				1 => "Shuffle", 
				_ => "Repeat Song", 
			};
		}

		internal void CyclePlaylistMode(PlayerData player)
		{
			Ensure(player);
			ConfigEntry<int> obj = playlistModes[player.LocalIndex];
			obj.Value = (obj.Value + 1) % 3;
			((BaseUnityPlugin)p).Config.Save();
		}

		internal void ToggleNowPlaying()
		{
			showNowPlaying.Value = !showNowPlaying.Value;
			((BaseUnityPlugin)p).Config.Save();
		}

		internal bool Restart(PlayerData player)
		{
			Ensure(player);
			return modes[player.LocalIndex].Value == 0;
		}

		internal string SelectedName(PlayerData player)
		{
			string hash = Hash(player);
			RadioTrack radioTrack = tracks.FirstOrDefault((RadioTrack t) => t.hash == hash);
			if (radioTrack != null)
			{
				return radioTrack.file;
			}
			return "Off";
		}

		internal void Choose(PlayerData player, string hash)
		{
			Ensure(player);
			selected[player.LocalIndex].Value = hash ?? "";
			((BaseUnityPlugin)p).Config.Save();
		}

		internal void ChangeVolume(PlayerData player, int delta)
		{
			Ensure(player);
			ConfigEntry<int> obj = volumes[player.LocalIndex];
			obj.Value = Mathf.Clamp(obj.Value + delta, 0, 100);
			((BaseUnityPlugin)p).Config.Save();
		}

		internal void SetVolume(PlayerData player, int value)
		{
			Ensure(player);
			value = Mathf.Clamp(value, 0, 100);
			if (volumes[player.LocalIndex].Value != value)
			{
				volumes[player.LocalIndex].Value = value;
				((BaseUnityPlugin)p).Config.Save();
			}
		}

		internal void ToggleResume(PlayerData player)
		{
			Ensure(player);
			modes[player.LocalIndex].Value = 1 - modes[player.LocalIndex].Value;
			((BaseUnityPlugin)p).Config.Save();
		}

		internal void ToggleOthers()
		{
			others.Value = ((others.Value == 0) ? 100 : 0);
			((BaseUnityPlugin)p).Config.Save();
		}

		internal void SetOtherRadioVolume(int value)
		{
			value = Mathf.Clamp(value, 0, 100);
			if (others.Value != value)
			{
				others.Value = value;
				((BaseUnityPlugin)p).Config.Save();
			}
		}

		internal string SelectedHornHash(PlayerData player)
		{
			Ensure(player);
			return selectedHorn[player.LocalIndex].Value;
		}

		internal string HornHash(PlayerData player)
		{
			if (!HornsEnabled)
			{
				return "";
			}
			return SelectedHornHash(player);
		}

		internal string SelectedHornName(PlayerData player)
		{
			string hash = SelectedHornHash(player);
			RadioTrack radioTrack = hornTracks.FirstOrDefault((RadioTrack t) => t.hash == hash);
			if (radioTrack != null)
			{
				return radioTrack.file;
			}
			return "Normal game horn";
		}

		internal void ChooseHorn(PlayerData player, string hash)
		{
			Ensure(player);
			selectedHorn[player.LocalIndex].Value = hash ?? "";
			((BaseUnityPlugin)p).Config.Save();
			MaintainNativeHornMute();
		}

		internal int OwnHornVolume(PlayerData player)
		{
			Ensure(player);
			return hornVolumes[player.LocalIndex].Value;
		}

		internal void SetOwnHornVolume(PlayerData player, int value)
		{
			Ensure(player);
			value = Mathf.Clamp(value, 0, 100);
			if (hornVolumes[player.LocalIndex].Value != value)
			{
				hornVolumes[player.LocalIndex].Value = value;
				((BaseUnityPlugin)p).Config.Save();
			}
		}

		internal void SetOtherHornVolume(int value)
		{
			value = Mathf.Clamp(value, 0, 100);
			if (otherHornVolume.Value != value)
			{
				otherHornVolume.Value = value;
				((BaseUnityPlugin)p).Config.Save();
			}
		}

		internal int HornSequence(int playerId)
		{
			if (!hornSequence.TryGetValue(playerId, out var value))
			{
				return 0;
			}
			return value;
		}

		private AudioClip Load(RadioTrack track)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			if (track == null)
			{
				return null;
			}
			if (Object.op_Implicit((Object)(object)track.clip))
			{
				return track.clip;
			}
			if (failed.Contains(track.hash))
			{
				return null;
			}
			try
			{
				PcmWave pcmWave = RadioAudioFiles.Decode(track.path);
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
				MethodInfo method = typeof(AudioClip).GetMethod("Construct_Internal", bindingAttr);
				MethodInfo method2 = typeof(AudioClip).GetMethod("CreateUserSound", bindingAttr);
				MethodInfo method3 = typeof(AudioClip).GetMethod("SetData", bindingAttr, null, new Type[4]
				{
					typeof(AudioClip),
					typeof(float[]),
					typeof(int),
					typeof(int)
				}, null);
				if (method == null || method2 == null || method3 == null)
				{
					throw new InvalidOperationException("The Slip & Skid Radio Audio Bootstrap patcher is missing. Install it in BepInEx/patchers and restart the game.");
				}
				AudioClip val = (AudioClip)method.Invoke(null, null);
				method2.Invoke(val, new object[5]
				{
					track.file,
					pcmWave.samples.Length / pcmWave.channels,
					pcmWave.channels,
					pcmWave.rate,
					false
				});
				if (!(bool)method3.Invoke(null, new object[4]
				{
					val,
					pcmWave.samples,
					pcmWave.samples.Length / pcmWave.channels,
					0
				}))
				{
					Object.Destroy((Object)(object)val);
					throw new InvalidOperationException("Audio upload failed");
				}
				track.clip = val;
				return val;
			}
			catch (Exception ex)
			{
				failed.Add(track.hash);
				p.Note("Radio file failed: " + track.file + " — " + ex.Message);
				return null;
			}
		}

		internal void NotifyHonk(PlayerData player)
		{
			if (Object.op_Implicit((Object)(object)player) && ((NetworkBehaviour)player).IsOwner)
			{
				int value = player.playerIndex.Value;
				if (!hornSequence.TryGetValue(value, out var value2))
				{
					value2 = 0;
				}
				value2++;
				hornSequence[value] = value2;
				observedHornSequence[value] = value2;
				remoteHornHashes[value] = HornHash(player);
				if (HornsEnabled && !string.IsNullOrEmpty(remoteHornHashes[value]))
				{
					PlayHorn(value, remoteHornHashes[value], localOwner: true);
				}
				LogHornSourcesOnce(player);
				MaintainNativeHornMute();
			}
		}

		internal void Frame(RadioPacket packet)
		{
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			PlayerData val = RadioPlugin.Player(packet.player);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.controller) || val.isDead.Value || val.finishedRace.Value)
			{
				PauseRadio(packet.player);
				return;
			}
			remoteHornHashes[packet.player] = packet.hornClip ?? "";
			if (!observedHornSequence.TryGetValue(packet.player, out var value))
			{
				observedHornSequence[packet.player] = packet.hornSequence;
			}
			else if (packet.hornSequence != value)
			{
				observedHornSequence[packet.player] = packet.hornSequence;
				if (HornsEnabled && packet.hornSequence != 0 && !string.IsNullOrEmpty(packet.hornClip))
				{
					PlayHorn(packet.player, packet.hornClip, ((NetworkBehaviour)val).IsOwner);
				}
			}
			if (!Enabled || !p.Racing)
			{
				PauseRadio(packet.player);
				return;
			}
			if (!playback.TryGetValue(packet.player, out var value2))
			{
				value2 = new RadioPlayback();
				playback[packet.player] = value2;
			}
			RadioTrack radioTrack = tracks.FirstOrDefault((RadioTrack t) => t.hash == packet.clip);
			if (radioTrack == null)
			{
				PauseRadio(packet.player);
				if (packet.playbackMode != 2 && !string.IsNullOrEmpty(packet.clip) && !missingNotice)
				{
					missingNotice = true;
					p.Note("A driver's selected radio file is absent locally. Install the same MP3 or WAV file on every client to hear it.");
				}
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)SplitScreenAudioManager.instance))
				{
					return;
				}
				if (value2.hash != radioTrack.hash || !Object.op_Implicit((Object)(object)value2.player) || value2.localOwner != ((NetworkBehaviour)val).IsOwner)
				{
					AudioClip val2 = Load(radioTrack);
					if (!Object.op_Implicit((Object)(object)val2))
					{
						return;
					}
					if (Object.op_Implicit((Object)(object)value2.player))
					{
						Object.Destroy((Object)(object)((Component)value2.player).gameObject);
					}
					value2.player = Object.Instantiate<SplitScreenAudioPlayer>(SplitScreenAudioManager.instance.temporaryAudioPlayerPrefab);
					((Object)value2.player).name = "Accelerator radio " + packet.player;
					value2.player.onEnd = null;
					value2.player.maxInstancesAtTheSameTime = 0;
					value2.sources = ((Component)value2.player).GetComponentsInChildren<AudioSource>(true);
					SplitScreenAudioSource[] sources = value2.player.sources;
					foreach (SplitScreenAudioSource val3 in sources)
					{
						val3.SwitchClip(val2);
						val3.SetSpatialBlend((float)((!((NetworkBehaviour)val).IsOwner) ? 1 : 0));
						if (!((NetworkBehaviour)val).IsOwner)
						{
							val3.SetRollOfCurve(AnimationCurve.Linear(0f, 1f, 30f, 0f));
						}
					}
					AudioSource[] sources2 = value2.sources;
					foreach (AudioSource obj in sources2)
					{
						obj.loop = !((NetworkBehaviour)val).IsOwner || PlaylistMode(val) == 0;
						obj.playOnAwake = false;
					}
					value2.hash = radioTrack.hash;
					value2.held = false;
					value2.localOwner = ((NetworkBehaviour)val).IsOwner;
					value2.playedSeconds = 0f;
					value2.announced = false;
				}
				((Component)value2.player).transform.position = val.controller.car.position;
				if (((NetworkBehaviour)val).IsOwner && value2.sources != null)
				{
					AudioSource[] sources2 = value2.sources;
					foreach (AudioSource val4 in sources2)
					{
						if (Object.op_Implicit((Object)(object)val4))
						{
							val4.loop = PlaylistMode(val) == 0;
						}
					}
				}
				float num2 = Mathf.Min(packet.volume, p.VolumeCap) * (((NetworkBehaviour)val).IsOwner ? 1f : ((float)others.Value / 100f));
				value2.player.SetVolumeAndPitch(num2, 1f);
				bool flag = packet.playbackMode == 1 || (packet.playbackMode == 0 && packet.throttle);
				if (flag && !value2.held)
				{
					if (packet.restart)
					{
						value2.playedSeconds = 0f;
					}
					AudioSource[] sources2 = value2.sources;
					foreach (AudioSource val5 in sources2)
					{
						if (packet.restart)
						{
							val5.time = 0f;
							val5.Play();
							continue;
						}
						if (unpause != null)
						{
							unpause.Invoke(val5, null);
						}
						if (!val5.isPlaying)
						{
							val5.Play();
						}
					}
					value2.held = true;
					SplitScreenAudioManager.ForceOwnerUpdate(value2.player);
					if (((NetworkBehaviour)val).IsOwner && !value2.announced && ShowNowPlaying)
					{
						RadioNowPlaying.Show(Path.GetFileNameWithoutExtension(radioTrack.file), val.DisplayNameRaw);
						value2.announced = true;
					}
				}
				else if (!flag && value2.held)
				{
					AudioSource[] sources2 = value2.sources;
					for (int num = 0; num < sources2.Length; num++)
					{
						sources2[num].Pause();
					}
					value2.held = false;
				}
			}
		}

		private void PlayHorn(int playerId, string hash, bool localOwner)
		{
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			if (!HornsEnabled || string.IsNullOrEmpty(hash) || !Object.op_Implicit((Object)(object)SplitScreenAudioManager.instance))
			{
				return;
			}
			PlayerData val = RadioPlugin.Player(playerId);
			RadioTrack radioTrack = hornTracks.FirstOrDefault((RadioTrack t) => t.hash == hash);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.controller) || radioTrack == null)
			{
				if (radioTrack == null && failedHornNotices.Add(hash) && !missingHornNotice)
				{
					missingHornNotice = true;
					p.Note("A custom horn audio file selected by a player is not installed on this client. Put the same MP3 or WAV file in the Radio/horns folder on every client.");
				}
				return;
			}
			AudioClip val2 = Load(radioTrack);
			if (Object.op_Implicit((Object)(object)val2))
			{
				if (hornPlayback.TryGetValue(playerId, out var value) && Object.op_Implicit((Object)(object)value.player))
				{
					Object.Destroy((Object)(object)((Component)value.player).gameObject);
				}
				RadioPlayback radioPlayback = new RadioPlayback();
				radioPlayback.player = Object.Instantiate<SplitScreenAudioPlayer>(SplitScreenAudioManager.instance.temporaryAudioPlayerPrefab);
				((Object)radioPlayback.player).name = "Custom horn " + playerId;
				radioPlayback.player.onEnd = null;
				radioPlayback.player.maxInstancesAtTheSameTime = 0;
				radioPlayback.sources = ((Component)radioPlayback.player).GetComponentsInChildren<AudioSource>(true);
				radioPlayback.hash = hash;
				SplitScreenAudioSource[] sources = radioPlayback.player.sources;
				foreach (SplitScreenAudioSource obj in sources)
				{
					obj.SwitchClip(val2);
					obj.SetSpatialBlend(1f);
					obj.SetRollOfCurve(AnimationCurve.Linear(0f, 1f, 24f, 0f));
				}
				AudioSource[] sources2 = radioPlayback.sources;
				foreach (AudioSource obj2 in sources2)
				{
					obj2.loop = false;
					obj2.playOnAwake = false;
					obj2.time = 0f;
					obj2.Play();
				}
				int num2 = (localOwner ? OwnHornVolume(val) : OtherHornVolume);
				radioPlayback.player.SetVolumeAndPitch((float)num2 / 100f, 1f);
				((Component)radioPlayback.player).transform.position = val.controller.car.position;
				SplitScreenAudioManager.ForceOwnerUpdate(radioPlayback.player);
				hornPlayback[playerId] = radioPlayback;
				Object.Destroy((Object)(object)((Component)radioPlayback.player).gameObject, Mathf.Max(val2.length + 0.25f, 0.5f));
			}
		}

		private void AdvanceTrack(PlayerData driver)
		{
			if (!Object.op_Implicit((Object)(object)driver) || !((NetworkBehaviour)driver).IsOwner || tracks.Count == 0)
			{
				return;
			}
			int num = PlaylistMode(driver);
			if (num == 0)
			{
				return;
			}
			string current = Hash(driver);
			int num2 = tracks.FindIndex((RadioTrack t) => t.hash == current);
			int num3 = ((num == 2) ? ((num2 + 1) % tracks.Count) : shuffleRandom.Next(tracks.Count));
			if (num == 1 && tracks.Count > 1)
			{
				num3 = shuffleRandom.Next(tracks.Count - 1);
				if (num3 >= num2 && num2 >= 0)
				{
					num3++;
				}
			}
			Choose(driver, tracks[num3].hash);
		}

		internal void Tick()
		{
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled || !p.Racing)
			{
				int[] array = playback.Keys.ToArray();
				foreach (int id in array)
				{
					PauseRadio(id);
				}
			}
			else
			{
				foreach (KeyValuePair<int, RadioPlayback> item in playback)
				{
					PlayerData val = RadioPlugin.Player(item.Key);
					if (!Object.op_Implicit((Object)(object)val) || val.isDead.Value || val.finishedRace.Value || !Object.op_Implicit((Object)(object)val.controller))
					{
						PauseRadio(item.Key);
						continue;
					}
					if (Object.op_Implicit((Object)(object)item.Value.player))
					{
						((Component)item.Value.player).transform.position = val.controller.car.position;
					}
					if (!((NetworkBehaviour)val).IsOwner || !item.Value.held || PlaybackMode(val) == 2)
					{
						continue;
					}
					item.Value.playedSeconds += Time.deltaTime;
					if (PlaylistMode(val) == 0)
					{
						RadioTrack radioTrack = tracks.FirstOrDefault((RadioTrack t) => t.hash == item.Value.hash);
						if (radioTrack != null && Object.op_Implicit((Object)(object)radioTrack.clip) && radioTrack.clip.length > 0f && item.Value.playedSeconds > radioTrack.clip.length)
						{
							item.Value.playedSeconds %= radioTrack.clip.length;
						}
					}
					else
					{
						RadioTrack radioTrack2 = tracks.FirstOrDefault((RadioTrack t) => t.hash == item.Value.hash);
						if (radioTrack2 != null && Object.op_Implicit((Object)(object)radioTrack2.clip) && radioTrack2.clip.length > 0f && item.Value.playedSeconds >= radioTrack2.clip.length)
						{
							AdvanceTrack(val);
						}
					}
				}
			}
			KeyValuePair<int, RadioPlayback>[] array2 = hornPlayback.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<int, RadioPlayback> keyValuePair = array2[i];
				PlayerData val2 = RadioPlugin.Player(keyValuePair.Key);
				if (Object.op_Implicit((Object)(object)keyValuePair.Value.player) && Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.controller))
				{
					((Component)keyValuePair.Value.player).transform.position = val2.controller.car.position;
				}
				if (!Object.op_Implicit((Object)(object)keyValuePair.Value.player))
				{
					hornPlayback.Remove(keyValuePair.Key);
				}
			}
			MaintainNativeHornMute();
		}

		private void LogHornSourcesOnce(PlayerData player)
		{
			if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)player.controller))
			{
				return;
			}
			int instanceID = ((Object)player.controller).GetInstanceID();
			if (loggedHornSourceControllers.Add(instanceID))
			{
				AudioSource[] componentsInChildren = ((Component)player.controller).GetComponentsInChildren<AudioSource>(true);
				string text = string.Join(", ", componentsInChildren.Select((AudioSource source) => (Object.op_Implicit((Object)(object)source) ? ((Object)source).name : "<destroyed>") + "[" + ((Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)source.clip)) ? ((Object)source.clip).name : "no clip") + "]"));
				p.Note("Custom horn audio probe for player " + player.playerIndex.Value + ": " + ((componentsInChildren.Length == 0) ? "no AudioSources found on the car controller hierarchy" : text));
			}
		}

		private bool HasCustomHorn(PlayerData player)
		{
			if (!Object.op_Implicit((Object)(object)player) || !HornsEnabled)
			{
				return false;
			}
			string hash;
			if (((NetworkBehaviour)player).IsOwner)
			{
				hash = HornHash(player);
			}
			else if (!remoteHornHashes.TryGetValue(player.playerIndex.Value, out hash))
			{
				return false;
			}
			if (!string.IsNullOrEmpty(hash))
			{
				return hornTracks.Any((RadioTrack t) => t.hash == hash);
			}
			return false;
		}

		private static bool IsHornSource(AudioSource source)
		{
			if (!Object.op_Implicit((Object)(object)source))
			{
				return false;
			}
			string text = ((Object)source).name ?? "";
			string text2 = (Object.op_Implicit((Object)(object)((Component)source).gameObject) ? ((Object)((Component)source).gameObject).name : "");
			string text3 = (Object.op_Implicit((Object)(object)source.clip) ? ((Object)source.clip).name : "");
			if (text.IndexOf("horn", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("honk", StringComparison.OrdinalIgnoreCase) < 0 && text2.IndexOf("horn", StringComparison.OrdinalIgnoreCase) < 0 && text2.IndexOf("honk", StringComparison.OrdinalIgnoreCase) < 0 && text3.IndexOf("horn", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text3.IndexOf("honk", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private void MaintainNativeHornMute()
		{
			HashSet<AudioSource> hashSet = new HashSet<AudioSource>();
			if (HornsEnabled && Object.op_Implicit((Object)(object)GameManager.instance))
			{
				foreach (PlayerData item in RadioGame.Players.Where((PlayerData x) => Object.op_Implicit((Object)(object)x) && Object.op_Implicit((Object)(object)x.controller) && HasCustomHorn(x)))
				{
					AudioSource[] componentsInChildren = ((Component)item.controller).GetComponentsInChildren<AudioSource>(true);
					foreach (AudioSource val in componentsInChildren)
					{
						if (Object.op_Implicit((Object)(object)val) && IsHornSource(val))
						{
							hashSet.Add(val);
							if (!mutedHornSources.ContainsKey(val))
							{
								mutedHornSources[val] = new HornMuteState
								{
									mute = val.mute
								};
							}
							val.mute = true;
						}
					}
				}
			}
			KeyValuePair<AudioSource, HornMuteState>[] array = mutedHornSources.ToArray();
			for (int num = 0; num < array.Length; num++)
			{
				KeyValuePair<AudioSource, HornMuteState> keyValuePair = array[num];
				AudioSource key = keyValuePair.Key;
				if (!Object.op_Implicit((Object)(object)key) || !hashSet.Contains(key))
				{
					if (Object.op_Implicit((Object)(object)key))
					{
						key.mute = keyValuePair.Value.mute;
					}
					mutedHornSources.Remove(key);
				}
			}
		}

		private void PauseRadio(int id)
		{
			if (!playback.TryGetValue(id, out var value))
			{
				return;
			}
			if (value.sources != null)
			{
				AudioSource[] sources = value.sources;
				foreach (AudioSource val in sources)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						val.Pause();
					}
				}
			}
			value.held = false;
		}

		private void StopRadio()
		{
			foreach (RadioPlayback value in playback.Values)
			{
				if (Object.op_Implicit((Object)(object)value.player))
				{
					Object.Destroy((Object)(object)((Component)value.player).gameObject);
				}
			}
			playback.Clear();
			if (Object.op_Implicit((Object)(object)preview))
			{
				Object.Destroy((Object)(object)preview);
			}
		}

		private void StopHorns()
		{
			foreach (RadioPlayback value in hornPlayback.Values)
			{
				if (Object.op_Implicit((Object)(object)value.player))
				{
					Object.Destroy((Object)(object)((Component)value.player).gameObject);
				}
			}
			hornPlayback.Clear();
			MaintainNativeHornMute();
		}

		internal void StopPreview()
		{
			if (Object.op_Implicit((Object)(object)preview))
			{
				Object.Destroy((Object)(object)preview);
			}
			preview = null;
		}

		internal void Preview(PlayerData player)
		{
			PreviewTrack(tracks.FirstOrDefault((RadioTrack t) => t.hash == Hash(player)), Volume(player));
		}

		internal void PreviewHorn(PlayerData player)
		{
			PreviewTrack(hornTracks.FirstOrDefault((RadioTrack t) => t.hash == SelectedHornHash(player)), (float)OwnHornVolume(player) / 100f);
		}

		private void PreviewTrack(RadioTrack track, float volume)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			StopPreview();
			AudioClip val = Load(track);
			if (Object.op_Implicit((Object)(object)val))
			{
				preview = new GameObject("Local audio preview");
				AudioSource obj = preview.AddComponent<AudioSource>();
				obj.clip = val;
				obj.volume = Mathf.Min(Mathf.Clamp01(volume), 0.35f);
				obj.spatialBlend = 0f;
				obj.Play();
				Object.Destroy((Object)(object)preview, 3f);
			}
		}

		internal void Stop()
		{
			StopPreview();
			StopRadio();
			StopHorns();
			KeyValuePair<AudioSource, HornMuteState>[] array = mutedHornSources.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<AudioSource, HornMuteState> keyValuePair = array[i];
				if (Object.op_Implicit((Object)(object)keyValuePair.Key))
				{
					keyValuePair.Key.mute = keyValuePair.Value.mute;
				}
				mutedHornSources.Remove(keyValuePair.Key);
			}
		}

		internal void Dispose()
		{
			Stop();
			foreach (RadioTrack item in tracks.Concat(hornTracks))
			{
				if (Object.op_Implicit((Object)(object)item.clip))
				{
					Object.Destroy((Object)(object)item.clip);
				}
			}
		}
	}
	public sealed class RadioTabPointer : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		internal Action Clicked;

		public void OnPointerClick(PointerEventData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)data.button == 0)
			{
				Clicked?.Invoke();
			}
		}
	}
	public sealed class RadioCustomization : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<Tab, bool> <>9__14_0;

			public static UnityAction <>9__15_2;

			internal bool <Install>b__14_0(Tab t)
			{
				if (t != null && Object.op_Implicit((Object)(object)t.container) && Object.op_Implicit((Object)(object)t.containerLayout) && Object.op_Implicit((Object)(object)t.headerLabel) && Object.op_Implicit((Object)(object)t.iconHolder) && Object.op_Implicit((Object)(object)t.root) && t.headerLabel.transform.IsChildOf(((Component)t.containerLayout).transform) && ((Component)t.iconHolder).transform.IsChildOf(((Component)t.containerLayout).transform))
				{
					return ((Component)t.container).transform.IsChildOf(((Component)t.containerLayout).transform);
				}
				return false;
			}

			internal void <CreateTab>b__15_2()
			{
				if (Object.op_Implicit((Object)(object)RadioPlugin.Instance))
				{
					RadioPlugin.Instance.Radio.StopPreview();
				}
			}
		}

		internal static readonly Dictionary<Tab, string> Labels = new Dictionary<Tab, string>();

		private UnlockablePlayerCustomizationSelector selector;

		private Tab radioTab;

		private Tab hornTab;

		private RadioAudioGrid radio;

		private RadioAudioGrid horns;

		private readonly List<GameObject> headers = new List<GameObject>();

		internal PlayerData Player { get; private set; }

		internal RadioAudioGrid Current
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)selector) || !Object.op_Implicit((Object)(object)selector.tabs) || selector.tabs.tabs == null)
				{
					return null;
				}
				int currentTabIndex = selector.tabs.CurrentTabIndex;
				if (currentTabIndex < 0 || currentTabIndex >= selector.tabs.tabs.Length)
				{
					return null;
				}
				Tab val = selector.tabs.tabs[currentTabIndex];
				if (val != radioTab)
				{
					if (val != hornTab)
					{
						return null;
					}
					return horns;
				}
				return radio;
			}
		}

		internal static RadioCustomization Attach(UnlockablePlayerCustomizationSelector selector, PlayerData player)
		{
			if (!Object.op_Implicit((Object)(object)RadioPlugin.Instance) || !Object.op_Implicit((Object)(object)selector) || !Object.op_Implicit((Object)(object)selector.tabs) || !Object.op_Implicit((Object)(object)player) || !((NetworkBehaviour)player).IsOwner)
			{
				return null;
			}
			RadioCustomization radioCustomization = ((Component)selector).GetComponent<RadioCustomization>();
			if (!Object.op_Implicit((Object)(object)radioCustomization))
			{
				radioCustomization = ((Component)selector).gameObject.AddComponent<RadioCustomization>();
			}
			radioCustomization.Player = player;
			if ((Object)(object)radioCustomization.selector == (Object)null)
			{
				radioCustomization.Install(selector);
			}
			else
			{
				radioCustomization.radio.Bind(player);
				radioCustomization.horns.Bind(player);
			}
			return radioCustomization;
		}

		private void Install(UnlockablePlayerCustomizationSelector owner)
		{
			Tab[] tabs = owner.tabs.tabs;
			Tab val = tabs?.FirstOrDefault((Func<Tab, bool>)((Tab t) => t != null && Object.op_Implicit((Object)(object)t.container) && Object.op_Implicit((Object)(object)t.containerLayout) && Object.op_Implicit((Object)(object)t.headerLabel) && Object.op_Implicit((Object)(object)t.iconHolder) && Object.op_Implicit((Object)(object)t.root) && t.headerLabel.transform.IsChildOf(((Component)t.containerLayout).transform) && ((Component)t.iconHolder).transform.IsChildOf(((Component)t.containerLayout).transform) && ((Component)t.container).transform.IsChildOf(((Component)t.containerLayout).transform)));
			if (val != null && Object.op_Implicit((Object)(object)owner.carPaintGrid) && Object.op_Implicit((Object)(object)owner.carPaintGrid.selectionGridElementPrefab))
			{
				selector = owner;
				radioTab = CreateTab(val, "Radio", horn: false, out radio);
				hornTab = CreateTab(val, "Horn", horn: true, out horns);
				owner.tabs.tabs = tabs.Concat((IEnumerable<Tab>)(object)new Tab[2] { radioTab, hornTab }).ToArray();
				radioTab.Init();
				hornTab.Init();
				radioTab.Deselect();
				hornTab.Deselect();
				RadioPlugin.Instance.Note("Garage Radio and Horn tabs attached for local driver " + Player.LocalIndex + ".");
			}
		}

		private Tab CreateTab(Tab source, string title, bool horn, out RadioAudioGrid grid)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0133: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_0237: Expected O, but got Unknown
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Expected O, but got Unknown
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Expected O, but got Unknown
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Expected O, but got Unknown
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Expected O, but got Unknown
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Expected O, but got Unknown
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Expected O, but got Unknown
			//IL_0312: Expected O, but got Unknown
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Expected O, but got Unknown
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Expected O, but got Unknown
			//IL_035f: 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_0367: Expected O, but got Unknown
			//IL_036c: Expected O, but got Unknown
			//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_03d0: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(((Component)source.containerLayout).gameObject, ((Component)source.containerLayout).transform.parent, false);
			((Object)val).name = "SlipSkid " + title + " tab";
			headers.Add(val);
			TMP_Text component = ((Component)FindClone(val.transform, ((Component)source.containerLayout).transform, source.headerLabel.transform)).GetComponent<TMP_Text>();
			Image component2 = ((Component)FindClone(val.transform, ((Component)source.containerLayout).transform, ((Component)source.iconHolder).transform)).GetComponent<Image>();
			component.richText = false;
			component.text = title;
			component.fontSize = Mathf.Min(component.fontSize, 26f);
			GameObject val2 = new GameObject("SlipSkid " + title + " grid", new Type[1] { typeof(RectTransform) });
			val2.SetActive(false);
			val2.transform.SetParent(source.root.transform.parent, false);
			CopyRect((RectTransform)source.root.transform, (RectTransform)val2.transform);
			grid = val2.AddComponent<RadioAudioGrid>();
			grid.Initialize(Player, horn, selector.carPaintGrid.selectionGridElementPrefab);
			Tab created = new Tab
			{
				headerName = source.headerName,
				icon = RadioIcons.Sprite(horn),
				defaultColor = source.defaultColor,
				selectedColor = source.selectedColor,
				defaultLabelColor = source.defaultLabelColor,
				selectedLabelColor = source.selectedLabelColor,
				iconColor = source.iconColor,
				defaultBorderRadius = source.defaultBorderRadius,
				selectedBorderRadius = source.selectedBorderRadius,
				headerLabel = component,
				iconHolder = component2,
				root = val2,
				container = ((Component)FindClone(val.transform, ((Component)source.containerLayout).transform, ((Component)source.container).transform)).GetComponent<GradientImageWithBorderRadius>(),
				containerLayout = val.GetComponent<LayoutElement>(),
				onSelect = new UnityEvent(),
				onDeselect = new UnityEvent()
			};
			Labels[created] = title;
			EventTrigger[] componentsInChildren = val.GetComponentsInChildren<EventTrigger>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			val.AddComponent<RadioTabPointer>().Clicked = delegate
			{
				SelectTab(created);
			};
			((Graphic)created.container).raycastTarget = true;
			CustomButton[] componentsInChildren2 = val.GetComponentsInChildren<CustomButton>(true);
			UnityAction val3 = default(UnityAction);
			foreach (CustomButton obj in componentsInChildren2)
			{
				obj.useLocalizationString = false;
				obj.useLabel = false;
				obj.onSubmit = new UnityEvent();
				obj.onEnter = new UnityEvent();
				obj.onExit = new UnityEvent();
				obj.onDown = new UnityEvent();
				obj.onUp = new UnityEvent();
				UnityEvent onSubmit = obj.onSubmit;
				UnityAction obj2 = val3;
				if (obj2 == null)
				{
					UnityAction val4 = delegate
					{
						SelectTab(created);
					};
					UnityAction val5 = val4;
					val3 = val4;
					obj2 = val5;
				}
				onSubmit.AddListener(obj2);
			}
			Button[] componentsInChildren3 = val.GetComponentsInChildren<Button>(true);
			UnityAction val6 = default(UnityAction);
			foreach (Button obj3 in componentsInChildren3)
			{
				obj3.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick = obj3.onClick;
				UnityAction obj4 = val6;
				if (obj4 == null)
				{
					UnityAction val7 = delegate
					{
						SelectTab(created);
					};
					UnityAction val5 = val7;
					val6 = val7;
					obj4 = val5;
				}
				((UnityEvent)onClick).AddListener(obj4);
			}
			RadioAudioGrid targetGrid = grid;
			created.onSelect.AddListener((UnityAction)delegate
			{
				targetGrid.Bind(Player);
				targetGrid.FocusSelected();
			});
			UnityEvent onDeselect = created.onDeselect;
			object obj5 = <>c.<>9__15_2;
			if (obj5 == null)
			{
				UnityAction val8 = delegate
				{
					if (Object.op_Implicit((Object)(object)RadioPlugin.Instance))
					{
						RadioPlugin.Instance.Radio.StopPreview();
					}
				};
				<>c.<>9__15_2 = val8;
				obj5 = (object)val8;
			}
			onDeselect.AddListener((UnityAction)obj5);
			val.SetActive(true);
			return created;
		}

		private static Transform FindClone(Transform clone, Transform originalRoot, Transform original)
		{
			Stack<int> stack = new Stack<int>();
			Transform val = original;
			while ((Object)(object)val != (Object)(object)originalRoot)
			{
				stack.Push(val.GetSiblingIndex());
				val = val.parent;
			}
			Transform val2 = clone;
			while (stack.Count > 0)
			{
				val2 = val2.GetChild(stack.Pop());
			}
			return val2;
		}

		private void SelectTab(Tab tab)
		{
			if (Object.op_Implicit((Object)(object)selector) && Object.op_Implicit((Object)(object)selector.tabs) && Object.op_Implicit((Object)(object)Player) && ((NetworkBehaviour)Player).IsOwner && Object.op_Implicit((Object)(object)selector.rootContainer) && selector.rootContainer.activeInHierarchy && !radio.Locked && !horns.Locked)
			{
				int num = RadioUiRules.IndexOf(selector.tabs.tabs, tab);
				if (num >= 0)
				{
					selector.tabs.Select(num);
				}
			}
		}

		internal static void CopyRect(RectTransform from, RectTransform to)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			to.anchorMin = from.anchorMin;
			to.anchorMax = from.anchorMax;
			to.pivot = from.pivot;
			to.anchoredPosition = from.anchoredPosition;
			to.sizeDelta = from.sizeDelta;
			((Transform)to).localRotation = ((Transform)from).localRotation;
			((Transform)to).localScale = ((Transform)from).localScale;
		}

		internal void SetLocked(bool value)
		{
			if (Object.op_Implicit((Object)(object)radio))
			{
				radio.Locked = value;
			}
			if (Object.op_Implicit((Object)(object)horns))
			{
				horns.Locked = value;
			}
		}

		private void OnDestroy()
		{
			if (radioTab != null)
			{
				Labels.Remove(radioTab);
			}
			if (hornTab != null)
			{
				Labels.Remove(hornTab);
			}
			if (Object.op_Implicit((Object)(object)radio))
			{
				Object.Destroy((Object)(object)((Component)radio).gameObject);
			}
			if (Object.op_Implicit((Object)(object)horns))
			{
				Object.Destroy((Object)(object)((Component)horns).gameObject);
			}
			foreach (GameObject header in headers)
			{
				if (Object.op_Implicit((Object)(object)header))
				{
					Object.Destroy((Object)(object)header);
				}
			}
		}
	}
	[HarmonyPatch(typeof(LobbyMenu), "ToggleReady")]
	internal static class RadioFallbackReadyPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !RadioMenu.BlockLobbyInput;
		}
	}
	[HarmonyPatch(typeof(LobbyMenu), "QuitLobbyStartedUpdate")]
	internal static class RadioFallbackQuitStartPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !RadioMenu.BlockLobbyInput;
		}
	}
	[HarmonyPatch(typeof(LobbyMenu), "QuitLobby")]
	internal static class RadioFallbackQuitPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !RadioMenu.BlockLobbyInput;
		}
	}
	[HarmonyPatch(typeof(PlayerInLobby), "OnPlayerNavigate")]
	internal static class RadioFallbackNavigatePatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !RadioMenu.BlockLobbyInput;
		}
	}
	[HarmonyPatch(typeof(PlayerInLobby), "OnPlayerNavigateTabs")]
	internal static class RadioFallbackTabsPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !RadioMenu.BlockLobbyInput;
		}
	}
	[HarmonyPatch(typeof(PlayerInLobby), "OnPlayerValidate")]
	internal static class RadioFallbackSubmitPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !RadioMenu.BlockLobbyInput;
		}
	}
	[HarmonyPatch(typeof(UnlockablePlayerCustomizationSelector), "Init")]
	internal static class RadioGarageInitPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UnlockablePlayerCustomizationSelector __instance, PlayerData __0)
		{
			RadioCustomization.Attach(__instance, __0);
		}
	}
	[HarmonyPatch(typeof(Tab), "Init")]
	internal static class RadioGarageHeaderPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Tab __instance)
		{
			if (!RadioCustomization.Labels.TryGetValue(__instance, out var value))
			{
				return true;
			}
			__instance.headerLabel.text = value;
			__instance.iconHolder.sprite = __instance.icon;
			((Behaviour)__instance.iconHolder).enabled = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(UnlockablePlayerCustomizationSelector), "GetGridFromTab")]
	internal static class RadioGarageGridPatch
	{
		[HarmonyPriority(0)]
		[HarmonyPostfix]
		private static void Postfix(UnlockablePlayerCustomizationSelector __instance, ref GridUI __result)
		{
			RadioCustomization component = ((Component)__instance).GetComponent<RadioCustomization>();
			RadioAudioGrid radioAudioGrid = (Object.op_Implicit((Object)(object)component) ? component.Current : null);
			if (Object.op_Implicit((Object)(object)radioAudioGrid))
			{
				__result = (GridUI)(object)radioAudioGrid;
			}
		}
	}
	[HarmonyPatch(typeof(UnlockablePlayerCustomizationSelector), "UpdateGridHoveredView")]
	internal static class RadioGarageHoveredPatch
	{
		[HarmonyPriority(800)]
		[HarmonyPrefix]
		private static bool Prefix(UnlockablePlayerCustomizationSelector __instance, ref (UnlockableContentType, object) __result)
		{
			RadioCustomization component = ((Component)__instance).GetComponent<RadioCustomization>();
			RadioAudioGrid radioAudioGrid = (Object.op_Implicit((Object)(object)component) ? component.Current : null);
			if (!Object.op_Implicit((Object)(object)radioAudioGrid))
			{
				return true;
			}
			radioAudioGrid.FocusSelected();
			__result = ((UnlockableContentType)0, null);
			return false;
		}
	}
	[HarmonyPatch(typeof(UnlockablePlayerCustomizationSelector), "Select")]
	internal static class RadioGarageSelectPatch
	{
		[HarmonyPriority(800)]
		[HarmonyPrefix]
		private static bool Prefix(UnlockablePlayerCustomizationSelector __instance, ref object __result)
		{
			RadioCustomization component = ((Component)__instance).GetComponent<RadioCustomization>();
			RadioAudioGrid radioAudioGrid = (Object.op_Implicit((Object)(object)component) ? component.Current : null);
			if (!Object.op_Implicit((Object)(object)radioAudioGrid))
			{
				return true;
			}
			((GridUI)radioAudioGrid).Select();
			__result = null;
			return false;
		}
	}
	[HarmonyPatch(typeof(UnlockablePlayerCustomizationSelector), "LockView")]
	internal static class RadioGarageLockPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UnlockablePlayerCustomizationSelector __instance)
		{
			RadioCustomization component = ((Component)__instance).GetComponent<RadioCustomization>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.SetLocked(value: true);
			}
		}
	}
	[HarmonyPatch(typeof(UnlockablePlayerCustomizationSelector), "Unlock")]
	internal static class RadioGarageUnlockPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UnlockablePlayerCustomizationSelector __instance)
		{
			RadioCustomization component = ((Component)__instance).GetComponent<RadioCustomization>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.SetLocked(value: false);
			}
		}
	}
	internal static class RadioGame
	{
		internal static IEnumerable<PlayerData> Players
		{
			get
			{
				PlayerManager instance = PlayerManager.instance;
				if (!Object.op_Implicit((Object)(object)instance) || instance.players == null)
				{
					return Array.Empty<PlayerData>();
				}
				return instance.players;
			}
		}

		internal static bool TryGetState(out GameState state)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected I4, but got Unknown
			state = (GameState)0;
			GameManager instance = GameManager.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.networkVariables) || instance.networkVariables.state == null)
			{
				return false;
			}
			state = (GameState)(int)instance.networkVariables.state.Value;
			return true;
		}

		internal static bool IsState(GameState state)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetState(out var state2))
			{
				return state2 == state;
			}
			return false;
		}
	}
	internal static class RadioIcons
	{
		private static readonly Texture2D[] textures = (Texture2D[])(object)new Texture2D[2];

		private static readonly Sprite[] sprites = (Sprite[])(object)new Sprite[2];

		internal static Texture2D Texture(bool horn)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			int num = (horn ? 1 : 0);
			if (Object.op_Implicit((Object)(object)textures[num]))
			{
				return textures[num];
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			((Object)val).name = (horn ? "Custom horn icon" : "Accelerator radio icon");
			Color[] array = (Color[])(object)new Color[16384];
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					Color clear = Color.clear;
					if (horn)
					{
						bool flag = (j >= 19 && j <= 43 && i >= 45 && i <= 82) || (j >= 40 && j <= 77 && (float)i >= 45f - (float)(j - 40) * 0.65f && (float)i <= 82f + (float)(j - 40) * 0.65f);
						bool flag2 = (j >= 16 && j <= 46 && i >= 42 && i <= 85) || (j >= 37 && j <= 80 && (float)i >= 42f - (float)(j - 40) * 0.65f && (float)i <= 85f + (float)(j - 40) * 0.65f);
						float num2 = Mathf.Sqrt((float)((j - 65) * (j - 65) + (i - 64) * (i - 64)));
						bool num3 = j > 84 && (Mathf.Abs(num2 - 30f) < 3f || Mathf.Abs(num2 - 43f) < 3f) && i > 28 && i < 100;
						if (flag2)
						{
							((Color)(ref clear))..ctor(0.17f, 0.19f, 0.29f);
						}
						if (flag)
						{
							((Color)(ref clear))..ctor(0.67f, 0.7f, 0.82f);
						}
						if (num3)
						{
							((Color)(ref clear))..ctor(1f, 0.76f, 0.19f);
						}
					}
					else
					{
						bool flag3 = j >= 20 && j <= 108 && i >= 27 && i <= 92;
						bool num4 = j >= 25 && j <= 103 && i >= 32 && i <= 87;
						if (flag3)
						{
							((Color)(ref clear))..ctor(0.17f, 0.19f, 0.29f);
						}
						if (num4)
						{
							((Color)(ref clear))..ctor(0.67f, 0.7f, 0.85f);
						}
						if (j > 31 && j < 72 && i > 66 && i < 80)
						{
							((Color)(ref clear))..ctor(0.91f, 0.94f, 1f);
						}
						if (Mathf.Sqrt((float)((j - 50) * (j - 50) + (i - 48) * (i - 48))) < 13f)
						{
							((Color)(ref clear))..ctor(0.22f, 0.25f, 0.4f);
						}
						if (j > 82 && j < 96 && i > 38 && i < 56)
						{
							((Color)(ref clear))..ctor(1f, 0.76f, 0.19f);
						}
						if (Line(j, i, 33f, 92f, 76f, 115f, 3f))
						{
							((Color)(ref clear))..ctor(0.17f, 0.19f, 0.29f);
						}
					}
					array[i * 128 + j] = clear;
				}
			}
			val.SetPixels(array);
			val.Apply();
			textures[num] = val;
			return val;
		}

		private static bool Line(float x, float y, float ax, float ay, float bx, float by, float radius)
		{
			float num = bx - ax;
			float num2 = by - ay;
			float num3 = Mathf.Clamp01(((x - ax) * num + (y - ay) * num2) / (num * num + num2 * num2));
			float num4 = x - ax - num3 * num;
			float num5 = y - ay - num3 * num2;
			return num4 * num4 + num5 * num5 < radius * radius;
		}

		internal static Sprite Sprite(bool horn)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			int num = (horn ? 1 : 0);
			if (!Object.op_Implicit((Object)(object)sprites[num]))
			{
				sprites[num] = Sprite.Create(Texture(horn), new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
			}
			return sprites[num];
		}

		internal static void Dispose()
		{
			for (int i = 0; i < 2; i++)
			{
				if (Object.op_Implicit((Object)(object)sprites[i]))
				{
					Object.Destroy((Object)(object)sprites[i]);
				}
				if (Object.op_Implicit((Object)(object)textures[i]))
				{
					Object.Destroy((Object)(object)textures[i]);
				}
				sprites[i] = null;
				textures[i] = null;
			}
		}
	}
	public sealed class RadioMenu : MonoBehaviour
	{
		internal static bool RadioOpen;

		private static int closedFrame = -10;

		private static bool swallowCloseButton;

		private static RadioMenu instance;

		private GameObject root;

		private GameObject ownedEvents;

		private PlayerData player;

		private int driverIndex;

		private bool horn;

		private bool savedCursor;

		private bool oldVisible;

		private CursorLockMode oldLock;

		private RadioAudioGrid grid;

		private float nextMove;

		internal static bool BlockLobbyInput
		{
			get
			{
				if (!RadioOpen && Time.frameCount > closedFrame + 1)
				{
					if (swallowCloseButton)
					{
						if (Keyboard.current == null || !((ButtonControl)Keyboard.current.escapeKey).isPressed)
						{
							if (Gamepad.current != null)
							{
								return Gamepad.current.buttonEast.isPressed;
							}
							return false;
						}
						return true;
					}
					return false;
				}
				return true;
			}
		}

		internal static void StartUi()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)instance))
			{
				GameObject val = new GameObject("Slip & Skid Radio interface");
				Object.DontDestroyOnLoad((Object)val);
				instance = val.AddComponent<RadioMenu>();
			}
		}

		internal static void StopUi()
		{
			RadioOpen = false;
			if (Object.op_Implicit((Object)(object)instance))
			{
				Object.Destroy((Object)(object)((Component)instance).gameObject);
			}
			instance = null;
		}

		internal static void ToggleRadio()
		{
			RadioOpen = !RadioOpen;
		}

		private void Update()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (swallowCloseButton && (current == null || !((ButtonControl)current.escapeKey).isPressed) && (Gamepad.current == null || !Gamepad.current.buttonEast.isPressed))
			{
				swallowCloseButton = false;
			}
			if (current != null && ((ButtonControl)current.f8Key).wasPressedThisFrame)
			{
				ToggleRadio();
			}
			if (!Object.op_Implicit((Object)(object)RadioPlugin.Instance))
			{
				Close();
				return;
			}
			if (!RadioOpen)
			{
				Close();
				return;
			}
			if (!savedCursor)
			{
				oldVisible = Cursor.visible;
				oldLock = Cursor.lockState;
				savedCursor = true;
			}
			Cursor.visible = true;
			Cursor.lockState = (CursorLockMode)0;
			if (!Object.op_Implicit((Object)(object)root) || (player != null && (!Object.op_Implicit((Object)(object)player) || !((NetworkBehaviour)player).IsOwner)))
			{
				Build();
			}
			Gamepad current2 = Gamepad.current;
			if ((current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) || (current2 != null && current2.buttonEast.wasPressedThisFrame))
			{
				swallowCloseButton = true;
				RadioOpen = false;
				Close();
				return;
			}
			if (current2 != null && (current2.leftShoulder.wasPressedThisFrame || current2.rightShoulder.wasPressedThisFrame))
			{
				horn = !horn;
				Build();
			}
			if (!Object.op_Implicit((Object)(object)grid))
			{
				return;
			}
			Vector2 val = Vector2.zero;
			if (current != null)
			{
				((Vector2)(ref val))..ctor((float)((((ButtonControl)current.rightArrowKey).isPressed ? 1 : 0) - (((ButtonControl)current.leftArrowKey).isPressed ? 1 : 0)), (float)((((ButtonControl)current.upArrowKey).isPressed ? 1 : 0) - (((ButtonControl)current.downArrowKey).isPressed ? 1 : 0)));
			}
			if (current2 != null && val == Vector2.zero)
			{
				val = ((InputControl<Vector2>)(object)current2.dpad).ReadValue();
				if (((Vector2)(ref val)).sqrMagnitude < 0.3f)
				{
					val = ((InputControl<Vector2>)(object)current2.leftStick).ReadValue();
				}
			}
			if (((Vector2)(ref val)).sqrMagnitude < 0.3f)
			{
				nextMove = 0f;
			}
			else if (Time.unscaledTime >= nextMove)
			{
				nextMove = Time.unscaledTime + 0.18f;
				if (Mathf.Abs(val.x) > Mathf.Abs(val.y))
				{
					if (val.x > 0f)
					{
						((GridUI)grid).MoveRight();
					}
					else
					{
						((GridUI)grid).MoveLeft();
					}
				}
				else if (val.y > 0f)
				{
					((GridUI)grid).MoveUp();
				}
				else
				{
					((GridUI)grid).MoveDown();
				}
			}
			if ((current != null && ((ButtonControl)current.enterKey).wasPressedThisFrame) || (current2 != null && current2.buttonSouth.wasPressedThisFrame))
			{
				((GridUI)grid).Select();
			}
		}

		private void ClearRoot()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				root.SetActive(false);
				Object.Destroy((Object)(object)root);
				root = null;
			}
			grid = null;
		}

		private void Close()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			ClearRoot();
			if (Object.op_Implicit((Object)(object)ownedEvents))
			{
				Object.Destroy((Object)(object)ownedEvents);
				ownedEvents = null;
			}
			if (savedCursor)
			{
				closedFrame = Time.frameCount;
				Cursor.visible = oldVisible;
				Cursor.lockState = oldLock;
				savedCursor = false;
			}
		}

		private void Build()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: 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)
			//IL_03b0: 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_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			ClearRoot();
			if (!Object.op_Implicit((Object)(object)EventSystem.current) && !Object.op_Implicit((Object)(object)ownedEvents))
			{
				ownedEvents = new GameObject("Radio input", new Type[2]
				{
					typeof(EventSystem),
					typeof(InputSystemUIInputModule)
				});
				ownedEvents.transform.SetParent(((Component)this).transform, false);
				ownedEvents.GetComponent<InputSystemUIInputModule>().AssignDefaultActions();
			}
			root = new GameObject("Radio and Horn window", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			root.transform.SetParent(((Component)this).transform, false);
			Canvas component = root.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 250;
			CanvasScaler component2 = root.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.matchWidthOrHeight = 1f;
			GameObject val = new GameObject("Audio customisations", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(root.transform, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			val2.sizeDelta = new Vector2(620f, 830f);
			((Graphic)val.GetComponent<Image>()).color = new Color(0.83f, 0.85f, 0.93f, 0.99f);
			Text(val.transform, "SLIP & SKID AUDIO", 18f, 12f, 470f, 36f, 26);
			Button(val.transform, "Close", 496f, 10f, 106f, delegate
			{
				RadioOpen = false;
				Close();
			});
			Button(val.transform, "Radio", 18f, 60f, 285f, delegate
			{
				horn = false;
				Build();