CatalpaBow.H3VC.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using FistVR;
using H3MP;
using H3MP.Networking;
using H3MP.Scripts;
using H3VC.AudioPipelines;
using H3VC.Converter;
using H3VC.Data;
using H3VC.H3MPWrapper;
using H3VC.Network;
using H3VC.NetworkImplement.Mute;
using H3VC.Networks;
using H3VC.Networks.NetworkImplement;
using H3VC.Netwroks;
using H3VC.Presenter;
using H3VC.Servers;
using H3VC.Speakers;
using H3VC.Test;
using H3VC.VC;
using H3VC.VCUsers;
using H3VC.View;
using H3VC.VoiceRecoders;
using H3VC.VoiceRecoders.MicImpement;
using H3VC.src.View;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NAudio.Wave;
using UniRx;
using UniRx.Diagnostics;
using UniRx.InternalUtil;
using UniRx.Operators;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityOpus;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("CatalpaBow")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Add 3d audio voicechat to H3MP")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+c594efcbeda7c2038853a7f8a2dd3abb034aa0ef")]
[assembly: AssemblyProduct("CatalpaBow.H3VC")]
[assembly: AssemblyTitle("H3VC")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace H3VC
{
	[BepInPlugin("CatalpaBow.H3VC", "H3VC", "0.1.1")]
	[BepInProcess("h3vr.exe")]
	public class Mod : BaseUnityPlugin
	{
		internal AudioTest audioTest;

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			VCMain.Intialize();
			ViewMain.Intialize();
			PresenterMain.Intialize(VCMain.recoder);
		}

		private void Update()
		{
		}
	}
	public static class TestPacket
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static GenericCustomPacketReceivedDelegate <0>__PacketReceived;
		}

		public static void Intialize()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__PacketReceived;
			if (obj == null)
			{
				GenericCustomPacketReceivedDelegate val = PacketReceived;
				<>O.<0>__PacketReceived = val;
				obj = (object)val;
			}
			Mod.GenericCustomPacketReceived += (GenericCustomPacketReceivedDelegate)obj;
		}

		public static void PacketReceived(int clientID, string ID, Packet packet)
		{
			if (!(ID != "TestPacket"))
			{
				string text = packet.ReadString(true);
				Mod.Logger.LogMessage((object)text);
			}
		}

		public static void Send()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Packet val = new Packet(-1);
			val.Write("TestPacket");
			val.Write("HelloWorldYoYo");
			ClientSend.SendTCPData(val, false);
		}

		public static void Test()
		{
		}
	}
	public class H3VRRaycaster : BaseRaycaster
	{
		public override Camera eventCamera
		{
			get
			{
				throw new NotImplementedException();
			}
		}

		public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
		{
			throw new NotImplementedException();
		}
	}
}
namespace H3VC.View
{
	public static class AssetBundleLoader
	{
		private static AssetBundle bundle;

		public static AssetBundle Load()
		{
			if ((Object)(object)bundle != (Object)null)
			{
				return bundle;
			}
			bundle = AssetBundle.LoadFromFile(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName + "\\miccfgview");
			return bundle;
		}
	}
	public class H3VCWristMenuSection : FVRWristMenuSection
	{
		public override void Enable()
		{
		}

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Image obj = ((Component)this).gameObject.AddComponent<Image>();
			((Graphic)obj).rectTransform.sizeDelta = new Vector2(500f, 350f);
			((Graphic)obj).color = new Color(0.1f, 0.1f, 0.1f, 1f);
		}
	}
	public class VoiceRcoderWristMenuPatch : MonoBehaviour
	{
		[HarmonyPatch(typeof(FVRWristMenu2), "Update")]
		[HarmonyPrefix]
		private static void PrefixUpdate()
		{
		}

		[HarmonyPatch(typeof(FVRWristMenu2), "Awake")]
		[HarmonyPrefix]
		private static void PrefixAwake(FVRWristMenu2 __instance)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Section_H3VC", new Type[1] { typeof(RectTransform) });
			GameObject val2 = Object.Instantiate<GameObject>(AssetBundleLoader.Load().LoadAsset<GameObject>("MicSettings"));
			val2.transform.parent = val.transform;
			VoiceRecoderView.SingleInstance.Value = val2.GetComponent<VoiceRecoderView>();
			val.transform.SetParent(__instance.MenuGO.transform);
			val.transform.localPosition = new Vector3(0f, 300f, 0f);
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(350f, 350f);
			FVRWristMenuSection val3 = (FVRWristMenuSection)(object)val.AddComponent<H3VCWristMenuSection>();
			val3.ButtonText = "H3VC";
			__instance.Sections.Add(val3);
			val.SetActive(false);
		}
	}
	public class VoiceRecoderView : MonoBehaviour
	{
		public static ReactiveProperty<VoiceRecoderView> SingleInstance = new ReactiveProperty<VoiceRecoderView>();

		public UniRx.IObservable<Unit> OnViewDestroied;

		public UniRx.IObservable<bool> OnMuteChanged;

		public UniRx.IObservable<Unit> OnPreviousDevice;

		public UniRx.IObservable<Unit> OnNextDevice;

		public UniRx.IObservable<Unit> OnPreviousSoundMode;

		public UniRx.IObservable<Unit> OnNextSoundMode;

		public UniRx.IObservable<Unit> OnInceraseVolume;

		public UniRx.IObservable<Unit> OnDecreaseVolume;

		[SerializeField]
		private Toggle muteToggle;

		[SerializeField]
		private Text soundModeName;

		[SerializeField]
		private Button soundModePrevious;

		[SerializeField]
		private Button soundModeNext;

		[SerializeField]
		private Text deviceNameText;

		[SerializeField]
		private Button devicePrevious;

		[SerializeField]
		private Button deviceNext;

		[SerializeField]
		private GameObject levelMeter;

		[SerializeField]
		private Text volumeNum;

		[SerializeField]
		private Button decreaseVolume;

		[SerializeField]
		private Button increaseVolume;

		public void OnDestroy()
		{
			Mod.Logger.LogInfo((object)"Destroied!");
		}

		public void Awake()
		{
			OnMuteChanged = muteToggle.OnValueChangedAsObservable();
			OnPreviousDevice = devicePrevious.OnClickAsObservable();
			OnNextDevice = deviceNext.OnClickAsObservable();
			OnPreviousSoundMode = soundModePrevious.OnClickAsObservable();
			OnNextSoundMode = soundModeNext.OnClickAsObservable();
			OnDecreaseVolume = decreaseVolume.OnClickAsObservable();
			OnInceraseVolume = increaseVolume.OnClickAsObservable();
			SingleInstance.Value = this;
		}

		public void ChangeSoundMode(string modeName)
		{
			soundModeName.text = modeName;
		}

		public void ChangeDeviceName(string deviceName)
		{
			deviceNameText.text = deviceName;
		}

		public void ChangeVolumeNum(int val)
		{
			volumeNum.text = val.ToString();
		}

		public void SetVoiceLevel(float val)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			levelMeter.transform.localScale = new Vector3(val, 1f, 1f);
		}
	}
}
namespace H3VC.View.FVRComponent
{
	public class FVRDropdown : FVRPointable
	{
		private Dropdown dropdown;

		public void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = ((Component)this).GetComponent<RectTransform>();
			dropdown = ((Component)this).GetComponent<Dropdown>();
			((Component)this).gameObject.AddComponent<BoxCollider>().size = new Vector3(component.sizeDelta.x, component.sizeDelta.y, 0f);
		}

		public override void OnPoint(FVRViveHand hand)
		{
			((FVRPointable)this).OnPoint(hand);
			if (hand.Input.TriggerDown && (Object)(object)dropdown != (Object)null)
			{
				dropdown.Show();
			}
		}
	}
	public class FVRToggle : FVRPointable
	{
		private Toggle toggle;

		public void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = ((Component)this).GetComponent<RectTransform>();
			toggle = ((Component)this).GetComponent<Toggle>();
			((Component)this).gameObject.AddComponent<BoxCollider>().size = new Vector3(component.sizeDelta.x, component.sizeDelta.y, 0f);
		}

		public override void OnPoint(FVRViveHand hand)
		{
			((FVRPointable)this).OnPoint(hand);
			if (hand.Input.TriggerDown && (Object)(object)toggle != (Object)null)
			{
				toggle.isOn = !toggle.isOn;
			}
		}
	}
}
namespace H3VC.VoiceRecoders
{
	public abstract class BaseMicrophone : IMutipleDevice
	{
		public abstract UniRx.IObservable<float[]> OnAudioReady { get; }

		public BaseMicrophone()
		{
		}

		public abstract void StartRecoding();

		public abstract IEnumerable<MicDeviceInfo> ShowDevices();

		public abstract MicDeviceInfo ChangeDevice(int deviceNumber);

		public abstract int DeviceCount();
	}
	public interface IMutipleDevice
	{
		IEnumerable<MicDeviceInfo> ShowDevices();

		MicDeviceInfo ChangeDevice(int deviceID);

		int DeviceCount();
	}
	public class MicDeviceInfo
	{
		public readonly int deviceID;

		public string name { get; private set; }

		public MicDeviceInfo(int _deviceID, string _name)
		{
			deviceID = _deviceID;
			name = _name;
		}
	}
	public class VoiceLevelMeter
	{
		private VoiceRecoder recoder;

		private ReactiveProperty<float> _crntVoiceLevel;

		private List<float> averageBuf;

		[SerializeField]
		private float dB_Min = -80f;

		[SerializeField]
		private float dB_Max = -0f;

		public IReadOnlyReactiveProperty<float> VoiceLevel => _crntVoiceLevel;

		public VoiceLevelMeter(VoiceRecoder _recoder)
		{
			averageBuf = new List<float>();
			recoder = _recoder;
			_crntVoiceLevel = new ReactiveProperty<float>();
			Intialize();
		}

		private void Intialize()
		{
			(from samples in recoder.OnAudioReady.ThrottleFirst(TimeSpan.FromMilliseconds(16.0))
				select samples.Value.pcmBuffer.Average()).Select(ToDecibel).Select(Normalization).Subscribe(delegate(float level)
			{
				_crntVoiceLevel.Value = level;
			});
		}

		private float Normalization(float dB)
		{
			float num = dB;
			if (num > dB_Max)
			{
				num = dB_Max;
			}
			else if (num < dB_Min)
			{
				num = dB_Min;
			}
			return 1f + num / (dB_Max - dB_Min);
		}

		private float ToDecibel(float sampleAverage)
		{
			return 20f * Mathf.Log10(sampleAverage);
		}
	}
	public class VoiceRecoder : IAudioInput
	{
		public int id = -1;

		private BaseMicrophone mic;

		private VoiceLevelMeter levelMeter;

		public ReactiveProperty<float> volume;

		public ReactiveProperty<bool> isMute;

		public ReactiveProperty<SoundMode> soundMode;

		public ReactiveProperty<MicDeviceInfo> crntDevice;

		public IReadOnlyReactiveProperty<float> VoiceLevel => levelMeter.VoiceLevel;

		public UniRx.IObservable<KeyValuePair<int, PCMSegment>> OnAudioReady => from samples in mic.OnAudioReady
			select samples.Select((float sample) => sample * volume.Value * 2f).ToArray() into sgmnt
			select new PCMSegment(sgmnt, sgmnt.Length) into pcmData
			select new KeyValuePair<int, PCMSegment>(id, pcmData);

		public UniRx.IObservable<KeyValuePair<int, bool>> OnMuteChanged => isMute.Select((bool isMute) => new KeyValuePair<int, bool>(id, isMute));

		public UniRx.IObservable<KeyValuePair<int, SoundMode>> OnSoundModeChanged => soundMode.Select((SoundMode mode) => new KeyValuePair<int, SoundMode>(id, mode));

		public VoiceRecoder(BaseMicrophone _mic)
		{
			mic = _mic;
			volume = new ReactiveProperty<float>();
			volume.Value = 0.5f;
			crntDevice = new ReactiveProperty<MicDeviceInfo>();
			crntDevice.Value = mic.ShowDevices().First();
			isMute = new ReactiveProperty<bool>();
			soundMode = new ReactiveProperty<SoundMode>();
			StartRecoding();
			levelMeter = new VoiceLevelMeter(this);
		}

		public void DecreaseVolume()
		{
			ChangeVolume(volume.Value - 0.1f);
		}

		public void IncreaseVolume()
		{
			ChangeVolume(volume.Value + 0.1f);
		}

		private void ChangeVolume(float val)
		{
			if (val < 0f)
			{
				val = 0f;
			}
			if ((double)val > 2.0)
			{
				val = 2f;
			}
			volume.Value = val;
		}

		private void StartRecoding()
		{
			mic.StartRecoding();
		}

		public IEnumerable<MicDeviceInfo> ShowDevices()
		{
			return mic.ShowDevices();
		}

		public void ChangeDevice(int deviceID)
		{
			mic.ChangeDevice(deviceID);
		}

		public void NextDevice()
		{
			int num = crntDevice.Value.deviceID + 1;
			if (num >= mic.DeviceCount())
			{
				num = 0;
			}
			crntDevice.Value = mic.ChangeDevice(num);
		}

		public void PreviousDevice()
		{
			int num = crntDevice.Value.deviceID - 1;
			if (num < 0)
			{
				num = mic.DeviceCount() - 1;
			}
			crntDevice.Value = mic.ChangeDevice(num);
		}

		public void NextSoundMode()
		{
			int length = Enum.GetValues(typeof(SoundMode)).Length;
			if ((int)(soundMode.Value + 1) >= length)
			{
				soundMode.Value = SoundMode.positional;
			}
			else
			{
				soundMode.Value++;
			}
		}

		public void PreviousSoundMode()
		{
			int length = Enum.GetValues(typeof(SoundMode)).Length;
			if (soundMode.Value - 1 < SoundMode.positional)
			{
				soundMode.Value = (SoundMode)(length - 1);
			}
			else
			{
				soundMode.Value--;
			}
		}
	}
}
namespace H3VC.VoiceRecoders.MicImplement
{
	[Obsolete("", true)]
	public class UnityVoiceMic
	{
	}
}
namespace H3VC.VoiceRecoders.MicImpement
{
	public class NAudioMic : BaseMicrophone
	{
		private Subject<float[]> OnAudioReadySubject;

		private float[] floatSamples;

		private WaveInEvent waveIn;

		public override UniRx.IObservable<float[]> OnAudioReady => OnAudioReadySubject;

		public NAudioMic()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			OnAudioReadySubject = new Subject<float[]>();
			floatSamples = new float[4096];
			int deviceNumber = 0;
			waveIn = new WaveInEvent();
			waveIn.DeviceNumber = deviceNumber;
			waveIn.WaveFormat = new WaveFormat(48000, 1);
			waveIn.BufferMilliseconds = 10;
			waveIn.DataAvailable += DataAvailableHandler;
		}

		private void DataAvailableHandler(object sender, WaveInEventArgs e)
		{
			try
			{
				int recodedPartLength = Bit16ToNormizedFloat(ref floatSamples, e);
				float[] value = CutRecodedSamples(recodedPartLength);
				OnAudioReadySubject.OnNext(value);
			}
			catch (Exception ex)
			{
				Mod.Logger.LogError((object)ex);
			}
		}

		private int Bit16ToNormizedFloat(ref float[] floatSamples, WaveInEventArgs e)
		{
			int num = 0;
			for (num = 0; num < e.BytesRecorded; num += 2)
			{
				float num2 = (float)(short)((e.Buffer[num + 1] << 8) | e.Buffer[num]) / 32768f;
				floatSamples[num / 2] = num2;
			}
			return num / 2;
		}

		private float[] CutRecodedSamples(int recodedPartLength)
		{
			float[] array = new float[recodedPartLength];
			Array.Copy(floatSamples, array, recodedPartLength);
			return array;
		}

		public override void StartRecoding()
		{
			waveIn.StartRecording();
		}

		public override MicDeviceInfo ChangeDevice(int newDeviceNumber)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			waveIn.StopRecording();
			waveIn.Dispose();
			waveIn = new WaveInEvent();
			waveIn.DeviceNumber = newDeviceNumber;
			waveIn.WaveFormat = new WaveFormat(48000, 1);
			waveIn.BufferMilliseconds = 10;
			waveIn.DataAvailable += DataAvailableHandler;
			waveIn.StartRecording();
			WaveInCapabilities capabilities = WaveIn.GetCapabilities(newDeviceNumber);
			return new MicDeviceInfo(newDeviceNumber, ((WaveInCapabilities)(ref capabilities)).ProductName);
		}

		public override IEnumerable<MicDeviceInfo> ShowDevices()
		{
			for (int i = 0; i < WaveIn.DeviceCount; i++)
			{
				int deviceID = i;
				WaveInCapabilities capabilities = WaveIn.GetCapabilities(i);
				yield return new MicDeviceInfo(deviceID, ((WaveInCapabilities)(ref capabilities)).ProductName);
			}
		}

		public override int DeviceCount()
		{
			return WaveIn.DeviceCount;
		}
	}
}
namespace H3VC.VCUsers
{
	public class VCUserList
	{
		private ReactiveCollection<int> _crntUsers;

		public IReadOnlyReactiveCollection<int> crntUserIDs => _crntUsers;

		public UniRx.IObservable<int> OnJoined => from evnt in crntUserIDs.ObserveAdd()
			select evnt.Value;

		public UniRx.IObservable<int> OnLeaved => from evnt in crntUserIDs.ObserveRemove()
			select evnt.Value;

		public VCUserList()
		{
			ReactiveCollection<int> reactiveCollection = new ReactiveCollection<int>();
			foreach (int key in GameManager.players.Keys)
			{
				reactiveCollection.Add(key);
			}
			_crntUsers = reactiveCollection;
			(from plMngr in Observable.FromEvent<OnPlayerAddedDelegate, PlayerManager>((Action<PlayerManager> h) => new OnPlayerAddedDelegate(h.Invoke), delegate(OnPlayerAddedDelegate h)
				{
					GameManager.OnPlayerAdded += h;
				}, delegate(OnPlayerAddedDelegate h)
				{
					GameManager.OnPlayerAdded -= h;
				})
				select plMngr.ID).Subscribe(_crntUsers.Add);
			(from plMngr in Observable.FromEvent<OnPlayerRemovedDelegate, PlayerManager>((Action<PlayerManager> h) => new OnPlayerRemovedDelegate(h.Invoke), delegate(OnPlayerRemovedDelegate h)
				{
					Mod.OnPlayerRemoved += h;
				}, delegate(OnPlayerRemovedDelegate h)
				{
					Mod.OnPlayerRemoved -= h;
				})
				select plMngr.ID).Subscribe(delegate(int id)
			{
				_crntUsers.Remove(id);
			});
			OnJoined.Subscribe(delegate(int id)
			{
				Mod.Logger.LogInfo((object)("VCUser:" + id + "is joined!"));
			});
			OnLeaved.Subscribe(delegate(int id)
			{
				Mod.Logger.LogInfo((object)("VCUser:" + id + "is leaved!"));
			});
		}
	}
}
namespace H3VC.VC
{
	public static class VCMain
	{
		public static AudioPipeline audioPipeline;

		public static VoiceRecoder recoder;

		public static PlayerAudioSpeakers speakers;

		public static VCUserList userList;

		public static AudioRelayServer server;

		public static void Intialize()
		{
			userList = new VCUserList();
			recoder = new VoiceRecoder(new NAudioMic());
			speakers = new PlayerAudioSpeakers(userList);
			NetworkAudioListener inOthers = new NetworkAudioListener();
			NetworkAudioStreamer outSelf = new NetworkAudioStreamer();
			audioPipeline = new AudioPipeline(recoder, outSelf, inOthers, speakers);
			server = new AudioRelayServer();
		}
	}
}
namespace H3VC.Speakers
{
	public class PlayerAudioSpeaker
	{
		public readonly int id;

		private SoundMode soundMode;

		private bool isMute;

		private UnitySpeaker voicePlayer;

		public PlayerAudioSpeaker(UnitySpeaker pl, int _id)
		{
			id = _id;
			voicePlayer = pl;
			soundMode = H3VC.Data.SoundMode.positional;
			voicePlayer.SetPositional(isPositional: false);
		}

		public void Mute(bool isMute)
		{
			voicePlayer.DontPlaySound(isMute);
			this.isMute = isMute;
		}

		public void SoundMode(SoundMode mode)
		{
			ManualLogSource logger = Mod.Logger;
			int num = id;
			logger.LogInfo((object)("UserID:" + num + " is SoundModeChanged"));
			soundMode = mode;
			if (mode == H3VC.Data.SoundMode.positional)
			{
				voicePlayer.SetPositional(isPositional: true);
			}
			else
			{
				voicePlayer.SetPositional(isPositional: false);
			}
		}

		public void Play(PCMSegment sgmnt)
		{
			voicePlayer.Play(sgmnt);
			if (isMute)
			{
				Mute(isMute: true);
				return;
			}
			string text = Players.CurrentScene(id);
			string text2 = Players.CurrentScene(Players.IDSelf());
			bool flag = text == text2;
			if ((soundMode == H3VC.Data.SoundMode.localScene || soundMode == H3VC.Data.SoundMode.positional) && !flag)
			{
				voicePlayer.DontPlaySound(isMute: true);
			}
			else
			{
				voicePlayer.DontPlaySound(isMute: false);
			}
		}
	}
	public class PlayerAudioSpeakers : IAudioOutput
	{
		public List<PlayerAudioSpeaker> speakerList;

		private readonly VCUserList userList;

		public PlayerAudioSpeakers(VCUserList _userList)
		{
			userList = _userList;
			speakerList = userList.crntUserIDs.Select(VoiceSpeakerBuilder.Build).ToList();
			(from spkr in userList.OnJoined.Select(VoiceSpeakerBuilder.Build)
				where spkr != null
				select spkr).Subscribe(speakerList.Add);
			userList.OnLeaved.Subscribe(delegate(int id)
			{
				speakerList.RemoveAll((PlayerAudioSpeaker spkr) => spkr.id == id);
			});
		}

		public void StreamAudio(int id, PCMSegment sgmnt)
		{
			speakerList.Find((PlayerAudioSpeaker spkr) => spkr.id == id)?.Play(sgmnt);
		}

		public void Mute(int id, bool isMute)
		{
			speakerList.Find((PlayerAudioSpeaker spkr) => spkr.id == id)?.Mute(isMute);
		}

		public void SoundMode(int id, SoundMode mode)
		{
			speakerList.Find((PlayerAudioSpeaker spkr) => spkr.id == id)?.SoundMode(mode);
		}
	}
	[RequireComponent(typeof(AudioSource))]
	public class UnitySpeaker : MonoBehaviour
	{
		private const NumChannels channels = NumChannels.Mono;

		private const SamplingFrequency frequency = SamplingFrequency.Frequency_48000;

		private const int audioClipLength = 48000;

		private const int delaySamplesLength = 3840;

		private float[] samplesBuf;

		private int previousTimeSamples;

		private int previousDistance;

		private int previousHead;

		public AudioSource source { get; private set; }

		public int head { get; private set; }

		private void Awake()
		{
			Intialize(1);
		}

		public void Intialize(int channels)
		{
			source = ((Component)this).GetComponent<AudioSource>();
			source.spatialBlend = 1f;
			source.clip = AudioClip.Create("Voice", 48000, channels, 48000, false);
			source.loop = true;
		}

		public void DontPlaySound(bool isMute)
		{
			if (isMute)
			{
				source.volume = 0f;
			}
			else
			{
				source.volume = 1f;
			}
		}

		private void OnDisable()
		{
			source.Stop();
		}

		public void Play(PCMSegment sgmnt)
		{
			Play(sgmnt.pcmBuffer, sgmnt.pcmLength);
		}

		public void Play(float[] samples, int samplesLength)
		{
			if (samplesBuf == null || samplesBuf.Length != samplesLength + 2)
			{
				samplesBuf = new float[samplesLength + 2];
				Mod.Logger.LogInfo((object)("samplesBufSize is changed:" + samplesLength + 2));
			}
			Array.Copy(samples, 0, samplesBuf, 1, samplesLength);
			samplesBuf[0] = samplesBuf[1];
			samplesBuf[samplesBuf.Length - 1] = samplesBuf[samplesBuf.Length - 2];
			source.clip.SetData(samplesBuf, head);
			head += samplesBuf.Length;
			head %= source.clip.samples;
			if (!source.isPlaying && head > 3840)
			{
				Mod.Logger.LogInfo((object)"Played");
				source.Play();
			}
			int num = 0;
			num = ((source.timeSamples <= head) ? (head - source.timeSamples) : (head + source.clip.samples - source.timeSamples));
			if (num > 5760)
			{
				int num2 = head - 3840;
				source.timeSamples = ((num2 < 0) ? (source.clip.samples + num2) : num2);
			}
			Log();
		}

		public void SetInScene()
		{
			source.spatialBlend = 0f;
		}

		public void SetPositional(bool isPositional)
		{
			if (isPositional)
			{
				source.spatialBlend = 1f;
			}
			else
			{
				source.spatialBlend = 0f;
			}
		}

