Decompiled source of VoiceRecognitionAPI v2.0.0

plugins/VoiceRecognitionAPI.dll

Decompiled 10 months ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Speech.Recognition;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using LethalSettings.UI;
using LethalSettings.UI.Components;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using VoiceRecognitionAPI.Patches;
using VoiceRecognitionAPI.Util;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("VoiceRecognitionAPI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+23865624517bd7dd15f907e8e16576f0a7caa773")]
[assembly: AssemblyProduct("VoiceRecognitionAPI")]
[assembly: AssemblyTitle("VoiceRecognitionAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace VoiceRecognitionAPI
{
	public class VoiceRecognitionEngineAlreadyStarted : Exception
	{
		public VoiceRecognitionEngineAlreadyStarted()
		{
		}

		public VoiceRecognitionEngineAlreadyStarted(string message)
			: base(message)
		{
		}
	}
	internal class SpeechHandler
	{
		internal object recognition;

		public static SpeechHandler instance { get; private set; }

		internal SpeechHandler()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			if (instance != null)
			{
				return;
			}
			instance = this;
			if (Voice.phrases.Count == 0)
			{
				VoicePlugin.logger.LogWarning((object)"this is awkward, no mods registered any voice phrases. Cancelling creating the speech recognition engine!");
				instance = null;
				return;
			}
			VoicePlugin.logger.LogInfo((object)"Setting up the recognition engine.");
			recognition = (object)new SpeechRecognitionEngine();
			SpeechRecognitionEngine val = (SpeechRecognitionEngine)recognition;
			try
			{
				val.SetInputToDefaultAudioDevice();
			}
			catch (Exception ex) when (ex is PlatformNotSupportedException || ex is COMException)
			{
				VoicePlugin.logger.LogError((object)("Failed create recognition engine. This is most likely due to your language not supporting Microsoft's speech recognition!\n" + ex));
				instance = null;
				return;
			}
			foreach (string phrase in Voice.phrases)
			{
				VoicePlugin.logger.LogDebug((object)("registering phrase: " + phrase));
			}
			GrammarBuilder val2 = new GrammarBuilder(new Choices(Voice.phrases.ToArray()))
			{
				Culture = val.RecognizerInfo.Culture
			};
			VoicePlugin.logger.LogInfo((object)"Almost done setting up..");
			val.LoadGrammar(new Grammar(val2));
			val.RecognizeCompleted += RecognizeCompletedHandler;
			val.RecognizeAsync();
			VoicePlugin.logger.LogInfo((object)"Speech Recognition Engine is Ready to Go!!");
		}

		private void RecognizeCompletedHandler(object sender, RecognizeCompletedEventArgs e)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			VoicePlugin.logger.LogDebug((object)"Speech Engine event fired.");
			((SpeechRecognitionEngine)recognition).RecognizeAsync();
			if (((AsyncCompletedEventArgs)(object)e).Error != null)
			{
				VoicePlugin.logger.LogError((object)("An error occured during recognition: " + ((AsyncCompletedEventArgs)(object)e).Error));
			}
			else if (e.InitialSilenceTimeout || e.BabbleTimeout)
			{
				VoicePlugin.logger.LogDebug((object)"babble timeout");
			}
			else if (e.Result != null)
			{
				Voice.VoiceRecognition(e);
			}
			else
			{
				VoicePlugin.logger.LogDebug((object)"No result.");
			}
		}
	}
	public static class Voice
	{
		public class VoiceRecognitionEventArgs : EventArgs
		{
			public string Message;

			public float Confidence;
		}

		public const float DEFAULT_MIN_CONFIDENCE = 0.7f;

		internal static List<string> phrases;

		public static bool RECOGNITION_SETUP { get; internal set; }

		internal static event EventHandler<VoiceRecognitionEventArgs> VoiceRecognitionFinishedEvent;

		public static EventHandler<VoiceRecognitionEventArgs> RegisterCustomHandler(EventHandler<VoiceRecognitionEventArgs> callback)
		{
			VoiceRecognitionFinishedEvent += callback;
			return callback;
		}

		public static EventHandler<VoiceRecognitionEventArgs> ListenForPhrase(string phrase, Action<string> callback, float minConfidence = 0.7f)
		{
			return ListenForPhrases(new string[1] { phrase }, callback, minConfidence);
		}

		public static void RegisterPhrases(string[] phrases)
		{
			Voice.phrases.AddRange(phrases);
		}

		public static EventHandler<VoiceRecognitionEventArgs> ListenForPhrases(string[] phrases, Action<string> callback, float minConfidence = 0.7f)
		{
			if (RECOGNITION_SETUP)
			{
				throw new VoiceRecognitionEngineAlreadyStarted("The voice recognition engine was already started. If you are a developer, Make sure to setup your voice recognition patterns in Awake().");
			}
			RegisterPhrases(phrases);
			EventHandler<VoiceRecognitionEventArgs> obj = delegate(object __, VoiceRecognitionEventArgs args)
			{
				if (phrases.Contains(args.Message) && args.Confidence >= minConfidence)
				{
					callback(args.Message);
				}
			};
			VoiceRecognitionFinishedEvent += obj;
			return obj;
		}

		public static void StopListeningForPhrase(EventHandler<VoiceRecognitionEventArgs> callback)
		{
			VoiceRecognitionFinishedEvent -= callback;
		}

		internal static void VoiceRecognition(RecognizeCompletedEventArgs e)
		{
			VoiceRecognitionEventArgs voiceRecognitionEventArgs = new VoiceRecognitionEventArgs();
			voiceRecognitionEventArgs.Message = ((RecognizedPhrase)e.Result).Text;
			voiceRecognitionEventArgs.Confidence = ((RecognizedPhrase)e.Result).Confidence;
			try
			{
				Voice.VoiceRecognitionFinishedEvent(VoicePlugin.instance, voiceRecognitionEventArgs);
			}
			catch (Exception ex)
			{
				VoicePlugin.logger.LogError((object)("Something failed to do something " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		static Voice()
		{
			Voice.VoiceRecognitionFinishedEvent = delegate(object __, VoiceRecognitionEventArgs args)
			{
				VoicePlugin.logger.LogDebug((object)("Recognized: \"" + args.Message + "\" with a confidence of " + args.Confidence));
			};
			phrases = new List<string>();
		}
	}
	[BepInPlugin("me.loaforc.voicerecognitionapi", "VoiceRecognitionAPI", "2.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class VoicePlugin : BaseUnityPlugin
	{
		public const string modGUID = "me.loaforc.voicerecognitionapi";

		public const string modName = "VoiceRecognitionAPI";

		public const string modVersion = "2.0.0";

		private static readonly Harmony harmony = new Harmony("me.loaforc.voicerecognitionapi");

		internal static VoicePlugin instance;

		internal static ManualLogSource logger;

		private void Awake()
		{
			if (!((Object)(object)instance == (Object)null))
			{
				return;
			}
			instance = this;
			logger = Logger.CreateLogSource("me.loaforc.voicerecognitionapi");
			AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
			{
				logger.LogDebug((object)("Importing " + args.Name));
				string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), new AssemblyName(args.Name).Name + ".dll");
				logger.LogDebug((object)("Located at: " + text));
				if (!File.Exists(text))
				{
					return null;
				}
				FileStream fileStream = File.OpenRead(text);
				logger.LogDebug((object)("Found file! Length: " + fileStream.Length));
				byte[] array = new byte[fileStream.Length];
				fileStream.Read(array, 0, array.Length);
				try
				{
					Assembly assembly = Assembly.Load(array);
					logger.LogDebug((object)("Loaded " + assembly.FullName));
					return assembly;
				}
				catch (Exception ex)
				{
					logger.LogError((object)("Failed to load assembly: \n" + ex));
					return null;
				}
			};
			logger.LogInfo((object)"Checking if LethalSettings is installed.");
			if (Chainloader.PluginInfos.ContainsKey("com.willis.lc.lethalsettings"))
			{
				logger.LogInfo((object)"It is! Adding voice recognition test to the settings menu.");
				VoiceRecognitionSettings.Init();
			}
			else
			{
				logger.LogInfo((object)"it isn't :( - you won't be able to test voice recognition easily inside the game");
			}
			logger.LogInfo((object)"Applying Patches");
			harmony.PatchAll(typeof(GameNetworkManagerPatch));
			logger.LogInfo((object)"VoiceRecognitionAPI:2.0.0 has succesfully loaded!");
		}
	}
}
namespace VoiceRecognitionAPI.Util
{
	internal class VoiceRecognitionSettings
	{
		private static bool testingRecogntion;

		internal static void Init()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			LabelComponent successMessage = new LabelComponent
			{
				Text = "",
				Alignment = (TextAlignmentOptions)513,
				FontSize = 14f
			};
			ModSettingsConfig val = new ModSettingsConfig();
			val.Name = "VoiceRecognitionAPI";
			val.Id = "me.loaforc.voicerecognitionapi";
			val.Description = "Allows you to test out voice recognition!";
			val.MenuComponents = (MenuComponent[])(object)new MenuComponent[2]
			{
				(MenuComponent)new ButtonComponent
				{
					Text = "Test Voice Recognition",
					OnClick = delegate
					{
						successMessage.Text = "Please say \"I love the company!\"";
						testingRecogntion = true;
					}
				},
				(MenuComponent)successMessage
			};
			ModMenu.RegisterMod(val, true, true);
			Voice.ListenForPhrase("i love the company", delegate
			{
				if (testingRecogntion)
				{
					testingRecogntion = false;
					successMessage.Text = "The company thanks you! (Your voice recognition is working)";
				}
			});
		}
	}
}
namespace VoiceRecognitionAPI.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		internal static void SetupRecognitionEngine()
		{
			new SpeechHandler();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

plugins/System.Speech.dll

Decompiled 10 months ago
using System;
using System.CodeDom.Compiler;
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.Net;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Speech.AudioFormat;
using System.Speech.Internal;
using System.Speech.Internal.GrammarBuilding;
using System.Speech.Internal.ObjectTokens;
using System.Speech.Internal.SapiInterop;
using System.Speech.Internal.SrgsCompiler;
using System.Speech.Internal.SrgsParser;
using System.Speech.Internal.Synthesis;
using System.Speech.Recognition;
using System.Speech.Recognition.SrgsGrammar;
using System.Speech.Synthesis;
using System.Speech.Synthesis.TtsEngine;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.XPath;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
using Microsoft.Win32;

[assembly: AssemblyCopyright("Copyright (c) Microsoft Corporation. All rights reserved.")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft (R) Windows (R) Operating System")]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("d:\\sp1qfe.public.x86fre\\internal\\strongnamekeys\\fake\\windows.snk")]
[assembly: AssemblyFileVersion("6.0.6001.17014")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: PermissionSet(SecurityAction.RequestOptional, Unrestricted = true)]
[assembly: SecurityPermission(SecurityAction.RequestOptional, Unrestricted = true)]
[assembly: RegistryPermission(SecurityAction.RequestOptional, Unrestricted = true)]
[assembly: EnvironmentPermission(SecurityAction.RequestOptional, Unrestricted = true)]
[assembly: FileIOPermission(SecurityAction.RequestOptional, Unrestricted = true)]
[assembly: AssemblyVersion("3.0.0.0")]
[module: UnverifiableCode]
namespace System.Speech.Internal
{
	internal static class AudioFormatConverter
	{
		private enum StreamFormat
		{
			Default = -1,
			NoAssignedFormat,
			Text,
			NonStandardFormat,
			ExtendedAudioFormat,
			PCM_8kHz8BitMono,
			PCM_8kHz8BitStereo,
			PCM_8kHz16BitMono,
			PCM_8kHz16BitStereo,
			PCM_11kHz8BitMono,
			PCM_11kHz8BitStereo,
			PCM_11kHz16BitMono,
			PCM_11kHz16BitStereo,
			PCM_12kHz8BitMono,
			PCM_12kHz8BitStereo,
			PCM_12kHz16BitMono,
			PCM_12kHz16BitStereo,
			PCM_16kHz8BitMono,
			PCM_16kHz8BitStereo,
			PCM_16kHz16BitMono,
			PCM_16kHz16BitStereo,
			PCM_22kHz8BitMono,
			PCM_22kHz8BitStereo,
			PCM_22kHz16BitMono,
			PCM_22kHz16BitStereo,
			PCM_24kHz8BitMono,
			PCM_24kHz8BitStereo,
			PCM_24kHz16BitMono,
			PCM_24kHz16BitStereo,
			PCM_32kHz8BitMono,
			PCM_32kHz8BitStereo,
			PCM_32kHz16BitMono,
			PCM_32kHz16BitStereo,
			PCM_44kHz8BitMono,
			PCM_44kHz8BitStereo,
			PCM_44kHz16BitMono,
			PCM_44kHz16BitStereo,
			PCM_48kHz8BitMono,
			PCM_48kHz8BitStereo,
			PCM_48kHz16BitMono,
			PCM_48kHz16BitStereo,
			TrueSpeech_8kHz1BitMono,
			CCITT_ALaw_8kHzMono,
			CCITT_ALaw_8kHzStereo,
			CCITT_ALaw_11kHzMono,
			CCITT_ALaw_11kHzStereo,
			CCITT_ALaw_22kHzMono,
			CCITT_ALaw_22kHzStereo,
			CCITT_ALaw_44kHzMono,
			CCITT_ALaw_44kHzStereo,
			CCITT_uLaw_8kHzMono,
			CCITT_uLaw_8kHzStereo,
			CCITT_uLaw_11kHzMono,
			CCITT_uLaw_11kHzStereo,
			CCITT_uLaw_22kHzMono,
			CCITT_uLaw_22kHzStereo,
			CCITT_uLaw_44kHzMono,
			CCITT_uLaw_44kHzStereo,
			ADPCM_8kHzMono,
			ADPCM_8kHzStereo,
			ADPCM_11kHzMono,
			ADPCM_11kHzStereo,
			ADPCM_22kHzMono,
			ADPCM_22kHzStereo,
			ADPCM_44kHzMono,
			ADPCM_44kHzStereo,
			GSM610_8kHzMono,
			GSM610_11kHzMono,
			GSM610_22kHzMono,
			GSM610_44kHzMono,
			NUM_FORMATS
		}

		private enum WaveFormatId
		{
			Pcm = 1,
			AdPcm = 2,
			TrueSpeech = 34,
			Alaw = 6,
			Mulaw = 7,
			Gsm610 = 49
		}

		[StructLayout(LayoutKind.Sequential)]
		private class WaveFormatEx
		{
			public ushort wFormatTag;

			public ushort nChannels;

			public uint nSamplesPerSec;

			public uint nAvgBytesPerSec;

			public ushort nBlockAlign;

			public ushort wBitsPerSample;

			public ushort cbSize;
		}

		internal static SpeechAudioFormatInfo ToSpeechAudioFormatInfo(IntPtr waveFormatPtr)
		{
			WaveFormatEx waveFormatEx = (WaveFormatEx)Marshal.PtrToStructure(waveFormatPtr, typeof(WaveFormatEx));
			byte[] array = new byte[waveFormatEx.cbSize];
			IntPtr ptr = new IntPtr(waveFormatPtr.ToInt64() + Marshal.SizeOf((object)waveFormatEx));
			for (int i = 0; i < waveFormatEx.cbSize; i++)
			{
				array[i] = Marshal.ReadByte(ptr, i);
			}
			return new SpeechAudioFormatInfo((EncodingFormat)waveFormatEx.wFormatTag, (int)waveFormatEx.nSamplesPerSec, (short)waveFormatEx.wBitsPerSample, (short)waveFormatEx.nChannels, (int)waveFormatEx.nAvgBytesPerSec, (short)waveFormatEx.nBlockAlign, array);
		}

		internal static SpeechAudioFormatInfo ToSpeechAudioFormatInfo(string formatString)
		{
			if (short.TryParse(formatString, NumberStyles.None, CultureInfo.InvariantCulture, out var result))
			{
				return ConvertFormat((StreamFormat)result);
			}
			return null;
		}

		private static SpeechAudioFormatInfo ConvertFormat(StreamFormat eFormat)
		{
			WaveFormatEx waveFormatEx = new WaveFormatEx();
			byte[] array = null;
			if (eFormat >= StreamFormat.PCM_8kHz8BitMono && eFormat <= StreamFormat.PCM_48kHz16BitStereo)
			{
				uint num = (uint)(eFormat - 4);
				bool flag = (num & 1) != 0;
				bool flag2 = (num & 2) != 0;
				uint num2 = (num & 0x3C) >> 2;
				uint[] array2 = new uint[9] { 8000u, 11025u, 12000u, 16000u, 22050u, 24000u, 32000u, 44100u, 48000u };
				waveFormatEx.wFormatTag = 1;
				waveFormatEx.nChannels = (waveFormatEx.nBlockAlign = (ushort)((!flag) ? 1u : 2u));
				waveFormatEx.nSamplesPerSec = array2[num2];
				waveFormatEx.wBitsPerSample = 8;
				if (flag2)
				{
					waveFormatEx.wBitsPerSample *= 2;
					waveFormatEx.nBlockAlign *= 2;
				}
				waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;
			}
			else
			{
				switch (eFormat)
				{
				case StreamFormat.TrueSpeech_8kHz1BitMono:
					waveFormatEx.wFormatTag = 34;
					waveFormatEx.nChannels = 1;
					waveFormatEx.nSamplesPerSec = 8000u;
					waveFormatEx.nAvgBytesPerSec = 1067u;
					waveFormatEx.nBlockAlign = 32;
					waveFormatEx.wBitsPerSample = 1;
					waveFormatEx.cbSize = 32;
					array = new byte[32];
					array[0] = 1;
					array[2] = 240;
					break;
				case StreamFormat.CCITT_ALaw_8kHzMono:
				case StreamFormat.CCITT_ALaw_8kHzStereo:
				case StreamFormat.CCITT_ALaw_11kHzMono:
				case StreamFormat.CCITT_ALaw_11kHzStereo:
				case StreamFormat.CCITT_ALaw_22kHzMono:
				case StreamFormat.CCITT_ALaw_22kHzStereo:
				case StreamFormat.CCITT_ALaw_44kHzMono:
				case StreamFormat.CCITT_ALaw_44kHzStereo:
				{
					uint num8 = (uint)(eFormat - 41);
					uint num9 = num8 / 2;
					uint[] array13 = new uint[4] { 8000u, 11025u, 22050u, 44100u };
					bool flag5 = (num8 & 1) != 0;
					waveFormatEx.wFormatTag = 6;
					waveFormatEx.nChannels = (waveFormatEx.nBlockAlign = (ushort)((!flag5) ? 1u : 2u));
					waveFormatEx.nSamplesPerSec = array13[num9];
					waveFormatEx.wBitsPerSample = 8;
					waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;
					break;
				}
				default:
					if (eFormat >= StreamFormat.CCITT_uLaw_8kHzMono && eFormat <= StreamFormat.CCITT_uLaw_44kHzStereo)
					{
						uint num3 = (uint)(eFormat - 49);
						uint num4 = num3 / 2;
						uint[] array3 = new uint[4] { 8000u, 11025u, 22050u, 44100u };
						bool flag3 = (num3 & 1) != 0;
						waveFormatEx.wFormatTag = 7;
						waveFormatEx.nChannels = (waveFormatEx.nBlockAlign = (ushort)((!flag3) ? 1u : 2u));
						waveFormatEx.nSamplesPerSec = array3[num4];
						waveFormatEx.wBitsPerSample = 8;
						waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * waveFormatEx.nBlockAlign;
					}
					else if (eFormat >= StreamFormat.ADPCM_8kHzMono && eFormat <= StreamFormat.ADPCM_44kHzStereo)
					{
						uint[] array4 = new uint[4] { 8000u, 11025u, 22050u, 44100u };
						uint[] array5 = new uint[8] { 4096u, 8192u, 5644u, 11289u, 11155u, 22311u, 22179u, 44359u };
						uint[] array6 = new uint[4] { 256u, 256u, 512u, 1024u };
						byte[] array7 = new byte[32]
						{
							244, 1, 7, 0, 0, 1, 0, 0, 0, 2,
							0, 255, 0, 0, 0, 0, 192, 0, 64, 0,
							240, 0, 0, 0, 204, 1, 48, 255, 136, 1,
							24, 255
						};
						byte[] array8 = new byte[32]
						{
							244, 3, 7, 0, 0, 1, 0, 0, 0, 2,
							0, 255, 0, 0, 0, 0, 192, 0, 64, 0,
							240, 0, 0, 0, 204, 1, 48, 255, 136, 1,
							24, 255
						};
						byte[] array9 = new byte[32]
						{
							244, 7, 7, 0, 0, 1, 0, 0, 0, 2,
							0, 255, 0, 0, 0, 0, 192, 0, 64, 0,
							240, 0, 0, 0, 204, 1, 48, 255, 136, 1,
							24, 255
						};
						byte[][] array10 = new byte[4][] { array7, array7, array8, array9 };
						uint num5 = (uint)(eFormat - 57);
						uint num6 = num5 / 2;
						bool flag4 = (num5 & 1) != 0;
						waveFormatEx.wFormatTag = 2;
						waveFormatEx.nChannels = (ushort)((!flag4) ? 1u : 2u);
						waveFormatEx.nSamplesPerSec = array4[num6];
						waveFormatEx.nAvgBytesPerSec = array5[num5];
						waveFormatEx.nBlockAlign = (ushort)(array6[num6] * waveFormatEx.nChannels);
						waveFormatEx.wBitsPerSample = 4;
						waveFormatEx.cbSize = 32;
						array = (byte[])array10[num6].Clone();
					}
					else if (eFormat >= StreamFormat.GSM610_8kHzMono && eFormat <= StreamFormat.GSM610_44kHzMono)
					{
						uint[] array11 = new uint[4] { 8000u, 11025u, 22050u, 44100u };
						uint[] array12 = new uint[4] { 1625u, 2239u, 4478u, 8957u };
						uint num7 = (uint)(eFormat - 65);
						waveFormatEx.wFormatTag = 49;
						waveFormatEx.nChannels = 1;
						waveFormatEx.nSamplesPerSec = array11[num7];
						waveFormatEx.nAvgBytesPerSec = array12[num7];
						waveFormatEx.nBlockAlign = 65;
						waveFormatEx.wBitsPerSample = 0;
						waveFormatEx.cbSize = 2;
						array = new byte[2] { 64, 1 };
					}
					else
					{
						waveFormatEx = null;
						switch (eFormat)
						{
						default:
							throw new FormatException();
						case StreamFormat.NoAssignedFormat:
						case StreamFormat.Text:
							break;
						}
					}
					break;
				}
			}
			if (waveFormatEx == null)
			{
				return null;
			}
			return new SpeechAudioFormatInfo((EncodingFormat)waveFormatEx.wFormatTag, (int)waveFormatEx.nSamplesPerSec, waveFormatEx.wBitsPerSample, waveFormatEx.nChannels, (int)waveFormatEx.nAvgBytesPerSec, waveFormatEx.nBlockAlign, array);
		}
	}
}
namespace System.Speech.AudioFormat
{
	public enum EncodingFormat
	{
		Pcm = 1,
		ALaw = 6,
		ULaw = 7
	}
	[Serializable]
	public class SpeechAudioFormatInfo
	{
		private int _averageBytesPerSecond;

		private short _bitsPerSample;

		private short _blockAlign;

		private EncodingFormat _encodingFormat;

		private short _channelCount;

		private int _samplesPerSecond;

		private byte[] _formatSpecificData;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public int AverageBytesPerSecond => _averageBytesPerSecond;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public int BitsPerSample => _bitsPerSample;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public int BlockAlign => _blockAlign;

		public EncodingFormat EncodingFormat => _encodingFormat;

		public int ChannelCount => _channelCount;

		public int SamplesPerSecond => _samplesPerSecond;

		internal byte[] WaveFormat
		{
			get
			{
				WAVEFORMATEX wAVEFORMATEX = default(WAVEFORMATEX);
				wAVEFORMATEX.wFormatTag = (short)EncodingFormat;
				wAVEFORMATEX.nChannels = (short)ChannelCount;
				wAVEFORMATEX.nSamplesPerSec = SamplesPerSecond;
				wAVEFORMATEX.nAvgBytesPerSec = AverageBytesPerSecond;
				wAVEFORMATEX.nBlockAlign = (short)BlockAlign;
				wAVEFORMATEX.wBitsPerSample = (short)BitsPerSample;
				wAVEFORMATEX.cbSize = (short)FormatSpecificData().Length;
				byte[] array = wAVEFORMATEX.ToBytes();
				if (wAVEFORMATEX.cbSize > 0)
				{
					byte[] array2 = new byte[array.Length + wAVEFORMATEX.cbSize];
					Array.Copy(array, array2, array.Length);
					Array.Copy(FormatSpecificData(), 0, array2, array.Length, wAVEFORMATEX.cbSize);
					array = array2;
				}
				return array;
			}
		}

		private SpeechAudioFormatInfo(EncodingFormat encodingFormat, int samplesPerSecond, short bitsPerSample, short channelCount, byte[] formatSpecificData)
		{
			if (encodingFormat == (EncodingFormat)0)
			{
				throw new ArgumentException(SR.Get(SRID.CannotUseCustomFormat), "encodingFormat");
			}
			if (samplesPerSecond <= 0)
			{
				throw new ArgumentOutOfRangeException("samplesPerSecond", SR.Get(SRID.MustBeGreaterThanZero));
			}
			if (bitsPerSample <= 0)
			{
				throw new ArgumentOutOfRangeException("bitsPerSample", SR.Get(SRID.MustBeGreaterThanZero));
			}
			if (channelCount <= 0)
			{
				throw new ArgumentOutOfRangeException("channelCount", SR.Get(SRID.MustBeGreaterThanZero));
			}
			_encodingFormat = encodingFormat;
			_samplesPerSecond = samplesPerSecond;
			_bitsPerSample = bitsPerSample;
			_channelCount = channelCount;
			if (formatSpecificData == null)
			{
				_formatSpecificData = new byte[0];
			}
			else
			{
				_formatSpecificData = (byte[])formatSpecificData.Clone();
			}
			switch (encodingFormat)
			{
			case EncodingFormat.ALaw:
			case EncodingFormat.ULaw:
				if (bitsPerSample != 8)
				{
					throw new ArgumentOutOfRangeException("bitsPerSample");
				}
				if (formatSpecificData != null && formatSpecificData.Length != 0)
				{
					throw new ArgumentOutOfRangeException("formatSpecificData");
				}
				break;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public SpeechAudioFormatInfo(EncodingFormat encodingFormat, int samplesPerSecond, int bitsPerSample, int channelCount, int averageBytesPerSecond, int blockAlign, byte[] formatSpecificData)
			: this(encodingFormat, samplesPerSecond, (short)bitsPerSample, (short)channelCount, formatSpecificData)
		{
			if (averageBytesPerSecond <= 0)
			{
				throw new ArgumentOutOfRangeException("averageBytesPerSecond", SR.Get(SRID.MustBeGreaterThanZero));
			}
			if (blockAlign <= 0)
			{
				throw new ArgumentOutOfRangeException("blockAlign", SR.Get(SRID.MustBeGreaterThanZero));
			}
			_averageBytesPerSecond = averageBytesPerSecond;
			_blockAlign = (short)blockAlign;
		}

		public SpeechAudioFormatInfo(int samplesPerSecond, AudioBitsPerSample bitsPerSample, AudioChannel channel)
			: this(EncodingFormat.Pcm, samplesPerSecond, (short)bitsPerSample, (short)channel, null)
		{
			_blockAlign = (short)(_channelCount * (_bitsPerSample / 8));
			_averageBytesPerSecond = _samplesPerSecond * _blockAlign;
		}

		public byte[] FormatSpecificData()
		{
			return (byte[])_formatSpecificData.Clone();
		}

		public override bool Equals(object obj)
		{
			if (!(obj is SpeechAudioFormatInfo speechAudioFormatInfo))
			{
				return false;
			}
			if (!_averageBytesPerSecond.Equals(speechAudioFormatInfo._averageBytesPerSecond) || !_bitsPerSample.Equals(speechAudioFormatInfo._bitsPerSample) || !_blockAlign.Equals(speechAudioFormatInfo._blockAlign) || !_encodingFormat.Equals(speechAudioFormatInfo._encodingFormat) || !_channelCount.Equals(speechAudioFormatInfo._channelCount) || !_samplesPerSecond.Equals(speechAudioFormatInfo._samplesPerSecond))
			{
				return false;
			}
			if (_formatSpecificData.Length != speechAudioFormatInfo._formatSpecificData.Length)
			{
				return false;
			}
			for (int i = 0; i < _formatSpecificData.Length; i++)
			{
				if (_formatSpecificData[i] != speechAudioFormatInfo._formatSpecificData[i])
				{
					return false;
				}
			}
			return true;
		}

		public override int GetHashCode()
		{
			return _averageBytesPerSecond.GetHashCode();
		}
	}
	public enum AudioChannel
	{
		Mono = 1,
		Stereo
	}
	public enum AudioBitsPerSample
	{
		Eight = 8,
		Sixteen = 0x10
	}
}
namespace System.Speech.Internal
{
	internal interface IAsyncDispatch
	{
		void Post(object evt);

		void Post(object[] evt);

		void PostOperation(Delegate callback, params object[] parameters);
	}
	internal class AsyncSerializedWorker : IAsyncDispatch
	{
		private AsyncOperation _asyncOperation;

		private SendOrPostCallback _workerPostCallback;

		private Queue _queue;

		private bool _hasPendingPost;

		private bool _isAsyncMode;

		private WaitCallback _workerCallback;

		private WaitCallback _defaultCallback;

		private bool _isEnabled;

		internal bool Enabled
		{
			get
			{
				lock (_queue.SyncRoot)
				{
					return _isEnabled;
				}
			}
			set
			{
				lock (_queue.SyncRoot)
				{
					_isEnabled = value;
				}
			}
		}

		internal WaitCallback DefaultCallback
		{
			get
			{
				lock (_queue.SyncRoot)
				{
					return _defaultCallback;
				}
			}
		}

		internal bool AsyncMode
		{
			get
			{
				lock (_queue.SyncRoot)
				{
					return _isAsyncMode;
				}
			}
			set
			{
				bool flag = false;
				lock (_queue.SyncRoot)
				{
					if (_isAsyncMode != value)
					{
						_isAsyncMode = value;
						if (_queue.Count > 0)
						{
							flag = true;
						}
					}
				}
				if (flag)
				{
					OnWorkItemPending();
				}
			}
		}

		internal event WaitCallback WorkItemPending;

		internal AsyncSerializedWorker(WaitCallback defaultCallback, AsyncOperation asyncOperation)
		{
			_asyncOperation = asyncOperation;
			_workerPostCallback = WorkerProc;
			Initialize(defaultCallback);
		}

		private void Initialize(WaitCallback defaultCallback)
		{
			_queue = new Queue();
			_hasPendingPost = false;
			_workerCallback = WorkerProc;
			_defaultCallback = defaultCallback;
			_isAsyncMode = true;
			_isEnabled = true;
		}

		public void Post(object evt)
		{
			AddItem(new AsyncWorkItem(DefaultCallback, evt));
		}

		public void Post(object[] evt)
		{
			lock (_queue.SyncRoot)
			{
				if (Enabled)
				{
					for (int i = 0; i < evt.Length; i++)
					{
						AddItem(new AsyncWorkItem(DefaultCallback, evt[i]));
					}
				}
			}
		}

		public void PostOperation(Delegate callback, params object[] parameters)
		{
			AddItem(new AsyncWorkItem(callback, parameters));
		}

		internal void Purge()
		{
			lock (_queue.SyncRoot)
			{
				_queue.Clear();
			}
		}

		internal AsyncWorkItem NextWorkItem()
		{
			lock (_queue.SyncRoot)
			{
				if (_queue.Count == 0)
				{
					return null;
				}
				AsyncWorkItem result = (AsyncWorkItem)_queue.Dequeue();
				if (_queue.Count == 0)
				{
					_hasPendingPost = false;
				}
				return result;
			}
		}

		internal void ConsumeQueue()
		{
			AsyncWorkItem asyncWorkItem;
			while ((asyncWorkItem = NextWorkItem()) != null)
			{
				asyncWorkItem.Invoke();
			}
		}

		private void AddItem(AsyncWorkItem item)
		{
			bool flag = true;
			lock (_queue.SyncRoot)
			{
				if (Enabled)
				{
					_queue.Enqueue(item);
					if (!_hasPendingPost || !_isAsyncMode)
					{
						flag = false;
						_hasPendingPost = true;
					}
				}
			}
			if (!flag)
			{
				OnWorkItemPending();
			}
		}

		private void WorkerProc(object ignored)
		{
			while (true)
			{
				AsyncWorkItem asyncWorkItem;
				lock (_queue.SyncRoot)
				{
					if (_queue.Count <= 0 || !_isAsyncMode)
					{
						if (_queue.Count == 0)
						{
							_hasPendingPost = false;
						}
						break;
					}
					asyncWorkItem = (AsyncWorkItem)_queue.Dequeue();
				}
				asyncWorkItem.Invoke();
			}
		}

		private void OnWorkItemPending()
		{
			if (!_hasPendingPost)
			{
				return;
			}
			if (AsyncMode)
			{
				if (_asyncOperation == null)
				{
					ThreadPool.QueueUserWorkItem(_workerCallback, null);
				}
				else
				{
					_asyncOperation.Post(_workerPostCallback, null);
				}
			}
			else if (this.WorkItemPending != null)
			{
				this.WorkItemPending(null);
			}
		}
	}
	internal class AsyncWorkItem
	{
		private Delegate _dynamicCallback;

		private object[] _postData;

		internal AsyncWorkItem(Delegate dynamicCallback, params object[] postData)
		{
			_dynamicCallback = dynamicCallback;
			_postData = postData;
		}

		internal void Invoke()
		{
			if ((object)_dynamicCallback != null)
			{
				_dynamicCallback.DynamicInvoke(_postData);
			}
		}
	}
	internal static class Helpers
	{
		internal const int _sizeOfChar = 2;

		internal static readonly char[] _achTrimChars = new char[4] { ' ', '\t', '\n', '\r' };

		internal static void ThrowIfEmptyOrNull(string s, string paramName)
		{
			if (string.IsNullOrEmpty(s))
			{
				if (s == null)
				{
					throw new ArgumentNullException(paramName);
				}
				throw new ArgumentException(SR.Get(SRID.StringCanNotBeEmpty, paramName), paramName);
			}
		}

		internal static void ThrowIfNull(object value, string paramName)
		{
			if (value == null)
			{
				throw new ArgumentNullException(paramName);
			}
		}

		internal static bool CompareInvariantCulture(CultureInfo culture1, CultureInfo culture2)
		{
			if (culture1.Equals(culture2))
			{
				return true;
			}
			while (!culture1.IsNeutralCulture)
			{
				culture1 = culture1.Parent;
			}
			while (!culture2.IsNeutralCulture)
			{
				culture2 = culture2.Parent;
			}
			return culture1.Equals(culture2);
		}

		internal static void CopyStream(Stream inputStream, Stream outputStream, int bytesToCopy)
		{
			int num = ((bytesToCopy > 4096) ? 4096 : bytesToCopy);
			byte[] buffer = new byte[num];
			while (bytesToCopy > 0)
			{
				int num2 = inputStream.Read(buffer, 0, num);
				if (num2 <= 0)
				{
					throw new EndOfStreamException(SR.Get(SRID.StreamEndedUnexpectedly));
				}
				outputStream.Write(buffer, 0, num2);
				bytesToCopy -= num2;
			}
		}

		internal static byte[] ReadStreamToByteArray(Stream inputStream, int bytesToCopy)
		{
			byte[] array = new byte[bytesToCopy];
			BlockingRead(inputStream, array, 0, bytesToCopy);
			return array;
		}

		internal static void BlockingRead(Stream stream, byte[] buffer, int offset, int count)
		{
			while (count > 0)
			{
				int num = stream.Read(buffer, offset, count);
				if (num <= 0)
				{
					throw new EndOfStreamException();
				}
				count -= num;
				offset += num;
			}
		}

		internal static void CombineCulture(string language, string location, CultureInfo parentCulture, int layoutId)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			CultureInfo cultureInfo = new CultureInfo(language);
			RegionInfo regionInfo = new RegionInfo(location);
			string text = cultureInfo.TwoLetterISOLanguageName + "-" + regionInfo.TwoLetterISORegionName;
			CultureAndRegionInfoBuilder val = new CultureAndRegionInfoBuilder(text, (CultureAndRegionModifiers)0);
			val.LoadDataFromRegionInfo(regionInfo);
			val.LoadDataFromCultureInfo(cultureInfo);
			val.IetfLanguageTag = text;
			val.Parent = parentCulture;
			val.ThreeLetterISOLanguageName = cultureInfo.ThreeLetterISOLanguageName;
			val.TwoLetterISOLanguageName = cultureInfo.TwoLetterISOLanguageName;
			val.ThreeLetterWindowsLanguageName = cultureInfo.ThreeLetterWindowsLanguageName;
			val.RegionNativeName = regionInfo.NativeName;
			string text2 = cultureInfo.EnglishName.Substring(0, cultureInfo.EnglishName.IndexOf("(", StringComparison.Ordinal) - 1);
			string text3 = cultureInfo.NativeName.Substring(0, cultureInfo.NativeName.IndexOf("(", StringComparison.Ordinal) - 1);
			val.CultureEnglishName = text2 + " (" + val.RegionEnglishName + ")";
			val.CultureNativeName = text3 + " (" + val.RegionNativeName + ")";
			val.CurrencyNativeName = regionInfo.CurrencyNativeName;
			val.NumberFormat.PositiveInfinitySymbol = cultureInfo.NumberFormat.PositiveInfinitySymbol;
			val.NumberFormat.NegativeInfinitySymbol = cultureInfo.NumberFormat.NegativeInfinitySymbol;
			val.NumberFormat.NaNSymbol = cultureInfo.NumberFormat.NaNSymbol;
			DateTimeFormatInfo gregorianDateTimeFormat = val.GregorianDateTimeFormat;
			DateTimeFormatInfo dateTimeFormat = cultureInfo.DateTimeFormat;
			dateTimeFormat.Calendar = new GregorianCalendar();
			val.KeyboardLayoutId = layoutId;
			gregorianDateTimeFormat.AbbreviatedDayNames = dateTimeFormat.AbbreviatedDayNames;
			gregorianDateTimeFormat.AbbreviatedMonthGenitiveNames = dateTimeFormat.AbbreviatedMonthGenitiveNames;
			gregorianDateTimeFormat.AbbreviatedMonthNames = dateTimeFormat.AbbreviatedMonthNames;
			gregorianDateTimeFormat.DayNames = dateTimeFormat.DayNames;
			gregorianDateTimeFormat.MonthGenitiveNames = dateTimeFormat.MonthGenitiveNames;
			gregorianDateTimeFormat.MonthNames = dateTimeFormat.MonthNames;
			gregorianDateTimeFormat.ShortestDayNames = dateTimeFormat.ShortestDayNames;
			val.Register();
		}
	}
	internal sealed class HGlobalSafeHandle : SafeHandle
	{
		private int _bufferSize;

		public override bool IsInvalid => handle == IntPtr.Zero;

		internal HGlobalSafeHandle()
			: base(IntPtr.Zero, ownsHandle: true)
		{
		}

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

		protected override void Dispose(bool disposing)
		{
			ReleaseHandle();
			base.Dispose(disposing);
			GC.SuppressFinalize(this);
		}

		internal IntPtr Buffer(int size)
		{
			if (size > _bufferSize)
			{
				if (_bufferSize == 0)
				{
					SetHandle(Marshal.AllocHGlobal(size));
				}
				else
				{
					SetHandle(Marshal.ReAllocHGlobal(handle, (IntPtr)size));
				}
				GC.AddMemoryPressure(size - _bufferSize);
				_bufferSize = size;
			}
			return handle;
		}

		protected override bool ReleaseHandle()
		{
			if (handle != IntPtr.Zero)
			{
				if (_bufferSize > 0)
				{
					GC.RemoveMemoryPressure(_bufferSize);
					_bufferSize = 0;
				}
				Marshal.FreeHGlobal(handle);
				handle = IntPtr.Zero;
				return true;
			}
			return false;
		}
	}
	internal enum AlphabetType
	{
		Sapi,
		Ipa,
		Ups
	}
	internal class AlphabetConverter
	{
		internal class PhoneMapData
		{
			private class ConversionUnit
			{
				public string sapi;

				public string ups;

				public bool isDefault;
			}

			private Hashtable prefixSapiTable;

			private Hashtable prefixUpsTable;

			private ConversionUnit[] convertTable;

			internal PhoneMapData(Stream input)
			{
				using BinaryReader binaryReader = new BinaryReader(input, Encoding.Unicode);
				int num = binaryReader.ReadInt32();
				convertTable = new ConversionUnit[num];
				for (int i = 0; i < num; i++)
				{
					convertTable[i] = new ConversionUnit();
					convertTable[i].sapi = ReadPhoneString(binaryReader);
					convertTable[i].ups = ReadPhoneString(binaryReader);
					convertTable[i].isDefault = ((binaryReader.ReadInt32() != 0) ? true : false);
				}
				prefixSapiTable = InitializePrefix(isSapi: true);
				prefixUpsTable = InitializePrefix(isSapi: false);
			}

			internal bool IsPrefix(string prefix, bool isSapi)
			{
				if (isSapi)
				{
					return prefixSapiTable.ContainsKey(prefix);
				}
				return prefixUpsTable.ContainsKey(prefix);
			}

			internal string ConvertPhoneme(string phoneme, bool isSapi)
			{
				ConversionUnit conversionUnit = ((!isSapi) ? ((ConversionUnit)prefixUpsTable[phoneme]) : ((ConversionUnit)prefixSapiTable[phoneme]));
				if (conversionUnit == null)
				{
					return null;
				}
				if (!isSapi)
				{
					return conversionUnit.sapi;
				}
				return conversionUnit.ups;
			}

			private Hashtable InitializePrefix(bool isSapi)
			{
				Hashtable hashtable = Hashtable.Synchronized(new Hashtable());
				for (int i = 0; i < convertTable.Length; i++)
				{
					string text = ((!isSapi) ? convertTable[i].ups : convertTable[i].sapi);
					for (int j = 0; j + 1 < text.Length; j++)
					{
						string key = text.Substring(0, j + 1);
						if (!hashtable.ContainsKey(key))
						{
							hashtable[key] = null;
						}
					}
					if (convertTable[i].isDefault || hashtable[text] == null)
					{
						hashtable[text] = convertTable[i];
					}
				}
				return hashtable;
			}

			private static string ReadPhoneString(BinaryReader reader)
			{
				int num = reader.ReadInt16() / 2;
				char[] value = reader.ReadChars(num);
				return new string(value, 0, num - 1);
			}
		}

		private int _currentLangId;

		private PhoneMapData _phoneMap;

		private static int[] _langIds = new int[7] { 2052, 1028, 1031, 1033, 1034, 1036, 1041 };

		private static string[] _resourceNames = new string[7] { "upstable_chs.upsmap", "upstable_cht.upsmap", "upstable_deu.upsmap", "upstable_enu.upsmap", "upstable_esp.upsmap", "upstable_fra.upsmap", "upstable_jpn.upsmap" };

		private static PhoneMapData[] _phoneMaps = new PhoneMapData[7];

		private static object _staticLock = new object();

		internal AlphabetConverter(int langId)
		{
			_currentLangId = -1;
			SetLanguageId(langId);
		}

		internal char[] SapiToIpa(char[] phonemes)
		{
			return Convert(phonemes, isSapi: true);
		}

		internal char[] IpaToSapi(char[] phonemes)
		{
			return Convert(phonemes, isSapi: false);
		}

		internal bool IsPrefix(string phonemes, bool isSapi)
		{
			return _phoneMap.IsPrefix(phonemes, isSapi);
		}

		internal bool IsConvertibleUnit(string phonemes, bool isSapi)
		{
			return _phoneMap.ConvertPhoneme(phonemes, isSapi) != null;
		}

		internal int SetLanguageId(int langId)
		{
			if (langId < 0)
			{
				throw new ArgumentException(SR.Get(SRID.MustBeGreaterThanZero), "langId");
			}
			if (langId == _currentLangId)
			{
				return _currentLangId;
			}
			int currentLangId = _currentLangId;
			int i;
			for (i = 0; i < _langIds.Length && _langIds[i] != langId; i++)
			{
			}
			if (i == _langIds.Length)
			{
				_currentLangId = langId;
				_phoneMap = null;
			}
			else
			{
				lock (_staticLock)
				{
					if (_phoneMaps[i] == null)
					{
						_phoneMaps[i] = CreateMap(_resourceNames[i]);
					}
					_phoneMap = _phoneMaps[i];
					_currentLangId = langId;
				}
			}
			return currentLangId;
		}

		private char[] Convert(char[] phonemes, bool isSapi)
		{
			if (_phoneMap == null || phonemes.Length == 0)
			{
				return (char[])phonemes.Clone();
			}
			StringBuilder stringBuilder = new StringBuilder();
			string text = new string(phonemes);
			string text2 = null;
			int i;
			int num = (i = 0);
			int num2 = -1;
			for (; i < text.Length; i++)
			{
				string text3 = text.Substring(num, i - num + 1);
				if (_phoneMap.IsPrefix(text3, isSapi))
				{
					string text4 = _phoneMap.ConvertPhoneme(text3, isSapi);
					if (text4 != null)
					{
						text2 = text4;
						num2 = i;
					}
					continue;
				}
				if (text2 == null)
				{
					break;
				}
				stringBuilder.Append(text2);
				i = num2;
				num = num2 + 1;
				text2 = null;
			}
			if (text2 != null && num2 == phonemes.Length - 1)
			{
				stringBuilder.Append(text2);
				return stringBuilder.ToString().ToCharArray();
			}
			return null;
		}

		private PhoneMapData CreateMap(string resourceName)
		{
			Assembly assembly = Assembly.GetAssembly(GetType());
			Stream manifestResourceStream = assembly.GetManifestResourceStream(resourceName);
			if (manifestResourceStream == null)
			{
				throw new FileLoadException(SR.Get(SRID.CannotLoadResourceFromManifest, resourceName, assembly.FullName));
			}
			return new PhoneMapData(new BufferedStream(manifestResourceStream));
		}
	}
	internal sealed class PhonemeConverter
	{
		private class PhoneMap
		{
			internal int _lcid;

			internal PhoneId[] _phoneIds;

			internal PhoneMap()
			{
			}
		}

		private class PhoneId : IComparer<PhoneId>
		{
			internal string _phone;

			internal char[] _cp;

			internal PhoneId()
			{
			}

			int IComparer<PhoneId>.Compare(PhoneId x, PhoneId y)
			{
				return x._phone.CompareTo(y._phone);
			}
		}

		private class PhoneMapCompressed
		{
			internal int _lcid;

			internal int _count;

			internal byte[] _phones;

			internal char[] _cps;

			internal PhoneMapCompressed()
			{
			}

			internal PhoneMapCompressed(int lcid, int count, byte[] phoneIds, char[] cps)
			{
				_lcid = lcid;
				_count = count;
				_phones = phoneIds;
				_cps = cps;
			}
		}

		private PhoneMap _phoneMap;

		private static readonly PhoneMap[] _phoneMaps;

		private static PhoneMapCompressed[] _phoneMapsCompressed;

		private static char[] _updIds;

		private static readonly PhonemeConverter _upsConverter;

		internal static PhonemeConverter UpsConverter => _upsConverter;

		static PhonemeConverter()
		{
			_phoneMapsCompressed = new PhoneMapCompressed[8]
			{
				new PhoneMapCompressed(0, 207, new byte[720]
				{
					46, 0, 95, 33, 0, 95, 38, 0, 95, 44,
					0, 95, 46, 0, 95, 63, 0, 95, 94, 0,
					95, 124, 0, 95, 124, 124, 0, 95, 83, 0,
					43, 0, 65, 0, 65, 65, 0, 65, 68, 86,
					0, 65, 69, 0, 65, 69, 88, 0, 65, 72,
					0, 65, 73, 255, 255, 0, 65, 78, 255, 0,
					65, 79, 0, 65, 79, 69, 0, 65, 79, 88,
					255, 255, 0, 65, 80, 73, 0, 65, 83, 80,
					0, 65, 84, 82, 0, 65, 85, 255, 255, 0,
					65, 88, 0, 65, 88, 82, 0, 66, 0, 66,
					66, 0, 66, 72, 0, 66, 73, 77, 0, 66,
					86, 65, 0, 66, 86, 68, 0, 67, 0, 67,
					67, 255, 255, 0, 67, 67, 50, 0, 67, 67,
					75, 0, 67, 69, 78, 0, 67, 72, 255, 255,
					0, 67, 72, 50, 0, 67, 74, 0, 67, 84,
					0, 67, 86, 68, 0, 68, 0, 68, 69, 78,
					0, 68, 72, 0, 68, 73, 77, 0, 68, 82,
					0, 68, 88, 0, 68, 88, 82, 0, 68, 90,
					255, 255, 0, 68, 90, 50, 0, 69, 0, 69,
					72, 0, 69, 72, 88, 255, 255, 0, 69, 73,
					255, 255, 0, 69, 74, 67, 0, 69, 78, 255,
					0, 69, 82, 0, 69, 82, 82, 0, 69, 83,
					72, 0, 69, 84, 0, 69, 85, 0, 69, 88,
					0, 69, 90, 72, 0, 70, 0, 71, 0, 71,
					50, 0, 71, 65, 0, 71, 72, 0, 71, 73,
					77, 0, 71, 76, 0, 71, 84, 0, 72, 0,
					72, 71, 0, 72, 72, 0, 72, 76, 71, 0,
					72, 90, 0, 73, 0, 73, 72, 0, 73, 88,
					0, 73, 89, 88, 255, 255, 0, 74, 0, 74,
					67, 255, 255, 0, 74, 67, 50, 0, 74, 68,
					0, 74, 72, 255, 255, 0, 74, 72, 50, 0,
					74, 73, 77, 0, 74, 74, 255, 255, 0, 75,
					0, 76, 0, 76, 65, 66, 0, 76, 65, 77,
					0, 76, 65, 82, 0, 76, 67, 75, 0, 76,
					67, 75, 50, 0, 76, 71, 0, 76, 72, 0,
					76, 74, 0, 76, 76, 65, 0, 76, 78, 71,
					0, 76, 79, 87, 0, 76, 82, 0, 76, 82,
					68, 0, 76, 83, 72, 0, 76, 84, 0, 77,
					0, 77, 67, 78, 0, 77, 70, 0, 77, 82,
					68, 0, 78, 0, 78, 65, 82, 0, 78, 65,
					83, 0, 78, 67, 75, 0, 78, 67, 75, 50,
					0, 78, 67, 75, 51, 0, 78, 71, 0, 78,
					74, 0, 78, 82, 0, 78, 83, 82, 0, 78,
					83, 89, 0, 79, 0, 79, 69, 0, 79, 69,
					78, 255, 0, 79, 73, 255, 255, 0, 79, 78,
					255, 0, 79, 85, 0, 79, 87, 88, 255, 255,
					0, 79, 88, 0, 80, 0, 80, 65, 76, 0,
					80, 67, 75, 0, 80, 70, 255, 255, 0, 80,
					72, 0, 80, 72, 82, 0, 81, 0, 81, 68,
					0, 81, 72, 0, 81, 73, 77, 0, 81, 78,
					0, 81, 79, 77, 0, 81, 81, 0, 81, 84,
					0, 82, 0, 82, 65, 0, 82, 65, 73, 0,
					82, 69, 84, 0, 82, 72, 0, 82, 72, 79,
					0, 82, 72, 90, 0, 82, 82, 0, 82, 84,
					69, 0, 82, 84, 82, 0, 83, 0, 83, 49,
					0, 83, 50, 0, 83, 67, 0, 83, 72, 0,
					83, 72, 67, 0, 83, 72, 88, 0, 83, 82,
					0, 83, 89, 76, 0, 84, 0, 84, 45, 0,
					84, 43, 0, 84, 61, 0, 84, 49, 0, 84,
					50, 0, 84, 51, 0, 84, 52, 0, 84, 53,
					0, 84, 67, 75, 0, 84, 67, 75, 50, 0,
					84, 72, 0, 84, 82, 0, 84, 83, 255, 255,
					0, 84, 83, 50, 0, 84, 83, 82, 255, 255,
					0, 85, 0, 85, 72, 0, 85, 82, 0, 85,
					85, 0, 85, 87, 88, 255, 255, 0, 85, 89,
					88, 255, 255, 0, 86, 0, 86, 65, 0, 86,
					67, 68, 0, 86, 69, 76, 0, 86, 76, 83,
					0, 86, 80, 72, 0, 86, 83, 76, 0, 87,
					0, 87, 72, 0, 87, 74, 0, 88, 0, 88,
					83, 72, 0, 88, 83, 84, 0, 89, 0, 89,
					72, 0, 89, 88, 0, 90, 0, 90, 67, 0,
					90, 72, 0, 90, 72, 74, 0, 90, 82, 0
				}, new char[249]
				{
					'.', '\u0001', '\u0002', '\u0003', '↘', '↗', '\u203f', '|', '‖', '\u0004',
					'\u0361', 'a', 'ɑ', '\u031f', 'æ', 'ɐ', 'ʌ', 'a', '\u0361', 'i',
					'a', '\u0303', 'ɔ', 'ɶ', 'ɔ', '\u0361', 'ə', '\u033a', 'ʰ', '\u0318',
					'a', '\u0361', 'ʊ', 'ə', 'ɚ', 'b', 'ʙ', 'β', 'ɓ', 'ʱ',
					'\u0324', 'ç', '\u0740', '\u0361', 'ɕ', 'ʨ', 'ǂ', '\u0308', 't', '\u0361',
					'ʃ', 'ʧ', 'ʝ', 'c', '\u0330', 'd', '\u032a', 'ð', 'ɗ', 'ɖ',
					'ɾ', 'ɽ', 'd', '\u0361', 'z', 'ʣ', 'e', 'ɛ', 'ɛ', '\u0361',
					'ə', 'e', '\u0361', 'i', 'ʼ', 'e', '\u0303', 'ɜ', 'ɝ', 'ʜ',
					'ʡ', 'ø', 'ɘ', 'ʢ', 'f', 'g', 'ɡ', 'ɰ', 'ɣ', 'ɠ',
					'ʟ', 'ʔ', 'h', 'ʕ', 'ħ', 'ˑ', 'ɦ', 'i', 'ɪ', 'ɨ',
					'i', '\u0361', 'ə', 'j', 'd', '\u0361', 'ʑ', 'ʥ', 'ɟ', 'd',
					'\u0361', 'ʒ', 'ʤ', 'ʄ', 'j', '\u0361', 'j', 'k', 'l', 'ʷ',
					'\u033b', 'ˡ', 'ǁ', 'ʖ', 'ɫ', 'ɮ', 'ʎ', '\u033c', 'ː', '\u031e',
					'ɭ', '\u031c', 'ɬ', 'ɺ', 'm', '\u033d', 'ɱ', '\u0339', 'n', '\u031a',
					'\u0303', '!', 'ǃ', 'ʗ', 'ŋ', 'ɲ', 'ɳ', 'ⁿ', '\u032f', 'o',
					'œ', 'œ', '\u0303', 'ɔ', '\u0361', 'i', 'o', '\u0303', 'ɤ', 'o',
					'\u0361', 'ə', 'ɵ', 'p', 'ʲ', 'ʘ', 'p', '\u0361', 'f', 'ɸ',
					'ˤ', 'ɒ', 'ɢ', 'χ', 'ʛ', 'ɴ', 'ʠ', 'ʀ', 'q', 'ɻ',
					'ɹ', '\u031d', '\u0331', 'ʁ', '\u02de', 'ʴ', 'r', '\u0320', '\u0319', 's',
					'ˈ', 'ˌ', 'ɕ', 'ʃ', 'ʆ', 'ɧ', 'ʂ', '\u0329', 't', '↓',
					'↑', '→', '\u030f', '\u0300', '\u0304', '\u0301', '\u030b', 'ǀ', 'ʇ', 'θ',
					'ʈ', 't', '\u0361', 's', 'ʦ', 't', '\u0361', 'ʂ', 'u', 'ʊ',
					'ɞ', 'ɯ', 'u', '\u0361', 'ə', 'y', '\u0361', 'ə', 'v', 'ʋ',
					'\u032c', 'ˠ', '\u030a', '\u0334', '\u0325', 'w', 'ʍ', 'ɥ', 'x', '\u02d8',
					'\u0306', 'y', 'ʏ', 'ʉ', 'z', 'ʑ', 'ʒ', 'ʓ', 'ʐ'
				}),
				new PhoneMapCompressed(1028, 52, new byte[260]
				{
					48, 48, 50, 49, 0, 48, 48, 50, 54, 0,
					48, 48, 50, 65, 0, 48, 48, 50, 66, 0,
					48, 48, 50, 67, 0, 48, 48, 50, 68, 0,
					48, 48, 50, 69, 0, 48, 48, 51, 70, 0,
					48, 48, 53, 70, 0, 48, 50, 67, 55, 0,
					48, 50, 67, 57, 0, 48, 50, 67, 65, 0,
					48, 50, 67, 66, 0, 48, 50, 68, 57, 0,
					51, 48, 48, 48, 0, 51, 49, 48, 53, 0,
					51, 49, 48, 54, 0, 51, 49, 48, 55, 0,
					51, 49, 48, 56, 0, 51, 49, 48, 57, 0,
					51, 49, 48, 65, 0, 51, 49, 48, 66, 0,
					51, 49, 48, 67, 0, 51, 49, 48, 68, 0,
					51, 49, 48, 69, 0, 51, 49, 48, 70, 0,
					51, 49, 49, 48, 0, 51, 49, 49, 49, 0,
					51, 49, 49, 50, 0, 51, 49, 49, 51, 0,
					51, 49, 49, 52, 0, 51, 49, 49, 53, 0,
					51, 49, 49, 54, 0, 51, 49, 49, 55, 0,
					51, 49, 49, 56, 0, 51, 49, 49, 57, 0,
					51, 49, 49, 65, 0, 51, 49, 49, 66, 0,
					51, 49, 49, 67, 0, 51, 49, 49, 68, 0,
					51, 49, 49, 69, 0, 51, 49, 49, 70, 0,
					51, 49, 50, 48, 0, 51, 49, 50, 49, 0,
					51, 49, 50, 50, 0, 51, 49, 50, 51, 0,
					51, 49, 50, 52, 0, 51, 49, 50, 53, 0,
					51, 49, 50, 54, 0, 51, 49, 50, 55, 0,
					51, 49, 50, 56, 0, 51, 49, 50, 57, 0
				}, new char[52]
				{
					'!', '&', '*', '+', ',', '-', '.', '?', '_', 'ˇ',
					'ˉ', 'ˊ', 'ˋ', '\u02d9', '\u3000', 'ㄅ', 'ㄆ', 'ㄇ', 'ㄈ', 'ㄉ',
					'ㄊ', 'ㄋ', 'ㄌ', 'ㄍ', 'ㄎ', 'ㄏ', 'ㄐ', 'ㄑ', 'ㄒ', 'ㄓ',
					'ㄔ', 'ㄕ', 'ㄖ', 'ㄗ', 'ㄘ', 'ㄙ', 'ㄚ', 'ㄛ', 'ㄜ', 'ㄝ',
					'ㄞ', 'ㄟ', 'ㄠ', 'ㄡ', 'ㄢ', 'ㄣ', 'ㄤ', 'ㄥ', 'ㄦ', 'ㄧ',
					'ㄨ', 'ㄩ'
				}),
				new PhoneMapCompressed(1031, 53, new byte[129]
				{
					45, 0, 33, 0, 38, 0, 44, 0, 46, 0,
					58, 0, 63, 0, 94, 0, 95, 0, 126, 0,
					49, 0, 50, 0, 65, 0, 65, 87, 0, 65,
					88, 0, 65, 89, 0, 66, 0, 67, 72, 0,
					68, 0, 69, 72, 0, 69, 85, 0, 69, 89,
					0, 70, 0, 71, 0, 72, 0, 73, 72, 0,
					73, 89, 0, 74, 72, 0, 75, 0, 76, 0,
					77, 0, 78, 0, 78, 71, 0, 79, 69, 0,
					79, 72, 0, 79, 87, 0, 79, 89, 0, 80,
					0, 80, 70, 0, 82, 0, 83, 0, 83, 72,
					0, 84, 0, 84, 83, 0, 85, 69, 0, 85,
					72, 0, 85, 87, 0, 85, 89, 0, 86, 0,
					88, 0, 89, 0, 90, 0, 90, 72, 0
				}, new char[53]
				{
					'\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\f', '\u0006', '\b', '\a', '\v',
					'\t', '\n', '\r', '\u000e', '\u000f', '\u0010', '\u0011', '\u0013', '\u0012', '\u0014',
					'\u0015', '\u0016', '\u0017', '\u0018', '\u0019', '\u001a', '\u001b', '\u001c', '\u001d', '\u001e',
					'\u001f', ' ', '!', '"', '#', '$', '%', '&', '\'', '(',
					')', '*', '+', ',', '-', '.', '/', '0', '1', '2',
					'3', '4', '5'
				}),
				new PhoneMapCompressed(1033, 49, new byte[121]
				{
					45, 0, 33, 0, 38, 0, 44, 0, 46, 0,
					63, 0, 95, 0, 49, 0, 50, 0, 65, 65,
					0, 65, 69, 0, 65, 72, 0, 65, 79, 0,
					65, 87, 0, 65, 88, 0, 65, 89, 0, 66,
					0, 67, 72, 0, 68, 0, 68, 72, 0, 69,
					72, 0, 69, 82, 0, 69, 89, 0, 70, 0,
					71, 0, 72, 0, 73, 72, 0, 73, 89, 0,
					74, 72, 0, 75, 0, 76, 0, 77, 0, 78,
					0, 78, 71, 0, 79, 87, 0, 79, 89, 0,
					80, 0, 82, 0, 83, 0, 83, 72, 0, 84,
					0, 84, 72, 0, 85, 72, 0, 85, 87, 0,
					86, 0, 87, 0, 89, 0, 90, 0, 90, 72,
					0
				}, new char[49]
				{
					'\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\a', '\b', '\t', '\n',
					'\v', '\f', '\r', '\u000e', '\u000f', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014',
					'\u0015', '\u0016', '\u0017', '\u0018', '\u0019', '\u001a', '\u001b', '\u001c', '\u001d', '\u001e',
					'\u001f', ' ', '!', '"', '#', '$', '%', '&', '\'', '(',
					')', '*', '+', ',', '-', '.', '/', '0', '1'
				}),
				new PhoneMapCompressed(1034, 35, new byte[76]
				{
					45, 0, 33, 0, 38, 0, 44, 0, 46, 0,
					63, 0, 95, 0, 49, 0, 50, 0, 65, 0,
					66, 0, 67, 72, 0, 68, 0, 69, 0, 70,
					0, 71, 0, 73, 0, 74, 0, 74, 74, 0,
					75, 0, 76, 0, 76, 76, 0, 77, 0, 78,
					0, 78, 74, 0, 79, 0, 80, 0, 82, 0,
					82, 82, 0, 83, 0, 84, 0, 84, 72, 0,
					85, 0, 87, 0, 88, 0
				}, new char[35]
				{
					'\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\a', '\b', '\t', '\n',
					'\u0012', '\u0015', '\u0010', '\v', '\u0017', '\u0014', '\f', '!', '\u0016', '\u0013',
					'\u001d', '\u001e', '\u001a', '\u001b', '\u001c', '\r', '\u0011', '\u001f', ' ', '\u0018',
					'\u000f', '#', '\u000e', '"', '\u0019'
				}),
				new PhoneMapCompressed(1036, 42, new byte[100]
				{
					45, 0, 33, 0, 38, 0, 44, 0, 46, 0,
					63, 0, 95, 0, 126, 0, 49, 0, 65, 0,
					65, 65, 0, 65, 88, 0, 66, 0, 68, 0,
					69, 72, 0, 69, 85, 0, 69, 89, 0, 70,
					0, 71, 0, 72, 89, 0, 73, 89, 0, 75,
					0, 76, 0, 77, 0, 78, 0, 78, 71, 0,
					78, 74, 0, 79, 69, 0, 79, 72, 0, 79,
					87, 0, 80, 0, 82, 0, 83, 0, 83, 72,
					0, 84, 0, 85, 87, 0, 85, 89, 0, 86,
					0, 87, 0, 89, 0, 90, 0, 90, 72, 0
				}, new char[42]
				{
					'\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\a', '\t', '\b', '\v',
					'\n', '\r', '\u000e', '\u000f', '\u0010', '\u001e', '\u0011', '\u0012', '\u0013', '\u0014',
					'\u0016', '\u0017', '\u0018', '\u0019', '\u001a', '\u001b', '\u001c', '\u001d', '\f', '\u001f',
					' ', '!', '"', '#', '$', '%', '\u0015', '&', '\'', '(',
					')', '*'
				}),
				new PhoneMapCompressed(1041, 102, new byte[510]
				{
					48, 48, 50, 49, 0, 48, 48, 50, 55, 0,
					48, 48, 50, 66, 0, 48, 48, 50, 69, 0,
					48, 48, 51, 70, 0, 48, 48, 53, 70, 0,
					48, 48, 55, 67, 0, 51, 48, 57, 67, 0,
					51, 48, 65, 49, 0, 51, 48, 65, 50, 0,
					51, 48, 65, 51, 0, 51, 48, 65, 52, 0,
					51, 48, 65, 53, 0, 51, 48, 65, 54, 0,
					51, 48, 65, 55, 0, 51, 48, 65, 56, 0,
					51, 48, 65, 57, 0, 51, 48, 65, 65, 0,
					51, 48, 65, 66, 0, 51, 48, 65, 67, 0,
					51, 48, 65, 68, 0, 51, 48, 65, 69, 0,
					51, 48, 65, 70, 0, 51, 48, 66, 48, 0,
					51, 48, 66, 49, 0, 51, 48, 66, 50, 0,
					51, 48, 66, 51, 0, 51, 48, 66, 52, 0,
					51, 48, 66, 53, 0, 51, 48, 66, 54, 0,
					51, 48, 66, 55, 0, 51, 48, 66, 56, 0,
					51, 48, 66, 57, 0, 51, 48, 66, 65, 0,
					51, 48, 66, 66, 0, 51, 48, 66, 67, 0,
					51, 48, 66, 68, 0, 51, 48, 66, 69, 0,
					51, 48, 66, 70, 0, 51, 48, 67, 48, 0,
					51, 48, 67, 49, 0, 51, 48, 67, 50, 0,
					51, 48, 67, 51, 0, 51, 48, 67, 52, 0,
					51, 48, 67, 53, 0, 51, 48, 67, 54, 0,
					51, 48, 67, 55, 0, 51, 48, 67, 56, 0,
					51, 48, 67, 57, 0, 51, 48, 67, 65, 0,
					51, 48, 67, 66, 0, 51, 48, 67, 67, 0,
					51, 48, 67, 68, 0, 51, 48, 67, 69, 0,
					51, 48, 67, 70, 0, 51, 48, 68, 48, 0,
					51, 48, 68, 49, 0, 51, 48, 68, 50, 0,
					51, 48, 68, 51, 0, 51, 48, 68, 52, 0,
					51, 48, 68, 53, 0, 51, 48, 68, 54, 0,
					51, 48, 68, 55, 0, 51, 48, 68, 56, 0,
					51, 48, 68, 57, 0, 51, 48, 68, 65, 0,
					51, 48, 68, 66, 0, 51, 48, 68, 67, 0,
					51, 48, 68, 68, 0, 51, 48, 68, 69, 0,
					51, 48, 68, 70, 0, 51, 48, 69, 48, 0,
					51, 48, 69, 49, 0, 51, 48, 69, 50, 0,
					51, 48, 69, 51, 0, 51, 48, 69, 52, 0,
					51, 48, 69, 53, 0, 51, 48, 69, 54, 0,
					51, 48, 69, 55, 0, 51, 48, 69, 56, 0,
					51, 48, 69, 57, 0, 51, 48, 69, 65, 0,
					51, 48, 69, 66, 0, 51, 48, 69, 67, 0,
					51, 48, 69, 68, 0, 51, 48, 69, 69, 0,
					51, 48, 69, 70, 0, 51, 48, 70, 48, 0,
					51, 48, 70, 49, 0, 51, 48, 70, 50, 0,
					51, 48, 70, 51, 0, 51, 48, 70, 52, 0,
					51, 48, 70, 53, 0, 51, 48, 70, 54, 0,
					51, 48, 70, 55, 0, 51, 48, 70, 56, 0,
					51, 48, 70, 57, 0, 51, 48, 70, 65, 0,
					51, 48, 70, 66, 0, 51, 48, 70, 67, 0,
					51, 48, 70, 68, 0, 51, 48, 70, 69, 0
				}, new char[102]
				{
					'!', '\'', '+', '.', '?', '_', '|', '\u309c', 'ァ', 'ア',
					'ィ', 'イ', 'ゥ', 'ウ', 'ェ', 'エ', 'ォ', 'オ', 'カ', 'ガ',
					'キ', 'ギ', 'ク', 'グ', 'ケ', 'ゲ', 'コ', 'ゴ', 'サ', 'ザ',
					'シ', 'ジ', 'ス', 'ズ', 'セ', 'ゼ', 'ソ', 'ゾ', 'タ', 'ダ',
					'チ', 'ヂ', 'ッ', 'ツ', 'ヅ', 'テ', 'デ', 'ト', 'ド', 'ナ',
					'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'バ', 'パ', 'ヒ', 'ビ', 'ピ',
					'フ', 'ブ', 'プ', 'ヘ', 'ベ', 'ペ', 'ホ', 'ボ', 'ポ', 'マ',
					'ミ', 'ム', 'メ', 'モ', 'ャ', 'ヤ', 'ュ', 'ユ', 'ョ', 'ヨ',
					'ラ', 'リ', 'ル', 'レ', 'ロ', 'ヮ', 'ワ', 'ヰ', 'ヱ', 'ヲ',
					'ン', 'ヴ', 'ヵ', 'ヶ', 'ヷ', 'ヸ', 'ヹ', 'ヺ', '・', 'ー',
					'ヽ', 'ヾ'
				}),
				new PhoneMapCompressed(2052, 422, new byte[1755]
				{
					45, 0, 33, 0, 38, 0, 42, 0, 44, 0,
					46, 0, 63, 0, 95, 0, 43, 0, 49, 0,
					50, 0, 51, 0, 52, 0, 53, 0, 65, 0,
					65, 73, 0, 65, 78, 0, 65, 78, 71, 0,
					65, 79, 0, 66, 65, 0, 66, 65, 73, 0,
					66, 65, 78, 0, 66, 65, 78, 71, 0, 66,
					65, 79, 0, 66, 69, 73, 0, 66, 69, 78,
					0, 66, 69, 78, 71, 0, 66, 73, 0, 66,
					73, 65, 78, 0, 66, 73, 65, 79, 0, 66,
					73, 69, 0, 66, 73, 78, 0, 66, 73, 78,
					71, 0, 66, 79, 0, 66, 85, 0, 67, 65,
					0, 67, 65, 73, 0, 67, 65, 78, 0, 67,
					65, 78, 71, 0, 67, 65, 79, 0, 67, 69,
					0, 67, 69, 78, 0, 67, 69, 78, 71, 0,
					67, 72, 65, 0, 67, 72, 65, 73, 0, 67,
					72, 65, 78, 0, 67, 72, 65, 78, 71, 0,
					67, 72, 65, 79, 0, 67, 72, 69, 0, 67,
					72, 69, 78, 0, 67, 72, 69, 78, 71, 0,
					67, 72, 73, 0, 67, 72, 79, 78, 71, 0,
					67, 72, 79, 85, 0, 67, 72, 85, 0, 67,
					72, 85, 65, 73, 0, 67, 72, 85, 65, 78,
					0, 67, 72, 85, 65, 78, 71, 0, 67, 72,
					85, 73, 0, 67, 72, 85, 78, 0, 67, 72,
					85, 79, 0, 67, 73, 0, 67, 79, 78, 71,
					0, 67, 79, 85, 0, 67, 85, 0, 67, 85,
					65, 78, 0, 67, 85, 73, 0, 67, 85, 78,
					0, 67, 85, 79, 0, 68, 65, 0, 68, 65,
					73, 0, 68, 65, 78, 0, 68, 65, 78, 71,
					0, 68, 65, 79, 0, 68, 69, 0, 68, 69,
					73, 0, 68, 69, 78, 0, 68, 69, 78, 71,
					0, 68, 73, 0, 68, 73, 65, 0, 68, 73,
					65, 78, 0, 68, 73, 65, 79, 0, 68, 73,
					69, 0, 68, 73, 78, 71, 0, 68, 73, 85,
					0, 68, 79, 78, 71, 0, 68, 79, 85, 0,
					68, 85, 0, 68, 85, 65, 78, 0, 68, 85,
					73, 0, 68, 85, 78, 0, 68, 85, 79, 0,
					69, 0, 69, 73, 0, 69, 78, 0, 69, 82,
					0, 70, 65, 0, 70, 65, 78, 0, 70, 65,
					78, 71, 0, 70, 69, 73, 0, 70, 69, 78,
					0, 70, 69, 78, 71, 0, 70, 79, 0, 70,
					79, 85, 0, 70, 85, 0, 71, 65, 0, 71,
					65, 73, 0, 71, 65, 78, 0, 71, 65, 78,
					71, 0, 71, 65, 79, 0, 71, 69, 0, 71,
					69, 73, 0, 71, 69, 78, 0, 71, 69, 78,
					71, 0, 71, 79, 78, 71, 0, 71, 79, 85,
					0, 71, 85, 0, 71, 85, 65, 0, 71, 85,
					65, 73, 0, 71, 85, 65, 78, 0, 71, 85,
					65, 78, 71, 0, 71, 85, 73, 0, 71, 85,
					78, 0, 71, 85, 79, 0, 72, 65, 0, 72,
					65, 73, 0, 72, 65, 78, 0, 72, 65, 78,
					71, 0, 72, 65, 79, 0, 72, 69, 0, 72,
					69, 73, 0, 72, 69, 78, 0, 72, 69, 78,
					71, 0, 72, 79, 78, 71, 0, 72, 79, 85,
					0, 72, 85, 0, 72, 85, 65, 0, 72, 85,
					65, 73, 0, 72, 85, 65, 78, 0, 72, 85,
					65, 78, 71, 0, 72, 85, 73, 0, 72, 85,
					78, 0, 72, 85, 79, 0, 74, 73, 0, 74,
					73, 65, 0, 74, 73, 65, 78, 0, 74, 73,
					65, 78, 71, 0, 74, 73, 65, 79, 0, 74,
					73, 69, 0, 74, 73, 78, 0, 74, 73, 78,
					71, 0, 74, 73, 79, 78, 71, 0, 74, 73,
					85, 0, 74, 85, 0, 74, 85, 65, 78, 0,
					74, 85, 69, 0, 74, 85, 78, 0, 75, 65,
					0, 75, 65, 73, 0, 75, 65, 78, 0, 75,
					65, 78, 71, 0, 75, 65, 79, 0, 75, 69,
					0, 75, 69, 73, 0, 75, 69, 78, 0, 75,
					69, 78, 71, 0, 75, 79, 78, 71, 0, 75,
					79, 85, 0, 75, 85, 0, 75, 85, 65, 0,
					75, 85, 65, 73, 0, 75, 85, 65, 78, 0,
					75, 85, 65, 78, 71, 0, 75, 85, 73, 0,
					75, 85, 78, 0, 75, 85, 79, 0, 76, 65,
					0, 76, 65, 73, 0, 76, 65, 78, 0, 76,
					65, 78, 71, 0, 76, 65, 79, 0, 76, 69,
					0, 76, 69, 73, 0, 76, 69, 78, 71, 0,
					76, 73, 0, 76, 73, 65, 0, 76, 73, 65,
					78, 0, 76, 73, 65, 78, 71, 0, 76, 73,
					65, 79, 0, 76, 73, 69, 0, 76, 73, 78,
					0, 76, 73, 78, 71, 0, 76, 73, 85, 0,
					76, 79, 0, 76, 79, 78, 71, 0, 76, 79,
					85, 0, 76, 85, 0, 76, 85, 65, 78, 0,
					76, 85, 69, 0, 76, 85, 78, 0, 76, 85,
					79, 0, 76, 86, 0, 77, 65, 0, 77, 65,
					73, 0, 77, 65, 78, 0, 77, 65, 78, 71,
					0, 77, 65, 79, 0, 77, 69, 0, 77, 69,
					73, 0, 77, 69, 78, 0, 77, 69, 78, 71,
					0, 77, 73, 0, 77, 73, 65, 78, 0, 77,
					73, 65, 79, 0, 77, 73, 69, 0, 77, 73,
					78, 0, 77, 73, 78, 71, 0, 77, 73, 85,
					0, 77, 79, 0, 77, 79, 85, 0, 77, 85,
					0, 78, 65, 0, 78, 65, 73, 0, 78, 65,
					78, 0, 78, 65, 78, 71, 0, 78, 65, 79,
					0, 78, 69, 0, 78, 69, 73, 0, 78, 69,
					78, 0, 78, 69, 78, 71, 0, 78, 73, 0,
					78, 73, 65, 78, 0, 78, 73, 65, 78, 71,
					0, 78, 73, 65, 79, 0, 78, 73, 69, 0,
					78, 73, 78, 0, 78, 73, 78, 71, 0, 78,
					73, 85, 0, 78, 79, 78, 71, 0, 78, 79,
					85, 0, 78, 85, 0, 78, 85, 65, 78, 0,
					78, 85, 69, 0, 78, 85, 79, 0, 78, 86,
					0, 79, 0, 79, 85, 0, 80, 65, 0, 80,
					65, 73, 0, 80, 65, 78, 0, 80, 65, 78,
					71, 0, 80, 65, 79, 0, 80, 69, 73, 0,
					80, 69, 78, 0, 80, 69, 78, 71, 0, 80,
					73, 0, 80, 73, 65, 78, 0, 80, 73, 65,
					79, 0, 80, 73, 69, 0, 80, 73, 78, 0,
					80, 73, 78, 71, 0, 80, 79, 0, 80, 79,
					85, 0, 80, 85, 0, 81, 73, 0, 81, 73,
					65, 0, 81, 73, 65, 78, 0, 81, 73, 65,
					78, 71, 0, 81, 73, 65, 79, 0, 81, 73,
					69, 0, 81, 73, 78, 0, 81, 73, 78, 71,
					0, 81, 73, 79, 78, 71, 0, 81, 73, 85,
					0, 81, 85, 0, 81, 85, 65, 78, 0, 81,
					85, 69, 0, 81, 85, 78, 0, 82, 65, 78,
					0, 82, 65, 78, 71, 0, 82, 65, 79, 0,
					82, 69, 0, 82, 69, 78, 0, 82, 69, 78,
					71, 0, 82, 73, 0, 82, 79, 78, 71, 0,
					82, 79, 85, 0, 82, 85, 0, 82, 85, 65,
					78, 0, 82, 85, 73, 0, 82, 85, 78, 0,
					82, 85, 79, 0, 83, 65, 0, 83, 65, 73,
					0, 83, 65, 78, 0, 83, 65, 78, 71, 0,
					83, 65, 79, 0, 83, 69, 0, 83, 69, 78,
					0, 83, 69, 78, 71, 0, 83, 72, 65, 0,
					83, 72, 65, 73, 0, 83, 72, 65, 78, 0,
					83, 72, 65, 78, 71, 0, 83, 72, 65, 79,
					0, 83, 72, 69, 0, 83, 72, 69, 73, 0,
					83, 72, 69, 78, 0, 83, 72, 69, 78, 71,
					0, 83, 72, 73, 0, 83, 72, 79, 85, 0,
					83, 72, 85, 0, 83, 72, 85, 65, 0, 83,
					72, 85, 65, 73, 0, 83, 72, 85, 65, 78,
					0, 83, 72, 85, 65, 78, 71, 0, 83, 72,
					85, 73, 0, 83, 72, 85, 78, 0, 83, 72,
					85, 79, 0, 83, 73, 0, 83, 79, 78, 71,
					0, 83, 79, 85, 0, 83, 85, 0, 83, 85,
					65, 78, 0, 83, 85, 73, 0, 83, 85, 78,
					0, 83, 85, 79, 0, 84, 65, 0, 84, 65,
					73, 0, 84, 65, 78, 0, 84, 65, 78, 71,
					0, 84, 65, 79, 0, 84, 69, 0, 84, 69,
					73, 0, 84, 69, 78, 71, 0, 84, 73, 0,
					84, 73, 65, 78, 0, 84, 73, 65, 79, 0,
					84, 73, 69, 0, 84, 73, 78, 71, 0, 84,
					79, 78, 71, 0, 84, 79, 85, 0, 84, 85,
					0, 84, 85, 65, 78, 0, 84, 85, 73, 0,
					84, 85, 78, 0, 84, 85, 79, 0, 87, 65,
					0, 87, 65, 73, 0, 87, 65, 78, 0, 87,
					65, 78, 71, 0, 87, 69, 73, 0, 87, 69,
					78, 0, 87, 69, 78, 71, 0, 87, 79, 0,
					87, 85, 0, 88, 73, 0, 88, 73, 65, 0,
					88, 73, 65, 78, 0, 88, 73, 65, 78, 71,
					0, 88, 73, 65, 79, 0, 88, 73, 69, 0,
					88, 73, 78, 0, 88, 73, 78, 71, 0, 88,
					73, 79, 78, 71, 0, 88, 73, 85, 0, 88,
					85, 0, 88, 85, 65, 78, 0, 88, 85, 69,
					0, 88, 85, 78, 0, 89, 65, 0, 89, 65,
					78, 0, 89, 65, 78, 71, 0, 89, 65, 79,
					0, 89, 69, 0, 89, 73, 0, 89, 73, 78,
					0, 89, 73, 78, 71, 0, 89, 79, 0, 89,
					79, 78, 71, 0, 89, 79, 85, 0, 89, 85,
					0, 89, 85, 65, 78, 0, 89, 85, 69, 0,
					89, 85, 78, 0, 90, 65, 0, 90, 65, 73,
					0, 90, 65, 78, 0, 90, 65, 78, 71, 0,
					90, 65, 79, 0, 90, 69, 0, 90, 69, 73,
					0, 90, 69, 78, 0, 90, 69, 78, 71, 0,
					90, 72, 65, 0, 90, 72, 65, 73, 0, 90,
					72, 65, 78, 0, 90, 72, 65, 78, 71, 0,
					90, 72, 65, 79, 0, 90, 72, 69, 0, 90,
					72, 69, 73, 0, 90, 72, 69, 78, 0, 90,
					72, 69, 78, 71, 0, 90, 72, 73, 0, 90,
					72, 79, 78, 71, 0, 90, 72, 79, 85, 0,
					90, 72, 85, 0, 90, 72, 85, 65, 0, 90,
					72, 85, 65, 73, 0, 90, 72, 85, 65, 78,
					0, 90, 72, 85, 65, 78, 71, 0, 90, 72,
					85, 73, 0, 90, 72, 85, 78, 0, 90, 72,
					85, 79, 0, 90, 73, 0, 90, 79, 78, 71,
					0, 90, 79, 85, 0, 90, 85, 0, 90, 85,
					65, 78, 0, 90, 85, 73, 0, 90, 85, 78,
					0, 90, 85, 79, 0
				}, new char[422]
				{
					'\u0001', '\u0002', '\u0003', '\t', '\u0004', '\u0005', '\u0006', '\a', '\b', '\n',
					'\v', '\f', '\r', '\u000e', '\u000f', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014',
					'\u0015', '\u0016', '\u0017', '\u0018', '\u0019', '\u001a', '\u001b', '\u001c', '\u001d', '\u001e',
					'\u001f', ' ', '!', '"', '#', '$', '%', '&', '\'', '(',
					')', '*', '+', ',', '-', '.', '/', '0', '1', '2',
					'3', '4', '5', '6', '7', '8', '9', ':', ';', '<',
					'=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F',
					'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
					'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
					'[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd',
					'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
					'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
					'y', 'z', '{', '|', '}', '~', '\u007f', '\u0080', '\u0081', '\u0082',
					'\u0083', '\u0084', '\u0085', '\u0086', '\u0087', '\u0088', '\u0089', '\u008a', '\u008b', '\u008c',
					'\u008d', '\u008e', '\u008f', '\u0090', '\u0091', '\u0092', '\u0093', '\u0094', '\u0095', '\u0096',
					'\u0097', '\u0098', '\u0099', '\u009a', '\u009b', '\u009c', '\u009d', '\u009e', '\u009f', '\u00a0',
					'¡', '¢', '£', '¤', '¥', '¦', '§', '\u00a8', '©', 'ª',
					'«', '¬', '\u00ad', '®', '\u00af', '°', '±', '²', '³', '\u00b4',
					'µ', '¶', '·', '\u00b8', '¹', 'º', '»', '¼', '½', '¾',
					'¿', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È',
					'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò',
					'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü',
					'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ',
					'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð',
					'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú',
					'û', 'ü', 'ý', 'þ', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą',
					'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď',
					'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę',
					'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ',
					'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ',
					'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ',
					'ķ', 'ĸ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ',
					'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ŋ',
					'ŋ', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ',
					'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş',
					'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ',
					'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų',
					'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż',
					'Ž', 'ž', 'ſ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƅ', 'ƅ', 'Ɔ',
					'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'ƍ', 'Ǝ', 'Ə', 'Ɛ',
					'Ƒ', 'ƒ', 'Ɠ', 'Ɣ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ',
					'ƛ', 'Ɯ', 'Ɲ', 'ƞ', 'Ɵ', 'Ơ', 'ơ', 'Ƣ', 'ƣ', 'Ƥ',
					'ƥ', 'Ʀ'
				})
			};
			_updIds = new char[185]
			{
				'\u0001', '\u0002', '\u0003', '\u0004', '!', '.', 'a', 'b', 'c', 'd',
				'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
				'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
				'y', 'z', '|', 'æ', 'ç', 'ð', 'ø', 'ħ', 'ŋ', 'œ',
				'ǀ', 'ǁ', 'ǂ', 'ǃ', 'ɐ', 'ɑ', 'ɒ', 'ɓ', 'ɔ', 'ɕ',
				'ɖ', 'ɗ', 'ɘ', 'ə', 'ɚ', 'ɛ', 'ɜ', 'ɝ', 'ɞ', 'ɟ',
				'ɠ', 'ɡ', 'ɢ', 'ɣ', 'ɤ', 'ɥ', 'ɦ', 'ɧ', 'ɨ', 'ɪ',
				'ɫ', 'ɬ', 'ɭ', 'ɮ', 'ɯ', 'ɰ', 'ɱ', 'ɲ', 'ɳ', 'ɴ',
				'ɵ', 'ɶ', 'ɸ', 'ɹ', 'ɺ', 'ɻ', 'ɽ', 'ɾ', 'ʀ', 'ʁ',
				'ʂ', 'ʃ', 'ʄ', 'ʆ', 'ʇ', 'ʈ', 'ʉ', 'ʊ', 'ʋ', 'ʌ',
				'ʍ', 'ʎ', 'ʏ', 'ʐ', 'ʑ', 'ʒ', 'ʓ', 'ʔ', 'ʕ', 'ʖ',
				'ʗ', 'ʘ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʡ', 'ʢ',
				'ʣ', 'ʤ', 'ʥ', 'ʦ', 'ʧ', 'ʨ', 'ʰ', 'ʱ', 'ʲ', 'ʴ',
				'ʷ', 'ʼ', 'ˈ', 'ˌ', 'ː', 'ˑ', '\u02d8', '\u02de', 'ˠ', 'ˡ',
				'ˤ', '\u0300', '\u0301', '\u0303', '\u0304', '\u0306', '\u0308', '\u030a', '\u030b', '\u030f',
				'\u0318', '\u0319', '\u031a', '\u031c', '\u031d', '\u031e', '\u031f', '\u0320', '\u0324', '\u0325',
				'\u0329', '\u032a', '\u032c', '\u032f', '\u0330', '\u0331', '\u0334', '\u0339', '\u033a', '\u033b',
				'\u033c', '\u033d', '\u0361', 'β', 'θ', 'χ', '\u0740', '‖', '\u203f', 'ⁿ',
				'↑', '→', '↓', '↗', '↘'
			};
			_phoneMaps = DecompressPhoneMaps(_phoneMapsCompressed);
			_upsConverter = new PhonemeConverter(_phoneMaps[0]);
		}

		private PhonemeConverter(PhoneMap phoneMap)
		{
			_phoneMap = phoneMap;
		}

		internal static string ConvertPronToId(string pronunciation, int lcid)
		{
			PhonemeConverter phonemeConverter = UpsConverter;
			PhoneMap[] phoneMaps = _phoneMaps;
			foreach (PhoneMap phoneMap in phoneMaps)
			{
				if (phoneMap._lcid == lcid)
				{
					phonemeConverter = new PhonemeConverter(phoneMap);
				}
			}
			string text = phonemeConverter.ConvertPronToId(pronunciation);
			if (string.IsNullOrEmpty(text))
			{
				throw new FormatException(SR.Get(SRID.EmptyPronunciationString));
			}
			return text;
		}

		internal string ConvertPronToId(string sPhone)
		{
			sPhone = sPhone.Trim(Helpers._achTrimChars);
			if (string.IsNullOrEmpty(sPhone))
			{
				return string.Empty;
			}
			int i = 0;
			int length = sPhone.Length;
			StringBuilder stringBuilder = new StringBuilder(length);
			PhoneId phoneId = new PhoneId();
			while (i < length)
			{
				int num = sPhone.IndexOf(' ', i + 1);
				if (num < 0)
				{
					num = length;
				}
				string text = sPhone.Substring(i, num - i);
				string phone = text.ToUpperInvariant();
				phoneId._phone = phone;
				int num2 = Array.BinarySearch(_phoneMap._phoneIds, phoneId, phoneId);
				if (num2 >= 0)
				{
					char[] cp = _phoneMap._phoneIds[num2]._cp;
					foreach (char value in cp)
					{
						stringBuilder.Append(value);
					}
					for (i = num; i < length && sPhone[i] == ' '; i++)
					{
					}
					continue;
				}
				throw new FormatException(SR.Get(SRID.InvalidPhoneme, text));
			}
			return stringBuilder.ToString();
		}

		internal static void ValidateUpsIds(string ids)
		{
			ValidateUpsIds(ids.ToCharArray());
		}

		internal static void ValidateUpsIds(char[] ids)
		{
			foreach (char c in ids)
			{
				if (Array.BinarySearch(_updIds, c) < 0)
				{
					throw new FormatException(SR.Get(SRID.InvalidPhoneme, c));
				}
			}
		}

		private static PhoneMap[] DecompressPhoneMaps(PhoneMapCompressed[] pmComps)
		{
			PhoneMap[] array = new PhoneMap[pmComps.Length];
			for (int i = 0; i < pmComps.Length; i++)
			{
				PhoneMapCompressed phoneMapCompressed = pmComps[i];
				PhoneMap phoneMap = (array[i] = new PhoneMap());
				phoneMap._lcid = phoneMapCompressed._lcid;
				phoneMap._phoneIds = new PhoneId[phoneMapCompressed._count];
				int num = 0;
				int num2 = 0;
				for (int j = 0; j < phoneMap._phoneIds.Length; j++)
				{
					phoneMap._phoneIds[j] = new PhoneId();
					int num3 = 0;
					int k;
					for (k = num; phoneMapCompressed._phones[k] != 0; k++)
					{
						if (phoneMapCompressed._phones[k] == byte.MaxValue)
						{
							num3++;
						}
					}
					int num4 = k - num - num3;
					char[] array2 = new char[num4];
					for (int l = 0; l < num4; l++)
					{
						array2[l] = (char)phoneMapCompressed._phones[num++];
					}
					num += num3 + 1;
					phoneMap._phoneIds[j]._phone = new string(array2);
					phoneMap._phoneIds[j]._cp = new char[num3 + 1];
					for (int m = 0; m < phoneMap._phoneIds[j]._cp.Length; m++)
					{
						phoneMap._phoneIds[j]._cp[m] = phoneMapCompressed._cps[num2++];
					}
				}
			}
			return array;
		}
	}
	internal abstract class RedBackList : IEnumerable
	{
		private class MyEnumerator : IEnumerator
		{
			private TreeNode _node;

			private TreeNode _root;

			private bool _moved;

			public object Current
			{
				get
				{
					if (_node == null)
					{
						throw new InvalidOperationException();
					}
					return _node.Key;
				}
			}

			internal MyEnumerator(TreeNode node)
			{
				_root = node;
			}

			public bool MoveNext()
			{
				if (!_moved)
				{
					_node = ((_root != null) ? FindMinSubTree(_root) : null);
					_moved = true;
				}
				else
				{
					_node = ((_node != null) ? FindSuccessor(_node) : null);
				}
				return _node != null;
			}

			public void Reset()
			{
				_moved = false;
				_node = null;
			}
		}

		private class TreeNode
		{
			private object _key;

			private bool _isRed;

			private TreeNode _leftChild;

			private TreeNode _rightChild;

			private TreeNode _parent;

			internal TreeNode Left
			{
				get
				{
					return _leftChild;
				}
				set
				{
					_leftChild = value;
					if (_leftChild != null)
					{
						_leftChild._parent = this;
					}
				}
			}

			internal TreeNode Right
			{
				get
				{
					return _rightChild;
				}
				set
				{
					_rightChild = value;
					if (_rightChild != null)
					{
						_rightChild._parent = this;
					}
				}
			}

			internal TreeNode Parent
			{
				get
				{
					return _parent;
				}
				set
				{
					_parent = value;
				}
			}

			internal bool IsRed
			{
				get
				{
					return _isRed;
				}
				set
				{
					_isRed = value;
				}
			}

			internal object Key => _key;

			internal TreeNode(object key)
			{
				_key = key;
			}

			internal void CopyNode(TreeNode from)
			{
				_key = from._key;
			}
		}

		private enum NodeColor
		{
			BLACK,
			RED
		}

		private TreeNode _root;

		internal bool IsEmpty => _root == null;

		internal bool CountIsOne
		{
			get
			{
				if (_root != null && _root.Left == null)
				{
					return _root.Right == null;
				}
				return false;
			}
		}

		internal bool ContainsMoreThanOneItem
		{
			get
			{
				if (_root != null)
				{
					if (_root.Right == null)
					{
						return _root.Left != null;
					}
					return true;
				}
				return false;
			}
		}

		internal object First
		{
			get
			{
				if (_root == null)
				{
					return null;
				}
				return FindMinSubTree(_root).Key;
			}
		}

		internal RedBackList()
		{
		}

		internal void Add(object key)
		{
			TreeNode treeNode = new TreeNode(key);
			treeNode.IsRed = true;
			InsertNode(_root, treeNode);
			FixUpInsertion(treeNode);
			_root = FindRoot(treeNode);
		}

		internal void Remove(object key)
		{
			TreeNode treeNode = FindItem(_root, key);
			if (treeNode == null)
			{
				throw new KeyNotFoundException();
			}
			TreeNode treeNode2 = DeleteNode(treeNode);
			FixUpRemoval(treeNode2);
			if (treeNode2 == _root)
			{
				if (_root.Left != null)
				{
					_root = FindRoot(_root.Left);
				}
				else if (_root.Right != null)
				{
					_root = FindRoot(_root.Right);
				}
				else
				{
					_root = null;
				}
			}
			else
			{
				_root = FindRoot(_root);
			}
		}

		public IEnumerator GetEnumerator()
		{
			return new MyEnumerator(_root);
		}

		protected abstract int CompareTo(object object1, object object2);

		private static TreeNode GetUncle(TreeNode node)
		{
			if (node.Parent == node.Parent.Parent.Left)
			{
				return node.Parent.Parent.Right;
			}
			return node.Parent.Parent.Left;
		}

		private static TreeNode GetSibling(TreeNode node, TreeNode parent)
		{
			if (node == parent.Left)
			{
				return parent.Right;
			}
			return parent.Left;
		}

		private static NodeColor GetColor(TreeNode node)
		{
			if (node != null)
			{
				if (!node.IsRed)
				{
					return NodeColor.BLACK;
				}
				return NodeColor.RED;
			}
			return NodeColor.BLACK;
		}

		private static void SetColor(TreeNode node, NodeColor color)
		{
			if (node != null)
			{
				node.IsRed = color == NodeColor.RED;
			}
		}

		private static void TakeParent(TreeNode node, TreeNode newNode)
		{
			if (node.Parent == null)
			{
				if (newNode != null)
				{
					newNode.Parent = null;
				}
				return;
			}
			if (node.Parent.Left == node)
			{
				node.Parent.Left = newNode;
				return;
			}
			if (node.Parent.Right == node)
			{
				node.Parent.Right = newNode;
				return;
			}
			throw new InvalidOperationException();
		}

		private static TreeNode RotateLeft(TreeNode node)
		{
			TreeNode right = node.Right;
			node.Right = right.Left;
			TakeParent(node, right);
			right.Left = node;
			return right;
		}

		private static TreeNode RotateRight(TreeNode node)
		{
			TreeNode left = node.Left;
			node.Left = left.Right;
			TakeParent(node, left);
			left.Right = node;
			return left;
		}

		private static TreeNode FindMinSubTree(TreeNode node)
		{
			while (node.Left != null)
			{
				node = node.Left;
			}
			return node;
		}

		private static TreeNode FindSuccessor(TreeNode node)
		{
			if (node.Right == null)
			{
				while (node.Parent != null && node.Parent.Left != node)
				{
					node = node.Parent;
				}
				if (node.Parent != null)
				{
					return node.Parent;
				}
				return null;
			}
			return FindMinSubTree(node.Right);
		}

		private static TreeNode DeleteNode(TreeNode node)
		{
			if (node.Right == null)
			{
				TakeParent(node, node.Left);
				return node;
			}
			if (node.Left == null)
			{
				TakeParent(node, node.Right);
				return node;
			}
			TreeNode treeNode = FindSuccessor(node);
			node.CopyNode(treeNode);
			TakeParent(treeNode, treeNode.Right);
			return treeNode;
		}

		private TreeNode InsertNode(TreeNode node, TreeNode newNode)
		{
			if (node == null)
			{
				return newNode;
			}
			int num = CompareTo(newNode.Key, node.Key);
			if (num < 0)
			{
				node.Left = InsertNode(node.Left, newNode);
			}
			else
			{
				node.Right = InsertNode(node.Right, newNode);
			}
			return node;
		}

		private TreeNode FindItem(TreeNode node, object key)
		{
			if (node == null)
			{
				return null;
			}
			int num = CompareTo(key, node.Key);
			if (num == 0)
			{
				return node;
			}
			if (num < 0)
			{
				return FindItem(node.Left, key);
			}
			return FindItem(node.Right, key);
		}

		private TreeNode FindRoot(TreeNode node)
		{
			while (node.Parent != null)
			{
				node = node.Parent;
			}
			return node;
		}

		private void FixUpInsertion(TreeNode node)
		{
			FixInsertCase1(node);
		}

		private void FixInsertCase1(TreeNode node)
		{
			if (node.Parent == null)
			{
				node.IsRed = false;
			}
			else
			{
				FixInsertCase2(node);
			}
		}

		private void FixInsertCase2(TreeNode node)
		{
			if (GetColor(node.Parent) != 0)
			{
				TreeNode uncle = GetUncle(node);
				if (GetColor(uncle) == NodeColor.RED)
				{
					SetColor(node.Parent, NodeColor.BLACK);
					SetColor(uncle, NodeColor.BLACK);
					SetColor(node.Parent.Parent, NodeColor.RED);
					FixInsertCase1(node.Parent.Parent);
				}
				else
				{
					FixInsertCase3(node);
				}
			}
		}

		private void FixInsertCase3(TreeNode node)
		{
			if (node == node.Parent.Right && node.Parent == node.Parent.Parent.Left)
			{
				RotateLeft(node.Parent);
				node = node.Left;
			}
			else if (node == node.Parent.Left && node.Parent == node.Parent.Parent.Right)
			{
				RotateRight(node.Parent);
				node = node.Right;
			}
			FixInsertCase4(node);
		}

		private void FixInsertCase4(TreeNode node)
		{
			SetColor(node.Parent, NodeColor.BLACK);
			SetColor(node.Parent.Parent, NodeColor.RED);
			if (node == node.Parent.Left)
			{
				RotateRight(node.Parent.Parent);
			}
			else
			{
				RotateLeft(node.Parent.Parent);
			}
		}

		private static void FixUpRemoval(TreeNode node)
		{
			TreeNode node2 = ((node.Left == null) ? node.Right : node.Left);
			if (GetColor(node) == NodeColor.BLACK)
			{
				if (GetColor(node2) == NodeColor.RED)
				{
					SetColor(node2, NodeColor.BLACK);
				}
				else if (node.Parent != null)
				{
					FixRemovalCase2(GetSibling(node2, node.Parent));
				}
			}
		}

		private static void FixRemovalCase1(TreeNode node)
		{
			if (node.Parent != null)
			{
				FixRemovalCase2(GetSibling(node, node.Parent));
			}
		}

		private static void FixRemovalCase2(TreeNode sibling)
		{
			if (GetColor(sibling) == NodeColor.RED)
			{
				TreeNode parent = sibling.Parent;
				SetColor(parent, NodeColor.RED);
				SetColor(sibling, NodeColor.BLACK);
				if (sibling == parent.Right)
				{
					RotateLeft(sibling.Parent);
					sibling = parent.Right;
				}
				else
				{
					RotateRight(sibling.Parent);
					sibling = parent.Left;
				}
			}
			FixRemovalCase3(sibling);
		}

		private static void FixRemovalCase3(TreeNode sibling)
		{
			if (GetColor(sibling.Parent) == NodeColor.BLACK && GetColor(sibling) == NodeColor.BLACK && GetColor(sibling.Left) == NodeColor.BLACK && GetColor(sibling.Right) == NodeColor.BLACK)
			{
				SetColor(sibling, NodeColor.RED);
				FixRemovalCase1(sibling.Parent);
			}
			else
			{
				FixRemovalCase4(sibling);
			}
		}

		private static void FixRemovalCase4(TreeNode sibling)
		{
			if (GetColor(sibling.Parent) == NodeColor.RED && GetColor(sibling) == NodeColor.BLACK && GetColor(sibling.Left) == NodeColor.BLACK && GetColor(sibling.Right) == NodeColor.BLACK)
			{
				SetColor(sibling, NodeColor.RED);
				SetColor(sibling.Parent, NodeColor.BLACK);
			}
			else
			{
				FixRemovalCase5(sibling);
			}
		}

		private static void FixRemovalCase5(TreeNode sibling)
		{
			if (sibling == sibling.Parent.Right && GetColor(sibling) == NodeColor.BLACK && GetColor(sibling.Left) == NodeColor.RED && GetColor(sibling.Right) == NodeColor.BLACK)
			{
				SetColor(sibling, NodeColor.RED);
				SetColor(sibling.Left, NodeColor.BLACK);
				RotateRight(sibling);
				sibling = sibling.Parent;
			}
			else if (sibling == sibling.Parent.Left && GetColor(sibling) == NodeColor.BLACK && GetColor(sibling.Right) == NodeColor.RED && GetColor(sibling.Left) == NodeColor.BLACK)
			{
				SetColor(sibling, NodeColor.RED);
				SetColor(sibling.Right, NodeColor.BLACK);
				RotateLeft(sibling);
				sibling = sibling.Parent;
			}
			FixRemovalCase6(sibling);
		}

		private static void FixRemovalCase6(TreeNode sibling)
		{
			SetColor(sibling, GetColor(sibling.Parent));
			SetColor(sibling.Parent, NodeColor.BLACK);
			if (sibling == sibling.Parent.Right)
			{
				SetColor(sibling.Right, NodeColor.BLACK);
				RotateLeft(sibling.Parent);
			}
			else
			{
				SetColor(sibling.Left, NodeColor.BLACK);
				RotateRight(sibling.Parent);
			}
		}
	}
	internal class ResourceLoader
	{
		internal Stream LoadFile(Uri uri, out string mimeType, out Uri baseUri, out string localPath)
		{
			localPath = null;
			Stream stream = null;
			if (!uri.IsAbsoluteUri || uri.IsFile)
			{
				string text = (uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString);
				try
				{
					stream = new FileStream(text, FileMode.Open, FileAccess.Read, FileShare.Read);
				}
				catch
				{
					if (Directory.Exists(text))
					{
						throw new InvalidOperationException(SR.Get(SRID.CannotReadFromDirectory, text));
					}
					throw;
				}
				baseUri = null;
			}
			else
			{
				try
				{
					stream = DownloadData(uri, out baseUri);
				}
				catch (WebException ex)
				{
					throw new IOException(ex.Message, ex);
				}
			}
			mimeType = null;
			return stream;
		}

		internal void UnloadFile(string localPath)
		{
		}

		internal Stream LoadFile(Uri uri, out string localPath, out Uri redirectedUri)
		{
			string mimeType;
			return LoadFile(uri, out mimeType, out redirectedUri, out localPath);
		}

		private static Stream DownloadData(Uri uri, out Uri redirectedUri)
		{
			WebRequest webRequest = WebRequest.Create(uri);
			webRequest.Credentials = CredentialCache.DefaultCredentials;
			using HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
			using (httpWebResponse.GetResponseStream())
			{
				redirectedUri = httpWebResponse.ResponseUri;
				using WebClient webClient = new WebClient();
				webClient.UseDefaultCredentials = true;
				return new MemoryStream(webClient.DownloadData(redirectedUri));
			}
		}
	}
	internal static class SapiAttributeParser
	{
		internal static CultureInfo GetCultureInfoFromLanguageString(string valueString)
		{
			string[] array = valueString.Split(new char[1] { ';' });
			string text = array[0].Trim();
			if (!string.IsNullOrEmpty(text))
			{
				try
				{
					return new CultureInfo(int.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture), useUserOverride: false);
				}
				catch (ArgumentException)
				{
					return null;
				}
			}
			return null;
		}

		internal static List<SpeechAudioFormatInfo> GetAudioFormatsFromString(string valueString)
		{
			List<SpeechAudioFormatInfo> list = new List<SpeechAudioFormatInfo>();
			string[] array = valueString.Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (!string.IsNullOrEmpty(text))
				{
					SpeechAudioFormatInfo speechAudioFormatInfo = AudioFormatConverter.ToSpeechAudioFormatInfo(text);
					if (speechAudioFormatInfo != null)
					{
						list.Add(speechAudioFormatInfo);
					}
				}
			}
			return list;
		}
	}
	internal class SeekableReadStream : Stream
	{
		private long _virtualPosition;

		private List<byte> _buffer = new List<byte>();

		private Stream _baseStream;

		private bool _cacheDataForSeeking = true;

		private bool _canSeek;

		internal bool CacheDataForSeeking
		{
			set
			{
				_cacheDataForSeeking = value;
			}
		}

		public override bool CanRead => true;

		public override bool CanSeek
		{
			get
			{
				if (!_canSeek)
				{
					return _cacheDataForSeeking;
				}
				return true;
			}
		}

		public override bool CanWrite => false;

		public override long Length => _baseStream.Length;

		public override long Position
		{
			get
			{
				if (_canSeek)
				{
					return _baseStream.Position;
				}
				return _virtualPosition;
			}
			set
			{
				if (_canSeek)
				{
					_baseStream.Position = value;
				}
				else
				{
					if (value == _virtualPosition)
					{
						return;
					}
					if (value < 0)
					{
						throw new ArgumentOutOfRangeException("value", SR.Get(SRID.MustBeGreaterThanZero));
					}
					if (!_cacheDataForSeeking)
					{
						throw new NotSupportedException(SR.Get(SRID.SeekNotSupported));
					}
					if (value < _buffer.Count)
					{
						_virtualPosition = value;
						return;
					}
					long num = value - _buffer.Count;
					if (num > int.MaxValue)
					{
						throw new NotSupportedException(SR.Get(SRID.SeekNotSupported));
					}
					byte[] array = new byte[num];
					Helpers.BlockingRead(_baseStream, array, 0, (int)num);
					_buffer.AddRange(array);
					_virtualPosition = value;
				}
			}
		}

		internal SeekableReadStream(Stream baseStream)
		{
			_canSeek = baseStream.CanSeek;
			_baseStream = baseStream;
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			if (_canSeek)
			{
				return _baseStream.Read(buffer, offset, count);
			}
			int num = 0;
			if (_virtualPosition < _buffer.Count)
			{
				int num2 = (int)(_buffer.Count - _virtualPosition);
				if (num2 > count)
				{
					num2 = count;
				}
				_buffer.CopyTo((int)_virtualPosition, buffer, offset, num2);
				count -= num2;
				_virtualPosition += num2;
				offset += num2;
				num += num2;
				if (!_cacheDataForSeeking && _virtualPosition >= _buffer.Count)
				{
					_buffer.Clear();
				}
			}
			if (count > 0)
			{
				int num3 = _baseStream.Read(buffer, offset, count);
				num += num3;
				_virtualPosition += num3;
				if (_cacheDataForSeeking)
				{
					_buffer.Capacity += num3;
					for (int i = 0; i < num3; i++)
					{
						_buffer.Add(buffer[offset + i]);
					}
				}
			}
			return num;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			return Position = checked(origin switch
			{
				SeekOrigin.Begin => offset, 
				SeekOrigin.Current => Position + offset, 
				SeekOrigin.End => Length + offset, 
				_ => throw new ArgumentException(SR.Get(SRID.EnumInvalid, "SeekOrigin"), "origin"), 
			});
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException(SR.Get(SRID.SeekNotSupported));
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException(SR.Get(SRID.StreamMustBeWriteable));
		}

		public override void Flush()
		{
			_baseStream.Flush();
		}
	}
	internal sealed class StreamMarshaler : IDisposable
	{
		private HGlobalSafeHandle _safeHMem = new HGlobalSafeHandle();

		private Stream _stream;

		internal Stream Stream => _stream;

		internal uint Position
		{
			set
			{
				_stream.Position = value;
			}
		}

		internal StreamMarshaler()
		{
		}

		internal StreamMarshaler(Stream stream)
		{
			_stream = stream;
		}

		public void Dispose()
		{
			_safeHMem.Dispose();
		}

		internal void ReadArray<T>(T[] ao, int c)
		{
			Type typeFromHandle = typeof(T);
			int num = Marshal.SizeOf(typeFromHandle);
			int num2 = num * c;
			byte[] source = Helpers.ReadStreamToByteArray(_stream, num2);
			IntPtr intPtr = _safeHMem.Buffer(num2);
			Marshal.Copy(source, 0, intPtr, num2);
			for (int i = 0; i < c; i++)
			{
				ao[i] = (T)Marshal.PtrToStructure((IntPtr)((long)intPtr + i * num), typeFromHandle);
			}
		}

		internal void WriteArray<T>(T[] ao, int c)
		{
			Type typeFromHandle = typeof(T);
			int num = Marshal.SizeOf(typeFromHandle);
			int num2 = num * c;
			byte[] array = new byte[num2];
			IntPtr intPtr = _safeHMem.Buffer(num2);
			for (int i = 0; i < c; i++)
			{
				Marshal.StructureToPtr((object)ao[i], (IntPtr)((long)intPtr + i * num), fDeleteOld: false);
			}
			Marshal.Copy(intPtr, array, 0, num2);
			_stream.Write(array, 0, num2);
		}

		internal void ReadArrayChar(char[] ach, int c)
		{
			int num = c * 2;
			if (num > 0)
			{
				byte[] source = Helpers.ReadStreamToByteArray(_stream, num);
				IntPtr intPtr = _safeHMem.Buffer(num);
				Marshal.Copy(source, 0, intPtr, num);
				Marshal.Copy(intPtr, ach, 0, c);
			}
		}

		internal string ReadNullTerminatedString()
		{
			BinaryReader binaryReader = new BinaryReader(_stream, Encoding.Unicode);
			StringBuilder stringBuilder = new StringBuilder();
			while (true)
			{
				char c = binaryReader.ReadChar();
				if (c == '\0')
				{
					break;
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		internal void WriteArrayChar(char[] ach, int c)
		{
			int num = c * 2;
			if (num > 0)
			{
				byte[] array = new byte[num];
				IntPtr intPtr = _safeHMem.Buffer(num);
				Marshal.Copy(ach, 0, intPtr, c);
				Marshal.Copy(intPtr, array, 0, num);
				_stream.Write(array, 0, num);
			}
		}

		internal void ReadStream(object o)
		{
			int num = Marshal.SizeOf(o.GetType());
			byte[] source = Helpers.ReadStreamToByteArray(_stream, num);
			IntPtr intPtr = _safeHMem.Buffer(num);
			Marshal.Copy(source, 0, intPtr, num);
			Marshal.PtrToStructure(intPtr, o);
		}

		internal void WriteStream(object o)
		{
			int num = Marshal.SizeOf(o.GetType());
			byte[] array = new byte[num];
			IntPtr intPtr = _safeHMem.Buffer(num);
			Marshal.StructureToPtr(o, intPtr, fDeleteOld: false);
			Marshal.Copy(intPtr, array, 0, num);
			_stream.Write(array, 0, num);
		}
	}
	internal class StringBlob
	{
		private const int _sizeOfChar = 2;

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

		private List<string> _refStrings = new List<string>();

		private List<int> _offsetStrings = new List<int>();

		private int _cWords;

		private int _totalStringSizes = 1;

		internal string this[int index]
		{
			get
			{
				if (index < 1 || index > _cWords)
				{
					throw new InvalidOperationException();
				}
				return _refStrings[index - 1];
			}
		}

		internal int Count => _cWords;

		internal StringBlob()
		{
		}

		internal StringBlob(char[] pszStringArray)
		{
			int num = pszStringArray.Length;
			if (num <= 0)
			{
				return;
			}
			if (pszStringArray[0] != 0)
			{
				throw new FormatException(SR.Get(SRID.RecognizerInvalidBinaryGrammar));
			}
			int i = 1;
			int num2 = num;
			int num3 = 1;
			for (; i < num2; i++)
			{
				if (pszStringArray[i] == '\0')
				{
					string text = new string(pszStringArray, num3, i - num3);
					_refStrings.Add(text);
					_offsetStrings.Add(_totalStringSizes);
					_strings.Add(text, ++_cWords);
					_totalStringSizes += text.Length + 1;
					num3 = i + 1;
				}
			}
		}

		internal int Add(string psz, out int idWord)
		{
			int num = 0;
			idWord = 0;
			if (!string.IsNullOrEmpty(psz))
			{
				if (!_strings.TryGetValue(psz, out idWord))
				{
					idWord = ++_cWords;
					num = _totalStringSizes;
					_refStrings.Add(psz);
					_offsetStrings.Add(num);
					_strings.Add(psz, _cWords);
					_totalStringSizes += psz.Length + 1;
				}
				else
				{
					num = OffsetFromId(idWord);
				}
			}
			return num;
		}

		internal int Find(string psz)
		{
			if (string.IsNullOrEmpty(psz) || _cWords == 0)
			{
				return 0;
			}
			if (!_strings.TryGetValue(psz, out var value))
			{
				return -1;
			}
			return value;
		}

		internal string FromOffset(int offset)
		{
			int num = 1;
			int num2 = 1;
			if (offset == 1 && _cWords >= 1)
			{
				return this[num2];
			}
			foreach (string refString in _refStrings)
			{
				num2++;
				num += refString.Length + 1;
				if (offset == num)
				{
					return this[num2];
				}
			}
			return null;
		}

		internal int StringSize()
		{
			if (_cWords <= 0)
			{
				return 0;
			}
			return _totalStringSizes;
		}

		internal int SerializeSize()
		{
			return ((StringSize() * 2 + 3) & -4) / 2;
		}

		internal char[] SerializeData()
		{
			int num = SerializeSize();
			char[] array = new char[num];
			int num2 = 1;
			foreach (string refString in _refStrings)
			{
				for (int i = 0; i < refString.Length; i++)
				{
					array[num2++] = refString[i];
				}
				array[num2++] = '\0';
			}
			if (StringSize() % 2 == 1)
			{
				array[num2++] = '쳌';
			}
			return array;
		}

		internal int OffsetFromId(int index)
		{
			if (index > 0)
			{
				return _offsetStrings[index - 1];
			}
			return 0;
		}
	}
}
namespace System.Speech.Internal.SapiInterop
{
	[ComImport]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	[Guid("14056581-E16C-11D2-BB90-00C04F8EE6C0")]
	internal interface ISpDataKey
	{
		[PreserveSig]
		int SetData([MarshalAs(UnmanagedType.LPWStr)] string valueName, uint cbData, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data);

		[PreserveSig]
		int GetData([MarshalAs(UnmanagedType.LPWStr)] string valueName, ref uint pcbData, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data);

		[PreserveSig]
		int SetStringValue([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.LPWStr)] string value);

		[PreserveSig]
		int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.LPWStr)] out string value);

		[PreserveSig]
		int SetDWORD([MarshalAs(UnmanagedType.LPWStr)] string valueName, uint dwValue);

		[PreserveSig]
		int GetDWORD([MarshalAs(UnmanagedType.LPWStr)] string valueName, ref uint pdwValue);

		[PreserveSig]
		int OpenKey([MarshalAs(UnmanagedType.LPWStr)] string subKeyName, out ISpDataKey ppSubKey);

		[PreserveSig]
		int CreateKey([MarshalAs(UnmanagedType.LPWStr)] string subKey, out ISpDataKey ppSubKey);

		[PreserveSig]
		int DeleteKey([MarshalAs(UnmanagedType.LPWStr)] string subKey);

		[PreserveSig]
		int DeleteValue([MarshalAs(UnmanagedType.LPWStr)] string valueName);

		[PreserveSig]
		int EnumKeys(uint index, [MarshalAs(UnmanagedType.LPWStr)] out string ppszSubKeyName);

		[PreserveSig]
		int EnumValues(uint index, [MarshalAs(UnmanagedType.LPWStr)] out string valueName);
	}
}
namespace System.Speech.Internal.ObjectTokens
{
	internal class RegistryDataKey : ISpDataKey, IEnumerable<RegistryDataKey>, IEnumerable, IDisposable
	{
		internal enum SAPIErrorCodes
		{
			STG_E_FILENOTFOUND = -2147287038,
			SPERR_UNSUPPORTED_FORMAT = -2147201021,
			SPERR_DEVICE_BUSY = -2147201018,
			SPERR_DEVICE_NOT_SUPPORTED = -2147201017,
			SPERR_DEVICE_NOT_ENABLED = -2147201016,
			SPERR_NO_DRIVER = -2147201015,
			SPERR_TOO_MANY_GRAMMARS = -2147200990,
			SPERR_INVALID_IMPORT = -2147200988,
			SPERR_AUDIO_BUFFER_OVERFLOW = -2147200977,
			SPERR_NO_AUDIO_DATA = -2147200976,
			SPERR_NO_MORE_ITEMS = -2147200967,
			SPERR_NOT_FOUND = -2147200966,
			SPERR_GENERIC_MMSYS_ERROR = -2147200964,
			SPERR_NOT_TOPLEVEL_RULE = -2147200940,
			SPERR_NOT_ACTIVE_SESSION = -2147200925,
			SPERR_SML_GENERATION_FAIL = -2147200921,
			SPERR_SHARED_ENGINE_DISABLED = -2147200906,
			SPERR_RECOGNIZER_NOT_FOUND = -2147200905,
			SPERR_AUDIO_NOT_FOUND = -2147200904,
			S_OK = 0,
			S_FALSE = 1,
			E_INVALIDARG = -2147024809,
			SP_NO_RULES_TO_ACTIVATE = 282747,
			ERROR_MORE_DATA = 20714
		}

		internal string _sKeyId;

		internal ISpDataKey _sapiRegKey;

		internal bool _disposeSapiKey;

		internal string Id => (string)_sKeyId.Clone();

		internal string Name
		{
			get
			{
				int num = _sKeyId.LastIndexOf('\\');
				return _sKeyId.Substring(num + 1);
			}
		}

		protected RegistryDataKey(string fullPath, IntPtr regHandle)
		{
			ISpRegDataKey spRegDataKey = (ISpRegDataKey)new SpDataKey();
			spRegDataKey.SetKey(regHandle, fReadOnly: false);
			_sapiRegKey = spRegDataKey;
			_sKeyId = fullPath;
			_disposeSapiKey = true;
		}

		protected RegistryDataKey(string fullPath, RegistryKey managedRegKey)
			: this(fullPath, HKEYfromRegKey(managedRegKey))
		{
		}

		protected RegistryDataKey(string fullPath, RegistryDataKey copyKey)
		{
			_sKeyId = fullPath;
			_sapiRegKey = copyKey._sapiRegKey;
			_disposeSapiKey = copyKey._disposeSapiKey;
		}

		protected RegistryDataKey(string fullPath, ISpDataKey copyKey, bool shouldDispose)
		{
			_sKeyId = fullPath;
			_sapiRegKey = copyKey;
			_disposeSapiKey = shouldDispose;
		}

		protected RegistryDataKey(ISpObjectToken sapiToken)
			: this(GetTokenIdFromToken(sapiToken), sapiToken, shouldDispose: false)
		{
		}

		internal static RegistryDataKey Open(string registryPath, bool fCreateIfNotExist)
		{
			if (string.IsNullOrEmpty(registryPath))
			{
				return null;
			}
			registryPath = registryPath.Trim(new char[1] { '\\' });
			string firstKeyAndParseRemainder = GetFirstKeyAndParseRemainder(ref registryPath);
			IntPtr intPtr = RootHKEYFromRegPath(firstKeyAndParseRemainder);
			if (IntPtr.Zero == intPtr)
			{
				return null;
			}
			RegistryDataKey registryDataKey = new RegistryDataKey(firstKeyAndParseRemainder, intPtr);
			if (string.IsNullOrEmpty(registryPath))
			{
				return registryDataKey;
			}
			return OpenSubKey(registryDataKey, registryPath, fCreateIfNotExist);
		}

		internal static RegistryDataKey Create(string keyId, RegistryKey hkey)
		{
			return new RegistryDataKey(keyId, hkey);
		}

		private static RegistryDataKey OpenSubKey(RegistryDataKey baseKey, string registryPath, bool createIfNotExist)
		{
			if (string.IsNullOrEmpty(registryPath) || baseKey == null)
			{
				return null;
			}
			string firstKeyAndParseRemainder = GetFirstKeyAndParseRemainder(ref registryPath);
			RegistryDataKey registryDataKey = (createIfNotExist ? baseKey.CreateKey(firstKeyAndParseRemainder) : baseKey.OpenKey(firstKeyAndParseRemainder));
			if (string.IsNullOrEmpty(registryPath))
			{
				return registryDataKey;
			}
			return OpenSubKey(registryDataKey, registryPath, createIfNotExist);
		}

		private static string GetTokenIdFromToken(ISpObjectToken sapiToken)
		{
			IntPtr ppszCoMemTokenId = IntPtr.Zero;
			try
			{
				sapiToken.GetId(out ppszCoMemTokenId);
				return Marshal.PtrToStringUni(ppszCoMemTokenId);
			}
			finally
			{
				Marshal.FreeCoTaskMem(ppszCoMemTokenId);
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		[PreserveSig]
		public int SetData([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.SysUInt)] uint cbData, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data)
		{
			return _sapiRegKey.SetData(valueName, cbData, data);
		}

		[PreserveSig]
		public int GetData([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.SysUInt)] ref uint pcbData, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data)
		{
			return _sapiRegKey.GetData(valueName, ref pcbData, data);
		}

		[PreserveSig]
		public int SetStringValue([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.LPWStr)] string value)
		{
			return _sapiRegKey.SetStringValue(valueName, value);
		}

		[PreserveSig]
		public int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.LPWStr)] out string value)
		{
			return _sapiRegKey.GetStringValue(valueName, out value);
		}

		[PreserveSig]
		public int SetDWORD([MarshalAs(UnmanagedType.LPWStr)] string valueName, [MarshalAs(UnmanagedType.SysUInt)] uint value)
		{
			return _sapiRegKey.SetDWORD(valueName, value);
		}

		[PreserveSig]
		public int GetDWORD([MarshalAs(UnmanagedType.LPWStr)] string valueName, ref uint pdwValue)
		{
			return _sapiRegKey.GetDWORD(valueName, ref pdwValue);
		}

		[PreserveSig]
		public int OpenKey([MarshalAs(UnmanagedType.LPWStr)] string subKeyName, out ISpDataKey ppSubKey)
		{
			return _sapiRegKey.OpenKey(subKeyName, out ppSubKey);
		}

		[PreserveSig]
		public int CreateKey([MarshalAs(UnmanagedType.LPWStr)] string subKeyName, out ISpDataKey ppSubKey)
		{
			return _sapiRegKey.CreateKey(subKeyName, out ppSubKey);
		}

		[PreserveSig]
		public int DeleteKey([MarshalAs(UnmanagedType.LPWStr)] string subKeyName)
		{
			return _sapiRegKey.DeleteKey(subKeyName);
		}

		[PreserveSig]
		public int DeleteValue([MarshalAs(UnmanagedType.LPWStr)] string valueName)
		{
			return _sapiRegKey.DeleteValue(valueName);
		}

		[PreserveSig]
		public int EnumKeys(uint index, [MarshalAs(UnmanagedType.LPWStr)] out string ppszSubKeyName)
		{
			return _sapiRegKey.EnumKeys(index, out ppszSubKeyName);
		}

		[PreserveSig]
		public int EnumValues(uint index, [MarshalAs(UnmanagedType.LPWStr)] out string valueName)
		{
			return _sapiRegKey.EnumValues(index, out valueName);
		}

		internal bool SetString(string valueName, string sValue)
		{
			return 0 == SetStringValue(valueName, sValue);
		}

		internal bool TryOpenKey(string keyName, out RegistryDataKey subKey)
		{
			if (string.IsNullOrEmpty(keyName))
			{
				subKey = null;
				return false;
			}
			subKey = OpenKey(keyName);
			return null != subKey;
		}

		internal bool TryGetString(string valueName, out string value)
		{
			if (valueName == null)
			{
				valueName = string.Empty;
			}
			return 0 == GetStringValue(valueName, out value);
		}

		internal bool HasValue(string valueName)
		{
			uint pdwValue = 0u;
			byte[] data = new byte[0];
			if (_sapiRegKey.GetStringValue(valueName, out var _) != 0 && _sapiRegKey.GetDWORD(valueName, ref pdwValue) != 0)
			{
				return 0 == _sapiRegKey.GetData(valueName, ref pdwValue, data);
			}
			return true;
		}

		internal bool TryGetDWORD(string valueName, ref uint value)
		{
			if (string.IsNullOrEmpty(valueName))
			{
				return false;
			}
			return 0 == _sapiRegKey.GetDWORD(valueName, ref value);
		}

		internal RegistryDataKey OpenKey(string keyName)
		{
			Helpers.ThrowIfEmptyOrNull(keyName, "keyName");
			if (_sapiRegKey.OpenKey(keyName, out var ppSubKey) != 0)
			{
				return null;
			}
			return new RegistryDataKey(_sKeyId + "\\" + keyName, ppSubKey, shouldDispose: true);
		}

		internal RegistryDataKey CreateKey(string keyName)
		{
			Helpers.ThrowIfEmptyOrNull(keyName, "keyName");
			if (_sapiRegKey.CreateKey(keyName, out var ppSubKey) != 0)
			{
				return null;
			}
			return new RegistryDataKey(_sKeyId + "\\" + keyName, ppSubKey, shouldDispose: true);
		}

		internal string[] GetValueNames()
		{
			List<string> list = new List<string>();
			string valueName;
			for (uint num = 0u; _sapiRegKey.EnumValues(num, out valueName) == 0; num++)
			{
				list.Add(valueName);
			}
			return list.ToArray();
		}

		IEnumerator<RegistryDataKey> IEnumerable<RegistryDataKey>.GetEnumerator()
		{
			string childKeyName = string.Empty;
			for (uint i = 0u; _sapiRegKey.EnumKeys(i, out childKeyName) == 0; i++)
			{
				yield return CreateKey(childKeyName);
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<RegistryDataKey>)this).GetEnumerator();
		}

		internal bool DeleteSubKeyTree(string childKeyName)
		{
			using (RegistryDataKey registryDataKey = OpenKey(childKeyName))
			{
				if (registryDataKey == null)
				{
					return true;
				}
				if (!registryDataKey.DeleteSubKeys())
				{
					return false;
				}
			}
			return 0 == DeleteKey(childKeyName);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing && _sapiRegKey != null && _disposeSapiKey)
			{
				Marshal.ReleaseComObject(_sapiRegKey);
				_sapiRegKey = null;
			}
		}

		private static IntPtr HKEYfromRegKey(RegistryKey regKey)
		{
			Type typeFromHandle = typeof(RegistryKey);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
			FieldInfo field = typeFromHandle.GetField("hkey", bindingAttr);
			SafeHandle safeHandle = (SafeHandle)field.GetValue(regKey);
			return safeHandle.DangerousGetHandle();
		}

		private static IntPtr RootHKEYFromRegPath(string rootPath)
		{
			RegistryKey registryKey = RegKeyFromRootPath(rootPath);
			if (registryKey == null)
			{
				return IntPtr.Zero;
			}
			return HKEYfromRegKey(registryKey);
		}

		private static string GetFirstKeyAndParseRemainder(ref string registryPath)
		{
			registryPath.Trim(new char[1] { '\\' });
			int num = registryPath.IndexOf('\\');
			string result;
			if (num >= 0)
			{
				result = registryPath.Substring(0, num);
				registryPath = registryPath.Substring(num + 1, registryPath.Length - num - 1);
			}
			else
			{
				result = registryPath;
				registryPath = string.Empty;
			}
			return result;
		}

		private static RegistryKey RegKeyFromRootPath(string rootPath)
		{
			RegistryKey[] array = new RegistryKey[4]
			{
				Registry.ClassesRoot,
				Registry.LocalMachine,
				Registry.CurrentUser,
				Registry.CurrentConfig
			};
			RegistryKey[] array2 = array;
			foreach (RegistryKey registryKey in array2)
			{
				if (registryKey.Name.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase))
				{
					return registryKey;
				}
			}
			return null;
		}

		private bool DeleteSubKeys()
		{
			string ppszSubKeyName;
			while (EnumKeys(0u, out ppszSubKeyName) == 0)
			{
				using (RegistryDataKey registryDataKey = OpenKey(ppszSubKeyName))
				{
					if (registryDataKey == null)
					{
						return false;
					}
					if (!registryDataKey.DeleteSubKeys())
					{
						return false;
					}
				}
				if (DeleteKey(ppszSubKeyName) != 0)
				{
					return false;
				}
			}
			return true;
		}
	}
}
namespace System.Speech.Internal.SapiInterop
{
	[ComImport]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	[Guid("14056589-E16C-11D2-BB90-00C04F8EE6C0")]
	internal interface ISpObjectToken : ISpDataKey
	{
		[PreserveSig]
		new int SetData([MarshalAs(UnmanagedType.LPWStr)] string pszValueName, uint cbData, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pData);

