Decompiled source of Babbler v0.9.5

Babbler.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Speech.AudioFormat;
using System.Speech.Synthesis;
using System.Text;
using Babbler.Implementation.Characteristics;
using Babbler.Implementation.Common;
using Babbler.Implementation.Config;
using Babbler.Implementation.Hosts;
using Babbler.Implementation.Phonetic;
using Babbler.Implementation.Speakers;
using Babbler.Implementation.Synthesis;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FMOD;
using FMODUnity;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.IO;
using Microsoft.CodeAnalysis;
using SOD.Common.BepInEx;
using UnityEngine;
using UniverseLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Arsonide")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("Arsonide")]
[assembly: AssemblyDescription("Plugin that makes citizens audibly speak in Shadows of Doubt.")]
[assembly: AssemblyFileVersion("0.9.5")]
[assembly: AssemblyInformationalVersion("0.9.5")]
[assembly: AssemblyProduct("Babbler")]
[assembly: AssemblyTitle("Babbler")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Arsonide/Babbler")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.9.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Babbler
{
	[BepInPlugin("AAAA_Babbler", "Babbler", "0.9.5")]
	public class BabblerPlugin : PluginController<BabblerPlugin>
	{
		private bool _hasInitializedImmediate;

		private bool _hasInitializedDeferred;

		public override void Load()
		{
			((PluginController<BabblerPlugin, IEmptyBindings>)(object)this).Load();
			_hasInitializedImmediate = false;
			_hasInitializedDeferred = false;
			BabblerConfig.Initialize(base.Config);
			if (!BabblerConfig.Enabled.Value)
			{
				Utilities.Log("Plugin Babbler is disabled.", (LogLevel)16);
				return;
			}
			Utilities.Log("Plugin Babbler is loaded!", (LogLevel)16);
			((PluginController<BabblerPlugin, IEmptyBindings>)(object)this).Harmony.PatchAll();
			Utilities.Log("Plugin Babbler is patched!", (LogLevel)16);
			ClassInjector.RegisterTypeInIl2Cpp<SpeakerHost>();
			Utilities.Log("Plugin Babbler has added custom types!", (LogLevel)16);
			InitializeImmediate();
		}

		public override bool Unload()
		{
			UninitializeImmediate();
			UninitializeDeferred();
			return ((PluginController<BabblerPlugin, IEmptyBindings>)(object)this).Unload();
		}

		private void InitializeImmediate()
		{
			if (!_hasInitializedImmediate)
			{
				_hasInitializedImmediate = true;
				Utilities.Log("Plugin is running immediate initialization.", (LogLevel)32);
				if (BabblerConfig.Mode.Value == SpeechMode.Synthesis)
				{
					SynthesisVoiceRegistry.Initialize();
				}
			}
		}

		public void InitializeDeferred()
		{
			if (!_hasInitializedDeferred)
			{
				_hasInitializedDeferred = true;
				Utilities.Log("Plugin is running deferred initialization.", (LogLevel)32);
				FMODRegistry.Initialize();
				SpeechMode value = BabblerConfig.Mode.Value;
				SpeechMode speechMode = value;
				if (speechMode == SpeechMode.Phonetic || speechMode == SpeechMode.Droning)
				{
					PhoneticVoiceRegistry.Initialize();
				}
			}
		}

		private void UninitializeImmediate()
		{
			if (_hasInitializedImmediate)
			{
				Utilities.Log("Plugin is running immediate uninitialization.", (LogLevel)32);
				SpeakerHostPool.CleanupSpeakerHosts();
			}
		}

		private void UninitializeDeferred()
		{
			if (_hasInitializedDeferred)
			{
				Utilities.Log("Plugin is running deferred uninitialization.", (LogLevel)32);
				SpeechMode value = BabblerConfig.Mode.Value;
				SpeechMode speechMode = value;
				if (speechMode == SpeechMode.Phonetic || speechMode == SpeechMode.Droning)
				{
					PhoneticVoiceRegistry.Uninitialize();
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Babbler";

		public const string PLUGIN_NAME = "Babbler";

		public const string PLUGIN_VERSION = "0.9.5";
	}
}
namespace Babbler.Implementation.Synthesis
{
	public static class SynthesisExtensions
	{
		public static List<InstalledVoice> GetOneCoreVoices(this SpeechSynthesizer synthesizer)
		{
			List<InstalledVoice> list = new List<InstalledVoice>();
			Type typeFromHandle = typeof(SpeechSynthesizer);
			object obj = typeFromHandle.GetProperty("VoiceSynthesizer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(synthesizer);
			if (obj == null)
			{
				return list;
			}
			Assembly assembly = typeFromHandle.Assembly;
			Type type = assembly.GetType("System.Speech.Internal.ObjectTokens.ObjectTokenCategory");
			if (type == null)
			{
				return list;
			}
			Type typeFromHandle2 = typeof(VoiceInfo);
			Type typeFromHandle3 = typeof(InstalledVoice);
			string fullName = typeFromHandle2.FullName;
			string fullName2 = typeFromHandle3.FullName;
			if (string.IsNullOrEmpty(fullName) || string.IsNullOrEmpty(fullName2))
			{
				return list;
			}
			if (!(type.GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, new object[1] { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech_OneCore\\Voices" }) is IDisposable disposable))
			{
				return list;
			}
			using (disposable)
			{
				if (!(type.GetMethod("FindMatchingTokens", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(disposable, new object[2]) is IList list2))
				{
					return list;
				}
				foreach (object item in list2)
				{
					if (item == null || item.GetType().GetProperty("Attributes", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(item) == null)
					{
						continue;
					}
					object obj2 = assembly.CreateInstance(fullName, ignoreCase: true, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[1] { item }, null, null);
					if (obj2 != null)
					{
						object obj3 = assembly.CreateInstance(fullName2, ignoreCase: true, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[2] { obj, obj2 }, null, null);
						InstalledVoice val = (InstalledVoice)((obj3 is InstalledVoice) ? obj3 : null);
						if (val != null)
						{
							list.Add(val);
						}
					}
				}
			}
			return list;
		}

		public static void AddVoices(this SpeechSynthesizer synthesizer, List<InstalledVoice> voices)
		{
			Type type = ((object)synthesizer).GetType();
			object obj = type.GetProperty("VoiceSynthesizer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(synthesizer);
			if (obj == null)
			{
				return;
			}
			Type type2 = obj.GetType();
			if (!(type2.GetField("_installedVoices", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj) is IList list))
			{
				return;
			}
			foreach (InstalledVoice voice in voices)
			{
				list.Add(voice);
			}
		}
	}
	public enum SynthesisVoiceFilterType
	{
		Everything,
		Blacklist,
		Whitelist
	}
	public static class SynthesisVoiceRegistry
	{
		public static List<InstalledVoice> OneCoreVoices = null;

		private const int PRIME_VOICE = 37;

		private static List<string> MaleVoices = new List<string>();

		private static List<string> FemaleVoices = new List<string>();

		private static List<string> NonBinaryVoices = new List<string>();

		private static List<string> AllVoices = new List<string>();

		private static List<string> VoiceFilterInput = new List<string>();

		private static bool HasMaleVoices;

		private static bool HasFemaleVoices;

		private static bool HasNonBinaryVoices;

		private static bool HasAnyVoices;

		public static void Initialize()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected I4, but got Unknown
			MaleVoices.Clear();
			FemaleVoices.Clear();
			NonBinaryVoices.Clear();
			AllVoices.Clear();
			SetupVoiceFilterInput();
			SpeechSynthesizer val = new SpeechSynthesizer();
			try
			{
				OneCoreVoices = val.GetOneCoreVoices();
				if (OneCoreVoices != null)
				{
					val.AddVoices(OneCoreVoices);
				}
			}
			catch (Exception ex)
			{
				Utilities.Log("Exception encountered while SynthesisVoiceRegistry tried to get OneCore voices: " + ex.Message, (LogLevel)32);
			}
			foreach (InstalledVoice installedVoice in val.GetInstalledVoices())
			{
				if (PassesVoiceFilterInput(installedVoice))
				{
					VoiceInfo voiceInfo = installedVoice.VoiceInfo;
					string name = voiceInfo.Name;
					VoiceGender gender = voiceInfo.Gender;
					AllVoices.Add(name);
					VoiceGender val2 = gender;
					VoiceGender val3 = val2;
					switch ((int)val3)
					{
					case 1:
						MaleVoices.Add(name);
						break;
					case 2:
						FemaleVoices.Add(name);
						break;
					default:
						NonBinaryVoices.Add(name);
						break;
					}
				}
			}
			HasMaleVoices = MaleVoices.Count > 0;
			HasFemaleVoices = FemaleVoices.Count > 0;
			HasNonBinaryVoices = NonBinaryVoices.Count > 0;
			HasAnyVoices = AllVoices.Count > 0;
			val.SpeakCompleted -= OnSpeakCompleted;
			val.SpeakCompleted += OnSpeakCompleted;
			val.SetOutputToNull();
			val.SpeakAsync("Initialize");
			Utilities.Log($"SynthesisVoiceRegistry has initialized! Male Voices: {MaleVoices.Count}, Female Voices: {FemaleVoices.Count}, Non-Binary Voices: {NonBinaryVoices.Count}", (LogLevel)32);
			if (AllVoices.Count <= 0 && BabblerConfig.Mode.Value == SpeechMode.Synthesis)
			{
				BabblerConfig.Mode.Value = SpeechMode.Phonetic;
				Utilities.Log("The plugin is configured for Synthesis but no voices are installed, reverting to Phonetic mode!", (LogLevel)2);
			}
		}

		private static void OnSpeakCompleted(object sender, SpeakCompletedEventArgs e)
		{
			SpeechSynthesizer val = (SpeechSynthesizer)((sender is SpeechSynthesizer) ? sender : null);
			if (val != null)
			{
				val.SpeakCompleted -= OnSpeakCompleted;
				val.Dispose();
			}
		}

		public static string GetVoice(Human human, out VoiceCharacteristics characteristics)
		{
			characteristics = VoiceCharacteristics.Create(human, HasMaleVoices, HasFemaleVoices, HasNonBinaryVoices);
			List<string> list = characteristics.Category switch
			{
				VoiceCategory.Male => MaleVoices, 
				VoiceCategory.Female => FemaleVoices, 
				VoiceCategory.NonBinary => NonBinaryVoices, 
				_ => AllVoices, 
			};
			return list[Utilities.GetDeterministicInteger(characteristics.Hash, 37, 0, list.Count)];
		}

		private static void SetupVoiceFilterInput()
		{
			VoiceFilterInput.Clear();
			string text = BabblerConfig.SynthesisVoiceFilterInput.Value.ToLowerInvariant();
			VoiceFilterInput.AddRange(text.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries));
		}

		private static bool PassesVoiceFilterInput(InstalledVoice voice)
		{
			switch (BabblerConfig.SynthesisVoiceFilter.Value)
			{
			case SynthesisVoiceFilterType.Blacklist:
				foreach (string item in VoiceFilterInput)
				{
					if (voice.VoiceInfo.Name.ToLowerInvariant().Contains(item))
					{
						return false;
					}
				}
				return true;
			case SynthesisVoiceFilterType.Whitelist:
				foreach (string item2 in VoiceFilterInput)
				{
					if (voice.VoiceInfo.Name.ToLowerInvariant().Contains(item2))
					{
						return true;
					}
				}
				return false;
			default:
				return true;
			}
		}
	}
}
namespace Babbler.Implementation.Speakers
{
	public abstract class BaseSpeaker
	{
		public Action OnFinishedSpeaking;

		protected readonly List<Channel> ActiveChannels = new List<Channel>();

		protected SpeechContext SpeechContext { get; private set; }

		protected Human SpeechPerson { get; private set; }

		protected Transform SpeechSource { get; private set; }

		protected float SpeechPitch { get; private set; }

		public virtual void InitializeSpeaker()
		{
		}

		public virtual void UninitializeSpeaker()
		{
		}

		public virtual void StopSpeaker()
		{
			ActiveChannels.Clear();
		}

		public virtual void StartSpeaker(string speechInput, SpeechContext speechContext, Human speechPerson)
		{
			StopSpeaker();
			SpeechContext = speechContext;
			SpeechPerson = speechPerson;
			SpeechSource = CacheSpeechSource(speechContext, speechPerson);
			SpeechPitch = CacheSpeechPitch(speechPerson);
		}

		public virtual void UpdateSpeaker()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = Vector3.zero;
			if ((Object)(object)SpeechSource != (Object)null)
			{
				position = SpeechSource.position;
			}
			else
			{
				Utilities.Log("Babbler speaker had a null SpeechSource, which should not happen!", (LogLevel)32);
			}
			bool flag = false;
			bool flag2 = default(bool);
			for (int num = ActiveChannels.Count - 1; num >= 0; num--)
			{
				Channel channel = ActiveChannels[num];
				if ((int)((Channel)(ref channel)).isPlaying(ref flag2) == 0 && flag2)
				{
					SetChannelPosition(position, channel);
					flag = true;
				}
				else
				{
					ActiveChannels.RemoveAt(num);
					if (ActiveChannels.Count <= 0)
					{
						OnLastChannelFinished();
					}
				}
			}
			if (flag)
			{
				FMODRegistry.TryUpdate();
			}
		}

		protected virtual float CacheSpeechPitch(Human speechPerson)
		{
			return 1f;
		}

		private Transform CacheSpeechSource(SpeechContext speechContext, Human speechPerson)
		{
			Transform val2;
			if (speechContext == SpeechContext.PhoneSpeech || speechContext == SpeechContext.PhoneShout)
			{
				Interactable interactingWith = ((Actor)Player.Instance).interactingWith;
				object obj;
				if (interactingWith == null)
				{
					obj = null;
				}
				else
				{
					InteractableController controller = interactingWith.controller;
					obj = ((controller != null) ? controller.phoneReciever : null);
				}
				if (obj == null)
				{
					Interactable phoneInteractable = Player.Instance.phoneInteractable;
					if (phoneInteractable == null)
					{
						obj = null;
					}
					else
					{
						InteractableController controller2 = phoneInteractable.controller;
						obj = ((controller2 != null) ? controller2.phoneReciever : null);
					}
					if (obj == null)
					{
						Telephone answeringPhone = Player.Instance.answeringPhone;
						if (answeringPhone == null)
						{
							obj = null;
						}
						else
						{
							Interactable interactable = answeringPhone.interactable;
							if (interactable == null)
							{
								obj = null;
							}
							else
							{
								InteractableController controller3 = interactable.controller;
								obj = ((controller3 != null) ? controller3.phoneReciever : null);
							}
						}
					}
				}
				GameObject val = (GameObject)obj;
				val2 = ((val != null) ? val.transform : null);
			}
			else
			{
				val2 = ((speechPerson != null) ? ((Actor)speechPerson).lookAtThisTransform : null);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Player instance = Player.Instance;
				val2 = ((instance != null) ? ((Component)instance).transform : null);
			}
			return val2;
		}

		protected void SetChannelPosition(Vector3 position, Channel channel)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			VECTOR val = default(VECTOR);
			val.x = position.x;
			val.y = position.y;
			val.z = position.z;
			VECTOR val2 = val;
			val = default(VECTOR);
			val.x = 0f;
			val.y = 0f;
			val.z = 0f;
			VECTOR val3 = val;
			((Channel)(ref channel)).set3DAttributes(ref val2, ref val3);
		}

		protected virtual void OnLastChannelFinished()
		{
		}
	}
	public class DroningSpeaker : PhoneticSpeaker
	{
		private const int PRIME_PHONEME = 97;

		protected override void ProcessSpeechInput(Human speechPerson, ref string speechInput)
		{
			base.ProcessSpeechInput(speechPerson, ref speechInput);
			char c = PickPhoneme(speechPerson);
			Utilities.GlobalStringBuilder.Clear();
			string text = speechInput;
			foreach (char c2 in text)
			{
				Utilities.GlobalStringBuilder.Append((c2 != ' ') ? c : c2);
			}
			speechInput = Utilities.GlobalStringBuilder.ToString();
		}

		private char PickPhoneme(Human human)
		{
			return BabblerConfig.DroningValidPhonemes.Value[Utilities.GetDeterministicInteger(CurrentHash, 97, 0, BabblerConfig.DroningValidPhonemes.Value.Length)];
		}

		protected override void CacheSpeechVarianceFactors()
		{
			if (Utilities.GetDeterministicFloat(CurrentHash, 401, 0f, 1f) <= BabblerConfig.DroningChanceDelayVariance.Value)
			{
				CurrentDelayVarianceFactor = Utilities.GetDeterministicFloat(CurrentHash, 419, 0f, 1f);
			}
			else
			{
				CurrentDelayVarianceFactor = -1f;
			}
			if (Utilities.GetDeterministicFloat(CurrentHash, 409, 0f, 1f) <= BabblerConfig.DroningChancePitchVariance.Value)
			{
				CurrentPitchVarianceFactor = Utilities.GetDeterministicFloat(CurrentHash, 421, 0f, 1f);
			}
			else
			{
				CurrentPitchVarianceFactor = -1f;
			}
		}

		protected override float GetPhonemeDelay()
		{
			float value = BabblerConfig.DroningSpeechDelay.Value;
			if (CurrentDelayVarianceFactor < 0f)
			{
				return value;
			}
			float num = BabblerConfig.DroningSpeechDelay.Value + Utilities.GetRandomFloat(BabblerConfig.DroningMinDelayVariance.Value, BabblerConfig.DroningMaxDelayVariance.Value);
			return Mathf.Lerp(value, num, CurrentDelayVarianceFactor);
		}

		protected override float GetPhonemePitch()
		{
			float speechPitch = base.SpeechPitch;
			if (CurrentPitchVarianceFactor < 0f)
			{
				return speechPitch;
			}
			float num = speechPitch * Utilities.GetRandomFloat(BabblerConfig.DroningMinPitchVariance.Value, BabblerConfig.DroningMaxPitchVariance.Value);
			return Mathf.Lerp(speechPitch, num, CurrentPitchVarianceFactor);
		}
	}
	public class PhoneticSpeaker : BaseSpeaker
	{
		protected const int PRIME_DELAY_CHANCE = 401;

		protected const int PRIME_PITCH_CHANCE = 409;

		protected const int PRIME_DELAY_FACTOR = 419;

		protected const int PRIME_PITCH_FACTOR = 421;

		private readonly List<PhoneticSound> _phoneticsToSpeak = new List<PhoneticSound>();

		private Coroutine _phoneticCoroutine;

		private PhoneticVoice _currentVoice;

		protected int CurrentHash;

		protected float CurrentDelayVarianceFactor;

		protected float CurrentPitchVarianceFactor;

		public override void StopSpeaker()
		{
			base.StopSpeaker();
			if (_phoneticCoroutine != null)
			{
				RuntimeHelper.StopCoroutine(_phoneticCoroutine);
				_phoneticCoroutine = null;
			}
		}

		public override void StartSpeaker(string speechInput, SpeechContext speechContext, Human speechPerson)
		{
			base.StartSpeaker(speechInput, speechContext, speechPerson);
			CurrentHash = Utilities.GetDeterministicStringHash(speechPerson.seed);
			CacheSpeechVarianceFactors();
			ProcessSpeechInput(speechPerson, ref speechInput);
			PopulatePhoneticSounds(speechInput);
			_phoneticCoroutine = RuntimeHelper.StartCoroutine(PhoneticRoutine());
		}

		private IEnumerator PhoneticRoutine()
		{
			foreach (PhoneticSound phoneme in _phoneticsToSpeak)
			{
				if (FMODRegistry.TryPlaySound(phoneme.Sound, FMODRegistry.GetChannelGroup(base.SpeechContext), out var channel))
				{
					((Channel)(ref channel)).setPitch(GetPhonemePitch());
					SetChannelPosition(base.SpeechSource.position, channel);
					FMODRegistry.TryUpdate();
					ActiveChannels.Add(channel);
					float delay = GetPhonemeDelay();
					float syllableExpiration = Time.realtimeSinceStartup + phoneme.Length + delay;
					while (Time.realtimeSinceStartup < syllableExpiration)
					{
						yield return null;
					}
					channel = default(Channel);
				}
			}
			OnFinishedSpeaking?.Invoke();
		}

		protected virtual void ProcessSpeechInput(Human speechPerson, ref string speechInput)
		{
		}

		private void PopulatePhoneticSounds(string speechInput)
		{
			_phoneticsToSpeak.Clear();
			ReadOnlySpan<char> readOnlySpan = speechInput.ToLowerInvariant().AsSpan();
			for (int i = 0; i < readOnlySpan.Length; i++)
			{
				ReadOnlySpan<char> readOnlySpan2 = readOnlySpan.Slice(i, Math.Min(2, readOnlySpan.Length - i));
				string text = readOnlySpan2.ToString();
				if (readOnlySpan2.Length > 1 && _currentVoice.TryGetPhoneticSound(text, out var result))
				{
					_phoneticsToSpeak.Add(result);
					i++;
				}
				else if (_currentVoice.TryGetPhoneticSound(text[0].ToString(), out result))
				{
					_phoneticsToSpeak.Add(result);
				}
			}
		}

		protected override float CacheSpeechPitch(Human speechPerson)
		{
			_currentVoice = PhoneticVoiceRegistry.GetVoice(speechPerson, out var characteristics);
			float value;
			float value2;
			switch (characteristics.Category)
			{
			case VoiceCategory.Male:
				value = BabblerConfig.PhoneticMinFrequencyMale.Value;
				value2 = BabblerConfig.PhoneticMaxFrequencyMale.Value;
				break;
			case VoiceCategory.Female:
				value = BabblerConfig.PhoneticMinFrequencyFemale.Value;
				value2 = BabblerConfig.PhoneticMaxFrequencyFemale.Value;
				break;
			default:
				value = BabblerConfig.PhoneticMinFrequencyNonBinary.Value;
				value2 = BabblerConfig.PhoneticMaxFrequencyNonBinary.Value;
				break;
			}
			float num = value + characteristics.Pitch * (value2 - value);
			return num / _currentVoice.Frequency;
		}

		protected virtual void CacheSpeechVarianceFactors()
		{
			if (Utilities.GetDeterministicFloat(CurrentHash, 401, 0f, 1f) <= BabblerConfig.PhoneticChanceDelayVariance.Value)
			{
				CurrentDelayVarianceFactor = Utilities.GetDeterministicFloat(CurrentHash, 419, 0f, 1f);
			}
			else
			{
				CurrentDelayVarianceFactor = -1f;
			}
			if (Utilities.GetDeterministicFloat(CurrentHash, 409, 0f, 1f) <= BabblerConfig.PhoneticChancePitchVariance.Value)
			{
				CurrentPitchVarianceFactor = Utilities.GetDeterministicFloat(CurrentHash, 421, 0f, 1f);
			}
			else
			{
				CurrentPitchVarianceFactor = -1f;
			}
		}

		protected virtual float GetPhonemeDelay()
		{
			float value = BabblerConfig.PhoneticSpeechDelay.Value;
			if (CurrentDelayVarianceFactor < 0f)
			{
				return value;
			}
			float num = BabblerConfig.PhoneticSpeechDelay.Value + Utilities.GetRandomFloat(BabblerConfig.PhoneticMinDelayVariance.Value, BabblerConfig.PhoneticMaxDelayVariance.Value);
			return Mathf.Lerp(value, num, CurrentDelayVarianceFactor);
		}

		protected virtual float GetPhonemePitch()
		{
			float speechPitch = base.SpeechPitch;
			if (CurrentPitchVarianceFactor < 0f)
			{
				return speechPitch;
			}
			float num = speechPitch * Utilities.GetRandomFloat(BabblerConfig.PhoneticMinPitchVariance.Value, BabblerConfig.PhoneticMaxPitchVariance.Value);
			return Mathf.Lerp(speechPitch, num, CurrentPitchVarianceFactor);
		}
	}
	public class SynthesisSpeaker : BaseSpeaker
	{
		private SpeechSynthesizer _synthesizer;

		private MemoryStream _memoryStream;

		public override void InitializeSpeaker()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			base.InitializeSpeaker();
			_synthesizer = new SpeechSynthesizer();
			try
			{
				if (SynthesisVoiceRegistry.OneCoreVoices != null)
				{
					_synthesizer.AddVoices(SynthesisVoiceRegistry.OneCoreVoices);
				}
			}
			catch (Exception ex)
			{
				Utilities.Log("Exception encountered while SynthesisSpeaker tried to add OneCore voices: " + ex.Message, (LogLevel)32);
			}
			_memoryStream = new MemoryStream();
			_synthesizer.SetOutputToAudioStream((Stream)_memoryStream, new SpeechAudioFormatInfo(44100, (AudioBitsPerSample)16, (AudioChannel)1));
		}

		public override void UninitializeSpeaker()
		{
			base.UninitializeSpeaker();
			_synthesizer.Dispose();
			_memoryStream.Dispose();
		}

		public override void StopSpeaker()
		{
			base.StopSpeaker();
			_synthesizer.SpeakCompleted -= OnSpeakCompleted;
			_synthesizer.SpeakAsyncCancelAll();
		}

		public override void StartSpeaker(string speechInput, SpeechContext speechContext, Human speechPerson)
		{
			base.StartSpeaker(speechInput, speechContext, speechPerson);
			_synthesizer.SpeakCompleted -= OnSpeakCompleted;
			_synthesizer.SpeakCompleted += OnSpeakCompleted;
			_synthesizer.SpeakAsync(speechInput);
		}

		private void OnSpeakCompleted(object sender, SpeakCompletedEventArgs args)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			SpeechSynthesizer val = (SpeechSynthesizer)((sender is SpeechSynthesizer) ? sender : null);
			if (val != null)
			{
				val.SpeakCompleted -= OnSpeakCompleted;
				_memoryStream.Position = 0L;
				CREATESOUNDEXINFO val2 = default(CREATESOUNDEXINFO);
				val2.cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO));
				val2.length = (uint)_memoryStream.Length;
				val2.format = (SOUND_FORMAT)2;
				val2.defaultfrequency = 44100;
				val2.numchannels = 1;
				CREATESOUNDEXINFO extraInfo = val2;
				if (FMODRegistry.TryCreateSound(_memoryStream.ToArray(), (MODE)6160, ref extraInfo, out var sound) && FMODRegistry.TryPlaySound(sound, FMODRegistry.GetChannelGroup(base.SpeechContext), out var channel))
				{
					((Channel)(ref channel)).setPitch(base.SpeechPitch);
					SetChannelPosition(base.SpeechSource.position, channel);
					FMODRegistry.TryUpdate();
					ActiveChannels.Add(channel);
				}
			}
		}

		protected override float CacheSpeechPitch(Human speechPerson)
		{
			VoiceCharacteristics characteristics;
			string voice = SynthesisVoiceRegistry.GetVoice(speechPerson, out characteristics);
			_synthesizer.SelectVoice(voice);
			_synthesizer.Rate = Mathf.RoundToInt(Mathf.Lerp((float)BabblerConfig.SynthesisMinSpeed.Value, (float)BabblerConfig.SynthesisMaxSpeed.Value, characteristics.Rate));
			return characteristics.Category switch
			{
				VoiceCategory.Male => Mathf.Lerp(BabblerConfig.SynthesisMinPitchMale.Value, BabblerConfig.SynthesisMaxPitchMale.Value, characteristics.Pitch), 
				VoiceCategory.Female => Mathf.Lerp(BabblerConfig.SynthesisMinPitchFemale.Value, BabblerConfig.SynthesisMaxPitchFemale.Value, characteristics.Pitch), 
				_ => Mathf.Lerp(BabblerConfig.SynthesisMinPitchNonBinary.Value, BabblerConfig.SynthesisMaxPitchNonBinary.Value, characteristics.Pitch), 
			};
		}

		protected override void OnLastChannelFinished()
		{
			base.OnLastChannelFinished();
			_memoryStream.Seek(0L, SeekOrigin.Begin);
			_memoryStream.SetLength(0L);
			OnFinishedSpeaking?.Invoke();
		}
	}
}
namespace Babbler.Implementation.Phonetic
{
	public class PhoneticSound
	{
		public string Phonetic;

		public string FilePath;

		public Sound Sound;

		public float Length;

		public bool Released;
	}
	public class PhoneticVoice
	{
		private readonly Dictionary<string, PhoneticSound> _phonemes = new Dictionary<string, PhoneticSound>();

		public string Name { get; private set; }

		public float Frequency { get; private set; }

		public void Initialize(string directory)
		{
			_phonemes.Clear();
			if (!Directory.Exists(directory))
			{
				return;
			}
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(directory);
			string[] array = fileNameWithoutExtension.Split('_', StringSplitOptions.RemoveEmptyEntries);
			if (array.Length != 2 || !float.TryParse(array[1], out var result))
			{
				return;
			}
			Frequency = result;
			Name = array[0];
			string[] files = Directory.GetFiles(directory, "*.wav");
			foreach (string text in files)
			{
				string fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(text);
				string[] array2 = fileNameWithoutExtension2.Split('_');
				if (array2.Length != 2)
				{
					continue;
				}
				string text2 = array2[1].ToLowerInvariant();
				PhoneticSound value = CreatePhoneticSound(text, text2);
				if (fileNameWithoutExtension2.StartsWith("symbol"))
				{
					if (text2.Contains("space"))
					{
						_phonemes[" "] = value;
						_phonemes[","] = value;
					}
					else if (text2.Contains("exclamation"))
					{
						_phonemes["!"] = value;
					}
					else if (text2.Contains("question"))
					{
						_phonemes["?"] = value;
					}
					else if (text2.Contains("period"))
					{
						_phonemes["."] = value;
					}
				}
				else
				{
					_phonemes[text2] = value;
				}
			}
		}

		public void Uninitialize()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<string, PhoneticSound> phoneme in _phonemes)
			{
				if (!phoneme.Value.Released)
				{
					((Sound)(ref phoneme.Value.Sound)).release();
					phoneme.Value.Released = true;
				}
			}
		}

		private PhoneticSound CreatePhoneticSound(string filePath, string phonetic)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!FMODRegistry.TryCreateSound(filePath, (MODE)16, out var sound))
			{
				return null;
			}
			uint num = default(uint);
			((Sound)(ref sound)).getLength(ref num, (TIMEUNIT)1);
			float length = (float)num / 1000f;
			return new PhoneticSound
			{
				Phonetic = phonetic,
				FilePath = filePath,
				Sound = sound,
				Length = length,
				Released = false
			};
		}

		public bool TryGetPhoneticSound(string phonetic, out PhoneticSound result)
		{
			return _phonemes.TryGetValue(phonetic, out result);
		}
	}
	public static class PhoneticVoiceRegistry
	{
		private const int PRIME_VOICE = 211;

		private static readonly List<PhoneticVoice> Voices = new List<PhoneticVoice>();

		public static void Initialize()
		{
			Voices.Clear();
			string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException(), "Phonemes");
			string[] directories = Directory.GetDirectories(path);
			foreach (string directory in directories)
			{
				PhoneticVoice phoneticVoice = new PhoneticVoice();
				phoneticVoice.Initialize(directory);
				Voices.Add(phoneticVoice);
			}
			Utilities.Log($"SynthesisVoiceRegistry has initialized! Voices: {Voices.Count}", (LogLevel)32);
		}

		public static void Uninitialize()
		{
			foreach (PhoneticVoice voice in Voices)
			{
				voice.Uninitialize();
			}
		}

		public static PhoneticVoice GetVoice(Human human, out VoiceCharacteristics characteristics)
		{
			characteristics = VoiceCharacteristics.Create(human, maleVoiceAvailable: true, femaleVoiceAvailable: true, nonBinaryVoiceAvailable: true);
			return Voices[Utilities.GetDeterministicInteger(characteristics.Hash, 211, 0, Voices.Count)];
		}
	}
}
namespace Babbler.Implementation.Hosts
{
	public class SpeakerHost : MonoBehaviour
	{
		public BaseSpeaker Speaker;