		public void Log()
		{
			_ = source.isPlaying;
		}
	}
	public static class VoiceSpeakerBuilder
	{
		public static PlayerAudioSpeaker Build(int id)
		{
			if (!GameManager.players.TryGetValue(id, out var value))
			{
				return null;
			}
			return new PlayerAudioSpeaker(((Component)value.head).gameObject.AddComponent<UnitySpeaker>(), id);
		}
	}
}
namespace H3VC.Servers
{
	public class AudioRelayServer
	{
		private static AudioRelayServer _instance;

		private VoiceReceiver receiver;

		private IDisposable serverDisposer;

		public static AudioRelayServer Insntance => _instance ?? (_instance = new AudioRelayServer());

		public AudioRelayServer()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			receiver = VoiceReceiver.Instance;
			Mod.OnConnection += new OnConnectionDelegate(Start);
			Server.OnServerClose += new OnServerCloseDelegate(Stop);
		}

		public void Start()
		{
			if (ThreadManager.host)
			{
				Mod.Logger.LogInfo((object)"H3VC ServerStart");
				serverDisposer = receiver.OnVoiceReceived.Subscribe(delegate(UniRx.Tuple<int, OpusSegment> data)
				{
					VoiceSender.ServerSend(data.Item1, data.Item2);
				});
			}
		}

		public void Stop()
		{
			Mod.Logger.LogInfo((object)"H3VC ServerClose");
			serverDisposer.Dispose();
		}
	}
}
namespace H3VC.Netwroks
{
	public enum TransportProtocol
	{
		TCP,
		UDP
	}
}
namespace H3VC.Network
{
	public class VoiceReceiver : IDisposable
	{
		private static VoiceReceiver _instance;

		public static string packetName = "H3VC_VoiceData";

		private Subject<UniRx.Tuple<int, OpusSegment>> voiceReceivedStream;

		public static VoiceReceiver Instance => _instance ?? (_instance = new VoiceReceiver());

		public UniRx.IObservable<UniRx.Tuple<int, OpusSegment>> OnVoiceReceived => voiceReceivedStream;

		public VoiceReceiver()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			voiceReceivedStream = new Subject<UniRx.Tuple<int, OpusSegment>>();
			Mod.GenericCustomPacketReceived += new GenericCustomPacketReceivedDelegate(PacketHandler);
		}

		private void PacketHandler(int clientID, string name, Packet pkt)
		{
			if (!(name != packetName))
			{
				int num = pkt.ReadInt(true);
				byte[] data = pkt.ReadBytes(num, true);
				int length = pkt.ReadInt(true);
				voiceReceivedStream.OnNext(UniRx.Tuple.Create(clientID, new OpusSegment(data, length)));
			}
		}

		public void Dispose()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Mod.GenericCustomPacketReceived -= new GenericCustomPacketReceivedDelegate(PacketHandler);
		}
	}
	internal static class VoiceSender
	{
		public const string packetID = "H3VC_VoiceData";

		public static void ClientSend(OpusSegment sgmnt)
		{
			ClientSend.SendUDPData(sgmnt.ToPacket(-1, "H3VC_VoiceData"), false);
		}

		public static void ServerSend(int sender, OpusSegment sgmnt)
		{
			Packet val = sgmnt.ToPacket(-1, "H3VC_VoiceData");
			val.WriteLength();
			foreach (ServerClient value in Server.clients.Values)
			{
				if (value.ID == sender)
				{
					break;
				}
				value.udp.SendData(val);
			}
		}

		public static void SendFromClient(OpusSegment sgmnt)
		{
			if (ThreadManager.host)
			{
				ServerSend(0, sgmnt);
			}
			else
			{
				ClientSend(sgmnt);
			}
		}
	}
}
namespace H3VC.NetworkImplement.Mute
{
	public static class MuteEvent
	{
		public static MuteSender sender;

		public static MuteReceiver receiver;

		static MuteEvent()
		{
			TransportProtocol prtcl = TransportProtocol.TCP;
			sender = new MuteSender("H3VC_Mute", prtcl);
			receiver = new MuteReceiver("H3VC_Mute");
		}
	}
	public static class SoundModeEvent
	{
		public static SoundModeSender sender;

		public static SoundModeReceiver receiver;

		static SoundModeEvent()
		{
			TransportProtocol prtcl = TransportProtocol.TCP;
			sender = new SoundModeSender("H3VC_SoundMode", prtcl);
			receiver = new SoundModeReceiver("H3VC_SoundMode");
		}
	}
}
namespace H3VC.Networks
{
	public class NetworkAudioListener : IAudioInput
	{
		private VoiceDecoder decoder;

		public UniRx.IObservable<KeyValuePair<int, PCMSegment>> OnAudioReady => VoiceReceiver.Instance.OnVoiceReceived.Select(delegate(UniRx.Tuple<int, OpusSegment> audioData)
		{
			PCMSegment value = decoder.Decode(audioData.Item2);
			return new KeyValuePair<int, PCMSegment>(audioData.Item1, value);
		});

		public UniRx.IObservable<KeyValuePair<int, bool>> OnMuteChanged => MuteEvent.receiver.OnReceivedWithSenderID;

		public UniRx.IObservable<KeyValuePair<int, SoundMode>> OnSoundModeChanged => SoundModeEvent.receiver.OnReceivedWithSenderID;

		public NetworkAudioListener()
		{
			decoder = new VoiceDecoder();
		}
	}
	public class NetworkAudioStreamer : IAudioOutput
	{
		private VoiceEncoder encoder;

		public NetworkAudioStreamer()
		{
			encoder = new VoiceEncoder();
		}

		public void Mute(int id, bool isMute)
		{
			MuteEvent.sender.SendFromClient(isMute);
		}

		public void SoundMode(int id, SoundMode mode)
		{
			SoundModeEvent.sender.SendFromClient(mode);
		}

		public void StreamAudio(int id, PCMSegment sgmnt)
		{
			foreach (OpusSegment item in encoder.Encode(sgmnt.pcmBuffer))
			{
				VoiceSender.SendFromClient(item);
			}
		}
	}
}
namespace H3VC.Networks.NetworkImplement
{
	public class MuteReceiver : ReceiverBase<bool>
	{
		public MuteReceiver(string id)
			: base(id)
		{
		}

		public override bool Unpacket(CustomPacketReceivedEventData data)
		{
			return data.packet.ReadBool(true);
		}
	}
	public class MuteSender : SenderBase<bool>
	{
		public MuteSender(string id, TransportProtocol prtcl)
			: base(id, prtcl)
		{
		}

		public override void WritePacketData(ref Packet pkt, bool data)
		{
			pkt.Write(data);
		}
	}
	public abstract class ReceiverBase<ReceiveT>
	{
		public string packetID;

		public UniRx.IObservable<ReceiveT> OnReceived;

		public UniRx.IObservable<KeyValuePair<int, ReceiveT>> OnReceivedWithSenderID;

		public UniRx.IObservable<CustomPacketReceivedEventData> OnReceivedRaw;

		public ReceiverBase(string packetID)
		{
			ReceiverBase<ReceiveT> receiverBase = this;
			this.packetID = packetID;
			OnReceivedRaw = H3MPNetworkEvents.OnCustomPacketRecevied.Where((CustomPacketReceivedEventData evntData) => evntData.id == packetID);
			OnReceived = OnReceivedRaw.Select(Unpacket);
			OnReceivedWithSenderID = OnReceivedRaw.Select((CustomPacketReceivedEventData data) => new KeyValuePair<int, ReceiveT>(data.clientID, receiverBase.Unpacket(data)));
		}

		public abstract ReceiveT Unpacket(CustomPacketReceivedEventData data);
	}
	public abstract class SenderBase<SendT>
	{
		protected string packetID;

		protected TransportProtocol prtcl;

		protected SenderBase(string pktID, TransportProtocol prtcl)
		{
			packetID = pktID;
			this.prtcl = prtcl;
		}

		private void ClientSend(SendT data)
		{
			ClientSend.SendUDPData(ToPacket(data), false);
		}

		public void ServerSend(SendT data)
		{
			Packet pkt = ToPacket(data);
			ServerRelaySend(0, pkt);
		}

		public void ServerRelaySend(int sender, Packet pkt)
		{
			pkt.WriteLength();
			if (prtcl == TransportProtocol.TCP)
			{
				foreach (ServerClient value in Server.clients.Values)
				{
					if (value.ID == sender)
					{
						break;
					}
					value.udp.SendData(pkt);
				}
				return;
			}
			foreach (ServerClient value2 in Server.clients.Values)
			{
				if (value2.ID == sender)
				{
					break;
				}
				value2.tcp.SendData(pkt);
			}
		}

		public Packet ToPacket(SendT data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			Packet pkt = new Packet(-1);
			pkt.Write(packetID);
			WritePacketData(ref pkt, data);
			return pkt;
		}

		public abstract void WritePacketData(ref Packet pkt, SendT data);

		public void SendFromClient(SendT data)
		{
			if (ThreadManager.host)
			{
				ServerSend(data);
			}
			else
			{
				ClientSend(data);
			}
		}
	}
	public class SoundModeReceiver : ReceiverBase<SoundMode>
	{
		public SoundModeReceiver(string id)
			: base(id)
		{
		}

		public override SoundMode Unpacket(CustomPacketReceivedEventData data)
		{
			return (SoundMode)data.packet.ReadInt(true);
		}
	}
	public class SoundModeSender : SenderBase<SoundMode>
	{
		public SoundModeSender(string id, TransportProtocol prtcl)
			: base(id, prtcl)
		{
		}

		public override void WritePacketData(ref Packet pkt, SoundMode data)
		{
			pkt.Write((int)data);
		}
	}
}
namespace H3VC.src.View
{
	public static class ViewMain
	{
		public static void Intialize()
		{
			Harmony.CreateAndPatchAll(typeof(VoiceRcoderWristMenuPatch), (string)null);
		}
	}
}
namespace H3VC.src.VC.Logger
{
	public class UnitySpeakerAnalizer
	{
		private UnitySpeaker spkr;

		private int speakrCrntPosDelay;

		private int headPos => spkr.head;

		private int crntPos => spkr.source.timeSamples;
	}
}
namespace H3VC.H3MPWrapper
{
	public static class H3MPNetworkEvents
	{
		public static UniRx.IObservable<CustomPacketReceivedEventData> OnCustomPacketRecevied = Observable.FromEvent<GenericCustomPacketReceivedDelegate, CustomPacketReceivedEventData>((Action<CustomPacketReceivedEventData> h) => (GenericCustomPacketReceivedDelegate)delegate(int cID, string id, Packet pkt)
		{
			h(new CustomPacketReceivedEventData(cID, id, pkt));
		}, delegate(GenericCustomPacketReceivedDelegate h)
		{
			Mod.GenericCustomPacketReceived += h;
		}, delegate(GenericCustomPacketReceivedDelegate h)
		{
			Mod.GenericCustomPacketReceived -= h;
		});
	}
	public class CustomPacketReceivedEventData
	{
		public int clientID;

		public string id;

		public Packet packet;

		public CustomPacketReceivedEventData(int clientID, string id, Packet pkt)
		{
			this.clientID = clientID;
			this.id = id;
			packet = pkt;
		}
	}
	public static class Players
	{
		public static string CurrentScene(int id)
		{
			if (id == IDSelf())
			{
				return GameManager.scene;
			}
			if (GameManager.players.TryGetValue(id, out var value))
			{
				return value.scene;
			}
			return "";
		}

		public static int IDSelf()
		{
			return GameManager.ID;
		}
	}
}
namespace H3VC.AudioPipelines
{
	public class AudioPipeline
	{
		private IAudioInput selfIn;

		private IAudioOutput selfOut;

		private IAudioInput otherIn;

		private IAudioOutput otherOut;

		public AudioPipeline(IAudioInput _inSelf, IAudioOutput _outSelf, IAudioInput _inOthers, IAudioOutput _outOthers)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			selfIn = _inSelf;
			selfOut = _outSelf;
			otherIn = _inOthers;
			otherOut = _outOthers;
			Mod.OnConnection += new OnConnectionDelegate(StartStream);
		}

		public void StartStream()
		{
			selfIn.OnAudioReady.Subscribe(delegate(KeyValuePair<int, PCMSegment> audioData)
			{
				selfOut.StreamAudio(audioData.Key, audioData.Value);
			});
			selfIn.OnMuteChanged.Subscribe(delegate(KeyValuePair<int, bool> isMute)
			{
				selfOut.Mute(isMute.Key, isMute.Value);
			});
			selfIn.OnSoundModeChanged.Subscribe(delegate(KeyValuePair<int, SoundMode> mode)
			{
				selfOut.SoundMode(mode.Key, mode.Value);
			});
			otherIn.OnAudioReady.Subscribe(delegate(KeyValuePair<int, PCMSegment> audioData)
			{
				otherOut.StreamAudio(audioData.Key, audioData.Value);
			});
			otherIn.OnMuteChanged.Subscribe(delegate(KeyValuePair<int, bool> isMute)
			{
				otherOut.Mute(isMute.Key, isMute.Value);
			});
			otherIn.OnSoundModeChanged.Subscribe(delegate(KeyValuePair<int, SoundMode> mode)
			{
				otherOut.SoundMode(mode.Key, mode.Value);
			});
		}
	}
	public interface IAudioInput
	{
		UniRx.IObservable<KeyValuePair<int, PCMSegment>> OnAudioReady { get; }

		UniRx.IObservable<KeyValuePair<int, bool>> OnMuteChanged { get; }

		UniRx.IObservable<KeyValuePair<int, SoundMode>> OnSoundModeChanged { get; }
	}
	public interface IAudioOutput
	{
		void StreamAudio(int id, PCMSegment sgmnt);

		void Mute(int id, bool isMute);

		void SoundMode(int id, SoundMode mode);
	}
}
namespace H3VC.Data
{
	public class OpusSegment
	{
		public readonly byte[] data;

		public readonly int dataLength;

		public readonly int length;

		public OpusSegment(byte[] _data, int _length)
		{
			data = _data;
			dataLength = _data.GetLength(0);
			length = _length;
		}

		public Packet ToPacket(int id, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			Packet val = new Packet(id);
			val.Write(name);
			val.Write(dataLength);
			val.Write(data);
			val.Write(length);
			return val;
		}
	}
	public class PCMSegment
	{
		public readonly float[] pcmBuffer;

		public readonly int pcmLength;

		public PCMSegment(float[] _pcmBuffer, int _pcmLength)
		{
			pcmBuffer = _pcmBuffer;
			pcmLength = _pcmLength;
		}
	}
	public enum SoundMode
	{
		positional,
		localScene,
		globalScene
	}
}
namespace H3VC.Converter
{
	public class VoiceDecoder
	{
		private const NumChannels channels = NumChannels.Mono;

		private Decoder decoder;

		private readonly float[] pcmBuffer = new float[5760];

		public VoiceDecoder()
		{
			decoder = new Decoder(SamplingFrequency.Frequency_48000, NumChannels.Mono);
		}

		private void OnDisable()
		{
			decoder.Dispose();
			decoder = null;
		}

		public PCMSegment Decode(OpusSegment segment)
		{
			int pcmLength = decoder.Decode(segment.data, segment.length, pcmBuffer);
			return new PCMSegment(pcmBuffer, pcmLength);
		}
	}
	public class VoiceEncoder
	{
		private const int bitrate = 96000;

		private const int frameSize = 120;

		private const int outputBufferSize = 480;

		private Encoder encoder;

		private Queue<float> pcmQueue = new Queue<float>();

		private readonly float[] frameBuffer = new float[120];

		private readonly byte[] outputBuffer = new byte[480];

		public VoiceEncoder()
		{
			encoder = new Encoder(SamplingFrequency.Frequency_48000, NumChannels.Mono, OpusApplication.Audio)
			{
				Bitrate = 96000,
				Complexity = 10,
				Signal = OpusSignal.Music
			};
		}

		private void Disable()
		{
			encoder.Dispose();
			encoder = null;
			pcmQueue.Clear();
		}

		public IEnumerable<OpusSegment> Encode(float[] data)
		{
			foreach (float item in data)
			{
				pcmQueue.Enqueue(item);
			}
			while (pcmQueue.Count > 120)
			{
				for (int j = 0; j < 120; j++)
				{
					frameBuffer[j] = pcmQueue.Dequeue();
				}
				int length = encoder.Encode(frameBuffer, outputBuffer);
				yield return new OpusSegment(outputBuffer, length);
			}
		}
	}
}
namespace H3VC.Test
{
	public class AssetBundleLoadTest
	{
		public static void Test()
		{
			if ((Object)(object)AssetBundleLoader.Load().LoadAsset<GameObject>("MicSetting") == (Object)null)
			{
				Mod.Logger.LogError((object)"asset is null");
			}
			else
			{
				Mod.Logger.LogInfo((object)"Load is sucsessed!");
			}
		}
	}
	internal class TestMain
	{
	}
	internal class AudioTest
	{
		private VoiceRecoder recoder;

		private UnitySpeaker spkr;

		public AudioTest(VoiceRecoder recoder)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			this.recoder = recoder;
			spkr = new GameObject().AddComponent<UnitySpeaker>();
			spkr.SetPositional(isPositional: false);
			Mod.Logger.LogInfo((object)AudioSettings.outputSampleRate);
			recoder.OnAudioReady.Subscribe(delegate(KeyValuePair<int, PCMSegment> data)
			{
				spkr.Play(data.Value);
			});
		}
	}
	public class SpeakerTests
	{
		private PlayerAudioSpeakers spkrs;

		public SpeakerTests(PlayerAudioSpeakers _spkrs)
		{
			spkrs = _spkrs;
		}

		public bool UserCountTests()
		{
			return spkrs.speakerList.Count == GameManager.players.Count;
		}
	}
	public static class Tester
	{
		public static void Assert(bool isSucsess)
		{
			if (isSucsess)
			{
				Mod.Logger.LogInfo((object)"Test is Sucsesed:");
			}
			else
			{
				Mod.Logger.LogError((object)"Test is Failed");
			}
		}

		public static void UserListTest()
		{
			Mod.Logger.LogDebug((object)("-----------" + MethodBase.GetCurrentMethod().Name + "-----------"));
			Mod.Logger.LogDebug((object)("UserListCount:" + VCMain.userList.crntUserIDs.Count));
			Mod.Logger.LogDebug((object)("H3MPPlayersCount:" + GameManager.players.Count));
			Assert(VCMain.userList.crntUserIDs.Count == GameManager.players.Count);
		}

		public static void Spkr_CountTest()
		{
			Mod.Logger.LogDebug((object)("-----------" + MethodBase.GetCurrentMethod().Name + "-----------"));
			Mod.Logger.LogDebug((object)("spkeakerListCount:" + VCMain.speakers.speakerList.Count));
			Mod.Logger.LogDebug((object)("UserListCount:" + VCMain.userList.crntUserIDs.Count));
			Assert(VCMain.speakers.speakerList.Count == GameManager.players.Count);
		}
	}
}
namespace H3VC.Presenter
{
	public static class PresenterMain
	{
		public static VoiceRecoderPresenter presenter;

		public static void Intialize(VoiceRecoder model)
		{
			VoiceRecoderView.SingleInstance.Where((VoiceRecoderView instance) => instance != null).Subscribe(delegate(VoiceRecoderView view)
			{
				if (presenter == null)
				{
					presenter = new VoiceRecoderPresenter(model, view);
				}
				else
				{
					presenter.ResetView(view);
				}
			});
		}
	}
	public class VoiceRecoderPresenter
	{
		private VoiceRecoder model;

		private VoiceRecoderView view;

		public VoiceRecoderPresenter(VoiceRecoder model, VoiceRecoderView view)
		{
			this.model = model;
			this.view = view;
			Intialize();
		}

		public void Intialize()
		{
			view.OnMuteChanged.Subscribe(delegate(bool isMute)
			{
				model.isMute.Value = isMute;
			}).AddTo((Component)(object)view);
			view.OnNextSoundMode.Subscribe(delegate
			{
				model.NextSoundMode();
			}).AddTo((Component)(object)view);
			view.OnPreviousSoundMode.Subscribe(delegate
			{
				model.PreviousSoundMode();
			}).AddTo((Component)(object)view);
			view.OnNextDevice.Subscribe(delegate
			{
				model.NextDevice();
			}).AddTo((Component)(object)view);
			view.OnPreviousDevice.Subscribe(delegate
			{
				model.PreviousDevice();
			}).AddTo((Component)(object)view);
			view.OnDecreaseVolume.Subscribe(delegate
			{
				model.DecreaseVolume();
			});
			view.OnInceraseVolume.Subscribe(delegate
			{
				model.IncreaseVolume();
			});
			model.soundMode.Subscribe(delegate(SoundMode mode)
			{
				view.ChangeSoundMode(mode.ToString());
			}).AddTo((Component)(object)view);
			model.crntDevice.Subscribe(delegate(MicDeviceInfo info)
			{
				view.ChangeDeviceName(info.name);
			}).AddTo((Component)(object)view);
			model.VoiceLevel.Subscribe(delegate(float level)
			{
				view.SetVoiceLevel(level);
			}).AddTo((Component)(object)view);
			model.volume.Select((float val) => (int)(Math.Round(val * 10f) * 10.0)).Subscribe(delegate(int percent)
			{
				view.ChangeVolumeNum(percent);
			});
		}

		public void ResetView(VoiceRecoderView view)
		{
			this.view = view;
			Intialize();
		}
	}
}
namespace UnityOpus
{
	public class Decoder : IDisposable
	{
		public const int maximumPacketDuration = 5760;

		private IntPtr decoder;

		private readonly NumChannels channels;

		private readonly float[] softclipMem;

		private bool disposedValue;

		public Decoder(SamplingFrequency samplingFrequency, NumChannels channels)
		{
			this.channels = channels;
			decoder = Library.OpusDecoderCreate(samplingFrequency, channels, out var error);
			if (error != 0)
			{
				Debug.LogError((object)("[UnityOpus] Failed to create Decoder. Error code is " + error));
				decoder = IntPtr.Zero;
			}
			softclipMem = new float[(int)channels];
		}

		public int Decode(byte[] data, int dataLength, float[] pcm, int decodeFec = 0)
		{
			if (decoder == IntPtr.Zero)
			{
				return 0;
			}
			int num = Library.OpusDecodeFloat(decoder, data, dataLength, pcm, pcm.Length / (int)channels, decodeFec);
			Library.OpusPcmSoftClip(pcm, num / (int)channels, channels, softclipMem);
			return num;
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!disposedValue && !(decoder == IntPtr.Zero))
			{
				Library.OpusDecoderDestroy(decoder);
				decoder = IntPtr.Zero;
				disposedValue = true;
			}
		}