		[PreserveSig]
		new int GetData([MarshalAs(UnmanagedType.LPWStr)] string pszValueName, ref uint pcbData, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pData);

		[PreserveSig]
		new int SetStringValue([MarshalAs(UnmanagedType.LPWStr)] string pszValueName, [MarshalAs(UnmanagedType.LPWStr)] string pszValue);

		[PreserveSig]
		new int GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string pszValueName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszValue);

		[PreserveSig]
		new int SetDWORD([MarshalAs(UnmanagedType.LPWStr)] string pszValueName, uint dwValue);

		[PreserveSig]
		new int GetDWORD([MarshalAs(UnmanagedType.LPWStr)] string pszValueName, ref uint pdwValue);

		[PreserveSig]
		new int OpenKey([MarshalAs(UnmanagedType.LPWStr)] string pszSubKeyName, out ISpDataKey ppSubKey);

		[PreserveSig]
		new int CreateKey([MarshalAs(UnmanagedType.LPWStr)] string pszSubKey, out ISpDataKey ppSubKey);

		[PreserveSig]
		new int DeleteKey([MarshalAs(UnmanagedType.LPWStr)] string pszSubKey);

		[PreserveSig]
		new int DeleteValue([MarshalAs(UnmanagedType.LPWStr)] string pszValueName);