		private void Awake()
		{
			switch (BabblerConfig.Mode.Value)
			{
			case SpeechMode.Synthesis:
				Speaker = new SynthesisSpeaker();
				break;
			case SpeechMode.Phonetic:
				Speaker = new PhoneticSpeaker();
				break;
			case SpeechMode.Droning:
				Speaker = new DroningSpeaker();
				break;
			default:
				Speaker = new PhoneticSpeaker();
				break;
			}
			BaseSpeaker speaker = Speaker;
			speaker.OnFinishedSpeaking = (Action)Delegate.Remove(speaker.OnFinishedSpeaking, new Action(OnFinishedSpeaking));
			BaseSpeaker speaker2 = Speaker;
			speaker2.OnFinishedSpeaking = (Action)Delegate.Combine(speaker2.OnFinishedSpeaking, new Action(OnFinishedSpeaking));
			Speaker.InitializeSpeaker();
		}

		private void OnDestroy()
		{
			BaseSpeaker speaker = Speaker;
			speaker.OnFinishedSpeaking = (Action)Delegate.Remove(speaker.OnFinishedSpeaking, new Action(OnFinishedSpeaking));
			Speaker.UninitializeSpeaker();
		}

		private void OnEnable()
		{
			Speaker.StopSpeaker();
		}

		private void OnDisable()
		{
			Speaker.StopSpeaker();
		}

		private void Update()
		{
			Speaker.UpdateSpeaker();
		}

		private void OnFinishedSpeaking()
		{
			SpeakerHostPool.ReleaseSpeakerHost(this);
		}
	}
	public static class SpeakerHostPool
	{
		private static List<SpeakerHost> AvailableHosts = new List<SpeakerHost>();

		private static List<SpeakerHost> AllHosts = new List<SpeakerHost>();

		public static void Play(string speechInput, SpeechContext speechContext, Human speechPerson)
		{
			SpeakerHost speakerHost = GetSpeakerHost();
			speakerHost.Speaker.StartSpeaker(speechInput, speechContext, speechPerson);
		}

		private static SpeakerHost GetSpeakerHost()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			int num = AvailableHosts.Count - 1;
			SpeakerHost speakerHost;
			if (num >= 0)
			{
				speakerHost = AvailableHosts[num];
				AvailableHosts.RemoveAt(num);
				((Component)speakerHost).gameObject.SetActive(true);
			}
			else
			{
				GameObject val = new GameObject("BabblerSpeakerHost");
				val.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
				speakerHost = val.AddComponent<SpeakerHost>();
				Object.DontDestroyOnLoad((Object)(object)val);
				AllHosts.Add(speakerHost);
				Utilities.Log($"Created speaker host, current count is {AllHosts.Count}.", (LogLevel)32);
			}
			return speakerHost;
		}

		public static void ReleaseSpeakerHost(SpeakerHost speakerHost)
		{
			((Component)speakerHost).gameObject.SetActive(false);
			AvailableHosts.Add(speakerHost);
		}

		public static void CleanupSpeakerHosts()
		{
			for (int num = AllHosts.Count - 1; num >= 0; num--)
			{
				SpeakerHost speakerHost = AllHosts[num];
				if (((Component)speakerHost).gameObject.activeSelf)
				{
					((Component)speakerHost).gameObject.SetActive(false);
				}
				Object.DestroyImmediate((Object)(object)((Component)speakerHost).gameObject);
			}
			Utilities.Log("Cleaned up all speaker hosts.", (LogLevel)32);
		}
	}
}
namespace Babbler.Implementation.Config
{
	public static class BabblerConfig
	{
		public static ConfigEntry<string> DroningValidPhonemes;

		public static ConfigEntry<float> DroningSpeechDelay;

		public static ConfigEntry<float> DroningChanceDelayVariance;

		public static ConfigEntry<float> DroningMinDelayVariance;

		public static ConfigEntry<float> DroningMaxDelayVariance;

		public static ConfigEntry<float> DroningChancePitchVariance;

		public static ConfigEntry<float> DroningMinPitchVariance;

		public static ConfigEntry<float> DroningMaxPitchVariance;

		public static ConfigEntry<float> DroningMinFrequencyMale;

		public static ConfigEntry<float> DroningMaxFrequencyMale;

		public static ConfigEntry<float> DroningMinFrequencyFemale;

		public static ConfigEntry<float> DroningMaxFrequencyFemale;

		public static ConfigEntry<float> DroningMinFrequencyNonBinary;

		public static ConfigEntry<float> DroningMaxFrequencyNonBinary;

		private const string ExpectedVersion = "74d012a7e2564fa9badbc23749a9b16c";

		public static ConfigEntry<string> Version;

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<SpeechMode> Mode;

		public static ConfigEntry<bool> DistortPhoneSpeech;

		public static ConfigEntry<float> ConversationalVolume;

		public static ConfigEntry<float> OverheardVolume;

		public static ConfigEntry<float> PhoneVolume;

		public static ConfigEntry<float> ConversationalShoutMultiplier;

		public static ConfigEntry<float> OverheardShoutMultiplier;

		public static ConfigEntry<float> PhoneShoutMultiplier;

		public static ConfigEntry<float> FemaleThreshold;

		public static ConfigEntry<float> MaleThreshold;

		public static ConfigEntry<float> GenderDiversity;

		public static ConfigEntry<float> PhoneticSpeechDelay;

		public static ConfigEntry<float> PhoneticChanceDelayVariance;

		public static ConfigEntry<float> PhoneticMinDelayVariance;

		public static ConfigEntry<float> PhoneticMaxDelayVariance;

		public static ConfigEntry<float> PhoneticChancePitchVariance;

		public static ConfigEntry<float> PhoneticMinPitchVariance;

		public static ConfigEntry<float> PhoneticMaxPitchVariance;

		public static ConfigEntry<float> PhoneticMinFrequencyMale;

		public static ConfigEntry<float> PhoneticMaxFrequencyMale;

		public static ConfigEntry<float> PhoneticMinFrequencyFemale;

		public static ConfigEntry<float> PhoneticMaxFrequencyFemale;

		public static ConfigEntry<float> PhoneticMinFrequencyNonBinary;

		public static ConfigEntry<float> PhoneticMaxFrequencyNonBinary;

		public static ConfigEntry<SynthesisVoiceFilterType> SynthesisVoiceFilter;

		public static ConfigEntry<string> SynthesisVoiceFilterInput;

		public static ConfigEntry<int> SynthesisMinSpeed;

		public static ConfigEntry<int> SynthesisMaxSpeed;

		public static ConfigEntry<float> SynthesisMinPitchMale;

		public static ConfigEntry<float> SynthesisMaxPitchMale;

		public static ConfigEntry<float> SynthesisMinPitchFemale;

		public static ConfigEntry<float> SynthesisMaxPitchFemale;

		public static ConfigEntry<float> SynthesisMinPitchNonBinary;

		public static ConfigEntry<float> SynthesisMaxPitchNonBinary;

