Decompiled source of Audio Formats v1.1.1

AudioFormats.dll

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

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

		public static ConfigEntry<AudioLoadMode> LoadMode;

		public static ConfigEntry<int> MaxConcurrentLoads;

		public static ConfigEntry<int> LazyLoadingThreshold;

		public static ConfigEntry<bool> VerboseLogging;

		public static void Bind(ConfigFile config)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			PreferManagedDecoders = config.Bind<bool>("Decoding", "PreferManagedDecoders", false, "If active, .ogg and .mp3 files are always decoded by the bundled NVorbis / NLayer decoders instead of Unity's built-in one. Slower and uses more memory, but gives identical results on every machine. Leave this off unless a file that plays fine elsewhere is refused by the game.");
			LoadMode = config.Bind<AudioLoadMode>("Decoding", "LoadMode", AudioLoadMode.Decompress, "How a clip is held in memory once loaded. Decompress: expanded to raw PCM on load. Costs the most time and memory - a minute of 24 kHz mono is ~3 MB of PCM against ~300 KB of ogg - but has no catch. CompressedInMemory: measured to be ignored by this game's Unity version, which decompresses anyway. Behaves like Decompress. Streaming: decoded straight from the file while it plays, about five times faster to load. The file then stays open for as long as the game runs, and Unity only plays one instance of a streamed clip at a time.");
			MaxConcurrentLoads = config.Bind<int>("Decoding", "MaxConcurrentLoads", 256, new ConfigDescription("How many audio files may be loading at the same time. SideLoader asks for every file of a pack in one go, and a pack with thousands of clips would otherwise hold them all open at once. 0 removes the limit.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4096), Array.Empty<object>()));
			LazyLoadingThreshold = config.Bind<int>("Decoding", "LazyLoadingThreshold", 100, new ConfigDescription("A pack holding at least this many .ogg/.mp3 files is only indexed at startup, and each of its clips is decoded the first time something plays it. A voice pack holds hours of audio of which a session plays minutes, so loading all of it up front costs the loading time, and the memory, of everything the player never hears. 0 always loads everything up front. Only applies to packs whose files sit in a folder, never to a .zip pack.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>()));
			VerboseLogging = config.Bind<bool>("Debug", "VerboseLogging", false, "If active, log the sample rate, channel count and decoder used for each loaded clip, on top of the timing summary written after each pack is loaded.");
		}
	}
	[BepInPlugin("Tchernobill.AudioFormats", "Audio Formats", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class AudioFormatsPlugin : BaseUnityPlugin
	{
		public const string GUID = "Tchernobill.AudioFormats";

		public const string NAME = "Audio Formats";

		public const string VERSION = "1.1.1";

		public static AudioFormatsPlugin Instance { get; private set; }

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

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

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

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

		private static AudioClip DecodeManaged(string filePath, AudioFileFormat format, string clipName)
		{
			long timestamp = Stopwatch.GetTimestamp();
			AudioClip result = ManagedAudioDecoder.DecodeFile(filePath, format, clipName);
			LoadStats.AddManagedDecode(Stopwatch.GetTimestamp() - timestamp);
			return result;
		}

		private static long FileLength(string filePath)
		{
			try
			{
				return new FileInfo(filePath).Length;
			}
			catch
			{
				return 0L;
			}
		}

		private static void Complete(AudioClip clip, string clipName, string filePath, SLPack pack, Action<AudioClip> onClipLoaded, bool usedManagedDecoder, long fileBytes)
		{
			LoadStats.CountResult(clip, usedManagedDecoder, fileBytes);
			if (!Object.op_Implicit((Object)(object)clip))
			{
				Log.Warning("Could not load audio clip '" + Path.GetFileName(filePath) + "'.");
				return;
			}
			FinalizeTimed(clip, clipName, pack);
			Log.Debug("Loaded audio clip: " + Path.GetFileName(filePath));
			onClipLoaded?.Invoke(clip);
		}

		private static AudioClip FinalizeTimed(AudioClip clip, string clipName, SLPack pack)
		{
			long timestamp = Stopwatch.GetTimestamp();
			AudioClip result = SideLoaderBridge.FinalizeAudioClip(clip, clipName, pack);
			LoadStats.AddFinalize(Stopwatch.GetTimestamp() - timestamp);
			return result;
		}
	}
	public enum AudioFileFormat
	{
		Unknown,
		Wav,
		Ogg,
		Mp3
	}
	public static class AudioFileFormats
	{
		public static readonly string[] AddedExtensions = new string[2] { ".ogg", ".mp3" };

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

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

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

		public static AudioType ToUnityAudioType(AudioFileFormat format)
		{
			return (AudioType)(format switch
			{
				AudioFileFormat.Ogg => 14, 
				AudioFileFormat.Mp3 => 13, 
				AudioFileFormat.Wav => 20, 
				_ => 0, 
			});
		}
	}
	public enum AudioLoadMode
	{
		Decompress,
		CompressedInMemory,
		Streaming
	}
	internal static class AudioLoadQueue
	{
		private static readonly Queue<Func<IEnumerator>> s_pending = new Queue<Func<IEnumerator>>();

		private static int s_active;

		private static bool s_pumping;

		public static void Enqueue(Func<IEnumerator> job)
		{
			if (job == null)
			{
				return;
			}
			LoadStats.BeginBatch();
			s_pending.Enqueue(job);
			LoadStats.CountRequest();
			if (!s_pumping)
			{
				AudioFormatsPlugin instance = AudioFormatsPlugin.Instance;
				if (!Object.op_Implicit((Object)(object)instance))
				{
					Log.Warning("The AudioFormats plugin object is gone, queued audio loads are dropped.");
					s_pending.Clear();
					LoadStats.EndBatch();
				}
				else
				{
					s_pumping = true;
					((MonoBehaviour)instance).StartCoroutine(Pump());
				}
			}
		}

		private static IEnumerator Pump()
		{
			AudioFormatsPlugin host = AudioFormatsPlugin.Instance;
			while (s_pending.Count > 0 || s_active > 0)
			{
				int value = AudioFormatsConfig.MaxConcurrentLoads.Value;
				while (s_pending.Count > 0 && (value <= 0 || s_active < value))
				{
					s_active++;
					((MonoBehaviour)host).StartCoroutine(Run(s_pending.Dequeue()));
				}
				yield return null;
			}
			s_pumping = false;
			LoadStats.EndBatch();
		}

		private static IEnumerator Run(Func<IEnumerator> job)
		{
			IEnumerator routine = null;
			try
			{
				routine = job();
			}
			catch (Exception ex)
			{
				Log.Warning("Could not start an audio load: " + ex.Message);
			}
			while (routine != null)
			{
				bool flag;
				try
				{
					flag = routine.MoveNext();
				}
				catch (Exception ex2)
				{
					Log.Warning("Audio load failed: " + ex2.Message);
					break;
				}
				if (!flag)
				{
					break;
				}
				yield return routine.Current;
			}
			s_active--;
		}
	}
	public static class LazyAudioClips
	{
		private class Entry
		{
			public string Path;

			public SLPack Pack;

			public AudioClip Clip;

			public bool Loading;
		}

		private static readonly Dictionary<string, Entry> s_index = new Dictionary<string, Entry>();

		public static int Count => s_index.Count;

		internal static void Index(SLPack pack, string filePath)
		{
			s_index[Path.GetFileNameWithoutExtension(filePath)] = new Entry
			{
				Path = filePath,
				Pack = pack
			};
		}

		public static bool Contains(string clipName)
		{
			if (!string.IsNullOrEmpty(clipName))
			{
				return s_index.ContainsKey(clipName);
			}
			return false;
		}

		public static void Prefetch(string clipName)
		{
			if (!string.IsNullOrEmpty(clipName) && s_index.TryGetValue(clipName, out var entry) && !Object.op_Implicit((Object)(object)entry.Clip) && !entry.Loading)
			{
				entry.Loading = true;
				AudioClipLoader.LoadFromFile(entry.Path, entry.Pack, delegate(AudioClip clip)
				{
					entry.Clip = clip;
					entry.Loading = false;
				});
			}
		}

		public static AudioClip GetLoaded(string clipName)
		{
			if (string.IsNullOrEmpty(clipName) || !s_index.TryGetValue(clipName, out var value))
			{
				return null;
			}
			return value.Clip;
		}

		public static AudioClip GetNow(string clipName)
		{
			if (string.IsNullOrEmpty(clipName) || !s_index.TryGetValue(clipName, out var value))
			{
				return null;
			}
			if (Object.op_Implicit((Object)(object)value.Clip))
			{
				return value.Clip;
			}
			AudioFileFormat format = AudioFileFormats.FromExtension(value.Path);
			AudioClip val = ManagedAudioDecoder.DecodeFile(value.Path, format, clipName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			value.Clip = SideLoaderBridge.FinalizeAudioClip(val, clipName, value.Pack);
			value.Loading = false;
			return value.Clip;
		}
	}
	internal static class LoadStats
	{
		private const int ReportThreshold = 25;

		private static readonly Stopwatch s_wallClock = new Stopwatch();

		private static long s_unityDecodeTicks;

		private static long s_managedDecodeTicks;

		private static long s_finalizeTicks;

		private static long s_overheadTicks;

		private static int s_requested;

		private static int s_unityDecoded;

		private static int s_managedDecoded;

		private static int s_failed;

		private static long s_bytes;

		private static double s_seconds;

		private static int s_startFrame;

		public static bool Running => s_wallClock.IsRunning;

		public static void BeginBatch()
		{
			if (!s_wallClock.IsRunning)
			{
				s_unityDecodeTicks = (s_managedDecodeTicks = (s_finalizeTicks = (s_overheadTicks = 0L)));
				s_requested = (s_unityDecoded = (s_managedDecoded = (s_failed = 0)));
				UnityAudioDecoder.ResetFirstClipReport();
				s_bytes = 0L;
				s_seconds = 0.0;
				s_startFrame = Time.frameCount;
				s_wallClock.Reset();
				s_wallClock.Start();
			}
		}

		public static void CountRequest()
		{
			s_requested++;
		}

		public static void AddUnityDecode(long ticks)
		{
			s_unityDecodeTicks += ticks;
		}

		public static void AddManagedDecode(long ticks)
		{
			s_managedDecodeTicks += ticks;
		}

		public static void AddFinalize(long ticks)
		{
			s_finalizeTicks += ticks;
		}

		public static void AddOverhead(long ticks)
		{
			s_overheadTicks += ticks;
		}

		public static void CountResult(AudioClip clip, bool usedManagedDecoder, long fileBytes)
		{
			if (!Object.op_Implicit((Object)(object)clip))
			{
				s_failed++;
				return;
			}
			if (usedManagedDecoder)
			{
				s_managedDecoded++;
			}
			else
			{
				s_unityDecoded++;
			}
			s_bytes += fileBytes;
			if (clip.frequency > 0)
			{
				s_seconds += (double)clip.samples / (double)clip.frequency;
			}
		}

		public static void EndBatch()
		{
			if (s_wallClock.IsRunning)
			{
				s_wallClock.Stop();
				if (s_requested >= 25)
				{
					double num = 1000.0 / (double)Stopwatch.Frequency;
					Log.Message($"Loaded {s_unityDecoded + s_managedDecoded}/{s_requested} audio clips in " + $"{s_wallClock.ElapsedMilliseconds} ms ({Time.frameCount - s_startFrame} frames): " + $"{(double)s_bytes / 1048576.0:0.#} MB of files, {s_seconds / 60.0:0.#} min of audio, " + $"{s_failed} failed.");
					Log.Message($"  main thread: {(double)s_unityDecodeTicks * num:0} ms in Unity's decoder ({s_unityDecoded} clips), " + $"{(double)s_managedDecodeTicks * num:0} ms in the managed decoder ({s_managedDecoded} clips), " + $"{(double)s_finalizeTicks * num:0} ms registering them in SideLoader (that one includes " + "every other mod hooked on FinalizeAudioClip), " + $"{(double)s_overheadTicks * num:0} ms of request setup and disposal.");
				}
			}
		}
	}
	public static class ManagedAudioDecoder
	{
		private const int ReadChunkFloats = 16384;

		private static bool? s_oggAvailable;

		private static bool? s_mp3Available;

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

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

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

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

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

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

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

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

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

		private int m_count;

		public int Count => m_count;

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

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

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

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

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

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

		public static void PackLoadAudioClip(SLPack pack, string relativeDirectory, string file, Action<AudioClip> onClipLoaded)
		{
			if (s_packLoadAudioClip == null)
			{
				Log.Warning("SLPack.LoadAudioClip was not found - is SideLoader up to date?");
				return;
			}
			try
			{
				s_packLoadAudioClip.Invoke(pack, new object[3] { relativeDirectory, file, onClipLoaded });
			}
			catch (Exception ex)
			{
				Log.Warning("Could not load '" + file + "' from pack '" + ((pack != null) ? pack.Name : null) + "': " + (ex.InnerException?.Message ?? ex.Message));
			}
		}
	}
	internal static class UnityAudioDecoder
	{
		private static readonly List<UnityWebRequest> s_streamingRequests = new List<UnityWebRequest>();

		private static bool s_reportedFirstClip;

		public static void ResetFirstClipReport()
		{
			s_reportedFirstClip = false;
		}

		public static IEnumerator LoadCoroutine(string filePath, AudioFileFormat format, string clipName, Action<AudioClip> onSuccess, Action<string> onFailure, Action<long> onBytesRead = null)
		{
			string absoluteUri;
			try
			{
				absoluteUri = new Uri(Path.GetFullPath(filePath)).AbsoluteUri;
			}
			catch (Exception ex)
			{
				onFailure("could not build a file:// url (" + ex.Message + ")");
				yield break;
			}
			long timestamp = Stopwatch.GetTimestamp();
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, AudioFileFormats.ToUnityAudioType(format));
			AudioLoadMode mode = AudioFormatsConfig.LoadMode.Value;
			DownloadHandler downloadHandler = request.downloadHandler;
			DownloadHandlerAudioClip handler = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null);
			if (handler != null)
			{
				handler.compressed = mode == AudioLoadMode.CompressedInMemory;
				handler.streamAudio = mode == AudioLoadMode.Streaming;
			}
			LoadStats.AddOverhead(Stopwatch.GetTimestamp() - timestamp);
			try
			{
				yield return request.SendWebRequest();
				while (!request.isDone)
				{
					yield return null;
				}
				if (!string.IsNullOrEmpty(request.error))
				{
					onFailure(request.error);
					yield break;
				}
				AudioClip content;
				try
				{
					long timestamp2 = Stopwatch.GetTimestamp();
					content = DownloadHandlerAudioClip.GetContent(request);
					LoadStats.AddUnityDecode(Stopwatch.GetTimestamp() - timestamp2);
				}
				catch (Exception ex2)
				{
					onFailure(ex2.Message);
					yield break;
				}
				if (!Object.op_Implicit((Object)(object)content) || (int)content.loadState == 3 || content.samples <= 0)
				{
					onFailure("Unity could not decode the file");
					yield break;
				}
				onBytesRead?.Invoke((long)request.downloadedBytes);
				if (!s_reportedFirstClip)
				{
					s_reportedFirstClip = true;
					string[] obj = new string[8]
					{
						$"First clip of this run, asked for {mode}: Unity read back ",
						"compressed=",
						null,
						null,
						null,
						null,
						null,
						null
					};
					obj[2] = ((handler != null) ? handler.compressed.ToString() : null) ?? "n/a";
					obj[3] = ", streamAudio=";
					obj[4] = ((handler != null) ? handler.streamAudio.ToString() : null) ?? "n/a";
					obj[5] = ", ";
					obj[6] = $"and gave a clip with loadType={content.loadType} (never truthful here), ";
					obj[7] = $"loadState={content.loadState}.";
					Log.Debug(string.Concat(obj));
				}
				((Object)content).name = clipName;
				Log.Debug($"Decoded '{clipName}' with Unity's decoder: {content.samples} samples, " + $"{content.channels} ch, {content.frequency} Hz" + $", {content.loadType}.");
				onSuccess(content);
			}
			finally
			{
				long timestamp3 = Stopwatch.GetTimestamp();
				if (mode == AudioLoadMode.Streaming)
				{
					s_streamingRequests.Add(request);
				}
				else
				{
					request.Dispose();
				}
				LoadStats.AddOverhead(Stopwatch.GetTimestamp() - timestamp3);
			}
		}
	}
	internal static class Log
	{
		private static ManualLogSource s_source;

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

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

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

		public static void Debug(string message)
		{
			if (AudioFormatsConfig.VerboseLogging != null && AudioFormatsConfig.VerboseLogging.Value)
			{
				ManualLogSource obj = s_source;
				if (obj != null)
				{
					obj.LogInfo((object)message);
				}
			}
		}
	}
}
namespace Tchernobill.AudioFormats.Patches
{
	[HarmonyPatch(typeof(AudioClipCategory), "LoadContent")]
	internal static class Patch_AudioClipCategory_LoadContent
	{
		[HarmonyPostfix]
		public static void Postfix(SLPack pack, Dictionary<string, object> __result)
		{
			if (pack == null || __result == null)
			{
				return;
			}
			string pathForCategory = pack.GetPathForCategory<AudioClipCategory>();
			if (!pack.DirectoryExists(pathForCategory))
			{
				return;
			}
			List<string> list = new List<string>();
			string[] files = pack.GetFiles(pathForCategory);
			foreach (string text in files)
			{
				if (AudioFileFormats.IsAdded(AudioFileFormats.FromExtension(text)))
				{
					list.Add(text);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			if (ShouldLoadLazily(list))
			{
				foreach (string item in list)
				{
					LazyAudioClips.Index(pack, item);
				}
				Log.Message($"Indexed {list.Count} .ogg/.mp3 clips from pack '{pack.Name}'. " + "They are decoded the first time something plays them.");
				return;
			}
			foreach (string item2 in list)
			{
				string key = item2;
				SideLoaderBridge.PackLoadAudioClip(pack, pathForCategory, Path.GetFileName(item2), delegate(AudioClip clip)
				{
					if (Object.op_Implicit((Object)(object)clip))
					{
						__result[key] = clip;
					}
				});
			}
			Log.Message($"Queued {list.Count} .ogg/.mp3 clips from pack '{pack.Name}'.");
		}

		private static bool ShouldLoadLazily(List<string> clips)
		{
			int value = AudioFormatsConfig.LazyLoadingThreshold.Value;
			if (value <= 0 || clips.Count < value)
			{
				return false;
			}
			return File.Exists(clips[0]);
		}
	}
	[HarmonyPatch(typeof(CustomAudio), "ConvertByteArrayToAudioClip")]
	internal static class Patch_CustomAudio_ConvertByteArrayToAudioClip
	{
		[HarmonyPrefix]
		public static bool Prefix(byte[] sourceData, string name, ref AudioClip __result)
		{
			AudioFileFormat format = AudioFileFormats.FromHeader(sourceData);
			if (!AudioFileFormats.IsAdded(format))
			{
				return true;
			}
			__result = ManagedAudioDecoder.Decode(sourceData, format, name);
			return false;
		}
	}
	[HarmonyPatch(typeof(CustomAudio), "LoadAudioClip", new Type[]
	{
		typeof(byte[]),
		typeof(string),
		typeof(SLPack)
	})]
	internal static class Patch_CustomAudio_LoadAudioClip_Bytes
	{
		[HarmonyPrefix]
		public static bool Prefix(byte[] data, string name, SLPack pack, ref AudioClip __result)
		{
			if (!AudioFileFormats.IsAdded(AudioFileFormats.FromHeader(data)))
			{
				return true;
			}
			__result = AudioClipLoader.LoadFromBytes(data, name, pack);
			return false;
		}
	}
	[HarmonyPatch(typeof(CustomAudio), "LoadAudioClip", new Type[]
	{
		typeof(string),
		typeof(SLPack),
		typeof(Action<AudioClip>)
	})]
	internal static class Patch_CustomAudio_LoadAudioClip_File
	{
		[HarmonyPrefix]
		public static bool Prefix(string filePath, SLPack pack, Action<AudioClip> onClipLoaded)
		{
			if (!AudioFileFormats.IsAdded(AudioFileFormats.FromExtension(filePath)))
			{
				return true;
			}
			AudioClipLoader.LoadFromFile(filePath, pack, onClipLoaded);
			return false;
		}
	}
}

NLayer.dll

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

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

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

		int SampleRateIndex { get; }

		int FrameLength { get; }

		int BitRate { get; }

		MpegVersion Version { get; }

		MpegLayer Layer { get; }

		MpegChannelMode ChannelMode { get; }

		int ChannelModeExtension { get; }

		int SampleCount { get; }

		int BitRateIndex { get; }

		bool IsCopyrighted { get; }

		bool HasCrc { get; }

		bool IsCorrupted { get; }

		void Reset();

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

		private bool _closeStream;

		private bool _eofFound;

		private MpegStreamReader _reader;

		private MpegFrameDecoder _decoder;

		private object _seekLock = new object();

		private long _position;

		private int _encoderDelay;

		private int _encoderPadding;

		private bool _decoderDelaySkipped;

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

		private int _readBufLen;

		private int _readBufOfs;

		public int SampleRate => _reader.SampleRate;

		public int Channels => OutputChannels;

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

		public bool CanSeek => _reader.CanSeek;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		private LayerIIDecoder _layerIIDecoder;

		private LayerIIIDecoder _layerIIIDecoder;

		private float[] _eqFactors;

		private float[] _ch0;

		private float[] _ch1;

		public StereoMode StereoMode { get; set; }

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

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

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

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

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

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

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

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

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

		private int _start;

		private int _end = -1;

		private int _bitsLeft;

		private long _bitsRead;

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

		public long BitsRead => _bitsRead;

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

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

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

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

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

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

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

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

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

		private MpegStreamReader _reader;

		private byte[] _savedBuffer;

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

		internal long Offset { get; private set; }

		internal int Length { get; set; }

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

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

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

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

		protected abstract int Validate();

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

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

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

			internal int Length;

			internal int Bits;

			internal int Mask;

			internal HuffmanListNode Next;
		}

		private static readonly byte[][,] _codeTables;

		private static readonly float[] _floatLookup;

		private static HuffmanListNode[] _llCache;

		private static int[] _llCacheMaxBits;

		private static readonly int[] LIN_BITS;

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

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

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

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

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

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

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

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

		private int _encoderDelay = -1;

		private int _encoderPadding = -1;

		private bool _v2Parsed;

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

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

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

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

		private ID3Frame()
		{
		}

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

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

		private void ParseV1(int offset)
		{
		}

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

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

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

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

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

		private const float INV_SQRT_2 = 0.70710677f;

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

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

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

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

		private float[] _eq;

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

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

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

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

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

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

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

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

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

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

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

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

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

		internal StereoMode StereoMode { get; set; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		private int _channels;

		private int _jsbound;

		private int _granuleCount;

		private int[][] _allocLookupTable;

		private int[][] _scfsi;

		private int[][] _samples;

		private int[][][] _scalefac;

		private float[] _polyPhaseBuf;

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

		private int[][] _allocation;

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

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

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

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

		protected abstract int[] GetRateTable(IMpegFrame frame);

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

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

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

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

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

			private static float[][] _swin;

			private static float[] icos72_table;

			private List<float[]> _prevBlock;

			private List<float[]> _nextBlock;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			private const float sqrt32 = 0.8660254f;

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

NVorbis.dll

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

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

		private ulong _bitBucket;

		private int _bitCount;

		private int _readBits;

		private byte _overflowBits;

		private PacketFlags _packetFlags;

		private long _granulePosition;

		private long _pageGranulePosition;

		private int _length;

		private int _granuleCount;

		private int _pageSequenceNumber;

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

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

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

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

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

		public long BitsRead => _readBits;

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

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

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

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

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

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

		protected abstract int ReadNextByte();

		public virtual void Done()
		{
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		internal int Length;

		internal int Bits;

		internal int Mask;

		internal HuffmanListNode Next;

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

		bool CanSeek { get; }

		long WasteBits { get; }

		int PagesRead { get; }

		event EventHandler<NewStreamEventArgs> NewStream;

		bool Init();

		bool FindNextStream();

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

		bool CanSeek { get; }

		long ContainerBits { get; }

		event EventHandler<ParameterChangeEventArgs> ParameterChange;

		int GetTotalPageCount();

		DataPacket GetNextPacket();

		DataPacket PeekNextPacket();

		DataPacket GetPacket(int packetIndex);

		long GetGranuleCount();

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

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

		int InstantBitRate { get; }

		TimeSpan PageLatency { get; }

		TimeSpan PacketLatency { get; }

		TimeSpan SecondLatency { get; }

		long OverheadBits { get; }

		long AudioBits { get; }

		int PagesRead { get; }

		int TotalPages { get; }

		bool Clipped { get; }

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

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

		private int _n;

		private int _n2;

		private int _n4;

		private int _n8;

		private int _ld;

		private float[] _A;

		private float[] _B;

		private float[] _C;

		private ushort[] _bitrev;

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

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

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

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

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

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

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

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

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

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

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

		public bool IgnoreStream { get; set; }

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

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

		private int _start;

		private int _end;

		private int _bufLen;

		internal int Channels;

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

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

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

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

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

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

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

			[FieldOffset(0)]
			public uint Bits;
		}

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

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

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

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

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

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

			private int _start;

			private int _count;

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

			public int Count => _count;

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

			private FastRange()
			{
			}

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

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

		internal int BookNum;

		internal int Dimensions;

		internal int Entries;

		private int[] Lengths;

		private float[] LookupTable;

		internal int MapType;

		private HuffmanListNode PrefixOverflowTree;

		private List<HuffmanListNode> PrefixList;

		private int PrefixBitLength;

		private int MaxBits;

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

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

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

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

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

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

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

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

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

			protected abstract bool HasEnergy { get; }

			internal bool ForceEnergy { get; set; }

			internal bool ForceNoEnergy { get; set; }

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

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

				internal float Amp;

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

			private int _order;

			private int _rate;

			private int _bark_map_size;

			private int _ampBits;

			private int _ampOfs;

			private int _ampDiv;

			private VorbisCodebook[] _books;

			private int _bookBits;

			private Dictionary<int, float[]> _wMap;

			private Dictionary<int, int[]> _barkMaps;

			private PacketData0[] _reusablePacketData;

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

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

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

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

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

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

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

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

				public int PostCount;

				protected override bool HasEnergy => PostCount > 0;
			}

			private int[] _partitionClass;

			private int[] _classDimensions;

			private int[] _classSubclasses;

			private int[] _xList;

			private int[] _classMasterBookIndex;

			private int[] _hNeigh;

			private int[] _lNeigh;

			private int[] _sortIdx;

			private int _multiplier;

			private int _range;

			private int _yBits;

			private VorbisCodebook[] _classMasterbooks;

			private VorbisCodebook[][] _subclassBooks;

			private int[][] _subclassBookIndex;

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

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

			private PacketData1[] _reusablePacketData;

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

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

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

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

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

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

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

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

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

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

		private VorbisStreamDecoder _vorbis;

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

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

		protected abstract void Init(DataPacket packet);

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

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

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

		internal class Submap
		{
			internal VorbisFloor Floor;

			internal VorbisResidue Residue;

			internal Submap()
			{
			}
		}

		internal class CouplingStep
		{
			internal int Magnitude;

			internal int Angle;

			internal CouplingStep()
			{
			}
		}

		private VorbisStreamDecoder _vorbis;

		internal Submap[] Submaps;

		internal Submap[] ChannelSubmap;

		internal CouplingStep[] CouplingSteps;

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

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

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

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

		private VorbisStreamDecoder _vorbis;

		private float[][] _windows;

		internal bool BlockFlag;

		internal int WindowType;

		internal int TransformType;

		internal VorbisMapping Mapping;

		internal int BlockSize;

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

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

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

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

		private IContainerReader _containerReader;

		private List<VorbisStreamDecoder> _decoders;

		private List<int> _serials;

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

		public int Channels => ActiveDecoder._channels;

		public int SampleRate => ActiveDecoder._sampleRate;

		public int UpperBitrate => ActiveDecoder._upperBitrate;

		public int NominalBitrate => ActiveDecoder._nominalBitrate;

		public int LowerBitrate => ActiveDecoder._lowerBitrate;

		public string Vendor => ActiveDecoder._vendor;

		public string[] Comments => ActiveDecoder._comments;

		public bool IsParameterChange => ActiveDecoder.IsParameterChange;

		public long ContainerOverheadBits => ActiveDecoder.ContainerBits;

		public bool ClipSamples { get; set; }

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

		public int StreamIndex => _streamIdx;

		public int StreamCount => _decoders.Count;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			private int _end;

			private int _partitionSize;

			private int _classifications;

			private int _maxStages;

			private VorbisCodebook[][] _books;

			private VorbisCodebook _classBook;

			private int[] _cascade;

			private int[] _entryCache;

			private int[][] _decodeMap;

			private int[][][] _partWordCache;

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

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

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

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

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

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

		private class Residue2 : Residue0
		{
			private int _channels;

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

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

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

		private VorbisStreamDecoder _vorbis;

		private float[][] _residue;

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

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

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

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

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

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

		internal int _nominalBitrate;

		internal int _lowerBitrate;

		internal string _vendor;

		internal string[] _comments;

		internal int _channels;

		internal int _sampleRate;

		internal int Block0Size;

		internal int Block1Size;

		internal VorbisCodebook[] Books;

		internal VorbisTime[] Times;

		internal VorbisFloor[] Floors;

		internal VorbisResidue[] Residues;

		internal VorbisMapping[] Maps;

		internal VorbisMode[] Modes;

		private int _modeFieldBits;

		internal long _glueBits;

		internal long _metaBits;

		internal long _bookBits;

		internal long _timeHdrBits;

		internal long _floorHdrBits;

		internal long _resHdrBits;

		internal long _mapHdrBits;

		internal long _modeHdrBits;

		internal long _wasteHdrBits;

		internal long _modeBits;

		internal long _floorBits;

		internal long _resBits;

		internal long _wasteBits;

		internal long _samples;

		internal int _packetCount;

		internal Stopwatch _sw = new Stopwatch();

		private IPacketProvider _packetProvider;

		private DataPacket _parameterChangePacket;

		private List<int> _pagesSeen;

		private int _lastPageSeen;

		private bool _eosFound;

		private object _seekLock = new object();

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

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

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

		private float[] _prevBuffer;

		private RingBuffer _outputBuffer;

		private Queue<int> _bitsPerPacketHistory;

		private Queue<int> _sampleCountHistory;

		private int _preparedLength;

		internal bool _clipped;

		private Stack<DataPacket> _resyncQueue;

		private long _currentPosition;

		private long _reportedPosition;

		private VorbisMode _mode;

		private bool _prevFlag;

		private bool _nextFlag;

		private bool[] _noExecuteChannel;

		private VorbisFloor.PacketData[] _floorData;

		private float[][] _residue;

		private bool _isParameterChange;

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

		internal bool CanSeek => _packetProvider.CanSeek;

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

		internal long ContainerBits => _packetProvider.ContainerBits;

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

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

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

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

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

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

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

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

		public int TotalPages => _packetProvider.GetTotalPageCount();

		public bool Clipped => _clipped;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			protected override void Init(DataPacket packet)
			{
			}
		}

		private VorbisStreamDecoder _vorbis;

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

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

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

			public PageFlags Flags { get; set; }

			public long GranulePosition { get; set; }

			public int SequenceNumber { get; set; }

			public long DataOffset { get; set; }

			public int[] PacketSizes { get; set; }

			public bool LastPacketContinues { get; set; }

			public bool IsResync { get; set; }
		}

		private Crc _crc = new Crc();

		private Stream _stream;

		private bool _closeOnDispose;

		private Dictionary<int, PacketReader> _packetReaders;

		private List<int> _disposedStreamSerials;

		private long _nextPageOffset;

		private int _pageCount;

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

		private long _containerBits;

		private long _wasteBits;

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

		public int PagesRead => _pageCount;

		public bool CanSeek => true;

		public long WasteBits => _wasteBits;

		public event EventHandler<NewStreamEventArgs> NewStream;

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

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

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

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

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

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

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

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

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