		[PreserveSig]
		new int EnumKeys(uint Index, [MarshalAs(UnmanagedType.LPWStr)] out string ppszSubKeyName);

		[PreserveSig]
		new int EnumValues(uint Index, [MarshalAs(UnmanagedType.LPWStr)] out string ppszValueName);

		void SetId([MarshalAs(UnmanagedType.LPWStr)] string pszCategoryId, [MarshalAs(UnmanagedType.LPWStr)] string pszTokenId, [MarshalAs(UnmanagedType.Bool)] bool fCreateIfNotExist);

		void GetId(out IntPtr ppszCoMemTokenId);

		void Slot15();

		void Slot16();

		void Slot17();

		void Slot18();

		void Slot19();

		void Slot20();

		void Slot21();

		void MatchesAttributes([MarshalAs(UnmanagedType.LPWStr)] string pszAttributes, [MarshalAs(UnmanagedType.Bool)] out bool pfMatches);
	}
}
namespace System.Speech.Internal.ObjectTokens
{
	internal class ObjectToken : RegistryDataKey, ISpObjectToken, ISpDataKey
	{
		[ComImport]
		[Guid("5B559F40-E952-11D2-BB91-00C04F8EE6C0")]
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface ISpObjectWithToken
		{
			[PreserveSig]
			int SetObjectToken(ISpObjectToken pToken);

			[PreserveSig]
			int GetObjectToken(IntPtr ppToken);
		}