		private static void InitializeDroning(ConfigFile config)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Expected O, but got Unknown
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			DroningValidPhonemes = config.Bind<string>("6. Droning", "Valid Phonemes", "aeiouybdglmptvw", new ConfigDescription("Citizens pick one phoneme to repeat, that is chosen from these phonemes.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningSpeechDelay = config.Bind<float>("6. Droning", "Speech Delay", -0.175f, new ConfigDescription("The delay of each phoneme is its length plus this. Negative numbers cause overlapping phonemes.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningChanceDelayVariance = config.Bind<float>("6. Droning", "Chance Delay Variance", 0.4f, new ConfigDescription("This is the chance for any citizen to speak with variations in their phoneme delay.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			DroningMinDelayVariance = config.Bind<float>("6. Droning", "Min Delay Variance", 0f, new ConfigDescription("A value between the min and max delay variance is chosen to add to the speech delay to create variations in it.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMaxDelayVariance = config.Bind<float>("6. Droning", "Max Delay Variance", 0.3f, new ConfigDescription("A value between the min and max delay variance is chosen to add to the speech delay to create variations in it.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningChancePitchVariance = config.Bind<float>("6. Droning", "Chance Pitch Variance", 0.2f, new ConfigDescription("This is the chance for any citizen to speak with variations in their phoneme pitch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			DroningMinPitchVariance = config.Bind<float>("6. Droning", "Min Pitch Variance", 0.8f, new ConfigDescription("A value between the min and max pitch variance is chosen to multiply with the phoneme pitch to create variations of it.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMaxPitchVariance = config.Bind<float>("6. Droning", "Max Pitch Variance", 1.2f, new ConfigDescription("A value between the min and max pitch variance is chosen to multiply with the phoneme pitch to create variations of it.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMinFrequencyMale = config.Bind<float>("6. Droning", "Min Frequency Male", 100f, new ConfigDescription("Lowest possible frequency (in hertz) for male voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMaxFrequencyMale = config.Bind<float>("6. Droning", "Max Frequency Male", 180f, new ConfigDescription("Highest possible frequency (in hertz) for male voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMinFrequencyFemale = config.Bind<float>("6. Droning", "Min Frequency Female", 165f, new ConfigDescription("Lowest possible frequency (in hertz) for female voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMaxFrequencyFemale = config.Bind<float>("6. Droning", "Max Frequency Female", 255f, new ConfigDescription("Highest possible frequency (in hertz) for female voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMinFrequencyNonBinary = config.Bind<float>("6. Droning", "Min Frequency Non-Binary", 100f, new ConfigDescription("Lowest possible frequency (in hertz) for non-binary voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			DroningMaxFrequencyNonBinary = config.Bind<float>("6. Droning", "Max Frequency Non-Binary", 255f, new ConfigDescription("Highest possible frequency (in hertz) for non-binary voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			Utilities.EnforceMinMax(ref DroningMinDelayVariance, ref DroningMaxDelayVariance);
			Utilities.EnforceMinMax(ref DroningMinPitchVariance, ref DroningMaxPitchVariance);
			Utilities.EnforceMinMax(ref DroningMinFrequencyMale, ref DroningMaxFrequencyMale);
			Utilities.EnforceMinMax(ref DroningMinFrequencyFemale, ref DroningMaxFrequencyFemale);
			Utilities.EnforceMinMax(ref DroningMinFrequencyNonBinary, ref DroningMaxFrequencyNonBinary);
		}

		public static void ResetDroning()
		{
			DroningValidPhonemes.Value = (string)((ConfigEntryBase)DroningValidPhonemes).DefaultValue;
			DroningSpeechDelay.Value = (float)((ConfigEntryBase)DroningSpeechDelay).DefaultValue;
			DroningChanceDelayVariance.Value = (float)((ConfigEntryBase)DroningChanceDelayVariance).DefaultValue;
			DroningMinDelayVariance.Value = (float)((ConfigEntryBase)DroningMinDelayVariance).DefaultValue;
			DroningMaxDelayVariance.Value = (float)((ConfigEntryBase)DroningMaxDelayVariance).DefaultValue;
			DroningChancePitchVariance.Value = (float)((ConfigEntryBase)DroningChancePitchVariance).DefaultValue;
			DroningMinPitchVariance.Value = (float)((ConfigEntryBase)DroningMinPitchVariance).DefaultValue;
			DroningMaxPitchVariance.Value = (float)((ConfigEntryBase)DroningMaxPitchVariance).DefaultValue;
			DroningMinFrequencyMale.Value = (float)((ConfigEntryBase)DroningMinFrequencyMale).DefaultValue;
			DroningMaxFrequencyMale.Value = (float)((ConfigEntryBase)DroningMaxFrequencyMale).DefaultValue;
			DroningMinFrequencyFemale.Value = (float)((ConfigEntryBase)DroningMinFrequencyFemale).DefaultValue;
			DroningMaxFrequencyFemale.Value = (float)((ConfigEntryBase)DroningMaxFrequencyFemale).DefaultValue;
			DroningMinFrequencyNonBinary.Value = (float)((ConfigEntryBase)DroningMinFrequencyNonBinary).DefaultValue;
			DroningMaxFrequencyNonBinary.Value = (float)((ConfigEntryBase)DroningMaxFrequencyNonBinary).DefaultValue;
		}

		public static void Initialize(ConfigFile config)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Expected O, but got Unknown
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Expected O, but got Unknown
			ProcessOldConfigFile(config);
			Enabled = config.Bind<bool>("1. General", "Enabled", true, new ConfigDescription("Another method of enabling and disabling Babbler.", (AcceptableValueBase)null, Array.Empty<object>()));
			Mode = config.Bind<SpeechMode>("1. General", "Mode", SpeechMode.Synthesis, new ConfigDescription("Determines whether citizens will talk with text to speech synthesis, phonetic sounds, or monosyllabic droning.", (AcceptableValueBase)null, Array.Empty<object>()));
			Version = config.Bind<string>("1. General", "Version", string.Empty, new ConfigDescription("Babbler uses this to reset your configuration between major versions. Don't modify it or it will reset your configuration!", (AcceptableValueBase)null, Array.Empty<object>()));
			DistortPhoneSpeech = config.Bind<bool>("1. General", "Distort Phone Speech", true, new ConfigDescription("When enabled, a band pass is applied to phones to make them sound a little tinnier, like phones.", (AcceptableValueBase)null, Array.Empty<object>()));
			FemaleThreshold = config.Bind<float>("2. Gender", "Female Threshold", 0.49f, new ConfigDescription("Increase for more female voices, decrease for less, defaults to what the stock game uses for citizens.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MaleThreshold = config.Bind<float>("2. Gender", "Male Threshold", 0.51f, new ConfigDescription("Decrease for more male voices, increase for less, defaults to what the stock game uses for citizens.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			GenderDiversity = config.Bind<float>("2. Gender", "Gender Diversity", 0.05f, new ConfigDescription("Adds a random element to voice gender selection, increase for more diverse voices.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ConversationalVolume = config.Bind<float>("3. Volume", "Conversational Volume", 0.7f, new ConfigDescription("How loud voices will be when you are speaking directly to a person.", (AcceptableValueBase)null, Array.Empty<object>()));
			OverheardVolume = config.Bind<float>("3. Volume", "Overheard Volume", 0.3f, new ConfigDescription("How loud voices that you overhear nearby will be when you are not talking directly to them.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneVolume = config.Bind<float>("3. Volume", "Phone Volume", 0.5f, new ConfigDescription("How loud voices will be when you are talking with a person over the phone.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConversationalShoutMultiplier = config.Bind<float>("3. Volume", "Conversational Shout Multiplier", 2.9f, new ConfigDescription("When speaking in all caps, how much to multiply the normal conversational volume.", (AcceptableValueBase)null, Array.Empty<object>()));
			OverheardShoutMultiplier = config.Bind<float>("3. Volume", "Overheard Shout Multiplier", 6.6f, new ConfigDescription("When speaking in all caps, how much to multiply the normal overheard volume.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneShoutMultiplier = config.Bind<float>("3. Volume", "Phone Shout Multiplier", 4f, new ConfigDescription("When speaking in all caps, how much to multiply the normal phone volume.", (AcceptableValueBase)null, Array.Empty<object>()));
			InitializeSynthesis(config);
			InitializePhonetic(config);
			InitializeDroning(config);
			ProcessUpgrades();
			Utilities.Log("BabblerConfig has initialized!", (LogLevel)32);
		}

		private static void ProcessOldConfigFile(ConfigFile newFile)
		{
			string configFilePath = newFile.ConfigFilePath;
			string text = configFilePath.Replace("AAAA_", string.Empty);
			try
			{
				if (File.Exists(text))
				{
					if (File.Exists(configFilePath))
					{
						File.Delete(configFilePath);
					}
					Utilities.Log("Babbler found old config file path, renaming config file!", (LogLevel)16);
					File.Move(text, configFilePath);
					newFile.Reload();
				}
			}
			catch (Exception ex)
			{
				Utilities.Log("Error processing old config file: " + ex.Message, (LogLevel)2);
			}
		}

		private static void ProcessUpgrades()
		{
			if (!(Version.Value == "74d012a7e2564fa9badbc23749a9b16c"))
			{
				Utilities.Log("Detected either a new installation or a major upgrade of Babbler, resetting the configuration file!", (LogLevel)16);
				Version.Value = "74d012a7e2564fa9badbc23749a9b16c";
				Reset();
			}
		}

		private static void Reset()
		{
			Enabled.Value = (bool)((ConfigEntryBase)Enabled).DefaultValue;
			Mode.Value = (SpeechMode)((ConfigEntryBase)Mode).DefaultValue;
			DistortPhoneSpeech.Value = (bool)((ConfigEntryBase)DistortPhoneSpeech).DefaultValue;
			ConversationalVolume.Value = (float)((ConfigEntryBase)ConversationalVolume).DefaultValue;
			OverheardVolume.Value = (float)((ConfigEntryBase)OverheardVolume).DefaultValue;
			PhoneVolume.Value = (float)((ConfigEntryBase)PhoneVolume).DefaultValue;
			ConversationalShoutMultiplier.Value = (float)((ConfigEntryBase)ConversationalShoutMultiplier).DefaultValue;
			OverheardShoutMultiplier.Value = (float)((ConfigEntryBase)OverheardShoutMultiplier).DefaultValue;
			PhoneShoutMultiplier.Value = (float)((ConfigEntryBase)PhoneShoutMultiplier).DefaultValue;
			FemaleThreshold.Value = (float)((ConfigEntryBase)FemaleThreshold).DefaultValue;
			MaleThreshold.Value = (float)((ConfigEntryBase)MaleThreshold).DefaultValue;
			GenderDiversity.Value = (float)((ConfigEntryBase)GenderDiversity).DefaultValue;
			ResetSynthesis();
			ResetPhonetic();
			ResetDroning();
		}

		private static void InitializePhonetic(ConfigFile config)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Expected O, but got Unknown
			PhoneticSpeechDelay = config.Bind<float>("5. Phonetic", "Speech Delay", -0.175f, new ConfigDescription("The delay of each phoneme is its length plus this. Negative numbers cause overlapping phonemes.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticChanceDelayVariance = config.Bind<float>("5. Phonetic", "Chance Delay Variance", 0f, new ConfigDescription("This is the chance for any citizen to speak with variations in their phoneme delay.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			PhoneticMinDelayVariance = config.Bind<float>("5. Phonetic", "Min Delay Variance", 0f, new ConfigDescription("A value between the min and max delay variance is chosen to add to the speech delay to create variations in it.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMaxDelayVariance = config.Bind<float>("5. Phonetic", "Max Delay Variance", 0f, new ConfigDescription("A value between the min and max delay variance is chosen to add to the speech delay to create variations in it.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticChancePitchVariance = config.Bind<float>("5. Phonetic", "Chance Pitch Variance", 0.2f, new ConfigDescription("This is the chance for any citizen to speak with variations in their phoneme pitch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			PhoneticMinPitchVariance = config.Bind<float>("5. Phonetic", "Min Pitch Variance", 0.9f, new ConfigDescription("A value between the min and max pitch variance is chosen to multiply with the phoneme pitch to create variations of it.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMaxPitchVariance = config.Bind<float>("5. Phonetic", "Max Pitch Variance", 1.1f, new ConfigDescription("A value between the min and max pitch variance is chosen to multiply with the phoneme pitch to create variations of it.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMinFrequencyMale = config.Bind<float>("5. Phonetic", "Min Frequency Male", 100f, new ConfigDescription("Lowest possible frequency (in hertz) for male voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMaxFrequencyMale = config.Bind<float>("5. Phonetic", "Max Frequency Male", 180f, new ConfigDescription("Highest possible frequency (in hertz) for male voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMinFrequencyFemale = config.Bind<float>("5. Phonetic", "Min Frequency Female", 165f, new ConfigDescription("Lowest possible frequency (in hertz) for female voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMaxFrequencyFemale = config.Bind<float>("5. Phonetic", "Max Frequency Female", 255f, new ConfigDescription("Highest possible frequency (in hertz) for female voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMinFrequencyNonBinary = config.Bind<float>("5. Phonetic", "Min Frequency Non-Binary", 100f, new ConfigDescription("Lowest possible frequency (in hertz) for non-binary voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			PhoneticMaxFrequencyNonBinary = config.Bind<float>("5. Phonetic", "Max Frequency Non-Binary", 255f, new ConfigDescription("Highest possible frequency (in hertz) for non-binary voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			Utilities.EnforceMinMax(ref PhoneticMinDelayVariance, ref PhoneticMaxDelayVariance);
			Utilities.EnforceMinMax(ref PhoneticMinPitchVariance, ref PhoneticMaxPitchVariance);
			Utilities.EnforceMinMax(ref PhoneticMinFrequencyMale, ref PhoneticMaxFrequencyMale);
			Utilities.EnforceMinMax(ref PhoneticMinFrequencyFemale, ref PhoneticMaxFrequencyFemale);
			Utilities.EnforceMinMax(ref PhoneticMinFrequencyNonBinary, ref PhoneticMaxFrequencyNonBinary);
		}

		public static void ResetPhonetic()
		{
			PhoneticSpeechDelay.Value = (float)((ConfigEntryBase)PhoneticSpeechDelay).DefaultValue;
			PhoneticChanceDelayVariance.Value = (float)((ConfigEntryBase)PhoneticChanceDelayVariance).DefaultValue;
			PhoneticMinDelayVariance.Value = (float)((ConfigEntryBase)PhoneticMinDelayVariance).DefaultValue;
			PhoneticMaxDelayVariance.Value = (float)((ConfigEntryBase)PhoneticMaxDelayVariance).DefaultValue;
			PhoneticChancePitchVariance.Value = (float)((ConfigEntryBase)PhoneticChancePitchVariance).DefaultValue;
			PhoneticMinPitchVariance.Value = (float)((ConfigEntryBase)PhoneticMinPitchVariance).DefaultValue;
			PhoneticMaxPitchVariance.Value = (float)((ConfigEntryBase)PhoneticMaxPitchVariance).DefaultValue;
			PhoneticMinFrequencyMale.Value = (float)((ConfigEntryBase)PhoneticMinFrequencyMale).DefaultValue;
			PhoneticMaxFrequencyMale.Value = (float)((ConfigEntryBase)PhoneticMaxFrequencyMale).DefaultValue;
			PhoneticMinFrequencyFemale.Value = (float)((ConfigEntryBase)PhoneticMinFrequencyFemale).DefaultValue;
			PhoneticMaxFrequencyFemale.Value = (float)((ConfigEntryBase)PhoneticMaxFrequencyFemale).DefaultValue;
			PhoneticMinFrequencyNonBinary.Value = (float)((ConfigEntryBase)PhoneticMinFrequencyNonBinary).DefaultValue;
			PhoneticMaxFrequencyNonBinary.Value = (float)((ConfigEntryBase)PhoneticMaxFrequencyNonBinary).DefaultValue;
		}

		private static void InitializeSynthesis(ConfigFile config)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			SynthesisVoiceFilter = config.Bind<SynthesisVoiceFilterType>("4. Synthesis", "Voice Filter Type", SynthesisVoiceFilterType.Everything, new ConfigDescription("Determines which installed voices on Windows Babbler will use. Set to \"Everything\" for all installed voices, \"Blacklist\" to block some, or \"Whitelist\" to only allow some.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisVoiceFilterInput = config.Bind<string>("4. Synthesis", "Voice Filter", string.Empty, new ConfigDescription("If filter type is set to blacklist or whitelist, this is where you put the names you want to filter for in, separated by semicolons. The names are case-insensitive and flexible, so \"david\" matches \"Microsoft David\", etc.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisMinSpeed = config.Bind<int>("4. Synthesis", "Min Speed", -2, new ConfigDescription("Lowest possible speed for speech. Zero being the standard speed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10, 10), Array.Empty<object>()));
			SynthesisMaxSpeed = config.Bind<int>("4. Synthesis", "Max Speed", 3, new ConfigDescription("Highest possible speed for speech. Zero being the standard speed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10, 10), Array.Empty<object>()));
			SynthesisMinPitchMale = config.Bind<float>("4. Synthesis", "Min Pitch Male", 0.75f, new ConfigDescription("Lowest possible pitch (relative percent) for male voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisMaxPitchMale = config.Bind<float>("4. Synthesis", "Max Pitch Male", 1.25f, new ConfigDescription("Highest possible pitch (relative percent) for male voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisMinPitchFemale = config.Bind<float>("4. Synthesis", "Min Pitch Female", 0.75f, new ConfigDescription("Lowest possible pitch (relative percent) for female voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisMaxPitchFemale = config.Bind<float>("4. Synthesis", "Max Pitch Female", 1.25f, new ConfigDescription("Highest possible pitch (relative percent) for female voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisMinPitchNonBinary = config.Bind<float>("4. Synthesis", "Min Pitch Non-Binary", 0.75f, new ConfigDescription("Lowest possible pitch (relative percent) for non-binary voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			SynthesisMaxPitchNonBinary = config.Bind<float>("4. Synthesis", "Max Pitch Non-Binary", 1.25f, new ConfigDescription("Highest possible pitch (relative percent) for non-binary voices.", (AcceptableValueBase)null, Array.Empty<object>()));
			Utilities.EnforceMinMax(ref SynthesisMinSpeed, ref SynthesisMaxSpeed);
			Utilities.EnforceMinMax(ref SynthesisMinPitchMale, ref SynthesisMaxPitchMale);
			Utilities.EnforceMinMax(ref SynthesisMinPitchFemale, ref SynthesisMaxPitchFemale);
			Utilities.EnforceMinMax(ref SynthesisMinPitchNonBinary, ref SynthesisMaxPitchNonBinary);
		}

		public static void ResetSynthesis()
		{
			SynthesisVoiceFilter.Value = (SynthesisVoiceFilterType)((ConfigEntryBase)SynthesisVoiceFilter).DefaultValue;
			SynthesisVoiceFilterInput.Value = (string)((ConfigEntryBase)SynthesisVoiceFilterInput).DefaultValue;
			SynthesisMinSpeed.Value = (int)((ConfigEntryBase)SynthesisMinSpeed).DefaultValue;
			SynthesisMaxSpeed.Value = (int)((ConfigEntryBase)SynthesisMaxSpeed).DefaultValue;
			SynthesisMinPitchMale.Value = (float)((ConfigEntryBase)SynthesisMinPitchMale).DefaultValue;
			SynthesisMaxPitchMale.Value = (float)((ConfigEntryBase)SynthesisMaxPitchMale).DefaultValue;
			SynthesisMinPitchFemale.Value = (float)((ConfigEntryBase)SynthesisMinPitchFemale).DefaultValue;
			SynthesisMaxPitchFemale.Value = (float)((ConfigEntryBase)SynthesisMaxPitchFemale).DefaultValue;
			SynthesisMinPitchNonBinary.Value = (float)((ConfigEntryBase)SynthesisMinPitchNonBinary).DefaultValue;
			SynthesisMaxPitchNonBinary.Value = (float)((ConfigEntryBase)SynthesisMaxPitchNonBinary).DefaultValue;
		}
	}
}
namespace Babbler.Implementation.Common
{
	public static class FMODRegistry
	{
		private static System System;

		private static ChannelGroup ConversationalGroup;

		private static ChannelGroup OverheardGroup;

		private static ChannelGroup PhoneGroup;

		private static ChannelGroup ConversationalShoutGroup;

		private static ChannelGroup OverheardShoutGroup;

		private static ChannelGroup PhoneShoutGroup;

		public static void Initialize()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			System = RuntimeManager.CoreSystem;
			SetupConversationalGroup();
			SetupOverheardGroup();
			SetupPhoneGroup();
			Utilities.Log("FMODRegistry has initialized!", (LogLevel)32);
		}

		private static void SetupConversationalGroup()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			TryCreateChannelGroup("BabblerConversationalGroup", out ConversationalGroup);
			TryCreateChannelGroup("BabblerConversationalShoutGroup", out ConversationalShoutGroup);
			((ChannelGroup)(ref ConversationalGroup)).setVolume(BabblerConfig.ConversationalVolume.Value);
			((ChannelGroup)(ref ConversationalShoutGroup)).setVolume(BabblerConfig.ConversationalVolume.Value * BabblerConfig.ConversationalShoutMultiplier.Value);
		}

		private static void SetupOverheardGroup()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			TryCreateChannelGroup("BabblerOverheardGroup", out OverheardGroup);
			TryCreateChannelGroup("BabblerOverheardShoutGroup", out OverheardShoutGroup);
			((ChannelGroup)(ref OverheardGroup)).setVolume(BabblerConfig.OverheardVolume.Value);
			((ChannelGroup)(ref OverheardShoutGroup)).setVolume(BabblerConfig.OverheardVolume.Value * BabblerConfig.OverheardShoutMultiplier.Value);
		}

		private static void SetupPhoneGroup()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			TryCreateChannelGroup("BabblerPhoneGroup", out PhoneGroup);
			TryCreateChannelGroup("BabblerPhoneShoutGroup", out PhoneShoutGroup);
			((ChannelGroup)(ref PhoneGroup)).setVolume(BabblerConfig.PhoneVolume.Value);
			((ChannelGroup)(ref PhoneShoutGroup)).setVolume(BabblerConfig.PhoneVolume.Value * BabblerConfig.PhoneShoutMultiplier.Value);
			if (BabblerConfig.DistortPhoneSpeech.Value)
			{
				TryCreateDSP((DSP_TYPE)36, out var dsp);
				((DSP)(ref dsp)).setParameterInt(0, 6);
				((DSP)(ref dsp)).setParameterFloat(1, 300f);
				((DSP)(ref dsp)).setParameterInt(4, 9);
				((DSP)(ref dsp)).setParameterFloat(5, 1700f);
				((DSP)(ref dsp)).setParameterFloat(6, 1f);
				((DSP)(ref dsp)).setParameterInt(8, 3);
				((DSP)(ref dsp)).setParameterFloat(9, 3400f);
				((ChannelGroup)(ref PhoneGroup)).addDSP(CHANNELCONTROL_DSP_INDEX.HEAD, dsp);
				TryCreateDSP((DSP_TYPE)36, out var dsp2);
				((DSP)(ref dsp2)).setParameterInt(0, 6);
				((DSP)(ref dsp2)).setParameterFloat(1, 300f);
				((DSP)(ref dsp2)).setParameterInt(4, 9);
				((DSP)(ref dsp2)).setParameterFloat(5, 1700f);
				((DSP)(ref dsp2)).setParameterFloat(6, 1f);
				((DSP)(ref dsp2)).setParameterInt(8, 3);
				((DSP)(ref dsp2)).setParameterFloat(9, 3400f);
				((ChannelGroup)(ref PhoneShoutGroup)).addDSP(CHANNELCONTROL_DSP_INDEX.HEAD, dsp2);
			}
		}

		public static ChannelGroup GetChannelGroup(SpeechContext speechContext)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			return (ChannelGroup)(speechContext switch
			{
				SpeechContext.ConversationalSpeech => ConversationalGroup, 
				SpeechContext.OverheardSpeech => OverheardGroup, 
				SpeechContext.PhoneSpeech => PhoneGroup, 
				SpeechContext.ConversationalShout => ConversationalShoutGroup, 
				SpeechContext.OverheardShout => OverheardShoutGroup, 
				SpeechContext.PhoneShout => PhoneShoutGroup, 
				_ => OverheardGroup, 
			});
		}

		private static bool TryCreateChannelGroup(string name, out ChannelGroup channelGroup)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			RESULT val = ((System)(ref System)).createChannelGroup("BabblerSpeechGroup", ref channelGroup);
			if ((int)val == 0)
			{
				return true;
			}
			Utilities.Log($"FMODRegistry failed to create channel group \"{name}\" at {Utilities.GetCallingMethodName()}. Error: {((object)(RESULT)(ref val)).ToString()}", (LogLevel)2);
			return false;
		}

		private static bool TryCreateDSP(DSP_TYPE dspType, out DSP dsp)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			RESULT val = ((System)(ref System)).createDSPByType(dspType, ref dsp);
			if ((int)val == 0)
			{
				return true;
			}
			Utilities.Log($"FMODRegistry failed to create DSP \"{((object)(DSP_TYPE)(ref dspType)).ToString()}\" at {Utilities.GetCallingMethodName()}. Error: {((object)(RESULT)(ref val)).ToString()}", (LogLevel)2);
			return false;
		}

		public static bool TryCreateSound(string name, MODE mode, out Sound sound)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			RESULT val = ((System)(ref System)).createSound(name, mode, ref sound);
			if ((int)val == 0)
			{
				return true;
			}
			Utilities.Log($"FMODRegistry failed to create sound \"{name}\" at {Utilities.GetCallingMethodName()}. Error: {((object)(RESULT)(ref val)).ToString()}", (LogLevel)2);
			return false;
		}

		public static bool TryCreateSound(byte[] data, MODE mode, ref CREATESOUNDEXINFO extraInfo, out Sound sound)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			RESULT val = ((System)(ref System)).createSound(Il2CppStructArray<byte>.op_Implicit(data), mode, ref extraInfo, ref sound);
			if ((int)val == 0)
			{
				return true;
			}
			Utilities.Log("FMODRegistry failed to create sound \"MemoryStream\" at " + Utilities.GetCallingMethodName() + ". Error: " + ((object)(RESULT)(ref val)).ToString(), (LogLevel)2);
			return false;
		}

		public static bool TryPlaySound(Sound sound, ChannelGroup channelGroup, out Channel channel)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			RESULT val = ((System)(ref System)).playSound(sound, channelGroup, false, ref channel);
			if ((int)val == 0)
			{
				return true;
			}
			Utilities.Log("FMODRegistry failed to play sound at " + Utilities.GetCallingMethodName() + ". Error: " + ((object)(RESULT)(ref val)).ToString(), (LogLevel)2);
			return false;
		}

		public static bool TryUpdate()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_000e: Invalid comparison between Unknown and I4
			RESULT val = ((System)(ref System)).update();
			if ((int)val == 0)
			{
				return true;
			}
			Utilities.Log("FMODRegistry failed to update core system at " + Utilities.GetCallingMethodName() + ". Error: " + ((object)(RESULT)(ref val)).ToString(), (LogLevel)2);
			return false;
		}
	}
	public enum SpeechContext
	{
		ConversationalSpeech,
		OverheardSpeech,
		PhoneSpeech,
		ConversationalShout,
		OverheardShout,
		PhoneShout
	}
	public enum SpeechMode
	{
		Phonetic,
		Synthesis,
		Droning
	}
	public static class Utilities
	{
		public const bool DEBUG_BUILD = false;

		public static readonly StringBuilder GlobalStringBuilder = new StringBuilder();

		public static readonly Random GlobalRandom = new Random();

		public static void Log(string message, LogLevel level = 16)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((int)level == 32)
			{
				bool flag = false;
			}
			else
			{
				PluginController<BabblerPlugin, IEmptyBindings>.Log.Log(level, (object)message);
			}
		}

		public static string GetCallingMethodName()
		{
			StackTrace stackTrace = new StackTrace();
			StackFrame[] frames = stackTrace.GetFrames();
			if (frames == null || frames.Length <= 2)
			{
				return string.Empty;
			}
			MethodBase method = frames[2].GetMethod();
			if (method == null)
			{
				return string.Empty;
			}
			return method.Name;
		}

		public static float GetRandomFloat(float minimum, float maximum)
		{
			return minimum + GlobalRandom.NextSingle() * (maximum - minimum);
		}

		public static int GetDeterministicInteger(int hash, int prime, int min, int max)
		{
			int num = max - min;
			int num2 = Mathf.Abs(hash * prime);
			return num2 % num + min;
		}

		public static float GetDeterministicFloat(int hash, int prime, float min, float max)
		{
			float num = (float)(Mathf.Abs(hash * prime) % 100000) / 100000f;
			return num * (max - min) + min;
		}

		public static void EnforceMinMax(ref ConfigEntry<float> minimum, ref ConfigEntry<float> maximum)
		{
			float value = Mathf.Min(minimum.Value, maximum.Value);
			float value2 = Mathf.Max(minimum.Value, maximum.Value);
			minimum.Value = value;
			maximum.Value = value2;
		}

		public static void EnforceMinMax(ref ConfigEntry<int> minimum, ref ConfigEntry<int> maximum)
		{
			int value = Mathf.Min(minimum.Value, maximum.Value);
			int value2 = Mathf.Max(minimum.Value, maximum.Value);
			minimum.Value = value;
			maximum.Value = value2;
		}

		public static int GetDeterministicStringHash(string s)
		{
			int num = 352654597;
			int num2 = num;
			for (int i = 0; i < s.Length; i += 2)
			{
				num = ((num << 5) + num) ^ s[i];
				if (i == s.Length - 1)
				{
					break;
				}
				num2 = ((num2 << 5) + num2) ^ s[i + 1];
			}
			return num + num2 * 1566083941;
		}
	}
}
namespace Babbler.Implementation.Characteristics
{
	public enum VoiceCategory
	{
		Male,
		Female,
		NonBinary,
		Any
	}
	public struct VoiceCharacteristics
	{
		private const int PRIME_DIVERSITY = 31;

		private const int PRIME_PITCH = 47;

		private const int PRIME_RATE = 89;

		public VoiceCategory Category;

		public float Pitch;

		public float Rate;

		public int Hash;

		private VoiceCharacteristics(VoiceCategory category, float pitch, float rate, int hash)
		{
			Category = category;
			Pitch = pitch;
			Rate = rate;
			Hash = hash;
		}

		public static VoiceCharacteristics Create(Human human, bool maleVoiceAvailable, bool femaleVoiceAvailable, bool nonBinaryVoiceAvailable)
		{
			int deterministicStringHash = Utilities.GetDeterministicStringHash(human.seed);
			float diverseGenderScale = GetDiverseGenderScale(human, deterministicStringHash);
			float pitchScalar;
			float rateScalar;
			VoiceCategory profileInformation = GetProfileInformation(diverseGenderScale, deterministicStringHash, maleVoiceAvailable, femaleVoiceAvailable, nonBinaryVoiceAvailable, out pitchScalar, out rateScalar);
			return new VoiceCharacteristics(profileInformation, pitchScalar, rateScalar, deterministicStringHash);
		}

		private static float GetDiverseGenderScale(Human human, int hashCode)
		{
			float num = ((float)(hashCode % 31) / 31f - 0.5f) * 2f * BabblerConfig.GenderDiversity.Value;
			return Mathf.Clamp(human.genderScale + num, 0f, 1f);
		}

		private static VoiceCategory GetProfileInformation(float diverseGenderScale, int hashCode, bool hasMaleVoices, bool hasFemaleVoices, bool hasNonBinaryVoices, out float pitchScalar, out float rateScalar)
		{
			rateScalar = Utilities.GetDeterministicFloat(hashCode, 89, 0f, 1f);
			if (diverseGenderScale < BabblerConfig.FemaleThreshold.Value && hasFemaleVoices)
			{
				pitchScalar = Mathf.InverseLerp(0f, BabblerConfig.FemaleThreshold.Value, diverseGenderScale);
				return VoiceCategory.Female;
			}
			if (diverseGenderScale > BabblerConfig.MaleThreshold.Value && hasMaleVoices)
			{
				pitchScalar = Mathf.InverseLerp(BabblerConfig.MaleThreshold.Value, 1f, diverseGenderScale);
				return VoiceCategory.Male;
			}
			if (hasNonBinaryVoices)
			{
				pitchScalar = Mathf.InverseLerp(BabblerConfig.FemaleThreshold.Value, BabblerConfig.MaleThreshold.Value, diverseGenderScale);
				return VoiceCategory.NonBinary;
			}
			pitchScalar = Utilities.GetDeterministicFloat(hashCode, 47, 0f, 1f);
			return VoiceCategory.Any;
		}
	}
}
namespace Babbler.Hooks
{
	[HarmonyPatch(typeof(MainMenuController), "Start")]
	public class MainMenuControllerHook
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			PluginController<BabblerPlugin, IEmptyBindings>.Instance.InitializeDeferred();
		}
	}
	[HarmonyPatch(typeof(SpeechBubbleController), "Setup")]
	public class SpeechBubbleControllerHook
	{
		private static Human LastPhoneHuman;

		[HarmonyPostfix]
		public static void Postfix(SpeechBubbleController __instance, QueueElement newSpeech, SpeechController newSpeechController)
		{
			string text = ((__instance != null) ? __instance.actualString : null);
			if (!string.IsNullOrWhiteSpace(text) && !__instance.isPlayer && !CutSceneController.Instance.cutSceneActive && !IsEmoteSpeech(text) && !HasCharacterRepeated(text, 3))
			{
				BubbleHumanSearch(__instance, out var speakingHuman, out var telephoneHuman, out var anyHuman);
				if ((Object)(object)anyHuman == (Object)null)
				{
					Utilities.Log("Babbler unable to find a human to associate with message \"" + text + "\"!", (LogLevel)32);
					return;
				}
				SpeechContext speechContext = GetSpeechContext(text, speakingHuman, telephoneHuman, newSpeechController);
				SpeakerHostPool.Play(__instance.actualString, speechContext, anyHuman);
			}
		}

		private static SpeechContext GetSpeechContext(string speechInput, Human speakingHuman, Human telephoneHuman, SpeechController speechController)
		{
			bool flag = IsAllCaps(speechInput);
			if ((Object)(object)speakingHuman == (Object)null && (Object)(object)telephoneHuman != (Object)null)
			{
				return flag ? SpeechContext.PhoneShout : SpeechContext.PhoneSpeech;
			}
			if ((Object)(object)speechController.actor != (Object)(object)Player.Instance && InteractionController.Instance.dialogMode && InteractionController.Instance.talkingTo == speechController.interactable)
			{
				return flag ? SpeechContext.ConversationalShout : SpeechContext.ConversationalSpeech;
			}
			return (!flag) ? SpeechContext.OverheardSpeech : SpeechContext.OverheardShout;
		}

		private static bool IsEmoteSpeech(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return true;
			}
			return input[0] switch
			{
				'[' => input.EndsWith("]"), 
				'(' => input.EndsWith(")"), 
				'{' => input.EndsWith("}"), 
				'<' => input.EndsWith(">"), 
				_ => false, 
			};
		}

		private static bool HasCharacterRepeated(string input, int times)
		{
			if (string.IsNullOrEmpty(input) || times <= 0)
			{
				return false;
			}
			string text = input.ToLowerInvariant();
			int num = 1;
			for (int i = 1; i < text.Length; i++)
			{
				if (text[i] == text[i - 1])
				{
					num++;
					if (num >= times)
					{
						return true;
					}
				}
				else
				{
					num = 1;
				}
			}
			return false;
		}

		private static bool IsAllCaps(string input)
		{
			foreach (char c in input)
			{
				if (char.IsLetter(c) && !char.IsUpper(c))
				{
					return false;
				}
			}
			return true;
		}

		private static void BubbleHumanSearch(SpeechBubbleController bubbleController, out Human speakingHuman, out Human telephoneHuman, out Human anyHuman)
		{
			SpeechController val = ((bubbleController != null) ? bubbleController.speechController : null);
			object obj;
			if (val == null)
			{
				obj = null;
			}
			else
			{
				Interactable interactable = val.interactable;
				obj = ((interactable != null) ? interactable.controller : null);
			}
			InteractableController val2 = (InteractableController)obj;
			Actor val3 = ((val != null) ? val.actor : null);
			bool flag = ((val != null) ? val.phoneLine : null) != null || ((Object)(object)val2 != (Object)null && val2.isPhone);
			Human val4 = (Human)(object)((val3 is Human) ? val3 : null);
			object obj2;
			if (val3 == null)
			{
				obj2 = null;
			}
			else
			{
				NewAIController ai = val3.ai;
				obj2 = ((ai != null) ? ai.human : null);
			}
			Human val5 = (Human)obj2;
			speakingHuman = val4 ?? val5;
			telephoneHuman = GetOtherPhoneHuman();
			if (flag)
			{
				if ((Object)(object)telephoneHuman == (Object)null)
				{
					Player instance = Player.Instance;
					PhoneCall val6 = ((instance != null) ? instance.activeCall : null);
					if (val6 != null)
					{
						telephoneHuman = GetOperatorHuman();
						LastPhoneHuman = telephoneHuman;
					}
					else
					{
						telephoneHuman = LastPhoneHuman;
					}
				}
				else
				{
					LastPhoneHuman = telephoneHuman;
				}
			}
			anyHuman = speakingHuman ?? telephoneHuman;
		}

		private static Human GetOtherPhoneHuman()
		{
			Player instance = Player.Instance;
			PhoneCall val = ((instance != null) ? instance.activeCall : null);
			if (val == null)
			{
				return null;
			}
			SideJob val2 = default(SideJob);
			if (val.source.job > -1 && SideJobController.Instance.allJobsDictionary.TryGetValue(val.source.job, ref val2))
			{
				return val2.poster;
			}
			Human val3 = default(Human);
			if (CityData.Instance.GetHuman(val.caller, ref val3, true) && (Object)(object)val3 != (Object)null && !((Actor)val3).isPlayer)
			{
				return val3;
			}
			Human val4 = default(Human);
			if (CityData.Instance.GetHuman(val.receiver, ref val4, true) && (Object)(object)val4 != (Object)null && !((Actor)val4).isPlayer)
			{
				return val4;
			}
			return null;
		}

		private static Human GetOperatorHuman()
		{
			int deterministicStringHash = Utilities.GetDeterministicStringHash(CityData.Instance.seed);
			int num = Mathf.RoundToInt(SessionData.Instance.gameTime / 8f);
			int num2 = deterministicStringHash + num;
			int num3 = num2 * (num2 + 1) / 2 + num;
			int num4 = Mathf.Abs(num3) % CityData.Instance.citizenDirectory.Count;
			return (Human)(object)CityData.Instance.citizenDirectory._items[num4];
		}
	}
}

plugins/System.Speech.dll

Decompiled 3 days ago
#define TRACE
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
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.CodeAnalysis;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyDefaultAlias("System.Speech")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Provides types to perform speech synthesis and speech recognition.\r\n\r\nCommonly Used Types\r\nSystem.Speech.Synthesis.SpeechSynthesizer\r\nSystem.Speech.Recognition.SpeechRecognizer")]
[assembly: AssemblyFileVersion("8.0.23.53103")]
[assembly: AssemblyInformationalVersion("8.0.0+5535e31a712343a63f5d7d796cd874e563e5ac14")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("System.Speech")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: SupportedOSPlatform("Windows")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("8.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class Interop
{
	internal static class Libraries
	{
		internal const string Activeds = "activeds.dll";

		internal const string Advapi32 = "advapi32.dll";

		internal const string Authz = "authz.dll";

		internal const string BCrypt = "BCrypt.dll";

		internal const string Credui = "credui.dll";

		internal const string Crypt32 = "crypt32.dll";

		internal const string CryptUI = "cryptui.dll";

		internal const string Dnsapi = "dnsapi.dll";

		internal const string Dsrole = "dsrole.dll";

		internal const string Gdi32 = "gdi32.dll";

		internal const string HttpApi = "httpapi.dll";

		internal const string IpHlpApi = "iphlpapi.dll";

		internal const string Kernel32 = "kernel32.dll";

		internal const string Logoncli = "logoncli.dll";

		internal const string Mswsock = "mswsock.dll";

		internal const string NCrypt = "ncrypt.dll";

		internal const string Netapi32 = "netapi32.dll";

		internal const string Netutils = "netutils.dll";

		internal const string NtDll = "ntdll.dll";

		internal const string Odbc32 = "odbc32.dll";

		internal const string Ole32 = "ole32.dll";

		internal const string OleAut32 = "oleaut32.dll";

		internal const string Pdh = "pdh.dll";

		internal const string Secur32 = "secur32.dll";

		internal const string Shell32 = "shell32.dll";

		internal const string SspiCli = "sspicli.dll";

		internal const string User32 = "user32.dll";

		internal const string Version = "version.dll";

		internal const string WebSocket = "websocket.dll";

		internal const string Wevtapi = "wevtapi.dll";

		internal const string WinHttp = "winhttp.dll";

		internal const string WinMM = "winmm.dll";

		internal const string Wkscli = "wkscli.dll";

		internal const string Wldap32 = "wldap32.dll";

		internal const string Ws2_32 = "ws2_32.dll";

		internal const string Wtsapi32 = "wtsapi32.dll";

		internal const string CompressionNative = "System.IO.Compression.Native";

		internal const string GlobalizationNative = "System.Globalization.Native";

		internal const string MsQuic = "msquic.dll";

		internal const string HostPolicy = "hostpolicy";

		internal const string Ucrtbase = "ucrtbase.dll";

		internal const string Xolehlp = "xolehlp.dll";

		internal const string Comdlg32 = "comdlg32.dll";

		internal const string Gdiplus = "gdiplus.dll";

		internal const string Oleaut32 = "oleaut32.dll";

		internal const string Winspool = "winspool.drv";
	}

	internal static class WinMM
	{
		internal enum MMSYSERR
		{
			NOERROR = 0,
			ERROR = 1,
			BADDEVICEID = 2,
			NOTENABLED = 3,
			ALLOCATED = 4,
			INVALHANDLE = 5,
			NODRIVER = 6,
			NOMEM = 7,
			NOTSUPPORTED = 8,
			BADERRNUM = 9,
			INVALFLAG = 10,
			INVALPARAM = 11,
			HANDLEBUSY = 12,
			INVALIDALIAS = 13,
			BADDB = 14,
			KEYNOTFOUND = 15,
			READERROR = 16,
			WRITEERROR = 17,
			DELETEERROR = 18,
			VALNOTFOUND = 19,
			NODRIVERCB = 20,
			LASTERROR = 20
		}

		internal struct WAVEOUTCAPS
		{
			private const int szPnameLength = 32;

			private ushort wMid;

			private ushort wPid;

			private uint vDriverVersion;

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

			private uint dwFormats;

			private ushort wChannels;

			private ushort wReserved1;

			private ushort dwSupport;
		}

		internal enum MM_MSG
		{
			MM_WOM_OPEN = 955,
			MM_WOM_CLOSE,
			MM_WOM_DONE
		}

		internal delegate void WaveOutProc(IntPtr hwo, MM_MSG uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2);

		internal struct WAVEHDR
		{
			internal IntPtr lpData;

			internal uint dwBufferLength;

			internal uint dwBytesRecorded;

			internal uint dwUser;

			internal uint dwFlags;

			internal uint dwLoops;

			internal IntPtr lpNext;

			internal uint reserved;
		}

		internal const uint CALLBACK_WINDOW = 65536u;

		internal const uint CALLBACK_NULL = 0u;

		internal const uint CALLBACK_FUNCTION = 196608u;

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutClose(IntPtr hwo);

		[DllImport("winmm.dll", EntryPoint = "waveOutGetDevCapsW", ExactSpelling = true)]
		[LibraryImport("winmm.dll", EntryPoint = "waveOutGetDevCapsW")]
		internal static extern MMSYSERR waveOutGetDevCaps(IntPtr uDeviceID, ref WAVEOUTCAPS caps, int cbwoc);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern int waveOutGetNumDevs();

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutOpen(ref IntPtr phwo, int uDeviceID, byte[] pwfx, WaveOutProc dwCallback, IntPtr dwInstance, uint fdwOpen);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutPause(IntPtr hwo);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutPrepareHeader(IntPtr hwo, IntPtr pwh, int cbwh);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutUnprepareHeader(IntPtr hwo, IntPtr pwh, int cbwh);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutReset(IntPtr hwo);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutRestart(IntPtr hwo);

		[DllImport("winmm.dll", ExactSpelling = true)]
		[LibraryImport("winmm.dll")]
		internal static extern MMSYSERR waveOutWrite(IntPtr hwo, IntPtr pwh, int cbwh);
	}
}
namespace System
{
	internal static class Obsoletions
	{
		internal const string SharedUrlFormat = "https://aka.ms/dotnet-warnings/{0}";

		internal const string SystemTextEncodingUTF7Message = "The UTF-7 encoding is insecure and should not be used. Consider using UTF-8 instead.";

		internal const string SystemTextEncodingUTF7DiagId = "SYSLIB0001";

		internal const string PrincipalPermissionAttributeMessage = "PrincipalPermissionAttribute is not honored by the runtime and must not be used.";

		internal const string PrincipalPermissionAttributeDiagId = "SYSLIB0002";

		internal const string CodeAccessSecurityMessage = "Code Access Security is not supported or honored by the runtime.";

		internal const string CodeAccessSecurityDiagId = "SYSLIB0003";

		internal const string ConstrainedExecutionRegionMessage = "The Constrained Execution Region (CER) feature is not supported.";

		internal const string ConstrainedExecutionRegionDiagId = "SYSLIB0004";

		internal const string GlobalAssemblyCacheMessage = "The Global Assembly Cache is not supported.";

		internal const string GlobalAssemblyCacheDiagId = "SYSLIB0005";

		internal const string ThreadAbortMessage = "Thread.Abort is not supported and throws PlatformNotSupportedException.";

		internal const string ThreadResetAbortMessage = "Thread.ResetAbort is not supported and throws PlatformNotSupportedException.";

		internal const string ThreadAbortDiagId = "SYSLIB0006";

		internal const string DefaultCryptoAlgorithmsMessage = "The default implementation of this cryptography algorithm is not supported.";

		internal const string DefaultCryptoAlgorithmsDiagId = "SYSLIB0007";

		internal const string CreatePdbGeneratorMessage = "The CreatePdbGenerator API is not supported and throws PlatformNotSupportedException.";

		internal const string CreatePdbGeneratorDiagId = "SYSLIB0008";

		internal const string AuthenticationManagerMessage = "The AuthenticationManager Authenticate and PreAuthenticate methods are not supported and throw PlatformNotSupportedException.";

		internal const string AuthenticationManagerDiagId = "SYSLIB0009";

		internal const string RemotingApisMessage = "This Remoting API is not supported and throws PlatformNotSupportedException.";

		internal const string RemotingApisDiagId = "SYSLIB0010";

		internal const string BinaryFormatterMessage = "BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.";

		internal const string BinaryFormatterDiagId = "SYSLIB0011";

		internal const string CodeBaseMessage = "Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.";

		internal const string CodeBaseDiagId = "SYSLIB0012";

		internal const string EscapeUriStringMessage = "Uri.EscapeUriString can corrupt the Uri string in some cases. Consider using Uri.EscapeDataString for query string components instead.";

		internal const string EscapeUriStringDiagId = "SYSLIB0013";

		internal const string WebRequestMessage = "WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.";

		internal const string WebRequestDiagId = "SYSLIB0014";

		internal const string DisablePrivateReflectionAttributeMessage = "DisablePrivateReflectionAttribute has no effect in .NET 6.0+.";

		internal const string DisablePrivateReflectionAttributeDiagId = "SYSLIB0015";

		internal const string GetContextInfoMessage = "Use the Graphics.GetContextInfo overloads that accept arguments for better performance and fewer allocations.";

		internal const string GetContextInfoDiagId = "SYSLIB0016";

		internal const string StrongNameKeyPairMessage = "Strong name signing is not supported and throws PlatformNotSupportedException.";

		internal const string StrongNameKeyPairDiagId = "SYSLIB0017";

		internal const string ReflectionOnlyLoadingMessage = "ReflectionOnly loading is not supported and throws PlatformNotSupportedException.";

		internal const string ReflectionOnlyLoadingDiagId = "SYSLIB0018";

		internal const string RuntimeEnvironmentMessage = "RuntimeEnvironment members SystemConfigurationFile, GetRuntimeInterfaceAsIntPtr, and GetRuntimeInterfaceAsObject are not supported and throw PlatformNotSupportedException.";

		internal const string RuntimeEnvironmentDiagId = "SYSLIB0019";

		internal const string JsonSerializerOptionsIgnoreNullValuesMessage = "JsonSerializerOptions.IgnoreNullValues is obsolete. To ignore null values when serializing, set DefaultIgnoreCondition to JsonIgnoreCondition.WhenWritingNull.";

		internal const string JsonSerializerOptionsIgnoreNullValuesDiagId = "SYSLIB0020";

		internal const string DerivedCryptographicTypesMessage = "Derived cryptographic types are obsolete. Use the Create method on the base type instead.";

		internal const string DerivedCryptographicTypesDiagId = "SYSLIB0021";

		internal const string RijndaelMessage = "The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.";

		internal const string RijndaelDiagId = "SYSLIB0022";

		internal const string RNGCryptoServiceProviderMessage = "RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.";

		internal const string RNGCryptoServiceProviderDiagId = "SYSLIB0023";

		internal const string AppDomainCreateUnloadMessage = "Creating and unloading AppDomains is not supported and throws an exception.";

		internal const string AppDomainCreateUnloadDiagId = "SYSLIB0024";

		internal const string SuppressIldasmAttributeMessage = "SuppressIldasmAttribute has no effect in .NET 6.0+.";

		internal const string SuppressIldasmAttributeDiagId = "SYSLIB0025";

		internal const string X509CertificateImmutableMessage = "X509Certificate and X509Certificate2 are immutable. Use the appropriate constructor to create a new certificate.";

		internal const string X509CertificateImmutableDiagId = "SYSLIB0026";

		internal const string PublicKeyPropertyMessage = "PublicKey.Key is obsolete. Use the appropriate method to get the public key, such as GetRSAPublicKey.";

		internal const string PublicKeyPropertyDiagId = "SYSLIB0027";

		internal const string X509CertificatePrivateKeyMessage = "X509Certificate2.PrivateKey is obsolete. Use the appropriate method to get the private key, such as GetRSAPrivateKey, or use the CopyWithPrivateKey method to create a new instance with a private key.";

		internal const string X509CertificatePrivateKeyDiagId = "SYSLIB0028";

		internal const string ProduceLegacyHmacValuesMessage = "ProduceLegacyHmacValues is obsolete. Producing legacy HMAC values is not supported.";

		internal const string ProduceLegacyHmacValuesDiagId = "SYSLIB0029";

		internal const string UseManagedSha1Message = "HMACSHA1 always uses the algorithm implementation provided by the platform. Use a constructor without the useManagedSha1 parameter.";

		internal const string UseManagedSha1DiagId = "SYSLIB0030";

		internal const string CryptoConfigEncodeOIDMessage = "EncodeOID is obsolete. Use the ASN.1 functionality provided in System.Formats.Asn1.";

		internal const string CryptoConfigEncodeOIDDiagId = "SYSLIB0031";

		internal const string CorruptedStateRecoveryMessage = "Recovery from corrupted process state exceptions is not supported; HandleProcessCorruptedStateExceptionsAttribute is ignored.";

		internal const string CorruptedStateRecoveryDiagId = "SYSLIB0032";

		internal const string Rfc2898CryptDeriveKeyMessage = "Rfc2898DeriveBytes.CryptDeriveKey is obsolete and is not supported. Use PasswordDeriveBytes.CryptDeriveKey instead.";

		internal const string Rfc2898CryptDeriveKeyDiagId = "SYSLIB0033";

		internal const string CmsSignerCspParamsCtorMessage = "CmsSigner(CspParameters) is obsolete and is not supported. Use an alternative constructor instead.";

		internal const string CmsSignerCspParamsCtorDiagId = "SYSLIB0034";

		internal const string SignerInfoCounterSigMessage = "ComputeCounterSignature without specifying a CmsSigner is obsolete and is not supported. Use the overload that accepts a CmsSigner.";

		internal const string SignerInfoCounterSigDiagId = "SYSLIB0035";

		internal const string RegexCompileToAssemblyMessage = "Regex.CompileToAssembly is obsolete and not supported. Use the GeneratedRegexAttribute with the regular expression source generator instead.";

		internal const string RegexCompileToAssemblyDiagId = "SYSLIB0036";

		internal const string AssemblyNameMembersMessage = "AssemblyName members HashAlgorithm, ProcessorArchitecture, and VersionCompatibility are obsolete and not supported.";

		internal const string AssemblyNameMembersDiagId = "SYSLIB0037";

		internal const string SystemDataSerializationFormatBinaryMessage = "SerializationFormat.Binary is obsolete and should not be used. See https://aka.ms/serializationformat-binary-obsolete for more information.";

		internal const string SystemDataSerializationFormatBinaryDiagId = "SYSLIB0038";

		internal const string TlsVersion10and11Message = "TLS versions 1.0 and 1.1 have known vulnerabilities and are not recommended. Use a newer TLS version instead, or use SslProtocols.None to defer to OS defaults.";

		internal const string TlsVersion10and11DiagId = "SYSLIB0039";

		internal const string EncryptionPolicyMessage = "EncryptionPolicy.NoEncryption and AllowEncryption significantly reduce security and should not be used in production code.";

		internal const string EncryptionPolicyDiagId = "SYSLIB0040";

		internal const string Rfc2898OutdatedCtorMessage = "The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.";

		internal const string Rfc2898OutdatedCtorDiagId = "SYSLIB0041";

		internal const string EccXmlExportImportMessage = "ToXmlString and FromXmlString have no implementation for ECC types, and are obsolete. Use a standard import and export format such as ExportSubjectPublicKeyInfo or ImportSubjectPublicKeyInfo for public keys and ExportPkcs8PrivateKey or ImportPkcs8PrivateKey for private keys.";

		internal const string EccXmlExportImportDiagId = "SYSLIB0042";

		internal const string EcDhPublicKeyBlobMessage = "ECDiffieHellmanPublicKey.ToByteArray() and the associated constructor do not have a consistent and interoperable implementation on all platforms. Use ECDiffieHellmanPublicKey.ExportSubjectPublicKeyInfo() instead.";

		internal const string EcDhPublicKeyBlobDiagId = "SYSLIB0043";

		internal const string AssemblyNameCodeBaseMessage = "AssemblyName.CodeBase and AssemblyName.EscapedCodeBase are obsolete. Using them for loading an assembly is not supported.";

		internal const string AssemblyNameCodeBaseDiagId = "SYSLIB0044";

		internal const string CryptoStringFactoryMessage = "Cryptographic factory methods accepting an algorithm name are obsolete. Use the parameterless Create factory method on the algorithm type instead.";

		internal const string CryptoStringFactoryDiagId = "SYSLIB0045";

		internal const string ControlledExecutionRunMessage = "ControlledExecution.Run method may corrupt the process and should not be used in production code.";

		internal const string ControlledExecutionRunDiagId = "SYSLIB0046";

		internal const string XmlSecureResolverMessage = "XmlSecureResolver is obsolete. Use XmlResolver.ThrowingResolver instead when attempting to forbid XML external entity resolution.";

		internal const string XmlSecureResolverDiagId = "SYSLIB0047";

		internal const string RsaEncryptDecryptValueMessage = "RSA.EncryptValue and DecryptValue are not supported and throw NotSupportedException. Use RSA.Encrypt and RSA.Decrypt instead.";

		internal const string RsaEncryptDecryptDiagId = "SYSLIB0048";

		internal const string JsonSerializerOptionsAddContextMessage = "JsonSerializerOptions.AddContext is obsolete. To register a JsonSerializerContext, use either the TypeInfoResolver or TypeInfoResolverChain properties.";

		internal const string JsonSerializerOptionsAddContextDiagId = "SYSLIB0049";

		internal const string LegacyFormatterMessage = "Formatter-based serialization is obsolete and should not be used.";

		internal const string LegacyFormatterDiagId = "SYSLIB0050";

		internal const string LegacyFormatterImplMessage = "This API supports obsolete formatter-based serialization. It should not be called or extended by application code.";

		internal const string LegacyFormatterImplDiagId = "SYSLIB0051";

		internal const string RegexExtensibilityImplMessage = "This API supports obsolete mechanisms for Regex extensibility. It is not supported.";

		internal const string RegexExtensibilityDiagId = "SYSLIB0052";

		internal const string AesGcmTagConstructorMessage = "AesGcm should indicate the required tag size for encryption and decryption. Use a constructor that accepts the tag size.";

		internal const string AesGcmTagConstructorDiagId = "SYSLIB0053";
	}
}
namespace System.Runtime.InteropServices
{
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	internal sealed class LibraryImportAttribute : Attribute
	{
		public string LibraryName { get; }

		public string EntryPoint { get; set; }

		public StringMarshalling StringMarshalling { get; set; }

		public Type StringMarshallingCustomType { get; set; }

		public bool SetLastError { get; set; }

		public LibraryImportAttribute(string libraryName)
		{
			LibraryName = libraryName;
		}
	}
	internal enum StringMarshalling
	{
		Custom,
		Utf8,
		Utf16
	}
}
namespace System.Speech
{
	internal static class SR
	{
		private static ResourceManager s_resourceManager = new ResourceManager("ExceptionStringTable", typeof(SR).Assembly);

		internal static string Get(SRID id, params object[] args)
		{
			string text = s_resourceManager.GetString(id.ToString());
			if (string.IsNullOrEmpty(text))
			{
				text = s_resourceManager.GetString("Unavailable");
			}
			else if (args != null && args.Length != 0)
			{
				text = string.Format(text, args);
			}
			return text;
		}
	}
	internal enum SRID
	{
		NullParamIllegal,
		ArrayOfNullIllegal,
		ParamsEntryNullIllegal,
		Unavailable,
		UnexpectedError,
		CollectionReadOnly,
		StringCanNotBeEmpty,
		EnumInvalid,
		NotSupportedWithThisVersionOfSAPI,
		NotSupportedWithThisVersionOfSAPI2,
		NotSupportedWithThisVersionOfSAPIBaseUri,
		NotSupportedWithThisVersionOfSAPITagFormat,
		NotSupportedWithThisVersionOfSAPICompareOption,
		MustBeGreaterThanZero,
		InvalidXml,
		OperationAborted,
		InvariantCultureInfo,
		DuplicatedEntry,
		StreamMustBeReadable,
		StreamMustBeWriteable,
		StreamMustBeSeekable,
		StreamEndedUnexpectedly,
		CannotReadFromDirectory,
		UnknownMimeFormat,
		CannotLoadResourceFromManifest,
		TokenInUse,
		TokenDeleted,
		TokenUninitialized,
		InvalidTokenId,
		NotFound,
		NoBackSlash,
		InvalidRegistryEntry,
		TokenCannotCreateInstance,
		InvalidXmlFormat,
		IncorrectAttributeValue,
		MissingRequiredAttribute,
		InvalidRuleRefSelf,
		InvalidDynamicExport,
		InvalidToken,
		MetaNameHTTPEquiv,
		EmptyRule,
		InvalidTokenString,
		InvalidQuotedString,
		ExportDynamicRule,
		EmptyDisplayString,
		EmptyPronunciationString,
		InvalidPhoneme,
		MuliplePronunciationString,
		MultipleDisplayString,
		RuleRedefinition,
		EmptyOneOf,
		InvalidGrammarOrdering,
		MinMaxOutOfRange,
		InvalidExampleOrdering,
		GrammarDefTwice,
		UnsupportedFormat,
		InvalidImport,
		DuplicatedRuleName,
		RootRuleAlreadyDefined,
		RuleNameIdConflict,
		RuleNotDynamic,
		StateWithNoArcs,
		NoTerminatingRulePath,
		RuleRefNoUri,
		UnavailableProperty,
		MinGreaterThanMax,
		ReqConfidenceNotSupported,
		SapiPropertiesAndSemantics,
		InvalidAttributeDefinedTwice,
		GrammarCompilerError,
		RuleScriptNotFound,
		DynamicRuleNotFound,
		RuleScriptInvalidParameters,
		RuleScriptInvalidReturnType,
		NoClassname,
		EmbeddedClassLibraryFailed,
		CannotFindClass,
		StrongTypedGrammarNotAGrammar,
		NoScriptsForRules,
		ClassNotPublic,
		MethodNotPublic,
		IncompatibleLanguageProperties,
		IncompatibleNamespaceProperties,
		IncompatibleDebugProperties,
		CannotLoadDotNetSemanticCode,
		InvalidSemanticProcessingType,
		InvalidScriptDefinition,
		InvalidMethodName,
		ConstructorNotAllowed,
		OverloadNotAllowed,
		OnInitOnPublicRule,
		ArgumentMismatch,
		CantGetPropertyFromSerializedInfo,
		CantFindAConstructor,
		TooManyArcs,
		TooManyRulesWithSemanticsGlobals,
		MaxTransitionsCount,
		UnknownElement,
		CircularRuleRef,
		InvalidFlagsSet,
		RuleDefinedMultipleTimes,
		RuleDefinedMultipleTimes2,
		RuleNotDefined,
		RootNotDefined,
		InvalidLanguage,
		InvalidRuleId,
		InvalidRepeatProbability,
		InvalidConfidence,
		InvalidMinRepeat,
		InvalidMaxRepeat,
		InvalidWeight,
		InvalidName,
		InvalidValueType,
		TagFormatNotSet,
		NoName,
		NoName1,
		InvalidSpecialRuleRef,
		InvalidRuleRef,
		InvalidNotEmptyElement,
		InvalidEmptyElement,
		InvalidEmptyRule,
		UndefRuleRef,
		UnsupportedLanguage,
		UnsupportedPhoneticAlphabet,
		UnsupportedLexicon,
		InvalidScriptAttribute,
		NoLanguageSet,
		MethodAttributeDefinedMultipleTimes,
		RuleAttributeDefinedMultipleTimes,
		InvalidAssemblyReferenceAttribute,
		InvalidImportNamespaceAttribute,
		NoUriForSpecialRuleRef,
		NoAliasForSpecialRuleRef,
		NoSmlData,
		InvalidNameValueProperty,
		InvalidTagInAnEmptyItem,
		InvalidSrgs,
		InvalidSrgsNamespace,
		Line,
		Position,
		InvalidVersion,
		InvalidTagFormat,
		MissingTagFormat,
		InvalidGrammarMode,
		InvalidGrammarAttribute,
		InvalidRuleAttribute,
		InvalidRulerefAttribute,
		InvalidOneOfAttribute,
		InvalidItemAttribute,
		InvalidTokenAttribute,
		InvalidItemRepeatAttribute,
		InvalidReqConfAttribute,
		InvalidTagAttribute,
		InvalidLexiconAttribute,
		InvalidMetaAttribute,
		InvalidItemAttribute2,
		InvalidElement,
		InvalidRuleScope,
		InvalidDynamicSetting,
		InvalidSubsetAttribute,
		InvalidVoiceElementInPromptOutput,
		NoRuleId,
		PromptBuilderInvalideState,
		PromptBuilderStateEnded,
		PromptBuilderStateSentence,
		PromptBuilderStateParagraph,
		PromptBuilderStateVoice,
		PromptBuilderStateStyle,
		PromptBuilderAgeOutOfRange,
		PromptBuilderMismatchStyle,
		PromptBuilderMismatchVoice,
		PromptBuilderMismatchParagraph,
		PromptBuilderMismatchSentence,
		PromptBuilderNestedParagraph,
		PromptBuilderNestedSentence,
		PromptBuilderInvalidAttribute,
		PromptBuilderInvalidElement,
		PromptBuilderInvalidVariant,
		PromptBuilderDatabaseName,
		PromptAsyncOperationCancelled,
		SynthesizerPauseResumeMismatched,
		SynthesizerInvalidMediaType,
		SynthesizerUnknownMediaType,
		SynthesizerSpeakError,
		SynthesizerInvalidWaveFile,
		SynthesizerPromptInUse,
		SynthesizerUnknownPriority,
		SynthesizerUnknownEvent,
		SynthesizerVoiceFailed,
		SynthesizerSetVoiceNoMatch,
		SynthesizerNoCulture,
		SynthesizerSyncSpeakWhilePaused,
		SynthesizerSyncSetOutputWhilePaused,
		SynthesizerNoCulture2,
		SynthesizerNoSpeak,
		SynthesizerSetOutputSpeaking,
		InvalidSpeakAttribute,
		UnsupportedAlphabet,
		GrammarInvalidWeight,
		GrammarInvalidPriority,
		DictationInvalidTopic,
		DictationTopicNotFound,
		RecognizerGrammarNotFound,
		RecognizerRuleNotFound,
		RecognizerInvalidBinaryGrammar,
		RecognizerRuleNotFoundStream,
		RecognizerNoRootRuleToActivate,
		RecognizerNoRootRuleToActivate1,
		RecognizerRuleActivationFailed,
		RecognizerAlreadyRecognizing,
		RecognizerHasNoGrammar,
		NegativeTimesNotSupported,
		AudioDeviceFormatError,
		AudioDeviceError,
		AudioDeviceInternalError,
		RecognizerNotFound,
		RecognizerNotEnabled,
		RecognitionNotSupported,
		RecognitionNotSupportedOn64bit,
		GrammarAlreadyLoaded,
		RecognizerNoInputSource,
		GrammarNotLoaded,
		GrammarLoadingInProgress,
		GrammarLoadFailed,
		GrammarWrongRecognizer,
		NotSupportedOnDictationGrammars,
		LocalFilesOnly,
		NotValidAudioFile,
		NotValidAudioStream,
		FileNotFound,
		CannotSetPriorityOnDictation,
		RecognizerUpdateTableTooLarge,
		MaxAlternatesInvalid,
		RecognizerSettingGetError,
		RecognizerSettingUpdateError,
		RecognizerSettingNotSupported,
		ResourceUsageOutOfRange,
		RateOutOfRange,
		EndSilenceOutOfRange,
		RejectionThresholdOutOfRange,
		ReferencedGrammarNotFound,
		SapiErrorRuleNotFound2,
		NoAudioAvailable,
		ResultNotGrammarAvailable,
		ResultInvalidFormat,
		UnhandledVariant,
		DupSemanticKey,
		DupSemanticValue,
		CannotUseCustomFormat,
		NoPromptEngine,
		NoPromptEngineInterface,
		SeekNotSupported,
		ExtraDataNotPresent,
		BitsPerSampleInvalid,
		DataBlockSizeInvalid,
		NotWholeNumberBlocks,
		BlockSignatureInvalid,
		NumberOfSamplesInvalid,
		SapiErrorUninitialized,
		SapiErrorAlreadyInitialized,
		SapiErrorNotSupportedFormat,
		SapiErrorInvalidFlags,
		SapiErrorEndOfStream,
		SapiErrorDeviceBusy,
		SapiErrorDeviceNotSupported,
		SapiErrorDeviceNotEnabled,
		SapiErrorNoDriver,
		SapiErrorFileMustBeUnicode,
		InsufficientData,
		SapiErrorInvalidPhraseID,
		SapiErrorBufferTooSmall,
		SapiErrorFormatNotSpecified,
		SapiErrorAudioStopped0,
		AudioPaused,
		SapiErrorRuleNotFound,
		SapiErrorTTSEngineException,
		SapiErrorTTSNLPException,
		SapiErrorEngineBUSY,
		AudioConversionEnabled,
		NoHypothesisAvailable,
		SapiErrorCantCreate,
		AlreadyInLex,
		SapiErrorNotInLex,
		LexNothingToSync,
		SapiErrorLexVeryOutOfSync,
		SapiErrorUndefinedForwardRuleRef,
		SapiErrorEmptyRule,
		SapiErrorGrammarCompilerInternalError,
		SapiErrorRuleNotDynamic,
		SapiErrorDuplicateRuleName,
		SapiErrorDuplicateResourceName,
		SapiErrorTooManyGrammars,
		SapiErrorCircularReference,
		SapiErrorInvalidImport,
		SapiErrorInvalidWAVFile,
		RequestPending,
		SapiErrorAllWordsOptional,
		SapiErrorInstanceChangeInvalid,
		SapiErrorRuleNameIdConflict,
		SapiErrorNoRules,
		SapiErrorCircularRuleRef,
		NoParseFound,
		SapiErrorInvalidHandle,
		SapiErrorRemoteCallTimedout,
		SapiErrorAudioBufferOverflow,
		SapiErrorNoAudioData,
		SapiErrorDeadAlternate,
		SapiErrorHighLowConfidence,
		SapiErrorInvalidFormatString,
		SPNotSupportedOnStreamInput,
		SapiErrorAppLexReadOnly,
		SapiErrorNoTerminatingRulePath,
		WordExistsWithoutPronunciation,
		SapiErrorStreamClosed,
		SapiErrorNoMoreItems,
		SapiErrorNotFound,
		SapiErrorInvalidAudioState,
		SapiErrorGenericMMSYS,
		SapiErrorMarshalerException,
		SapiErrorNotDynamicGrammar,
		SapiErrorAmbiguousProperty,
		SapiErrorInvalidRegistrykey,
		SapiErrorInvalidTokenId,
		SapiErrorXMLBadSyntax,
		SapiErrorXMLResourceNotFound,
		SapiErrorTokenInUse,
		SapiErrorTokenDeleted,
		SapiErrorMultilingualNotSupported,
		SapiErrorExportDynamicRule,
		SapiErrorSTGF,
		SapiErrorWordFormat,
		SapiErrorStreamNotActive,
		SapiErrorEngineResponseInvalid,
		SapiErrorSREngineException,
		SapiErrorStreamPosInvalid,
		SapiErrorRecognizerInactive,
		SapiErrorRemoteCallOnWrongThread,
		SapiErrorRemoteProcessTerminated,
		SapiErrorRemoteProcessAlreadyRunning,
		SapiErrorLangIdMismatch,
		SapiErrorPartialParseFound,
		SapiErrorNotTopLevelRule,
		SapiErrorNoRuleActive,
		SapiErrorLexRequiresCookie,
		SapiErrorStreamUninitialized,
		SapiErrorUnused0,
		SapiErrorNotSupportedLang,
		SapiErrorVoicePaused,
		SapiErrorAudioBufferUnderflow,
		SapiErrorAudioStoppedUnexpectedly,
		SapiErrorNoWordPronunciation,
		SapiErrorAlternatesWouldBeInconsistent,
		SapiErrorNotSupportedForSharedRecognizer,
		SapiErrorTimeOut,
		SapiErrorReenterSynchronize,
		SapiErrorStateWithNoArcs,
		SapiErrorNotActiveSession,
		SapiErrorAlreadyDeleted,
		SapiErrorAudioStopped,
		SapiErrorRecoXMLGenerationFail,
		SapiErrorSMLGenerationFail,
		SapiErrorNotPromptVoice,
		SapiErrorRootRuleAlreadyDefined,
		SapiErrorUnused1,
		SapiErrorUnused2,
		SapiErrorUnused3,
		SapiErrorUnused4,
		SapiErrorUnused5,
		SapiErrorUnused6,
		SapiErrorScriptDisallowed,
		SapiErrorRemoteCallTimedOutStart,
		SapiErrorRemoteCallTimedOutConnect,
		SapiErrorSecMgrChangeNotAllowed,
		SapiErrorCompleteButExtendable,
		SapiErrorFailedToDeleteFile,
		SapiErrorSharedEngineDisabled,
		SapiErrorRecognizerNotFound,
		SapiErrorAudioNotFound,
		SapiErrorNoVowel,
		SapiErrorNotSupportedPhoneme,
		SapiErrorNoRulesToActivate,
		SapiErrorNoWordEntryNotification,
		SapiErrorWordNeedsNormalization,
		SapiErrorCannotNormalize,
		LimitReached,
		NotSupported,
		SapiErrorTopicNotAdaptable,
		SapiErrorPhonemeConversion,
		SapiErrorNotSupportedForInprocRecognizer,
		SapiErrorOverload,
		SapiLexInvalidData,
		SapiConfigInvalidData,
		SapiLexUnexpectedFormat,
		SapiStringTooLong,
		SapiStringEmpty,
		SapiErrorUnused7,
		SapiErrorUnused8,
		SapiErrorUnused9,
		SapiErrorUnused10,
		SapiErrorUnused11,
		SapiErrorUnused12,
		SapiNonWordTransition,
		SapiSisrAttributesNotAllowed,
		SapiSisrMixedNotAllowed,
		SapiVoiceNotFound
	}
}
namespace System.Speech.Synthesis
{
	public class BookmarkReachedEventArgs : PromptEventArgs
	{
		private string _bookmark;

		private TimeSpan _audioPosition;

		public string Bookmark => _bookmark;

		public TimeSpan AudioPosition => _audioPosition;

		internal BookmarkReachedEventArgs(Prompt prompt, string bookmark, TimeSpan audioPosition)
			: base(prompt)
		{
			_bookmark = bookmark;
			_audioPosition = audioPosition;
		}
	}
	[DebuggerDisplay("{_text}")]
	public class FilePrompt : Prompt
	{
		public FilePrompt(string path, SynthesisMediaType media)
			: this(new Uri(path, UriKind.Relative), media)
		{
		}

		public FilePrompt(Uri promptFile, SynthesisMediaType media)
			: base(promptFile, media)
		{
		}
	}
	[DebuggerDisplay("{VoiceInfo.Name} = [{Enabled ? \"Enabled\" : \"Disabled\"}]")]
	public class InstalledVoice
	{
		private VoiceInfo _voice;

		private bool _enabled;

		private VoiceSynthesis _voiceSynthesizer;

		public VoiceInfo VoiceInfo => _voice;

		public bool Enabled
		{
			get
			{
				return _enabled;
			}
			set
			{
				SetEnabledFlag(value, switchContext: true);
			}
		}

		internal InstalledVoice(VoiceSynthesis voiceSynthesizer, VoiceInfo voice)
		{
			_voiceSynthesizer = voiceSynthesizer;
			_voice = voice;
			_enabled = true;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is InstalledVoice installedVoice))
			{
				return false;
			}
			if (VoiceInfo.Name == installedVoice.VoiceInfo.Name && VoiceInfo.Age == installedVoice.VoiceInfo.Age && VoiceInfo.Gender == installedVoice.VoiceInfo.Gender)
			{
				return VoiceInfo.Culture.Equals(installedVoice.VoiceInfo.Culture);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return VoiceInfo.Name.GetHashCode();
		}

		internal static InstalledVoice Find(List<InstalledVoice> list, VoiceInfo voiceId)
		{
			foreach (InstalledVoice item in list)
			{
				if (item.Enabled && item.VoiceInfo.Equals(voiceId))
				{
					return item;
				}
			}
			return null;
		}

		internal static InstalledVoice FirstEnabled(List<InstalledVoice> list, CultureInfo culture)
		{
			InstalledVoice installedVoice = null;
			foreach (InstalledVoice item in list)
			{
				if (item.Enabled)
				{
					if (Helpers.CompareInvariantCulture(item.VoiceInfo.Culture, culture))
					{
						return item;
					}
					if (installedVoice == null)
					{
						installedVoice = item;
					}
				}
			}
			return installedVoice;
		}

		internal void SetEnabledFlag(bool value, bool switchContext)
		{
			try
			{
				if (_enabled == value)
				{
					return;
				}
				_enabled = value;
				if (!_enabled)
				{
					if (_voice.Equals(_voiceSynthesizer.CurrentVoice(switchContext).VoiceInfo))
					{
						_voiceSynthesizer.Voice = null;
					}
				}
				else
				{
					_voiceSynthesizer.Voice = null;
				}
			}
			catch (InvalidOperationException)
			{
				_voiceSynthesizer.Voice = null;
			}
		}
	}
	public class PhonemeReachedEventArgs : PromptEventArgs
	{
		private string _currentPhoneme;

		private TimeSpan _audioPosition;

		private TimeSpan _duration;

		private SynthesizerEmphasis _emphasis;

		private string _nextPhoneme;

		public string Phoneme => _currentPhoneme;

		public TimeSpan AudioPosition => _audioPosition;

		public TimeSpan Duration => _duration;

		public SynthesizerEmphasis Emphasis => _emphasis;

		public string NextPhoneme => _nextPhoneme;

		internal PhonemeReachedEventArgs(Prompt prompt, string currentPhoneme, TimeSpan audioPosition, TimeSpan duration, SynthesizerEmphasis emphasis, string nextPhoneme)
			: base(prompt)
		{
			_currentPhoneme = currentPhoneme;
			_audioPosition = audioPosition;
			_duration = duration;
			_emphasis = emphasis;
			_nextPhoneme = nextPhoneme;
		}
	}
	[DebuggerDisplay("{_text}")]
	public class Prompt
	{
		internal string _text;

		internal Uri _audio;

		internal SynthesisMediaType _media;

		internal bool _syncSpeak;

		private bool _completed;

		private object _synthesizer;

		private static ResourceLoader s_resourceLoader = new ResourceLoader();

		public bool IsCompleted
		{
			get
			{
				return _completed;
			}
			internal set
			{
				_completed = value;
			}
		}

		internal object Synthesizer
		{
			set
			{
				if (value != null && (_synthesizer != null || _completed))
				{
					throw new ArgumentException(SR.Get(SRID.SynthesizerPromptInUse), "value");
				}
				_synthesizer = value;
			}
		}

		internal Exception Exception { get; set; }

		public Prompt(string textToSpeak)
			: this(textToSpeak, SynthesisTextFormat.Text)
		{
		}

		public Prompt(PromptBuilder promptBuilder)
		{
			Helpers.ThrowIfNull(promptBuilder, "promptBuilder");
			_text = promptBuilder.ToXml();
			_media = SynthesisMediaType.Ssml;
		}

		public Prompt(string textToSpeak, SynthesisTextFormat media)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			if ((uint)(_media = (SynthesisMediaType)media) <= 1u)
			{
				_text = textToSpeak;
				return;
			}
			throw new ArgumentException(SR.Get(SRID.SynthesizerUnknownMediaType), "media");
		}

		internal Prompt(Uri promptFile, SynthesisMediaType media)
		{
			Helpers.ThrowIfNull(promptFile, "promptFile");
			switch (_media = media)
			{
			case SynthesisMediaType.Text:
			case SynthesisMediaType.Ssml:
			{
				string mimeType;
				Uri baseUri;
				string localPath;
				using Stream stream = s_resourceLoader.LoadFile(promptFile, out mimeType, out baseUri, out localPath);
				try
				{
					using StreamReader streamReader = new StreamReader(stream);
					_text = streamReader.ReadToEnd();
					break;
				}
				finally
				{
					s_resourceLoader.UnloadFile(localPath);
				}
			}
			case SynthesisMediaType.WaveAudio:
				_text = promptFile.ToString();
				_audio = promptFile;
				break;
			default:
				throw new ArgumentException(SR.Get(SRID.SynthesizerUnknownMediaType), "media");
			}
		}
	}
	public enum SynthesisMediaType
	{
		Text,
		Ssml,
		WaveAudio
	}
	public enum SynthesisTextFormat
	{
		Text,
		Ssml
	}
	[Serializable]
	public class PromptBuilder
	{
		internal enum SsmlState
		{
			Header = 1,
			Paragraph = 2,
			Sentence = 4,
			StyleEmphasis = 8,
			StyleProsody = 0x10,
			Voice = 0x20,
			Ended = 0x40
		}

		[Serializable]
		private struct StackElement
		{
			internal SsmlElement _possibleChildren;

			internal SsmlState _state;

			internal CultureInfo _culture;

			internal StackElement(SsmlElement possibleChildren, SsmlState state, CultureInfo culture)
			{
				_possibleChildren = possibleChildren;
				_state = state;
				_culture = culture;
			}
		}

		private enum ElementType
		{
			Prosody,
			Emphasis,
			SayAs,
			Phoneme,
			Sub,
			Break,
			Audio,
			Bookmark,
			StartVoice,
			StartParagraph,
			StartSentence,
			EndSentence,
			EndParagraph,
			StartStyle,
			EndStyle,
			EndVoice,
			Text,
			SsmlMarkup
		}

		[Serializable]
		private struct AttributeItem
		{
			internal string _key;

			internal string _value;

			internal string _namespace;

			internal AttributeItem(string key, string value)
			{
				_key = key;
				_value = value;
				_namespace = null;
			}

			internal AttributeItem(string ns, string key, string value)
				: this(key, value)
			{
				_namespace = ns;
			}
		}

		[Serializable]
		private sealed class Element
		{
			internal ElementType _type;

			internal string _text;

			internal Collection<AttributeItem> _attributes;

			internal Element(ElementType type)
			{
				_type = type;
			}

			internal Element(ElementType type, string text)
				: this(type)
			{
				_text = text;
			}
		}

		private Stack<StackElement> _elementStack = new Stack<StackElement>();

		private CultureInfo _culture;

		private List<Element> _elements = new List<Element>();

		private static ResourceLoader s_resourceLoader = new ResourceLoader();

		private const string _xmlnsDefault = "http://www.w3.org/2001/10/synthesis";

		private static readonly string[] s_promptBuilderElementName = new string[11]
		{
			"prosody", "emphasis", "say-as", "phoneme", "sub", "break", "audio", "mark", "voice", "p",
			"s"
		};

		public bool IsEmpty => _elements.Count == 0;

		public CultureInfo Culture
		{
			get
			{
				return _culture;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value");
				}
				_culture = value;
			}
		}

		public PromptBuilder()
			: this(CultureInfo.CurrentUICulture)
		{
		}

		public PromptBuilder(CultureInfo culture)
		{
			Helpers.ThrowIfNull(culture, "culture");
			if (culture.Equals(CultureInfo.InvariantCulture))
			{
				throw new ArgumentException(SR.Get(SRID.InvariantCultureInfo), "culture");
			}
			_culture = culture;
			ClearContent();
		}

		public void ClearContent()
		{
			_elements.Clear();
			_elementStack.Push(new StackElement(SsmlElement.AudioMarkTextWithStyle | SsmlElement.ParagraphOrSentence | SsmlElement.Lexicon | SsmlElement.Meta | SsmlElement.MetaData, SsmlState.Header, _culture));
		}

		public void AppendText(string textToSpeak)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			_elements.Add(new Element(ElementType.Text, textToSpeak));
		}

		public void AppendText(string textToSpeak, PromptRate rate)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			if (rate < PromptRate.NotSet || rate > PromptRate.ExtraSlow)
			{
				throw new ArgumentOutOfRangeException("rate");
			}
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			Element element = new Element(ElementType.Prosody, textToSpeak);
			_elements.Add(element);
			string value = null;
			switch (rate)
			{
			case PromptRate.ExtraFast:
				value = "x-fast";
				break;
			case PromptRate.ExtraSlow:
				value = "x-slow";
				break;
			default:
				value = rate.ToString().ToLowerInvariant();
				break;
			case PromptRate.NotSet:
				break;
			}
			if (!string.IsNullOrEmpty(value))
			{
				element._attributes = new Collection<AttributeItem>();
				element._attributes.Add(new AttributeItem("rate", value));
			}
		}

		public void AppendText(string textToSpeak, PromptVolume volume)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			if (volume < PromptVolume.NotSet || volume > PromptVolume.Default)
			{
				throw new ArgumentOutOfRangeException("volume");
			}
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			Element element = new Element(ElementType.Prosody, textToSpeak);
			_elements.Add(element);
			string value = null;
			switch (volume)
			{
			case PromptVolume.ExtraSoft:
				value = "x-soft";
				break;
			case PromptVolume.ExtraLoud:
				value = "x-loud";
				break;
			default:
				value = volume.ToString().ToLowerInvariant();
				break;
			case PromptVolume.NotSet:
				break;
			}
			if (!string.IsNullOrEmpty(value))
			{
				element._attributes = new Collection<AttributeItem>();
				element._attributes.Add(new AttributeItem("volume", value));
			}
		}

		public void AppendText(string textToSpeak, PromptEmphasis emphasis)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			if (emphasis < PromptEmphasis.NotSet || emphasis > PromptEmphasis.Reduced)
			{
				throw new ArgumentOutOfRangeException("emphasis");
			}
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			Element element = new Element(ElementType.Emphasis, textToSpeak);
			_elements.Add(element);
			if (emphasis != 0)
			{
				element._attributes = new Collection<AttributeItem>();
				element._attributes.Add(new AttributeItem("level", emphasis.ToString().ToLowerInvariant()));
			}
		}

		public void StartStyle(PromptStyle style)
		{
			Helpers.ThrowIfNull(style, "style");
			StackElement stackElement = _elementStack.Peek();
			ValidateElement(stackElement, SsmlElement.Prosody);
			SsmlState ssmlState = (SsmlState)0;
			SsmlElement possibleChildren = stackElement._possibleChildren;
			_elements.Add(new Element(ElementType.StartStyle));
			if (style.Emphasis != 0)
			{
				Element element = new Element(ElementType.Emphasis);
				_elements.Add(element);
				element._attributes = new Collection<AttributeItem>();
				element._attributes.Add(new AttributeItem("level", style.Emphasis.ToString().ToLowerInvariant()));
				possibleChildren = SsmlElement.AudioMarkTextWithStyle;
				ssmlState = SsmlState.StyleEmphasis;
			}
			if (style.Rate != 0 || style.Volume != 0)
			{
				if (ssmlState != 0)
				{
					_elements.Add(new Element(ElementType.StartStyle));
				}
				Element element2 = new Element(ElementType.Prosody);
				_elements.Add(element2);
				if (style.Rate != 0)
				{
					string value = style.Rate switch
					{
						PromptRate.ExtraFast => "x-fast", 
						PromptRate.ExtraSlow => "x-slow", 
						_ => style.Rate.ToString().ToLowerInvariant(), 
					};
					element2._attributes = new Collection<AttributeItem>();
					element2._attributes.Add(new AttributeItem("rate", value));
				}
				if (style.Volume != 0)
				{
					string value2 = style.Volume switch
					{
						PromptVolume.ExtraSoft => "x-soft", 
						PromptVolume.ExtraLoud => "x-loud", 
						_ => style.Volume.ToString().ToLowerInvariant(), 
					};
					Element element3 = element2;
					if (element3._attributes == null)
					{
						element3._attributes = new Collection<AttributeItem>();
					}
					element2._attributes.Add(new AttributeItem("volume", value2));
				}
				possibleChildren = SsmlElement.AudioMarkTextWithStyle | SsmlElement.ParagraphOrSentence;
				ssmlState |= SsmlState.StyleProsody;
			}
			_elementStack.Push(new StackElement(possibleChildren, ssmlState, stackElement._culture));
		}

		public void EndStyle()
		{
			StackElement stackElement = _elementStack.Pop();
			if (stackElement._state != 0)
			{
				if ((stackElement._state & (SsmlState)24) == 0)
				{
					throw new InvalidOperationException(SR.Get(SRID.PromptBuilderMismatchStyle));
				}
				_elements.Add(new Element(ElementType.EndStyle));
				if (stackElement._state == (SsmlState)24)
				{
					_elements.Add(new Element(ElementType.EndStyle));
				}
			}
		}

		public void StartVoice(VoiceInfo voice)
		{
			Helpers.ThrowIfNull(voice, "voice");
			if (!VoiceInfo.ValidateGender(voice.Gender))
			{
				throw new ArgumentException(SR.Get(SRID.EnumInvalid, "VoiceGender"), "voice");
			}
			if (!VoiceInfo.ValidateAge(voice.Age))
			{
				throw new ArgumentException(SR.Get(SRID.EnumInvalid, "VoiceAge"), "voice");
			}
			StackElement stackElement = _elementStack.Peek();
			ValidateElement(stackElement, SsmlElement.Voice);
			CultureInfo culture = voice.Culture ?? stackElement._culture;
			Element element = new Element(ElementType.StartVoice);
			element._attributes = new Collection<AttributeItem>();
			_elements.Add(element);
			if (!string.IsNullOrEmpty(voice.Name))
			{
				element._attributes.Add(new AttributeItem("name", voice.Name));
			}
			if (voice.Culture != null)
			{
				element._attributes.Add(new AttributeItem("xml", "lang", voice.Culture.Name));
			}
			if (voice.Gender != 0)
			{
				element._attributes.Add(new AttributeItem("gender", voice.Gender.ToString().ToLowerInvariant()));
			}
			if (voice.Age != 0)
			{
				element._attributes.Add(new AttributeItem("age", ((int)voice.Age).ToString(CultureInfo.InvariantCulture)));
			}
			if (voice.Variant >= 0)
			{
				element._attributes.Add(new AttributeItem("variant", voice.Variant.ToString(CultureInfo.InvariantCulture)));
			}
			_elementStack.Push(new StackElement(SsmlElement.AudioMarkTextWithStyle | SsmlElement.Sentence, SsmlState.Voice, culture));
		}

		public void StartVoice(string name)
		{
			Helpers.ThrowIfEmptyOrNull(name, "name");
			StartVoice(new VoiceInfo(name));
		}

		public void StartVoice(VoiceGender gender)
		{
			StartVoice(new VoiceInfo(gender));
		}

		public void StartVoice(VoiceGender gender, VoiceAge age)
		{
			StartVoice(new VoiceInfo(gender, age));
		}

		public void StartVoice(VoiceGender gender, VoiceAge age, int voiceAlternate)
		{
			StartVoice(new VoiceInfo(gender, age, voiceAlternate));
		}

		public void StartVoice(CultureInfo culture)
		{
			StartVoice(new VoiceInfo(culture));
		}

		public void EndVoice()
		{
			if (_elementStack.Pop()._state != SsmlState.Voice)
			{
				throw new InvalidOperationException(SR.Get(SRID.PromptBuilderMismatchVoice));
			}
			_elements.Add(new Element(ElementType.EndVoice));
		}

		public void StartParagraph()
		{
			StartParagraph(null);
		}

		public void StartParagraph(CultureInfo culture)
		{
			StackElement stackElement = _elementStack.Peek();
			ValidateElement(stackElement, SsmlElement.Paragraph);
			Element element = new Element(ElementType.StartParagraph);
			_elements.Add(element);
			if (culture != null)
			{
				if (culture.Equals(CultureInfo.InvariantCulture))
				{
					throw new ArgumentException(SR.Get(SRID.InvariantCultureInfo), "culture");
				}
				element._attributes = new Collection<AttributeItem>();
				element._attributes.Add(new AttributeItem("xml", "lang", culture.Name));
			}
			else
			{
				culture = stackElement._culture;
			}
			_elementStack.Push(new StackElement(SsmlElement.AudioMarkTextWithStyle | SsmlElement.Sentence, SsmlState.Paragraph, culture));
		}

		public void EndParagraph()
		{
			if (_elementStack.Pop()._state != SsmlState.Paragraph)
			{
				throw new InvalidOperationException(SR.Get(SRID.PromptBuilderMismatchParagraph));
			}
			_elements.Add(new Element(ElementType.EndParagraph));
		}

		public void StartSentence()
		{
			StartSentence(null);
		}

		public void StartSentence(CultureInfo culture)
		{
			StackElement stackElement = _elementStack.Peek();
			ValidateElement(stackElement, SsmlElement.Sentence);
			Element element = new Element(ElementType.StartSentence);
			_elements.Add(element);
			if (culture != null)
			{
				if (culture.Equals(CultureInfo.InvariantCulture))
				{
					throw new ArgumentException(SR.Get(SRID.InvariantCultureInfo), "culture");
				}
				element._attributes = new Collection<AttributeItem>();
				element._attributes.Add(new AttributeItem("xml", "lang", culture.Name));
			}
			else
			{
				culture = stackElement._culture;
			}
			_elementStack.Push(new StackElement(SsmlElement.AudioMarkTextWithStyle, SsmlState.Sentence, culture));
		}

		public void EndSentence()
		{
			if (_elementStack.Pop()._state != SsmlState.Sentence)
			{
				throw new InvalidOperationException(SR.Get(SRID.PromptBuilderMismatchSentence));
			}
			_elements.Add(new Element(ElementType.EndSentence));
		}

		public void AppendTextWithHint(string textToSpeak, SayAs sayAs)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			if (sayAs < SayAs.SpellOut || sayAs > SayAs.Text)
			{
				throw new ArgumentOutOfRangeException("sayAs");
			}
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			if (sayAs != SayAs.Text)
			{
				Element element = new Element(ElementType.SayAs, textToSpeak);
				_elements.Add(element);
				element._attributes = new Collection<AttributeItem>();
				string value = null;
				string value2 = null;
				switch (sayAs)
				{
				case SayAs.SpellOut:
					value = "characters";
					break;
				case SayAs.NumberOrdinal:
					value = "ordinal";
					break;
				case SayAs.NumberCardinal:
					value = "cardinal";
					break;
				case SayAs.Date:
					value = "date";
					break;
				case SayAs.DayMonthYear:
					value = "date";
					value2 = "dmy";
					break;
				case SayAs.MonthDayYear:
					value = "date";
					value2 = "mdy";
					break;
				case SayAs.YearMonthDay:
					value = "date";
					value2 = "ymd";
					break;
				case SayAs.YearMonth:
					value = "date";
					value2 = "ym";
					break;
				case SayAs.MonthYear:
					value = "date";
					value2 = "my";
					break;
				case SayAs.MonthDay:
					value = "date";
					value2 = "md";
					break;
				case SayAs.DayMonth:
					value = "date";
					value2 = "dm";
					break;
				case SayAs.Year:
					value = "date";
					value2 = "y";
					break;
				case SayAs.Month:
					value = "date";
					value2 = "m";
					break;
				case SayAs.Day:
					value = "date";
					value2 = "d";
					break;
				case SayAs.Time:
					value = "time";
					break;
				case SayAs.Time24:
					value = "time";
					value2 = "hms24";
					break;
				case SayAs.Time12:
					value = "time";
					value2 = "hms12";
					break;
				case SayAs.Telephone:
					value = "telephone";
					break;
				}
				element._attributes.Add(new AttributeItem("interpret-as", value));
				if (!string.IsNullOrEmpty(value2))
				{
					element._attributes.Add(new AttributeItem("format", value2));
				}
			}
			else
			{
				AppendText(textToSpeak);
			}
		}

		public void AppendTextWithHint(string textToSpeak, string sayAs)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			Helpers.ThrowIfEmptyOrNull(sayAs, "sayAs");
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			Element element = new Element(ElementType.SayAs, textToSpeak);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("interpret-as", sayAs));
		}

		public void AppendTextWithPronunciation(string textToSpeak, string pronunciation)
		{
			Helpers.ThrowIfEmptyOrNull(textToSpeak, "textToSpeak");
			Helpers.ThrowIfEmptyOrNull(pronunciation, "pronunciation");
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			PhonemeConverter.ValidateUpsIds(pronunciation);
			Element element = new Element(ElementType.Phoneme, textToSpeak);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("ph", pronunciation));
		}

		public void AppendTextWithAlias(string textToSpeak, string substitute)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			Helpers.ThrowIfNull(substitute, "substitute");
			ValidateElement(_elementStack.Peek(), SsmlElement.Text);
			Element element = new Element(ElementType.Sub, textToSpeak);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("alias", substitute));
		}

		public void AppendBreak()
		{
			ValidateElement(_elementStack.Peek(), SsmlElement.Break);
			_elements.Add(new Element(ElementType.Break));
		}

		public void AppendBreak(PromptBreak strength)
		{
			ValidateElement(_elementStack.Peek(), SsmlElement.Break);
			Element element = new Element(ElementType.Break);
			_elements.Add(element);
			string text = null;
			text = strength switch
			{
				PromptBreak.None => "none", 
				PromptBreak.ExtraSmall => "x-weak", 
				PromptBreak.Small => "weak", 
				PromptBreak.Medium => "medium", 
				PromptBreak.Large => "strong", 
				PromptBreak.ExtraLarge => "x-strong", 
				_ => throw new ArgumentNullException("strength"), 
			};
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("strength", text));
		}

		public void AppendBreak(TimeSpan duration)
		{
			ValidateElement(_elementStack.Peek(), SsmlElement.Break);
			if (duration.Ticks < 0)
			{
				throw new ArgumentOutOfRangeException("duration");
			}
			Element element = new Element(ElementType.Break);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("time", duration.TotalMilliseconds + "ms"));
		}

		public void AppendAudio(string path)
		{
			Helpers.ThrowIfEmptyOrNull(path, "path");
			Uri audioFile;
			try
			{
				audioFile = new Uri(path, UriKind.RelativeOrAbsolute);
			}
			catch (UriFormatException ex)
			{
				throw new ArgumentException(ex.Message, path, ex);
			}
			ValidateElement(_elementStack.Peek(), SsmlElement.Audio);
			AppendAudio(audioFile);
		}

		public void AppendAudio(Uri audioFile)
		{
			Helpers.ThrowIfNull(audioFile, "audioFile");
			ValidateElement(_elementStack.Peek(), SsmlElement.Audio);
			Element element = new Element(ElementType.Audio);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("src", audioFile.ToString()));
		}

		public void AppendAudio(Uri audioFile, string alternateText)
		{
			Helpers.ThrowIfNull(audioFile, "audioFile");
			Helpers.ThrowIfNull(alternateText, "alternateText");
			ValidateElement(_elementStack.Peek(), SsmlElement.Audio);
			Element element = new Element(ElementType.Audio, alternateText);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("src", audioFile.ToString()));
		}

		public void AppendBookmark(string bookmarkName)
		{
			Helpers.ThrowIfEmptyOrNull(bookmarkName, "bookmarkName");
			ValidateElement(_elementStack.Peek(), SsmlElement.Mark);
			Element element = new Element(ElementType.Bookmark);
			_elements.Add(element);
			element._attributes = new Collection<AttributeItem>();
			element._attributes.Add(new AttributeItem("name", bookmarkName));
		}

		public void AppendPromptBuilder(PromptBuilder promptBuilder)
		{
			Helpers.ThrowIfNull(promptBuilder, "promptBuilder");
			StringReader stringReader = new StringReader(promptBuilder.ToXml());
			XmlTextReader xmlTextReader = new XmlTextReader(stringReader);
			AppendSsml(xmlTextReader);
			xmlTextReader.Close();
			stringReader.Close();
		}

		public void AppendSsml(string path)
		{
			Helpers.ThrowIfEmptyOrNull(path, "path");
			AppendSsml(new Uri(path, UriKind.Relative));
		}

		public void AppendSsml(Uri ssmlFile)
		{
			Helpers.ThrowIfNull(ssmlFile, "ssmlFile");
			string localPath;
			Uri redirectedUri;
			using Stream input = s_resourceLoader.LoadFile(ssmlFile, out localPath, out redirectedUri);
			try
			{
				AppendSsml(new XmlTextReader(input));
			}
			finally
			{
				s_resourceLoader.UnloadFile(localPath);
			}
		}

		public void AppendSsml(XmlReader ssmlFile)
		{
			Helpers.ThrowIfNull(ssmlFile, "ssmlFile");
			AppendSsmlInternal(ssmlFile);
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public void AppendSsmlMarkup(string ssmlMarkup)
		{
			Helpers.ThrowIfEmptyOrNull(ssmlMarkup, "ssmlMarkup");
			_elements.Add(new Element(ElementType.SsmlMarkup, ssmlMarkup));
		}

		public string ToXml()
		{
			using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
			using XmlTextWriter writer = new XmlTextWriter(stringWriter);
			WriteXml(writer);
			SsmlState state = _elementStack.Peek()._state;
			if (state != SsmlState.Header)
			{
				string text = SR.Get(SRID.PromptBuilderInvalideState);
				switch (state)
				{
				case SsmlState.Ended:
					text += SR.Get(SRID.PromptBuilderStateEnded);
					break;
				case SsmlState.Sentence:
					text += SR.Get(SRID.PromptBuilderStateSentence);
					break;
				case SsmlState.Paragraph:
					text += SR.Get(SRID.PromptBuilderStateParagraph);
					break;
				case SsmlState.StyleEmphasis:
				case SsmlState.StyleProsody:
				case (SsmlState)24:
					text += SR.Get(SRID.PromptBuilderStateStyle);
					break;
				case SsmlState.Voice:
					text += SR.Get(SRID.PromptBuilderStateVoice);
					break;
				default:
					throw new NotSupportedException();
				}
				throw new InvalidOperationException(text);
			}
			return stringWriter.ToString();
		}

		private void WriteXml(XmlTextWriter writer)
		{
			writer.WriteStartElement("speak");
			writer.WriteAttributeString("version", "1.0");
			writer.WriteAttributeString("xmlns", "http://www.w3.org/2001/10/synthesis");
			writer.WriteAttributeString("xml", "lang", null, _culture.Name);
			bool flag = false;
			foreach (Element element in _elements)
			{
				flag = flag || element._type == ElementType.StartSentence || element._type == ElementType.StartParagraph || element._type == ElementType.StartStyle || element._type == ElementType.StartVoice;
				switch (element._type)
				{
				case ElementType.Text:
					writer.WriteString(element._text);
					break;
				case ElementType.SsmlMarkup:
					writer.WriteRaw(element._text);
					break;
				case ElementType.Prosody:
				case ElementType.Emphasis:
				case ElementType.SayAs:
				case ElementType.Phoneme:
				case ElementType.Sub:
				case ElementType.Break:
				case ElementType.Audio:
				case ElementType.Bookmark:
				case ElementType.StartVoice:
				case ElementType.StartParagraph:
				case ElementType.StartSentence:
					writer.WriteStartElement(s_promptBuilderElementName[(int)element._type]);
					if (element._attributes != null)
					{
						foreach (AttributeItem attribute in element._attributes)
						{
							if (attribute._namespace == null)
							{
								writer.WriteAttributeString(attribute._key, attribute._value);
							}
							else
							{
								writer.WriteAttributeString(attribute._namespace, attribute._key, null, attribute._value);
							}
						}
					}
					if (element._text != null)
					{
						writer.WriteString(element._text);
					}
					if (!flag)
					{
						writer.WriteEndElement();
					}
					flag = false;
					break;
				case ElementType.EndSentence:
				case ElementType.EndParagraph:
				case ElementType.EndStyle:
				case ElementType.EndVoice:
					writer.WriteEndElement();
					break;
				default:
					throw new NotSupportedException();
				case ElementType.StartStyle:
					break;
				}
			}
			writer.WriteEndElement();
		}

		private static void ValidateElement(StackElement stackElement, SsmlElement currentElement)
		{
			if ((stackElement._possibleChildren & currentElement) == 0)
			{
				throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, SR.Get(SRID.PromptBuilderInvalidElement), currentElement.ToString(), stackElement._state.ToString()));
			}
		}

		private void AppendSsmlInternal(XmlReader ssmlFile)
		{
			StackElement stackElement = _elementStack.Peek();
			ValidateElement(_elementStack.Peek(), SsmlElement.Voice);
			using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
			using (XmlTextWriter writer = new XmlTextWriter(stringWriter))
			{
				TextWriterEngine engine = new TextWriterEngine(writer, stackElement._culture);
				SsmlParser.Parse(ssmlFile, engine, null);
			}
			_elements.Add(new Element(ElementType.SsmlMarkup, stringWriter.ToString()));
		}
	}
	public abstract class PromptEventArgs : AsyncCompletedEventArgs
	{
		private Prompt _prompt;

		public Prompt Prompt => _prompt;

		internal PromptEventArgs(Prompt prompt)
			: base(prompt.Exception, prompt.Exception != null, prompt)
		{
			_prompt = prompt;
		}
	}
	public class SpeakStartedEventArgs : PromptEventArgs
	{
		internal SpeakStartedEventArgs(Prompt prompt)
			: base(prompt)
		{
		}
	}
	[Serializable]
	public class PromptStyle
	{
		private PromptRate _rate;

		private PromptVolume _volume;

		private PromptEmphasis _emphasis;

		public PromptRate Rate
		{
			get
			{
				return _rate;
			}
			set
			{
				_rate = value;
			}
		}

		public PromptVolume Volume
		{
			get
			{
				return _volume;
			}
			set
			{
				_volume = value;
			}
		}

		public PromptEmphasis Emphasis
		{
			get
			{
				return _emphasis;
			}
			set
			{
				_emphasis = value;
			}
		}

		public PromptStyle()
		{
		}

		public PromptStyle(PromptRate rate)
		{
			Rate = rate;
		}

		public PromptStyle(PromptVolume volume)
		{
			Volume = volume;
		}

		public PromptStyle(PromptEmphasis emphasis)
		{
			Emphasis = emphasis;
		}
	}
	public enum SayAs
	{
		SpellOut,
		NumberOrdinal,
		NumberCardinal,
		Date,
		DayMonthYear,
		MonthDayYear,
		YearMonthDay,
		YearMonth,
		MonthYear,
		MonthDay,
		DayMonth,
		Year,
		Month,
		Day,
		Time,
		Time24,
		Time12,
		Telephone,
		Text
	}
	public enum VoiceGender
	{
		NotSet,
		Male,
		Female,
		Neutral
	}
	public enum VoiceAge
	{
		NotSet = 0,
		Child = 10,
		Teen = 15,
		Adult = 30,
		Senior = 65
	}
	public enum PromptRate
	{
		NotSet,
		ExtraFast,
		Fast,
		Medium,
		Slow,
		ExtraSlow
	}
	public enum PromptVolume
	{
		NotSet,
		Silent,
		ExtraSoft,
		Soft,
		Medium,
		Loud,
		ExtraLoud,
		Default
	}
	public enum PromptEmphasis
	{
		NotSet,
		Strong,
		Moderate,
		None,
		Reduced
	}
	public enum PromptBreak
	{
		None,
		ExtraSmall,
		Small,
		Medium,
		Large,
		ExtraLarge
	}
	public class SpeakCompletedEventArgs : PromptEventArgs
	{
		internal SpeakCompletedEventArgs(Prompt prompt)
			: base(prompt)
		{
		}
	}
	public class SpeakProgressEventArgs : PromptEventArgs
	{
		private TimeSpan _audioPosition;

		private int _iWordPos;

		private int _cWordLen;

		private string _word;

		public TimeSpan AudioPosition => _audioPosition;

		public int CharacterPosition => _iWordPos;

		public int CharacterCount
		{
			get
			{
				return _cWordLen;
			}
			internal set
			{
				_cWordLen = value;
			}
		}

		public string Text
		{
			get
			{
				return _word;
			}
			internal set
			{
				_word = value;
			}
		}

		internal SpeakProgressEventArgs(Prompt prompt, TimeSpan audioPosition, int iWordPos, int cWordLen)
			: base(prompt)
		{
			_audioPosition = audioPosition;
			_iWordPos = iWordPos;
			_cWordLen = cWordLen;
		}
	}
	public sealed class SpeechSynthesizer : IDisposable
	{
		private VoiceSynthesis _voiceSynthesis;

		private bool _isDisposed;

		private bool _paused;

		private Stream _outputStream;

		private bool _closeStreamOnExit;

		public SynthesizerState State => VoiceSynthesizer.State;

		public int Rate
		{
			get
			{
				return VoiceSynthesizer.Rate;
			}
			set
			{
				if (value < -10 || value > 10)
				{
					throw new ArgumentOutOfRangeException("value", SR.Get(SRID.RateOutOfRange));
				}
				VoiceSynthesizer.Rate = value;
			}
		}

		public int Volume
		{
			get
			{
				return VoiceSynthesizer.Volume;
			}
			set
			{
				if (value < 0 || value > 100)
				{
					throw new ArgumentOutOfRangeException("value", SR.Get(SRID.ResourceUsageOutOfRange));
				}
				VoiceSynthesizer.Volume = value;
			}
		}

		public VoiceInfo Voice => VoiceSynthesizer.CurrentVoice(switchContext: true).VoiceInfo;

		private VoiceSynthesis VoiceSynthesizer
		{
			get
			{
				if (_voiceSynthesis == null && _isDisposed)
				{
					throw new ObjectDisposedException("SpeechSynthesizer");
				}
				if (_voiceSynthesis == null)
				{
					WeakReference speechSynthesizer = new WeakReference(this);
					_voiceSynthesis = new VoiceSynthesis(speechSynthesizer);
				}
				return _voiceSynthesis;
			}
		}

		public event EventHandler<SpeakStartedEventArgs> SpeakStarted
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesis voiceSynthesizer = VoiceSynthesizer;
				voiceSynthesizer._speakStarted = (EventHandler<SpeakStartedEventArgs>)Delegate.Combine(voiceSynthesizer._speakStarted, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesis voiceSynthesizer = VoiceSynthesizer;
				voiceSynthesizer._speakStarted = (EventHandler<SpeakStartedEventArgs>)Delegate.Remove(voiceSynthesizer._speakStarted, value);
			}
		}

		public event EventHandler<SpeakCompletedEventArgs> SpeakCompleted
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesis voiceSynthesizer = VoiceSynthesizer;
				voiceSynthesizer._speakCompleted = (EventHandler<SpeakCompletedEventArgs>)Delegate.Combine(voiceSynthesizer._speakCompleted, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesis voiceSynthesizer = VoiceSynthesizer;
				voiceSynthesizer._speakCompleted = (EventHandler<SpeakCompletedEventArgs>)Delegate.Remove(voiceSynthesizer._speakCompleted, value);
			}
		}

		public event EventHandler<SpeakProgressEventArgs> SpeakProgress
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.AddEvent(TtsEventId.WordBoundary, ref VoiceSynthesizer._speakProgress, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.RemoveEvent(TtsEventId.WordBoundary, ref VoiceSynthesizer._speakProgress, value);
			}
		}

		public event EventHandler<BookmarkReachedEventArgs> BookmarkReached
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.AddEvent(TtsEventId.Bookmark, ref VoiceSynthesizer._bookmarkReached, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.RemoveEvent(TtsEventId.Bookmark, ref VoiceSynthesizer._bookmarkReached, value);
			}
		}

		public event EventHandler<VoiceChangeEventArgs> VoiceChange
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.AddEvent(TtsEventId.VoiceChange, ref VoiceSynthesizer._voiceChange, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.RemoveEvent(TtsEventId.VoiceChange, ref VoiceSynthesizer._voiceChange, value);
			}
		}

		public event EventHandler<PhonemeReachedEventArgs> PhonemeReached
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.AddEvent(TtsEventId.Phoneme, ref VoiceSynthesizer._phonemeReached, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.RemoveEvent(TtsEventId.Phoneme, ref VoiceSynthesizer._phonemeReached, value);
			}
		}

		public event EventHandler<VisemeReachedEventArgs> VisemeReached
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.AddEvent(TtsEventId.Viseme, ref VoiceSynthesizer._visemeReached, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesizer.RemoveEvent(TtsEventId.Viseme, ref VoiceSynthesizer._visemeReached, value);
			}
		}

		public event EventHandler<StateChangedEventArgs> StateChanged
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesis voiceSynthesizer = VoiceSynthesizer;
				voiceSynthesizer._stateChanged = (EventHandler<StateChangedEventArgs>)Delegate.Combine(voiceSynthesizer._stateChanged, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				Helpers.ThrowIfNull(value, "value");
				VoiceSynthesis voiceSynthesizer = VoiceSynthesizer;
				voiceSynthesizer._stateChanged = (EventHandler<StateChangedEventArgs>)Delegate.Remove(voiceSynthesizer._stateChanged, value);
			}
		}

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

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