		~Decoder()
		{
			Dispose(disposing: false);
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
	public class Encoder : IDisposable
	{
		private int bitrate;

		private int complexity;

		private OpusSignal signal;

		private IntPtr encoder;

		private NumChannels channels;

		private bool disposedValue;

		public int Bitrate
		{
			get
			{
				return bitrate;
			}
			set
			{
				Library.OpusEncoderSetBitrate(encoder, value);
				bitrate = value;
			}
		}

		public int Complexity
		{
			get
			{
				return complexity;
			}
			set
			{
				Library.OpusEncoderSetComplexity(encoder, value);
				complexity = value;
			}
		}

		public OpusSignal Signal
		{
			get
			{
				return signal;
			}
			set
			{
				Library.OpusEncoderSetSignal(encoder, value);
				signal = value;
			}
		}

		public Encoder(SamplingFrequency samplingFrequency, NumChannels channels, OpusApplication application)
		{
			this.channels = channels;
			encoder = Library.OpusEncoderCreate(samplingFrequency, channels, application, out var error);
			if (error != 0)
			{
				Debug.LogError((object)("[UnityOpus] Failed to init encoder. Error code: " + error));
				encoder = IntPtr.Zero;
			}
		}

		public int Encode(float[] pcm, byte[] output)
		{
			if (encoder == IntPtr.Zero)
			{
				return 0;
			}
			return Library.OpusEncodeFloat(encoder, pcm, pcm.Length / (int)channels, output, output.Length);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!disposedValue && !(encoder == IntPtr.Zero))
			{
				Library.OpusEncoderDestroy(encoder);
				encoder = IntPtr.Zero;
				disposedValue = true;
			}
		}

		~Encoder()
		{
			Dispose(disposing: false);
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
	public enum SamplingFrequency
	{
		Frequency_8000 = 8000,
		Frequency_12000 = 12000,
		Frequency_16000 = 16000,
		Frequency_24000 = 24000,
		Frequency_48000 = 48000
	}
	public enum NumChannels
	{
		Mono = 1,
		Stereo
	}
	public enum OpusApplication
	{
		VoIP = 2048,
		Audio = 2049,
		RestrictedLowDelay = 2051
	}
	public enum OpusSignal
	{
		Auto = -1000,
		Voice = 3001,
		Music = 3002
	}
	public enum ErrorCode
	{
		OK = 0,
		BadArg = -1,
		BufferTooSmall = -2,
		InternalError = -3,
		InvalidPacket = -4,
		Unimplemented = -5,
		InvalidState = -6,
		AllocFail = -7
	}
	public static class Library
	{
		public delegate IntPtr OpusEncoderCreateDelegate(SamplingFrequency samplingFrequency, NumChannels channels, OpusApplication application, out ErrorCode error);

		public delegate int OpusEncodeDelegate(IntPtr encoder, short[] pcm, int frameSize, byte[] data, int maxDataBytes);

		public delegate int OpusEncodeFloatDelegate(IntPtr encoder, float[] pcm, int frameSize, byte[] data, int maxDataBytes);

		public delegate int OpusEncoderDestroyDelegate(IntPtr encoder);

		public delegate int OpusEncoderSetBitrateDelegate(IntPtr encoder, int bitrate);

		public delegate int OpusEncoderSetComplexityDelegate(IntPtr encoder, int complexity);

		public delegate int OpusEncoderSetSignalDelegate(IntPtr encoder, OpusSignal signal);

		public delegate IntPtr OpusDecoderCreateDelegate(SamplingFrequency samplingFrequency, NumChannels channels, out ErrorCode error);

		public delegate int OpusDecodeDelegate(IntPtr decoder, byte[] data, int len, short[] pcm, int frameSize, int decodeFec);

		public delegate int OpusDecodeFloatDelegate(IntPtr decoder, byte[] data, int len, float[] pcm, int frameSize, int decodeFec);

		public delegate void OpusDecoderDestroyDelegate(IntPtr decoder);

		public delegate void OpusPcmSoftClipDelegate(float[] pcm, int frameSize, NumChannels channels, float[] softclipMem);

		public const int maximumPacketDuration = 5760;

		private static IntPtr dllHandle;

		public static readonly OpusEncoderCreateDelegate OpusEncoderCreate;

		public static readonly OpusEncodeDelegate OpusEncode;

		public static OpusEncodeFloatDelegate OpusEncodeFloat;

		public static OpusEncoderDestroyDelegate OpusEncoderDestroy;

		public static OpusEncoderSetBitrateDelegate OpusEncoderSetBitrate;

		public static OpusEncoderSetComplexityDelegate OpusEncoderSetComplexity;

		public static OpusEncoderSetSignalDelegate OpusEncoderSetSignal;

		public static OpusDecoderCreateDelegate OpusDecoderCreate;

		public static OpusDecodeDelegate OpusDecode;

		public static OpusDecodeFloatDelegate OpusDecodeFloat;

		public static OpusDecoderDestroyDelegate OpusDecoderDestroy;

		public static OpusPcmSoftClipDelegate OpusPcmSoftClip;

		static Library()
		{
			dllHandle = LoadLibrary(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName + "\\UnityOpus.dll");
			_ = dllHandle == IntPtr.Zero;
			OpusEncoderCreate = GetFunctionPointer<OpusEncoderCreateDelegate>("OpusEncoderCreate");
			OpusEncode = GetFunctionPointer<OpusEncodeDelegate>("OpusEncode");
			OpusEncodeFloat = GetFunctionPointer<OpusEncodeFloatDelegate>("OpusEncodeFloat");
			OpusEncoderDestroy = GetFunctionPointer<OpusEncoderDestroyDelegate>("OpusEncodeFloat");
			OpusEncoderSetBitrate = GetFunctionPointer<OpusEncoderSetBitrateDelegate>("OpusEncoderSetBitrate");
			OpusEncoderSetComplexity = GetFunctionPointer<OpusEncoderSetComplexityDelegate>("OpusEncoderSetComplexity");
			OpusEncoderSetSignal = GetFunctionPointer<OpusEncoderSetSignalDelegate>("OpusEncoderSetSignal");
			OpusDecoderCreate = GetFunctionPointer<OpusDecoderCreateDelegate>("OpusDecoderCreate");
			OpusDecode = GetFunctionPointer<OpusDecodeDelegate>("OpusDecode");
			OpusDecodeFloat = GetFunctionPointer<OpusDecodeFloatDelegate>("OpusDecodeFloat");
			OpusDecoderDestroy = GetFunctionPointer<OpusDecoderDestroyDelegate>("OpusDecoderDestroy");
			OpusPcmSoftClip = GetFunctionPointer<OpusPcmSoftClipDelegate>("OpusPcmSoftClip");
			AppDomain.CurrentDomain.ProcessExit += ProcessExitHandler;
			AppDomain.CurrentDomain.UnhandledException += ProcessExitHandler;
		}

		private static T GetFunctionPointer<T>(string functionName) where T : Delegate
		{
			return (T)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dllHandle, functionName), typeof(T));
		}

		private static void ProcessExitHandler(object sender, EventArgs e)
		{
			FreeLibrary(dllHandle);
		}

		[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
		internal static extern IntPtr LoadLibrary(string lpFileName);

		[DllImport("kernel32", SetLastError = true)]
		internal static extern bool FreeLibrary(IntPtr hModule);

		[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
		internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
	}
}
namespace UniRx
{
	public static class WebRequestExtensions
	{
		private static IObservable<TResult> AbortableDeferredAsyncRequest<TResult>(Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, WebRequest request)
		{
			return Observable.Create(delegate(IObserver<TResult> observer)
			{
				int isCompleted = -1;
				IDisposable subscription = Observable.FromAsyncPattern(begin, delegate(IAsyncResult ar)
				{
					try
					{
						Interlocked.Increment(ref isCompleted);
						return end(ar);
					}
					catch (WebException ex)
					{
						if (ex.Status != WebExceptionStatus.RequestCanceled)
						{
							throw;
						}
						return default(TResult);
					}
				})().Subscribe(observer);
				return Disposable.Create(delegate
				{
					if (Interlocked.Increment(ref isCompleted) == 0)
					{
						subscription.Dispose();
						request.Abort();
					}
				});
			});
		}

		public static IObservable<WebResponse> GetResponseAsObservable(this WebRequest request)
		{
			return AbortableDeferredAsyncRequest(request.BeginGetResponse, request.EndGetResponse, request);
		}

		public static IObservable<HttpWebResponse> GetResponseAsObservable(this HttpWebRequest request)
		{
			return AbortableDeferredAsyncRequest(request.BeginGetResponse, (IAsyncResult ar) => (HttpWebResponse)request.EndGetResponse(ar), request);
		}

		public static IObservable<Stream> GetRequestStreamAsObservable(this WebRequest request)
		{
			return AbortableDeferredAsyncRequest(request.BeginGetRequestStream, request.EndGetRequestStream, request);
		}
	}
	public sealed class BooleanDisposable : IDisposable, ICancelable
	{
		public bool IsDisposed { get; private set; }

		public BooleanDisposable()
		{
		}

		internal BooleanDisposable(bool isDisposed)
		{
			IsDisposed = isDisposed;
		}

		public void Dispose()
		{
			if (!IsDisposed)
			{
				IsDisposed = true;
			}
		}
	}
	public sealed class CompositeDisposable : ICollection<IDisposable>, IEnumerable<IDisposable>, IEnumerable, IDisposable, ICancelable
	{
		private readonly object _gate = new object();

		private bool _disposed;

		private List<IDisposable> _disposables;

		private int _count;

		private const int SHRINK_THRESHOLD = 64;

		public int Count => _count;

		public bool IsReadOnly => false;

		public bool IsDisposed => _disposed;

		public CompositeDisposable()
		{
			_disposables = new List<IDisposable>();
		}

		public CompositeDisposable(int capacity)
		{
			if (capacity < 0)
			{
				throw new ArgumentOutOfRangeException("capacity");
			}
			_disposables = new List<IDisposable>(capacity);
		}

		public CompositeDisposable(params IDisposable[] disposables)
		{
			if (disposables == null)
			{
				throw new ArgumentNullException("disposables");
			}
			_disposables = new List<IDisposable>(disposables);
			_count = _disposables.Count;
		}

		public CompositeDisposable(IEnumerable<IDisposable> disposables)
		{
			if (disposables == null)
			{
				throw new ArgumentNullException("disposables");
			}
			_disposables = new List<IDisposable>(disposables);
			_count = _disposables.Count;
		}

		public void Add(IDisposable item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			bool flag = false;
			lock (_gate)
			{
				flag = _disposed;
				if (!_disposed)
				{
					_disposables.Add(item);
					_count++;
				}
			}
			if (flag)
			{
				item.Dispose();
			}
		}

		public bool Remove(IDisposable item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			bool flag = false;
			lock (_gate)
			{
				if (!_disposed)
				{
					int num = _disposables.IndexOf(item);
					if (num >= 0)
					{
						flag = true;
						_disposables[num] = null;
						_count--;
						if (_disposables.Capacity > 64 && _count < _disposables.Capacity / 2)
						{
							List<IDisposable> disposables = _disposables;
							_disposables = new List<IDisposable>(_disposables.Capacity / 2);
							foreach (IDisposable item2 in disposables)
							{
								if (item2 != null)
								{
									_disposables.Add(item2);
								}
							}
						}
					}
				}
			}
			if (flag)
			{
				item.Dispose();
			}
			return flag;
		}

		public void Dispose()
		{
			IDisposable[] array = null;
			lock (_gate)
			{
				if (!_disposed)
				{
					_disposed = true;
					array = _disposables.ToArray();
					_disposables.Clear();
					_count = 0;
				}
			}
			if (array != null)
			{
				IDisposable[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					array2[i]?.Dispose();
				}
			}
		}

		public void Clear()
		{
			IDisposable[] array = null;
			lock (_gate)
			{
				array = _disposables.ToArray();
				_disposables.Clear();
				_count = 0;
			}
			IDisposable[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i]?.Dispose();
			}
		}

		public bool Contains(IDisposable item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			lock (_gate)
			{
				return _disposables.Contains(item);
			}
		}

		public void CopyTo(IDisposable[] array, int arrayIndex)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (arrayIndex < 0 || arrayIndex >= array.Length)
			{
				throw new ArgumentOutOfRangeException("arrayIndex");
			}
			lock (_gate)
			{
				List<IDisposable> list = new List<IDisposable>();
				foreach (IDisposable item in list)
				{
					if (item != null)
					{
						list.Add(item);
					}
				}
				Array.Copy(list.ToArray(), 0, array, arrayIndex, array.Length - arrayIndex);
			}
		}

		public IEnumerator<IDisposable> GetEnumerator()
		{
			List<IDisposable> list = new List<IDisposable>();
			lock (_gate)
			{
				foreach (IDisposable disposable in _disposables)
				{
					if (disposable != null)
					{
						list.Add(disposable);
					}
				}
			}
			return list.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public sealed class DictionaryDisposable<TKey, TValue> : IDisposable, IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable where TValue : IDisposable
	{
		private bool isDisposed;

		private readonly Dictionary<TKey, TValue> inner;

		public TValue this[TKey key]
		{
			get
			{
				lock (inner)
				{
					return inner[key];
				}
			}
			set
			{
				lock (inner)
				{
					if (isDisposed)
					{
						value.Dispose();
					}
					if (TryGetValue(key, out var value2))
					{
						value2.Dispose();
						inner[key] = value;
					}
					else
					{
						inner[key] = value;
					}
				}
			}
		}

		public int Count
		{
			get
			{
				lock (inner)
				{
					return inner.Count;
				}
			}
		}

		public Dictionary<TKey, TValue>.KeyCollection Keys
		{
			get
			{
				throw new NotSupportedException("please use .Select(x => x.Key).ToArray()");
			}
		}

		public Dictionary<TKey, TValue>.ValueCollection Values
		{
			get
			{
				throw new NotSupportedException("please use .Select(x => x.Value).ToArray()");
			}
		}

		bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)inner).IsReadOnly;

		ICollection<TKey> IDictionary<TKey, TValue>.Keys
		{
			get
			{
				lock (inner)
				{
					return new List<TKey>(inner.Keys);
				}
			}
		}

		ICollection<TValue> IDictionary<TKey, TValue>.Values
		{
			get
			{
				lock (inner)
				{
					return new List<TValue>(inner.Values);
				}
			}
		}

		public DictionaryDisposable()
		{
			inner = new Dictionary<TKey, TValue>();
		}

		public DictionaryDisposable(IEqualityComparer<TKey> comparer)
		{
			inner = new Dictionary<TKey, TValue>(comparer);
		}

		public void Add(TKey key, TValue value)
		{
			lock (inner)
			{
				if (isDisposed)
				{
					value.Dispose();
				}
				else
				{
					inner.Add(key, value);
				}
			}
		}

		public void Clear()
		{
			lock (inner)
			{
				foreach (KeyValuePair<TKey, TValue> item in inner)
				{
					item.Value.Dispose();
				}
				inner.Clear();
			}
		}

		public bool Remove(TKey key)
		{
			lock (inner)
			{
				if (inner.TryGetValue(key, out var value))
				{
					bool num = inner.Remove(key);
					if (num)
					{
						value.Dispose();
					}
					return num;
				}
				return false;
			}
		}

		public bool ContainsKey(TKey key)
		{
			lock (inner)
			{
				return inner.ContainsKey(key);
			}
		}

		public bool TryGetValue(TKey key, out TValue value)
		{
			lock (inner)
			{
				return inner.TryGetValue(key, out value);
			}
		}

		public Dictionary<TKey, TValue>.Enumerator GetEnumerator()
		{
			lock (inner)
			{
				return new Dictionary<TKey, TValue>(inner).GetEnumerator();
			}
		}

		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			lock (inner)
			{
				((ISerializable)inner).GetObjectData(info, context);
			}
		}

		public void OnDeserialization(object sender)
		{
			lock (inner)
			{
				((IDeserializationCallback)inner).OnDeserialization(sender);
			}
		}

		void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
		{
			Add(item.Key, item.Value);
		}

		bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
		{
			lock (inner)
			{
				return ((ICollection<KeyValuePair<TKey, TValue>>)inner).Contains(item);
			}
		}

		void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
		{
			lock (inner)
			{
				((ICollection<KeyValuePair<TKey, TValue>>)inner).CopyTo(array, arrayIndex);
			}
		}

		IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
		{
			lock (inner)
			{
				return new List<KeyValuePair<TKey, TValue>>(inner).GetEnumerator();
			}
		}

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

		bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
		{
			throw new NotSupportedException();
		}

