Decompiled source of Babbler v0.9.6

plugins\System.Speech.dll

Decompiled 2 months 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;

Babbler.dll

Decompiled 2 months 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 System.Text.Json;
using System.Threading.Tasks;
using Babbler.Hooks;
using Babbler.Implementation.Characteristics;
using Babbler.Implementation.Common;
using Babbler.Implementation.Config;
using Babbler.Implementation.Emotes;
using Babbler.Implementation.Hosts;
using Babbler.Implementation.Occlusion;
using Babbler.Implementation.Occlusion.Vents;
using Babbler.Implementation.Occlusion.Vents.Explorer;
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.Collections.Generic;
using Il2CppSystem.IO;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.Helpers;
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.6")]
[assembly: AssemblyInformationalVersion("0.9.6")]
[assembly: AssemblyProduct("Babbler")]
[assembly: AssemblyTitle("Babbler")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Arsonide/Babbler")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.9.6.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.6")]
	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>();
			ClassInjector.RegisterTypeInIl2Cpp<VentTagPeekable>();
			ClassInjector.RegisterTypeInIl2Cpp<VentTagInteractable>();
			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);
				SpeakerHostPool.InitializePools();
				ReplacementRegistry.Initialize();
				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();
				}
				VolumeCacheHook.Initialize();
				EmoteSoundRegistry.Initialize();
				VentRegistry.Initialize();
				TVWatcher.Initialize();
			}
		}

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

		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();
				}
				EmoteSoundRegistry.Uninitialize();
				VentRegistry.Uninitialize();
				TVWatcher.Uninitialize();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Babbler";

		public const string PLUGIN_NAME = "Babbler";

		public const string PLUGIN_VERSION = "0.9.6";
	}
}
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 readonly List<string>[] VoicePriorities = new List<string>[4];

		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);
			return characteristics.SelectDeterministicGenderedListElement(VoicePriorities, AllVoices, MaleVoices, FemaleVoices, NonBinaryVoices, 37);
		}

		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 SoundContext SoundContext { 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, SoundContext soundContext, Human speechPerson)
		{
			StopSpeaker();
			SoundContext = soundContext;
			SpeechPerson = speechPerson;
			SpeechSource = CacheSpeechSource(soundContext, speechPerson);
			SpeechPitch = CacheSpeechPitch(speechPerson, speechInput);
		}

		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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = Vector3.zero;
			OcclusionResult occlusionResult = OcclusionChecker.CheckOcclusion(SpeechPerson, (Human)(object)Player.Instance, SoundContext);
			if (!occlusionResult.AlternativePosition)
			{
				if ((Object)(object)SpeechSource != (Object)null)
				{
					position = SpeechSource.position;
				}
				else
				{
					Utilities.Log("Babbler speaker had a null SpeechSource, which should not happen!", (LogLevel)32);
				}
			}
			else
			{
				position = occlusionResult.Position;
			}
			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);
					SetChannelVolume(occlusionResult.State, channel);
					flag = true;
				}
				else
				{
					ActiveChannels.RemoveAt(num);
					if (ActiveChannels.Count <= 0)
					{
						OnLastChannelFinished();
					}
				}
			}
			if (flag)
			{
				FMODRegistry.TryUpdate();
			}
		}

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

		private Transform CacheSpeechSource(SoundContext soundContext, Human speechPerson)
		{
			Transform val2;
			if (soundContext == SoundContext.PhoneSpeech || soundContext == SoundContext.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 void SetChannelVolume(OcclusionState occlusionState, Channel channel)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			((Channel)(ref channel)).setVolume(FMODRegistry.GetVolume(SoundContext, occlusionState));
		}

		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 EmoteSpeaker : BaseSpeaker, IDelayableSpeaker
	{
		private static float _emotesAllowedTimestamp = -1f;

		private EmoteSound _emoteToPlay;

		private Coroutine _emotePlayCoroutine;

		private float _delay;

		public override void StopSpeaker()
		{
			base.StopSpeaker();
			if (_emotePlayCoroutine != null)
			{
				RuntimeHelper.StopCoroutine(_emotePlayCoroutine);
				_emotePlayCoroutine = null;
			}
			_delay = 0f;
		}

		public override void StartSpeaker(string speechInput, SoundContext soundContext, Human speechPerson)
		{
			base.StartSpeaker(speechInput, soundContext, speechPerson);
			if (_emoteToPlay == null)
			{
				OnFinishedSpeaking?.Invoke();
			}
			else
			{
				_emotePlayCoroutine = RuntimeHelper.StartCoroutine(EmotePlayRoutine());
			}
		}

		private IEnumerator EmotePlayRoutine()
		{
			while (_delay > 0f)
			{
				yield return null;
				_delay -= Time.deltaTime;
			}
			while (Time.realtimeSinceStartup < _emotesAllowedTimestamp)
			{
				yield return null;
			}
			if (!FMODRegistry.TryPlaySound(_emoteToPlay.Sound, FMODRegistry.GetChannelGroup(base.SoundContext), out var channel))
			{
				OnFinishedSpeaking?.Invoke();
				yield break;
			}
			float minStagger = BabblerConfig.EmotesMinStagger.Value;
			float maxStagger = BabblerConfig.EmotesMaxStagger.Value;
			float staggerDuration = Utilities.GlobalRandom.NextSingle() * (maxStagger - minStagger) + minStagger;
			_emotesAllowedTimestamp = Time.realtimeSinceStartup + staggerDuration;
			bool pitchShiftsAllowed = BabblerConfig.EmotesUsePitchShifts.Value && _emoteToPlay.CanPitchShift;
			((Channel)(ref channel)).setPitch(pitchShiftsAllowed ? base.SpeechPitch : 1f);
			SetChannelPosition(base.SpeechSource.position, channel);
			SetChannelVolume(OcclusionState.NoOcclusion, channel);
			FMODRegistry.TryUpdate();
			ActiveChannels.Add(channel);
			float expiration = Time.realtimeSinceStartup + _emoteToPlay.Length + 0.2f;
			while (Time.realtimeSinceStartup < expiration)
			{
				yield return null;
			}
			OnFinishedSpeaking?.Invoke();
		}

		protected override float CacheSpeechPitch(Human speechPerson, string speechInput)
		{
			if (!EmoteSoundRegistry.TryGetEmote(speechInput, speechPerson, out var characteristics, out _emoteToPlay))
			{
				return 1f;
			}
			float value;
			float value2;
			switch (characteristics.Category)
			{
			case VoiceCategory.Male:
				value = BabblerConfig.EmotesMinFrequencyMale.Value;
				value2 = BabblerConfig.EmotesMaxFrequencyMale.Value;
				break;
			case VoiceCategory.Female:
				value = BabblerConfig.EmotesMinFrequencyFemale.Value;
				value2 = BabblerConfig.EmotesMaxFrequencyFemale.Value;
				break;
			default:
				value = BabblerConfig.EmotesMinFrequencyNonBinary.Value;
				value2 = BabblerConfig.EmotesMaxFrequencyNonBinary.Value;
				break;
			}
			float num = value + characteristics.Pitch * (value2 - value);
			return num / _emoteToPlay.Frequency;
		}

		public void InitializeDelay(float delay)
		{
			_delay = delay;
		}
	}
	public interface IDelayableSpeaker
	{
		void InitializeDelay(float delay);
	}
	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, SoundContext soundContext, Human speechPerson)
		{
			base.StartSpeaker(speechInput, soundContext, 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.SoundContext), out var channel))
				{
					((Channel)(ref channel)).setPitch(GetPhonemePitch());
					SetChannelPosition(base.SpeechSource.position, channel);
					SetChannelVolume(OcclusionState.NoOcclusion, 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, string speechInput)
		{
			_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, SoundContext soundContext, Human speechPerson)
		{
			base.StartSpeaker(speechInput, soundContext, 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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.SoundContext), out var channel))
				{
					((Channel)(ref channel)).setPitch(base.SpeechPitch);
					SetChannelPosition(base.SpeechSource.position, channel);
					SetChannelVolume(OcclusionState.NoOcclusion, channel);
					FMODRegistry.TryUpdate();
					ActiveChannels.Add(channel);
				}
			}
		}

		protected override float CacheSpeechPitch(Human speechPerson, string speechInput)
		{
			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.Occlusion
{
	public static class OcclusionChecker
	{
		private static Vector3Int _occlusionBoundsMin;

		private static Vector3Int _occlusionBoundsMax;

		public static OcclusionResult CheckOcclusion(Human speaker, Human listener, SoundContext context)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if (context == SoundContext.PhoneSpeech || context == SoundContext.PhoneShout || context == SoundContext.PhoneEmote)
			{
				return OcclusionResult.CreateNoOcclusion();
			}
			if (!BabblerConfig.OcclusionEnabled.Value)
			{
				return OcclusionResult.CreateNoOcclusion();
			}
			if (!((Actor)speaker).currentCityTile.isInPlayerVicinity)
			{
				return OcclusionResult.CreateFullOcclusion();
			}
			bool flag = Utilities.IsHumanOutside(speaker);
			bool flag2 = Utilities.IsHumanOutside(listener);
			if (flag && flag2)
			{
				return IsHumanInOcclusionBounds(speaker) ? OcclusionResult.CreateNoOcclusion() : OcclusionResult.CreateFullOcclusion();
			}
			if (flag ^ flag2)
			{
				return IsHumanInOcclusionBounds(listener) ? CalculateOcclusionDoorMuffleResult(speaker, listener, crossThreshold: true) : OcclusionResult.CreateFullOcclusion();
			}
			if ((Object)(object)((Actor)speaker).currentBuilding == (Object)null || ((Actor)speaker).currentBuilding.buildingID != ((Actor)listener).currentBuilding.buildingID)
			{
				return OcclusionResult.CreateFullOcclusion();
			}
			Vector3Int currentNodeCoord = ((Actor)speaker).currentNodeCoord;
			int z = ((Vector3Int)(ref currentNodeCoord)).z;
			currentNodeCoord = ((Actor)listener).currentNodeCoord;
			if (Mathf.Abs(z - ((Vector3Int)(ref currentNodeCoord)).z) > 3 || !IsHumanInOcclusionBounds(speaker))
			{
				return OcclusionResult.CreateFullOcclusion();
			}
			if (((Actor)listener).inAirVent)
			{
				return CalculateOcclusionVentResult(speaker, listener);
			}
			if (((Actor)speaker).currentGameLocation.isLobby && ((Actor)listener).currentGameLocation.isLobby)
			{
				return OcclusionResult.CreateNoOcclusion();
			}
			bool flag3 = ((Actor)listener).currentGameLocation.isLobby || ((Actor)speaker).currentGameLocation.isLobby;
			if (!flag3 && ((Actor)speaker).currentGameLocation.thisAsAddress.id != ((Actor)listener).currentGameLocation.thisAsAddress.id)
			{
				return OcclusionResult.CreateFullOcclusion();
			}
			return CalculateOcclusionDoorMuffleResult(speaker, listener, flag3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static OcclusionResult CalculateOcclusionDoorMuffleResult(Human speaker, Human listener, bool crossThreshold)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			//IL_0129: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			NewRoom currentRoom = ((Actor)speaker).currentRoom;
			NewRoom currentRoom2 = ((Actor)listener).currentRoom;
			if (currentRoom.roomID == currentRoom2.roomID)
			{
				return OcclusionResult.CreateNoOcclusion();
			}
			int num = 0;
			int num2 = 0;
			Vector3 val = Vector3.zero;
			Vector3 val2 = Vector3.zero;
			Enumerator<NodeAccess> enumerator = currentRoom.entrances.GetEnumerator();
			while (enumerator.MoveNext())
			{
				NodeAccess current = enumerator.Current;
				if ((int)current.accessType != 5 && current.GetOtherRoom(currentRoom).roomID == currentRoom2.roomID)
				{
					if ((Object)(object)current.door == (Object)null || !current.door.isClosed)
					{
						num++;
						val += current.worldAccessPoint;
					}
					else
					{
						num2++;
						val2 += current.worldAccessPoint;
					}
				}
			}
			if (num + num2 > 0)
			{
				OcclusionState state;
				Vector3 val3;
				if (num > 0)
				{
					state = OcclusionState.MuffleOpenDoor;
					val3 = val / (float)num;
				}
				else
				{
					state = OcclusionState.MuffleClosedDoor;
					val3 = val2 / (float)num2;
				}
				Vector3 val4 = val3 - ((Actor)listener).aimTransform.position;
				float num3 = Vector3.Distance(((Actor)speaker).aimTransform.position, val3);
				Vector3 position = val3 + ((Vector3)(ref val4)).normalized * num3;
				OcclusionResult result = default(OcclusionResult);
				result.State = state;
				result.AlternativePosition = true;
				result.Position = position;
				return result;
			}
			return crossThreshold ? OcclusionResult.CreateFullOcclusion() : OcclusionResult.CreateDistantOcclusion();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static OcclusionResult CalculateOcclusionVentResult(Human speaker, Human listener)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00dd: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			if (!VentRegistry.TryGetVents(((Actor)speaker).currentRoom, out var vents) || vents.Count <= 0)
			{
				return OcclusionResult.CreateFullOcclusion();
			}
			VentRegistry.CacheNearbyVentCoordinates(Player.Instance.currentDuctSection);
			int num = 0;
			Vector3 val = Vector3.zero;
			foreach (VentTagCache item in vents)
			{
				if (VentRegistry.IsVentNearby(item))
				{
					num++;
					val += item.AudioPosition;
				}
			}
			if (num <= 0)
			{
				return OcclusionResult.CreateFullOcclusion();
			}
			Vector3 val2 = val / (float)num;
			Vector3 val3 = val2 - ((Actor)listener).aimTransform.position;
			float num2 = Vector3.Distance(((Actor)speaker).aimTransform.position, val2);
			Vector3 position = val2 + ((Vector3)(ref val3)).normalized * num2;
			OcclusionResult result = default(OcclusionResult);
			result.State = OcclusionState.MuffleVent;
			result.AlternativePosition = true;
			result.Position = position;
			return result;
		}

		public static void CachePlayerBounds()
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Vector3Int currentNodeCoord = ((Actor)Player.Instance).currentNodeCoord;
			int value = BabblerConfig.OcclusionNodeRange.Value;
			_occlusionBoundsMin = currentNodeCoord - new Vector3Int(value, value, value);
			_occlusionBoundsMax = currentNodeCoord + new Vector3Int(value, value, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool IsHumanInOcclusionBounds(Human speaker)
		{
			//IL_0002: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			Vector3Int currentNodeCoord = ((Actor)speaker).currentNodeCoord;
			int result;
			if (((Vector3Int)(ref currentNodeCoord)).x >= ((Vector3Int)(ref _occlusionBoundsMin)).x)
			{
				currentNodeCoord = ((Actor)speaker).currentNodeCoord;
				if (((Vector3Int)(ref currentNodeCoord)).x <= ((Vector3Int)(ref _occlusionBoundsMax)).x)
				{
					currentNodeCoord = ((Actor)speaker).currentNodeCoord;
					if (((Vector3Int)(ref currentNodeCoord)).y >= ((Vector3Int)(ref _occlusionBoundsMin)).y)
					{
						currentNodeCoord = ((Actor)speaker).currentNodeCoord;
						if (((Vector3Int)(ref currentNodeCoord)).y <= ((Vector3Int)(ref _occlusionBoundsMax)).y)
						{
							currentNodeCoord = ((Actor)speaker).currentNodeCoord;
							if (((Vector3Int)(ref currentNodeCoord)).z >= ((Vector3Int)(ref _occlusionBoundsMin)).z)
							{
								currentNodeCoord = ((Actor)speaker).currentNodeCoord;
								result = ((((Vector3Int)(ref currentNodeCoord)).z <= ((Vector3Int)(ref _occlusionBoundsMax)).z) ? 1 : 0);
								goto IL_00a6;
							}
						}
					}
				}
			}
			result = 0;
			goto IL_00a6;
			IL_00a6:
			return (byte)result != 0;
		}
	}
	public struct OcclusionResult
	{
		public OcclusionState State;

		public bool AlternativePosition;

		public Vector3 Position;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static OcclusionResult CreateFullOcclusion()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			OcclusionResult result = default(OcclusionResult);
			result.State = OcclusionState.FullOcclusion;
			result.AlternativePosition = false;
			result.Position = Vector3.zero;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static OcclusionResult CreateNoOcclusion()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			OcclusionResult result = default(OcclusionResult);
			result.State = OcclusionState.NoOcclusion;
			result.AlternativePosition = false;
			result.Position = Vector3.zero;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static OcclusionResult CreateDistantOcclusion()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			OcclusionResult result = default(OcclusionResult);
			result.State = OcclusionState.DistantOcclusion;
			result.AlternativePosition = false;
			result.Position = Vector3.zero;
			return result;
		}
	}
	public enum OcclusionState
	{
		NoOcclusion,
		MuffleOpenDoor,
		MuffleClosedDoor,
		MuffleVent,
		DistantOcclusion,
		FullOcclusion
	}
}
namespace Babbler.Implementation.Occlusion.Vents
{
	public static class VentRegistry
	{
		private const int REGISTRATION_BATCH_COUNT = 5;

		private static bool _occlusionEnabled;

		private static readonly Queue<VentTagCache> _unregisteredTags = new Queue<VentTagCache>();

		private static readonly Dictionary<int, List<VentTagCache>> _registeredTags = new Dictionary<int, List<VentTagCache>>();

		private static readonly List<int> _registeredRooms = new List<int>();

		private static readonly List<List<VentTagCache>> _registrationPool = new List<List<VentTagCache>>();

		private static readonly HashSet<Vector3Int> _nearbyVentCoordinates = new HashSet<Vector3Int>();

		private static Vector3Int _lastNearbyCheck = Vector3Int.zero;

		private static readonly DuctExplorer _explorer = new DuctExplorer();

		public static void Initialize()
		{
			_occlusionEnabled = BabblerConfig.OcclusionEnabled.Value;
			if (_occlusionEnabled)
			{
				InteriorControls.Instance.ductStraightWithPeekVent.AddComponent<VentTagPeekable>();
				PrefabControls.Instance.airVent.prefab.AddComponent<VentTagInteractable>();
				Lib.SaveGame.OnBeforeLoad -= OnBeforeEnterGame;
				Lib.SaveGame.OnBeforeLoad += OnBeforeEnterGame;
				Lib.SaveGame.OnBeforeNewGame -= OnBeforeEnterGame;
				Lib.SaveGame.OnBeforeNewGame += OnBeforeEnterGame;
			}
		}

		public static void Uninitialize()
		{
			if (_occlusionEnabled)
			{
				Lib.SaveGame.OnBeforeLoad -= OnBeforeEnterGame;
				Lib.SaveGame.OnBeforeNewGame -= OnBeforeEnterGame;
			}
		}

		private static void OnBeforeEnterGame(object sender, EventArgs eventArgs)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			ClearRegistrations();
			_unregisteredTags.Clear();
			_nearbyVentCoordinates.Clear();
			_lastNearbyCheck = Vector3Int.zero;
		}

		public static void Tick()
		{
			//IL_0040: 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)
			if (!_occlusionEnabled || (Object)(object)PathFinder.Instance == (Object)null)
			{
				return;
			}
			int num = 5;
			NewNode val = default(NewNode);
			while (_unregisteredTags.Count > 0 && num > 0)
			{
				VentTagCache tag = _unregisteredTags.Dequeue();
				if (PathFinder.Instance.nodeMap.TryGetValue(Vector3Int.op_Implicit(CityData.Instance.RealPosToNodeInt(tag.TransformPosition)), ref val) && (Object)(object)((val != null) ? val.room : null) != (Object)null)
				{
					tag.Node = val;
					tag.Room = val.room;
					RegisterVent(tag.Room.roomID, tag);
				}
				num--;
			}
		}

		public static bool TryGetVents(NewRoom room, out List<VentTagCache> vents)
		{
			return _registeredTags.TryGetValue(room.roomID, out vents);
		}

		public static void CacheNearbyVentCoordinates(AirDuctSection playerDuct)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			NewNode val = ((playerDuct != null) ? playerDuct.node : null);
			if (val == null)
			{
				return;
			}
			Vector3Int nodeCoord = val.nodeCoord;
			if (nodeCoord == _lastNearbyCheck)
			{
				return;
			}
			_lastNearbyCheck = nodeCoord;
			_explorer.Reset();
			_explorer.StartExploration(playerDuct);
			_nearbyVentCoordinates.Clear();
			int i = 0;
			for (int value = BabblerConfig.OcclusionVentRange.Value; i < value; i++)
			{
				List<Vector3Int> list = _explorer.TickExploration(playerDuct);
				foreach (Vector3Int item in list)
				{
					_nearbyVentCoordinates.Add(item);
				}
			}
		}

		public static bool IsVentNearby(VentTagCache tag)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return _nearbyVentCoordinates.Contains(tag.Node.nodeCoord);
		}

		public static void QueueVentTagRegistration(VentTagCache tag)
		{
			_unregisteredTags.Enqueue(tag);
		}

		private static void RegisterVent(int roomId, VentTagCache tag)
		{
			if (!_registeredTags.TryGetValue(roomId, out var value))
			{
				value = GetPooledList();
				value.Add(tag);
				_registeredTags.Add(roomId, value);
				_registeredRooms.Add(roomId);
			}
			else
			{
				value.Add(tag);
			}
		}

		private static void ClearRegistrations()
		{
			for (int num = _registeredRooms.Count - 1; num >= 0; num--)
			{
				int key = _registeredRooms[num];
				ReturnPooledList(_registeredTags[key]);
				_registeredTags.Remove(key);
				_registeredRooms.RemoveAt(num);
			}
		}

		private static List<VentTagCache> GetPooledList()
		{
			List<VentTagCache> result;
			if (_registrationPool.Count > 0)
			{
				int index = _registrationPool.Count - 1;
				result = _registrationPool[index];
				_registrationPool.RemoveAt(index);
			}
			else
			{
				result = new List<VentTagCache>();
			}
			return result;
		}

		private static void ReturnPooledList(List<VentTagCache> list)
		{
			list.Clear();
			_registrationPool.Add(list);
		}
	}
	public struct VentTagCache
	{
		public Vector3 TransformPosition;

		public Vector3 CenterPosition;

		public Vector3 AudioPosition;

		public NewNode Node;

		public NewRoom Room;
	}
	public class VentTagInteractable : MonoBehaviour
	{
		private void Start()
		{
			//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_0010: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)this).transform;
			Vector3 position = transform.position;
			Vector3 centerPosition = position;
			Vector3 audioPosition = position + transform.forward * 0.425f - transform.up * 0.375f;
			VentTagCache tag = default(VentTagCache);
			tag.TransformPosition = position;
			tag.CenterPosition = centerPosition;
			tag.AudioPosition = audioPosition;
			VentRegistry.QueueVentTagRegistration(tag);
		}
	}
	public class VentTagPeekable : MonoBehaviour
	{
		private void OnDestroy()
		{
			//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: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)this).transform;
			Vector3 position = transform.position;
			Vector3 val = position + transform.forward * 0.425f;
			Vector3 audioPosition = val - transform.up * 0.375f;
			VentTagCache tag = default(VentTagCache);
			tag.TransformPosition = position;
			tag.CenterPosition = val;
			tag.AudioPosition = audioPosition;
			VentRegistry.QueueVentTagRegistration(tag);
		}
	}
}
namespace Babbler.Implementation.Occlusion.Vents.Explorer
{
	public class DuctExplorer
	{
		private readonly Queue<AirDuctSection> _queue = new Queue<AirDuctSection>();