		public void SelectVoice(string name)
		{
			Helpers.ThrowIfEmptyOrNull(name, "name");
			TTSVoice engine = VoiceSynthesizer.GetEngine(name, CultureInfo.CurrentUICulture, VoiceGender.NotSet, VoiceAge.NotSet, 1, switchContext: true);
			if (engine == null || name != engine.VoiceInfo.Name)
			{
				throw new ArgumentException(SR.Get(SRID.SynthesizerSetVoiceNoMatch));
			}
			VoiceSynthesizer.Voice = engine;
		}

		public void SelectVoiceByHints(VoiceGender gender)
		{
			SelectVoiceByHints(gender, VoiceAge.NotSet, 1, CultureInfo.CurrentUICulture);
		}

		public void SelectVoiceByHints(VoiceGender gender, VoiceAge age)
		{
			SelectVoiceByHints(gender, age, 1, CultureInfo.CurrentUICulture);
		}

		public void SelectVoiceByHints(VoiceGender gender, VoiceAge age, int voiceAlternate)
		{
			SelectVoiceByHints(gender, age, voiceAlternate, CultureInfo.CurrentUICulture);
		}

		public void SelectVoiceByHints(VoiceGender gender, VoiceAge age, int voiceAlternate, CultureInfo culture)
		{
			Helpers.ThrowIfNull(culture, "culture");
			if (voiceAlternate < 0)
			{
				throw new ArgumentOutOfRangeException("voiceAlternate", SR.Get(SRID.PromptBuilderInvalidVariant));
			}
			if (!VoiceInfo.ValidateGender(gender))
			{
				throw new ArgumentException(SR.Get(SRID.EnumInvalid, "VoiceGender"), "gender");
			}
			if (!VoiceInfo.ValidateAge(age))
			{
				throw new ArgumentException(SR.Get(SRID.EnumInvalid, "VoiceAge"), "age");
			}
			TTSVoice engine = VoiceSynthesizer.GetEngine(null, culture, gender, age, voiceAlternate, switchContext: true);
			if (engine == null)
			{
				throw new InvalidOperationException(SR.Get(SRID.SynthesizerSetVoiceNoMatch));
			}
			VoiceSynthesizer.Voice = engine;
		}