		public void Dispose()
		{
			lock (inner)
			{
				if (isDisposed)
				{
					return;
				}
				isDisposed = true;
				foreach (KeyValuePair<TKey, TValue> item in inner)
				{
					item.Value.Dispose();
				}
				inner.Clear();
			}
		}
	}
	public static class Disposable
	{
		private class EmptyDisposable : IDisposable
		{
			public static EmptyDisposable Singleton = new EmptyDisposable();

			private EmptyDisposable()
			{
			}

			public void Dispose()
			{
			}
		}

		private class AnonymousDisposable : IDisposable
		{
			private bool isDisposed;

			private readonly Action dispose;

			public AnonymousDisposable(Action dispose)
			{
				this.dispose = dispose;
			}

			public void Dispose()
			{
				if (!isDisposed)
				{
					isDisposed = true;
					dispose();
				}
			}
		}

		private class AnonymousDisposable<T> : IDisposable
		{
			private bool isDisposed;

			private readonly T state;

			private readonly Action<T> dispose;

			public AnonymousDisposable(T state, Action<T> dispose)
			{
				this.state = state;
				this.dispose = dispose;
			}

			public void Dispose()
			{
				if (!isDisposed)
				{
					isDisposed = true;
					dispose(state);
				}
			}
		}

		public static readonly IDisposable Empty = EmptyDisposable.Singleton;

		public static IDisposable Create(Action disposeAction)
		{
			return new AnonymousDisposable(disposeAction);
		}

		public static IDisposable CreateWithState<TState>(TState state, Action<TState> disposeAction)
		{
			return new AnonymousDisposable<TState>(state, disposeAction);
		}
	}
	public static class DisposableExtensions
	{
		public static T AddTo<T>(this T disposable, ICollection<IDisposable> container) where T : IDisposable
		{
			if (disposable == null)
			{
				throw new ArgumentNullException("disposable");
			}
			if (container == null)
			{
				throw new ArgumentNullException("container");
			}
			container.Add(disposable);
			return disposable;
		}

		public static T AddTo<T>(this T disposable, GameObject gameObject) where T : IDisposable
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				disposable.Dispose();
				return disposable;
			}
			ObservableDestroyTrigger observableDestroyTrigger = gameObject.GetComponent<ObservableDestroyTrigger>();
			if ((Object)(object)observableDestroyTrigger == (Object)null)
			{
				observableDestroyTrigger = gameObject.AddComponent<ObservableDestroyTrigger>();
			}
			if (!observableDestroyTrigger.IsActivated && !observableDestroyTrigger.IsMonitoredActivate && !((Component)observableDestroyTrigger).gameObject.activeInHierarchy)
			{
				observableDestroyTrigger.IsMonitoredActivate = true;
				MainThreadDispatcher.StartEndOfFrameMicroCoroutine(MonitorTriggerHealth(observableDestroyTrigger, gameObject));
			}
			observableDestroyTrigger.AddDisposableOnDestroy(disposable);
			return disposable;
		}

		private static IEnumerator MonitorTriggerHealth(ObservableDestroyTrigger trigger, GameObject targetGameObject)
		{
			do
			{
				yield return null;
				if (trigger.IsActivated)
				{
					yield break;
				}
			}
			while (!((Object)(object)targetGameObject == (Object)null));
			trigger.ForceRaiseOnDestroy();
		}

		public static T AddTo<T>(this T disposable, Component gameObjectComponent) where T : IDisposable
		{
			if ((Object)(object)gameObjectComponent == (Object)null)
			{
				disposable.Dispose();
				return disposable;
			}
			return disposable.AddTo(gameObjectComponent.gameObject);
		}

		public static T AddTo<T>(this T disposable, ICollection<IDisposable> container, GameObject gameObject) where T : IDisposable
		{
			return disposable.AddTo(container).AddTo(gameObject);
		}

		public static T AddTo<T>(this T disposable, ICollection<IDisposable> container, Component gameObjectComponent) where T : IDisposable
		{
			return disposable.AddTo(container).AddTo(gameObjectComponent);
		}
	}
	public interface ICancelable : IDisposable
	{
		bool IsDisposed { get; }
	}
	public sealed class MultipleAssignmentDisposable : IDisposable, ICancelable
	{
		private static readonly BooleanDisposable True = new BooleanDisposable(isDisposed: true);

		private object gate = new object();

		private IDisposable current;

		public bool IsDisposed
		{
			get
			{
				lock (gate)
				{
					return current == True;
				}
			}
		}

		public IDisposable Disposable
		{
			get
			{
				lock (gate)
				{
					return (current == True) ? UniRx.Disposable.Empty : current;
				}
			}
			set
			{
				bool flag = false;
				lock (gate)
				{
					flag = current == True;
					if (!flag)
					{
						current = value;
					}
				}
				if (flag)
				{
					value?.Dispose();
				}
			}
		}

		public void Dispose()
		{
			IDisposable disposable = null;
			lock (gate)
			{
				if (current != True)
				{
					disposable = current;
					current = True;
				}
			}
			disposable?.Dispose();
		}
	}
	public sealed class RefCountDisposable : ICancelable, IDisposable
	{
		private sealed class InnerDisposable : IDisposable
		{
			private RefCountDisposable _parent;

			private object parentLock = new object();

			public InnerDisposable(RefCountDisposable parent)
			{
				_parent = parent;
			}

			public void Dispose()
			{
				RefCountDisposable parent;
				lock (parentLock)
				{
					parent = _parent;
					_parent = null;
				}
				parent?.Release();
			}
		}

		private readonly object _gate = new object();

		private IDisposable _disposable;

		private bool _isPrimaryDisposed;

		private int _count;

		public bool IsDisposed => _disposable == null;

		public RefCountDisposable(IDisposable disposable)
		{
			if (disposable == null)
			{
				throw new ArgumentNullException("disposable");
			}
			_disposable = disposable;
			_isPrimaryDisposed = false;
			_count = 0;
		}

		public IDisposable GetDisposable()
		{
			lock (_gate)
			{
				if (_disposable == null)
				{
					return Disposable.Empty;
				}
				_count++;
				return new InnerDisposable(this);
			}
		}

		public void Dispose()
		{
			IDisposable disposable = null;
			lock (_gate)
			{
				if (_disposable != null && !_isPrimaryDisposed)
				{
					_isPrimaryDisposed = true;
					if (_count == 0)
					{
						disposable = _disposable;
						_disposable = null;
					}
				}
			}
			disposable?.Dispose();
		}

		private void Release()
		{
			IDisposable disposable = null;
			lock (_gate)
			{
				if (_disposable != null)
				{
					_count--;
					if (_isPrimaryDisposed && _count == 0)
					{
						disposable = _disposable;
						_disposable = null;
					}
				}
			}
			disposable?.Dispose();
		}
	}
	public static class Observable
	{
		private class ConnectableObservable<T> : IConnectableObservable<T>, IObservable<T>
		{
			private class Connection : IDisposable
			{
				private readonly ConnectableObservable<T> parent;

				private IDisposable subscription;

				public Connection(ConnectableObservable<T> parent, IDisposable subscription)
				{
					this.parent = parent;
					this.subscription = subscription;
				}

				public void Dispose()
				{
					lock (parent.gate)
					{
						if (subscription != null)
						{
							subscription.Dispose();
							subscription = null;
							parent.connection = null;
						}
					}
				}
			}

			private readonly IObservable<T> source;

			private readonly ISubject<T> subject;

			private readonly object gate = new object();

			private Connection connection;

			public ConnectableObservable(IObservable<T> source, ISubject<T> subject)
			{
				this.source = source.AsObservable();
				this.subject = subject;
			}

			public IDisposable Connect()
			{
				lock (gate)
				{
					if (connection == null)
					{
						IDisposable subscription = source.Subscribe(subject);
						connection = new Connection(this, subscription);
					}
					return connection;
				}
			}

			public IDisposable Subscribe(IObserver<T> observer)
			{
				return subject.Subscribe(observer);
			}
		}

		private class EveryAfterUpdateInvoker : IEnumerator
		{
			private long count = -1L;

			private readonly IObserver<long> observer;

			private readonly CancellationToken cancellationToken;

			public object Current => null;

			public EveryAfterUpdateInvoker(IObserver<long> observer, CancellationToken cancellationToken)
			{
				this.observer = observer;
				this.cancellationToken = cancellationToken;
			}

			public bool MoveNext()
			{
				if (!cancellationToken.IsCancellationRequested)
				{
					if (count != -1)
					{
						observer.OnNext(count++);
					}
					else
					{
						count++;
					}
					return true;
				}
				return false;
			}

			public void Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, -1);

		private static readonly HashSet<Type> YieldInstructionTypes = new HashSet<Type>
		{
			typeof(WWW),
			typeof(WaitForEndOfFrame),
			typeof(WaitForFixedUpdate),
			typeof(WaitForSeconds),
			typeof(AsyncOperation),
			typeof(Coroutine)
		};

		private static IObservable<T> AddRef<T>(IObservable<T> xs, RefCountDisposable r)
		{
			return Create((IObserver<T> observer) => new CompositeDisposable(r.GetDisposable(), xs.Subscribe(observer)));
		}

		public static IObservable<TSource> Scan<TSource>(this IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
		{
			return new ScanObservable<TSource>(source, accumulator);
		}

		public static IObservable<TAccumulate> Scan<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
		{
			return new ScanObservable<TSource, TAccumulate>(source, seed, accumulator);
		}

		public static IObservable<TSource> Aggregate<TSource>(this IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
		{
			return new AggregateObservable<TSource>(source, accumulator);
		}

		public static IObservable<TAccumulate> Aggregate<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
		{
			return new AggregateObservable<TSource, TAccumulate>(source, seed, accumulator);
		}

		public static IObservable<TResult> Aggregate<TSource, TAccumulate, TResult>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
		{
			return new AggregateObservable<TSource, TAccumulate, TResult>(source, seed, accumulator, resultSelector);
		}

		public static IConnectableObservable<T> Multicast<T>(this IObservable<T> source, ISubject<T> subject)
		{
			return new ConnectableObservable<T>(source, subject);
		}

		public static IConnectableObservable<T> Publish<T>(this IObservable<T> source)
		{
			return source.Multicast(new Subject<T>());
		}

		public static IConnectableObservable<T> Publish<T>(this IObservable<T> source, T initialValue)
		{
			return source.Multicast(new BehaviorSubject<T>(initialValue));
		}

		public static IConnectableObservable<T> PublishLast<T>(this IObservable<T> source)
		{
			return source.Multicast(new AsyncSubject<T>());
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source)
		{
			return source.Multicast(new ReplaySubject<T>());
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, IScheduler scheduler)
		{
			return source.Multicast(new ReplaySubject<T>(scheduler));
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, int bufferSize)
		{
			return source.Multicast(new ReplaySubject<T>(bufferSize));
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, int bufferSize, IScheduler scheduler)
		{
			return source.Multicast(new ReplaySubject<T>(bufferSize, scheduler));
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, TimeSpan window)
		{
			return source.Multicast(new ReplaySubject<T>(window));
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, TimeSpan window, IScheduler scheduler)
		{
			return source.Multicast(new ReplaySubject<T>(window, scheduler));
		}

		public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, int bufferSize, TimeSpan window, IScheduler scheduler)
		{
			return source.Multicast(new ReplaySubject<T>(bufferSize, window, scheduler));
		}

		public static IObservable<T> RefCount<T>(this IConnectableObservable<T> source)
		{
			return new RefCountObservable<T>(source);
		}

		public static IObservable<T> Share<T>(this IObservable<T> source)
		{
			return source.Publish().RefCount();
		}

		public static T Wait<T>(this IObservable<T> source)
		{
			return new Wait<T>(source, InfiniteTimeSpan).Run();
		}

		public static T Wait<T>(this IObservable<T> source, TimeSpan timeout)
		{
			return new Wait<T>(source, timeout).Run();
		}

		private static IEnumerable<IObservable<T>> CombineSources<T>(IObservable<T> first, IObservable<T>[] seconds)
		{
			yield return first;
			for (int i = 0; i < seconds.Length; i++)
			{
				yield return seconds[i];
			}
		}

		public static IObservable<TSource> Concat<TSource>(params IObservable<TSource>[] sources)
		{
			if (sources == null)
			{
				throw new ArgumentNullException("sources");
			}
			return new ConcatObservable<TSource>(sources);
		}

		public static IObservable<TSource> Concat<TSource>(this IEnumerable<IObservable<TSource>> sources)
		{
			if (sources == null)
			{
				throw new ArgumentNullException("sources");
			}
			return new ConcatObservable<TSource>(sources);
		}

		public static IObservable<TSource> Concat<TSource>(this IObservable<IObservable<TSource>> sources)
		{
			return sources.Merge(1);
		}

		public static IObservable<TSource> Concat<TSource>(this IObservable<TSource> first, params IObservable<TSource>[] seconds)
		{
			if (first == null)
			{
				throw new ArgumentNullException("first");
			}
			if (seconds == null)
			{
				throw new ArgumentNullException("seconds");
			}
			if (first is ConcatObservable<TSource> concatObservable)
			{
				return concatObservable.Combine(seconds);
			}
			return CombineSources(first, seconds).Concat();
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources)
		{
			return sources.Merge(Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, IScheduler scheduler)
		{
			return new MergeObservable<TSource>(sources.ToObservable(scheduler), scheduler == Scheduler.CurrentThread);
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent)
		{
			return sources.Merge(maxConcurrent, Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent, IScheduler scheduler)
		{
			return new MergeObservable<TSource>(sources.ToObservable(scheduler), maxConcurrent, scheduler == Scheduler.CurrentThread);
		}

		public static IObservable<TSource> Merge<TSource>(params IObservable<TSource>[] sources)
		{
			return Merge(Scheduler.DefaultSchedulers.ConstantTimeOperations, sources);
		}

		public static IObservable<TSource> Merge<TSource>(IScheduler scheduler, params IObservable<TSource>[] sources)
		{
			return new MergeObservable<TSource>(sources.ToObservable(scheduler), scheduler == Scheduler.CurrentThread);
		}

		public static IObservable<T> Merge<T>(this IObservable<T> first, params IObservable<T>[] seconds)
		{
			return CombineSources(first, seconds).Merge();
		}

		public static IObservable<T> Merge<T>(this IObservable<T> first, IObservable<T> second, IScheduler scheduler)
		{
			return Merge<T>(scheduler, first, second);
		}

		public static IObservable<T> Merge<T>(this IObservable<IObservable<T>> sources)
		{
			return new MergeObservable<T>(sources, isRequiredSubscribeOnCurrentThread: false);
		}

		public static IObservable<T> Merge<T>(this IObservable<IObservable<T>> sources, int maxConcurrent)
		{
			return new MergeObservable<T>(sources, maxConcurrent, isRequiredSubscribeOnCurrentThread: false);
		}

		public static IObservable<TResult> Zip<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector)
		{
			return new ZipObservable<TLeft, TRight, TResult>(left, right, selector);
		}

		public static IObservable<IList<T>> Zip<T>(this IEnumerable<IObservable<T>> sources)
		{
			return Zip(sources.ToArray());
		}

		public static IObservable<IList<T>> Zip<T>(params IObservable<T>[] sources)
		{
			return new ZipObservable<T>(sources);
		}

		public static IObservable<TR> Zip<T1, T2, T3, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, ZipFunc<T1, T2, T3, TR> resultSelector)
		{
			return new ZipObservable<T1, T2, T3, TR>(source1, source2, source3, resultSelector);
		}

		public static IObservable<TR> Zip<T1, T2, T3, T4, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, ZipFunc<T1, T2, T3, T4, TR> resultSelector)
		{
			return new ZipObservable<T1, T2, T3, T4, TR>(source1, source2, source3, source4, resultSelector);
		}

		public static IObservable<TR> Zip<T1, T2, T3, T4, T5, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, ZipFunc<T1, T2, T3, T4, T5, TR> resultSelector)
		{
			return new ZipObservable<T1, T2, T3, T4, T5, TR>(source1, source2, source3, source4, source5, resultSelector);
		}

		public static IObservable<TR> Zip<T1, T2, T3, T4, T5, T6, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, ZipFunc<T1, T2, T3, T4, T5, T6, TR> resultSelector)
		{
			return new ZipObservable<T1, T2, T3, T4, T5, T6, TR>(source1, source2, source3, source4, source5, source6, resultSelector);
		}

		public static IObservable<TR> Zip<T1, T2, T3, T4, T5, T6, T7, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, ZipFunc<T1, T2, T3, T4, T5, T6, T7, TR> resultSelector)
		{
			return new ZipObservable<T1, T2, T3, T4, T5, T6, T7, TR>(source1, source2, source3, source4, source5, source6, source7, resultSelector);
		}

		public static IObservable<TResult> CombineLatest<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector)
		{
			return new CombineLatestObservable<TLeft, TRight, TResult>(left, right, selector);
		}

		public static IObservable<IList<T>> CombineLatest<T>(this IEnumerable<IObservable<T>> sources)
		{
			return CombineLatest(sources.ToArray());
		}

		public static IObservable<IList<TSource>> CombineLatest<TSource>(params IObservable<TSource>[] sources)
		{
			return new CombineLatestObservable<TSource>(sources);
		}

		public static IObservable<TR> CombineLatest<T1, T2, T3, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, CombineLatestFunc<T1, T2, T3, TR> resultSelector)
		{
			return new CombineLatestObservable<T1, T2, T3, TR>(source1, source2, source3, resultSelector);
		}

		public static IObservable<TR> CombineLatest<T1, T2, T3, T4, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, CombineLatestFunc<T1, T2, T3, T4, TR> resultSelector)
		{
			return new CombineLatestObservable<T1, T2, T3, T4, TR>(source1, source2, source3, source4, resultSelector);
		}

		public static IObservable<TR> CombineLatest<T1, T2, T3, T4, T5, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, CombineLatestFunc<T1, T2, T3, T4, T5, TR> resultSelector)
		{
			return new CombineLatestObservable<T1, T2, T3, T4, T5, TR>(source1, source2, source3, source4, source5, resultSelector);
		}

		public static IObservable<TR> CombineLatest<T1, T2, T3, T4, T5, T6, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, CombineLatestFunc<T1, T2, T3, T4, T5, T6, TR> resultSelector)
		{
			return new CombineLatestObservable<T1, T2, T3, T4, T5, T6, TR>(source1, source2, source3, source4, source5, source6, resultSelector);
		}

		public static IObservable<TR> CombineLatest<T1, T2, T3, T4, T5, T6, T7, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, CombineLatestFunc<T1, T2, T3, T4, T5, T6, T7, TR> resultSelector)
		{
			return new CombineLatestObservable<T1, T2, T3, T4, T5, T6, T7, TR>(source1, source2, source3, source4, source5, source6, source7, resultSelector);
		}

		public static IObservable<TResult> ZipLatest<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector)
		{
			return new ZipLatestObservable<TLeft, TRight, TResult>(left, right, selector);
		}

		public static IObservable<IList<T>> ZipLatest<T>(this IEnumerable<IObservable<T>> sources)
		{
			return ZipLatest(sources.ToArray());
		}

		public static IObservable<IList<TSource>> ZipLatest<TSource>(params IObservable<TSource>[] sources)
		{
			return new ZipLatestObservable<TSource>(sources);
		}

		public static IObservable<TR> ZipLatest<T1, T2, T3, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, ZipLatestFunc<T1, T2, T3, TR> resultSelector)
		{
			return new ZipLatestObservable<T1, T2, T3, TR>(source1, source2, source3, resultSelector);
		}

		public static IObservable<TR> ZipLatest<T1, T2, T3, T4, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, ZipLatestFunc<T1, T2, T3, T4, TR> resultSelector)
		{
			return new ZipLatestObservable<T1, T2, T3, T4, TR>(source1, source2, source3, source4, resultSelector);
		}

		public static IObservable<TR> ZipLatest<T1, T2, T3, T4, T5, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, ZipLatestFunc<T1, T2, T3, T4, T5, TR> resultSelector)
		{
			return new ZipLatestObservable<T1, T2, T3, T4, T5, TR>(source1, source2, source3, source4, source5, resultSelector);
		}

		public static IObservable<TR> ZipLatest<T1, T2, T3, T4, T5, T6, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, ZipLatestFunc<T1, T2, T3, T4, T5, T6, TR> resultSelector)
		{
			return new ZipLatestObservable<T1, T2, T3, T4, T5, T6, TR>(source1, source2, source3, source4, source5, source6, resultSelector);
		}

		public static IObservable<TR> ZipLatest<T1, T2, T3, T4, T5, T6, T7, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, ZipLatestFunc<T1, T2, T3, T4, T5, T6, T7, TR> resultSelector)
		{
			return new ZipLatestObservable<T1, T2, T3, T4, T5, T6, T7, TR>(source1, source2, source3, source4, source5, source6, source7, resultSelector);
		}

		public static IObservable<T> Switch<T>(this IObservable<IObservable<T>> sources)
		{
			return new SwitchObservable<T>(sources);
		}

		public static IObservable<TResult> WithLatestFrom<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector)
		{
			return new WithLatestFromObservable<TLeft, TRight, TResult>(left, right, selector);
		}

		public static IObservable<T[]> WhenAll<T>(params IObservable<T>[] sources)
		{
			if (sources.Length == 0)
			{
				return Return(new T[0]);
			}
			return new WhenAllObservable<T>(sources);
		}

		public static IObservable<Unit> WhenAll(params IObservable<Unit>[] sources)
		{
			if (sources.Length == 0)
			{
				return ReturnUnit();
			}
			return new WhenAllObservable(sources);
		}

		public static IObservable<T[]> WhenAll<T>(this IEnumerable<IObservable<T>> sources)
		{
			if (sources is IObservable<T>[] sources2)
			{
				return WhenAll(sources2);
			}
			return new WhenAllObservable<T>(sources);
		}

		public static IObservable<Unit> WhenAll(this IEnumerable<IObservable<Unit>> sources)
		{
			if (sources is IObservable<Unit>[] sources2)
			{
				return WhenAll(sources2);
			}
			return new WhenAllObservable(sources);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, T value)
		{
			return new StartWithObservable<T>(source, value);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, Func<T> valueFactory)
		{
			return new StartWithObservable<T>(source, valueFactory);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, params T[] values)
		{
			return source.StartWith(Scheduler.DefaultSchedulers.ConstantTimeOperations, values);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, IEnumerable<T> values)
		{
			return source.StartWith(Scheduler.DefaultSchedulers.ConstantTimeOperations, values);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, IScheduler scheduler, T value)
		{
			return Return(value, scheduler).Concat(source);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, IScheduler scheduler, IEnumerable<T> values)
		{
			T[] array = values as T[];
			if (array == null)
			{
				array = values.ToArray();
			}
			return source.StartWith(scheduler, array);
		}

		public static IObservable<T> StartWith<T>(this IObservable<T> source, IScheduler scheduler, params T[] values)
		{
			return values.ToObservable(scheduler).Concat(source);
		}

		public static IObservable<T> Synchronize<T>(this IObservable<T> source)
		{
			return new SynchronizeObservable<T>(source, new object());
		}

		public static IObservable<T> Synchronize<T>(this IObservable<T> source, object gate)
		{
			return new SynchronizeObservable<T>(source, gate);
		}

		public static IObservable<T> ObserveOn<T>(this IObservable<T> source, IScheduler scheduler)
		{
			return new ObserveOnObservable<T>(source, scheduler);
		}

		public static IObservable<T> SubscribeOn<T>(this IObservable<T> source, IScheduler scheduler)
		{
			return new SubscribeOnObservable<T>(source, scheduler);
		}

		public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, TimeSpan dueTime)
		{
			return new DelaySubscriptionObservable<T>(source, dueTime, Scheduler.DefaultSchedulers.TimeBasedOperations);
		}

		public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, TimeSpan dueTime, IScheduler scheduler)
		{
			return new DelaySubscriptionObservable<T>(source, dueTime, scheduler);
		}

		public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, DateTimeOffset dueTime)
		{
			return new DelaySubscriptionObservable<T>(source, dueTime, Scheduler.DefaultSchedulers.TimeBasedOperations);
		}

		public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, DateTimeOffset dueTime, IScheduler scheduler)
		{
			return new DelaySubscriptionObservable<T>(source, dueTime, scheduler);
		}

		public static IObservable<T> Amb<T>(params IObservable<T>[] sources)
		{
			return Amb((IEnumerable<IObservable<T>>)sources);
		}

		public static IObservable<T> Amb<T>(IEnumerable<IObservable<T>> sources)
		{
			IObservable<T> observable = Never<T>();
			foreach (IObservable<T> source in sources)
			{
				observable = observable.Amb(source);
			}
			return observable;
		}

		public static IObservable<T> Amb<T>(this IObservable<T> source, IObservable<T> second)
		{
			return new AmbObservable<T>(source, second);
		}

		public static IObservable<T> AsObservable<T>(this IObservable<T> source)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (source is AsObservableObservable<T>)
			{
				return source;
			}
			return new AsObservableObservable<T>(source);
		}

		public static IObservable<T> ToObservable<T>(this IEnumerable<T> source)
		{
			return source.ToObservable(Scheduler.DefaultSchedulers.Iteration);
		}

		public static IObservable<T> ToObservable<T>(this IEnumerable<T> source, IScheduler scheduler)
		{
			return new ToObservableObservable<T>(source, scheduler);
		}

		public static IObservable<TResult> Cast<TSource, TResult>(this IObservable<TSource> source)
		{
			return new CastObservable<TSource, TResult>(source);
		}

		public static IObservable<TResult> Cast<TSource, TResult>(this IObservable<TSource> source, TResult witness)
		{
			return new CastObservable<TSource, TResult>(source);
		}

		public static IObservable<TResult> OfType<TSource, TResult>(this IObservable<TSource> source)
		{
			return new OfTypeObservable<TSource, TResult>(source);
		}

		public static IObservable<TResult> OfType<TSource, TResult>(this IObservable<TSource> source, TResult witness)
		{
			return new OfTypeObservable<TSource, TResult>(source);
		}

		public static IObservable<Unit> AsUnitObservable<T>(this IObservable<T> source)
		{
			return new AsUnitObservableObservable<T>(source);
		}

		public static IObservable<Unit> AsSingleUnitObservable<T>(this IObservable<T> source)
		{
			return new AsSingleUnitObservableObservable<T>(source);
		}

		public static IObservable<T> Create<T>(Func<IObserver<T>, IDisposable> subscribe)
		{
			if (subscribe == null)
			{
				throw new ArgumentNullException("subscribe");
			}
			return new CreateObservable<T>(subscribe);
		}

		public static IObservable<T> Create<T>(Func<IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread)
		{
			if (subscribe == null)
			{
				throw new ArgumentNullException("subscribe");
			}
			return new CreateObservable<T>(subscribe, isRequiredSubscribeOnCurrentThread);
		}

		public static IObservable<T> CreateWithState<T, TState>(TState state, Func<TState, IObserver<T>, IDisposable> subscribe)
		{
			if (subscribe == null)
			{
				throw new ArgumentNullException("subscribe");
			}
			return new CreateObservable<T, TState>(state, subscribe);
		}

		public static IObservable<T> CreateWithState<T, TState>(TState state, Func<TState, IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread)
		{
			if (subscribe == null)
			{
				throw new ArgumentNullException("subscribe");
			}
			return new CreateObservable<T, TState>(state, subscribe, isRequiredSubscribeOnCurrentThread);
		}

		public static IObservable<T> CreateSafe<T>(Func<IObserver<T>, IDisposable> subscribe)
		{
			if (subscribe == null)
			{
				throw new ArgumentNullException("subscribe");
			}
			return new CreateSafeObservable<T>(subscribe);
		}

		public static IObservable<T> CreateSafe<T>(Func<IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread)
		{
			if (subscribe == null)
			{
				throw new ArgumentNullException("subscribe");
			}
			return new CreateSafeObservable<T>(subscribe, isRequiredSubscribeOnCurrentThread);
		}

		public static IObservable<T> Empty<T>()
		{
			return Empty<T>(Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<T> Empty<T>(IScheduler scheduler)
		{
			if (scheduler == Scheduler.Immediate)
			{
				return ImmutableEmptyObservable<T>.Instance;
			}
			return new EmptyObservable<T>(scheduler);
		}

		public static IObservable<T> Empty<T>(T witness)
		{
			return Empty<T>(Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<T> Empty<T>(IScheduler scheduler, T witness)
		{
			return Empty<T>(scheduler);
		}

		public static IObservable<T> Never<T>()
		{
			return ImmutableNeverObservable<T>.Instance;
		}

		public static IObservable<T> Never<T>(T witness)
		{
			return ImmutableNeverObservable<T>.Instance;
		}

		public static IObservable<T> Return<T>(T value)
		{
			return Return(value, Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<T> Return<T>(T value, IScheduler scheduler)
		{
			if (scheduler == Scheduler.Immediate)
			{
				return new ImmediateReturnObservable<T>(value);
			}
			return new ReturnObservable<T>(value, scheduler);
		}

		public static IObservable<Unit> Return(Unit value)
		{
			return ImmutableReturnUnitObservable.Instance;
		}

		public static IObservable<bool> Return(bool value)
		{
			if (!value)
			{
				return ImmutableReturnFalseObservable.Instance;
			}
			return ImmutableReturnTrueObservable.Instance;
		}

		public static IObservable<Unit> ReturnUnit()
		{
			return ImmutableReturnUnitObservable.Instance;
		}

		public static IObservable<T> Throw<T>(Exception error)
		{
			return Throw<T>(error, Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<T> Throw<T>(Exception error, T witness)
		{
			return Throw<T>(error, Scheduler.DefaultSchedulers.ConstantTimeOperations);
		}

		public static IObservable<T> Throw<T>(Exception error, IScheduler scheduler)
		{
			return new ThrowObservable<T>(error, scheduler);
		}

		public static IObservable<T> Throw<T>(Exception error, IScheduler scheduler, T witness)
		{
			return Throw<T>(error, scheduler);
		}

		public static IObservable<int> Range(int start, int count)
		{
			return Range(start, count, Scheduler.DefaultSchedulers.Iteration);
		}

		public static IObservable<int> Range(int start, int count, IScheduler scheduler)
		{
			return new RangeObservable(start, count, scheduler);
		}

		public static IObservable<T> Repeat<T>(T value)
		{
			return Repeat(value, Scheduler.DefaultSchedulers.Iteration);
		}

		public static IObservable<T> Repeat<T>(T value, IScheduler scheduler)
		{
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return new RepeatObservable<T>(value, null, scheduler);
		}

		public static IObservable<T> Repeat<T>(T value, int repeatCount)
		{
			return Repeat(value, repeatCount, Scheduler.DefaultSchedulers.Iteration);
		}

		public static IObservable<T> Repeat<T>(T value, int repeatCount, IScheduler scheduler)
		{
			if (repeatCount < 0)
			{
				throw new ArgumentOutOfRangeException("repeatCount");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return new RepeatObservable<T>(value, repeatCount, scheduler);
		}

		public static IObservable<T> Repeat<T>(this IObservable<T> source)
		{
			return RepeatInfinite(source).Concat();
		}

		private static IEnumerable<IObservable<T>> RepeatInfinite<T>(IObservable<T> source)
		{
			while (true)
			{
				yield return source;
			}
		}

		public static IObservable<T> RepeatSafe<T>(this IObservable<T> source)
		{
			return new RepeatSafeObservable<T>(RepeatInfinite(source), source.IsRequiredSubscribeOnCurrentThread());
		}

		public static IObservable<T> Defer<T>(Func<IObservable<T>> observableFactory)
		{
			return new DeferObservable<T>(observableFactory);
		}

		public static IObservable<T> Start<T>(Func<T> function)
		{
			return new StartObservable<T>(function, null, Scheduler.DefaultSchedulers.AsyncConversions);
		}

		public static IObservable<T> Start<T>(Func<T> function, TimeSpan timeSpan)
		{
			return new StartObservable<T>(function, timeSpan, Scheduler.DefaultSchedulers.AsyncConversions);
		}

		public static IObservable<T> Start<T>(Func<T> function, IScheduler scheduler)
		{
			return new StartObservable<T>(function, null, scheduler);
		}

		public static IObservable<T> Start<T>(Func<T> function, TimeSpan timeSpan, IScheduler scheduler)
		{
			return new StartObservable<T>(function, timeSpan, scheduler);
		}

		public static IObservable<Unit> Start(Action action)
		{
			return new StartObservable<Unit>(action, null, Scheduler.DefaultSchedulers.AsyncConversions);
		}

		public static IObservable<Unit> Start(Action action, TimeSpan timeSpan)
		{
			return new StartObservable<Unit>(action, timeSpan, Scheduler.DefaultSchedulers.AsyncConversions);
		}

		public static IObservable<Unit> Start(Action action, IScheduler scheduler)
		{
			return new StartObservable<Unit>(action, null, scheduler);
		}

		public static IObservable<Unit> Start(Action action, TimeSpan timeSpan, IScheduler scheduler)
		{
			return new StartObservable<Unit>(action, timeSpan, scheduler);
		}

		public static Func<IObservable<T>> ToAsync<T>(Func<T> function)
		{
			return ToAsync(function, Scheduler.DefaultSchedulers.AsyncConversions);
		}

		public static Func<IObservable<T>> ToAsync<T>(Func<T> function, IScheduler scheduler)
		{
			return delegate
			{
				AsyncSubject<T> subject = new AsyncSubject<T>();
				scheduler.Schedule(delegate
				{
					T val = default(T);
					try
					{
						val = function();
					}
					catch (Exception error)
					{
						subject.OnError(error);
						return;
					}
					subject.OnNext(val);
					subject.OnCompleted();
				});
				return subject.AsObservable();
			};
		}

		public static Func<IObservable<Unit>> ToAsync(Action action)
		{
			return ToAsync(action, Scheduler.DefaultSchedulers.AsyncConversions);
		}

		public static Func<IObservable<Unit>> ToAsync(Action action, IScheduler scheduler)
		{
			return delegate
			{
				AsyncSubject<Unit> subject = new AsyncSubject<Unit>();
				scheduler.Schedule(delegate
				{
					try
					{
						action();
					}
					catch (Exception error)
					{
						subject.OnError(error);
						return;
					}
					subject.OnNext(Unit.Default);
					subject.OnCompleted();
				});
				return subject.AsObservable();
			};
		}

		public static IObservable<TR> Select<T, TR>(this IObservable<T> source, Func<T, TR> selector)
		{
			if (source is WhereObservable<T> whereObservable)
			{
				return whereObservable.CombineSelector(selector);
			}
			return new SelectObservable<T, TR>(source, selector);
		}

		public static IObservable<TR> Select<T, TR>(this IObservable<T> source, Func<T, int, TR> selector)
		{
			return new SelectObservable<T, TR>(source, selector);
		}

		public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, bool> predicate)
		{
			if (source is WhereObservable<T> whereObservable)
			{
				return whereObservable.CombinePredicate(predicate);
			}
			if (source is ISelect<T> select)
			{
				return select.CombinePredicate(predicate);
			}
			return new WhereObservable<T>(sou

NAudio.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using NAudio.CoreAudioApi;
using NAudio.CoreAudioApi.Interfaces;
using NAudio.Dmo;
using NAudio.Dsp;
using NAudio.FileFormats.Wav;
using NAudio.MediaFoundation;
using NAudio.Mixer;
using NAudio.Utils;
using NAudio.Wave;
using NAudio.Wave.Asio;
using NAudio.Wave.Compression;
using NAudio.Wave.SampleProviders;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("NAudio")]
[assembly: AssemblyDescription("NAudio .NET Audio Library")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Mark Heath")]
[assembly: AssemblyProduct("NAudio")]
[assembly: AssemblyCopyright("© 2001-2017 Mark Heath")]
[assembly: AssemblyTrademark("")]
[assembly: InternalsVisibleTo("NAudioTests")]
[assembly: ComVisible(false)]
[assembly: Guid("e82fa7f0-f952-4d93-b7b0-392bbf53b2a4")]
[assembly: AssemblyFileVersion("1.8.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.0.0")]
[module: UnverifiableCode]
namespace NAudio
{
	public enum Manufacturers
	{
		Microsoft = 1,
		Creative = 2,
		Mediavision = 3,
		Fujitsu = 4,
		Artisoft = 20,
		TurtleBeach = 21,
		Ibm = 22,
		Vocaltec = 23,
		Roland = 24,
		DspSolutions = 25,
		Nec = 26,
		Ati = 27,
		Wanglabs = 28,
		Tandy = 29,
		Voyetra = 30,
		Antex = 31,
		IclPS = 32,
		Intel = 33,
		Gravis = 34,
		Val = 35,
		Interactive = 36,
		Yamaha = 37,
		Everex = 38,
		Echo = 39,
		Sierra = 40,
		Cat = 41,
		Apps = 42,
		DspGroup = 43,
		Melabs = 44,
		ComputerFriends = 45,
		Ess = 46,
		Audiofile = 47,
		Motorola = 48,
		Canopus = 49,
		Epson = 50,
		Truevision = 51,
		Aztech = 52,
		Videologic = 53,
		Scalacs = 54,
		Korg = 55,
		Apt = 56,
		Ics = 57,
		Iteratedsys = 58,
		Metheus = 59,
		Logitech = 60,
		Winnov = 61,
		Ncr = 62,
		Exan = 63,
		Ast = 64,
		Willowpond = 65,
		Sonicfoundry = 66,
		Vitec = 67,
		Moscom = 68,
		Siliconsoft = 69,
		Supermac = 73,
		Audiopt = 74,
		Speechcomp = 76,
		Ahead = 77,
		Dolby = 78,
		Oki = 79,
		Auravision = 80,
		Olivetti = 81,
		Iomagic = 82,
		Matsushita = 83,
		Controlres = 84,
		Xebec = 85,
		Newmedia = 86,
		Nms = 87,
		Lyrrus = 88,
		Compusic = 89,
		Opti = 90,
		Adlacc = 91,
		Compaq = 92,
		Dialogic = 93,
		Insoft = 94,
		Mptus = 95,
		Weitek = 96,
		LernoutAndHauspie = 97,
		Qciar = 98,
		Apple = 99,
		Digital = 100,
		Motu = 101,
		Workbit = 102,
		Ositech = 103,
		Miro = 104,
		Cirruslogic = 105,
		Isolution = 106,
		Horizons = 107,
		Concepts = 108,
		Vtg = 109,
		Radius = 110,
		Rockwell = 111,
		Xyz = 112,
		Opcode = 113,
		Voxware = 114,
		NorthernTelecom = 115,
		Apicom = 116,
		Grande = 117,
		Addx = 118,
		Wildcat = 119,
		Rhetorex = 120,
		Brooktree = 121,
		Ensoniq = 125,
		Fast = 126,
		Nvidia = 127,
		Oksori = 128,
		Diacoustics = 129,
		Gulbransen = 130,
		KayElemetrics = 131,
		Crystal = 132,
		SplashStudios = 133,
		Quarterdeck = 134,
		Tdk = 135,
		DigitalAudioLabs = 136,
		Seersys = 137,
		Picturetel = 138,
		AttMicroelectronics = 139,
		Osprey = 140,
		Mediatrix = 141,
		Soundesigns = 142,
		Aldigital = 143,
		SpectrumSignalProcessing = 144,
		Ecs = 145,
		Amd = 146,
		Coredynamics = 147,
		Canam = 148,
		Softsound = 149,
		Norris = 150,
		Ddd = 151,
		Euphonics = 152,
		Precept = 153,
		CrystalNet = 154,
		Chromatic = 155,
		Voiceinfo = 156,
		Viennasys = 157,
		Connectix = 158,
		Gadgetlabs = 159,
		Frontier = 160,
		Viona = 161,
		Casio = 162,
		Diamondmm = 163,
		S3 = 164,
		FraunhoferIis = 172
	}
	public class MmException : Exception
	{
		private MmResult result;

		private string function;

		public MmResult Result => result;

		public MmException(MmResult result, string function)
			: base(ErrorMessage(result, function))
		{
			this.result = result;
			this.function = function;
		}

		private static string ErrorMessage(MmResult result, string function)
		{
			return $"{result} calling {function}";
		}

		public static void Try(MmResult result, string function)
		{
			if (result != 0)
			{
				throw new MmException(result, function);
			}
		}
	}
	public enum MmResult
	{
		NoError = 0,
		UnspecifiedError = 1,
		BadDeviceId = 2,
		NotEnabled = 3,
		AlreadyAllocated = 4,
		InvalidHandle = 5,
		NoDriver = 6,
		MemoryAllocationError = 7,
		NotSupported = 8,
		BadErrorNumber = 9,
		InvalidFlag = 10,
		InvalidParameter = 11,
		HandleBusy = 12,
		InvalidAlias = 13,
		BadRegistryDatabase = 14,
		RegistryKeyNotFound = 15,
		RegistryReadError = 16,
		RegistryWriteError = 17,
		RegistryDeleteError = 18,
		RegistryValueNotFound = 19,
		NoDriverCallback = 20,
		MoreData = 21,
		WaveBadFormat = 32,
		WaveStillPlaying = 33,
		WaveHeaderUnprepared = 34,
		WaveSync = 35,
		AcmNotPossible = 512,
		AcmBusy = 513,
		AcmHeaderUnprepared = 514,
		AcmCancelled = 515,
		MixerInvalidLine = 1024,
		MixerInvalidControl = 1025,
		MixerInvalidValue = 1026
	}
}
namespace NAudio.Mixer
{
	public class BooleanMixerControl : MixerControl
	{
		private MixerInterop.MIXERCONTROLDETAILS_BOOLEAN boolDetails;

		public bool Value
		{
			get
			{
				GetControlDetails();
				return boolDetails.fValue == 1;
			}
			set
			{
				boolDetails.fValue = (value ? 1 : 0);
				mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf((object)boolDetails));
				Marshal.StructureToPtr((object)boolDetails, mixerControlDetails.paDetails, fDeleteOld: false);
				MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails");
				Marshal.FreeHGlobal(mixerControlDetails.paDetails);
			}
		}

		internal BooleanMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
			boolDetails = (MixerInterop.MIXERCONTROLDETAILS_BOOLEAN)Marshal.PtrToStructure(pDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN));
		}
	}
	public class CustomMixerControl : MixerControl
	{
		internal CustomMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
		}
	}
	public class ListTextMixerControl : MixerControl
	{
		internal ListTextMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
		}
	}
	public class Mixer
	{
		private MixerInterop.MIXERCAPS caps;

		private IntPtr mixerHandle;

		private MixerFlags mixerHandleType;

		public static int NumberOfDevices => MixerInterop.mixerGetNumDevs();

		public int DestinationCount => (int)caps.cDestinations;

		public string Name => caps.szPname;

		public Manufacturers Manufacturer => (Manufacturers)caps.wMid;

		public int ProductID => caps.wPid;

		public IEnumerable<MixerLine> Destinations
		{
			get
			{
				for (int destination = 0; destination < DestinationCount; destination++)
				{
					yield return GetDestination(destination);
				}
			}
		}

		public static IEnumerable<Mixer> Mixers
		{
			get
			{
				for (int device = 0; device < NumberOfDevices; device++)
				{
					yield return new Mixer(device);
				}
			}
		}

		public Mixer(int mixerIndex)
		{
			if (mixerIndex < 0 || mixerIndex >= NumberOfDevices)
			{
				throw new ArgumentOutOfRangeException("mixerID");
			}
			caps = default(MixerInterop.MIXERCAPS);
			MmException.Try(MixerInterop.mixerGetDevCaps((IntPtr)mixerIndex, ref caps, Marshal.SizeOf((object)caps)), "mixerGetDevCaps");
			mixerHandle = (IntPtr)mixerIndex;
			mixerHandleType = MixerFlags.Mixer;
		}

		public MixerLine GetDestination(int destinationIndex)
		{
			if (destinationIndex < 0 || destinationIndex >= DestinationCount)
			{
				throw new ArgumentOutOfRangeException("destinationIndex");
			}
			return new MixerLine(mixerHandle, destinationIndex, mixerHandleType);
		}
	}
	public abstract class MixerControl
	{
		internal MixerInterop.MIXERCONTROL mixerControl;

		internal MixerInterop.MIXERCONTROLDETAILS mixerControlDetails;

		protected IntPtr mixerHandle;

		protected int nChannels;

		protected MixerFlags mixerHandleType;

		public string Name => mixerControl.szName;

		public MixerControlType ControlType => mixerControl.dwControlType;

		public bool IsBoolean => IsControlBoolean(mixerControl.dwControlType);

		public bool IsListText => IsControlListText(mixerControl.dwControlType);

		public bool IsSigned => IsControlSigned(mixerControl.dwControlType);

		public bool IsUnsigned => IsControlUnsigned(mixerControl.dwControlType);

		public bool IsCustom => IsControlCustom(mixerControl.dwControlType);

		public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType)
		{
			List<MixerControl> list = new List<MixerControl>();
			if (mixerLine.ControlsCount > 0)
			{
				int num = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
				MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS);
				IntPtr intPtr = Marshal.AllocHGlobal(num * mixerLine.ControlsCount);
				mixerLineControls.cbStruct = Marshal.SizeOf((object)mixerLineControls);
				mixerLineControls.dwLineID = mixerLine.LineId;
				mixerLineControls.cControls = mixerLine.ControlsCount;
				mixerLineControls.pamxctrl = intPtr;
				mixerLineControls.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
				try
				{
					MmResult mmResult = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.Mixer | mixerHandleType);
					if (mmResult != 0)
					{
						throw new MmException(mmResult, "mixerGetLineControls");
					}
					for (int i = 0; i < mixerLineControls.cControls; i++)
					{
						MixerInterop.MIXERCONTROL mIXERCONTROL = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)(intPtr.ToInt64() + num * i), typeof(MixerInterop.MIXERCONTROL));
						MixerControl item = GetMixerControl(mixerHandle, mixerLine.LineId, mIXERCONTROL.dwControlID, mixerLine.Channels, mixerHandleType);
						list.Add(item);
					}
				}
				finally
				{
					Marshal.FreeHGlobal(intPtr);
				}
			}
			return list;
		}

		public static MixerControl GetMixerControl(IntPtr mixerHandle, int nLineID, int controlId, int nChannels, MixerFlags mixerFlags)
		{
			MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS);
			MixerInterop.MIXERCONTROL mIXERCONTROL = default(MixerInterop.MIXERCONTROL);
			IntPtr intPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf((object)mIXERCONTROL));
			mixerLineControls.cbStruct = Marshal.SizeOf((object)mixerLineControls);
			mixerLineControls.cControls = 1;
			mixerLineControls.dwControlID = controlId;
			mixerLineControls.cbmxctrl = Marshal.SizeOf((object)mIXERCONTROL);
			mixerLineControls.pamxctrl = intPtr;
			mixerLineControls.dwLineID = nLineID;
			MmResult mmResult = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.ListText | mixerFlags);
			if (mmResult != 0)
			{
				Marshal.FreeCoTaskMem(intPtr);
				throw new MmException(mmResult, "mixerGetLineControls");
			}
			mIXERCONTROL = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure(mixerLineControls.pamxctrl, typeof(MixerInterop.MIXERCONTROL));
			Marshal.FreeCoTaskMem(intPtr);
			if (IsControlBoolean(mIXERCONTROL.dwControlType))
			{
				return new BooleanMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlSigned(mIXERCONTROL.dwControlType))
			{
				return new SignedMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlUnsigned(mIXERCONTROL.dwControlType))
			{
				return new UnsignedMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlListText(mIXERCONTROL.dwControlType))
			{
				return new ListTextMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlCustom(mIXERCONTROL.dwControlType))
			{
				return new CustomMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			throw new InvalidOperationException($"Unknown mixer control type {mIXERCONTROL.dwControlType}");
		}

		protected void GetControlDetails()
		{
			mixerControlDetails.cbStruct = Marshal.SizeOf((object)mixerControlDetails);
			mixerControlDetails.dwControlID = mixerControl.dwControlID;
			if (IsCustom)
			{
				mixerControlDetails.cChannels = 0;
			}
			else if ((mixerControl.fdwControl & (true ? 1u : 0u)) != 0)
			{
				mixerControlDetails.cChannels = 1;
			}
			else
			{
				mixerControlDetails.cChannels = nChannels;
			}
			if ((mixerControl.fdwControl & 2u) != 0)
			{
				mixerControlDetails.hwndOwner = (IntPtr)mixerControl.cMultipleItems;
			}
			else if (IsCustom)
			{
				mixerControlDetails.hwndOwner = IntPtr.Zero;
			}
			else
			{
				mixerControlDetails.hwndOwner = IntPtr.Zero;
			}
			if (IsBoolean)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN));
			}
			else if (IsListText)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_LISTTEXT));
			}
			else if (IsSigned)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_SIGNED));
			}
			else if (IsUnsigned)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_UNSIGNED));
			}
			else
			{
				mixerControlDetails.cbDetails = mixerControl.Metrics.customData;
			}
			int num = mixerControlDetails.cbDetails * mixerControlDetails.cChannels;
			if ((mixerControl.fdwControl & 2u) != 0)
			{
				num *= (int)mixerControl.cMultipleItems;
			}
			IntPtr intPtr = Marshal.AllocCoTaskMem(num);
			mixerControlDetails.paDetails = intPtr;
			MmResult mmResult = MixerInterop.mixerGetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType);
			if (mmResult == MmResult.NoError)
			{
				GetDetails(mixerControlDetails.paDetails);
			}
			Marshal.FreeCoTaskMem(intPtr);
			if (mmResult != 0)
			{
				throw new MmException(mmResult, "mixerGetControlDetails");
			}
		}

		protected abstract void GetDetails(IntPtr pDetails);

		private static bool IsControlBoolean(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.BooleanMeter:
			case MixerControlType.Boolean:
			case MixerControlType.OnOff:
			case MixerControlType.Mute:
			case MixerControlType.Mono:
			case MixerControlType.Loudness:
			case MixerControlType.StereoEnhance:
			case MixerControlType.Button:
			case MixerControlType.SingleSelect:
			case MixerControlType.Mux:
			case MixerControlType.MultipleSelect:
			case MixerControlType.Mixer:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlListText(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.Equalizer:
			case MixerControlType.SingleSelect:
			case MixerControlType.Mux:
			case MixerControlType.MultipleSelect:
			case MixerControlType.Mixer:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlSigned(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.SignedMeter:
			case MixerControlType.PeakMeter:
			case MixerControlType.Signed:
			case MixerControlType.Decibels:
			case MixerControlType.Slider:
			case MixerControlType.Pan:
			case MixerControlType.QSoundPan:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlUnsigned(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.UnsignedMeter:
			case MixerControlType.Unsigned:
			case MixerControlType.Percent:
			case MixerControlType.Fader:
			case MixerControlType.Volume:
			case MixerControlType.Bass:
			case MixerControlType.Treble:
			case MixerControlType.Equalizer:
			case MixerControlType.MicroTime:
			case MixerControlType.MilliTime:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlCustom(MixerControlType controlType)
		{
			return controlType == MixerControlType.Custom;
		}

		public override string ToString()
		{
			return $"{Name} {ControlType}";
		}
	}
	[Flags]
	internal enum MixerControlClass
	{
		Custom = 0,
		Meter = 0x10000000,
		Switch = 0x20000000,
		Number = 0x30000000,
		Slider = 0x40000000,
		Fader = 0x50000000,
		Time = 0x60000000,
		List = 0x70000000,
		Mask = 0x70000000
	}
	[Flags]
	internal enum MixerControlSubclass
	{
		SwitchBoolean = 0,
		SwitchButton = 0x1000000,
		MeterPolled = 0,
		TimeMicrosecs = 0,
		TimeMillisecs = 0x1000000,
		ListSingle = 0,
		ListMultiple = 0x1000000,
		Mask = 0xF000000
	}
	[Flags]
	internal enum MixerControlUnits
	{
		Custom = 0,
		Boolean = 0x10000,
		Signed = 0x20000,
		Unsigned = 0x30000,
		Decibels = 0x40000,
		Percent = 0x50000,
		Mask = 0xFF0000
	}
	public enum MixerControlType
	{
		Custom = 0,
		BooleanMeter = 268500992,
		SignedMeter = 268566528,
		PeakMeter = 268566529,
		UnsignedMeter = 268632064,
		Boolean = 536936448,
		OnOff = 536936449,
		Mute = 536936450,
		Mono = 536936451,
		Loudness = 536936452,
		StereoEnhance = 536936453,
		Button = 553713664,
		Decibels = 805568512,
		Signed = 805437440,
		Unsigned = 805502976,
		Percent = 805634048,
		Slider = 1073872896,
		Pan = 1073872897,
		QSoundPan = 1073872898,
		Fader = 1342373888,
		Volume = 1342373889,
		Bass = 1342373890,
		Treble = 1342373891,
		Equalizer = 1342373892,
		SingleSelect = 1879113728,
		Mux = 1879113729,
		MultipleSelect = 1895890944,
		Mixer = 1895890945,
		MicroTime = 1610809344,
		MilliTime = 1627586560
	}
	public class MixerLine
	{
		private MixerInterop.MIXERLINE mixerLine;

		private IntPtr mixerHandle;

		private MixerFlags mixerHandleType;

		public string Name => mixerLine.szName;

		public string ShortName => mixerLine.szShortName;

		public int LineId => mixerLine.dwLineID;

		public MixerLineComponentType ComponentType => mixerLine.dwComponentType;

		public string TypeDescription => mixerLine.dwComponentType switch
		{
			MixerLineComponentType.DestinationUndefined => "Undefined Destination", 
			MixerLineComponentType.DestinationDigital => "Digital Destination", 
			MixerLineComponentType.DestinationLine => "Line Level Destination", 
			MixerLineComponentType.DestinationMonitor => "Monitor Destination", 
			MixerLineComponentType.DestinationSpeakers => "Speakers Destination", 
			MixerLineComponentType.DestinationHeadphones => "Headphones Destination", 
			MixerLineComponentType.DestinationTelephone => "Telephone Destination", 
			MixerLineComponentType.DestinationWaveIn => "Wave Input Destination", 
			MixerLineComponentType.DestinationVoiceIn => "Voice Recognition Destination", 
			MixerLineComponentType.SourceUndefined => "Undefined Source", 
			MixerLineComponentType.SourceDigital => "Digital Source", 
			MixerLineComponentType.SourceLine => "Line Level Source", 
			MixerLineComponentType.SourceMicrophone => "Microphone Source", 
			MixerLineComponentType.SourceSynthesizer => "Synthesizer Source", 
			MixerLineComponentType.SourceCompactDisc => "Compact Disk Source", 
			MixerLineComponentType.SourceTelephone => "Telephone Source", 
			MixerLineComponentType.SourcePcSpeaker => "PC Speaker Source", 
			MixerLineComponentType.SourceWaveOut => "Wave Out Source", 
			MixerLineComponentType.SourceAuxiliary => "Auxiliary Source", 
			MixerLineComponentType.SourceAnalog => "Analog Source", 
			_ => "Invalid Component Type", 
		};

		public int Channels => mixerLine.cChannels;

		public int SourceCount => mixerLine.cConnections;

		public int ControlsCount => mixerLine.cControls;

		public bool IsActive => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_ACTIVE) != 0;

		public bool IsDisconnected => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_DISCONNECTED) != 0;

		public bool IsSource => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_SOURCE) != 0;

		public IEnumerable<MixerControl> Controls => MixerControl.GetMixerControls(mixerHandle, this, mixerHandleType);

		public IEnumerable<MixerLine> Sources
		{
			get
			{
				for (int source = 0; source < SourceCount; source++)
				{
					yield return GetSource(source);
				}
			}
		}

		public string TargetName => mixerLine.szPname;

		public MixerLine(IntPtr mixerHandle, int destinationIndex, MixerFlags mixerHandleType)
		{
			this.mixerHandle = mixerHandle;
			this.mixerHandleType = mixerHandleType;
			mixerLine = default(MixerInterop.MIXERLINE);
			mixerLine.cbStruct = Marshal.SizeOf((object)mixerLine);
			mixerLine.dwDestination = destinationIndex;
			MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.Mixer), "mixerGetLineInfo");
		}

		public MixerLine(IntPtr mixerHandle, int destinationIndex, int sourceIndex, MixerFlags mixerHandleType)
		{
			this.mixerHandle = mixerHandle;
			this.mixerHandleType = mixerHandleType;
			mixerLine = default(MixerInterop.MIXERLINE);
			mixerLine.cbStruct = Marshal.SizeOf((object)mixerLine);
			mixerLine.dwDestination = destinationIndex;
			mixerLine.dwSource = sourceIndex;
			MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.ListText), "mixerGetLineInfo");
		}

		public static int GetMixerIdForWaveIn(int waveInDevice)
		{
			int mixerID = -1;
			MmException.Try(MixerInterop.mixerGetID((IntPtr)waveInDevice, out mixerID, MixerFlags.WaveIn), "mixerGetID");
			return mixerID;
		}

		public MixerLine GetSource(int sourceIndex)
		{
			if (sourceIndex < 0 || sourceIndex >= SourceCount)
			{
				throw new ArgumentOutOfRangeException("sourceIndex");
			}
			return new MixerLine(mixerHandle, mixerLine.dwDestination, sourceIndex, mixerHandleType);
		}

		public override string ToString()
		{
			return $"{Name} {TypeDescription} ({ControlsCount} controls, ID={mixerLine.dwLineID})";
		}
	}
	[Flags]
	public enum MixerFlags
	{
		Handle = int.MinValue,
		Mixer = 0,
		MixerHandle = int.MinValue,
		WaveOut = 0x10000000,
		WaveOutHandle = -1879048192,
		WaveIn = 0x20000000,
		WaveInHandle = -1610612736,
		MidiOut = 0x30000000,
		MidiOutHandle = -1342177280,
		MidiIn = 0x40000000,
		MidiInHandle = -1073741824,
		Aux = 0x50000000,
		Value = 0,
		ListText = 1,
		QueryMask = 0xF,
		All = 0,
		OneById = 1,
		OneByType = 2,
		GetLineInfoOfDestination = 0,
		GetLineInfoOfSource = 1,
		GetLineInfoOfLineId = 2,
		GetLineInfoOfComponentType = 3,
		GetLineInfoOfTargetType = 4,
		GetLineInfoOfQueryMask = 0xF
	}
	internal class MixerInterop
	{
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
		public struct MIXERCONTROLDETAILS
		{
			public int cbStruct;

			public int dwControlID;

			public int cChannels;

			public IntPtr hwndOwner;

			public int cbDetails;

			public IntPtr paDetails;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERCAPS
		{
			public ushort wMid;

			public ushort wPid;

			public uint vDriverVersion;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
			public string szPname;

			public uint fdwSupport;

			public uint cDestinations;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERLINECONTROLS
		{
			public int cbStruct;

			public int dwLineID;

			public int dwControlID;

			public int cControls;

			public int cbmxctrl;

			public IntPtr pamxctrl;
		}

		[Flags]
		public enum MIXERLINE_LINEF
		{
			MIXERLINE_LINEF_ACTIVE = 1,
			MIXERLINE_LINEF_DISCONNECTED = 0x8000,
			MIXERLINE_LINEF_SOURCE = int.MinValue
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERLINE
		{
			public int cbStruct;

			public int dwDestination;

			public int dwSource;

			public int dwLineID;

			public MIXERLINE_LINEF fdwLine;

			public IntPtr dwUser;

			public MixerLineComponentType dwComponentType;

			public int cChannels;

			public int cConnections;

			public int cControls;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
			public string szShortName;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
			public string szName;

			public uint dwType;

			public uint dwDeviceID;

			public ushort wMid;

			public ushort wPid;

			public uint vDriverVersion;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
			public string szPname;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct Bounds
		{
			public int minimum;

			public int maximum;

			public int reserved2;

			public int reserved3;

			public int reserved4;

			public int reserved5;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct Metrics
		{
			public int step;

			public int customData;

			public int reserved2;

			public int reserved3;

			public int reserved4;

			public int reserved5;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERCONTROL
		{
			public uint cbStruct;

			public int dwControlID;

			public MixerControlType dwControlType;

			public uint fdwControl;

			public uint cMultipleItems;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
			public string szShortName;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
			public string szName;

			public Bounds Bounds;

			public Metrics Metrics;
		}

		public struct MIXERCONTROLDETAILS_BOOLEAN
		{
			public int fValue;
		}

		public struct MIXERCONTROLDETAILS_SIGNED
		{
			public int lValue;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERCONTROLDETAILS_LISTTEXT
		{
			public uint dwParam1;

			public uint dwParam2;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
			public string szName;
		}

		public struct MIXERCONTROLDETAILS_UNSIGNED
		{
			public uint dwValue;
		}

		public const uint MIXERCONTROL_CONTROLF_UNIFORM = 1u;

		public const uint MIXERCONTROL_CONTROLF_MULTIPLE = 2u;

		public const uint MIXERCONTROL_CONTROLF_DISABLED = 2147483648u;

		public const int MAXPNAMELEN = 32;

		public const int MIXER_SHORT_NAME_CHARS = 16;

		public const int MIXER_LONG_NAME_CHARS = 64;

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern int mixerGetNumDevs();

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerOpen(out IntPtr hMixer, int uMxId, IntPtr dwCallback, IntPtr dwInstance, MixerFlags dwOpenFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerClose(IntPtr hMixer);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetControlDetails(IntPtr hMixer, ref MIXERCONTROLDETAILS mixerControlDetails, MixerFlags dwDetailsFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetDevCaps(IntPtr nMixerID, ref MIXERCAPS mixerCaps, int mixerCapsSize);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetID(IntPtr hMixer, out int mixerID, MixerFlags dwMixerIDFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetLineControls(IntPtr hMixer, ref MIXERLINECONTROLS mixerLineControls, MixerFlags dwControlFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetLineInfo(IntPtr hMixer, ref MIXERLINE mixerLine, MixerFlags dwInfoFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerMessage(IntPtr hMixer, uint nMessage, IntPtr dwParam1, IntPtr dwParam2);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerSetControlDetails(IntPtr hMixer, ref MIXERCONTROLDETAILS mixerControlDetails, MixerFlags dwDetailsFlags);
	}
	public enum MixerLineComponentType
	{
		DestinationUndefined = 0,
		DestinationDigital = 1,
		DestinationLine = 2,
		DestinationMonitor = 3,
		DestinationSpeakers = 4,
		DestinationHeadphones = 5,
		DestinationTelephone = 6,
		DestinationWaveIn = 7,
		DestinationVoiceIn = 8,
		SourceUndefined = 4096,
		SourceDigital = 4097,
		SourceLine = 4098,
		SourceMicrophone = 4099,
		SourceSynthesizer = 4100,
		SourceCompactDisc = 4101,
		SourceTelephone = 4102,
		SourcePcSpeaker = 4103,
		SourceWaveOut = 4104,
		SourceAuxiliary = 4105,
		SourceAnalog = 4106
	}
	public class SignedMixerControl : MixerControl
	{
		private MixerInterop.MIXERCONTROLDETAILS_SIGNED signedDetails;

		public int Value
		{
			get
			{
				GetControlDetails();
				return signedDetails.lValue;
			}
			set
			{
				signedDetails.lValue = value;
				mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf((object)signedDetails));
				Marshal.StructureToPtr((object)signedDetails, mixerControlDetails.paDetails, fDeleteOld: false);
				MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails");
				Marshal.FreeHGlobal(mixerControlDetails.paDetails);
			}
		}

		public int MinValue => mixerControl.Bounds.minimum;

		public int MaxValue => mixerControl.Bounds.maximum;

		public double Percent
		{
			get
			{
				return 100.0 * (double)(Value - MinValue) / (double)(MaxValue - MinValue);
			}
			set
			{
				Value = (int)((double)MinValue + value / 100.0 * (double)(MaxValue - MinValue));
			}
		}

		internal SignedMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
			signedDetails = (MixerInterop.MIXERCONTROLDETAILS_SIGNED)Marshal.PtrToStructure(mixerControlDetails.paDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_SIGNED));
		}

		public override string ToString()
		{
			return $"{base.ToString()} {Percent}%";
		}
	}
	public class UnsignedMixerControl : MixerControl
	{
		private MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[] unsignedDetails;

		public uint Value
		{
			get
			{
				GetControlDetails();
				return unsignedDetails[0].dwValue;
			}
			set
			{
				int num = Marshal.SizeOf((object)unsignedDetails[0]);
				mixerControlDetails.paDetails = Marshal.AllocHGlobal(num * nChannels);
				for (int i = 0; i < nChannels; i++)
				{
					unsignedDetails[i].dwValue = value;
					long num2 = mixerControlDetails.paDetails.ToInt64() + num * i;
					Marshal.StructureToPtr((object)unsignedDetails[i], (IntPtr)num2, fDeleteOld: false);
				}
				MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails");
				Marshal.FreeHGlobal(mixerControlDetails.paDetails);
			}
		}

		public uint MinValue => (uint)mixerControl.Bounds.minimum;

		public uint MaxValue => (uint)mixerControl.Bounds.maximum;

		public double Percent
		{
			get
			{
				return 100.0 * (double)(Value - MinValue) / (double)(MaxValue - MinValue);
			}
			set
			{
				Value = (uint)((double)MinValue + value / 100.0 * (double)(MaxValue - MinValue));
			}
		}

		internal UnsignedMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
			unsignedDetails = new MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[nChannels];
			for (int i = 0; i < nChannels; i++)
			{
				unsignedDetails[i] = (MixerInterop.MIXERCONTROLDETAILS_UNSIGNED)Marshal.PtrToStructure(mixerControlDetails.paDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_UNSIGNED));
			}
		}

		public override string ToString()
		{
			return $"{base.ToString()} {Percent}%";
		}
	}
}
namespace NAudio.Gui
{
	public class Fader : Control
	{
		private int minimum;

		private int maximum;

		private float percent;

		private Orientation orientation;

		private Container components;

		private readonly int SliderHeight = 30;

		private readonly int SliderWidth = 15;

		private Rectangle sliderRectangle;

		private bool dragging;

		private int dragY;

		public int Minimum
		{
			get
			{
				return minimum;
			}
			set
			{
				minimum = value;
			}
		}

		public int Maximum
		{
			get
			{
				return maximum;
			}
			set
			{
				maximum = value;
			}
		}

		public int Value
		{
			get
			{
				return (int)(percent * (float)(maximum - minimum)) + minimum;
			}
			set
			{
				percent = (float)(value - minimum) / (float)(maximum - minimum);
			}
		}

		public Orientation Orientation
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return orientation;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				orientation = value;
			}
		}

		public Fader()
		{
			InitializeComponent();
			((Control)this).SetStyle((ControlStyles)73730, true);
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((Control)this).Dispose(disposing);
		}

		private void DrawSlider(Graphics g)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			Brush val = (Brush)new SolidBrush(Color.White);
			Pen val2 = new Pen(Color.Black);
			sliderRectangle.X = (((Control)this).Width - SliderWidth) / 2;
			sliderRectangle.Width = SliderWidth;
			sliderRectangle.Y = (int)((float)(((Control)this).Height - SliderHeight) * percent);
			sliderRectangle.Height = SliderHeight;
			g.FillRectangle(val, sliderRectangle);
			g.DrawLine(val2, sliderRectangle.Left, sliderRectangle.Top + sliderRectangle.Height / 2, sliderRectangle.Right, sliderRectangle.Top + sliderRectangle.Height / 2);
			val.Dispose();
			val2.Dispose();
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Graphics graphics = e.Graphics;
			if ((int)Orientation == 1)
			{
				Brush val = (Brush)new SolidBrush(Color.Black);
				graphics.FillRectangle(val, ((Control)this).Width / 2, SliderHeight / 2, 2, ((Control)this).Height - SliderHeight);
				val.Dispose();
				DrawSlider(graphics);
			}
			((Control)this).OnPaint(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			if (sliderRectangle.Contains(e.X, e.Y))
			{
				dragging = true;
				dragY = e.Y - sliderRectangle.Y;
			}
			((Control)this).OnMouseDown(e);
		}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (dragging)
			{
				int num = e.Y - dragY;
				if (num < 0)
				{
					percent = 0f;
				}
				else if (num > ((Control)this).Height - SliderHeight)
				{
					percent = 1f;
				}
				else
				{
					percent = (float)num / (float)(((Control)this).Height - SliderHeight);
				}
				((Control)this).Invalidate();
			}
			((Control)this).OnMouseMove(e);
		}

		protected override void OnMouseUp(MouseEventArgs e)
		{
			dragging = false;
			((Control)this).OnMouseUp(e);
		}

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
		}
	}
	public class PanSlider : UserControl
	{
		private Container components;

		private float pan;

		public float Pan
		{
			get
			{
				return pan;
			}
			set
			{
				if (value < -1f)
				{
					value = -1f;
				}
				if (value > 1f)
				{
					value = 1f;
				}
				if (value != pan)
				{
					pan = value;
					if (this.PanChanged != null)
					{
						this.PanChanged(this, EventArgs.Empty);
					}
					((Control)this).Invalidate();
				}
			}
		}

		public event EventHandler PanChanged;

		public PanSlider()
		{
			InitializeComponent();
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((ContainerControl)this).Dispose(disposing);
		}

		private void InitializeComponent()
		{
			((Control)this).Name = "PanSlider";
			((Control)this).Size = new Size(104, 16);
		}

		protected override void OnPaint(PaintEventArgs pe)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			StringFormat val = new StringFormat();
			val.LineAlignment = (StringAlignment)1;
			val.Alignment = (StringAlignment)1;
			string text;
			if ((double)pan == 0.0)
			{
				pe.Graphics.FillRectangle(Brushes.Orange, ((Control)this).Width / 2 - 1, 1, 3, ((Control)this).Height - 2);
				text = "C";
			}
			else if (pan > 0f)
			{
				pe.Graphics.FillRectangle(Brushes.Orange, ((Control)this).Width / 2, 1, (int)((float)(((Control)this).Width / 2) * pan), ((Control)this).Height - 2);
				text = $"{pan * 100f:F0}%R";
			}
			else
			{
				pe.Graphics.FillRectangle(Brushes.Orange, (int)((float)(((Control)this).Width / 2) * (pan + 1f)), 1, (int)((float)(((Control)this).Width / 2) * (0f - pan)), ((Control)this).Height - 2);
				text = $"{pan * -100f:F0}%L";
			}
			pe.Graphics.DrawRectangle(Pens.Black, 0, 0, ((Control)this).Width - 1, ((Control)this).Height - 1);
			pe.Graphics.DrawString(text, ((Control)this).Font, Brushes.Black, (RectangleF)((Control)this).ClientRectangle, val);
		}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if ((int)e.Button == 1048576)
			{
				SetPanFromMouse(e.X);
			}
			((Control)this).OnMouseMove(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			SetPanFromMouse(e.X);
			((UserControl)this).OnMouseDown(e);
		}

		private void SetPanFromMouse(int x)
		{
			Pan = (float)x / (float)((Control)this).Width * 2f - 1f;
		}
	}
	public class Pot : UserControl
	{
		private double minimum;

		private double maximum = 1.0;

		private double value = 0.5;

		private int beginDragY;

		private double beginDragValue;

		private bool dragging;

		private IContainer components;

		public double Minimum
		{
			get
			{
				return minimum;
			}
			set
			{
				if (value >= maximum)
				{
					throw new ArgumentOutOfRangeException("Minimum must be less than maximum");
				}
				minimum = value;
				if (Value < minimum)
				{
					Value = minimum;
				}
			}
		}

		public double Maximum
		{
			get
			{
				return maximum;
			}
			set
			{
				if (value <= minimum)
				{
					throw new ArgumentOutOfRangeException("Maximum must be greater than minimum");
				}
				maximum = value;
				if (Value > maximum)
				{
					Value = maximum;
				}
			}
		}

		public double Value
		{
			get
			{
				return value;
			}
			set
			{
				SetValue(value, raiseEvents: false);
			}
		}

		public event EventHandler ValueChanged;

		public Pot()
		{
			((Control)this).SetStyle((ControlStyles)73730, true);
			InitializeComponent();
		}

		private void SetValue(double newValue, bool raiseEvents)
		{
			if (value != newValue)
			{
				value = newValue;
				if (raiseEvents && this.ValueChanged != null)
				{
					this.ValueChanged(this, EventArgs.Empty);
				}
				((Control)this).Invalidate();
			}
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			int num = Math.Min(((Control)this).Width - 4, ((Control)this).Height - 4);
			Pen val = new Pen(((Control)this).ForeColor, 3f);
			val.LineJoin = (LineJoin)2;
			GraphicsState val2 = e.Graphics.Save();
			e.Graphics.TranslateTransform((float)(((Control)this).Width / 2), (float)(((Control)this).Height / 2));
			e.Graphics.SmoothingMode = (SmoothingMode)4;
			e.Graphics.DrawArc(val, new Rectangle(num / -2, num / -2, num, num), 135f, 270f);
			double num2 = (value - minimum) / (maximum - minimum);
			double num3 = 135.0 + num2 * 270.0;
			double num4 = (double)num / 2.0 * Math.Cos(Math.PI * num3 / 180.0);
			double num5 = (double)num / 2.0 * Math.Sin(Math.PI * num3 / 180.0);
			e.Graphics.DrawLine(val, 0f, 0f, (float)num4, (float)num5);
			e.Graphics.Restore(val2);
			((Control)this).OnPaint(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			dragging = true;
			beginDragY = e.Y;
			beginDragValue = value;
			((UserControl)this).OnMouseDown(e);
		}

		protected override void OnMouseUp(MouseEventArgs e)
		{
			dragging = false;
			((Control)this).OnMouseUp(e);
		}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (dragging)
			{
				int num = beginDragY - e.Y;
				double num2 = (maximum - minimum) * ((double)num / 150.0);
				double num3 = beginDragValue + num2;
				if (num3 < minimum)
				{
					num3 = minimum;
				}
				if (num3 > maximum)
				{
					num3 = maximum;
				}
				SetValue(num3, raiseEvents: true);
			}
			((Control)this).OnMouseMove(e);
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((ContainerControl)this).Dispose(disposing);
		}

		private void InitializeComponent()
		{
			((Control)this).SuspendLayout();
			((ContainerControl)this).AutoScaleDimensions = new SizeF(6f, 13f);
			((ContainerControl)this).AutoScaleMode = (AutoScaleMode)1;
			((Control)this).Name = "Pot";
			((Control)this).Size = new Size(32, 32);
			((Control)this).ResumeLayout(false);
		}
	}
	public class VolumeMeter : Control
	{
		private Brush foregroundBrush;

		private float amplitude;

		private IContainer components;

		[DefaultValue(-3.0)]
		public float Amplitude
		{
			get
			{
				return amplitude;
			}
			set
			{
				amplitude = value;
				((Control)this).Invalidate();
			}
		}

		[DefaultValue(-60.0)]
		public float MinDb { get; set; }

		[DefaultValue(18.0)]
		public float MaxDb { get; set; }

		[DefaultValue(/*Could not decode attribute arguments.*/)]
		public Orientation Orientation { get; set; }

		public VolumeMeter()
		{
			((Control)this).SetStyle((ControlStyles)139266, true);
			MinDb = -60f;
			MaxDb = 18f;
			Amplitude = 0f;
			Orientation = (Orientation)1;
			InitializeComponent();
			((Control)this).OnForeColorChanged(EventArgs.Empty);
		}

		protected override void OnForeColorChanged(EventArgs e)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			foregroundBrush = (Brush)new SolidBrush(((Control)this).ForeColor);
			((Control)this).OnForeColorChanged(e);
		}

		protected override void OnPaint(PaintEventArgs pe)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			pe.Graphics.DrawRectangle(Pens.Black, 0, 0, ((Control)this).Width - 1, ((Control)this).Height - 1);
			double num = 20.0 * Math.Log10(Amplitude);
			if (num < (double)MinDb)
			{
				num = MinDb;
			}
			if (num > (double)MaxDb)
			{
				num = MaxDb;
			}
			double num2 = (num - (double)MinDb) / (double)(MaxDb - MinDb);
			int num3 = ((Control)this).Width - 2;
			int num4 = ((Control)this).Height - 2;
			if ((int)Orientation == 0)
			{
				num3 = (int)((double)num3 * num2);
				pe.Graphics.FillRectangle(foregroundBrush, 1, 1, num3, num4);
			}
			else
			{
				num4 = (int)((double)num4 * num2);
				pe.Graphics.FillRectangle(foregroundBrush, 1, ((Control)this).Height - 1 - num4, num3, num4);
			}
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((Control)this).Dispose(disposing);
		}

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
		}
	}
	public class VolumeSlider : UserControl
	{
		private Container components;

		private float volume = 1f;

		private float MinDb = -48f;

		[DefaultValue(1f)]
		public float Volume
		{
			get
			{
				return volume;
			}
			set
			{
				if (value < 0f)
				{
					value = 0f;
				}
				if (value > 1f)
				{
					value = 1f;
				}
				if (volume != value)
				{
					volume = value;
					if (this.VolumeChanged != null)
					{
						this.VolumeChanged(this, EventArgs.Empty);
					}
					((Control)this).Invalidate();
				}
			}
		}

		public event EventHandler VolumeChanged;

		public VolumeSlider()
		{
			InitializeComponent();
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((ContainerControl)this).Dispose(disposing);
		}

		private void InitializeComponent()
		{
			((Control)this).Name = "VolumeSlider";
			((Control)this).Size = new Size(96, 16);
		}

		protected override void OnPaint(PaintEventArgs pe)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			StringFormat val = new StringFormat();
			val.LineAlignment = (StringAlignment)1;
			val.Alignment = (StringAlignment)1;
			pe.Graphics.DrawRectangle(Pens.Black, 0, 0, ((Control)this).Width - 1, ((Control)this).Height - 1);
			float num = 20f * (float)Math.Log10(Volume);
			float num2 = 1f - num / MinDb;
			pe.Graphics.FillRectangle(Brushes.LightGreen, 1, 1, (int)((float)(((Control)this).Width - 2) * num2), ((Control)this).Height - 2);
			string text = $"{num:F2} dB";
			pe.Graphics.DrawString(text, ((Control)this).Font, Brushes.Black, (RectangleF)((Control)this).ClientRectangle, val);
		}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if ((int)e.Button == 1048576)
			{
				SetVolumeFromMouse(e.X);
			}
			((Control)this).OnMouseMove(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			SetVolumeFromMouse(e.X);
			((UserControl)this).OnMouseDown(e);
		}

		private void SetVolumeFromMouse(int x)
		{
			float num = (1f - (float)x / (float)((Control)this).Width) * MinDb;
			if (x <= 0)
			{
				Volume = 0f;
			}
			else
			{
				Volume = (float)Math.Pow(10.0, num / 20f);
			}
		}
	}
	public class WaveformPainter : Control
	{
		private Pen foregroundPen;

		private List<float> samples = new List<float>(1000);

		private int maxSamples;

		private int insertPos;

		private IContainer components;

		public WaveformPainter()
		{
			((Control)this).SetStyle((ControlStyles)139266, true);
			InitializeComponent();
			((Control)this).OnForeColorChanged(EventArgs.Empty);
			((Control)this).OnResize(EventArgs.Empty);
		}

		protected override void OnResize(EventArgs e)
		{
			maxSamples = ((Control)this).Width;
			((Control)this).OnResize(e);
		}

		protected override void OnForeColorChanged(EventArgs e)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			foregroundPen = new Pen(((Control)this).ForeColor);
			((Control)this).OnForeColorChanged(e);
		}

		public void AddMax(float maxSample)
		{
			if (maxSamples != 0)
			{
				if (samples.Count <= maxSamples)
				{
					samples.Add(maxSample);
				}
				else if (insertPos < maxSamples)
				{
					samples[insertPos] = maxSample;
				}
				insertPos++;
				insertPos %= maxSamples;
				((Control)this).Invalidate();
			}
		}

		protected override void OnPaint(PaintEventArgs pe)
		{
			((Control)this).OnPaint(pe);
			for (int i = 0; i < ((Control)this).Width; i++)
			{
				float num = (float)((Control)this).Height * GetSample(i - ((Control)this).Width + insertPos);
				float num2 = ((float)((Control)this).Height - num) / 2f;
				pe.Graphics.DrawLine(foregroundPen, (float)i, num2, (float)i, num2 + num);
			}
		}

		private float GetSample(int index)
		{
			if (index < 0)
			{
				index += maxSamples;
			}
			if ((index >= 0) & (index < samples.Count))
			{
				return samples[index];
			}
			return 0f;
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((Control)this).Dispose(disposing);
		}

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
		}
	}
	public class WaveViewer : UserControl
	{
		private Container components;

		private WaveStream waveStream;

		private int samplesPerPixel = 128;

		private long startPosition;

		private int bytesPerSample;

		public WaveStream WaveStream
		{
			get
			{
				return waveStream;
			}
			set
			{
				waveStream = value;
				if (waveStream != null)
				{
					bytesPerSample = waveStream.WaveFormat.BitsPerSample / 8 * waveStream.WaveFormat.Channels;
				}
				((Control)this).Invalidate();
			}
		}

		public int SamplesPerPixel
		{
			get
			{
				return samplesPerPixel;
			}
			set
			{
				samplesPerPixel = value;
				((Control)this).Invalidate();
			}
		}

		public long StartPosition
		{
			get
			{
				return startPosition;
			}
			set
			{
				startPosition = value;
			}
		}

		public WaveViewer()
		{
			InitializeComponent();
			((Control)this).DoubleBuffered = true;
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			((ContainerControl)this).Dispose(disposing);
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			if (waveStream != null)
			{
				waveStream.Position = 0L;
				byte[] array = new byte[samplesPerPixel * bytesPerSample];
				waveStream.Position = startPosition + e.ClipRectangle.Left * bytesPerSample * samplesPerPixel;
				for (float num = e.ClipRectangle.X; num < (float)e.ClipRectangle.Right; num += 1f)
				{
					short num2 = 0;
					short num3 = 0;
					int num4 = waveStream.Read(array, 0, samplesPerPixel * bytesPerSample);
					if (num4 == 0)
					{
						break;
					}
					for (int i = 0; i < num4; i += 2)
					{
						short num5 = BitConverter.ToInt16(array, i);
						if (num5 < num2)
						{
							num2 = num5;
						}
						if (num5 > num3)
						{
							num3 = num5;
						}
					}
					float num6 = ((float)num2 - -32768f) / 65535f;
					float num7 = ((float)num3 - -32768f) / 65535f;
					e.Graphics.DrawLine(Pens.Black, num, (float)((Control)this).Height * num6, num, (float)((Control)this).Height * num7);
				}
			}
			((Control)this).OnPaint(e);
		}

		private void InitializeComponent()
		{
			components = new Container();
		}
	}
}
namespace NAudio.SoundFont
{
	public class Generator
	{
		private GeneratorEnum generatorType;