		private readonly HashSet<Vector3Int> _visited = new HashSet<Vector3Int>();

		private readonly List<Vector3Int> _results = new List<Vector3Int>();

		private List<AirDuctSection> _neighbors = new List<AirDuctSection>();

		private List<Vector3Int> _neighborOffsets = new List<Vector3Int>();

		private List<AirVent> _vents = new List<AirVent>();

		public void Reset()
		{
			_queue.Clear();
			_visited.Clear();
			_results.Clear();
			_neighbors.Clear();
			_vents.Clear();
		}

		public void StartExploration(AirDuctSection startSection)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			_queue.Enqueue(startSection);
			_visited.Add(startSection.duct);
		}

		public List<Vector3Int> TickExploration(AirDuctSection duct)
		{
			//IL_0088: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Invalid comparison between Unknown and I4
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			_results.Clear();
			if (_queue.Count <= 0)
			{
				return _results;
			}
			int count = _queue.Count;
			for (int i = 0; i < count; i++)
			{
				AirDuctSection val = _queue.Dequeue();
				GetVentInformation(val, ref _neighbors, ref _neighborOffsets, ref _vents);
				for (int j = 0; j < _neighbors.Count; j++)
				{
					AirDuctSection val2 = _neighbors[j];
					if (!_visited.Contains(val2.duct))
					{
						_queue.Enqueue(val2);
						_visited.Add(val2.duct);
					}
				}
				bool flag = false;
				foreach (AirVent vent in _vents)
				{
					if ((int)vent.ventType == 0)
					{
						_results.Add(val.node.nodeCoord);
						flag = true;
					}
					else
					{
						_results.Add(vent.roomNode.nodeCoord);
					}
				}
				if (val.peekSection && !flag)
				{
					_results.Add(val.node.nodeCoord);
				}
			}
			return _results;
		}