		public Prompt SpeakAsync(string textToSpeak)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			Prompt prompt = new Prompt(textToSpeak, SynthesisTextFormat.Text);
			SpeakAsync(prompt);
			return prompt;
		}

		public void SpeakAsync(Prompt prompt)
		{
			Helpers.ThrowIfNull(prompt, "prompt");
			prompt.Synthesizer = this;
			VoiceSynthesizer.SpeakAsync(prompt);
		}

		public Prompt SpeakSsmlAsync(string textToSpeak)
		{
			Helpers.ThrowIfNull(textToSpeak, "textToSpeak");
			Prompt prompt = new Prompt(textToSpeak, SynthesisTextFormat.Ssml);
			SpeakAsync(prompt);
			return prompt;
		}

		public Prompt SpeakAsync(PromptBuilder promptBuilder)
		{
			Helpers.ThrowIfNull(promptBuilder, "promptBuilder");
			Prompt prompt = new Prompt(promptBuilder);
			SpeakAsync(prompt);
			return prompt;
		}

		public void Speak(string textToSpeak)
		{
			Speak(new Prompt(textToSpeak, SynthesisTextFormat.Text));
		}

		public void Speak(Prompt prompt)
		{
			Helpers.ThrowIfNull(prompt, "prompt");
			if (State == SynthesizerState.Paused)
			{
				throw new InvalidOperationException(SR.Get(SRID.SynthesizerSyncSpeakWhilePaused));
			}
			prompt.Synthesizer = this;
			prompt._syncSpeak = true;
			VoiceSynthesizer.Speak(prompt);
		}