		private ushort rawAmount;

		private Instrument instrument;

		private SampleHeader sampleHeader;

		public GeneratorEnum GeneratorType
		{
			get
			{
				return generatorType;
			}
			set
			{
				generatorType = value;
			}
		}

		public ushort UInt16Amount
		{
			get
			{
				return rawAmount;
			}
			set
			{
				rawAmount = value;
			}
		}

		public short Int16Amount
		{
			get
			{
				return (short)rawAmount;
			}
			set
			{
				rawAmount = (ushort)value;
			}
		}

		public byte LowByteAmount
		{
			get
			{
				return (byte)(rawAmount & 0xFFu);
			}
			set
			{
				rawAmount &= 65280;
				rawAmount += value;
			}
		}

		public byte HighByteAmount
		{
			get
			{
				return (byte)((rawAmount & 0xFF00) >> 8);
			}
			set
			{
				rawAmount &= 255;
				rawAmount += (ushort)(value << 8);
			}
		}

		public Instrument Instrument
		{
			get
			{
				return instrument;
			}
			set
			{
				instrument = value;
			}
		}

		public SampleHeader SampleHeader
		{
			get
			{
				return sampleHeader;
			}
			set
			{
				sampleHeader = value;
			}
		}

		public override string ToString()
		{
			if (generatorType == GeneratorEnum.Instrument)
			{
				return $"Generator Instrument {instrument.Name}";
			}
			if (generatorType == GeneratorEnum.SampleID)
			{
				return $"Generator SampleID {sampleHeader}";
			}
			return $"Generator {generatorType} {rawAmount}";
		}
	}
	internal class GeneratorBuilder : StructureBuilder<Generator>
	{
		public override int Length => 4;