		private void GetVentInformation(AirDuctSection thisDuct, ref List<AirDuctSection> neighbors, ref List<Vector3Int> neighborOffsets, ref List<AirVent> vents)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Invalid comparison between Unknown and I4
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Invalid comparison between Unknown and I4
			neighbors.Clear();
			neighborOffsets.Clear();
			vents.Clear();
			AirDuctSection val2 = default(AirDuctSection);
			foreach (Vector3Int item in (Il2CppArrayBase<Vector3Int>)(object)CityData.Instance.offsetArrayX6)
			{
				Vector3Int val = thisDuct.duct + item;
				if (thisDuct.node.building.ductMap.TryGetValue(val, ref val2) && (item == thisDuct.next || item == thisDuct.previous || val2.next == -item || val2.previous == -item) && !neighbors.Contains(val2))
				{
					neighbors.Add(val2);
					neighborOffsets.Add(item);
				}
			}
			if (thisDuct.level == 2)
			{
				AirVent val3 = FindCeilingVent(thisDuct.node);
				if (val3 != null && !vents.Contains(val3))
				{
					vents.Add(val3);
				}
				return;
			}
			Vector3Int val4 = default(Vector3Int);
			NewNode foundNode = default(NewNode);
			foreach (Vector2Int item2 in (Il2CppArrayBase<Vector2Int>)(object)CityData.Instance.offsetArrayX4)
			{
				Vector2Int current2 = item2;
				((Vector3Int)(ref val4))..ctor(((Vector2Int)(ref current2)).x, ((Vector2Int)(ref current2)).y, 0);
				Vector3Int val5 = thisDuct.node.nodeCoord + val4;
				if (!PathFinder.Instance.nodeMap.TryGetValue(Vector3Int.op_Implicit(val5), ref foundNode))
				{
					continue;
				}
				AirVent val6 = FindWallVent(foundNode, thisDuct.node);
				if (val6 == null)
				{
					continue;
				}
				if ((int)val6.ventType == 1 && thisDuct.level == 1)
				{
					if (!vents.Contains(val6))
					{
						vents.Add(val6);
					}
				}
				else if ((int)val6.ventType == 2 && thisDuct.level == 0 && !vents.Contains(val6))
				{
					vents.Add(val6);
				}
			}
		}

		private AirVent FindCeilingVent(NewNode ductNode)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			Enumerator<AirVent> enumerator = ductNode.room.airVents.GetEnumerator();
			while (enumerator.MoveNext())
			{
				AirVent current = enumerator.Current;
				if (current.node.nodeCoord == ductNode.nodeCoord && (int)current.ventType == 0)
				{
					return current;
				}
			}
			return null;
		}

		private AirVent FindWallVent(NewNode foundNode, NewNode ductNode)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<AirVent> enumerator = foundNode.room.airVents.GetEnumerator();
			while (enumerator.MoveNext())
			{
				AirVent current = enumerator.Current;
				if (current.node.nodeCoord == ductNode.nodeCoord && current.roomNode.nodeCoord == foundNode.nodeCoord)
				{
					return current;
				}
			}
			return null;
		}
	}
}
namespace Babbler.Implementation.Hosts
{
	public class SpeakerHost : MonoBehaviour
	{
		public SpeakerHostPool Pool;