		public void Speak(PromptBuilder promptBuilder)
		{
			Speak(new Prompt(promptBuilder));
		}

		public void SpeakSsml(string textToSpeak)
		{
			Speak(new Prompt(textToSpeak, SynthesisTextFormat.Ssml));
		}

		public void Pause()
		{
			if (!_paused)
			{
				VoiceSynthesizer.Pause();
				_paused = true;
			}
		}

		public void Resume()
		{
			if (_paused)
			{
				VoiceSynthesizer.Resume();
				_paused = false;
			}
		}

		public void SpeakAsyncCancel(Prompt prompt)
		{
			Helpers.ThrowIfNull(prompt, "prompt");
			VoiceSynthesizer.Abort(prompt);
		}

		public void SpeakAsyncCancelAll()
		{
			VoiceSynthesizer.Abort();
		}

		public void SetOutputToWaveFile(string path)
		{
			Helpers.ThrowIfEmptyOrNull(path, "path");
			SetOutputToNull();
			SetOutputStream(new FileStream(path, FileMode.Create, FileAccess.Write), null, headerInfo: true, closeStreamOnExit: true);
		}

		public void SetOutputToWaveFile(string path, SpeechAudioFormatInfo formatInfo)
		{
			Helpers.ThrowIfEmptyOrNull(path, "path");
			Helpers.ThrowIfNull(formatInfo, "formatInfo");
			SetOutputToNull();
			SetOutputStream(new FileStream(path, FileMode.Create, FileAccess.Write), formatInfo, headerInfo: true, closeStreamOnExit: true);
		}

