Decompiled source of Bullets Per Minute OST v1.0.0
NAudio.dll
Decompiled 10 hours 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.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; 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.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; using Microsoft.Win32; using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; using NAudio.Dmo; using NAudio.Dsp; using NAudio.FileFormats.Wav; using NAudio.MediaFoundation; using NAudio.Mixer; using NAudio.Utils; using NAudio.Wave; using NAudio.Wave.Asio; using NAudio.Wave.Compression; using NAudio.Wave.SampleProviders; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("NAudio")] [assembly: AssemblyDescription("NAudio .NET Audio Library")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Mark Heath")] [assembly: AssemblyProduct("NAudio")] [assembly: AssemblyCopyright("© 2001-2017 Mark Heath")] [assembly: AssemblyTrademark("")] [assembly: InternalsVisibleTo("NAudioTests")] [assembly: ComVisible(false)] [assembly: Guid("e82fa7f0-f952-4d93-b7b0-392bbf53b2a4")] [assembly: AssemblyFileVersion("1.8.4.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.8.4.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 { private MmResult result; private string function; public MmResult Result => result; public MmException(MmResult result, string function) : base(ErrorMessage(result, function)) { this.result = result; this.function = function; } private static string ErrorMessage(MmResult result, string function) { return $"{result} calling {function}"; } public static void Try(MmResult result, string function) { if (result != 0) { throw new MmException(result, function); } } } public enum MmResult { NoError = 0, UnspecifiedError = 1, BadDeviceId = 2, NotEnabled = 3, AlreadyAllocated = 4, InvalidHandle = 5, NoDriver = 6, MemoryAllocationError = 7, NotSupported = 8, BadErrorNumber = 9, InvalidFlag = 10, InvalidParameter = 11, HandleBusy = 12, InvalidAlias = 13, BadRegistryDatabase = 14, RegistryKeyNotFound = 15, RegistryReadError = 16, RegistryWriteError = 17, RegistryDeleteError = 18, RegistryValueNotFound = 19, NoDriverCallback = 20, MoreData = 21, WaveBadFormat = 32, WaveStillPlaying = 33, WaveHeaderUnprepared = 34, WaveSync = 35, AcmNotPossible = 512, AcmBusy = 513, AcmHeaderUnprepared = 514, AcmCancelled = 515, MixerInvalidLine = 1024, MixerInvalidControl = 1025, MixerInvalidValue = 1026 } } namespace NAudio.Mixer { public class BooleanMixerControl : MixerControl { private MixerInterop.MIXERCONTROLDETAILS_BOOLEAN boolDetails; public bool Value { get { GetControlDetails(); return boolDetails.fValue == 1; } set { boolDetails.fValue = (value ? 1 : 0); mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf((object)boolDetails)); Marshal.StructureToPtr((object)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 = (MixerInterop.MIXERCONTROLDETAILS_BOOLEAN)Marshal.PtrToStructure(pDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN)); } } 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) { if (mixerIndex < 0 || mixerIndex >= NumberOfDevices) { throw new ArgumentOutOfRangeException("mixerID"); } caps = default(MixerInterop.MIXERCAPS); MmException.Try(MixerInterop.mixerGetDevCaps((IntPtr)mixerIndex, ref caps, Marshal.SizeOf((object)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) { List<MixerControl> list = new List<MixerControl>(); if (mixerLine.ControlsCount > 0) { int num = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL)); MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS); IntPtr intPtr = Marshal.AllocHGlobal(num * mixerLine.ControlsCount); mixerLineControls.cbStruct = Marshal.SizeOf((object)mixerLineControls); mixerLineControls.dwLineID = mixerLine.LineId; mixerLineControls.cControls = mixerLine.ControlsCount; mixerLineControls.pamxctrl = intPtr; mixerLineControls.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL)); try { MmResult mmResult = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.Mixer | mixerHandleType); if (mmResult != 0) { throw new MmException(mmResult, "mixerGetLineControls"); } for (int i = 0; i < mixerLineControls.cControls; i++) { MixerInterop.MIXERCONTROL mIXERCONTROL = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)(intPtr.ToInt64() + num * i), typeof(MixerInterop.MIXERCONTROL)); 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) { MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS); MixerInterop.MIXERCONTROL mIXERCONTROL = default(MixerInterop.MIXERCONTROL); IntPtr intPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf((object)mIXERCONTROL)); mixerLineControls.cbStruct = Marshal.SizeOf((object)mixerLineControls); mixerLineControls.cControls = 1; mixerLineControls.dwControlID = controlId; mixerLineControls.cbmxctrl = Marshal.SizeOf((object)mIXERCONTROL); mixerLineControls.pamxctrl = intPtr; mixerLineControls.dwLineID = nLineID; MmResult mmResult = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.ListText | mixerFlags); if (mmResult != 0) { Marshal.FreeCoTaskMem(intPtr); throw new MmException(mmResult, "mixerGetLineControls"); } mIXERCONTROL = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure(mixerLineControls.pamxctrl, typeof(MixerInterop.MIXERCONTROL)); Marshal.FreeCoTaskMem(intPtr); if (IsControlBoolean(mIXERCONTROL.dwControlType)) { return new BooleanMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels); } if (IsControlSigned(mIXERCONTROL.dwControlType)) { return new SignedMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels); } if (IsControlUnsigned(mIXERCONTROL.dwControlType)) { return new UnsignedMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels); } if (IsControlListText(mIXERCONTROL.dwControlType)) { return new ListTextMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels); } if (IsControlCustom(mIXERCONTROL.dwControlType)) { return new CustomMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels); } throw new InvalidOperationException($"Unknown mixer control type {mIXERCONTROL.dwControlType}"); } protected void GetControlDetails() { mixerControlDetails.cbStruct = Marshal.SizeOf((object)mixerControlDetails); mixerControlDetails.dwControlID = mixerControl.dwControlID; if (IsCustom) { mixerControlDetails.cChannels = 0; } else if ((mixerControl.fdwControl & (true ? 1u : 0u)) != 0) { mixerControlDetails.cChannels = 1; } else { mixerControlDetails.cChannels = nChannels; } if ((mixerControl.fdwControl & 2u) != 0) { mixerControlDetails.hwndOwner = (IntPtr)mixerControl.cMultipleItems; } else if (IsCustom) { mixerControlDetails.hwndOwner = IntPtr.Zero; } else { mixerControlDetails.hwndOwner = IntPtr.Zero; } if (IsBoolean) { mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN)); } else if (IsListText) { mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_LISTTEXT)); } else if (IsSigned) { mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_SIGNED)); } else if (IsUnsigned) { mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_UNSIGNED)); } else { mixerControlDetails.cbDetails = mixerControl.Metrics.customData; } int num = mixerControlDetails.cbDetails * mixerControlDetails.cChannels; if ((mixerControl.fdwControl & 2u) != 0) { num *= (int)mixerControl.cMultipleItems; } IntPtr intPtr = Marshal.AllocCoTaskMem(num); mixerControlDetails.paDetails = intPtr; MmResult mmResult = MixerInterop.mixerGetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType); if (mmResult == MmResult.NoError) { GetDetails(mixerControlDetails.paDetails); } Marshal.FreeCoTaskMem(intPtr); if (mmResult != 0) { throw new MmException(mmResult, "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 } 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) { this.mixerHandle = mixerHandle; this.mixerHandleType = mixerHandleType; mixerLine = default(MixerInterop.MIXERLINE); mixerLine.cbStruct = Marshal.SizeOf((object)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) { this.mixerHandle = mixerHandle; this.mixerHandleType = mixerHandleType; mixerLine = default(MixerInterop.MIXERLINE); mixerLine.cbStruct = Marshal.SizeOf((object)mixerLine); mixerLine.dwDestination = destinationIndex; mixerLine.dwSource = sourceIndex; MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.ListText), "mixerGetLineInfo"); } public static int GetMixerIdForWaveIn(int waveInDevice) { 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})"; } } [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 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 { signedDetails.lValue = value; mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf((object)signedDetails)); Marshal.StructureToPtr((object)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 = (MixerInterop.MIXERCONTROLDETAILS_SIGNED)Marshal.PtrToStructure(mixerControlDetails.paDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_SIGNED)); } 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 { int num = Marshal.SizeOf((object)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((object)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] = (MixerInterop.MIXERCONTROLDETAILS_UNSIGNED)Marshal.PtrToStructure(mixerControlDetails.paDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_UNSIGNED)); } } public override string ToString() { return $"{base.ToString()} {Percent}%"; } } } namespace NAudio.Gui { public class Fader : Control { private int minimum; private int maximum; private float percent; private Orientation orientation; private Container components; private readonly int SliderHeight = 30; private readonly int SliderWidth = 15; private Rectangle sliderRectangle; private bool dragging; private int dragY; public int Minimum { get { return minimum; } set { minimum = value; } } public int Maximum { get { return maximum; } set { maximum = value; } } public int Value { get { return (int)(percent * (float)(maximum - minimum)) + minimum; } set { percent = (float)(value - minimum) / (float)(maximum - minimum); } } public Orientation Orientation { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return orientation; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) orientation = value; } } public Fader() { InitializeComponent(); ((Control)this).SetStyle((ControlStyles)73730, true); } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((Control)this).Dispose(disposing); } private void DrawSlider(Graphics g) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown Brush val = (Brush)new SolidBrush(Color.White); Pen val2 = new Pen(Color.Black); sliderRectangle.X = (((Control)this).Width - SliderWidth) / 2; sliderRectangle.Width = SliderWidth; sliderRectangle.Y = (int)((float)(((Control)this).Height - SliderHeight) * percent); sliderRectangle.Height = SliderHeight; g.FillRectangle(val, sliderRectangle); g.DrawLine(val2, sliderRectangle.Left, sliderRectangle.Top + sliderRectangle.Height / 2, sliderRectangle.Right, sliderRectangle.Top + sliderRectangle.Height / 2); val.Dispose(); val2.Dispose(); } protected override void OnPaint(PaintEventArgs e) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Graphics graphics = e.Graphics; if ((int)Orientation == 1) { Brush val = (Brush)new SolidBrush(Color.Black); graphics.FillRectangle(val, ((Control)this).Width / 2, SliderHeight / 2, 2, ((Control)this).Height - SliderHeight); val.Dispose(); DrawSlider(graphics); } ((Control)this).OnPaint(e); } protected override void OnMouseDown(MouseEventArgs e) { if (sliderRectangle.Contains(e.X, e.Y)) { dragging = true; dragY = e.Y - sliderRectangle.Y; } ((Control)this).OnMouseDown(e); } protected override void OnMouseMove(MouseEventArgs e) { if (dragging) { int num = e.Y - dragY; if (num < 0) { percent = 0f; } else if (num > ((Control)this).Height - SliderHeight) { percent = 1f; } else { percent = (float)num / (float)(((Control)this).Height - SliderHeight); } ((Control)this).Invalidate(); } ((Control)this).OnMouseMove(e); } protected override void OnMouseUp(MouseEventArgs e) { dragging = false; ((Control)this).OnMouseUp(e); } private void InitializeComponent() { this.components = new System.ComponentModel.Container(); } } public class PanSlider : UserControl { private Container components; private float pan; public float Pan { get { return pan; } set { if (value < -1f) { value = -1f; } if (value > 1f) { value = 1f; } if (value != pan) { pan = value; if (this.PanChanged != null) { this.PanChanged(this, EventArgs.Empty); } ((Control)this).Invalidate(); } } } public event EventHandler PanChanged; public PanSlider() { InitializeComponent(); } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((ContainerControl)this).Dispose(disposing); } private void InitializeComponent() { ((Control)this).Name = "PanSlider"; ((Control)this).Size = new Size(104, 16); } protected override void OnPaint(PaintEventArgs pe) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown StringFormat val = new StringFormat(); val.LineAlignment = (StringAlignment)1; val.Alignment = (StringAlignment)1; string text; if ((double)pan == 0.0) { pe.Graphics.FillRectangle(Brushes.Orange, ((Control)this).Width / 2 - 1, 1, 3, ((Control)this).Height - 2); text = "C"; } else if (pan > 0f) { pe.Graphics.FillRectangle(Brushes.Orange, ((Control)this).Width / 2, 1, (int)((float)(((Control)this).Width / 2) * pan), ((Control)this).Height - 2); text = $"{pan * 100f:F0}%R"; } else { pe.Graphics.FillRectangle(Brushes.Orange, (int)((float)(((Control)this).Width / 2) * (pan + 1f)), 1, (int)((float)(((Control)this).Width / 2) * (0f - pan)), ((Control)this).Height - 2); text = $"{pan * -100f:F0}%L"; } pe.Graphics.DrawRectangle(Pens.Black, 0, 0, ((Control)this).Width - 1, ((Control)this).Height - 1); pe.Graphics.DrawString(text, ((Control)this).Font, Brushes.Black, (RectangleF)((Control)this).ClientRectangle, val); } protected override void OnMouseMove(MouseEventArgs e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)e.Button == 1048576) { SetPanFromMouse(e.X); } ((Control)this).OnMouseMove(e); } protected override void OnMouseDown(MouseEventArgs e) { SetPanFromMouse(e.X); ((UserControl)this).OnMouseDown(e); } private void SetPanFromMouse(int x) { Pan = (float)x / (float)((Control)this).Width * 2f - 1f; } } public class Pot : UserControl { private double minimum; private double maximum = 1.0; private double value = 0.5; private int beginDragY; private double beginDragValue; private bool dragging; private IContainer components; public double Minimum { get { return minimum; } set { if (value >= maximum) { throw new ArgumentOutOfRangeException("Minimum must be less than maximum"); } minimum = value; if (Value < minimum) { Value = minimum; } } } public double Maximum { get { return maximum; } set { if (value <= minimum) { throw new ArgumentOutOfRangeException("Maximum must be greater than minimum"); } maximum = value; if (Value > maximum) { Value = maximum; } } } public double Value { get { return value; } set { SetValue(value, raiseEvents: false); } } public event EventHandler ValueChanged; public Pot() { ((Control)this).SetStyle((ControlStyles)73730, true); InitializeComponent(); } private void SetValue(double newValue, bool raiseEvents) { if (value != newValue) { value = newValue; if (raiseEvents && this.ValueChanged != null) { this.ValueChanged(this, EventArgs.Empty); } ((Control)this).Invalidate(); } } protected override void OnPaint(PaintEventArgs e) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown int num = Math.Min(((Control)this).Width - 4, ((Control)this).Height - 4); Pen val = new Pen(((Control)this).ForeColor, 3f); val.LineJoin = (LineJoin)2; GraphicsState val2 = e.Graphics.Save(); e.Graphics.TranslateTransform((float)(((Control)this).Width / 2), (float)(((Control)this).Height / 2)); e.Graphics.SmoothingMode = (SmoothingMode)4; e.Graphics.DrawArc(val, new Rectangle(num / -2, num / -2, num, num), 135f, 270f); double num2 = (value - minimum) / (maximum - minimum); double num3 = 135.0 + num2 * 270.0; double num4 = (double)num / 2.0 * Math.Cos(Math.PI * num3 / 180.0); double num5 = (double)num / 2.0 * Math.Sin(Math.PI * num3 / 180.0); e.Graphics.DrawLine(val, 0f, 0f, (float)num4, (float)num5); e.Graphics.Restore(val2); ((Control)this).OnPaint(e); } protected override void OnMouseDown(MouseEventArgs e) { dragging = true; beginDragY = e.Y; beginDragValue = value; ((UserControl)this).OnMouseDown(e); } protected override void OnMouseUp(MouseEventArgs e) { dragging = false; ((Control)this).OnMouseUp(e); } protected override void OnMouseMove(MouseEventArgs e) { if (dragging) { int num = beginDragY - e.Y; double num2 = (maximum - minimum) * ((double)num / 150.0); double num3 = beginDragValue + num2; if (num3 < minimum) { num3 = minimum; } if (num3 > maximum) { num3 = maximum; } SetValue(num3, raiseEvents: true); } ((Control)this).OnMouseMove(e); } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((ContainerControl)this).Dispose(disposing); } private void InitializeComponent() { ((Control)this).SuspendLayout(); ((ContainerControl)this).AutoScaleDimensions = new SizeF(6f, 13f); ((ContainerControl)this).AutoScaleMode = (AutoScaleMode)1; ((Control)this).Name = "Pot"; ((Control)this).Size = new Size(32, 32); ((Control)this).ResumeLayout(false); } } public class VolumeMeter : Control { private Brush foregroundBrush; private float amplitude; private IContainer components; [DefaultValue(-3.0)] public float Amplitude { get { return amplitude; } set { amplitude = value; ((Control)this).Invalidate(); } } [DefaultValue(-60.0)] public float MinDb { get; set; } [DefaultValue(18.0)] public float MaxDb { get; set; } [DefaultValue(/*Could not decode attribute arguments.*/)] public Orientation Orientation { get; set; } public VolumeMeter() { ((Control)this).SetStyle((ControlStyles)139266, true); MinDb = -60f; MaxDb = 18f; Amplitude = 0f; Orientation = (Orientation)1; InitializeComponent(); ((Control)this).OnForeColorChanged(EventArgs.Empty); } protected override void OnForeColorChanged(EventArgs e) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown foregroundBrush = (Brush)new SolidBrush(((Control)this).ForeColor); ((Control)this).OnForeColorChanged(e); } protected override void OnPaint(PaintEventArgs pe) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) pe.Graphics.DrawRectangle(Pens.Black, 0, 0, ((Control)this).Width - 1, ((Control)this).Height - 1); double num = 20.0 * Math.Log10(Amplitude); if (num < (double)MinDb) { num = MinDb; } if (num > (double)MaxDb) { num = MaxDb; } double num2 = (num - (double)MinDb) / (double)(MaxDb - MinDb); int num3 = ((Control)this).Width - 2; int num4 = ((Control)this).Height - 2; if ((int)Orientation == 0) { num3 = (int)((double)num3 * num2); pe.Graphics.FillRectangle(foregroundBrush, 1, 1, num3, num4); } else { num4 = (int)((double)num4 * num2); pe.Graphics.FillRectangle(foregroundBrush, 1, ((Control)this).Height - 1 - num4, num3, num4); } } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((Control)this).Dispose(disposing); } private void InitializeComponent() { this.components = new System.ComponentModel.Container(); } } public class VolumeSlider : UserControl { private Container components; private float volume = 1f; private float MinDb = -48f; [DefaultValue(1f)] public float Volume { get { return volume; } set { if (value < 0f) { value = 0f; } if (value > 1f) { value = 1f; } if (volume != value) { volume = value; if (this.VolumeChanged != null) { this.VolumeChanged(this, EventArgs.Empty); } ((Control)this).Invalidate(); } } } public event EventHandler VolumeChanged; public VolumeSlider() { InitializeComponent(); } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((ContainerControl)this).Dispose(disposing); } private void InitializeComponent() { ((Control)this).Name = "VolumeSlider"; ((Control)this).Size = new Size(96, 16); } protected override void OnPaint(PaintEventArgs pe) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown StringFormat val = new StringFormat(); val.LineAlignment = (StringAlignment)1; val.Alignment = (StringAlignment)1; pe.Graphics.DrawRectangle(Pens.Black, 0, 0, ((Control)this).Width - 1, ((Control)this).Height - 1); float num = 20f * (float)Math.Log10(Volume); float num2 = 1f - num / MinDb; pe.Graphics.FillRectangle(Brushes.LightGreen, 1, 1, (int)((float)(((Control)this).Width - 2) * num2), ((Control)this).Height - 2); string text = $"{num:F2} dB"; pe.Graphics.DrawString(text, ((Control)this).Font, Brushes.Black, (RectangleF)((Control)this).ClientRectangle, val); } protected override void OnMouseMove(MouseEventArgs e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)e.Button == 1048576) { SetVolumeFromMouse(e.X); } ((Control)this).OnMouseMove(e); } protected override void OnMouseDown(MouseEventArgs e) { SetVolumeFromMouse(e.X); ((UserControl)this).OnMouseDown(e); } private void SetVolumeFromMouse(int x) { float num = (1f - (float)x / (float)((Control)this).Width) * MinDb; if (x <= 0) { Volume = 0f; } else { Volume = (float)Math.Pow(10.0, num / 20f); } } } public class WaveformPainter : Control { private Pen foregroundPen; private List<float> samples = new List<float>(1000); private int maxSamples; private int insertPos; private IContainer components; public WaveformPainter() { ((Control)this).SetStyle((ControlStyles)139266, true); InitializeComponent(); ((Control)this).OnForeColorChanged(EventArgs.Empty); ((Control)this).OnResize(EventArgs.Empty); } protected override void OnResize(EventArgs e) { maxSamples = ((Control)this).Width; ((Control)this).OnResize(e); } protected override void OnForeColorChanged(EventArgs e) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown foregroundPen = new Pen(((Control)this).ForeColor); ((Control)this).OnForeColorChanged(e); } public void AddMax(float maxSample) { if (maxSamples != 0) { if (samples.Count <= maxSamples) { samples.Add(maxSample); } else if (insertPos < maxSamples) { samples[insertPos] = maxSample; } insertPos++; insertPos %= maxSamples; ((Control)this).Invalidate(); } } protected override void OnPaint(PaintEventArgs pe) { ((Control)this).OnPaint(pe); for (int i = 0; i < ((Control)this).Width; i++) { float num = (float)((Control)this).Height * GetSample(i - ((Control)this).Width + insertPos); float num2 = ((float)((Control)this).Height - num) / 2f; pe.Graphics.DrawLine(foregroundPen, (float)i, num2, (float)i, num2 + num); } } private float GetSample(int index) { if (index < 0) { index += maxSamples; } if ((index >= 0) & (index < samples.Count)) { return samples[index]; } return 0f; } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((Control)this).Dispose(disposing); } private void InitializeComponent() { this.components = new System.ComponentModel.Container(); } } public class WaveViewer : UserControl { private Container components; private WaveStream waveStream; private int samplesPerPixel = 128; private long startPosition; private int bytesPerSample; public WaveStream WaveStream { get { return waveStream; } set { waveStream = value; if (waveStream != null) { bytesPerSample = waveStream.WaveFormat.BitsPerSample / 8 * waveStream.WaveFormat.Channels; } ((Control)this).Invalidate(); } } public int SamplesPerPixel { get { return samplesPerPixel; } set { samplesPerPixel = value; ((Control)this).Invalidate(); } } public long StartPosition { get { return startPosition; } set { startPosition = value; } } public WaveViewer() { InitializeComponent(); ((Control)this).DoubleBuffered = true; } protected override void Dispose(bool disposing) { if (disposing && components != null) { components.Dispose(); } ((ContainerControl)this).Dispose(disposing); } protected override void OnPaint(PaintEventArgs e) { if (waveStream != null) { waveStream.Position = 0L; byte[] array = new byte[samplesPerPixel * bytesPerSample]; waveStream.Position = startPosition + e.ClipRectangle.Left * bytesPerSample * samplesPerPixel; for (float num = e.ClipRectangle.X; num < (float)e.ClipRectangle.Right; num += 1f) { short num2 = 0; short num3 = 0; int num4 = waveStream.Read(array, 0, samplesPerPixel * bytesPerSample); if (num4 == 0) { break; } for (int i = 0; i < num4; i += 2) { short num5 = BitConverter.ToInt16(array, i); if (num5 < num2) { num2 = num5; } if (num5 > num3) { num3 = num5; } } float num6 = ((float)num2 - -32768f) / 65535f; float num7 = ((float)num3 - -32768f) / 65535f; e.Graphics.DrawLine(Pens.Black, num, (float)((Control)this).Height * num6, num, (float)((Control)this).Height * num7); } } ((Control)this).OnPaint(e); } private void InitializeComponent() { components = new Container(); } } } namespace NAudio.SoundFont { public class Generator { private GeneratorEnum generatorType; private ushort rawAmount; private Instrument instrument; private SampleHeader sampleHeader; public GeneratorEnum GeneratorType { get { return generatorType; } set { generatorType = value; } } public ushort UInt16Amount { get { return rawAmount; } set { rawAmount = value; } } public short Int16Amount { get { return (short)rawAmount; } set { rawAmount = (ushort)value; } } public byte LowByteAmount { get { return (byte)(rawAmount & 0xFFu); } set { rawAmount &= 65280; rawAmount += value; } } public byte HighByteAmount { get { return (byte)((rawAmount & 0xFF00) >> 8); } set { rawAmount &= 255; rawAmount += (ushort)(value << 8); } } public Instrument Instrument { get { return instrument; } set { instrument = value; } } public SampleHeader SampleHeader { get { return sampleHeader; } set { sampleHeader = value; } } public override string ToString() { if (generatorType == GeneratorEnum.Instrument) { return $"Generator Instrument {instrument.Name}"; } if (generatorType == GeneratorEnum.SampleID) { return $"Generator SampleID {sampleHeader}"; } return $"Generator {generatorType} {rawAmount}"; } } internal class GeneratorBuilder : StructureBuilder<Generator> { public override int Length => 4; public Generator[] Generators => data.ToArray(); public override Generator Read(BinaryReader br) { Generator generator = new Generator(); generator.GeneratorType = (GeneratorEnum)br.ReadUInt16(); generator.UInt16Amount = br.ReadUInt16(); data.Add(generator); return generator; } public override void Write(BinaryWriter bw, Generator o) { } public void Load(Instrument[] instruments) { Generator[] generators = Generators; foreach (Generator generator in generators) { if (generator.GeneratorType == GeneratorEnum.Instrument) { generator.Instrument = instruments[generator.UInt16Amount]; } } } public void Load(SampleHeader[] sampleHeaders) { Generator[] generators = Generators; foreach (Generator generator in generators) { if (generator.GeneratorType == GeneratorEnum.SampleID) { generator.SampleHeader = sampleHeaders[generator.UInt16Amount]; } } } } public enum GeneratorEnum { StartAddressOffset, EndAddressOffset, StartLoopAddressOffset, EndLoopAddressOffset, StartAddressCoarseOffset, ModulationLFOToPitch, VibratoLFOToPitch, ModulationEnvelopeToPitch, InitialFilterCutoffFrequency, InitialFilterQ, ModulationLFOToFilterCutoffFrequency, ModulationEnvelopeToFilterCutoffFrequency, EndAddressCoarseOffset, ModulationLFOToVolume, Unused1, ChorusEffectsSend, ReverbEffectsSend, Pan, Unused2, Unused3, Unused4, DelayModulationLFO, FrequencyModulationLFO, DelayVibratoLFO, FrequencyVibratoLFO, DelayModulationEnvelope, AttackModulationEnvelope, HoldModulationEnvelope, DecayModulationEnvelope, SustainModulationEnvelope, ReleaseModulationEnvelope, KeyNumberToModulationEnvelopeHold, KeyNumberToModulationEnvelopeDecay, DelayVolumeEnvelope, AttackVolumeEnvelope, HoldVolumeEnvelope, DecayVolumeEnvelope, SustainVolumeEnvelope, ReleaseVolumeEnvelope, KeyNumberToVolumeEnvelopeHold, KeyNumberToVolumeEnvelopeDecay, Instrument, Reserved1, KeyRange, VelocityRange, StartLoopAddressCoarseOffset, KeyNumber, Velocity, InitialAttenuation, Reserved2, EndLoopAddressCoarseOffset, CoarseTune, FineTune, SampleID, SampleModes, Reserved3, ScaleTuning, ExclusiveClass, OverridingRootKey, Unused5, UnusedEnd } public class InfoChunk { public SFVersion SoundFontVersion { get; } public string WaveTableSoundEngine { get; set; } public string BankName { get; set; } public string DataROM { get; set; } public string CreationDate { get; set; } public string Author { get; set; } public string TargetProduct { get; set; } public string Copyright { get; set; } public string Comments { get; set; } public string Tools { get; set; } public SFVersion ROMVersion { get; set; } internal InfoChunk(RiffChunk chunk) { bool flag = false; bool flag2 = false; if (chunk.ReadChunkID() != "INFO") { throw new InvalidDataException("Not an INFO chunk"); } RiffChunk nextSubChunk; while ((nextSubChunk = chunk.GetNextSubChunk()) != null) { switch (nextSubChunk.ChunkID) { case "ifil": flag = true; SoundFontVersion = nextSubChunk.GetDataAsStructure(new SFVersionBuilder()); break; case "isng": WaveTableSoundEngine = nextSubChunk.GetDataAsString(); break; case "INAM": flag2 = true; BankName = nextSubChunk.GetDataAsString(); break; case "irom": DataROM = nextSubChunk.GetDataAsString(); break; case "iver": ROMVersion = nextSubChunk.GetDataAsStructure(new SFVersionBuilder()); break; case "ICRD": CreationDate = nextSubChunk.GetDataAsString(); break; case "IENG": Author = nextSubChunk.GetDataAsString(); break; case "IPRD": TargetProduct = nextSubChunk.GetDataAsString(); break; case "ICOP": Copyright = nextSubChunk.GetDataAsString(); break; case "ICMT": Comments = nextSubChunk.GetDataAsString(); break; case "ISFT": Tools = nextSubChunk.GetDataAsString(); break; default: throw new InvalidDataException($"Unknown chunk type {nextSubChunk.ChunkID}"); } } if (!flag) { throw new InvalidDataException("Missing SoundFont version information"); } if (!flag2) { throw new InvalidDataException("Missing SoundFont name information"); } } public override string ToString() { return string.Format("Bank Name: {0}\r\nAuthor: {1}\r\nCopyright: {2}\r\nCreation Date: {3}\r\nTools: {4}\r\nComments: {5}\r\nSound Engine: {6}\r\nSoundFont Version: {7}\r\nTarget Product: {8}\r\nData ROM: {9}\r\nROM Version: {10}", BankName, Author, Copyright, CreationDate, Tools, "TODO-fix comments", WaveTableSoundEngine, SoundFontVersion, TargetProduct, DataROM, ROMVersion); } } public class Instrument { private string name; internal ushort startInstrumentZoneIndex; internal ushort endInstrumentZoneIndex; private Zone[] zones; public string Name { get { return name; } set { name = value; } } public Zone[] Zones { get { return zones; } set { zones = value; } } 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 { private ModulatorType sourceModulationData; private GeneratorEnum destinationGenerator; private short amount; private ModulatorType sourceModulationAmount; private TransformEnum sourceTransform; public ModulatorType SourceModulationData { get { return sourceModulationData; } set { sourceModulationData = value; } } public GeneratorEnum DestinationGenerator { get { return destinationGenerator; } set { destinationGenerator = value; } } public short Amount { get { return amount; } set { amount = value; } } public ModulatorType SourceModulationAmount { get { return sourceModulationAmount; } set { sourceModulationAmount = value; } } public TransformEnum SourceTransform { get { return sourceTransform; } set { sourceTransform = value; } } public override string ToString() { return $"Modulator {sourceModulationData} {destinationGenerator} {amount} {sourceModulationAmount} {sourceTransform}"; } } internal class ModulatorBuilder : StructureBuilder<Modulator> { public override int Length => 10; public Modulator[] Modulators => data.ToArray(); public override Modulator Read(BinaryReader br) { Modulator modulator = new Modulator(); modulator.SourceModulationData = new ModulatorType(br.ReadUInt16()); modulator.DestinationGenerator = (GeneratorEnum)br.ReadUInt16(); modulator.Amount = br.ReadInt16(); modulator.SourceModulationAmount = new ModulatorType(br.ReadUInt16()); modulator.SourceTransform = (TransformEnum)br.ReadUInt16(); data.Add(modulator); return modulator; } public override void Write(BinaryWriter bw, Modulator o) { } } public enum ControllerSourceEnum { NoController = 0, NoteOnVelocity = 2, NoteOnKeyNumber = 3, PolyPressure = 10, ChannelPressure = 13, PitchWheel = 14, PitchWheelSensitivity = 16 } public enum SourceTypeEnum { Linear, Concave, Convex, Switch } public class ModulatorType { private bool polarity; private bool direction; private bool midiContinuousController; private ControllerSourceEnum controllerSource; private SourceTypeEnum sourceType; private ushort midiContinuousControllerNumber; internal ModulatorType(ushort raw) { polarity = (raw & 0x200) == 512; direction = (raw & 0x100) == 256; midiContinuousController = (raw & 0x80) == 128; sourceType = (SourceTypeEnum)((raw & 0xFC00) >> 10); controllerSource = (ControllerSourceEnum)(raw & 0x7F); midiContinuousControllerNumber = (ushort)(raw & 0x7Fu); } public override string ToString() { if (midiContinuousController) { return $"{sourceType} CC{midiContinuousControllerNumber}"; } return $"{sourceType} {controllerSource}"; } } public class Preset { private string name; private ushort patchNumber; private ushort bank; internal ushort startPresetZoneIndex; internal ushort endPresetZoneIndex; internal uint library; internal uint genre; internal uint morphology; private Zone[] zones; public string Name { get { return name; } set { name = value; } } public ushort PatchNumber { get { return patchNumber; } set { patchNumber = value; } } public ushort Bank { get { return bank; } set { bank = value; } } public Zone[] Zones { get { return zones; } set { zones = value; } } 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 uint chunkSize; private long dataOffset; private BinaryReader riffFile; public string ChunkID { get { return chunkID; } set { if (value == null) { throw new ArgumentNullException("ChunkID may not be null"); } if (value.Length != 4) { throw new ArgumentException("ChunkID must be four characters"); } chunkID = value; } } public uint ChunkSize => chunkSize; public long DataOffset => dataOffset; 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 { private byte[] sampleData; public byte[] SampleData => sampleData; public SampleDataChunk(RiffChunk chunk) { string text = chunk.ReadChunkID(); if (text != "sdta") { throw new InvalidDataException($"Not a sample data chunk ({text})"); } sampleData = chunk.GetData(); } } public class SampleHeader { public string SampleName; public uint Start; public uint End; public uint StartLoop; public uint EndLoop; public uint SampleRate; public byte OriginalPitch; public sbyte PitchCorrection; public ushort SampleLink; public SFSampleLink SFSampleLink; public override string ToString() { return SampleName; } } internal class SampleHeaderBuilder : StructureBuilder<SampleHeader> { public override int Length => 46; public SampleHeader[] SampleHeaders => data.ToArray(); public override SampleHeader Read(BinaryReader br) { SampleHeader sampleHeader = new SampleHeader(); byte[] array = br.ReadBytes(20); sampleHeader.SampleName = ByteEncoding.Instance.GetString(array, 0, array.Length); sampleHeader.Start = br.ReadUInt32(); sampleHeader.End = br.ReadUInt32(); sampleHeader.StartLoop = br.ReadUInt32(); sampleHeader.EndLoop = br.ReadUInt32(); sampleHeader.SampleRate = br.ReadUInt32(); sampleHeader.OriginalPitch = br.ReadByte(); sampleHeader.PitchCorrection = br.ReadSByte(); sampleHeader.SampleLink = br.ReadUInt16(); sampleHeader.SFSampleLink = (SFSampleLink)br.ReadUInt16(); data.Add(sampleHeader); return sampleHeader; } public override void Write(BinaryWriter bw, SampleHeader sampleHeader) { } internal void RemoveEOS() { data.RemoveAt(data.Count - 1); } } public enum SampleMode { NoLoop, LoopContinuously, ReservedNoLoop, LoopAndContinue } public enum SFSampleLink : ushort { MonoSample = 1, RightSample = 2, LeftSample = 4, LinkedSample = 8, RomMonoSample = 32769, RomRightSample = 32770, RomLeftSample = 32772, RomLinkedSample = 32776 } public class SFVersion { private short major; private short minor; public short Major { get { return major; } set { major = value; } } public short Minor { get { return minor; } set { minor = value; } } } internal class SFVersionBuilder : StructureBuilder<SFVersion> { public override int Length => 4; public override SFVersion Read(BinaryReader br) { SFVersion sFVersion = new SFVersion(); sFVersion.Major = br.ReadInt16(); sFVersion.Minor = br.ReadInt16(); data.Add(sFVersion); return sFVersion; } public override void Write(BinaryWriter bw, SFVersion v) { bw.Write(v.Major); bw.Write(v.Minor); } } public class SoundFont { private InfoChunk info; private PresetsChunk presetsChunk; private SampleDataChunk sampleData; public InfoChunk FileInfo => info; public Preset[] Presets => presetsChunk.Presets; public Instrument[] Instruments => presetsChunk.Instruments; public SampleHeader[] SampleHeaders => presetsChunk.SampleHeaders; public byte[] SampleData => sampleData.SampleData; public SoundFont(string fileName) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read)) { } public SoundFont(Stream sfFile) { using (sfFile) { RiffChunk topLevelChunk = RiffChunk.GetTopLevelChunk(new BinaryReader(sfFile)); if (topLevelChunk.ChunkID == "RIFF") { string text = topLevelChunk.ReadChunkID(); if (text != "sfbk") { throw new InvalidDataException($"Not a SoundFont ({text})"); } RiffChunk nextSubChunk = topLevelChunk.GetNextSubChunk(); if (nextSubChunk.ChunkID == "LIST") { info = new InfoChunk(nextSubChunk); RiffChunk nextSubChunk2 = topLevelChunk.GetNextSubChunk(); sampleData = new SampleDataChunk(nextSubChunk2); nextSubChunk2 = topLevelChunk.GetNextSubChunk(); presetsChunk = new PresetsChunk(nextSubChunk2); return; } throw new InvalidDataException($"Not info list found ({nextSubChunk.ChunkID})"); } throw new InvalidDataException("Not a RIFF file"); } } public override string ToString() { return $"Info Chunk:\r\n{info}\r\nPresets Chunk:\r\n{presetsChunk}"; } } internal abstract class StructureBuilder<T> { protected List<T> data; public abstract int Length { get; } public T[] Data => data.ToArray(); public StructureBuilder() { Reset(); } public abstract T Read(BinaryReader br); public abstract void Write(BinaryWriter bw, T o); public void Reset() { data = new List<T>(); } } public class Zone { internal ushort generatorIndex; internal ushort modulatorIndex; internal ushort generatorCount; internal ushort modulatorCount; private Modulator[] modulators; private Generator[] generators; public Modulator[] Modulators { get { return modulators; } set { modulators = value; } } public Generator[] Generators { get { return generators; } set { generators = value; } } 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.Dmo { internal 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 WMMEDIASUBTYPE_MP3 = new Guid("00000055-0000-0010-8000-00AA00389B71"); 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(); } } 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 } 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); } 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; } } } [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); } [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 exception) { if (exception.GetHResult() != -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 exception) { if (exception.GetHResult() != -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? mediaType = (inputType = GetInputType(inputStreamIndex, typeIndex)); inputType = inputType; if (inputType.HasValue) { yield return mediaType.Value; typeIndex++; continue; } break; } } public IEnumerable<DmoMediaType> GetOutputTypes(int outputStreamIndex) { int typeIndex = 0; while (true) { DmoMediaType? outputType; DmoMediaType? mediaType = (outputType = GetOutputType(outputStreamIndex, typeIndex)); outputType = outputType; if (outputType.HasValue) { yield return mediaType.Value; typeIndex++; continue; } break; } } public bool SupportsInputType(int inputStreamIndex, DmoMediaType mediaType) { return SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); } private bool SetInputType(int inputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags) { switch (mediaObject.SetInputType(inputStreamIndex, ref mediaType, flags)) { case -2147220991: throw new ArgumentException("Invalid stream index"); default: _ = -2147220987; return false; case 0: return true; } } public void SetInputType(int inputStreamIndex, DmoMediaType mediaType) { if (!SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None)) { throw new ArgumentException("Media Type not supported"); } } public void SetInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool num = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None); DmoInterop.MoFreeMediaType(ref mediaType); if (!num) { throw new ArgumentException("Media Type not supported"); } } public bool SupportsInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool result = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); DmoInterop.MoFreeMediaType(ref mediaType); return result; } private DmoMediaType CreateDmoMediaTypeForWaveFormat(WaveFormat waveFormat) { DmoMediaType mediaType = default(DmoMediaType); int formatBlockBytes = Marshal.SizeOf((object)waveFormat); DmoInterop.MoInitMediaType(ref mediaType, formatBlockBytes); mediaType.SetWaveFormat(waveFormat); return mediaType; } public bool SupportsOutputType(int outputStreamIndex, DmoMediaType mediaType) { return SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); } public bool SupportsOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool result = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY); DmoInterop.MoFreeMediaType(ref mediaType); return result; } private bool SetOutputType(int outputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags) { int num = mediaObject.SetOutputType(outputStreamIndex, ref mediaType, flags); return num switch { -2147220987 => false, 0 => true, _ => throw Marshal.GetExceptionForHR(num), }; } public void SetOutputType(int outputStreamIndex, DmoMediaType mediaType) { if (!SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None)) { throw new ArgumentException("Media Type not supported"); } } public void SetOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat) { DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat); bool num = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None); DmoInterop.MoFreeMediaType(ref mediaType); if (!num) { throw new ArgumentException("Media Type not supported"); } } public MediaObjectSizeInfo GetInputSizeInfo(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetInputSizeInfo(inputStreamIndex, out var size, out var maxLookahead, out var alignment)); return new MediaObjectSizeInfo(size, maxLookahead, alignment); } public MediaObjectSizeInfo GetOutputSizeInfo(int outputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetOutputSizeInfo(outputStreamIndex, out var size, out var alignment)); return new MediaObjectSizeInfo(size, 0, alignment); } public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long timestamp, long duration) { Marshal.ThrowExceptionForHR(mediaObject.ProcessInput(inputStreamIndex, mediaBuffer, flags, timestamp, duration)); } public void ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, DmoOutputDataBuffer[] outputBuffers) { Marshal.ThrowExceptionForHR(mediaObject.ProcessOutput(flags, outputBufferCount, outputBuffers, out var _)); } public void AllocateStreamingResources() { Marshal.ThrowExceptionForHR(mediaObject.AllocateStreamingResources()); } public void FreeStreamingResources() { Marshal.ThrowExceptionForHR(mediaObject.FreeStreamingResources()); } public long GetInputMaxLatency(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetInputMaxLatency(inputStreamIndex, out var referenceTimeMaxLatency)); return referenceTimeMaxLatency; } public void Flush() { Marshal.ThrowExceptionForHR(mediaObject.Flush()); } public void Discontinuity(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.Discontinuity(inputStreamIndex)); } public bool IsAcceptingData(int inputStreamIndex) { Marshal.ThrowExceptionForHR(mediaObject.GetInputStatus(inputStreamIndex, out var flags)); return (flags & DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA) == DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA; } public void Dispose() { if (mediaObject != null) { Marshal.ReleaseComObject(mediaObject); mediaObject = null; } } } public class MediaObjectSizeInfo { public int Size { get; private set; } public int MaxLookahead { get; } public int Alignment { get; } public MediaObjectSizeInfo(int size, int maxLookahead, int alignment) { Size = size; MaxLookahead = maxLookahead; Alignment = alignment; } public override string ToString() { return $"Size: {Size}, Alignment {Alignment}, MaxLookahead {MaxLookahead}"; } } internal struct MediaParamInfo { public MediaParamType mpType; public MediaParamCurveType mopCaps; public float mpdMinValue; public float mpdMaxValue; public float mpdNeutralValue; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szUnitText; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szLabel; } internal enum MediaParamType { Int, Float, Bool, Enum, Max } [Flags] internal enum MediaParamCurveType { MP_CURVE_JUMP = 1, MP_CURVE_LINEAR = 2, MP_CURVE_SQUARE = 4, MP_CURVE_INVSQUARE = 8, MP_CURVE_SINE = 0x10 } internal static class MediaTypes { public static readonly Guid MEDIATYPE_AnalogAudio = new Guid("0482DEE1-7817-11cf-8a03-00aa006ecb65"); public static readonly Guid MEDIATYPE_AnalogVideo = new Guid("0482DDE1-7817-11cf-8A03-00AA006ECB65"); public static readonly Guid MEDIATYPE_Audio = new Guid("73647561-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_AUXLine21Data = new Guid("670AEA80-3A82-11d0-B79B-00AA003767A7"); public static readonly Guid MEDIATYPE_File = new Guid("656c6966-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Interleaved = new Guid("73766169-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Midi = new Guid("7364696D-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_ScriptCommand = new Guid("73636d64-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Stream = new Guid("e436eb83-524f-11ce-9f53-0020af0ba770"); public static readonly Guid MEDIATYPE_Text = new Guid("73747874-0000-0010-8000-00AA00389B71"); public static readonly Guid MEDIATYPE_Timecode = new Guid("0482DEE3-7817-11cf-8a03-00aa006ecb65"); public static readonly Guid MEDIATYPE_Video = new Guid("73646976-0000-0010-8000-00AA00389B71"); public static readonly Guid[] MajorTypes = new Guid[12] { MEDIATYPE_AnalogAudio, MEDIATYPE_AnalogVideo, MEDIATYPE_Audio, MEDIATYPE_AUXLine21Data, MEDIATYPE_File, MEDIATYPE_Interleaved, MEDIATYPE_Midi, MEDIATYPE_ScriptCommand, MEDIATYPE_Stream, MEDIATYPE_Text, MEDIATYPE_Timecode, MEDIATYPE_Video }; public static readonly string[] MajorTypeNames = new string[12] { "Analog Audio", "Analog Video", "Audio", "AUXLine21Data", "File", "Interleaved", "Midi", "ScriptCommand", "Stream", "Text", "Timecode", "Video" }; public static string GetMediaTypeName(Guid majorType) { for (int i = 0; i < MajorTypes.Length; i++) { if (majorType == MajorTypes[i]) { return MajorTypeNames[i]; } } throw new ArgumentException("Major Type not found"); } } [ComImport] [Guid("bbeea841-0a63-4f52-a7ab-a9b3a84ed38a")] internal class WindowsMediaMp3DecoderComObject { } public class WindowsMediaMp3Decoder : IDisposable { private MediaObject mediaObject; private IPropertyStore propertyStoreInterface; private WindowsMediaMp3DecoderComObject mediaComObject; public MediaObject MediaObject => mediaObject; public WindowsMediaMp3Decoder() { mediaComObject = new WindowsMediaMp3DecoderComObject(); mediaObject = new MediaObject((IMediaObject)mediaComObject); propertyStoreInterface = (IPropertyStore)mediaComObject; } public void Dispose() { if (propertyStoreInterface != null) { Marshal.ReleaseComObject(propertyStoreInterface); propertyStoreInterface = null; } if (mediaObject != null) { mediaObject.Dispose(); mediaObject = null; } if (mediaComObject != null) { Marshal.ReleaseComObject(mediaComObject); mediaComObject = null; } } } [Flags] public enum DmoInputDataBufferFlags { None = 0, SyncPoint = 1, Time = 2, TimeLength = 4 } [Flags] internal enum DmoInputStatusFlags { None = 0, DMO_INPUT_STATUSF_ACCEPT_DATA = 1 } 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) { majortype = MediaTypes.MEDIATYPE_Audio; if (waveFormat is WaveFormatExtensible waveFormatExtensible) { subtype = waveFormatExtensible.SubFormat; } else { switch (waveFormat.Encoding) { case WaveFormatEncoding.Pcm: subtype = AudioMediaSubtypes.MEDIASUBTYPE_PCM; break; case WaveFormatEncoding.IeeeFloat: subtype = AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; break; case WaveFormatEncoding.MpegLayer3: subtype = AudioMediaSubtypes.WMMEDIASUBTYPE_MP3; break; default: throw new ArgumentException($"Not a supported encoding {waveFormat.Encoding}"); } } bFixedSizeSamples = SubType == AudioMediaSubtypes.MEDIASUBTYPE_PCM || SubType == AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT; formattype = DmoMediaTypeGuids.FORMAT_WaveFormatEx; if (cbFormat < Marshal.SizeOf((object)waveFormat)) { throw new InvalidOperationException("Not enough memory assigned for a WaveFormat structure"); } Marshal.StructureToPtr((object)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;
OriginalSoundTrack.dll
Decompiled 10 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Xml; using BepInEx; using BepInEx.Configuration; using EntityStates.Missions.BrotherEncounter; using NAudio.Wave; using NAudio.Wave.SampleProviders; using On.EntityStates.Missions.BrotherEncounter; using On.RoR2; using On.RoR2.UI; using R2API.Utils; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.ConVar; using RoR2.UI; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("OriginalSoundTrack")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OriginalSoundTrack")] [assembly: AssemblyTitle("OriginalSoundTrack")] [assembly: AssemblyVersion("1.0.0.0")] namespace OriginalSoundTrack; internal class NetworkCompatibilityAttribute : Attribute { private CompatibilityLevel noNeedForSync; private VersionStrictness differentModVersionsAreOk; public NetworkCompatibilityAttribute(CompatibilityLevel noNeedForSync, VersionStrictness differentModVersionsAreOk) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) this.noNeedForSync = noNeedForSync; this.differentModVersionsAreOk = differentModVersionsAreOk; } } [BepInPlugin("com.mrcountermax.moreostsmod", "MoreOSTsMod", "2.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class OriginalSoundTrack : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<string, string> <>9__16_8; public static hook_OnEnter <>9__16_6; public static Func<FileInfo, bool> <>9__18_0; internal string <Awake>b__16_8(string str) { return str.Trim(); } internal void <Awake>b__16_6(orig_OnEnter orig, EncounterFinished self) { orig.Invoke(self); Debug.Log((object)"====================== FINAL BOSS FIGHT DONE ======================"); } internal bool <SearchForAudioFiles>b__18_0(FileInfo f) { return Path.GetExtension(f.Name) == ".mp3" || Path.GetExtension(f.Name) == ".wav"; } } private FadeInOutSampleProvider fader; private WaveOutEvent outputDevice; private FileInfo[] soundFiles; private List<Music> musics = new List<Music>(); private AudioFileReader currentSong; private string currentSongFullName = ""; private bool startedTeleporterEvent = false; private bool songPaused = false; private float currentMusicVolume; private ConfigEntry<float> globalMusicVolume; private bool shouldLoop = true; private string oldMusicVolume = ""; private string currentScene = ""; private Random rnd = new Random(); private XmlElement settings; private Texture2D modIconTexture; public void Awake() { //IL_0024: 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_0051: Expected O, but got Unknown //IL_0051: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Expected O, but got Unknown //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Expected O, but got Unknown //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Expected O, but got Unknown //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Expected O, but got Unknown //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Expected O, but got Unknown //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Expected O, but got Unknown //IL_048b: 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_0496: Expected O, but got Unknown string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = directoryName; globalMusicVolume = ((BaseUnityPlugin)this).Config.Bind<float>(new ConfigDefinition("General", "Volume"), 40f, new ConfigDescription("The volume of the More OSTs Mod music. KEEP THE GAME'S MUSIC VOLUME AT 0!!!", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(globalMusicVolume, new StepSliderConfig { min = 0f, max = 100f, increment = 1f, formatString = "{0:0}%" })); globalMusicVolume.SettingChanged += delegate { UpdateVolume(); }; modIconTexture = new Texture2D(0, 0); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("OriginalSoundTrack.ror2_more_osts_mod_clean.png")) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); byte[] array = memoryStream.ToArray(); ImageConversion.LoadImage(modIconTexture, array); } Sprite modIcon = Sprite.Create(modIconTexture, new Rect(0f, 0f, (float)((Texture)modIconTexture).width, (float)((Texture)modIconTexture).height), new Vector2(0f, 0f)); ModSettingsManager.SetModIcon(modIcon); try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(directoryName + "/settings.xml"); settings = xmlDocument["settings"]; shouldLoop = settings["loop"].InnerText.ToLower() == "true"; if (settings["music-path"] != null) { text = settings["music-path"].InnerText; } soundFiles = SearchForAudioFiles(text); foreach (XmlNode childNode in settings["music"].ChildNodes) { if (childNode.NodeType == XmlNodeType.Comment) { continue; } Music music = new Music(); music.name = GetAttribute(childNode, "name"); music.scenes = (from str in GetAttribute(childNode, "scenes").Split(new char[1] { ',' }) select str.Trim()).ToArray(); music.boss = GetAttribute(childNode, "boss").ToLower() == "true"; music.volume = 1f; string attribute = GetAttribute(childNode, "volume"); if (attribute != "") { music.volume = float.Parse(attribute, CultureInfo.InvariantCulture); } FileInfo[] array2 = soundFiles; foreach (FileInfo fileInfo in array2) { if (fileInfo.Name == music.name) { music.fullName = fileInfo.FullName; break; } } musics.Add(music); } } catch (Exception ex) { Debug.LogWarning((object)"!!!!! OriginalSoundTrack Mod: Failed to parse settings.xml !!!!!"); Debug.Log((object)"OriginalSoundTrack Mod: Music will be randomly selected from what is found in the plugin dir."); Debug.Log((object)ex); } if (soundFiles == null) { text = directoryName; soundFiles = SearchForAudioFiles(text); } if (soundFiles.Length == 0) { Debug.LogError((object)"!!!!! OriginalSoundTrack Mod: No audio files found. Exiting. !!!!!"); Debug.LogError((object)("OriginalSoundTrack Mod: Looked for .mp3 and .wav files in: " + text)); return; } if (outputDevice == null) { outputDevice = new WaveOutEvent(); } TeleporterInteraction.OnInteractionBegin += (hook_OnInteractionBegin)delegate(orig_OnInteractionBegin orig, TeleporterInteraction self, Interactor activator) { orig.Invoke(self, activator); if (!startedTeleporterEvent) { startedTeleporterEvent = true; PickOutMusic(isForTeleporter: true); } }; TeleporterInteraction.RpcClientOnActivated += (hook_RpcClientOnActivated)delegate(orig_RpcClientOnActivated orig, TeleporterInteraction self, GameObject activator) { orig.Invoke(self, activator); if (!startedTeleporterEvent) { startedTeleporterEvent = true; PickOutMusic(isForTeleporter: true); } }; PauseScreenController.OnEnable += (hook_OnEnable)delegate(orig_OnEnable orig, PauseScreenController self) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 orig.Invoke(self); if (outputDevice != null && (int)outputDevice.PlaybackState == 1) { outputDevice.Pause(); songPaused = true; } }; PauseScreenController.OnDisable += (hook_OnDisable)delegate(orig_OnDisable orig, PauseScreenController self) { orig.Invoke(self); if (outputDevice != null && songPaused) { outputDevice.Play(); songPaused = false; } }; Phase1.OnEnter += (hook_OnEnter)delegate(orig_OnEnter orig, Phase1 self) { orig.Invoke(self); Debug.Log((object)"====================== FINAL BOSS FIGHT START ======================"); PickOutMusic(isForTeleporter: true); }; object obj = <>c.<>9__16_6; if (obj == null) { hook_OnEnter val = delegate(orig_OnEnter orig, EncounterFinished self) { orig.Invoke(self); Debug.Log((object)"====================== FINAL BOSS FIGHT DONE ======================"); }; <>c.<>9__16_6 = val; obj = (object)val; } EncounterFinished.OnEnter += (hook_OnEnter)obj; SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode) { Debug.Log((object)"====================== CHANGE SCENE ========================"); Debug.Log((object)((Scene)(ref scene)).name); if (currentScene != ((Scene)(ref scene)).name) { currentScene = ((Scene)(ref scene)).name; startedTeleporterEvent = false; PickOutMusic(); } }; } private void UpdateVolume() { currentSong.Volume = currentMusicVolume * globalMusicVolume.Value / 100f; } private FileInfo[] SearchForAudioFiles(string path) { DirectoryInfo directoryInfo = new DirectoryInfo(path); if (directoryInfo.Exists) { return (from f in directoryInfo.GetFiles() where Path.GetExtension(f.Name) == ".mp3" || Path.GetExtension(f.Name) == ".wav" select f).ToArray(); } return new FileInfo[0]; } private string GetAttribute(XmlNode node, string attribute) { if (node.Attributes != null) { XmlNode namedItem = node.Attributes.GetNamedItem(attribute); if (namedItem != null) { return namedItem.Value; } } return ""; } private bool sceneMostlyMatches(string[] scenes) { foreach (string value in scenes) { if (currentScene.Contains(value)) { return true; } } return false; } private void PickOutMusic(bool isForTeleporter = false) { Music[] array = musics.Where(delegate(Music music) { bool flag = isForTeleporter == music.boss; return music.fullName != null && flag && sceneMostlyMatches(music.scenes); }).ToArray(); Debug.Log((object)"====== Selecting Music ======"); Debug.Log((object)("Current Scene: " + currentScene)); Debug.Log((object)("Is For Teleporter: " + isForTeleporter)); Debug.Log((object)"Choices: "); Music[] array2 = array; foreach (Music music2 in array2) { Debug.Log((object)music2.name); } Debug.Log((object)""); string fullName = currentSongFullName; Music music3 = null; int num = 0; if (array.Length != 0) { while (fullName == currentSongFullName && num < 10) { music3 = array[rnd.Next(array.Length)]; fullName = music3.fullName; num++; } ((MonoBehaviour)this).StartCoroutine((IEnumerator)PlayMusic(fullName, music3.volume)); return; } Debug.Log((object)"======= MUSIC PICK FAILED! ======="); Debug.Log((object)"choosing random song..."); num = 0; while (fullName == currentSongFullName && num < 10) { fullName = soundFiles[rnd.Next(soundFiles.Length)].FullName; num++; } ((MonoBehaviour)this).StartCoroutine((IEnumerator)PlayMusic(fullName)); } private IEnumerator<WaitForSeconds> PlayMusic(string file, float volume = 1f) { currentMusicVolume = volume; if (file != currentSongFullName) { currentSongFullName = file; if ((int)outputDevice.PlaybackState == 1) { fader.BeginFadeOut(1500.0); yield return new WaitForSeconds(1.5f); outputDevice.Stop(); currentSong = null; } currentSong = new AudioFileReader(file); UpdateVolume(); LoopStream looper = new LoopStream((WaveStream)(object)currentSong, shouldLoop); fader = new FadeInOutSampleProvider((ISampleProvider)new WaveToSampleProvider((IWaveProvider)(object)looper), false); WaveExtensionMethods.Init((IWavePlayer)(object)outputDevice, (ISampleProvider)(object)fader, false); Debug.Log((object)("====== Now Playing: " + file)); outputDevice.Play(); songPaused = false; } else { Debug.Log((object)("PlayMusic: Already playing: " + file)); } } public void Update() { if (oldMusicVolume == "" && (Object)(object)Console.instance != (Object)null) { BaseConVar val = Console.instance.FindConVar("volume_music"); if (val != null) { oldMusicVolume = val.GetString(); val.SetString("0"); } } } private void FixedUpdate() { if (currentSong != null && ((Stream)(object)currentSong).Position >= ((Stream)(object)currentSong).Length && !shouldLoop) { outputDevice.Stop(); ((Stream)(object)currentSong).Position = ((Stream)(object)currentSong).Length - 1; PickOutMusic(startedTeleporterEvent); } } private void OnDestroy() { BaseConVar val = Console.instance.FindConVar("volume_music"); if (val != null) { val.SetString(oldMusicVolume); } } } public class Music { public string name; public string fullName; public string[] scenes; public bool boss = false; public float volume = 1f; } public class LoopStream : WaveStream { private WaveStream sourceStream; private bool EnableLooping = true; public override WaveFormat WaveFormat => sourceStream.WaveFormat; public override long Position { get { return ((Stream)(object)sourceStream).Position; } set { ((Stream)(object)sourceStream).Position = value; } } public override long Length => ((Stream)(object)sourceStream).Length; public LoopStream(WaveStream sourceStream, bool shouldLoop) { this.sourceStream = sourceStream; EnableLooping = shouldLoop; } public override int Read(byte[] buffer, int offset, int count) { int i; int num2; for (i = 0; i < count; i += num2) { int num = count - i; num2 = ((Stream)(object)sourceStream).Read(buffer, offset + i, num); if (num2 < num || ((Stream)(object)sourceStream).Position >= ((Stream)(object)sourceStream).Length) { if (!EnableLooping) { break; } ((Stream)(object)sourceStream).Position = 0L; } } return i; } }