		public BaseSpeaker Speaker;

		private bool _initialized;

		private void OnDestroy()
		{
			Uninitialize();
		}

		public void Initialize()
		{
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			if (Pool.SpeakerType == SpeakerType.Speech)
			{
				switch (Pool.SpeechMode)
				{
				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;
				}
			}
			else
			{
				Speaker = new EmoteSpeaker();
			}
			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 Uninitialize()
		{
			if (_initialized)
			{
				BaseSpeaker speaker = Speaker;
				speaker.OnFinishedSpeaking = (Action)Delegate.Remove(speaker.OnFinishedSpeaking, new Action(OnFinishedSpeaking));
				Speaker.UninitializeSpeaker();
				_initialized = false;
			}
		}

		private void OnEnable()
		{
			if (Speaker != null)
			{
				Speaker.StopSpeaker();
			}
		}

		private void OnDisable()
		{
			if (Speaker != null)
			{
				Speaker.StopSpeaker();
			}
		}

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

		private void OnFinishedSpeaking()
		{
			Pool.ReleaseSpeakerHost(this);
		}
	}
	public class SpeakerHostPool
	{
		public static SpeakerHostPool Speech;

		public static SpeakerHostPool Emotes;

		private List<SpeakerHost> AvailableHosts = new List<SpeakerHost>();

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

