Decompiled source of V2T v4.1.2
Mods/V2T.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Http; 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.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using HarmonyLib; using Il2Cpp; using Il2CppEpic.OnlineServices; using Il2CppEpic.OnlineServices.Connect; using Il2CppEpic.OnlineServices.P2P; using Il2CppEpic.OnlineServices.Platform; using Il2CppEpic.OnlineServices.Sessions; using Il2CppGameGUI.Options; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppKeepsake; using Il2CppKeepsake.Common.Unity; using Il2CppKeepsake.Data; using Il2CppKeepsake.Framework.Networking.Data; using Il2CppKeepsake.Framework.Networking.Logic; using Il2CppKeepsake.HyperSpace.GameMode.Logic; using Il2CppKeepsake.HyperSpace.NewInputSystem; using Il2CppKeepsake.HyperSpace.Online.Data; using Il2CppKeepsake.HyperSpace.Online.Epic.Util; using Il2CppKeepsake.HyperSpace.Online.Epic.Util.Transport; using Il2CppKeepsake.HyperSpace.Online.Lobby.Data; using Il2CppKeepsake.HyperSpace.Online.Lobby.Logic; using Il2CppKeepsake.HyperSpace.Online.Steam; using Il2CppKeepsake.HyperSpace.Online.Util; using Il2CppKeepsake.HyperSpace.System.LoadingScreen.Presentation; using Il2CppKeepsake.Modal; using Il2CppKeepsake.NetworkedTimer; using Il2CppKeepsake.PlayerGroupBar; using Il2CppKeepsake.PlayerStatusBar; using Il2CppSteamworks; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Collections.ObjectModel; using Il2CppSystem.Threading; using Il2CppTMPro; using Il2CppUniRx; using MelonLoader; using MelonLoader.NativeUtils; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using NAudio.CoreAudioApi; using NAudio.Wave; using NAudio.Wave.SampleProviders; using Unity.Netcode; using Unity.Networking.Transport; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; using V2T; using Whisper.net; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(V2TMod), "V2T", "4.1.2", "Pasharacc", null)] [assembly: MelonGame("Keepsake Games", "Jump Space")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("V2T")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("4.1.2.0")] [assembly: AssemblyInformationalVersion("4.1.2")] [assembly: AssemblyProduct("V2T")] [assembly: AssemblyTitle("V2T")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.1.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 V2T { internal static class BrowserUi { [HarmonyPatch(typeof(GUI_ServerBrowser), "Open")] private static class HookOpen { private static void Postfix(GUI_ServerBrowser __instance) { _browser = __instance; } } [HarmonyPatch(typeof(GUI_ServerBrowser), "Handle_Pending")] private static class HookPending { private static void Postfix(GUI_ServerBrowser __instance, bool pending) { _browser = __instance; _pending = pending; if (!pending) { _nextSnapshot = 0f; } LiveResults(pending); } } private delegate void Act(); private struct Cols { public float Lobby; public float Players; public float Mission; public float Jumps; public float Ship; public float Region; public float End; } private struct ListItem { public LobbyInfo Lobby; public string Header; public int Count; public Color Colour; public Ghost Gone; public float Size; public float Fade; } internal enum FieldLook { Talking, Live, Listening, Transcribing, Translating, Sent, NoAudio, Warning } private struct CrewCard { public string Id; public string Name; public string Station; public int Level; public bool You; public bool Host; public bool HasReady; public bool Ready; public bool Downed; public bool Reviving; public bool Defeated; public bool NotSeated; public bool InJumpSeat; public bool HasBleed; public float BleedLeft; public float BleedMax; public float BleedAt; public float ReviveStart; public float ReviveTime; public float Health; public float MaxHealth; public float Shield; public float MaxShield; } private readonly struct Glass { public readonly int Id; public readonly Color Top; public readonly Color Mid; public readonly Color Bottom; public readonly Color Lit; public readonly float LitA; public Glass(int id, Color top, Color mid, Color bottom, Color lit, float litA) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Id = id; Top = top; Mid = mid; Bottom = bottom; Lit = lit; LitA = litA; } } private struct WalletChip { public string Text; public string Id; public bool Ingot; public Color Colour; public Color IconTint; public Texture2D Icon; } private struct HostView { public HostMode Mode; public string Name; public string Password; public bool Auto; public int Region; } internal enum LayoutItem { None, Chat, Crew, Own, Comms, Wallet } private sealed class JoinAttempt { public LobbyInfo Lobby; public string Title = "Joining"; public IntPtr AskReq; public JoinWatch Watch; public bool Cancelled; public bool SaidIt; public string Status = ""; public string LoggedStatus = ""; public float EndedAt = -1f; } private sealed class Seen { public LobbyInfo Last; public int FriendMask; public float NewAt = -100f; public float SeatsAt = -100f; public float MaxAt = -100f; public float JumpsAt = -100f; public float MissionAt = -100f; public float ShipAt = -100f; public float NameAt = -100f; public float HostAt = -100f; public float LockAt = -100f; public float TagAt = -100f; public float LevelAt = -100f; public float RegionAt = -100f; public float FriendAt = -100f; public int SeatsFrom; public int JumpsFrom; public int LitFrom; public int FriendsNew; public Color MissionFrom; } private sealed class Ghost { public LobbyInfo L; public float At; public int Segment; public int Index; } [HarmonyPatch(typeof(GUI_MainMenu), "OnEnable")] private static class HookMenuEnable { private static void Postfix(GUI_MainMenu __instance) { _menuInst = __instance; } } [HarmonyPatch(typeof(GUI_MainMenu), "Show")] private static class HookMenuShow { private static void Postfix(GUI_MainMenu __instance) { _menuInst = __instance; } } private static bool _escWarned; private static bool _escLogged; private static bool _hostingPublic; private static float _hostingReadAt = -10f; private static bool _escGuest; private static bool _escHost; private static string _gapNote = ""; private static float? _gapCache; private static float _gapNext; private static bool _filtersLoaded; private static bool _threatDrag; private static bool _dragHigh; private static bool _regionsOpen; private static Rect _threatTrack; private static Rect _threatLabel; private static Rect _regionsButton; private static Rect _regionsMenu; private static float _cellStep; private static readonly List<(Rect R, int Kind, int Index, string Code)> _menuHits = new List<(Rect, int, int, string)>(); private static readonly Dictionary<string, string> _regionNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<int, Color> _threatSeen = new Dictionary<int, Color>(); private const int HitRegion = 0; private const int HitContinent = 1; private const int HitAll = 2; private const int HitNone = 3; private const int HitGoodPing = 4; private static GUI_ServerBrowser _browser; private static bool _pending; private static bool _wasOpen; private static bool _logged; private static bool _warned; private static bool _sampled; private static readonly BrowserFilter Filter = new BrowserFilter(); private static SortKey _sort = SortKey.Players; private static bool _desc = true; private static List<LobbyInfo> _all = new List<LobbyInfo>(); private static readonly List<LobbyInfo> _friends = new List<LobbyInfo>(); private static readonly List<LobbyInfo> _public = new List<LobbyInfo>(); private static readonly List<LobbyInfo> _locked = new List<LobbyInfo>(); private static int _longestRun; private static int _dupesLoggedAt = -1; private static float _nextSnapshot; private static float _scroll; private static float _joinAt = -10f; private static bool _searchFocus; private static int _drawFailures; private static bool _broken; private static float _drawnAt = -10f; private static bool _typing; private static bool _unsubscribed; private static CanvasGroup _group; private static bool _groupAdded; private static bool _hiding; private static GraphicRaycaster _raycaster; private static bool _raycasterWasOn; private static readonly Dictionary<string, string> ShipByGuid = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, string> MissionByGuid = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static bool _ownLogged; private static bool _ownWarned; private static readonly Color Green = new Color(0.25f, 1f, 0.4f); private static readonly Color Ink = new Color(0.95f, 0.96f, 0.98f); private static readonly Color Grey = new Color(0.49f, 0.53f, 0.58f); private static readonly Color Empty = new Color(0.17f, 0.2f, 0.22f); private static readonly Color FriendBlue = new Color(0.4f, 0.75f, 0.96f); private static readonly Color RecentViolet = new Color(0.71f, 0.61f, 1f); private static readonly Color LockGold = new Color(0.79f, 0.64f, 0.15f); private static readonly Color DartGreen = new Color(0.25f, 1f, 0.4f); private static readonly Color CatamaranBlue = new Color(0.22f, 0.74f, 0.97f); private static readonly Color HammerheadRed = new Color(1f, 0.42f, 0.26f); private static readonly Color[] Tier = (Color[])(object)new Color[4] { new Color(0.29f, 0.87f, 0.5f), new Color(1f, 0.82f, 0.25f), new Color(1f, 0.54f, 0.24f), new Color(1f, 0.3f, 0.3f) }; private static readonly Color[] ThreatScale = (Color[])(object)new Color[10] { new Color(0.29f, 0.87f, 0.5f), new Color(0.64f, 0.9f, 0.21f), new Color(1f, 0.82f, 0.25f), new Color(1f, 0.69f, 0.18f), new Color(1f, 0.54f, 0.24f), new Color(1f, 0.3f, 0.3f), new Color(0.88f, 0.14f, 0.37f), new Color(0.76f, 0.09f, 0.36f), new Color(0.61f, 0.15f, 0.69f), new Color(0.48f, 0.12f, 0.64f) }; private static readonly Color[] ShipPalette = (Color[])(object)new Color[6] { new Color(0.22f, 0.74f, 0.97f), new Color(0.91f, 0.47f, 0.98f), new Color(0.98f, 0.8f, 0.08f), new Color(0.18f, 0.83f, 0.75f), new Color(0.98f, 0.57f, 0.24f), new Color(0.65f, 0.55f, 0.98f) }; private static float _s = 1f; private static GUIStyle _label; private static GUIStyle _invisible; private static int _labelSize; private static Rect _searchRect; private static float _storeOpenedAt = -10f; private static int _listVersion; private static int _measuredVersion = -1; private static float _measuredS; private static float _missionTextW; private static float _shipTextW; private static float _regionTextW; private static int _mostSeats; private static readonly List<ListItem> _items = new List<ListItem>(); private const string YourLobby = "Your Lobby"; private static readonly Color YourYellow = new Color(1f, 0.8f, 0.12f); private static readonly Dictionary<float[][], Vector2> _glyphMin = new Dictionary<float[][], Vector2>(); private static readonly Color MissionBubble = new Color(0.075f, 0.09f, 0.1f); private static GUI_Modal _modalView; private static CanvasGroup _modalGroup; private static bool _modalHidden; private static bool _warnedDialog; private static float _dialogAt = -10f; private static float _nextFocus; private static float _shownAt; private static IntPtr _shownReq; private static IntPtr _pressedReq; private static IntPtr _queuedReq; private static ModalButton _queuedButton; private static bool _queuedJoin; private static string _queuedLabel; private static string _loggedDialog; private static GUIStyle _wrap; private static bool _mono; private static float _dim = 1f; private static readonly Dictionary<int, GUIStyle> _fills = new Dictionary<int, GUIStyle>(); private static readonly Dictionary<int, GUIStyle> _lines = new Dictionary<int, GUIStyle>(); private static readonly Dictionary<int, GUIStyle> _lines2 = new Dictionary<int, GUIStyle>(); private static Texture2D _logo; private static bool _logoFailed; private static readonly float[][] ShipGlyph = new float[1][] { new float[12] { 0f, 0.5f, 0.33f, 0.08f, 0.72f, 0.08f, 1f, 0.5f, 0.72f, 0.92f, 0.33f, 0.92f } }; private static readonly float[][] DartGlyph = new float[1][] { new float[70] { 0.387f, 0.181f, 0.413f, 0.184f, 0.528f, 0.257f, 0.535f, 0.301f, 0.596f, 0.325f, 0.617f, 0.372f, 0.662f, 0.385f, 0.678f, 0.445f, 0.704f, 0.469f, 0.704f, 0.531f, 0.678f, 0.555f, 0.662f, 0.615f, 0.617f, 0.628f, 0.596f, 0.675f, 0.535f, 0.699f, 0.528f, 0.743f, 0.396f, 0.819f, 0.375f, 0.816f, 0.362f, 0.795f, 0.343f, 0.727f, 0.352f, 0.709f, 0.369f, 0.704f, 0.326f, 0.667f, 0.3f, 0.597f, 0.296f, 0.552f, 0.301f, 0.51f, 0.342f, 0.505f, 0.34f, 0.492f, 0.298f, 0.484f, 0.298f, 0.411f, 0.326f, 0.333f, 0.369f, 0.296f, 0.352f, 0.291f, 0.343f, 0.27f, 0.362f, 0.205f } }; private static readonly float[][] CatamaranGlyph = new float[1][] { new float[94] { 0.331f, 0.092f, 0.421f, 0.117f, 0.387f, 0.142f, 0.421f, 0.204f, 0.464f, 0.215f, 0.452f, 0.218f, 0.461f, 0.254f, 0.548f, 0.269f, 0.579f, 0.258f, 0.584f, 0.28f, 0.722f, 0.301f, 0.767f, 0.323f, 0.791f, 0.377f, 0.787f, 0.413f, 0.702f, 0.41f, 0.7f, 0.442f, 0.683f, 0.467f, 0.683f, 0.533f, 0.7f, 0.558f, 0.702f, 0.59f, 0.787f, 0.587f, 0.791f, 0.623f, 0.784f, 0.648f, 0.746f, 0.691f, 0.584f, 0.72f, 0.579f, 0.742f, 0.548f, 0.731f, 0.461f, 0.746f, 0.452f, 0.782f, 0.466f, 0.782f, 0.421f, 0.796f, 0.387f, 0.858f, 0.421f, 0.883f, 0.331f, 0.908f, 0.271f, 0.858f, 0.266f, 0.764f, 0.238f, 0.742f, 0.233f, 0.713f, 0.221f, 0.706f, 0.209f, 0.623f, 0.218f, 0.504f, 0.209f, 0.377f, 0.221f, 0.294f, 0.233f, 0.287f, 0.238f, 0.258f, 0.266f, 0.236f, 0.271f, 0.142f } }; private static readonly float[][] HammerheadGlyph = new float[1][] { new float[154] { 0.198f, 0.065f, 0.229f, 0.065f, 0.246f, 0.101f, 0.295f, 0.153f, 0.305f, 0.153f, 0.315f, 0.133f, 0.391f, 0.138f, 0.429f, 0.179f, 0.464f, 0.179f, 0.467f, 0.215f, 0.512f, 0.231f, 0.547f, 0.231f, 0.567f, 0.205f, 0.598f, 0.2f, 0.622f, 0.158f, 0.709f, 0.179f, 0.761f, 0.272f, 0.757f, 0.329f, 0.764f, 0.34f, 0.802f, 0.334f, 0.957f, 0.381f, 0.968f, 0.396f, 0.964f, 0.417f, 0.985f, 0.422f, 0.988f, 0.443f, 0.968f, 0.459f, 0.968f, 0.484f, 0.943f, 0.49f, 0.94f, 0.505f, 0.968f, 0.516f, 0.968f, 0.541f, 0.985f, 0.547f, 0.988f, 0.572f, 0.968f, 0.578f, 0.968f, 0.604f, 0.947f, 0.629f, 0.802f, 0.666f, 0.764f, 0.66f, 0.757f, 0.671f, 0.761f, 0.728f, 0.709f, 0.821f, 0.622f, 0.842f, 0.598f, 0.8f, 0.567f, 0.795f, 0.547f, 0.769f, 0.512f, 0.769f, 0.467f, 0.785f, 0.464f, 0.821f, 0.429f, 0.821f, 0.391f, 0.862f, 0.315f, 0.868f, 0.305f, 0.847f, 0.295f, 0.847f, 0.246f, 0.899f, 0.229f, 0.935f, 0.198f, 0.935f, 0.188f, 0.909f, 0.177f, 0.909f, 0.146f, 0.8f, 0.126f, 0.79f, 0.081f, 0.712f, 0.081f, 0.609f, 0.043f, 0.557f, 0.039f, 0.531f, 0.012f, 0.526f, 0.022f, 0.521f, 0.015f, 0.505f, 0.022f, 0.479f, 0.012f, 0.474f, 0.039f, 0.469f, 0.043f, 0.443f, 0.081f, 0.391f, 0.081f, 0.288f, 0.126f, 0.21f, 0.146f, 0.2f, 0.177f, 0.091f, 0.188f, 0.091f } }; private static readonly HashSet<float[][]> WideIcons = new HashSet<float[][]> { DartGlyph, CatamaranGlyph, HammerheadGlyph }; private static readonly float[][] Chevron = new float[1][] { new float[12] { 0f, 0f, 0.55f, 0f, 1f, 0.5f, 0.55f, 1f, 0f, 1f, 0.45f, 0.5f } }; private static readonly float[][] TriDown = new float[1][] { new float[6] { 0f, 0.15f, 1f, 0.15f, 0.5f, 0.9f } }; private static readonly float[][] TriUp = new float[1][] { new float[6] { 0f, 0.85f, 1f, 0.85f, 0.5f, 0.1f } }; private static readonly float[][] Padlock = new float[2][] { new float[8] { 0.12f, 0.45f, 0.88f, 0.45f, 0.88f, 1f, 0.12f, 1f }, null }; private static readonly float[][] Clock = new float[2][]; private static readonly float[][] Person = new float[3][]; private static readonly Dictionary<float[][], Texture2D> _icons = new Dictionary<float[][], Texture2D>(); private static Texture2D _glowRamp; private static float _typingDrawnAt = -10f; private static readonly Color HudRed = new Color(1f, 0.28f, 0.22f); private static readonly Color MeterOff = new Color(0.15f, 0.19f, 0.18f); private static readonly Color BarOff = new Color(0.11f, 0.23f, 0.15f); private static readonly float[][] IcMic = new float[1][]; private static readonly float[][] IcMicOff = new float[1][]; private static readonly float[][] IcSpk = new float[1][]; private static readonly float[][] IcSpkOff = new float[1][]; private static readonly float[][] IcChat = new float[1][]; private static readonly float[][] IcChatOff = new float[1][]; private static readonly float[] ChatTail = new float[6] { 0.26f, 0.66f, 0.46f, 0.66f, 0.22f, 0.9f }; private static readonly float[][] IcCrown = new float[1][] { new float[14] { 0.1f, 0.8f, 0.9f, 0.8f, 0.96f, 0.28f, 0.7f, 0.5f, 0.5f, 0.16f, 0.3f, 0.5f, 0.04f, 0.28f } }; private static readonly float[][] IcPersonPlus = new float[1][]; private static readonly float[][] IcCheck = new float[1][]; private static readonly float[][] IcPhonesOff = new float[1][]; private static readonly float[][] IcSkull = new float[1][]; private static readonly float[][] IcKeyboard = new float[1][]; private static readonly float[][] IcGlobe = new float[1][]; private static bool _cpLangOpen; private static bool _cpWarned; private static bool _cpLogged; private static bool _cpOff; private static int _cpFailures; private static Rect _cpLangRect; private static Rect _cpDropRect; private static readonly Color CpSub = new Color(0.55f, 0.59f, 0.64f); private static bool _cpListening; private static float _cpListenAt; private static readonly HashSet<int> _cpHeldAtStart = new HashSet<int>(); private static bool _cpFits = true; private static bool _cpBesideLogged; private static bool _cpFitLogged; private static readonly Color GameBlue = new Color(0.49f, 0.83f, 0.99f); private static bool _balDrag; private static int _cpListenFor; private static readonly List<CrewCard> _cards = new List<CrewCard>(); private static GUI_LobbyHandler _lobby; private static GUI_PlayerGroupBar_Controller _bar; private static float _lobbySearchAt; private static float _barSearchAt; private static float _cardsTickAt; private static float _cardsDrawnAt = -10f; private static bool _cardsWanted; private static bool _inviteWanted; private static bool _mission; private static bool _anchorKnown; private static bool _crewHidden; private static bool _cardsWarned; private static Rect _cardsAnchor; private static GameObject _standInA; private static GameObject _standInB; private static GameObject _hiddenA; private static GameObject _hiddenB; private static CanvasGroup _groupA; private static CanvasGroup _groupB; private static float _alphaA = 1f; private static float _alphaB = 1f; private static string _cardsLogged = ""; private static string _anchorLogged = ""; private static readonly Dictionary<string, float> _firstSeen = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private static GUI_PlayerStatusBar_Health _ownHealth; private static GUI_PlayerStatusBar_LocationText _ownLoc; private static GUI_PlayerStatusBar_Name _ownName; private static GameObject _ownBox; private static float _ownSearchAt; private static bool _ownWanted; private static bool _ownRectKnown; private static CrewCard _ownCard; private static Rect _ownRect; private static string _missionKey = ""; private static string _ownCardLogged = ""; private static bool _crewTopKnown; private static float _crewTop; private static readonly List<(CanvasGroup G, CanvasGroup Above)> _keepShown = new List<(CanvasGroup, CanvasGroup)>(); private const float DetectSeconds = 20f; private static readonly Color CardInk = new Color(0.04f, 0.055f, 0.067f); private static readonly Color InviteGrey = new Color(0.17f, 0.2f, 0.22f); private static readonly Color KeyYellow = new Color(1f, 0.88f, 0.3f); private static readonly Color CrownGold = new Color(1f, 0.8f, 0.12f); private static readonly Color HealthGreen = new Color(0.29f, 0.87f, 0.5f); private static readonly Color HealthAmber = new Color(1f, 0.72f, 0.15f); private static readonly Color ShieldBlue = new Color(0.22f, 0.74f, 0.97f); private static readonly Color BarGrey = new Color(0.23f, 0.26f, 0.28f); private static readonly Color StationInk = new Color(0.86f, 0.9f, 0.93f); private static readonly Dictionary<string, bool> _readyWas = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, float> _readyAt = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private const float ReadyFillTime = 0.45f; private const float ReadySwooshTime = 0.4f; private const float ReadyPopTime = 0.3f; private const float ReadyPopAt = 0.77f; private static readonly Dictionary<string, string> _searchLogged = new Dictionary<string, string>(); private static GUI_Toggler _toggler; private static bool _seat; private static string _seatLogged = ""; private static readonly Dictionary<string, Color> _gameColours = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase); private static float _gameColoursAt; private static string _gameColoursLogged = ""; private static bool _jumpCharging; private static float _jumpHoldUntil; private static string _jumpLogged = ""; private static readonly Dictionary<string, float> _bleedMax = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> _bleedLogged = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static bool _bleedWarned; private static readonly Dictionary<string, float> _reviveStart = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, float> _reviveHold = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private static readonly Color DownRed = new Color(1f, 0.16f, 0.12f); private static readonly Dictionary<string, (float Phase, float At)> _phases = new Dictionary<string, (float, float)>(StringComparer.Ordinal); private static Rect _crewTopRect; private static Rect _hangarStats; private static bool _hangarStatsKnown; private static bool _hangarCrewFootKnown; private static float _hangarCrewFoot; private static readonly Color OwnGreen = new Color(0.2f, 0.78f, 0.36f); private const float CardBodyAlpha = 0.42f; private static readonly Dictionary<int, GUIStyle> _cardRings = new Dictionary<int, GUIStyle>(); private static readonly Dictionary<int, Texture2D> _fillets = new Dictionary<int, Texture2D>(); private const float StationWeight = 0.4f; private static Texture2D _swooshTex; private static readonly Dictionary<string, float> _noV2tAt = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private static readonly Glass GlassGreen = new Glass(1, Hex(4047479), Hex(2792026), Hex(2062919), Hex(13172700), 0.55f); private static readonly Glass GlassAmber = new Glass(2, Hex(15773756), Hex(13208094), Hex(10841620), Hex(16773320), 0.55f); private static readonly Glass GlassRed = new Glass(3, Hex(15751242), Hex(13056816), Hex(10496546), Hex(16766925), 0.5f); private static readonly Glass GlassBlue = new Glass(4, Hex(5219310), Hex(3375308), Hex(2384550), Hex(13822975), 0.6f); private static readonly Glass GlassV2T = new Glass(6, Hex(5435514), Hex(3394652), Hex(2401865), Hex(14745576), 0.55f); private static readonly Glass GlassTrack = new Glass(5, Hex(461581), Hex(1054491), Hex(1252128), Color.black, 0f); private static readonly Dictionary<int, GUIStyle> _glass = new Dictionary<int, GUIStyle>(); private static string _volDragKey; private static bool _meKnown; private static bool _mePrompt; private static bool _meReady; private static bool _meHasReady; private static bool _meMissionPicked; private static string _meKey = ""; private static float _meKeySearchAt = -10f; private static bool _meKeyLogged; private static bool _mePickedLogged; private static bool _meReadyWarned; private static float _meReadySince = -1f; private static bool _meCardReady; private static bool _meCardReadyKnown; private static float _meReadyPendingAt = -1f; private static float _meLastReadyAt = -10f; private static float _mePromptFlipAt = -10f; private static float _mePromptFlipPrev = -20f; private static int _meLevel; private static string _meRank = ""; private static string _meXpText = ""; private static string _meReadyText = ""; private static float _meXpFrac; private static float _meDrawnAt = -10f; private static GameObject _meGo; private static readonly List<WalletChip> _chips = new List<WalletChip>(); private static GUI_PlayerWallet _wallet; private static float _walletSearchAt; private static Rect _walletRect; private static readonly Dictionary<string, Texture2D> _chipIcons = new Dictionary<string, Texture2D>(); private static string _homeSaved; private static readonly Regex Tags = new Regex("<[^>]*>", RegexOptions.Compiled); private static bool _meWarned; private static bool _walletWarned; private static string _meLogged; private static string _walletLogged; private static CanvasGroup _groupMe; private static CanvasGroup _groupWallet; private static float _alphaMe; private static float _alphaWallet; private static bool _meHidden; private static readonly Color ReadyAmber = new Color(1f, 0.72f, 0.15f); private static float _readyFlash = 1f; private const float PopTime = 0.4f; private const float PingEvery = 1.6f; private const float PingTime = 0.9f; private const float BounceTime = 0.3f; private static bool _readyWasUp; private static float _readyShownAt; private static HostView _host; private static float _hostReadAt = -10f; private static float _hostActAt = -10f; private static bool _hostLogged; private static bool _hostWarned; private static bool _hostActWarned; private static string[] _regionWire; private static string _appliedSig; private static int _draftMin = -1; private static int _draftMax = -1; private static int _draftFriends = -1; private const int ListTries = 3; private static bool _listChecking; private static bool _listSearching; private static bool _listSawPending; private static int _listTry; private static float _listStartedAt = -1f; private static float _listRetryAt = -1f; private static float _listDoneAt = -1f; private static float _autoCheckAt = -1f; private static int _listResult; private static int _listCount; private static string _listSession; private static readonly Color FieldLabel = new Color(0.25f, 1f, 0.4f, 0.75f); private static readonly Color Muted = new Color(0.62f, 0.69f, 0.64f); private static readonly Color ChipInk = new Color(0.81f, 0.84f, 0.86f); private static readonly Color PuckGrey = new Color(0.72f, 0.75f, 0.78f); private const int FocusNone = 0; private const int FocusName = 1; private const int FocusPassword = 2; private static int _hostFocus; private static string _hostEdit = ""; private static Rect _nameBox; private static Rect _passBox; private static bool _warnedWrite; private static HostMode _appliedMode = (HostMode)(-1); private static bool _levelDrag; private static bool _levelDragHigh; private static int _levelLo = -1; private static int _levelHi = -1; private static readonly Color ToggleOff = new Color(0.047f, 0.059f, 0.067f); private static readonly Color ToggleOffLine = new Color(0.23f, 0.255f, 0.28f); private const float RegionHeadH = 26f; private const float RegionPuckH = 28f; private const float RegionPuckGap = 5f; private const float RegionBoxPad = 8f; private const int RegionsPerRow = 2; private static bool _layoutEdit; private static LayoutItem _lDrag; private static int _lCorner; private static Vector2 _lFrom; private static Rect _lRectFrom; private static float _lScaleFrom; private static Rect _lResetAll; private static Rect _lDone; private static Rect _lBar; private static readonly HashSet<LayoutItem> _lSel = new HashSet<LayoutItem>(); private static readonly Dictionary<LayoutItem, Rect> _lGroupFrom = new Dictionary<LayoutItem, Rect>(); private static bool _marquee; private static Vector2 _mFrom; private static Vector2 _mTo; private static readonly HashSet<LayoutItem> _mBase = new HashSet<LayoutItem>(); private static readonly Dictionary<LayoutItem, Rect> _lLabelRects = new Dictionary<LayoutItem, Rect>(); private static LayoutItem _pendingToggle; private static Vector2 _pendingFrom; private static Rect _pendingRect; private static bool _pendingMove; private static Rect _lTextTrack; private static Rect _lTextHit; private static float _notchSince = -1f; private static readonly Dictionary<LayoutItem, Rect> _lResetRects = new Dictionary<LayoutItem, Rect>(); private static Rect _ownBlockRect; private const int FauxMin = 2; private const int FauxMax = 11; private static int _fauxPlayers = 4; private static bool _fauxDrag; private static Rect _fauxTrack; private static Rect _fauxHit; private static readonly (string Name, int Level, Color Colour, string Station, float Health, float Shield)[] Faux = new(string, int, Color, string, float, float)[10] { (ChatFeed.PreviewName(0), 12, ChatFeed.PreviewPalette[0], "Cargo bay", 100f, 50f), (ChatFeed.PreviewName(1), 7, ChatFeed.PreviewPalette[1], "Bridge", 72f, 20f), (ChatFeed.PreviewName(2), 15, ChatFeed.PreviewPalette[2], "Engine room", 45f, 0f), (ChatFeed.PreviewName(3), 4, ChatFeed.PreviewPalette[3], "Turrets", 100f, 35f), (ChatFeed.PreviewName(4), 9, ChatFeed.PreviewPalette[4], "Core room", 28f, 0f), (ChatFeed.PreviewName(5), 11, ChatFeed.PreviewPalette[5], "In space", 90f, 50f), (ChatFeed.PreviewName(6), 3, ChatFeed.PreviewPalette[6], "Airlock", 60f, 10f), (ChatFeed.PreviewName(7), 14, ChatFeed.PreviewPalette[7], "Hangar bay", 100f, 50f), (ChatFeed.PreviewName(8), 6, ChatFeed.PreviewPalette[8], "Medbay", 85f, 25f), (ChatFeed.PreviewName(9), 10, ChatFeed.PreviewPalette[9], "Armory", 55f, 40f) }; private static readonly LayoutItem[] AllItems = new LayoutItem[5] { LayoutItem.Chat, LayoutItem.Crew, LayoutItem.Own, LayoutItem.Comms, LayoutItem.Wallet }; private static bool _sizeDrag; private static float _sizeTouchedAt = -10f; private static CanvasGroup _pmGroup; private static float _pmAlpha; private static bool _pmRaycasts; private static bool _pmInteractable; private static bool _pmHidden; private const float FadeOut = 0.35f; private static readonly Color FailAmber = new Color(1f, 0.66f, 0.2f); private static JoinAttempt _join; private static LobbyInfo _asked; private static IntPtr _askedReq; private static float _askedAt = -1000f; private static LoadingScreenPresentationBehaviour _loadingView; private static float _nextLoadingLook; private static TMP_Text _hiddenText; private static CanvasGroup _hiddenCancel; private static bool _joinWarned; private static float _cardH = -1f; private static float _cardAt = -10f; private static IntPtr _loggedFail; private const float ChangePing = 1.45f; private const float WashTime = 2.25f; private const float SeatIn = 0.28f; private const float RedIn = 0.43f; private const float RedOut = 1.18f; private const float MissionIn = 0.45f; private const float BlockStep = 0.095f; private const float BlockIn = 0.225f; private const float BlockOut = 0.7f; private const float MissionWindow = 1.6500001f; private const float NewOpen = 0.4f; private const float NewGlow = 3.1f; private const float GoneRedIn = 0.225f; private const float GoneFadeAt = 1.25f; private const float GoneCloseAt = 2.05f; private const float GoneEnd = 2.4f; private static readonly Color GoneRed = new Color(1f, 0.3f, 0.3f); private static readonly Dictionary<string, Seen> _seen = new Dictionary<string, Seen>(StringComparer.Ordinal); private static readonly List<Ghost> _ghosts = new List<Ghost>(); private static readonly List<Ghost> _segGhosts = new List<Ghost>(); private static bool _changesPrimed; private static bool _ghostRow; private static int _changeLogs; private const int ChevSteps = 9; private const float ChevPad = 2f; private const float ChevRes = 3f; private static readonly Texture2D[] _chevRings = (Texture2D[])(object)new Texture2D[9]; private const float LiveEvery = 5f; private const float GlowDown = 0.8f; private static float _liveEvery = 5f; private static float _liveAskedAt = -100f; private static float _lastResultsAt = -100f; private static float _glowDownAt = -100f; private static float _pendingSince = -1f; private static bool _liveAsked; private static bool _resortNext = true; private static bool _resortPending; private static bool _everLoaded; private static bool _liveWarned; private static readonly Dictionary<string, GUI_ServerListEntry> RowById = new Dictionary<string, GUI_ServerListEntry>(StringComparer.Ordinal); private static readonly List<string> OrderFriends = new List<string>(); private static readonly List<string> OrderPublic = new List<string>(); private static readonly List<string> OrderLocked = new List<string>(); private static bool _itemsWarned; private static LobbyInfo _joinWait; private static float _joinWaitAt; private const float LiveBarW = 5f; private const float LiveBarH = 14f; private const float LiveBarGap = 4f; private static bool _menuArmed = true; private static bool _menuWarned; private static bool _prologueLogged; private static float _menuSeenAt = -1f; private static float _nextMenuCheck; private static bool _hangarNext; private static float _hangarNextAt = -100f; private static float _leaveAt = -1f; private static IntPtr _leaveReq; private static bool _leaveGuest; private static GUI_MainMenu _menuInst; private static string _menuWaitLogged; private static float _cardShownAt = -1f; private static readonly Color TileAmber = new Color(1f, 0.72f, 0.15f); private static readonly Color TileCream = new Color(1f, 0.89f, 0.64f); private const float SheenEvery = 5f; private const float SheenIdle = 0.62f; private static readonly float[][] DownloadGlyph = new float[2][] { new float[14] { 0.417f, 0.125f, 0.583f, 0.125f, 0.583f, 0.458f, 0.75f, 0.458f, 0.5f, 0.75f, 0.25f, 0.458f, 0.417f, 0.458f }, new float[16] { 0.125f, 0.667f, 0.25f, 0.667f, 0.25f, 0.792f, 0.75f, 0.792f, 0.75f, 0.667f, 0.875f, 0.667f, 0.875f, 0.917f, 0.125f, 0.917f } }; private static Texture2D _sheen; private static Rect _tileRect; private static bool _tileHover; private static bool _tileLogged; private static float _updateOpenedAt = -10f; private static int _sheenW; private static int _sheenH; private static float[] _sheenMask; private static Color32[] _sheenPx; private static GUI_PauseMenu EscMenu { get { try { GUI_PauseMenu pauseMenu = gameGUI.PauseMenu; return ((Object)(object)pauseMenu != (Object)null && pauseMenu.IsOpen) ? pauseMenu : null; } catch { return null; } } } private static bool HostingPublic { get { ReadEscSeat(); return _hostingPublic; } } private static bool OnSomeoneElsesShip { get { ReadEscSeat(); return _escGuest; } } private static bool InOwnSession { get { ReadEscSeat(); return _escHost; } } public static bool Typing { get { if (!_typing) { return _cpListening; } return true; } } private static bool Open { get { try { return (Object)(object)_browser != (Object)null && _browser.IsOpen; } catch { return false; } } } private static bool OnJoinTab { get { try { GUI_ServerBrowserTab joinLobbyTab = _browser.m_JoinLobbyTab; if ((Object)(object)joinLobbyTab == (Object)null) { return false; } GUI_ServerBrowserTab currentlySelectedTab = _browser.CurrentlySelectedTab; if ((Object)(object)currentlySelectedTab != (Object)null) { return ((Il2CppObjectBase)currentlySelectedTab).Pointer == ((Il2CppObjectBase)joinLobbyTab).Pointer; } return (Object)(object)((Component)joinLobbyTab).gameObject != (Object)null && ((Component)joinLobbyTab).gameObject.activeInHierarchy; } catch { return false; } } } private static bool ModalUp { get { try { return ModalManager.ModalVisible; } catch { return false; } } } private static bool Active { get { if (Prefs.LobbyBrowser.Value && !_broken && Open) { return OnJoinTab; } return false; } } private static bool Drawing => Time.unscaledTime - _drawnAt < 0.5f; private static float MissionBodyWidth => Mathf.Round(Mathf.Max(100f * _s, _missionTextW + 14f * _s + 2f)); private static float MissionPuckWidth => Mathf.Round(28f * _s) + MissionBodyWidth; private static float ShipPuckWidth => Mathf.Round(Mathf.Max(96f * _s, _shipTextW + 20f * _s + 1f)); private static float PlayersCellWidth => Width("16/16", Body) + 8f * _s + (float)_mostSeats * 10f * _s; private static float JumpsCellWidth => 96f * _s + 16.5f * _s; private static float RegionCellWidth => 24f * _s + 6f * _s + _regionTextW + 2f; private static ModalRequest CurrentRequest { get { try { return ModalManager.ModalVisible ? ModalManager.CurrentModal : null; } catch { return null; } } } private static int Body => Mathf.RoundToInt(16f * _s); private static int Small => Mathf.RoundToInt(13f * _s); private static int Big => Mathf.RoundToInt(20f * _s); internal static bool EscOpen { get { if ((Object)(object)EscMenu != (Object)null) { return !ModalUp; } return false; } } private static int CpTiny => Mathf.RoundToInt(11f * _s); private static float CpWidth => Mathf.Round(360f * _s); private static float CpGap => Mathf.Round(16f * _s); private static bool CpBeside { get { if (Prefs.BrowserControlPanel != null && Prefs.BrowserControlPanel.Value && !_cpOff) { return _cpFits; } return false; } } internal static bool ListeningForKey => _cpListening; internal static bool CrewCardsShown { get { if (_cardsWanted && CardsMode) { return Prefs.ShowHud.Value; } return false; } } private static bool CardsMode { get { if (!Prefs.CrewCards.Value) { if (EscOpen) { return !_layoutEdit; } return false; } return true; } } internal static bool GameHudHidden { get; private set; } internal static Rect CrewTopRect => _crewTopRect; private static bool MeReady { get { if (!_meCardReadyKnown) { if (_meHasReady) { return _meReady; } return false; } return _meCardReady; } } private static bool MeCardUp { get { if (!_mission && _meKnown) { return Prefs.HangarCard.Value; } return false; } } private static bool ReadyBlockUp { get { if (_meKnown && _meMissionPicked) { return !MeReady; } return false; } } private static string ReadyKeyLabel { get { if (!string.IsNullOrEmpty(_meKey)) { return _meKey; } return "B"; } } private static bool OnHostTab { get { try { GUI_ServerBrowserTab currentlySelectedTab = _browser.CurrentlySelectedTab; if ((Object)(object)currentlySelectedTab == (Object)null) { return false; } GUI_ServerBrowserTab hostLobbyTab = _browser.m_HostLobbyTab; GUI_ServerBrowserTab updateLobbyTab = _browser.m_UpdateLobbyTab; return ((Object)(object)hostLobbyTab != (Object)null && ((Il2CppObjectBase)currentlySelectedTab).Pointer == ((Il2CppObjectBase)hostLobbyTab).Pointer) || ((Object)(object)updateLobbyTab != (Object)null && ((Il2CppObjectBase)currentlySelectedTab).Pointer == ((Il2CppObjectBase)updateLobbyTab).Pointer); } catch { return false; } } } private static bool HostActive { get { if (Prefs.LobbyBrowser.Value && !_broken && Open) { return OnHostTab; } return false; } } private static int CurLevelMin { get { if (_draftMin < 0) { return Prefs.HostLevelMin.Value; } return _draftMin; } } private static int CurLevelMax { get { if (_draftMax < 0) { return Prefs.HostLevelMax.Value; } return _draftMax; } } private static bool CurFriends { get { if (_draftFriends < 0) { return Prefs.HostFriendsWelcome.Value; } return _draftFriends == 1; } } internal static bool LayoutEditing => _layoutEdit; internal static bool HudClickable { get { if (EscOpen) { return !_layoutEdit; } return false; } } private static float GridStep => Math.Max(24f, Mathf.Round((float)Screen.height / 24f)); internal static bool ChatPreviewing { get { if (!_layoutEdit) { if (Hud.InSession && EscOpen) { if (!_sizeDrag) { return Time.unscaledTime - _sizeTouchedAt < 3f; } return true; } return false; } return true; } } internal static bool ChatBoxCustom { get { if (Prefs.ChatBoxW != null && Prefs.ChatBoxW.Value > 0.02f && Prefs.ChatBoxH.Value > 0.02f && Prefs.ChatBoxX.Value >= 0f) { return Prefs.ChatBoxY.Value >= 0f; } return false; } } internal static Rect ChatBoxPixels { get { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!ChatBoxCustom) { return ChatBoxStandard(); } float num = Mathf.Clamp01(Prefs.ChatBoxW.Value) * (float)Screen.width; float num2 = Mathf.Clamp01(Prefs.ChatBoxH.Value) * (float)Screen.height; float num3 = Mathf.Clamp(Prefs.ChatBoxX.Value * (float)Screen.width, 0f, Math.Max(0f, (float)Screen.width - num)); float num4 = Mathf.Clamp(Prefs.ChatBoxY.Value * (float)Screen.height, 0f, Math.Max(0f, (float)Screen.height - num2)); return new Rect(Mathf.Round(num3), Mathf.Round(num4), Mathf.Round(num), Mathf.Round(num2)); } } private static bool LivePaused { get { if (!ModalUp && _join == null && _joinWait == null) { return !OnJoinTab; } return true; } } private static bool UpdateShown { get { if (UpdateCheck.Result == UpdateCheck.State.Newer) { return !string.IsNullOrEmpty(UpdateCheck.Latest); } return false; } } private static void DrawBrowseButton() { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: 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_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) GUI_PauseMenu escMenu = EscMenu; if ((Object)(object)escMenu == (Object)null || ModalUp) { return; } Event current = Event.current; int depth = GUI.depth; try { _s = Mathf.Clamp((float)Screen.height / 1080f, 0.7f, 2.2f); _mono = false; _dim = 1f; Styles(); GUI.depth = -2000; string text = (HostingPublic ? "Manage Session" : "Host Game"); float num = Mathf.Round(40f * _s); float num2 = Mathf.Round(12f * _s); float num3 = Mathf.Round(Width("Browse lobbies", Body, bold: true) + 44f * _s); float num4 = Mathf.Round(Width(text, Body, bold: true) + 44f * _s); if (Time.unscaledTime >= _gapNext) { _gapCache = MenuGap(escMenu); _gapNext = Time.unscaledTime + 0.5f; } float? gapCache = _gapCache; float num5 = (gapCache.HasValue ? gapCache.Value : ((float)Screen.height * 0.588f)); float num6 = ((float)Screen.width - (num3 + num2 + num4)) / 2f; Rect val = default(Rect); ((Rect)(ref val))..ctor(Mathf.Round(num6), Mathf.Round(num5 - num / 2f), num3, num); bool flag = ((Rect)(ref val)).Contains(current.mousePosition); Round(val, Color.black, 0.88f, 10f); Round(val, Green, flag ? 0.2f : 0.1f, 10f); RoundLine2(val, Green, flag ? 0.9f : 0.55f, 10f); float num7 = ((Rect)(ref val)).x + (num3 - Width("Browse lobbies", Body, bold: true)) / 2f; TextAt(num7 + 1f, ((Rect)(ref val)).center.y - 0.6f * _s, "Browse lobbies", Body, Green, 0.55f, bold: true); TextAt(num7, ((Rect)(ref val)).center.y - 0.6f * _s, "Browse lobbies", Body, Green, 1f, bold: true); if (GUI.Button(val, GUIContent.none, _invisible)) { BrowseFromMenu(escMenu); } Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).xMax + num2, ((Rect)(ref val)).y, num4, num); float num8 = ((Rect)(ref val2)).x + (num4 - Width(text, Body, bold: true)) / 2f; if (OnSomeoneElsesShip) { Round(val2, ToggleOff, 1f, 10f); RoundLine(val2, ToggleOffLine, 1f, 10f); TextAt(num8 + 1f, ((Rect)(ref val2)).center.y - 0.6f * _s, text, Body, Grey, 0.55f, bold: true); TextAt(num8, ((Rect)(ref val2)).center.y - 0.6f * _s, text, Body, Grey, 1f, bold: true); } else { bool flag2 = ((Rect)(ref val2)).Contains(current.mousePosition); Round(val2, Color.black, 0.88f, 10f); Round(val2, Green, flag2 ? 0.2f : 0.1f, 10f); RoundLine2(val2, Green, flag2 ? 0.9f : 0.55f, 10f); TextAt(num8 + 1f, ((Rect)(ref val2)).center.y - 0.6f * _s, text, Body, Green, 0.55f, bold: true); TextAt(num8, ((Rect)(ref val2)).center.y - 0.6f * _s, text, Body, Green, 1f, bold: true); if (GUI.Button(val2, GUIContent.none, _invisible)) { HostFromMenu(escMenu); } } if (!_escLogged) { _escLogged = true; MelonLogger.Msg($"[browser] Esc menu: \"Browse lobbies\" at {val}, \"{text}\" beside it ({(gapCache.HasValue ? "in the measured gap" : "at the fallback height")}; {_gapNote})"); } } catch (Exception ex) { if (!_escWarned) { _escWarned = true; MelonLogger.Warning("[browser] could not draw Browse lobbies: " + ex.Message); } } finally { GUI.depth = depth; } } private static void HostFromMenu(GUI_PauseMenu pm) { try { GUI_ServerBrowser serverBrowser = pm.m_ServerBrowser; if ((Object)(object)serverBrowser == (Object)null) { MelonLogger.Warning("[browser] Host Game: the Esc menu has no lobby screen"); return; } pm.OpenServerBrowser(); _browser = serverBrowser; MelonLogger.Msg($"[browser] {(HostingPublic ? "Manage Session" : "Host Game")} from the Esc menu: V2T's host popup: {OnHostTab}"); } catch (Exception ex) { MelonLogger.Warning("[browser] Host Game failed: " + ex.Message); } } private static void ReadEscSeat() { float unscaledTime = Time.unscaledTime; if (unscaledTime - _hostingReadAt < 0.25f) { return; } _hostingReadAt = unscaledTime; _hostingPublic = false; _escGuest = false; _escHost = false; try { JoinSeat joinSeat = ChatBridge.Seat(); TextChatManager manager = ChatBridge.Manager; bool? obj; if (manager == null) { obj = null; } else { NetworkSessionData networkSessionData = ((NetworkedObject_Base)manager).m_NetworkSessionData; obj = ((networkSessionData == null) ? ((bool?)null) : ((ReactiveProperty<bool>)(object)networkSessionData.m_IsSessionPublic)?.Value); } bool? flag = obj; bool valueOrDefault = flag == true; _escGuest = joinSeat == JoinSeat.Guest; _escHost = joinSeat == JoinSeat.Host; _hostingPublic = joinSeat == JoinSeat.Host && BrowserModel.HostModeOf(mainMenu: false, joinSeat, valueOrDefault) == HostMode.Public; } catch { } } private static float? MenuGap(GUI_PauseMenu pm) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) try { Il2CppArrayBase<Selectable> componentsInChildren = ((Component)pm).gameObject.GetComponentsInChildren<Selectable>(false); if (componentsInChildren == null || componentsInChildren.Length < 2) { _gapNote = "no buttons found"; return null; } List<(float, float)> list = new List<(float, float)>(); for (int i = 0; i < componentsInChildren.Length; i++) { Selectable val = componentsInChildren[i]; if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } Rect? val2 = ScreenRect(((Component)val).GetComponent<RectTransform>(), ((Component)val).gameObject); if (!val2.HasValue) { continue; } Rect value = val2.Value; if (((Rect)(ref value)).height > 4f) { value = val2.Value; if (((Rect)(ref value)).height < (float)Screen.height * 0.2f) { value = val2.Value; float yMin = ((Rect)(ref value)).yMin; value = val2.Value; list.Add((yMin, ((Rect)(ref value)).yMax)); } } } list.Sort(((float Top, float Bottom) p, (float Top, float Bottom) q) => p.Top.CompareTo(q.Top)); float num = 0f; float value2 = 0f; float num2 = float.MinValue; foreach (var item in list) { if (num2 > float.MinValue && item.Item1 - num2 > num) { float num3 = (num2 + item.Item1) / 2f; if (num3 > (float)Screen.height * 0.3f && num3 < (float)Screen.height * 0.8f) { num = item.Item1 - num2; value2 = num3; } } num2 = Math.Max(num2, item.Item2); } _gapNote = $"{list.Count} buttons, widest gap {num:F0} px"; return (num > 20f) ? new float?(value2) : ((float?)null); } catch (Exception ex) { _gapNote = "measuring failed: " + ex.Message; return null; } } private static Rect? ScreenRect(RectTransform rt, GameObject go) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_008e: 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) //IL_00ad: 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 ((Object)(object)rt == (Object)null) { return null; } Canvas componentInParent = go.GetComponentInParent<Canvas>(); Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>(4L); rt.GetWorldCorners(val); Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null); float num = float.MaxValue; float num2 = float.MinValue; float num3 = float.MaxValue; float num4 = float.MinValue; for (int i = 0; i < 4; i++) { Vector3 val3 = (((Object)(object)val2 != (Object)null) ? Vector2.op_Implicit(RectTransformUtility.WorldToScreenPoint(val2, ((Il2CppArrayBase<Vector3>)(object)val)[i])) : ((Il2CppArrayBase<Vector3>)(object)val)[i]); num = Math.Min(num, val3.x); num2 = Math.Max(num2, val3.x); num3 = Math.Min(num3, val3.y); num4 = Math.Max(num4, val3.y); } return new Rect(num, (float)Screen.height - num4, num2 - num, num4 - num3); } private static Rect? MenuPanelRect(GUI_PauseMenu pm) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) try { GameObject menuParent = pm.m_MenuParent; if ((Object)(object)menuParent == (Object)null || !menuParent.activeInHierarchy) { return null; } RectTransform component = menuParent.GetComponent<RectTransform>(); if ((Object)(object)component == (Object)null) { return null; } Canvas componentInParent = menuParent.GetComponentInParent<Canvas>(); Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>(4L); component.GetWorldCorners(val); Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null); float num = float.MaxValue; float num2 = float.MinValue; float num3 = float.MaxValue; float num4 = float.MinValue; for (int i = 0; i < 4; i++) { Vector3 val3 = (((Object)(object)val2 != (Object)null) ? Vector2.op_Implicit(RectTransformUtility.WorldToScreenPoint(val2, ((Il2CppArrayBase<Vector3>)(object)val)[i])) : ((Il2CppArrayBase<Vector3>)(object)val)[i]); num = Math.Min(num, val3.x); num2 = Math.Max(num2, val3.x); num3 = Math.Min(num3, val3.y); num4 = Math.Max(num4, val3.y); } if (num2 - num < 20f || num4 - num3 < 20f) { return null; } return new Rect(num, (float)Screen.height - num4, num2 - num, num4 - num3); } catch { return null; } } private static void BrowseFromMenu(GUI_PauseMenu pm) { try { GUI_ServerBrowser serverBrowser = pm.m_ServerBrowser; if ((Object)(object)serverBrowser == (Object)null) { MelonLogger.Warning("[browser] Browse lobbies: the Esc menu has no lobby screen"); return; } pm.OpenServerBrowser(); _browser = serverBrowser; if (!ShowListTab(serverBrowser, out var wasShown)) { MelonLogger.Warning("[browser] Browse lobbies: the lobby screen has no list tab"); return; } MelonLogger.Msg($"[browser] Browse lobbies from the Esc menu: list tab {(wasShown ? "was there" : "was hidden, shown")}, now on the list: {OnJoinTab}"); } catch (Exception ex) { MelonLogger.Warning("[browser] Browse lobbies failed: " + ex.Message); } } private static void LoadFilters() { if (_filtersLoaded) { return; } _filtersLoaded = true; try { int val = Math.Max(0, Math.Min(10, Prefs.BrowserThreatMin.Value)); int val2 = Math.Max(0, Math.Min(10, Prefs.BrowserThreatMax.Value)); Filter.ThreatMin = Math.Min(val, val2); Filter.ThreatMax = Math.Max(val, val2); Filter.HiddenRegions.Clear(); foreach (string item in BrowserModel.ParseHidden(Prefs.BrowserHiddenRegions.Value)) { Filter.HiddenRegions.Add(item); } } catch (Exception ex) { MelonLogger.Warning("[browser] could not read the saved filters: " + ex.Message); } } private static void SaveFilters() { try { Prefs.BrowserThreatMin.Value = Filter.ThreatMin; Prefs.BrowserThreatMax.Value = Filter.ThreatMax; Prefs.BrowserHiddenRegions.Value = BrowserModel.HiddenText(Filter.HiddenRegions); MelonPreferences.Save(); } catch { } } private static string RegionLabel(string code) { if (!_regionNames.TryGetValue(code, out var value) || string.IsNullOrWhiteSpace(value)) { return BrowserModel.RegionName(code); } return value; } private static Color LevelColour(int v) { //IL_0004: 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_0030: Unknown result type (might be due to invalid IL or missing references) if (v <= 0) { return Green; } if (!_threatSeen.TryGetValue(v, out var value)) { return ThreatScale[Mathf.Clamp(v - 1, 0, ThreatScale.Length - 1)]; } return value; } private static void NoteRowLooks(LobbyInfo l) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(l.RegionCode) && !string.IsNullOrWhiteSpace(l.RegionText) && !string.Equals(l.RegionText, l.RegionCode, StringComparison.OrdinalIgnoreCase)) { _regionNames[l.RegionCode] = l.RegionText; } if (l.ThreatR >= 0f && l.Threat > 0) { _threatSeen[l.Threat] = new Color(l.ThreatR, l.ThreatG, l.ThreatB); } } private static float DrawThreatRange(float right, float y, float h, Event e) { //IL_00a6: 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_00ad: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Invalid comparison between Unknown and I4 //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Invalid comparison between Unknown and I4 //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) int num = 10; float num2 = Mathf.Round(12f * _s); float num3 = Mathf.Round(14f * _s); float num4 = Mathf.Max(1f, Mathf.Round(2f * _s)); float num5 = (float)(num + 1) * num2 + (float)num * num4; float num6 = Width("Threat", Small); Width("10–10", Small, bold: true); float num7 = 10f * _s; float num8 = 9f * _s; float num9 = ThreatRangeWidth(); Rect r = default(Rect); ((Rect)(ref r))..ctor(Mathf.Round(right - num9), y, num9, h); Vector2 mousePosition = e.mousePosition; RoundLine(r, Green, Filter.ThreatAll ? 0.35f : 0.9f, 7f); float num10 = ((Rect)(ref r)).x + num7; _threatLabel = new Rect(num10 - 4f * _s, y, num6 + 8f * _s, h); bool flag = !Filter.ThreatAll && ((Rect)(ref _threatLabel)).Contains(mousePosition); Text(new Rect(num10, y, num6 + 2f, h), "Threat", Small, (Color)(flag ? Ink : new Color(0.62f, 0.69f, 0.64f)), 1f, bold: false, (TextAnchor)3); float num11 = num10 + num6 + num8; float num12 = Mathf.Round(y + (h - num3) / 2f); _threatTrack = new Rect(num11 - num4, y, num5 + 2f * num4, h); _cellStep = num2 + num4; Rect r2 = default(Rect); for (int i = 0; i <= num; i++) { ((Rect)(ref r2))..ctor(Mathf.Round(num11 + (float)i * (num2 + num4)), num12, num2, num3); bool flag2 = i >= Filter.ThreatMin && i <= Filter.ThreatMax; Round(r2, flag2 ? LevelColour(i) : Empty, 1f, 2f); if (!Filter.ThreatAll && (i == Filter.ThreatMin || i == Filter.ThreatMax)) { float num13 = Mathf.Round(2f * _s); RoundLine2(new Rect(((Rect)(ref r2)).x - num13, ((Rect)(ref r2)).y - num13, ((Rect)(ref r2)).width + num13 * 2f, ((Rect)(ref r2)).height + num13 * 2f), Ink, 1f, 3f); } } string text = (Filter.ThreatAll ? "Any" : ((Filter.ThreatMin == Filter.ThreatMax) ? Filter.ThreatMin.ToString() : $"{Filter.ThreatMin}–{Filter.ThreatMax}")); TextAt(num11 + num5 + num8, y + h / 2f, text, Small, Filter.ThreatAll ? Grey : Ink, 1f, bold: true); if ((int)e.type == 0 && e.button == 0) { if (((Rect)(ref _threatTrack)).Contains(mousePosition)) { int v = CellAt(mousePosition.x, num11); _dragHigh = BrowserModel.GrabsHigh(Filter.ThreatMin, Filter.ThreatMax, v); BrowserModel.MoveEnd(Filter, _dragHigh, v); _threatDrag = true; _scroll = 0f; Arrange(); e.Use(); } else if (flag) { Filter.ThreatMin = 0; Filter.ThreatMax = num; _scroll = 0f; Arrange(); SaveFilters(); e.Use(); } } else if ((int)e.type == 3 && _threatDrag) { int v2 = CellAt(mousePosition.x, num11); int num14 = (_dragHigh ? Filter.ThreatMax : Filter.ThreatMin); BrowserModel.MoveEnd(Filter, _dragHigh, v2); if ((_dragHigh ? Filter.ThreatMax : Filter.ThreatMin) != num14) { Arrange(); } e.Use(); } else if ((int)e.type == 1 && _threatDrag) { _threatDrag = false; SaveFilters(); e.Use(); } return ((Rect)(ref r)).x; } private static float ThreatRangeWidth() { int num = 10; float num2 = Mathf.Round(12f * _s); float num3 = Mathf.Max(1f, Mathf.Round(2f * _s)); float num4 = (float)(num + 1) * num2 + (float)num * num3; float num5 = Width("Threat", Small); float num6 = Width("10–10", Small, bold: true); float num7 = 10f * _s; float num8 = 9f * _s; return Mathf.Round(num7 + num5 + num8 + num4 + num8 + num6 + num7); } private static int CellAt(float mx, float trackX) { return Mathf.Clamp(Mathf.FloorToInt((mx - trackX) / Mathf.Max(1f, _cellStep)), 0, 10); } private static float DrawRegionsButton(float right, float y, float h, Event e) { //IL_00ae: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017c: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) int count = BrowserModel.MenuRegions().Count; int count2 = Filter.HiddenRegions.Count; string text = ((count2 == 0) ? "Regions: All" : $"Regions: {count - count2} of {count}"); float num = 8f * _s; float num2 = Mathf.Round(Width(text, Small) + 22f * _s + num + 6f * _s); Rect val = default(Rect); ((Rect)(ref val))..ctor(Mathf.Round(right - num2), y, num2, h); _regionsButton = val; bool flag = _regionsOpen || count2 > 0; bool flag2 = ((Rect)(ref val)).Contains(e.mousePosition); if (flag) { Round(val, Green, _regionsOpen ? 0.22f : 0.14f, 7f); } else if (flag2) { Round(val, Green, 0.07f, 7f); } RoundLine(val, Green, flag ? 1f : 0.35f, 7f); Color c = (Color)(flag ? Green : new Color(0.62f, 0.69f, 0.64f)); Text(new Rect(((Rect)(ref val)).x + 11f * _s, y, num2, h), text, Small, c, 1f, bold: false, (TextAnchor)3); Icon(new Rect(((Rect)(ref val)).xMax - 11f * _s - num, y + (h - num) / 2f, num, num), _regionsOpen ? TriUp : TriDown, c, 1f); if ((int)e.type == 0 && e.button == 0 && flag2) { _regionsOpen = !_regionsOpen; e.Use(); } return ((Rect)(ref val)).x; } private static void MenuInput(Event e) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_004b: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if (!_regionsOpen) { return; } if ((int)e.type == 4 && (int)e.keyCode == 27) { _regionsOpen = false; e.Use(); } else if ((int)e.type == 6 && ((Rect)(ref _regionsMenu)).Contains(e.mousePosition)) { e.Use(); } else { if ((int)e.type != 0) { return; } Vector2 mousePosition = e.mousePosition; if (((Rect)(ref _regionsButton)).Contains(mousePosition)) { return; } if (((Rect)(ref _regionsMenu)).Contains(mousePosition)) { foreach (var menuHit in _menuHits) { var (val, _, _, _) = menuHit; if (((Rect)(ref val)).Contains(mousePosition)) { ApplyMenu(menuHit.Kind, menuHit.Index, menuHit.Code); break; } } e.Use(); } else { _regionsOpen = false; e.Use(); } } } private static void ApplyMenu(int kind, int index, string code) { switch (kind) { case 0: if (!Filter.HiddenRegions.Remove(code)) { Filter.HiddenRegions.Add(code); } break; case 1: BrowserModel.ToggleContinent(Filter, BrowserModel.Continents[index].Codes); break; case 2: Filter.HiddenRegions.Clear(); break; case 3: foreach (string item in BrowserModel.MenuRegions()) { Filter.HiddenRegions.Add(item); } break; case 4: BrowserModel.KeepGoodPing(Filter, RegionPing.Get); break; } _scroll = 0f; Arrange(); SaveFilters(); } private static void DrawRegionsMenu(Rect panel) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_08f7: Unknown result type (might be due to invalid IL or missing references) //IL_08fc: Unknown result type (might be due to invalid IL or missing references) //IL_0915: Unknown result type (might be due to invalid IL or missing references) //IL_0926: Unknown result type (might be due to invalid IL or missing references) //IL_0937: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_05da: Unknown result type (might be due to invalid IL or missing references) //IL_05ee: Unknown result type (might be due to invalid IL or missing references) //IL_065b: Unknown result type (might be due to invalid IL or missing references) //IL_06ea: Unknown result type (might be due to invalid IL or missing references) //IL_06a4: Unknown result type (might be due to invalid IL or missing references) //IL_06a9: Unknown result type (might be due to invalid IL or missing references) //IL_072d: Unknown result type (might be due to invalid IL or missing references) //IL_0726: Unknown result type (might be due to invalid IL or missing references) //IL_075f: Unknown result type (might be due to invalid IL or missing references) //IL_0758: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_07cc: Unknown result type (might be due to invalid IL or missing references) //IL_07de: Unknown result type (might be due to invalid IL or missing references) //IL_07d7: Unknown result type (might be due to invalid IL or missing references) //IL_0849: Unknown result type (might be due to invalid IL or missing references) //IL_085f: Unknown result type (might be due to invalid IL or missing references) _menuHits.Clear(); if (!_regionsOpen) { _regionsMenu = default(Rect); return; } (string, string[])[] continents = BrowserModel.Continents; Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); foreach (LobbyInfo item4 in _all) { if (!string.IsNullOrEmpty(item4.RegionCode)) { dictionary[item4.RegionCode] = ((!dictionary.TryGetValue(item4.RegionCode, out var value)) ? 1 : (value + 1)); } } float num = Mathf.Round(26f * _s); float num2 = Mathf.Round(14f * _s); float num3 = 8f * _s; float num4 = 0f; (string, string[])[] array = continents; for (int i = 0; i < array.Length; i++) { (string, string[]) tuple = array[i]; num4 = Mathf.Max(num4, Width(tuple.Item1, Small, bold: true) - 30f * _s); string[] item = tuple.Item2; foreach (string code in item) { num4 = Mathf.Max(num4, Width(RegionLabel(code), Small)); } } float num5 = 16f * _s + 6f * _s; float num6 = Width("99", Small); float num7 = 10f * _s; float num8 = Mathf.Round(num7 + num + num3 + num4 + num3 + num5 + num3 + num6 + num7); float num9 = Mathf.Round(26f * _s); float num10 = Mathf.Round(30f * _s); float num11 = 16f * _s; float num12 = 12f * _s; float num13 = 14f * _s; int num14 = 3; int num15 = (continents.Length + num14 - 1) / num14; float[] array2 = new float[num15]; for (int k = 0; k < continents.Length; k++) { array2[k / num14] = Mathf.Max(array2[k / num14], num10 + (float)continents[k].Item2.Length * num9 + 6f * _s); } float num16 = Mathf.Round(24f * _s); float num17 = num13 * 2f + (float)num14 * num8 + (float)(num14 - 1) * num11; float num18 = num13 * 2f + num16; float[] array3 = array2; foreach (float num19 in array3) { num18 += num19 + num12; } float num20 = Mathf.Clamp(((Rect)(ref _regionsButton)).xMax - num17, ((Rect)(ref panel)).x + 8f * _s, ((Rect)(ref panel)).xMax - num17 - 8f * _s); Rect val = default(Rect); ((Rect)(ref val))..ctor(Mathf.Round(num20), Mathf.Round(((Rect)(ref _regionsButton)).yMax + 6f * _s), Mathf.Round(num17), Mathf.Round(num18)); _regionsMenu = val; Fill(new Rect(((Rect)(ref val)).x + 4f * _s, ((Rect)(ref val)).y + 8f * _s, ((Rect)(ref val)).width, ((Rect)(ref val)).height), Color.black, 0.35f); Round(val, new Color(0.02f, 0.04f, 0.05f), 0.99f, 14f); RoundLine(val, Green, 0.6f, 14f); Vector2 mousePosition = Event.current.mousePosition; float num21 = ((Rect)(ref val)).y + num13; Rect r = default(Rect); Rect val2 = default(Rect); Rect item3 = default(Rect); for (int l = 0; l < num15; l++) { for (int m = 0; m < num14; m++) { int num22 = l * num14 + m; if (num22 >= continents.Length) { break; } (string, string[]) tuple2 = continents[num22]; ((Rect)(ref r))..ctor(((Rect)(ref val)).x + num13 + (float)m * (num8 + num11), num21, num8, array2[l]); Round(r, Color.white, 0.035f, 10f); int num23 = 0; string[] item = tuple2.Item2; foreach (string item2 in item) { if (!Filter.HiddenRegions.Contains(item2)) { num23++; } } ((Rect)(ref val2))..ctor(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, num10); if (((Rect)(ref val2)).Contains(mousePosition)) { Round(val2, Green, 0.06f, 10f); } float num24 = ((Rect)(ref val2)).y + num10 / 2f; Switch(new Rect(((Rect)(ref r)).x + num7, Mathf.Round(num24 - num2 / 2f), num, num2), num23 == tuple2.Item2.Length, num23 > 0 && num23 < tuple2.Item2.Length); TextAt(((Rect)(ref r)).x + num7 + num + num3, num24, tuple2.Item1, Small, Green, 1f, bold: true); string text = $"{num23}/{tuple2.Item2.Length}"; TextAt(((Rect)(ref r)).xMax - num7 - Width(text, Small), num24, text, Small, Grey, 1f); Fill(new Rect(((Rect)(ref r)).x + num7, ((Rect)(ref val2)).yMax - 1f, ((Rect)(ref r)).width - num7 * 2f, Mathf.Max(1f, _s)), Green, 0.18f); _menuHits.Add((val2, 1, num22, null)); for (int n = 0; n < tuple2.Item2.Length; n++) { string text2 = tuple2.Item2[n]; bool flag = !Filter.HiddenRegions.Contains(text2); ((Rect)(ref item3))..ctor(((Rect)(ref r)).x, ((Rect)(ref val2)).yMax + 3f * _s + (float)n * num9, ((Rect)(ref r)).width, num9); if (((Rect)(ref item3)).Contains(mousePosition)) { Round(new Rect(((Rect)(ref item3)).x + 4f * _s, ((Rect)(ref item3)).y + 1f, ((Rect)(ref item3)).width - 8f * _s, ((Rect)(ref item3)).height - 2f), Green, 0.06f, 6f); } float num25 = ((Rect)(ref item3)).y + num9 / 2f; Switch(new Rect(((Rect)(ref r)).x + num7, Mathf.Round(num25 - num2 / 2f), num, num2), flag, some: false); float num26 = ((Rect)(ref r)).x + num7 + num + num3; TextAt(num26, num25, Fit(RegionLabel(text2), Small, bold: false, num4), Small, flag ? Ink : Grey, 1f); int num27 = BrowserModel.PingTier(RegionPing.Get(text2)); Color val3 = ((num27 < 0) ? Grey : Tier[num27]); int num28 = ((num27 >= 0) ? (4 - num27) : 0); float num29 = num26 + num4 + num3; float num30 = num25 + 7f * _s; for (int num31 = 0; num31 < 4; num31++) { float num32 = (5f + (float)num31 * 3f) * _s; Fill(new Rect(num29 + (float)num31 * 6f * _s, num30 - num32, 4f * _s, num32), (num31 < num28) ? val3 : Empty, flag ? 1f : 0.45f); } int value2; int num33 = (dictionary.TryGetValue(text2, out value2) ? value2 : 0); string text3 = ((num33 > 0) ? num33.ToString() : "–"); TextAt(((Rect)(ref r)).xMax - num7 - Width(text3, Small), num25, text3, Small, Grey, 1f); _menuHits.Add((item3, 0, num22, text2)); } } num21 += array2[l] + num12; } float y = num21; float x = ((Rect)(ref val)).x + num13; float h = num16; Fill(new Rect(((Rect)(ref val)).x + num13, num21 - num12 / 2f, ((Rect)(ref val)).width - num13 * 2f, Mathf.Max(1f, _s)), Green, 0.15f); MenuButton(MenuButton(MenuButton(x, y, h, "All", 2, mousePosition), y, h, "None", 3, mousePosition), y, h, "Good ping only", 4, mousePosition); } private static float MenuButton(float x, float y, float h, string label, int kind, Vector2 mouse) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Round(Width(label, Small) + 20f * _s); Rect val = default(Rect); ((Rect)(ref val))..ctor(x, y, num, h); bool flag = ((Rect)(ref val)).Contains(mouse); if (flag) { Round(val, Green, 0.1f, 7f); } RoundLine(val, Green, flag ? 0.8f : 0.3f, 7f); Text(val, label, Small, (Color)(flag ? Green : new Color(0.62f, 0.69f, 0.64f)), 1f, bold: false, (TextAnchor)4); _menuHits.Add((val, kind, -1, null)); return x + num + 8f * _s; } private static void Switch(Rect r, bool on, bool some) { //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) //IL_001a: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) float radius = ((Rect)(ref r)).height / 2f / _s; Round(r, (on || some) ? Green : Empty, on ? 0.35f : (some ? 0.18f : 1f), radius); float num = ((Rect)(ref r)).height - 4f * _s; Round(new Rect(on ? (((Rect)(ref r)).xMax - 2f * _s - num) : (some ? (((Rect)(ref r)).center.x - num / 2f) : (((Rect)(ref r)).x + 2f * _s)), ((Rect)(ref r)).y + 2f * _s, num, num), (Color)(on ? Green : (some ? new Color(0.25f, 1f, 0.4f, 0.7f) : Grey)), 1f, num / 2f / _s); } public static void Tick() { JoinTick(); MenuTick(); if (!Open) { if (_wasOpen) { _wasOpen = false; _typing = false; _unsubscribed = false; _searchFocus = false; _regionsOpen = false; _threatDrag = false; _hostFocus = 0; } return; } if (!_wasOpen) { _wasOpen = true; _scroll = 0f; _nextSnapshot = 0f; if (Prefs.LobbyBrowser.Value) { RegionPing.Start(); FriendLobbies.Refresh(); } if (!_logged) { _logged = true; LogLayout(); } LoadFilters(); _appliedSig = null; DropAccessDraft(); LiveOpened(); } if (!Prefs.LobbyBrowser.Value) { return; } HostTick(); RegionPing.Tick(); float unscaledTime = Time.unscaledTime; if (unscaledTime >= _nextSnapshot) { _nextSnapshot = unscaledTime + 0.3f; Snapshot(); } LiveTick(unscaledTime); JoinWaitTick(unscaledTime); bool flag = (Active && _searchFocus) || (HostActive && _hostFocus != 0); if (flag && !_unsubscribed) { try { _browser.UnsubscribeToInputEvents(); _unsubscribed = true; } catch { } } else if (!flag && _unsubscribed) { try { _browser.SubscribeToInputEvents(); } catch { } _unsubscribed = false; } _typing = flag; } public static void LateTick() { bool flag = (Active || HostActive) && (Drawing || ModalUp); try { if (flag) { Hide(); } else if (_hiding) { Unhide(); } DialogLateTick(); } catch (Exception ex) { if (!_warned) { _warned = true; MelonLogger.Warning("[browser] could not hide the game's lobby list: " + ex.Message); } } } private static void Hide() { GameObject gameObject = ((Component)_browser).gameObject; if ((Object)(object)_group == (Object)null || (Object)(object)((Component)_group).gameObject == (Object)null || ((Il2CppObjectBase)((Component)_group).gameObject).Pointer != ((Il2CppObjectBase)gameObject).Pointer) { _group = gameObject.GetComponent<CanvasGroup>(); _groupAdded = (Object)(object)_group == (Object)null; if (_groupAdded) { _group = gameObject.AddComponent<CanvasGroup>(); } Canvas componentInParent = gameObject.GetComponentInParent<Canvas>(); Canvas val = (((Object)(object)componentInParent != (Object)null) ? componentInParent.rootCanvas : null); _raycaster = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<GraphicRaycaster>() : null); if ((Object)(object)_raycaster != (Object)null) { _raycasterWasOn = ((Behaviour)_raycaster).enabled; } } _group.alpha = 0f; _group.interactable = false; _group.blocksRaycasts = false; if ((Object)(object)_raycaster != (Object)null) { ((Behaviour)_raycaster).enabled = false; } _hiding = true; } private static void Unhide() { _hiding = false; if ((Object)(object)_group != (Object)null) { _group.alpha = 1f; _group.interactable = true; _group.blocksRaycasts = true; } if ((Object)(object)_raycaster != (Object)null) { ((Behaviour)_raycaster).enabled = _raycasterWasOn; } } private static void Snapshot() { List<LobbyInfo> list = new List<LobbyInfo>(); bool flag = false; try { List<GUI_ServerListEntry> entryList = _browser.m_EntryList; IReadOnlyList<GUI_ServerListEntry> val = ((entryList != null) ? ((Il2CppObjectBase)entryList).TryCast<IReadOnlyList<GUI_ServerListEntry>>() : null); int num = ((entryList != null) ? ((Il2CppObjectBase)entryList).TryCast<IReadOnlyCollection<GUI_ServerListEntry>>() : null)?.Count ?? 0; string localKey = VoicePeers.LocalKey; DateTime utcNow = DateTime.UtcNow; List<LobbyInfo> list2 = new List<LobbyInfo>(); RowById.Clear(); for (int i = 0; i < num; i++) { GUI_ServerListEntry val2 = val[i]; if ((Object)(object)val2 == (Object)null) { continue; } LobbyInfo lobbyInfo = Read(val2, localKey, utcNow); if (lobbyInfo != null) { list2.Add(lobbyInfo); NoteRowLooks(lobbyInfo); if (!string.IsNullOrEmpty(lobbyInfo.Id)) { RowById[lobbyInfo.Id] = val2; } } } flag = ReadItems(list, localKey, utcNow); if (!flag) { list.AddRange(list2); AddOwn(list, localKey, utcNow); } } catch (Exception ex) { if (!_warned) { _warned = true; MelonLogger.Warning("[browser] could not read the lobby list: " + ex.Message); } } if (list.Count == 0 && _pending && _all.Count > 0) { return; } Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); List<LobbyInfo> list3 = new List<LobbyInfo>(list.Count); foreach (LobbyInfo item in list) { if (string.IsNullOrEmpty(item.Id)) { list3.Add(item); continue; } if (dictionary.TryGetValue(item.Id, out var value)) { list3[value] = item; continue; } dictionary[item.Id] = list3.Count; list3.Add(item); } if (list3.Count != list.Count && list3.Count != _dupesLoggedAt) { _dupesLoggedAt = list3.Count; MelonLogger.Msg($"[browser] the game's list holds {list.Count - list3.Count} lobbies twice - shown once"); } list = list3; NoteChanges(list, flag); _all = list; _listVersion++; if (!_sampled && list.Count > 0) { _sampled = true; LogSample(); } _longestRun = 0; foreach (LobbyInfo item2 in list) { _longestRun = Math.Max(_longestRun, item2.Jumps); } Arrange(Prefs.BrowserLive.Value && !_resortNext); _resortNext = false; } private static void AddOwn(List<LobbyInfo> list, string me, DateTime nowUtc) { try { OnlineSessionListData data = _browser.m_Data; ReactiveCollection<IOnlineSession> val = ((data != null) ? data.m_Items : null); if (val == null) { return; } string text = null; try { NetworkSessionData networkSessionData = _browser.m_NetworkSessionData; text = ((networkSessionData == null) ? null : ((ReactiveProperty<string>)(object)networkSessionData.m_SessionId)?.Value); } catch { } int count = ((Collection<IOnlineSession>)(object)val).Count; for (int i = 0; i < count; i++) { IOnlineSession obj2 = ((Collection<IOnlineSession>)(object)val)[i]; EpicSession val2 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast<EpicSession>() : null); if (val2 == null) { continue; } string id = val2.Id ?? ""; string a = val2.OwnerId ?? ""; if (((!string.IsNullOrEmpty(text) && string.Equals(id, text, StringComparison.OrdinalIgnoreCase)) || (!string.IsNullOrEmpty(me) && string.Equals(a, me, StringComparison.OrdinalIgnoreCase))) && !list.Exists((LobbyInfo x) => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase))) { LobbyInfo lobbyInfo = FromSession(val2); lobbyInfo.Full = lobbyInfo.MaxPlayers > 0 && lobbyInfo.Players >= lobbyInfo.MaxPlayers; lobbyInfo.RegionText = RegionLabel(lobbyInfo.RegionCode); string currentSpaceShipAssetGuid = val2.CurrentSpaceShipAssetGuid; string missionDataAssetGUID = val2.MissionDataAssetGUID; if (!string.IsNullOrEmpty(currentSpaceShipAssetGuid) && ShipByGuid.TryGetValue(currentSpaceShipAssetGuid, out var value)) { lobbyInfo.Ship = value; } if (!string.IsNullOrEmpty(missionDataAssetGUID) && MissionByGuid.TryGetValue(missionDataAssetGUID, out var value2)) { lobbyInfo.MissionRaw = value2; } lobbyInfo.Mission = BrowserModel.MissionName(lobbyInfo.MissionRaw, lobbyInfo.Threat); Finish(lobbyInfo, me, nowUtc); list.Add(lobbyInfo); if (!_ownLogged) { _ownLogged = true; MelonLogger.Msg("[browser] your own lobby added to the list (the game leaves it out): \"" + lobbyInfo.Name + "\"" + (string.IsNullOrEmpty(lobbyInfo.Ship) ? ", ship not seen on another lobby yet" : "")); } } } } catch (Exception ex) { if (!_ownWarned) { _ownWarned = true; MelonLogger.Warning("[browser] could not add your own lobby: " + ex.Message); } } } private static LobbyInfo FromSession(EpicSession s) { string text = s.Name ?? ""; return new LobbyInfo { Id = (s.Id ?? ""), V2T = text.Contains("\u200b\u2060\u200b"), Name = text.Replace("\u200b\u2060\u200b", "").Trim(), Host = (s.OwnerName ?? ""), HostId = (s.OwnerId ?? ""), RegionCode = (s.Region ?? ""), Players = s.CurrentMemberCount, MaxPlayers = s.MaxMemberCount, Jumps = s.NumberOfJumps, Threat = s.ChallengeRating, Password = s.IsPasswordProtected }; } private static LobbyInfo Read(GUI_ServerListEntry row, string me, DateTime nowUtc) { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) IOnlineSession sessionListItem = row.m_SessionListItem; EpicSession val = ((sessionListItem != null) ? ((Il2CppObjectBase)sessionListItem).TryCast<EpicSession>() : null); if (val == null) { return null; } LobbyInfo lobbyInfo = FromSession(val); lobbyInfo.Row = row; try { lobbyInfo.Full = row.IsFull; } catch { lobbyInfo.Full = lobbyInfo.MaxPlayers > 0 && lobbyInfo.Players >= lobbyInfo.MaxPlayers; } try { TMP_Text regionName = row.m_RegionName; lobbyInfo.RegionText = StripTags((regionName != null) ? regionName.text : null); } catch { } if (string.IsNullOrWhiteSpace(lobbyInfo.RegionText)) { lobbyInfo.RegionText = lobbyInfo.RegionCode; } try { TMP_Text shipTypeName = row.m_ShipTypeName; lobbyInfo.Ship = StripTags((shipTypeName != null) ? shipTypeName.text : null); } catch { } try { TMP_Text serverStatus = row.m_ServerStatus; lobbyInfo.MissionRaw = StripTags((serverStatus != null) ? serverStatus.text : null); } catch { } lobbyInfo.Mission = BrowserModel.MissionName(lobbyInfo.MissionRaw, lobbyInfo.Threat); try { Material challengeRatingIconMaterial = row.m_ChallengeRatingIconMaterial; if ((Object)(object)challengeRatingIconMaterial != (Object)null) { Color color = challengeRatingIconMaterial.GetColor(GUI_ServerListEntry.ThreatColorID); if (color.a > 0.05f && color.r + color.g + color.b > 0.2f) { lobbyInfo.ThreatR = color.r; lobbyInfo.ThreatG = color.g; lobbyInfo.ThreatB = color.b; } } } catch { } try { string currentSpaceShipAssetGuid = val.CurrentSpaceShipAssetGuid; string missionDataAssetGUID = val.MissionDataAssetGUID; if (!string.IsNullOrEmpty(currentSpaceShipAssetGuid) && !string.IsNullOrEmpty(lobbyInfo.Ship)) { ShipByGuid[currentSpaceShipAssetGuid] = lobbyInfo.Ship; } if (!string.IsNullOrEmpty(missionDataAssetGUID) && !string.IsNullOrEmpty(lobbyInfo.MissionRaw)) { MissionByGuid[missionDataAssetGUID] = lobbyInfo.MissionRaw; } } catch { } Finish(lobbyInfo, me, nowUtc); return lobbyInfo; } private static void Finish(LobbyInfo l, string me, DateTime nowUtc) { if (l.V2T && CrewShare.LevelsFor(l.Id, l.HostId, out var min, out var max)) { l.LevelMin = min; l.LevelMax = max; l.Name = BrowserModel.StripLevelTag(l.Name).TrimEnd(); } l.Mine = !string.IsNullOrEmpty(me) && string.Equals(l.HostId, me, StringComparison.OrdinalIgnoreCase); l.OutOfLevel = !l.Mine && l.LevelMin > 0 && !BrowserModel.FitsLobby(Prefs.MyLevel.Value, l.LevelMin, l.LevelMax); l.FriendName = (l.Mine ? null : FriendLobbies.FriendFor(l.HostId)); if (!l.Mine && RecentPlayers.TryGet(l.HostId, out var seenUtc, out var _) && BrowserModel.IsRecent(seenUtc, nowUtc)) { l.PlayedWith = seenUtc; } l.PingMs = RegionPing.Get(l.RegionCode); l.Crew = CrewShare.For(l.Id, l.HostId); if (l.Crew == null) { return; } for (int i = 1; i < l.Crew.Count; i++) { if (FriendLobbies.FriendForTail(l.Crew[i].IdTail) != null) { l.FriendInside = true; break; } } } private static string StripTags(string s) { if (string.IsNullOrEmpty(s)) { return ""; } StringBuilder stringBuilder = new StringBuilder(s.Length); bool flag = false; foreach (char c in s) { if (c == '<') { flag = true; } else if (c == '>' && flag) { flag = false; } else if (!flag) { stringBuilder.Append(c); } } return stringBuilder.ToString().Trim(); } private static void Join(LobbyInfo l) { if (l == null || l.Mine) { return; } float unscaledTime = Time.unscaledTime; if (!(unscaledTime - _joinAt < 1.5f)) { _joinAt = unscaledTime; GUI_ServerListEntry val = FindRow(l.Id); if ((Object)(object)val == (Object)null) { _joinWait = l; _joinWaitAt = unscaledTime; MelonLogger.Msg("[browser] \"" + l.Name + "\": its row is being rebuilt - joining as soon as it is back"); } else { JoinRow(l, val); } } } private static void JoinRow(LobbyInfo l, GUI_ServerListEntry row) { try { MelonLogger.Msg($"[browser] joining \"{l.Name}\" (host {l.Host}, {l.RegionCode}, {l.Players}/{l.MaxPlayers})"); _asked = l; _askedAt = Time.unscaledTime; _askedReq = IntPtr.Zero; row.Join(); } catch (Exception ex) { MelonLogger.Warning("[browser] could not join: " + ex.Message); } } private static void SortBy(SortKey key) { if (_sort == key) { _desc = !_desc; } else { _sort = key; _desc = BrowserModel.DefaultDescending(key); } _scroll = 0f; Arrange(); } public static void Draw() { if (_join != null) { DrawJoin(); } else { if (DrawLeaveDialog()) { return; } if (Prefs.LobbyBrowser.Value && !_broken && !Open && !_layoutEdit) { DrawBrowseButton(); } if (!Open) { DrawControlPanel(); } if (Open) { try { DrawScreens(); } finally { DrawModeSwitch(); } } } } private static void DrawScreens() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison betwee
UserLibs/NAudio.Core.dll
Decompiled a month 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.4.0.0")] [assembly: AssemblyInformationalVersion("2.4.0+7c855e6737435f781dcbac782930a0de7a13cb2b")] [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.4.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 != MmResult.NoError) { 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 ArgumentException("Incorrect length for IEEE extended.", "bytes"); } 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; } base.Dispose(disposing); } } 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 & 0xFF); } 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: nextSubChunk.GetData(); break; } } if (!flag) { throw new InvalidDataException("Missing SoundFont version information"); } if (!flag2) { throw new InvalidDataException("Missing SoundFont name information"); } } public override string ToString() { return $"Bank Name: {BankName}\r\nAuthor: {Author}\r\nCopyright: {Copyright}\r\nCreation Date: {CreationDate}\r\nTools: {Tools}\r\nComments: {Comments}\r\nSound Engine: {WaveTableSoundEngine}\r\nSoundFont Version: {SoundFontVersion}\r\nTarget Product: {TargetProduct}\r\nData ROM: {DataROM}\r\nROM Version: {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 & 0x7F); } 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("value", "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 + ")"); } RiffChunk nextSubChunk; while ((nextSubChunk = chunk.GetNextSubChunk()) != null) { if (nextSubChunk.ChunkID == "smpl") { SampleData = nextSubChunk.GetData(); } } if (SampleData == null) { SampleData = new byte[0]; } } } 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 ushort Major { get; set; } public ushort 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.ReadUInt16(); sFVersion.Minor = br.ReadUInt16(); 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(int size) { return ByteArrayExtensions.Concat(Encoding.UTF8.GetBytes("ID3"), new byte[2] { 3, 0 }, new byte[1], GetId3TagHeaderSize(size)); } private static Stream CreateId3v2TagStream(IEnumerable<KeyValuePair<string, string>> tags) { List<byte[]> list = new List<byte[]>(); int num = 0; foreach (KeyValuePair<string, string> tag in tags) { byte[] array = CreateId3v2Frame(tag.Key, tag.Value); list.Add(array); num += array.Length; } byte[] array2 = CreateId3v2TagHeader(num); MemoryStream memoryStream = new MemoryStream(array2.Length + num); memoryStream.Write(array2, 0, array2.Length); foreach (byte[] item in list) { memoryStream.Write(item, 0, item.Length); } memoryStream.Position = 0L; return memoryStream; } public static bool TrySkipTag(Stream input) { if (input == null) { throw new ArgumentNullException("input"); } if (!input.CanSeek || input.Length - input.Position < 10) { return false; } long position = input.Position; if (!TryReadTagHeader(new BinaryReader(input), out var dataLength, out var footerLength)) { input.Position = position; return false; } long num = position + 10 + dataLength + footerLength; if (num > input.Length) { input.Position = position; return false; } input.Position = num; return true; } private static int ReadSynchsafeInt32(byte[] bytes, int offset) { return bytes[offset] * 2097152 + bytes[offset + 1] * 16384 + bytes[offset + 2] * 128 + bytes[offset + 3]; } private static bool TryReadTagHeader(BinaryReader reader, out int dataLength, out int footerLength) { dataLength = 0; footerLength = 0; byte[] array = reader.ReadBytes(10); if (array.Length < 10) { return false; } if (array[0] != 73 || array[1] != 68 || array[2] != 51) { return false; } if ((array[6] & 0x80) != 0 || (array[7] & 0x80) != 0 || (array[8] & 0x80) != 0 || (array[9] & 0x80) != 0) { return false; } dataLength = ReadSynchsafeInt32(array, 6); footerLength = (((array[5] & 0x10) == 16) ? 10 : 0); return true; } private static void SkipBytes(BinaryReader reader, int bytesToSkip) { if (bytesToSkip <= 0) { return; } byte[] array = new byte[Math.Min(4096, bytesToSkip)]; while (bytesToSkip > 0) { int num = reader.Read(array, 0, Math.Min(array.Length, bytesToSkip)); if (num > 0) { bytesToSkip -= num; continue; } break; } } private Id3v2Tag(Stream input) { tagStartPosition = input.Position; BinaryReader binaryReader = new BinaryReader(input); if (TryReadTagHeader(binaryReader, out var dataLength, out var footerLength)) { SkipBytes(binaryReader, dataLength); SkipBytes(binaryReader, footerLength); 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; private const int ConsecutiveFrameHeadersRequired = 2; 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) { Id3v2Tag.TrySkipTag(input); 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) || !IsLikelyAudioFrameSequence(input, 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 static bool IsLikelyAudioFrameSequence(Stream input, Mp3Frame firstFrame) { if (!input.CanSeek) { return true; } long position = input.Position; long num = firstFrame.FileOffset; Mp3Frame mp3Frame = firstFrame; try { for (int i = 0; i < 2; i++) { num += mp3Frame.FrameLength; if (num > input.Length - 4) { return true; } input.Position = num; byte[] array = new byte[4]; if (input.Read(array, 0, array.Length) < array.Length) { return false; } Mp3Frame mp3Frame2 = new Mp3Frame(); if (!IsValidHeader(array, mp3Frame2)) { return num + firstFrame.FrameLength >= input.Length; } if (mp3Frame2.MpegVersion != firstFrame.MpegVersion || mp3Frame2.MpegLayer != firstFrame.MpegLayer || mp3Frame2.SampleRate != firstFrame.SampleRate) { return num + firstFrame.FrameLength >= input.Length; } mp3Frame = mp3Frame2; } return true; } finally { input.Position = position; } } 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]; if ((headerBytes[3] & 3) == 2) { return false; } 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 ((num2 & 1) != 0) { xingHeader.framesOffset = num; num += 4; } if ((num2 & 2) != 0) { xingHeader.bytesOffset = num; num += 4; } if ((num2 & 4) != 0) { xingHeader.tocOffset = num; num += 100; } if ((num2 & 8) != 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)((uint)waveFormatTag ^ (uint)channels ^ (uint)sampleRate ^ (uint)averageBytesPerSecond ^ (uint)blockAlign) ^ (int)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)(n & 0xFF) }; } private byte[] SwapEndian(int n) { return new byte[4] { (byte)((n >> 24) & 0xFF), (byte)((n >> 16) & 0xFF), (byte)((n >> 8) & 0xFF), (byte)(n & 0xFF) }; } 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) { int num = format.BitsPerSample / 8; if (num <= 1) { outStream.Write(data, offset, count); } else { byte[] array = new byte[count]; int num2 = count - count % num; for (int i = 0; i < num2; i += num) { for (int j = 0; j < num; j++) { array[i + j] = data[offset + i + (num - 1 - j)]; } } for (int k = num2; k < count; k++) { array[k] = data[offset + k]; } outStream.Write(array, 0, count); } dataChunkSize += count; } private static int ConvertFloatTo32BitPcm(float sample) { if (sample >= 1f) { return int.MaxValue; } if (sample <= -1f) { return int.MinValue; } return (int)((double)sample * 2147483647.0); } public void WriteSample(float sample) { if (WaveFormat.BitsPerSample == 16) { writer.Write(SwapEndian((short)(32767f * sample))); dataChunkSize += 2L; return; } if (WaveFormat.BitsPerSample == 24) { byte[] bytes = BitConverter.GetBytes(ConvertFloatTo32BitPcm(sample)); value24[2] = bytes[1]; value24[1] = bytes[2]; value24[0] = bytes[3]; writer.Write(value24); dataChunkSize += 3L; return; } if (WaveFormat.BitsPerSample == 32 && WaveFormat.Encoding == WaveFormatEncoding.Extensible) { writer.Write(SwapEndian(ConvertFloatTo32BitPcm(sample))); dataChunkSize += 4L; return; } if (WaveFormat.BitsPerSample == 32 && WaveFormat.Encoding == WaveFormatEncoding.IeeeFloat) { byte[] bytes2 = BitConverter.GetBytes(sample); if (BitConverter.IsLittleEndian) { Array.Reverse((Array)bytes2); } writer.Write(bytes2); dataChunkSize += 4L; return; } throw new InvalidOperationException("Only 16, 24 or 32 bit PCM or IEEE float audio data supported"); } 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++) { int num = samples[j + offset] << 8; value24[0] = (byte)((num >> 16) & 0xFF); value24[1] = (byte)((num >> 8) & 0xFF); value24[2] = (byte)(num & 0xFF); 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++) { int n = samples[k + offset] << 16; writer.Write(SwapEndian(n)); } 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; } } base.Dispose(disposing); } 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 BinaryWriter writer; private readonly long dataChunkSizePosition; private long dataLength; private bool isDisposed; public BwfWriter(string filename, WaveFormat format, BextChunkInfo bextChunkInfo) { if (filename == null) { throw new ArgumentNullException("filename"); } if (format == null) { throw new ArgumentNullException("format"); } if (bextChunkInfo == null) { throw new ArgumentNullException("bextChunkInfo"); } this.format = format; try { 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); } catch { writer?.Dispose(); throw; } } public void Write(byte[] buffer, int offset, int count) { if (isDisposed) { throw new ObjectDisposedException("BwfWriter"); } if (buffer == null) { throw new ArgumentNullException("buffer"); } writer.Write(buffer, offset, count); dataLength += count; } public void Flush() { if (isDisposed) { throw new ObjectDisposedException("BwfWriter"); } 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() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!isDisposed) { if (disposing && writer != null) { 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_
UserLibs/NAudio.Wasapi.dll
Decompiled a month 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.4.0.0")] [assembly: AssemblyInformationalVersion("2.4.0+7c855e6737435f781dcbac782930a0de7a13cb2b")] [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.4.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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][MarshalAs(UnmanagedType.LPStruct)] 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 { 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; } } public static IEnumerable<IMFActivate> EnumerateTransforms(Guid category) { MediaFoundationInterop.MFTEnumEx(category, _MFT_ENUM_FLAG.MFT_ENUM_FLAG_ALL, null, null, out var interfacesPointer, out var pcMFTActivate); IMFActivate[] array = new IMFActivate[pcMFTActivate]; for (int i = 0; i < pcMFTActivate; i++) { IntPtr pUnk = Marshal.ReadIntPtr(new IntPtr(interfacesPointer.ToInt64() + i * Marshal.SizeOf(interfacesPointer))); array[i] = (IMFActivate)Marshal.GetObjectForIUnknown(pUnk); } IMFActivate[] array2 = array; for (int j = 0; j < array2.Length; j++) { yield return array2[j]; } Marshal.FreeCoTaskMem(interfacesPointer); } 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][MarshalAs(UnmanagedType.LPStruct)] MFT_REGISTER_TYPE_INFO pInputType, [In][MarshalAs(UnmanagedType.LPStruct)] 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 { private const int DefaultInputChunkDurationMs = 100; 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[GetInputChunkSize(sourceProvider.WaveFormat)]; outputBuffer = new byte[outputWaveFormat.AverageBytesPerSecond + outputWaveFormat.BlockAlign]; } private static int GetInputChunkSize(WaveFormat waveFormat) { int num = Math.Max(1, waveFormat.BlockAlign); int num2 = waveFormat.AverageBytesPerSecond * 100 / 1000; num2 -= num2 % num; if (num2 < num) { num2 = num; } return num2; } 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); transform = null; initializedForStreaming = false; } } 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 (disposed) { throw new ObjectDisposedException(GetType().FullName); } 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(); } try { transform.ProcessInput(0, iMFSample, 0); } finally { 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); IMFMediaBuffer ppBuffer = null; bool flag = false; try { 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: return 0; default: Marshal.ThrowExceptionForHR(num); break; case 0: break; } array[0].pSample.ConvertToContiguousBuffer(out ppBuffer); ppBuffer.Lock(out var ppbBuffer, out var _, out var pcbCurrentLength); flag = true; outputBuffer = BufferHelpers.Ensure(outputBuffer, pcbCurrentLength); Marshal.Copy(ppbBuffer, outputBuffer, 0, pcbCurrentLength); outputBufferOffset = 0; outputBufferCount = pcbCurrentLength; outputPosition += BytesToNsPosition(outputBufferCount, WaveFormat); return pcbCurrentLength; } finally { if (ppBuffer != null) { if (flag) { ppBuffer.Unlock(); } Marshal.ReleaseComObject(ppBuffer); } if (array[0].pEvents != null) { Marshal.ReleaseComObject(array[0].pEvents); } IMFSample pSample = array[0].pSample; if (pSample != null && pSample != iMFSample) { Marshal.ReleaseComObject(pSample); } iMFSample.RemoveAllBuffers(); Marshal.ReleaseComObject(iMFSample); Marshal.ReleaseComObject(iMFMediaBuffer); } } 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); bool flag = false; try { iMFMediaBuffer.Lock(out var ppbBuffer, out var _, out var _); flag = true; Marshal.Copy(sourceBuffer, 0, ppbBuffer, num); iMFMediaBuffer.Unlock(); flag = false; iMFMediaBuffer.SetCurrentLength(num); IMFSample iMFSample = MediaFoundationApi.CreateSample(); iMFSample.AddBuffer(iMFMediaBuffer); iMFSample.SetSampleTime(inputPosition); long num2 = BytesToNsPosition(num, sourceProvider.WaveFormat); iMFSample.SetSampleDuration(num2); inputPosition += num2; return iMFSample; } finally { if (flag) { iMFMediaBuffer.Unlock(); } Marshal.ReleaseComObject(iMFMediaBuffer); } } 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 { public static IEnumerable<DmoDescriptor> GetAudioEffectNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_EFFECT); } public static IEnumerable<DmoDescriptor> GetAudioEncoderNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_ENCODER); } public static IEnumerable<DmoDescriptor> GetAudioDecoderNames() { return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_DECODER); } private static IEnumerable<DmoDescriptor> GetDmos(Guid category) { Marshal.ThrowExceptionForHR(DmoInterop.DMOEnum(ref category, DmoEnumFlags.None, 0, null, 0, null, out var enumDmo)); int itemsFetched; do { enumDmo.Next(1, out var clsid, out var name, out itemsFetched); if (itemsFetched == 1) { string name2 = Marshal.PtrToStringUni(name); Marshal.FreeCoTaskMem(name); yield return new DmoDescriptor(name2, clsid); } } while (itemsFetched > 0); } } [Flags] internal enum DmoEnumFlags { None = 0, DMO_ENUMF_INCLUDE_KEYED = 1 } internal static class DmoGuids { public static readonly Guid DMOCATEGORY_AUDIO_DECODER = new Guid("57f2db8b-e6bb-4513-9d43-dcd2a6593125"); public static readonly Guid DMOCATEGORY_AUDIO_ENCODER = new Guid("33D9A761-90C8-11d0-BD43-00A0C911CE86"); public static readonly Guid DMOCATEGORY_VIDEO_DECODER = new Guid("4a69b442-28be-4991-969c-b500adf5d8a8"); public static readonly Guid DMOCATEGORY_VIDEO_ENCODER = new Guid("33D9A760-90C8-11d0-BD43-00A0C911CE86"); public static readonly Guid DMOCATEGORY_AUDIO_EFFECT = new Guid("f3602b3f-0592-48df-a4cd-674721e7ebeb"); public static readonly Guid DMOCATEGORY_VIDEO_EFFECT = new Guid("d990ee14-776c-4723-be46-3da2f56f10b9"); public static readonly Guid DMOCATEGORY_AUDIO_CAPTURE_EFFECT = new Guid("f665aaba-3e09-4920-aa5f-219811148f09"); } internal static class DmoMediaTypeGuids { public static readonly Guid FORMAT_None = new Guid("0F6417D6-C318-11D0-A43F-00A0C9223196"); public static readonly Guid FORMAT_VideoInfo = new Guid("05589f80-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_VideoInfo2 = new Guid("F72A76A0-EB0A-11d0-ACE4-0000C0CC16BA"); public static readonly Guid FORMAT_WaveFormatEx = new Guid("05589f81-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_MPEGVideo = new Guid("05589f82-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_MPEGStreams = new Guid("05589f83-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_DvInfo = new Guid("05589f84-c356-11ce-bf01-00aa0055595a"); public static readonly Guid FORMAT_525WSS = new Guid("C7ECF04D-4582-4869-9ABB-BFB523B62EDF"); } internal enum DmoHResults { DMO_E_INVALIDSTREAMINDEX = -2147220991, DMO_E_INVALIDTYPE, DMO_E_TYPE_NOT_SET, DMO_E_NOTACCEPTING, DMO_E_TYPE_NOT_ACCEPTED, DMO_E_NO_MORE_ITEMS } [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 greater than maximum buffer size"); } length = value; } } public MediaBuffer(int maxLength) { buffer = Marshal.AllocCoTaskMem(maxLength); this.maxLength = maxLength; } public void Dispose() { if (buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(buffer); buffer = IntPtr.Zero; GC.SuppressFinalize(this); } } ~MediaBuffer() { Dispose(); } int IMediaBuffer.SetLength(int length) { if (length > maxLength) { return -2147483645; } this.length = length; return 0; } int IMediaBuffer.GetMaxLength(out int maxLength) { maxLength = this.maxLength; return 0; } int IMediaBuffer.GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer) { if (bufferPointerPointer != IntPtr.Zero) { Marshal.WriteIntPtr(bufferPointerPointer, buffer); } if (validDataLengthPointer != IntPtr.Zero) { Marshal.WriteInt32(validDataLengthPointer, length); } return 0; } public void LoadData(byte[] data, int bytes) { Length = bytes; Marshal.Copy(data, 0, buffer, bytes); } public void RetrieveData(byte[] data, int offset) { Marshal.Copy(buffer, data, offset, Length); } } public class MediaObject : IDisposable { private IMediaObject mediaObject; private readonly int inputStreams; private readonly int outputStreams; public int InputStreamCount => inputStreams; public int OutputStreamCount => outputStreams; internal MediaObject(IMediaObject mediaObject) { this.mediaObject = mediaObject; mediaObject.GetStreamCount(out inputStreams, out outputStreams); } public DmoMediaType? GetInputType(int inputStream, int inputTypeIndex) { try { if (mediaObject.GetInputType(inputStream, inputTypeIndex, out var mediaType) == 0) { DmoInterop.MoFreeMediaType(ref mediaType); return mediaType; } } catch (COMException ex) { if (HResult.GetHResult(ex) != -2147220986) { throw; } } return null; } public DmoMediaType? GetOutputType(int outputStream, int outputTypeIndex) { try { if (mediaObject.GetOutputType(outputStream, outputTypeIndex, out var mediaType) == 0) { DmoInterop.MoFreeMediaType(ref mediaType); return mediaType; } } catch (COMException ex) { if (HResult.GetHResult(ex) != -2147220986) { throw; } } return null; } public DmoMediaType GetOutputCurrentType(int outputStreamIndex) { DmoMediaType mediaType; int outputCurrentType = mediaObject.GetOutputCurrentType(outputStreamIndex, out mediaType); switch (outputCurrentType) { case 0: DmoInterop.MoFreeMediaType(ref mediaType); return mediaType; case -2147220989: throw new InvalidOperationException("Media type was not set."); default: throw Marshal.GetExceptionForHR(outputCurrentType); } } public IEnumerable<DmoMediaType> GetInputTypes(int inputStreamIndex) { int typeIndex = 0; while (true) { DmoMediaType? inputType; DmoMediaType? dmoMediaType = (inputType = GetInputType(inputStreamIndex, typeIndex)); if (dmoMediaType.HasValue) { yield return inputType.Value; typeIndex++; continue; } break; } } public IEnumerable<DmoMediaType> GetOutputTypes(int outputStreamIndex) { int typeIndex = 0; while (true) { DmoMediaType? outputType; DmoMediaType? dmoMediaType = (outputType = GetOutputType(outputStreamIndex, typeIndex)); if (dmoMediaType.HasValue) { yield return outputType.Value; typeIndex++; continue; } break; } } public bool SupportsInputType(int inputStream
UserLibs/NAudio.WinMM.dll
Decompiled a month agousing System; 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: SupportedOSPlatform("windows")] [assembly: AssemblyCompany("NAudio.WinMM")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Mark Heath 2023")] [assembly: AssemblyFileVersion("2.4.0.0")] [assembly: AssemblyInformationalVersion("2.4.0+7c855e6737435f781dcbac782930a0de7a13cb2b")] [assembly: AssemblyProduct("NAudio.WinMM")] [assembly: AssemblyTitle("NAudio.WinMM")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/naudio/NAudio")] [assembly: AssemblyVersion("2.4.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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 { private MixerInterop.MIXERCAPS caps; private IntPtr mixerHandle; private MixerFlags mixerHandleType; public static int NumberOfDevices => MixerInterop.mixerGetNumDevs(); public int DestinationCount => (int)caps.cDestinations; public string Name => caps.szPname; public Manufacturers Manufacturer => (Manufacturers)caps.wMid; public int ProductID => caps.wPid; public IEnumerable<MixerLine> Destinations { get { for (int destination = 0; destination < DestinationCount; destination++) { yield return GetDestination(destination); } } } public static IEnumerable<Mixer> Mixers { get { for (int device = 0; device < NumberOfDevices; device++) { yield return new Mixer(device); } } } public Mixer(int mixerIndex) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (mixerIndex < 0 || mixerIndex >= NumberOfDevices) { throw new ArgumentOutOfRangeException("mixerIndex"); } 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 & 1) != 0) { mixerControlDetails.cChannels = 1; } else { mixerControlDetails.cChannels = nChannels; } if ((mixerControl.fdwControl & 2) != 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 & 2) != 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 { private MixerInterop.MIXERLINE mixerLine; private IntPtr mixerHandle; private MixerFlags mixerHandleType; public string Name => mixerLine.szName; public string ShortName => mixerLine.szShortName; public int LineId => mixerLine.dwLineID; public MixerLineComponentType ComponentType => mixerLine.dwComponentType; public string TypeDescription => mixerLine.dwComponentType switch { MixerLineComponentType.DestinationUndefined => "Undefined Destination", MixerLineComponentType.DestinationDigital => "Digital Destination", MixerLineComponentType.DestinationLine => "Line Level Destination", MixerLineComponentType.DestinationMonitor => "Monitor Destination", MixerLineComponentType.DestinationSpeakers => "Speakers Destination", MixerLineComponentType.DestinationHeadphones => "Headphones Destination", MixerLineComponentType.DestinationTelephone => "Telephone Destination", MixerLineComponentType.DestinationWaveIn => "Wave Input Destination", MixerLineComponentType.DestinationVoiceIn => "Voice Recognition Destination", MixerLineComponentType.SourceUndefined => "Undefined Source", MixerLineComponentType.SourceDigital => "Digital Source", MixerLineComponentType.SourceLine => "Line Level Source", MixerLineComponentType.SourceMicrophone => "Microphone Source", MixerLineComponentType.SourceSynthesizer => "Synthesizer Source", MixerLineComponentType.SourceCompactDisc => "Compact Disk Source", MixerLineComponentType.SourceTelephone => "Telephone Source", MixerLineComponentType.SourcePcSpeaker => "PC Speaker Source", MixerLineComponentType.SourceWaveOut => "Wave Out Source", MixerLineComponentType.SourceAuxiliary => "Auxiliary Source", MixerLineComponentType.SourceAnalog => "Analog Source", _ => "Invalid Component Type", }; public int Channels => mixerLine.cChannels; public int SourceCount => mixerLine.cConnections; public int ControlsCount => mixerLine.cControls; public bool IsActive => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_ACTIVE) != 0; public bool IsDisconnected => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_DISCONNECTED) != 0; public bool IsSource => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_SOURCE) != 0; public IEnumerable<MixerControl> Controls => MixerControl.GetMixerControls(mixerHandle, this, mixerHandleType); public IEnumerable<MixerLine> Sources { get { for (int source = 0; source < SourceCount; source++) { yield return GetSource(source); } } } public string TargetName => mixerLine.szPname; public MixerLine(IntPtr mixerHandle, int destinationIndex, MixerFlags mixerHandleType) { //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; 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 = new MmTime { wType = 4u }; MmException.Try(WaveInterop.waveInGetPosition(waveInHandle, out mmTime, Marshal.SizeOf(mmTime)), "waveInGetPosition"); if (mmTime.wType != 4) { throw new InvalidOperationException($"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 static int DeviceCount => WaveInterop.waveOutGetNumDevs(); 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 static WaveOutCapabilities GetCapabilities(int devNumber) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) WaveOutCapabilities waveOutCaps = default(WaveOutCapabilities); int waveOutCapsSize = Marshal.SizeOf(waveOutCaps); MmException.Try(WaveInterop.waveOutGetDevCaps((IntPtr)devNumber, out waveOutCaps, waveOutCapsSize), "waveOutGetDevCaps"); return waveOutCaps; } 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 = new MmTime { wType = 4u }; MmException.Try(WaveInterop.waveOutGetPosition(hWaveOut, ref mmTime, Marshal.SizeOf(mmTime)), "waveOutGetPosition"); if (mmTime.wType != 4) { throw new InvalidOperationException($"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][MarshalAs(UnmanagedType.LPStruct)] 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][MarshalAs(UnmanagedType.LPStruct)] AcmStreamHeaderStruct streamHeader, AcmStreamConvertFlags streamConvertFlags); [DllImport("Msacm32.dll")] public static extern MmResult acmStreamPrepareHeader(IntPtr hAcmStream, [In][Out][MarshalAs(UnmanagedType.LPStruct)] 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][MarshalAs(UnmanagedType.LPStruct)] 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) { throw new MmException(val, "acmStreamClose"); } } if (driverHandle != IntPtr.Zero) { AcmInterop.acmDriverClose(driverHandle, 0); driverHandle = IntPtr.Zero; } } ~AcmStream() { Dispose(disposing: false); } } internal class AcmStreamHeader : IDisposable { private AcmStreamHeaderStruct streamHeader; private GCHandle hSourceBuffer; private GCHandle hDestBuffer; private IntPtr streamHandle; private bool firstTime; private bool disposed; public byte[] SourceBuffer { get; private set; } public byte[] DestBuffer { get; private set; } public AcmStreamHeader(IntPtr streamHandle, int sourceBufferLength, int destBufferLength) { streamHeader = new AcmStreamHeaderStruct(); SourceBuffer = new byte[sourceBufferLength]; hSourceBuffer = GCHandle.Alloc(SourceBuffer, GCHandleType.Pinned); DestBuffer = new byte[destBufferLength]; hDestBuffer = GCHandle.Alloc(DestBuffer, GCHandleType.Pinned); this.streamHandle = streamHandle; firstTime = true; } private void Prepare() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) streamHeader.cbStruct = Marshal.SizeOf(streamHeader); streamHeader.sourceBufferLength = SourceBuffer.Length; streamHeader.sourceBufferPointer = hSourceBuffer.AddrOfPinnedObject(); streamHeader.destBufferLength = DestBuffer.Length; streamHeader.destBufferPointer = hDestBuffer.AddrOfPinnedObject(); MmException.Try(AcmInterop.acmStreamPrepareHeader(streamHandle, streamHeader, 0), "acmStreamPrepareHeader"); } private void Unprepare() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) streamHeader.sourceBufferLength = SourceBuffer.Length; streamHeader.sourceBufferPointer = hSourceBuffer.AddrOfPinnedObject(); streamHeader.destBufferLength = DestBuffer.Length; streamHeader.destBufferPointer = hDestBuffer.AddrOfPinnedObject(); MmResult val = AcmInterop.acmStreamUnprepareHeader(streamHandle, streamHeader, 0); if ((int)val != 0) { throw new MmException(val, "acmStreamUnprepareHeader"); } } public void Reposition() { firstTime = true; } public int Convert(int bytesToConvert, out int sourceBytesConverted) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) Prepare(); try { streamHeader.sourceBufferLength = bytesToConvert; streamHeader.sourceBufferLengthUsed = bytesToConvert; AcmStreamConvertFlags streamConvertFlags = (firstTime ? (AcmStreamConvertFlags.BlockAlign | AcmStreamConvertFlags.Start) : AcmStreamConvertFlags.BlockAlign); MmException.Try(AcmInterop.acmStreamConvert(streamHandle, streamHeader, streamConvertFlags), "acmStreamConvert"); firstTime = false; sourceBytesConverted = streamHeader.sourceBufferLengthUsed; } finally { Unprepare(); } return streamHeader.destBufferLengthUsed; } public void Dispose() { GC.SuppressFinalize(this); Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (!disposed) { SourceBuffer = null; DestBuffer = null; if (hSourceBuffer.IsAllocated) { hSourceBuffer.Free(); } if (hDestBuffer.IsAllocated) { hDestBuffer.Free(); } } disposed = true; } ~AcmStreamHeader() { Dispose(disposing: false); } } [Flags] internal enum AcmStreamHeaderStatusFlags { Done = 0x10000, Prepared = 0x20000, InQueue = 0x100000 } [StructLayout(LayoutKind.Sequential, Size = 128)] internal class AcmStreamHeaderStruct { public int cbStruct; public AcmStreamHeaderStatusFlags fdwStatus; public IntPtr userData; public IntPtr sourceBufferPointer; public int sourceBufferLength; public int sourceBufferLengthUsed; public IntPtr sourceUserData; public IntPtr destBufferPointer; public int destBufferLength; public int destBufferLengthUsed; public IntPtr destUserData; } [Flags] internal enum AcmStreamOpenFlags { Query = 1, Async = 2, NonRealTime = 4, CallbackTypeMask = 0x70000, CallbackNull = 0, CallbackWindow = 0x10000, CallbackTask = 0x20000, CallbackFunction = 0x30000, CallbackThread = 0x20000, CallbackEvent = 0x50000 } internal enum AcmStreamSizeFlags { Source, Destination } [StructLayout(LayoutKind.Sequential)] public class WaveFilter { public int StructureSize = Marshal.SizeOf(typeof(WaveFilter)); public int FilterTag; public int Filter; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public int[] Reserved; } }
UserLibs/Whisper.net.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Sources; using Microsoft.CodeAnalysis; using Whisper.net.Internals; using Whisper.net.Internals.ModelLoader; using Whisper.net.Internals.Native; using Whisper.net.Internals.Native.Implementations; using Whisper.net.Internals.Native.Implementations.Cuda; using Whisper.net.LibraryLoader; using Whisper.net.Logger; using Whisper.net.Native; using Whisper.net.SamplingStrategy; using Whisper.net.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("Sandro Hanea")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Cross-platform dotnet bindings for Whisper.")] [assembly: AssemblyFileVersion("1.8.1.0")] [assembly: AssemblyInformationalVersion("1.8.1+b36b61db21ed682c19ae96102318f6c815b00d2d")] [assembly: AssemblyProduct("Whisper.net")] [assembly: AssemblyTitle("Whisper.net")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/sandrohanea/whisper.net")] [assembly: InternalsVisibleTo("Whisper.net.Maui.Tests")] [assembly: InternalsVisibleTo("Whisper.net.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.8.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [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] [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] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] P_0) { TransformFlags = P_0; } } [CompilerGenerated] [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 Whisper.net { public class BeamSearchSamplingStrategyBuilder : IWhisperSamplingStrategyBuilder { private readonly BeamSearchSamplingStrategy beamSearchSamplingStrategy; public WhisperProcessorBuilder ParentBuilder { get; } internal BeamSearchSamplingStrategyBuilder(WhisperProcessorBuilder whisperProcessorBuilder, BeamSearchSamplingStrategy beamSearchSamplingStrategy) { ParentBuilder = whisperProcessorBuilder; this.beamSearchSamplingStrategy = beamSearchSamplingStrategy; } public BeamSearchSamplingStrategyBuilder WithBeamSize(int beamSize) { beamSearchSamplingStrategy.BeamSize = beamSize; return this; } public BeamSearchSamplingStrategyBuilder WithPatience(float patience) { beamSearchSamplingStrategy.Patience = patience; return this; } } public class GreedySamplingStrategyBuilder : IWhisperSamplingStrategyBuilder { private readonly GreedySamplingStrategy greedySamplingStrategy; public WhisperProcessorBuilder ParentBuilder { get; } internal GreedySamplingStrategyBuilder(WhisperProcessorBuilder parentBuilder, GreedySamplingStrategy greedySamplingStrategy) { ParentBuilder = parentBuilder; this.greedySamplingStrategy = greedySamplingStrategy; } public GreedySamplingStrategyBuilder WithBestOf(int bestOf) { greedySamplingStrategy.BestOf = bestOf; return this; } } public interface IStringPool { string? GetStringUtf8(IntPtr nativePointer); void ReturnString(string? returnedString); } public interface IWhisperSamplingStrategyBuilder { WhisperProcessorBuilder ParentBuilder { get; } } public enum WhisperAlignmentHeadsPreset { None, NTopMost, Custom, TinyEn, Tiny, BaseEn, Base, SmallEn, Small, MediumEn, Medium, LargeV1, LargeV2, LargeV3, LargeV3Turbo } public readonly struct WhisperAlignmentHead { public int TextLayer { get; } public int Head { get; } public WhisperAlignmentHead(int textLayer, int head) { TextLayer = textLayer; Head = head; } } public sealed class WhisperFactory : IDisposable { private readonly IWhisperProcessorModelLoader loader; private readonly Lazy<IntPtr> contextLazy; private readonly bool isEagerlyInitialized; private readonly StringPool stringPool = new StringPool(); private bool wasDisposed; private static readonly Lazy<LoadResult> libraryLoaded = new Lazy<LoadResult>(delegate { LoadResult loadResult = NativeLibraryLoader.LoadNativeLibrary(); if (loadResult.IsSuccess) { LogProvider.InitializeLogging(loadResult.NativeWhisper); } return loadResult; }, isThreadSafe: true); private WhisperFactory(IWhisperProcessorModelLoader loader, bool delayInit) { CheckLibraryLoaded(); this.loader = loader; if (!delayInit) { IntPtr nativeContext = loader.LoadNativeContext(libraryLoaded.Value.NativeWhisper); isEagerlyInitialized = true; contextLazy = new Lazy<IntPtr>(() => nativeContext); } else { contextLazy = new Lazy<IntPtr>(() => loader.LoadNativeContext(libraryLoaded.Value.NativeWhisper), isThreadSafe: false); } } public static string? GetRuntimeInfo() { CheckLibraryLoaded(); IntPtr intPtr = libraryLoaded.Value.NativeWhisper.WhisperPrintSystemInfo(); string result = Marshal.PtrToStringAnsi(intPtr); Marshal.FreeHGlobal(intPtr); return result; } public static IEnumerable<string> GetSupportedLanguages() { CheckLibraryLoaded(); for (int i = 0; i < libraryLoaded.Value.NativeWhisper.Whisper_Lang_Max_Id(); i++) { string text = Marshal.PtrToStringAnsi(libraryLoaded.Value.NativeWhisper.Whisper_Lang_Str(i)); if (!string.IsNullOrEmpty(text)) { yield return text; } } } public static WhisperFactory FromPath(string path) { return FromPath(path, WhisperFactoryOptions.Default); } public static WhisperFactory FromPath(string path, WhisperFactoryOptions options) { return new WhisperFactory(new WhisperProcessorModelFileLoader(path, options), options.DelayInitialization); } public static WhisperFactory FromBuffer(Memory<byte> memory) { return FromBuffer(memory, WhisperFactoryOptions.Default); } public static WhisperFactory FromBuffer(Memory<byte> memory, WhisperFactoryOptions options) { return new WhisperFactory(new WhisperProcessorModelMemoryLoader(memory, options), options.DelayInitialization); } public WhisperProcessorBuilder CreateBuilder() { if (wasDisposed) { throw new ObjectDisposedException("WhisperFactory"); } if (contextLazy.Value == IntPtr.Zero) { throw new WhisperModelLoadException("Failed to load the whisper model."); } return new WhisperProcessorBuilder(contextLazy.Value, libraryLoaded.Value.NativeWhisper, stringPool); } public void Dispose() { if (!wasDisposed) { if ((contextLazy.IsValueCreated || isEagerlyInitialized) && contextLazy.Value != IntPtr.Zero) { libraryLoaded.Value.NativeWhisper.Whisper_Free(contextLazy.Value); } loader.Dispose(); wasDisposed = true; } } private static void CheckLibraryLoaded() { if (!libraryLoaded.Value.IsSuccess) { throw new Exception("Failed to load native whisper library. Error: " + libraryLoaded.Value.ErrorMessage); } } } public struct WhisperFactoryOptions { public static WhisperFactoryOptions Default => new WhisperFactoryOptions(); public bool UseGpu { get; set; } public bool UseFlashAttention { get; set; } public bool UseDtwTimeStamps { get; set; } public WhisperAlignmentHeadsPreset HeadsPreset { get; set; } public WhisperAlignmentHead[]? CustomAlignmentHeads { get; set; } public int GpuDevice { get; set; } public uint DtwMemSize { get; set; } public int DtwNTop { get; set; } public bool DelayInitialization { get; set; } public WhisperFactoryOptions() { CustomAlignmentHeads = null; UseGpu = true; UseFlashAttention = false; UseDtwTimeStamps = false; HeadsPreset = WhisperAlignmentHeadsPreset.None; GpuDevice = 0; DtwMemSize = 134217728u; DtwNTop = -1; DelayInitialization = false; } } public class WhisperModelLoadException : Exception { public WhisperModelLoadException(string message) : base(message) { } } public sealed class WhisperProcessor : IAsyncDisposable, IDisposable { [CompilerGenerated] private sealed class <>c__DisplayClass26_0 { public ConcurrentQueue<SegmentData> buffer; public AsyncAutoResetEvent resetEvent; public WhisperProcessor <>4__this; internal void <ProcessAsync>b__2(Task _) { resetEvent.Set(); } } [CompilerGenerated] private sealed class <ProcessAsync>d__25 : IAsyncEnumerable<SegmentData>, IAsyncEnumerator<SegmentData>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine { public int <>1__state; public AsyncIteratorMethodBuilder <>t__builder; public ManualResetValueTaskSourceCore<bool> <>v__promiseOfValueOrEnd; private SegmentData <>2__current; private bool <>w__disposeMode; private CancellationTokenSource <>x__combinedTokens; private int <>l__initialThreadId; private Stream waveStream; public Stream <>3__waveStream; private CancellationToken cancellationToken; public CancellationToken <>3__cancellationToken; public WhisperProcessor <>4__this; private TaskAwaiter<float[]> <>u__1; private IAsyncEnumerator<SegmentData> <>7__wrap1; private object <>7__wrap2; private int <>7__wrap3; private ValueTaskAwaiter<bool> <>u__2; private ValueTaskAwaiter <>u__3; SegmentData IAsyncEnumerator<SegmentData>.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ProcessAsync>d__25(int <>1__state) { <>t__builder = AsyncIteratorMethodBuilder.Create(); this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } private void MoveNext() { int num = <>1__state; WhisperProcessor whisperProcessor = <>4__this; try { TaskAwaiter<float[]> awaiter2; ValueTaskAwaiter awaiter; float[] result; switch (num) { default: if (!<>w__disposeMode) { num = (<>1__state = -1); WaveParser waveParser = new WaveParser(waveStream); <>2__current = null; awaiter2 = waveParser.GetAvgSamplesAsync(cancellationToken).GetAwaiter(); if (!awaiter2.IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter2; <ProcessAsync>d__25 stateMachine = this; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine); return; } goto IL_00b8; } goto end_IL_000e; case 0: awaiter2 = <>u__1; <>u__1 = default(TaskAwaiter<float[]>); num = (<>1__state = -1); goto IL_00b8; case -4: case 1: try { ValueTaskAwaiter<bool> awaiter3; if (num != -4) { if (num != 1) { goto IL_0139; } awaiter3 = <>u__2; <>u__2 = default(ValueTaskAwaiter<bool>); num = (<>1__state = -1); goto IL_01a4; } num = (<>1__state = -1); if (!<>w__disposeMode) { goto IL_0139; } goto end_IL_00f1; IL_0139: <>2__current = null; awaiter3 = <>7__wrap1.MoveNextAsync().GetAwaiter(); if (!awaiter3.IsCompleted) { num = (<>1__state = 1); <>u__2 = awaiter3; <ProcessAsync>d__25 stateMachine = this; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine); return; } goto IL_01a4; IL_01a4: if (awaiter3.GetResult()) { SegmentData current = <>7__wrap1.Current; <>2__current = current; num = (<>1__state = -4); goto IL_031e; } end_IL_00f1:; } catch (object obj) { <>7__wrap2 = obj; } if (<>7__wrap1 == null) { break; } <>2__current = null; awaiter = <>7__wrap1.DisposeAsync().GetAwaiter(); if (!awaiter.IsCompleted) { num = (<>1__state = 2); <>u__3 = awaiter; <ProcessAsync>d__25 stateMachine = this; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); return; } goto IL_0231; case 2: { awaiter = <>u__3; <>u__3 = default(ValueTaskAwaiter); num = (<>1__state = -1); goto IL_0231; } IL_0231: awaiter.GetResult(); break; IL_00b8: result = awaiter2.GetResult(); <>7__wrap1 = whisperProcessor.ProcessAsync(result, cancellationToken).GetAsyncEnumerator(); <>7__wrap2 = null; <>7__wrap3 = 0; goto case -4; } object obj2 = <>7__wrap2; if (obj2 != null) { ExceptionDispatchInfo.Capture((obj2 as Exception) ?? throw obj2).Throw(); } _ = <>7__wrap3; if (!<>w__disposeMode) { <>7__wrap2 = null; <>7__wrap1 = null; } end_IL_000e:; } catch (Exception exception) { <>1__state = -2; <>7__wrap1 = null; <>7__wrap2 = null; if (<>x__combinedTokens != null) { <>x__combinedTokens.Dispose(); <>x__combinedTokens = null; } <>2__current = null; <>t__builder.Complete(); <>v__promiseOfValueOrEnd.SetException(exception); return; } <>1__state = -2; <>7__wrap1 = null; <>7__wrap2 = null; if (<>x__combinedTokens != null) { <>x__combinedTokens.Dispose(); <>x__combinedTokens = null; } <>2__current = null; <>t__builder.Complete(); <>v__promiseOfValueOrEnd.SetResult(result: false); return; IL_031e: <>v__promiseOfValueOrEnd.SetResult(result: true); } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } [DebuggerHidden] IAsyncEnumerator<SegmentData> IAsyncEnumerable<SegmentData>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)) { <ProcessAsync>d__25 <ProcessAsync>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = -3; <>t__builder = AsyncIteratorMethodBuilder.Create(); <>w__disposeMode = false; <ProcessAsync>d__ = this; } else { <ProcessAsync>d__ = new <ProcessAsync>d__25(-3) { <>4__this = <>4__this }; } <ProcessAsync>d__.waveStream = <>3__waveStream; if (<>3__cancellationToken.Equals(default(CancellationToken))) { <ProcessAsync>d__.cancellationToken = cancellationToken; } else if (cancellationToken.Equals(<>3__cancellationToken) || cancellationToken.Equals(default(CancellationToken))) { <ProcessAsync>d__.cancellationToken = <>3__cancellationToken; } else { <>x__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(<>3__cancellationToken, cancellationToken); <ProcessAsync>d__.cancellationToken = <>x__combinedTokens.Token; } return <ProcessAsync>d__; } [DebuggerHidden] ValueTask<bool> IAsyncEnumerator<SegmentData>.MoveNextAsync() { if (<>1__state == -2) { return default(ValueTask<bool>); } <>v__promiseOfValueOrEnd.Reset(); <ProcessAsync>d__25 stateMachine = this; <>t__builder.MoveNext(ref stateMachine); short version = <>v__promiseOfValueOrEnd.Version; if (<>v__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded) { return new ValueTask<bool>(<>v__promiseOfValueOrEnd.GetResult(version)); } return new ValueTask<bool>(this, version); } [DebuggerHidden] bool IValueTaskSource<bool>.GetResult(short token) { return <>v__promiseOfValueOrEnd.GetResult(token); } [DebuggerHidden] ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token) { return <>v__promiseOfValueOrEnd.GetStatus(token); } [DebuggerHidden] void IValueTaskSource<bool>.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { <>v__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags); } [DebuggerHidden] void IValueTaskSource.GetResult(short token) { <>v__promiseOfValueOrEnd.GetResult(token); } [DebuggerHidden] ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) { return <>v__promiseOfValueOrEnd.GetStatus(token); } [DebuggerHidden] void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { <>v__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags); } [DebuggerHidden] ValueTask IAsyncDisposable.DisposeAsync() { if (<>1__state >= -1) { throw new NotSupportedException(); } if (<>1__state == -2) { return default(ValueTask); } <>w__disposeMode = true; <>v__promiseOfValueOrEnd.Reset(); <ProcessAsync>d__25 stateMachine = this; <>t__builder.MoveNext(ref stateMachine); return new ValueTask(this, <>v__promiseOfValueOrEnd.Version); } } [CompilerGenerated] private sealed class <ProcessAsync>d__26 : IAsyncEnumerable<SegmentData>, IAsyncEnumerator<SegmentData>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine { public int <>1__state; public AsyncIteratorMethodBuilder <>t__builder; public ManualResetValueTaskSourceCore<bool> <>v__promiseOfValueOrEnd; private SegmentData <>2__current; private bool <>w__disposeMode; private CancellationTokenSource <>x__combinedTokens; private int <>l__initialThreadId; public WhisperProcessor <>4__this; private CancellationToken cancellationToken; public CancellationToken <>3__cancellationToken; private ReadOnlyMemory<float> samples; public ReadOnlyMemory<float> <>3__samples; private <>c__DisplayClass26_0 <>8__1; private Task <whisperTask>5__2; private ConfiguredTaskAwaitable<Task>.ConfiguredTaskAwaiter <>u__1; private ConfiguredTaskAwaitable.ConfiguredTaskAwaiter <>u__2; SegmentData IAsyncEnumerator<SegmentData>.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ProcessAsync>d__26(int <>1__state) { <>t__builder = AsyncIteratorMethodBuilder.Create(); this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } private void MoveNext() { int num = <>1__state; WhisperProcessor whisperProcessor = <>4__this; try { switch (num) { default: if (!<>w__disposeMode) { num = (<>1__state = -1); <>8__1 = new <>c__DisplayClass26_0(); <>8__1.<>4__this = <>4__this; <>8__1.resetEvent = new AsyncAutoResetEvent(); <>8__1.buffer = new ConcurrentQueue<SegmentData>(); break; } goto end_IL_000e; case -5: case -4: case 0: case 1: break; } try { ConfiguredTaskAwaitable<Task>.ConfiguredTaskAwaiter awaiter2; ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter; SegmentData result; switch (num) { default: whisperProcessor.options.OnSegmentEventHandlers.Add(OnSegmentHandler); whisperProcessor.options.WhisperAbortEventHandler = OnWhisperAbortHandler; whisperProcessor.currentCancellationToken = cancellationToken; <whisperTask>5__2 = whisperProcessor.ProcessInternalAsync(samples, cancellationToken).ContinueWith(delegate { <>8__1.resetEvent.Set(); }, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Default); goto IL_023c; case 0: awaiter2 = <>u__1; <>u__1 = default(ConfiguredTaskAwaitable<Task>.ConfiguredTaskAwaiter); num = (<>1__state = -1); goto IL_01e1; case -4: num = (<>1__state = -1); if (!<>w__disposeMode) { goto IL_01e9; } goto end_IL_0086; case 1: awaiter = <>u__2; <>u__2 = default(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter); num = (<>1__state = -1); goto IL_02cd; case -5: { num = (<>1__state = -1); if (!<>w__disposeMode) { break; } goto end_IL_0086; } IL_023c: if (!<whisperTask>5__2.IsCompleted || !<>8__1.buffer.IsEmpty) { cancellationToken.ThrowIfCancellationRequested(); if (<>8__1.buffer.IsEmpty) { <>2__current = null; awaiter2 = Task.WhenAny(new Task[2] { <whisperTask>5__2, <>8__1.resetEvent.WaitAsync() }).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter(); if (!awaiter2.IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter2; <ProcessAsync>d__26 stateMachine = this; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine); return; } goto IL_01e1; } goto IL_01e9; } <>2__current = null; awaiter = <whisperTask>5__2.ConfigureAwait(continueOnCapturedContext: false).GetAwaiter(); if (!awaiter.IsCompleted) { num = (<>1__state = 1); <>u__2 = awaiter; <ProcessAsync>d__26 stateMachine = this; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); return; } goto IL_02cd; IL_02cd: awaiter.GetResult(); break; IL_01e1: awaiter2.GetResult(); goto IL_01e9; IL_01e9: if (<>8__1.buffer.IsEmpty || !<>8__1.buffer.TryDequeue(out result)) { goto IL_023c; } <>2__current = result; num = (<>1__state = -4); goto IL_03ed; } if (<>8__1.buffer.TryDequeue(out SegmentData result2)) { <>2__current = result2; num = (<>1__state = -5); goto IL_03ed; } <whisperTask>5__2 = null; end_IL_0086:; } finally { if (num == -1) { whisperProcessor.options.OnSegmentEventHandlers.Remove(OnSegmentHandler); } } _ = <>w__disposeMode; end_IL_000e:; } catch (Exception exception) { <>1__state = -2; <>8__1 = null; <whisperTask>5__2 = null; if (<>x__combinedTokens != null) { <>x__combinedTokens.Dispose(); <>x__combinedTokens = null; } <>2__current = null; <>t__builder.Complete(); <>v__promiseOfValueOrEnd.SetException(exception); return; } <>1__state = -2; <>8__1 = null; <whisperTask>5__2 = null; if (<>x__combinedTokens != null) { <>x__combinedTokens.Dispose(); <>x__combinedTokens = null; } <>2__current = null; <>t__builder.Complete(); <>v__promiseOfValueOrEnd.SetResult(result: false); return; IL_03ed: <>v__promiseOfValueOrEnd.SetResult(result: true); void OnSegmentHandler(SegmentData segmentData) { ((<>c__DisplayClass26_0)this).buffer.Enqueue(segmentData); ((<>c__DisplayClass26_0)this).resetEvent.Set(); } bool OnWhisperAbortHandler() { if (((<>c__DisplayClass26_0)this).<>4__this.currentCancellationToken.HasValue && ((<>c__DisplayClass26_0)this).<>4__this.currentCancellationToken.Value.IsCancellationRequested) { return true; } return false; } } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } [DebuggerHidden] IAsyncEnumerator<SegmentData> IAsyncEnumerable<SegmentData>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)) { <ProcessAsync>d__26 <ProcessAsync>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = -3; <>t__builder = AsyncIteratorMethodBuilder.Create(); <>w__disposeMode = false; <ProcessAsync>d__ = this; } else { <ProcessAsync>d__ = new <ProcessAsync>d__26(-3) { <>4__this = <>4__this }; } <ProcessAsync>d__.samples = <>3__samples; if (<>3__cancellationToken.Equals(default(CancellationToken))) { <ProcessAsync>d__.cancellationToken = cancellationToken; } else if (cancellationToken.Equals(<>3__cancellationToken) || cancellationToken.Equals(default(CancellationToken))) { <ProcessAsync>d__.cancellationToken = <>3__cancellationToken; } else { <>x__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(<>3__cancellationToken, cancellationToken); <ProcessAsync>d__.cancellationToken = <>x__combinedTokens.Token; } return <ProcessAsync>d__; } [DebuggerHidden] ValueTask<bool> IAsyncEnumerator<SegmentData>.MoveNextAsync() { if (<>1__state == -2) { return default(ValueTask<bool>); } <>v__promiseOfValueOrEnd.Reset(); <ProcessAsync>d__26 stateMachine = this; <>t__builder.MoveNext(ref stateMachine); short version = <>v__promiseOfValueOrEnd.Version; if (<>v__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded) { return new ValueTask<bool>(<>v__promiseOfValueOrEnd.GetResult(version)); } return new ValueTask<bool>(this, version); } [DebuggerHidden] bool IValueTaskSource<bool>.GetResult(short token) { return <>v__promiseOfValueOrEnd.GetResult(token); } [DebuggerHidden] ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token) { return <>v__promiseOfValueOrEnd.GetStatus(token); } [DebuggerHidden] void IValueTaskSource<bool>.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { <>v__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags); } [DebuggerHidden] void IValueTaskSource.GetResult(short token) { <>v__promiseOfValueOrEnd.GetResult(token); } [DebuggerHidden] ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) { return <>v__promiseOfValueOrEnd.GetStatus(token); } [DebuggerHidden] void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { <>v__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags); } [DebuggerHidden] ValueTask IAsyncDisposable.DisposeAsync() { if (<>1__state >= -1) { throw new NotSupportedException(); } if (<>1__state == -2) { return default(ValueTask); } <>w__disposeMode = true; <>v__promiseOfValueOrEnd.Reset(); <ProcessAsync>d__26 stateMachine = this; <>t__builder.MoveNext(ref stateMachine); return new ValueTask(this, <>v__promiseOfValueOrEnd.Version); } } private static readonly ConcurrentDictionary<long, WhisperProcessor> processorInstances = new ConcurrentDictionary<long, WhisperProcessor>(); private static long currentProcessorId; private const byte trueByte = 1; private const byte falseByte = 0; private readonly IntPtr currentWhisperContext; private readonly WhisperProcessorOptions options; private readonly INativeWhisper nativeWhisper; private readonly List<GCHandle> gcHandles = new List<GCHandle>(); private readonly SemaphoreSlim processingSemaphore; private WhisperFullParams whisperParams; private IntPtr? language; private IntPtr? initialPromptText; private IntPtr? suppressRegex; private bool isDisposed; private int segmentIndex; private CancellationToken? currentCancellationToken; private readonly long myId; internal WhisperProcessor(WhisperProcessorOptions options, INativeWhisper nativeWhisper) { this.options = options; this.nativeWhisper = nativeWhisper; myId = Interlocked.Increment(ref currentProcessorId); processorInstances[myId] = this; currentWhisperContext = options.ContextHandle; whisperParams = GetWhisperParams(); processingSemaphore = new SemaphoreSlim(1); } public void ChangeLanguage(string? newLanguage) { IntPtr? intPtr = language; WhisperFullParams whisperFullParams = whisperParams; if (string.IsNullOrEmpty(newLanguage)) { whisperFullParams.Language = IntPtr.Zero; } else { language = Marshal.StringToHGlobalAnsi(newLanguage); whisperFullParams.Language = language.Value; } if (intPtr.HasValue) { Marshal.FreeHGlobal(intPtr.Value); } whisperParams = whisperFullParams; } public string? DetectLanguage(float[] samples) { return DetectLanguageWithProbability(samples.AsSpan()).language; } public (string? language, float probability) DetectLanguageWithProbability(float[] samples) { return DetectLanguageWithProbability(samples.AsSpan()); } public unsafe (string? language, float probability) DetectLanguageWithProbability(ReadOnlySpan<float> samples) { float[] array = new float[nativeWhisper.Whisper_Lang_Max_Id()]; fixed (float* ptr = array) { IntPtr whisperState = GetWhisperState(); try { fixed (float* ptr2 = samples) { nativeWhisper.Whisper_PCM_To_Mel_With_State(currentWhisperContext, whisperState, (IntPtr)ptr2, samples.Length, whisperParams.Threads); } int num = nativeWhisper.Whisper_Lang_Auto_Detect_With_State(currentWhisperContext, whisperState, 0, whisperParams.Threads, (IntPtr)ptr); if (num == -1) { return (language: null, probability: 0f); } return (language: Marshal.PtrToStringAnsi(nativeWhisper.Whisper_Lang_Str(num)), probability: array[num]); } finally { nativeWhisper.Whisper_Free_State(whisperState); } } } public void Process(Stream waveStream) { float[] avgSamples = new WaveParser(waveStream).GetAvgSamples(); Process(avgSamples); } public void Process(float[] samples) { Process(samples.AsSpan()); } public unsafe void Process(ReadOnlySpan<float> samples) { if (isDisposed) { throw new ObjectDisposedException("This processor has already been disposed."); } fixed (float* ptr = samples) { IntPtr whisperState = GetWhisperState(); try { processingSemaphore.Wait(); segmentIndex = 0; nativeWhisper.Whisper_Full_With_State(currentWhisperContext, whisperState, whisperParams, (IntPtr)ptr, samples.Length); } finally { nativeWhisper.Whisper_Free_State(whisperState); processingSemaphore.Release(); } } } [AsyncIteratorStateMachine(typeof(<ProcessAsync>d__25))] public IAsyncEnumerable<SegmentData> ProcessAsync(Stream waveStream, [EnumeratorCancellation] CancellationToken cancellationToken = default(CancellationToken)) { return new <ProcessAsync>d__25(-2) { <>4__this = this, <>3__waveStream = waveStream, <>3__cancellationToken = cancellationToken }; } [AsyncIteratorStateMachine(typeof(<ProcessAsync>d__26))] public IAsyncEnumerable<SegmentData> ProcessAsync(ReadOnlyMemory<float> samples, [EnumeratorCancellation] CancellationToken cancellationToken = default(CancellationToken)) { return new <ProcessAsync>d__26(-2) { <>4__this = this, <>3__samples = samples, <>3__cancellationToken = cancellationToken }; } public IAsyncEnumerable<SegmentData> ProcessAsync(float[] samples, CancellationToken cancellationToken = default(CancellationToken)) { return ProcessAsync(samples.AsMemory(), cancellationToken); } public void Return(SegmentData segmentData) { options.StringPool?.ReturnString(segmentData.Text); WhisperToken[] tokens = segmentData.Tokens; foreach (WhisperToken whisperToken in tokens) { options.StringPool?.ReturnString(whisperToken?.Text); } } public void Dispose() { if (processingSemaphore.CurrentCount == 0) { throw new Exception("Cannot dispose while processing, please use DisposeAsync instead."); } processorInstances.TryRemove(myId, out WhisperProcessor _); if (language.HasValue) { Marshal.FreeHGlobal(language.Value); language = null; } if (initialPromptText.HasValue) { Marshal.FreeHGlobal(initialPromptText.Value); initialPromptText = null; } if (suppressRegex.HasValue) { Marshal.FreeHGlobal(suppressRegex.Value); suppressRegex = null; } foreach (GCHandle gcHandle in gcHandles) { gcHandle.Free(); } gcHandles.Clear(); isDisposed = true; } private unsafe Task ProcessInternalAsync(ReadOnlyMemory<float> samples, CancellationToken cancellationToken) { if (isDisposed) { throw new ObjectDisposedException("This processor has already been disposed."); } return Task.Factory.StartNew(delegate { fixed (float* ptr = samples.Span) { processingSemaphore.Wait(); segmentIndex = 0; IntPtr whisperState = GetWhisperState(); try { nativeWhisper.Whisper_Full_With_State(currentWhisperContext, whisperState, whisperParams, (IntPtr)ptr, samples.Length); } finally { nativeWhisper.Whisper_Free_State(whisperState); processingSemaphore.Release(); } } }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default); } private IntPtr GetWhisperState() { IntPtr intPtr = nativeWhisper.Whisper_Init_State(currentWhisperContext); if (RuntimeOptions.LoadedLibrary == RuntimeLibrary.OpenVino) { IntPtr modelPath = Marshal.StringToHGlobalAnsi(options.OpenVinoModelPath); IntPtr device = Marshal.StringToHGlobalAnsi(options.OpenVinoDevice); IntPtr cacheDir = Marshal.StringToHGlobalAnsi(options.OpenVinoCacheDir); nativeWhisper.Whisper_Ctx_Init_Openvino_Encoder_With_State(options.ContextHandle, intPtr, modelPath, device, cacheDir); } return intPtr; } private WhisperFullParams GetWhisperParams() { WhisperSamplingStrategy nativeStrategy = options.SamplingStrategy.GetNativeStrategy(); IntPtr intPtr = nativeWhisper.Whisper_Full_Default_Params_By_Ref(nativeStrategy); WhisperFullParams result = Marshal.PtrToStructure<WhisperFullParams>(intPtr); nativeWhisper.Whisper_Free_Params(intPtr); result.Strategy = nativeStrategy; if (options.Threads.HasValue) { result.Threads = options.Threads.Value; } if (options.MaxLastTextTokens.HasValue) { result.MaxLastTextTokens = options.MaxLastTextTokens.Value; } if (options.Offset.HasValue) { result.OffsetMs = (int)options.Offset.Value.TotalMilliseconds; } if (options.Duration.HasValue) { result.DurationMs = (int)options.Duration.Value.TotalMilliseconds; } if (options.Translate.HasValue) { result.Translate = (options.Translate.Value ? ((byte)1) : ((byte)0)); } if (options.NoContext.HasValue) { result.NoContext = (options.NoContext.Value ? ((byte)1) : ((byte)0)); } if (options.SingleSegment.HasValue) { result.SingleSegment = (options.SingleSegment.Value ? ((byte)1) : ((byte)0)); } if (options.PrintSpecialTokens.HasValue) { result.PrintSpecialTokens = (options.PrintSpecialTokens.Value ? ((byte)1) : ((byte)0)); } if (options.PrintProgress.HasValue) { result.PrintProgress = (options.PrintProgress.Value ? ((byte)1) : ((byte)0)); } if (options.PrintResults.HasValue) { result.PrintResults = (options.PrintResults.Value ? ((byte)1) : ((byte)0)); } if (options.UseTokenTimestamps.HasValue) { result.UseTokenTimestamps = (options.UseTokenTimestamps.Value ? ((byte)1) : ((byte)0)); } if (options.TokenTimestampsThreshold.HasValue) { result.TokenTimestampsThreshold = options.TokenTimestampsThreshold.Value; } if (options.TokenTimestampsSumThreshold.HasValue) { result.TokenTimestampsSumThreshold = options.TokenTimestampsSumThreshold.Value; } if (options.MaxSegmentLength.HasValue) { result.MaxSegmentLength = options.MaxSegmentLength.Value; } if (options.SplitOnWord.HasValue) { result.SplitOnWord = (options.SplitOnWord.Value ? ((byte)1) : ((byte)0)); } if (options.MaxTokensPerSegment.HasValue) { result.MaxTokensPerSegment = options.MaxTokensPerSegment.Value; } if (options.AudioContextSize.HasValue) { result.AudioContextSize = options.AudioContextSize.Value; } if (!string.IsNullOrEmpty(options.SuppressRegex)) { suppressRegex = Marshal.StringToHGlobalAnsi(options.SuppressRegex); result.SuppressRegex = suppressRegex.Value; } if (!string.IsNullOrEmpty(options.Prompt)) { _ = options.Prompt.Length; initialPromptText = Marshal.StringToHGlobalAnsi(options.Prompt); result.InitialPrompt = initialPromptText.Value; } if (options.Language != null) { language = Marshal.StringToHGlobalAnsi(options.Language); result.Language = language.Value; } if (options.SuppressBlank.HasValue) { result.SuppressBlank = (options.SuppressBlank.Value ? ((byte)1) : ((byte)0)); } if (options.Temperature.HasValue) { result.Temperature = options.Temperature.Value; } if (options.MaxInitialTs.HasValue) { result.MaxInitialTs = options.MaxInitialTs.Value; } if (options.LengthPenalty.HasValue) { result.LengthPenalty = options.LengthPenalty.Value; } if (options.TemperatureInc.HasValue) { result.TemperatureInc = options.TemperatureInc.Value; } if (options.EntropyThreshold.HasValue) { result.EntropyThreshold = options.EntropyThreshold.Value; } if (options.LogProbThreshold.HasValue) { result.LogProbThreshold = options.LogProbThreshold.Value; } if (options.NoSpeechThreshold.HasValue) { result.NoSpeechThreshold = options.NoSpeechThreshold.Value; } if (options.SamplingStrategy is GreedySamplingStrategy { BestOf: not null } greedySamplingStrategy) { result.WhisperParamGreedy.BestOf = greedySamplingStrategy.BestOf.Value; } if (options.SamplingStrategy is BeamSearchSamplingStrategy { BeamSize: var beamSize } beamSearchSamplingStrategy) { if (beamSize.HasValue) { result.WhisperParamBeamSearch.BeamSize = beamSearchSamplingStrategy.BeamSize.Value; } if (beamSearchSamplingStrategy.Patience.HasValue) { result.WhisperParamBeamSearch.Patience = beamSearchSamplingStrategy.Patience.Value; } } IntPtr onProgressCallbackUserData = (result.OnAbortUserData = (result.OnEncoderBeginUserData = (result.OnNewSegmentUserData = new IntPtr(myId)))); WhisperNewSegmentCallback whisperNewSegmentCallback = OnNewSegmentStatic; GCHandle item = GCHandle.Alloc(whisperNewSegmentCallback); gcHandles.Add(item); result.OnNewSegment = Marshal.GetFunctionPointerForDelegate(whisperNewSegmentCallback); WhisperEncoderBeginCallback whisperEncoderBeginCallback = OnEncoderBeginStatic; item = GCHandle.Alloc(whisperEncoderBeginCallback); gcHandles.Add(item); result.OnEncoderBegin = Marshal.GetFunctionPointerForDelegate(whisperEncoderBeginCallback); WhisperAbortCallback whisperAbortCallback = OnWhisperAbortStatic; item = GCHandle.Alloc(whisperAbortCallback); gcHandles.Add(item); result.OnAbort = Marshal.GetFunctionPointerForDelegate(whisperAbortCallback); if (options.OnProgressHandlers.Count > 0) { WhisperProgressCallback whisperProgressCallback = OnProgressStatic; item = GCHandle.Alloc(whisperProgressCallback); gcHandles.Add(item); result.OnProgressCallback = Marshal.GetFunctionPointerForDelegate(whisperProgressCallback); result.OnProgressCallbackUserData = onProgressCallbackUserData; } return result; } private static byte OnWhisperAbortStatic(IntPtr userData) { if (!processorInstances.TryGetValue(userData.ToInt64(), out WhisperProcessor value)) { throw new Exception("Couldn't find processor instance for user data"); } return (value.options.WhisperAbortEventHandler?.Invoke() ?? false) ? ((byte)1) : ((byte)0); } private static void OnNewSegmentStatic(IntPtr ctx, IntPtr state, int nNew, IntPtr userData) { if (!processorInstances.TryGetValue(userData.ToInt64(), out WhisperProcessor value)) { throw new Exception("Couldn't find processor instance for user data"); } value.OnNewSegment(state); } private static byte OnEncoderBeginStatic(IntPtr ctx, IntPtr state, IntPtr userData) { if (!processorInstances.TryGetValue(userData.ToInt64(), out WhisperProcessor value)) { throw new Exception("Couldn't find processor instance for user data"); } return value.OnEncoderBegin() ? ((byte)1) : ((byte)0); } private static void OnProgressStatic(IntPtr ctx, IntPtr state, int progress, IntPtr userData) { if (!processorInstances.TryGetValue(userData.ToInt64(), out WhisperProcessor value)) { throw new Exception("Couldn't find processor instance for user data"); } value.OnProgress(progress); } private void OnProgress(int progress) { if (currentCancellationToken.HasValue && currentCancellationToken.Value.IsCancellationRequested) { return; } foreach (OnProgressHandler onProgressHandler in options.OnProgressHandlers) { onProgressHandler?.Invoke(progress); if (currentCancellationToken.HasValue && currentCancellationToken.Value.IsCancellationRequested) { break; } } } private bool OnEncoderBegin() { if (currentCancellationToken.HasValue && currentCancellationToken.Value.IsCancellationRequested) { return false; } EncoderBeginData e = new EncoderBeginData(); foreach (OnEncoderBeginEventHandler onEncoderBeginEventHandler in options.OnEncoderBeginEventHandlers) { if (!onEncoderBeginEventHandler(e)) { return false; } } return true; } private void OnNewSegment(IntPtr state) { if (currentCancellationToken.HasValue && currentCancellationToken.Value.IsCancellationRequested) { return; } int num = nativeWhisper.Whisper_Full_N_Segments_From_State(state); while (segmentIndex < num) { TimeSpan end = TimeSpan.FromMilliseconds(nativeWhisper.Whisper_Full_Get_Segment_T1_From_State(state, segmentIndex) * 10); TimeSpan start = TimeSpan.FromMilliseconds(nativeWhisper.Whisper_Full_Get_Segment_T0_From_State(state, segmentIndex) * 10); string text = StringFromNativeUtf8(nativeWhisper.Whisper_Full_Get_Segment_Text_From_State(state, segmentIndex)); float num2 = 0f; float num3 = 0f; double num4 = 0.0; int num5 = nativeWhisper.Whisper_Full_N_Tokens_From_State(state, segmentIndex); int lang_id = nativeWhisper.Whisper_Full_Lang_Id_From_State(state); string text2 = Marshal.PtrToStringAnsi(nativeWhisper.Whisper_Lang_Str(lang_id)); float noSpeechProbability = nativeWhisper.Whisper_Full_Get_Segment_No_Speech_Prob_From_State(state, segmentIndex); WhisperToken[] array = new WhisperToken[num5]; for (int i = 0; i < num5; i++) { WhisperTokenData whisperTokenData = nativeWhisper.Whisper_Full_Get_Token_Data_From_State(state, segmentIndex, i); string text3 = StringFromNativeUtf8(nativeWhisper.Whisper_Full_Get_Token_Text_From_State(currentWhisperContext, state, segmentIndex, i)); array[i] = new WhisperToken { Id = whisperTokenData.id, TimestampId = whisperTokenData.tid, DtwTimestamp = whisperTokenData.t_dtw, VoiceLen = whisperTokenData.vlen, Probability = whisperTokenData.p, ProbabilityLog = whisperTokenData.plog, TimestampProbability = whisperTokenData.pt, TimestampProbabilitySum = whisperTokenData.ptsum, Text = text3, Start = whisperTokenData.t0, End = whisperTokenData.t1 }; if (!options.ComputeProbabilities) { continue; } float num6 = nativeWhisper.Whisper_Full_Get_Token_P_From_State(state, segmentIndex, i); num4 += (double)num6; if (i == 0) { num2 = num6; num3 = num6; continue; } if (num6 < num2) { num2 = num6; } if (num6 > num3) { num3 = num6; } } if (!string.IsNullOrEmpty(text)) { SegmentData e = new SegmentData(text, start, end, num2, num3, (float)(num4 / (double)num5), noSpeechProbability, text2, array); foreach (OnSegmentEventHandler onSegmentEventHandler in options.OnSegmentEventHandlers) { onSegmentEventHandler?.Invoke(e); if (currentCancellationToken.HasValue && currentCancellationToken.Value.IsCancellationRequested) { return; } } } segmentIndex++; } } private string? StringFromNativeUtf8(IntPtr nativeUtf8) { if (options.StringPool != null) { return options.StringPool.GetStringUtf8(nativeUtf8); } return DefaultStringFromNativeUtf8(nativeUtf8); } private static string? DefaultStringFromNativeUtf8(IntPtr nativeUtf8) { int i; for (i = 0; Marshal.ReadByte(nativeUtf8, i) != 0; i++) { } byte[] array = new byte[i]; Marshal.Copy(nativeUtf8, array, 0, array.Length); return Encoding.UTF8.GetString(array); } public async ValueTask DisposeAsync() { await processingSemaphore.WaitAsync(); processingSemaphore.Release(); Dispose(); } } public class WhisperProcessorBuilder { private readonly WhisperProcessorOptions whisperProcessorOptions; private readonly INativeWhisper nativeWhisper; private readonly IStringPool stringPool; internal WhisperProcessorBuilder(IntPtr context, INativeWhisper nativeWhisper, IStringPool stringPool) { whisperProcessorOptions = new WhisperProcessorOptions { ContextHandle = context }; this.nativeWhisper = nativeWhisper; this.stringPool = stringPool; } public WhisperProcessorBuilder WithThreads(int threads) { whisperProcessorOptions.Threads = threads; return this; } public WhisperProcessorBuilder WithMaxLastTextTokens(int maxLastTextTokens) { whisperProcessorOptions.MaxLastTextTokens = maxLastTextTokens; return this; } public WhisperProcessorBuilder WithOffset(TimeSpan offset) { whisperProcessorOptions.Offset = offset; return this; } public WhisperProcessorBuilder WithDuration(TimeSpan duration) { whisperProcessorOptions.Duration = duration; return this; } public WhisperProcessorBuilder WithTranslate() { whisperProcessorOptions.Translate = true; return this; } public WhisperProcessorBuilder WithNoContext() { whisperProcessorOptions.NoContext = true; return this; } public WhisperProcessorBuilder WithSingleSegment() { whisperProcessorOptions.SingleSegment = true; return this; } public WhisperProcessorBuilder WithPrintSpecialTokens() { whisperProcessorOptions.PrintSpecialTokens = true; return this; } public WhisperProcessorBuilder WithPrintProgress() { whisperProcessorOptions.PrintProgress = true; return this; } public WhisperProcessorBuilder WithPrintResults() { whisperProcessorOptions.PrintResults = true; return this; } public WhisperProcessorBuilder WithPrintTimestamps(bool printTimestamps = true) { whisperProcessorOptions.PrintTimestamps = printTimestamps; return this; } public WhisperProcessorBuilder WithTokenTimestamps() { whisperProcessorOptions.UseTokenTimestamps = true; return this; } public WhisperProcessorBuilder WithTokenTimestampsThreshold(float tokenTimestampsThreshold) { whisperProcessorOptions.TokenTimestampsThreshold = tokenTimestampsThreshold; return this; } public WhisperProcessorBuilder WithTokenTimestampsSumThreshold(float tokenTimestampsSumThreshold) { whisperProcessorOptions.TokenTimestampsSumThreshold = tokenTimestampsSumThreshold; return this; } public WhisperProcessorBuilder WithMaxSegmentLength(int maxSegmentLength) { whisperProcessorOptions.MaxSegmentLength = maxSegmentLength; return this; } public WhisperProcessorBuilder SplitOnWord() { whisperProcessorOptions.SplitOnWord = true; return this; } public WhisperProcessorBuilder WithMaxTokensPerSegment(int maxTokensPerSegment) { whisperProcessorOptions.MaxTokensPerSegment = maxTokensPerSegment; return this; } public WhisperProcessorBuilder WithAudioContextSize(int audioContextSize) { whisperProcessorOptions.AudioContextSize = audioContextSize; return this; } public WhisperProcessorBuilder WithSuppressRegex(string regex) { whisperProcessorOptions.SuppressRegex = regex; return this; } public WhisperProcessorBuilder WithPrompt(string prompt) { whisperProcessorOptions.Prompt = prompt; return this; } public WhisperProcessorBuilder WithLanguage(string language) { whisperProcessorOptions.Language = language; return this; } public WhisperProcessorBuilder WithLanguageDetection() { whisperProcessorOptions.Language = string.Empty; return this; } public WhisperProcessorBuilder WithoutSuppressBlank() { whisperProcessorOptions.SuppressBlank = false; return this; } public WhisperProcessorBuilder WithTemperature(float temperature) { whisperProcessorOptions.Temperature = temperature; return this; } public WhisperProcessorBuilder WithMaxInitialTs(float maxInitialTs) { whisperProcessorOptions.MaxInitialTs = maxInitialTs; return this; } public WhisperProcessorBuilder WithLengthPenalty(float lengthPenalty) { whisperProcessorOptions.LengthPenalty = lengthPenalty; return this; } public WhisperProcessorBuilder WithTemperatureInc(float temperature) { whisperProcessorOptions.TemperatureInc = temperature; return this; } public WhisperProcessorBuilder WithEntropyThreshold(float entropyThreshold) { whisperProcessorOptions.EntropyThreshold = entropyThreshold; return this; } public WhisperProcessorBuilder WithLogProbThreshold(float logProbThreshold) { whisperProcessorOptions.LogProbThreshold = logProbThreshold; return this; } public WhisperProcessorBuilder WithNoSpeechThreshold(float noSpeechThreshold) { whisperProcessorOptions.NoSpeechThreshold = noSpeechThreshold; return this; } public WhisperProcessorBuilder WithSegmentEventHandler(OnSegmentEventHandler segmentEventHandler) { whisperProcessorOptions.OnSegmentEventHandlers.Add(segmentEventHandler); return this; } public WhisperProcessorBuilder WithProgressHandler(OnProgressHandler progressHandler) { whisperProcessorOptions.OnProgressHandlers.Add(progressHandler); return this; } public WhisperProcessorBuilder WithEncoderBeginHandler(OnEncoderBeginEventHandler encoderBeginEventHandler) { whisperProcessorOptions.OnEncoderBeginEventHandlers.Add(encoderBeginEventHandler); return this; } public WhisperProcessorBuilder WithStringPool(IStringPool? stringPool = null) { whisperProcessorOptions.StringPool = stringPool ?? this.stringPool; return this; } public WhisperProcessorBuilder WithoutStringPool() { whisperProcessorOptions.StringPool = null; return this; } public IWhisperSamplingStrategyBuilder WithGreedySamplingStrategy() { GreedySamplingStrategy greedySamplingStrategy = new GreedySamplingStrategy(); whisperProcessorOptions.SamplingStrategy = greedySamplingStrategy; return new GreedySamplingStrategyBuilder(this, greedySamplingStrategy); } public IWhisperSamplingStrategyBuilder WithBeamSearchSamplingStrategy() { BeamSearchSamplingStrategy beamSearchSamplingStrategy = new BeamSearchSamplingStrategy(); whisperProcessorOptions.SamplingStrategy = beamSearchSamplingStrategy; return new BeamSearchSamplingStrategyBuilder(this, beamSearchSamplingStrategy); } public WhisperProcessorBuilder WithProbabilities() { whisperProcessorOptions.ComputeProbabilities = true; return this; } public WhisperProcessorBuilder WithOpenVinoEncoder(string? openVinoEncoderPath, string? openVinoDevice, string? openVinoCachePath) { whisperProcessorOptions.OpenVinoModelPath = openVinoEncoderPath; whisperProcessorOptions.OpenVinoDevice = openVinoDevice; whisperProcessorOptions.OpenVinoCacheDir = openVinoCachePath; return this; } public WhisperProcessor Build() { return new WhisperProcessor(whisperProcessorOptions, nativeWhisper); } } public delegate void OnProgressHandler(int progress); public delegate void OnSegmentEventHandler(SegmentData e); public delegate bool OnEncoderBeginEventHandler(EncoderBeginData e); public delegate bool WhisperAbortEventHandler(); public class EncoderBeginData { } public class WhisperToken { public int Id; public int TimestampId; public float Probability; public float ProbabilityLog; public float TimestampProbability; public float TimestampProbabilitySum; public long Start; public long End; public long DtwTimestamp; public float VoiceLen; public string? Text; } public class SegmentData { public string Text { get; } public TimeSpan Start { get; } public TimeSpan End { get; } public float MinProbability { get; } public float MaxProbability { get; } public float Probability { get; } public string Language { get; } public WhisperToken[] Tokens { get; } public float NoSpeechProbability { get; } public SegmentData(string text, TimeSpan start, TimeSpan end, float minProbability, float maxProbability, float probability, float noSpeechProbability, string language, WhisperToken[] tokens) { Text = text; Start = start; End = end; MinProbability = minProbability; MaxProbability = maxProbability; Probability = probability; Language = language; Tokens = tokens; NoSpeechProbability = noSpeechProbability; base..ctor(); } } internal sealed class WhisperProcessorOptions { public string? OpenVinoModelPath { get; set; } public string? OpenVinoDevice { get; set; } public string? OpenVinoCacheDir { get; set; } public IWhisperSamplingStrategy SamplingStrategy { get; set; } = new GreedySamplingStrategy(); public IntPtr ContextHandle { get; set; } public int? Threads { get; set; } public int? MaxLastTextTokens { get; set; } public TimeSpan? Offset { get; set; } public TimeSpan? Duration { get; set; } public bool? Translate { get; set; } public bool? NoContext { get; set; } public bool? SingleSegment { get; set; } public bool? PrintSpecialTokens { get; set; } public bool? PrintProgress { get; set; } = false; public bool? PrintResults { get; set; } public bool? PrintTimestamps { get; set; } public bool? UseTokenTimestamps { get; set; } public float? TokenTimestampsThreshold { get; set; } public float? TokenTimestampsSumThreshold { get; set; } public int? MaxSegmentLength { get; set; } public bool? SplitOnWord { get; set; } public int? MaxTokensPerSegment { get; set; } public int? AudioContextSize { get; set; } public string? SuppressRegex { get; set; } public string? Prompt { get; set; } public string? Language { get; set; } public bool? SuppressBlank { get; set; } public float? Temperature { get; set; } public float? MaxInitialTs { get; set; } public float? LengthPenalty { get; set; } public float? TemperatureInc { get; set; } public float? EntropyThreshold { get; set; } public float? LogProbThreshold { get; set; } public float? NoSpeechThreshold { get; set; } public List<OnSegmentEventHandler> OnSegmentEventHandlers { get; set; } = new List<OnSegmentEventHandler>(); public List<OnProgressHandler> OnProgressHandlers { get; set; } = new List<OnProgressHandler>(); public List<OnEncoderBeginEventHandler> OnEncoderBeginEventHandlers { get; set; } = new List<OnEncoderBeginEventHandler>(); public WhisperAbortEventHandler? WhisperAbortEventHandler { get; set; } public bool ComputeProbabilities { get; set; } public IStringPool? StringPool { get; set; } } } namespace Whisper.net.Wave { public class CorruptedWaveException : Exception { public CorruptedWaveException(string? message) : base(message) { } } public class NotSupportedWaveException : Exception { public NotSupportedWaveException(string? message) : base(message) { } } public sealed class WaveParser(Stream waveStream) { [CompilerGenerated] private sealed class <InternalReadSamples>d__33 : IAsyncEnumerable<long[]>, IAsyncEnumerator<long[]>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine { public int <>1__state; public AsyncIteratorMethodBuilder <>t__builder; public ManualResetValueTaskSourceCore<bool> <>v__promiseOfValueOrEnd; private long[] <>2__current; private bool <>w__disposeMode; private CancellationTokenSource <>x__combinedTokens; private int <>l__initialThreadId; public WaveParser <>4__this; private bool useAsync; public bool <>3__useAsync; private CancellationToken cancellationToken; public CancellationToken <>3__cancellationToken; private byte[] <buffer>5__2; private int <sampleIndex>5__3; private int <bytesRead>5__4; private TaskAwaiter<int> <>u__1; private int <i>5__5; long[] IAsyncEnumerator<long[]>.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InternalReadSamples>d__33(int <>1__state) { <>t__builder = AsyncIteratorMethodBuilder.Create(); this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } private void MoveNext() { int num = <>1__state; WaveParser waveParser = <>4__this; try { TaskAwaiter<int> awaiter; int result; int count; long[] array; switch (num) { default: if (!<>w__disposeMode) { num = (<>1__state = -1); <buffer>5__2 = new byte[2048 * waveParser.channels]; <buffer>5__2.AsMemory(); <sampleIndex>5__3 = 0; <bytesRead>5__4 = int.MaxValue; goto IL_027e; } goto end_IL_000e; case 0: awaiter = <>u__1; <>u__1 = default(TaskAwaiter<int>); num = (<>1__state = -1); goto IL_0121; case -4: { num = (<>1__state = -1); if (!<>w__disposeMode) { <sampleIndex>5__3++; goto IL_026d; } goto end_IL_000e; } IL_0121: result = awaiter.GetResult(); <bytesRead>5__4 = result; goto IL_014b; IL_014b: <i>5__5 = 0; goto IL_026d; IL_027e: if (<bytesRead>5__4 <= 0 || <sampleIndex>5__3 >= waveParser.SamplesCount) { break; } count = (int)Math.Min(<buffer>5__2.Length, (waveParser.SamplesCount - <sampleIndex>5__3) * waveParser.FrameSize); if (useAsync) { <>2__current = null; awaiter = waveParser.waveStream.ReadAsync(<buffer>5__2, 0, count, cancellationToken).GetAwaiter(); if (!awaiter.IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter; <InternalReadSamples>d__33 stateMachine = this; <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); return; } goto IL_0121; } <bytesRead>5__4 = waveParser.waveStream.Read(<buffer>5__2, 0, count); goto IL_014b; IL_026d: if (<i>5__5 >= <bytesRead>5__4) { goto IL_027e; } array = new long[waveParser.channels]; for (int i = 0; i < waveParser.channels; i++) { var (num2, num3) = waveParser.bitsPerSample switch { 8 => (<buffer>5__2[<i>5__5] - 128, 1), 16 => (BitConverter.ToInt16(<buffer>5__2, <i>5__5), 2), 24 => (BitConverter.ToInt32(<buffer>5__2, <i>5__5) >> 8, 3), _ => (BitConverter.ToInt32(<buffer>5__2, <i>5__5), 4), }; array[i] = num2; <i>5__5 += num3; } <>2__current = array; num = (<>1__state = -4); goto IL_0349; } if (<sampleIndex>5__3 < waveParser.SamplesCount) { throw new CorruptedWaveException("Invalid wave file, the size is too small and couldn't read all the samples."); } end_IL_000e:; } catch (Exception exception) { <>1__state = -2; <buffer>5__2 = null; if (<>x__combinedTokens != null) { <>x__combinedTokens.Dispose(); <>x__combinedTokens = null; } <>2__current = null; <>t__builder.Complete(); <>v__promiseOfValueOrEnd.SetException(exception); return; } <>1__state = -2; <buffer>5__2 = null; if (<>x__combinedTokens != null) { <>x__combinedTokens.Dispose(); <>x__combinedTokens = null; } <>2__current = null; <>t__builder.Complete(); <>v__promiseOfValueOrEnd.SetResult(result: false); return; IL_0349: <>v__promiseOfValueOrEnd.SetResult(result: true); } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } [DebuggerHidden] IAsyncEnumerator<long[]> IAsyncEnumerable<long[]>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)) { <InternalReadSamples>d__33 <InternalReadSamples>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = -3; <>t__builder = AsyncIteratorMethodBuilder.Create(); <>w__disposeMode = false; <InternalReadSamples>d__ = this; } else { <InternalReadSamples>d__ = new <InternalReadSamples>d__33(-3) { <>4__this = <>4__this }; } <InternalReadSamples>d__.useAsync = <>3__useAsync; if (<>3__cancellationToken.Equals(default(CancellationToken))) { <InternalReadSamples>d__.cancellationToken = cancellationToken; } else if (cancellationToken.Equals(<>3__cancellationToken) || cancellationToken.Equals(default(CancellationToken))) { <InternalReadSamples>d__.cancellationToken = <>3__cancellationToken; } else { <>x__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(<>3__cancellationToken, cancellationToken); <InternalReadSamples>d__.cancellationToken = <>x__combinedTokens.Token; } return <InternalReadSamples>d__; } [DebuggerHidden] ValueTask<bool> IAsyncEnumerator<long[]>.MoveNextAsync() { if (<>1__state == -2) { return default(ValueTask<bool>); } <>v__promiseOfValueOrEnd.Reset(); <InternalReadSamples>d__33 stateMachine = this; <>t__builder.MoveNext(ref stateMachine); short version = <>v__promiseOfValueOrEnd.Version; if (<>v__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded) { return new ValueTask<bool>(<>v__promiseOfValueOrEnd.GetResult(version)); } return new ValueTask<bool>(this, version); } [DebuggerHidden] bool IValueTaskSource<bool>.GetResult(short token) { return <>v__promiseOfValueOrEnd.GetResult(token); } [DebuggerHidden] ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token) { return <>v__promiseOfValueOrEnd.GetStatus(token); } [DebuggerHidden] void IValueTaskSource<bool>.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { <>v__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags); } [DebuggerHidden] void IValueTaskSource.GetResult(short token) { <>v__promiseOfValueOrEnd.GetResult(token); } [DebuggerHidden] ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) { return <>v__promiseOfValueOrEnd.GetStatus(token); } [DebuggerHidden] void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { <>v__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags); } [DebuggerHidden] ValueTask IAsyncDisposable.DisposeAsync() { if (<>1__state >= -1) { throw new NotSupportedException(); } if (<>1__state == -2) { return default(ValueTask); } <>w__disposeMode = true; <>v__promiseOfValueOrEnd.Reset(); <InternalReadSamples>d__33 stateMachine = this; <>t__builder.MoveNext(ref stateMachine); return new ValueTask(this, <>v__promiseOfValueOrEnd.Version); } } private static readonly byte[] expectedSubFormatForPcm = new byte[16] { 1, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }; private ushort channels; private uint sampleRate; private ushort bitsPerSample; private uint dataChunkSize; private long dataChunkPosition; private bool isInitialized; public ushort Channels => channels; public uint SampleRate => sampleRate; public ushort BitsPerSample => bitsPerSample; public uint DataChunkSize => dataChunkSize; public long DataChunkPosition => dataChunkPosition; public bool IsInitialized => isInitialized; public long SamplesCount => dataChunkSize / (bitsPerSample / 8) / channels; public int FrameSize => bitsPerSample / 8 * channels; public float ValueToDivide => bitsPerSample switch { 8 => 128f, 16 => 32768f, 24 => 8388608f, _ => 2.1474836E+09f, }; public async Task<float[]> GetAvgSamplesAsync(CancellationToken cancellationToken = default(CancellationToken)) { await InitializeAsync(cancellationToken); float[] samples = new float[SamplesCount]; int sampleIndex = 0; await foreach (long[] item in InternalReadSamples(useAsync: true, cancellationToken)) { long num = 0L; for (int i = 0; i < item.Length; i++) { num += item[i]; } samples[sampleIndex++] = (float)num / ValueToDivide / (float)(int)channels; } return samples; } public float[] GetAvgSamples() { Initialize(); IAsyncEnumerator<long[]> asyncEnumerator = InternalReadSamples(useAsync: false, CancellationToken.None).GetAsyncEnumerator(); float[] array = new float[SamplesCount]; int num = 0; while (asyncEnumerator.MoveNextAsync().GetAwaiter().GetResult()) { long[] current = asyncEnumerator.Current; long num2 = 0L; for (int i = 0; i < current.Length; i++) { num2 += current[i]; } array[num++] = (float)num2 / ValueToDivide / (float)(int)channels; } return array; } public float[] GetChannelSamples(int channelIndex = 0) { Initialize(); if (channelIndex >= channels) { throw new ArgumentOutOfRangeException("channelIndex"); } float[] array = new float[SamplesCount]; int num = 0; IAsyncEnumerator<long[]> asyncEnumerator = InternalReadSamples(useAsync: false, CancellationToken.None).GetAsyncEnumerator(); while (asyncEnumerator.MoveNextAsync().GetAwaiter().GetResult()) { long[] current = asyncEnumerator.Current; array[num++] = (float)current[channelIndex] / ValueToDivide; } return array; } public async Task<float[]> GetChannelSamplesAsync(int channelIndex = 0, CancellationToken cancellationToken = default(CancellationToken)) { await InitializeAsync(cancellationToken); if (channelIndex >= channels) { throw new ArgumentOutOfRangeException("channelIndex"); } float[] samples = new float[SamplesCount]; int sampleIndex = 0; await foreach (long[] item in InternalReadSamples(useAsync: true, cancellationToken)) { samples[sampleIndex++] = (float)item[channelIndex] / ValueToDivide; } return samples; } public void Initialize() { InternalInitialize(useAsync: false, CancellationToken.None).GetAwaiter().GetResult(); } public Task InitializeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return InternalInitialize(useAsync: true, cancellationToken); } [AsyncIteratorStateMachine(typeof(<InternalReadSamples>d__33))] private IAsyncEnumerable<long[]> InternalReadSamples(bool useAsync, [EnumeratorCancellation] CancellationToken cancellationToken) { return new <InternalReadSamples>d__33(-2) { <>4__this = this, <>3__useAsync = useAsync, <>3__cancellationToken = cancellationToken }; } private async Task InternalInitialize(bool useAsync, CancellationToken cancellationToken) { if (isInitialized) { return; } byte[] buffer = new byte[12]; if (await ReadBytesAsync(buffer, 0, 12) != 12) { throw new CorruptedWaveException("Invalid wave file, the size is too small."); } if (buffer[0] != 82 || buffer[1] != 73 || buffer[2] != 70 || buffer[3] != 70) { throw new CorruptedWaveException("Invalid wave file RIFF header."); } if (buffer[8] != 87 || buffer[9] != 65 || buffer[10] != 86 || buffer[11] != 69) { throw new CorruptedWaveException("Invalid wave file header."); } int num; while (true) { byte[] nextChunkHeader = new byte[8]; if (await ReadBytesAsync(nextChunkHeader, 0, 8) != 8) { throw new CorruptedWaveException("Invalid wave file, cannot read next chunk."); } num = BitConverter.ToInt32(nextChunkHeader, 4); if (num < 0) { throw new CorruptedWaveException("Invalid wave chunk size."); } if (nextChunkHeader[0] == 102 && nextChunkHeader[1] == 109 && nextChunkHeader[2] == 116 && nextChunkHeader[3] == 32) { break; } if (waveStream.CanSeek) { waveStream.Seek(num, SeekOrigin.Current); continue; } byte[] buffer2 = new byte[num]; await ReadBytesAsync(buffer2, 0, num); } int fmtChunkSize = num; if (fmtChunkSize < 16) { throw new CorruptedWaveException("Invalid wave format size."); } byte[] fmtBuffer = new byte[fmtChunkSize]; if (await ReadBytesAsync(fmtBuffer, 0, fmtChunkSize) != fmtChunkSize) { throw new CorruptedWaveException("Invalid wave file, cannot read format chunk."); } ushort num2 = BitConverter.ToUInt16(fmtBuffer, 0); if (num2 != 1 && num2 != 65534) { throw new CorruptedWaveException("Unsupported wave file"); } if (num2 == 65534) { if (fmtChunkSize < 40) { throw new CorruptedWaveException("Invalid wave format size."); } for (int i = 0; i < 16; i++) { if (fmtBuffer[24 + i] != expectedSubFormatForPcm[i]) { throw new CorruptedWaveException("Unsupported wave file format. Only PCM is supported."); } } } channels = BitConverter.ToUInt16(fmtBuffer, 2); if (channels == 0) { throw new NotSupportedWaveException("Cannot read wave file with 0 channels."); } sampleRate = BitConverter.ToUInt32(fmtBuffer, 4); if (sampleRate != 16000) { throw new NotSupportedWaveException("Only 16KHz sample rate is supported."); } bitsPerSample = BitConverter.ToUInt16(fmtBuffer, 14); if (bitsPerSample != 8 && bitsPerSample != 16 && bitsPerSample != 24 && bitsPerSample != 32) { throw new NotSupportedWaveException($"Bits per sample {bitsPerSample} is not supported."); } await ReadBytesAsync(buffer, 0, 8); while (buffer[0] != 100 || buffer[1] != 97 || buffer[2] != 116 || buffer[3] != 97) { int num3 = BitConverter.ToInt32(buffer, 4); if (num3 < 0) { throw new CorruptedWaveException("Invalid wave chunk size."); } if (waveStream.CanSeek) { waveStream.Seek(num3, SeekOrigin.Current); } else { byte[] buffer3 = new byte[num3]; await ReadBytesAsync(buffer3, 0, num3); } if (await ReadBytesAsync(buffer, 0, 8) != 8) { throw new CorruptedWaveException("Invalid wave chunk size."); } } dataChunkSize = BitConverter.ToUInt32(buffer, 4); if (dataChunkSize == uint.MaxValue) { dataChunkSize = (uint)(waveStream.Length - waveStream.Position); } dataChunkPosition = waveStream.Position; isInitialized = true; async Task<int> ReadBytesAsync(byte[] buffer4, int offset, int count) { if (useAsync) { return await waveStream.ReadAsync(buffer4, offset, count, cancellationToken); } return waveStream.Read(buffer4, offset, count); } } } } namespace Whisper.net.SamplingStrategy { internal class BeamSearchSamplingStrategy : IWhisperSamplingStrategy { public int? BeamSize { get; set; } public float? Patience { get; set; } public WhisperSamplingStrategy GetNativeStrategy() { return WhisperSamplingStrategy.StrategyBeamSearch; } } internal class GreedySamplingStrategy : IWhisperSamplingStrategy { public int? BestOf { get; set; } public WhisperSamplingStrategy GetNativeStrategy() { return WhisperSamplingStrategy.StrategyGreedy; } } internal interface IWhisperSamplingStrategy { WhisperSamplingStrategy GetNativeStrategy(); } } namespace Whisper.net.Logger { public static class LogProvider { private static readonly WhisperGgmlLogCallback logCallback = LogUnmanaged; public static IDisposable AddConsoleLogging(WhisperLogLevel minLevel = WhisperLogLevel.Info) { return new WhisperLogger(delegate(WhisperLogLevel level, string? message) { if (level <= minLevel) { Console.WriteLine($"[{level}] {message}"); } }); } public static IDisposable AddLogger(Action<WhisperLogLevel, string?> logAction) { return new WhisperLogger(logAction); } internal static void InitializeLogging(INativeWhisper nativeWhisper) { IntPtr functionPointerForDelegate = Marshal.GetFunctionPointerForDelegate(logCallback); nativeWhisper.Whisper_Log_Set(functionPointerForDelegate, IntPtr.Zero); } internal static void LogUnmanaged(GgmlLogLevel level, IntPtr message, IntPtr user_data) { string message2 = Marshal.PtrToStringAnsi(message); WhisperLogger.Log(level switch { GgmlLogLevel.Error => WhisperLogLevel.Error, GgmlLogLevel.Warning => WhisperLogLevel.Warning, _ => WhisperLogLevel.Info, }, message2); } } internal class WhisperLogger : IDisposable { private readonly Action<WhisperLogLevel, string?> logAction; public static event Action<WhisperLogLevel, string?>? OnLog; public WhisperLogger(Action<WhisperLogLevel, string?> logAction) { this.logAction = logAction; OnLog += logAction; } public void Dispose() { OnLog -= logAction; } public static void Log(WhisperLogLevel level, string? message) { WhisperLogger.OnLog?.Invoke(level, message); } } public enum WhisperLogLevel { None, Error, Warning, Info, Cont, Debug } } namespace Whisper.net.LibraryLoader { internal static class CudaHelper { public static bool IsCudaAvailable() { WhisperLogger.Log(WhisperLogLevel.Debug, "Checking for CUDA availability."); INativeCuda nativeCuda = null; int count = 0; try { try { INativeCuda nativeCuda3; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { INativeCuda nativeCuda2 = new DllImportNativeLibcuda(); nativeCuda3 = nativeCuda2; } else { INativeCuda nativeCuda2 = new DllImportNativeCuda_64_12(); nativeCuda3 = nativeCuda2; } nativeCuda = nativeCuda3; nativeCuda.CudaGetDeviceCount(out count); } catch { WhisperLogger.Log(WhisperLogLevel.Debug, "Cudart library couldn't be loaded."); return false; } WhisperLogger.Log(WhisperLogLevel.Debug, $"NUmber of CUDA devices found: {count}"); return count > 0; } finally { nativeCuda?.Dispose(); } } } internal interface ILibraryLoader { bool TryOpenLibrary(string fileName, out IntPtr libHandle); string GetLastError(); void CloseLibrary(IntPtr handle); } internal class LibdlLibraryLoader : ILibraryLoader { private bool? useLibdl2; [DllImport("libdl", CharSet = CharSet.Auto, EntryPoint = "dlopen")] public static extern IntPtr NativeOpenLibraryLibdl(string? filename, int flags); [DllImport("libdl", CharSet = CharSet.Auto, EntryPoint = "dlerror")] public static extern IntPtr GetLoadError(); [DllImport("libdl", CharSet = CharSet.Auto, EntryPoint = "dlclose")] public static extern int NativeCloseLibraryLibdl(IntPtr handle); [DllImport("libdl.so.2", CharSet = CharSet.Auto, EntryPoint = "dlopen")] public static extern IntPtr NativeOpenLibraryLibdl2(string? filename, int flags); [DllImport("libdl.so.2", CharSet = CharSet.Auto, EntryPoint = "dlerror")] public static extern IntPtr GetLoadError2(); [DllImport("libdl.so.2", CharSet = CharSet.Auto, EntryPoint = "dlclose")] public static extern int NativeCloseLibraryLibdl2(IntPtr handle); public void CloseLibrary(IntPtr handle) { if (useLibdl2.HasValue) { if (useLibdl2.Value) { NativeCloseLibraryLibdl2(handle); } else { NativeCloseLibraryLibdl(handle); } return; } try { NativeCloseLibraryLibdl(handle); useLibdl2 = false; } catch (DllNotFoundException) { NativeCloseLibraryLibdl2(handle); useLibdl2 = true; } } public bool TryOpenLibrary(string fileName, out IntPtr libHandle) { try { if (useLibdl2.HasValue) { libHandle = (useLibdl2.Value ? NativeOpenLibraryLibdl2(fileName, 258) : NativeOpenLibraryLibdl(fileName, 258)); return libHandle != IntPtr.Zero; } try { libHandle = NativeOpenLibraryLibdl(fileName, 258); useLibdl2 = false; return libHandle != IntPtr.Zero; } catch (DllNotFoundException) { libHandle = NativeOpenLibraryLibdl2(fileName, 258); useLibdl2 = true; return libHandle != IntPtr.Zero; } } catch (DllNotFoundException) { libHandle = IntPtr.Zero; return false; } } public string GetLastError() { if (useLibdl2.HasValue) { IntPtr error = (useLibdl2.Value ? GetLoadError2() : GetLoadError()); return GetError(error); } try { IntPtr loadError = GetLoadError(); useLibdl2 = false; return GetError(loadError); } catch (DllNotFoundException) { IntPtr loadError2 = GetLoadError2(); useLibdl2 = true; return GetError(loadError2); } } private string GetError(IntPtr error) { return Marshal.PtrToStringAnsi(error) ?? "Unknown error"; } } internal class LoadResult { public INativeWhisper? NativeWhisper; public bool IsSuccess { get; } public string? ErrorMessage { get; } private LoadResult(bool isSuccess, string? errorMessage, INativeWhisper? nativeWhisper) { IsSuccess = isSuccess; ErrorMessage = errorMessage; NativeWhisper = nativeWhisper; } public static LoadResult Success(INativeWhisper nativeWhisper) { return new LoadResult(isSuccess: true, null, nativeWhisper); } public static LoadResult Failure(string errorMessage) { return new LoadResult(isSuccess: false, errorMessage, null); } } public static class NativeLibraryLoader { private static readonly string[] dependencyOrder = new string[7] { "ggml-base-whisper", "ggml-cpu-whisper", "ggml-blas-whisper", "ggml-metal-whisper", "ggml-cuda-whisper", "ggml-vulkan-whisper", "ggml-whisper" }; internal static LoadResult LoadNativeLibrary() { if (RuntimeOptions.LoadedLibrary.HasValue || RuntimeInformation.OSArchitecture.ToString().Equals("wasm", StringComparison.OrdinalIgnoreCase)) { WhisperLogger.Log(WhisperLogLevel.Debug, "Using DllImportsNativeLibWhisper for whisper library with bypassed loading."); return LoadResult.Success(new DllImportsNativeLibWhisper()); } return LoadLibraryComponent(); } private static LoadResult LoadLibraryComponent() { _ = Environment.OSVersion.Platform; string text; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { text = "win"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { text = "linux"; } else { if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { throw new PlatformNotSupportedException("Unsupported OS Version"); } text = "macos"; } string text2 = text; string architecture = RuntimeInformation.ProcessArchitecture switch { Architecture.X64 => "x64", Architecture.X86 => "x86", Architecture.Arm => "arm", Architecture.Arm64 => "arm64", _ => throw new PlatformNotSupportedException($"Unsupported process architecture: {RuntimeInformation.ProcessArchitecture}"), }; ILibraryLoader libraryLoader; switch (text2) { case "win": libraryLoader = new WindowsLibraryLoader(); break; case "macos": case "linux": libraryLoader = new LibdlLibraryLoader(); break; default: throw new PlatformNotSupportedException("Currently " + text2 + " platform is not supported"); } ILibraryLoader libraryLoader2 = libraryLoader; string text3 = null; List<(string RuntimePath, RuntimeLibrary RuntimeLibrary)> list = GetRuntimePaths(architecture, text2).ToList(); List<RuntimeLibrary> runtimeLibraries = list.Select<(string, RuntimeLibrary), RuntimeLibrary>(((string RuntimePath, RuntimeLibrary RuntimeLibrary) x) => x.RuntimeLibrary).ToList(); foreach (var (runtimePath, runtimeLibrary) in list) { if (!IsRuntimeSupported(runtimeLibrary, text2, architecture, runtimeLibraries)) { continue; } string libraryPath = GetLibraryPath(text2, "whisper", runtimePath); if (!File.Exists(libraryPath)) { continue; } List<IntPtr> list2 = new List<IntPtr>(); text3 = null; string[] array = dependencyOrder; foreach (string libraryName in array) { string libraryPath2 = GetLibraryPath(text2, libraryName, runtimePath); if (!File.Exists(libraryPath2)) { continue; } WhisperLogger.Log(WhisperLogLevel.Debug, "Loading dependency at " + libraryPath2); if (!libraryLoader2.TryOpenLibrary(libraryPath2, out var libHandle)) { text3 = libraryLoader2.GetLastError(); WhisperLogger.Log(WhisperLogLevel.Debug, "Couldn't load dependency at " + libraryPath2 + ". Received: " + text3); foreach (IntPtr item in list2) { libraryLoader2.CloseLibrary(item); } list2.Clear(); } else { list2.Add(libHandle); } } WhisperLogger.Log(WhisperLogLevel.Debug, "Trying to load whisper library from " + libraryPath); if (!libraryLoader2.TryOpenLibrary(libraryPath, out var _)) { text3 = libraryLoader2.GetLastError(); foreach (IntPtr item2 in list2) { libraryLoader2.CloseLibrary(item2); } WhisperLogger.Log(WhisperLogLevel.Debug, "Failed to load whisper library from " + libraryPath + ". Error: " + text3); continue; } WhisperLogger.Log(WhisperLogLevel.Debug, "Successfully loaded whisper library from " + libraryPath); RuntimeOptions.LoadedLibrary = runtimeLibrary; WhisperLogger.Log(WhisperLogLevel.Debug, "Using DllImportsNativeWhisper for whisper library"); return LoadResult.Success(new DllImportsNativeWhisper()); } if (text3 == null) { throw new FileNotFoundException("Native Library not found in default paths.Verify you have have included the native Whisper library in your application, or install the default libraries with the Whisper.net.Runtime NuGet."); } return LoadResult.Failure(text3); } private static string GetLibraryPath(string platform, string libraryName, string runtimePath) { return Path.Combine(runtimePath, platform switch { "win" => libraryName + ".dll", "macos" => "lib" + libraryName + ".dylib", "linux" => "lib" + libraryName + ".so", _ => throw new PlatformNotSupportedException("Unsupported OS platform: " + platform), }); } private static bool IsRuntimeSupported(RuntimeLibrary runtime, string platform, string architecture, List<RuntimeLibrary> runtimeLibraries) { WhisperLogger.Log(WhisperLogLevel.Debug, $"Checking if runtime {runtime} is supported on the platform: {platform}"); if (runtime == RuntimeLibrary.Cuda && !CudaHelper.IsCudaAvailable()) { if (runtimeLibraries.IndexOf(RuntimeLibrary.Cuda) == RuntimeOptions.RuntimeLibraryOrder.Count - 1) { WhisperLogger.Log(WhisperLogLevel.Debug, "Cuda runtime is not available, but it's the last runtime in the list. It will be used as a fallback to the CPU runtime."); return true; } WhisperLogger.Log(WhisperLogLevel.Debug, "Cuda driver is not available or no cuda device is identified."); return false; } return true; } private static IEnumerable<(string RuntimePath, RuntimeLibrary RuntimeLibrary)> GetRuntimePaths(string architecture, string platform) { string location = typeof(NativeLibraryLoader).Assembly.Location; IEnumerable<string> assemblySearchPaths = new string[5] { GetSafeDirectoryName(RuntimeOptions.LibraryPath), AppDomain.CurrentDomain.RelativeSearchPath, AppDomain.CurrentDomain.BaseDirectory, GetSafeDirectoryName(location), GetSafeDirectoryName(Environment.GetCommandLineArgs().FirstOrDefault()) }.Where((string it) => !string.IsNullOrEmpty(it)).Distinct(); foreach (RuntimeLibrary library in RuntimeOptions.RuntimeLibraryOrder) { foreach (string item in assemblySearchPaths) { string path = (string.IsNullOrEmpty(item) ? "runtimes" : Path.Combine(item, "runtimes")); string text = library switch { RuntimeLibrary.Cuda => Path.Combine(path, "cuda", platform + "-" + architecture), RuntimeLibrary.Vulkan => Path.Combine(path, "vulkan", platform + "-" + architecture), RuntimeLibrary.Cpu => Path.Combine(path, platform + "-" + architecture), RuntimeLibrary.CpuNoAvx => Path.Combine(path, "noavx", platform + "-" + architecture), RuntimeLibrary.CoreML => Path.Combine(path, "coreml", platform + "-" + architecture), RuntimeLibrary.OpenVino => Path.Combine(path, "openvino", platform + "-" + architecture), _ => throw new InvalidOperationException("Unknown runtime library"), }; WhisperLogger.Log(WhisperLogLevel.Debug, $"Searching for runtime directory {library} in {text}"); if (Directory.Exists(text)) { yield return (RuntimePath: text, RuntimeLibrary: library); } else { WhisperLogger.Log(WhisperLogLevel.Debug, $"Runtime directory for {library} not found in {text}"); } } } } private static string? GetSafeDirectoryName(string? path) { if (string.IsNullOrWhiteSpace(path)) { return null; } try { return Path.GetDirectoryName(path); } catch (Exception ex) { WhisperLogger.Log(WhisperLogLevel.Debug, "Failed to get directory name from path: " + path + ". Error: " + ex.Message); return null; } } } public enum RuntimeLibrary { Cpu, Cuda, Vulkan, CoreML, OpenVino, CpuNoAvx } public static class RuntimeOptions { private static readonly List<RuntimeLibrary> defaultRuntimeOrder = new List<RuntimeLibrary>(6) { RuntimeLibrary.Cuda, RuntimeLibrary.Vulkan, RuntimeLibrary.CoreML, RuntimeLibrary.OpenVino, RuntimeLibrary.Cpu, RuntimeLibrary.CpuNoAvx }; public static string? LibraryPath { get; set; } public static List<RuntimeLibrary> RuntimeLibraryOrder { get; set; } = defaultRuntimeOrder; public static RuntimeLibrary? LoadedLibrary { get; set; } } internal class WindowsLibraryLoader : ILibraryLoader { [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPTStr)] string? lpFileName); [DllImport("kernel32", SetLastError = true)] private static extern bool FreeLibrary(IntPtr hModule); public void CloseLibrary(nint handle) { FreeLibrary(handle); } public bool TryOpenLibrary(string fileName, out IntPtr libHandle) { try { libHandle = LoadLibrary(fileName); return libHandle != IntPtr.Zero; } catch { libHandle = IntPtr.Zero; return false; } } public string GetLastError() { return new Win32Exception(Marshal.GetLastWin32Error()).Message; } } } namespace Whisper.net.Native { internal enum WhisperSamplingStrategy { StrategyGreedy, StrategyBeamSearch } internal enum WhisperAlignmentHeadsPreset { WHISPER_AHEADS_NONE, WHISPER_AHEADS_N_TOP_MOST, WHISPER_AHEADS_CUSTOM, WHISPER_AHEADS_TINY_EN, WHISPER_AHEADS_TINY, WHISPER_AHEADS_BASE_EN, WHISPER_AHEADS_BASE, WHISPER_AHEADS_SMALL_EN, WHISPER_AHEADS_SMALL, WHISPER_AHEADS_MEDIUM_EN, WHISPER_AHEADS_MEDIUM, WHISPER_AHEADS_LARGE_V1, WHISPER_AHEADS_LARGE_V2, WHISPER_AHEADS_LARGE_V3, WHISPER_AHEADS_LARGE_V3_TURBO } internal struct WhisperParamGreedy { public int BestOf; } internal struct WhisperParamBeamSearch { public int BeamSize; public float Patience; } internal enum GgmlLogLevel { Error = 2, Warning, Info } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void WhisperNewSegmentCallback(IntPtr ctx, IntPtr state, int n_new, IntPtr user_data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate byte WhisperEncoderBeginCallback(IntPtr ctx, IntPtr state, IntPtr user_data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void WhisperProgressCallback(IntPtr ctx, IntPtr state, int progress, IntPtr user_data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate byte WhisperLogitsFilterCallback(IntPtr ctx, IntPtr state, IntPtr tokens, int tokens_count, IntPtr logits, IntPtr user_data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate byte WhisperAbortCallback(IntPtr user_data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void WhisperGgmlLogCallback(GgmlLogLevel level, IntPtr message, IntPtr user_data); internal struct WhisperAhead { public int n_text_layer; public int n_head; } internal struct WhisperAheads { public UIntPtr NHeads; public IntPtr Heads; } internal struct WhisperContextParams { public byte UseGpu; public byte FlashAttention; public int GpuDevice; public byte DtwTokenLevelTimestamp; public WhisperAlignmentHeadsPreset HeadsPreset; public int DtwNTop; public WhisperAheads WhisperAheads; public UIntPtr Dtw_mem_size; } internal struct WhisperFullParams { public WhisperSamplingStrategy Strategy; public int Threads; public int MaxLastTextTokens; public int OffsetMs; public int DurationMs; public byte Translate; public byte NoContext; public byte NoTimestamps; public byte SingleSegment; public byte PrintSpecialTokens; public byte PrintProgress; public byte PrintResults; public byte PrintTimestamps; public byte UseTokenTimestamps; public float TokenTimestampsThreshold; public float TokenTimestampsSumThreshold; public int MaxSegmentLength; public byte SplitOnWord; public int MaxTokensPerSegment; public byte DebugMode; public int AudioContextSize; public byte TinyDiarizeSpeakerTurnDirection; public IntPtr SuppressRegex; public IntPtr InitialPrompt; public IntPtr PromptTokens; public int PromptNTokens; public IntPtr Language; public byte DetectLanguage; public byte SuppressBlank; public byte SupressNonSpeechTokens; public float Temperature; public float MaxInitialTs; public float LengthPenalty; public float TemperatureInc; public float EntropyThreshold; public float LogProbThreshold; public float NoSpeechThreshold; public WhisperParamGreedy WhisperParamGreedy; public WhisperParamBeamSearch WhisperParamBeamSearch; public IntPtr OnNewSegment; public IntPtr OnNewSegmentUserData; public IntPtr OnProgressCallback; public IntPtr OnProgressCallbackUserData; public IntPtr OnEncoderBegin; public IntPtr OnEncoderBeginUserData; public IntPtr OnAbort; public IntPtr OnAbortUserData; public IntPtr LogitsFilterCallback; public IntPtr LogitsFilterCallbackData; public IntPtr WhisperGrammarElement; public UIntPtr NGrammarRules; public UIntPtr StartGrammarRule; public float GrammarPenalty; } internal struct WhisperContext { } internal struct WhisperTokenData { public int id; public int tid; public float p; public float plog; public float pt; public float ptsum; public long t0; public long t1; public long t_dtw; public float vlen; } } namespace Whisper.net.Internals { internal class AsyncAutoResetEvent { private static readonly Task Completed = Task.CompletedTask; private TaskCompletionSource<bool>? waitTcs; private int isSignaled; public Task WaitAsync() { if (Interlocked.CompareExchange(ref isSignaled, 0, 1) == 1) { return Completed; } TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); Interlocked.Exchange(ref waitTcs, taskCompletionSource)?.TrySetCanceled(); return taskCompletionSource.Task; } public void Set() { TaskCompletionSource<bool> taskCompletionSource = Interlocked.Exchange(ref waitTcs, null); if (taskCompletionSource != null) { taskCompletionSource.SetResult(result: true); } else { Interlocked.Exchange(ref isSignaled, 1); } } } internal class StringPool : IStringPool { public sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T> where T : class { public static ReferenceEqualityComparer<T> Instance { get; } = new ReferenceEqualityComparer<T>(); public bool Equals(T? x, T? y) { return x == y; } public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); } } private readonly SortedList<int, Stack<string>> pool = new SortedList<int, Stack<string>>(); private readonly Dictionary<string, int> stringCapacities = new Dictionary<string, int>(ReferenceEqualityComparer<string>.Instance); public unsafe string? GetStringUtf8(IntPtr nativePointer) { if (nativePointer == IntPtr.Zero) { return null; } int i; for (i = 0; Marshal.ReadByte(nativePointer, i) != 0; i++) { } int num = i; int candidateCapacity; string text = TryGetCandidateFromPool(num, out candidateCapacity); if (text == null) { text = new string('\0', num); candidateCapacity = num; stringCapacities[text] = candidateCapacity; } byte* bytes = (byte*)nativePointer.ToPointer(); fixed (char* chars = text) { int chars2 = Encoding.UTF8.GetChars(bytes, i, chars, candidateCapacity); if (chars2 != candidateCapacity) { UnsafeSetStringLength(text, chars2); } } return text; } public void ReturnString(string? returnedString) { if (returnedString != null && stringCapacities.TryGetValue(returnedString, out var value)) { if (!pool.TryGetValue(value, out Stack<string> value2)) { value2 = new Stack<string>(); pool[value] = value2; } value2.Push(returnedString); } } private string? TryGetCandidateFromPool(int requiredCharCount, out int candidateCapacity) { candidateCapacity = 0; string text = null; int num = 0; int num2 = pool.Count - 1; int num3 = -1; while (num <= num2) { int num4 = (num + num2) / 2; if (pool.Keys[num4] < requiredCharCount) { num = num4 + 1; continue; } num3 = num4; num2 = num4 - 1; } if (num3 != -1) { for (int i = num3; i < pool.Count; i++) { int num5 = pool.Keys[i]; if (num5 > requiredCharCount * 2) { break; } if (pool.Values[i].Count > 0) { text = pool.Values[i].Pop(); candidateCapacity = num5; if (pool.Values[i].Count == 0) { pool.RemoveAt(i); } break; } } if (text == null) { for (int j = num3; j < pool.Count; j++) { int num6 = pool.Keys[j]; if (pool.Values[j].Count > 0) { text = pool.Values[j].Pop(); candidateCapacity = num6; if (pool.Values[j].Count == 0) { pool.RemoveAt(j); } break; } } } } return text; } private unsafe static void UnsafeSetStringLength(string str, int newLength) { fixed (char* ptr = str) { *((int*)ptr - 1) = newLength; } } } } namespace Whisper.net.Internals.Native { internal interface INativeCuda : IDisposable { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int cudaGetDeviceCount(out int count); cudaGetDeviceCount CudaGetDeviceCount { get; } } internal interface INativeWhisper : IDisposable { [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr whisper_init_from_file_with_params_no_state(string path, WhisperContextParams whisperContextParams); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr whisper_init_from_buffer_with_params_no_state(IntPtr buffer, nuint buffer_size, WhisperContextParams whisperContextParams); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate void whisper_free(IntPtr context); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate void whisper_free_params(IntPtr paramsPtr); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr whisper_full_default_params_by_ref(WhisperSamplingStrategy strategy); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int whisper_full_with_state(IntPtr context, IntPtr state, WhisperFullParams parameters, IntPtr samples, int nSamples); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int whisper_full_n_segments_from_state(IntPtr state); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate long whisper_full_get_segment_t0_from_state(IntPtr state, int index); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate long whisper_full_get_segment_t1_from_state(IntPtr state, int index); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr whisper_full_get_segment_text_from_state(IntPtr state, int index); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int whisper_full_n_tokens_from_state(IntPtr state, int index); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate float whisper_full_get_token_p_from_state(IntPtr state, int segmentIndex, int tokenIndex); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int whisper_lang_max_id(); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int whisper_lang_auto_detect_with_state(IntPtr context, IntPtr state, int offset_ms, int n_threads, IntPtr lang_probs); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int whisper_pcm_to_mel_with_state(IntPtr context, IntPtr state, IntPtr samples, int nSamples, int nThreads); [UnmanagedFunctionPointer(Cal
Plugins/V2TBootstrap.dll
Decompiled a month agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using V2T.Bootstrap; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(BootstrapPlugin), "V2T Bootstrap", "2.0.4", "Pasharacc", null)] [assembly: MelonGame("Keepsake Games", "Jump Space")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("V2TBootstrap")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.4.0")] [assembly: AssemblyInformationalVersion("2.0.4")] [assembly: AssemblyProduct("V2TBootstrap")] [assembly: AssemblyTitle("V2TBootstrap")] [assembly: AssemblyVersion("2.0.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 V2T.Bootstrap { public class BootstrapPlugin : MelonPlugin { public override void OnPreInitialization() { try { Cleaner.Apply(Path.Combine(MelonEnvironment.DependenciesDirectory, "Il2CppAssemblyGenerator"), (Action<string>)((MelonBase)this).LoggerInstance.Msg, (Action<string>)((MelonBase)this).LoggerInstance.Warning); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("could not clear the previous Cpp2IL output: " + ex); } } } public static class Cleaner { public static string Apply(string genDir, Action<string> log, Action<string> warn) { string path = Path.Combine(genDir, "Cpp2IL", "cpp2il_out"); if (!Directory.Exists(path)) { log("no previous Cpp2IL output to clear"); return "nothing to clear"; } int value = Directory.GetFiles(path, "*", SearchOption.AllDirectories).Length; Directory.Delete(path, recursive: true); if (Directory.Exists(path)) { warn("previous Cpp2IL output could not be removed; a stale assembly may break generation after a game update"); return "FAILED to clear"; } log($"cleared the previous Cpp2IL output ({value} files) so a game update cannot leave stale assemblies in it"); return $"cleared {value} files"; } } }