		public void SetOutputToWaveStream(Stream audioDestination)
		{
			Helpers.ThrowIfNull(audioDestination, "audioDestination");
			SetOutputStream(audioDestination, null, headerInfo: true, closeStreamOnExit: false);
		}

		public void SetOutputToAudioStream(Stream audioDestination, SpeechAudioFormatInfo formatInfo)
		{
			Helpers.ThrowIfNull(audioDestination, "audioDestination");
			Helpers.ThrowIfNull(formatInfo, "formatInfo");
			SetOutputStream(audioDestination, formatInfo, headerInfo: false, closeStreamOnExit: false);
		}

		public void SetOutputToDefaultAudioDevice()
		{
			SetOutputStream(null, null, headerInfo: true, closeStreamOnExit: false);
		}

		public void SetOutputToNull()
		{
			if (_outputStream != Stream.Null)
			{
				VoiceSynthesizer.SetOutput(Stream.Null, null, headerInfo: true);
			}
			if (_outputStream != null && _closeStreamOnExit)
			{
				_outputStream.Close();
			}
			_outputStream = Stream.Null;
		}

		public Prompt GetCurrentlySpokenPrompt()
		{
			return VoiceSynthesizer.Prompt;
		}

		public ReadOnlyCollection<InstalledVoice> GetInstalledVoices()
		{
			return VoiceSynthesizer.GetInstalledVoices(null);
		}

		public ReadOnlyCollection<InstalledVoice> GetInstalledVoices(CultureInfo culture)
		{
			Helpers.ThrowIfNull(culture, "culture");
			if (culture.Equals(CultureInfo.InvariantCulture))
			{
				throw new ArgumentException(SR.Get(SRID.InvariantCultureInfo), "culture");
			}
			return VoiceSynthesizer.GetInstalledVoices(culture);
		}

		public void AddLexicon(Uri uri, string mediaType)
		{
			Helpers.ThrowIfNull(uri, "uri");
			VoiceSynthesizer.AddLexicon(uri, mediaType);
		}

		public void RemoveLexicon(Uri uri)
		{
			Helpers.ThrowIfNull(uri, "uri");
			VoiceSynthesizer.RemoveLexicon(uri);
		}

		private void SetOutputStream(Stream stream, SpeechAudioFormatInfo formatInfo, bool headerInfo, bool closeStreamOnExit)
		{
			SetOutputToNull();
			_outputStream = stream;
			_closeStreamOnExit = closeStreamOnExit;
			VoiceSynthesizer.SetOutput(stream, formatInfo, headerInfo);
		}

