Decompiled source of mszguns v2.0.1
Mods/mszguns.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Il2Cpp; using Il2CppDG.Tweening; using Il2CppDG.Tweening.Core; using Il2CppDG.Tweening.Plugins.Options; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using InventoryFramework; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using MultiSide.shared; using NAudio.Wave; using Newtonsoft.Json; using UnityEngine; using VGltf; using VGltf.Types; using mszguns; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "Miside Zero AK47", "2.0.0", "gameknight963", null)] [assembly: MelonOptionalDependencies(new string[] { "Multiside.shared" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("mszguns")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ea64eccaf8e04528403e11d3d55c582edd51a6b1")] [assembly: AssemblyProduct("mszguns")] [assembly: AssemblyTitle("mszguns")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.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 NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 mszguns { public static class AudioImporter { public static AudioClip Load(string filePath) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (!File.Exists(filePath)) { throw new FileNotFoundException(filePath); } AudioFileReader val = new AudioFileReader(filePath); try { int channels = ((WaveStream)val).WaveFormat.Channels; int sampleRate = ((WaveStream)val).WaveFormat.SampleRate; float[] array = ReadAllSamples(val); AudioClip val2 = AudioClip.Create(Path.GetFileNameWithoutExtension(filePath), array.Length / channels, channels, sampleRate, false); val2.SetData(Il2CppStructArray<float>.op_Implicit(array), 0); return val2; } finally { ((IDisposable)val)?.Dispose(); } } private static float[] ReadAllSamples(AudioFileReader reader) { List<float> list = new List<float>((int)(((Stream)(object)reader).Length / 4)); float[] array = new float[4096]; int num; while ((num = reader.Read(array, 0, array.Length)) > 0) { for (int i = 0; i < num; i++) { list.Add(array[i]); } } return list.ToArray(); } } public class Core : MelonMod { private List<Gun> guns = new List<Gun>(); private List<GameObject> gunObjects = new List<GameObject>(); private List<AudioClip> gunShots = new List<AudioClip>(); private List<AudioSource> gunSources = new List<AudioSource>(); private static Gun? activeGun; private GameObject? activeGunObject; private AudioSource? activeSource; private SettingsManager? settingsManager; private float fireTimer = 0f; private const string MoveTweenId = "gun_move"; private const string RotateTweenId = "gun_rotate"; public static string ModResources { get; set; } = Path.Combine(MelonEnvironment.ModsDirectory, "mszguns"); public static string? ActiveGunId => activeGun?.Id; public static Texture2D? BulletHoleTexture { get; private set; } public override void OnInitializeMelon() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown guns = GunLoader.LoadAll(ModResources); foreach (Gun gun in guns) { InventoryManager.Instance.RegisterItem(new ItemDefinition(gun.Id, gun.DisplayName, LoadSprite(GunLoader.GetIconPath(ModResources, gun)))); } InventoryManager.Instance.OnItemSelected += Instance_OnItemSelected; BulletHoleTexture = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(BulletHoleTexture, Il2CppStructArray<byte>.op_Implicit(File.ReadAllBytes(GunLoader.GetDefaultHolePath(ModResources)))); ((Object)BulletHoleTexture).hideFlags = (HideFlags)32; GunNetworking.Init(ModResources, guns, ((MelonBase)this).LoggerInstance); } public override void OnLateInitializeMelon() { settingsManager = Void.instance.settings; } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { //IL_0087: 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) //IL_00ad: 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_00bd: Unknown result type (might be due to invalid IL or missing references) if (sceneName != "Version 1.9 POST") { return; } Transform transform = ((Component)Camera.main).transform; gunObjects.Clear(); gunShots.Clear(); gunSources.Clear(); foreach (Gun gun in guns) { GameObject val = GunLoader.LoadGun(GunLoader.GetModelPath(ModResources, gun)); val.transform.parent = transform; val.transform.eulerAngles = transform.eulerAngles; val.transform.position = transform.position; Transform transform2 = val.transform; transform2.localPosition += gun.NormalPosition.ToVector3(); val.active = false; AudioClip val2 = AudioImporter.Load(GunLoader.GetAudioPath(ModResources, gun)); AudioSource val3 = val.AddComponent<AudioSource>(); val3.clip = val2; val3.volume = gun.AudioVolume; val3.playOnAwake = false; gunObjects.Add(val); gunShots.Add(val2); gunSources.Add(val3); } } public override void OnUpdate() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (activeGun == null || (Object)(object)activeGunObject == (Object)null) { return; } InventoryItem selectedItem = InventoryManager.Instance.SelectedItem; if (!(((selectedItem != null) ? selectedItem.Definition.Id : null) != activeGun.Id)) { if (Input.GetMouseButtonDown(1)) { DOTween.Kill(Object.op_Implicit("gun_move"), false); TweenSettingsExtensions.SetId<TweenerCore<Vector3, Vector3, VectorOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOLocalMove(activeGunObject.transform, activeGun.AdsPosition.ToVector3(), activeGun.AdsSpeed, false), (Ease)6), "gun_move"); TweenSettingsExtensions.SetId<TweenerCore<float, float, FloatOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<float, float, FloatOptions>>(ShortcutExtensions.DOFieldOfView(Camera.main, activeGun.AdsFov, activeGun.AdsSpeed), (Ease)6), "gun_move"); } if (Input.GetMouseButtonUp(1)) { DOTween.Kill(Object.op_Implicit("gun_move"), false); TweenSettingsExtensions.SetId<TweenerCore<Vector3, Vector3, VectorOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOLocalMove(activeGunObject.transform, activeGun.NormalPosition.ToVector3(), activeGun.AdsSpeed, false), (Ease)6), "gun_move"); TweenSettingsExtensions.SetId<TweenerCore<float, float, FloatOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<float, float, FloatOptions>>(ShortcutExtensions.DOFieldOfView(Camera.main, settingsManager.fov, activeGun.AdsSpeed), (Ease)6), "gun_move"); } if (Input.GetMouseButton(0) && fireTimer <= 0f) { fireTimer = activeGun.FireRate; Shoot(activeGun, activeGunObject, activeSource, BulletHoleTexture); } fireTimer -= Time.deltaTime; } } private void Shoot(Gun gun, GameObject gunObject, AudioSource source, Texture2D holeTexture) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: 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_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) Gun gun2 = gun; Texture2D holeTexture2 = holeTexture; GameObject gunObject2 = gunObject; source.PlayOneShot(source.clip); switch (gun2.Effect) { case ShotEffect.Normal: { RaycastHit hit = default(RaycastHit); if (Physics.Raycast(((Component)Camera.main).transform.position, ((Component)Camera.main).transform.forward, ref hit, gun2.Range)) { SpawnBulletHole(hit, holeTexture2, gun2.BulletHoleDuration); GunNetworking.Instance?.SendShot(ShotEffect.Normal, ((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, gun2.BulletHoleDuration); } GunNetworking.Instance?.SendFireAudioMessage(); break; } case ShotEffect.Shotgun: Enumerable.Range(0, 8).ToList().ForEach(delegate { //IL_000b: 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) //IL_003d: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0092: Unknown result type (might be due to invalid IL or missing references) Vector3 val3 = ((Component)Camera.main).transform.forward + new Vector3(Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f), 0f); RaycastHit hit2 = default(RaycastHit); if (Physics.Raycast(((Component)Camera.main).transform.position, val3, ref hit2, gun2.Range)) { SpawnBulletHole(hit2, holeTexture2, gun2.BulletHoleDuration); GunNetworking.Instance?.SendShot(ShotEffect.Shotgun, ((RaycastHit)(ref hit2)).point, ((RaycastHit)(ref hit2)).normal, gun2.BulletHoleDuration); } }); GunNetworking.Instance?.SendFireAudioMessage(); break; case ShotEffect.Cube: { GameObject val = GameObject.CreatePrimitive((PrimitiveType)3); val.transform.position = ((Component)Camera.main).transform.position + ((Component)Camera.main).transform.forward; val.transform.localScale = Vector3.one * 0.2f; Rigidbody val2 = val.AddComponent<Rigidbody>(); val2.velocity = ((Component)Camera.main).transform.forward * 20f; Object.Destroy((Object)(object)val, 5f); GunNetworking.Instance?.SendShot(ShotEffect.Cube, ((Component)Camera.main).transform.position + ((Component)Camera.main).transform.forward, ((Component)Camera.main).transform.forward, 0f); GunNetworking.Instance?.SendFireAudioMessage(); break; } } DOTween.Kill(Object.op_Implicit("gun_rotate"), false); TweenSettingsExtensions.OnComplete<TweenerCore<Quaternion, Vector3, QuaternionOptions>>(TweenSettingsExtensions.SetId<TweenerCore<Quaternion, Vector3, QuaternionOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Quaternion, Vector3, QuaternionOptions>>(ShortcutExtensions.DOLocalRotate(gunObject2.transform, gun2.RecoilAngle.ToVector3(), gun2.RecoilKickDuration, (RotateMode)0), (Ease)6), "gun_rotate"), TweenCallback.op_Implicit((Action)delegate { //IL_0017: Unknown result type (might be due to invalid IL or missing references) TweenSettingsExtensions.SetId<TweenerCore<Quaternion, Vector3, QuaternionOptions>>(TweenSettingsExtensions.SetEase<TweenerCore<Quaternion, Vector3, QuaternionOptions>>(ShortcutExtensions.DOLocalRotate(gunObject2.transform, gun2.NormalAngle.ToVector3(), gun2.RecoilRecoverDuration, (RotateMode)0), (Ease)6), "gun_rotate"); })); } private void Instance_OnItemSelected(InventoryItem? item) { InventoryItem item2 = item; if ((Object)(object)Camera.main == (Object)null) { return; } foreach (GameObject gunObject in gunObjects) { gunObject.active = false; } if (item2 == null) { activeGun = null; activeGunObject = null; activeSource = null; Camera.main.fieldOfView = settingsManager.fov; GunNetworking.Instance?.SendEquip(null); return; } int num = guns.FindIndex((Gun g) => g.Id == item2.Definition.Id); if (num != -1) { activeGun = guns[num]; activeGunObject = gunObjects[num]; activeSource = gunSources[num]; activeGunObject.active = true; fireTimer = 0f; GunNetworking.Instance?.SendEquip(activeGun.Id); } } internal static void SpawnBulletHole(Vector3 point, Vector3 normal, Texture2D texture, float duration) { //IL_002f: 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_0036: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00e3: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) GameObject hole = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)hole).name = "bullet hole"; hole.transform.position = point + normal * 0.01f; hole.transform.rotation = Quaternion.LookRotation(-normal); hole.transform.Rotate(0f, 0f, Random.Range(0f, 360f)); hole.transform.localScale = Vector3.one * Random.Range(0.1f, 0.3f); Object.Destroy((Object)(object)hole.GetComponent<MeshCollider>()); MeshRenderer component = hole.GetComponent<MeshRenderer>(); Material val = new Material(Shader.Find("Unlit/Transparent")); val.SetTexture("_MainTex", (Texture)(object)texture); ((Renderer)component).material = val; TweenSettingsExtensions.OnComplete<TweenerCore<Color, Color, ColorOptions>>(TweenSettingsExtensions.SetDelay<TweenerCore<Color, Color, ColorOptions>>(ShortcutExtensions.DOColor(((Renderer)component).material, new Color(1f, 1f, 1f, 0f), 1f), duration), TweenCallback.op_Implicit((Action)delegate { Object.Destroy((Object)(object)hole); })); } private static void SpawnBulletHole(RaycastHit hit, Texture2D texture, float duration) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) SpawnBulletHole(((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, texture, duration); } public Sprite LoadSprite(string path) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0038: 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) byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } public static class Extensions { public static Vector3 ToVector3(this float[] arr) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) return new Vector3(arr[0], arr[1], arr[2]); } public static Transform? FindRecursive(this Transform parent, string name) { for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (((Object)child).name == name) { return child; } Transform val = child.FindRecursive(name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } internal static class GltfHelpers { public static void BuildNode(GltfContainer container, int nodeIndex, Transform parent) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown Node val = container.Gltf.Nodes[nodeIndex]; GameObject val2 = new GameObject(((GltfChildOfRootProperty)val).Name ?? "Node"); val2.transform.SetParent(parent, false); if (val.Mesh.HasValue) { var (sharedMesh, num) = BuildMesh(container, val.Mesh.Value); val2.AddComponent<MeshFilter>().sharedMesh = sharedMesh; MeshRenderer val3 = val2.AddComponent<MeshRenderer>(); Material val4 = new Material(Shader.Find("Standard")); if (num.HasValue) { Texture2D val5 = LoadTexture(container, num.Value); if ((Object)(object)val5 != (Object)null) { val4.mainTexture = (Texture)(object)val5; } } ((Renderer)val3).material = val4; } if (val.Children != null) { int[] children = val.Children; foreach (int nodeIndex2 in children) { BuildNode(container, nodeIndex2, val2.transform); } } } public static (Mesh, int?) BuildMesh(GltfContainer container, int meshIndex) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Mesh val = container.Gltf.Meshes[meshIndex]; Mesh val2 = new Mesh(); PrimitiveType val3 = val.Primitives[0]; int accessorIndex = val3.Attributes["POSITION"]; Vector3[] array = ReadVec3Array(container, accessorIndex); val2.vertices = Il2CppStructArray<Vector3>.op_Implicit(array); if (val3.Attributes.ContainsKey("TEXCOORD_0")) { int accessorIndex2 = val3.Attributes["TEXCOORD_0"]; Vector2[] array2 = ReadVec2Array(container, accessorIndex2); val2.uv = Il2CppStructArray<Vector2>.op_Implicit(array2); } if (val3.Indices.HasValue) { int[] array3 = ReadIntArray(container, val3.Indices.Value); for (int i = 0; i < array3.Length; i += 3) { ref int reference = ref array3[i + 2]; ref int reference2 = ref array3[i]; int num = array3[i]; int num2 = array3[i + 2]; reference = num; reference2 = num2; } val2.triangles = Il2CppStructArray<int>.op_Implicit(array3); } val2.RecalculateNormals(); val2.RecalculateBounds(); return (val2, val3.Material); } public static Texture2D? LoadTexture(GltfContainer container, int materialIndex) { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown Material val = container.Gltf.Materials[materialIndex]; if (val.PbrMetallicRoughness?.BaseColorTexture == null) { return null; } int index = ((TextureInfo)val.PbrMetallicRoughness.BaseColorTexture).Index; Texture val2 = container.Gltf.Textures[index]; if (!val2.Source.HasValue) { return null; } Image val3 = container.Gltf.Images[val2.Source.Value]; if (!val3.BufferView.HasValue) { return null; } BufferView val4 = container.Gltf.BufferViews[val3.BufferView.Value]; byte[] sourceArray = container.Buffer.Payload.ToArray(); byte[] array = new byte[val4.ByteLength]; Array.Copy(sourceArray, val4.ByteOffset, array, 0, val4.ByteLength); Texture2D val5 = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val5, Il2CppStructArray<byte>.op_Implicit(array)); return val5; } public static Vector2[] ReadVec2Array(GltfContainer container, int accessorIndex) { //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) Accessor val = container.Gltf.Accessors[accessorIndex]; BufferView val2 = container.Gltf.BufferViews[val.BufferView.Value]; byte[] value = container.Buffer.Payload.ToArray(); int num = val2.ByteOffset + val.ByteOffset; Vector2[] array = (Vector2[])(object)new Vector2[val.Count]; for (int i = 0; i < val.Count; i++) { float num2 = BitConverter.ToSingle(value, num + i * 8); float num3 = BitConverter.ToSingle(value, num + i * 8 + 4); array[i] = new Vector2(num2, 1f - num3); } return array; } public static Vector3[] ReadVec3Array(GltfContainer container, int accessorIndex) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) Accessor val = container.Gltf.Accessors[accessorIndex]; BufferView val2 = container.Gltf.BufferViews[val.BufferView.Value]; byte[] value = container.Buffer.Payload.ToArray(); int num = val2.ByteOffset + val.ByteOffset; Vector3[] array = (Vector3[])(object)new Vector3[val.Count]; for (int i = 0; i < val.Count; i++) { float num2 = BitConverter.ToSingle(value, num + i * 12); float num3 = BitConverter.ToSingle(value, num + i * 12 + 4); float num4 = BitConverter.ToSingle(value, num + i * 12 + 8); array[i] = new Vector3(0f - num2, num3, num4); } return array; } public static int[] ReadIntArray(GltfContainer container, int accessorIndex) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 Accessor val = container.Gltf.Accessors[accessorIndex]; BufferView val2 = container.Gltf.BufferViews[val.BufferView.Value]; byte[] value = container.Buffer.Payload.ToArray(); int num = val2.ByteOffset + val.ByteOffset; int[] array = new int[val.Count]; for (int i = 0; i < val.Count; i++) { if ((int)val.ComponentType == 5123) { array[i] = BitConverter.ToUInt16(value, num + i * 2); } else if ((int)val.ComponentType == 5125) { array[i] = (int)BitConverter.ToUInt32(value, num + i * 4); } } return array; } } public class Grip { public string BoneName { get; set; } = ""; public float PositionWeight { get; set; } = 1f; public float RotationWeight { get; set; } = 1f; } public class Gun { public int[] Version { get; set; } = new int[3] { 1, 0, 0 }; public string Id { get; set; } = ""; public string DisplayName { get; set; } = ""; public string ModelFile { get; set; } = ""; public string? AudioFile { get; set; } public string? IconFile { get; set; } public string? HoleFile { get; set; } public float FireRate { get; set; } = 0.1f; public float AudioVolume { get; set; } = 0.5f; public float Damage { get; set; } = 10f; public float Range { get; set; } = 100f; public float AdsSpeed { get; set; } = 0.2f; public float AdsFov { get; set; } = 50f; public float RecoilKickDuration { get; set; } = 0.05f; public float RecoilRecoverDuration { get; set; } = 0.15f; public float BulletHoleDuration { get; set; } = 10f; public float[] NormalPosition { get; set; } = new float[3]; public float[] AdsPosition { get; set; } = new float[3]; public float[] NormalAngle { get; set; } = new float[3]; public float[] RecoilAngle { get; set; } = new float[3]; public ShotEffect Effect { get; set; } = ShotEffect.Normal; } internal static class GunLoader { public static List<Gun> LoadAll(string modResources) { List<Gun> list = new List<Gun>(); string[] directories = Directory.GetDirectories(modResources); foreach (string text in directories) { string path = Path.Combine(text, "gun.json"); if (File.Exists(path)) { Gun gun = JsonConvert.DeserializeObject<Gun>(File.ReadAllText(path)); if (string.IsNullOrEmpty(gun.Id)) { gun.Id = Path.GetFileName(text); } Gun gun2 = gun; if (gun2.ModelFile == null) { Gun gun3 = gun2; string? obj = Directory.GetFiles(text, "*.glb").FirstOrDefault() ?? ""; string text2 = obj; gun3.ModelFile = obj; } gun2 = gun; if (gun2.AudioFile == null) { Gun gun4 = gun2; string? obj2 = Directory.GetFiles(text, "*.wav").FirstOrDefault() ?? Directory.GetFiles(text, "*.mp3").FirstOrDefault(); string text2 = obj2; gun4.AudioFile = obj2; } gun2 = gun; if (gun2.IconFile == null) { Gun gun5 = gun2; string? obj3 = Directory.GetFiles(text, "icon.*").FirstOrDefault() ?? Directory.GetFiles(text, "*.png").FirstOrDefault(); string text2 = obj3; gun5.IconFile = obj3; } gun2 = gun; if (gun2.HoleFile == null) { string text2 = (gun2.HoleFile = Directory.GetFiles(text, "hole.*").FirstOrDefault()); } list.Add(gun); } } return list; } public static GameObject LoadGun(string path) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) GltfContainer val; using (FileStream fileStream = new FileStream(path, FileMode.Open)) { val = GltfContainer.FromGlb((Stream)fileStream); } GameObject val2 = new GameObject("Gun"); if (val.Gltf.Scene.HasValue) { int[] nodes = val.Gltf.Scenes[val.Gltf.Scene.Value].Nodes; foreach (int nodeIndex in nodes) { GltfHelpers.BuildNode(val, nodeIndex, val2.transform); } } val2.transform.localScale = Vector3.one * 0.075f; return val2; } public static string GetModelPath(string modResources, Gun gun) { return Path.IsPathRooted(gun.ModelFile) ? gun.ModelFile : Path.Combine(modResources, gun.Id, gun.ModelFile); } public static string GetAudioPath(string modResources, Gun gun) { return (gun.AudioFile != null && Path.IsPathRooted(gun.AudioFile)) ? gun.AudioFile : Fallback(modResources, gun.Id, gun.AudioFile ?? "shot.wav", "shot.wav"); } public static string GetIconPath(string modResources, Gun gun) { return (gun.IconFile != null && Path.IsPathRooted(gun.IconFile)) ? gun.IconFile : Fallback(modResources, gun.Id, gun.IconFile ?? "icon.png", "icon.png"); } public static string GetHolePath(string modResources, Gun gun) { return (gun.HoleFile != null && Path.IsPathRooted(gun.HoleFile)) ? gun.HoleFile : Fallback(modResources, gun.Id, gun.HoleFile ?? "hole.png", "hole.png"); } public static string GetDefaultHolePath(string modResources) { return Path.Combine(modResources, "hole.png"); } private static string Fallback(string modResources, string gunId, string file, string fallback) { string text = Path.Combine(modResources, gunId, file); return File.Exists(text) ? text : Path.Combine(modResources, fallback); } } public class GunNetworking { private class GunNetworkLogger { [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private Instance <logger>P; public bool _loggingEnabled; public GunNetworkLogger(Instance logger) { <logger>P = logger; _loggingEnabled = false; base..ctor(); } public void SetLoggingEnabled(bool enabled) { _loggingEnabled = enabled; } public void Msg(object obj) { if (_loggingEnabled) { <logger>P.Msg(obj); } } public void Warning(object obj) { if (_loggingEnabled) { <logger>P.Warning(obj); } } public void Error(object obj) { if (_loggingEnabled) { <logger>P.Warning(obj); } } } private readonly Dictionary<int, string> _remoteGuns = new Dictionary<int, string>(); private readonly Dictionary<int, Dictionary<string, GameObject>> _remoteGunObjects = new Dictionary<int, Dictionary<string, GameObject>>(); private readonly string _modResources; private readonly List<Gun> _guns; private GunNetworkLogger? _logger; private bool _loggingEnabled = false; public static GunNetworking? Instance { get; private set; } public bool LoggingEnabled { get { return _loggingEnabled; } set { _loggingEnabled = value; _logger?.SetLoggingEnabled(value); } } private GunNetworking(string modResources, List<Gun> guns) { _modResources = modResources; _guns = guns; } public static void Init(string modResources, List<Gun> guns, Instance logger) { if (AppDomain.CurrentDomain.GetAssemblies().Any((Assembly a) => a.GetName().Name == "Multiside.shared")) { Instance = new GunNetworking(modResources, guns); Instance._logger = new GunNetworkLogger(logger); Instance._logger.SetLoggingEnabled(Instance.LoggingEnabled); Instance._logger.Msg("Starting in Online mode"); Instance.InitNetwork(); } } private void InitNetwork() { if (NetworkRegistry.Provider != null) { Subscribe(NetworkRegistry.Provider); } else { NetworkRegistry.OnProviderRegistered += Subscribe; } } private void Subscribe(INetworkProvider provider) { INetworkProvider provider2 = provider; _logger?.Msg("GunNetworking: subscribing to network events"); provider2.OnReceived += delegate(int actor, string channel, object data) { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) if (channel == "mszguns.equip") { string text = (string)data; _logger?.Msg($"GunNetworking: equip received from {actor}: '{text}'"); if (string.IsNullOrEmpty(text)) { _remoteGuns.Remove(actor); } else { _remoteGuns[actor] = text; } GameObject playerObject = provider2.GetPlayerObject(actor); if ((Object)(object)playerObject == (Object)null) { _logger?.Warning($"GunNetworking: no player object for actor {actor}"); } else { SetRemoteGun(actor, playerObject, text); } } else if (channel == "mszguns.audio") { GameObject playerObject2 = provider2.GetPlayerObject(actor); if ((Object)(object)playerObject2 != (Object)null) { PlayRemoteShot(playerObject2); } } else if (!(channel != "mszguns.shot")) { float[] array = (float[])data; ShotEffect shotEffect = (ShotEffect)array[7]; if (shotEffect == ShotEffect.Cube) { SpawnRemoteCube(new Vector3(array[0], array[1], array[2]), new Vector3(array[3], array[4], array[5])); } else if (array.Length >= 7 && !((Object)(object)Core.BulletHoleTexture == (Object)null)) { Core.SpawnBulletHole(new Vector3(array[0], array[1], array[2]), new Vector3(array[3], array[4], array[5]), Core.BulletHoleTexture, array[6]); } } }; provider2.OnPlayerLeft += delegate(int actor) { _logger?.Msg($"GunNetworking: player {actor} left, cleaning up"); _remoteGuns.Remove(actor); _remoteGunObjects.Remove(actor); }; provider2.OnRoomJoined += delegate { _logger?.Msg("GunNetworking: room joined, broadcasting equip: '" + Core.ActiveGunId + "'"); SendEquip(Core.ActiveGunId); }; provider2.OnPlayerJoined += delegate(int actor) { _logger?.Msg($"GunNetworking: player {actor} joined, sending equip: '{Core.ActiveGunId}'"); if (!string.IsNullOrEmpty(Core.ActiveGunId)) { provider2.SendTo(actor, "mszguns.equip", (object)Core.ActiveGunId, true); } }; } public void SendFireAudioMessage() { INetworkProvider provider = NetworkRegistry.Provider; if (provider != null) { provider.Send("mszguns.audio", (object)(-1), true); } } private void SetRemoteGun(int actor, GameObject playerObj, string gunId) { //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) string gunId2 = gunId; _logger?.Msg($"GunNetworking: setting remote gun for actor {actor}: '{gunId2}'"); if (_remoteGunObjects.TryGetValue(actor, out Dictionary<string, GameObject> value)) { foreach (GameObject value3 in value.Values) { value3.SetActive(false); } if (!string.IsNullOrEmpty(gunId2) && value.TryGetValue(gunId2, out var value2)) { _logger?.Msg("GunNetworking: using cached model for '" + gunId2 + "'"); value2.SetActive(true); UpdateAudioClip(playerObj, gunId2); return; } } if (string.IsNullOrEmpty(gunId2)) { return; } Gun gun = _guns.FirstOrDefault((Gun g) => g.Id == gunId2); if (gun == null) { _logger?.Warning("GunNetworking: gun '" + gunId2 + "' not found in registry"); return; } _logger?.Msg("GunNetworking: loading model for '" + gunId2 + "'"); GameObject val = GunLoader.LoadGun(GunLoader.GetModelPath(_modResources, gun)); ((Object)val).name = "RemoteGun"; Transform val2 = playerObj.transform.Find("Zero/PLAYER Armature/Rig Root/Hips/Spine/Chest/Neck2/Neck1/Head/CameraHoldHead/playerCamera"); if ((Object)(object)val2 == (Object)null) { _logger?.Warning($"GunNetworking: could not find camera transform on actor {actor}, parenting to root"); } val.transform.SetParent(val2 ?? playerObj.transform, false); val.transform.localPosition = gun.NormalPosition.ToVector3(); val.transform.localEulerAngles = gun.NormalAngle.ToVector3(); if (!_remoteGunObjects.ContainsKey(actor)) { _remoteGunObjects[actor] = new Dictionary<string, GameObject>(); } _remoteGunObjects[actor][gunId2] = val; UpdateAudioClip(playerObj, gunId2); } private void UpdateAudioClip(GameObject playerObj, string gunId) { string gunId2 = gunId; Gun gun = _guns.FirstOrDefault((Gun g) => g.Id == gunId2); if (gun == null) { _logger?.Warning("HandleGunAudio: gun '" + gunId2 + "' not found"); return; } AudioSource val = playerObj.GetComponent<AudioSource>(); if ((Object)(object)val == (Object)null) { _logger?.Msg("GunNetworking: adding AudioSource to player object for '" + gunId2 + "'"); val = playerObj.AddComponent<AudioSource>(); val.spatialBlend = 1f; val.maxDistance = 50f; val.rolloffMode = (AudioRolloffMode)1; } if ((Object)(object)val.clip == (Object)null || ((Object)val.clip).name != gun.Id) { val.clip = AudioImporter.Load(GunLoader.GetAudioPath(_modResources, gun)); } } private void PlayRemoteShot(GameObject playerObj) { AudioSource component = playerObj.GetComponent<AudioSource>(); component.PlayOneShot(component.clip); } private static void SpawnRemoteCube(Vector3 spawnPos, Vector3 spawnDir) { //IL_000e: 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_0025: 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_003e: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)3); val.transform.position = spawnPos; val.transform.localScale = Vector3.one * 0.2f; Rigidbody val2 = val.AddComponent<Rigidbody>(); val2.velocity = spawnDir * 20f; Object.Destroy((Object)(object)val, 5f); } public void SendShot(ShotEffect effect, Vector3 pos, Vector3 dir, float duration) { //IL_0019: 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_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) INetworkProvider provider = NetworkRegistry.Provider; if (provider != null) { provider.Send("mszguns.shot", (object)new float[8] { pos.x, pos.y, pos.z, dir.x, dir.y, dir.z, duration, (float)effect }, true); } } public void SendEquip(string? gunId) { INetworkProvider provider = NetworkRegistry.Provider; if (provider != null) { provider.Send("mszguns.equip", (object)(gunId ?? ""), true); } } } public enum ShotEffect { Normal, Shotgun, Cube } }
UserLibs/NAudio.Core.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using NAudio.Dmo; using NAudio.Dsp; using NAudio.FileFormats.Wav; using NAudio.Utils; using NAudio.Wave; using NAudio.Wave.SampleProviders; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Mark Heath")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Mark Heath 2026")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0+c89fee940ee6f8d7374d18714a6b85d8b7a18ab0")] [assembly: AssemblyProduct("NAudio.Core")] [assembly: AssemblyTitle("NAudio.Core")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NAudio")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.3.0.0")] [module: UnverifiableCode] namespace NAudio { public enum Manufacturers { Microsoft = 1, Creative = 2, Mediavision = 3, Fujitsu = 4, Artisoft = 20, TurtleBeach = 21, Ibm = 22, Vocaltec = 23, Roland = 24, DspSolutions = 25, Nec = 26, Ati = 27, Wanglabs = 28, Tandy = 29, Voyetra = 30, Antex = 31, IclPS = 32, Intel = 33, Gravis = 34, Val = 35, Interactive = 36, Yamaha = 37, Everex = 38, Echo = 39, Sierra = 40, Cat = 41, Apps = 42, DspGroup = 43, Melabs = 44, ComputerFriends = 45, Ess = 46, Audiofile = 47, Motorola = 48, Canopus = 49, Epson = 50, Truevision = 51, Aztech = 52, Videologic = 53, Scalacs = 54, Korg = 55, Apt = 56, Ics = 57, Iteratedsys = 58, Metheus = 59, Logitech = 60, Winnov = 61, Ncr = 62, Exan = 63, Ast = 64, Willowpond = 65, Sonicfoundry = 66, Vitec = 67, Moscom = 68, Siliconsoft = 69, Supermac = 73, Audiopt = 74, Speechcomp = 76, Ahead = 77, Dolby = 78, Oki = 79, Auravision = 80, Olivetti = 81, Iomagic = 82, Matsushita = 83, Controlres = 84, Xebec = 85, Newmedia = 86, Nms = 87, Lyrrus = 88, Compusic = 89, Opti = 90, Adlacc = 91, Compaq = 92, Dialogic = 93, Insoft = 94, Mptus = 95, Weitek = 96, LernoutAndHauspie = 97, Qciar = 98, Apple = 99, Digital = 100, Motu = 101, Workbit = 102, Ositech = 103, Miro = 104, Cirruslogic = 105, Isolution = 106, Horizons = 107, Concepts = 108, Vtg = 109, Radius = 110, Rockwell = 111, Xyz = 112, Opcode = 113, Voxware = 114, NorthernTelecom = 115, Apicom = 116, Grande = 117, Addx = 118, Wildcat = 119, Rhetorex = 120, Brooktree = 121, Ensoniq = 125, Fast = 126, Nvidia = 127, Oksori = 128, Diacoustics = 129, Gulbransen = 130, KayElemetrics = 131, Crystal = 132, SplashStudios = 133, Quarterdeck = 134, Tdk = 135, DigitalAudioLabs = 136, Seersys = 137, Picturetel = 138, AttMicroelectronics = 139, Osprey = 140, Mediatrix = 141, Soundesigns = 142, Aldigital = 143, SpectrumSignalProcessing = 144, Ecs = 145, Amd = 146, Coredynamics = 147, Canam = 148, Softsound = 149, Norris = 150, Ddd = 151, Euphonics = 152, Precept = 153, CrystalNet = 154, Chromatic = 155, Voiceinfo = 156, Viennasys = 157, Connectix = 158, Gadgetlabs = 159, Frontier = 160, Viona = 161, Casio = 162, Diamondmm = 163, S3 = 164, FraunhoferIis = 172 } public class MmException : Exception { public MmResult Result { get; } public string Function { get; } public MmException(MmResult result, string function) : base(ErrorMessage(result, function)) { Result = result; Function = function; } private static string ErrorMessage(MmResult result, string function) { return $"{result} calling {function}"; } public static void Try(MmResult result, string function) { if (result != 0) { throw new MmException(result, function); } } } public enum MmResult { NoError = 0, UnspecifiedError = 1, BadDeviceId = 2, NotEnabled = 3, AlreadyAllocated = 4, InvalidHandle = 5, NoDriver = 6, MemoryAllocationError = 7, NotSupported = 8, BadErrorNumber = 9, InvalidFlag = 10, InvalidParameter = 11, HandleBusy = 12, InvalidAlias = 13, BadRegistryDatabase = 14, RegistryKeyNotFound = 15, RegistryReadError = 16, RegistryWriteError = 17, RegistryDeleteError = 18, RegistryValueNotFound = 19, NoDriverCallback = 20, MoreData = 21, WaveBadFormat = 32, WaveStillPlaying = 33, WaveHeaderUnprepared = 34, WaveSync = 35, AcmNotPossible = 512, AcmBusy = 513, AcmHeaderUnprepared = 514, AcmCancelled = 515, MixerInvalidLine = 1024, MixerInvalidControl = 1025, MixerInvalidValue = 1026 } } namespace NAudio.CoreAudioApi { public enum CaptureState { Stopped, Starting, Capturing, Stopping } } namespace NAudio.Dmo { public class AudioMediaSubtypes { public static readonly Guid MEDIASUBTYPE_PCM = new Guid("00000001-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_PCMAudioObsolete = new Guid("e436eb8a-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_MPEG1Packet = new Guid("e436eb80-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_MPEG1Payload = new Guid("e436eb81-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_MPEG2_AUDIO = new Guid("e06d802b-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid MEDIASUBTYPE_DVD_LPCM_AUDIO = new Guid("e06d8032-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid MEDIASUBTYPE_DRM_Audio = new Guid("00000009-0000-0010-8000-00aa00389b71"); public static readonly Guid MEDIASUBTYPE_IEEE_FLOAT = new Guid("00000003-0000-0010-8000-00aa00389b71"); public static readonly Guid MEDIASUBTYPE_DOLBY_AC3 = new Guid("e06d802c-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid MEDIASUBTYPE_DOLBY_AC3_SPDIF = new Guid("00000092-0000-0010-8000-00aa00389b71"); public static readonly Guid MEDIASUBTYPE_RAW_SPORT = new Guid("00000240-0000-0010-8000-00aa00389b71"); public static readonly Guid MEDIASUBTYPE_SPDIF_TAG_241h = new Guid("00000241-0000-0010-8000-00aa00389b71"); public static readonly Guid MEDIASUBTYPE_I420 = new Guid("30323449-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_IYUV = new Guid("56555949-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_RGB1 = new Guid("e436eb78-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_RGB24 = new Guid("e436eb7d-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_RGB32 = new Guid("e436eb7e-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_RGB4 = new Guid("e436eb79-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_RGB555 = new Guid("e436eb7c-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_RGB565 = new Guid("e436eb7b-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_RGB8 = new Guid("e436eb7a-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_UYVY = new Guid("59565955-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_VIDEOIMAGE = new Guid("1d4a45f2-e5f6-4b44-8388-f0ae5c0e0c37"); public static readonly Guid MEDIASUBTYPE_YUY2 = new Guid("32595559-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_YV12 = new Guid("31313259-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_YVU9 = new Guid("39555659-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIASUBTYPE_YVYU = new Guid("55595659-0000-0010-8000-00AA00389B71"); public static readonly Guid WMFORMAT_MPEG2Video = new Guid("e06d80e3-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid WMFORMAT_Script = new Guid("5C8510F2-DEBE-4ca7-BBA5-F07A104F8DFF"); public static readonly Guid WMFORMAT_VideoInfo = new Guid("05589f80-c356-11ce-bf01-00aa0055595a"); public static readonly Guid WMFORMAT_WaveFormatEx = new Guid("05589f81-c356-11ce-bf01-00aa0055595a"); public static readonly Guid WMFORMAT_WebStream = new Guid("da1e6b13-8359-4050-b398-388e965bf00c"); public static readonly Guid WMMEDIASUBTYPE_ACELPnet = new Guid("00000130-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_Base = new Guid("00000000-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_DRM = new Guid("00000009-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_MP3 = new Guid("00000055-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_MP43 = new Guid("3334504D-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_MP4S = new Guid("5334504D-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_M4S2 = new Guid("3253344D-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_P422 = new Guid("32323450-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_MPEG2_VIDEO = new Guid("e06d8026-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid WMMEDIASUBTYPE_MSS1 = new Guid("3153534D-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_MSS2 = new Guid("3253534D-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_PCM = new Guid("00000001-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WebStream = new Guid("776257d4-c627-41cb-8f81-7ac7ff1c40cc"); public static readonly Guid WMMEDIASUBTYPE_WMAudio_Lossless = new Guid("00000163-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMAudioV2 = new Guid("00000161-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMAudioV7 = new Guid("00000161-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMAudioV8 = new Guid("00000161-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMAudioV9 = new Guid("00000162-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMSP1 = new Guid("0000000A-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMV1 = new Guid("31564D57-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMV2 = new Guid("32564D57-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMV3 = new Guid("33564D57-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMVA = new Guid("41564D57-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WMVP = new Guid("50564D57-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIASUBTYPE_WVP2 = new Guid("32505657-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIATYPE_Audio = new Guid("73647561-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIATYPE_FileTransfer = new Guid("D9E47579-930E-4427-ADFC-AD80F290E470"); public static readonly Guid WMMEDIATYPE_Image = new Guid("34A50FD8-8AA5-4386-81FE-A0EFE0488E31"); public static readonly Guid WMMEDIATYPE_Script = new Guid("73636d64-0000-0010-8000-00AA00389B71"); public static readonly Guid WMMEDIATYPE_Text = new Guid("9BBA1EA7-5AB2-4829-BA57-0940209BCF3E"); public static readonly Guid WMMEDIATYPE_Video = new Guid("73646976-0000-0010-8000-00AA00389B71"); public static readonly Guid WMSCRIPTTYPE_TwoStrings = new Guid("82f38a70-c29f-11d1-97ad-00a0c95ea850"); public static readonly Guid MEDIASUBTYPE_WAVE = new Guid("e436eb8b-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_AU = new Guid("e436eb8c-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIASUBTYPE_AIFF = new Guid("e436eb8d-524f-11ce-9f53-0020af0ba770"); public static readonly Guid[] AudioSubTypes = new Guid[13] { MEDIASUBTYPE_PCM, MEDIASUBTYPE_PCMAudioObsolete, MEDIASUBTYPE_MPEG1Packet, MEDIASUBTYPE_MPEG1Payload, MEDIASUBTYPE_MPEG2_AUDIO, MEDIASUBTYPE_DVD_LPCM_AUDIO, MEDIASUBTYPE_DRM_Audio, MEDIASUBTYPE_IEEE_FLOAT, MEDIASUBTYPE_DOLBY_AC3, MEDIASUBTYPE_DOLBY_AC3_SPDIF, MEDIASUBTYPE_RAW_SPORT, MEDIASUBTYPE_SPDIF_TAG_241h, WMMEDIASUBTYPE_MP3 }; public static readonly string[] AudioSubTypeNames = new string[13] { "PCM", "PCM Obsolete", "MPEG1Packet", "MPEG1Payload", "MPEG2_AUDIO", "DVD_LPCM_AUDIO", "DRM_Audio", "IEEE_FLOAT", "DOLBY_AC3", "DOLBY_AC3_SPDIF", "RAW_SPORT", "SPDIF_TAG_241h", "MP3" }; public static string GetAudioSubtypeName(Guid subType) { for (int i = 0; i < AudioSubTypes.Length; i++) { if (subType == AudioSubTypes[i]) { return AudioSubTypeNames[i]; } } return subType.ToString(); } } } namespace NAudio.Utils { public static class BufferHelpers { public static byte[] Ensure(byte[] buffer, int bytesRequired) { if (buffer == null || buffer.Length < bytesRequired) { buffer = new byte[bytesRequired]; } return buffer; } public static float[] Ensure(float[] buffer, int samplesRequired) { if (buffer == null || buffer.Length < samplesRequired) { buffer = new float[samplesRequired]; } return buffer; } } public static class ByteArrayExtensions { public static bool IsEntirelyNull(byte[] buffer) { for (int i = 0; i < buffer.Length; i++) { if (buffer[i] != 0) { return false; } } return true; } public static string DescribeAsHex(byte[] buffer, string separator, int bytesPerLine) { StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (byte b in buffer) { stringBuilder.AppendFormat("{0:X2}{1}", b, separator); if (++num % bytesPerLine == 0) { stringBuilder.Append("\r\n"); } } stringBuilder.Append("\r\n"); return stringBuilder.ToString(); } public static string DecodeAsString(byte[] buffer, int offset, int length, Encoding encoding) { for (int i = 0; i < length; i++) { if (buffer[offset + i] == 0) { length = i; } } return encoding.GetString(buffer, offset, length); } public static byte[] Concat(params byte[][] byteArrays) { int num = 0; byte[][] array = byteArrays; foreach (byte[] array2 in array) { num += array2.Length; } if (num <= 0) { return new byte[0]; } byte[] array3 = new byte[num]; int num2 = 0; array = byteArrays; foreach (byte[] array4 in array) { Array.Copy(array4, 0, array3, num2, array4.Length); num2 += array4.Length; } return array3; } } public class ByteEncoding : Encoding { public static readonly ByteEncoding Instance = new ByteEncoding(); private ByteEncoding() { } public override int GetByteCount(char[] chars, int index, int count) { return count; } public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { for (int i = 0; i < charCount; i++) { bytes[byteIndex + i] = (byte)chars[charIndex + i]; } return charCount; } public override int GetCharCount(byte[] bytes, int index, int count) { for (int i = 0; i < count; i++) { if (bytes[index + i] == 0) { return i; } } return count; } public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { for (int i = 0; i < byteCount; i++) { byte b = bytes[byteIndex + i]; if (b == 0) { return i; } chars[charIndex + i] = (char)b; } return byteCount; } public override int GetMaxCharCount(int byteCount) { return byteCount; } public override int GetMaxByteCount(int charCount) { return charCount; } } public class ChunkIdentifier { public static int ChunkIdentifierToInt32(string s) { if (s.Length != 4) { throw new ArgumentException("Must be a four character string"); } byte[] bytes = Encoding.UTF8.GetBytes(s); if (bytes.Length != 4) { throw new ArgumentException("Must encode to exactly four bytes"); } return BitConverter.ToInt32(bytes, 0); } } public class CircularBuffer { private readonly byte[] buffer; private readonly object lockObject; private int writePosition; private int readPosition; private int byteCount; public int MaxLength => buffer.Length; public int Count { get { lock (lockObject) { return byteCount; } } } public CircularBuffer(int size) { buffer = new byte[size]; lockObject = new object(); } public int Write(byte[] data, int offset, int count) { lock (lockObject) { int num = 0; if (count > buffer.Length - byteCount) { count = buffer.Length - byteCount; } int num2 = Math.Min(buffer.Length - writePosition, count); Array.Copy(data, offset, buffer, writePosition, num2); writePosition += num2; writePosition %= buffer.Length; num += num2; if (num < count) { Array.Copy(data, offset + num, buffer, writePosition, count - num); writePosition += count - num; num = count; } byteCount += num; return num; } } public int Read(byte[] data, int offset, int count) { lock (lockObject) { if (count > byteCount) { count = byteCount; } int num = 0; int num2 = Math.Min(buffer.Length - readPosition, count); Array.Copy(buffer, readPosition, data, offset, num2); num += num2; readPosition += num2; readPosition %= buffer.Length; if (num < count) { Array.Copy(buffer, readPosition, data, offset + num, count - num); readPosition += count - num; num = count; } byteCount -= num; return num; } } public void Reset() { lock (lockObject) { ResetInner(); } } private void ResetInner() { byteCount = 0; readPosition = 0; writePosition = 0; } public void Advance(int count) { lock (lockObject) { if (count >= byteCount) { ResetInner(); return; } byteCount -= count; readPosition += count; readPosition %= MaxLength; } } } public class Decibels { private const double LOG_2_DB = 8.685889638065037; private const double DB_2_LOG = 0.11512925464970228; public static double LinearToDecibels(double lin) { return Math.Log(lin) * 8.685889638065037; } public static double DecibelsToLinear(double dB) { return Math.Exp(dB * 0.11512925464970228); } } [AttributeUsage(AttributeTargets.Field)] public class FieldDescriptionAttribute : Attribute { public string Description { get; } public FieldDescriptionAttribute(string description) { Description = description; } public override string ToString() { return Description; } } public static class FieldDescriptionHelper { public static string Describe(Type t, Guid guid) { FieldInfo[] fields = t.GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsPublic || !fieldInfo.IsStatic || !(fieldInfo.FieldType == typeof(Guid)) || !((Guid)fieldInfo.GetValue(null) == guid)) { continue; } object[] customAttributes = fieldInfo.GetCustomAttributes(inherit: false); for (int j = 0; j < customAttributes.Length; j++) { if (customAttributes[j] is FieldDescriptionAttribute fieldDescriptionAttribute) { return fieldDescriptionAttribute.Description; } } return fieldInfo.Name; } return guid.ToString(); } } public static class HResult { public const int S_OK = 0; public const int S_FALSE = 1; public const int E_INVALIDARG = -2147483645; private const int FACILITY_AAF = 18; private const int FACILITY_ACS = 20; private const int FACILITY_BACKGROUNDCOPY = 32; private const int FACILITY_CERT = 11; private const int FACILITY_COMPLUS = 17; private const int FACILITY_CONFIGURATION = 33; private const int FACILITY_CONTROL = 10; private const int FACILITY_DISPATCH = 2; private const int FACILITY_DPLAY = 21; private const int FACILITY_HTTP = 25; private const int FACILITY_INTERNET = 12; private const int FACILITY_ITF = 4; private const int FACILITY_MEDIASERVER = 13; private const int FACILITY_MSMQ = 14; private const int FACILITY_NULL = 0; private const int FACILITY_RPC = 1; private const int FACILITY_SCARD = 16; private const int FACILITY_SECURITY = 9; private const int FACILITY_SETUPAPI = 15; private const int FACILITY_SSPI = 9; private const int FACILITY_STORAGE = 3; private const int FACILITY_SXS = 23; private const int FACILITY_UMI = 22; private const int FACILITY_URT = 19; private const int FACILITY_WIN32 = 7; private const int FACILITY_WINDOWS = 8; private const int FACILITY_WINDOWS_CE = 24; public static int MAKE_HRESULT(int sev, int fac, int code) { return (sev << 31) | (fac << 16) | code; } public static int GetHResult(this COMException exception) { return exception.ErrorCode; } } public static class IEEE { private static double UnsignedToFloat(ulong u) { return (double)(long)(u - int.MaxValue - 1) + 2147483648.0; } private static double ldexp(double x, int exp) { return x * Math.Pow(2.0, exp); } private static double frexp(double x, out int exp) { exp = (int)Math.Floor(Math.Log(x) / Math.Log(2.0)) + 1; return 1.0 - (Math.Pow(2.0, exp) - x) / Math.Pow(2.0, exp); } private static ulong FloatToUnsigned(double f) { return (ulong)((long)(f - 2147483648.0) + int.MaxValue + 1); } public static byte[] ConvertToIeeeExtended(double num) { int num2; if (num < 0.0) { num2 = 32768; num *= -1.0; } else { num2 = 0; } ulong num4; ulong num5; int num3; if (num == 0.0) { num3 = 0; num4 = 0uL; num5 = 0uL; } else { double num6 = frexp(num, out num3); if (num3 > 16384 || !(num6 < 1.0)) { num3 = num2 | 0x7FFF; num4 = 0uL; num5 = 0uL; } else { num3 += 16382; if (num3 < 0) { num6 = ldexp(num6, num3); num3 = 0; } num3 |= num2; num6 = ldexp(num6, 32); double num7 = Math.Floor(num6); num4 = FloatToUnsigned(num7); num6 = ldexp(num6 - num7, 32); num7 = Math.Floor(num6); num5 = FloatToUnsigned(num7); } } return new byte[10] { (byte)(num3 >> 8), (byte)num3, (byte)(num4 >> 24), (byte)(num4 >> 16), (byte)(num4 >> 8), (byte)num4, (byte)(num5 >> 24), (byte)(num5 >> 16), (byte)(num5 >> 8), (byte)num5 }; } public static double ConvertFromIeeeExtended(byte[] bytes) { if (bytes.Length != 10) { throw new Exception("Incorrect length for IEEE extended."); } int num = ((bytes[0] & 0x7F) << 8) | bytes[1]; uint num2 = (uint)((bytes[2] << 24) | (bytes[3] << 16) | (bytes[4] << 8) | bytes[5]); uint num3 = (uint)((bytes[6] << 24) | (bytes[7] << 16) | (bytes[8] << 8) | bytes[9]); double num4; if (num == 0 && num2 == 0 && num3 == 0) { num4 = 0.0; } else if (num == 32767) { num4 = double.NaN; } else { num -= 16383; num4 = ldexp(UnsignedToFloat(num2), num -= 31); num4 += ldexp(UnsignedToFloat(num3), num -= 32); } if ((bytes[0] & 0x80) == 128) { return 0.0 - num4; } return num4; } } public class IgnoreDisposeStream : Stream { public Stream SourceStream { get; private set; } public bool IgnoreDispose { get; set; } public override bool CanRead => SourceStream.CanRead; public override bool CanSeek => SourceStream.CanSeek; public override bool CanWrite => SourceStream.CanWrite; public override long Length => SourceStream.Length; public override long Position { get { return SourceStream.Position; } set { SourceStream.Position = value; } } public IgnoreDisposeStream(Stream sourceStream) { SourceStream = sourceStream; IgnoreDispose = true; } public override void Flush() { SourceStream.Flush(); } public override int Read(byte[] buffer, int offset, int count) { return SourceStream.Read(buffer, offset, count); } public override long Seek(long offset, SeekOrigin origin) { return SourceStream.Seek(offset, origin); } public override void SetLength(long value) { SourceStream.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { SourceStream.Write(buffer, offset, count); } protected override void Dispose(bool disposing) { if (!IgnoreDispose) { SourceStream.Dispose(); SourceStream = null; } } } public static class NativeMethods { [DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary(string dllToLoad); [DllImport("kernel32.dll")] public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")] public static extern bool FreeLibrary(IntPtr hModule); } public static class WavePositionExtensions { public static TimeSpan GetPositionTimeSpan(this IWavePosition @this) { return TimeSpan.FromMilliseconds((double)(@this.GetPosition() / (@this.OutputWaveFormat.Channels * @this.OutputWaveFormat.BitsPerSample / 8)) * 1000.0 / (double)@this.OutputWaveFormat.SampleRate); } } } namespace NAudio.FileFormats.Wav { public class WaveFileChunkReader { private WaveFormat waveFormat; private long dataChunkPosition; private long dataChunkLength; private List<RiffChunk> riffChunks; private readonly bool strictMode; private bool isRf64; private readonly bool storeAllChunks; private long riffSize; public WaveFormat WaveFormat => waveFormat; public long DataChunkPosition => dataChunkPosition; public long DataChunkLength => dataChunkLength; public List<RiffChunk> RiffChunks => riffChunks; public WaveFileChunkReader() { storeAllChunks = true; strictMode = false; } public void ReadWaveHeader(Stream stream) { dataChunkPosition = -1L; waveFormat = null; riffChunks = new List<RiffChunk>(); dataChunkLength = 0L; BinaryReader binaryReader = new BinaryReader(stream); ReadRiffHeader(binaryReader); riffSize = binaryReader.ReadUInt32(); if (binaryReader.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE")) { throw new FormatException("Not a WAVE file - no WAVE header"); } if (isRf64) { ReadDs64Chunk(binaryReader); } int num = ChunkIdentifier.ChunkIdentifierToInt32("data"); int num2 = ChunkIdentifier.ChunkIdentifierToInt32("fmt "); long num3 = Math.Min(riffSize + 8, stream.Length); while (stream.Position <= num3 - 8) { int num4 = binaryReader.ReadInt32(); uint num5 = binaryReader.ReadUInt32(); if (num4 == num) { dataChunkPosition = stream.Position; if (!isRf64) { dataChunkLength = num5; } stream.Position += dataChunkLength; } else if (num4 == num2) { if (num5 > int.MaxValue) { throw new InvalidDataException($"Format chunk length must be between 0 and {int.MaxValue}."); } waveFormat = WaveFormat.FromFormatChunk(binaryReader, (int)num5); } else { if (num5 > stream.Length - stream.Position) { if (!strictMode) { } break; } if (storeAllChunks) { if (num5 > int.MaxValue) { throw new InvalidDataException($"RiffChunk chunk length must be between 0 and {int.MaxValue}."); } riffChunks.Add(GetRiffChunk(stream, num4, (int)num5)); } stream.Position += num5; } if (num5 % 2 != 0 && binaryReader.PeekChar() == 0) { stream.Position++; } } if (waveFormat == null) { throw new FormatException("Invalid WAV file - No fmt chunk found"); } if (dataChunkPosition == -1) { throw new FormatException("Invalid WAV file - No data chunk found"); } } private void ReadDs64Chunk(BinaryReader reader) { int num = ChunkIdentifier.ChunkIdentifierToInt32("ds64"); if (reader.ReadInt32() != num) { throw new FormatException("Invalid RF64 WAV file - No ds64 chunk found"); } int num2 = reader.ReadInt32(); riffSize = reader.ReadInt64(); dataChunkLength = reader.ReadInt64(); reader.ReadInt64(); reader.ReadBytes(num2 - 24); } private static RiffChunk GetRiffChunk(Stream stream, int chunkIdentifier, int chunkLength) { return new RiffChunk(chunkIdentifier, chunkLength, stream.Position); } private void ReadRiffHeader(BinaryReader br) { int num = br.ReadInt32(); if (num == ChunkIdentifier.ChunkIdentifierToInt32("RF64")) { isRf64 = true; } else if (num != ChunkIdentifier.ChunkIdentifierToInt32("RIFF")) { throw new FormatException("Not a WAVE file - no RIFF header"); } } } } namespace NAudio.SoundFont { public class Generator { public GeneratorEnum GeneratorType { get; set; } public ushort UInt16Amount { get; set; } public short Int16Amount { get { return (short)UInt16Amount; } set { UInt16Amount = (ushort)value; } } public byte LowByteAmount { get { return (byte)(UInt16Amount & 0xFFu); } set { UInt16Amount &= 65280; UInt16Amount += value; } } public byte HighByteAmount { get { return (byte)((UInt16Amount & 0xFF00) >> 8); } set { UInt16Amount &= 255; UInt16Amount += (ushort)(value << 8); } } public Instrument Instrument { get; set; } public SampleHeader SampleHeader { get; set; } public override string ToString() { if (GeneratorType == GeneratorEnum.Instrument) { return "Generator Instrument " + Instrument.Name; } if (GeneratorType == GeneratorEnum.SampleID) { return $"Generator SampleID {SampleHeader}"; } return $"Generator {GeneratorType} {UInt16Amount}"; } } internal class GeneratorBuilder : StructureBuilder<Generator> { public override int Length => 4; public Generator[] Generators => data.ToArray(); public override Generator Read(BinaryReader br) { Generator generator = new Generator(); generator.GeneratorType = (GeneratorEnum)br.ReadUInt16(); generator.UInt16Amount = br.ReadUInt16(); data.Add(generator); return generator; } public override void Write(BinaryWriter bw, Generator o) { } public void Load(Instrument[] instruments) { Generator[] generators = Generators; foreach (Generator generator in generators) { if (generator.GeneratorType == GeneratorEnum.Instrument) { generator.Instrument = instruments[generator.UInt16Amount]; } } } public void Load(SampleHeader[] sampleHeaders) { Generator[] generators = Generators; foreach (Generator generator in generators) { if (generator.GeneratorType == GeneratorEnum.SampleID) { generator.SampleHeader = sampleHeaders[generator.UInt16Amount]; } } } } public enum GeneratorEnum { StartAddressOffset, EndAddressOffset, StartLoopAddressOffset, EndLoopAddressOffset, StartAddressCoarseOffset, ModulationLFOToPitch, VibratoLFOToPitch, ModulationEnvelopeToPitch, InitialFilterCutoffFrequency, InitialFilterQ, ModulationLFOToFilterCutoffFrequency, ModulationEnvelopeToFilterCutoffFrequency, EndAddressCoarseOffset, ModulationLFOToVolume, Unused1, ChorusEffectsSend, ReverbEffectsSend, Pan, Unused2, Unused3, Unused4, DelayModulationLFO, FrequencyModulationLFO, DelayVibratoLFO, FrequencyVibratoLFO, DelayModulationEnvelope, AttackModulationEnvelope, HoldModulationEnvelope, DecayModulationEnvelope, SustainModulationEnvelope, ReleaseModulationEnvelope, KeyNumberToModulationEnvelopeHold, KeyNumberToModulationEnvelopeDecay, DelayVolumeEnvelope, AttackVolumeEnvelope, HoldVolumeEnvelope, DecayVolumeEnvelope, SustainVolumeEnvelope, ReleaseVolumeEnvelope, KeyNumberToVolumeEnvelopeHold, KeyNumberToVolumeEnvelopeDecay, Instrument, Reserved1, KeyRange, VelocityRange, StartLoopAddressCoarseOffset, KeyNumber, Velocity, InitialAttenuation, Reserved2, EndLoopAddressCoarseOffset, CoarseTune, FineTune, SampleID, SampleModes, Reserved3, ScaleTuning, ExclusiveClass, OverridingRootKey, Unused5, UnusedEnd } public class InfoChunk { public SFVersion SoundFontVersion { get; } public string WaveTableSoundEngine { get; set; } public string BankName { get; set; } public string DataROM { get; set; } public string CreationDate { get; set; } public string Author { get; set; } public string TargetProduct { get; set; } public string Copyright { get; set; } public string Comments { get; set; } public string Tools { get; set; } public SFVersion ROMVersion { get; set; } internal InfoChunk(RiffChunk chunk) { bool flag = false; bool flag2 = false; if (chunk.ReadChunkID() != "INFO") { throw new InvalidDataException("Not an INFO chunk"); } RiffChunk nextSubChunk; while ((nextSubChunk = chunk.GetNextSubChunk()) != null) { switch (nextSubChunk.ChunkID) { case "ifil": flag = true; SoundFontVersion = nextSubChunk.GetDataAsStructure(new SFVersionBuilder()); break; case "isng": WaveTableSoundEngine = nextSubChunk.GetDataAsString(); break; case "INAM": flag2 = true; BankName = nextSubChunk.GetDataAsString(); break; case "irom": DataROM = nextSubChunk.GetDataAsString(); break; case "iver": ROMVersion = nextSubChunk.GetDataAsStructure(new SFVersionBuilder()); break; case "ICRD": CreationDate = nextSubChunk.GetDataAsString(); break; case "IENG": Author = nextSubChunk.GetDataAsString(); break; case "IPRD": TargetProduct = nextSubChunk.GetDataAsString(); break; case "ICOP": Copyright = nextSubChunk.GetDataAsString(); break; case "ICMT": Comments = nextSubChunk.GetDataAsString(); break; case "ISFT": Tools = nextSubChunk.GetDataAsString(); break; default: throw new InvalidDataException("Unknown chunk type " + nextSubChunk.ChunkID); } } if (!flag) { throw new InvalidDataException("Missing SoundFont version information"); } if (!flag2) { throw new InvalidDataException("Missing SoundFont name information"); } } public override string ToString() { return string.Format("Bank Name: {0}\r\nAuthor: {1}\r\nCopyright: {2}\r\nCreation Date: {3}\r\nTools: {4}\r\nComments: {5}\r\nSound Engine: {6}\r\nSoundFont Version: {7}\r\nTarget Product: {8}\r\nData ROM: {9}\r\nROM Version: {10}", BankName, Author, Copyright, CreationDate, Tools, "TODO-fix comments", WaveTableSoundEngine, SoundFontVersion, TargetProduct, DataROM, ROMVersion); } } public class Instrument { internal ushort startInstrumentZoneIndex; internal ushort endInstrumentZoneIndex; public string Name { get; set; } public Zone[] Zones { get; set; } public override string ToString() { return Name; } } internal class InstrumentBuilder : StructureBuilder<Instrument> { private Instrument lastInstrument; public override int Length => 22; public Instrument[] Instruments => data.ToArray(); public override Instrument Read(BinaryReader br) { Instrument instrument = new Instrument(); string text = Encoding.UTF8.GetString(br.ReadBytes(20), 0, 20); if (text.IndexOf('\0') >= 0) { text = text.Substring(0, text.IndexOf('\0')); } instrument.Name = text; instrument.startInstrumentZoneIndex = br.ReadUInt16(); if (lastInstrument != null) { lastInstrument.endInstrumentZoneIndex = (ushort)(instrument.startInstrumentZoneIndex - 1); } data.Add(instrument); lastInstrument = instrument; return instrument; } public override void Write(BinaryWriter bw, Instrument instrument) { } public void LoadZones(Zone[] zones) { for (int i = 0; i < data.Count - 1; i++) { Instrument instrument = data[i]; instrument.Zones = new Zone[instrument.endInstrumentZoneIndex - instrument.startInstrumentZoneIndex + 1]; Array.Copy(zones, instrument.startInstrumentZoneIndex, instrument.Zones, 0, instrument.Zones.Length); } data.RemoveAt(data.Count - 1); } } public enum TransformEnum { Linear } public class Modulator { public ModulatorType SourceModulationData { get; set; } public GeneratorEnum DestinationGenerator { get; set; } public short Amount { get; set; } public ModulatorType SourceModulationAmount { get; set; } public TransformEnum SourceTransform { get; set; } public override string ToString() { return $"Modulator {SourceModulationData} {DestinationGenerator} {Amount} {SourceModulationAmount} {SourceTransform}"; } } internal class ModulatorBuilder : StructureBuilder<Modulator> { public override int Length => 10; public Modulator[] Modulators => data.ToArray(); public override Modulator Read(BinaryReader br) { Modulator modulator = new Modulator(); modulator.SourceModulationData = new ModulatorType(br.ReadUInt16()); modulator.DestinationGenerator = (GeneratorEnum)br.ReadUInt16(); modulator.Amount = br.ReadInt16(); modulator.SourceModulationAmount = new ModulatorType(br.ReadUInt16()); modulator.SourceTransform = (TransformEnum)br.ReadUInt16(); data.Add(modulator); return modulator; } public override void Write(BinaryWriter bw, Modulator o) { } } public enum ControllerSourceEnum { NoController = 0, NoteOnVelocity = 2, NoteOnKeyNumber = 3, PolyPressure = 10, ChannelPressure = 13, PitchWheel = 14, PitchWheelSensitivity = 16 } public enum SourceTypeEnum { Linear, Concave, Convex, Switch } public class ModulatorType { private bool polarity; private bool direction; private bool midiContinuousController; private ControllerSourceEnum controllerSource; private SourceTypeEnum sourceType; private ushort midiContinuousControllerNumber; internal ModulatorType(ushort raw) { polarity = (raw & 0x200) == 512; direction = (raw & 0x100) == 256; midiContinuousController = (raw & 0x80) == 128; sourceType = (SourceTypeEnum)((raw & 0xFC00) >> 10); controllerSource = (ControllerSourceEnum)(raw & 0x7F); midiContinuousControllerNumber = (ushort)(raw & 0x7Fu); } public override string ToString() { if (midiContinuousController) { return $"{sourceType} CC{midiContinuousControllerNumber}"; } return $"{sourceType} {controllerSource}"; } } public class Preset { internal ushort startPresetZoneIndex; internal ushort endPresetZoneIndex; internal uint library; internal uint genre; internal uint morphology; public string Name { get; set; } public ushort PatchNumber { get; set; } public ushort Bank { get; set; } public Zone[] Zones { get; set; } public override string ToString() { return $"{Bank}-{PatchNumber} {Name}"; } } internal class PresetBuilder : StructureBuilder<Preset> { private Preset lastPreset; public override int Length => 38; public Preset[] Presets => data.ToArray(); public override Preset Read(BinaryReader br) { Preset preset = new Preset(); string text = Encoding.UTF8.GetString(br.ReadBytes(20), 0, 20); if (text.IndexOf('\0') >= 0) { text = text.Substring(0, text.IndexOf('\0')); } preset.Name = text; preset.PatchNumber = br.ReadUInt16(); preset.Bank = br.ReadUInt16(); preset.startPresetZoneIndex = br.ReadUInt16(); preset.library = br.ReadUInt32(); preset.genre = br.ReadUInt32(); preset.morphology = br.ReadUInt32(); if (lastPreset != null) { lastPreset.endPresetZoneIndex = (ushort)(preset.startPresetZoneIndex - 1); } data.Add(preset); lastPreset = preset; return preset; } public override void Write(BinaryWriter bw, Preset preset) { } public void LoadZones(Zone[] presetZones) { for (int i = 0; i < data.Count - 1; i++) { Preset preset = data[i]; preset.Zones = new Zone[preset.endPresetZoneIndex - preset.startPresetZoneIndex + 1]; Array.Copy(presetZones, preset.startPresetZoneIndex, preset.Zones, 0, preset.Zones.Length); } data.RemoveAt(data.Count - 1); } } public class PresetsChunk { private PresetBuilder presetHeaders = new PresetBuilder(); private ZoneBuilder presetZones = new ZoneBuilder(); private ModulatorBuilder presetZoneModulators = new ModulatorBuilder(); private GeneratorBuilder presetZoneGenerators = new GeneratorBuilder(); private InstrumentBuilder instruments = new InstrumentBuilder(); private ZoneBuilder instrumentZones = new ZoneBuilder(); private ModulatorBuilder instrumentZoneModulators = new ModulatorBuilder(); private GeneratorBuilder instrumentZoneGenerators = new GeneratorBuilder(); private SampleHeaderBuilder sampleHeaders = new SampleHeaderBuilder(); public Preset[] Presets => presetHeaders.Presets; public Instrument[] Instruments => instruments.Instruments; public SampleHeader[] SampleHeaders => sampleHeaders.SampleHeaders; internal PresetsChunk(RiffChunk chunk) { string text = chunk.ReadChunkID(); if (text != "pdta") { throw new InvalidDataException($"Not a presets data chunk ({text})"); } RiffChunk nextSubChunk; while ((nextSubChunk = chunk.GetNextSubChunk()) != null) { switch (nextSubChunk.ChunkID) { case "phdr": case "PHDR": nextSubChunk.GetDataAsStructureArray(presetHeaders); break; case "pbag": case "PBAG": nextSubChunk.GetDataAsStructureArray(presetZones); break; case "pmod": case "PMOD": nextSubChunk.GetDataAsStructureArray(presetZoneModulators); break; case "pgen": case "PGEN": nextSubChunk.GetDataAsStructureArray(presetZoneGenerators); break; case "inst": case "INST": nextSubChunk.GetDataAsStructureArray(instruments); break; case "ibag": case "IBAG": nextSubChunk.GetDataAsStructureArray(instrumentZones); break; case "imod": case "IMOD": nextSubChunk.GetDataAsStructureArray(instrumentZoneModulators); break; case "igen": case "IGEN": nextSubChunk.GetDataAsStructureArray(instrumentZoneGenerators); break; case "shdr": case "SHDR": nextSubChunk.GetDataAsStructureArray(sampleHeaders); break; default: throw new InvalidDataException($"Unknown chunk type {nextSubChunk.ChunkID}"); } } instrumentZoneGenerators.Load(sampleHeaders.SampleHeaders); instrumentZones.Load(instrumentZoneModulators.Modulators, instrumentZoneGenerators.Generators); instruments.LoadZones(instrumentZones.Zones); presetZoneGenerators.Load(instruments.Instruments); presetZones.Load(presetZoneModulators.Modulators, presetZoneGenerators.Generators); presetHeaders.LoadZones(presetZones.Zones); sampleHeaders.RemoveEOS(); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Preset Headers:\r\n"); Preset[] presets = presetHeaders.Presets; foreach (Preset arg in presets) { stringBuilder.AppendFormat("{0}\r\n", arg); } stringBuilder.Append("Instruments:\r\n"); Instrument[] array = instruments.Instruments; foreach (Instrument arg2 in array) { stringBuilder.AppendFormat("{0}\r\n", arg2); } return stringBuilder.ToString(); } } internal class RiffChunk { private string chunkID; private BinaryReader riffFile; public string ChunkID { get { return chunkID; } set { if (value == null) { throw new ArgumentNullException("ChunkID may not be null"); } if (value.Length != 4) { throw new ArgumentException("ChunkID must be four characters"); } chunkID = value; } } public uint ChunkSize { get; private set; } public long DataOffset { get; private set; } public static RiffChunk GetTopLevelChunk(BinaryReader file) { RiffChunk riffChunk = new RiffChunk(file); riffChunk.ReadChunk(); return riffChunk; } private RiffChunk(BinaryReader file) { riffFile = file; chunkID = "????"; ChunkSize = 0u; DataOffset = 0L; } public string ReadChunkID() { byte[] array = riffFile.ReadBytes(4); if (array.Length != 4) { throw new InvalidDataException("Couldn't read Chunk ID"); } return ByteEncoding.Instance.GetString(array, 0, array.Length); } private void ReadChunk() { chunkID = ReadChunkID(); ChunkSize = riffFile.ReadUInt32(); DataOffset = riffFile.BaseStream.Position; } public RiffChunk GetNextSubChunk() { if (riffFile.BaseStream.Position + 8 < DataOffset + ChunkSize) { RiffChunk riffChunk = new RiffChunk(riffFile); riffChunk.ReadChunk(); return riffChunk; } return null; } public byte[] GetData() { riffFile.BaseStream.Position = DataOffset; byte[] array = riffFile.ReadBytes((int)ChunkSize); if (array.Length != ChunkSize) { throw new InvalidDataException($"Couldn't read chunk's data Chunk: {this}, read {array.Length} bytes"); } return array; } public string GetDataAsString() { byte[] data = GetData(); if (data == null) { return null; } return ByteEncoding.Instance.GetString(data, 0, data.Length); } public T GetDataAsStructure<T>(StructureBuilder<T> s) { riffFile.BaseStream.Position = DataOffset; if (s.Length != ChunkSize) { throw new InvalidDataException($"Chunk size is: {ChunkSize} so can't read structure of: {s.Length}"); } return s.Read(riffFile); } public T[] GetDataAsStructureArray<T>(StructureBuilder<T> s) { riffFile.BaseStream.Position = DataOffset; if (ChunkSize % s.Length != 0L) { throw new InvalidDataException($"Chunk size is: {ChunkSize} not a multiple of structure size: {s.Length}"); } int num = (int)(ChunkSize / s.Length); T[] array = new T[num]; for (int i = 0; i < num; i++) { array[i] = s.Read(riffFile); } return array; } public override string ToString() { return $"RiffChunk ID: {ChunkID} Size: {ChunkSize} Data Offset: {DataOffset}"; } } internal class SampleDataChunk { public byte[] SampleData { get; private set; } public SampleDataChunk(RiffChunk chunk) { string text = chunk.ReadChunkID(); if (text != "sdta") { throw new InvalidDataException("Not a sample data chunk (" + text + ")"); } SampleData = chunk.GetData(); } } public class SampleHeader { public string SampleName; public uint Start; public uint End; public uint StartLoop; public uint EndLoop; public uint SampleRate; public byte OriginalPitch; public sbyte PitchCorrection; public ushort SampleLink; public SFSampleLink SFSampleLink; public override string ToString() { return SampleName; } } internal class SampleHeaderBuilder : StructureBuilder<SampleHeader> { public override int Length => 46; public SampleHeader[] SampleHeaders => data.ToArray(); public override SampleHeader Read(BinaryReader br) { SampleHeader sampleHeader = new SampleHeader(); byte[] array = br.ReadBytes(20); sampleHeader.SampleName = ByteEncoding.Instance.GetString(array, 0, array.Length); sampleHeader.Start = br.ReadUInt32(); sampleHeader.End = br.ReadUInt32(); sampleHeader.StartLoop = br.ReadUInt32(); sampleHeader.EndLoop = br.ReadUInt32(); sampleHeader.SampleRate = br.ReadUInt32(); sampleHeader.OriginalPitch = br.ReadByte(); sampleHeader.PitchCorrection = br.ReadSByte(); sampleHeader.SampleLink = br.ReadUInt16(); sampleHeader.SFSampleLink = (SFSampleLink)br.ReadUInt16(); data.Add(sampleHeader); return sampleHeader; } public override void Write(BinaryWriter bw, SampleHeader sampleHeader) { } internal void RemoveEOS() { data.RemoveAt(data.Count - 1); } } public enum SampleMode { NoLoop, LoopContinuously, ReservedNoLoop, LoopAndContinue } public enum SFSampleLink : ushort { MonoSample = 1, RightSample = 2, LeftSample = 4, LinkedSample = 8, RomMonoSample = 32769, RomRightSample = 32770, RomLeftSample = 32772, RomLinkedSample = 32776 } public class SFVersion { public short Major { get; set; } public short Minor { get; set; } } internal class SFVersionBuilder : StructureBuilder<SFVersion> { public override int Length => 4; public override SFVersion Read(BinaryReader br) { SFVersion sFVersion = new SFVersion(); sFVersion.Major = br.ReadInt16(); sFVersion.Minor = br.ReadInt16(); data.Add(sFVersion); return sFVersion; } public override void Write(BinaryWriter bw, SFVersion v) { bw.Write(v.Major); bw.Write(v.Minor); } } public class SoundFont { private InfoChunk info; private PresetsChunk presetsChunk; private SampleDataChunk sampleData; public InfoChunk FileInfo => info; public Preset[] Presets => presetsChunk.Presets; public Instrument[] Instruments => presetsChunk.Instruments; public SampleHeader[] SampleHeaders => presetsChunk.SampleHeaders; public byte[] SampleData => sampleData.SampleData; public SoundFont(string fileName) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read)) { } public SoundFont(Stream sfFile) { using (sfFile) { RiffChunk topLevelChunk = RiffChunk.GetTopLevelChunk(new BinaryReader(sfFile)); if (topLevelChunk.ChunkID == "RIFF") { string text = topLevelChunk.ReadChunkID(); if (text != "sfbk") { throw new InvalidDataException($"Not a SoundFont ({text})"); } RiffChunk nextSubChunk = topLevelChunk.GetNextSubChunk(); if (nextSubChunk.ChunkID == "LIST") { info = new InfoChunk(nextSubChunk); RiffChunk nextSubChunk2 = topLevelChunk.GetNextSubChunk(); sampleData = new SampleDataChunk(nextSubChunk2); nextSubChunk2 = topLevelChunk.GetNextSubChunk(); presetsChunk = new PresetsChunk(nextSubChunk2); return; } throw new InvalidDataException($"Not info list found ({nextSubChunk.ChunkID})"); } throw new InvalidDataException("Not a RIFF file"); } } public override string ToString() { return $"Info Chunk:\r\n{info}\r\nPresets Chunk:\r\n{presetsChunk}"; } } internal abstract class StructureBuilder<T> { protected List<T> data; public abstract int Length { get; } public T[] Data => data.ToArray(); public StructureBuilder() { Reset(); } public abstract T Read(BinaryReader br); public abstract void Write(BinaryWriter bw, T o); public void Reset() { data = new List<T>(); } } public class Zone { internal ushort generatorIndex; internal ushort modulatorIndex; internal ushort generatorCount; internal ushort modulatorCount; public Modulator[] Modulators { get; set; } public Generator[] Generators { get; set; } public override string ToString() { return $"Zone {generatorCount} Gens:{generatorIndex} {modulatorCount} Mods:{modulatorIndex}"; } } internal class ZoneBuilder : StructureBuilder<Zone> { private Zone lastZone; public Zone[] Zones => data.ToArray(); public override int Length => 4; public override Zone Read(BinaryReader br) { Zone zone = new Zone(); zone.generatorIndex = br.ReadUInt16(); zone.modulatorIndex = br.ReadUInt16(); if (lastZone != null) { lastZone.generatorCount = (ushort)(zone.generatorIndex - lastZone.generatorIndex); lastZone.modulatorCount = (ushort)(zone.modulatorIndex - lastZone.modulatorIndex); } data.Add(zone); lastZone = zone; return zone; } public override void Write(BinaryWriter bw, Zone zone) { } public void Load(Modulator[] modulators, Generator[] generators) { for (int i = 0; i < data.Count - 1; i++) { Zone zone = data[i]; zone.Generators = new Generator[zone.generatorCount]; Array.Copy(generators, zone.generatorIndex, zone.Generators, 0, zone.generatorCount); zone.Modulators = new Modulator[zone.modulatorCount]; Array.Copy(modulators, zone.modulatorIndex, zone.Modulators, 0, zone.modulatorCount); } data.RemoveAt(data.Count - 1); } } } namespace NAudio.Wave { public enum ChannelMode { Stereo, JointStereo, DualChannel, Mono } public class Id3v2Tag { private long tagStartPosition; private long tagEndPosition; private byte[] rawData; public byte[] RawData => rawData; public static Id3v2Tag ReadTag(Stream input) { try { return new Id3v2Tag(input); } catch (FormatException) { return null; } } public static Id3v2Tag Create(IEnumerable<KeyValuePair<string, string>> tags) { return ReadTag(CreateId3v2TagStream(tags)); } private static byte[] FrameSizeToBytes(int n) { byte[] bytes = BitConverter.GetBytes(n); Array.Reverse((Array)bytes); return bytes; } private static byte[] CreateId3v2Frame(string key, string value) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } if (string.IsNullOrEmpty(value)) { throw new ArgumentNullException("value"); } if (key.Length != 4) { throw new ArgumentOutOfRangeException("key", "key " + key + " must be 4 characters long"); } byte[] array = new byte[2] { 255, 254 }; byte[] array2 = new byte[3]; byte[] array3 = new byte[2]; byte[] array4 = ((!(key == "COMM")) ? ByteArrayExtensions.Concat(new byte[1] { 1 }, array, Encoding.Unicode.GetBytes(value)) : ByteArrayExtensions.Concat(new byte[1] { 1 }, array2, array3, array, Encoding.Unicode.GetBytes(value))); return ByteArrayExtensions.Concat(Encoding.UTF8.GetBytes(key), FrameSizeToBytes(array4.Length), new byte[2], array4); } private static byte[] GetId3TagHeaderSize(int size) { byte[] array = new byte[4]; for (int num = array.Length - 1; num >= 0; num--) { array[num] = (byte)(size % 128); size /= 128; } return array; } private static byte[] CreateId3v2TagHeader(IEnumerable<byte[]> frames) { int num = 0; foreach (byte[] frame in frames) { num += frame.Length; } return ByteArrayExtensions.Concat(Encoding.UTF8.GetBytes("ID3"), new byte[2] { 3, 0 }, new byte[1], GetId3TagHeaderSize(num)); } private static Stream CreateId3v2TagStream(IEnumerable<KeyValuePair<string, string>> tags) { List<byte[]> list = new List<byte[]>(); foreach (KeyValuePair<string, string> tag in tags) { list.Add(CreateId3v2Frame(tag.Key, tag.Value)); } byte[] array = CreateId3v2TagHeader(list); MemoryStream memoryStream = new MemoryStream(); memoryStream.Write(array, 0, array.Length); foreach (byte[] item in list) { memoryStream.Write(item, 0, item.Length); } memoryStream.Position = 0L; return memoryStream; } private Id3v2Tag(Stream input) { tagStartPosition = input.Position; BinaryReader binaryReader = new BinaryReader(input); byte[] array = binaryReader.ReadBytes(10); if (array.Length >= 3 && array[0] == 73 && array[1] == 68 && array[2] == 51) { if ((array[5] & 0x40) == 64) { byte[] array2 = binaryReader.ReadBytes(4); _ = array2[0] * 2097152 + array2[1] * 16384 + array2[2] * 128; _ = array2[3]; } int num = array[6] * 2097152; num += array[7] * 16384; num += array[8] * 128; num += array[9]; binaryReader.ReadBytes(num); if ((array[5] & 0x10) == 16) { binaryReader.ReadBytes(10); } tagEndPosition = input.Position; input.Position = tagStartPosition; rawData = binaryReader.ReadBytes((int)(tagEndPosition - tagStartPosition)); return; } input.Position = tagStartPosition; throw new FormatException("Not an ID3v2 tag"); } } public interface IMp3FrameDecompressor : IDisposable { WaveFormat OutputFormat { get; } int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset); void Reset(); } public class Mp3Frame { private static readonly int[,,] bitRates = new int[2, 3, 15] { { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } } }; private static readonly int[,] samplesPerFrame = new int[2, 3] { { 384, 1152, 1152 }, { 384, 1152, 576 } }; private static readonly int[] sampleRatesVersion1 = new int[3] { 44100, 48000, 32000 }; private static readonly int[] sampleRatesVersion2 = new int[3] { 22050, 24000, 16000 }; private static readonly int[] sampleRatesVersion25 = new int[3] { 11025, 12000, 8000 }; private const int MaxFrameLength = 16384; public int SampleRate { get; private set; } public int FrameLength { get; private set; } public int BitRate { get; private set; } public byte[] RawData { get; private set; } public MpegVersion MpegVersion { get; private set; } public MpegLayer MpegLayer { get; private set; } public ChannelMode ChannelMode { get; private set; } public int SampleCount { get; private set; } public int ChannelExtension { get; private set; } public int BitRateIndex { get; private set; } public bool Copyright { get; private set; } public bool CrcPresent { get; private set; } public long FileOffset { get; private set; } public static Mp3Frame LoadFromStream(Stream input) { return LoadFromStream(input, readData: true); } public static Mp3Frame LoadFromStream(Stream input, bool readData) { Mp3Frame mp3Frame = new Mp3Frame(); mp3Frame.FileOffset = input.Position; byte[] array = new byte[4]; if (input.Read(array, 0, array.Length) < array.Length) { return null; } while (!IsValidHeader(array, mp3Frame)) { array[0] = array[1]; array[1] = array[2]; array[2] = array[3]; if (input.Read(array, 3, 1) < 1) { return null; } mp3Frame.FileOffset++; } int num = mp3Frame.FrameLength - 4; if (readData) { mp3Frame.RawData = new byte[mp3Frame.FrameLength]; Array.Copy(array, mp3Frame.RawData, 4); if (input.Read(mp3Frame.RawData, 4, num) < num) { throw new EndOfStreamException("Unexpected end of stream before frame complete"); } } else { input.Position += num; } return mp3Frame; } private Mp3Frame() { } private static bool IsValidHeader(byte[] headerBytes, Mp3Frame frame) { if (headerBytes[0] == byte.MaxValue && (headerBytes[1] & 0xE0) == 224) { frame.MpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3); if (frame.MpegVersion == MpegVersion.Reserved) { return false; } frame.MpegLayer = (MpegLayer)((headerBytes[1] & 6) >> 1); if (frame.MpegLayer == MpegLayer.Reserved) { return false; } int num = ((frame.MpegLayer != MpegLayer.Layer1) ? ((frame.MpegLayer == MpegLayer.Layer2) ? 1 : 2) : 0); frame.CrcPresent = (headerBytes[1] & 1) == 0; frame.BitRateIndex = (headerBytes[2] & 0xF0) >> 4; if (frame.BitRateIndex == 15) { return false; } int num2 = ((frame.MpegVersion != MpegVersion.Version1) ? 1 : 0); frame.BitRate = bitRates[num2, num, frame.BitRateIndex] * 1000; if (frame.BitRate == 0) { return false; } int num3 = (headerBytes[2] & 0xC) >> 2; if (num3 == 3) { return false; } if (frame.MpegVersion == MpegVersion.Version1) { frame.SampleRate = sampleRatesVersion1[num3]; } else if (frame.MpegVersion == MpegVersion.Version2) { frame.SampleRate = sampleRatesVersion2[num3]; } else { frame.SampleRate = sampleRatesVersion25[num3]; } bool flag = (headerBytes[2] & 2) == 2; _ = headerBytes[2]; frame.ChannelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6); frame.ChannelExtension = (headerBytes[3] & 0x30) >> 4; if (frame.ChannelExtension != 0 && frame.ChannelMode != ChannelMode.JointStereo) { return false; } frame.Copyright = (headerBytes[3] & 8) == 8; _ = headerBytes[3]; _ = headerBytes[3]; int num4 = (flag ? 1 : 0); frame.SampleCount = samplesPerFrame[num2, num]; int num5 = frame.SampleCount / 8; if (frame.MpegLayer == MpegLayer.Layer1) { frame.FrameLength = (num5 * frame.BitRate / frame.SampleRate + num4) * 4; } else { frame.FrameLength = num5 * frame.BitRate / frame.SampleRate + num4; } if (frame.FrameLength > 16384) { return false; } return true; } return false; } } public enum MpegLayer { Reserved, Layer3, Layer2, Layer1 } public enum MpegVersion { Version25, Reserved, Version2, Version1 } public class XingHeader { [Flags] private enum XingHeaderOptions { Frames = 1, Bytes = 2, Toc = 4, VbrScale = 8 } private static int[] sr_table = new int[4] { 44100, 48000, 32000, 99999 }; private int vbrScale = -1; private int startOffset; private int endOffset; private int tocOffset = -1; private int framesOffset = -1; private int bytesOffset = -1; private Mp3Frame frame; public int Frames { get { if (framesOffset == -1) { return -1; } return ReadBigEndian(frame.RawData, framesOffset); } set { if (framesOffset == -1) { throw new InvalidOperationException("Frames flag is not set"); } WriteBigEndian(frame.RawData, framesOffset, value); } } public int Bytes { get { if (bytesOffset == -1) { return -1; } return ReadBigEndian(frame.RawData, bytesOffset); } set { if (framesOffset == -1) { throw new InvalidOperationException("Bytes flag is not set"); } WriteBigEndian(frame.RawData, bytesOffset, value); } } public int VbrScale => vbrScale; public Mp3Frame Mp3Frame => frame; private static int ReadBigEndian(byte[] buffer, int offset) { return (((((buffer[offset] << 8) | buffer[offset + 1]) << 8) | buffer[offset + 2]) << 8) | buffer[offset + 3]; } private void WriteBigEndian(byte[] buffer, int offset, int value) { byte[] bytes = BitConverter.GetBytes(value); for (int i = 0; i < 4; i++) { buffer[offset + 3 - i] = bytes[i]; } } public static XingHeader LoadXingHeader(Mp3Frame frame) { XingHeader xingHeader = new XingHeader(); xingHeader.frame = frame; int num = 0; if (frame.MpegVersion == MpegVersion.Version1) { num = ((frame.ChannelMode == ChannelMode.Mono) ? 21 : 36); } else { if (frame.MpegVersion != MpegVersion.Version2) { return null; } num = ((frame.ChannelMode == ChannelMode.Mono) ? 13 : 21); } if (frame.RawData[num] == 88 && frame.RawData[num + 1] == 105 && frame.RawData[num + 2] == 110 && frame.RawData[num + 3] == 103) { xingHeader.startOffset = num; num += 4; } else { if (frame.RawData[num] != 73 || frame.RawData[num + 1] != 110 || frame.RawData[num + 2] != 102 || frame.RawData[num + 3] != 111) { return null; } xingHeader.startOffset = num; num += 4; } int num2 = ReadBigEndian(frame.RawData, num); num += 4; if (((uint)num2 & (true ? 1u : 0u)) != 0) { xingHeader.framesOffset = num; num += 4; } if (((uint)num2 & 2u) != 0) { xingHeader.bytesOffset = num; num += 4; } if (((uint)num2 & 4u) != 0) { xingHeader.tocOffset = num; num += 100; } if (((uint)num2 & 8u) != 0) { xingHeader.vbrScale = ReadBigEndian(frame.RawData, num); num += 4; } xingHeader.endOffset = num; return xingHeader; } private XingHeader() { } } public static class WaveExtensionMethods { public static ISampleProvider ToSampleProvider(this IWaveProvider waveProvider) { return SampleProviderConverters.ConvertWaveProviderIntoSampleProvider(waveProvider); } public static void Init(this IWavePlayer wavePlayer, ISampleProvider sampleProvider, bool convertTo16Bit = false) { IWaveProvider waveProvider2; if (!convertTo16Bit) { IWaveProvider waveProvider = new SampleToWaveProvider(sampleProvider); waveProvider2 = waveProvider; } else { IWaveProvider waveProvider = new SampleToWaveProvider16(sampleProvider); waveProvider2 = waveProvider; } IWaveProvider waveProvider3 = waveProvider2; wavePlayer.Init(waveProvider3); } public static WaveFormat AsStandardWaveFormat(this WaveFormat waveFormat) { if (!(waveFormat is WaveFormatExtensible waveFormatExtensible)) { return waveFormat; } return waveFormatExtensible.ToStandardWaveFormat(); } public static IWaveProvider ToWaveProvider(this ISampleProvider sampleProvider) { return new SampleToWaveProvider(sampleProvider); } public static IWaveProvider ToWaveProvider16(this ISampleProvider sampleProvider) { return new SampleToWaveProvider16(sampleProvider); } public static ISampleProvider FollowedBy(this ISampleProvider sampleProvider, ISampleProvider next) { return new ConcatenatingSampleProvider(new ISampleProvider[2] { sampleProvider, next }); } public static ISampleProvider FollowedBy(this ISampleProvider sampleProvider, TimeSpan silenceDuration, ISampleProvider next) { OffsetSampleProvider offsetSampleProvider = new OffsetSampleProvider(sampleProvider) { LeadOut = silenceDuration }; return new ConcatenatingSampleProvider(new ISampleProvider[2] { offsetSampleProvider, next }); } public static ISampleProvider Skip(this ISampleProvider sampleProvider, TimeSpan skipDuration) { return new OffsetSampleProvider(sampleProvider) { SkipOver = skipDuration }; } public static ISampleProvider Take(this ISampleProvider sampleProvider, TimeSpan takeDuration) { return new OffsetSampleProvider(sampleProvider) { Take = takeDuration }; } public static ISampleProvider ToMono(this ISampleProvider sourceProvider, float leftVol = 0.5f, float rightVol = 0.5f) { if (sourceProvider.WaveFormat.Channels == 1) { return sourceProvider; } return new StereoToMonoSampleProvider(sourceProvider) { LeftVolume = leftVol, RightVolume = rightVol }; } public static ISampleProvider ToStereo(this ISampleProvider sourceProvider, float leftVol = 1f, float rightVol = 1f) { if (sourceProvider.WaveFormat.Channels == 2) { return sourceProvider; } return new MonoToStereoSampleProvider(sourceProvider) { LeftVolume = leftVol, RightVolume = rightVol }; } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class AdpcmWaveFormat : WaveFormat { private short samplesPerBlock; private short numCoeff; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] private short[] coefficients; public int SamplesPerBlock => samplesPerBlock; public int NumCoefficients => numCoeff; public short[] Coefficients => coefficients; private AdpcmWaveFormat() : this(8000, 1) { } public AdpcmWaveFormat(int sampleRate, int channels) : base(sampleRate, 0, channels) { waveFormatTag = WaveFormatEncoding.Adpcm; extraSize = 32; switch (base.sampleRate) { case 8000: case 11025: blockAlign = 256; break; case 22050: blockAlign = 512; break; default: blockAlign = 1024; break; } bitsPerSample = 4; samplesPerBlock = (short)((blockAlign - 7 * channels) * 8 / (bitsPerSample * channels) + 2); averageBytesPerSecond = base.SampleRate * blockAlign / samplesPerBlock; numCoeff = 7; coefficients = new short[14] { 256, 0, 512, -256, 0, 0, 192, 64, 240, 0, 460, -208, 392, -232 }; } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(samplesPerBlock); writer.Write(numCoeff); short[] array = coefficients; foreach (short value in array) { writer.Write(value); } } public override string ToString() { return $"Microsoft ADPCM {base.SampleRate} Hz {channels} channels {bitsPerSample} bits per sample {samplesPerBlock} samples per block"; } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class Gsm610WaveFormat : WaveFormat { private readonly short samplesPerBlock; public short SamplesPerBlock => samplesPerBlock; public Gsm610WaveFormat() { waveFormatTag = WaveFormatEncoding.Gsm610; channels = 1; averageBytesPerSecond = 1625; bitsPerSample = 0; blockAlign = 65; sampleRate = 8000; extraSize = 2; samplesPerBlock = 320; } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(samplesPerBlock); } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class ImaAdpcmWaveFormat : WaveFormat { private short samplesPerBlock; private ImaAdpcmWaveFormat() { } public ImaAdpcmWaveFormat(int sampleRate, int channels, int bitsPerSample) { waveFormatTag = WaveFormatEncoding.DviAdpcm; base.sampleRate = sampleRate; base.channels = (short)channels; base.bitsPerSample = (short)bitsPerSample; extraSize = 2; blockAlign = 0; averageBytesPerSecond = 0; samplesPerBlock = 0; } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class Mp3WaveFormat : WaveFormat { public Mp3WaveFormatId id; public Mp3WaveFormatFlags flags; public ushort blockSize; public ushort framesPerBlock; public ushort codecDelay; private const short Mp3WaveFormatExtraBytes = 12; public Mp3WaveFormat(int sampleRate, int channels, int blockSize, int bitRate) { waveFormatTag = WaveFormatEncoding.MpegLayer3; base.channels = (short)channels; averageBytesPerSecond = bitRate / 8; bitsPerSample = 0; blockAlign = 1; base.sampleRate = sampleRate; extraSize = 12; id = Mp3WaveFormatId.Mpeg; flags = Mp3WaveFormatFlags.PaddingIso; this.blockSize = (ushort)blockSize; framesPerBlock = 1; codecDelay = 0; } } [Flags] public enum Mp3WaveFormatFlags { PaddingIso = 0, PaddingOn = 1, PaddingOff = 2 } public enum Mp3WaveFormatId : ushort { Unknown, Mpeg, ConstantFrameSize } [StructLayout(LayoutKind.Sequential, Pack = 2)] internal class OggWaveFormat : WaveFormat { public uint dwVorbisACMVersion; public uint dwLibVorbisVersion; } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class TrueSpeechWaveFormat : WaveFormat { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] private short[] unknown; public TrueSpeechWaveFormat() { waveFormatTag = WaveFormatEncoding.DspGroupTrueSpeech; channels = 1; averageBytesPerSecond = 1067; bitsPerSample = 1; blockAlign = 32; sampleRate = 8000; extraSize = 32; unknown = new short[16]; unknown[0] = 1; unknown[1] = 240; } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); short[] array = unknown; foreach (short value in array) { writer.Write(value); } } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class WaveFormat { protected WaveFormatEncoding waveFormatTag; protected short channels; protected int sampleRate; protected int averageBytesPerSecond; protected short blockAlign; protected short bitsPerSample; protected short extraSize; public WaveFormatEncoding Encoding => waveFormatTag; public int Channels => channels; public int SampleRate => sampleRate; public int AverageBytesPerSecond => averageBytesPerSecond; public virtual int BlockAlign => blockAlign; public int BitsPerSample => bitsPerSample; public int ExtraSize => extraSize; public WaveFormat() : this(44100, 16, 2) { } public WaveFormat(int sampleRate, int channels) : this(sampleRate, 16, channels) { } public int ConvertLatencyToByteSize(int milliseconds) { int num = (int)((double)AverageBytesPerSecond / 1000.0 * (double)milliseconds); if (num % BlockAlign != 0) { num = num + BlockAlign - num % BlockAlign; } return num; } public static WaveFormat CreateCustomFormat(WaveFormatEncoding tag, int sampleRate, int channels, int averageBytesPerSecond, int blockAlign, int bitsPerSample) { return new WaveFormat { waveFormatTag = tag, channels = (short)channels, sampleRate = sampleRate, averageBytesPerSecond = averageBytesPerSecond, blockAlign = (short)blockAlign, bitsPerSample = (short)bitsPerSample, extraSize = 0 }; } public static WaveFormat CreateALawFormat(int sampleRate, int channels) { return CreateCustomFormat(WaveFormatEncoding.ALaw, sampleRate, channels, sampleRate * channels, channels, 8); } public static WaveFormat CreateMuLawFormat(int sampleRate, int channels) { return CreateCustomFormat(WaveFormatEncoding.MuLaw, sampleRate, channels, sampleRate * channels, channels, 8); } public WaveFormat(int rate, int bits, int channels) { if (channels < 1) { throw new ArgumentOutOfRangeException("channels", "Channels must be 1 or greater"); } waveFormatTag = WaveFormatEncoding.Pcm; this.channels = (short)channels; sampleRate = rate; bitsPerSample = (short)bits; extraSize = 0; blockAlign = (short)(channels * (bits / 8)); averageBytesPerSecond = sampleRate * blockAlign; } public static WaveFormat CreateIeeeFloatWaveFormat(int sampleRate, int channels) { WaveFormat waveFormat = new WaveFormat(); waveFormat.waveFormatTag = WaveFormatEncoding.IeeeFloat; waveFormat.channels = (short)channels; waveFormat.bitsPerSample = 32; waveFormat.sampleRate = sampleRate; waveFormat.blockAlign = (short)(4 * channels); waveFormat.averageBytesPerSecond = sampleRate * waveFormat.blockAlign; waveFormat.extraSize = 0; return waveFormat; } public static WaveFormat MarshalFromPtr(IntPtr pointer) { WaveFormat waveFormat = Marshal.PtrToStructure<WaveFormat>(pointer); switch (waveFormat.Encoding) { case WaveFormatEncoding.Pcm: waveFormat.extraSize = 0; break; case WaveFormatEncoding.Extensible: waveFormat = Marshal.PtrToStructure<WaveFormatExtensible>(pointer); break; case WaveFormatEncoding.Adpcm: waveFormat = Marshal.PtrToStructure<AdpcmWaveFormat>(pointer); break; case WaveFormatEncoding.Gsm610: waveFormat = Marshal.PtrToStructure<Gsm610WaveFormat>(pointer); break; default: if (waveFormat.ExtraSize > 0) { waveFormat = Marshal.PtrToStructure<WaveFormatExtraData>(pointer); } break; } return waveFormat; } public static IntPtr MarshalToPtr(WaveFormat format) { IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(format)); Marshal.StructureToPtr(format, intPtr, fDeleteOld: false); return intPtr; } public static WaveFormat FromFormatChunk(BinaryReader br, int formatChunkLength) { WaveFormatExtraData waveFormatExtraData = new WaveFormatExtraData(); waveFormatExtraData.ReadWaveFormat(br, formatChunkLength); waveFormatExtraData.ReadExtraData(br); return waveFormatExtraData; } private void ReadWaveFormat(BinaryReader br, int formatChunkLength) { if (formatChunkLength < 16) { throw new InvalidDataException("Invalid WaveFormat Structure"); } waveFormatTag = (WaveFormatEncoding)br.ReadUInt16(); channels = br.ReadInt16(); sampleRate = br.ReadInt32(); averageBytesPerSecond = br.ReadInt32(); blockAlign = br.ReadInt16(); bitsPerSample = br.ReadInt16(); if (formatChunkLength > 16) { extraSize = br.ReadInt16(); if (extraSize != formatChunkLength - 18) { extraSize = (short)(formatChunkLength - 18); } } } public WaveFormat(BinaryReader br) { int formatChunkLength = br.ReadInt32(); ReadWaveFormat(br, formatChunkLength); } public override string ToString() { switch (waveFormatTag) { case WaveFormatEncoding.Pcm: case WaveFormatEncoding.Extensible: return $"{bitsPerSample} bit PCM: {sampleRate}Hz {channels} channels"; case WaveFormatEncoding.IeeeFloat: return $"{bitsPerSample} bit IEEFloat: {sampleRate}Hz {channels} channels"; default: return waveFormatTag.ToString(); } } public override bool Equals(object obj) { if (obj is WaveFormat waveFormat) { if (waveFormatTag == waveFormat.waveFormatTag && channels == waveFormat.channels && sampleRate == waveFormat.sampleRate && averageBytesPerSecond == waveFormat.averageBytesPerSecond && blockAlign == waveFormat.blockAlign) { return bitsPerSample == waveFormat.bitsPerSample; } return false; } return false; } public override int GetHashCode() { return (int)waveFormatTag ^ (int)channels ^ sampleRate ^ averageBytesPerSecond ^ blockAlign ^ bitsPerSample; } public virtual void Serialize(BinaryWriter writer) { writer.Write(18 + extraSize); writer.Write((short)Encoding); writer.Write((short)Channels); writer.Write(SampleRate); writer.Write(AverageBytesPerSecond); writer.Write((short)BlockAlign); writer.Write((short)BitsPerSample); writer.Write(extraSize); } } public sealed class WaveFormatCustomMarshaler : ICustomMarshaler { private static WaveFormatCustomMarshaler marshaler; public static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new WaveFormatCustomMarshaler(); } return marshaler; } public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { Marshal.FreeHGlobal(pNativeData); } public int GetNativeDataSize() { throw new NotImplementedException(); } public IntPtr MarshalManagedToNative(object ManagedObj) { return WaveFormat.MarshalToPtr((WaveFormat)ManagedObj); } public object MarshalNativeToManaged(IntPtr pNativeData) { return WaveFormat.MarshalFromPtr(pNativeData); } } public enum WaveFormatEncoding : ushort { Unknown = 0, Pcm = 1, Adpcm = 2, IeeeFloat = 3, Vselp = 4, IbmCvsd = 5, ALaw = 6, MuLaw = 7, Dts = 8, Drm = 9, WmaVoice9 = 10, OkiAdpcm = 16, DviAdpcm = 17, ImaAdpcm = 17, MediaspaceAdpcm = 18, SierraAdpcm = 19, G723Adpcm = 20, DigiStd = 21, DigiFix = 22, DialogicOkiAdpcm = 23, MediaVisionAdpcm = 24, CUCodec = 25, YamahaAdpcm = 32, SonarC = 33, DspGroupTrueSpeech = 34, EchoSpeechCorporation1 = 35, AudioFileAf36 = 36, Aptx = 37, AudioFileAf10 = 38, Prosody1612 = 39, Lrc = 40, DolbyAc2 = 48, Gsm610 = 49, MsnAudio = 50, AntexAdpcme = 51, ControlResVqlpc = 52, DigiReal = 53, DigiAdpcm = 54, ControlResCr10 = 55, WAVE_FORMAT_NMS_VBXADPCM = 56, WAVE_FORMAT_CS_IMAADPCM = 57, WAVE_FORMAT_ECHOSC3 = 58, WAVE_FORMAT_ROCKWELL_ADPCM = 59, WAVE_FORMAT_ROCKWELL_DIGITALK = 60, WAVE_FORMAT_XEBEC = 61, WAVE_FORMAT_G721_ADPCM = 64, WAVE_FORMAT_G728_CELP = 65, WAVE_FORMAT_MSG723 = 66, Mpeg = 80, WAVE_FORMAT_RT24 = 82, WAVE_FORMAT_PAC = 83, MpegLayer3 = 85, WAVE_FORMAT_LUCENT_G723 = 89, WAVE_FORMAT_CIRRUS = 96, WAVE_FORMAT_ESPCM = 97, WAVE_FORMAT_VOXWARE = 98, WAVE_FORMAT_CANOPUS_ATRAC = 99, WAVE_FORMAT_G726_ADPCM = 100, WAVE_FORMAT_G722_ADPCM = 101, WAVE_FORMAT_DSAT_DISPLAY = 103, WAVE_FORMAT_VOXWARE_BYTE_ALIGNED = 105, WAVE_FORMAT_VOXWARE_AC8 = 112, WAVE_FORMAT_VOXWARE_AC10 = 113, WAVE_FORMAT_VOXWARE_AC16 = 114, WAVE_FORMAT_VOXWARE_AC20 = 115, WAVE_FORMAT_VOXWARE_RT24 = 116, WAVE_FORMAT_VOXWARE_RT29 = 117, WAVE_FORMAT_VOXWARE_RT29HW = 118, WAVE_FORMAT_VOXWARE_VR12 = 119, WAVE_FORMAT_VOXWARE_VR18 = 120, WAVE_FORMAT_VOXWARE_TQ40 = 121, WAVE_FORMAT_SOFTSOUND = 128, WAVE_FORMAT_VOXWARE_TQ60 = 129, WAVE_FORMAT_MSRT24 = 130, WAVE_FORMAT_G729A = 131, WAVE_FORMAT_MVI_MVI2 = 132, WAVE_FORMAT_DF_G726 = 133, WAVE_FORMAT_DF_GSM610 = 134, WAVE_FORMAT_ISIAUDIO = 136, WAVE_FORMAT_ONLIVE = 137, WAVE_FORMAT_SBC24 = 145, WAVE_FORMAT_DOLBY_AC3_SPDIF = 146, WAVE_FORMAT_MEDIASONIC_G723 = 147, WAVE_FORMAT_PROSODY_8KBPS = 148, WAVE_FORMAT_ZYXEL_ADPCM = 151, WAVE_FORMAT_PHILIPS_LPCBB = 152, WAVE_FORMAT_PACKED = 153, WAVE_FORMAT_MALDEN_PHONYTALK = 160, Gsm = 161, G729 = 162, G723 = 163, Acelp = 164, RawAac = 255, WAVE_FORMAT_RHETOREX_ADPCM = 256, WAVE_FORMAT_IRAT = 257, WAVE_FORMAT_VIVO_G723 = 273, WAVE_FORMAT_VIVO_SIREN = 274, WAVE_FORMAT_DIGITAL_G723 = 291, WAVE_FORMAT_SANYO_LD_ADPCM = 293, WAVE_FORMAT_SIPROLAB_ACEPLNET = 304, WAVE_FORMAT_SIPROLAB_ACELP4800 = 305, WAVE_FORMAT_SIPROLAB_ACELP8V3 = 306, WAVE_FORMAT_SIPROLAB_G729 = 307, WAVE_FORMAT_SIPROLAB_G729A = 308, WAVE_FORMAT_SIPROLAB_KELVIN = 309, WAVE_FORMAT_G726ADPCM = 320, WAVE_FORMAT_QUALCOMM_PUREVOICE = 336, WAVE_FORMAT_QUALCOMM_HALFRATE = 337, WAVE_FORMAT_TUBGSM = 341, WAVE_FORMAT_MSAUDIO1 = 352, WindowsMediaAudio = 353, WindowsMediaAudioProfessional = 354, WindowsMediaAudioLosseless = 355, WindowsMediaAudioSpdif = 356, WAVE_FORMAT_UNISYS_NAP_ADPCM = 368, WAVE_FORMAT_UNISYS_NAP_ULAW = 369, WAVE_FORMAT_UNISYS_NAP_ALAW = 370, WAVE_FORMAT_UNISYS_NAP_16K = 371, WAVE_FORMAT_CREATIVE_ADPCM = 512, WAVE_FORMAT_CREATIVE_FASTSPEECH8 = 514, WAVE_FORMAT_CREATIVE_FASTSPEECH10 = 515, WAVE_FORMAT_UHER_ADPCM = 528, WAVE_FORMAT_QUARTERDECK = 544, WAVE_FORMAT_ILINK_VC = 560, WAVE_FORMAT_RAW_SPORT = 576, WAVE_FORMAT_ESST_AC3 = 577, WAVE_FORMAT_IPI_HSX = 592, WAVE_FORMAT_IPI_RPELP = 593, WAVE_FORMAT_CS2 = 608, WAVE_FORMAT_SONY_SCX = 624, WAVE_FORMAT_FM_TOWNS_SND = 768, WAVE_FORMAT_BTV_DIGITAL = 1024, WAVE_FORMAT_QDESIGN_MUSIC = 1104, WAVE_FORMAT_VME_VMPCM = 1664, WAVE_FORMAT_TPC = 1665, WAVE_FORMAT_OLIGSM = 4096, WAVE_FORMAT_OLIADPCM = 4097, WAVE_FORMAT_OLICELP = 4098, WAVE_FORMAT_OLISBC = 4099, WAVE_FORMAT_OLIOPR = 4100, WAVE_FORMAT_LH_CODEC = 4352, WAVE_FORMAT_NORRIS = 5120, WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS = 5376, MPEG_ADTS_AAC = 5632, MPEG_RAW_AAC = 5633, MPEG_LOAS = 5634, NOKIA_MPEG_ADTS_AAC = 5640, NOKIA_MPEG_RAW_AAC = 5641, VODAFONE_MPEG_ADTS_AAC = 5642, VODAFONE_MPEG_RAW_AAC = 5643, MPEG_HEAAC = 5648, WAVE_FORMAT_DVM = 8192, Vorbis1 = 26447, Vorbis2 = 26448, Vorbis3 = 26449, Vorbis1P = 26479, Vorbis2P = 26480, Vorbis3P = 26481, Extensible = 65534, WAVE_FORMAT_DEVELOPMENT = ushort.MaxValue } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class WaveFormatExtensible : WaveFormat { private short wValidBitsPerSample; private int dwChannelMask; private Guid subFormat; public Guid SubFormat => subFormat; private WaveFormatExtensible() { } public WaveFormatExtensible(int rate, int bits, int channels, int channelMask = 0) : base(rate, bits, channels) { waveFormatTag = WaveFormatEncoding.Extensible; extraSize = 22; wValidBitsPerSample = (short)bits; if (channelMask != 0) { dwChannelMask = channelMask; } else { for (int i = 0; i < channels; i++) { dwChannelMask |= 1 << i; } } if (bits == 32) { subFormat = AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; } else { subFormat = AudioMediaSubtypes.MEDIASUBTYPE_PCM; } } public WaveFormat ToStandardWaveFormat() { if (subFormat == AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT && bitsPerSample == 32) { return WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels); } if (subFormat == AudioMediaSubtypes.MEDIASUBTYPE_PCM) { return new WaveFormat(sampleRate, bitsPerSample, channels); } return this; } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(wValidBitsPerSample); writer.Write(dwChannelMask); byte[] array = subFormat.ToByteArray(); writer.Write(array, 0, array.Length); } public override string ToString() { return "WAVE_FORMAT_EXTENSIBLE " + AudioMediaSubtypes.GetAudioSubtypeName(subFormat) + " " + $"{base.SampleRate}Hz {base.Channels} channels {base.BitsPerSample} bit"; } } [StructLayout(LayoutKind.Sequential, Pack = 2)] public class WaveFormatExtraData : WaveFormat { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] private byte[] extraData = new byte[100]; public byte[] ExtraData => extraData; internal WaveFormatExtraData() { } public WaveFormatExtraData(BinaryReader reader) : base(reader) { ReadExtraData(reader); } internal void ReadExtraData(BinaryReader reader) { if (extraSize > 0) { reader.Read(extraData, 0, extraSize); } } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); if (extraSize > 0) { writer.Write(extraData, 0, extraSize); } } } public interface IWaveIn : IDisposable { WaveFormat WaveFormat { get; set; } event EventHandler<WaveInEventArgs> DataAvailable; event EventHandler<StoppedEventArgs> RecordingStopped; void StartRecording(); void StopRecording(); } public class WaveInEventArgs : EventArgs { private byte[] buffer; private int bytes; public byte[] Buffer => buffer; public int BytesRecorded => bytes; public WaveInEventArgs(byte[] buffer, int bytes) { this.buffer = buffer; this.bytes = bytes; } } public class AiffFileWriter : Stream { private Stream outStream; private BinaryWriter writer; private long dataSizePos; private long commSampleCountPos; private long dataChunkSize = 8L; private WaveFormat format; private string filename; private byte[] value24 = new byte[3]; public string Filename => filename; public override long Length => dataChunkSize; public WaveFormat WaveFormat => format; public override bool CanRead => false; public override bool CanWrite => true; public override bool CanSeek => false; public override long Position { get { return dataChunkSize; } set { throw new InvalidOperationException("Repositioning an AiffFileWriter is not supported"); } } public static void CreateAiffFile(string filename, WaveStream sourceProvider) { using AiffFileWriter aiffFileWriter = new AiffFileWriter(filename, sourceProvider.WaveFormat); byte[] array = new byte[16384]; while (sourceProvider.Position < sourceProvider.Length) { int count = Math.Min((int)(sourceProvider.Length - sourceProvider.Position), array.Length); int num = sourceProvider.Read(array, 0, count); if (num == 0) { break; } aiffFileWriter.Write(array, 0, num); } } public AiffFileWriter(Stream outStream, WaveFormat format) { this.outStream = outStream; this.format = format; writer = new BinaryWriter(outStream, Encoding.UTF8); writer.Write(Encoding.UTF8.GetBytes("FORM")); writer.Write(0); writer.Write(Encoding.UTF8.GetBytes("AIFF")); CreateCommChunk(); WriteSsndChunkHeader(); } public AiffFileWriter(string filename, WaveFormat format) : this(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read), format) { this.filename = filename; } private void WriteSsndChunkHeader() { writer.Write(Encoding.UTF8.GetBytes("SSND")); dataSizePos = outStream.Position; writer.Write(0); writer.Write(0); writer.Write(SwapEndian(format.BlockAlign)); } private byte[] SwapEndian(short n) { return new byte[2] { (byte)(n >> 8), (byte)((uint)n & 0xFFu) }; } private byte[] SwapEndian(int n) { return new byte[4] { (byte)((uint)(n >> 24) & 0xFFu), (byte)((uint)(n >> 16) & 0xFFu), (byte)((uint)(n >> 8) & 0xFFu), (byte)((uint)n & 0xFFu) }; } private void CreateCommChunk() { writer.Write(Encoding.UTF8.GetBytes("COMM")); writer.Write(SwapEndian(18)); writer.Write(SwapEndian((short)format.Channels)); commSampleCountPos = outStream.Position; writer.Write(0); writer.Write(SwapEndian((short)format.BitsPerSample)); writer.Write(IEEE.ConvertToIeeeExtended(format.SampleRate)); } public override int Read(byte[] buffer, int offset, int count) { throw new InvalidOperationException("Cannot read from an AiffFileWriter"); } public override long Seek(long offset, SeekOrigin origin) { throw new InvalidOperationException("Cannot seek within an AiffFileWriter"); } public override void SetLength(long value) { throw new InvalidOperationException("Cannot set length of an AiffFileWriter"); } public override void Write(byte[] data, int offset, int count) { byte[] array = new byte[data.Length]; int num = format.BitsPerSample / 8; for (int i = 0; i < data.Length; i++) { int num2 = (int)Math.Floor((double)i / (double)num) * num + (num - i % num - 1); array[i] = data[num2]; } outStream.Write(array, offset, count); dataChunkSize += count; } public void WriteSample(float sample) { if (WaveFormat.BitsPerSample == 16) { writer.Write(SwapEndian((short)(32767f * sample))); dataChunkSize += 2L; } else if (WaveFormat.BitsPerSample == 24) { byte[] bytes = BitConverter.GetBytes((int)(2.1474836E+09f * sample)); value24[2] = bytes[1]; value24[1] = bytes[2]; value24[0] = bytes[3]; writer.Write(value24); dataChunkSize += 3L; } else { if (WaveFormat.BitsPerSample != 32 || WaveFormat.Encoding != WaveFormatEncoding.Extensible) { throw new InvalidOperationException("Only 16, 24 or 32 bit PCM or IEEE float audio data supported"); } writer.Write(SwapEndian(65535 * (int)sample)); dataChunkSize += 4L; } } public void WriteSamples(float[] samples, int offset, int count) { for (int i = 0; i < count; i++) { WriteSample(samples[offset + i]); } } public void WriteSamples(short[] samples, int offset, int count) { if (WaveFormat.BitsPerSample == 16) { for (int i = 0; i < count; i++) { writer.Write(SwapEndian(samples[i + offset])); } dataChunkSize += count * 2; } else if (WaveFormat.BitsPerSample == 24) { for (int j = 0; j < count; j++) { byte[] bytes = BitConverter.GetBytes(65535 * samples[j + offset]); value24[2] = bytes[1]; value24[1] = bytes[2]; value24[0] = bytes[3]; writer.Write(value24); } dataChunkSize += count * 3; } else { if (WaveFormat.BitsPerSample != 32 || WaveFormat.Encoding != WaveFormatEncoding.Extensible) { throw new InvalidOperationException("Only 16, 24 or 32 bit PCM audio data supported"); } for (int k = 0; k < count; k++) { writer.Write(SwapEndian(65535 * samples[k + offset])); } dataChunkSize += count * 4; } } public override void Flush() { writer.Flush(); } protected override void Dispose(bool disposing) { if (disposing && outStream != null) { try { UpdateHeader(writer); } finally { outStream.Dispose(); outStream = null; } } } protected virtual void UpdateHeader(BinaryWriter writer) { Flush(); writer.Seek(4, SeekOrigin.Begin); writer.Write(SwapEndian((int)(outStream.Length - 8))); UpdateCommChunk(writer); UpdateSsndChunk(writer); } private void UpdateCommChunk(BinaryWriter writer) { writer.Seek((int)commSampleCountPos, SeekOrigin.Begin); writer.Write(SwapEndian((int)(dataChunkSize * 8 / format.BitsPerSample / format.Channels))); } private void UpdateSsndChunk(BinaryWriter writer) { writer.Seek((int)dataSizePos, SeekOrigin.Begin); writer.Write(SwapEndian((int)dataChunkSize)); } ~AiffFileWriter() { Dispose(disposing: false); } } public class BextChunkInfo { public string Description { get; set; } public string Originator { get; set; } public string OriginatorReference { get; set; } public DateTime OriginationDateTime { get; set; } public string OriginationDate => OriginationDateTime.ToString("yyyy-MM-dd"); public string OriginationTime => OriginationDateTime.ToString("HH:mm:ss"); public long TimeReference { get; set; } public ushort Version => 1; public string UniqueMaterialIdentifier { get; set; } public byte[] Reserved { get; } public string CodingHistory { get; set; } public BextChunkInfo() { Reserved = new byte[190]; } } public class BwfWriter : IDisposable { private readonly WaveFormat format; private readonly BinaryWriter writer; private readonly long dataChunkSizePosition; private long dataLength; private bool isDisposed; public BwfWriter(string filename, WaveFormat format, BextChunkInfo bextChunkInfo) { this.format = format; writer = new BinaryWriter(File.OpenWrite(filename)); writer.Write(Encoding.UTF8.GetBytes("RIFF")); writer.Write(0); writer.Write(Encoding.UTF8.GetBytes("WAVE")); writer.Write(Encoding.UTF8.GetBytes("JUNK")); writer.Write(28); writer.Write(0L); writer.Write(0L); writer.Write(0L); writer.Write(0); writer.Write(Encoding.UTF8.GetBytes("bext")); byte[] bytes = Encoding.ASCII.GetBytes(bextChunkInfo.CodingHistory ?? ""); int num = 602 + bytes.Length; if (num % 2 != 0) { num++; } writer.Write(num); _ = writer.BaseStream.Position; writer.Write(GetAsBytes(bextChunkInfo.Description, 256)); writer.Write(GetAsBytes(bextChunkInfo.Originator, 32)); writer.Write(GetAsBytes(bextChunkInfo.OriginatorReference, 32)); writer.Write(GetAsBytes(bextChunkInfo.OriginationDate, 10)); writer.Write(GetAsBytes(bextChunkInfo.OriginationTime, 8)); writer.Write(bextChunkInfo.TimeReference); writer.Write(bextChunkInfo.Version); writer.Write(GetAsBytes(bextChunkInfo.UniqueMaterialIdentifier, 64)); writer.Write(bextChunkInfo.Reserved); writer.Write(bytes); if (bytes.Length % 2 != 0) { writer.Write((byte)0); } writer.Write(Encoding.UTF8.GetBytes("fmt ")); format.Serialize(writer); writer.Write(Encoding.UTF8.GetBytes("data")); dataChunkSizePosition = writer.BaseStream.Position; writer.Write(-1); } public void Write(byte[] buffer, int offset, int count) { if (isDisposed) { throw new ObjectDisposedException("This BWF Writer already disposed"); } writer.Write(buffer, offset, count); dataLength += count; } public void Flush() { if (isDisposed) { throw new ObjectDisposedException("This BWF Writer already disposed"); } writer.Flush(); FixUpChunkSizes(restorePosition: true); } private void FixUpChunkSizes(bool restorePosition) { long position = writer.BaseStream.Position; bool num = dataLength > int.MaxValue; long num2 = writer.BaseStream.Length - 8; if (num) { int num3 = format.BitsPerSample / 8 * format.Channels; writer.BaseStream.Position = 0L; writer.Write(Encoding.UTF8.GetBytes("RF64")); writer.Write(-1); writer.BaseStream.Position += 4L; writer.Write(Encoding.UTF8.GetBytes("ds64")); writer.BaseStream.Position += 4L; writer.Write(num2); writer.Write(dataLength); writer.Write(dataLength / num3); } else { writer.BaseStream.Position = 4L; writer.Write((uint)num2); writer.BaseStream.Position = dataChunkSizePosition; writer.Write((uint)dataLength); } if (restorePosition) { writer.BaseStream.Position = position; } } public void Dispose() { if (!isDisposed) { FixUpChunkSizes(restorePosition: false); writer.Dispose(); isDisposed = true; } } private static byte[] GetAsBytes(string message, int byteSize) { byte[] array = new byte[byteSize]; byte[] bytes = Encoding.ASCII.GetBytes(message ?? ""); Array.Copy(bytes, array, Math.Min(bytes.Length, byteSize)); return array; } } public class CueWaveFileWriter : WaveFileWriter { private CueList cues; public CueWaveFileWriter(string fileName, WaveFormat waveFormat) : base(fileName, waveFormat) { } public void AddCue(int position, string label) { if (cues == null) { cues = new CueList(); } cues.Add(new Cue(position, label)); } private void WriteCues(BinaryWriter w) { if (cues != null) { int count = cues.GetRiffChunks().Length; w.Seek(0, SeekOrigin.End); if (w.BaseStream.Length % 2 == 1) { w.Write((byte)0); } w.Write(cues.GetRiffChunks(), 0, count); w.Seek(4, SeekOrigin.Begin); w.Write((int)(w.BaseStream.Length - 8)); } } protected override void UpdateHeader(BinaryWriter writer) { base.UpdateHeader(writer); WriteCues(writer); } } public class DirectSoundOut : IWavePlayer, IDisposable { [StructLayout(LayoutKind.Sequential, Pack = 2)] internal class BufferDescription { public int dwSize; [MarshalAs(UnmanagedType.U4)] public DirectSoundBufferCaps dwFlags; public uint dwBufferBytes; public int dwReserved; public IntPtr lpwfxFormat; public Guid guidAlgo; } [StructLayout(LayoutKind.Sequential, Pack = 2)] internal class BufferCaps { public int dwSize; public int dwFlags; public int dwBufferBytes; public int dwUnlockTransferRate; public int dwPlayCpuOverhead; } internal enum DirectSoundCooperativeLevel : uint { DSSCL_NORMAL = 1u, DSSCL_PRIORITY, DSSCL_EXCLUSIVE, DSSCL_WRITEPRIMARY } [Flags] internal enum DirectSoundPlayFlags : uint { DSBPLAY_LOOPING = 1u, DSBPLAY_LOCHARDWARE = 2u, DSBPLAY_LOCSOFTWARE = 4u, DSBPLAY_TERMINATEBY_TIME = 8u, DSBPLAY_TERMINATEBY_DISTANCE = 0x10u, DSBPLAY_TERMINATEBY_PRIORITY = 0x20u } internal enum DirectSoundBufferLockFlag : uint { None, FromWriteCursor, EntireBuffer } [Flags] internal enum DirectSoundBufferStatus : uint { DSBSTATUS_PLAYING = 1u, DSBSTATUS_BUFFERLOST = 2u, DSBSTATUS_LOOPING = 4u, DSBSTATUS_LOCHARDWARE = 8u, DSBSTATUS_LOCSOFTWARE = 0x10u, DSBSTATUS_TERMINATED = 0x20u } [Flags] internal enum DirectSoundBufferCaps : uint { DSBCAPS_PRIMARYBUFFER = 1u, DSBCAPS_STATIC = 2u, DSBCAPS_LOCHARDWARE = 4u, DSBCAPS_LOCSOFTWARE = 8u, DSBCAPS_CTRL3D = 0x10u, DSBCAPS_CTRLFREQUENCY = 0x20u, DSBCAPS_CTRLPAN = 0x40u, DSBCAPS_CTRLVOLUME = 0x80u, DSBCAPS_CTRLPOSITIONNOTIFY = 0x100u, DSBCAPS_CTRLFX = 0x200u, DSBCAPS_STICKYFOCUS = 0x4000u, DSBCAPS_GLOBALFOCUS = 0x8000u, DSBCAPS_GETCURRENTPOSITION2 = 0x10000u, DSBCAPS_MUTE3DATMAXDISTANCE = 0x20000u, DSBCAPS_LOCDEFER = 0x40000u } internal struct DirectSoundBufferPositionNotify { public uint dwOffset; public IntPtr hEventNotify; } [ComImport] [Guid("279AFA83-4981-11CE-A521-0020AF0BE560")] [SuppressUnmanagedCodeSecurity] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSound { void CreateSoundBuffer([In] BufferDescription desc, [MarshalAs(UnmanagedType.Interface)] out object dsDSoundBuffer, IntPtr pUnkOuter); void GetCaps(IntPtr caps); void DuplicateSoundBuffer([In][MarshalAs(UnmanagedType.Interface)] IDirectSoundBuffer bufferOriginal, [In][MarshalAs(UnmanagedType.Interface)] IDirectSoundBuffer bufferDuplicate); void SetCooperativeLevel(IntPtr HWND, [In][MarshalAs(UnmanagedType.U4)] DirectSoundCooperativeLevel dwLevel); void Compact(); void GetSpeakerConfig(IntPtr pdwSpeakerConfig); void SetSpeakerConfig(uint pdwSpeakerConfig); void Initialize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guid); } [ComImport] [Guid("279AFA85-4981-11CE-A521-0020AF0BE560")] [SuppressUnmanagedCodeSecurity] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundBuffer { void GetCaps([MarshalAs(UnmanagedType.LPStruct)] BufferCaps pBufferCaps); void GetCurrentPosition(out uint currentPlayCursor, out uint currentWriteCursor); void GetFormat(); [return: MarshalAs(UnmanagedType.I4)] int GetVolume(); void GetPan(out uint pan); [return: MarshalAs(UnmanagedType.I4)] int GetFrequency(); [return: MarshalAs(UnmanagedType.U4)] DirectSoundBufferStatus GetStatus(); void Initialize([In][MarshalAs(UnmanagedType.Interface)] IDirectSound directSound, [In] BufferDescription desc); void Lock(int dwOffset, uint dwBytes, out IntPtr audioPtr1, out int audioBytes1, out IntPtr audioPtr2, out int audioBytes2, [MarshalAs(UnmanagedType.U4)] DirectSoundBufferLockFlag dwFlags); void Play(uint dwReserved1, uint dwPriority, [In][MarshalAs(UnmanagedType.U4)] DirectSoundPlayFlags dwFlags); void SetCurrentPosition(uint dwNewPosition); void SetFormat([In] WaveFormat pcfxFormat); void SetVolume(int volume); void SetPan(uint pan); void SetFrequency(uint frequency); void Stop(); void Unlock(IntPtr pvAudioPtr1, int dwAudioBytes1, IntPtr pvAudioPtr2, int dwAudioBytes2); void Restore(); } [ComImport] [Guid("b0210783-89cd-11d0-af08-00a0c925cd16")] [SuppressUnmanagedCodeSecurity] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IDirectSoundNotify { void SetNotificationPositions(uint dwPositionNotifies, [In][MarshalAs(UnmanagedType.LPArray)] DirectSoundBufferPositionNotify[] pcPositionNotifies); } private delegate bool DSEnumCallback(IntPtr lpGuid, IntPtr lpcstrDescription, IntPtr lpcstrModule, IntPtr lpContext); private PlaybackState playbackState; private WaveFormat waveFormat; private int samplesTotalSize; private int samplesFrameSize; private int nextSamplesWriteIndex; private int desiredLatency; private Guid device; private byte[] sam
UserLibs/NAudio.dll
Decompiled a day agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using NAudio.Wave.SampleProviders; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Mark Heath & Contributors")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Mark Heath 2026")] [assembly: AssemblyDescription("NAudio, an audio library for .NET")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0+c89fee940ee6f8d7374d18714a6b85d8b7a18ab0")] [assembly: AssemblyProduct("NAudio")] [assembly: AssemblyTitle("NAudio")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NAudio")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.3.0.0")] [module: UnverifiableCode] namespace NAudio.Wave; public class AudioFileReader : WaveStream, ISampleProvider { private WaveStream readerStream; private readonly SampleChannel sampleChannel; private readonly int destBytesPerSample; private readonly int sourceBytesPerSample; private readonly long length; private readonly object lockObject; public string FileName { get; } public override WaveFormat WaveFormat => sampleChannel.WaveFormat; public override long Length => length; public override long Position { get { return SourceToDest(((Stream)(object)readerStream).Position); } set { lock (lockObject) { ((Stream)(object)readerStream).Position = DestToSource(value); } } } public float Volume { get { return sampleChannel.Volume; } set { sampleChannel.Volume = value; } } public AudioFileReader(string fileName) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown lockObject = new object(); FileName = fileName; CreateReaderStream(fileName); sourceBytesPerSample = readerStream.WaveFormat.BitsPerSample / 8 * readerStream.WaveFormat.Channels; sampleChannel = new SampleChannel((IWaveProvider)(object)readerStream, false); destBytesPerSample = 4 * sampleChannel.WaveFormat.Channels; length = SourceToDest(((Stream)(object)readerStream).Length); } private void CreateReaderStream(string fileName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown if (fileName.EndsWith(".wav", StringComparison.OrdinalIgnoreCase)) { readerStream = (WaveStream)new WaveFileReader(fileName); if ((int)readerStream.WaveFormat.Encoding != 1 && (int)readerStream.WaveFormat.Encoding != 3) { readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream); readerStream = (WaveStream)new BlockAlignReductionStream(readerStream); } } else if (fileName.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)) { if (Environment.OSVersion.Version.Major < 6) { readerStream = (WaveStream)(object)new Mp3FileReader(fileName); } else { readerStream = (WaveStream)new MediaFoundationReader(fileName); } } else if (fileName.EndsWith(".aiff", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".aif", StringComparison.OrdinalIgnoreCase)) { readerStream = (WaveStream)new AiffFileReader(fileName); } else { readerStream = (WaveStream)new MediaFoundationReader(fileName); } } public override int Read(byte[] buffer, int offset, int count) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown WaveBuffer val = new WaveBuffer(buffer); int count2 = count / 4; return Read(val.FloatBuffer, offset / 4, count2) * 4; } public int Read(float[] buffer, int offset, int count) { lock (lockObject) { return sampleChannel.Read(buffer, offset, count); } } private long SourceToDest(long sourceBytes) { return destBytesPerSample * (sourceBytes / sourceBytesPerSample); } private long DestToSource(long destBytes) { return sourceBytesPerSample * (destBytes / destBytesPerSample); } protected override void Dispose(bool disposing) { if (disposing && readerStream != null) { ((Stream)(object)readerStream).Dispose(); readerStream = null; } ((Stream)this).Dispose(disposing); } } public class Mp3FileReader : Mp3FileReaderBase { public Mp3FileReader(string mp3FileName) : base((Stream)File.OpenRead(mp3FileName), new FrameDecompressorBuilder(CreateAcmFrameDecompressor), true) { }//IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown public Mp3FileReader(Stream inputStream) : base(inputStream, new FrameDecompressorBuilder(CreateAcmFrameDecompressor), false) { }//IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown public static IMp3FrameDecompressor CreateAcmFrameDecompressor(WaveFormat mp3Format) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return (IMp3FrameDecompressor)new AcmMp3FrameDecompressor(mp3Format); } }
UserLibs/NAudio.Wasapi.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; using NAudio.Dmo; using NAudio.Dmo.Effect; using NAudio.MediaFoundation; using NAudio.Utils; using NAudio.Wasapi.CoreAudioApi; using NAudio.Wasapi.CoreAudioApi.Interfaces; using NAudio.Wave; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Mark Heath")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Mark Heath 2026")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0+c89fee940ee6f8d7374d18714a6b85d8b7a18ab0")] [assembly: AssemblyProduct("NAudio.Wasapi")] [assembly: AssemblyTitle("NAudio.Wasapi")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NAudio")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.3.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace NAudio.MediaFoundation { public static class AudioSubtypes { [FieldDescription("AAC")] public static readonly Guid MFAudioFormat_AAC = new Guid("00001610-0000-0010-8000-00aa00389b71"); [FieldDescription("ADTS")] public static readonly Guid MFAudioFormat_ADTS = new Guid("00001600-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby AC3 SPDIF")] public static readonly Guid MFAudioFormat_Dolby_AC3_SPDIF = new Guid("00000092-0000-0010-8000-00aa00389b71"); [FieldDescription("DRM")] public static readonly Guid MFAudioFormat_DRM = new Guid("00000009-0000-0010-8000-00aa00389b71"); [FieldDescription("DTS")] public static readonly Guid MFAudioFormat_DTS = new Guid("00000008-0000-0010-8000-00aa00389b71"); [FieldDescription("IEEE floating-point")] public static readonly Guid MFAudioFormat_Float = new Guid("00000003-0000-0010-8000-00aa00389b71"); [FieldDescription("MP3")] public static readonly Guid MFAudioFormat_MP3 = new Guid("00000055-0000-0010-8000-00aa00389b71"); [FieldDescription("MPEG")] public static readonly Guid MFAudioFormat_MPEG = new Guid("00000050-0000-0010-8000-00aa00389b71"); [FieldDescription("WMA 9 Voice codec")] public static readonly Guid MFAudioFormat_MSP1 = new Guid("0000000a-0000-0010-8000-00aa00389b71"); [FieldDescription("PCM")] public static readonly Guid MFAudioFormat_PCM = new Guid("00000001-0000-0010-8000-00aa00389b71"); [FieldDescription("WMA SPDIF")] public static readonly Guid MFAudioFormat_WMASPDIF = new Guid("00000164-0000-0010-8000-00aa00389b71"); [FieldDescription("WMAudio Lossless")] public static readonly Guid MFAudioFormat_WMAudio_Lossless = new Guid("00000163-0000-0010-8000-00aa00389b71"); [FieldDescription("Windows Media Audio")] public static readonly Guid MFAudioFormat_WMAudioV8 = new Guid("00000161-0000-0010-8000-00aa00389b71"); [FieldDescription("Windows Media Audio Professional")] public static readonly Guid MFAudioFormat_WMAudioV9 = new Guid("00000162-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby AC3")] public static readonly Guid MFAudioFormat_Dolby_AC3 = new Guid("e06d802c-db46-11cf-b4d1-00805f6cbbea"); public static readonly Guid MFAudioFormat_FLAC = new Guid("0000f1ac-0000-0010-8000-00aa00389b71"); public static readonly Guid MFAudioFormat_ALAC = new Guid("63616c61-0000-0010-8000-00aa00389b71"); [FieldDescription("MPEG-4 and AAC Audio Types")] public static readonly Guid MEDIASUBTYPE_RAW_AAC1 = new Guid("000000ff-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby Audio Types")] public static readonly Guid MEDIASUBTYPE_DVM = new Guid("00002000-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby Audio Types")] public static readonly Guid MEDIASUBTYPE_DOLBY_DDPLUS = new Guid("a7fb87af-2d02-42fb-a4d4-05cd93843bdd"); [FieldDescription("μ-law")] public static readonly Guid KSDATAFORMAT_SUBTYPE_MULAW = new Guid("00000007-0000-0010-8000-00aa00389b71"); [FieldDescription("ADPCM")] public static readonly Guid KSDATAFORMAT_SUBTYPE_ADPCM = new Guid("00000002-0000-0010-8000-00aa00389b71"); [FieldDescription("Dolby Digital Plus for HDMI")] public static readonly Guid KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS = new Guid("0000000a-0cea-0010-8000-00aa00389b71"); [FieldDescription("MSAudio1")] public static readonly Guid MEDIASUBTYPE_MSAUDIO1 = new Guid("00000160-0000-0010-8000-00aa00389b71"); [FieldDescription("IMA ADPCM")] public static readonly Guid ImaAdpcm = new Guid("00000011-0000-0010-8000-00aa00389b71"); [FieldDescription("WMSP2")] public static readonly Guid WMMEDIASUBTYPE_WMSP2 = new Guid("0000000b-0000-0010-8000-00aa00389b71"); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("7FEE9E9A-4A89-47a6-899C-B6A53A70FB67")] public interface IMFActivate : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void ActivateObject([In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv); void ShutdownObject(); void DetachObject(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("2CD2D921-C447-44A7-A13C-4ADABFC247E3")] public interface IMFAttributes { void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr Value); void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); void DeleteAllItems(); void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); void LockStore(); void UnlockStore(); void GetCount(out int pcItems); void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("ad4c1b00-4bf7-422f-9175-756693d9130d")] public interface IMFByteStream { void GetCapabilities(ref int pdwCapabiities); void GetLength(ref long pqwLength); void SetLength(long qwLength); void GetCurrentPosition(ref long pqwPosition); void SetCurrentPosition(long qwPosition); void IsEndOfStream([MarshalAs(UnmanagedType.Bool)] ref bool pfEndOfStream); void Read(IntPtr pb, int cb, ref int pcbRead); void BeginRead(IntPtr pb, int cb, IntPtr pCallback, IntPtr punkState); void EndRead(IntPtr pResult, ref int pcbRead); void Write(IntPtr pb, int cb, ref int pcbWritten); void BeginWrite(IntPtr pb, int cb, IntPtr pCallback, IntPtr punkState); void EndWrite(IntPtr pResult, ref int pcbWritten); void Seek(int SeekOrigin, long llSeekOffset, int dwSeekFlags, ref long pqwCurrentPosition); void Flush(); void Close(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("5BC8A76B-869A-46A3-9B03-FA218A66AEBE")] public interface IMFCollection { void GetElementCount(out int pcElements); void GetElement([In] int dwElementIndex, [MarshalAs(UnmanagedType.IUnknown)] out object ppUnkElement); void AddElement([In][MarshalAs(UnmanagedType.IUnknown)] object pUnkElement); void RemoveElement([In] int dwElementIndex, [MarshalAs(UnmanagedType.IUnknown)] out object ppUnkElement); void InsertElementAt([In] int dwIndex, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); void RemoveAllElements(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("045FA593-8799-42b8-BC8D-8968C6453507")] public interface IMFMediaBuffer { void Lock(out IntPtr ppbBuffer, out int pcbMaxLength, out int pcbCurrentLength); void Unlock(); void GetCurrentLength(out int pcbCurrentLength); void SetCurrentLength(int cbCurrentLength); void GetMaxLength(out int pcbMaxLength); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("DF598932-F10C-4E39-BBA2-C308F101DAA3")] public interface IMFMediaEvent : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void GetType(out MediaEventType pmet); void GetExtendedType(out Guid pguidExtendedType); void GetStatus([MarshalAs(UnmanagedType.Error)] out int phrStatus); void GetValue([Out] IntPtr pvValue); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("44AE0FA8-EA31-4109-8D2E-4CAE4997C555")] public interface IMFMediaType : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void GetMajorType(out Guid pguidMajorType); void IsCompressedFormat([MarshalAs(UnmanagedType.Bool)] out bool pfCompressed); [PreserveSig] int IsEqual([In][MarshalAs(UnmanagedType.Interface)] IMFMediaType pIMediaType, ref int pdwFlags); void GetRepresentation([In] Guid guidRepresentation, ref IntPtr ppvRepresentation); void FreeRepresentation([In] Guid guidRepresentation, [In] IntPtr pvRepresentation); } [ComImport] [Guid("E7FE2E12-661C-40DA-92F9-4F002AB67627")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMFReadWriteClassFactory { void CreateInstanceFromURL([In][MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In][MarshalAs(UnmanagedType.LPWStr)] string pwszURL, [In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pAttributes, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); void CreateInstanceFromObject([In][MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In][MarshalAs(UnmanagedType.IUnknown)] object punkObject, [In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pAttributes, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); } [ComImport] [Guid("48e2ed0f-98c2-4a37-bed5-166312ddd83f")] public class MFReadWriteClassFactory { } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("c40a00f2-b93a-4d80-ae8c-5a1c634f58e4")] public interface IMFSample : IMFAttributes { new void GetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][Out] IntPtr pValue); new void GetItemType([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pType); new void CompareItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void Compare([MarshalAs(UnmanagedType.Interface)] IMFAttributes pTheirs, int matchType, [MarshalAs(UnmanagedType.Bool)] out bool pbResult); new void GetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int punValue); new void GetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out long punValue); new void GetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out double pfValue); new void GetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out Guid pguidValue); new void GetStringLength([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcchLength); new void GetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszValue, int cchBufSize, out int pcchLength); new void GetAllocatedString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [MarshalAs(UnmanagedType.LPWStr)] out string ppwszValue, out int pcchLength); new void GetBlobSize([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out int pcbBlobSize); new void GetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] pBuf, int cbBufSize, out int pcbBlobSize); new void GetAllocatedBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, out IntPtr ip, out int pcbSize); new void GetUnknown([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv); new void SetItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, IntPtr value); new void DeleteItem([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey); new void DeleteAllItems(); new void SetUINT32([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, int unValue); new void SetUINT64([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, long unValue); new void SetDouble([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, double fValue); new void SetGUID([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidValue); new void SetString([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPWStr)] string wszValue); new void SetBlob([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBuf, int cbBufSize); new void SetUnknown([MarshalAs(UnmanagedType.LPStruct)] Guid guidKey, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnknown); new void LockStore(); new void UnlockStore(); new void GetCount(out int pcItems); new void GetItemByIndex(int unIndex, out Guid pGuidKey, [In][Out] IntPtr pValue); new void CopyAllItems([In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pDest); void GetSampleFlags(out int pdwSampleFlags); void SetSampleFlags(int dwSampleFlags); void GetSampleTime(out long phnsSampletime); void SetSampleTime(long hnsSampleTime); void GetSampleDuration(out long phnsSampleDuration); void SetSampleDuration(long hnsSampleDuration); void GetBufferCount(out int pdwBufferCount); void GetBufferByIndex(int dwIndex, out IMFMediaBuffer ppBuffer); void ConvertToContiguousBuffer(out IMFMediaBuffer ppBuffer); void AddBuffer(IMFMediaBuffer pBuffer); void RemoveBufferByIndex(int dwIndex); void RemoveAllBuffers(); void GetTotalLength(out int pcbTotalLength); void CopyToBuffer(IMFMediaBuffer pBuffer); } [ComImport] [Guid("3137f1cd-fe5e-4805-a5d8-fb477448cb3d")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMFSinkWriter { void AddStream([In][MarshalAs(UnmanagedType.Interface)] IMFMediaType pTargetMediaType, out int pdwStreamIndex); void SetInputMediaType([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.Interface)] IMFMediaType pInputMediaType, [In][MarshalAs(UnmanagedType.Interface)] IMFAttributes pEncodingParameters); void BeginWriting(); void WriteSample([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.Interface)] IMFSample pSample); void SendStreamTick([In] int dwStreamIndex, [In] long llTimestamp); void PlaceMarker([In] int dwStreamIndex, [In] IntPtr pvContext); void NotifyEndOfSegment([In] int dwStreamIndex); void Flush([In] int dwStreamIndex); void DoFinalize(); void GetServiceForStream([In] int dwStreamIndex, [In] ref Guid guidService, [In] ref Guid riid, out IntPtr ppvObject); void GetStatistics([In] int dwStreamIndex, [In][Out] MF_SINK_WRITER_STATISTICS pStats); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("70ae66f2-c809-4e4f-8915-bdcb406b7993")] public interface IMFSourceReader { void GetStreamSelection([In] int dwStreamIndex, [MarshalAs(UnmanagedType.Bool)] out bool pSelected); void SetStreamSelection([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.Bool)] bool pSelected); void GetNativeMediaType([In] int dwStreamIndex, [In] int dwMediaTypeIndex, out IMFMediaType ppMediaType); void GetCurrentMediaType([In] int dwStreamIndex, out IMFMediaType ppMediaType); void SetCurrentMediaType([In] int dwStreamIndex, IntPtr pdwReserved, [In] IMFMediaType pMediaType); void SetCurrentPosition([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidTimeFormat, [In] IntPtr varPosition); void ReadSample([In] int dwStreamIndex, [In] int dwControlFlags, out int pdwActualStreamIndex, out MF_SOURCE_READER_FLAG pdwStreamFlags, out ulong pllTimestamp, out IMFSample ppSample); void Flush([In] int dwStreamIndex); void GetServiceForStream([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppvObject); [PreserveSig] int GetPresentationAttribute([In] int dwStreamIndex, [In][MarshalAs(UnmanagedType.LPStruct)] Guid guidAttribute, [Out] IntPtr pvarAttribute); } [Flags] public enum MF_SOURCE_READER_FLAG { None = 0, MF_SOURCE_READERF_ERROR = 1, MF_SOURCE_READERF_ENDOFSTREAM = 2, MF_SOURCE_READERF_NEWSTREAM = 4, MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED = 0x10, MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED = 0x20, MF_SOURCE_READERF_STREAMTICK = 0x100, MF_SOURCE_READERF_ALLEFFECTSREMOVED = 0x200 } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("bf94c121-5b05-4e6f-8000-ba598961414d")] public interface IMFTransform { void GetStreamLimits(out int pdwInputMinimum, out int pdwInputMaximum, out int pdwOutputMinimum, out int pdwOutputMaximum); void GetStreamCount(out int pcInputStreams, out int pcOutputStreams); void GetStreamIds([In] int dwInputIdArraySize, [In][Out] IntPtr pdwInputIDs, [In] int dwOutputIdArraySize, [In][Out] IntPtr pdwOutputIDs); void GetInputStreamInfo([In] int dwInputStreamId, out MFT_INPUT_STREAM_INFO pStreamInfo); void GetOutputStreamInfo([In] int dwOutputStreamId, out MFT_OUTPUT_STREAM_INFO pStreamInfo); void GetAttributes(out IMFAttributes pAttributes); void GetInputStreamAttributes([In] int dwInputStreamId, out IMFAttributes pAttributes); void GetOutputStreamAttributes([In] int dwOutputStreamId, out IMFAttributes pAttributes); void DeleteInputStream([In] int dwOutputStreamId); void AddInputStreams([In] int cStreams, [In] IntPtr adwStreamIDs); void GetInputAvailableType([In] int dwInputStreamId, [In] int dwTypeIndex, out IMFMediaType ppType); void GetOutputAvailableType([In] int dwOutputStreamId, [In] int dwTypeIndex, out IMFMediaType ppType); void SetInputType([In] int dwInputStreamId, [In] IMFMediaType pType, [In] _MFT_SET_TYPE_FLAGS dwFlags); void SetOutputType([In] int dwOutputStreamId, [In] IMFMediaType pType, [In] _MFT_SET_TYPE_FLAGS dwFlags); void GetInputCurrentType([In] int dwInputStreamId, out IMFMediaType ppType); void GetOutputCurrentType([In] int dwOutputStreamId, out IMFMediaType ppType); void GetInputStatus([In] int dwInputStreamId, out _MFT_INPUT_STATUS_FLAGS pdwFlags); void GetOutputStatus([In] int dwInputStreamId, out _MFT_OUTPUT_STATUS_FLAGS pdwFlags); void SetOutputBounds([In] long hnsLowerBound, [In] long hnsUpperBound); void ProcessEvent([In] int dwInputStreamId, [In] IMFMediaEvent pEvent); void ProcessMessage([In] MFT_MESSAGE_TYPE eMessage, [In] IntPtr ulParam); void ProcessInput([In] int dwInputStreamId, [In] IMFSample pSample, int dwFlags); [PreserveSig] int ProcessOutput([In] _MFT_PROCESS_OUTPUT_FLAGS dwFlags, [In] int cOutputBufferCount, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] MFT_OUTPUT_DATA_BUFFER[] pOutputSamples, out _MFT_PROCESS_OUTPUT_STATUS pdwStatus); } public enum MediaEventType { MEUnknown = 0, MEError = 1, MEExtendedType = 2, MENonFatalError = 3, MESessionUnknown = 100, MESessionTopologySet = 101, MESessionTopologiesCleared = 102, MESessionStarted = 103, MESessionPaused = 104, MESessionStopped = 105, MESessionClosed = 106, MESessionEnded = 107, MESessionRateChanged = 108, MESessionScrubSampleComplete = 109, MESessionCapabilitiesChanged = 110, MESessionTopologyStatus = 111, MESessionNotifyPresentationTime = 112, MENewPresentation = 113, MELicenseAcquisitionStart = 114, MELicenseAcquisitionCompleted = 115, MEIndividualizationStart = 116, MEIndividualizationCompleted = 117, MEEnablerProgress = 118, MEEnablerCompleted = 119, MEPolicyError = 120, MEPolicyReport = 121, MEBufferingStarted = 122, MEBufferingStopped = 123, MEConnectStart = 124, MEConnectEnd = 125, MEReconnectStart = 126, MEReconnectEnd = 127, MERendererEvent = 128, MESessionStreamSinkFormatChanged = 129, MESourceUnknown = 200, MESourceStarted = 201, MEStreamStarted = 202, MESourceSeeked = 203, MEStreamSeeked = 204, MENewStream = 205, MEUpdatedStream = 206, MESourceStopped = 207, MEStreamStopped = 208, MESourcePaused = 209, MEStreamPaused = 210, MEEndOfPresentation = 211, MEEndOfStream = 212, MEMediaSample = 213, MEStreamTick = 214, MEStreamThinMode = 215, MEStreamFormatChanged = 216, MESourceRateChanged = 217, MEEndOfPresentationSegment = 218, MESourceCharacteristicsChanged = 219, MESourceRateChangeRequested = 220, MESourceMetadataChanged = 221, MESequencerSourceTopologyUpdated = 222, MESinkUnknown = 300, MEStreamSinkStarted = 301, MEStreamSinkStopped = 302, MEStreamSinkPaused = 303, MEStreamSinkRateChanged = 304, MEStreamSinkRequestSample = 305, MEStreamSinkMarker = 306, MEStreamSinkPrerolled = 307, MEStreamSinkScrubSampleComplete = 308, MEStreamSinkFormatChanged = 309, MEStreamSinkDeviceChanged = 310, MEQualityNotify = 311, MESinkInvalidated = 312, MEAudioSessionNameChanged = 313, MEAudioSessionVolumeChanged = 314, MEAudioSessionDeviceRemoved = 315, MEAudioSessionServerShutdown = 316, MEAudioSessionGroupingParamChanged = 317, MEAudioSessionIconChanged = 318, MEAudioSessionFormatChanged = 319, MEAudioSessionDisconnected = 320, MEAudioSessionExclusiveModeOverride = 321, METrustUnknown = 400, MEPolicyChanged = 401, MEContentProtectionMessage = 402, MEPolicySet = 403, MEWMDRMLicenseBackupCompleted = 500, MEWMDRMLicenseBackupProgress = 501, MEWMDRMLicenseRestoreCompleted = 502, MEWMDRMLicenseRestoreProgress = 503, MEWMDRMLicenseAcquisitionCompleted = 506, MEWMDRMIndividualizationCompleted = 508, MEWMDRMIndividualizationProgress = 513, MEWMDRMProximityCompleted = 514, MEWMDRMLicenseStoreCleaned = 515, MEWMDRMRevocationDownloadCompleted = 516, METransformUnknown = 600, METransformNeedInput = 601, METransformHaveOutput = 602, METransformDrainComplete = 603, METransformMarker = 604 } public static class MediaFoundationAttributes { public static readonly Guid MF_TRANSFORM_ASYNC = new Guid("f81a699a-649a-497d-8c73-29f8fed6ad7a"); public static readonly Guid MF_TRANSFORM_ASYNC_UNLOCK = new Guid("e5666d6b-3422-4eb6-a421-da7db1f8e207"); [FieldDescription("Transform Flags")] public static readonly Guid MF_TRANSFORM_FLAGS_Attribute = new Guid("9359bb7e-6275-46c4-a025-1c01e45f1a86"); [FieldDescription("Transform Category")] public static readonly Guid MF_TRANSFORM_CATEGORY_Attribute = new Guid("ceabba49-506d-4757-a6ff-66c184987e4e"); [FieldDescription("Class identifier")] public static readonly Guid MFT_TRANSFORM_CLSID_Attribute = new Guid("6821c42b-65a4-4e82-99bc-9a88205ecd0c"); [FieldDescription("Container type")] public static readonly Guid MF_TRANSCODE_CONTAINERTYPE = new Guid(353366591, 19132, 18315, 172, 79, 225, 145, 111, 186, 28, 202); [FieldDescription("Input Types")] public static readonly Guid MFT_INPUT_TYPES_Attributes = new Guid("4276c9b1-759d-4bf3-9cd0-0d723d138f96"); [FieldDescription("Output Types")] public static readonly Guid MFT_OUTPUT_TYPES_Attributes = new Guid("8eae8cf3-a44f-4306-ba5c-bf5dda242818"); public static readonly Guid MFT_ENUM_HARDWARE_URL_Attribute = new Guid("2fb866ac-b078-4942-ab6c-003d05cda674"); [FieldDescription("Name")] public static readonly Guid MFT_FRIENDLY_NAME_Attribute = new Guid("314ffbae-5b41-4c95-9c19-4e7d586face3"); public static readonly Guid MFT_CONNECTED_STREAM_ATTRIBUTE = new Guid("71eeb820-a59f-4de2-bcec-38db1dd611a4"); public static readonly Guid MFT_CONNECTED_TO_HW_STREAM = new Guid("34e6e728-06d6-4491-a553-4795650db912"); [FieldDescription("Preferred Output Format")] public static readonly Guid MFT_PREFERRED_OUTPUTTYPE_Attribute = new Guid("7e700499-396a-49ee-b1b4-f628021e8c9d"); public static readonly Guid MFT_PROCESS_LOCAL_Attribute = new Guid("543186e4-4649-4e65-b588-4aa352aff379"); public static readonly Guid MFT_PREFERRED_ENCODER_PROFILE = new Guid("53004909-1ef5-46d7-a18e-5a75f8b5905f"); public static readonly Guid MFT_HW_TIMESTAMP_WITH_QPC_Attribute = new Guid("8d030fb8-cc43-4258-a22e-9210bef89be4"); public static readonly Guid MFT_FIELDOFUSE_UNLOCK_Attribute = new Guid("8ec2e9fd-9148-410d-831e-702439461a8e"); public static readonly Guid MFT_CODEC_MERIT_Attribute = new Guid("88a7cb15-7b07-4a34-9128-e64c6703c4d3"); public static readonly Guid MFT_ENUM_TRANSCODE_ONLY_ATTRIBUTE = new Guid("111ea8cd-b62a-4bdb-89f6-67ffcdc2458b"); [FieldDescription("PMP Host Context")] public static readonly Guid MF_PD_PMPHOST_CONTEXT = new Guid("6c990d31-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("App Context")] public static readonly Guid MF_PD_APP_CONTEXT = new Guid("6c990d32-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Duration")] public static readonly Guid MF_PD_DURATION = new Guid("6c990d33-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Total File Size")] public static readonly Guid MF_PD_TOTAL_FILE_SIZE = new Guid("6c990d34-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Audio encoding bitrate")] public static readonly Guid MF_PD_AUDIO_ENCODING_BITRATE = new Guid("6c990d35-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Video Encoding Bitrate")] public static readonly Guid MF_PD_VIDEO_ENCODING_BITRATE = new Guid("6c990d36-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("MIME Type")] public static readonly Guid MF_PD_MIME_TYPE = new Guid("6c990d37-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Last Modified Time")] public static readonly Guid MF_PD_LAST_MODIFIED_TIME = new Guid("6c990d38-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Element ID")] public static readonly Guid MF_PD_PLAYBACK_ELEMENT_ID = new Guid("6c990d39-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Preferred Language")] public static readonly Guid MF_PD_PREFERRED_LANGUAGE = new Guid("6c990d3a-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Playback boundary time")] public static readonly Guid MF_PD_PLAYBACK_BOUNDARY_TIME = new Guid("6c990d3b-bb8e-477a-8598-0d5d96fcd88a"); [FieldDescription("Audio is variable bitrate")] public static readonly Guid MF_PD_AUDIO_ISVARIABLEBITRATE = new Guid("33026ee0-e387-4582-ae0a-34a2ad3baa18"); [FieldDescription("Major Media Type")] public static readonly Guid MF_MT_MAJOR_TYPE = new Guid("48eba18e-f8c9-4687-bf11-0a74c9f96a8f"); [FieldDescription("Media Subtype")] public static readonly Guid MF_MT_SUBTYPE = new Guid("f7e34c9a-42e8-4714-b74b-cb29d72c35e5"); [FieldDescription("Audio block alignment")] public static readonly Guid MF_MT_AUDIO_BLOCK_ALIGNMENT = new Guid("322de230-9eeb-43bd-ab7a-ff412251541d"); [FieldDescription("Audio average bytes per second")] public static readonly Guid MF_MT_AUDIO_AVG_BYTES_PER_SECOND = new Guid("1aab75c8-cfef-451c-ab95-ac034b8e1731"); [FieldDescription("Audio number of channels")] public static readonly Guid MF_MT_AUDIO_NUM_CHANNELS = new Guid("37e48bf5-645e-4c5b-89de-ada9e29b696a"); [FieldDescription("Audio samples per second")] public static readonly Guid MF_MT_AUDIO_SAMPLES_PER_SECOND = new Guid("5faeeae7-0290-4c31-9e8a-c534f68d9dba"); [FieldDescription("Audio bits per sample")] public static readonly Guid MF_MT_AUDIO_BITS_PER_SAMPLE = new Guid("f2deb57f-40fa-4764-aa33-ed4f2d1ff669"); [FieldDescription("Enable Hardware Transforms")] public static readonly Guid MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS = new Guid("a634a91c-822b-41b9-a494-4de4643612b0"); [FieldDescription("Disable Sink Writer Throttling")] public static readonly Guid MF_SINK_WRITER_DISABLE_THROTTLING = new Guid("08b845d8-2b74-4afe-9d53-be16d2d5ae4f"); [FieldDescription("User data")] public static readonly Guid MF_MT_USER_DATA = new Guid("b6bc765f-4c3b-40a4-bd51-2535b66fe09d"); [FieldDescription("All samples independent")] public static readonly Guid MF_MT_ALL_SAMPLES_INDEPENDENT = new Guid("c9173739-5e56-461c-b713-46fb995cb95f"); [FieldDescription("Fixed size samples")] public static readonly Guid MF_MT_FIXED_SIZE_SAMPLES = new Guid("b8ebefaf-b718-4e04-b0a9-116775e3321b"); [FieldDescription("DirectShow Format Guid")] public static readonly Guid MF_MT_AM_FORMAT_TYPE = new Guid("73d1072d-1870-4174-a063-29ff4ff6c11e"); [FieldDescription("Preferred legacy format structure")] public static readonly Guid MF_MT_AUDIO_PREFER_WAVEFORMATEX = new Guid("a901aaba-e037-458a-bdf6-545be2074042"); [FieldDescription("Is Compressed")] public static readonly Guid MF_MT_COMPRESSED = new Guid("3afd0cee-18f2-4ba5-a110-8bea502e1f92"); [FieldDescription("Average bitrate")] public static readonly Guid MF_MT_AVG_BITRATE = new Guid("20332624-fb0d-4d9e-bd0d-cbf6786c102e"); [FieldDescription("AAC payload type")] public static readonly Guid MF_MT_AAC_PAYLOAD_TYPE = new Guid("bfbabe79-7434-4d1c-94f0-72a3b9e17188"); [FieldDescription("AAC Audio Profile Level Indication")] public static readonly Guid MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION = new Guid("7632f0e6-9538-4d61-acda-ea29c8c14456"); } public static class MediaFoundationErrors { public const int MF_E_PLATFORM_NOT_INITIALIZED = -1072875856; public const int MF_E_BUFFERTOOSMALL = -1072875855; public const int MF_E_INVALIDREQUEST = -1072875854; public const int MF_E_INVALIDSTREAMNUMBER = -1072875853; public const int MF_E_INVALIDMEDIATYPE = -1072875852; public const int MF_E_NOTACCEPTING = -1072875851; public const int MF_E_NOT_INITIALIZED = -1072875850; public const int MF_E_UNSUPPORTED_REPRESENTATION = -1072875849; public const int MF_E_NO_MORE_TYPES = -1072875847; public const int MF_E_UNSUPPORTED_SERVICE = -1072875846; public const int MF_E_UNEXPECTED = -1072875845; public const int MF_E_INVALIDNAME = -1072875844; public const int MF_E_INVALIDTYPE = -1072875843; public const int MF_E_INVALID_FILE_FORMAT = -1072875842; public const int MF_E_INVALIDINDEX = -1072875841; public const int MF_E_INVALID_TIMESTAMP = -1072875840; public const int MF_E_UNSUPPORTED_SCHEME = -1072875837; public const int MF_E_UNSUPPORTED_BYTESTREAM_TYPE = -1072875836; public const int MF_E_UNSUPPORTED_TIME_FORMAT = -1072875835; public const int MF_E_NO_SAMPLE_TIMESTAMP = -1072875832; public const int MF_E_NO_SAMPLE_DURATION = -1072875831; public const int MF_E_INVALID_STREAM_DATA = -1072875829; public const int MF_E_RT_UNAVAILABLE = -1072875825; public const int MF_E_UNSUPPORTED_RATE = -1072875824; public const int MF_E_THINNING_UNSUPPORTED = -1072875823; public const int MF_E_REVERSE_UNSUPPORTED = -1072875822; public const int MF_E_UNSUPPORTED_RATE_TRANSITION = -1072875821; public const int MF_E_RATE_CHANGE_PREEMPTED = -1072875820; public const int MF_E_NOT_FOUND = -1072875819; public const int MF_E_NOT_AVAILABLE = -1072875818; public const int MF_E_NO_CLOCK = -1072875817; public const int MF_S_MULTIPLE_BEGIN = 866008; public const int MF_E_MULTIPLE_BEGIN = -1072875815; public const int MF_E_MULTIPLE_SUBSCRIBERS = -1072875814; public const int MF_E_TIMER_ORPHANED = -1072875813; public const int MF_E_STATE_TRANSITION_PENDING = -1072875812; public const int MF_E_UNSUPPORTED_STATE_TRANSITION = -1072875811; public const int MF_E_UNRECOVERABLE_ERROR_OCCURRED = -1072875810; public const int MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS = -1072875809; public const int MF_E_SAMPLE_NOT_WRITABLE = -1072875808; public const int MF_E_INVALID_KEY = -1072875806; public const int MF_E_BAD_STARTUP_VERSION = -1072875805; public const int MF_E_UNSUPPORTED_CAPTION = -1072875804; public const int MF_E_INVALID_POSITION = -1072875803; public const int MF_E_ATTRIBUTENOTFOUND = -1072875802; public const int MF_E_PROPERTY_TYPE_NOT_ALLOWED = -1072875801; public const int MF_E_PROPERTY_TYPE_NOT_SUPPORTED = -1072875800; public const int MF_E_PROPERTY_EMPTY = -1072875799; public const int MF_E_PROPERTY_NOT_EMPTY = -1072875798; public const int MF_E_PROPERTY_VECTOR_NOT_ALLOWED = -1072875797; public const int MF_E_PROPERTY_VECTOR_REQUIRED = -1072875796; public const int MF_E_OPERATION_CANCELLED = -1072875795; public const int MF_E_BYTESTREAM_NOT_SEEKABLE = -1072875794; public const int MF_E_DISABLED_IN_SAFEMODE = -1072875793; public const int MF_E_CANNOT_PARSE_BYTESTREAM = -1072875792; public const int MF_E_SOURCERESOLVER_MUTUALLY_EXCLUSIVE_FLAGS = -1072875791; public const int MF_E_MEDIAPROC_WRONGSTATE = -1072875790; public const int MF_E_RT_THROUGHPUT_NOT_AVAILABLE = -1072875789; public const int MF_E_RT_TOO_MANY_CLASSES = -1072875788; public const int MF_E_RT_WOULDBLOCK = -1072875787; public const int MF_E_NO_BITPUMP = -1072875786; public const int MF_E_RT_OUTOFMEMORY = -1072875785; public const int MF_E_RT_WORKQUEUE_CLASS_NOT_SPECIFIED = -1072875784; public const int MF_E_INSUFFICIENT_BUFFER = -1072860816; public const int MF_E_CANNOT_CREATE_SINK = -1072875782; public const int MF_E_BYTESTREAM_UNKNOWN_LENGTH = -1072875781; public const int MF_E_SESSION_PAUSEWHILESTOPPED = -1072875780; public const int MF_S_ACTIVATE_REPLACED = 866045; public const int MF_E_FORMAT_CHANGE_NOT_SUPPORTED = -1072875778; public const int MF_E_INVALID_WORKQUEUE = -1072875777; public const int MF_E_DRM_UNSUPPORTED = -1072875776; public const int MF_E_UNAUTHORIZED = -1072875775; public const int MF_E_OUT_OF_RANGE = -1072875774; public const int MF_E_INVALID_CODEC_MERIT = -1072875773; public const int MF_E_HW_MFT_FAILED_START_STREAMING = -1072875772; public const int MF_S_ASF_PARSEINPROGRESS = 1074608792; public const int MF_E_ASF_PARSINGINCOMPLETE = -1072874856; public const int MF_E_ASF_MISSINGDATA = -1072874855; public const int MF_E_ASF_INVALIDDATA = -1072874854; public const int MF_E_ASF_OPAQUEPACKET = -1072874853; public const int MF_E_ASF_NOINDEX = -1072874852; public const int MF_E_ASF_OUTOFRANGE = -1072874851; public const int MF_E_ASF_INDEXNOTLOADED = -1072874850; public const int MF_E_ASF_TOO_MANY_PAYLOADS = -1072874849; public const int MF_E_ASF_UNSUPPORTED_STREAM_TYPE = -1072874848; public const int MF_E_ASF_DROPPED_PACKET = -1072874847; public const int MF_E_NO_EVENTS_AVAILABLE = -1072873856; public const int MF_E_INVALID_STATE_TRANSITION = -1072873854; public const int MF_E_END_OF_STREAM = -1072873852; public const int MF_E_SHUTDOWN = -1072873851; public const int MF_E_MP3_NOTFOUND = -1072873850; public const int MF_E_MP3_OUTOFDATA = -1072873849; public const int MF_E_MP3_NOTMP3 = -1072873848; public const int MF_E_MP3_NOTSUPPORTED = -1072873847; public const int MF_E_NO_DURATION = -1072873846; public const int MF_E_INVALID_FORMAT = -1072873844; public const int MF_E_PROPERTY_NOT_FOUND = -1072873843; public const int MF_E_PROPERTY_READ_ONLY = -1072873842; public const int MF_E_PROPERTY_NOT_ALLOWED = -1072873841; public const int MF_E_MEDIA_SOURCE_NOT_STARTED = -1072873839; public const int MF_E_UNSUPPORTED_FORMAT = -1072873832; public const int MF_E_MP3_BAD_CRC = -1072873831; public const int MF_E_NOT_PROTECTED = -1072873830; public const int MF_E_MEDIA_SOURCE_WRONGSTATE = -1072873829; public const int MF_E_MEDIA_SOURCE_NO_STREAMS_SELECTED = -1072873828; public const int MF_E_CANNOT_FIND_KEYFRAME_SAMPLE = -1072873827; public const int MF_E_NETWORK_RESOURCE_FAILURE = -1072872856; public const int MF_E_NET_WRITE = -1072872855; public const int MF_E_NET_READ = -1072872854; public const int MF_E_NET_REQUIRE_NETWORK = -1072872853; public const int MF_E_NET_REQUIRE_ASYNC = -1072872852; public const int MF_E_NET_BWLEVEL_NOT_SUPPORTED = -1072872851; public const int MF_E_NET_STREAMGROUPS_NOT_SUPPORTED = -1072872850; public const int MF_E_NET_MANUALSS_NOT_SUPPORTED = -1072872849; public const int MF_E_NET_INVALID_PRESENTATION_DESCRIPTOR = -1072872848; public const int MF_E_NET_CACHESTREAM_NOT_FOUND = -1072872847; public const int MF_I_MANUAL_PROXY = 1074610802; public const int MF_E_NET_REQUIRE_INPUT = -1072872844; public const int MF_E_NET_REDIRECT = -1072872843; public const int MF_E_NET_REDIRECT_TO_PROXY = -1072872842; public const int MF_E_NET_TOO_MANY_REDIRECTS = -1072872841; public const int MF_E_NET_TIMEOUT = -1072872840; public const int MF_E_NET_CLIENT_CLOSE = -1072872839; public const int MF_E_NET_BAD_CONTROL_DATA = -1072872838; public const int MF_E_NET_INCOMPATIBLE_SERVER = -1072872837; public const int MF_E_NET_UNSAFE_URL = -1072872836; public const int MF_E_NET_CACHE_NO_DATA = -1072872835; public const int MF_E_NET_EOL = -1072872834; public const int MF_E_NET_BAD_REQUEST = -1072872833; public const int MF_E_NET_INTERNAL_SERVER_ERROR = -1072872832; public const int MF_E_NET_SESSION_NOT_FOUND = -1072872831; public const int MF_E_NET_NOCONNECTION = -1072872830; public const int MF_E_NET_CONNECTION_FAILURE = -1072872829; public const int MF_E_NET_INCOMPATIBLE_PUSHSERVER = -1072872828; public const int MF_E_NET_SERVER_ACCESSDENIED = -1072872827; public const int MF_E_NET_PROXY_ACCESSDENIED = -1072872826; public const int MF_E_NET_CANNOTCONNECT = -1072872825; public const int MF_E_NET_INVALID_PUSH_TEMPLATE = -1072872824; public const int MF_E_NET_INVALID_PUSH_PUBLISHING_POINT = -1072872823; public const int MF_E_NET_BUSY = -1072872822; public const int MF_E_NET_RESOURCE_GONE = -1072872821; public const int MF_E_NET_ERROR_FROM_PROXY = -1072872820; public const int MF_E_NET_PROXY_TIMEOUT = -1072872819; public const int MF_E_NET_SERVER_UNAVAILABLE = -1072872818; public const int MF_E_NET_TOO_MUCH_DATA = -1072872817; public const int MF_E_NET_SESSION_INVALID = -1072872816; public const int MF_E_OFFLINE_MODE = -1072872815; public const int MF_E_NET_UDP_BLOCKED = -1072872814; public const int MF_E_NET_UNSUPPORTED_CONFIGURATION = -1072872813; public const int MF_E_NET_PROTOCOL_DISABLED = -1072872812; public const int MF_E_ALREADY_INITIALIZED = -1072871856; public const int MF_E_BANDWIDTH_OVERRUN = -1072871855; public const int MF_E_LATE_SAMPLE = -1072871854; public const int MF_E_FLUSH_NEEDED = -1072871853; public const int MF_E_INVALID_PROFILE = -1072871852; public const int MF_E_INDEX_NOT_COMMITTED = -1072871851; public const int MF_E_NO_INDEX = -1072871850; public const int MF_E_CANNOT_INDEX_IN_PLACE = -1072871849; public const int MF_E_MISSING_ASF_LEAKYBUCKET = -1072871848; public const int MF_E_INVALID_ASF_STREAMID = -1072871847; public const int MF_E_STREAMSINK_REMOVED = -1072870856; public const int MF_E_STREAMSINKS_OUT_OF_SYNC = -1072870854; public const int MF_E_STREAMSINKS_FIXED = -1072870853; public const int MF_E_STREAMSINK_EXISTS = -1072870852; public const int MF_E_SAMPLEALLOCATOR_CANCELED = -1072870851; public const int MF_E_SAMPLEALLOCATOR_EMPTY = -1072870850; public const int MF_E_SINK_ALREADYSTOPPED = -1072870849; public const int MF_E_ASF_FILESINK_BITRATE_UNKNOWN = -1072870848; public const int MF_E_SINK_NO_STREAMS = -1072870847; public const int MF_S_SINK_NOT_FINALIZED = 870978; public const int MF_E_METADATA_TOO_LONG = -1072870845; public const int MF_E_SINK_NO_SAMPLES_PROCESSED = -1072870844; public const int MF_E_VIDEO_REN_NO_PROCAMP_HW = -1072869856; public const int MF_E_VIDEO_REN_NO_DEINTERLACE_HW = -1072869855; public const int MF_E_VIDEO_REN_COPYPROT_FAILED = -1072869854; public const int MF_E_VIDEO_REN_SURFACE_NOT_SHARED = -1072869853; public const int MF_E_VIDEO_DEVICE_LOCKED = -1072869852; public const int MF_E_NEW_VIDEO_DEVICE = -1072869851; public const int MF_E_NO_VIDEO_SAMPLE_AVAILABLE = -1072869850; public const int MF_E_NO_AUDIO_PLAYBACK_DEVICE = -1072869756; public const int MF_E_AUDIO_PLAYBACK_DEVICE_IN_USE = -1072869755; public const int MF_E_AUDIO_PLAYBACK_DEVICE_INVALIDATED = -1072869754; public const int MF_E_AUDIO_SERVICE_NOT_RUNNING = -1072869753; public const int MF_E_TOPO_INVALID_OPTIONAL_NODE = -1072868850; public const int MF_E_TOPO_CANNOT_FIND_DECRYPTOR = -1072868847; public const int MF_E_TOPO_CODEC_NOT_FOUND = -1072868846; public const int MF_E_TOPO_CANNOT_CONNECT = -1072868845; public const int MF_E_TOPO_UNSUPPORTED = -1072868844; public const int MF_E_TOPO_INVALID_TIME_ATTRIBUTES = -1072868843; public const int MF_E_TOPO_LOOPS_IN_TOPOLOGY = -1072868842; public const int MF_E_TOPO_MISSING_PRESENTATION_DESCRIPTOR = -1072868841; public const int MF_E_TOPO_MISSING_STREAM_DESCRIPTOR = -1072868840; public const int MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED = -1072868839; public const int MF_E_TOPO_MISSING_SOURCE = -1072868838; public const int MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED = -1072868837; public const int MF_E_SEQUENCER_UNKNOWN_SEGMENT_ID = -1072864852; public const int MF_S_SEQUENCER_CONTEXT_CANCELED = 876973; public const int MF_E_NO_SOURCE_IN_CACHE = -1072864850; public const int MF_S_SEQUENCER_SEGMENT_AT_END_OF_STREAM = 876975; public const int MF_E_TRANSFORM_TYPE_NOT_SET = -1072861856; public const int MF_E_TRANSFORM_STREAM_CHANGE = -1072861855; public const int MF_E_TRANSFORM_INPUT_REMAINING = -1072861854; public const int MF_E_TRANSFORM_PROFILE_MISSING = -1072861853; public const int MF_E_TRANSFORM_PROFILE_INVALID_OR_CORRUPT = -1072861852; public const int MF_E_TRANSFORM_PROFILE_TRUNCATED = -1072861851; public const int MF_E_TRANSFORM_PROPERTY_PID_NOT_RECOGNIZED = -1072861850; public const int MF_E_TRANSFORM_PROPERTY_VARIANT_TYPE_WRONG = -1072861849; public const int MF_E_TRANSFORM_PROPERTY_NOT_WRITEABLE = -1072861848; public const int MF_E_TRANSFORM_PROPERTY_ARRAY_VALUE_WRONG_NUM_DIM = -1072861847; public const int MF_E_TRANSFORM_PROPERTY_VALUE_SIZE_WRONG = -1072861846; public const int MF_E_TRANSFORM_PROPERTY_VALUE_OUT_OF_RANGE = -1072861845; public const int MF_E_TRANSFORM_PROPERTY_VALUE_INCOMPATIBLE = -1072861844; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_OUTPUT_MEDIATYPE = -1072861843; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_INPUT_MEDIATYPE = -1072861842; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION = -1072861841; public const int MF_E_TRANSFORM_CONFLICTS_WITH_OTHER_CURRENTLY_ENABLED_FEATURES = -1072861840; public const int MF_E_TRANSFORM_NEED_MORE_INPUT = -1072861838; public const int MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_SPKR_CONFIG = -1072861837; public const int MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING = -1072861836; public const int MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT = 879989; public const int MF_E_UNSUPPORTED_D3D_TYPE = -1072861834; public const int MF_E_TRANSFORM_ASYNC_LOCKED = -1072861833; public const int MF_E_TRANSFORM_CANNOT_INITIALIZE_ACM_DRIVER = -1072861832; public const int MF_E_LICENSE_INCORRECT_RIGHTS = -1072860856; public const int MF_E_LICENSE_OUTOFDATE = -1072860855; public const int MF_E_LICENSE_REQUIRED = -1072860854; public const int MF_E_DRM_HARDWARE_INCONSISTENT = -1072860853; public const int MF_E_NO_CONTENT_PROTECTION_MANAGER = -1072860852; public const int MF_E_LICENSE_RESTORE_NO_RIGHTS = -1072860851; public const int MF_E_BACKUP_RESTRICTED_LICENSE = -1072860850; public const int MF_E_LICENSE_RESTORE_NEEDS_INDIVIDUALIZATION = -1072860849; public const int MF_S_PROTECTION_NOT_REQUIRED = 880976; public const int MF_E_COMPONENT_REVOKED = -1072860847; public const int MF_E_TRUST_DISABLED = -1072860846; public const int MF_E_WMDRMOTA_NO_ACTION = -1072860845; public const int MF_E_WMDRMOTA_ACTION_ALREADY_SET = -1072860844; public const int MF_E_WMDRMOTA_DRM_HEADER_NOT_AVAILABLE = -1072860843; public const int MF_E_WMDRMOTA_DRM_ENCRYPTION_SCHEME_NOT_SUPPORTED = -1072860842; public const int MF_E_WMDRMOTA_ACTION_MISMATCH = -1072860841; public const int MF_E_WMDRMOTA_INVALID_POLICY = -1072860840; public const int MF_E_POLICY_UNSUPPORTED = -1072860839; public const int MF_E_OPL_NOT_SUPPORTED = -1072860838; public const int MF_E_TOPOLOGY_VERIFICATION_FAILED = -1072860837; public const int MF_E_SIGNATURE_VERIFICATION_FAILED = -1072860836; public const int MF_E_DEBUGGING_NOT_ALLOWED = -1072860835; public const int MF_E_CODE_EXPIRED = -1072860834; public const int MF_E_GRL_VERSION_TOO_LOW = -1072860833; public const int MF_E_GRL_RENEWAL_NOT_FOUND = -1072860832; public const int MF_E_GRL_EXTENSIBLE_ENTRY_NOT_FOUND = -1072860831; public const int MF_E_KERNEL_UNTRUSTED = -1072860830; public const int MF_E_PEAUTH_UNTRUSTED = -1072860829; public const int MF_E_NON_PE_PROCESS = -1072860827; public const int MF_E_REBOOT_REQUIRED = -1072860825; public const int MF_S_WAIT_FOR_POLICY_SET = 881000; public const int MF_S_VIDEO_DISABLED_WITH_UNKNOWN_SOFTWARE_OUTPUT = 881001; public const int MF_E_GRL_INVALID_FORMAT = -1072860822; public const int MF_E_GRL_UNRECOGNIZED_FORMAT = -1072860821; public const int MF_E_ALL_PROCESS_RESTART_REQUIRED = -1072860820; public const int MF_E_PROCESS_RESTART_REQUIRED = -1072860819; public const int MF_E_USERMODE_UNTRUSTED = -1072860818; public const int MF_E_PEAUTH_SESSION_NOT_STARTED = -1072860817; public const int MF_E_PEAUTH_PUBLICKEY_REVOKED = -1072860815; public const int MF_E_GRL_ABSENT = -1072860814; public const int MF_S_PE_TRUSTED = 881011; public const int MF_E_PE_UNTRUSTED = -1072860812; public const int MF_E_PEAUTH_NOT_STARTED = -1072860811; public const int MF_E_INCOMPATIBLE_SAMPLE_PROTECTION = -1072860810; public const int MF_E_PE_SESSIONS_MAXED = -1072860809; public const int MF_E_HIGH_SECURITY_LEVEL_CONTENT_NOT_ALLOWED = -1072860808; public const int MF_E_TEST_SIGNED_COMPONENTS_NOT_ALLOWED = -1072860807; public const int MF_E_ITA_UNSUPPORTED_ACTION = -1072860806; public const int MF_E_ITA_ERROR_PARSING_SAP_PARAMETERS = -1072860805; public const int MF_E_POLICY_MGR_ACTION_OUTOFBOUNDS = -1072860804; public const int MF_E_BAD_OPL_STRUCTURE_FORMAT = -1072860803; public const int MF_E_ITA_UNRECOGNIZED_ANALOG_VIDEO_PROTECTION_GUID = -1072860802; public const int MF_E_NO_PMP_HOST = -1072860801; public const int MF_E_ITA_OPL_DATA_NOT_INITIALIZED = -1072860800; public const int MF_E_ITA_UNRECOGNIZED_ANALOG_VIDEO_OUTPUT = -1072860799; public const int MF_E_ITA_UNRECOGNIZED_DIGITAL_VIDEO_OUTPUT = -1072860798; public const int MF_E_CLOCK_INVALID_CONTINUITY_KEY = -1072849856; public const int MF_E_CLOCK_NO_TIME_SOURCE = -1072849855; public const int MF_E_CLOCK_STATE_ALREADY_SET = -1072849854; public const int MF_E_CLOCK_NOT_SIMPLE = -1072849853; public const int MF_S_CLOCK_STOPPED = 891972; public const int MF_E_NO_MORE_DROP_MODES = -1072848856; public const int MF_E_NO_MORE_QUALITY_LEVELS = -1072848855; public const int MF_E_DROPTIME_NOT_SUPPORTED = -1072848854; public const int MF_E_QUALITYKNOB_WAIT_LONGER = -1072848853; public const int MF_E_QM_INVALIDSTATE = -1072848852; public const int MF_E_TRANSCODE_NO_CONTAINERTYPE = -1072847856; public const int MF_E_TRANSCODE_PROFILE_NO_MATCHING_STREAMS = -1072847855; public const int MF_E_TRANSCODE_NO_MATCHING_ENCODER = -1072847854; public const int MF_E_ALLOCATOR_NOT_INITIALIZED = -1072846856; public const int MF_E_ALLOCATOR_NOT_COMMITED = -1072846855; public const int MF_E_ALLOCATOR_ALREADY_COMMITED = -1072846854; public const int MF_E_STREAM_ERROR = -1072846853; public const int MF_E_INVALID_STREAM_STATE = -1072846852; public const int MF_E_HW_STREAM_NOT_CONNECTED = -1072846851; } public static class MediaFoundationApi { [CompilerGenerated] private sealed class <EnumerateTransforms>d__2 : IEnumerable<IMFActivate>, IEnumerable, IEnumerator<IMFActivate>, IEnumerator, IDisposable { private int <>1__state; private IMFActivate <>2__current; private int <>l__initialThreadId; private Guid category; public Guid <>3__category; private IntPtr <interfacesPointer>5__2; private IMFActivate[] <>7__wrap2; private int <>7__wrap3; IMFActivate IEnumerator<IMFActivate>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EnumerateTransforms>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MediaFoundationInterop.MFTEnumEx(category, _MFT_ENUM_FLAG.MFT_ENUM_FLAG_ALL, null, null, out <interfacesPointer>5__2, out var pcMFTActivate); IMFActivate[] array = new IMFActivate[pcMFTActivate]; for (int i = 0; i < pcMFTActivate; i++) { IntPtr pUnk = Marshal.ReadIntPtr(new IntPtr(<interfacesPointer>5__2.ToInt64() + i * Marshal.SizeOf(<interfacesPointer>5__2))); array[i] = (IMFActivate)Marshal.GetObjectForIUnknown(pUnk); } <>7__wrap2 = array; <>7__wrap3 = 0; break; } case 1: <>1__state = -1; <>7__wrap3++; break; } if (<>7__wrap3 < <>7__wrap2.Length) { IMFActivate iMFActivate = <>7__wrap2[<>7__wrap3]; <>2__current = iMFActivate; <>1__state = 1; return true; } <>7__wrap2 = null; Marshal.FreeCoTaskMem(<interfacesPointer>5__2); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<IMFActivate> IEnumerable<IMFActivate>.GetEnumerator() { <EnumerateTransforms>d__2 <EnumerateTransforms>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <EnumerateTransforms>d__ = this; } else { <EnumerateTransforms>d__ = new <EnumerateTransforms>d__2(0); } <EnumerateTransforms>d__.category = <>3__category; return <EnumerateTransforms>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<IMFActivate>)this).GetEnumerator(); } } private static bool initialized; public static void Startup() { if (!initialized) { int num = 2; OperatingSystem oSVersion = Environment.OSVersion; if (oSVersion.Version.Major == 6 && oSVersion.Version.Minor == 0) { num = 1; } MediaFoundationInterop.MFStartup((num << 16) | 0x70); initialized = true; } } [IteratorStateMachine(typeof(<EnumerateTransforms>d__2))] public static IEnumerable<IMFActivate> EnumerateTransforms(Guid category) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EnumerateTransforms>d__2(-2) { <>3__category = category }; } public static void Shutdown() { if (initialized) { MediaFoundationInterop.MFShutdown(); initialized = false; } } public static IMFMediaType CreateMediaType() { MediaFoundationInterop.MFCreateMediaType(out var ppMFType); return ppMFType; } public static IMFMediaType CreateMediaTypeFromWaveFormat(WaveFormat waveFormat) { IMFMediaType iMFMediaType = CreateMediaType(); try { MediaFoundationInterop.MFInitMediaTypeFromWaveFormatEx(iMFMediaType, waveFormat, Marshal.SizeOf<WaveFormat>(waveFormat)); return iMFMediaType; } catch (Exception) { Marshal.ReleaseComObject(iMFMediaType); throw; } } public static IMFMediaBuffer CreateMemoryBuffer(int bufferSize) { MediaFoundationInterop.MFCreateMemoryBuffer(bufferSize, out var ppBuffer); return ppBuffer; } public static IMFSample CreateSample() { MediaFoundationInterop.MFCreateSample(out var ppIMFSample); return ppIMFSample; } public static IMFAttributes CreateAttributes(int initialSize) { MediaFoundationInterop.MFCreateAttributes(out var ppMFAttributes, initialSize); return ppMFAttributes; } public static IMFByteStream CreateByteStream(object stream) { if (stream is IStream) { MediaFoundationInterop.MFCreateMFByteStreamOnStream(stream as IStream, out var ppByteStream); return ppByteStream; } throw new ArgumentException("Stream must be IStream in desktop apps"); } public static IMFSourceReader CreateSourceReaderFromByteStream(IMFByteStream byteStream) { MediaFoundationInterop.MFCreateSourceReaderFromByteStream(byteStream, null, out var ppSourceReader); return ppSourceReader; } } public static class MediaFoundationInterop { public const int MF_SOURCE_READER_ALL_STREAMS = -2; public const int MF_SOURCE_READER_FIRST_AUDIO_STREAM = -3; public const int MF_SOURCE_READER_FIRST_VIDEO_STREAM = -4; public const int MF_SOURCE_READER_MEDIASOURCE = -1; public const int MF_SDK_VERSION = 2; public const int MF_API_VERSION = 112; public const int MF_VERSION = 131184; [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFStartup(int version, int dwFlags = 0); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFShutdown(); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateMediaType(out IMFMediaType ppMFType); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFInitMediaTypeFromWaveFormatEx([In] IMFMediaType pMFType, [In] WaveFormat pWaveFormat, [In] int cbBufSize); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateWaveFormatExFromMFMediaType(IMFMediaType pMFType, ref IntPtr ppWF, ref int pcbSize, int flags = 0); [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateSourceReaderFromURL([In][MarshalAs(UnmanagedType.LPWStr)] string pwszURL, [In] IMFAttributes pAttributes, [MarshalAs(UnmanagedType.Interface)] out IMFSourceReader ppSourceReader); [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateSourceReaderFromByteStream([In] IMFByteStream pByteStream, [In] IMFAttributes pAttributes, [MarshalAs(UnmanagedType.Interface)] out IMFSourceReader ppSourceReader); [DllImport("mfreadwrite.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateSinkWriterFromURL([In][MarshalAs(UnmanagedType.LPWStr)] string pwszOutputURL, [In] IMFByteStream pByteStream, [In] IMFAttributes pAttributes, out IMFSinkWriter ppSinkWriter); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateMFByteStreamOnStreamEx([MarshalAs(UnmanagedType.IUnknown)] object punkStream, out IMFByteStream ppByteStream); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFCreateMFByteStreamOnStream([In] IStream punkStream, out IMFByteStream ppByteStream); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFTEnumEx([In] Guid guidCategory, [In] _MFT_ENUM_FLAG flags, [In] MFT_REGISTER_TYPE_INFO pInputType, [In] MFT_REGISTER_TYPE_INFO pOutputType, out IntPtr pppMFTActivate, out int pcMFTActivate); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateSample(out IMFSample ppIMFSample); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateMemoryBuffer(int cbMaxLength, out IMFMediaBuffer ppBuffer); [DllImport("mfplat.dll", ExactSpelling = true, PreserveSig = false)] internal static extern void MFCreateAttributes([MarshalAs(UnmanagedType.Interface)] out IMFAttributes ppMFAttributes, [In] int cInitialSize); [DllImport("mf.dll", ExactSpelling = true, PreserveSig = false)] public static extern void MFTranscodeGetAudioOutputAvailableTypes([In][MarshalAs(UnmanagedType.LPStruct)] Guid guidSubType, [In] _MFT_ENUM_FLAG dwMFTFlags, [In] IMFAttributes pCodecConfig, [MarshalAs(UnmanagedType.Interface)] out IMFCollection ppAvailableTypes); } public abstract class MediaFoundationTransform : IWaveProvider, IDisposable { protected readonly IWaveProvider sourceProvider; protected readonly WaveFormat outputWaveFormat; private readonly byte[] sourceBuffer; private byte[] outputBuffer; private int outputBufferOffset; private int outputBufferCount; private IMFTransform transform; private bool disposed; private long inputPosition; private long outputPosition; private bool initializedForStreaming; public WaveFormat WaveFormat => outputWaveFormat; public MediaFoundationTransform(IWaveProvider sourceProvider, WaveFormat outputFormat) { outputWaveFormat = outputFormat; this.sourceProvider = sourceProvider; sourceBuffer = new byte[sourceProvider.WaveFormat.AverageBytesPerSecond]; outputBuffer = new byte[outputWaveFormat.AverageBytesPerSecond + outputWaveFormat.BlockAlign]; } private void InitializeTransformForStreaming() { transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_COMMAND_FLUSH, IntPtr.Zero); transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, IntPtr.Zero); transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_START_OF_STREAM, IntPtr.Zero); initializedForStreaming = true; } protected abstract IMFTransform CreateTransform(); protected virtual void Dispose(bool disposing) { if (transform != null) { Marshal.ReleaseComObject(transform); } } public void Dispose() { if (!disposed) { disposed = true; Dispose(disposing: true); GC.SuppressFinalize(this); } } ~MediaFoundationTransform() { Dispose(disposing: false); } public int Read(byte[] buffer, int offset, int count) { if (transform == null) { transform = CreateTransform(); InitializeTransformForStreaming(); } int i = 0; if (outputBufferCount > 0) { i += ReadFromOutputBuffer(buffer, offset, count - i); } for (; i < count; i += ReadFromOutputBuffer(buffer, offset + i, count - i)) { IMFSample iMFSample = ReadFromSource(); if (iMFSample == null) { EndStreamAndDrain(); i += ReadFromOutputBuffer(buffer, offset + i, count - i); ClearOutputBuffer(); break; } if (!initializedForStreaming) { InitializeTransformForStreaming(); } transform.ProcessInput(0, iMFSample, 0); Marshal.ReleaseComObject(iMFSample); ReadFromTransform(); } return i; } private void EndStreamAndDrain() { transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_END_OF_STREAM, IntPtr.Zero); transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_COMMAND_DRAIN, IntPtr.Zero); int num; do { num = ReadFromTransform(); } while (num > 0); inputPosition = 0L; outputPosition = 0L; transform.ProcessMessage(MFT_MESSAGE_TYPE.MFT_MESSAGE_NOTIFY_END_STREAMING, IntPtr.Zero); initializedForStreaming = false; } private void ClearOutputBuffer() { outputBufferCount = 0; outputBufferOffset = 0; } private int ReadFromTransform() { MFT_OUTPUT_DATA_BUFFER[] array = new MFT_OUTPUT_DATA_BUFFER[1]; IMFSample iMFSample = MediaFoundationApi.CreateSample(); IMFMediaBuffer iMFMediaBuffer = MediaFoundationApi.CreateMemoryBuffer(outputBuffer.Length); iMFSample.AddBuffer(iMFMediaBuffer); iMFSample.SetSampleTime(outputPosition); array[0].pSample = iMFSample; _MFT_PROCESS_OUTPUT_STATUS pdwStatus; int num = transform.ProcessOutput(_MFT_PROCESS_OUTPUT_FLAGS.None, 1, array, out pdwStatus); switch (num) { case -1072861838: Marshal.ReleaseComObject(iMFMediaBuffer); Marshal.ReleaseComObject(iMFSample); return 0; default: Marshal.ThrowExceptionForHR(num); break; case 0: break; } array[0].pSample.ConvertToContiguousBuffer(out var ppBuffer); ppBuffer.Lock(out var ppbBuffer, out var _, out var pcbCurrentLength); outputBuffer = BufferHelpers.Ensure(outputBuffer, pcbCurrentLength); Marshal.Copy(ppbBuffer, outputBuffer, 0, pcbCurrentLength); outputBufferOffset = 0; outputBufferCount = pcbCurrentLength; ppBuffer.Unlock(); outputPosition += BytesToNsPosition(outputBufferCount, WaveFormat); Marshal.ReleaseComObject(iMFMediaBuffer); iMFSample.RemoveAllBuffers(); Marshal.ReleaseComObject(iMFSample); Marshal.ReleaseComObject(ppBuffer); return pcbCurrentLength; } private static long BytesToNsPosition(int bytes, WaveFormat waveFormat) { return 10000000L * (long)bytes / waveFormat.AverageBytesPerSecond; } private IMFSample ReadFromSource() { int num = sourceProvider.Read(sourceBuffer, 0, sourceBuffer.Length); if (num == 0) { return null; } IMFMediaBuffer iMFMediaBuffer = MediaFoundationApi.CreateMemoryBuffer(num); iMFMediaBuffer.Lock(out var ppbBuffer, out var _, out var _); Marshal.Copy(sourceBuffer, 0, ppbBuffer, num); iMFMediaBuffer.Unlock(); iMFMediaBuffer.SetCurrentLength(num); IMFSample iMFSample = MediaFoundationApi.CreateSample(); iMFSample.AddBuffer(iMFMediaBuffer); iMFSample.SetSampleTime(inputPosition); long num2 = BytesToNsPosition(num, sourceProvider.WaveFormat); iMFSample.SetSampleDuration(num2); inputPosition += num2; Marshal.ReleaseComObject(iMFMediaBuffer); return iMFSample; } private int ReadFromOutputBuffer(byte[] buffer, int offset, int needed) { int num = Math.Min(needed, outputBufferCount); Array.Copy(outputBuffer, outputBufferOffset, buffer, offset, num); outputBufferOffset += num; outputBufferCount -= num; if (outputBufferCount == 0) { outputBufferOffset = 0; } return num; } public void Reposition() { if (initializedForStreaming) { EndStreamAndDrain(); ClearOutputBuffer(); InitializeTransformForStreaming(); } } } public static class MediaFoundationTransformCategories { [FieldDescription("Video Decoder")] public static readonly Guid VideoDecoder = new Guid("{d6c02d4b-6833-45b4-971a-05a4b04bab91}"); [FieldDescription("Video Encoder")] public static readonly Guid VideoEncoder = new Guid("{f79eac7d-e545-4387-bdee-d647d7bde42a}"); [FieldDescription("Video Effect")] public static readonly Guid VideoEffect = new Guid("{12e17c21-532c-4a6e-8a1c-40825a736397}"); [FieldDescription("Multiplexer")] public static readonly Guid Multiplexer = new Guid("{059c561e-05ae-4b61-b69d-55b61ee54a7b}"); [FieldDescription("Demultiplexer")] public static readonly Guid Demultiplexer = new Guid("{a8700a7a-939b-44c5-99d7-76226b23b3f1}"); [FieldDescription("Audio Decoder")] public static readonly Guid AudioDecoder = new Guid("{9ea73fb4-ef7a-4559-8d5d-719d8f0426c7}"); [FieldDescription("Audio Encoder")] public static readonly Guid AudioEncoder = new Guid("{91c64bd0-f91e-4d8c-9276-db248279d975}"); [FieldDescription("Audio Effect")] public static readonly Guid AudioEffect = new Guid("{11064c48-3648-4ed0-932e-05ce8ac811b7}"); [FieldDescription("Video Processor")] public static readonly Guid VideoProcessor = new Guid("{302EA3FC-AA5F-47f9-9F7A-C2188BB16302}"); [FieldDescription("Other")] public static readonly Guid Other = new Guid("{90175d57-b7ea-4901-aeb3-933a8747756f}"); } public class MediaType { private readonly IMFMediaType mediaType; public int SampleRate { get { return GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_SAMPLES_PER_SECOND); } set { mediaType.SetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_SAMPLES_PER_SECOND, value); } } public int ChannelCount { get { return GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_NUM_CHANNELS); } set { mediaType.SetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_NUM_CHANNELS, value); } } public int BitsPerSample { get { return GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_BITS_PER_SAMPLE); } set { mediaType.SetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_BITS_PER_SAMPLE, value); } } public int AverageBytesPerSecond => GetUInt32(MediaFoundationAttributes.MF_MT_AUDIO_AVG_BYTES_PER_SECOND); public Guid SubType { get { return GetGuid(MediaFoundationAttributes.MF_MT_SUBTYPE); } set { mediaType.SetGUID(MediaFoundationAttributes.MF_MT_SUBTYPE, value); } } public Guid MajorType { get { return GetGuid(MediaFoundationAttributes.MF_MT_MAJOR_TYPE); } set { mediaType.SetGUID(MediaFoundationAttributes.MF_MT_MAJOR_TYPE, value); } } public IMFMediaType MediaFoundationObject => mediaType; public MediaType(IMFMediaType mediaType) { this.mediaType = mediaType; } public MediaType() { mediaType = MediaFoundationApi.CreateMediaType(); } public MediaType(WaveFormat waveFormat) { mediaType = MediaFoundationApi.CreateMediaTypeFromWaveFormat(waveFormat); } private int GetUInt32(Guid key) { mediaType.GetUINT32(key, out var punValue); return punValue; } private Guid GetGuid(Guid key) { mediaType.GetGUID(key, out var pguidValue); return pguidValue; } public int TryGetUInt32(Guid key, int defaultValue = -1) { int punValue = defaultValue; try { mediaType.GetUINT32(key, out punValue); } catch (COMException ex) { if (HResult.GetHResult(ex) != -1072875802) { if (HResult.GetHResult(ex) == -1072875843) { throw new ArgumentException("Not a UINT32 parameter"); } throw; } } return punValue; } public void SetUInt32(Guid key, int value) { mediaType.SetUINT32(key, value); } } public static class MediaTypes { public static readonly Guid MFMediaType_Default = new Guid("81A412E6-8103-4B06-857F-1862781024AC"); [FieldDescription("Audio")] public static readonly Guid MFMediaType_Audio = new Guid("73647561-0000-0010-8000-00aa00389b71"); [FieldDescription("Video")] public static readonly Guid MFMediaType_Video = new Guid("73646976-0000-0010-8000-00aa00389b71"); [FieldDescription("Protected Media")] public static readonly Guid MFMediaType_Protected = new Guid("7b4b6fe6-9d04-4494-be14-7e0bd076c8e4"); [FieldDescription("SAMI captions")] public static readonly Guid MFMediaType_SAMI = new Guid("e69669a0-3dcd-40cb-9e2e-3708387c0616"); [FieldDescription("Script stream")] public static readonly Guid MFMediaType_Script = new Guid("72178c22-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("Still image stream")] public static readonly Guid MFMediaType_Image = new Guid("72178c23-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("HTML stream")] public static readonly Guid MFMediaType_HTML = new Guid("72178c24-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("Binary stream")] public static readonly Guid MFMediaType_Binary = new Guid("72178c25-e45b-11d5-bc2a-00b0d0f3f4ab"); [FieldDescription("File transfer")] public static readonly Guid MFMediaType_FileTransfer = new Guid("72178c26-e45b-11d5-bc2a-00b0d0f3f4ab"); } public struct MFT_INPUT_STREAM_INFO { public long hnsMaxLatency; public _MFT_INPUT_STREAM_INFO_FLAGS dwFlags; public int cbSize; public int cbMaxLookahead; public int cbAlignment; } public enum MFT_MESSAGE_TYPE { MFT_MESSAGE_COMMAND_FLUSH = 0, MFT_MESSAGE_COMMAND_DRAIN = 1, MFT_MESSAGE_SET_D3D_MANAGER = 2, MFT_MESSAGE_DROP_SAMPLES = 3, MFT_MESSAGE_COMMAND_TICK = 4, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING = 268435456, MFT_MESSAGE_NOTIFY_END_STREAMING = 268435457, MFT_MESSAGE_NOTIFY_END_OF_STREAM = 268435458, MFT_MESSAGE_NOTIFY_START_OF_STREAM = 268435459, MFT_MESSAGE_COMMAND_MARKER = 536870912 } public struct MFT_OUTPUT_DATA_BUFFER { public int dwStreamID; public IMFSample pSample; public _MFT_OUTPUT_DATA_BUFFER_FLAGS dwStatus; public IMFCollection pEvents; } public struct MFT_OUTPUT_STREAM_INFO { public _MFT_OUTPUT_STREAM_INFO_FLAGS dwFlags; public int cbSize; public int cbAlignment; } [StructLayout(LayoutKind.Sequential)] public class MFT_REGISTER_TYPE_INFO { public Guid guidMajorType; public Guid guidSubtype; } [StructLayout(LayoutKind.Sequential)] public class MF_SINK_WRITER_STATISTICS { public int cb; public long llLastTimestampReceived; public long llLastTimestampEncoded; public long llLastTimestampProcessed; public long llLastStreamTickReceived; public long llLastSinkSampleRequest; public long qwNumSamplesReceived; public long qwNumSamplesEncoded; public long qwNumSamplesProcessed; public long qwNumStreamTicksReceived; public int dwByteCountQueued; public long qwByteCountProcessed; public int dwNumOutstandingSinkSampleRequests; public int dwAverageSampleRateReceived; public int dwAverageSampleRateEncoded; public int dwAverageSampleRateProcessed; } public static class TranscodeContainerTypes { public static readonly Guid MFTranscodeContainerType_ASF = new Guid(1125085038u, 46783, 20417, 160, 189, 158, 228, 110, 238, 42, 251); public static readonly Guid MFTranscodeContainerType_MPEG4 = new Guid(3698118749u, 47568, 16623, 189, 53, 250, 98, 44, 26, 178, 138); public static readonly Guid MFTranscodeContainerType_MP3 = new Guid(3828922642u, 33777, 19942, 158, 58, 159, 251, 198, 221, 36, 209); public static readonly Guid MFTranscodeContainerType_3GP = new Guid(885326183, 17522, 20276, 158, 160, 196, 159, 186, 207, 3, 125); public static readonly Guid MFTranscodeContainerType_AC3 = new Guid(1837994435u, 35985, 20177, 135, 66, 140, 52, 125, 91, 68, 208); public static readonly Guid MFTranscodeContainerType_ADTS = new Guid(321901181, 3842, 17374, 163, 1, 56, 251, 187, 179, 131, 78); public static readonly Guid MFTranscodeContainerType_MPEG2 = new Guid(3217218553u, 31668, 20367, 175, 222, 225, 18, 196, 75, 168, 130); public static readonly Guid MFTranscodeContainerType_FMPEG4 = new Guid(2611508977u, 16799, 19319, 161, 224, 53, 149, 157, 157, 64, 4); public static readonly Guid MFTranscodeContainerType_WAVE = new Guid(1690518844, 3878, 18241, 190, 99, 135, 189, 248, 187, 147, 91); public static readonly Guid MFTranscodeContainerType_AVI = new Guid(2128603311, 16431, 19830, 163, 60, 97, 159, 209, 87, 208, 241); public static readonly Guid MFTranscodeContainerType_AMR = new Guid(39672531, 25114, 18267, 150, 77, 102, 177, 200, 36, 240, 121); } [Flags] public enum _MFT_ENUM_FLAG { None = 0, MFT_ENUM_FLAG_SYNCMFT = 1, MFT_ENUM_FLAG_ASYNCMFT = 2, MFT_ENUM_FLAG_HARDWARE = 4, MFT_ENUM_FLAG_FIELDOFUSE = 8, MFT_ENUM_FLAG_LOCALMFT = 0x10, MFT_ENUM_FLAG_TRANSCODE_ONLY = 0x20, MFT_ENUM_FLAG_SORTANDFILTER = 0x40, MFT_ENUM_FLAG_ALL = 0x3F } [Flags] public enum _MFT_INPUT_STATUS_FLAGS { None = 0, MFT_INPUT_STATUS_ACCEPT_DATA = 1 } [Flags] public enum _MFT_INPUT_STREAM_INFO_FLAGS { None = 0, MFT_INPUT_STREAM_WHOLE_SAMPLES = 1, MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER = 2, MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE = 4, MFT_INPUT_STREAM_HOLDS_BUFFERS = 8, MFT_INPUT_STREAM_DOES_NOT_ADDREF = 0x100, MFT_INPUT_STREAM_REMOVABLE = 0x200, MFT_INPUT_STREAM_OPTIONAL = 0x400, MFT_INPUT_STREAM_PROCESSES_IN_PLACE = 0x800 } [Flags] public enum _MFT_OUTPUT_DATA_BUFFER_FLAGS { None = 0, MFT_OUTPUT_DATA_BUFFER_INCOMPLETE = 0x1000000, MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE = 0x100, MFT_OUTPUT_DATA_BUFFER_STREAM_END = 0x200, MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE = 0x300 } [Flags] public enum _MFT_OUTPUT_STATUS_FLAGS { None = 0, MFT_OUTPUT_STATUS_SAMPLE_READY = 1 } [Flags] public enum _MFT_OUTPUT_STREAM_INFO_FLAGS { None = 0, MFT_OUTPUT_STREAM_WHOLE_SAMPLES = 1, MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER = 2, MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE = 4, MFT_OUTPUT_STREAM_DISCARDABLE = 8, MFT_OUTPUT_STREAM_OPTIONAL = 0x10, MFT_OUTPUT_STREAM_PROVIDES_SAMPLES = 0x100, MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES = 0x200, MFT_OUTPUT_STREAM_LAZY_READ = 0x400, MFT_OUTPUT_STREAM_REMOVABLE = 0x800 } [Flags] public enum _MFT_PROCESS_OUTPUT_FLAGS { None = 0, MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER = 1, MFT_PROCESS_OUTPUT_REGENERATE_LAST_OUTPUT = 2 } [Flags] public enum _MFT_PROCESS_OUTPUT_STATUS { None = 0, MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS = 0x100 } [Flags] public enum _MFT_SET_TYPE_FLAGS { None = 0, MFT_SET_TYPE_TEST_ONLY = 1 } } namespace NAudio.Dmo { public class DmoDescriptor { public string Name { get; private set; } public Guid Clsid { get; private set; } public DmoDescriptor(string name, Guid clsid) { Name = name; Clsid = clsid; } } public class DmoEnumerator { [CompilerGenerated] private sealed class <GetDmos>d__3 : IEnumerable<DmoDescriptor>, IEnumerable, IEnumerator<DmoDescriptor>, IEnumerator, IDisposable { private int <>1__state; private DmoDescriptor <>2__current; private int <>l__initialThreadId; private Guid category; public Guid <>3__category; private IEnumDmo <enumDmo>5__2; private int <itemsFetched>5__3; DmoDescriptor IEnumerator<DmoDescriptor>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetDmos>d__3(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <enumDmo>5__2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_007c; } <>1__state = -1; Marshal.ThrowExceptionForHR(DmoInterop.DMOEnum(ref category, DmoEnumFlags.None, 0, null, 0, null, out <enumDmo>5__2)); goto IL_0032; IL_007c: if (<itemsFetched>5__3 <= 0) { return false; } goto IL_0032; IL_0032: <enumDmo>5__2.Next(1, out var clsid, out var name, out <itemsFetched>5__3); if (<itemsFetched>5__3 == 1) { string name2 = Marshal.PtrToStringUni(name); Marshal.FreeCoTaskMem(name); <>2__current = new DmoDescriptor(name2, clsid); <>1__state = 1; return true; } goto IL_007c; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<DmoDescriptor> IEnumerable<DmoDescriptor>.GetEnumerator() { <GetDmos>d__3 <GetDmos>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <GetDmos>d__ = this; } else { <GetDmos>d__ = new <GetDmos>d__3(0); } <GetDmos>d__.category = <>3__category; return <GetDmos>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<DmoDescriptor>)this).GetEnumerator(); } } public static IEnumerable<DmoDescriptor> GetAudioEffectNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_EFFECT); } public static IEnumerable<DmoDescriptor> GetAudioEncoderNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_ENCODER); } public static IEnumerable<DmoDescriptor> GetAudioDecoderNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_DECODER); } [IteratorStateMachine(typeof(<GetDmos>d__3))] private static IEnumerable<DmoDescriptor> GetDmos(Guid category) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetDmos>d__3(-2) { <>3__category = category }; } } [Flags] internal enum DmoEnumFlags { None = 0, DMO_ENUMF_INCLUDE_KEYED = 1 } internal static class DmoGuids { public static readonly Guid DMOCATEGORY_AUDIO_DECODER = new Guid("57f2db8b-e6bb-4513-9d43-dcd2a6593125"); public static readonly Guid DMOCATEGORY_AUDIO_ENCODER = new Guid("33D9A761-90C8-11d0-BD43-00A0C911CE86"); public static readonly Guid DMOCATEGORY_VIDEO_DECODER = new Guid("4a69b442-28be-4991-969c-b500adf5d8a8"); public static readonly Guid DMOCATEGORY_VIDEO_ENCODER = new Guid("33D9A760-90C8-11d0-BD43-00A0C911CE86"); public static readonly Guid DMOCATEGORY_AUDIO_EFFECT = new Guid("f3602b3f-0592-48df-a4cd-674721e7ebeb"); public static readonly Guid DMOCATEGORY_VIDEO_EFFECT = new Guid("d990ee14-776c-4723-be46-3da2f56f10b9"); public static readonly Guid DMOCATEGORY_AUDIO_CAPTURE_EFFECT = new Guid("f665aaba-3e09-4920-aa5f-219811148f09"); } internal static class DmoMediaTypeGuids { public static readonly Guid FORMAT_None = new Guid("0F6417D6-C318-11D0-A43F-00A0C9223196"); public static readonly Guid FORMAT_VideoInfo = new Guid("05589f80-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_VideoInfo2 = new Guid("F72A76A0-EB0A-11d0-ACE4-0000C0CC16BA"); public static readonly Guid FORMAT_WaveFormatEx = new Guid("05589f81-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_MPEGVideo = new Guid("05589f82-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_MPEGStreams = new Guid("05589f83-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_DvInfo = new Guid("05589f84-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_525WSS = new Guid("C7ECF04D-4582-4869-9ABB-BFB523B62EDF"); } internal enum DmoHResults { DMO_E_INVALIDSTREAMINDEX = -2147220991, DMO_E_INVALIDTYPE, DMO_E_TYPE_NOT_SET, DMO_E_NOTACCEPTING, DMO_E_TYPE_NOT_ACCEPTED, DMO_E_NO_MORE_ITEMS } [Flags] public enum DmoInPlaceProcessFlags { Normal = 0, Zero = 1 } public enum DmoInPlaceProcessReturn { Normal, HasEffectTail } [Flags] public enum DmoInputDataBufferFlags { None = 0, SyncPoint = 1, Time = 2, TimeLength = 4 } [Flags] internal enum DmoInputStatusFlags { None = 0, DMO_INPUT_STATUSF_ACCEPT_DATA = 1 } internal static class DmoInterop { [DllImport("msdmo.dll")] public static extern int DMOEnum([In] ref Guid guidCategory, DmoEnumFlags flags, int inTypes, [In] DmoPartialMediaType[] inTypesArray, int outTypes, [In] DmoPartialMediaType[] outTypesArray, out IEnumDmo enumDmo); [DllImport("msdmo.dll")] public static extern int MoFreeMediaType([In] ref DmoMediaType mediaType); [DllImport("msdmo.dll")] public static extern int MoInitMediaType([In][Out] ref DmoMediaType mediaType, int formatBlockBytes); [DllImport("msdmo.dll")] public static extern int DMOGetName([In] ref Guid clsidDMO, [Out] StringBuilder name); } public struct DmoMediaType { private Guid majortype; private Guid subtype; private bool bFixedSizeSamples; private bool bTemporalCompression; private int lSampleSize; private Guid formattype; private IntPtr pUnk; private int cbFormat; private IntPtr pbFormat; public Guid MajorType => majortype; public string MajorTypeName => MediaTypes.GetMediaTypeName(majortype); public Guid SubType => subtype; public string SubTypeName { get { if (majortype == MediaTypes.MEDIATYPE_Audio) { return AudioMediaSubtypes.GetAudioSubtypeName(subtype); } return subtype.ToString(); } } public bool FixedSizeSamples => bFixedSizeSamples; public int SampleSize => lSampleSize; public Guid FormatType => formattype; public string FormatTypeName { get { if (formattype == DmoMediaTypeGuids.FORMAT_None) { return "None"; } if (formattype == Guid.Empty) { return "Null"; } if (formattype == DmoMediaTypeGuids.FORMAT_WaveFormatEx) { return "WaveFormatEx"; } return FormatType.ToString(); } } public WaveFormat GetWaveFormat() { if (formattype == DmoMediaTypeGuids.FORMAT_WaveFormatEx) { return WaveFormat.MarshalFromPtr(pbFormat); } throw new InvalidOperationException("Not a WaveFormat type"); } public void SetWaveFormat(WaveFormat waveFormat) { //IL_0024: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0066: Unknown result type (might be due to invalid IL or missing references) majortype = MediaTypes.MEDIATYPE_Audio; WaveFormatExtensible val = (WaveFormatExtensible)(object)((waveFormat is WaveFormatExtensible) ? waveFormat : null); if (val != null) { subtype = val.SubFormat; } else { WaveFormatEncoding encoding = waveFormat.Encoding; if ((int)encoding != 1) { if ((int)encoding != 3) { if ((int)encoding != 85) { throw new ArgumentException($"Not a supported encoding {waveFormat.Encoding}"); } subtype = AudioMediaSubtypes.WMMEDIASUBTYPE_MP3; } else { subtype = AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; } } else { subtype = AudioMediaSubtypes.MEDIASUBTYPE_PCM; } } bFixedSizeSamples = SubType == AudioMediaSubtypes.MEDIASUBTYPE_PCM || SubType == AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; formattype = DmoMediaTypeGuids.FORMAT_WaveFormatEx; if (cbFormat < Marshal.SizeOf<WaveFormat>(waveFormat)) { throw new InvalidOperationException("Not enough memory assigned for a WaveFormat structure"); } Marshal.StructureToPtr<WaveFormat>(waveFormat, pbFormat, fDeleteOld: false); } } [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct DmoOutputDataBuffer : IDisposable { [MarshalAs(UnmanagedType.Interface)] private IMediaBuffer pBuffer; private DmoOutputDataBufferFlags dwStatus; private long rtTimestamp; private long referenceTimeDuration; public IMediaBuffer MediaBuffer { get { return pBuffer; } internal set { pBuffer = value; } } public int Length => ((MediaBuffer)pBuffer).Length; public DmoOutputDataBufferFlags StatusFlags { get { return dwStatus; } internal set { dwStatus = value; } } public long Timestamp { get { return rtTimestamp; } internal set { rtTimestamp = value; } } public long Duration { get { return referenceTimeDuration; } internal set { referenceTimeDuration = value; } } public bool MoreDataAvailable => (StatusFlags & DmoOutputDataBufferFlags.Incomplete) == DmoOutputDataBufferFlags.Incomplete; public DmoOutputDataBuffer(int maxBufferSize) { pBuffer = new MediaBuffer(maxBufferSize); dwStatus = DmoOutputDataBufferFlags.None; rtTimestamp = 0L; referenceTimeDuration = 0L; } public void Dispose() { if (pBuffer != null) { ((MediaBuffer)pBuffer).Dispose(); pBuffer = null; GC.SuppressFinalize(this); } } public void RetrieveData(byte[] data, int offset) { ((MediaBuffer)pBuffer).RetrieveData(data, offset); } } [Flags] public enum DmoOutputDataBufferFlags { None = 0, SyncPoint = 1, Time = 2, TimeLength = 4, Incomplete = 0x1000000 } internal struct DmoPartialMediaType { private Guid type; private Guid subtype; public Guid Type { get { return type; } internal set { type = value; } } public Guid Subtype { get { return subtype; } internal set { subtype = value; } } } [Flags] public enum DmoProcessOutputFlags { None = 0, DiscardWhenNoBuffer = 1 } [Flags] internal enum DmoSetTypeFlags { None = 0, DMO_SET_TYPEF_TEST_ONLY = 1, DMO_SET_TYPEF_CLEAR = 2 } [ComImport] [Guid("2c3cd98a-2bfa-4a53-9c27-5249ba64ba0f")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IEnumDmo { int Next(int itemsToFetch, out Guid clsid, out IntPtr name, out int itemsFetched); int Skip(int itemsToSkip); int Reset(); int Clone(out IEnumDmo enumPointer); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("59eff8b9-938c-4a26-82f2-95cb84cdc837")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMediaBuffer { [PreserveSig] int SetLength(int length); [PreserveSig] int GetMaxLength(out int maxLength); [PreserveSig] int GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("d8ad0f58-5494-4102-97c5-ec798e59bcf4")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaObject { [PreserveSig] int GetStreamCount(out int inputStreams, out int outputStreams); [PreserveSig] int GetInputStreamInfo(int inputStreamIndex, out InputStreamInfoFlags flags); [PreserveSig] int GetOutputStreamInfo(int outputStreamIndex, out OutputStreamInfoFlags flags); [PreserveSig] int GetInputType(int inputStreamIndex, int typeIndex, out DmoMediaType mediaType); [PreserveSig] int GetOutputType(int outputStreamIndex, int typeIndex, out DmoMediaType mediaType); [PreserveSig] int SetInputType(int inputStreamIndex, [In] ref DmoMediaType mediaType, DmoSetTypeFlags flags); [PreserveSig] int SetOutputType(int outputStreamIndex, [In] ref DmoMediaType mediaType, DmoSetTypeFlags flags); [PreserveSig] int GetInputCurrentType(int inputStreamIndex, out DmoMediaType mediaType); [PreserveSig] int GetOutputCurrentType(int outputStreamIndex, out DmoMediaType mediaType); [PreserveSig] int GetInputSizeInfo(int inputStreamIndex, out int size, out int maxLookahead, out int alignment); [PreserveSig] int GetOutputSizeInfo(int outputStreamIndex, out int size, out int alignment); [PreserveSig] int GetInputMaxLatency(int inputStreamIndex, out long referenceTimeMaxLatency); [PreserveSig] int SetInputMaxLatency(int inputStreamIndex, long referenceTimeMaxLatency); [PreserveSig] int Flush(); [PreserveSig] int Discontinuity(int inputStreamIndex); [PreserveSig] int AllocateStreamingResources(); [PreserveSig] int FreeStreamingResources(); [PreserveSig] int GetInputStatus(int inputStreamIndex, out DmoInputStatusFlags flags); [PreserveSig] int ProcessInput(int inputStreamIndex, [In] IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long referenceTimeTimestamp, long referenceTimeDuration); [PreserveSig] int ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DmoOutputDataBuffer[] outputBuffers, out int statusReserved); [PreserveSig] int Lock(bool acquireLock); } [ComImport] [SuppressUnmanagedCodeSecurity] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("651B9AD0-0FC7-4AA9-9538-D89931010741")] internal interface IMediaObjectInPlace { [PreserveSig] int Process([In] int size, [In] IntPtr data, [In] long refTimeStart, [In] DmoInPlaceProcessFlags dwFlags); [PreserveSig] int Clone([MarshalAs(UnmanagedType.Interface)] out IMediaObjectInPlace mediaObjectInPlace); [PreserveSig] int GetLatency(out long latencyTime); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("6d6cbb60-a223-44aa-842f-a2f06750be6d")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMediaParamInfo { [PreserveSig] int GetParamCount(out int paramCount); [PreserveSig] int GetParamInfo(int paramIndex, ref MediaParamInfo paramInfo); [PreserveSig] int GetParamText(int paramIndex, out IntPtr paramText); [PreserveSig] int GetNumTimeFormats(out int numTimeFormats); [PreserveSig] int GetSupportedTimeFormat(int formatIndex, out Guid guidTimeFormat); [PreserveSig] int GetCurrentTimeFormat(out Guid guidTimeFormat, out int mediaTimeData); } [Flags] internal enum InputStreamInfoFlags { None = 0, DMO_INPUT_STREAMF_WHOLE_SAMPLES = 1, DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER = 2, DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE = 4, DMO_INPUT_STREAMF_HOLDS_BUFFERS = 8 } [ComImport] [Guid("E7E9984F-F09F-4da4-903F-6E2E0EFE56B5")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IWMResamplerProps { int SetHalfFilterLength(int outputQuality); int SetUserChannelMtx([In] float[] channelConversionMatrix); } public class MediaBuffer : IMediaBuffer, IDisposable { private IntPtr buffer; private int length; private readonly int maxLength; public int Length { get { return length; } set { if (length > maxLength) { throw new ArgumentException("Cannot be gr
UserLibs/NAudio.WinMM.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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.Threading; using Microsoft.CodeAnalysis; using Microsoft.Win32; using NAudio.CoreAudioApi; using NAudio.Mixer; using NAudio.Utils; using NAudio.Wave.Compression; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("NAudio.WinMM")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Mark Heath 2023")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0+c89fee940ee6f8d7374d18714a6b85d8b7a18ab0")] [assembly: AssemblyProduct("NAudio.WinMM")] [assembly: AssemblyTitle("NAudio.WinMM")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NAudio")] [assembly: AssemblyVersion("2.3.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace NAudio.Mixer { public class BooleanMixerControl : MixerControl { private MixerInterop.MIXERCONTROLDETAILS_BOOLEAN boolDetails; public bool Value { get { GetControlDetails(); return boolDetails.fValue == 1; } set { //IL_0055: Unknown result type (might be due to invalid IL or missing references) boolDetails.fValue = (value ? 1 : 0); mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf(boolDetails)); Marshal.StructureToPtr(boolDetails, mixerControlDetails.paDetails, fDeleteOld: false); MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails"); Marshal.FreeHGlobal(mixerControlDetails.paDetails); } } internal BooleanMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels) { base.mixerControl = mixerControl; base.mixerHandle = mixerHandle; base.mixerHandleType = mixerHandleType; base.nChannels = nChannels; mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS); GetControlDetails(); } protected override void GetDetails(IntPtr pDetails) { boolDetails = Marshal.PtrToStructure<MixerInterop.MIXERCONTROLDETAILS_BOOLEAN>(pDetails); } } public class CustomMixerControl : MixerControl { internal CustomMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels) { base.mixerControl = mixerControl; base.mixerHandle = mixerHandle; base.mixerHandleType = mixerHandleType; base.nChannels = nChannels; mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS); GetControlDetails(); } protected override void GetDetails(IntPtr pDetails) { } } public class ListTextMixerControl : MixerControl { internal ListTextMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels) { base.mixerControl = mixerControl; base.mixerHandle = mixerHandle; base.mixerHandleType = mixerHandleType; base.nChannels = nChannels; mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS); GetControlDetails(); } protected override void GetDetails(IntPtr pDetails) { } } public class Mixer { [CompilerGenerated] private sealed class <get_Destinations>d__16 : IEnumerable<MixerLine>, IEnumerable, IEnumerator<MixerLine>, IEnumerator, IDisposable { private int <>1__state; private MixerLine <>2__current; private int <>l__initialThreadId; public Mixer <>4__this; private int <destination>5__2; MixerLine IEnumerator<MixerLine>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Destinations>d__16(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; Mixer mixer = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <destination>5__2 = 0; break; case 1: <>1__state = -1; <destination>5__2++; break; } if (<destination>5__2 < mixer.DestinationCount) { <>2__current = mixer.GetDestination(<destination>5__2); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MixerLine> IEnumerable<MixerLine>.GetEnumerator() { <get_Destinations>d__16 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_Destinations>d__16(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MixerLine>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <get_Mixers>d__18 : IEnumerable<Mixer>, IEnumerable, IEnumerator<Mixer>, IEnumerator, IDisposable { private int <>1__state; private Mixer <>2__current; private int <>l__initialThreadId; private int <device>5__2; Mixer IEnumerator<Mixer>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Mixers>d__18(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <device>5__2 = 0; break; case 1: <>1__state = -1; <device>5__2++; break; } if (<device>5__2 < NumberOfDevices) { <>2__current = new Mixer(<device>5__2); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<Mixer> IEnumerable<Mixer>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <get_Mixers>d__18(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Mixer>)this).GetEnumerator(); } } private MixerInterop.MIXERCAPS caps; private IntPtr mixerHandle; private MixerFlags mixerHandleType; public static int NumberOfDevices => MixerInterop.mixerGetNumDevs(); public int DestinationCount => (int)caps.cDestinations; public string Name => caps.szPname; public Manufacturers Manufacturer => (Manufacturers)caps.wMid; public int ProductID => caps.wPid; public IEnumerable<MixerLine> Destinations { [IteratorStateMachine(typeof(<get_Destinations>d__16))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <get_Destinations>d__16(-2) { <>4__this = this }; } } public static IEnumerable<Mixer> Mixers { [IteratorStateMachine(typeof(<get_Mixers>d__18))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <get_Mixers>d__18(-2); } } public Mixer(int mixerIndex) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (mixerIndex < 0 || mixerIndex >= NumberOfDevices) { throw new ArgumentOutOfRangeException("mixerID"); } caps = default(MixerInterop.MIXERCAPS); MmException.Try(MixerInterop.mixerGetDevCaps((IntPtr)mixerIndex, ref caps, Marshal.SizeOf(caps)), "mixerGetDevCaps"); mixerHandle = (IntPtr)mixerIndex; mixerHandleType = MixerFlags.Mixer; } public MixerLine GetDestination(int destinationIndex) { if (destinationIndex < 0 || destinationIndex >= DestinationCount) { throw new ArgumentOutOfRangeException("destinationIndex"); } return new MixerLine(mixerHandle, destinationIndex, mixerHandleType); } } public abstract class MixerControl { internal MixerInterop.MIXERCONTROL mixerControl; internal MixerInterop.MIXERCONTROLDETAILS mixerControlDetails; protected IntPtr mixerHandle; protected int nChannels; protected MixerFlags mixerHandleType; public string Name => mixerControl.szName; public MixerControlType ControlType => mixerControl.dwControlType; public bool IsBoolean => IsControlBoolean(mixerControl.dwControlType); public bool IsListText => IsControlListText(mixerControl.dwControlType); public bool IsSigned => IsControlSigned(mixerControl.dwControlType); public bool IsUnsigned => IsControlUnsigned(mixerControl.dwControlType); public bool IsCustom => IsControlCustom(mixerControl.dwControlType); public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) List<MixerControl> list = new List<MixerControl>(); if (mixerLine.ControlsCount > 0) { int num = Marshal.SizeOf<MixerInterop.MIXERCONTROL>(); MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS); IntPtr intPtr = Marshal.AllocHGlobal(num * mixerLine.ControlsCount); mixerLineControls.cbStruct = Marshal.SizeOf(mixerLineControls); mixerLineControls.dwLineID = mixerLine.LineId; mixerLineControls.cControls = mixerLine.ControlsCount; mixerLineControls.pamxctrl = intPtr; mixerLineControls.cbmxctrl = Marshal.SizeOf<MixerInterop.MIXERCONTROL>(); try { MmResult val = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.Mixer | mixerHandleType); if ((int)val != 0) { throw new MmException(val, "mixerGetLineControls"); } for (int i = 0; i < mixerLineControls.cControls; i++) { MixerInterop.MIXERCONTROL mIXERCONTROL = Marshal.PtrToStructure<MixerInterop.MIXERCONTROL>((IntPtr)(intPtr.ToInt64() + num * i)); MixerControl item = GetMixerControl(mixerHandle, mixerLine.LineId, mIXERCONTROL.dwControlID, mixerLine.Channels, mixerHandleType); list.Add(item); } } finally { Marshal.FreeHGlobal(intPtr); } } return list; } public static MixerControl GetMixerControl(IntPtr mixerHandle, int nLineId, int controlId, int nChannels, MixerFlags mixerFlags) { //IL_005d: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS); MixerInterop.MIXERCONTROL structure = default(MixerInterop.MIXERCONTROL); IntPtr intPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(structure)); mixerLineControls.cbStruct = Marshal.SizeOf(mixerLineControls); mixerLineControls.cControls = 1; mixerLineControls.dwControlID = controlId; mixerLineControls.cbmxctrl = Marshal.SizeOf(structure); mixerLineControls.pamxctrl = intPtr; mixerLineControls.dwLineID = nLineId; MmResult val = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.ListText | mixerFlags); if ((int)val != 0) { Marshal.FreeCoTaskMem(intPtr); throw new MmException(val, "mixerGetLineControls"); } structure = Marshal.PtrToStructure<MixerInterop.MIXERCONTROL>(mixerLineControls.pamxctrl); Marshal.FreeCoTaskMem(intPtr); if (IsControlBoolean(structure.dwControlType)) { return new BooleanMixerControl(structure, mixerHandle, mixerFlags, nChannels); } if (IsControlSigned(structure.dwControlType)) { return new SignedMixerControl(structure, mixerHandle, mixerFlags, nChannels); } if (IsControlUnsigned(structure.dwControlType)) { return new UnsignedMixerControl(structure, mixerHandle, mixerFlags, nChannels); } if (IsControlListText(structure.dwControlType)) { return new ListTextMixerControl(structure, mixerHandle, mixerFlags, nChannels); } if (IsControlCustom(structure.dwControlType)) { return new CustomMixerControl(structure, mixerHandle, mixerFlags, nChannels); } throw new InvalidOperationException($"Unknown mixer control type {structure.dwControlType}"); } protected void GetControlDetails() { //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: 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) mixerControlDetails.cbStruct = Marshal.SizeOf(mixerControlDetails); mixerControlDetails.dwControlID = mixerControl.dwControlID; if (IsCustom) { mixerControlDetails.cChannels = 0; } else if ((mixerControl.fdwControl & (true ? 1u : 0u)) != 0) { mixerControlDetails.cChannels = 1; } else { mixerControlDetails.cChannels = nChannels; } if ((mixerControl.fdwControl & 2u) != 0) { mixerControlDetails.hwndOwner = (IntPtr)mixerControl.cMultipleItems; } else if (IsCustom) { mixerControlDetails.hwndOwner = IntPtr.Zero; } else { mixerControlDetails.hwndOwner = IntPtr.Zero; } if (IsBoolean) { mixerControlDetails.cbDetails = Marshal.SizeOf<MixerInterop.MIXERCONTROLDETAILS_BOOLEAN>(); } else if (IsListText) { mixerControlDetails.cbDetails = Marshal.SizeOf<MixerInterop.MIXERCONTROLDETAILS_LISTTEXT>(); } else if (IsSigned) { mixerControlDetails.cbDetails = Marshal.SizeOf<MixerInterop.MIXERCONTROLDETAILS_SIGNED>(); } else if (IsUnsigned) { mixerControlDetails.cbDetails = Marshal.SizeOf<MixerInterop.MIXERCONTROLDETAILS_UNSIGNED>(); } else { mixerControlDetails.cbDetails = mixerControl.Metrics.customData; } int num = mixerControlDetails.cbDetails * mixerControlDetails.cChannels; if ((mixerControl.fdwControl & 2u) != 0) { num *= (int)mixerControl.cMultipleItems; } IntPtr intPtr = Marshal.AllocCoTaskMem(num); mixerControlDetails.paDetails = intPtr; MmResult val = MixerInterop.mixerGetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType); if ((int)val == 0) { GetDetails(mixerControlDetails.paDetails); } Marshal.FreeCoTaskMem(intPtr); if ((int)val != 0) { throw new MmException(val, "mixerGetControlDetails"); } } protected abstract void GetDetails(IntPtr pDetails); private static bool IsControlBoolean(MixerControlType controlType) { switch (controlType) { case MixerControlType.BooleanMeter: case MixerControlType.Boolean: case MixerControlType.OnOff: case MixerControlType.Mute: case MixerControlType.Mono: case MixerControlType.Loudness: case MixerControlType.StereoEnhance: case MixerControlType.Button: case MixerControlType.SingleSelect: case MixerControlType.Mux: case MixerControlType.MultipleSelect: case MixerControlType.Mixer: return true; default: return false; } } private static bool IsControlListText(MixerControlType controlType) { if (controlType == MixerControlType.Equalizer || (uint)(controlType - 1879113728) <= 1u || (uint)(controlType - 1895890944) <= 1u) { return true; } return false; } private static bool IsControlSigned(MixerControlType controlType) { switch (controlType) { case MixerControlType.SignedMeter: case MixerControlType.PeakMeter: case MixerControlType.Signed: case MixerControlType.Decibels: case MixerControlType.Slider: case MixerControlType.Pan: case MixerControlType.QSoundPan: return true; default: return false; } } private static bool IsControlUnsigned(MixerControlType controlType) { switch (controlType) { case MixerControlType.UnsignedMeter: case MixerControlType.Unsigned: case MixerControlType.Percent: case MixerControlType.Fader: case MixerControlType.Volume: case MixerControlType.Bass: case MixerControlType.Treble: case MixerControlType.Equalizer: case MixerControlType.MicroTime: case MixerControlType.MilliTime: return true; default: return false; } } private static bool IsControlCustom(MixerControlType controlType) { return controlType == MixerControlType.Custom; } public override string ToString() { return $"{Name} {ControlType}"; } } [Flags] internal enum MixerControlClass { Custom = 0, Meter = 0x10000000, Switch = 0x20000000, Number = 0x30000000, Slider = 0x40000000, Fader = 0x50000000, Time = 0x60000000, List = 0x70000000, Mask = 0x70000000 } [Flags] internal enum MixerControlSubclass { SwitchBoolean = 0, SwitchButton = 0x1000000, MeterPolled = 0, TimeMicrosecs = 0, TimeMillisecs = 0x1000000, ListSingle = 0, ListMultiple = 0x1000000, Mask = 0xF000000 } [Flags] internal enum MixerControlUnits { Custom = 0, Boolean = 0x10000, Signed = 0x20000, Unsigned = 0x30000, Decibels = 0x40000, Percent = 0x50000, Mask = 0xFF0000 } public enum MixerControlType { Custom = 0, BooleanMeter = 268500992, SignedMeter = 268566528, PeakMeter = 268566529, UnsignedMeter = 268632064, Boolean = 536936448, OnOff = 536936449, Mute = 536936450, Mono = 536936451, Loudness = 536936452, StereoEnhance = 536936453, Button = 553713664, Decibels = 805568512, Signed = 805437440, Unsigned = 805502976, Percent = 805634048, Slider = 1073872896, Pan = 1073872897, QSoundPan = 1073872898, Fader = 1342373888, Volume = 1342373889, Bass = 1342373890, Treble = 1342373891, Equalizer = 1342373892, SingleSelect = 1879113728, Mux = 1879113729, MultipleSelect = 1895890944, Mixer = 1895890945, MicroTime = 1610809344, MilliTime = 1627586560 } [Flags] public enum MixerFlags { Handle = int.MinValue, Mixer = 0, MixerHandle = int.MinValue, WaveOut = 0x10000000, WaveOutHandle = -1879048192, WaveIn = 0x20000000, WaveInHandle = -1610612736, MidiOut = 0x30000000, MidiOutHandle = -1342177280, MidiIn = 0x40000000, MidiInHandle = -1073741824, Aux = 0x50000000, Value = 0, ListText = 1, QueryMask = 0xF, All = 0, OneById = 1, OneByType = 2, GetLineInfoOfDestination = 0, GetLineInfoOfSource = 1, GetLineInfoOfLineId = 2, GetLineInfoOfComponentType = 3, GetLineInfoOfTargetType = 4, GetLineInfoOfQueryMask = 0xF } internal class MixerInterop { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] public struct MIXERCONTROLDETAILS { public int cbStruct; public int dwControlID; public int cChannels; public IntPtr hwndOwner; public int cbDetails; public IntPtr paDetails; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MIXERCAPS { public ushort wMid; public ushort wPid; public uint vDriverVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szPname; public uint fdwSupport; public uint cDestinations; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MIXERLINECONTROLS { public int cbStruct; public int dwLineID; public int dwControlID; public int cControls; public int cbmxctrl; public IntPtr pamxctrl; } [Flags] public enum MIXERLINE_LINEF { MIXERLINE_LINEF_ACTIVE = 1, MIXERLINE_LINEF_DISCONNECTED = 0x8000, MIXERLINE_LINEF_SOURCE = int.MinValue } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MIXERLINE { public int cbStruct; public int dwDestination; public int dwSource; public int dwLineID; public MIXERLINE_LINEF fdwLine; public IntPtr dwUser; public MixerLineComponentType dwComponentType; public int cChannels; public int cConnections; public int cControls; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string szShortName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string szName; public uint dwType; public uint dwDeviceID; public ushort wMid; public ushort wPid; public uint vDriverVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szPname; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Bounds { public int minimum; public int maximum; public int reserved2; public int reserved3; public int reserved4; public int reserved5; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Metrics { public int step; public int customData; public int reserved2; public int reserved3; public int reserved4; public int reserved5; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MIXERCONTROL { public uint cbStruct; public int dwControlID; public MixerControlType dwControlType; public uint fdwControl; public uint cMultipleItems; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string szShortName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string szName; public Bounds Bounds; public Metrics Metrics; } public struct MIXERCONTROLDETAILS_BOOLEAN { public int fValue; } public struct MIXERCONTROLDETAILS_SIGNED { public int lValue; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MIXERCONTROLDETAILS_LISTTEXT { public uint dwParam1; public uint dwParam2; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string szName; } public struct MIXERCONTROLDETAILS_UNSIGNED { public uint dwValue; } public const uint MIXERCONTROL_CONTROLF_UNIFORM = 1u; public const uint MIXERCONTROL_CONTROLF_MULTIPLE = 2u; public const uint MIXERCONTROL_CONTROLF_DISABLED = 2147483648u; public const int MAXPNAMELEN = 32; public const int MIXER_SHORT_NAME_CHARS = 16; public const int MIXER_LONG_NAME_CHARS = 64; [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern int mixerGetNumDevs(); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerOpen(out IntPtr hMixer, int uMxId, IntPtr dwCallback, IntPtr dwInstance, MixerFlags dwOpenFlags); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerClose(IntPtr hMixer); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerGetControlDetails(IntPtr hMixer, ref MIXERCONTROLDETAILS mixerControlDetails, MixerFlags dwDetailsFlags); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerGetDevCaps(IntPtr nMixerID, ref MIXERCAPS mixerCaps, int mixerCapsSize); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerGetID(IntPtr hMixer, out int mixerID, MixerFlags dwMixerIDFlags); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerGetLineControls(IntPtr hMixer, ref MIXERLINECONTROLS mixerLineControls, MixerFlags dwControlFlags); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerGetLineInfo(IntPtr hMixer, ref MIXERLINE mixerLine, MixerFlags dwInfoFlags); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerMessage(IntPtr hMixer, uint nMessage, IntPtr dwParam1, IntPtr dwParam2); [DllImport("winmm.dll", CharSet = CharSet.Ansi)] public static extern MmResult mixerSetControlDetails(IntPtr hMixer, ref MIXERCONTROLDETAILS mixerControlDetails, MixerFlags dwDetailsFlags); } public class MixerLine { [CompilerGenerated] private sealed class <get_Sources>d__32 : IEnumerable<MixerLine>, IEnumerable, IEnumerator<MixerLine>, IEnumerator, IDisposable { private int <>1__state; private MixerLine <>2__current; private int <>l__initialThreadId; public MixerLine <>4__this; private int <source>5__2; MixerLine IEnumerator<MixerLine>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Sources>d__32(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; MixerLine mixerLine = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <source>5__2 = 0; break; case 1: <>1__state = -1; <source>5__2++; break; } if (<source>5__2 < mixerLine.SourceCount) { <>2__current = mixerLine.GetSource(<source>5__2); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MixerLine> IEnumerable<MixerLine>.GetEnumerator() { <get_Sources>d__32 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_Sources>d__32(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MixerLine>)this).GetEnumerator(); } } private MixerInterop.MIXERLINE mixerLine; private IntPtr mixerHandle; private MixerFlags mixerHandleType; public string Name => mixerLine.szName; public string ShortName => mixerLine.szShortName; public int LineId => mixerLine.dwLineID; public MixerLineComponentType ComponentType => mixerLine.dwComponentType; public string TypeDescription => mixerLine.dwComponentType switch { MixerLineComponentType.DestinationUndefined => "Undefined Destination", MixerLineComponentType.DestinationDigital => "Digital Destination", MixerLineComponentType.DestinationLine => "Line Level Destination", MixerLineComponentType.DestinationMonitor => "Monitor Destination", MixerLineComponentType.DestinationSpeakers => "Speakers Destination", MixerLineComponentType.DestinationHeadphones => "Headphones Destination", MixerLineComponentType.DestinationTelephone => "Telephone Destination", MixerLineComponentType.DestinationWaveIn => "Wave Input Destination", MixerLineComponentType.DestinationVoiceIn => "Voice Recognition Destination", MixerLineComponentType.SourceUndefined => "Undefined Source", MixerLineComponentType.SourceDigital => "Digital Source", MixerLineComponentType.SourceLine => "Line Level Source", MixerLineComponentType.SourceMicrophone => "Microphone Source", MixerLineComponentType.SourceSynthesizer => "Synthesizer Source", MixerLineComponentType.SourceCompactDisc => "Compact Disk Source", MixerLineComponentType.SourceTelephone => "Telephone Source", MixerLineComponentType.SourcePcSpeaker => "PC Speaker Source", MixerLineComponentType.SourceWaveOut => "Wave Out Source", MixerLineComponentType.SourceAuxiliary => "Auxiliary Source", MixerLineComponentType.SourceAnalog => "Analog Source", _ => "Invalid Component Type", }; public int Channels => mixerLine.cChannels; public int SourceCount => mixerLine.cConnections; public int ControlsCount => mixerLine.cControls; public bool IsActive => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_ACTIVE) != 0; public bool IsDisconnected => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_DISCONNECTED) != 0; public bool IsSource => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_SOURCE) != 0; public IEnumerable<MixerControl> Controls => MixerControl.GetMixerControls(mixerHandle, this, mixerHandleType); public IEnumerable<MixerLine> Sources { [IteratorStateMachine(typeof(<get_Sources>d__32))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <get_Sources>d__32(-2) { <>4__this = this }; } } public string TargetName => mixerLine.szPname; public MixerLine(IntPtr mixerHandle, int destinationIndex, MixerFlags mixerHandleType) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) this.mixerHandle = mixerHandle; this.mixerHandleType = mixerHandleType; mixerLine = default(MixerInterop.MIXERLINE); mixerLine.cbStruct = Marshal.SizeOf(mixerLine); mixerLine.dwDestination = destinationIndex; MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.Mixer), "mixerGetLineInfo"); } public MixerLine(IntPtr mixerHandle, int destinationIndex, int sourceIndex, MixerFlags mixerHandleType) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) this.mixerHandle = mixerHandle; this.mixerHandleType = mixerHandleType; mixerLine = default(MixerInterop.MIXERLINE); mixerLine.cbStruct = Marshal.SizeOf(mixerLine); mixerLine.dwDestination = destinationIndex; mixerLine.dwSource = sourceIndex; MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.ListText), "mixerGetLineInfo"); } public static int GetMixerIdForWaveIn(int waveInDevice) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) int mixerID = -1; MmException.Try(MixerInterop.mixerGetID((IntPtr)waveInDevice, out mixerID, MixerFlags.WaveIn), "mixerGetID"); return mixerID; } public MixerLine GetSource(int sourceIndex) { if (sourceIndex < 0 || sourceIndex >= SourceCount) { throw new ArgumentOutOfRangeException("sourceIndex"); } return new MixerLine(mixerHandle, mixerLine.dwDestination, sourceIndex, mixerHandleType); } public override string ToString() { return $"{Name} {TypeDescription} ({ControlsCount} controls, ID={mixerLine.dwLineID})"; } } public enum MixerLineComponentType { DestinationUndefined = 0, DestinationDigital = 1, DestinationLine = 2, DestinationMonitor = 3, DestinationSpeakers = 4, DestinationHeadphones = 5, DestinationTelephone = 6, DestinationWaveIn = 7, DestinationVoiceIn = 8, SourceUndefined = 4096, SourceDigital = 4097, SourceLine = 4098, SourceMicrophone = 4099, SourceSynthesizer = 4100, SourceCompactDisc = 4101, SourceTelephone = 4102, SourcePcSpeaker = 4103, SourceWaveOut = 4104, SourceAuxiliary = 4105, SourceAnalog = 4106 } public class SignedMixerControl : MixerControl { private MixerInterop.MIXERCONTROLDETAILS_SIGNED signedDetails; public int Value { get { GetControlDetails(); return signedDetails.lValue; } set { //IL_0052: Unknown result type (might be due to invalid IL or missing references) signedDetails.lValue = value; mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf(signedDetails)); Marshal.StructureToPtr(signedDetails, mixerControlDetails.paDetails, fDeleteOld: false); MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails"); Marshal.FreeHGlobal(mixerControlDetails.paDetails); } } public int MinValue => mixerControl.Bounds.minimum; public int MaxValue => mixerControl.Bounds.maximum; public double Percent { get { return 100.0 * (double)(Value - MinValue) / (double)(MaxValue - MinValue); } set { Value = (int)((double)MinValue + value / 100.0 * (double)(MaxValue - MinValue)); } } internal SignedMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels) { base.mixerControl = mixerControl; base.mixerHandle = mixerHandle; base.mixerHandleType = mixerHandleType; base.nChannels = nChannels; mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS); GetControlDetails(); } protected override void GetDetails(IntPtr pDetails) { signedDetails = Marshal.PtrToStructure<MixerInterop.MIXERCONTROLDETAILS_SIGNED>(mixerControlDetails.paDetails); } public override string ToString() { return $"{base.ToString()} {Percent}%"; } } public class UnsignedMixerControl : MixerControl { private MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[] unsignedDetails; public uint Value { get { GetControlDetails(); return unsignedDetails[0].dwValue; } set { //IL_008f: Unknown result type (might be due to invalid IL or missing references) int num = Marshal.SizeOf(unsignedDetails[0]); mixerControlDetails.paDetails = Marshal.AllocHGlobal(num * nChannels); for (int i = 0; i < nChannels; i++) { unsignedDetails[i].dwValue = value; long num2 = mixerControlDetails.paDetails.ToInt64() + num * i; Marshal.StructureToPtr(unsignedDetails[i], (IntPtr)num2, fDeleteOld: false); } MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails"); Marshal.FreeHGlobal(mixerControlDetails.paDetails); } } public uint MinValue => (uint)mixerControl.Bounds.minimum; public uint MaxValue => (uint)mixerControl.Bounds.maximum; public double Percent { get { return 100.0 * (double)(Value - MinValue) / (double)(MaxValue - MinValue); } set { Value = (uint)((double)MinValue + value / 100.0 * (double)(MaxValue - MinValue)); } } internal UnsignedMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels) { base.mixerControl = mixerControl; base.mixerHandle = mixerHandle; base.mixerHandleType = mixerHandleType; base.nChannels = nChannels; mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS); GetControlDetails(); } protected override void GetDetails(IntPtr pDetails) { unsignedDetails = new MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[nChannels]; for (int i = 0; i < nChannels; i++) { unsignedDetails[i] = Marshal.PtrToStructure<MixerInterop.MIXERCONTROLDETAILS_UNSIGNED>(mixerControlDetails.paDetails); } } public override string ToString() { return $"{base.ToString()} {Percent}%"; } } } namespace NAudio.Wave { internal enum AcmMetrics { CountDrivers = 1, CountCodecs = 2, CountConverters = 3, CountFilters = 4, CountDisabled = 5, CountHardware = 6, CountLocalDrivers = 20, CountLocalCodecs = 21, CountLocalConverters = 22, CountLocalFilters = 23, CountLocalDisabled = 24, HardwareWaveInput = 30, HardwareWaveOutput = 31, MaxSizeFormat = 50, MaxSizeFilter = 51, DriverSupport = 100, DriverPriority = 101 } [Flags] internal enum AcmStreamConvertFlags { BlockAlign = 4, Start = 0x10, End = 0x20 } [StructLayout(LayoutKind.Explicit)] public struct MmTime { public const int TIME_MS = 1; public const int TIME_SAMPLES = 2; public const int TIME_BYTES = 4; [FieldOffset(0)] public uint wType; [FieldOffset(4)] public uint ms; [FieldOffset(4)] public uint sample; [FieldOffset(4)] public uint cb; [FieldOffset(4)] public uint ticks; [FieldOffset(4)] public byte smpteHour; [FieldOffset(5)] public byte smpteMin; [FieldOffset(6)] public byte smpteSec; [FieldOffset(7)] public byte smpteFrame; [FieldOffset(8)] public byte smpteFps; [FieldOffset(9)] public byte smpteDummy; [FieldOffset(10)] public byte smptePad0; [FieldOffset(11)] public byte smptePad1; [FieldOffset(4)] public uint midiSongPtrPos; } public enum WaveCallbackStrategy { FunctionCallback, NewWindow, ExistingWindow, Event } [StructLayout(LayoutKind.Sequential)] public sealed class WaveHeader { public IntPtr dataBuffer; public int bufferLength; public int bytesRecorded; public IntPtr userData; public WaveHeaderFlags flags; public int loops; public IntPtr next; public IntPtr reserved; } [Flags] public enum WaveHeaderFlags { BeginLoop = 4, Done = 1, EndLoop = 8, InQueue = 0x10, Prepared = 2 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct WaveInCapabilities { private short manufacturerId; private short productId; private int driverVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] private string productName; private SupportedWaveFormat supportedFormats; private short channels; private short reserved; private Guid manufacturerGuid; private Guid productGuid; private Guid nameGuid; private const int MaxProductNameLength = 32; public int Channels => channels; public string ProductName => productName; public Guid NameGuid => nameGuid; public Guid ProductGuid => productGuid; public Guid ManufacturerGuid => manufacturerGuid; public bool SupportsWaveFormat(SupportedWaveFormat waveFormat) { return (supportedFormats & waveFormat) == waveFormat; } } public static class WaveCapabilitiesHelpers { public static readonly Guid MicrosoftDefaultManufacturerId = new Guid("d5a47fa8-6d98-11d1-a21a-00a0c9223196"); public static readonly Guid DefaultWaveOutGuid = new Guid("E36DC310-6D9A-11D1-A21A-00A0C9223196"); public static readonly Guid DefaultWaveInGuid = new Guid("E36DC311-6D9A-11D1-A21A-00A0C9223196"); public static string GetNameFromGuid(Guid guid) { string result = null; using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\Control\\MediaCategories")) { using RegistryKey registryKey2 = registryKey.OpenSubKey(guid.ToString("B")); if (registryKey2 != null) { result = registryKey2.GetValue("Name") as string; } } return result; } } public class WaveInterop { [Flags] public enum WaveInOutOpenFlags { CallbackNull = 0, CallbackFunction = 0x30000, CallbackEvent = 0x50000, CallbackWindow = 0x10000, CallbackThread = 0x20000 } public enum WaveMessage { WaveInOpen = 958, WaveInClose = 959, WaveInData = 960, WaveOutClose = 956, WaveOutDone = 957, WaveOutOpen = 955 } public delegate void WaveCallback(IntPtr hWaveOut, WaveMessage message, IntPtr dwInstance, WaveHeader wavhdr, IntPtr dwReserved); [DllImport("winmm.dll")] public static extern int mmioStringToFOURCC([MarshalAs(UnmanagedType.LPStr)] string s, int flags); [DllImport("winmm.dll")] public static extern int waveOutGetNumDevs(); [DllImport("winmm.dll")] public static extern MmResult waveOutPrepareHeader(IntPtr hWaveOut, WaveHeader lpWaveOutHdr, int uSize); [DllImport("winmm.dll")] public static extern MmResult waveOutUnprepareHeader(IntPtr hWaveOut, WaveHeader lpWaveOutHdr, int uSize); [DllImport("winmm.dll")] public static extern MmResult waveOutWrite(IntPtr hWaveOut, WaveHeader lpWaveOutHdr, int uSize); [DllImport("winmm.dll")] public static extern MmResult waveOutOpen(out IntPtr hWaveOut, IntPtr uDeviceID, WaveFormat lpFormat, WaveCallback dwCallback, IntPtr dwInstance, WaveInOutOpenFlags dwFlags); [DllImport("winmm.dll", EntryPoint = "waveOutOpen")] public static extern MmResult waveOutOpenWindow(out IntPtr hWaveOut, IntPtr uDeviceID, WaveFormat lpFormat, IntPtr callbackWindowHandle, IntPtr dwInstance, WaveInOutOpenFlags dwFlags); [DllImport("winmm.dll")] public static extern MmResult waveOutReset(IntPtr hWaveOut); [DllImport("winmm.dll")] public static extern MmResult waveOutClose(IntPtr hWaveOut); [DllImport("winmm.dll")] public static extern MmResult waveOutPause(IntPtr hWaveOut); [DllImport("winmm.dll")] public static extern MmResult waveOutRestart(IntPtr hWaveOut); [DllImport("winmm.dll")] public static extern MmResult waveOutGetPosition(IntPtr hWaveOut, ref MmTime mmTime, int uSize); [DllImport("winmm.dll")] public static extern MmResult waveOutSetVolume(IntPtr hWaveOut, int dwVolume); [DllImport("winmm.dll")] public static extern MmResult waveOutGetVolume(IntPtr hWaveOut, out int dwVolume); [DllImport("winmm.dll", CharSet = CharSet.Auto)] public static extern MmResult waveOutGetDevCaps(IntPtr deviceID, out WaveOutCapabilities waveOutCaps, int waveOutCapsSize); [DllImport("winmm.dll")] public static extern int waveInGetNumDevs(); [DllImport("winmm.dll", CharSet = CharSet.Auto)] public static extern MmResult waveInGetDevCaps(IntPtr deviceID, out WaveInCapabilities waveInCaps, int waveInCapsSize); [DllImport("winmm.dll")] public static extern MmResult waveInAddBuffer(IntPtr hWaveIn, WaveHeader pwh, int cbwh); [DllImport("winmm.dll")] public static extern MmResult waveInClose(IntPtr hWaveIn); [DllImport("winmm.dll")] public static extern MmResult waveInOpen(out IntPtr hWaveIn, IntPtr uDeviceID, WaveFormat lpFormat, WaveCallback dwCallback, IntPtr dwInstance, WaveInOutOpenFlags dwFlags); [DllImport("winmm.dll", EntryPoint = "waveInOpen")] public static extern MmResult waveInOpenWindow(out IntPtr hWaveIn, IntPtr uDeviceID, WaveFormat lpFormat, IntPtr callbackWindowHandle, IntPtr dwInstance, WaveInOutOpenFlags dwFlags); [DllImport("winmm.dll")] public static extern MmResult waveInPrepareHeader(IntPtr hWaveIn, WaveHeader lpWaveInHdr, int uSize); [DllImport("winmm.dll")] public static extern MmResult waveInUnprepareHeader(IntPtr hWaveIn, WaveHeader lpWaveInHdr, int uSize); [DllImport("winmm.dll")] public static extern MmResult waveInReset(IntPtr hWaveIn); [DllImport("winmm.dll")] public static extern MmResult waveInStart(IntPtr hWaveIn); [DllImport("winmm.dll")] public static extern MmResult waveInStop(IntPtr hWaveIn); [DllImport("winmm.dll")] public static extern MmResult waveInGetPosition(IntPtr hWaveIn, out MmTime mmTime, int uSize); } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct WaveOutCapabilities { private short manufacturerId; private short productId; private int driverVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] private string productName; private SupportedWaveFormat supportedFormats; private short channels; private short reserved; private WaveOutSupport support; private Guid manufacturerGuid; private Guid productGuid; private Guid nameGuid; private const int MaxProductNameLength = 32; public int Channels => channels; public bool SupportsPlaybackRateControl => (support & WaveOutSupport.PlaybackRate) == WaveOutSupport.PlaybackRate; public string ProductName => productName; public Guid NameGuid => nameGuid; public Guid ProductGuid => productGuid; public Guid ManufacturerGuid => manufacturerGuid; public bool SupportsWaveFormat(SupportedWaveFormat waveFormat) { return (supportedFormats & waveFormat) == waveFormat; } } [Flags] public enum SupportedWaveFormat { WAVE_FORMAT_1M08 = 1, WAVE_FORMAT_1S08 = 2, WAVE_FORMAT_1M16 = 4, WAVE_FORMAT_1S16 = 8, WAVE_FORMAT_2M08 = 0x10, WAVE_FORMAT_2S08 = 0x20, WAVE_FORMAT_2M16 = 0x40, WAVE_FORMAT_2S16 = 0x80, WAVE_FORMAT_4M08 = 0x100, WAVE_FORMAT_4S08 = 0x200, WAVE_FORMAT_4M16 = 0x400, WAVE_FORMAT_4S16 = 0x800, WAVE_FORMAT_44M08 = 0x100, WAVE_FORMAT_44S08 = 0x200, WAVE_FORMAT_44M16 = 0x400, WAVE_FORMAT_44S16 = 0x800, WAVE_FORMAT_48M08 = 0x1000, WAVE_FORMAT_48S08 = 0x2000, WAVE_FORMAT_48M16 = 0x4000, WAVE_FORMAT_48S16 = 0x8000, WAVE_FORMAT_96M08 = 0x10000, WAVE_FORMAT_96S08 = 0x20000, WAVE_FORMAT_96M16 = 0x40000, WAVE_FORMAT_96S16 = 0x80000 } [Flags] internal enum WaveOutSupport { Pitch = 1, PlaybackRate = 2, Volume = 4, LRVolume = 8, Sync = 0x10, SampleAccurate = 0x20 } public class AcmMp3FrameDecompressor : IMp3FrameDecompressor, IDisposable { private readonly AcmStream conversionStream; private readonly WaveFormat pcmFormat; private bool disposed; public WaveFormat OutputFormat => pcmFormat; public AcmMp3FrameDecompressor(WaveFormat sourceFormat) { pcmFormat = AcmStream.SuggestPcmFormat(sourceFormat); try { conversionStream = new AcmStream(sourceFormat, pcmFormat); } catch (Exception) { disposed = true; GC.SuppressFinalize(this); throw; } } public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset) { if (frame == null) { throw new ArgumentNullException("frame", "You must provide a non-null Mp3Frame to decompress"); } Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength); int sourceBytesConverted; int num = conversionStream.Convert(frame.FrameLength, out sourceBytesConverted); if (sourceBytesConverted != frame.FrameLength) { throw new InvalidOperationException($"Couldn't convert the whole MP3 frame (converted {sourceBytesConverted}/{frame.FrameLength})"); } Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, num); return num; } public void Reset() { conversionStream.Reposition(); } public void Dispose() { if (!disposed) { disposed = true; if (conversionStream != null) { conversionStream.Dispose(); } GC.SuppressFinalize(this); } } ~AcmMp3FrameDecompressor() { Dispose(); } } public class WaveFormatConversionProvider : IWaveProvider, IDisposable { private readonly AcmStream conversionStream; private readonly IWaveProvider sourceProvider; private readonly int preferredSourceReadSize; private int leftoverDestBytes; private int leftoverDestOffset; private int leftoverSourceBytes; private bool isDisposed; public WaveFormat WaveFormat { get; } public WaveFormatConversionProvider(WaveFormat targetFormat, IWaveProvider sourceProvider) { this.sourceProvider = sourceProvider; WaveFormat = targetFormat; conversionStream = new AcmStream(sourceProvider.WaveFormat, targetFormat); preferredSourceReadSize = Math.Min(sourceProvider.WaveFormat.AverageBytesPerSecond, conversionStream.SourceBuffer.Length); preferredSourceReadSize -= preferredSourceReadSize % sourceProvider.WaveFormat.BlockAlign; } public void Reposition() { leftoverDestBytes = 0; leftoverDestOffset = 0; leftoverSourceBytes = 0; conversionStream.Reposition(); } public int Read(byte[] buffer, int offset, int count) { int i = 0; if (count % WaveFormat.BlockAlign != 0) { count -= count % WaveFormat.BlockAlign; } int num5; for (; i < count; i += num5) { int num = Math.Min(count - i, leftoverDestBytes); if (num > 0) { Array.Copy(conversionStream.DestBuffer, leftoverDestOffset, buffer, offset + i, num); leftoverDestOffset += num; leftoverDestBytes -= num; i += num; } if (i >= count) { break; } int num2 = Math.Min(preferredSourceReadSize, conversionStream.SourceBuffer.Length - leftoverSourceBytes); int num3 = sourceProvider.Read(conversionStream.SourceBuffer, leftoverSourceBytes, num2) + leftoverSourceBytes; if (num3 == 0) { break; } int sourceBytesConverted; int num4 = conversionStream.Convert(num3, out sourceBytesConverted); if (sourceBytesConverted == 0) { break; } leftoverSourceBytes = num3 - sourceBytesConverted; if (leftoverSourceBytes > 0) { Buffer.BlockCopy(conversionStream.SourceBuffer, sourceBytesConverted, conversionStream.SourceBuffer, 0, leftoverSourceBytes); } if (num4 <= 0) { break; } int val = count - i; num5 = Math.Min(num4, val); if (num5 < num4) { leftoverDestBytes = num4 - num5; leftoverDestOffset = num5; } Array.Copy(conversionStream.DestBuffer, 0, buffer, i + offset, num5); } return i; } protected virtual void Dispose(bool disposing) { if (!isDisposed) { isDisposed = true; conversionStream?.Dispose(); } } public void Dispose() { GC.SuppressFinalize(this); Dispose(disposing: true); } ~WaveFormatConversionProvider() { Dispose(disposing: false); } } public class WaveFormatConversionStream : WaveStream { private readonly WaveFormatConversionProvider conversionProvider; private readonly WaveFormat targetFormat; private readonly long length; private long position; private readonly WaveStream sourceStream; private bool isDisposed; public override long Position { get { return position; } set { value -= value % ((WaveStream)this).BlockAlign; long num = EstimateDestToSource(value); ((Stream)(object)sourceStream).Position = num; position = EstimateSourceToDest(((Stream)(object)sourceStream).Position); conversionProvider.Reposition(); } } public override long Length => length; public override WaveFormat WaveFormat => targetFormat; public WaveFormatConversionStream(WaveFormat targetFormat, WaveStream sourceStream) { this.sourceStream = sourceStream; this.targetFormat = targetFormat; conversionProvider = new WaveFormatConversionProvider(targetFormat, (IWaveProvider)(object)sourceStream); length = EstimateSourceToDest((int)((Stream)(object)sourceStream).Length); position = 0L; } public static WaveStream CreatePcmStream(WaveStream sourceStream) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if ((int)sourceStream.WaveFormat.Encoding == 1) { return sourceStream; } WaveFormat val = AcmStream.SuggestPcmFormat(sourceStream.WaveFormat); if (val.SampleRate < 8000) { if ((int)sourceStream.WaveFormat.Encoding != 163) { throw new InvalidOperationException("Invalid suggested output format, please explicitly provide a target format"); } val = new WaveFormat(8000, 16, 1); } return (WaveStream)(object)new WaveFormatConversionStream(val, sourceStream); } [Obsolete("can be unreliable, use of this method not encouraged")] public int SourceToDest(int source) { return (int)EstimateSourceToDest(source); } private long EstimateSourceToDest(long source) { long num = source * targetFormat.AverageBytesPerSecond / sourceStream.WaveFormat.AverageBytesPerSecond; return num - num % targetFormat.BlockAlign; } private long EstimateDestToSource(long dest) { long num = dest * sourceStream.WaveFormat.AverageBytesPerSecond / targetFormat.AverageBytesPerSecond; return (int)(num - num % sourceStream.WaveFormat.BlockAlign); } [Obsolete("can be unreliable, use of this method not encouraged")] public int DestToSource(int dest) { return (int)EstimateDestToSource(dest); } public override int Read(byte[] buffer, int offset, int count) { int num = conversionProvider.Read(buffer, offset, count); position += num; return num; } protected override void Dispose(bool disposing) { if (!isDisposed) { isDisposed = true; if (disposing) { ((Stream)(object)sourceStream).Dispose(); conversionProvider.Dispose(); } } ((Stream)this).Dispose(disposing); } } public class WaveInBuffer : IDisposable { private readonly WaveHeader header; private readonly int bufferSize; private readonly byte[] buffer; private GCHandle hBuffer; private IntPtr waveInHandle; private GCHandle hHeader; private GCHandle hThis; public byte[] Data => buffer; public bool Done => (header.flags & WaveHeaderFlags.Done) == WaveHeaderFlags.Done; public bool InQueue => (header.flags & WaveHeaderFlags.InQueue) == WaveHeaderFlags.InQueue; public int BytesRecorded => header.bytesRecorded; public int BufferSize => bufferSize; public WaveInBuffer(IntPtr waveInHandle, int bufferSize) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) this.bufferSize = bufferSize; buffer = new byte[bufferSize]; hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); this.waveInHandle = waveInHandle; header = new WaveHeader(); hHeader = GCHandle.Alloc(header, GCHandleType.Pinned); header.dataBuffer = hBuffer.AddrOfPinnedObject(); header.bufferLength = bufferSize; header.loops = 1; hThis = GCHandle.Alloc(this); header.userData = (IntPtr)hThis; MmException.Try(WaveInterop.waveInPrepareHeader(waveInHandle, header, Marshal.SizeOf(header)), "waveInPrepareHeader"); } public void Reuse() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) MmException.Try(WaveInterop.waveInUnprepareHeader(waveInHandle, header, Marshal.SizeOf(header)), "waveUnprepareHeader"); MmException.Try(WaveInterop.waveInPrepareHeader(waveInHandle, header, Marshal.SizeOf(header)), "waveInPrepareHeader"); MmException.Try(WaveInterop.waveInAddBuffer(waveInHandle, header, Marshal.SizeOf(header)), "waveInAddBuffer"); } ~WaveInBuffer() { Dispose(disposing: false); } public void Dispose() { GC.SuppressFinalize(this); Dispose(disposing: true); } protected void Dispose(bool disposing) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (waveInHandle != IntPtr.Zero) { WaveInterop.waveInUnprepareHeader(waveInHandle, header, Marshal.SizeOf(header)); waveInHandle = IntPtr.Zero; } if (hHeader.IsAllocated) { hHeader.Free(); } if (hBuffer.IsAllocated) { hBuffer.Free(); } if (hThis.IsAllocated) { hThis.Free(); } } } public class WaveInEvent : IWaveIn, IDisposable { private readonly AutoResetEvent callbackEvent; private readonly SynchronizationContext syncContext; private IntPtr waveInHandle; private volatile CaptureState captureState; private WaveInBuffer[] buffers; public static int DeviceCount => WaveInterop.waveInGetNumDevs(); public int BufferMilliseconds { get; set; } public int NumberOfBuffers { get; set; } public int DeviceNumber { get; set; } public WaveFormat WaveFormat { get; set; } public event EventHandler<WaveInEventArgs> DataAvailable; public event EventHandler<StoppedEventArgs> RecordingStopped; public WaveInEvent() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) callbackEvent = new AutoResetEvent(initialState: false); syncContext = SynchronizationContext.Current; DeviceNumber = 0; WaveFormat = new WaveFormat(8000, 16, 1); BufferMilliseconds = 100; NumberOfBuffers = 3; captureState = (CaptureState)0; } public static WaveInCapabilities GetCapabilities(int devNumber) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) WaveInCapabilities waveInCaps = default(WaveInCapabilities); int waveInCapsSize = Marshal.SizeOf(waveInCaps); MmException.Try(WaveInterop.waveInGetDevCaps((IntPtr)devNumber, out waveInCaps, waveInCapsSize), "waveInGetDevCaps"); return waveInCaps; } private void CreateBuffers() { int num = BufferMilliseconds * WaveFormat.AverageBytesPerSecond / 1000; if (num % WaveFormat.BlockAlign != 0) { num -= num % WaveFormat.BlockAlign; } buffers = new WaveInBuffer[NumberOfBuffers]; for (int i = 0; i < buffers.Length; i++) { buffers[i] = new WaveInBuffer(waveInHandle, num); } } private void OpenWaveInDevice() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) CloseWaveInDevice(); MmException.Try(WaveInterop.waveInOpenWindow(out waveInHandle, (IntPtr)DeviceNumber, WaveFormat, callbackEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent), "waveInOpen"); CreateBuffers(); } public void StartRecording() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) if ((int)captureState != 0) { throw new InvalidOperationException("Already recording"); } OpenWaveInDevice(); MmException.Try(WaveInterop.waveInStart(waveInHandle), "waveInStart"); captureState = (CaptureState)1; ThreadPool.QueueUserWorkItem(delegate { RecordThread(); }, null); } private void RecordThread() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Exception e = null; try { DoRecording(); } catch (Exception ex) { e = ex; } finally { captureState = (CaptureState)0; RaiseRecordingStoppedEvent(e); } } private void DoRecording() { //IL_0002: 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_00a6: Invalid comparison between Unknown and I4 //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown captureState = (CaptureState)2; WaveInBuffer[] array = buffers; foreach (WaveInBuffer waveInBuffer in array) { if (!waveInBuffer.InQueue) { waveInBuffer.Reuse(); } } while ((int)captureState == 2) { if (!callbackEvent.WaitOne()) { continue; } array = buffers; foreach (WaveInBuffer waveInBuffer2 in array) { if (waveInBuffer2.Done) { if (waveInBuffer2.BytesRecorded > 0) { this.DataAvailable?.Invoke(this, new WaveInEventArgs(waveInBuffer2.Data, waveInBuffer2.BytesRecorded)); } if ((int)captureState == 2) { waveInBuffer2.Reuse(); } } } } } private void RaiseRecordingStoppedEvent(Exception e) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown EventHandler<StoppedEventArgs> handler = this.RecordingStopped; if (handler == null) { return; } if (syncContext == null) { handler(this, new StoppedEventArgs(e)); return; } syncContext.Post(delegate { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown handler(this, new StoppedEventArgs(e)); }, null); } public void StopRecording() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) if ((int)captureState != 0) { captureState = (CaptureState)3; MmException.Try(WaveInterop.waveInStop(waveInHandle), "waveInStop"); MmException.Try(WaveInterop.waveInReset(waveInHandle), "waveInReset"); callbackEvent.Set(); } } public long GetPosition() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) MmTime mmTime = default(MmTime); mmTime.wType = 4u; MmException.Try(WaveInterop.waveInGetPosition(waveInHandle, out mmTime, Marshal.SizeOf(mmTime)), "waveInGetPosition"); if (mmTime.wType != 4) { throw new Exception($"waveInGetPosition: wType -> Expected {4}, Received {mmTime.wType}"); } return mmTime.cb; } protected virtual void Dispose(bool disposing) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (disposing) { if ((int)captureState != 0) { StopRecording(); } CloseWaveInDevice(); } } private void CloseWaveInDevice() { //IL_0006: 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) WaveInterop.waveInReset(waveInHandle); if (buffers != null) { for (int i = 0; i < buffers.Length; i++) { buffers[i].Dispose(); } buffers = null; } WaveInterop.waveInClose(waveInHandle); waveInHandle = IntPtr.Zero; } public MixerLine GetMixerLine() { if (waveInHandle != IntPtr.Zero) { return new MixerLine(waveInHandle, 0, MixerFlags.WaveInHandle); } return new MixerLine((IntPtr)DeviceNumber, 0, MixerFlags.WaveIn); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } public class WaveOutBuffer : IDisposable { private readonly WaveHeader header; private readonly int bufferSize; private readonly byte[] buffer; private readonly IWaveProvider waveStream; private readonly object waveOutLock; private GCHandle hBuffer; private IntPtr hWaveOut; private GCHandle hHeader; private GCHandle hThis; public bool InQueue => (header.flags & WaveHeaderFlags.InQueue) == WaveHeaderFlags.InQueue; public int BufferSize => bufferSize; public WaveOutBuffer(IntPtr hWaveOut, int bufferSize, IWaveProvider bufferFillStream, object waveOutLock) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) this.bufferSize = bufferSize; buffer = new byte[bufferSize]; hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); this.hWaveOut = hWaveOut; waveStream = bufferFillStream; this.waveOutLock = waveOutLock; header = new WaveHeader(); hHeader = GCHandle.Alloc(header, GCHandleType.Pinned); header.dataBuffer = hBuffer.AddrOfPinnedObject(); header.bufferLength = bufferSize; header.loops = 1; hThis = GCHandle.Alloc(this); header.userData = (IntPtr)hThis; lock (waveOutLock) { MmException.Try(WaveInterop.waveOutPrepareHeader(hWaveOut, header, Marshal.SizeOf(header)), "waveOutPrepareHeader"); } } ~WaveOutBuffer() { Dispose(disposing: false); } public void Dispose() { GC.SuppressFinalize(this); Dispose(disposing: true); } protected void Dispose(bool disposing) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (hHeader.IsAllocated) { hHeader.Free(); } if (hBuffer.IsAllocated) { hBuffer.Free(); } if (hThis.IsAllocated) { hThis.Free(); } if (hWaveOut != IntPtr.Zero) { lock (waveOutLock) { WaveInterop.waveOutUnprepareHeader(hWaveOut, header, Marshal.SizeOf(header)); } hWaveOut = IntPtr.Zero; } } public bool OnDone() { int num; lock (waveStream) { num = waveStream.Read(buffer, 0, buffer.Length); } if (num == 0) { return false; } for (int i = num; i < buffer.Length; i++) { buffer[i] = 0; } WriteToWaveOut(); return true; } private void WriteToWaveOut() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) MmResult val; lock (waveOutLock) { val = WaveInterop.waveOutWrite(hWaveOut, header, Marshal.SizeOf(header)); } if ((int)val != 0) { throw new MmException(val, "waveOutWrite"); } GC.KeepAlive(this); } } public class WaveOutEvent : IWavePlayer, IDisposable, IWavePosition { private readonly object waveOutLock; private readonly SynchronizationContext syncContext; private IntPtr hWaveOut; private WaveOutBuffer[] buffers; private IWaveProvider waveStream; private volatile PlaybackState playbackState; private AutoResetEvent callbackEvent; public int DesiredLatency { get; set; } public int NumberOfBuffers { get; set; } public int DeviceNumber { get; set; } = -1; public WaveFormat OutputWaveFormat => waveStream.WaveFormat; public PlaybackState PlaybackState => playbackState; public float Volume { get { return WaveOutUtils.GetWaveOutVolume(hWaveOut, waveOutLock); } set { WaveOutUtils.SetWaveOutVolume(value, hWaveOut, waveOutLock); } } public event EventHandler<StoppedEventArgs> PlaybackStopped; public WaveOutEvent() { syncContext = SynchronizationContext.Current; if (syncContext != null && (syncContext.GetType().Name == "LegacyAspNetSynchronizationContext" || syncContext.GetType().Name == "AspNetSynchronizationContext")) { syncContext = null; } DesiredLatency = 300; NumberOfBuffers = 2; waveOutLock = new object(); } public void Init(IWaveProvider waveProvider) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) if ((int)playbackState != 0) { throw new InvalidOperationException("Can't re-initialize during playback"); } if (hWaveOut != IntPtr.Zero) { DisposeBuffers(); CloseWaveOut(); } callbackEvent = new AutoResetEvent(initialState: false); waveStream = waveProvider; int bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers); MmResult val; lock (waveOutLock) { val = WaveInterop.waveOutOpenWindow(out hWaveOut, (IntPtr)DeviceNumber, waveStream.WaveFormat, callbackEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent); } MmException.Try(val, "waveOutOpen"); buffers = new WaveOutBuffer[NumberOfBuffers]; playbackState = (PlaybackState)0; for (int i = 0; i < NumberOfBuffers; i++) { buffers[i] = new WaveOutBuffer(hWaveOut, bufferSize, waveStream, waveOutLock); } } public void Play() { //IL_001c: 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_0057: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (buffers == null || waveStream == null) { throw new InvalidOperationException("Must call Init first"); } if ((int)playbackState == 0) { playbackState = (PlaybackState)1; callbackEvent.Set(); ThreadPool.QueueUserWorkItem(delegate { PlaybackThread(); }, null); } else if ((int)playbackState == 2) { Resume(); callbackEvent.Set(); } } private void PlaybackThread() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Exception e = null; try { DoPlayback(); } catch (Exception ex) { e = ex; } finally { playbackState = (PlaybackState)0; RaisePlaybackStoppedEvent(e); } } private void DoPlayback() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0016: 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) while ((int)playbackState != 0) { if (!callbackEvent.WaitOne(DesiredLatency)) { _ = playbackState; _ = 1; } if ((int)playbackState != 1) { continue; } int num = 0; WaveOutBuffer[] array = buffers; foreach (WaveOutBuffer waveOutBuffer in array) { if (waveOutBuffer.InQueue || waveOutBuffer.OnDone()) { num++; } } if (num == 0) { playbackState = (PlaybackState)0; callbackEvent.Set(); } } } public void Pause() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_003d: 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_0046: Unknown result type (might be due to invalid IL or missing references) if ((int)playbackState == 1) { playbackState = (PlaybackState)2; MmResult val; lock (waveOutLock) { val = WaveInterop.waveOutPause(hWaveOut); } if ((int)val != 0) { throw new MmException(val, "waveOutPause"); } } } private void Resume() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0045: 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_003d: Unknown result type (might be due to invalid IL or missing references) if ((int)playbackState == 2) { MmResult val; lock (waveOutLock) { val = WaveInterop.waveOutRestart(hWaveOut); } if ((int)val != 0) { throw new MmException(val, "waveOutRestart"); } playbackState = (PlaybackState)1; } } public void Stop() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_003f: 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) if ((int)playbackState != 0) { playbackState = (PlaybackState)0; MmResult val; lock (waveOutLock) { val = WaveInterop.waveOutReset(hWaveOut); } if ((int)val != 0) { throw new MmException(val, "waveOutReset"); } callbackEvent.Set(); } } public long GetPosition() { return WaveOutUtils.GetPositionBytes(hWaveOut, waveOutLock); } public void Dispose() { GC.SuppressFinalize(this); Dispose(disposing: true); } protected void Dispose(bool disposing) { Stop(); if (disposing) { DisposeBuffers(); } CloseWaveOut(); } private void CloseWaveOut() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (callbackEvent != null) { callbackEvent.Close(); callbackEvent = null; } lock (waveOutLock) { if (hWaveOut != IntPtr.Zero) { WaveInterop.waveOutClose(hWaveOut); hWaveOut = IntPtr.Zero; } } } private void DisposeBuffers() { if (buffers != null) { WaveOutBuffer[] array = buffers; for (int i = 0; i < array.Length; i++) { array[i].Dispose(); } buffers = null; } } ~WaveOutEvent() { Dispose(disposing: false); } private void RaisePlaybackStoppedEvent(Exception e) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown EventHandler<StoppedEventArgs> handler = this.PlaybackStopped; if (handler == null) { return; } if (syncContext == null) { handler(this, new StoppedEventArgs(e)); return; } syncContext.Post(delegate { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown handler(this, new StoppedEventArgs(e)); }, null); } } public static class WaveOutUtils { public static float GetWaveOutVolume(IntPtr hWaveOut, object lockObject) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) MmResult val; int dwVolume; lock (lockObject) { val = WaveInterop.waveOutGetVolume(hWaveOut, out dwVolume); } MmException.Try(val, "waveOutGetVolume"); return (float)(dwVolume & 0xFFFF) / 65535f; } public static void SetWaveOutVolume(float value, IntPtr hWaveOut, object lockObject) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (value < 0f) { throw new ArgumentOutOfRangeException("value", "Volume must be between 0.0 and 1.0"); } if (value > 1f) { throw new ArgumentOutOfRangeException("value", "Volume must be between 0.0 and 1.0"); } int dwVolume = (int)(value * 65535f) + ((int)(value * 65535f) << 16); MmResult val; lock (lockObject) { val = WaveInterop.waveOutSetVolume(hWaveOut, dwVolume); } MmException.Try(val, "waveOutSetVolume"); } public static long GetPositionBytes(IntPtr hWaveOut, object lockObject) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) lock (lockObject) { MmTime mmTime = default(MmTime); mmTime.wType = 4u; MmException.Try(WaveInterop.waveOutGetPosition(hWaveOut, ref mmTime, Marshal.SizeOf(mmTime)), "waveOutGetPosition"); if (mmTime.wType != 4) { throw new Exception($"waveOutGetPosition: wType -> Expected {4}, Received {mmTime.wType}"); } return mmTime.cb; } } } } namespace NAudio.Wave.Compression { public class AcmDriver : IDisposable { private static List<AcmDriver> drivers; private AcmDriverDetails details; private IntPtr driverId; private IntPtr driverHandle; private List<AcmFormatTag> formatTags; private List<AcmFormat> tempFormatsList; private IntPtr localDllHandle; public int MaxFormatSize { get { //IL_000a: Unknown result type (might be due to invalid IL or missing references) MmException.Try(AcmInterop.acmMetrics(driverHandle, AcmMetrics.MaxSizeFormat, out var output), "acmMetrics"); return output; } } public string ShortName => details.shortName; public string LongName => details.longName; public IntPtr DriverId => driverId; public IEnumerable<AcmFormatTag> FormatTags { get { //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (formatTags == null) { if (driverHandle == IntPtr.Zero) { throw new InvalidOperationException("Driver must be opened first"); } formatTags = new List<AcmFormatTag>(); AcmFormatTagDetails formatTagDetails = default(AcmFormatTagDetails); formatTagDetails.structureSize = Marshal.SizeOf(formatTagDetails); MmException.Try(AcmInterop.acmFormatTagEnum(driverHandle, ref formatTagDetails, AcmFormatTagEnumCallback, IntPtr.Zero, 0), "acmFormatTagEnum"); } return formatTags; } } public static bool IsCodecInstalled(string shortName) { foreach (AcmDriver item in EnumerateAcmDrivers()) { if (item.ShortName == shortName) { return true; } } return false; } public static AcmDriver AddLocalDriver(string driverFile) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) IntPtr intPtr = NativeMethods.LoadLibrary(driverFile); if (intPtr == IntPtr.Zero) { throw new ArgumentException("Failed to load driver file"); } IntPtr procAddress = NativeMethods.GetProcAddress(intPtr, "DriverProc"); if (procAddress == IntPtr.Zero) { NativeMethods.FreeLibrary(intPtr); throw new ArgumentException("Failed to discover DriverProc"); } IntPtr hAcmDriver; MmResult val = AcmInterop.acmDriverAdd(out hAcmDriver, intPtr, procAddress, 0, AcmDriverAddFlags.Function); if ((int)val != 0) { NativeMethods.FreeLibrary(intPtr); throw new MmException(val, "acmDriverAdd"); } AcmDriver acmDriver = new AcmDriver(hAcmDriver); if (string.IsNullOrEmpty(acmDriver.details.longName)) { acmDriver.details.longName = "Local driver: " + Path.GetFileName(driverFile); acmDriver.localDllHandle = intPtr; } return acmDriver; } public static void RemoveLocalDriver(AcmDriver localDriver) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (localDriver.localDllHandle == IntPtr.Zero) { throw new ArgumentException("Please pass in the AcmDriver returned by the AddLocalDriver method"); } MmResult val = AcmInterop.acmDriverRemove(localDriver.driverId, 0); NativeMethods.FreeLibrary(localDriver.localDllHandle); MmException.Try(val, "acmDriverRemove"); } public static bool ShowFormatChooseDialog(IntPtr ownerWindowHandle, string windowTitle, AcmFormatEnumFlags enumFlags, WaveFormat enumFormat, out WaveFormat selectedFormat, out string selectedFormatDescription, out string selectedFormatTagDescription) { //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_00ab: 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_00ea: Invalid comparison between Unknown and I4 //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Invalid comparison between Unknown and I4 //IL_00ec: 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_00f5: Unknown result type (might be due to invalid IL or missing references) AcmFormatChoose formatChoose = default(AcmFormatChoose); formatChoose.structureSize = Marshal.SizeOf(formatChoose); formatChoose.styleFlags = AcmFormatChooseStyleFlags.None; formatChoose.ownerWindowHandle = ownerWindowHandle; int num = 200; formatChoose.selectedWaveFormatPointer = Marshal.AllocHGlobal(num); formatChoose.selectedWaveFormatByteSize = num; formatChoose.title = windowTitle; formatChoose.name = null; formatChoose.formatEnumFlags = enumFlags; formatChoose.waveFormatEnumPointer = IntPtr.Zero; if (enumFormat != null) { IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf<WaveFormat>(enumFormat)); Marshal.StructureToPtr<WaveFormat>(enumFormat, intPtr, fDeleteOld: false); formatChoose.waveFormatEnumPointer = intPtr; } formatChoose.instanceHandle = IntPtr.Zero; formatChoose.templateName = null; MmResult val = AcmInterop.acmFormatChoose(ref formatChoose); selectedFormat = null; selectedFormatDescription = null; selectedFormatTagDescription = null; if ((int)val == 0) { selectedFormat = WaveFormat.MarshalFromPtr(formatChoose.selectedWaveFormatPointer); selectedFormatDescription = formatChoose.formatDescription; selectedFormatTagDescription = formatChoose.formatTagDescription; } Marshal.FreeHGlobal(formatChoose.waveFormatEnumPointer); Marshal.FreeHGlobal(formatChoose.selectedWaveFormatPointer); if ((int)val != 515 && (int)val != 0) { throw new MmException(val, "acmFormatChoose"); } return (int)val == 0; } public static AcmDriver FindByShortName(string shortName) { foreach (AcmDriver item in EnumerateAcmDrivers()) { if (item.ShortName == shortName) { return item; } } return null; } public static IEnumerable<AcmDriver> EnumerateAcmDrivers() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) drivers = new List<AcmDriver>(); MmException.Try(AcmInterop.acmDriverEnum(DriverEnumCallback, IntPtr.Zero, (AcmDriverEnumFlags)0), "acmDriverEnum"); return drivers; } private static bool DriverEnumCallback(IntPtr hAcmDriver, IntPtr dwInstance, AcmDriverDetailsSupportFlags flags) { drivers.Add(new AcmDriver(hAcmDriver)); return true; } private AcmDriver(IntPtr hAcmDriver) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) driverId = hAcmDriver; details = default(AcmDriverDetails); details.structureSize = Marshal.SizeOf(details); MmException.Try(AcmInterop.acmDriverDetails(hAcmDriver, ref details, 0), "acmDriverDetails"); } public override string ToString() { return LongName; } public IEnumerable<AcmFormat> GetFormats(AcmFormatTag formatTag) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected I4, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (driverHandle == IntPtr.Zero) { throw new InvalidOperationException("Driver must be opened first"); } tempFormatsList = new List<AcmFormat>(); AcmFormatDetails formatDetails = default(AcmFormatDetails); formatDetails.structSize = Marshal.SizeOf(formatDetails); formatDetails.waveFormatByteSize = 1024; formatDetails.waveFormatPointer = Marshal.AllocHGlobal(formatDetails.waveFormatByteSize); formatDetails.formatTag = (int)formatTag.FormatTag; MmResult val = AcmInterop.acmFormatEnum(driverHandle, ref formatDetails, AcmFormatEnumCallback, IntPtr.Zero, AcmFormatEnumFlags.None); Marshal.FreeHGlobal(formatDetails.waveFormatPointer); MmException.Try(val, "acmFormatEnum"); return tempFormatsList; } public void Open() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (driverHandle == IntPtr.Zero) { MmException.Try(AcmInterop.acmDriverOpen(out driverHandle, DriverId, 0), "acmDriverOpen"); } } public void Close() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (driverHandle != IntPtr.Zero) { MmException.Try(AcmInterop.acmDriverClose(driverHandle, 0), "acmDriverClose"); driverHandle = IntPtr.Zero; } } private bool AcmFormatTagEnumCallback(IntPtr hAcmDriverId, ref AcmFormatTagDetails formatTagDetails, IntPtr dwInstance, AcmDriverDetailsSupportFlags flags) { formatTags.Add(new AcmFormatTag(formatTagDetails)); return true; } private bool AcmFormatEnumCallback(IntPtr hAcmDriverId, ref AcmFormatDetails formatDetails, IntPtr dwInstance, AcmDriverDetailsSupportFlags flags) { tempFormatsList.Add(new AcmFormat(formatDetails)); return true; } public void Dispose() { if (driverHandle != IntPtr.Zero) { Close(); GC.SuppressFinalize(this); } } } internal enum AcmDriverAddFlags { Local = 0, Global = 8, Function = 3, NotifyWindowHandle = 4 } [StructLayout(LayoutKind.Sequential, Pack = 2)] internal struct AcmDriverDetails { public int structureSize; public uint fccType; public uint fccComp; public ushort manufacturerId; public ushort productId; public uint acmVersion; public uint driverVersion; public AcmDriverDetailsSupportFlags supportFlags; public int formatTagsCount; public int filterTagsCount; public IntPtr hicon; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string shortName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string longName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string copyright; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string licensing; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)] public string features; private const int ShortNameChars = 32; private const int LongNameChars = 128; private const int CopyrightChars = 80; private const int LicensingChars = 128; private const int FeaturesChars = 512; } [Flags] public enum AcmDriverDetailsSupportFlags { Codec = 1, Converter = 2, Filter = 4, Hardware = 8, Async = 0x10, Local = 0x40000000, Disabled = int.MinValue } [Flags] internal enum AcmDriverEnumFlags { NoLocal = 0x40000000, Disabled = int.MinValue } public class AcmFormat { private readonly AcmFormatDetails formatDetails; public int FormatIndex => formatDetails.formatIndex; public WaveFormatEncoding FormatTag => (WaveFormatEncoding)(ushort)formatDetails.formatTag; public AcmDriverDetailsSupportFlags SupportFlags => formatDetails.supportFlags; public WaveFormat WaveFormat { get; private set; } public int WaveFormatByteSize => formatDetails.waveFormatByteSize; public string FormatDescription => formatDetails.formatDescription; internal AcmFormat(AcmFormatDetails formatDetails) { this.formatDetails = formatDetails; WaveFormat = WaveFormat.MarshalFromPtr(formatDetails.waveFormatPointer); } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)] internal struct AcmFormatChoose { public int structureSize; public AcmFormatChooseStyleFlags styleFlags; public IntPtr ownerWindowHandle; public IntPtr selectedWaveFormatPointer; public int selectedWaveFormatByteSize; [MarshalAs(UnmanagedType.LPTStr)] public string title; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] public string formatTagDescription; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string formatDescription; [MarshalAs(UnmanagedType.LPTStr)] public string name; public int nameByteSize; public AcmFormatEnumFlags formatEnumFlags; public IntPtr waveFormatEnumPointer; public IntPtr instanceHandle; [MarshalAs(UnmanagedType.LPTStr)] public string templateName; public IntPtr customData; public AcmInterop.AcmFormatChooseHookProc windowCallbackFunction; } [Flags] internal enum AcmFormatChooseStyleFlags { None = 0, ShowHelp = 4, EnableHook = 8, EnableTemplate = 0x10, EnableTemplateHandle = 0x20, InitToWfxStruct = 0x40, ContextHelp = 0x80 } [StructLayout(LayoutKind.Sequential, Pack = 4)] internal struct AcmFormatDetails { public int structSize; public int formatIndex; public int formatTag; public AcmDriverDetailsSupportFlags supportFlags; public IntPtr waveFormatPointer; public int waveFormatByteSize; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string formatDescription; public const int FormatDescriptionChars = 128; } [Flags] public enum AcmFormatEnumFlags { None = 0, Convert = 0x100000, Hardware = 0x400000, Input = 0x800000, Channels = 0x20000, SamplesPerSecond = 0x40000, Output = 0x1000000, Suggest = 0x200000, BitsPerSample = 0x80000, FormatTag = 0x10000 } [Flags] internal enum AcmFormatSuggestFlags { FormatTag = 0x10000, Channels = 0x20000, SamplesPerSecond = 0x40000, BitsPerSample = 0x80000, TypeMask = 0xFF0000 } public class AcmFormatTag { private AcmFormatTagDetails formatTagDetails; public int FormatTagIndex => formatTagDetails.formatTagIndex; public WaveFormatEncoding FormatTag => (WaveFormatEncoding)(ushort)formatTagDetails.formatTag; public int FormatSize => formatTagDetails.formatSize; public AcmDriverDetailsSupportFlags SupportFlags => formatTagDetails.supportFlags; public int StandardFormatsCount => formatTagDetails.standardFormatsCount; public string FormatDescription => formatTagDetails.formatDescription; internal AcmFormatTag(AcmFormatTagDetails formatTagDetails) { this.formatTagDetails = formatTagDetails; } } internal struct AcmFormatTagDetails { public int structureSize; public int formatTagIndex; public int formatTag; public int formatSize; public AcmDriverDetailsSupportFlags supportFlags; public int standardFormatsCount; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] public string formatDescription; public const int FormatTagDescriptionChars = 48; } internal class AcmInterop { public delegate bool AcmDriverEnumCallback(IntPtr hAcmDriverId, IntPtr instance, AcmDriverDetailsSupportFlags flags); public delegate bool AcmFormatEnumCallback(IntPtr hAcmDriverId, ref AcmFormatDetails formatDetails, IntPtr dwInstance, AcmDriverDetailsSupportFlags flags); public delegate bool AcmFormatTagEnumCallback(IntPtr hAcmDriverId, ref AcmFormatTagDetails formatTagDetails, IntPtr dwInstance, AcmDriverDetailsSupportFlags flags); public delegate bool AcmFormatChooseHookProc(IntPtr windowHandle, int message, IntPtr wParam, IntPtr lParam); [DllImport("msacm32.dll")] public static extern MmResult acmDriverAdd(out IntPtr driverHandle, IntPtr driverModule, IntPtr driverFunctionAddress, int priority, AcmDriverAddFlags flags); [DllImport("msacm32.dll")] public static extern MmResult acmDriverRemove(IntPtr driverHandle, int removeFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmDriverClose(IntPtr hAcmDriver, int closeFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmDriverEnum(AcmDriverEnumCallback fnCallback, IntPtr dwInstance, AcmDriverEnumFlags flags); [DllImport("Msacm32.dll")] public static extern MmResult acmDriverDetails(IntPtr hAcmDriver, ref AcmDriverDetails driverDetails, int reserved); [DllImport("Msacm32.dll")] public static extern MmResult acmDriverOpen(out IntPtr pAcmDriver, IntPtr hAcmDriverId, int openFlags); [DllImport("Msacm32.dll", EntryPoint = "acmFormatChooseW")] public static extern MmResult acmFormatChoose(ref AcmFormatChoose formatChoose); [DllImport("Msacm32.dll")] public static extern MmResult acmFormatEnum(IntPtr hAcmDriver, ref AcmFormatDetails formatDetails, AcmFormatEnumCallback callback, IntPtr instance, AcmFormatEnumFlags flags); [DllImport("Msacm32.dll", EntryPoint = "acmFormatSuggest")] public static extern MmResult acmFormatSuggest2(IntPtr hAcmDriver, IntPtr sourceFormatPointer, IntPtr destFormatPointer, int sizeDestFormat, AcmFormatSuggestFlags suggestFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmFormatTagEnum(IntPtr hAcmDriver, ref AcmFormatTagDetails formatTagDetails, AcmFormatTagEnumCallback callback, IntPtr instance, int reserved); [DllImport("Msacm32.dll")] public static extern MmResult acmMetrics(IntPtr hAcmObject, AcmMetrics metric, out int output); [DllImport("Msacm32.dll", EntryPoint = "acmStreamOpen")] public static extern MmResult acmStreamOpen2(out IntPtr hAcmStream, IntPtr hAcmDriver, IntPtr sourceFormatPointer, IntPtr destFormatPointer, [In] WaveFilter waveFilter, IntPtr callback, IntPtr instance, AcmStreamOpenFlags openFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamClose(IntPtr hAcmStream, int closeFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamConvert(IntPtr hAcmStream, [In][Out] AcmStreamHeaderStruct streamHeader, AcmStreamConvertFlags streamConvertFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamPrepareHeader(IntPtr hAcmStream, [In][Out] AcmStreamHeaderStruct streamHeader, int prepareFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamReset(IntPtr hAcmStream, int resetFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamSize(IntPtr hAcmStream, int inputBufferSize, out int outputBufferSize, AcmStreamSizeFlags flags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamUnprepareHeader(IntPtr hAcmStream, [In][Out] AcmStreamHeaderStruct streamHeader, int flags); } public class AcmStream : IDisposable { private IntPtr streamHandle; private IntPtr driverHandle; private AcmStreamHeader streamHeader; private readonly WaveFormat sourceFormat; public byte[] SourceBuffer => streamHeader.SourceBuffer; public byte[] DestBuffer => streamHeader.DestBuffer; public AcmStream(WaveFormat sourceFormat, WaveFormat destFormat) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) try { streamHandle = IntPtr.Zero; this.sourceFormat = sourceFormat; int num = Math.Max(65536, sourceFormat.AverageBytesPerSecond); num -= num % sourceFormat.BlockAlign; IntPtr intPtr = WaveFormat.MarshalToPtr(sourceFormat); IntPtr intPtr2 = WaveFormat.MarshalToPtr(destFormat); try { MmException.Try(AcmInterop.acmStreamOpen2(out streamHandle, IntPtr.Zero, intPtr, intPtr2, null, IntPtr.Zero, IntPtr.Zero, AcmStreamOpenFlags.NonRealTime), "acmStreamOpen"); } finally { Marshal.FreeHGlobal(intPtr); Marshal.FreeHGlobal(intPtr2); } int destBufferLength = SourceToDest(num); streamHeader = new AcmStreamHeader(streamHandle, num, destBufferLength); driverHandle = IntPtr.Zero; } catch { Dispose(); throw; } } public AcmStream(IntPtr driverId, WaveFormat sourceFormat, WaveFilter waveFilter) { //IL_0031: 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) int num = Math.Max(16384, sourceFormat.AverageBytesPerSecond); this.sourceFormat = sourceFormat; num -= num % sourceFormat.BlockAlign; MmException.Try(AcmInterop.acmDriverOpen(out driverHandle, driverId, 0), "acmDriverOpen"); IntPtr intPtr = WaveFormat.MarshalToPtr(sourceFormat); try { MmException.Try(AcmInterop.acmStreamOpen2(out streamHandle, driverHandle, intPtr, intPtr, waveFilter, IntPtr.Zero, IntPtr.Zero, AcmStreamOpenFlags.NonRealTime), "acmStreamOpen"); } finally { Marshal.FreeHGlobal(intPtr); } streamHeader = new AcmStreamHeader(streamHandle, num, SourceToDest(num)); } public int SourceToDest(int source) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (source == 0) { return 0; } MmException.Try(AcmInterop.acmStreamSize(streamHandle, source, out var outputBufferSize, AcmStreamSizeFlags.Source), "acmStreamSize"); return outputBufferSize; } public int DestToSource(int dest) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (dest == 0) { return 0; } MmException.Try(AcmInterop.acmStreamSize(streamHandle, dest, out var outputBufferSize, AcmStreamSizeFlags.Destination), "acmStreamSize"); return outputBufferSize; } public static WaveFormat SuggestPcmFormat(WaveFormat compressedFormat) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) WaveFormat val = new WaveFormat(compressedFormat.SampleRate, 16, compressedFormat.Channels); IntPtr intPtr = WaveFormat.MarshalToPtr(val); IntPtr intPtr2 = WaveFormat.MarshalToPtr(compressedFormat); try { MmResult val2 = AcmInterop.acmFormatSuggest2(IntPtr.Zero, intPtr2, intPtr, Marshal.SizeOf<WaveFormat>(val), AcmFormatSuggestFlags.FormatTag); val = WaveFormat.MarshalFromPtr(intPtr); MmException.Try(val2, "acmFormatSuggest"); return val; } finally { Marshal.FreeHGlobal(intPtr); Marshal.FreeHGlobal(intPtr2); } } public void Reposition() { streamHeader.Reposition(); } public int Convert(int bytesToConvert, out int sourceBytesConverted) { if (bytesToConvert % sourceFormat.BlockAlign != 0) { bytesToConvert -= bytesToConvert % sourceFormat.BlockAlign; } if (streamHeader == null) { throw new ObjectDisposedException("AcmStream has already been disposed"); } return streamHeader.Convert(bytesToConvert, out sourceBytesConverted); } [Obsolete("Call the version returning sourceBytesConverted instead")] public int Convert(int bytesToConvert) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) int sourceBytesConverted; int result = Convert(bytesToConvert, out sourceBytesConverted); if (sourceBytesConverted != bytesToConvert) { throw new MmException((MmResult)8, "AcmStreamHeader.Convert didn't convert everything"); } return result; } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { //IL_0036: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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) if (disposing && streamHeader != null) { streamHeader.Dispose(); streamHeader = null; } if (streamHandle != IntPtr.Zero) { MmResult val = AcmInterop.acmStreamClose(streamHandle, 0); streamHandle = IntPtr.Zero; if ((int)val != 0) {
UserLibs/VGltf.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using VGltf.Glb; using VGltf.Types; using VJson; using VJson.Schema; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("yutopp")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2019")] [assembly: AssemblyDescription("A glTF and GLB serializer/deserializer library written in pure C#.")] [assembly: AssemblyFileVersion("0.0.0.0")] [assembly: AssemblyInformationalVersion("0.0.0")] [assembly: AssemblyProduct("VGltf")] [assembly: AssemblyTitle("VGltf")] [assembly: AssemblyVersion("0.0.0.0")] namespace VGltf { public sealed class BufferBuilder { private sealed class AsView { public ArraySegment<byte> Payload; public int? ByteStride; public BufferView.TargetEnum? Target; } private readonly List<AsView> _asViews = new List<AsView>(); public int AddView(ArraySegment<byte> payload, int? byteStride = null, BufferView.TargetEnum? target = null) { int count = _asViews.Count; _asViews.Add(new AsView { Payload = payload, ByteStride = byteStride, Target = target }); return count; } public byte[] BuildBytes(out List<BufferView> views) { views = new List<BufferView>(); using MemoryStream memoryStream = new MemoryStream(); uint num = 0u; foreach (AsView asView in _asViews) { uint num2 = Align.WritePadding(memoryStream, num, 4u, 0); num += num2; uint byteOffset = num; memoryStream.Write(asView.Payload.Array, asView.Payload.Offset, asView.Payload.Count); num += (uint)asView.Payload.Count; uint num3 = Align.WritePadding(memoryStream, num, 4u, 0); num += num3; views.Add(new BufferView { Buffer = 0, ByteOffset = (int)byteOffset, ByteLength = asView.Payload.Count, ByteStride = asView.ByteStride, Target = asView.Target }); } return memoryStream.ToArray(); } } public sealed class GltfContainer { public Gltf Gltf { get; } public StoredBuffer Buffer { get; } public JsonSchemaRegistry JsonSchemas { get; } public GltfContainer(Gltf gltf, StoredBuffer buffer = null, JsonSchemaRegistry reg = null) { Gltf = gltf; Buffer = buffer; JsonSchemas = reg; } public static GltfContainer FromGltf(Stream s, StoredBuffer buffer = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown JsonSchemaRegistry reg = new JsonSchemaRegistry(); return new GltfContainer(GltfReader.Read(s, reg), buffer, reg); } public static void FromGltf(Stream s, GltfContainer container) { GltfWriter.Write(s, container.Gltf, container.JsonSchemas); } public static GltfContainer FromGlb(Stream s) { return Reader.ReadAsContainer(s); } public static void ToGlb(Stream s, GltfContainer container) { Writer.WriteFromContainer(s, container); } } public static class GltfReader { public static Gltf Read(Stream s, JsonSchemaRegistry reg, bool withRepairment = true) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) JsonReader val = new JsonReader(s); try { INode val2 = val.Read(); if (withRepairment) { RepairKnownInvalidFormat(val2); } Gltf gltf = (Gltf)new JsonDeserializer(typeof(Gltf)).DeserializeFromNode(val2); if (reg != null) { ConstraintsViolationException val3 = JsonSchemaExtensions.Validate(JsonSchema.CreateFromType<Gltf>(reg, false), (object)gltf, reg); if (val3 != null) { throw val3; } } return gltf; } finally { ((IDisposable)val)?.Dispose(); } } public static Gltf ReadWithoutValidation(Stream s, bool withRepairment = true) { return Read(s, null, withRepairment); } public static void RepairKnownInvalidFormat(INode node) { RepairUniGLTFInvalidNamesForImages(node); RepairUniGLTFInvalidTargets(node); RepairUniGLTFInvalidTargets2(node); RepairUniGLTFInvalidIndexValues(node); RepairUniGLTFInvalidScene(node); } public static void RepairUniGLTFInvalidNamesForImages(INode node) { INode obj = node["images"]; ArrayNode val = (ArrayNode)(object)((obj is ArrayNode) ? obj : null); if (val == null) { return; } foreach (INode item in val) { ObjectNode val2 = (ObjectNode)(object)((item is ObjectNode) ? item : null); if (val2 != null) { INode obj2 = item["extra"]["name"]; StringNode val3 = (StringNode)(object)((obj2 is StringNode) ? obj2 : null); if (val3 != null && item["name"] is UndefinedNode) { val2.AddElement("name", (INode)(object)val3); } } } } public static void RepairUniGLTFInvalidTargets(INode node) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown INode obj = node["meshes"]; ArrayNode val = (ArrayNode)(object)((obj is ArrayNode) ? obj : null); if (val == null) { return; } foreach (INode item in val) { INode val2 = item["extras"]; if (val2 is UndefinedNode) { val2 = (INode)new ObjectNode(); ((ObjectNode)item).AddElement("extras", val2); } INode obj2 = item["primitives"]; ArrayNode val3 = (ArrayNode)(object)((obj2 is ArrayNode) ? obj2 : null); if (val3 == null) { continue; } List<string> list = null; foreach (INode item2 in val3) { INode obj3 = item2["targets"]; ArrayNode val4 = (ArrayNode)(object)((obj3 is ArrayNode) ? obj3 : null); if (val4 == null) { continue; } List<string> list2 = new List<string>(); foreach (INode item3 in val4) { ObjectNode val5 = (ObjectNode)(object)((item3 is ObjectNode) ? item3 : null); if (val5 == null) { continue; } List<string> list3 = new List<string>(); foreach (KeyValuePair<string, INode> item4 in val5) { string key = item4.Key; if (key == "extra") { list3.Add(key); INode obj4 = item3[key]["name"]; StringNode val6 = (StringNode)(object)((obj4 is StringNode) ? obj4 : null); if (val6 == null) { continue; } list2.Add(val6.Value); } if (!IsValidMorphTargetProperty(key)) { list3.Add(key); } } foreach (string item5 in list3) { val5.RemoveElement(item5); } } if (list == null || list.Count == list2.Count) { list = list2; } } if (list == null) { continue; } ArrayNode val7 = null; ObjectNode val8 = (ObjectNode)(object)((val2 is ObjectNode) ? val2 : null); if (val8 != null) { INode val9 = val8["targetNames"]; if (val9 is UndefinedNode) { val9 = (INode)new ArrayNode(); val8.AddElement("targetNames", val9); } val7 = (ArrayNode)(object)((val9 is ArrayNode) ? val9 : null); } if (val7 == null) { continue; } foreach (string item6 in list) { val7.AddElement((INode)new StringNode(item6)); } } } public static void RepairUniGLTFInvalidTargets2(INode node) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown INode obj = node["meshes"]; ArrayNode val = (ArrayNode)(object)((obj is ArrayNode) ? obj : null); if (val == null) { return; } foreach (INode item in val) { INode val2 = item["extras"]; if (val2 is UndefinedNode) { val2 = (INode)new ObjectNode(); ((ObjectNode)item).AddElement("extras", val2); } INode obj2 = item["primitives"]; ArrayNode val3 = (ArrayNode)(object)((obj2 is ArrayNode) ? obj2 : null); if (val3 == null) { continue; } List<string> list = null; foreach (INode item2 in val3) { INode val4 = item2["extras"]; if (val4 is UndefinedNode) { continue; } INode val5 = val4["targetNames"]; if (val5 is UndefinedNode) { continue; } ArrayNode val6 = (ArrayNode)(object)((val5 is ArrayNode) ? val5 : null); if (val6 == null) { continue; } List<string> list2 = new List<string>(); foreach (INode elem in val6.Elems) { StringNode val7 = (StringNode)(object)((elem is StringNode) ? elem : null); if (val7 != null) { list2.Add(val7.Value); } } if (list == null || list.Count == list2.Count) { list = list2; } } if (list == null) { continue; } ArrayNode val8 = null; ObjectNode val9 = (ObjectNode)(object)((val2 is ObjectNode) ? val2 : null); if (val9 != null) { INode val10 = val9["targetNames"]; if (val10 is UndefinedNode) { val10 = (INode)new ArrayNode(); val9.AddElement("targetNames", val10); } val8 = (ArrayNode)(object)((val10 is ArrayNode) ? val10 : null); } if (val8 == null) { continue; } foreach (string item3 in list) { val8.AddElement((INode)new StringNode(item3)); } } } public static void RepairUniGLTFInvalidIndexValues(INode node) { RepairUniGLTFInvalidIndexValuesForMeshes(node); } public static void RepairUniGLTFInvalidIndexValuesForMeshes(INode node) { INode obj = node["meshes"]; ArrayNode val = (ArrayNode)(object)((obj is ArrayNode) ? obj : null); if (val == null) { return; } foreach (INode item in val) { INode obj2 = item["primitives"]; ArrayNode val2 = (ArrayNode)(object)((obj2 is ArrayNode) ? obj2 : null); if (val2 == null) { continue; } foreach (INode item2 in val2) { ObjectNode val3 = (ObjectNode)(object)((item2 is ObjectNode) ? item2 : null); if (val3 == null) { continue; } INode obj3 = item2["indices"]; IntegerNode val4 = (IntegerNode)(object)((obj3 is IntegerNode) ? obj3 : null); if (val4 != null && val4.Value == -1) { val3.RemoveElement("indices"); } INode obj4 = item2["material"]; IntegerNode val5 = (IntegerNode)(object)((obj4 is IntegerNode) ? obj4 : null); if (val5 != null && val5.Value == -1) { val3.RemoveElement("material"); } INode obj5 = item2["mode"]; IntegerNode val6 = (IntegerNode)(object)((obj5 is IntegerNode) ? obj5 : null); if (val6 != null && val6.Value == -1) { val3.RemoveElement("mode"); } INode obj6 = item2["targets"]; ArrayNode val7 = (ArrayNode)(object)((obj6 is ArrayNode) ? obj6 : null); if (val7 == null) { continue; } foreach (INode item3 in val7) { ObjectNode val8 = (ObjectNode)(object)((item3 is ObjectNode) ? item3 : null); if (val8 == null) { continue; } List<string> list = new List<string>(); foreach (KeyValuePair<string, INode> item4 in val8) { INode value = item4.Value; IntegerNode val9 = (IntegerNode)(object)((value is IntegerNode) ? value : null); if (val9 != null && val9.Value == -1) { list.Add(item4.Key); } } foreach (string item5 in list) { val8.RemoveElement(item5); } } } } } public static void RepairUniGLTFInvalidScene(INode node) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown ObjectNode val = (ObjectNode)(object)((node is ObjectNode) ? node : null); if (val != null) { INode obj = node["asset"]["generator"]; StringNode val2 = (StringNode)(object)((obj is StringNode) ? obj : null); if (val2 != null && !(val2.Value != "UniGLTF") && node["scene"] is UndefinedNode) { val.AddElement("scene", (INode)new IntegerNode(0L)); } } } private static bool IsValidMorphTargetProperty(string name) { if (name.StartsWith("_")) { return true; } switch (name) { case "POSITION": case "NORMAL": case "TANGENT": return true; default: return false; } } } public class GltfWriter { public static void Write(Stream s, Gltf gltf, JsonSchemaRegistry reg) { ConstraintsViolationException val = JsonSchemaExtensions.Validate(JsonSchema.CreateFromType<Gltf>(reg, false), (object)gltf, reg); if (val != null) { throw val; } WriteWithoutValidation(s, gltf); } public static void WriteWithoutValidation(Stream s, Gltf gltf) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) new JsonSerializer(typeof(Gltf)).Serialize<Gltf>(s, gltf, 0); } } public sealed class Resource { public ArraySegment<byte> Data; } public interface IResourceLoader { Resource Load(string uri); string FullPathOf(string uri); } public sealed class ResourceLoaderFromFileStorage : IResourceLoader { private readonly string _baseDir; public ResourceLoaderFromFileStorage(string baseDir) { _baseDir = baseDir; } public Resource Load(string uri) { if (DataUriUtil.IsData(uri)) { return DataUriUtil.Extract(uri); } return LoadFromFile(_baseDir, uri); } public string FullPathOf(string uri) { if (DataUriUtil.IsData(uri)) { throw new InvalidOperationException("uri is data form"); } return EnsureCleanedPath(_baseDir, uri); } public static string EnsureCleanedPath(string baseDir, string uri) { string fullPath = Path.GetFullPath(baseDir); string fullPath2 = Path.GetFullPath(Path.Combine(baseDir, uri)); if (!fullPath2.StartsWith(fullPath)) { throw new ArgumentException($"Path must be a child of baseDir: Uri = {uri}, BaseDir = {baseDir}, FullPath = {fullPath2}"); } return fullPath2; } public static Resource LoadFromFile(string baseDir, string uri) { byte[] array = File.ReadAllBytes(EnsureCleanedPath(baseDir, uri)); return new Resource { Data = new ArraySegment<byte>(array) }; } } public sealed class ResourceLoaderFromEmbedOnly : IResourceLoader { public Resource Load(string uri) { if (!DataUriUtil.IsData(uri)) { throw new InvalidOperationException("uri is not data form"); } return DataUriUtil.Extract(uri); } public string FullPathOf(string uri) { throw new NotImplementedException(uri); } } public static class DataUriUtil { public static bool IsData(string uri) { return uri.StartsWith("data:"); } public static Resource Extract(string uri) { int num = uri.IndexOf(','); if (num == -1) { throw new ArgumentException("Invalid DataURI format (',' is missing)"); } return new Resource { Data = new ArraySegment<byte>(Convert.FromBase64String(uri.Substring(num + 1))) }; } } public sealed class ResourcesStore { private readonly Dictionary<int, Resource> _bufferResources = new Dictionary<int, Resource>(); private readonly Dictionary<int, Resource> _imageResources = new Dictionary<int, Resource>(); public GltfContainer Container { get; } public IResourceLoader Loader { get; } public Gltf Gltf => Container.Gltf; public StoredBuffer Buffer => Container.Buffer; public ResourcesStore(GltfContainer container, IResourceLoader loader) { Container = container; Loader = loader; } public Resource GetOrLoadBufferResourceAt(int index) { if (GetBufferResourceAt(index, out var resource)) { return resource; } VGltf.Types.Buffer buffer = Gltf.Buffers[index]; if (buffer.Uri != null) { resource = Loader.Load(buffer.Uri); resource.Data = new ArraySegment<byte>(resource.Data.Array, resource.Data.Offset, buffer.ByteLength); } else { if (index != 0) { throw new InvalidOperationException("When referencing binaryBuffer, index must be 0"); } if (Buffer == null) { throw new InvalidOperationException("GLB stored buffer is null"); } resource = new Resource { Data = new ArraySegment<byte>(Buffer.Payload.Array, Buffer.Payload.Offset, buffer.ByteLength) }; } _bufferResources.Add(index, resource); return resource; } public bool GetBufferResourceAt(int index, out Resource resource) { return _bufferResources.TryGetValue(index, out resource); } public Resource GetOrLoadBufferViewResourceAt(int index) { BufferView bufferView = Gltf.BufferViews[index]; Resource orLoadBufferResourceAt = GetOrLoadBufferResourceAt(bufferView.Buffer); ArraySegment<byte> data = new ArraySegment<byte>(orLoadBufferResourceAt.Data.Array, orLoadBufferResourceAt.Data.Offset + bufferView.ByteOffset, bufferView.ByteLength); return new Resource { Data = data }; } public Resource GetOrLoadImageResourceAt(int index) { if (GetImageResourceAt(index, out var resource)) { return resource; } Image image = Gltf.Images[index]; resource = ((image.Uri == null) ? GetOrLoadBufferViewResourceAt(image.BufferView.Value) : Loader.Load(image.Uri)); _imageResources.Add(index, resource); return resource; } public bool GetImageResourceAt(int index, out Resource resource) { return _imageResources.TryGetValue(index, out resource); } public TypedBuffer GetOrLoadTypedBufferByAccessorIndex(int index) { Accessor accessor = Gltf.Accessors[index]; return new TypedBuffer(this, accessor); } } public interface ITypedView<T> where T : struct { } public delegate Out Mapper<Elem, Out>(Elem[] xs, int i) where Elem : struct where Out : struct; public sealed class TypedArrayView<T> where T : struct { public readonly T[] TypedBuffer; private TypedArrayView(T[] typedBuffer) { TypedBuffer = typedBuffer; } public static TypedArrayView<T> CreateFromPrimitive<Prim>(ArraySegment<byte> buffer, int stride, int componentSize, int componentNum, int count, Mapper<Prim, T> mapper) where Prim : struct { T[] array = new T[count]; if (componentSize * componentNum == stride) { Prim[] array2 = new Prim[componentNum * count]; byte[]? array3 = buffer.Array; int offset = buffer.Offset; System.Buffer.BlockCopy(array3, offset, array2, 0, componentSize * componentNum * count); for (int i = 0; i < array2.Length / componentNum; i++) { array[i] = mapper(array2, i * componentNum); } } else { Prim[] array4 = new Prim[componentNum]; byte[] array5 = buffer.Array; int offset2 = buffer.Offset; for (int j = 0; j < count; j++) { int num = j * stride; System.Buffer.BlockCopy(array5, offset2 + num, array4, 0, componentSize * componentNum); array[j] = mapper(array4, 0); } } return new TypedArrayView<T>(array); } } public static class TypedArrayStorageFromBufferView { public static TypedArrayView<T> CreateFrom<Prim, T>(ResourcesStore store, int bufferViewIndex, int byteOffset, int componentSize, int componentNum, int count, Mapper<Prim, T> mapper) where Prim : struct where T : struct { BufferView bufferView = store.Gltf.BufferViews[bufferViewIndex]; Resource orLoadBufferViewResourceAt = store.GetOrLoadBufferViewResourceAt(bufferViewIndex); int num = componentSize * componentNum; int num2 = (bufferView.ByteStride.HasValue ? bufferView.ByteStride.Value : num); return TypedArrayView<T>.CreateFromPrimitive(new ArraySegment<byte>(orLoadBufferViewResourceAt.Data.Array, orLoadBufferViewResourceAt.Data.Offset + byteOffset, count * num2), num2, componentSize, componentNum, count, mapper); } } public sealed class TypedArrayEntity<T, U> where T : struct where U : struct { public readonly TypedArrayView<U> DenseView; public readonly TypedArrayView<uint> SparseIndices; public readonly TypedArrayView<U> SparseValues; public readonly int Length; private readonly int _componentNum; public TypedArrayEntity(ResourcesStore store, Accessor accessor, Mapper<T, U> mapper) { Length = accessor.Count; _componentNum = accessor.Type.NumOfComponents(); if (accessor.BufferView.HasValue) { DenseView = TypedArrayStorageFromBufferView.CreateFrom(store, accessor.BufferView.Value, accessor.ByteOffset, accessor.ComponentType.SizeInBytes(), accessor.Type.NumOfComponents(), accessor.Count, mapper); } if (accessor.Sparse == null) { return; } Accessor.SparseType sparse = accessor.Sparse; Accessor.SparseType.IndicesType indices = sparse.Indices; switch (indices.ComponentType) { case Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_BYTE: SparseIndices = TypedArrayStorageFromBufferView.CreateFrom(store, indices.BufferView, indices.ByteOffset, indices.ComponentType.SizeInBytes(), 1, sparse.Count, (Mapper<byte, uint>)((byte[] xs, int i) => xs[i])); break; case Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_SHORT: SparseIndices = TypedArrayStorageFromBufferView.CreateFrom(store, indices.BufferView, indices.ByteOffset, indices.ComponentType.SizeInBytes(), 1, sparse.Count, (Mapper<ushort, uint>)((ushort[] xs, int i) => xs[i])); break; case Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_INT: SparseIndices = TypedArrayStorageFromBufferView.CreateFrom(store, indices.BufferView, indices.ByteOffset, indices.ComponentType.SizeInBytes(), 1, sparse.Count, (uint[] xs, int i) => xs[i]); break; default: throw new NotSupportedException(); } Accessor.SparseType.ValuesType values = sparse.Values; SparseValues = TypedArrayStorageFromBufferView.CreateFrom(store, values.BufferView, values.ByteOffset, accessor.ComponentType.SizeInBytes(), accessor.Type.NumOfComponents(), sparse.Count, mapper); } public U[] AsArray() { U[] array = ((DenseView != null) ? DenseView.TypedBuffer : null); if (SparseValues == null) { return array; } U[] typedBuffer = SparseValues.TypedBuffer; uint num = SparseIndices.TypedBuffer[0]; U[] array2 = new U[Length]; int num2 = 0; for (int i = 0; i < array2.Length; i++) { U val = default(U); if (array != null) { val = array[i]; } if (i == num) { val = typedBuffer[num2]; num2++; num = ((num2 < SparseIndices.TypedBuffer.Length) ? SparseIndices.TypedBuffer[num2] : uint.MaxValue); } array2[i] = val; } return array2; } } public sealed class TypedBuffer { public readonly ResourcesStore Store; public readonly Accessor Accessor; public TypedBuffer(ResourcesStore store, Accessor accessor) { Store = store; Accessor = accessor; } public TypedArrayEntity<T, U> GetEntity<T, U>(Mapper<T, U> mapper) where T : struct where U : struct { return new TypedArrayEntity<T, U>(Store, Accessor, mapper); } public int[] GetPrimitivesAsInt() { if (Accessor.Type != 0) { throw new InvalidOperationException("Type must be Scalar: Actual = " + Accessor.Type); } return Accessor.ComponentType switch { Accessor.ComponentTypeEnum.BYTE => GetEntity((Mapper<sbyte, int>)((sbyte[] xs, int i) => xs[i])).AsArray(), Accessor.ComponentTypeEnum.UNSIGNED_BYTE => GetEntity((Mapper<byte, int>)((byte[] xs, int i) => xs[i])).AsArray(), Accessor.ComponentTypeEnum.SHORT => GetEntity((Mapper<short, int>)((short[] xs, int i) => xs[i])).AsArray(), Accessor.ComponentTypeEnum.UNSIGNED_SHORT => GetEntity((Mapper<ushort, int>)((ushort[] xs, int i) => xs[i])).AsArray(), Accessor.ComponentTypeEnum.UNSIGNED_INT => GetEntity((uint[] xs, int i) => (int)xs[i]).AsArray(), Accessor.ComponentTypeEnum.FLOAT => throw new InvalidOperationException("Cannot convert from float to int"), _ => throw new InvalidOperationException("Unexpected ComponentType: Actual = " + Accessor.ComponentType), }; } } } namespace VGltf.Types { [JsonSchema(Id = "accessor.schema.json")] public sealed class Accessor : GltfChildOfRootProperty { [Json] public enum ComponentTypeEnum { [JsonField] BYTE = 5120, [JsonField] UNSIGNED_BYTE = 5121, [JsonField] SHORT = 5122, [JsonField] UNSIGNED_SHORT = 5123, [JsonField] UNSIGNED_INT = 5125, [JsonField] FLOAT = 5126 } [Json(/*Could not decode attribute arguments.*/)] public enum TypeEnum { [JsonField(Name = "SCALAR")] Scalar, [JsonField(Name = "VEC2")] Vec2, [JsonField(Name = "VEC3")] Vec3, [JsonField(Name = "VEC4")] Vec4, [JsonField(Name = "MAT2")] Mat2, [JsonField(Name = "MAT3")] Mat3, [JsonField(Name = "MAT4")] Mat4 } [JsonSchema(Id = "accessor.sparse.schema.json")] public sealed class SparseType : GltfProperty { [JsonSchema(Id = "accessor.sparse.indices.schema.json")] public class IndicesType : GltfProperty { [Json] public enum ComponentTypeEnum { [JsonField] UNSIGNED_BYTE = 5121, [JsonField] UNSIGNED_SHORT = 5123, [JsonField] UNSIGNED_INT = 5125 } [JsonField(Name = "bufferView")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int BufferView; [JsonField(Name = "byteOffset")] [JsonSchema(Minimum = 0.0)] public int ByteOffset; [JsonField(Name = "componentType")] [JsonSchemaRequired] public ComponentTypeEnum ComponentType; } [JsonSchema(Id = "accessor.sparse.values.schema.json")] public sealed class ValuesType : GltfProperty { [JsonField(Name = "bufferView")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int BufferView; [JsonField(Name = "byteOffset")] [JsonSchema(Minimum = 0.0)] public int ByteOffset; } [JsonField(Name = "count")] [JsonSchema(Minimum = 0.0)] [JsonSchemaRequired] public int Count; [JsonField(Name = "indices")] [JsonSchemaRequired] public IndicesType Indices; [JsonField(Name = "values")] [JsonSchemaRequired] public ValuesType Values; } [JsonField(Name = "bufferView")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? BufferView; [JsonField(Name = "byteOffset")] [JsonSchema(Minimum = 0.0)] [JsonSchemaDependencies(new string[] { "bufferView" })] public int ByteOffset; [JsonField(Name = "componentType")] [JsonSchemaRequired] public ComponentTypeEnum ComponentType; [JsonField(Name = "normalized")] public bool Normalized; [JsonField(Name = "count")] [JsonSchema(Minimum = 1.0)] [JsonSchemaRequired] public int Count; [JsonField(Name = "type")] [JsonSchemaRequired] public TypeEnum Type; [JsonField(Name = "max")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1, MaxItems = 16)] public float[] Max; [JsonField(Name = "min")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1, MaxItems = 16)] public float[] Min; [JsonField(Name = "sparse")] [JsonFieldIgnorable] public SparseType Sparse; } public static class AccessorComponentTypeEnumExtensions { public static int SizeInBytes(this Accessor.ComponentTypeEnum e) { return e switch { Accessor.ComponentTypeEnum.BYTE => 1, Accessor.ComponentTypeEnum.UNSIGNED_BYTE => 1, Accessor.ComponentTypeEnum.SHORT => 2, Accessor.ComponentTypeEnum.UNSIGNED_SHORT => 2, Accessor.ComponentTypeEnum.UNSIGNED_INT => 4, Accessor.ComponentTypeEnum.FLOAT => 4, _ => throw new NotImplementedException(), }; } public static Type TypeOf(this Accessor.ComponentTypeEnum e) { return e switch { Accessor.ComponentTypeEnum.BYTE => typeof(sbyte), Accessor.ComponentTypeEnum.UNSIGNED_BYTE => typeof(byte), Accessor.ComponentTypeEnum.SHORT => typeof(short), Accessor.ComponentTypeEnum.UNSIGNED_SHORT => typeof(ushort), Accessor.ComponentTypeEnum.UNSIGNED_INT => typeof(uint), Accessor.ComponentTypeEnum.FLOAT => typeof(float), _ => throw new NotImplementedException(), }; } } public static class AccessorTypeEnumExtensions { public static int NumOfComponents(this Accessor.TypeEnum t) { return t switch { Accessor.TypeEnum.Scalar => 1, Accessor.TypeEnum.Vec2 => 2, Accessor.TypeEnum.Vec3 => 3, Accessor.TypeEnum.Vec4 => 4, Accessor.TypeEnum.Mat2 => 4, Accessor.TypeEnum.Mat3 => 9, Accessor.TypeEnum.Mat4 => 16, _ => throw new NotImplementedException(), }; } } public static class AccessorSparseIndicesComponentTypeEnumExtensions { public static Accessor.ComponentTypeEnum CommonType(this Accessor.SparseType.IndicesType.ComponentTypeEnum e) { return e switch { Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_BYTE => Accessor.ComponentTypeEnum.UNSIGNED_BYTE, Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_SHORT => Accessor.ComponentTypeEnum.UNSIGNED_SHORT, Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_INT => Accessor.ComponentTypeEnum.UNSIGNED_INT, _ => throw new NotImplementedException(), }; } public static int SizeInBytes(this Accessor.SparseType.IndicesType.ComponentTypeEnum e) { return e.CommonType().SizeInBytes(); } public static Type TypeOf(this Accessor.SparseType.IndicesType.ComponentTypeEnum e) { return e.CommonType().TypeOf(); } } [JsonSchema(Id = "animation.schema.json")] public sealed class Animation : GltfChildOfRootProperty { [JsonSchema(Id = "animation.channel.schema.json")] public class ChannelType : GltfProperty { [JsonSchema(Id = "animation.channel.target.schema.json")] public class TargetType : GltfProperty { [Json(/*Could not decode attribute arguments.*/)] public enum PathEnum { [JsonField(Name = "translation")] Translation, [JsonField(Name = "rotation")] Rotation, [JsonField(Name = "scale")] Scale, [JsonField(Name = "weights")] Weights } [JsonField(Name = "node")] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int Node; [JsonField(Name = "path")] [JsonSchemaRequired] public PathEnum Path; } [JsonField(Name = "sampler")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int Sampler; [JsonField(Name = "target")] [JsonSchemaRequired] public TargetType Target; } [JsonSchema(Id = "animation.sampler.schema.json")] public class SamplerType { [Json(/*Could not decode attribute arguments.*/)] public enum InterpolationEnum { [JsonField(Name = "LINEAR")] LINEAR, [JsonField(Name = "STEP")] STEP, [JsonField(Name = "CUBICSPLINE")] CUBICSPLINE } [JsonField(Name = "input")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int Input; [JsonField(Name = "interpolation")] public InterpolationEnum Interpolation; [JsonField(Name = "output")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int Output; } [JsonField(Name = "channels")] [JsonSchema(MinItems = 1)] [JsonSchemaRequired] public List<ChannelType> Channels; [JsonField(Name = "samplers")] [JsonSchema(MinItems = 1)] [JsonSchemaRequired] public List<SamplerType> Samplers; } [JsonSchema(Id = "asset.schema.json")] public sealed class Asset : GltfProperty { [JsonField(Name = "copyright")] [JsonFieldIgnorable] public string Copyright; [JsonField(Name = "generator")] [JsonFieldIgnorable] public string Generator; [JsonField(Name = "version")] [JsonSchema(Pattern = "^[0-9]+\\.[0-9]+$")] [JsonSchemaRequired] public string Version; [JsonField(Name = "minVersion")] [JsonFieldIgnorable] [JsonSchema(Pattern = "^[0-9]+\\.[0-9]+$")] public string MinVersion; } [JsonSchema(Id = "buffer.schema.json")] public sealed class Buffer : GltfChildOfRootProperty { [JsonField(Name = "uri")] [JsonFieldIgnorable] public string Uri; [JsonField(Name = "byteLength")] [JsonSchema(Minimum = 1.0)] [JsonSchemaRequired] public int ByteLength; } [JsonSchema(Id = "bufferView.schema.json")] public sealed class BufferView : GltfChildOfRootProperty { [Json] public enum TargetEnum { [JsonField] ARRAY_BUFFER = 34962, [JsonField] ELEMENT_ARRAY_BUFFER } [JsonField(Name = "buffer")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int Buffer; [JsonField(Name = "byteOffset")] [JsonFieldIgnorable] [JsonSchema(Minimum = 0.0)] public int ByteOffset; [JsonField(Name = "byteLength")] [JsonSchema(Minimum = 1.0)] [JsonSchemaRequired] public int ByteLength; [JsonField(Name = "byteStride")] [JsonFieldIgnorable] [JsonSchema(Minimum = 4.0, Maximum = 252.0, MultipleOf = 4.0)] public int? ByteStride; [JsonField(Name = "target")] [JsonFieldIgnorable] public TargetEnum? Target; } [JsonSchema(Id = "camera.schema.json")] public sealed class Camera : GltfChildOfRootProperty { [JsonSchema(Id = "camera.orthographic.schema.json")] public sealed class OrthographicType : GltfProperty { [JsonField(Name = "xmag")] [JsonSchemaRequired] public float Xmag; [JsonField(Name = "ymag")] [JsonSchemaRequired] public float Ymag; [JsonField(Name = "zfar")] [JsonSchema(ExclusiveMinimum = 0.0)] [JsonSchemaRequired] public float Zfar; [JsonField(Name = "znear")] [JsonSchema(Minimum = 0.0)] [JsonSchemaRequired] public float Znear; } [JsonSchema(Id = "camera.perspective.schema.json")] public sealed class PerspectiveType { [JsonField(Name = "aspectRatio")] [JsonFieldIgnorable] [JsonSchema(ExclusiveMinimum = 0.0)] public float? AspectRatio; [JsonField(Name = "yfov")] [JsonSchema(ExclusiveMinimum = 0.0)] [JsonSchemaRequired] public float Yfov; [JsonField(Name = "zfar")] [JsonFieldIgnorable] [JsonSchema(ExclusiveMinimum = 0.0)] public float? Zfar; [JsonField(Name = "znear")] [JsonSchema(ExclusiveMinimum = 0.0)] [JsonSchemaRequired] public float Znear; } [Json(/*Could not decode attribute arguments.*/)] public enum TypeEnum { [JsonField(Name = "perspective")] Perspective, [JsonField(Name = "orthographic")] Orthographic } [JsonField(Name = "orthographic")] [JsonFieldIgnorable] public OrthographicType Orthographic; [JsonField(Name = "perspective")] [JsonFieldIgnorable] public PerspectiveType Perspective; [JsonField(Name = "type")] [JsonSchemaRequired] public TypeEnum Type; } [JsonSchema(Id = "glTF.schema.json")] public sealed class Gltf : GltfProperty { [JsonField(Name = "extensionsUsed")] [JsonFieldIgnorable] [JsonSchema(UniqueItems = true, MinItems = 1)] public List<string> ExtensionsUsed; [JsonField(Name = "extensionsRequired")] [JsonFieldIgnorable] [JsonSchema(UniqueItems = true, MinItems = 1)] public List<string> ExtensionsRequired; [JsonField(Name = "accessors")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Accessor> Accessors; [JsonField(Name = "animations")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Animation> Animations; [JsonField(Name = "asset")] [JsonSchemaRequired] public Asset Asset; [JsonField(Name = "buffers")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Buffer> Buffers; [JsonField(Name = "bufferViews")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<BufferView> BufferViews; [JsonField(Name = "cameras")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Camera> Cameras; [JsonField(Name = "images")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Image> Images; [JsonField(Name = "materials")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Material> Materials; [JsonField(Name = "meshes")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Mesh> Meshes; [JsonField(Name = "nodes")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Node> Nodes; [JsonField(Name = "samplers")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Sampler> Samplers; [JsonField(Name = "scene")] [JsonFieldIgnorable] [JsonSchemaDependencies(new string[] { "scenes" })] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Scene; [JsonField(Name = "scenes")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Scene> Scenes; [JsonField(Name = "skins")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Skin> Skins; [JsonField(Name = "textures")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public List<Texture> Textures; public IEnumerable<int> RootNodesIndices { get { if (!Scene.HasValue) { return Enumerable.Empty<int>(); } Scene scene = Scenes[Scene.Value]; if (scene.Nodes == null) { return Enumerable.Empty<int>(); } return scene.Nodes; } } public IEnumerable<Node> RootNodes => RootNodesIndices.Select((int i) => Nodes[i]); } [Json] public abstract class GltfChildOfRootProperty : GltfProperty { [JsonField(Name = "name")] [JsonFieldIgnorable] public string Name; } [JsonSchema(Minimum = 0.0)] public sealed class GltfID : RefTag<int> { } [Json] public abstract class GltfProperty { [JsonField(Name = "extensions")] [JsonFieldIgnorable] public Dictionary<string, INode> Extensions; [JsonField(Name = "extras")] [JsonFieldIgnorable] public Dictionary<string, INode> Extras; public void AddExtension<T>(string name, T value) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (Extensions == null) { Extensions = new Dictionary<string, INode>(); } INode value2 = new JsonSerializer(typeof(T)).SerializeToNode<T>(value); Extensions.Add(name, value2); } public bool TryGetExtension<T>(string name, JsonSchemaRegistry reg, out T value) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (Extensions == null) { value = default(T); return false; } if (!Extensions.TryGetValue(name, out var value2)) { value = default(T); return false; } ConstraintsViolationException val = JsonSchemaExtensions.Validate(JsonSchema.CreateFromType<T>(reg, false), (object)value2, reg); if (val != null) { throw val; } object obj = new JsonDeserializer(typeof(T)).DeserializeFromNode(value2); value = (T)obj; return true; } public void AddExtra<T>(string name, T value) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (Extras == null) { Extras = new Dictionary<string, INode>(); } INode value2 = new JsonSerializer(typeof(T)).SerializeToNode<T>(value); Extras.Add(name, value2); } public bool TryGetExtra<T>(string name, JsonSchemaRegistry reg, out T value) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (Extras == null) { value = default(T); return false; } if (!Extras.TryGetValue(name, out var value2)) { value = default(T); return false; } ConstraintsViolationException val = JsonSchemaExtensions.Validate(JsonSchema.CreateFromType<T>(reg, false), (object)value2, reg); if (val != null) { throw val; } object obj = new JsonDeserializer(typeof(T)).DeserializeFromNode(value2); value = (T)obj; return true; } } [JsonSchema(Id = "image.schema.json")] public sealed class Image : GltfChildOfRootProperty { public const string MimeTypeImageJpeg = "image/jpeg"; public const string MimeTypeImagePng = "image/png"; [JsonField(Name = "uri")] [JsonFieldIgnorable] public string Uri; [JsonField(Name = "mimeType")] [JsonFieldIgnorable(WhenValueIs = "")] public string MimeType = ""; [JsonField(Name = "bufferView")] [JsonFieldIgnorable] [JsonSchemaDependencies(new string[] { "mimeType" })] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? BufferView; } public static class ImageExtensions { public static string GetExtension(this Image img) { string mimeType = img.MimeType; if (!(mimeType == "image/jpeg")) { if (mimeType == "image/png") { return ".png"; } if (img.Uri.StartsWith("data:image/jpeg;")) { return ".jpg"; } if (img.Uri.StartsWith("data:image/png;")) { return ".png"; } return Path.GetExtension(img.Uri).ToLower(); } return ".jpg"; } } [JsonSchema(Id = "material.schema.json")] public sealed class Material : GltfChildOfRootProperty { [JsonSchema(Id = "material.pbrMetallicRoughness.schema.json")] public sealed class PbrMetallicRoughnessType : GltfProperty { [JsonField(Name = "baseColorFactor")] [JsonSchema(MinItems = 4, MaxItems = 4)] [ItemsJsonSchema(Minimum = 0.0, Maximum = 1.0)] public float[] BaseColorFactor = new float[4] { 1f, 1f, 1f, 1f }; [JsonField(Name = "baseColorTexture")] [JsonFieldIgnorable] public BaseColorTextureInfoType BaseColorTexture; [JsonField(Name = "metallicFactor")] [JsonSchema(Minimum = 0.0, Maximum = 1.0)] public float MetallicFactor = 1f; [JsonField(Name = "roughnessFactor")] [JsonSchema(Minimum = 0.0, Maximum = 1.0)] public float RoughnessFactor = 1f; [JsonField(Name = "metallicRoughnessTexture")] [JsonFieldIgnorable] public MetallicRoughnessTextureInfoType MetallicRoughnessTexture; } [Json] public sealed class BaseColorTextureInfoType : TextureInfo { public override TextureInfoKind Kind => TextureInfoKind.BaseColor; } [Json] public sealed class MetallicRoughnessTextureInfoType : TextureInfo { public override TextureInfoKind Kind => TextureInfoKind.MetallicRoughness; } [JsonSchema(Id = "material.normalTextureInfo.schema.json")] public sealed class NormalTextureInfoType : TextureInfo { [JsonField(Name = "scale")] public float Scale = 1f; public override TextureInfoKind Kind => TextureInfoKind.Normal; } [JsonSchema(Id = "material.occlusionTextureInfo.schema.json")] public sealed class OcclusionTextureInfoType : TextureInfo { [JsonField(Name = "strength")] [JsonSchema(Minimum = 0.0, Maximum = 1.0)] public float Strength = 1f; public override TextureInfoKind Kind => TextureInfoKind.Occlusion; } [Json] public sealed class EmissiveTextureInfoType : TextureInfo { public override TextureInfoKind Kind => TextureInfoKind.Emissive; } [Json(/*Could not decode attribute arguments.*/)] public enum AlphaModeEnum { [JsonField(Name = "OPAQUE")] Opaque, [JsonField(Name = "MASK")] Mask, [JsonField(Name = "BLEND")] Blend } [JsonField(Name = "pbrMetallicRoughness")] [JsonFieldIgnorable] public PbrMetallicRoughnessType PbrMetallicRoughness; [JsonField(Name = "normalTexture")] [JsonFieldIgnorable] public NormalTextureInfoType NormalTexture; [JsonField(Name = "occlusionTexture")] [JsonFieldIgnorable] public OcclusionTextureInfoType OcclusionTexture; [JsonField(Name = "emissiveTexture")] [JsonFieldIgnorable] public EmissiveTextureInfoType EmissiveTexture; [JsonField(Name = "emissiveFactor")] [JsonFieldIgnorable] [JsonSchema(MinItems = 3, MaxItems = 3)] [ItemsJsonSchema(Minimum = 0.0, Maximum = 1.0)] public float[] EmissiveFactor = new float[3]; [JsonField(Name = "alphaMode")] public AlphaModeEnum AlphaMode; [JsonField(Name = "alphaCutoff")] [JsonSchema(Minimum = 0.0)] [JsonFieldIgnorable(WhenValueIs = 0f)] [JsonSchemaDependencies(new string[] { "alphaMode" })] public float AlphaCutoff = 0.5f; [JsonField(Name = "doubleSided")] public bool DoubleSided; } public static class MaterialExtensions { public static IEnumerable<TextureInfo> GetTextures(this Material mat) { if (mat.PbrMetallicRoughness != null) { yield return mat.PbrMetallicRoughness.BaseColorTexture; yield return mat.PbrMetallicRoughness.MetallicRoughnessTexture; } yield return mat.NormalTexture; yield return mat.OcclusionTexture; yield return mat.EmissiveTexture; } } [JsonSchema(Id = "mesh.schema.json")] public sealed class Mesh : GltfChildOfRootProperty { [JsonSchema(Id = "mesh.primitive.schema.json")] public sealed class PrimitiveType : GltfProperty { [Json] public enum ModeEnum { [JsonField] POINTS, [JsonField] LINES, [JsonField] LINE_LOOP, [JsonField] LINE_STRIP, [JsonField] TRIANGLES, [JsonField] TRIANGLE_STRIP, [JsonField] TRIANGLE_FAN } public static class AttributeName { public static readonly string POSITION = "POSITION"; public static readonly string NORMAL = "NORMAL"; public static readonly string TANGENT = "TANGENT"; public static readonly string TEXCOORD_0 = "TEXCOORD_0"; public static readonly string TEXCOORD_1 = "TEXCOORD_1"; public static readonly string COLOR_0 = "COLOR_0"; public static readonly string JOINTS_0 = "JOINTS_0"; public static readonly string WEIGHTS_0 = "WEIGHTS_0"; } [JsonField(Name = "attributes")] [JsonSchema(MinProperties = 1)] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public Dictionary<string, int> Attributes; [JsonField(Name = "indices")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Indices; [JsonField(Name = "material")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Material; [JsonField(Name = "mode")] [JsonFieldIgnorable] public ModeEnum? Mode = ModeEnum.TRIANGLES; [JsonField(Name = "targets")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] [ItemsJsonSchema(MinProperties = 1)] [ItemsJsonSchemaRef(/*Could not decode attribute arguments.*/)] public List<Dictionary<string, int>> Targets; } [JsonField(Name = "primitives")] [JsonSchema(MinItems = 1)] [JsonSchemaRequired] public List<PrimitiveType> Primitives; [JsonField(Name = "weights")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] public float[] Weights; } [JsonSchema(Id = "node.schema.json")] public sealed class Node : GltfChildOfRootProperty { [JsonField(Name = "camera")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Camera; [JsonField(Name = "children")] [JsonFieldIgnorable] [JsonSchema(UniqueItems = true, MinItems = 1)] [ItemsJsonSchemaRef(/*Could not decode attribute arguments.*/)] public int[] Children; [JsonField(Name = "skin")] [JsonFieldIgnorable] [JsonSchemaDependencies(new string[] { "mesh" })] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Skin; [JsonField(Name = "matrix")] [JsonFieldIgnorable] [JsonSchema(MinItems = 16, MaxItems = 16)] public float[] Matrix = new float[16] { 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f }; [JsonField(Name = "mesh")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Mesh; [JsonField(Name = "rotation")] [JsonFieldIgnorable] [JsonSchema(MinItems = 4, MaxItems = 4)] [ItemsJsonSchema(Minimum = -1.0, Maximum = 1.0)] public float[] Rotation = new float[4] { 0f, 0f, 0f, 1f }; [JsonField(Name = "scale")] [JsonFieldIgnorable] [JsonSchema(MinItems = 3, MaxItems = 3)] public float[] Scale = new float[3] { 1f, 1f, 1f }; [JsonField(Name = "translation")] [JsonFieldIgnorable] [JsonSchema(MinItems = 3, MaxItems = 3)] public float[] Translation = new float[3]; [JsonField(Name = "weights")] [JsonFieldIgnorable] [JsonSchema(MinItems = 1)] [JsonSchemaDependencies(new string[] { "mesh" })] public float[] Weights; } [JsonSchema(Id = "sampler.schema.json")] public sealed class Sampler : GltfChildOfRootProperty { [Json] public enum MagFilterEnum { [JsonField] NEAREST = 9728, [JsonField] LINEAR } [Json] public enum MinFilterEnum { [JsonField] NEAREST = 9728, [JsonField] LINEAR = 9729, [JsonField] NEAREST_MIPMAP_NEAREST = 9984, [JsonField] LINEAR_MIPMAP_NEAREST = 9985, [JsonField] NEAREST_MIPMAP_LINEAR = 9986, [JsonField] LINEAR_MIPMAP_LINEAR = 9987 } [Json] public enum WrapEnum { [JsonField] ClampToEdge = 33071, [JsonField] MirroredRepeat = 33648, [JsonField] Repeat = 10497 } [JsonField(Name = "magFilter")] [JsonFieldIgnorable] public MagFilterEnum? MagFilter; [JsonField(Name = "minFilter")] [JsonFieldIgnorable] public MinFilterEnum? MinFilter; [JsonField(Name = "wrapS")] [JsonFieldIgnorable(WhenValueIs = WrapEnum.Repeat)] public WrapEnum WrapS = WrapEnum.Repeat; [JsonField(Name = "wrapT")] [JsonFieldIgnorable(WhenValueIs = WrapEnum.Repeat)] public WrapEnum WrapT = WrapEnum.Repeat; } [JsonSchema(Id = "scene.schema.json")] public sealed class Scene : GltfChildOfRootProperty { [JsonField(Name = "nodes")] [JsonSchema(UniqueItems = true, MinItems = 1)] [ItemsJsonSchemaRef(/*Could not decode attribute arguments.*/)] public int[] Nodes; } [JsonSchema(Id = "skin.schema.json")] public sealed class Skin : GltfChildOfRootProperty { [JsonField(Name = "inverseBindMatrices")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? InverseBindMatrices; [JsonField(Name = "skeleton")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Skeleton; [JsonField(Name = "joints")] [JsonSchema(UniqueItems = true, MinItems = 1)] [JsonSchemaRequired] [ItemsJsonSchemaRef(/*Could not decode attribute arguments.*/)] public int[] Joints; } [JsonSchema(Id = "texture.schema.json")] public sealed class Texture : GltfChildOfRootProperty { [JsonField(Name = "sampler")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Sampler; [JsonField(Name = "source")] [JsonFieldIgnorable] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int? Source; } public enum TextureInfoKind { BaseColor, MetallicRoughness, Normal, Occlusion, Emissive } [Json] public abstract class TextureInfo : GltfProperty { [JsonField(Name = "index")] [JsonSchemaRequired] [JsonSchemaRef(/*Could not decode attribute arguments.*/)] public int Index; [JsonField(Name = "texCoord")] [JsonSchema(Minimum = 0.0)] [JsonSchemaRequired] public int TexCoord; public abstract TextureInfoKind Kind { get; } } } namespace VGltf.Types.Extensions { public static class GltfExtensions { public static Scene GetSceneObject(this Gltf gltf) { if (!gltf.Scene.HasValue) { throw new Exception("Scene is null"); } return gltf.Scenes[gltf.Scene.Value]; } public static Image GetImageByTextureIndex(this Gltf gltf, int index, out int? imageIndex) { Texture texture = gltf.Textures[index]; imageIndex = texture.Source; return gltf.Images[imageIndex.Value]; } public static Image GetImageByTextureIndex(this Gltf gltf, int index) { int? imageIndex; return gltf.GetImageByTextureIndex(index, out imageIndex); } public static Sampler GetSamplerByTextureIndex(this Gltf gltf, int index, out int? samplerIndex) { Texture texture = gltf.Textures[index]; samplerIndex = texture.Sampler; return gltf.Samplers[samplerIndex.Value]; } public static Sampler GetSamplerByTextureIndex(this Gltf gltf, int index) { int? samplerIndex; return gltf.GetSamplerByTextureIndex(index, out samplerIndex); } public static int AddImage(this Gltf gltf, Image item) { if (gltf.Images == null) { gltf.Images = new List<Image>(); } int count = gltf.Images.Count; gltf.Images.Add(item); return count; } public static int AddAccessor(this Gltf gltf, Accessor item) { if (gltf.Accessors == null) { gltf.Accessors = new List<Accessor>(); } int count = gltf.Accessors.Count; gltf.Accessors.Add(item); return count; } public static int AddMesh(this Gltf gltf, Mesh item) { if (gltf.Meshes == null) { gltf.Meshes = new List<Mesh>(); } int count = gltf.Meshes.Count; gltf.Meshes.Add(item); return count; } public static int AddNode(this Gltf gltf, Node item) { if (gltf.Nodes == null) { gltf.Nodes = new List<Node>(); } int count = gltf.Nodes.Count; gltf.Nodes.Add(item); return count; } public static int AddScene(this Gltf gltf, Scene item) { if (gltf.Scenes == null) { gltf.Scenes = new List<Scene>(); } int count = gltf.Scenes.Count; gltf.Scenes.Add(item); return count; } public static int AddMaterial(this Gltf gltf, Material item) { if (gltf.Materials == null) { gltf.Materials = new List<Material>(); } int count = gltf.Materials.Count; gltf.Materials.Add(item); return count; } public static int AddSampler(this Gltf gltf, Sampler item) { if (gltf.Samplers == null) { gltf.Samplers = new List<Sampler>(); } int count = gltf.Samplers.Count; gltf.Samplers.Add(item); return count; } public static int AddTexture(this Gltf gltf, Texture item) { if (gltf.Textures == null) { gltf.Textures = new List<Texture>(); } int count = gltf.Textures.Count; gltf.Textures.Add(item); return count; } public static int AddSkin(this Gltf gltf, Skin item) { if (gltf.Skins == null) { gltf.Skins = new List<Skin>(); } int count = gltf.Skins.Count; gltf.Skins.Add(item); return count; } public static void AddExtensionUsed(this Gltf gltf, string name) { if (gltf.ExtensionsUsed == null) { gltf.ExtensionsUsed = new List<string>(); } if (!gltf.ContainsExtensionUsed(name)) { gltf.ExtensionsUsed.Add(name); } } public static bool ContainsExtensionUsed(this Gltf gltf, string name) { if (gltf.ExtensionsUsed == null) { return false; } return gltf.ExtensionsUsed.Contains(name); } public static void AddExtensionRequired(this Gltf gltf, string name) { if (gltf.ExtensionsRequired == null) { gltf.ExtensionsRequired = new List<string>(); } if (!gltf.ContainsExtensionRequired(name)) { gltf.ExtensionsRequired.Add(name); } } public static bool ContainsExtensionRequired(this Gltf gltf, string name) { if (gltf.ExtensionsRequired == null) { return false; } return gltf.ExtensionsRequired.Contains(name); } } } namespace VGltf.Glb { public static class Align { public static uint CalcPadding(uint offset, uint alignment) { return (alignment - offset % alignment) % alignment; } public static uint WritePadding(Stream s, uint offset, uint alignment, byte pad = 0) { uint num = CalcPadding(offset, alignment); for (int i = 0; i < num; i++) { s.WriteByte(pad); } return num; } } public sealed class Header { public uint Magic; public uint Version; public uint Length; } public sealed class Chunk { public uint ChunkLength; public uint ChunkType; public byte[] ChunkData; } public sealed class StoredBuffer { public ArraySegment<byte> Payload; } public sealed class Reader : IDisposable { private readonly BinaryReader _r; public Reader(Stream s) { _r = new BinaryReader(s); } public void Dispose() { if (_r != null) { ((IDisposable)_r).Dispose(); } } public Header ReadHeader() { return new Header { Magic = _r.ReadUInt32(), Version = _r.ReadUInt32(), Length = _r.ReadUInt32() }; } public Chunk ReadChunk() { try { Chunk chunk = new Chunk(); chunk.ChunkLength = _r.ReadUInt32(); chunk.ChunkType = _r.ReadUInt32(); chunk.ChunkData = _r.ReadBytes((int)chunk.ChunkLength); return chunk; } catch (EndOfStreamException) { return null; } } public static GltfContainer ReadAsContainer(Stream s) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown using Reader reader = new Reader(s); Header header = reader.ReadHeader(); if (header.Magic != 1179937895) { throw new NotImplementedException(); } if (header.Version != 2) { throw new NotImplementedException(); } Gltf gltf = null; StoredBuffer storedBuffer = null; JsonSchemaRegistry reg = new JsonSchemaRegistry(); int num = 0; while (true) { Chunk chunk = reader.ReadChunk(); if (chunk == null) { break; } switch (chunk.ChunkType) { case 1313821514u: { if (num != 0) { throw new NotImplementedException("Json"); } if (gltf != null) { throw new NotImplementedException("Json"); } using (MemoryStream s2 = new MemoryStream(chunk.ChunkData)) { gltf = GltfReader.Read(s2, reg); } break; } case 5130562u: if (num != 1) { throw new NotImplementedException("BinaryBuffer"); } if (storedBuffer != null) { throw new NotImplementedException("BinaryBuffer"); } storedBuffer = new StoredBuffer { Payload = new ArraySegment<byte>(chunk.ChunkData) }; break; } num++; } if (gltf == null) { throw new NotImplementedException("Json is empty"); } return new GltfContainer(gltf, storedBuffer, reg); } } public sealed class Writer : IDisposable { private readonly BinaryWriter _w; public Writer(Stream s) { _w = new BinaryWriter(s); } public void Dispose() { if (_w != null) { ((IDisposable)_w).Dispose(); } } public void WriteHeader(Header h) { _w.Write(h.Magic); _w.Write(h.Version); _w.Write(h.Length); } public void WriteChunk(Chunk c) { _w.Write(c.ChunkLength); _w.Write(c.ChunkType); _w.Write(c.ChunkData); } public static void WriteFromContainer(Stream s, GltfContainer container) { using Writer writer = new Writer(s); uint num = 0u; byte[] array = null; if (container.Gltf == null) { throw new NotImplementedException("Json is empty"); } using (MemoryStream memoryStream = new MemoryStream()) { GltfWriter.Write(memoryStream, container.Gltf, container.JsonSchemas); array = memoryStream.ToArray(); } num += (uint)(8 + array.Length); uint num2 = Align.CalcPadding(num, 4u); num += num2; byte[] array2 = null; if (container.Buffer != null) { using (MemoryStream memoryStream2 = new MemoryStream()) { ArraySegment<byte> payload = container.Buffer.Payload; memoryStream2.Write(payload.Array, payload.Offset, payload.Count); array2 = memoryStream2.ToArray(); } num += (uint)(8 + array2.Length); } writer.WriteHeader(new Header { Magic = 1179937895u, Version = 2u, Length = 12 + num }); writer.WriteChunk(new Chunk { ChunkLength = (uint)array.Length + num2, ChunkType = 1313821514u, ChunkData = array }); writer._w.Write(new byte[4] { 32, 32, 32, 32 }, 0, (int)num2); if (array2 != null) { writer.WriteChunk(new Chunk { ChunkLength = (uint)array2.Length, ChunkType = 5130562u, ChunkData = array2 }); } } } } namespace VGltf.Ext.KhrMaterialsUnlit.Types { [JsonSchema(Title = "KHR_materials_unlit glTF extension", Description = "glTF extension that defines the unlit material model.", Id = "glTF.KHR_materials_unlit.schema.json")] public sealed class KhrMaterialsUnlit { public static readonly string ExtensionName = "KHR_materials_unlit"; } } namespace VGltf.Ext.KhrMaterialsEmissiveStrength.Types { [JsonSchema(Title = "KHR_materials_emissive_strength glTF extension", Description = "glTF extension that adjusts the strength of emissive material properties.", Id = "glTF.KHR_materials_emissive_strength.schema.json")] public sealed class KhrMaterialsEmissiveStrength { public static readonly string ExtensionName = "KHR_materials_emissive_strength"; [JsonField(Name = "emissiveStrength")] [JsonFieldIgnorable(WhenValueIs = 1f)] [JsonSchema(Minimum = 0.0)] public float EmissiveStrength = 1f; } }
UserLibs/VJson.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using VJson.Internal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("yutopp")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2019 -")] [assembly: AssemblyDescription("A JSON serializer/deserializer library written in pure C#.")] [assembly: AssemblyFileVersion("0.0.0.0")] [assembly: AssemblyInformationalVersion("0.0.0")] [assembly: AssemblyProduct("VJson")] [assembly: AssemblyTitle("VJson")] [assembly: AssemblyVersion("0.0.0.0")] namespace VJson { public enum EnumConversionType { AsInt, AsString } public class PreserveAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)] public sealed class JsonAttribute : PreserveAttribute { public bool ImplicitConstructable; public EnumConversionType EnumConversion; } [AttributeUsage(AttributeTargets.Field)] public sealed class JsonFieldAttribute : PreserveAttribute { public string Name; public int Order; public Type[] TypeHints; public static string FieldName(JsonFieldAttribute f, FieldInfo fi) { if (f != null && !string.IsNullOrEmpty(f.Name)) { return f.Name; } return fi.Name; } public static int FieldOrder(JsonFieldAttribute f) { return f?.Order ?? 0; } } [AttributeUsage(AttributeTargets.Field)] public sealed class JsonFieldIgnorableAttribute : PreserveAttribute { public object WhenValueIs; public int WhenLengthIs; public static bool IsIgnorable<T>(JsonFieldIgnorableAttribute f, T o) { if (f == null) { return false; } if (object.Equals(o, f.WhenValueIs)) { return true; } if ((object)o is Array array) { return array.Length == f.WhenLengthIs; } if ((object)o is IList list) { return list.Count == f.WhenLengthIs; } return false; } } public interface IValidator { } public sealed class JsonDeserializer { private Type _expectedInitialType; public JsonDeserializer(Type type) { _expectedInitialType = type; } public object Deserialize(string text) { using MemoryStream s = new MemoryStream(Encoding.UTF8.GetBytes(text)); return Deserialize(s); } public object Deserialize(Stream s) { using JsonReader jsonReader = new JsonReader(s); INode node = jsonReader.Read(); return DeserializeFromNode(node); } public object DeserializeFromNode(INode node) { return DeserializeValue(node, _expectedInitialType, default(State)); } private object DeserializeValue(INode node, Type expectedType, State state) { NodeKindWrapped targetKind = Node.KindOfTypeWrapped(expectedType); if (targetKind.Wrapped) { expectedType = Node.ValueTypeOfKind(targetKind.Kind); } return DeserializeValueAs(node, targetKind, expectedType, state); } private object DeserializeValueAs(INode node, NodeKindWrapped targetKind, Type targetType, State state) { switch (targetKind.Kind) { case NodeKind.Boolean: return DeserializeToBoolean(node, targetKind, targetType, state); case NodeKind.Integer: case NodeKind.Float: return DeserializeToNumber(node, targetKind, targetType, state); case NodeKind.String: return DeserializeToString(node, targetKind, targetType, state); case NodeKind.Array: return DeserializeToArray(node, targetKind, targetType, state); case NodeKind.Object: return DeserializeToObject(node, targetKind, targetType, state); case NodeKind.Null: return DeserializeToNull(node, targetKind, targetType, state); default: throw new NotImplementedException("Unmatched kind: " + targetKind.Kind); } } private object DeserializeToBoolean(INode node, NodeKindWrapped targetKind, Type targetType, State state) { if (node is NullNode) { if (!TypeHelper.IsBoxed(targetType)) { throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } if (!targetKind.Wrapped) { return null; } return NullNode.Null; } if (node is BooleanNode booleanNode) { if (!targetKind.Wrapped) { return CreateInstanceIfConstrucutable(targetType, booleanNode.Value, state); } return node; } throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } private object DeserializeToNumber(INode node, NodeKindWrapped targetKind, Type targetType, State state) { if (node is NullNode) { if (!TypeHelper.IsBoxed(targetType)) { throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } if (!targetKind.Wrapped) { return null; } return NullNode.Null; } if (node is IntegerNode integerNode) { if (!targetKind.Wrapped) { return CreateInstanceIfConstrucutable(targetType, integerNode.Value, state); } return node; } if (node is FloatNode floatNode) { if (!targetKind.Wrapped) { return CreateInstanceIfConstrucutable(targetType, floatNode.Value, state); } return node; } throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } private object DeserializeToString(INode node, NodeKindWrapped targetKind, Type targetType, State state) { if (node is NullNode) { if (!TypeHelper.IsBoxed(targetType)) { throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } if (!targetKind.Wrapped) { return null; } return NullNode.Null; } if (node is StringNode stringNode) { if (!targetKind.Wrapped) { return CreateInstanceIfConstrucutable(targetType, stringNode.Value, state); } return node; } throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } private object DeserializeToArray(INode node, NodeKindWrapped targetKind, Type targetType, State state) { if (!(targetType == typeof(object)) && !targetType.IsArray && (!TypeHelper.TypeWrap(targetType).IsGenericType || !(targetType.GetGenericTypeDefinition() == typeof(List<>)))) { throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } if (node is NullNode) { if (!targetKind.Wrapped) { return null; } return NullNode.Null; } if (node is ArrayNode arrayNode) { if (targetType.IsArray || targetType == typeof(object)) { Type type = targetType; if (type == typeof(object)) { type = typeof(object[]); } int num = ((arrayNode.Elems != null) ? arrayNode.Elems.Count : 0); Array array = (Array)Activator.CreateInstance(type, num); Type elementType = type.GetElementType(); for (int i = 0; i < num; i++) { object value = DeserializeValue(arrayNode.Elems[i], elementType, state.NestAsElem(i)); array.SetValue(value, i); } return array; } int num2 = ((arrayNode.Elems != null) ? arrayNode.Elems.Count : 0); IList list = (IList)Activator.CreateInstance(targetType); Type expectedType = TypeHelper.TypeWrap(targetType).GetGenericArguments()[0]; for (int j = 0; j < num2; j++) { object value2 = DeserializeValue(arrayNode.Elems[j], expectedType, state.NestAsElem(j)); list.Add(value2); } if (targetKind.Wrapped) { return new ArrayNode(list as List<INode>); } return list; } throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } private object DeserializeToObject(INode node, NodeKindWrapped targetKind, Type targetType, State state) { if (targetKind.Kind != 0) { throw new DeserializeFailureException(state.CreateNodeConversionFailureMessage(node, targetType)); } if (node is NullNode) { if (!targetKind.Wrapped) { return null; } return NullNode.Null; } if (node is ObjectNode objectNode) { if (targetType == typeof(object) || (TypeHelper.TypeWrap(targetType).IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<, >))) { Type type = targetType; if (type == typeof(object)) { type = (targetKind.Wrapped ? typeof(Dictionary<string, INode>) : typeof(Dictionary<string, object>)); } if (TypeHelper.TypeWrap(type).GetGenericArguments()[0] != typeof(string)) { throw new NotImplementedException(); } IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); if (objectNode.Elems != null) { Type type2 = TypeHelper.TypeWrap(type).GetGenericArguments()[1]; foreach (KeyValuePair<string, INode> elem in objectNode.Elems) { Type expectedType = type2; object value = DeserializeValue(elem.Value, expectedType, state.NestAsElem(elem.Key)); dictionary.Add(elem.Key, value); } } if (targetKind.Wrapped) { return new ObjectNode(dictionary as Dictionary<string, INode>); } return dictionary; } object obj = Activator.CreateInstance(targetType); { foreach (FieldInfo serializableField in TypeHelper.GetSerializableFields(targetType)) { JsonFieldAttribute customAttribute = TypeHelper.GetCustomAttribute<JsonFieldAttribute>(serializableField); string text = JsonFieldAttribute.FieldName(customAttribute, serializableField); INode value2 = null; if (objectNode.Elems == null || !objectNode.Elems.TryGetValue(text, out value2)) { continue; } State state2 = state.NestAsElem(text); if (customAttribute != null && customAttribute.TypeHints != null) { bool flag = false; Type[] typeHints = customAttribute.TypeHints; foreach (Type expectedType2 in typeHints) { try { object value3 = DeserializeValue(value2, expectedType2, state2); serializableField.SetValue(obj, value3); flag = true; } catch (Exception) { continue; } break; } if (!flag) { throw new DeserializeFailureException(state2.CreateNodeConversionFailureMessage(value2, customAttribute.TypeHints)); } } else { Type fieldType = serializableField.FieldType; object value4 = DeserializeValue(value2, fieldType, state2); serializableField.SetValue(obj, value4); } } return obj; } } NodeKindWrapped nodeKindWrapped = default(NodeKindWrapped); nodeKindWrapped.Kind = node.Kind; nodeKindWrapped.Wrapped = targetKind.Wrapped; NodeKindWrapped targetKind2 = nodeKindWrapped; if (targetKind.Wrapped) { targetType = Node.ValueTypeOfKind(node.Kind); } return DeserializeValueAs(node, targetKind2, targetType, state); } private object DeserializeToNull(INode node, NodeKindWrapped targetKind, Type targetType, State state) { if (node is NullNode) { if (!targetKind.Wrapped) { return null; } return NullNode.Null; } throw new NotImplementedException(); } private static object CreateInstanceIfConstrucutable<T>(Type targetType, T value, State state) { if (targetType == typeof(object)) { return value; } Type underlyingType = Nullable.GetUnderlyingType(targetType); if (underlyingType != null) { targetType = underlyingType; } if (TypeHelper.GetConverter(typeof(T), targetType, out var converter)) { if (converter == null) { return value; } if (converter(value, out var output)) { return output; } throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType)); } if (TypeHelper.TypeWrap(targetType).IsEnum) { switch (TypeHelper.GetCustomAttribute<JsonAttribute>(targetType)?.EnumConversion ?? EnumConversionType.AsInt) { case EnumConversionType.AsInt: { Type underlyingType2 = Enum.GetUnderlyingType(targetType); if (!TypeHelper.GetConverter(typeof(T), underlyingType2, out var converter2)) { throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType)); } object output2; if (converter2 != null) { if (!converter2(value, out output2)) { throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType)); } } else { output2 = value; } if (!Enum.IsDefined(targetType, output2)) { throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType, "Enum value is not defined")); } return Enum.ToObject(targetType, output2); } case EnumConversionType.AsString: { int num = Array.IndexOf(TypeHelper.GetStringEnumNames(targetType), value); if (num == -1) { throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType, "Enum name is not defined")); } return Enum.GetValues(targetType).GetValue(num); } } } JsonAttribute customAttribute = TypeHelper.GetCustomAttribute<JsonAttribute>(targetType); if (customAttribute == null || !customAttribute.ImplicitConstructable) { throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType, "Not implicit constructable")); } ConstructorInfo? constructor = TypeHelper.TypeWrap(targetType).GetConstructor(new Type[1] { typeof(T) }); if (constructor == null) { throw new DeserializeFailureException(state.CreateTypeConversionFailureMessage(value, targetType, "Suitable constructers are not found")); } return constructor.Invoke(new object[1] { value }); } } public class DeserializeFailureException : Exception { public DeserializeFailureException(string message) : base(message) { } public DeserializeFailureException(string message, DeserializeFailureException inner) : base($"{message}.{inner.Message}") { } } public sealed class JsonReader : IDisposable { private class ReaderWrapper : IDisposable { private StreamReader _reader; private int _lastToken; public ulong Position { get; private set; } public string LastToken { get { if (_lastToken == -1) { return "<EOS>"; } return ((char)_lastToken).ToString(); } } public ReaderWrapper(Stream s) { _reader = new StreamReader(s); Position = 0uL; } public void Dispose() { if (_reader != null) { ((IDisposable)_reader).Dispose(); } } public int Peek() { _lastToken = _reader.Peek(); return _lastToken; } public int Read() { ulong position = Position + 1; Position = position; _lastToken = _reader.Read(); return _lastToken; } } private ReaderWrapper _reader; private StringBuilder _strCache = new StringBuilder(); public JsonReader(Stream s) { _reader = new ReaderWrapper(s); } public void Dispose() { if (_reader != null) { ((IDisposable)_reader).Dispose(); } } public INode Read() { INode result = ReadElement(); if (_reader.Peek() != -1) { throw NodeExpectedError("EOS"); } return result; } private INode ReadElement() { SkipWS(); INode result = ReadValue(); SkipWS(); return result; } private INode ReadValue() { INode node = null; if ((node = ReadObject()) != null) { return node; } if ((node = ReadArray()) != null) { return node; } if ((node = ReadString()) != null) { return node; } if ((node = ReadNumber()) != null) { return node; } if ((node = ReadLiteral()) != null) { return node; } throw NodeExpectedError("value"); } private INode ReadObject() { int num = _reader.Peek(); if (num != 123) { return null; } _reader.Read(); ObjectNode objectNode = new ObjectNode(); int num2 = 0; while (true) { SkipWS(); num = _reader.Peek(); if (num == 125) { _reader.Read(); return objectNode; } if (num2 > 0) { if (num != 44) { throw TokenExpectedError(','); } _reader.Read(); } SkipWS(); INode node = ReadString(); if (node == null) { throw NodeExpectedError("string"); } SkipWS(); num = _reader.Peek(); if (num != 58) { throw TokenExpectedError(':'); } _reader.Read(); INode node2 = ReadElement(); if (node2 == null) { break; } objectNode.AddElement(((StringNode)node).Value, node2); num2++; } throw NodeExpectedError("element"); } private INode ReadArray() { int num = _reader.Peek(); if (num != 91) { return null; } _reader.Read(); ArrayNode arrayNode = new ArrayNode(); int num2 = 0; while (true) { SkipWS(); num = _reader.Peek(); if (num == 93) { _reader.Read(); return arrayNode; } if (num2 > 0) { if (num != 44) { throw TokenExpectedError(','); } _reader.Read(); } INode node = ReadElement(); if (node == null) { break; } arrayNode.AddElement(node); num2++; } throw NodeExpectedError("element"); } private INode ReadString() { int num = _reader.Peek(); if (num != 34) { return null; } _reader.Read(); while (true) { num = _reader.Peek(); switch (num) { case 34: _reader.Read(); return new StringNode(Regex.Unescape(CommitBuffer())); case 92: _reader.Read(); if (!ReadEscape()) { throw NodeExpectedError("escape"); } continue; } int num2 = _reader.Read(); int num3 = num2; bool num4 = char.IsHighSurrogate((char)num2); if (num4) { num = _reader.Read(); if (!char.IsLowSurrogate((char)num)) { throw NodeExpectedError("low-surrogate"); } num3 = char.ConvertToUtf32((char)num2, (char)num); } if (num3 < 32 || num3 > 1114111) { throw NodeExpectedError("unicode char (0x20 <= char <= 0x10ffff"); } SaveToBuffer(num2); if (num4) { SaveToBuffer(num); } } } private bool ReadEscape() { switch (_reader.Peek()) { case 34: SaveToBuffer(92); SaveToBuffer(_reader.Read()); return true; case 92: SaveToBuffer(92); SaveToBuffer(_reader.Read()); return true; case 47: SaveToBuffer(_reader.Read()); return true; case 98: SaveToBuffer(92); SaveToBuffer(_reader.Read()); return true; case 110: SaveToBuffer(92); SaveToBuffer(_reader.Read()); return true; case 114: SaveToBuffer(92); SaveToBuffer(_reader.Read()); return true; case 116: SaveToBuffer(92); SaveToBuffer(_reader.Read()); return true; case 117: { SaveToBuffer(92); SaveToBuffer(_reader.Read()); for (int i = 0; i < 4; i++) { if (!ReadHex()) { throw NodeExpectedError("hex"); } } return true; } default: return false; } } private bool ReadHex() { if (ReadDigit()) { return true; } int num = _reader.Peek(); if (num >= 65 && num <= 70) { SaveToBuffer(_reader.Read()); return true; } if (num >= 97 && num <= 102) { SaveToBuffer(_reader.Read()); return true; } return false; } private INode ReadNumber() { if (!ReadInt()) { return null; } int num = 0 | (ReadFrac() ? 1 : 0) | (ReadExp() ? 1 : 0); string s = CommitBuffer(); if (num != 0) { return new FloatNode(double.Parse(s)); } return new IntegerNode(long.Parse(s)); } private bool ReadInt() { if (ReadOneNine()) { ReadDigits(); return true; } if (ReadDigit()) { return true; } if (_reader.Peek() != 45) { return false; } SaveToBuffer(_reader.Read()); if (ReadOneNine()) { ReadDigits(); return true; } if (ReadDigit()) { return true; } throw NodeExpectedError("number"); } private bool ReadDigits() { if (!ReadDigit()) { return false; } while (ReadDigit()) { } return true; } private bool ReadDigit() { if (_reader.Peek() != 48) { return ReadOneNine(); } SaveToBuffer(_reader.Read()); return true; } private bool ReadOneNine() { int num = _reader.Peek(); if (num < 49 || num > 57) { return false; } SaveToBuffer(_reader.Read()); return true; } private bool ReadFrac() { if (_reader.Peek() != 46) { return false; } SaveToBuffer(_reader.Read()); if (!ReadDigits()) { throw NodeExpectedError("digits"); } return true; } private bool ReadExp() { int num = _reader.Peek(); if (num != 69 && num != 101) { return false; } SaveToBuffer(_reader.Read()); ReadSign(); if (!ReadDigits()) { throw NodeExpectedError("digits"); } return true; } private bool ReadSign() { int num = _reader.Peek(); if (num != 43 && num != 45) { return false; } SaveToBuffer(_reader.Read()); return true; } private INode ReadLiteral() { _ = string.Empty; switch (_reader.Peek()) { case 116: if (ConsumeChars(4).ToLower() != "true") { throw NodeExpectedError("true"); } return new BooleanNode(v: true); case 102: if (ConsumeChars(5).ToLower() != "false") { throw NodeExpectedError("false"); } return new BooleanNode(v: false); case 110: if (ConsumeChars(4).ToLower() != "null") { throw NodeExpectedError("null"); } return new NullNode(); default: return null; } } private void SkipWS() { while (true) { int num = _reader.Peek(); if ((uint)(num - 9) <= 1u || num == 13 || num == 32) { _reader.Read(); continue; } break; } } private void SaveToBuffer(int c) { _strCache.Append((char)c); } private string CommitBuffer() { string result = _strCache.ToString(); _strCache.Length = 0; return result; } private string ConsumeChars(int length) { for (int i = 0; i < length; i++) { int c = _reader.Read(); SaveToBuffer(c); } return CommitBuffer(); } private ParseFailedException NodeExpectedError(string expected) { return new ParseFailedException($"A node \"{expected}\" is expected but '{_reader.LastToken}' is provided", _reader.Position); } private ParseFailedException TokenExpectedError(char expected) { return new ParseFailedException($"A charactor '{expected}' is expected but '{_reader.LastToken}' is provided", _reader.Position); } } public class ParseFailedException : Exception { public ParseFailedException(string message, ulong pos) : base($"{message} (at position {pos})") { } } public sealed class JsonSerializer { private Type _type; public JsonSerializer(Type type) { _type = type; } public void Serialize<T>(Stream s, T o, int indent = 0) { using JsonWriter writer = new JsonWriter(s, indent); SerializeValue(writer, o); } public string Serialize<T>(T o, int indent = 0) { using MemoryStream memoryStream = new MemoryStream(); Serialize(memoryStream, o, indent); return Encoding.UTF8.GetString(memoryStream.ToArray()); } public INode SerializeToNode<T>(T o) { byte[] buffer = null; using (MemoryStream memoryStream = new MemoryStream()) { Serialize(memoryStream, o); buffer = memoryStream.ToArray(); } using MemoryStream s = new MemoryStream(buffer); return new JsonDeserializer(typeof(INode)).Deserialize(s) as INode; } private void SerializeValue<T>(JsonWriter writer, T o) { if (o is INode) { SerializeValue(writer, (o as INode).GenericContent); return; } switch (Node.KindOfValue(o)) { case NodeKind.String: case NodeKind.Integer: case NodeKind.Float: case NodeKind.Boolean: SerializePrimitive(writer, o); break; case NodeKind.Array: SerializeArray(writer, o); break; case NodeKind.Object: SerializeObject(writer, o); break; case NodeKind.Null: SerializeNull(writer, o); break; } } private void SerializePrimitive<T>(JsonWriter writer, T o) { if (TypeHelper.TypeWrap(o.GetType()).IsEnum) { switch (TypeHelper.GetCustomAttribute<JsonAttribute>(o.GetType())?.EnumConversion ?? EnumConversionType.AsInt) { case EnumConversionType.AsInt: SerializeValue(writer, Convert.ChangeType(o, Enum.GetUnderlyingType(o.GetType()))); break; case EnumConversionType.AsString: SerializeValue(writer, TypeHelper.GetStringEnumNameOf(o)); break; } } else { TypeHelper.TypeWrap(typeof(JsonWriter)).GetMethod("WriteValue", new Type[1] { o.GetType() }).Invoke(writer, new object[1] { o }); } } private void SerializeArray<T>(JsonWriter writer, T o) { writer.WriteArrayStart(); foreach (object item in TypeHelper.ToIEnumerable(o)) { SerializeValue(writer, item); } writer.WriteArrayEnd(); } private void SerializeObject<T>(JsonWriter writer, T o) { writer.WriteObjectStart(); foreach (KeyValuePair<string, object> item in TypeHelper.ToKeyValues(o)) { writer.WriteObjectKey(item.Key); SerializeValue(writer, item.Value); } writer.WriteObjectEnd(); } private void SerializeNull<T>(JsonWriter writer, T o) { writer.WriteValueNull(); } public object Deserialize(string text) { return new JsonDeserializer(_type).Deserialize(text); } public object Deserialize(Stream s) { return new JsonDeserializer(_type).Deserialize(s); } } public sealed class JsonWriter : IDisposable { private struct State { public StateKind Kind; public int Depth; } private enum StateKind { ObjectKeyHead, ObjectKeyOther, ObjectValue, ArrayHead, ArrayOther, None } private StreamWriter _writer; private int _indent; private string _indentStr; private Stack<State> _states = new Stack<State>(); public JsonWriter(Stream s, int indent = 0) { _writer = new StreamWriter(s); _indent = indent; if (_indent > 0) { _indentStr = new string(' ', _indent); } _states.Push(new State { Kind = StateKind.None, Depth = 0 }); } public void Dispose() { if (_writer != null) { ((IDisposable)_writer).Dispose(); } } public void WriteObjectStart() { State state = _states.Peek(); if (state.Kind == StateKind.ObjectKeyHead || state.Kind == StateKind.ObjectKeyOther) { throw new Exception(""); } WriteDelimiter(); _writer.Write("{"); _states.Push(new State { Kind = StateKind.ObjectKeyHead, Depth = state.Depth + 1 }); } public void WriteObjectKey(string key) { State state = _states.Peek(); if (state.Kind != 0 && state.Kind != StateKind.ObjectKeyOther) { throw new Exception(""); } WriteValue(key); _writer.Write(":"); _states.Pop(); _states.Push(new State { Kind = StateKind.ObjectValue, Depth = state.Depth }); } public void WriteObjectEnd() { State state = _states.Peek(); if (state.Kind != 0 && state.Kind != StateKind.ObjectKeyOther) { throw new Exception(""); } _states.Pop(); if (state.Kind == StateKind.ObjectKeyOther) { WriteIndentBreakForHuman(_states.Peek().Depth); } _writer.Write("}"); } public void WriteArrayStart() { State state = _states.Peek(); if (state.Kind == StateKind.ObjectKeyHead || state.Kind == StateKind.ObjectKeyOther) { throw new Exception(""); } WriteDelimiter(); _writer.Write("["); _states.Push(new State { Kind = StateKind.ArrayHead, Depth = state.Depth + 1 }); } public void WriteArrayEnd() { State state = _states.Peek(); if (state.Kind != StateKind.ArrayHead && state.Kind != StateKind.ArrayOther) { throw new Exception(""); } _states.Pop(); if (state.Kind == StateKind.ArrayOther) { WriteIndentBreakForHuman(_states.Peek().Depth); } _writer.Write("]"); } public void WriteValue(bool v) { WriteDelimiter(); _writer.Write(v ? "true" : "false"); } public void WriteValue(byte v) { WritePrimitive(v); } public void WriteValue(sbyte v) { WritePrimitive(v); } public void WriteValue(char v) { WritePrimitive(v); } public void WriteValue(decimal v) { WritePrimitive(v); } public void WriteValue(double v) { WritePrimitive(v); } public void WriteValue(float v) { WritePrimitive(v); } public void WriteValue(int v) { WritePrimitive(v); } public void WriteValue(uint v) { WritePrimitive(v); } public void WriteValue(long v) { WritePrimitive(v); } public void WriteValue(ulong v) { WritePrimitive(v); } public void WriteValue(short v) { WritePrimitive(v); } public void WriteValue(ushort v) { WritePrimitive(v); } public void WriteValue(string v) { WriteDelimiter(); _writer.Write('"'); _writer.Write(Escape(v).ToArray()); _writer.Write('"'); } public void WriteValueNull() { WriteDelimiter(); _writer.Write("null"); } private void WritePrimitive(char v) { WritePrimitive((int)v); } private void WritePrimitive(float v) { WritePrimitive($"{v:G9}"); } private void WritePrimitive(double v) { WritePrimitive($"{v:G17}"); } private void WritePrimitive<T>(T v) { WriteDelimiter(); _writer.Write(v); } private void WriteIndentBreakForHuman(int depth) { if (_indent > 0) { _writer.Write('\n'); for (int i = 0; i < depth; i++) { _writer.Write(_indentStr); } } } private void WriteSpaceForHuman() { if (_indent > 0) { _writer.Write(' '); } } private void WriteDelimiter() { State state = _states.Peek(); if (state.Kind == StateKind.ArrayHead) { WriteIndentBreakForHuman(state.Depth); _states.Pop(); _states.Push(new State { Kind = StateKind.ArrayOther, Depth = state.Depth }); return; } if (state.Kind == StateKind.ObjectKeyHead) { WriteIndentBreakForHuman(state.Depth); } if (state.Kind == StateKind.ArrayOther || state.Kind == StateKind.ObjectKeyOther) { _writer.Write(","); WriteIndentBreakForHuman(state.Depth); } if (state.Kind == StateKind.ObjectValue) { WriteSpaceForHuman(); _states.Pop(); _states.Push(new State { Kind = StateKind.ObjectKeyOther, Depth = state.Depth }); } } private IEnumerable<char> Escape(string s) { foreach (char c in s) { char modified = '\0'; if (c <= ' ' || c == '"' || c == '\\') { switch (c) { case '"': modified = '"'; break; case '\\': modified = '\\'; break; case '\b': modified = 'b'; break; case '\n': modified = 'n'; break; case '\r': modified = 'r'; break; case '\t': modified = 't'; break; } } if (modified != 0) { yield return '\\'; yield return modified; } else { yield return c; } } } } public enum NodeKind { Object, Array, String, Integer, Float, Boolean, Null, Undefined } public struct NodeKindWrapped { public NodeKind Kind; public bool Wrapped; } public interface INode { NodeKind Kind { get; } INode this[int index] { get; } INode this[string key] { get; } object GenericContent { get; } } public sealed class BooleanNode : INode { public static NodeKind KIND = NodeKind.Boolean; public static Type TYPE = typeof(bool); public NodeKind Kind => KIND; public INode this[int index] => UndefinedNode.Undef; public INode this[string key] => UndefinedNode.Undef; public bool Value { get; private set; } public object GenericContent => Value; public BooleanNode(bool v) { Value = v; } public override bool Equals(object rhsObj) { if (!(rhsObj is BooleanNode booleanNode)) { return false; } return Value.Equals(booleanNode.Value); } public override int GetHashCode() { return Value.GetHashCode(); } public override string ToString() { return "BOOLEAN: " + Value; } } public sealed class NullNode : INode { public static NodeKind KIND = NodeKind.Null; public static Type TYPE = typeof(object); public static readonly INode Null = new NullNode(); public NodeKind Kind => KIND; public INode this[int index] => UndefinedNode.Undef; public INode this[string key] => UndefinedNode.Undef; public object GenericContent => null; public override bool Equals(object rhsObj) { if (!(rhsObj is NullNode)) { return false; } return true; } public override int GetHashCode() { return 0; } public override string ToString() { return "NULL"; } } public sealed class UndefinedNode : INode { public static NodeKind KIND = NodeKind.Undefined; public static Type TYPE = typeof(object); public static readonly INode Undef = new UndefinedNode(); public NodeKind Kind => KIND; public INode this[int index] => Undef; public INode this[string key] => Undef; public object GenericContent => null; public override bool Equals(object rhsObj) { if (!(rhsObj is UndefinedNode)) { return false; } return true; } public override int GetHashCode() { return 0; } public override string ToString() { return "UNDEFINED"; } } public sealed class IntegerNode : INode { public static NodeKind KIND = NodeKind.Integer; public static Type TYPE = typeof(long); public NodeKind Kind => KIND; public INode this[int index] => UndefinedNode.Undef; public INode this[string key] => UndefinedNode.Undef; public long Value { get; private set; } public object GenericContent => Value; public IntegerNode(long v) { Value = v; } public override bool Equals(object rhsObj) { if (!(rhsObj is IntegerNode integerNode)) { return false; } return Value.Equals(integerNode.Value); } public override int GetHashCode() { return Value.GetHashCode(); } public override string ToString() { return "NUMBER(Int): " + Value; } } public sealed class FloatNode : INode { public static NodeKind KIND = NodeKind.Float; public static Type TYPE = typeof(double); public NodeKind Kind => KIND; public INode this[int index] => UndefinedNode.Undef; public INode this[string key] => UndefinedNode.Undef; public double Value { get; private set; } public object GenericContent => Value; public FloatNode(double v) { Value = v; } public override bool Equals(object rhsObj) { if (!(rhsObj is FloatNode floatNode)) { return false; } return Value.Equals(floatNode.Value); } public override int GetHashCode() { return Value.GetHashCode(); } public override string ToString() { return "NUMBER(Float): " + Value; } } public sealed class StringNode : INode { public static NodeKind KIND = NodeKind.String; public static Type TYPE = typeof(string); public NodeKind Kind => KIND; public INode this[int index] => UndefinedNode.Undef; public INode this[string key] => UndefinedNode.Undef; public string Value { get; private set; } public object GenericContent => Value; public StringNode(string v) { Value = v; } public override bool Equals(object rhsObj) { if (!(rhsObj is StringNode stringNode)) { return false; } return Value.Equals(stringNode.Value); } public override int GetHashCode() { return Value.GetHashCode(); } public override string ToString() { return "STRING: " + Value; } } public sealed class ObjectNode : INode, IEnumerable<KeyValuePair<string, INode>>, IEnumerable { public static NodeKind KIND = NodeKind.Object; public static Type TYPE = typeof(Dictionary<string, INode>); public Dictionary<string, INode> Elems; public NodeKind Kind => KIND; public INode this[int index] => UndefinedNode.Undef; public INode this[string key] { get { INode value = null; if (Elems != null) { Elems.TryGetValue(key, out value); } if (value == null) { return UndefinedNode.Undef; } return value; } } public object GenericContent { get { if (Elems == null) { return new Dictionary<string, INode>(); } return Elems; } } public ObjectNode() { } public ObjectNode(Dictionary<string, INode> v) { Elems = v; } public void AddElement(string key, INode elem) { if (Elems == null) { Elems = new Dictionary<string, INode>(); } Elems.Add(key, elem); } public void RemoveElement(string key) { if (Elems != null) { Elems.Remove(key); } } public IEnumerator<KeyValuePair<string, INode>> GetEnumerator() { if (Elems != null) { return Elems.OrderBy((KeyValuePair<string, INode> p) => p.Key).GetEnumerator(); } return Enumerable.Empty<KeyValuePair<string, INode>>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override bool Equals(object rhsObj) { if (!(rhsObj is ObjectNode objectNode)) { return false; } if (Elems == null) { return objectNode.Elems == null; } return Elems.OrderBy((KeyValuePair<string, INode> p) => p.Key).SequenceEqual(objectNode.Elems.OrderBy((KeyValuePair<string, INode> p) => p.Key)); } public override int GetHashCode() { if (Elems == null) { return 0; } return Elems.GetHashCode(); } public override string ToString() { if (Elems == null) { return "OBJECT: {}"; } return "OBJECT: " + string.Join("; ", (from p in Elems orderby p.Key select p.Key + " = " + p.Value).ToArray()); } } public sealed class ArrayNode : INode, IEnumerable<INode>, IEnumerable { public static NodeKind KIND = NodeKind.Array; public static Type TYPE = typeof(List<INode>); public List<INode> Elems; public NodeKind Kind => KIND; public INode this[int index] { get { INode node = ((Elems != null) ? Elems.ElementAtOrDefault(index) : null); if (node == null) { return UndefinedNode.Undef; } return node; } } public INode this[string key] => UndefinedNode.Undef; public object GenericContent { get { if (Elems == null) { return new List<INode>(); } return Elems; } } public ArrayNode() { } public ArrayNode(List<INode> v) { Elems = v; } public void AddElement(INode elem) { if (Elems == null) { Elems = new List<INode>(); } Elems.Add(elem); } public void RemoveElementAt(int index) { if (Elems != null && index >= 0 && index < Elems.Count) { Elems.RemoveAt(index); } } public IEnumerator<INode> GetEnumerator() { if (Elems != null) { return Elems.GetEnumerator(); } return Enumerable.Empty<INode>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override bool Equals(object rhsObj) { if (!(rhsObj is ArrayNode arrayNode)) { return false; } if (Elems == null) { return arrayNode.Elems == null; } return Elems.SequenceEqual(arrayNode.Elems); } public override int GetHashCode() { if (Elems == null) { return 0; } return Elems.GetHashCode(); } public override string ToString() { if (Elems == null) { return "ARRAY: []"; } return "ARRAY: " + string.Join("; ", Elems.Select((INode e) => e.ToString()).ToArray()); } } public static class Node { private static Dictionary<Type, NodeKind> _primitiveTable = new Dictionary<Type, NodeKind> { { typeof(bool), NodeKind.Boolean }, { typeof(byte), NodeKind.Integer }, { typeof(sbyte), NodeKind.Integer }, { typeof(char), NodeKind.Integer }, { typeof(decimal), NodeKind.Integer }, { typeof(double), NodeKind.Float }, { typeof(float), NodeKind.Float }, { typeof(int), NodeKind.Integer }, { typeof(uint), NodeKind.Integer }, { typeof(long), NodeKind.Integer }, { typeof(ulong), NodeKind.Integer }, { typeof(short), NodeKind.Integer }, { typeof(ushort), NodeKind.Integer }, { typeof(string), NodeKind.String } }; private static Dictionary<Type, NodeKind> _nodeKindTable = new Dictionary<Type, NodeKind> { { typeof(INode), ObjectNode.KIND }, { typeof(BooleanNode), BooleanNode.KIND }, { typeof(NullNode), NullNode.KIND }, { typeof(UndefinedNode), UndefinedNode.KIND }, { typeof(IntegerNode), IntegerNode.KIND }, { typeof(FloatNode), FloatNode.KIND }, { typeof(StringNode), StringNode.KIND }, { typeof(ObjectNode), ObjectNode.KIND }, { typeof(ArrayNode), ArrayNode.KIND } }; private static Dictionary<NodeKind, Type> _nodeTypeTable = new Dictionary<NodeKind, Type> { { BooleanNode.KIND, BooleanNode.TYPE }, { NullNode.KIND, NullNode.TYPE }, { UndefinedNode.KIND, UndefinedNode.TYPE }, { IntegerNode.KIND, IntegerNode.TYPE }, { FloatNode.KIND, FloatNode.TYPE }, { StringNode.KIND, StringNode.TYPE }, { ObjectNode.KIND, ObjectNode.TYPE }, { ArrayNode.KIND, ArrayNode.TYPE } }; public static NodeKind KindOfValue<T>(T o) { if (o == null) { return NodeKind.Null; } return KindOfType(o.GetType()); } public static NodeKindWrapped KindOfTypeWrapped(Type ty) { NodeKindWrapped result; if (TypeHelper.TypeWrap(typeof(INode)).IsAssignableFrom(ty)) { result = default(NodeKindWrapped); result.Kind = _nodeKindTable[ty]; result.Wrapped = true; return result; } result = default(NodeKindWrapped); result.Kind = KindOfType(ty); result.Wrapped = false; return result; } public static NodeKind KindOfType(Type ty) { if (TypeHelper.TypeWrap(ty).IsGenericType && ty.GetGenericTypeDefinition() == typeof(Nullable<>)) { return KindOfType(TypeHelper.TypeWrap(ty).GetGenericArguments()[0]); } if (_primitiveTable.TryGetValue(ty, out var value)) { return value; } if (TypeHelper.TypeWrap(ty).IsEnum) { JsonAttribute customAttribute = TypeHelper.GetCustomAttribute<JsonAttribute>(ty); if (customAttribute == null || customAttribute.EnumConversion != EnumConversionType.AsString) { return NodeKind.Integer; } return NodeKind.String; } if (TypeHelper.ElemTypeOfIEnumerable(ty) != null) { return NodeKind.Array; } return NodeKind.Object; } public static Type ValueTypeOfKind(NodeKind kind) { return _nodeTypeTable[kind]; } } internal static class TypeHelper { private struct RankedKey { public int Order; public string Key; } private class RankedKeyValueComparer : IComparer<KeyValuePair<RankedKey, object>> { public int Compare(KeyValuePair<RankedKey, object> a, KeyValuePair<RankedKey, object> b) { throw new NotImplementedException(); } int IComparer<KeyValuePair<RankedKey, object>>.Compare(KeyValuePair<RankedKey, object> a, KeyValuePair<RankedKey, object> b) { if (a.Key.Order != b.Key.Order) { return a.Key.Order - b.Key.Order; } return string.Compare(a.Key.Key, b.Key.Key); } } private class DeepEqualityComparer : EqualityComparer<object> { public override bool Equals(object a, object b) { return DeepEquals(a, b); } public override int GetHashCode(object a) { return a.GetHashCode(); } } public delegate bool Converter(object input, out object output); private static readonly Dictionary<Type, Dictionary<Type, Converter>> _convTable = new Dictionary<Type, Dictionary<Type, Converter>> { { typeof(bool), new Dictionary<Type, Converter> { { typeof(bool), null } } }, { typeof(double), new Dictionary<Type, Converter> { { typeof(decimal), delegate(object i, out object o) { return ConvertFromDoubleToDecimal((double)i, out o); } }, { typeof(double), null }, { typeof(float), delegate(object i, out object o) { return ConvertFromDoubleToFloat((double)i, out o); } } } }, { typeof(long), new Dictionary<Type, Converter> { { typeof(byte), delegate(object i, out object o) { return ConvertFromLongToByte((long)i, out o); } }, { typeof(sbyte), delegate(object i, out object o) { return ConvertFromLongToSbyte((long)i, out o); } }, { typeof(char), delegate(object i, out object o) { return ConvertFromLongToChar((long)i, out o); } }, { typeof(decimal), delegate(object i, out object o) { return ConvertFromLongToDecimal((long)i, out o); } }, { typeof(double), delegate(object i, out object o) { return ConvertFromLongToDouble((long)i, out o); } }, { typeof(float), delegate(object i, out object o) { return ConvertFromLongToFloat((long)i, out o); } }, { typeof(int), delegate(object i, out object o) { return ConvertFromLongToInt((long)i, out o); } }, { typeof(uint), delegate(object i, out object o) { return ConvertFromLongToUint((long)i, out o); } }, { typeof(long), null }, { typeof(ulong), delegate(object i, out object o) { return ConvertFromLongToUlong((long)i, out o); } }, { typeof(short), delegate(object i, out object o) { return ConvertFromLongToShort((long)i, out o); } }, { typeof(ushort), delegate(object i, out object o) { return ConvertFromLongToUshort((long)i, out o); } } } }, { typeof(string), new Dictionary<Type, Converter> { { typeof(string), null } } } }; public static TypeInfo TypeWrap(Type ty) { return ty.GetTypeInfo(); } public static bool IsBoxed(Type ty) { TypeInfo typeInfo = TypeWrap(ty); if (typeInfo.IsClass) { return true; } if (typeInfo.IsGenericType) { return ty.GetGenericTypeDefinition() == typeof(Nullable<>); } return false; } public static T GetCustomAttribute<T>(FieldInfo fi) where T : Attribute { return (T)(from a in fi.GetCustomAttributes(typeof(T), inherit: false) where a.GetType() == typeof(T) select a).FirstOrDefault(); } public static T GetCustomAttribute<T>(Type ty) where T : Attribute { return (T)(from a in TypeWrap(ty).GetCustomAttributes(typeof(T), inherit: false) where a.GetType() == typeof(T) select a).FirstOrDefault(); } public static string[] GetStringEnumNames(Type ty) { return TypeWrap(ty).GetFields(BindingFlags.Static | BindingFlags.Public).Select(delegate(FieldInfo fi) { JsonFieldAttribute customAttribute = GetCustomAttribute<JsonFieldAttribute>(fi); return (customAttribute != null && customAttribute.Name != null) ? customAttribute.Name : fi.Name; }).ToArray(); } public static string GetStringEnumNameOf(object e) { Type type = e.GetType(); int num = Array.IndexOf(Enum.GetValues(type), e); return GetStringEnumNames(type)[num]; } public static IEnumerable<object> ToIEnumerable(object o) { Type type = o.GetType(); if (type.IsArray) { if (type.HasElementType && TypeWrap(type.GetElementType()).IsClass) { return (IEnumerable<object>)o; } return ((IEnumerable)o).Cast<object>(); } return ((IEnumerable)o).Cast<object>(); } public static Type ElemTypeOfIEnumerable(Type ty) { if (ty.IsArray) { if (ty.HasElementType) { return ty.GetElementType(); } return null; } if (TypeWrap(ty).IsGenericType && ty.GetGenericTypeDefinition() == typeof(List<>)) { return TypeWrap(ty).GetGenericArguments()[0]; } return null; } public static IEnumerable<KeyValuePair<string, object>> ToKeyValues(object o) { List<KeyValuePair<RankedKey, object>> list = ToRankedKeyValuesUnordered(o).ToList(); list.Sort(new RankedKeyValueComparer()); return list.Select((KeyValuePair<RankedKey, object> v) => new KeyValuePair<string, object>(v.Key.Key, v.Value)); } public static IEnumerable<FieldInfo> GetSerializableFields(Type ty) { TypeInfo typeInfo = TypeWrap(ty); FieldInfo[] fields = typeInfo.GetFields(BindingFlags.Instance | BindingFlags.Public); IEnumerable<FieldInfo> second = from field in typeInfo.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) where GetCustomAttribute<JsonFieldAttribute>(field) != null select field; return fields.Concat(second); } private static IEnumerable<KeyValuePair<RankedKey, object>> ToRankedKeyValuesUnordered(object o) { Type type = o.GetType(); if (TypeWrap(type).IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { if (TypeWrap(type).GetGenericArguments()[0] != typeof(string)) { throw new NotImplementedException(); } foreach (DictionaryEntry item in (IDictionary)o) { yield return new KeyValuePair<RankedKey, object>(new RankedKey { Order = 0, Key = (string)item.Key }, item.Value); } yield break; } IEnumerable<FieldInfo> serializableFields = GetSerializableFields(type); foreach (FieldInfo item2 in serializableFields) { JsonFieldAttribute customAttribute = GetCustomAttribute<JsonFieldAttribute>(item2); string key = JsonFieldAttribute.FieldName(customAttribute, item2); object value = item2.GetValue(o); if (!JsonFieldIgnorableAttribute.IsIgnorable(GetCustomAttribute<JsonFieldIgnorableAttribute>(item2), value)) { yield return new KeyValuePair<RankedKey, object>(new RankedKey { Order = JsonFieldAttribute.FieldOrder(customAttribute), Key = key }, value); } } } public static bool DeepEquals(object lhs, object rhs) { NodeKind nodeKind = Node.KindOfValue(lhs); NodeKind nodeKind2 = Node.KindOfValue(rhs); if (nodeKind != nodeKind2) { return false; } switch (nodeKind) { case NodeKind.String: case NodeKind.Integer: case NodeKind.Float: case NodeKind.Boolean: return object.Equals(lhs, rhs); case NodeKind.Array: { IEnumerable<object> first = ToIEnumerable(lhs); IEnumerable<object> second = ToIEnumerable(rhs); return first.SequenceEqual(second, new DeepEqualityComparer()); } case NodeKind.Object: { Dictionary<string, object> dictionary = new Dictionary<string, object>(); foreach (KeyValuePair<string, object> item in ToKeyValues(lhs)) { dictionary.Add(item.Key, item.Value); } Dictionary<string, object> rhsKvs = new Dictionary<string, object>(); foreach (KeyValuePair<string, object> item2 in ToKeyValues(rhs)) { rhsKvs.Add(item2.Key, item2.Value); } if (!dictionary.Keys.SequenceEqual(rhsKvs.Keys)) { return false; } return dictionary.All((KeyValuePair<string, object> kv) => DeepEquals(kv.Value, rhsKvs[kv.Key])); } case NodeKind.Null: return true; default: throw new NotImplementedException(); } } private static bool ConvertFromDoubleToDecimal(double i, out object o) { try { o = (decimal)i; return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromDoubleToFloat(double i, out object o) { try { o = (float)i; return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToByte(long i, out object o) { try { if (i < 0) { throw new OverflowException(); } o = checked((byte)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToSbyte(long i, out object o) { try { o = checked((sbyte)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToChar(long i, out object o) { try { if (i < 0) { throw new OverflowException(); } o = (char)checked((ushort)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToDecimal(long i, out object o) { try { o = (decimal)i; return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToDouble(long i, out object o) { try { o = (double)i; return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToFloat(long i, out object o) { try { o = (float)i; return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToInt(long i, out object o) { try { o = checked((int)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToUint(long i, out object o) { try { if (i < 0) { throw new OverflowException(); } o = checked((uint)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToUlong(long i, out object o) { try { if (i < 0) { throw new OverflowException(); } o = checked((ulong)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToShort(long i, out object o) { try { o = checked((short)i); return true; } catch (OverflowException) { o = null; return false; } } private static bool ConvertFromLongToUshort(long i, out object o) { try { if (i < 0) { throw new OverflowException(); } o = checked((ushort)i); return true; } catch (OverflowException) { o = null; return false; } } public static bool GetConverter(Type fromTy, Type toTy, out Converter converter) { if (!_convTable.TryGetValue(fromTy, out var value)) { converter = null; return false; } return value.TryGetValue(toTy, out converter); } } } namespace VJson.Schema { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, Inherited = false)] public class JsonSchemaAttribute : PreserveAttribute { public string Schema; public string Id; public string Ref; public string Title; public string Description; public double MultipleOf = double.MinValue; public double Maximum = double.MinValue; public double ExclusiveMaximum = double.MinValue; public double Minimum = double.MaxValue; public double ExclusiveMinimum = double.MaxValue; public int MaxLength = int.MinValue; public int MinLength = int.MaxValue; public string Pattern; public int MaxItems = int.MinValue; public int MinItems = int.MaxValue; public bool UniqueItems; public int MaxProperties = int.MinValue; public int MinProperties = int.MaxValue; public string[] Required; } [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class ItemsJsonSchemaAttribute : JsonSchemaAttribute { } [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class JsonSchemaRequiredAttribute : PreserveAttribute { } [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class JsonSchemaDependenciesAttribute : PreserveAttribute { public string[] Dependencies { get; private set; } public JsonSchemaDependenciesAttribute(params string[] deps) { Dependencies = deps; } } public enum InfluenceRange { Entiry, AdditionalProperties } [AttributeUsage(AttributeTargets.Field, Inherited = false)] public class JsonSchemaRefAttribute : PreserveAttribute { public Type TagType { get; private set; } public InfluenceRange Influence { get; private set; } public JsonSchemaRefAttribute(Type tagType, InfluenceRange influence = InfluenceRange.Entiry) { if (!RefChecker.IsRefTagDerived(tagType, out var _)) { throw new ArgumentException("IRefTag<T> must be derived by tagType"); } TagType = tagType; Influence = influence; } } [AttributeUsage(AttributeTargets.Field, Inherited = false)] public sealed class ItemsJsonSchemaRefAttribute : JsonSchemaRefAttribute { public ItemsJsonSchemaRefAttribute(Type tagType, InfluenceRange influence = InfluenceRange.Entiry) : base(tagType, influence) { } } [Json(ImplicitConstructable = true)] public sealed class JsonSchema { [JsonField(Name = "$schema", Order = -10)] [JsonFieldIgnorable] public string Schema; [JsonField(Name = "$id", Order = -11)] [JsonFieldIgnorable] public string Id; [JsonField(Name = "$ref", Order = -12)] [JsonFieldIgnorable] public string Ref; [JsonField(Name = "title", Order = 0)] [JsonFieldIgnorable] public string Title; [JsonField(Name = "description", Order = 1)] [JsonFieldIgnorable] public string Description; [JsonField(Name = "type", TypeHints = new Type[] { typeof(string), typeof(string[]) }, Order = 10)] [JsonFieldIgnorable] public object Type; [JsonField(Name = "enum", Order = 11)] [JsonFieldIgnorable] public object[] Enum; [JsonField(Name = "const", Order = 12)] [JsonFieldIgnorable] public object Const; [JsonField(Name = "multipleOf", Order = 20)] [JsonFieldIgnorable(WhenValueIs = double.MinValue)] public double MultipleOf = double.MinValue; [JsonField(Name = "maximum", Order = 21)] [JsonFieldIgnorable(WhenValueIs = double.MinValue)] public double Maximum = double.MinValue; [JsonField(Name = "exclusiveMaximum", Order = 22)] [JsonFieldIgnorable(WhenValueIs = double.MinValue)] public double ExclusiveMaximum = double.MinValue; [JsonField(Name = "minimum", Order = 23)] [JsonFieldIgnorable(WhenValueIs = double.MaxValue)] public double Minimum = double.MaxValue; [JsonField(Name = "exclusiveMinimum", Order = 24)] [JsonFieldIgnorable(WhenValueIs = double.MaxValue)] public double ExclusiveMinimum = double.MaxValue; [JsonField(Name = "maxLength", Order = 30)] [JsonFieldIgnorable(WhenValueIs = int.MinValue)] public int MaxLength = int.MinValue; [JsonField(Name = "minLength", Order = 31)] [JsonFieldIgnorable(WhenValueIs = int.MaxValue)] public int MinLength = int.MaxValue; [JsonField(Name = "pattern", Order = 32)] [JsonFieldIgnorable] public string Pattern; [JsonField(Name = "items", TypeHints = new Type[] { typeof(JsonSchema), typeof(JsonSchema[]) }, Order = 40)] [JsonFieldIgnorable] private object items; [JsonField(Name = "additionalItems", Order = 41)] [JsonFieldIgnorable] public JsonSchema AdditionalItems; [JsonField(Name = "maxItems", Order = 42)] [JsonFieldIgnorable(WhenValueIs = int.MinValue)] public int MaxItems = int.MinValue; [JsonField(Name = "minItems", Order = 43)] [JsonFieldIgnorable(WhenValueIs = int.MaxValue)] public int MinItems = int.MaxValue; [JsonField(Name = "uniqueItems", Order = 44)] [JsonFieldIgnorable(WhenValueIs = false)] public bool UniqueItems; [JsonField(Name = "maxProperties", Order = 50)] [JsonFieldIgnorable(WhenValueIs = int.MinValue)] public int MaxProperties = int.MinValue; [JsonField(Name = "minProperties", Order = 51)] [JsonFieldIgnorable(WhenValueIs = int.MaxValue)] public int MinProperties = int.MaxValue; [JsonField(Name = "required", Order = 52)] [JsonFieldIgnorable] public string[] Required; [JsonField(Name = "properties", Order = 53)] [JsonFieldIgnorable] public Dictionary<string, JsonSchema> Properties; [JsonField(Name = "patternProperties", Order = 54)] [JsonFieldIgnorable] public Dictionary<string, JsonSchema> PatternProperties; [JsonField(Name = "additionalProperties", Order = 55)] [JsonFieldIgnorable] public JsonSchema AdditionalProperties; [JsonField(Name = "dependencies", TypeHints = new Type[] { typeof(Dictionary<string, string[]>), typeof(Dictionary<string, JsonSchema>) }, Order = 56)] [JsonFieldIgnorable] public object Dependencies; [JsonField(Name = "allOf", Order = 70)] [JsonFieldIgnorable] public List<JsonSchema> AllOf; [JsonField(Name = "anyOf", Order = 71)] [JsonFieldIgnorable] public List<JsonSchema> AnyOf; [JsonField(Name = "oneOf", Order = 72)] [JsonFieldIgnorable] public List<JsonSchema> OneOf; [JsonField(Name = "not", Order = 73)] [JsonFieldIgnorable] public JsonSchema Not; public object Items => items; public JsonSchema TypedItems { set { items = value; } } private bool EqualsOnlyAny(JsonSchema rhs) { if (EqualsSingletonOrArray<string>(Type, rhs.Type) && EqualsEnumerable(Enum, rhs.Enum)) { return object.Equals(Const, rhs.Const); } return false; } private bool EqualsOnlyNum(JsonSchema rhs) { if (MultipleOf == rhs.MultipleOf && Maximum == rhs.Maximum && ExclusiveMaximum == rhs.ExclusiveMaximum && Minimum == rhs.Minimum) { return ExclusiveMinimum == rhs.ExclusiveMinimum; } return false; } private bool EqualsOnlyString(JsonSchema rhs) { if (MaxLength == rhs.MaxLength && MinLength == rhs.MinLength) { return object.Equals(Pattern, rhs.Pattern); } return false; } private bool EqualsOnlyArray(JsonSchema rhs) { if (EqualsSingletonOrArray<JsonSchema>(Items, rhs.Items) && object.Equals(AdditionalItems, rhs.AdditionalItems) && MaxItems == rhs.MaxItems && MinItems == rhs.MinItems) { return UniqueItems == rhs.UniqueItems; } return false; } private bool EqualsOnlyObject(JsonSchema rhs) { return true; } private void AddToAllOf(JsonSchema s) { if (AllOf == null) { AllOf = new List<JsonSchema>(); } AllOf.Add(s); } private void AddToAnyOf(JsonSchema s) { if (AnyOf == null) { AnyOf = new List<JsonSchema>(); } AnyOf.Add(s); } private void AddToOneOf(JsonSchema s) { if (OneOf == null) { OneOf = new List<JsonSchema>(); } OneOf.Add(s); } private bool EqualsOnlySubBool(JsonSchema rhs) { if (EqualsEnumerable(AllOf, rhs.AllOf) && EqualsEnumerable(AnyOf, rhs.AnyOf) && EqualsEnumerable(OneOf, rhs.OneOf)) { return object.Equals(Not, rhs.Not); } return false; } public override bool Equals(object rhsObj) { if (!(rhsObj is JsonSchema jsonSchema)) { return false; } if (Title == jsonSchema.Title && Description == jsonSchema.Description && EqualsOnlyAny(jsonSchema) && EqualsOnlyNum(jsonSchema) && EqualsOnlyString(jsonSchema) && EqualsOnlyArray(jsonSchema) && EqualsOnlyObject(jsonSchema)) { return EqualsOnlySubBool(jsonSchema); } return false; } public override int GetHashCode() { throw new NotImplementedException(); } public override string ToString() { return new JsonSerializer(typeof(JsonSchema)).Serialize(this); } public JsonSchema() { } [Preserve] public JsonSchema(bool b) { if (!b) { Not = new JsonSchema(); } } public static JsonSchema CreateFromType<T>(JsonSchemaRegistry reg = null, bool asRef = false) { return CreateFromType(typeof(T), reg, asRef); } public static JsonSchema CreateFromType(Type ty, JsonSchemaRegistry reg = null, bool asRef = false) { string text; JsonSchema jsonSchema2; switch (Node.KindOfType(ty)) { case NodeKind.Boolean: return new JsonSchema { Type = "boolean" }; case NodeKind.Integer: { object[] enum2 = null; if (TypeHelper.TypeWrap(ty).IsEnum) { enum2 = System.Enum.GetValues(ty).Cast<object>().ToArray(); } return new JsonSchema { Type = "integer", Enum = enum2 }; } case NodeKind.Float: return new JsonSchema { Type = "number" }; case NodeKind.String: { object[] @enum = null; if (TypeHelper.TypeWrap(ty).IsEnum) { object[] stringEnumNames = TypeHelper.GetStringEnumNames(ty); @enum = stringEnumNames; } return new JsonSchema { Type = "string", Enum = @enum }; } case NodeKind.Array: { Type type = TypeHelper.ElemTypeOfIEnumerable(ty); return new JsonSchema { Type = "array", TypedItems = ((type != null) ? CreateFromType(type, reg, asRef: true) : null) }; } case NodeKind.Object: { if (ty == typeof(object)) { return new JsonSchema(); } if (TypeHelper.TypeWrap(ty).IsGenericType && ty.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { return new JsonSchema { Type = "object" }; } if (reg == null) { reg = new JsonSchemaRegistry(); } JsonSchemaAttribute customAttribute = TypeHelper.GetCustomAttribute<JsonSchemaAttribute>(ty); text = customAttribute?.Id; if (string.IsNullOrEmpty(text)) { text = ty.ToString(); } JsonSchema jsonSchema = reg.Resolve(text); if (jsonSchema != null) { if (asRef) { return new JsonSchema { Ref = text }; } return jsonSchema; } jsonSchema2 = CreateFromSchemaAttr(customAttribute); jsonSchema2.Type = "object"; Type baseType = TypeHelper.TypeWrap(ty).BaseType; HashSet<string> hashSet = null; if (baseType != null) { if (RefChecker.IsRefTag(baseType, out var elemType)) { JsonSchema jsonSchema3 = CreateFromType(elemType, reg); jsonSchema2.Type = jsonSchema3.Type; goto IL_0581; } JsonSchema jsonSchema4 = CreateFromType(baseType, reg, asRef: true); if (jsonSchema4 != null && jsonSchema4.Ref != null) { jsonSchema2.AddToAllOf(jsonSchema4); hashSet = new HashSet<string>(from f in TypeHelper.GetSerializableFields(baseType) select f.Name); } } Dictionary<string, JsonSchema> dictionary = new Dictionary<string, JsonSchema>(); List<string> list = new List<string>(); Dictionary<string, string[]> dictionary2 = new Dictionary<string, string[]>(); foreach (FieldInfo serializableField in TypeHelper.GetSerializableFields(ty)) { Type fieldType = serializableField.FieldType; string text2 = JsonFieldAttribute.FieldName(TypeHelper.GetCustomAttribute<JsonFieldAttribute>(serializableField), serializableField); if (hashSet != null && hashSet.Contains(serializableField.Name)) { dictionary.Add(text2, new JsonSchema()); continue; } JsonSchema jsonSchema5 = CreateFromSchemaAttr(TypeHelper.GetCustomAttribute<JsonSchemaAttribute>(serializableField)); ItemsJsonSchemaAttribute customAttribute2 = TypeHelper.GetCustomAttribute<ItemsJsonSchemaAttribute>(serializableField); if (customAttribute2 != null) { jsonSchema5.TypedItems = CreateFromSchemaAttr(customAttribute2); } if (TypeHelper.GetCustomAttribute<JsonSchemaRequiredAttribute>(serializableField) != null) { list.Add(text2); } JsonSchemaDependenciesAttribute customAttribute3 = TypeHelper.GetCustomAttribute<JsonSchemaDependenciesAttribute>(serializableField); if (customAttribute3 != null) { dictionary2.Add(text2, customAttribute3.Dependencies); } JsonSchema jsonSchema6 = CreateFromType(fieldType, reg, asRef: true); if (jsonSchema6.Ref != null) { jsonSchema5 = jsonSchema6; } else { if (jsonSchema5.Type == null) { jsonSchema5.Type = jsonSchema6.Type; } if (jsonSchema5.Enum == null) { jsonSchema5.Enum = jsonSchema6.Enum; } if (jsonSchema6.Items != null) { JsonSchema jsonSchema7 = jsonSchema6.Items as JsonSchema; if (jsonSchema7.Ref != null) { jsonSchema5.TypedItems = jsonSchema7; } else { if (jsonSchema7.Type != null) { if (jsonSchema5.Items is JsonSchema jsonSchema8) { jsonSchema8.Type = jsonSchema7.Type; } else { jsonSchema5.TypedItems = new JsonSchema { Type = jsonSchema7.Type }; } } if (jsonSchema7.Enum != null) { (jsonSchema5.Items as JsonSchema).Enum = jsonSchema7.Enum; } } } } JsonSchemaRefAttribute customAttribute4 = TypeHelper.GetCustomAttribute<JsonSchemaRefAttribute>(serializableField); if (customAttribute4 != null) { if (!RefChecker.IsRefTagDerived(customAttribute4.TagType, out var _)) { throw new ArgumentException("IRefTag<T> must be derived by tagType"); } JsonSchema s = CreateFromType(customAttribute4.TagType, reg, asRef: true); switch (customAttribute4.Influence) { case InfluenceRange.Entiry: jsonSchema5.AddToAllOf(s); break; case InfluenceRange.AdditionalProperties: if (jsonSchema5.AdditionalProperties == null) { jsonSchema5.AdditionalProperties = new JsonSchema(); } jsonSchema5.AdditionalProperties.AddToAllOf(s); break; } } ItemsJsonSchemaRefAttribute customAttribute5 = TypeHelper.GetCustomAttribute<ItemsJsonSchemaRefAttribute>(serializableField); if (customAttribute5 != null) { if (!RefChecker.IsRefTagDerived(customAttribute5.TagType, out var _)) { throw new ArgumentException("IRefTag<T> must be derived by tagType"); } JsonSchema s2 = CreateFromType(customAttribute5.TagType, reg, asRef: true); switch (customAttribute5.Influence) { case InfluenceRange.Entiry: if (jsonSchema5.Items == null) { jsonSchema5.TypedItems = new JsonSchema(); } ((JsonSchema)jsonSchema5.Items).AddToAllOf(s2); break; case InfluenceRange.AdditionalProperties: if (jsonSchema5.Items == null) { jsonSchema5.TypedItems = new JsonSchema(); } if (((JsonSchema)jsonSchema5.Items).AdditionalProperties == null) { ((JsonSchema)jsonSchema5.Items).AdditionalProperties = new JsonSchema(); } ((JsonSchema)jsonSchema5.Items).AdditionalProperties.AddToAllOf(s2); break; } } dictionary.Add(text2, jsonSchema5); } jsonSchema2.Properties = dictionary; if (list.Count != 0) { jsonSchema2.Required = list.ToArray(); } if (dictionary2.Count != 0) { jsonSchema2.Dependencies = dictionary2; } goto IL_0581; } default: { throw new NotImplementedException(); } IL_0581: reg.Register(text, jsonSchema2); if (asRef) { return new JsonSchema { Ref = text }; } return jsonSchema2; } } private static JsonSchema CreateFromSchemaAttr(JsonSchemaAttribute attr) { JsonSchema jsonSchema = new JsonSchema(); if (attr == null) { return jsonSchema; } jsonSchema.Schema = attr.Schema; jsonSchema.Id = attr.Id; jsonSchema.Ref = attr.Ref; jsonSchema.Title = attr.Title; jsonSchema.Description = attr.Description; jsonSchema.MultipleOf = attr.MultipleOf; jsonSchema.Maximum = attr.Maximum; jsonSchema.ExclusiveMaximum = attr.ExclusiveMaximum; jsonSchema.Minimum = attr.Minimum; jsonSchema.ExclusiveMinimum = attr.ExclusiveMinimum; jsonSchema.MaxLength = attr.MaxLength; jsonSchema.MinLength = attr.MinLength; jsonSchema.Pattern = attr.Pattern; jsonSchema.MaxItems = attr.MaxItems; jsonSchema.MinItems = attr.MinItems; jsonSchema.UniqueItems = attr.UniqueItems; jsonSchema.MaxProperties = attr.MaxProperties; jsonSchema.MinProperties = attr.MinProperties; jsonSchema.Required = attr.Required; return jsonSchema; } private static bool EqualsSingletonOrArray<T>(object lhs, object rhs) where T : class { if (lhs == null && rhs == null) { return true; } if (lhs == null || rhs == null) { return false; } T[] array = lhs as T[]; T[] array2 = rhs as T[]; if (array != null && array2 != null) { return EqualsEnumerable(array, array2); } T objA = lhs as T; T objB = rhs as T; return object.Equals(objA, objB); } private static bool EqualsEnumerable<E>(IEnumerable<E> lhs, IEnumerable<E> rhs) { if (lhs != null || rhs != null) { if (lhs != null && lhs != null) { return lhs.SequenceEqual(rhs); } return false; } return true; } } public static class JsonSchemaExtensions { public static ConstraintsViolationException Validate(this JsonSchema j, object o, JsonSchemaRegistry reg = null) { return new JsonSchemaValidator(j).Validate(o, reg); } internal static ConstraintsViolationException Validate(this JsonSchema j, object o, State state, JsonSchemaRegistry reg) { return new JsonSchemaValidator(j).Validate(o, state, reg); } } public class RefTag<T> where T : struct { } internal static class RefChecker { public static bool IsRefTagDerived(Type ty, out Type elemType) { Type baseType = TypeHelper.TypeWrap(ty).BaseType; if (baseType != null) { return IsRefTag(baseType, out elemType); } elemType = null; return false; } public static bool IsRefTag(Type ty, out Type elemType) { if (TypeHelper.TypeWrap(ty).IsGenericType && ty.GetGenericTypeDefinition() == typeof(RefTag<>)) { elemType = TypeHelper.TypeWrap(ty).GetGenericArguments()[0]; return true; } elemType = null; return false; } } public sealed class JsonSchemaRegistry { private readonly Dictionary<string, JsonSchema> _registory = new Dictionary<string, JsonSchema>(); public JsonSchema Resolve(string id) { JsonSchema value = null; if (_registory.TryGetValue(id, out value)) { return value; } return null; } public void Register(string id, JsonSchema j) { _registory.Add(id, j); } public IEnumerable<string> GetRegisteredIDs() { return _registory.Keys; } } public sealed class JsonSchemaValidator { private readonly JsonSchema _schema; public JsonSchemaValidator(JsonSchema j) { _schema = j; } public ConstraintsViolationException Validate(object o, JsonSchemaRegistry reg = null) { return Validate(o, default(State), reg); } internal ConstraintsViolationException Validate(object o, State state, JsonSchemaRegistry reg) { if (_schema.Ref != null) { return (reg?.Resolve(_schema.Ref) ?? throw new Exception("Schema is not registered or registory is null: Ref=" + _schema.Ref)).Validate(o, state, reg); } ConstraintsViolationException ex = null; if (o is INode) { return Validate((o as INode).GenericContent, state, reg); } NodeKind nodeKind = Node.KindOfValue(o); if (_schema.Type != null) { if (_schema.Type.GetType().IsArray) { string[] array = (string[])_schema.Type; bool flag = false; string[] array2 = array; foreach (string typeName in array2) { if (ValidateKind(nodeKind, typeName)) { flag = true; break; } } if (!flag) { string text = nodeKind.ToString(); string text2 = string.Join(", ", array); return new ConstraintsViolationException(state.CreateMessage("Type is not contained(Actual: {0}; Expected: [{1}])", text, text2)); } } else { string text3 = (string)_schema.Type; if (!ValidateKind(nodeKind, text3)) { string text4 = nodeKind.ToString(); string text5 = text3.ToString(); return new ConstraintsViolationException(state.CreateMessage("Type is not matched(Actual: {0}; Expected: {1})", text4, text5)); } } } if (_schema.Enum != null) { object lhs = o; if (o != null && TypeHelper.TypeWrap(o.GetType()).IsEnum && nodeKind == NodeKind.String) { lhs = TypeHelper.GetStringEnumNameOf(o); } bool flag2 = false; object[] @enum = _schema.Enum; foreach (object rhs in @enum) { if (TypeHelper.DeepEquals(lhs, rhs)) { flag2 = true; break; } } if (!flag2) { return new ConstraintsViolationException(state.CreateMessage("Enum is not matched")); } } if (_schema.Not != null) { ex = _schema.Not.Validate(o, state, reg); if (ex == null) { return new ConstraintsViolationException(state.CreateMessage("Not")); } } if (_schema.AllOf != null) { int num = 0; foreach (JsonSchema item in _schema.AllOf) { ex = item.Validate(o, state, reg); if (ex != null) { return new ConstraintsViolationException(state.CreateMessage("AllOf[{0}] is failed", num), ex); } num++; } } if (_schema.AnyOf != null) { bool flag3 = false; foreach (JsonSchema item2 in _schema.AnyOf) { ex = item2.Validate(o, state, reg); if (ex == null) { flag3 = true; break; } } if (!flag3) { return new ConstraintsViolationException(state.CreateMessage("None of AnyOf is matched")); } } if (_schema.OneOf != null) { int num2 = -1; int num3 = 0; foreach (JsonSchema item3 in _schema.OneOf) { ex = item3.Validate(o, state, reg); if (ex == null) { if (num2 != -1) { return new ConstraintsViolationException(state.CreateMessage("Both of OneOf[{0}] and OneOf[{1}] are matched", num2, num3)); } num2 = num3; } num3++; } if (num2 == -1) { return new ConstraintsViolationException(state.CreateMessage("None of AnyOf is matched")); } } switch (nodeKind) { case NodeKind.Integer: case NodeKind.Float: ex = ValidateNumber(Convert.ToDouble(o), state, reg); if (ex != null) { return new ConstraintsViolationException("Number", ex); } break; case NodeKind.String: { string v = ((o != null && TypeHelper.TypeWrap(o.GetType()).IsEnum) ? TypeHelper.GetStringEnumNameOf(o) : ((string)o)); ex = ValidateString(v, state, reg); if (ex != null) { return new ConstraintsViolationException("String", ex); } break; } case NodeKind.Array: ex = ValidateArray(TypeHelper.ToIEnumerable(o), state, reg); if (ex != null) { return new ConstraintsViolationException("Array", ex); } break; case NodeKind.Object: ex = ValidateObject(o, state, reg); if (ex != null) { return new ConstraintsViolationException("Object", ex); } break; default: throw new NotImplementedException(nodeKind.ToString()); case NodeKind.Boolean: case NodeKind.Null: break; } return null; } private ConstraintsViolationException ValidateNumber(double v, State state, JsonSchemaRegistry reg) { if (_schema.MultipleOf != double.MinValue) { if (_schema.MultipleOf <= 0.0) { throw new InvalidOperationException("MultipleOf must be greater than 0: Value = " + _schema.MultipleOf); } double num = v / _schema.MultipleOf; if (num != Math.Truncate(num)) { return new ConstraintsViolationException(state.CreateMessage("MultipleOf assertion !({0} % {1} == 0)", v, _schema.MultipleOf)); } } if (_schema.Maximum != double.MinValue && !(v <= _schema.Maximum)) { return new ConstraintsViolationException(state.CreateMessage("Maximum assertion !({0} <= {1})", v, _schema.Maximum)); } if (_schema.ExclusiveMaximum != double.MinValue && !(v < _schema.ExclusiveMaximum)) { return new ConstraintsViolationException(state.CreateMessage("ExclusiveMaximum assertion !({0} < {1})", v, _schema.ExclusiveMaximum)); } if (_schema.Minimum != double.MaxValue && !(v >= _schema.Minimum)) { return new ConstraintsViolationException(state.CreateMessage("Minimum assertion !({0} >= {1})", v, _schema.Minimum)); } if (_schema.ExclusiveMinimum != double.MaxValue && !(v > _schema.ExclusiveMinimum)) { return new ConstraintsViolationException(state.CreateMessage("ExclusiveMinimum assertion !({0} > {1})", v, _schema.ExclusiveMinimum)); } return null; } private ConstraintsViolationException ValidateString(string v, State state, JsonSchemaRegistry reg) { StringInfo stringInfo = null; if (_schema.MaxLength != int.MinValue) { stringInfo = stringInfo ?? new StringInfo(v); if (stringInfo.LengthInTextElements > _schema.MaxLength) { return new ConstraintsViolationException(state.CreateMessage("MaxLength assertion !({0} <= {1})", stringInfo.LengthInTextElements, _schema.MaxLength)); } } if (_schema.MinLength != int.MaxValue) { stringInfo = stringInfo ?? new StringInfo(v); if (stringInfo.LengthInTextElements < _schema.MinLength) { return new ConstraintsViolationException(state.CreateMessage("MinLength assertion !({0} >= {1})", stringInfo.LengthInTextElements, _schema.MinLength)); } } if (_schema.Pattern != null && !Regex.IsMatch(v, _schema.Pattern)) { return new ConstraintsViolationException(state.CreateMessage("Pattern assertion !(\"{0}\" matched \"{1}\")", v, _schema.Pattern)); } return null; } private ConstraintsViolationException ValidateArray(IEnumerable<object> vsIter, State state, JsonSchemaRegistry reg) { object[] array = vsIter.ToArray(); int num = array.Length; if (_schema.MaxItems != int.MinValue && num > _schema.MaxItems) { return new ConstraintsViolationException(state.CreateMessage("MaxItems assertion !({0} <= {1})", num, _schema.MaxItems)); } if (_schema.MinItems != int.MaxValue && num < _schema.MinItems) { return new ConstraintsViolationException(state.CreateMessage("MinItems assertion !({0} >= {1})", num, _schema.MinItems)); } if (_schema.UniqueItems) { for (int i = 0; i < array.Length; i++) { for (int j = 0; j < array.Length; j++) { if (i != j && TypeHelper.DeepEquals(array[i], array[j])) { return new ConstraintsViolationException(state.CreateMessage("UniqueItems assertion: Elements at {0} and {1} are duplicated", i, j)); } } } } List<object> list = null; if (_schema.Items != null) { if (_schema.Items.GetType().IsArray) { JsonSchema[] source = (JsonSchema[])_schema.Items; int num2 = 0; object[] array2 = array; foreach (object obj in array2) { JsonSchema jsonSchema = source.ElementAtOrDefault(num2); if (jsonSchema == null) { if (list == null) { list = new List<object>(); } list.Add(obj); continue; } ConstraintsViolationException ex = jsonSchema.Validate(obj, state.NestAsElem(num2), reg); if (ex != null) { return new ConstraintsViolationException("Items", ex); } num2++; } } else { JsonSchema j2 = (JsonSchema)_schema.Items; int num3 = 0; object[] array2 = array; foreach (object o in array2) { ConstraintsViolationException ex2 = j2.Validate(o, state.NestAsElem(num3), reg); if (ex2 != null) { return new ConstraintsViolationException("Items", ex2); } num3++; } } } if (_schema.AdditionalItems != null && list != null) { foreach (object item in list) { ConstraintsViolationException ex3 = _schema.AdditionalItems.Validate(item, state, reg); if (ex3 != null) { return new ConstraintsViolationException("AdditionalItems", ex3); } } } return null; } private ConstraintsViolationException ValidateObject(object v, State state, JsonSchemaRegistry reg) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); foreach (KeyValuePair<string, object> item in TypeHelper.ToKeyValues(v)) { ConstraintsViolationException ex = ValidateObjectField(item.Key, item.Value, state.NestAsElem(item.Key), reg); if (ex != null) { return ex; } dictionary.Add(item.Key, item.Value); } if (_schema.Required != null) { HashSet<string> hashSet = new HashSet<string>(_schema.Required); hashSet.IntersectWith(dictionary.Keys); if (hashSet.Count != _schema.Required.Count()) { string text = string.Join(", ", hashSet.ToArray()); string text2 = string.Join(", ", _schema.Required); return new ConstraintsViolationException(state.CreateMessage("Lack of required fields(Actual: [{0}]; Expected: [{1}])", text, text2)); } } if (_schema.MaxProperties != int.MinValue && dictionary.Count > _schema.MaxProperties) { return new ConstraintsViolationException(state.CreateMessage("MaxProperties assertion !({0} <= {1})", dictionary.Count, _schema.MaxProperties)); } if (_schema.MinProperties != int.MaxValue && dictionary.Count < _schema.MinProperties) { return new ConstraintsViolationException(state.CreateMessage("MaxProperties assertion !({0} >= {1})", dictionary.Count, _schema.MinProperties)); } if (_schema.Dependencies != null) { if (_schema.Dependencies is Dictionary<string, string[]> dictionary2) { foreach (KeyValuePair<string, object> item2 in dictionary) { string[] value = null; if (dictionary2.TryGetValue(item2.Key, out value)) { IEnumerable<string> source = ((string[])value.Clone()).Intersect(dictionary.Keys); if (source.Count() != value.Count()) { string text3 = string.Join(", ", source.ToArray()); string text4 = string.Join(", ", value); return new ConstraintsViolationException(state.CreateMessage("Dependencies assertion. Lack of depended fields for {0}(Actual: [{1}]; Expected: [{2}])", item2.Key, text3, text4)); } } } } else if (_schema.Dependencies is Dictionary<string, JsonSchema> dictionary3) { foreach (KeyValuePair<string, object> item3 in dictionary) { JsonSchema value2 = null; if (dictionary3.TryGetValue(item3.Key, out value2)) { ConstraintsViolationException ex2 = value2.Validate(v, default(State).NestAsElem(item3.Key), reg); if (ex2 != null) { return new ConstraintsViolationException(state.CreateMessage("Dependencies assertion. Failed to validation for {0}", item3.Key), ex2); } } } } } return null; } private ConstraintsViolationException ValidateObjectField(string key, object value, State state, JsonSchemaRegistry reg) { bool flag = false; if (_schema.Properties != null) { JsonSchema value2 = null; if (_schema.Properties.TryGetValue(key, out value2)) { flag = true; ConstraintsViolationException ex = value2.Validate(value, state, reg); if (ex != null) { return new ConstraintsViolationException("Property", ex); } } } if (_schema.PatternProperties != null) { foreach (KeyValuePair<string, JsonSchema> patternProperty in _schema.PatternProperties) { if (Regex.IsMatch(key, patternProperty.Key)) { flag = true; ConstraintsViolationException ex2 = patternProperty.Value.Validate(value, state, reg); if (ex2 != null) { return new ConstraintsViolationException("PatternProperties", ex2); } } } } if (_schema.AdditionalProperties != null && !flag) { ConstraintsViolationException ex3 = _schema.AdditionalProperties.Validate(value, state, reg); if (ex3 != null) { return new ConstraintsViolationException("AdditionalProperties", ex3); } } return null; } private static bool ValidateKind(NodeKind kind, string typeName) { switch (typeName) { case "null": return kind == NodeKind.Null; case "boolean": return kind == NodeKind.Boolean; case "object": return kind == NodeKind.Object; case "array": return kind == NodeKind.Array; case "number": if (kind != NodeKind.Integer) { return kind == NodeKind.Float; } return true; case "string": return kind == NodeKind.String; case "integer": return kind == NodeKind.Integer; default: throw new NotImplementedException(); } } } public class ConstraintsViolationException : Exception { public ConstraintsViolationException(string message) : base(message) { } public ConstraintsViolationException(string message, ConstraintsViolationException inner) : base($"{message}.{inner.Message}") { } } } namespace VJson.Internal { internal struct State { private string _elemName; private string ElemName { get { if (string.IsNullOrEmpty(_elemName)) { return "(root)"; } return _elemName; } } internal State NestAsElem(int elem) { State result = default(State); result._elemName = $"{ElemName}[{elem}]"; return result; } internal State NestAsElem(string elem) { State result = default(State); result._elemName = $"{ElemName}[\"{elem}\"]"; return result; } internal string CreateMessage(string format, params object[] args) { return $"{ElemName}: {string.Format(format, args)}."; } } internal static class StateExtension { public static string CreateNodeConversionFailureMessage(this State s, INode fromNode, IEnumerable<Type> toTypes) { string toDetail = string.Format("one of [{0}]", string.Join(", ", toTypes.Select((Type t) => t.ToString()).ToArray())); return s.CreateNodeConversionFailureMessage(fromNode, toDetail); } public static string CreateNodeConversionFailureMessage(this State s, INode fromNode, Type toType) { string text = toType.ToString(); if (fromNode.Kind == NodeKind.Null && !TypeHelper.IsBoxed(toType)) { text = $"non-boxed value({text})"; } return s.CreateNodeConversionFailureMessage(fromNode, text); } private static string CreateNodeConversionFailureMessage(this State s, INode fromNode, string toDetail) { string text = $"{fromNode.Kind} node"; switch (fromNode.Kind) { case NodeKind.Boolean: text = $"{text} ({((BooleanNode)fromNode).Value})"; break; case NodeKind.Integer: text = $"{text} ({((IntegerNode)fromNode).Value})"; break; case NodeKind.Float: text = $"{text} ({((FloatNode)fromNode).Value})"; break; } return s.CreateMessage("{0} cannot convert to {1}", text, toDetail); } public static string CreateTypeConversionFailureMessage<T>(this State s, T fromValue, Type toType, string reason = null) { string arg = $"{typeof(T).ToString()} value"; NodeKind nodeKind = Node.KindOfType(typeof(T)); if ((uint)(nodeKind - 3) <= 2u) { arg = $"{arg} ({fromValue})"; } string text = $"{arg} cannot convert to {toType}"; if (reason != null) { text = $"{text} (Reason: {reason})"; } return s.CreateMessage(text); } } }