		private const string sGenerateFileNameSpecifier = "{0}";

		private const string SPTOKENVALUE_CLSID = "CLSID";

		private ISpObjectToken _sapiObjectToken;

		private bool _disposeSapiObjectToken;

		private VoiceCategory _category;

		private RegistryDataKey _attributes;

		internal RegistryDataKey Attributes
		{
			get
			{
				if (_attributes == null)
				{
					return _attributes = OpenKey("Attributes");
				}
				return _attributes;
			}
		}

		internal ISpObjectToken SAPIToken => _sapiObjectToken;

		internal string Age
		{
			get
			{
				if (Attributes == null || !Attributes.TryGetString("Age", out var value))
				{
					return string.Empty;
				}
				return value;
			}
		}

		internal string Gender
		{
			get
			{
				if (Attributes == null || !Attributes.TryGetString("Gender", out var value))
				{
					return string.Empty;
				}
				return value;
			}
		}

		internal VoiceCategory VoiceCategory
		{
			get
			{
				return _category;
			}
			set
			{
				_category = value;
			}
		}

		internal CultureInfo Culture
		{
			get
			{
				CultureInfo result = null;
				if (Attributes.TryGetString("Language", out var value))
				{
					result = SapiAttributeParser.GetCultureInfoFromLanguageString(value);
				}
				return result;
			}
		}

