Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ZPMods The Playlist Mod v1.0.3
plugins/NAudio.dll
Decompiled 2 years 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;
plugins/ZPPlaylistMod.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Xml; using BepInEx; using BepInEx.Logging; using EntityStates; using EntityStates.Missions.BrotherEncounter; using NAudio.Dsp; using NAudio.Wave; using On.EntityStates.Missions.BrotherEncounter; using On.RoR2; using On.RoR2.UI; using On.RoR2.UI.MainMenu; using R2API.Utils; using RoR2; using RoR2.ConVar; using RoR2.UI; using RoR2.UI.MainMenu; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [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("ZPPlaylistMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ZPPlaylistMod")] [assembly: AssemblyTitle("ZPPlaylistMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace ZPPlaylistMod; internal static class Assets { internal static AssetBundle mainAssetBundle; private const string csProjName = "ZPPlaylistMod"; private const string assetbundleName = "playlistmodassetbundle"; private static string[] assetNames = new string[0]; internal static GameObject playlistMenuPrefab; internal static GameObject playlistSelectorPrefab; internal static GameObject playlistPauseDisplayPrefab; internal static Sprite defaultAlbumCover; internal static void Initialize() { LoadAssetBundle(); BuildPlaylistMenu(); BuildPlaylistSelector(); BuildPauseInfo(); BuildDefaultAlbumCover(); } internal static void LoadAssetBundle() { try { if ((Object)(object)mainAssetBundle == (Object)null) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ZPPlaylistMod.playlistmodassetbundle"); mainAssetBundle = AssetBundle.LoadFromStream(stream); } } catch (Exception ex) { Debug.LogError((object)("[ZP Playlist Mod] Failed to load assetbundle. Make sure your assetbundle name is setup correctly.\n" + ex)); return; } assetNames = mainAssetBundle.GetAllAssetNames(); } internal static bool CheckIfAssetExists(string resourceName) { if (assetNames == null) { Debug.LogError((object)("[ZP Playlist Mod] Failed to find asset: " + resourceName + ". Array 'assetNames' is empty.")); return false; } for (int i = 0; i < assetNames.Length; i++) { if (assetNames[i].Contains(resourceName.ToLowerInvariant())) { return true; } } Debug.LogError((object)("[ZP Playlist Mod] Failed to find asset: " + resourceName + " in the AssetBundle.")); return false; } internal static void BuildPlaylistMenu() { if (CheckIfAssetExists("ZP_Playlist_SelectionMenu")) { Object obj = mainAssetBundle.LoadAsset("ZP_Playlist_SelectionMenu"); playlistMenuPrefab = (GameObject)(object)((obj is GameObject) ? obj : null); ZPPlaylistMenu zPPlaylistMenu = playlistMenuPrefab.AddComponent<ZPPlaylistMenu>(); } } internal static void BuildPlaylistSelector() { if (CheckIfAssetExists("ZP_PlaylistButton")) { Object obj = mainAssetBundle.LoadAsset("ZP_PlaylistButton"); playlistSelectorPrefab = (GameObject)(object)((obj is GameObject) ? obj : null); ZPPlaylistSelector zPPlaylistSelector = playlistSelectorPrefab.AddComponent<ZPPlaylistSelector>(); } } internal static void BuildPauseInfo() { if (!CheckIfAssetExists("ZP_NowPlaying_Canvas")) { return; } Object obj = mainAssetBundle.LoadAsset("ZP_NowPlaying_Canvas"); playlistPauseDisplayPrefab = (GameObject)(object)((obj is GameObject) ? obj : null); Transform[] componentsInChildren = playlistPauseDisplayPrefab.GetComponentsInChildren<Transform>(); foreach (Transform val in componentsInChildren) { if (((Object)((Component)val).gameObject).name == "ZP_Playlist_PauseInfo") { ZPPlaylistPauseDisplay zPPlaylistPauseDisplay = ((Component)val).gameObject.AddComponent<ZPPlaylistPauseDisplay>(); } } } internal static void BuildDefaultAlbumCover() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (CheckIfAssetExists("ror2cover")) { Object obj = mainAssetBundle.LoadAsset("ror2cover"); Texture2D val = (Texture2D)(object)((obj is Texture2D) ? obj : null); defaultAlbumCover = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } } } 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; } } internal class MusicAlbum { [Flags] internal enum LoopPreventionMode { None = 0, Levels = 1, Bosses = 2, NextTrack = 4 } public string name; public string displayName; public string description; public Sprite icon; public float volumeMultiplier; public List<MusicTrack> musicTracks; internal LoopPreventionMode loopPreventionMode; public bool SceneHasSong(Scene scene, bool isBoss = false) { if (musicTracks == null || musicTracks.Count <= 0) { return false; } List<MusicTrack> list = new List<MusicTrack>(); foreach (MusicTrack musicTrack in musicTracks) { string[] scenes = musicTrack.scenes; foreach (string value in scenes) { if (((Scene)(ref scene)).name.Contains(value) && musicTrack.boss == isBoss) { list.Add(musicTrack); } } } if (list.Count > 0) { return true; } return false; } public MusicTrack[] GetSceneSongs(Scene scene, bool isBoss = false) { if (musicTracks == null || musicTracks.Count <= 0) { return null; } List<MusicTrack> list = new List<MusicTrack>(); foreach (MusicTrack musicTrack in musicTracks) { string[] scenes = musicTrack.scenes; foreach (string value in scenes) { if (((Scene)(ref scene)).name.Contains(value) && musicTrack.boss == isBoss) { list.Add(musicTrack); } } } if (list.Count > 0) { return list.ToArray(); } return null; } } internal class MusicTrack { public string name; public string fullName; public string displayName; public string[] scenes; public bool boss; } public class ZPPlaylistMenu : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__3_0; public static UnityAction <>9__3_1; internal void <Init>b__3_0() { Application.OpenURL("https://hpfeather.bandcamp.com"); } internal void <Init>b__3_1() { Application.OpenURL("https://twitter.com/ZPMods"); } } internal ZPPlaylistModMain _main; private Transform playlistButtonsHolder; public void Awake() { Init(); } public void Init() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); Transform[] array = componentsInChildren; foreach (Transform val in array) { if (((Object)((Component)val).gameObject).name == "ZP_FeatherBandcamp_Button") { ButtonClickedEvent onClick = ((Component)val).GetComponent<Button>().onClick; object obj = <>c.<>9__3_0; if (obj == null) { UnityAction val2 = delegate { Application.OpenURL("https://hpfeather.bandcamp.com"); }; <>c.<>9__3_0 = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } if (((Object)((Component)val).gameObject).name == "ZP_ZPTwitter_Button") { ButtonClickedEvent onClick2 = ((Component)val).GetComponent<Button>().onClick; object obj2 = <>c.<>9__3_1; if (obj2 == null) { UnityAction val3 = delegate { Application.OpenURL("https://twitter.com/ZPMods"); }; <>c.<>9__3_1 = val3; obj2 = (object)val3; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); } if (((Object)((Component)val).gameObject).name == "ZP_PlaylistButtons_Holder") { playlistButtonsHolder = val; } } } internal void RemoveAllPlaylistButtons() { if ((Object)(object)playlistButtonsHolder == (Object)null) { Init(); } for (int num = playlistButtonsHolder.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)playlistButtonsHolder.GetChild(num)).gameObject); } AddPlaylistButton(null); } internal void AddPlaylistButton(MusicAlbum album) { if ((Object)(object)playlistButtonsHolder == (Object)null) { Init(); } ToggleGroup component = ((Component)playlistButtonsHolder).GetComponent<ToggleGroup>(); GameObject val = Object.Instantiate<GameObject>(Assets.playlistSelectorPrefab, playlistButtonsHolder); ZPPlaylistSelector component2 = val.GetComponent<ZPPlaylistSelector>(); if (album == null) { if (Assets.CheckIfAssetExists("ror2cover")) { component2._main = _main; component2.OverrideAlbum("", "Chris Christodoulou - Risk of Rain 2", "Risk of Rain 2's default sound track.", Assets.defaultAlbumCover); } } else { component2._main = _main; component2.SetAlbum(album); } Toggle val2 = default(Toggle); if (val.TryGetComponent<Toggle>(ref val2)) { if ((Object)(object)component != (Object)null) { val2.group = component; } if (_main.GetSelectedAlbum() != null && album != null && _main.GetSelectedAlbum().name == album.name) { val2.SetIsOnWithoutNotify(true); } else if (_main.GetSelectedAlbum() == null && album == null) { val2.SetIsOnWithoutNotify(true); } } } } [BepInPlugin("com.ZPMods.ZPPlaylistMod", "ZP Playlist Mod", "1.0.0")] [BepInDependency("com.bepis.r2api", "4.4.1")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [R2APISubmoduleDependency(new string[] { "SoundAPI" })] public class ZPPlaylistModMain : BaseUnityPlugin { public const string ModGuid = "com.ZPMods.ZPPlaylistMod"; public const string ModName = "ZP Playlist Mod"; public const string ModVer = "1.0.0"; private string pluginPath; private LoopStream source; private WaveOutEvent outputDevice; private AudioFileReader currentSongFile; private bool startupMute = true; private bool muted = false; private bool fading = false; private bool isInBossEvent; private bool isInTeleporterRange; private MusicAlbum[] loadedAlbums; private string selectedAlbumName; private MusicAlbum selectedAlbum; private MusicTrack lastBossTrack; private MusicTrack lastLevelTrack; private MusicTrack selectedTrack; private Button openPlaylistMenuButton; private GameObject pauseTrackCanvas; private ZPPlaylistPauseDisplay pauseTrackDisplay; private Image playlistButtonAlbumCover; private float volumeMultiplier = 1f; private Coroutine fadeOutRoutine; public static ManualLogSource ModLogger; private void Awake() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; pluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Assets.Initialize(); if (outputDevice == null) { outputDevice = new WaveOutEvent(); } selectedAlbumName = "ZPFeatherEternal"; loadedAlbums = BuildAlbums(); ReloadPreviousAlbum(); InitHooks(); } private void Update() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Invalid comparison between Unknown and I4 if (fadeOutRoutine == null && currentSongFile != null && outputDevice != null && currentSongFile.Volume != Mathf.Clamp(volumeMultiplier, 0f, 1f) * GetGameMusicVolume()) { currentSongFile.Volume = Mathf.Clamp(volumeMultiplier, 0f, 1f) * GetGameMusicVolume(); } if (outputDevice != null && currentSongFile != null && (int)outputDevice.PlaybackState != 0 && (int)outputDevice.PlaybackState != 1 != PauseManager.isPaused) { if (PauseManager.isPaused) { outputDevice.Pause(); } if (!PauseManager.isPaused) { outputDevice.Play(); } } } private void InitHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown MainMenuController.Awake += new hook_Awake(SetUpPlaylistMenuObjects); PauseScreenController.OnEnable += new hook_OnEnable(OnPauseScreenEnable); PauseScreenController.OnDisable += new hook_OnDisable(OnPauseScreenDisable); PauseScreenController.Update += new hook_Update(OnPauseScreenUpdate); SceneManager.sceneLoaded += SceneLoadHook; MusicTrackDef.Play += new hook_Play(CheckOverrideMusic); MusicTrackDef.Stop += new hook_Stop(CheckStopMusic); MusicController.UpdateTeleporterParameters += new hook_UpdateTeleporterParameters(GetTeleportParameters); TeleporterInteraction.RpcClientOnActivated += new hook_RpcClientOnActivated(SetBossMusicValue); Phase1.OnEnter += new hook_OnEnter(OnMithrixFightStart); EncounterFinished.OnEnter += new hook_OnEnter(OnMithrixFightEnd); ChargedState.OnEnter += new hook_OnEnter(TeleporterStopMusic); } public void SetUpPlaylistMenuObjects(orig_Awake orig, MainMenuController self) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown orig.Invoke(self); Debug.Log((object)"[ZP Playlist Mod] Main Menu awake."); foreach (Transform item in ((Component)Object.FindObjectOfType<Canvas>()).transform) { Transform val = item; Debug.Log((object)((Object)((Component)val).gameObject).name); } MainMenuController val2 = Object.FindObjectOfType<MainMenuController>(); Object obj = Assets.mainAssetBundle.LoadAsset("ZP_OpenPlaylistMenu_Button"); RectTransform component = Object.Instantiate<GameObject>((GameObject)(object)((obj is GameObject) ? obj : null), ((Component)val2.titleMenuScreen).transform).GetComponent<RectTransform>(); component.anchoredPosition = Vector2.zero + Vector2.up * 50f + Vector2.left * 50f; openPlaylistMenuButton = ((Component)component).GetComponentInChildren<Button>(); playlistButtonAlbumCover = ((Component)((Component)((Selectable)openPlaylistMenuButton).targetGraphic).transform.GetChild(0)).GetComponent<Image>(); if ((Object)(object)Assets.playlistMenuPrefab != (Object)null) { RectTransform playlistMenuGo = Object.Instantiate<GameObject>(Assets.playlistMenuPrefab, ((Component)val2.titleMenuScreen).transform).GetComponent<RectTransform>(); ((Component)playlistMenuGo).gameObject.SetActive(false); ZPPlaylistMenu playlistMenuComponent = ((Component)playlistMenuGo).GetComponent<ZPPlaylistMenu>(); playlistMenuComponent._main = this; ((UnityEvent)openPlaylistMenuButton.onClick).AddListener((UnityAction)delegate { ((Component)playlistMenuGo).gameObject.SetActive(true); }); ((UnityEvent)openPlaylistMenuButton.onClick).AddListener((UnityAction)delegate { playlistMenuComponent.RemoveAllPlaylistButtons(); }); if (loadedAlbums != null) { MusicAlbum[] array = loadedAlbums; foreach (MusicAlbum album in array) { ((UnityEvent)openPlaylistMenuButton.onClick).AddListener((UnityAction)delegate { playlistMenuComponent.AddPlaylistButton(album); }); } } } UpdateMainMenuCover(); } public void OnPauseScreenEnable(orig_OnEnable orig, PauseScreenController self) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown orig.Invoke(self); Debug.Log((object)"[ZP Playlist Mod] Pause enabled."); foreach (Transform componentInChild in ((Component)self).GetComponentInChildren<Transform>(true)) { Transform val = componentInChild; } if ((Object)(object)pauseTrackCanvas == (Object)null) { pauseTrackCanvas = Object.Instantiate<GameObject>(Assets.playlistPauseDisplayPrefab); pauseTrackDisplay = pauseTrackCanvas.GetComponentInChildren<ZPPlaylistPauseDisplay>(); Debug.Log((object)"[ZP Playlist Mod] Canvas instantiated."); } if ((Object)(object)pauseTrackCanvas != (Object)null) { Debug.Log((object)"[ZP Playlist Mod] Canvas found."); pauseTrackCanvas.SetActive(true); if (selectedTrack != null) { Debug.Log((object)"[ZP Playlist Mod] Selected track found."); ((Component)pauseTrackDisplay).gameObject.SetActive(true); pauseTrackDisplay.SetDisplay(selectedAlbum.icon, selectedTrack.displayName); } else { ((Component)pauseTrackDisplay).gameObject.SetActive(false); } } } public void OnPauseScreenDisable(orig_OnDisable orig, PauseScreenController self) { orig.Invoke(self); if ((Object)(object)pauseTrackCanvas != (Object)null) { pauseTrackCanvas.SetActive(false); } } public void OnPauseScreenUpdate(orig_Update orig, PauseScreenController self) { orig.Invoke(self); if ((Object)(object)pauseTrackCanvas != (Object)null) { pauseTrackCanvas.SetActive((Object)(object)self.submenuObject == (Object)null); } } public void SceneLoadHook(Scene scene, LoadSceneMode mode) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (((Scene)(ref scene)).name == "splash") { startupMute = false; } isInBossEvent = false; StopMusicInstant(); if (outputDevice == null) { outputDevice = new WaveOutEvent(); } } public void SetBossMusicValue(orig_RpcClientOnActivated orig, TeleporterInteraction self, GameObject activatorObject) { orig.Invoke(self, activatorObject); isInBossEvent = true; } public void TeleporterStopMusic(orig_OnEnter orig, BaseState 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) { StartFadeOut(10f); } } public void OnMithrixFightStart(orig_OnEnter orig, Phase1 self) { orig.Invoke(self); isInBossEvent = true; } public void OnMithrixFightEnd(orig_OnEnter orig, EncounterFinished self) { orig.Invoke(self); isInBossEvent = false; } public void CheckStopMusic(orig_Stop orig, MusicTrackDef self) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (outputDevice != null && (int)outputDevice.PlaybackState == 1) { StartFadeOut(1f, overrideCurrentRoutine: false); } else { orig.Invoke(self); } } public void CheckOverrideMusic(orig_Play orig, MusicTrackDef self) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 if (outputDevice == null || startupMute || selectedAlbum == null || !selectedAlbum.SceneHasSong(SceneManager.GetActiveScene(), isInBossEvent)) { if (outputDevice != null && (int)outputDevice.PlaybackState == 1) { StartFadeOut(1f, overrideCurrentRoutine: false); } orig.Invoke(self); return; } MusicTrack[] sceneSongs = selectedAlbum.GetSceneSongs(SceneManager.GetActiveScene(), isInBossEvent); int num = Random.Range(0, sceneSongs.Length - 1); if (selectedAlbum.loopPreventionMode != 0 && sceneSongs.Length > 1) { if (selectedAlbum.loopPreventionMode.HasFlag(MusicAlbum.LoopPreventionMode.Levels) && lastLevelTrack != null && lastLevelTrack.name == sceneSongs[num].fullName) { num = (num + 1) % sceneSongs.Length; } if (selectedAlbum.loopPreventionMode.HasFlag(MusicAlbum.LoopPreventionMode.Bosses) && lastBossTrack != null && lastBossTrack.name == sceneSongs[num].fullName) { num = (num + 1) % sceneSongs.Length; } if (selectedAlbum.loopPreventionMode.HasFlag(MusicAlbum.LoopPreventionMode.NextTrack) && selectedTrack != null && selectedTrack.name == sceneSongs[num].fullName) { num = (num + 1) % sceneSongs.Length; } } volumeMultiplier = selectedAlbum.volumeMultiplier; ((MonoBehaviour)this).StartCoroutine(PlayMusic(sceneSongs[num])); } public void GetTeleportParameters(orig_UpdateTeleporterParameters orig, MusicController self, TeleporterInteraction teleporter, Transform cameraTransform, CharacterBody targetBody) { orig.Invoke(self, teleporter, cameraTransform, targetBody); if (isInTeleporterRange != self.rtpcTeleporterPlayerStatus.value > 0f) { Debug.Log((object)string.Format("[{0}] Is in teleporter range : {1}", "ZP Playlist Mod", !isInTeleporterRange)); if (self.rtpcTeleporterPlayerStatus.value < 0f) { SetHighPassFilter(); } else { RemoveFilters(); } } isInTeleporterRange = self.rtpcTeleporterPlayerStatus.value > 0f; } internal IEnumerator PlayMusic(MusicTrack track) { if ((int)outputDevice.PlaybackState == 1) { StartFadeOut(1f, overrideCurrentRoutine: false); } yield return (object)new WaitUntil((Func<bool>)(() => fadeOutRoutine == null)); if (!startupMute) { yield return (object)new WaitForEndOfFrame(); selectedTrack = track; if (selectedTrack.boss) { lastBossTrack = selectedTrack; } else { lastLevelTrack = selectedTrack; } currentSongFile = new AudioFileReader(track.fullName); currentSongFile.Volume = Mathf.Clamp(volumeMultiplier, 0f, 1f) * GetGameMusicVolume(); source = new LoopStream((WaveStream)(object)currentSongFile, shouldLoop: true); outputDevice.Init((IWaveProvider)(object)source); outputDevice.Play(); } } public void StartFadeOut(float seconds, bool overrideCurrentRoutine = true) { if (fadeOutRoutine != null) { if (!overrideCurrentRoutine) { return; } ((MonoBehaviour)this).StopCoroutine(fadeOutRoutine); } fadeOutRoutine = ((MonoBehaviour)this).StartCoroutine(FadeOutMusic(seconds)); } private IEnumerator FadeOutMusic(float time) { if ((int)outputDevice.PlaybackState == 1) { fading = true; float fadeRemainingTime = time; while (fadeRemainingTime > 0f) { fadeRemainingTime = Mathf.Max(0f, fadeRemainingTime - 0.05f); currentSongFile.Volume = Mathf.Clamp(volumeMultiplier, 0f, 1f) * GetGameMusicVolume() * (fadeRemainingTime / time); yield return (object)new WaitForSeconds(0.05f); } fading = false; outputDevice.Stop(); currentSongFile = null; selectedTrack = null; } fadeOutRoutine = null; } public void StopMusicInstant() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 if (fadeOutRoutine != null) { ((MonoBehaviour)this).StopCoroutine(fadeOutRoutine); } fadeOutRoutine = null; fading = false; if (outputDevice != null && (int)outputDevice.PlaybackState == 1) { outputDevice.Stop(); } currentSongFile = null; selectedTrack = null; } private MusicAlbum[] BuildAlbums() { //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) List<MusicAlbum> list = new List<MusicAlbum>(); string[] directories = Directory.GetDirectories(pluginPath); foreach (string text in directories) { try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(text + "/album.xml"); XmlElement xmlElement = xmlDocument["info"]; if (xmlDocument["info"] == null) { Debug.LogWarning((object)("[ZP Playlist Mod] 'info' element not found in 'album.xml' file at path : '" + text + "'.")); continue; } if (xmlElement["name"] == null) { Debug.LogWarning((object)("[ZP Playlist Mod] 'name' element not found in 'album.xml' file at path : '" + text + "'.")); continue; } MusicAlbum musicAlbum = new MusicAlbum(); musicAlbum.name = xmlElement["name"].InnerText; musicAlbum.displayName = ((xmlElement["displayName"] != null) ? xmlElement["displayName"].InnerText : "No album name"); musicAlbum.description = ((xmlElement["description"] != null) ? xmlElement["description"].InnerText : "No album description."); Sprite icon = null; if (xmlElement["icon"] != null && File.Exists(text + "/" + xmlElement["icon"].InnerText)) { Texture2D val = new Texture2D(1, 1); ImageConversion.LoadImage(val, File.ReadAllBytes(text + "/" + xmlElement["icon"].InnerText)); icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } else if (xmlElement["icon"] == null) { Debug.LogWarning((object)("[ZP Playlist Mod] 'icon' element not found in 'album.xml' file at path : '" + text + "'.")); } else { Debug.LogWarning((object)("[ZP Playlist Mod] 'icon' element found in 'album.xml' file at path : '" + text + "/" + xmlElement["icon"].InnerText + "' is either invalid or in wrong format.")); } musicAlbum.icon = icon; musicAlbum.loopPreventionMode = MusicAlbum.LoopPreventionMode.None; if (xmlElement["preventRepetitionMode"] != null) { string[] array = (from str in xmlElement["preventRepetitionMode"].InnerText.Split(new char[1] { ',' }) select str.Trim()).ToArray(); if (array.Contains("Levels")) { musicAlbum.loopPreventionMode ^= MusicAlbum.LoopPreventionMode.Levels; } if (array.Contains("Bosses")) { musicAlbum.loopPreventionMode ^= MusicAlbum.LoopPreventionMode.Bosses; } if (array.Contains("NextTrack")) { musicAlbum.loopPreventionMode ^= MusicAlbum.LoopPreventionMode.NextTrack; } } musicAlbum.volumeMultiplier = 1f; string text2 = ((xmlElement["volume"] != null) ? xmlElement["volume"].InnerText : "100"); if (text2 != "") { musicAlbum.volumeMultiplier = float.Parse(text2) / 100f; } FileInfo[] audioFiles = SearchForAudioFiles(text); musicAlbum.musicTracks = new List<MusicTrack>(); foreach (XmlNode childNode in xmlElement["music"].ChildNodes) { if (childNode.NodeType != XmlNodeType.Comment) { musicAlbum.musicTracks.Add(BuildTrack(childNode, audioFiles)); } } Debug.Log((object)("[ZP Playlist Mod] Album found at path : '" + text + "' \nAlbum name : " + musicAlbum.displayName)); list.Add(musicAlbum); } catch (Exception ex) { Debug.LogWarning((object)("[ZP Playlist Mod] 'album.xml' file not found for folder at path : '" + text + "'.")); Debug.Log((object)ex); } } return list.ToArray(); } private MusicTrack BuildTrack(XmlNode node, FileInfo[] audioFiles) { MusicTrack musicTrack = new MusicTrack(); musicTrack.name = GetAttribute(node, "name"); musicTrack.displayName = GetAttribute(node, "displayName"); musicTrack.scenes = (from str in GetAttribute(node, "scenes").Split(new char[1] { ',' }) select str.Trim()).ToArray(); musicTrack.boss = GetAttribute(node, "boss").ToLower() == "true"; foreach (FileInfo fileInfo in audioFiles) { if (fileInfo.Name == musicTrack.name) { musicTrack.fullName = fileInfo.FullName; break; } } return musicTrack; } 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 ""; } internal MusicAlbum GetSelectedAlbum() { return selectedAlbum; } public void SaveSelectedAlbum() { PlayerPrefs.SetString("ZPPlaylistAlbumName", selectedAlbum.name); } public void ReloadPreviousAlbum() { SetAlbum(PlayerPrefs.GetString("ZPPlaylistAlbumName", "")); } public void SetAlbum(string albumName) { selectedAlbumName = albumName; selectedAlbum = null; if (albumName == "" || loadedAlbums == null || loadedAlbums.Length == 0) { selectedAlbum = null; } else { MusicAlbum[] array = loadedAlbums; foreach (MusicAlbum musicAlbum in array) { if (selectedAlbumName == musicAlbum.name) { selectedAlbum = musicAlbum; break; } } } UpdateMainMenuCover(); } public void UpdateMainMenuCover() { if ((Object)(object)playlistButtonAlbumCover != (Object)null) { if (selectedAlbum != null) { playlistButtonAlbumCover.sprite = selectedAlbum.icon; } else { playlistButtonAlbumCover.sprite = Assets.defaultAlbumCover; } } else { Debug.LogWarning((object)"[ZP Playlist Mod] playlist button is null."); } } public float GetGameMusicVolume() { string @string = ((BaseConVar)AudioManager.cvVolumeMaster).GetString(); string string2 = ((BaseConVar)AudioManager.cvVolumeMsx).GetString(); @string = @string.Split(new char[1] { '.' })[0]; string2 = string2.Split(new char[1] { '.' })[0]; float.TryParse(@string, out var result); float.TryParse(string2, out var result2); return result2 / 100f * (result / 100f); } public void SetHighPassFilter() { if (currentSongFile == null || outputDevice == null) { return; } int channels = outputDevice.OutputWaveFormat.Channels; BiQuadFilter[] array = (BiQuadFilter[])(object)new BiQuadFilter[channels]; for (int i = 0; i < channels; i++) { if (array[i] == null) { array[i] = BiQuadFilter.HighPassFilter((float)outputDevice.OutputWaveFormat.SampleRate, 350f, 1f); } else { array[i].SetHighPassFilter((float)outputDevice.OutputWaveFormat.SampleRate, 350f, 1f); } Debug.LogWarning((object)"ADDED HIGH PASS FILTER"); } } public void RemoveFilters() { if (currentSongFile != null && outputDevice != null) { int channels = outputDevice.OutputWaveFormat.Channels; BiQuadFilter[] array = (BiQuadFilter[])(object)new BiQuadFilter[channels]; } } } internal class ZPPlaylistPauseDisplay : MonoBehaviour { private Animator animator; private TMP_Text trackNameLabel; private Image trackCover; public void Awake() { Init(); } public void Init() { animator = ((Component)this).GetComponent<Animator>(); Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); Transform[] array = componentsInChildren; foreach (Transform val in array) { if (((Object)((Component)val).gameObject).name == "ZP_Playlist_PauseTrackName") { trackNameLabel = ((Component)val).GetComponent<TMP_Text>(); } if (((Object)((Component)val).gameObject).name == "ZP_Playlist_PauseTrackIcon") { trackCover = ((Component)val).GetComponent<Image>(); } } } public void TriggerDisplayAnimation() { if (!((Object)(object)animator == (Object)null)) { animator.SetTrigger("Display"); } } public void SetDisplay(Sprite albumCover, string trackName) { trackCover.sprite = albumCover; trackNameLabel.text = trackName; } } internal class ZPPlaylistSelector : MonoBehaviour { internal ZPPlaylistModMain _main; public string albumId; public TMP_Text albumNameLabel; public TMP_Text albumDescLabel; public Image albumCover; public void Init() { Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); Transform[] array = componentsInChildren; foreach (Transform val in array) { if (((Object)((Component)val).gameObject).name == "ZP_PlaylistButton_NameLabel") { albumNameLabel = ((Component)val).GetComponent<TMP_Text>(); } if (((Object)((Component)val).gameObject).name == "ZP_PlaylistButton_DescLabel") { albumDescLabel = ((Component)val).GetComponent<TMP_Text>(); } if (((Object)((Component)val).gameObject).name == "ZP_PlaylistButtonIcon") { albumCover = ((Component)val).GetComponent<Image>(); } } Toggle val2 = default(Toggle); if (((Component)this).TryGetComponent<Toggle>(ref val2)) { ((UnityEvent<bool>)(object)val2.onValueChanged).AddListener((UnityAction<bool>)SetGameAlbum); } } public void SetAlbum(MusicAlbum album) { if ((Object)(object)albumNameLabel == (Object)null || (Object)(object)albumDescLabel == (Object)null || (Object)(object)albumCover == (Object)null) { Init(); } albumId = album.name; if ((Object)(object)albumNameLabel != (Object)null) { albumNameLabel.text = album.displayName; } if ((Object)(object)albumDescLabel != (Object)null) { albumDescLabel.text = album.description; } if ((Object)(object)albumCover != (Object)null) { albumCover.sprite = album.icon; } } public void OverrideAlbum(string albumId, string displayName, string desc, Sprite cover) { if ((Object)(object)albumNameLabel == (Object)null || (Object)(object)albumDescLabel == (Object)null || (Object)(object)albumCover == (Object)null) { Init(); } this.albumId = albumId; if ((Object)(object)albumNameLabel != (Object)null) { albumNameLabel.text = displayName; } if ((Object)(object)albumDescLabel != (Object)null) { albumDescLabel.text = desc; } if ((Object)(object)albumCover != (Object)null) { albumCover.sprite = cover; } else { Debug.LogError((object)"[ZP Playlist Mod] Album cover component not found."); } } private void SetGameAlbum(bool set) { if (set && (Object)(object)_main != (Object)null) { _main.SetAlbum(albumId); _main.SaveSelectedAlbum(); } } }