		private void Dispose(bool disposing)
		{
			if (!_isDisposed && disposing && _voiceSynthesis != null)
			{
				_isDisposed = true;
				SpeakAsyncCancelAll();
				if (_outputStream != null)
				{
					if (_closeStreamOnExit)
					{
						_outputStream.Close();
					}
					else
					{
						_outputStream.Flush();
					}
					_outputStream = null;
				}
			}
			if (_voiceSynthesis != null)
			{
				_voiceSynthesis.Dispose();
				_voiceSynthesis = null;
			}
			_isDisposed = true;
		}
	}
	public enum SynthesizerState
	{
		Ready,
		Speaking,
		Paused
	}
	[Flags]
	public enum SynthesizerEmphasis
	{
		Stressed = 1,
		Emphasized = 2
	}
	public class StateChangedEventArgs : EventArgs
	{
		private SynthesizerState _state;

		private SynthesizerState _previousState;

		public SynthesizerState State => _state;

		public SynthesizerState PreviousState => _previousState;

		internal StateChangedEventArgs(SynthesizerState state, SynthesizerState previousState)
		{
			_state = state;
			_previousState = previousState;
		}
	}
	public class VisemeReachedEventArgs : PromptEventArgs
	{
		private int _currentViseme;

		private TimeSpan _audioPosition;

		private TimeSpan _duration;

		private SynthesizerEmphasis _emphasis;

		private int _nextViseme;

		public int Viseme => _currentViseme;

		public TimeSpan AudioPosition => _audioPosition;

		public TimeSpan Duration => _duration;

		public SynthesizerEmphasis Emphasis => _emphasis;

		public int NextViseme => _nextViseme;

		internal VisemeReachedEventArgs(Prompt speakPrompt, int currentViseme, TimeSpan audioPosition, TimeSpan duration, SynthesizerEmphasis emphasis, int nextViseme)
			: base(speakPrompt)
		{
			_currentViseme = currentViseme;
			_audioPosition = audioPosition;
			_duration = duration;
			_emphasis = emphasis;
			_nextViseme = nextViseme;
		}
	}
	public class VoiceChangeEventArgs : PromptEventArgs
	{
		private VoiceInfo _voice;

		public VoiceInfo Voice => _voice;

		internal VoiceChangeEventArgs(Prompt prompt, VoiceInfo voice)
			: base(prompt)
		{
			_voice = voice;
		}
	}
	[Serializable]
	[DebuggerDisplay("{(_name != null ? \"'\" + _name + \"' \" : \"\") +  (_culture != null ? \" '\" + _culture.ToString () + \"' \" : \"\") + (_gender != VoiceGender.NotSet ? \" '\" + _gender.ToString () + \"' \" : \"\") + (_age != VoiceAge.NotSet ? \" '\" + _age.ToString () + \"' \" : \"\") + (_variant > 0 ? \" \" + _variant.ToString () : \"\")}")]
	public class VoiceInfo
	{
		private string _name;

		private CultureInfo _culture;

		private VoiceGender _gender;

		private VoiceAge _age;

		private int _variant = -1;

		[NonSerialized]
		private string _id;

		[NonSerialized]
		private string _registryKeyPath;

		[NonSerialized]
		private string _assemblyName;

		[NonSerialized]
		private string _clsid;

		[NonSerialized]
		private string _description;

		[NonSerialized]
		private ReadOnlyDictionary<string, string> _attributes;

		[NonSerialized]
		private ReadOnlyCollection<SpeechAudioFormatInfo> _audioFormats;

		public VoiceGender Gender => _gender;

		public VoiceAge Age => _age;

		public string Name => _name;

		public CultureInfo Culture => _culture;

		public string Id => _id;

		public string Description => _description ?? string.Empty;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public ReadOnlyCollection<SpeechAudioFormatInfo> SupportedAudioFormats => _audioFormats;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public IDictionary<string, string> AdditionalInfo => _attributes ?? (_attributes = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>(0)));

		internal int Variant => _variant;

		internal string AssemblyName => _assemblyName;

		internal string Clsid => _clsid;

		internal string RegistryKeyPath => _registryKeyPath;

		internal VoiceInfo(string name)
		{
			Helpers.ThrowIfEmptyOrNull(name, "name");
			_name = name;
		}

		internal VoiceInfo(CultureInfo culture)
		{
			Helpers.ThrowIfNull(culture, "culture");
			if (culture.Equals(CultureInfo.InvariantCulture))
			{
				throw new ArgumentException(SR.Get(SRID.InvariantCultureInfo), "culture");
			}
			_culture = culture;
		}

		internal VoiceInfo(ObjectToken token)
		{
			_registryKeyPath = token._sKeyId;
			_id = token.Name;
			_description = token.Description;
			_name = token.TokenName();
			SsmlParserHelpers.TryConvertAge(token.Age.ToLowerInvariant(), out _age);
			SsmlParserHelpers.TryConvertGender(token.Gender.ToLowerInvariant(), out _gender);
			if (token.Attributes.TryGetString("Language", out var value))
			{
				_culture = SapiAttributeParser.GetCultureInfoFromLanguageString(value);
			}
			if (token.TryGetString("Assembly", out var value2))
			{
				_assemblyName = value2;
			}
			if (token.TryGetString("CLSID", out var value3))
			{
				_clsid = value3;
			}
			if (token.Attributes != null)
			{
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				string[] valueNames = token.Attributes.GetValueNames();
				foreach (string text in valueNames)
				{
					if (token.Attributes.TryGetString(text, out var value4))
					{
						dictionary.Add(text, value4);
					}
				}
				_attributes = new ReadOnlyDictionary<string, string>(dictionary);
			}
			if (token.Attributes != null && token.Attributes.TryGetString("AudioFormats", out var value5))
			{
				_audioFormats = new ReadOnlyCollection<SpeechAudioFormatInfo>(SapiAttributeParser.GetAudioFormatsFromString(value5));
			}
			else
			{
				_audioFormats = new ReadOnlyCollection<SpeechAudioFormatInfo>(new List<SpeechAudioFormatInfo>());
			}
		}

		internal VoiceInfo(VoiceGender gender)
		{
			_gender = gender;
		}

		internal VoiceInfo(VoiceGender gender, VoiceAge age)
		{
			_gender = gender;
			_age = age;
		}

		internal VoiceInfo(VoiceGender gender, VoiceAge age, int voiceAlternate)
		{
			if (voiceAlternate < 0)
			{
				throw new ArgumentOutOfRangeException("voiceAlternate", SR.Get(SRID.PromptBuilderInvalidVariant));
			}
			_gender = gender;
			_age = age;
			_variant = voiceAlternate + 1;
		}

		public override bool Equals(object obj)
		{
			if (obj is VoiceInfo voiceInfo && _name == voiceInfo._name && (_age == voiceInfo._age || _age == VoiceAge.NotSet || voiceInfo._age == VoiceAge.NotSet) && (_gender == voiceInfo._gender || _gender == VoiceGender.NotSet || voiceInfo._gender == VoiceGender.NotSet))
			{
				if (_culture != null && voiceInfo._culture != null)
				{
					return _culture.Equals(voiceInfo._culture);
				}
				return true;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return _name.GetHashCode();
		}

		internal static bool ValidateGender(VoiceGender gender)
		{
			if (gender != VoiceGender.Female && gender != VoiceGender.Male && gender != VoiceGender.Neutral)
			{
				return gender == VoiceGender.NotSet;
			}
			return true;
		}

		internal static bool ValidateAge(VoiceAge age)
		{
			if (age != VoiceAge.Adult && age != VoiceAge.Child && age != 0 && age != VoiceAge.Senior)
			{
				return age == VoiceAge.Teen;
			}
			return true;
		}
	}
}
namespace System.Speech.Synthesis.TtsEngine
{
	[ComImport]
	[Guid("A74D7C8E-4CC5-4F2F-A6EB-804DEE18500E")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface ITtsEngine
	{
		[PreserveSig]
		void Speak(SPEAKFLAGS dwSpeakFlags, ref Guid rguidFormatId, IntPtr pWaveFormatEx, IntPtr pTextFragList, IntPtr pOutputSite);

		[PreserveSig]
		void GetOutputFormat(ref Guid pTargetFmtId, IntPtr pTargetWaveFormatEx, out Guid pOutputFormatId, out IntPtr ppCoMemOutputWaveFormatEx);
	}
	[StructLayout(LayoutKind.Sequential)]
	internal class SPVTEXTFRAG
	{
		public IntPtr pNext;

		public SPVSTATE State;

		public IntPtr pTextStart;

		public int ulTextLen;

		public int ulTextSrcOffset;

		public GCHandle gcText;

		public GCHandle gcNext;

		public GCHandle gcPhoneme;

		public GCHandle gcSayAsCategory;
	}
	[ComConversionLoss]
	[TypeLibType(16)]
	internal struct SPVSTATE
	{
		public SPVACTIONS eAction;

		public short LangID;

		public short wReserved;

		public int EmphAdj;

		public int RateAdj;

		public int Volume;

		public SPVPITCH PitchAdj;

		public int SilenceMSecs;

		public IntPtr pPhoneIds;

		public SPPARTOFSPEECH ePartOfSpeech;

		public SPVCONTEXT Context;
	}
	[TypeLibType(16)]
	internal struct SPVCONTEXT
	{
		public IntPtr pCategory;

		public IntPtr pBefore;

		public IntPtr pAfter;
	}
	[TypeLibType(16)]
	internal struct SPVPITCH
	{
		public int MiddleAdj;

		public int RangeAdj;
	}
	internal static class SAPIGuids
	{
		internal static readonly Guid SPDFID_WaveFormatEx = new Guid("C31ADBAE-527F-4ff5-A230-F62BB61FF70C");
	}
	[Flags]
	internal enum SPEAKFLAGS
	{
		SPF_DEFAULT = 0,
		SPF_ASYNC = 1,
		SPF_PURGEBEFORESPEAK = 2,
		SPF_IS_FILENAME = 4,
		SPF_IS_XML = 8,
		SPF_IS_NOT_XML = 0x10,
		SPF_PERSIST_XML = 0x20,
		SPF_NLP_SPEAK_PUNC = 0x40,
		SPF_PARSE_SAPI = 0x80,
		SPF_PARSE_SSML = 0x100
	}
	[Flags]
	internal enum SPVESACTIONS
	{
		SPVES_CONTINUE = 0,
		SPVES_ABORT = 1,
		SPVES_SKIP = 2,
		SPVES_RATE = 4,
		SPVES_VOLUME = 8
	}
	[TypeLibType(16)]
	internal enum SPVACTIONS
	{
		SPVA_Speak,
		SPVA_Silence,
		SPVA_Pronounce,
		SPVA_Bookmark,
		SPVA_SpellOut,
		SPVA_Section,
		SPVA_ParseUnknownTag
	}
	[TypeLibType(16)]
	internal enum SPPARTOFSPEECH
	{
		SPPS_NotOverridden = -1,
		SPPS_Unknown = 0,
		SPPS_Noun = 4096,
		SPPS_Verb = 8192,
		SPPS_Modifier = 12288,
		SPPS_Function = 16384,
		SPPS_Interjection = 20480,
		SPPS_SuppressWord = 61440
	}
	public abstract class TtsEngineSsml
	{
		protected TtsEngineSsml(string registryKey)
		{
		}

		public abstract IntPtr GetOutputFormat(SpeakOutputFormat speakOutputFormat, IntPtr targetWaveFormat);

		public abstract void AddLexicon(Uri uri, string mediaType, ITtsEngineSite site);

		public abstract void RemoveLexicon(Uri uri, ITtsEngineSite site);

		public abstract void Speak(TextFragment[] fragment, IntPtr waveHeader, ITtsEngineSite site);
	}
	[ImmutableObject(true)]
	public struct SpeechEventInfo : IEquatable<SpeechEventInfo>
	{
		private short _eventId;

		private short _parameterType;

		private int _param1;

		private IntPtr _param2;

		public short EventId
		{
			get
			{
				return _eventId;
			}
			internal set
			{
				_eventId = value;
			}
		}

		public short ParameterType
		{
			get
			{
				return _parameterType;
			}
			internal set
			{
				_parameterType = value;
			}
		}

		public int Param1
		{
			get
			{
				return _param1;
			}
			internal set
			{
				_param1 = value;
			}
		}

		public IntPtr Param2
		{
			get
			{
				return _param2;
			}
			internal set
			{
				_param2 = value;
			}
		}

		public SpeechEventInfo(short eventId, short parameterType, int param1, IntPtr param2)
		{
			_eventId = eventId;
			_parameterType = parameterType;
			_param1 = param1;
			_param2 = param2;
		}

		public static bool operator ==(SpeechEventInfo event1, SpeechEventInfo event2)
		{
			if (event1.EventId == event2.EventId && event1.ParameterType == event2.ParameterType && event1.Param1 == event2.Param1)
			{
				return event1.Param2 == event2.Param2;
			}
			return false;
		}

		public static bool operator !=(SpeechEventInfo event1, SpeechEventInfo event2)
		{
			return !(event1 == event2);
		}

		public bool Equals(SpeechEventInfo other)
		{
			return this == other;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is SpeechEventInfo))
			{
				return false;
			}
			return Equals((SpeechEventInfo)obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}
	}
	public interface ITtsEngineSite
	{
		int EventInterest { get; }

		int Actions { get; }

		int Rate { get; }

		int Volume { get; }

		void AddEvents(SpeechEventInfo[] events, int count);

		int Write(IntPtr data, int count);

		SkipInfo GetSkipInfo();

		void CompleteSkip(int skipped);

		Stream LoadResource(Uri uri, string mediaType);
	}
	public class SkipInfo
	{
		private int _type;

		private int _count;

		public int Type
		{
			get
			{
				return _type;
			}
			set
			{
				_type = value;
			}
		}

		public int Count
		{
			get
			{
				return _count;
			}
			set
			{
				_count = value;
			}
		}

		internal SkipInfo(int type, int count)
		{
			_type = type;
			_count = count;
		}

		public SkipInfo()
		{
		}
	}
	[StructLayout(LayoutKind.Sequential)]
	[DebuggerDisplay("{State.Action} = {TextToSpeak!=null?TextToSpeak:\"\"}")]
	public class TextFragment
	{
		private FragmentState _state;

		[MarshalAs(UnmanagedType.LPWStr)]
		private string _textToSpeak = string.Empty;

		private int _textOffset;

		private int _textLength;

		public FragmentState State
		{
			get
			{
				return _state;
			}
			set
			{
				_state = value;
			}
		}

		public string TextToSpeak
		{
			get
			{
				return _textToSpeak;
			}
			set
			{
				Helpers.ThrowIfEmptyOrNull(value, "value");
				_textToSpeak = value;
			}
		}

		public int TextOffset
		{
			get
			{
				return _textOffset;
			}
			set
			{
				_textOffset = value;
			}
		}

		public int TextLength
		{
			get
			{
				return _textLength;
			}
			set
			{
				_textLength = value;
			}
		}

		public TextFragment()
		{
		}

		internal TextFragment(FragmentState fragState)
			: this(fragState, null, null, 0, 0)
		{
		}

		internal TextFragment(FragmentState fragState, string textToSpeak)
			: this(fragState, textToSpeak, textToSpeak, 0, textToSpeak.Length)
		{
		}

		internal TextFragment(FragmentState fragState, string textToSpeak, string textFrag, int offset, int length)
		{
			if (fragState.Action == TtsEngineAction.Speak || fragState.Action == TtsEngineAction.Pronounce)
			{
				textFrag = textToSpeak;
			}
			if (!string.IsNullOrEmpty(textFrag))
			{
				TextToSpeak = textFrag;
			}
			State = fragState;
			TextOffset = offset;
			TextLength = length;
		}
	}
	[ImmutableObject(true)]
	public struct FragmentState : IEquatable<FragmentState>
	{
		private TtsEngineAction _action;

		private int _langId;

		private int _emphasis;

		private int _duration;

		private SayAs _sayAs;

		private Prosody _prosody;

		private char[] _phoneme;

		public TtsEngineAction Action
		{
			get
			{
				return _action;
			}
			internal set
			{
				_action = value;
			}
		}

		public int LangId
		{
			get
			{
				return _langId;
			}
			internal set
			{
				_langId = value;
			}
		}

		public int Emphasis
		{
			get
			{
				return _emphasis;
			}
			internal set
			{
				_emphasis = value;
			}
		}

		public int Duration
		{
			get
			{
				return _duration;
			}
			internal set
			{
				_duration = value;
			}
		}

		public SayAs SayAs
		{
			get
			{
				return _sayAs;
			}
			internal set
			{
				Helpers.ThrowIfNull(value, "value");
				_sayAs = value;
			}
		}

		public Prosody Prosody
		{
			get
			{
				return _prosody;
			}
			internal set
			{
				Helpers.ThrowIfNull(value, "value");
				_prosody = value;
			}
		}

		public char[] Phoneme
		{
			get
			{
				return _phoneme;
			}
			internal set
			{
				Helpers.ThrowIfNull(value, "value");
				_phoneme = value;
			}
		}

		public FragmentState(TtsEngineAction action, int langId, int emphasis, int duration, SayAs sayAs, Prosody prosody, char[] phonemes)
		{
			_action = action;
			_langId = langId;
			_emphasis = emphasis;
			_duration = duration;
			_sayAs = sayAs;
			_prosody = prosody;
			_phoneme = phonemes;
		}

		public static bool operator ==(FragmentState state1, FragmentState state2)
		{
			if (state1.Action == state2.Action && state1.LangId == state2.LangId && state1.Emphasis == state2.Emphasis && state1.Duration == state2.Duration && state1.SayAs == state2.SayAs && state1.Prosody == state2.Prosody)
			{
				return object.Equals(state1.Phoneme, state2.Phoneme);
			}
			return false;
		}

		public static bool operator !=(FragmentState state1, FragmentState state2)
		{
			return !(state1 == state2);
		}

		public bool Equals(FragmentState other)
		{
			return this == other;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is FragmentState))
			{
				return false;
			}
			return Equals((FragmentState)obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}
	}
	[StructLayout(LayoutKind.Sequential)]
	public class Prosody
	{
		internal ProsodyNumber _pitch;

		internal ProsodyNumber _range;

		internal ProsodyNumber _rate;

		internal int _duration;

		internal ProsodyNumber _volume;

		internal ContourPoint[] _contourPoints;

		public ProsodyNumber Pitch
		{
			get
			{
				return _pitch;
			}
			set
			{
				_pitch = value;
			}
		}

		public ProsodyNumber Range
		{
			get
			{
				return _range;
			}
			set
			{
				_range = value;
			}
		}

		public ProsodyNumber Rate
		{
			get
			{
				return _rate;
			}
			set
			{
				_rate = value;
			}
		}

		public int Duration
		{
			get
			{
				return _duration;
			}
			set
			{
				_duration = value;
			}
		}

		public ProsodyNumber Volume
		{
			get
			{
				return _volume;
			}
			set
			{
				_volume = value;
			}
		}

		public ContourPoint[] GetContourPoints()
		{
			return _contourPoints;
		}

		public void SetContourPoints(ContourPoint[] points)
		{
			Helpers.ThrowIfNull(points, "points");
			_contourPoints = (ContourPoint[])points.Clone();
		}

		public Prosody()
		{
			Pitch = new ProsodyNumber(0);
			Range = new ProsodyNumber(0);
			Rate = new ProsodyNumber(0);
			Volume = new ProsodyNumber(-1);
		}

		internal Prosody Clone()
		{
			Prosody prosody = new Prosody();
			prosody._pitch = _pitch;
			prosody._range = _range;
			prosody._rate = _rate;
			prosody._duration = _duration;
			prosody._volume = _volume;
			return prosody;
		}
	}
	[ImmutableObject(true)]
	public struct ContourPoint : IEquatable<ContourPoint>
	{
		private float _start;

		private float _change;

		private ContourPointChangeType _changeType;

		public float Start => _start;

		public float Change => _change;

		public ContourPointChangeType ChangeType => _changeType;

		public ContourPoint(float start, float change, ContourPointChangeType changeType)
		{
			_start = start;
			_change = change;
			_changeType = changeType;
		}

		public static bool operator ==(ContourPoint point1, ContourPoint point2)
		{
			if (point1.Start.Equals(point2.Start) && point1.Change.Equals(point2.Change))
			{
				return point1.ChangeType.Equals(point2.ChangeType);
			}
			return false;
		}

		public static bool operator !=(ContourPoint point1, ContourPoint point2)
		{
			return !(point1 == point2);
		}

		public bool Equals(ContourPoint other)
		{
			return this == other;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is ContourPoint))
			{
				return false;
			}
			return Equals((ContourPoint)obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}
	}
	[ImmutableObject(true)]
	public struct ProsodyNumber : IEquatable<ProsodyNumber>
	{
		public const int AbsoluteNumber = int.MaxValue;

		private int _ssmlAttributeId;

		private bool _isPercent;

		private float _number;

		private ProsodyUnit _unit;

		public int SsmlAttributeId
		{
			get
			{
				return _ssmlAttributeId;
			}
			internal set
			{
				_ssmlAttributeId = value;
			}
		}

		public bool IsNumberPercent
		{
			get
			{
				return _isPercent;
			}
			internal set
			{
				_isPercent = value;
			}
		}

		public float Number
		{
			get
			{
				return _number;
			}
			internal set
			{
				_number = value;
			}
		}

		public ProsodyUnit Unit
		{
			get
			{
				return _unit;
			}
			internal set
			{
				_unit = value;
			}
		}

		public ProsodyNumber(int ssmlAttributeId)
		{
			_ssmlAttributeId = ssmlAttributeId;
			_number = 1f;
			_isPercent = true;
			_unit = ProsodyUnit.Default;
		}

		public ProsodyNumber(float number)
		{
			_ssmlAttributeId = int.MaxValue;
			_number = number;
			_isPercent = false;
			_unit = ProsodyUnit.Default;
		}

		public static bool operator ==(ProsodyNumber prosodyNumber1, ProsodyNumber prosodyNumber2)
		{
			if (prosodyNumber1._ssmlAttributeId == prosodyNumber2._ssmlAttributeId && prosodyNumber1.Number.Equals(prosodyNumber2.Number) && prosodyNumber1.IsNumberPercent == prosodyNumber2.IsNumberPercent)
			{
				return prosodyNumber1.Unit == prosodyNumber2.Unit;
			}
			return false;
		}

		public static bool operator !=(ProsodyNumber prosodyNumber1, ProsodyNumber prosodyNumber2)
		{
			return !(prosodyNumber1 == prosodyNumber2);
		}

		public bool Equals(ProsodyNumber other)
		{
			return this == other;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is ProsodyNumber))
			{
				return false;
			}
			return Equals((ProsodyNumber)obj);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}
	}
	[StructLayout(LayoutKind.Sequential)]
	public class SayAs
	{
		[MarshalAs(UnmanagedType.LPWStr)]
		private string _interpretAs;

		[MarshalAs(UnmanagedType.LPWStr)]
		private string _format;

		[MarshalAs(UnmanagedType.LPWStr)]
		private string _detail;

		public string InterpretAs
		{
			get
			{
				return _interpretAs;
			}
			set
			{
				Helpers.ThrowIfEmptyOrNull(value, "value");
				_interpretAs = value;
			}
		}

		public string Format
		{
			get
			{
				return _format;
			}
			set
			{
				Helpers.ThrowIfEmptyOrNull(value, "value");
				_format = value;
			}
		}

		public string Detail
		{
			get
			{
				return _detail;
			}
			set
			{
				Helpers.ThrowIfEmptyOrNull(value, "value");
				_detail = value;
			}
		}
	}
	public enum TtsEngineAction
	{
		Speak,
		Silence,
		Pronounce,
		Bookmark,
		SpellOut,
		StartSentence,
		StartParagraph,
		ParseUnknownTag
	}
	public enum EmphasisWord
	{
		Default,
		Strong,
		Moderate,
		None,
		Reduced
	}
	public enum EmphasisBreak
	{
		None = -1,
		ExtraWeak = -2,
		Weak = -3,
		Medium = -4,
		Strong = -5,
		ExtraStrong = -6,
		Default = -7
	}
	public enum ProsodyPitch
	{
		Default,
		ExtraLow,
		Low,
		Medium,
		High,
		ExtraHigh
	}
	public enum ProsodyRange
	{
		Default,
		ExtraLow,
		Low,
		Medium,
		High,
		ExtraHigh
	}
	public enum ProsodyRate
	{
		Default,
		ExtraSlow,
		Slow,
		Medium,
		Fast,
		ExtraFast
	}
	public enum ProsodyVolume
	{
		Default = -1,
		Silent = -2,
		ExtraSoft = -3,
		Soft = -4,
		Medium = -5,
		Loud = -6,
		ExtraLoud = -7
	}
	public enum ProsodyUnit
	{
		Default,
		Hz,
		Semitone
	}
	public enum TtsEventId
	{
		StartInputStream = 1,
		EndInputStream,
		VoiceChange,
		Bookmark,
		WordBoundary,
		Phoneme,
		SentenceBoundary,
		Viseme,
		AudioLevel
	}
	public enum EventParameterType
	{
		Undefined,
		Token,
		Object,
		Pointer,
		String
	}
	public enum SpeakOutputFormat
	{
		WaveFormat,
		Text
	}
	public enum ContourPointChangeType
	{
		Hz,
		Percentage
	}
}
namespace System.Speech.Recognition
{
	public class AudioLevelUpdatedEventArgs : EventArgs
	{
		private int _audioLevel;

		public int AudioLevel => _audioLevel;

		internal AudioLevelUpdatedEventArgs(int audioLevel)
		{
			_audioLevel = audioLevel;
		}
	}
	public enum AudioSignalProblem
	{
		None,
		TooNoisy,
		NoSignal,
		TooLoud,
		TooSoft,
		TooFast,
		TooSlow
	}
	public class AudioSignalProblemOccurredEventArgs : EventArgs
	{
		private AudioSignalProblem _audioSignalProblem;

		private TimeSpan _recognizerPosition;

		private TimeSpan _audioPosition;

		private int _audioLevel;

		public AudioSignalProblem AudioSignalProblem => _audioSignalProblem;

		public int AudioLevel => _audioLevel;

		public TimeSpan AudioPosition => _audioPosition;

		public TimeSpan RecognizerAudioPosition => _recognizerPosition;

		internal AudioSignalProblemOccurredEventArgs(AudioSignalProblem audioSignalProblem, int audioLevel, TimeSpan audioPosition, TimeSpan recognizerPosition)
		{
			_audioSignalProblem = audioSignalProblem;