		public Generator[] Generators => data.ToArray();

		public override Generator Read(BinaryReader br)
		{
			Generator generator = new Generator();
			generator.GeneratorType = (GeneratorEnum)br.ReadUInt16();
			generator.UInt16Amount = br.ReadUInt16();
			data.Add(generator);
			return generator;
		}

		public override void Write(BinaryWriter bw, Generator o)
		{
		}

		public void Load(Instrument[] instruments)
		{
			Generator[] generators = Generators;
			foreach (Generator generator in generators)
			{
				if (generator.GeneratorType == GeneratorEnum.Instrument)
				{
					generator.Instrument = instruments[generator.UInt16Amount];
				}
			}
		}

		public void Load(SampleHeader[] sampleHeaders)
		{
			Generator[] generators = Generators;
			foreach (Generator generator in generators)
			{
				if (generator.GeneratorType == GeneratorEnum.SampleID)
				{
					generator.SampleHeader = sampleHeaders[generator.UInt16Amount];
				}
			}
		}
	}
	public enum GeneratorEnum
	{
		StartAddressOffset,
		EndAddressOffset,
		StartLoopAddressOffset,
		EndLoopAddressOffset,
		StartAddressCoarseOffset,
		ModulationLFOToPitch,
		VibratoLFOToPitch,
		ModulationEnvelopeToPitch,
		InitialFilterCutoffFrequency,
		InitialFilterQ,
		ModulationLFOToFilterCutoffFrequency,
		ModulationEnvelopeToFilterCutoffFrequency,
		EndAddressCoarseOffset,
		ModulationLFOToVolume,
		Unused1,
		ChorusEffectsSend,
		ReverbEffectsSend,
		Pan,
		Unused2,
		Unused3,
		Unused4,
		DelayModulationLFO,
		FrequencyModulationLFO,
		DelayVibratoLFO,
		FrequencyVibratoLFO,
		DelayModulationEnvelope,
		AttackModulationEnvelope,
		HoldModulationEnvelope,
		DecayModulationEnvelope,
		SustainModulationEnvelope,
		ReleaseModulationEnvelope,
		KeyNumberToModulationEnvelopeHold,
		KeyNumberToModulationEnvelopeDecay,
		DelayVolumeEnvelope,
		AttackVolumeEnvelope,
		HoldVolumeEnvelope,
		DecayVolumeEnvelope,
		SustainVolumeEnvelope,
		ReleaseVolumeEnvelope,
		KeyNumberToVolumeEnvelopeHold,
		KeyNumberToVolumeEnvelopeDecay,
		Instrument,
		Reserved1,
		KeyRange,
		VelocityRange,
		StartLoopAddressCoarseOffset,
		KeyNumber,
		Velocity,
		InitialAttenuation,
		Reserved2,
		EndLoopAddressCoarseOffset,
		CoarseTune,
		FineTune,
		SampleID,
		SampleModes,
		Reserved3,
		ScaleTuning,
		ExclusiveClass,
		OverridingRootKey,
		Unused5,
		UnusedEnd
	}
	public class InfoChunk
	{
		private SFVersion verSoundFont;