		public SpeakerType SpeakerType { get; private set; }

		public SpeechMode SpeechMode { get; private set; }

		public static void InitializePools()
		{
			Speech = new SpeakerHostPool(SpeakerType.Speech, BabblerConfig.Mode.Value);
			Emotes = new SpeakerHostPool(SpeakerType.Emote, SpeechMode.Phonetic);
		}

		public static void UninitializePools()
		{
			Speech.CleanupSpeakerHosts();
			Emotes.CleanupSpeakerHosts();
		}

		private SpeakerHostPool(SpeakerType speakerType, SpeechMode speechMode)
		{
			SpeakerType = speakerType;
			SpeechMode = speechMode;
		}

		public void Play(string speechInput, SoundContext soundContext, Human speechPerson, float delay = 0f)
		{
			SpeakerHost speakerHost = GetSpeakerHost();
			if (delay > 0f && speakerHost.Speaker is IDelayableSpeaker delayableSpeaker)
			{
				delayableSpeaker.InitializeDelay(delay);
			}
			speakerHost.Speaker.StartSpeaker(speechInput, soundContext, speechPerson);
		}

		private SpeakerHost GetSpeakerHost()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_005a: 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)
			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);
				speakerHost.Pool = this;
				speakerHost.Initialize();
				Log($"Created speaker host, current count is {AllHosts.Count}.");
			}
			return speakerHost;
		}

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

		private 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);
			}
			Log("Cleaned up all speaker hosts.");
		}

		private void Log(string log)
		{
			bool flag = true;
		}
	}
}
namespace Babbler.Implementation.Emotes
{
	public class EmoteSound
	{
		public string Key;