		internal string Description
		{
			get
			{
				string value = string.Empty;
				string valueName = string.Format(CultureInfo.InvariantCulture, "{0:x}", new object[1] { CultureInfo.CurrentUICulture.LCID });
				if (!TryGetString(valueName, out value))
				{
					TryGetString(null, out value);
				}
				return value;
			}
		}

		protected ObjectToken(ISpObjectToken sapiObjectToken, bool disposeSapiToken)
			: base(sapiObjectToken)
		{
			if (sapiObjectToken == null)
			{
				throw new ArgumentNullException("sapiObjectToken");
			}
			_sapiObjectToken = sapiObjectToken;
			_disposeSapiObjectToken = disposeSapiToken;
		}

		internal static ObjectToken FindBestMatch(string categoryId, string requiredAttributes, string optionalAttributes)
		{
			if (string.IsNullOrEmpty(categoryId))
			{
				throw new ArgumentNullException("categoryId");
			}
			using ObjectTokenCategory objectTokenCategory = ObjectTokenCategory.Create(categoryId);
			if (objectTokenCategory != null)
			{
				StringBuilder stringBuilder = new StringBuilder(optionalAttributes);
				if (!string.IsNullOrEmpty(optionalAttributes))
				{
					stringBuilder.Append(";");
				}
				stringBuilder.Append("VendorPreferred");
				IList<ObjectToken> list = objectTokenCategory.FindMatchingTokens(requiredAttributes, stringBuilder.ToString());
				return (list.Count > 0) ? list[0] : null;
			}
			return null;
		}