		private string waveTableSoundEngine;

		private string bankName;

		private string dataROM;

		private string creationDate;

		private string author;

		private string targetProduct;

		private string copyright;

		private string comments;

		private string tools;

		private SFVersion verROM;

		public SFVersion SoundFontVersion => verSoundFont;

		public string WaveTableSoundEngine
		{
			get
			{
				return waveTableSoundEngine;
			}
			set
			{
				waveTableSoundEngine = value;
			}
		}

		public string BankName
		{
			get
			{
				return bankName;
			}
			set
			{
				bankName = value;
			}
		}

		public string DataROM
		{
			get
			{
				return dataROM;
			}
			set
			{
				dataROM = value;
			}
		}

		public string CreationDate
		{
			get
			{
				return creationDate;
			}
			set
			{
				creationDate = value;
			}
		}

		public string Author
		{
			get
			{
				return author;
			}
			set
			{
				author = value;
			}
		}

		public string TargetProduct
		{
			get
			{
				return targetProduct;
			}
			set
			{
				targetProduct = value;
			}
		}

		public string Copyright
		{
			get
			{
				return copyright;
			}
			set
			{
				copyright = value;
			}
		}

		public string Comments
		{
			get
			{
				return comments;
			}
			set
			{
				comments = value;
			}
		}

		public string Tools
		{
			get
			{
				return tools;
			}
			set
			{
				tools = value;
			}
		}

		public SFVersion ROMVersion
		{
			get
			{
				return verROM;
			}
			set
			{
				verROM = value;
			}
		}

		internal InfoChunk(RiffChunk chunk)
		{
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			if (chunk.ReadChunkID() != "INFO")
			{
				throw new InvalidDataException("Not an INFO chunk");
			}
			RiffChunk nextSubChunk;
			while ((nextSubChunk = chunk.GetNextSubChunk()) != null)
			{
				switch (nextSubChunk.ChunkID)
				{
				case "ifil":
					flag = true;
					verSoundFont = nextSubChunk.GetDataAsStructure(new SFVersionBuilder());
					break;
				case "isng":
					flag2 = true;
					waveTableSoundEngine = nextSubChunk.GetDataAsString();
					break;
				case "INAM":
					flag3 = true;
					bankName = nextSubChunk.GetDataAsString();
					break;
				case "irom":
					dataROM = nextSubChunk.GetDataAsString();
					break;
				case "iver":
					verROM = nextSubChunk.GetDataAsStructure(new SFVersionBuilder());
					break;
				case "ICRD":
					creationDate = nextSubChunk.GetDataAsString();
					break;
				case "IENG":
					author = nextSubChunk.GetDataAsString();
					break;
				case "IPRD":
					targetProduct = nextSubChunk.GetDataAsString();
					break;
				case "ICOP":
					copyright = nextSubChunk.GetDataAsString();
					break;
				case "ICMT":
					comments = nextSubChunk.GetDataAsString();
					break;
				case "ISFT":
					tools = nextSubChunk.GetDataAsString();
					break;
				default:
					throw new InvalidDataException($"Unknown chunk type {nextSubChunk.ChunkID}");
				}
			}
			if (!flag)
			{
				throw new InvalidDataException("Missing SoundFont version information");
			}
			if (!flag2)
			{
				throw new InvalidDataException("Missing wavetable sound engine information");
			}
			if (!flag3)
			{
				throw new InvalidDataException("Missing SoundFont name information");
			}
		}

		public override string ToString()
		{
			return string.Format("Bank Name: {0}\r\nAuthor: {1}\r\nCopyright: {2}\r\nCreation Date: {3}\r\nTools: {4}\r\nComments: {5}\r\nSound Engine: {6}\r\nSoundFont Version: {7}\r\nTarget Product: {8}\r\nData ROM: {9}\r\nROM Version: {10}", BankName, Author, Copyright, CreationDate, Tools, "TODO-fix comments", WaveTableSoundEngine, SoundFontVersion, TargetProduct, DataROM, ROMVersion);
		}
	}
	public class Instrument
	{
		private string name;

		internal ushort startInstrumentZoneIndex;

		internal ushort endInstrumentZoneIndex;

		private Zone[] zones;

		public string Name
		{
			get
			{
				return name;
			}
			set
			{
				name = value;
			}
		}

		public Zone[] Zones
		{
			get
			{
				return zones;
			}
			set
			{
				zones = value;
			}
		}

		public override string ToString()
		{
			return name;
		}
	}
	internal class InstrumentBuilder : StructureBuilder<Instrument>
	{
		private Instrument lastInstrument;

		public override int Length => 22;

		public Instrument[] Instruments => data.ToArray();

		public override Instrument Read(BinaryReader br)
		{
			Instrument instrument = new Instrument();
			string text = Encoding.UTF8.GetString(br.ReadBytes(20), 0, 20);
			if (text.IndexOf('\0') >= 0)
			{
				text = text.Substring(0, text.IndexOf('\0'));
			}
			instrument.Name = text;
			instrument.startInstrumentZoneIndex = br.ReadUInt16();
			if (lastInstrument != null)
			{
				lastInstrument.endInstrumentZoneIndex = (ushort)(instrument.startInstrumentZoneIndex - 1);
			}
			data.Add(instrument);
			lastInstrument = instrument;
			return instrument;
		}

		public override void Write(BinaryWriter bw, Instrument instrument)
		{
		}

		public void LoadZones(Zone[] zones)
		{
			for (int i = 0; i < data.Count - 1; i++)
			{
				Instrument instrument = data[i];
				instrument.Zones = new Zone[instrument.endInstrumentZoneIndex - instrument.startInstrumentZoneIndex + 1];
				Array.Copy(zones, instrument.startInstrumentZoneIndex, instrument.Zones, 0, instrument.Zones.Length);
			}
			data.RemoveAt(data.Count - 1);
		}
	}
	public enum TransformEnum
	{
		Linear
	}
	public class Modulator
	{
		private ModulatorType sourceModulationData;

		private GeneratorEnum destinationGenerator;

		private short amount;

		private ModulatorType sourceModulationAmount;

		private TransformEnum sourceTransform;

		public ModulatorType SourceModulationData
		{
			get
			{
				return sourceModulationData;
			}
			set
			{
				sourceModulationData = value;
			}
		}

		public GeneratorEnum DestinationGenerator
		{
			get
			{
				return destinationGenerator;
			}
			set
			{
				destinationGenerator = value;
			}
		}

		public short Amount
		{
			get
			{
				return amount;
			}
			set
			{
				amount = value;
			}
		}

		public ModulatorType SourceModulationAmount
		{
			get
			{
				return sourceModulationAmount;
			}
			set
			{
				sourceModulationAmount = value;
			}
		}

		public TransformEnum SourceTransform
		{
			get
			{
				return sourceTransform;
			}
			set
			{
				sourceTransform = value;
			}
		}

		public override string ToString()
		{
			return $"Modulator {sourceModulationData} {destinationGenerator} {amount} {sourceModulationAmount} {sourceTransform}";
		}
	}
	internal class ModulatorBuilder : StructureBuilder<Modulator>
	{
		public override int Length => 10;

		public Modulator[] Modulators => data.ToArray();

		public override Modulator Read(BinaryReader br)
		{
			Modulator modulator = new Modulator();
			modulator.SourceModulationData = new ModulatorType(br.ReadUInt16());
			modulator.DestinationGenerator = (GeneratorEnum)br.ReadUInt16();
			modulator.Amount = br.ReadInt16();
			modulator.SourceModulationAmount = new ModulatorType(br.ReadUInt16());
			modulator.SourceTransform = (TransformEnum)br.ReadUInt16();
			data.Add(modulator);
			return modulator;
		}

		public override void Write(BinaryWriter bw, Modulator o)
		{
		}
	}
	public enum ControllerSourceEnum
	{
		NoController = 0,
		NoteOnVelocity = 2,
		NoteOnKeyNumber = 3,
		PolyPressure = 10,
		ChannelPressure = 13,
		PitchWheel = 14,
		PitchWheelSensitivity = 16
	}
	public enum SourceTypeEnum
	{
		Linear,
		Concave,
		Convex,
		Switch
	}
	public class ModulatorType
	{
		private bool polarity;

		private bool direction;

		private bool midiContinuousController;

		private ControllerSourceEnum controllerSource;

		private SourceTypeEnum sourceType;

		private ushort midiContinuousControllerNumber;

		internal ModulatorType(ushort raw)
		{
			polarity = (raw & 0x200) == 512;
			direction = (raw & 0x100) == 256;
			midiContinuousController = (raw & 0x80) == 128;
			sourceType = (SourceTypeEnum)((raw & 0xFC00) >> 10);
			controllerSource = (ControllerSourceEnum)(raw & 0x7F);
			midiContinuousControllerNumber = (ushort)(raw & 0x7Fu);
		}

		public override string ToString()
		{
			if (midiContinuousController)
			{
				return $"{sourceType} CC{midiContinuousControllerNumber}";
			}
			return $"{sourceType} {controllerSource}";
		}
	}
	public class Preset
	{
		private string name;

		private ushort patchNumber;

		private ushort bank;

		internal ushort startPresetZoneIndex;

		internal ushort endPresetZoneIndex;

		internal uint library;

		internal uint genre;

		internal uint morphology;

		private Zone[] zones;

		public string Name
		{
			get
			{
				return name;
			}
			set
			{
				name = value;
			}
		}

		public ushort PatchNumber
		{
			get
			{
				return patchNumber;
			}
			set
			{
				patchNumber = value;
			}
		}

		public ushort Bank
		{
			get
			{
				return bank;
			}
			set
			{
				bank = value;
			}
		}

		public Zone[] Zones
		{
			get
			{
				return zones;
			}
			set
			{
				zones = value;
			}
		}

		public override string ToString()
		{
			return $"{bank}-{patchNumber} {name}";
		}
	}
	internal class PresetBuilder : StructureBuilder<Preset>
	{
		private Preset lastPreset;

		public override int Length => 38;

		public Preset[] Presets => data.ToArray();

		public override Preset Read(BinaryReader br)
		{
			Preset preset = new Preset();
			string text = Encoding.UTF8.GetString(br.ReadBytes(20), 0, 20);
			if (text.IndexOf('\0') >= 0)
			{
				text = text.Substring(0, text.IndexOf('\0'));
			}
			preset.Name = text;
			preset.PatchNumber = br.ReadUInt16();
			preset.Bank = br.ReadUInt16();
			preset.startPresetZoneIndex = br.ReadUInt16();
			preset.library = br.ReadUInt32();
			preset.genre = br.ReadUInt32();
			preset.morphology = br.ReadUInt32();
			if (lastPreset != null)
			{
				lastPreset.endPresetZoneIndex = (ushort)(preset.startPresetZoneIndex - 1);
			}
			data.Add(preset);
			lastPreset = preset;
			return preset;
		}

		public override void Write(BinaryWriter bw, Preset preset)
		{
		}

		public void LoadZones(Zone[] presetZones)
		{
			for (int i = 0; i < data.Count - 1; i++)
			{
				Preset preset = data[i];
				preset.Zones = new Zone[preset.endPresetZoneIndex - preset.startPresetZoneIndex + 1];
				Array.Copy(presetZones, preset.startPresetZoneIndex, preset.Zones, 0, preset.Zones.Length);
			}
			data.RemoveAt(data.Count - 1);
		}
	}
	public class PresetsChunk
	{
		private PresetBuilder presetHeaders = new PresetBuilder();

		private ZoneBuilder presetZones = new ZoneBuilder();

		private ModulatorBuilder presetZoneModulators = new ModulatorBuilder();

		private GeneratorBuilder presetZoneGenerators = new GeneratorBuilder();

		private InstrumentBuilder instruments = new InstrumentBuilder();

		private ZoneBuilder instrumentZones = new ZoneBuilder();

		private ModulatorBuilder instrumentZoneModulators = new ModulatorBuilder();

		private GeneratorBuilder instrumentZoneGenerators = new GeneratorBuilder();

		private SampleHeaderBuilder sampleHeaders = new SampleHeaderBuilder();

		public Preset[] Presets => presetHeaders.Presets;

		public Instrument[] Instruments => instruments.Instruments;

		public SampleHeader[] SampleHeaders => sampleHeaders.SampleHeaders;

		internal PresetsChunk(RiffChunk chunk)
		{
			string text = chunk.ReadChunkID();
			if (text != "pdta")
			{
				throw new InvalidDataException($"Not a presets data chunk ({text})");
			}
			RiffChunk nextSubChunk;
			while ((nextSubChunk = chunk.GetNextSubChunk()) != null)
			{
				switch (nextSubChunk.ChunkID)
				{
				case "PHDR":
				case "phdr":
					nextSubChunk.GetDataAsStructureArray(presetHeaders);
					break;
				case "PBAG":
				case "pbag":
					nextSubChunk.GetDataAsStructureArray(presetZones);
					break;
				case "PMOD":
				case "pmod":
					nextSubChunk.GetDataAsStructureArray(presetZoneModulators);
					break;
				case "PGEN":
				case "pgen":
					nextSubChunk.GetDataAsStructureArray(presetZoneGenerators);
					break;
				case "INST":
				case "inst":
					nextSubChunk.GetDataAsStructureArray(instruments);
					break;
				case "IBAG":
				case "ibag":
					nextSubChunk.GetDataAsStructureArray(instrumentZones);
					break;
				case "IMOD":
				case "imod":
					nextSubChunk.GetDataAsStructureArray(instrumentZoneModulators);
					break;
				case "IGEN":
				case "igen":
					nextSubChunk.GetDataAsStructureArray(instrumentZoneGenerators);
					break;
				case "SHDR":
				case "shdr":
					nextSubChunk.GetDataAsStructureArray(sampleHeaders);
					break;
				default:
					throw new InvalidDataException($"Unknown chunk type {nextSubChunk.ChunkID}");
				}
			}
			instrumentZoneGenerators.Load(sampleHeaders.SampleHeaders);
			instrumentZones.Load(instrumentZoneModulators.Modulators, instrumentZoneGenerators.Generators);
			instruments.LoadZones(instrumentZones.Zones);
			presetZoneGenerators.Load(instruments.Instruments);
			presetZones.Load(presetZoneModulators.Modulators, presetZoneGenerators.Generators);
			presetHeaders.LoadZones(presetZones.Zones);
			sampleHeaders.RemoveEOS();
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Preset Headers:\r\n");
			Preset[] presets = presetHeaders.Presets;
			foreach (Preset arg in presets)
			{
				stringBuilder.AppendFormat("{0}\r\n", arg);
			}
			stringBuilder.Append("Instruments:\r\n");
			Instrument[] array = instruments.Instruments;
			foreach (Instrument arg2 in array)
			{
				stringBuilder.AppendFormat("{0}\r\n", arg2);
			}
			return stringBuilder.ToString();
		}
	}
	internal class RiffChunk
	{
		private string chunkID;

		private uint chunkSize;

		private long dataOffset;

		private BinaryReader riffFile;

		public string ChunkID
		{
			get
			{
				return chunkID;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("ChunkID may not be null");
				}
				if (value.Length != 4)
				{
					throw new ArgumentException("ChunkID must be four characters");
				}
				chunkID = value;
			}
		}

		public uint ChunkSize => chunkSize;

		public long DataOffset => dataOffset;

		public static RiffChunk GetTopLevelChunk(BinaryReader file)
		{
			RiffChunk riffChunk = new RiffChunk(file);
			riffChunk.ReadChunk();
			return riffChunk;
		}

		private RiffChunk(BinaryReader file)
		{
			riffFile = file;
			chunkID = "????";
			chunkSize = 0u;
			dataOffset = 0L;
		}

		public string ReadChunkID()
		{
			byte[] array = riffFile.ReadBytes(4);
			if (array.Length != 4)
			{
				throw new InvalidDataException("Couldn't read Chunk ID");
			}
			return ByteEncoding.Instance.GetString(array, 0, array.Length);
		}

		private void ReadChunk()
		{
			chunkID = ReadChunkID();
			chunkSize = riffFile.ReadUInt32();
			dataOffset = riffFile.BaseStream.Position;
		}

		public RiffChunk GetNextSubChunk()
		{
			if (riffFile.BaseStream.Position + 8 < dataOffset + chunkSize)
			{
				RiffChunk riffChunk = new RiffChunk(riffFile);
				riffChunk.ReadChunk();
				return riffChunk;
			}
			return null;
		}

		public byte[] GetData()
		{
			riffFile.BaseStream.Position = dataOffset;
			byte[] array = riffFile.ReadBytes((int)chunkSize);
			if (array.Length != chunkSize)
			{
				throw new InvalidDataException($"Couldn't read chunk's data Chunk: {this}, read {array.Length} bytes");
			}
			return array;
		}

		public string GetDataAsString()
		{
			byte[] data = GetData();
			if (data == null)
			{
				return null;
			}
			return ByteEncoding.Instance.GetString(data, 0, data.Length);
		}

		public T GetDataAsStructure<T>(StructureBuilder<T> s)
		{
			riffFile.BaseStream.Position = dataOffset;
			if (s.Length != chunkSize)
			{
				throw new InvalidDataException($"Chunk size is: {chunkSize} so can't read structure of: {s.Length}");
			}
			return s.Read(riffFile);
		}

		public T[] GetDataAsStructureArray<T>(StructureBuilder<T> s)
		{
			riffFile.BaseStream.Position = dataOffset;
			if (chunkSize % s.Length != 0L)
			{
				throw new InvalidDataException($"Chunk size is: {chunkSize} not a multiple of structure size: {s.Length}");
			}
			int num = (int)(chunkSize / s.Length);
			T[] array = new T[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = s.Read(riffFile);
			}
			return array;
		}