		public string FilePath;

		public VoiceCategory Category;

		public float Frequency;

		public bool CanPitchShift;

		public Sound Sound;

		public float Length;

		public bool Released;
	}
	public class EmoteSoundFamily
	{
		private readonly List<EmoteSound> _allSounds = new List<EmoteSound>();

		private readonly List<EmoteSound> _maleSounds = new List<EmoteSound>();

		private readonly List<EmoteSound> _femaleSounds = new List<EmoteSound>();

		private readonly List<EmoteSound> _nonBinarySounds = new List<EmoteSound>();

		private static readonly List<EmoteSound>[] EmotePriorities = new List<EmoteSound>[4];

		public string Key { get; private set; }

		public bool HasMaleEmotes => _maleSounds.Count > 0;

		public bool HasFemaleEmotes => _femaleSounds.Count > 0;

		public bool HasNonBinaryEmotes => _nonBinarySounds.Count > 0;

		public void Initialize(string directory)
		{
			_allSounds.Clear();
			_maleSounds.Clear();
			_femaleSounds.Clear();
			_nonBinarySounds.Clear();
			if (!Directory.Exists(directory))
			{
				return;
			}
			Key = Path.GetFileNameWithoutExtension(directory).ToLowerInvariant();
			string[] files = Directory.GetFiles(directory, "*.wav");
			foreach (string filePath in files)
			{
				EmoteSound emoteSound = CreateEmoteSound(filePath, Key);
				if (emoteSound != null)
				{
					switch (emoteSound.Category)
					{
					case VoiceCategory.Male:
						_maleSounds.Add(emoteSound);
						break;
					case VoiceCategory.Female:
						_femaleSounds.Add(emoteSound);
						break;
					default:
						_nonBinarySounds.Add(emoteSound);
						break;
					}
					_allSounds.Add(emoteSound);
				}
			}
		}

		public void Uninitialize()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			foreach (EmoteSound allSound in _allSounds)
			{
				if (!allSound.Released)
				{
					((Sound)(ref allSound.Sound)).release();
					allSound.Released = true;
				}
			}
		}