		internal static ObjectToken Open(ISpObjectToken sapiObjectToken)
		{
			return new ObjectToken(sapiObjectToken, disposeSapiToken: false);
		}

		internal static ObjectToken Open(string sCategoryId, string sTokenId, bool fCreateIfNotExist)
		{
			ISpObjectToken spObjectToken = (ISpObjectToken)new System.Speech.Internal.SapiInterop.SpObjectToken();
			try
			{
				spObjectToken.SetId(sCategoryId, sTokenId, fCreateIfNotExist);
			}
			catch (Exception)
			{
				Marshal.ReleaseComObject(spObjectToken);
				return null;
			}
			return new ObjectToken(spObjectToken, disposeSapiToken: true);
		}

		internal static ObjectToken Create(string sCategoryId, string sTokenId)
		{
			return Open(sCategoryId, sTokenId, fCreateIfNotExist: true);
		}

		protected override void Dispose(bool disposing)
		{
			try
			{
				if (disposing)
				{
					if (_disposeSapiObjectToken && _sapiObjectToken != null)
					{
						Marshal.ReleaseComObject(_sapiObjectToken);
						_sapiObjectToken = null;
					}
					if (_attributes != null)
					{
						_attributes.Dispose();
						_attributes = null;
					}
				}
			}
			finally
			{
				base.Dispose(disposing);
			}
		}

		public override bool Equals(object obj)
		{
			if (obj is ObjectToken objectToken)
			{
				return string.Compare(base.Id, obje