		public override string ToString()
		{
			return $"RiffChunk ID: {ChunkID} Size: {ChunkSize} Data Offset: {DataOffset}";
		}
	}
	internal class SampleDataChunk
	{
		private byte[] sampleData;

		public byte[] SampleData => sampleData;

		public SampleDataChunk(RiffChunk chunk)
		{
			string text = chunk.ReadChunkID();
			if (text != "sdta")
			{
				throw new InvalidDataException($"Not a sample data chunk ({text})");
			}
			sampleData = chunk.GetData();
		}
	}
	public class SampleHeader
	{
		public string SampleName;

		public uint Start;

		public uint End;

		public uint StartLoop;

		public uint EndLoop;

		public uint SampleRate;

		public byte OriginalPitch;

		public sbyte PitchCorrection;

		public ushort SampleLink;

		public SFSampleLink SFSampleLink;

		public override string ToString()
		{
			return SampleName;
		}
	}
	internal class SampleHeaderBuilder : StructureBuilder<SampleHeader>
	{
		public override int Length => 46;

		public SampleHeader[] SampleHeaders => data.ToArray();

		public override SampleHeader Read(BinaryReader br)
		{
			SampleHeader sampleHeader = new SampleHeader();
			byte[] array = br.ReadBytes(20);
			sampleHeader.SampleName = ByteEncoding.Instance.GetString(array, 0, array.Length);
			sampleHeader.Start = br.ReadUInt32();
			sampleHeader.End = br.ReadUInt32();
			sampleHeader.StartLoop = br.ReadUInt32();
			sampleHeader.EndLoop = br.ReadUInt32();
			sampleHeader.SampleRate = br.ReadUInt32();
			sampleHeader.OriginalPitch = br.ReadByte();
			sampleHeader.PitchCorrection = br.ReadSByte();
			sampleHeader.SampleLink = br.ReadUInt16();
			sampleHeader.SFSampleLink = (SFSampleLink)br.ReadUInt16();
			data.Add(sampleHeader);
			return sampleHeader;
		}

		public override void Write(BinaryWriter bw, SampleHeader sampleHeader)
		{
		}

		internal void RemoveEOS()
		{
			data.RemoveAt(data.Count - 1);
		}
	}
	public enum SampleMode
	{
		NoLoop,
		LoopContinuously,
		ReservedNoLoop,
		LoopAndContinue
	}
	public enum SFSampleLink : ushort
	{
		MonoSample = 1,
		RightSample = 2,
		LeftSample = 4,
		LinkedSample = 8,
		RomMonoSample = 32769,
		RomRightSample = 32770,
		RomLeftSample = 32772,
		RomLinkedSample = 32776
	}
	public class SFVersion
	{
		private short major;

		private short minor;

		public short Major
		{
			get
			{
				return major;
			}
			set
			{
				major = value;
			}
		}

		public short Minor
		{
			get
			{
				return minor;
			}
			set
			{
				minor = value;
			}
		}
	}
	internal class SFVersionBuilder : StructureBuilder<SFVersion>
	{
		public override int Length => 4;

		public override SFVersion Read(BinaryReader br)
		{
			SFVersion sFVersion = new SFVersion();
			sFVersion.Major = br.ReadInt16();
			sFVersion.Minor = br.ReadInt16();
			data.Add(sFVersion);
			return sFVersion;
		}

		public override void Write(BinaryWriter bw, SFVersion v)
		{
			bw.Write(v.Major);
			bw.Write(v.Minor);
		}
	}
	public class SoundFont
	{
		private InfoChunk info;

		private PresetsChunk presetsChunk;

		private SampleDataChunk sampleData;

		public InfoChunk FileInfo => info;

		public Preset[] Presets => presetsChunk.Presets;

		public Instrument[] Instruments => presetsChunk.Instruments;

		public SampleHeader[] SampleHeaders => presetsChunk.SampleHeaders;

		public byte[] SampleData => sampleData.SampleData;

		public SoundFont(string fileName)
			: this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
		{
		}

		public SoundFont(Stream sfFile)
		{
			using (sfFile)
			{
				RiffChunk topLevelChunk = RiffChunk.GetTopLevelChunk(new BinaryReader(sfFile));
				if (topLevelChunk.ChunkID == "RIFF")
				{
					string text = topLevelChunk.ReadChunkID();
					if (text != "sfbk")
					{
						throw new InvalidDataException($"Not a SoundFont ({text})");
					}
					RiffChunk nextSubChunk = topLevelChunk.GetNextSubChunk();
					if (nextSubChunk.ChunkID == "LIST")
					{
						info = new InfoChunk(nextSubChunk);
						RiffChunk nextSubChunk2 = topLevelChunk.GetNextSubChunk();
						sampleData = new SampleDataChunk(nextSubChunk2);
						nextSubChunk2 = topLevelChunk.GetNextSubChunk();
						presetsChunk = new PresetsChunk(nextSubChunk2);
						return;
					}
					throw new InvalidDataException($"Not info list found ({nextSubChunk.ChunkID})");
				}
				throw new InvalidDataException("Not a RIFF file");
			}
		}

		public override string ToString()
		{
			return $"Info Chunk:\r\n{info}\r\nPresets Chunk:\r\n{presetsChunk}";
		}
	}
	internal abstract class StructureBuilder<T>
	{
		protected List<T> data;

		public abstract int Length { get; }

		public T[] Data => data.ToArray();

		public StructureBuilder()
		{
			Reset();
		}

		public abstract T Read(BinaryReader br);

		public abstract void Write(BinaryWriter bw, T o);

		public void Reset()
		{
			data = new List<T>();
		}
	}
	public class Zone
	{
		internal ushort generatorIndex;

		internal ushort modulatorIndex;

		internal ushort generatorCount;

		internal ushort modulatorCount;

		private Modulator[] modulators;

		private Generator[] generators;

		public Modulator[] Modulators
		{
			get
			{
				return modulators;
			}
			set
			{
				modulators = value;
			}
		}

		public Generator[] Generators
		{
			get
			{
				return generators;
			}
			set
			{
				generators = value;
			}
		}

		public override string ToString()
		{
			return $"Zone {generatorCount} Gens:{generatorIndex} {modulatorCount} Mods:{modulatorIndex}";
		}
	}
	internal class ZoneBuilder : StructureBuilder<Zone>
	{
		private Zone lastZone;

		public Zone[] Zones => data.ToArray();

		public override int Length => 4;

		public override Zone Read(BinaryReader br)
		{
			Zone zone = new Zone();
			zone.generatorIndex = br.ReadUInt16();
			zone.modulatorIndex = br.ReadUInt16();
			if (lastZone != null)
			{
				lastZone.generatorCount = (ushort)(zone.generatorIndex - lastZone.generatorIndex);
				lastZone.modulatorCount = (ushort)(zone.modulatorIndex - lastZone.modulatorIndex);
			}
			data.Add(zone);
			lastZone = zone;
			return zone;
		}

		public override void Write(BinaryWriter bw, Zone zone)
		{
		}

		public void Load(Modulator[] modulators, Generator[] generators)
		{
			for (int i = 0; i < data.Count - 1; i++)
			{
				Zone zone = data[i];
				zone.Generators = new Generator[zone.generatorCount];
				Array.Copy(generators, zone.generatorIndex, zone.Generators, 0, zone.generatorCount);
				zone.Modulators = new Modulator[zone.modulatorCount];
				Array.Copy(modulators, zone.modulatorIndex, zone.Modulators, 0, zone.modulatorCount);
			}
			data.RemoveAt(data.Count - 1);
		}
	}
}
namespace NAudio.Sfz
{
	internal enum SfzParseState
	{
		Initial,
		Region
	}
	internal class Group
	{
	}
	internal class Region
	{
	}
	internal class SfzFileReader
	{
		public SfzFileReader(string fileName)
		{
			new StringBuilder();
			using StreamReader streamReader = new StreamReader(fileName);
			List<Region> list = new List<Region>();
			Region region = null;
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			int num = 0;
			string text;
			while ((text = streamReader.ReadLine()) != null)
			{
				num++;
				int num2 = text.IndexOf('/');
				if (num2 != -1)
				{
					text = text.Substring(num2);
				}
				for (int i = 0; i < text.Length; i++)
				{
					char c = text[i];
					if (char.IsWhiteSpace(c))
					{
						if (stringBuilder.Length != 0)
						{
							if (stringBuilder2.Length == 0)
							{
								throw new FormatException($"Invalid Whitespace Line {num}, Char {i}");
							}
							stringBuilder2.Append(c);
						}
					}
					else
					{
						if (c == '=' || c != '<')
						{
							continue;
						}
						if (text.Substring(i).StartsWith("<region>"))
						{
							if (region != null)
							{
								list.Add(region);
							}
							region = new Region();
							stringBuilder.Length = 0;
							stringBuilder2.Length = 0;
							i += 7;
							continue;
						}
						if (!text.Substring(i).StartsWith("<group>"))
						{
							throw new FormatException($"Unrecognised section Line {num}, Char {i}");
						}
						if (region != null)
						{
							list.Add(region);
						}
						stringBuilder.Length = 0;
						stringBuilder2.Length = 0;
						region = null;
						new Group();
						i += 6;
					}
				}
			}
		}
	}
}
namespace NAudio.Dmo
{
	internal class AudioMediaSubtypes
	{
		public static readonly Guid MEDIASUBTYPE_PCM = new Guid("00000001-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIASUBTYPE_PCMAudioObsolete = new Guid("e436eb8a-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_MPEG1Packet = new Guid("e436eb80-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_MPEG1Payload = new Guid("e436eb81-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_MPEG2_AUDIO = new Guid("e06d802b-db46-11cf-b4d1-00805f6cbbea");

		public static readonly Guid MEDIASUBTYPE_DVD_LPCM_AUDIO = new Guid("e06d8032-db46-11cf-b4d1-00805f6cbbea");

		public static readonly Guid MEDIASUBTYPE_DRM_Audio = new Guid("00000009-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_IEEE_FLOAT = new Guid("00000003-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_DOLBY_AC3 = new Guid("e06d802c-db46-11cf-b4d1-00805f6cbbea");

		public static readonly Guid MEDIASUBTYPE_DOLBY_AC3_SPDIF = new Guid("00000092-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_RAW_SPORT = new Guid("00000240-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_SPDIF_TAG_241h = new Guid("00000241-0000-0010-8000-00aa00389b71");

		public static readonly Guid WMMEDIASUBTYPE_MP3 = new Guid("00000055-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIASUBTYPE_WAVE = new Guid("e436eb8b-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_AU = new Guid("e436eb8c-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_AIFF = new Guid("e436eb8d-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid[] AudioSubTypes = new Guid[13]
		{
			MEDIASUBTYPE_PCM, MEDIASUBTYPE_PCMAudioObsolete, MEDIASUBTYPE_MPEG1Packet, MEDIASUBTYPE_MPEG1Payload, MEDIASUBTYPE_MPEG2_AUDIO, MEDIASUBTYPE_DVD_LPCM_AUDIO, MEDIASUBTYPE_DRM_Audio, MEDIASUBTYPE_IEEE_FLOAT, MEDIASUBTYPE_DOLBY_AC3, MEDIASUBTYPE_DOLBY_AC3_SPDIF,
			MEDIASUBTYPE_RAW_SPORT, MEDIASUBTYPE_SPDIF_TAG_241h, WMMEDIASUBTYPE_MP3
		};

		public static readonly string[] AudioSubTypeNames = new string[13]
		{
			"PCM", "PCM Obsolete", "MPEG1Packet", "MPEG1Payload", "MPEG2_AUDIO", "DVD_LPCM_AUDIO", "DRM_Audio", "IEEE_FLOAT", "DOLBY_AC3", "DOLBY_AC3_SPDIF",
			"RAW_SPORT", "SPDIF_TAG_241h", "MP3"
		};

		public static string GetAudioSubtypeName(Guid subType)
		{
			for (int i = 0; i < AudioSubTypes.Length; i++)
			{
				if (subType == AudioSubTypes[i])
				{
					return AudioSubTypeNames[i];
				}
			}
			return subType.ToString();
		}
	}
	public class DmoDescriptor
	{
		public string Name { get; private set; }

		public Guid Clsid { get; private set; }

		public DmoDescriptor(string name, Guid clsid)
		{
			Name = name;
			Clsid = clsid;
		}
	}
	public class DmoEnumerator
	{
		public static IEnumerable<DmoDescriptor> GetAudioEffectNames()
		{
			return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_EFFECT);
		}

		public static IEnumerable<DmoDescriptor> GetAudioEncoderNames()
		{
			return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_ENCODER);
		}

		public static IEnumerable<DmoDescriptor> GetAudioDecoderNames()
		{
			return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_DECODER);
		}

		private static IEnumerable<DmoDescriptor> GetDmos(Guid category)
		{
			Marshal.ThrowExceptionForHR(DmoInterop.DMOEnum(ref category, DmoEnumFlags.None, 0, null, 0, null, out var enumDmo));
			int itemsFetched;
			do
			{
				enumDmo.Next(1, out var clsid, out var name, out itemsFetched);
				if (itemsFetched == 1)
				{
					string name2 = Marshal.PtrToStringUni(name);
					Marshal.FreeCoTaskMem(name);
					yield return new DmoDescriptor(name2, clsid);
				}
			}
			while (itemsFetched > 0);
		}
	}
	[Flags]
	internal enum DmoEnumFlags
	{
		None = 0,
		DMO_ENUMF_INCLUDE_KEYED = 1
	}
	internal static class DmoGuids
	{
		public static readonly Guid DMOCATEGORY_AUDIO_DECODER = new Guid("57f2db8b-e6bb-4513-9d43-dcd2a6593125");

		public static readonly Guid DMOCATEGORY_AUDIO_ENCODER = new Guid("33D9A761-90C8-11d0-BD43-00A0C911CE86");

		public static readonly Guid DMOCATEGORY_VIDEO_DECODER = new Guid("4a69b442-28be-4991-969c-b500adf5d8a8");

		public static readonly Guid DMOCATEGORY_VIDEO_ENCODER = new Guid("33D9A760-90C8-11d0-BD43-00A0C911CE86");

		public static readonly Guid DMOCATEGORY_AUDIO_EFFECT = new Guid("f3602b3f-0592-48df-a4cd-674721e7ebeb");

		public static readonly Guid DMOCATEGORY_VIDEO_EFFECT = new Guid("d990ee14-776c-4723-be46-3da2f56f10b9");

		public static readonly Guid DMOCATEGORY_AUDIO_CAPTURE_EFFECT = new Guid("f665aaba-3e09-4920-aa5f-219811148f09");
	}
	internal static class DmoMediaTypeGuids
	{
		public static readonly Guid FORMAT_None = new Guid("0F6417D6-C318-11D0-A43F-00A0C9223196");

		public static readonly Guid FORMAT_VideoInfo = new Guid("05589f80-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_VideoInfo2 = new Guid("F72A76A0-EB0A-11d0-ACE4-0000C0CC16BA");

		public static readonly Guid FORMAT_WaveFormatEx = new Guid("05589f81-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_MPEGVideo = new Guid("05589f82-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_MPEGStreams = new Guid("05589f83-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_DvInfo = new Guid("05589f84-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_525WSS = new Guid("C7ECF04D-4582-4869-9ABB-BFB523B62EDF");
	}
	internal enum DmoHResults
	{
		DMO_E_INVALIDSTREAMINDEX = -2147220991,
		DMO_E_INVALIDTYPE,
		DMO_E_TYPE_NOT_SET,
		DMO_E_NOTACCEPTING,
		DMO_E_TYPE_NOT_ACCEPTED,
		DMO_E_NO_MORE_ITEMS
	}
	internal static class DmoInterop
	{
		[DllImport("msdmo.dll")]
		public static extern int DMOEnum([In] ref Guid guidCategory, DmoEnumFlags flags, int inTypes, [In] DmoPartialMediaType[] inTypesArray, int outTypes, [In] DmoPartialMediaType[] outTypesArray, out IEnumDmo enumDmo);

		[DllImport("msdmo.dll")]
		public static extern int MoFreeMediaType([In] ref DmoMediaType mediaType);

		[DllImport("msdmo.dll")]
		public static extern int MoInitMediaType([In][Out] ref DmoMediaType mediaType, int formatBlockBytes);

		[DllImport("msdmo.dll")]
		public static extern int DMOGetName([In] ref Guid clsidDMO, [Out] StringBuilder name);
	}
	internal struct DmoPartialMediaType
	{
		private Guid type;

		private Guid subtype;

		public Guid Type
		{
			get
			{
				return type;
			}
			internal set
			{
				type = value;
			}
		}

		public Guid Subtype
		{
			get
			{
				return subtype;
			}
			internal set
			{
				subtype = value;
			}
		}
	}
	[ComImport]
	[SuppressUnmanagedCodeSecurity]
	[Guid("6d6cbb60-a223-44aa-842f-a2f06750be6d")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IMediaParamInfo
	{
		[PreserveSig]
		int GetParamCount(out int paramCount);

		[PreserveSig]
		int GetParamInfo(int paramIndex, ref MediaParamInfo paramInfo);

		[PreserveSig]
		int GetParamText(int paramIndex, out IntPtr paramText);

		[PreserveSig]
		int GetNumTimeFormats(out int numTimeFormats);

		[PreserveSig]
		int GetSupportedTimeFormat(int formatIndex, out Guid guidTimeFormat);

		[PreserveSig]
		int GetCurrentTimeFormat(out Guid guidTimeFormat, out int mediaTimeData);
	}
	[Guid("E7E9984F-F09F-4da4-903F-6E2E0EFE56B5")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IWMResamplerProps
	{
		int SetHalfFilterLength(int outputQuality);

		int SetUserChannelMtx([In] float[] channelConversionMatrix);
	}
	public class MediaBuffer : IMediaBuffer, IDisposable
	{
		private IntPtr buffer;

		private int length;

		private int maxLength;

		public int Length
		{
			get
			{
				return length;
			}
			set
			{
				if (length > maxLength)
				{
					throw new ArgumentException("Cannot be greater than maximum buffer size");
				}
				length = value;
			}
		}

		public MediaBuffer(int maxLength)
		{
			buffer = Marshal.AllocCoTaskMem(maxLength);
			this.maxLength = maxLength;
		}

		public void Dispose()
		{
			if (buffer != IntPtr.Zero)
			{
				Marshal.FreeCoTaskMem(buffer);
				buffer = IntPtr.Zero;
				GC.SuppressFinalize(this);
			}
		}

		~MediaBuffer()
		{
			Dispose();
		}

		int IMediaBuffer.SetLength(int length)
		{
			if (length > maxLength)
			{
				return -2147483645;
			}
			this.length = length;
			return 0;
		}

		int IMediaBuffer.GetMaxLength(out int maxLength)
		{
			maxLength = this.maxLength;
			return 0;
		}

		int IMediaBuffer.GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer)
		{
			if (bufferPointerPointer != IntPtr.Zero)
			{
				Marshal.WriteIntPtr(bufferPointerPointer, buffer);
			}
			if (validDataLengthPointer != IntPtr.Zero)
			{
				Marshal.WriteInt32(validDataLengthPointer, length);
			}
			return 0;
		}

		public void LoadData(byte[] data, int bytes)
		{
			Length = bytes;
			Marshal.Copy(data, 0, buffer, bytes);
		}

		public void RetrieveData(byte[] data, int offset)
		{
			Marshal.Copy(buffer, data, offset, Length);
		}
	}
	public class MediaObject : IDisposable
	{
		private IMediaObject mediaObject;

		private int inputStreams;

		private int outputStreams;

		public int InputStreamCount => inputStreams;

		public int OutputStreamCount => outputStreams;

		internal MediaObject(IMediaObject mediaObject)
		{
			this.mediaObject = mediaObject;
			mediaObject.GetStreamCount(out inputStreams, out outputStreams);
		}

		public DmoMediaType? GetInputType(int inputStream, int inputTypeIndex)
		{
			try
			{
				if (mediaObject.GetInputType(inputStream, inputTypeIndex, out var mediaType) == 0)
				{
					DmoInterop.MoFreeMediaType(ref mediaType);
					return mediaType;
				}
			}
			catch (COMException exception)
			{
				if (exception.GetHResult() != -2147220986)
				{
					throw;
				}
			}
			return null;
		}

		public DmoMediaType? GetOutputType(int outputStream, int outputTypeIndex)
		{
			try
			{
				if (mediaObject.GetOutputType(outputStream, outputTypeIndex, out var mediaType) == 0)
				{
					DmoInterop.MoFreeMediaType(ref mediaType);
					return mediaType;
				}
			}
			catch (COMException exception)
			{
				if (exception.GetHResult() != -2147220986)
				{
					throw;
				}
			}
			return null;
		}

		public DmoMediaType GetOutputCurrentType(int outputStreamIndex)
		{
			DmoMediaType mediaType;
			int outputCurrentType = mediaObject.GetOutputCurrentType(outputStreamIndex, out mediaType);
			switch (outputCurrentType)
			{
			case 0:
				DmoInterop.MoFreeMediaType(ref mediaType);
				return mediaType;
			case -2147220989:
				throw new InvalidOperationException("Media type was not set.");
			default:
				throw Marshal.GetExceptionForHR(outputCurrentType);
			}
		}

		public IEnumerable<DmoMediaType> GetInputTypes(int inputStreamIndex)
		{
			int typeIndex = 0;
			while (true)
			{
				DmoMediaType? inputType;
				DmoMediaType? mediaType = (inputType = GetInputType(inputStreamIndex, typeIndex));
				inputType = inputType;
				if (inputType.HasValue)
				{
					yield return mediaType.Value;
					typeIndex++;
					continue;
				}
				break;
			}
		}

		public IEnumerable<DmoMediaType> GetOutputTypes(int outputStreamIndex)
		{
			int typeIndex = 0;
			while (true)
			{
				DmoMediaType? outputType;
				DmoMediaType? mediaType = (outputType = GetOutputType(outputStreamIndex, typeIndex));
				outputType = outputType;
				if (outputType.HasValue)
				{
					yield return mediaType.Value;
					typeIndex++;
					continue;
				}
				break;
			}
		}

		public bool SupportsInputType(int inputStreamIndex, DmoMediaType mediaType)
		{
			return SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
		}

		private bool SetInputType(int inputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags)
		{
			switch (mediaObject.SetInputType(inputStreamIndex, ref mediaType, flags))
			{
			case -2147220991:
				throw new ArgumentException("Invalid stream index");
			default:
				_ = -2147220987;
				return false;
			case 0:
				return true;
			}
		}

		public void SetInputType(int inputStreamIndex, DmoMediaType mediaType)
		{
			if (!SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None))
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public void SetInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool num = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None);
			DmoInterop.MoFreeMediaType(ref mediaType);
			if (!num)
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public bool SupportsInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool result = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
			DmoInterop.MoFreeMediaType(ref mediaType);
			return result;
		}

		private DmoMediaType CreateDmoMediaTypeForWaveFormat(WaveFormat waveFormat)
		{
			DmoMediaType mediaType = default(DmoMediaType);
			int formatBlockBytes = Marshal.SizeOf((object)waveFormat);
			DmoInterop.MoInitMediaType(ref mediaType, formatBlockBytes);
			mediaType.SetWaveFormat(waveFormat);
			return mediaType;
		}

		public bool SupportsOutputType(int outputStreamIndex, DmoMediaType mediaType)
		{
			return SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
		}

		public bool SupportsOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool result = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
			DmoInterop.MoFreeMediaType(ref mediaType);
			return result;
		}

		private bool SetOutputType(int outputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags)
		{
			int num = mediaObject.SetOutputType(outputStreamIndex, ref mediaType, flags);
			return num switch
			{
				-2147220987 => false, 
				0 => true, 
				_ => throw Marshal.GetExceptionForHR(num), 
			};
		}

		public void SetOutputType(int outputStreamIndex, DmoMediaType mediaType)
		{
			if (!SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None))
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public void SetOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool num = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None);
			DmoInterop.MoFreeMediaType(ref mediaType);
			if (!num)
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public MediaObjectSizeInfo GetInputSizeInfo(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetInputSizeInfo(inputStreamIndex, out var size, out var maxLookahead, out var alignment));
			return new MediaObjectSizeInfo(size, maxLookahead, alignment);
		}

		public MediaObjectSizeInfo GetOutputSizeInfo(int outputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetOutputSizeInfo(outputStreamIndex, out var size, out var alignment));
			return new MediaObjectSizeInfo(size, 0, alignment);
		}

		public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long timestamp, long duration)
		{
			Marshal.ThrowExceptionForHR(mediaObject.ProcessInput(inputStreamIndex, mediaBuffer, flags, timestamp, duration));
		}

		public void ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, DmoOutputDataBuffer[] outputBuffers)
		{
			Marshal.ThrowExceptionForHR(mediaObject.ProcessOutput(flags, outputBufferCount, outputBuffers, out var _));
		}

		public void AllocateStreamingResources()
		{
			Marshal.ThrowExceptionForHR(mediaObject.AllocateStreamingResources());
		}

		public void FreeStreamingResources()
		{
			Marshal.ThrowExceptionForHR(mediaObject.FreeStreamingResources());
		}

		public long GetInputMaxLatency(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetInputMaxLatency(inputStreamIndex, out var referenceTimeMaxLatency));
			return referenceTimeMaxLatency;
		}

		public void Flush()
		{
			Marshal.ThrowExceptionForHR(mediaObject.Flush());
		}

		public void Discontinuity(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.Discontinuity(inputStreamIndex));
		}

		public bool IsAcceptingData(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetInputStatus(inputStreamIndex, out var flags));
			return (flags & DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA) == DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA;
		}

		public void Dispose()
		{
			if (mediaObject != null)
			{
				Marshal.ReleaseComObject(mediaObject);
				mediaObject = null;
			}
		}
	}
	public class MediaObjectSizeInfo
	{
		public int Size { get; private set; }

		public int MaxLookahead { get; private set; }

		public int Alignment { get; private set; }

		public MediaObjectSizeInfo(int size, int maxLookahead, int alignment)
		{
			Size = size;
			MaxLookahead = maxLookahead;
			Alignment = alignment;
		}

		public override string ToString()
		{
			return $"Size: {Size}, Alignment {Alignment}, MaxLookahead {MaxLookahead}";
		}
	}
	internal struct MediaParamInfo
	{
		public MediaParamType mpType;

		public MediaParamCurveType mopCaps;

		public float mpdMinValue;

		public float mpdMaxValue;

		public float mpdNeutralValue;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
		public string szUnitText;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
		public string szLabel;
	}
	internal enum MediaParamType
	{
		Int,
		Float,
		Bool,
		Enum,
		Max
	}
	[Flags]
	internal enum MediaParamCurveType
	{
		MP_CURVE_JUMP = 1,
		MP_CURVE_LINEAR = 2,
		MP_CURVE_SQUARE = 4,
		MP_CURVE_INVSQUARE = 8,
		MP_CURVE_SINE = 0x10
	}
	internal static class MediaTypes
	{
		public static readonly Guid MEDIATYPE_AnalogAudio = new Guid("0482DEE1-7817-11cf-8a03-00aa006ecb65");

		public static readonly Guid MEDIATYPE_AnalogVideo = new Guid("0482DDE1-7817-11cf-8A03-00AA006ECB65");

		public static readonly Guid MEDIATYPE_Audio = new Guid("73647561-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_AUXLine21Data = new Guid("670AEA80-3A82-11d0-B79B-00AA003767A7");

		public static readonly Guid MEDIATYPE_File = new Guid("656c6966-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Interleaved = new Guid("73766169-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Midi = new Guid("7364696D-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_ScriptCommand = new Guid("73636d64-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Stream = new Guid("e436eb83-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIATYPE_Text = new Guid("73747874-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Timecode = new Guid("0482DEE3-7817-11cf-8a03-00aa006ecb65");

		public static readonly Guid MEDIATYPE_Video = new Guid("73646976-0000-0010-8000-00AA00389B71");

		public static readonly Guid[] MajorTypes = new Guid[12]
		{
			MEDIATYPE_AnalogAudio, MEDIATYPE_AnalogVideo, MEDIATYPE_Audio, MEDIATYPE_AUXLine21Data, MEDIATYPE_File, MEDIATYPE_Interleaved, MEDIATYPE_Midi, MEDIATYPE_ScriptCommand, MEDIATYPE_Stream, MEDIATYPE_Text,
			MEDIATYPE_Timecode, MEDIATYPE_Video
		};

		public static readonly string[] MajorTypeNames = new string[12]
		{
			"Analog Audio", "Analog Video", "Audio", "AUXLine21Data", "File", "Interleaved", "Midi", "ScriptCommand", "Stream", "Text",
			"Timecode", "Video"
		};

		public static string GetMediaTypeName(Guid majorType)
		{
			for (int i = 0; i < MajorTypes.Length; i++)
			{
				if (majorType == MajorTypes[i])
				{
					return MajorTypeNames[i];
				}
			}
			throw new ArgumentException("Major Type not found");
		}
	}
	[ComImport]
	[Guid("bbeea841-0a63-4f52-a7ab-a9b3a84ed38a")]
	internal class WindowsMediaMp3DecoderComObject
	{
	}
	public class WindowsMediaMp3Decoder : IDisposable
	{
		private MediaObject mediaObject;

		private IPropertyStore propertyStoreInterface;

		private WindowsMediaMp3DecoderComObject mediaComObject;

		public MediaObject MediaObject => mediaObject;

		public WindowsMediaMp3Decoder()
		{
			mediaComObject = new WindowsMediaMp3DecoderComObject();
			mediaObject = new MediaObject((IMediaObject)mediaComObject);
			propertyStoreInterface = (IPropertyStore)mediaComObject;
		}

		public void Dispose()
		{
			if (propertyStoreInterface != null)
			{
				Marshal.ReleaseComObject(propertyStoreInterface);
				propertyStoreInterface = null;
			}
			if (mediaObject != null)
			{
				mediaObject.Dispose();
				mediaObject = null;
			}
			if (mediaComObject != null)
			{
				Marshal.ReleaseComObject(mediaComObject);
				mediaComObject = null;
			}
		}
	}
	[Flags]
	public enum DmoInputDataBufferFlags
	{
		None = 0,
		SyncPoint = 1,
		Time = 2,
		TimeLength = 4
	}
	[Flags]
	internal enum DmoInputStatusFlags
	{
		None = 0,
		DMO_INPUT_STATUSF_ACCEPT_DATA = 1
	}
	public struct DmoMediaType
	{
		private Guid majortype;

		private Guid subtype;

		private bool bFixedSizeSamples;

		private bool bTemporalCompression;

		private int lSampleSize;

		private Guid formattype;

		private IntPtr pUnk;

		private int cbFormat;

		private IntPtr pbFormat;

		public Guid MajorType => majortype;

		public string MajorTypeName => MediaTypes.GetMediaTypeName(majortype);

		public Guid SubType => subtype;

		public strin