		private EmoteSound CreateEmoteSound(string filePath, string key)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (!FMODRegistry.TryCreateSound(filePath, (MODE)16, out var sound))
			{
				return null;
			}
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
			string[] array = fileNameWithoutExtension.Split('_');
			if (array.Length != 3)
			{
				return null;
			}
			string text = array[1].ToLowerInvariant();
			string s = array[2].ToLowerInvariant();
			VoiceCategory category = VoiceCategory.NonBinary;
			bool canPitchShift = true;
			string text2 = text;
			string text3 = text2;
			if (!(text3 == "male"))
			{
				if (text3 == "female")
				{
					category = VoiceCategory.Female;
				}
			}
			else
			{
				category = VoiceCategory.Male;
			}
			if (!float.TryParse(s, out var result))
			{
				result = 178f;
				canPitchShift = false;
			}
			uint num = default(uint);
			((Sound)(ref sound)).getLength(ref num, (TIMEUNIT)1);
			float length = (float)num / 1000f;
			return new EmoteSound
			{
				Key = key,
				Category = category,
				Frequency = result,
				CanPitchShift = canPitchShift,
				FilePath = filePath,
				Sound = sound,
				Length = length,
				Released = false
			};
		}

		public EmoteSound GetRandomSound(VoiceCharacteristics characteristics)
		{
			return characteristics.SelectRandomGenderedListElement(EmotePriorities, _allSounds, _maleSounds, _femaleSounds, _nonBinarySounds);
		}
	}
	public static class EmoteSoundRegistry
	{
		private static readonly Dictionary<string, EmoteSoundFamily> Groups = new Dictionary<string, EmoteSoundFamily>();

		public static void Initialize()
		{
			Groups.Clear();
			if (BabblerConfig.EmotesEnabled.Value)
			{
				string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException(), "Emotes", BabblerConfig.EmotesTheme.Value);
				if (Directory.Exists(path))
				{
					string[] directories = Directory.GetDirectories(path);
					foreach (string directory in directories)
					{
						EmoteSoundFamily emoteSoundFamily = new EmoteSoundFamily();
						emoteSoundFamily.Initialize(directory);
						Groups.Add(emoteSoundFamily.Key, emoteSoundFamily);
					}
				}
			}
			Utilities.Log($"EmoteSoundRegistry has initialized! Sounds: {Groups.Count}", (LogLevel)32);
		}

		public static void Uninitialize()
		{
			foreach (EmoteSoundFamily value in Groups.Values)
			{
				value.Uninitialize();
			}
		}

		public static bool HasEmote(string key)
		{
			return Groups.ContainsKey(key);
		}

		public static bool TryGetEmote(string key, Human human, out VoiceCharacteristics characteristics, out EmoteSound sound)
		{
			if (!Groups.TryGetValue(key, out var value))
			{
				characteristics = default(VoiceCharacteristics);
				sound = null;
				return false;
			}
			characteristics = VoiceCharacteristics.Create(human, value.HasMaleEmotes, value.HasFemaleEmotes, value.HasNonBinaryEmotes);
			sound = value.GetRandomSound(characteristics);
			return true;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsEmoteRelevantBroadphase(Human human)
		{
			if (!BabblerConfig.EmotesEnabled.Value)
			{
				return false;
			}
			return OcclusionChecker.CheckOcclusion(human, (Human)(object)Player.Instance, SoundContext.OverheardEmote).State != OcclusionState.FullOcclusion;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool CanPlayIncidentals(Human human, bool mouthVocalization)
		{
			if (!BabblerConfig.IncidentalsEnabled.Value)
			{
				return false;
			}
			if (mouthVocalization && ((Actor)human).isSpeaking)
			{
				return false;
			}
			return !((Actor)human).isPlayer && !((Actor)human).isAsleep && !((Actor)human).isDead && !((Actor)human).isStunned;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool ShouldPlayUncouthEmote(Human human, float minThreshold, float maxThreshold)
		{
			float num = human.conscientiousness;
			float drunk = human.drunk;
			if (((Actor)human).isHome)
			{
				num /= 2f;
			}
			float num2 = 1f - Mathf.Min(num, 1f - drunk);
			float num3 = Mathf.Lerp(minThreshold, maxThreshold, num2);
			return Utilities.GlobalRandom.NextSingle() <= num3;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool ShouldPlayExpressiveEmote(Human human, float minThreshold, float maxThreshold)
		{
			float num = (human.extraversion + human.creativity) / 2f;
			float num2 = Mathf.Lerp(minThreshold, maxThreshold, num);
			return Utilities.GlobalRandom.NextSingle() <= num2;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool ShouldPlayExtravertedEmote(Human human, float minThreshold, float maxThreshold)
		{
			float num = Mathf.Lerp(minThreshold, maxThreshold, human.extraversion);
			return Utilities.GlobalRandom.NextSingle() <= num;
		}
	}
	public static class TVWatcher
	{
		private static AIActionPreset _turnOnTVPreset;

		public static void Initialize()
		{
			if (BabblerConfig.IncidentalsEnabled.Value)
			{
				Lib.Time.OnMinuteChanged -= Tick;
				Lib.Time.OnMinuteChanged += Tick;
			}
		}

		public static void Uninitialize()
		{
			if (BabblerConfig.IncidentalsEnabled.Value)
			{
				Lib.Time.OnMinuteChanged -= Tick;
			}
		}

		private static void Tick(object sender, TimeChangedArgs args)
		{
			if (Utilities.IsHumanOutside((Human)(object)Player.Instance))
			{
				return;
			}
			NewBuilding currentBuilding = ((Actor)Player.Instance).currentBuilding;
			if ((Object)(object)currentBuilding == (Object)null)
			{
				return;
			}
			NewRoom currentRoom = ((Actor)Player.Instance).currentRoom;
			if ((Object)(object)currentRoom == (Object)null)
			{
				return;
			}
			int floor = currentRoom.floor.floor;
			NewFloor val = default(NewFloor);
			for (int i = floor - 3; i <= floor + 3; i++)
			{
				if (!currentBuilding.floors.TryGetValue(i, ref val))
				{
					continue;
				}
				Enumerator<NewAddress> enumerator = val.addresses.GetEnumerator();
				while (enumerator.MoveNext())
				{
					NewAddress current = enumerator.Current;
					Enumerator<Actor> enumerator2 = ((NewGameLocation)current).currentOccupants.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						Actor current2 = enumerator2.Current;
						TickOccupant((Human)(object)((current2 is Human) ? current2 : null));
					}
				}
			}
		}

		private static void TickOccupant(Human occupant)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			if (!((Object)(object)occupant == (Object)null) && !((Actor)occupant).isPlayer && ((Actor)occupant).isHome && (int)((Actor)occupant).animationController.idleAnimationState == 1 && EmoteSoundRegistry.CanPlayIncidentals(occupant, mouthVocalization: true) && IsTelevisionOn(((Actor)occupant).currentRoom) && EmoteSoundRegistry.IsEmoteRelevantBroadphase(occupant) && EmoteSoundRegistry.ShouldPlayExtravertedEmote(occupant, BabblerConfig.IncidentalsMinTVChance.Value, BabblerConfig.IncidentalsMaxTVChance.Value))
			{
				switch (Utilities.GlobalRandom.Next(0, 2))
				{
				case 0:
					SpeakerHostPool.Emotes.Play("chuckle", SoundContext.OverheardEmote, occupant);
					break;
				case 1:
					SpeakerHostPool.Emotes.Play("gasp", SoundContext.OverheardEmote, occupant);
					break;
				}
			}
		}

		private static bool IsTelevisionOn(NewRoom room)
		{
			if ((SoCustomComparison)(object)_turnOnTVPreset == (SoCustomComparison)null)
			{
				Enumerator<AIActionPreset, List<Interactable>> enumerator = room.actionReference.GetEnumerator();
				while (enumerator.MoveNext())
				{
					KeyValuePair<AIActionPreset, List<Interactable>> current = enumerator.Current;
					if (((SoCustomComparison)current.Key).presetName != "TurnOnTV")
					{
						continue;
					}
					_turnOnTVPreset = current.Key;
					break;
				}
				if ((SoCustomComparison)(object)_turnOnTVPreset == (SoCustomComparison)null)
				{
					return false;
				}
			}
			List<Interactable> val = default(List<Interactable>);
			if (!room.actionReference.TryGetValue(_turnOnTVPreset, ref val))
			{
				return false;
			}
			Enumerator<Interactable> enumerator2 = val.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				Interactable current2 = enumerator2.Current;
				if (current2.sw0)
				{
					return true;
				}
			}
			return false;
		}
	}
}
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;

		public static ConfigEntry<bool> EmotesEnabled;

		public static ConfigEntry<string> EmotesTheme;

		public static ConfigEntry<float> EmotesMinStagger;

		public static ConfigEntry<float> EmotesMaxStagger;

		public static ConfigEntry<bool> EmotesUsePitchShifts;

		public static ConfigEntry<float> EmotesMinFrequencyMale;

		public static ConfigEntry<float> EmotesMaxFrequencyMale;

		public static ConfigEntry<float> EmotesMinFrequencyFemale;

		public static ConfigEntry<float> EmotesMaxFrequencyFemale;

		public static ConfigEntry<float> EmotesMinFrequencyNonBinary;

		public static ConfigEntry<float> EmotesMaxFrequencyNonBinary;

		private const string ExpectedVersion = "c30388124ff54e8b8c917064b221c11d";

		public static ConfigEntry<string> Version;

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<SpeechMode> Mode;

		public static ConfigEntry<ConfigTemplate> Template;

		public static ConfigEntry<bool> DistortPhoneSpeech;

		public static ConfigEntry<float> FemaleThreshold;

		public static ConfigEntry<float> MaleThreshold;

		public static ConfigEntry<float> GenderDiversity;

		public static ConfigEntry<bool> IncidentalsEnabled;

		public static ConfigEntry<float> IncidentalsRange;

		public static ConfigEntry<float> IncidentalsMinDrunkForHiccups;

		public static ConfigEntry<float> IncidentalsMinBurpChance;

		public static ConfigEntry<float> IncidentalsMaxBurpChance;

		public static ConfigEntry<float> IncidentalsMinFartChance;

		public static ConfigEntry<float> IncidentalsMaxFartChance;

		public static ConfigEntry<float> IncidentalsMinHiccupChance;

		public static ConfigEntry<float> IncidentalsMaxHiccupChance;

		public static ConfigEntry<float> IncidentalsMinWhistleChance;

		public static ConfigEntry<float> IncidentalsMaxWhistleChance;

		public static ConfigEntry<float> IncidentalsMinTVChance;

		public static ConfigEntry<float> IncidentalsMaxTVChance;

		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;

		public static ConfigEntry<float> ConversationalVolume;

		public static ConfigEntry<float> ConversationalShoutVolume;

		public static ConfigEntry<float> ConversationalEmoteVolume;

		public static ConfigEntry<float> OverheardVolume;

		public static ConfigEntry<float> OverheardShoutVolume;

		public static ConfigEntry<float> OverheardEmoteVolume;

		public static ConfigEntry<float> PhoneVolume;

		public static ConfigEntry<float> PhoneShoutVolume;

		public static ConfigEntry<float> PhoneEmoteVolume;

		public static ConfigEntry<float> OpenDoorOcclusionMultiplier;

		public static ConfigEntry<float> ClosedDoorOcclusionMultiplier;

		public static ConfigEntry<float> VentOcclusionMultiplier;

		public static ConfigEntry<float> DistantOcclusionMultiplier;

		public static ConfigEntry<bool> OcclusionEnabled;

		public static ConfigEntry<int> OcclusionNodeRange;

		public static ConfigEntry<int> OcclusionVentRange;

		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);
		}

		private 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;
		}

		private static void InitializeEmotes(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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			EmotesEnabled = config.Bind<bool>("7. Emotes", "Enabled", true, new ConfigDescription("Whether emote sound effects (like sneezing, sighing, or coughing) are enabled.", (AcceptableValueBase)null, Array.Empty<object>()));
			EmotesTheme = config.Bind<string>("7. Emotes", "Theme", "Realistic", new ConfigDescription("Which theme to load and play for emote sound effects. Babbler comes with \"Realistic\" and \"Abstract\" but you can