Decompiled source of H3VC v0.1.1
CatalpaBow.H3VC.dll
Decompiled 8 months 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.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Security.Permissions; using System.Threading; using BepInEx; using BepInEx.Logging; using FistVR; using H3MP; using H3MP.Networking; using H3MP.Scripts; using H3VC.AudioPipelines; using H3VC.Converter; using H3VC.Data; using H3VC.H3MPWrapper; using H3VC.Network; using H3VC.NetworkImplement.Mute; using H3VC.Networks; using H3VC.Networks.NetworkImplement; using H3VC.Netwroks; using H3VC.Presenter; using H3VC.Servers; using H3VC.Speakers; using H3VC.Test; using H3VC.VC; using H3VC.VCUsers; using H3VC.View; using H3VC.VoiceRecoders; using H3VC.VoiceRecoders.MicImpement; using H3VC.src.View; using HarmonyLib; using Microsoft.CodeAnalysis; using NAudio.Wave; using UniRx; using UniRx.Diagnostics; using UniRx.InternalUtil; using UniRx.Operators; using UniRx.Triggers; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using UnityOpus; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("CatalpaBow")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Add 3d audio voicechat to H3MP")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+c594efcbeda7c2038853a7f8a2dd3abb034aa0ef")] [assembly: AssemblyProduct("CatalpaBow.H3VC")] [assembly: AssemblyTitle("H3VC")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string id = null, string name = null, string version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null) { } } } namespace H3VC { [BepInPlugin("CatalpaBow.H3VC", "H3VC", "0.1.1")] [BepInProcess("h3vr.exe")] public class Mod : BaseUnityPlugin { internal AudioTest audioTest; internal static ManualLogSource Logger { get; private set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; VCMain.Intialize(); ViewMain.Intialize(); PresenterMain.Intialize(VCMain.recoder); } private void Update() { } } public static class TestPacket { [CompilerGenerated] private static class <>O { public static GenericCustomPacketReceivedDelegate <0>__PacketReceived; } public static void Intialize() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__PacketReceived; if (obj == null) { GenericCustomPacketReceivedDelegate val = PacketReceived; <>O.<0>__PacketReceived = val; obj = (object)val; } Mod.GenericCustomPacketReceived += (GenericCustomPacketReceivedDelegate)obj; } public static void PacketReceived(int clientID, string ID, Packet packet) { if (!(ID != "TestPacket")) { string text = packet.ReadString(true); Mod.Logger.LogMessage((object)text); } } public static void Send() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown Packet val = new Packet(-1); val.Write("TestPacket"); val.Write("HelloWorldYoYo"); ClientSend.SendTCPData(val, false); } public static void Test() { } } public class H3VRRaycaster : BaseRaycaster { public override Camera eventCamera { get { throw new NotImplementedException(); } } public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList) { throw new NotImplementedException(); } } } namespace H3VC.View { public static class AssetBundleLoader { private static AssetBundle bundle; public static AssetBundle Load() { if ((Object)(object)bundle != (Object)null) { return bundle; } bundle = AssetBundle.LoadFromFile(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName + "\\miccfgview"); return bundle; } } public class H3VCWristMenuSection : FVRWristMenuSection { public override void Enable() { } private void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)this).gameObject.AddComponent<Image>(); ((Graphic)obj).rectTransform.sizeDelta = new Vector2(500f, 350f); ((Graphic)obj).color = new Color(0.1f, 0.1f, 0.1f, 1f); } } public class VoiceRcoderWristMenuPatch : MonoBehaviour { [HarmonyPatch(typeof(FVRWristMenu2), "Update")] [HarmonyPrefix] private static void PrefixUpdate() { } [HarmonyPatch(typeof(FVRWristMenu2), "Awake")] [HarmonyPrefix] private static void PrefixAwake(FVRWristMenu2 __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Section_H3VC", new Type[1] { typeof(RectTransform) }); GameObject val2 = Object.Instantiate<GameObject>(AssetBundleLoader.Load().LoadAsset<GameObject>("MicSettings")); val2.transform.parent = val.transform; VoiceRecoderView.SingleInstance.Value = val2.GetComponent<VoiceRecoderView>(); val.transform.SetParent(__instance.MenuGO.transform); val.transform.localPosition = new Vector3(0f, 300f, 0f); val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; val.GetComponent<RectTransform>().sizeDelta = new Vector2(350f, 350f); FVRWristMenuSection val3 = (FVRWristMenuSection)(object)val.AddComponent<H3VCWristMenuSection>(); val3.ButtonText = "H3VC"; __instance.Sections.Add(val3); val.SetActive(false); } } public class VoiceRecoderView : MonoBehaviour { public static ReactiveProperty<VoiceRecoderView> SingleInstance = new ReactiveProperty<VoiceRecoderView>(); public UniRx.IObservable<Unit> OnViewDestroied; public UniRx.IObservable<bool> OnMuteChanged; public UniRx.IObservable<Unit> OnPreviousDevice; public UniRx.IObservable<Unit> OnNextDevice; public UniRx.IObservable<Unit> OnPreviousSoundMode; public UniRx.IObservable<Unit> OnNextSoundMode; public UniRx.IObservable<Unit> OnInceraseVolume; public UniRx.IObservable<Unit> OnDecreaseVolume; [SerializeField] private Toggle muteToggle; [SerializeField] private Text soundModeName; [SerializeField] private Button soundModePrevious; [SerializeField] private Button soundModeNext; [SerializeField] private Text deviceNameText; [SerializeField] private Button devicePrevious; [SerializeField] private Button deviceNext; [SerializeField] private GameObject levelMeter; [SerializeField] private Text volumeNum; [SerializeField] private Button decreaseVolume; [SerializeField] private Button increaseVolume; public void OnDestroy() { Mod.Logger.LogInfo((object)"Destroied!"); } public void Awake() { OnMuteChanged = muteToggle.OnValueChangedAsObservable(); OnPreviousDevice = devicePrevious.OnClickAsObservable(); OnNextDevice = deviceNext.OnClickAsObservable(); OnPreviousSoundMode = soundModePrevious.OnClickAsObservable(); OnNextSoundMode = soundModeNext.OnClickAsObservable(); OnDecreaseVolume = decreaseVolume.OnClickAsObservable(); OnInceraseVolume = increaseVolume.OnClickAsObservable(); SingleInstance.Value = this; } public void ChangeSoundMode(string modeName) { soundModeName.text = modeName; } public void ChangeDeviceName(string deviceName) { deviceNameText.text = deviceName; } public void ChangeVolumeNum(int val) { volumeNum.text = val.ToString(); } public void SetVoiceLevel(float val) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) levelMeter.transform.localScale = new Vector3(val, 1f, 1f); } } } namespace H3VC.View.FVRComponent { public class FVRDropdown : FVRPointable { private Dropdown dropdown; public void Awake() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)this).GetComponent<RectTransform>(); dropdown = ((Component)this).GetComponent<Dropdown>(); ((Component)this).gameObject.AddComponent<BoxCollider>().size = new Vector3(component.sizeDelta.x, component.sizeDelta.y, 0f); } public override void OnPoint(FVRViveHand hand) { ((FVRPointable)this).OnPoint(hand); if (hand.Input.TriggerDown && (Object)(object)dropdown != (Object)null) { dropdown.Show(); } } } public class FVRToggle : FVRPointable { private Toggle toggle; public void Awake() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)this).GetComponent<RectTransform>(); toggle = ((Component)this).GetComponent<Toggle>(); ((Component)this).gameObject.AddComponent<BoxCollider>().size = new Vector3(component.sizeDelta.x, component.sizeDelta.y, 0f); } public override void OnPoint(FVRViveHand hand) { ((FVRPointable)this).OnPoint(hand); if (hand.Input.TriggerDown && (Object)(object)toggle != (Object)null) { toggle.isOn = !toggle.isOn; } } } } namespace H3VC.VoiceRecoders { public abstract class BaseMicrophone : IMutipleDevice { public abstract UniRx.IObservable<float[]> OnAudioReady { get; } public BaseMicrophone() { } public abstract void StartRecoding(); public abstract IEnumerable<MicDeviceInfo> ShowDevices(); public abstract MicDeviceInfo ChangeDevice(int deviceNumber); public abstract int DeviceCount(); } public interface IMutipleDevice { IEnumerable<MicDeviceInfo> ShowDevices(); MicDeviceInfo ChangeDevice(int deviceID); int DeviceCount(); } public class MicDeviceInfo { public readonly int deviceID; public string name { get; private set; } public MicDeviceInfo(int _deviceID, string _name) { deviceID = _deviceID; name = _name; } } public class VoiceLevelMeter { private VoiceRecoder recoder; private ReactiveProperty<float> _crntVoiceLevel; private List<float> averageBuf; [SerializeField] private float dB_Min = -80f; [SerializeField] private float dB_Max = -0f; public IReadOnlyReactiveProperty<float> VoiceLevel => _crntVoiceLevel; public VoiceLevelMeter(VoiceRecoder _recoder) { averageBuf = new List<float>(); recoder = _recoder; _crntVoiceLevel = new ReactiveProperty<float>(); Intialize(); } private void Intialize() { (from samples in recoder.OnAudioReady.ThrottleFirst(TimeSpan.FromMilliseconds(16.0)) select samples.Value.pcmBuffer.Average()).Select(ToDecibel).Select(Normalization).Subscribe(delegate(float level) { _crntVoiceLevel.Value = level; }); } private float Normalization(float dB) { float num = dB; if (num > dB_Max) { num = dB_Max; } else if (num < dB_Min) { num = dB_Min; } return 1f + num / (dB_Max - dB_Min); } private float ToDecibel(float sampleAverage) { return 20f * Mathf.Log10(sampleAverage); } } public class VoiceRecoder : IAudioInput { public int id = -1; private BaseMicrophone mic; private VoiceLevelMeter levelMeter; public ReactiveProperty<float> volume; public ReactiveProperty<bool> isMute; public ReactiveProperty<SoundMode> soundMode; public ReactiveProperty<MicDeviceInfo> crntDevice; public IReadOnlyReactiveProperty<float> VoiceLevel => levelMeter.VoiceLevel; public UniRx.IObservable<KeyValuePair<int, PCMSegment>> OnAudioReady => from samples in mic.OnAudioReady select samples.Select((float sample) => sample * volume.Value * 2f).ToArray() into sgmnt select new PCMSegment(sgmnt, sgmnt.Length) into pcmData select new KeyValuePair<int, PCMSegment>(id, pcmData); public UniRx.IObservable<KeyValuePair<int, bool>> OnMuteChanged => isMute.Select((bool isMute) => new KeyValuePair<int, bool>(id, isMute)); public UniRx.IObservable<KeyValuePair<int, SoundMode>> OnSoundModeChanged => soundMode.Select((SoundMode mode) => new KeyValuePair<int, SoundMode>(id, mode)); public VoiceRecoder(BaseMicrophone _mic) { mic = _mic; volume = new ReactiveProperty<float>(); volume.Value = 0.5f; crntDevice = new ReactiveProperty<MicDeviceInfo>(); crntDevice.Value = mic.ShowDevices().First(); isMute = new ReactiveProperty<bool>(); soundMode = new ReactiveProperty<SoundMode>(); StartRecoding(); levelMeter = new VoiceLevelMeter(this); } public void DecreaseVolume() { ChangeVolume(volume.Value - 0.1f); } public void IncreaseVolume() { ChangeVolume(volume.Value + 0.1f); } private void ChangeVolume(float val) { if (val < 0f) { val = 0f; } if ((double)val > 2.0) { val = 2f; } volume.Value = val; } private void StartRecoding() { mic.StartRecoding(); } public IEnumerable<MicDeviceInfo> ShowDevices() { return mic.ShowDevices(); } public void ChangeDevice(int deviceID) { mic.ChangeDevice(deviceID); } public void NextDevice() { int num = crntDevice.Value.deviceID + 1; if (num >= mic.DeviceCount()) { num = 0; } crntDevice.Value = mic.ChangeDevice(num); } public void PreviousDevice() { int num = crntDevice.Value.deviceID - 1; if (num < 0) { num = mic.DeviceCount() - 1; } crntDevice.Value = mic.ChangeDevice(num); } public void NextSoundMode() { int length = Enum.GetValues(typeof(SoundMode)).Length; if ((int)(soundMode.Value + 1) >= length) { soundMode.Value = SoundMode.positional; } else { soundMode.Value++; } } public void PreviousSoundMode() { int length = Enum.GetValues(typeof(SoundMode)).Length; if (soundMode.Value - 1 < SoundMode.positional) { soundMode.Value = (SoundMode)(length - 1); } else { soundMode.Value--; } } } } namespace H3VC.VoiceRecoders.MicImplement { [Obsolete("", true)] public class UnityVoiceMic { } } namespace H3VC.VoiceRecoders.MicImpement { public class NAudioMic : BaseMicrophone { private Subject<float[]> OnAudioReadySubject; private float[] floatSamples; private WaveInEvent waveIn; public override UniRx.IObservable<float[]> OnAudioReady => OnAudioReadySubject; public NAudioMic() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown OnAudioReadySubject = new Subject<float[]>(); floatSamples = new float[4096]; int deviceNumber = 0; waveIn = new WaveInEvent(); waveIn.DeviceNumber = deviceNumber; waveIn.WaveFormat = new WaveFormat(48000, 1); waveIn.BufferMilliseconds = 10; waveIn.DataAvailable += DataAvailableHandler; } private void DataAvailableHandler(object sender, WaveInEventArgs e) { try { int recodedPartLength = Bit16ToNormizedFloat(ref floatSamples, e); float[] value = CutRecodedSamples(recodedPartLength); OnAudioReadySubject.OnNext(value); } catch (Exception ex) { Mod.Logger.LogError((object)ex); } } private int Bit16ToNormizedFloat(ref float[] floatSamples, WaveInEventArgs e) { int num = 0; for (num = 0; num < e.BytesRecorded; num += 2) { float num2 = (float)(short)((e.Buffer[num + 1] << 8) | e.Buffer[num]) / 32768f; floatSamples[num / 2] = num2; } return num / 2; } private float[] CutRecodedSamples(int recodedPartLength) { float[] array = new float[recodedPartLength]; Array.Copy(floatSamples, array, recodedPartLength); return array; } public override void StartRecoding() { waveIn.StartRecording(); } public override MicDeviceInfo ChangeDevice(int newDeviceNumber) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) waveIn.StopRecording(); waveIn.Dispose(); waveIn = new WaveInEvent(); waveIn.DeviceNumber = newDeviceNumber; waveIn.WaveFormat = new WaveFormat(48000, 1); waveIn.BufferMilliseconds = 10; waveIn.DataAvailable += DataAvailableHandler; waveIn.StartRecording(); WaveInCapabilities capabilities = WaveIn.GetCapabilities(newDeviceNumber); return new MicDeviceInfo(newDeviceNumber, ((WaveInCapabilities)(ref capabilities)).ProductName); } public override IEnumerable<MicDeviceInfo> ShowDevices() { for (int i = 0; i < WaveIn.DeviceCount; i++) { int deviceID = i; WaveInCapabilities capabilities = WaveIn.GetCapabilities(i); yield return new MicDeviceInfo(deviceID, ((WaveInCapabilities)(ref capabilities)).ProductName); } } public override int DeviceCount() { return WaveIn.DeviceCount; } } } namespace H3VC.VCUsers { public class VCUserList { private ReactiveCollection<int> _crntUsers; public IReadOnlyReactiveCollection<int> crntUserIDs => _crntUsers; public UniRx.IObservable<int> OnJoined => from evnt in crntUserIDs.ObserveAdd() select evnt.Value; public UniRx.IObservable<int> OnLeaved => from evnt in crntUserIDs.ObserveRemove() select evnt.Value; public VCUserList() { ReactiveCollection<int> reactiveCollection = new ReactiveCollection<int>(); foreach (int key in GameManager.players.Keys) { reactiveCollection.Add(key); } _crntUsers = reactiveCollection; (from plMngr in Observable.FromEvent<OnPlayerAddedDelegate, PlayerManager>((Action<PlayerManager> h) => new OnPlayerAddedDelegate(h.Invoke), delegate(OnPlayerAddedDelegate h) { GameManager.OnPlayerAdded += h; }, delegate(OnPlayerAddedDelegate h) { GameManager.OnPlayerAdded -= h; }) select plMngr.ID).Subscribe(_crntUsers.Add); (from plMngr in Observable.FromEvent<OnPlayerRemovedDelegate, PlayerManager>((Action<PlayerManager> h) => new OnPlayerRemovedDelegate(h.Invoke), delegate(OnPlayerRemovedDelegate h) { Mod.OnPlayerRemoved += h; }, delegate(OnPlayerRemovedDelegate h) { Mod.OnPlayerRemoved -= h; }) select plMngr.ID).Subscribe(delegate(int id) { _crntUsers.Remove(id); }); OnJoined.Subscribe(delegate(int id) { Mod.Logger.LogInfo((object)("VCUser:" + id + "is joined!")); }); OnLeaved.Subscribe(delegate(int id) { Mod.Logger.LogInfo((object)("VCUser:" + id + "is leaved!")); }); } } } namespace H3VC.VC { public static class VCMain { public static AudioPipeline audioPipeline; public static VoiceRecoder recoder; public static PlayerAudioSpeakers speakers; public static VCUserList userList; public static AudioRelayServer server; public static void Intialize() { userList = new VCUserList(); recoder = new VoiceRecoder(new NAudioMic()); speakers = new PlayerAudioSpeakers(userList); NetworkAudioListener inOthers = new NetworkAudioListener(); NetworkAudioStreamer outSelf = new NetworkAudioStreamer(); audioPipeline = new AudioPipeline(recoder, outSelf, inOthers, speakers); server = new AudioRelayServer(); } } } namespace H3VC.Speakers { public class PlayerAudioSpeaker { public readonly int id; private SoundMode soundMode; private bool isMute; private UnitySpeaker voicePlayer; public PlayerAudioSpeaker(UnitySpeaker pl, int _id) { id = _id; voicePlayer = pl; soundMode = H3VC.Data.SoundMode.positional; voicePlayer.SetPositional(isPositional: false); } public void Mute(bool isMute) { voicePlayer.DontPlaySound(isMute); this.isMute = isMute; } public void SoundMode(SoundMode mode) { ManualLogSource logger = Mod.Logger; int num = id; logger.LogInfo((object)("UserID:" + num + " is SoundModeChanged")); soundMode = mode; if (mode == H3VC.Data.SoundMode.positional) { voicePlayer.SetPositional(isPositional: true); } else { voicePlayer.SetPositional(isPositional: false); } } public void Play(PCMSegment sgmnt) { voicePlayer.Play(sgmnt); if (isMute) { Mute(isMute: true); return; } string text = Players.CurrentScene(id); string text2 = Players.CurrentScene(Players.IDSelf()); bool flag = text == text2; if ((soundMode == H3VC.Data.SoundMode.localScene || soundMode == H3VC.Data.SoundMode.positional) && !flag) { voicePlayer.DontPlaySound(isMute: true); } else { voicePlayer.DontPlaySound(isMute: false); } } } public class PlayerAudioSpeakers : IAudioOutput { public List<PlayerAudioSpeaker> speakerList; private readonly VCUserList userList; public PlayerAudioSpeakers(VCUserList _userList) { userList = _userList; speakerList = userList.crntUserIDs.Select(VoiceSpeakerBuilder.Build).ToList(); (from spkr in userList.OnJoined.Select(VoiceSpeakerBuilder.Build) where spkr != null select spkr).Subscribe(speakerList.Add); userList.OnLeaved.Subscribe(delegate(int id) { speakerList.RemoveAll((PlayerAudioSpeaker spkr) => spkr.id == id); }); } public void StreamAudio(int id, PCMSegment sgmnt) { speakerList.Find((PlayerAudioSpeaker spkr) => spkr.id == id)?.Play(sgmnt); } public void Mute(int id, bool isMute) { speakerList.Find((PlayerAudioSpeaker spkr) => spkr.id == id)?.Mute(isMute); } public void SoundMode(int id, SoundMode mode) { speakerList.Find((PlayerAudioSpeaker spkr) => spkr.id == id)?.SoundMode(mode); } } [RequireComponent(typeof(AudioSource))] public class UnitySpeaker : MonoBehaviour { private const NumChannels channels = NumChannels.Mono; private const SamplingFrequency frequency = SamplingFrequency.Frequency_48000; private const int audioClipLength = 48000; private const int delaySamplesLength = 3840; private float[] samplesBuf; private int previousTimeSamples; private int previousDistance; private int previousHead; public AudioSource source { get; private set; } public int head { get; private set; } private void Awake() { Intialize(1); } public void Intialize(int channels) { source = ((Component)this).GetComponent<AudioSource>(); source.spatialBlend = 1f; source.clip = AudioClip.Create("Voice", 48000, channels, 48000, false); source.loop = true; } public void DontPlaySound(bool isMute) { if (isMute) { source.volume = 0f; } else { source.volume = 1f; } } private void OnDisable() { source.Stop(); } public void Play(PCMSegment sgmnt) { Play(sgmnt.pcmBuffer, sgmnt.pcmLength); } public void Play(float[] samples, int samplesLength) { if (samplesBuf == null || samplesBuf.Length != samplesLength + 2) { samplesBuf = new float[samplesLength + 2]; Mod.Logger.LogInfo((object)("samplesBufSize is changed:" + samplesLength + 2)); } Array.Copy(samples, 0, samplesBuf, 1, samplesLength); samplesBuf[0] = samplesBuf[1]; samplesBuf[samplesBuf.Length - 1] = samplesBuf[samplesBuf.Length - 2]; source.clip.SetData(samplesBuf, head); head += samplesBuf.Length; head %= source.clip.samples; if (!source.isPlaying && head > 3840) { Mod.Logger.LogInfo((object)"Played"); source.Play(); } int num = 0; num = ((source.timeSamples <= head) ? (head - source.timeSamples) : (head + source.clip.samples - source.timeSamples)); if (num > 5760) { int num2 = head - 3840; source.timeSamples = ((num2 < 0) ? (source.clip.samples + num2) : num2); } Log(); } public void SetInScene() { source.spatialBlend = 0f; } public void SetPositional(bool isPositional) { if (isPositional) { source.spatialBlend = 1f; } else { source.spatialBlend = 0f; } } public void Log() { _ = source.isPlaying; } } public static class VoiceSpeakerBuilder { public static PlayerAudioSpeaker Build(int id) { if (!GameManager.players.TryGetValue(id, out var value)) { return null; } return new PlayerAudioSpeaker(((Component)value.head).gameObject.AddComponent<UnitySpeaker>(), id); } } } namespace H3VC.Servers { public class AudioRelayServer { private static AudioRelayServer _instance; private VoiceReceiver receiver; private IDisposable serverDisposer; public static AudioRelayServer Insntance => _instance ?? (_instance = new AudioRelayServer()); public AudioRelayServer() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown receiver = VoiceReceiver.Instance; Mod.OnConnection += new OnConnectionDelegate(Start); Server.OnServerClose += new OnServerCloseDelegate(Stop); } public void Start() { if (ThreadManager.host) { Mod.Logger.LogInfo((object)"H3VC ServerStart"); serverDisposer = receiver.OnVoiceReceived.Subscribe(delegate(UniRx.Tuple<int, OpusSegment> data) { VoiceSender.ServerSend(data.Item1, data.Item2); }); } } public void Stop() { Mod.Logger.LogInfo((object)"H3VC ServerClose"); serverDisposer.Dispose(); } } } namespace H3VC.Netwroks { public enum TransportProtocol { TCP, UDP } } namespace H3VC.Network { public class VoiceReceiver : IDisposable { private static VoiceReceiver _instance; public static string packetName = "H3VC_VoiceData"; private Subject<UniRx.Tuple<int, OpusSegment>> voiceReceivedStream; public static VoiceReceiver Instance => _instance ?? (_instance = new VoiceReceiver()); public UniRx.IObservable<UniRx.Tuple<int, OpusSegment>> OnVoiceReceived => voiceReceivedStream; public VoiceReceiver() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown voiceReceivedStream = new Subject<UniRx.Tuple<int, OpusSegment>>(); Mod.GenericCustomPacketReceived += new GenericCustomPacketReceivedDelegate(PacketHandler); } private void PacketHandler(int clientID, string name, Packet pkt) { if (!(name != packetName)) { int num = pkt.ReadInt(true); byte[] data = pkt.ReadBytes(num, true); int length = pkt.ReadInt(true); voiceReceivedStream.OnNext(UniRx.Tuple.Create(clientID, new OpusSegment(data, length))); } } public void Dispose() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Mod.GenericCustomPacketReceived -= new GenericCustomPacketReceivedDelegate(PacketHandler); } } internal static class VoiceSender { public const string packetID = "H3VC_VoiceData"; public static void ClientSend(OpusSegment sgmnt) { ClientSend.SendUDPData(sgmnt.ToPacket(-1, "H3VC_VoiceData"), false); } public static void ServerSend(int sender, OpusSegment sgmnt) { Packet val = sgmnt.ToPacket(-1, "H3VC_VoiceData"); val.WriteLength(); foreach (ServerClient value in Server.clients.Values) { if (value.ID == sender) { break; } value.udp.SendData(val); } } public static void SendFromClient(OpusSegment sgmnt) { if (ThreadManager.host) { ServerSend(0, sgmnt); } else { ClientSend(sgmnt); } } } } namespace H3VC.NetworkImplement.Mute { public static class MuteEvent { public static MuteSender sender; public static MuteReceiver receiver; static MuteEvent() { TransportProtocol prtcl = TransportProtocol.TCP; sender = new MuteSender("H3VC_Mute", prtcl); receiver = new MuteReceiver("H3VC_Mute"); } } public static class SoundModeEvent { public static SoundModeSender sender; public static SoundModeReceiver receiver; static SoundModeEvent() { TransportProtocol prtcl = TransportProtocol.TCP; sender = new SoundModeSender("H3VC_SoundMode", prtcl); receiver = new SoundModeReceiver("H3VC_SoundMode"); } } } namespace H3VC.Networks { public class NetworkAudioListener : IAudioInput { private VoiceDecoder decoder; public UniRx.IObservable<KeyValuePair<int, PCMSegment>> OnAudioReady => VoiceReceiver.Instance.OnVoiceReceived.Select(delegate(UniRx.Tuple<int, OpusSegment> audioData) { PCMSegment value = decoder.Decode(audioData.Item2); return new KeyValuePair<int, PCMSegment>(audioData.Item1, value); }); public UniRx.IObservable<KeyValuePair<int, bool>> OnMuteChanged => MuteEvent.receiver.OnReceivedWithSenderID; public UniRx.IObservable<KeyValuePair<int, SoundMode>> OnSoundModeChanged => SoundModeEvent.receiver.OnReceivedWithSenderID; public NetworkAudioListener() { decoder = new VoiceDecoder(); } } public class NetworkAudioStreamer : IAudioOutput { private VoiceEncoder encoder; public NetworkAudioStreamer() { encoder = new VoiceEncoder(); } public void Mute(int id, bool isMute) { MuteEvent.sender.SendFromClient(isMute); } public void SoundMode(int id, SoundMode mode) { SoundModeEvent.sender.SendFromClient(mode); } public void StreamAudio(int id, PCMSegment sgmnt) { foreach (OpusSegment item in encoder.Encode(sgmnt.pcmBuffer)) { VoiceSender.SendFromClient(item); } } } } namespace H3VC.Networks.NetworkImplement { public class MuteReceiver : ReceiverBase<bool> { public MuteReceiver(string id) : base(id) { } public override bool Unpacket(CustomPacketReceivedEventData data) { return data.packet.ReadBool(true); } } public class MuteSender : SenderBase<bool> { public MuteSender(string id, TransportProtocol prtcl) : base(id, prtcl) { } public override void WritePacketData(ref Packet pkt, bool data) { pkt.Write(data); } } public abstract class ReceiverBase<ReceiveT> { public string packetID; public UniRx.IObservable<ReceiveT> OnReceived; public UniRx.IObservable<KeyValuePair<int, ReceiveT>> OnReceivedWithSenderID; public UniRx.IObservable<CustomPacketReceivedEventData> OnReceivedRaw; public ReceiverBase(string packetID) { ReceiverBase<ReceiveT> receiverBase = this; this.packetID = packetID; OnReceivedRaw = H3MPNetworkEvents.OnCustomPacketRecevied.Where((CustomPacketReceivedEventData evntData) => evntData.id == packetID); OnReceived = OnReceivedRaw.Select(Unpacket); OnReceivedWithSenderID = OnReceivedRaw.Select((CustomPacketReceivedEventData data) => new KeyValuePair<int, ReceiveT>(data.clientID, receiverBase.Unpacket(data))); } public abstract ReceiveT Unpacket(CustomPacketReceivedEventData data); } public abstract class SenderBase<SendT> { protected string packetID; protected TransportProtocol prtcl; protected SenderBase(string pktID, TransportProtocol prtcl) { packetID = pktID; this.prtcl = prtcl; } private void ClientSend(SendT data) { ClientSend.SendUDPData(ToPacket(data), false); } public void ServerSend(SendT data) { Packet pkt = ToPacket(data); ServerRelaySend(0, pkt); } public void ServerRelaySend(int sender, Packet pkt) { pkt.WriteLength(); if (prtcl == TransportProtocol.TCP) { foreach (ServerClient value in Server.clients.Values) { if (value.ID == sender) { break; } value.udp.SendData(pkt); } return; } foreach (ServerClient value2 in Server.clients.Values) { if (value2.ID == sender) { break; } value2.tcp.SendData(pkt); } } public Packet ToPacket(SendT data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Packet pkt = new Packet(-1); pkt.Write(packetID); WritePacketData(ref pkt, data); return pkt; } public abstract void WritePacketData(ref Packet pkt, SendT data); public void SendFromClient(SendT data) { if (ThreadManager.host) { ServerSend(data); } else { ClientSend(data); } } } public class SoundModeReceiver : ReceiverBase<SoundMode> { public SoundModeReceiver(string id) : base(id) { } public override SoundMode Unpacket(CustomPacketReceivedEventData data) { return (SoundMode)data.packet.ReadInt(true); } } public class SoundModeSender : SenderBase<SoundMode> { public SoundModeSender(string id, TransportProtocol prtcl) : base(id, prtcl) { } public override void WritePacketData(ref Packet pkt, SoundMode data) { pkt.Write((int)data); } } } namespace H3VC.src.View { public static class ViewMain { public static void Intialize() { Harmony.CreateAndPatchAll(typeof(VoiceRcoderWristMenuPatch), (string)null); } } } namespace H3VC.src.VC.Logger { public class UnitySpeakerAnalizer { private UnitySpeaker spkr; private int speakrCrntPosDelay; private int headPos => spkr.head; private int crntPos => spkr.source.timeSamples; } } namespace H3VC.H3MPWrapper { public static class H3MPNetworkEvents { public static UniRx.IObservable<CustomPacketReceivedEventData> OnCustomPacketRecevied = Observable.FromEvent<GenericCustomPacketReceivedDelegate, CustomPacketReceivedEventData>((Action<CustomPacketReceivedEventData> h) => (GenericCustomPacketReceivedDelegate)delegate(int cID, string id, Packet pkt) { h(new CustomPacketReceivedEventData(cID, id, pkt)); }, delegate(GenericCustomPacketReceivedDelegate h) { Mod.GenericCustomPacketReceived += h; }, delegate(GenericCustomPacketReceivedDelegate h) { Mod.GenericCustomPacketReceived -= h; }); } public class CustomPacketReceivedEventData { public int clientID; public string id; public Packet packet; public CustomPacketReceivedEventData(int clientID, string id, Packet pkt) { this.clientID = clientID; this.id = id; packet = pkt; } } public static class Players { public static string CurrentScene(int id) { if (id == IDSelf()) { return GameManager.scene; } if (GameManager.players.TryGetValue(id, out var value)) { return value.scene; } return ""; } public static int IDSelf() { return GameManager.ID; } } } namespace H3VC.AudioPipelines { public class AudioPipeline { private IAudioInput selfIn; private IAudioOutput selfOut; private IAudioInput otherIn; private IAudioOutput otherOut; public AudioPipeline(IAudioInput _inSelf, IAudioOutput _outSelf, IAudioInput _inOthers, IAudioOutput _outOthers) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown selfIn = _inSelf; selfOut = _outSelf; otherIn = _inOthers; otherOut = _outOthers; Mod.OnConnection += new OnConnectionDelegate(StartStream); } public void StartStream() { selfIn.OnAudioReady.Subscribe(delegate(KeyValuePair<int, PCMSegment> audioData) { selfOut.StreamAudio(audioData.Key, audioData.Value); }); selfIn.OnMuteChanged.Subscribe(delegate(KeyValuePair<int, bool> isMute) { selfOut.Mute(isMute.Key, isMute.Value); }); selfIn.OnSoundModeChanged.Subscribe(delegate(KeyValuePair<int, SoundMode> mode) { selfOut.SoundMode(mode.Key, mode.Value); }); otherIn.OnAudioReady.Subscribe(delegate(KeyValuePair<int, PCMSegment> audioData) { otherOut.StreamAudio(audioData.Key, audioData.Value); }); otherIn.OnMuteChanged.Subscribe(delegate(KeyValuePair<int, bool> isMute) { otherOut.Mute(isMute.Key, isMute.Value); }); otherIn.OnSoundModeChanged.Subscribe(delegate(KeyValuePair<int, SoundMode> mode) { otherOut.SoundMode(mode.Key, mode.Value); }); } } public interface IAudioInput { UniRx.IObservable<KeyValuePair<int, PCMSegment>> OnAudioReady { get; } UniRx.IObservable<KeyValuePair<int, bool>> OnMuteChanged { get; } UniRx.IObservable<KeyValuePair<int, SoundMode>> OnSoundModeChanged { get; } } public interface IAudioOutput { void StreamAudio(int id, PCMSegment sgmnt); void Mute(int id, bool isMute); void SoundMode(int id, SoundMode mode); } } namespace H3VC.Data { public class OpusSegment { public readonly byte[] data; public readonly int dataLength; public readonly int length; public OpusSegment(byte[] _data, int _length) { data = _data; dataLength = _data.GetLength(0); length = _length; } public Packet ToPacket(int id, string name) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Packet val = new Packet(id); val.Write(name); val.Write(dataLength); val.Write(data); val.Write(length); return val; } } public class PCMSegment { public readonly float[] pcmBuffer; public readonly int pcmLength; public PCMSegment(float[] _pcmBuffer, int _pcmLength) { pcmBuffer = _pcmBuffer; pcmLength = _pcmLength; } } public enum SoundMode { positional, localScene, globalScene } } namespace H3VC.Converter { public class VoiceDecoder { private const NumChannels channels = NumChannels.Mono; private Decoder decoder; private readonly float[] pcmBuffer = new float[5760]; public VoiceDecoder() { decoder = new Decoder(SamplingFrequency.Frequency_48000, NumChannels.Mono); } private void OnDisable() { decoder.Dispose(); decoder = null; } public PCMSegment Decode(OpusSegment segment) { int pcmLength = decoder.Decode(segment.data, segment.length, pcmBuffer); return new PCMSegment(pcmBuffer, pcmLength); } } public class VoiceEncoder { private const int bitrate = 96000; private const int frameSize = 120; private const int outputBufferSize = 480; private Encoder encoder; private Queue<float> pcmQueue = new Queue<float>(); private readonly float[] frameBuffer = new float[120]; private readonly byte[] outputBuffer = new byte[480]; public VoiceEncoder() { encoder = new Encoder(SamplingFrequency.Frequency_48000, NumChannels.Mono, OpusApplication.Audio) { Bitrate = 96000, Complexity = 10, Signal = OpusSignal.Music }; } private void Disable() { encoder.Dispose(); encoder = null; pcmQueue.Clear(); } public IEnumerable<OpusSegment> Encode(float[] data) { foreach (float item in data) { pcmQueue.Enqueue(item); } while (pcmQueue.Count > 120) { for (int j = 0; j < 120; j++) { frameBuffer[j] = pcmQueue.Dequeue(); } int length = encoder.Encode(frameBuffer, outputBuffer); yield return new OpusSegment(outputBuffer, length); } } } } namespace H3VC.Test { public class AssetBundleLoadTest { public static void Test() { if ((Object)(object)AssetBundleLoader.Load().LoadAsset<GameObject>("MicSetting") == (Object)null) { Mod.Logger.LogError((object)"asset is null"); } else { Mod.Logger.LogInfo((object)"Load is sucsessed!"); } } } internal class TestMain { } internal class AudioTest { private VoiceRecoder recoder; private UnitySpeaker spkr; public AudioTest(VoiceRecoder recoder) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) this.recoder = recoder; spkr = new GameObject().AddComponent<UnitySpeaker>(); spkr.SetPositional(isPositional: false); Mod.Logger.LogInfo((object)AudioSettings.outputSampleRate); recoder.OnAudioReady.Subscribe(delegate(KeyValuePair<int, PCMSegment> data) { spkr.Play(data.Value); }); } } public class SpeakerTests { private PlayerAudioSpeakers spkrs; public SpeakerTests(PlayerAudioSpeakers _spkrs) { spkrs = _spkrs; } public bool UserCountTests() { return spkrs.speakerList.Count == GameManager.players.Count; } } public static class Tester { public static void Assert(bool isSucsess) { if (isSucsess) { Mod.Logger.LogInfo((object)"Test is Sucsesed:"); } else { Mod.Logger.LogError((object)"Test is Failed"); } } public static void UserListTest() { Mod.Logger.LogDebug((object)("-----------" + MethodBase.GetCurrentMethod().Name + "-----------")); Mod.Logger.LogDebug((object)("UserListCount:" + VCMain.userList.crntUserIDs.Count)); Mod.Logger.LogDebug((object)("H3MPPlayersCount:" + GameManager.players.Count)); Assert(VCMain.userList.crntUserIDs.Count == GameManager.players.Count); } public static void Spkr_CountTest() { Mod.Logger.LogDebug((object)("-----------" + MethodBase.GetCurrentMethod().Name + "-----------")); Mod.Logger.LogDebug((object)("spkeakerListCount:" + VCMain.speakers.speakerList.Count)); Mod.Logger.LogDebug((object)("UserListCount:" + VCMain.userList.crntUserIDs.Count)); Assert(VCMain.speakers.speakerList.Count == GameManager.players.Count); } } } namespace H3VC.Presenter { public static class PresenterMain { public static VoiceRecoderPresenter presenter; public static void Intialize(VoiceRecoder model) { VoiceRecoderView.SingleInstance.Where((VoiceRecoderView instance) => instance != null).Subscribe(delegate(VoiceRecoderView view) { if (presenter == null) { presenter = new VoiceRecoderPresenter(model, view); } else { presenter.ResetView(view); } }); } } public class VoiceRecoderPresenter { private VoiceRecoder model; private VoiceRecoderView view; public VoiceRecoderPresenter(VoiceRecoder model, VoiceRecoderView view) { this.model = model; this.view = view; Intialize(); } public void Intialize() { view.OnMuteChanged.Subscribe(delegate(bool isMute) { model.isMute.Value = isMute; }).AddTo((Component)(object)view); view.OnNextSoundMode.Subscribe(delegate { model.NextSoundMode(); }).AddTo((Component)(object)view); view.OnPreviousSoundMode.Subscribe(delegate { model.PreviousSoundMode(); }).AddTo((Component)(object)view); view.OnNextDevice.Subscribe(delegate { model.NextDevice(); }).AddTo((Component)(object)view); view.OnPreviousDevice.Subscribe(delegate { model.PreviousDevice(); }).AddTo((Component)(object)view); view.OnDecreaseVolume.Subscribe(delegate { model.DecreaseVolume(); }); view.OnInceraseVolume.Subscribe(delegate { model.IncreaseVolume(); }); model.soundMode.Subscribe(delegate(SoundMode mode) { view.ChangeSoundMode(mode.ToString()); }).AddTo((Component)(object)view); model.crntDevice.Subscribe(delegate(MicDeviceInfo info) { view.ChangeDeviceName(info.name); }).AddTo((Component)(object)view); model.VoiceLevel.Subscribe(delegate(float level) { view.SetVoiceLevel(level); }).AddTo((Component)(object)view); model.volume.Select((float val) => (int)(Math.Round(val * 10f) * 10.0)).Subscribe(delegate(int percent) { view.ChangeVolumeNum(percent); }); } public void ResetView(VoiceRecoderView view) { this.view = view; Intialize(); } } } namespace UnityOpus { public class Decoder : IDisposable { public const int maximumPacketDuration = 5760; private IntPtr decoder; private readonly NumChannels channels; private readonly float[] softclipMem; private bool disposedValue; public Decoder(SamplingFrequency samplingFrequency, NumChannels channels) { this.channels = channels; decoder = Library.OpusDecoderCreate(samplingFrequency, channels, out var error); if (error != 0) { Debug.LogError((object)("[UnityOpus] Failed to create Decoder. Error code is " + error)); decoder = IntPtr.Zero; } softclipMem = new float[(int)channels]; } public int Decode(byte[] data, int dataLength, float[] pcm, int decodeFec = 0) { if (decoder == IntPtr.Zero) { return 0; } int num = Library.OpusDecodeFloat(decoder, data, dataLength, pcm, pcm.Length / (int)channels, decodeFec); Library.OpusPcmSoftClip(pcm, num / (int)channels, channels, softclipMem); return num; } protected virtual void Dispose(bool disposing) { if (!disposedValue && !(decoder == IntPtr.Zero)) { Library.OpusDecoderDestroy(decoder); decoder = IntPtr.Zero; disposedValue = true; } } ~Decoder() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } public class Encoder : IDisposable { private int bitrate; private int complexity; private OpusSignal signal; private IntPtr encoder; private NumChannels channels; private bool disposedValue; public int Bitrate { get { return bitrate; } set { Library.OpusEncoderSetBitrate(encoder, value); bitrate = value; } } public int Complexity { get { return complexity; } set { Library.OpusEncoderSetComplexity(encoder, value); complexity = value; } } public OpusSignal Signal { get { return signal; } set { Library.OpusEncoderSetSignal(encoder, value); signal = value; } } public Encoder(SamplingFrequency samplingFrequency, NumChannels channels, OpusApplication application) { this.channels = channels; encoder = Library.OpusEncoderCreate(samplingFrequency, channels, application, out var error); if (error != 0) { Debug.LogError((object)("[UnityOpus] Failed to init encoder. Error code: " + error)); encoder = IntPtr.Zero; } } public int Encode(float[] pcm, byte[] output) { if (encoder == IntPtr.Zero) { return 0; } return Library.OpusEncodeFloat(encoder, pcm, pcm.Length / (int)channels, output, output.Length); } protected virtual void Dispose(bool disposing) { if (!disposedValue && !(encoder == IntPtr.Zero)) { Library.OpusEncoderDestroy(encoder); encoder = IntPtr.Zero; disposedValue = true; } } ~Encoder() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } public enum SamplingFrequency { Frequency_8000 = 8000, Frequency_12000 = 12000, Frequency_16000 = 16000, Frequency_24000 = 24000, Frequency_48000 = 48000 } public enum NumChannels { Mono = 1, Stereo } public enum OpusApplication { VoIP = 2048, Audio = 2049, RestrictedLowDelay = 2051 } public enum OpusSignal { Auto = -1000, Voice = 3001, Music = 3002 } public enum ErrorCode { OK = 0, BadArg = -1, BufferTooSmall = -2, InternalError = -3, InvalidPacket = -4, Unimplemented = -5, InvalidState = -6, AllocFail = -7 } public static class Library { public delegate IntPtr OpusEncoderCreateDelegate(SamplingFrequency samplingFrequency, NumChannels channels, OpusApplication application, out ErrorCode error); public delegate int OpusEncodeDelegate(IntPtr encoder, short[] pcm, int frameSize, byte[] data, int maxDataBytes); public delegate int OpusEncodeFloatDelegate(IntPtr encoder, float[] pcm, int frameSize, byte[] data, int maxDataBytes); public delegate int OpusEncoderDestroyDelegate(IntPtr encoder); public delegate int OpusEncoderSetBitrateDelegate(IntPtr encoder, int bitrate); public delegate int OpusEncoderSetComplexityDelegate(IntPtr encoder, int complexity); public delegate int OpusEncoderSetSignalDelegate(IntPtr encoder, OpusSignal signal); public delegate IntPtr OpusDecoderCreateDelegate(SamplingFrequency samplingFrequency, NumChannels channels, out ErrorCode error); public delegate int OpusDecodeDelegate(IntPtr decoder, byte[] data, int len, short[] pcm, int frameSize, int decodeFec); public delegate int OpusDecodeFloatDelegate(IntPtr decoder, byte[] data, int len, float[] pcm, int frameSize, int decodeFec); public delegate void OpusDecoderDestroyDelegate(IntPtr decoder); public delegate void OpusPcmSoftClipDelegate(float[] pcm, int frameSize, NumChannels channels, float[] softclipMem); public const int maximumPacketDuration = 5760; private static IntPtr dllHandle; public static readonly OpusEncoderCreateDelegate OpusEncoderCreate; public static readonly OpusEncodeDelegate OpusEncode; public static OpusEncodeFloatDelegate OpusEncodeFloat; public static OpusEncoderDestroyDelegate OpusEncoderDestroy; public static OpusEncoderSetBitrateDelegate OpusEncoderSetBitrate; public static OpusEncoderSetComplexityDelegate OpusEncoderSetComplexity; public static OpusEncoderSetSignalDelegate OpusEncoderSetSignal; public static OpusDecoderCreateDelegate OpusDecoderCreate; public static OpusDecodeDelegate OpusDecode; public static OpusDecodeFloatDelegate OpusDecodeFloat; public static OpusDecoderDestroyDelegate OpusDecoderDestroy; public static OpusPcmSoftClipDelegate OpusPcmSoftClip; static Library() { dllHandle = LoadLibrary(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName + "\\UnityOpus.dll"); _ = dllHandle == IntPtr.Zero; OpusEncoderCreate = GetFunctionPointer<OpusEncoderCreateDelegate>("OpusEncoderCreate"); OpusEncode = GetFunctionPointer<OpusEncodeDelegate>("OpusEncode"); OpusEncodeFloat = GetFunctionPointer<OpusEncodeFloatDelegate>("OpusEncodeFloat"); OpusEncoderDestroy = GetFunctionPointer<OpusEncoderDestroyDelegate>("OpusEncodeFloat"); OpusEncoderSetBitrate = GetFunctionPointer<OpusEncoderSetBitrateDelegate>("OpusEncoderSetBitrate"); OpusEncoderSetComplexity = GetFunctionPointer<OpusEncoderSetComplexityDelegate>("OpusEncoderSetComplexity"); OpusEncoderSetSignal = GetFunctionPointer<OpusEncoderSetSignalDelegate>("OpusEncoderSetSignal"); OpusDecoderCreate = GetFunctionPointer<OpusDecoderCreateDelegate>("OpusDecoderCreate"); OpusDecode = GetFunctionPointer<OpusDecodeDelegate>("OpusDecode"); OpusDecodeFloat = GetFunctionPointer<OpusDecodeFloatDelegate>("OpusDecodeFloat"); OpusDecoderDestroy = GetFunctionPointer<OpusDecoderDestroyDelegate>("OpusDecoderDestroy"); OpusPcmSoftClip = GetFunctionPointer<OpusPcmSoftClipDelegate>("OpusPcmSoftClip"); AppDomain.CurrentDomain.ProcessExit += ProcessExitHandler; AppDomain.CurrentDomain.UnhandledException += ProcessExitHandler; } private static T GetFunctionPointer<T>(string functionName) where T : Delegate { return (T)Marshal.GetDelegateForFunctionPointer(GetProcAddress(dllHandle, functionName), typeof(T)); } private static void ProcessExitHandler(object sender, EventArgs e) { FreeLibrary(dllHandle); } [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32", SetLastError = true)] internal static extern bool FreeLibrary(IntPtr hModule); [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)] internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); } } namespace UniRx { public static class WebRequestExtensions { private static IObservable<TResult> AbortableDeferredAsyncRequest<TResult>(Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, WebRequest request) { return Observable.Create(delegate(IObserver<TResult> observer) { int isCompleted = -1; IDisposable subscription = Observable.FromAsyncPattern(begin, delegate(IAsyncResult ar) { try { Interlocked.Increment(ref isCompleted); return end(ar); } catch (WebException ex) { if (ex.Status != WebExceptionStatus.RequestCanceled) { throw; } return default(TResult); } })().Subscribe(observer); return Disposable.Create(delegate { if (Interlocked.Increment(ref isCompleted) == 0) { subscription.Dispose(); request.Abort(); } }); }); } public static IObservable<WebResponse> GetResponseAsObservable(this WebRequest request) { return AbortableDeferredAsyncRequest(request.BeginGetResponse, request.EndGetResponse, request); } public static IObservable<HttpWebResponse> GetResponseAsObservable(this HttpWebRequest request) { return AbortableDeferredAsyncRequest(request.BeginGetResponse, (IAsyncResult ar) => (HttpWebResponse)request.EndGetResponse(ar), request); } public static IObservable<Stream> GetRequestStreamAsObservable(this WebRequest request) { return AbortableDeferredAsyncRequest(request.BeginGetRequestStream, request.EndGetRequestStream, request); } } public sealed class BooleanDisposable : IDisposable, ICancelable { public bool IsDisposed { get; private set; } public BooleanDisposable() { } internal BooleanDisposable(bool isDisposed) { IsDisposed = isDisposed; } public void Dispose() { if (!IsDisposed) { IsDisposed = true; } } } public sealed class CompositeDisposable : ICollection<IDisposable>, IEnumerable<IDisposable>, IEnumerable, IDisposable, ICancelable { private readonly object _gate = new object(); private bool _disposed; private List<IDisposable> _disposables; private int _count; private const int SHRINK_THRESHOLD = 64; public int Count => _count; public bool IsReadOnly => false; public bool IsDisposed => _disposed; public CompositeDisposable() { _disposables = new List<IDisposable>(); } public CompositeDisposable(int capacity) { if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity"); } _disposables = new List<IDisposable>(capacity); } public CompositeDisposable(params IDisposable[] disposables) { if (disposables == null) { throw new ArgumentNullException("disposables"); } _disposables = new List<IDisposable>(disposables); _count = _disposables.Count; } public CompositeDisposable(IEnumerable<IDisposable> disposables) { if (disposables == null) { throw new ArgumentNullException("disposables"); } _disposables = new List<IDisposable>(disposables); _count = _disposables.Count; } public void Add(IDisposable item) { if (item == null) { throw new ArgumentNullException("item"); } bool flag = false; lock (_gate) { flag = _disposed; if (!_disposed) { _disposables.Add(item); _count++; } } if (flag) { item.Dispose(); } } public bool Remove(IDisposable item) { if (item == null) { throw new ArgumentNullException("item"); } bool flag = false; lock (_gate) { if (!_disposed) { int num = _disposables.IndexOf(item); if (num >= 0) { flag = true; _disposables[num] = null; _count--; if (_disposables.Capacity > 64 && _count < _disposables.Capacity / 2) { List<IDisposable> disposables = _disposables; _disposables = new List<IDisposable>(_disposables.Capacity / 2); foreach (IDisposable item2 in disposables) { if (item2 != null) { _disposables.Add(item2); } } } } } } if (flag) { item.Dispose(); } return flag; } public void Dispose() { IDisposable[] array = null; lock (_gate) { if (!_disposed) { _disposed = true; array = _disposables.ToArray(); _disposables.Clear(); _count = 0; } } if (array != null) { IDisposable[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i]?.Dispose(); } } } public void Clear() { IDisposable[] array = null; lock (_gate) { array = _disposables.ToArray(); _disposables.Clear(); _count = 0; } IDisposable[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i]?.Dispose(); } } public bool Contains(IDisposable item) { if (item == null) { throw new ArgumentNullException("item"); } lock (_gate) { return _disposables.Contains(item); } } public void CopyTo(IDisposable[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0 || arrayIndex >= array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } lock (_gate) { List<IDisposable> list = new List<IDisposable>(); foreach (IDisposable item in list) { if (item != null) { list.Add(item); } } Array.Copy(list.ToArray(), 0, array, arrayIndex, array.Length - arrayIndex); } } public IEnumerator<IDisposable> GetEnumerator() { List<IDisposable> list = new List<IDisposable>(); lock (_gate) { foreach (IDisposable disposable in _disposables) { if (disposable != null) { list.Add(disposable); } } } return list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public sealed class DictionaryDisposable<TKey, TValue> : IDisposable, IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable where TValue : IDisposable { private bool isDisposed; private readonly Dictionary<TKey, TValue> inner; public TValue this[TKey key] { get { lock (inner) { return inner[key]; } } set { lock (inner) { if (isDisposed) { value.Dispose(); } if (TryGetValue(key, out var value2)) { value2.Dispose(); inner[key] = value; } else { inner[key] = value; } } } } public int Count { get { lock (inner) { return inner.Count; } } } public Dictionary<TKey, TValue>.KeyCollection Keys { get { throw new NotSupportedException("please use .Select(x => x.Key).ToArray()"); } } public Dictionary<TKey, TValue>.ValueCollection Values { get { throw new NotSupportedException("please use .Select(x => x.Value).ToArray()"); } } bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)inner).IsReadOnly; ICollection<TKey> IDictionary<TKey, TValue>.Keys { get { lock (inner) { return new List<TKey>(inner.Keys); } } } ICollection<TValue> IDictionary<TKey, TValue>.Values { get { lock (inner) { return new List<TValue>(inner.Values); } } } public DictionaryDisposable() { inner = new Dictionary<TKey, TValue>(); } public DictionaryDisposable(IEqualityComparer<TKey> comparer) { inner = new Dictionary<TKey, TValue>(comparer); } public void Add(TKey key, TValue value) { lock (inner) { if (isDisposed) { value.Dispose(); } else { inner.Add(key, value); } } } public void Clear() { lock (inner) { foreach (KeyValuePair<TKey, TValue> item in inner) { item.Value.Dispose(); } inner.Clear(); } } public bool Remove(TKey key) { lock (inner) { if (inner.TryGetValue(key, out var value)) { bool num = inner.Remove(key); if (num) { value.Dispose(); } return num; } return false; } } public bool ContainsKey(TKey key) { lock (inner) { return inner.ContainsKey(key); } } public bool TryGetValue(TKey key, out TValue value) { lock (inner) { return inner.TryGetValue(key, out value); } } public Dictionary<TKey, TValue>.Enumerator GetEnumerator() { lock (inner) { return new Dictionary<TKey, TValue>(inner).GetEnumerator(); } } public void GetObjectData(SerializationInfo info, StreamingContext context) { lock (inner) { ((ISerializable)inner).GetObjectData(info, context); } } public void OnDeserialization(object sender) { lock (inner) { ((IDeserializationCallback)inner).OnDeserialization(sender); } } void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) { Add(item.Key, item.Value); } bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) { lock (inner) { return ((ICollection<KeyValuePair<TKey, TValue>>)inner).Contains(item); } } void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { lock (inner) { ((ICollection<KeyValuePair<TKey, TValue>>)inner).CopyTo(array, arrayIndex); } } IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() { lock (inner) { return new List<KeyValuePair<TKey, TValue>>(inner).GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { throw new NotSupportedException(); } public void Dispose() { lock (inner) { if (isDisposed) { return; } isDisposed = true; foreach (KeyValuePair<TKey, TValue> item in inner) { item.Value.Dispose(); } inner.Clear(); } } } public static class Disposable { private class EmptyDisposable : IDisposable { public static EmptyDisposable Singleton = new EmptyDisposable(); private EmptyDisposable() { } public void Dispose() { } } private class AnonymousDisposable : IDisposable { private bool isDisposed; private readonly Action dispose; public AnonymousDisposable(Action dispose) { this.dispose = dispose; } public void Dispose() { if (!isDisposed) { isDisposed = true; dispose(); } } } private class AnonymousDisposable<T> : IDisposable { private bool isDisposed; private readonly T state; private readonly Action<T> dispose; public AnonymousDisposable(T state, Action<T> dispose) { this.state = state; this.dispose = dispose; } public void Dispose() { if (!isDisposed) { isDisposed = true; dispose(state); } } } public static readonly IDisposable Empty = EmptyDisposable.Singleton; public static IDisposable Create(Action disposeAction) { return new AnonymousDisposable(disposeAction); } public static IDisposable CreateWithState<TState>(TState state, Action<TState> disposeAction) { return new AnonymousDisposable<TState>(state, disposeAction); } } public static class DisposableExtensions { public static T AddTo<T>(this T disposable, ICollection<IDisposable> container) where T : IDisposable { if (disposable == null) { throw new ArgumentNullException("disposable"); } if (container == null) { throw new ArgumentNullException("container"); } container.Add(disposable); return disposable; } public static T AddTo<T>(this T disposable, GameObject gameObject) where T : IDisposable { if ((Object)(object)gameObject == (Object)null) { disposable.Dispose(); return disposable; } ObservableDestroyTrigger observableDestroyTrigger = gameObject.GetComponent<ObservableDestroyTrigger>(); if ((Object)(object)observableDestroyTrigger == (Object)null) { observableDestroyTrigger = gameObject.AddComponent<ObservableDestroyTrigger>(); } if (!observableDestroyTrigger.IsActivated && !observableDestroyTrigger.IsMonitoredActivate && !((Component)observableDestroyTrigger).gameObject.activeInHierarchy) { observableDestroyTrigger.IsMonitoredActivate = true; MainThreadDispatcher.StartEndOfFrameMicroCoroutine(MonitorTriggerHealth(observableDestroyTrigger, gameObject)); } observableDestroyTrigger.AddDisposableOnDestroy(disposable); return disposable; } private static IEnumerator MonitorTriggerHealth(ObservableDestroyTrigger trigger, GameObject targetGameObject) { do { yield return null; if (trigger.IsActivated) { yield break; } } while (!((Object)(object)targetGameObject == (Object)null)); trigger.ForceRaiseOnDestroy(); } public static T AddTo<T>(this T disposable, Component gameObjectComponent) where T : IDisposable { if ((Object)(object)gameObjectComponent == (Object)null) { disposable.Dispose(); return disposable; } return disposable.AddTo(gameObjectComponent.gameObject); } public static T AddTo<T>(this T disposable, ICollection<IDisposable> container, GameObject gameObject) where T : IDisposable { return disposable.AddTo(container).AddTo(gameObject); } public static T AddTo<T>(this T disposable, ICollection<IDisposable> container, Component gameObjectComponent) where T : IDisposable { return disposable.AddTo(container).AddTo(gameObjectComponent); } } public interface ICancelable : IDisposable { bool IsDisposed { get; } } public sealed class MultipleAssignmentDisposable : IDisposable, ICancelable { private static readonly BooleanDisposable True = new BooleanDisposable(isDisposed: true); private object gate = new object(); private IDisposable current; public bool IsDisposed { get { lock (gate) { return current == True; } } } public IDisposable Disposable { get { lock (gate) { return (current == True) ? UniRx.Disposable.Empty : current; } } set { bool flag = false; lock (gate) { flag = current == True; if (!flag) { current = value; } } if (flag) { value?.Dispose(); } } } public void Dispose() { IDisposable disposable = null; lock (gate) { if (current != True) { disposable = current; current = True; } } disposable?.Dispose(); } } public sealed class RefCountDisposable : ICancelable, IDisposable { private sealed class InnerDisposable : IDisposable { private RefCountDisposable _parent; private object parentLock = new object(); public InnerDisposable(RefCountDisposable parent) { _parent = parent; } public void Dispose() { RefCountDisposable parent; lock (parentLock) { parent = _parent; _parent = null; } parent?.Release(); } } private readonly object _gate = new object(); private IDisposable _disposable; private bool _isPrimaryDisposed; private int _count; public bool IsDisposed => _disposable == null; public RefCountDisposable(IDisposable disposable) { if (disposable == null) { throw new ArgumentNullException("disposable"); } _disposable = disposable; _isPrimaryDisposed = false; _count = 0; } public IDisposable GetDisposable() { lock (_gate) { if (_disposable == null) { return Disposable.Empty; } _count++; return new InnerDisposable(this); } } public void Dispose() { IDisposable disposable = null; lock (_gate) { if (_disposable != null && !_isPrimaryDisposed) { _isPrimaryDisposed = true; if (_count == 0) { disposable = _disposable; _disposable = null; } } } disposable?.Dispose(); } private void Release() { IDisposable disposable = null; lock (_gate) { if (_disposable != null) { _count--; if (_isPrimaryDisposed && _count == 0) { disposable = _disposable; _disposable = null; } } } disposable?.Dispose(); } } public static class Observable { private class ConnectableObservable<T> : IConnectableObservable<T>, IObservable<T> { private class Connection : IDisposable { private readonly ConnectableObservable<T> parent; private IDisposable subscription; public Connection(ConnectableObservable<T> parent, IDisposable subscription) { this.parent = parent; this.subscription = subscription; } public void Dispose() { lock (parent.gate) { if (subscription != null) { subscription.Dispose(); subscription = null; parent.connection = null; } } } } private readonly IObservable<T> source; private readonly ISubject<T> subject; private readonly object gate = new object(); private Connection connection; public ConnectableObservable(IObservable<T> source, ISubject<T> subject) { this.source = source.AsObservable(); this.subject = subject; } public IDisposable Connect() { lock (gate) { if (connection == null) { IDisposable subscription = source.Subscribe(subject); connection = new Connection(this, subscription); } return connection; } } public IDisposable Subscribe(IObserver<T> observer) { return subject.Subscribe(observer); } } private class EveryAfterUpdateInvoker : IEnumerator { private long count = -1L; private readonly IObserver<long> observer; private readonly CancellationToken cancellationToken; public object Current => null; public EveryAfterUpdateInvoker(IObserver<long> observer, CancellationToken cancellationToken) { this.observer = observer; this.cancellationToken = cancellationToken; } public bool MoveNext() { if (!cancellationToken.IsCancellationRequested) { if (count != -1) { observer.OnNext(count++); } else { count++; } return true; } return false; } public void Reset() { throw new NotSupportedException(); } } private static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, -1); private static readonly HashSet<Type> YieldInstructionTypes = new HashSet<Type> { typeof(WWW), typeof(WaitForEndOfFrame), typeof(WaitForFixedUpdate), typeof(WaitForSeconds), typeof(AsyncOperation), typeof(Coroutine) }; private static IObservable<T> AddRef<T>(IObservable<T> xs, RefCountDisposable r) { return Create((IObserver<T> observer) => new CompositeDisposable(r.GetDisposable(), xs.Subscribe(observer))); } public static IObservable<TSource> Scan<TSource>(this IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator) { return new ScanObservable<TSource>(source, accumulator); } public static IObservable<TAccumulate> Scan<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator) { return new ScanObservable<TSource, TAccumulate>(source, seed, accumulator); } public static IObservable<TSource> Aggregate<TSource>(this IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator) { return new AggregateObservable<TSource>(source, accumulator); } public static IObservable<TAccumulate> Aggregate<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator) { return new AggregateObservable<TSource, TAccumulate>(source, seed, accumulator); } public static IObservable<TResult> Aggregate<TSource, TAccumulate, TResult>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector) { return new AggregateObservable<TSource, TAccumulate, TResult>(source, seed, accumulator, resultSelector); } public static IConnectableObservable<T> Multicast<T>(this IObservable<T> source, ISubject<T> subject) { return new ConnectableObservable<T>(source, subject); } public static IConnectableObservable<T> Publish<T>(this IObservable<T> source) { return source.Multicast(new Subject<T>()); } public static IConnectableObservable<T> Publish<T>(this IObservable<T> source, T initialValue) { return source.Multicast(new BehaviorSubject<T>(initialValue)); } public static IConnectableObservable<T> PublishLast<T>(this IObservable<T> source) { return source.Multicast(new AsyncSubject<T>()); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source) { return source.Multicast(new ReplaySubject<T>()); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, IScheduler scheduler) { return source.Multicast(new ReplaySubject<T>(scheduler)); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, int bufferSize) { return source.Multicast(new ReplaySubject<T>(bufferSize)); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, int bufferSize, IScheduler scheduler) { return source.Multicast(new ReplaySubject<T>(bufferSize, scheduler)); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, TimeSpan window) { return source.Multicast(new ReplaySubject<T>(window)); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, TimeSpan window, IScheduler scheduler) { return source.Multicast(new ReplaySubject<T>(window, scheduler)); } public static IConnectableObservable<T> Replay<T>(this IObservable<T> source, int bufferSize, TimeSpan window, IScheduler scheduler) { return source.Multicast(new ReplaySubject<T>(bufferSize, window, scheduler)); } public static IObservable<T> RefCount<T>(this IConnectableObservable<T> source) { return new RefCountObservable<T>(source); } public static IObservable<T> Share<T>(this IObservable<T> source) { return source.Publish().RefCount(); } public static T Wait<T>(this IObservable<T> source) { return new Wait<T>(source, InfiniteTimeSpan).Run(); } public static T Wait<T>(this IObservable<T> source, TimeSpan timeout) { return new Wait<T>(source, timeout).Run(); } private static IEnumerable<IObservable<T>> CombineSources<T>(IObservable<T> first, IObservable<T>[] seconds) { yield return first; for (int i = 0; i < seconds.Length; i++) { yield return seconds[i]; } } public static IObservable<TSource> Concat<TSource>(params IObservable<TSource>[] sources) { if (sources == null) { throw new ArgumentNullException("sources"); } return new ConcatObservable<TSource>(sources); } public static IObservable<TSource> Concat<TSource>(this IEnumerable<IObservable<TSource>> sources) { if (sources == null) { throw new ArgumentNullException("sources"); } return new ConcatObservable<TSource>(sources); } public static IObservable<TSource> Concat<TSource>(this IObservable<IObservable<TSource>> sources) { return sources.Merge(1); } public static IObservable<TSource> Concat<TSource>(this IObservable<TSource> first, params IObservable<TSource>[] seconds) { if (first == null) { throw new ArgumentNullException("first"); } if (seconds == null) { throw new ArgumentNullException("seconds"); } if (first is ConcatObservable<TSource> concatObservable) { return concatObservable.Combine(seconds); } return CombineSources(first, seconds).Concat(); } public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources) { return sources.Merge(Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, IScheduler scheduler) { return new MergeObservable<TSource>(sources.ToObservable(scheduler), scheduler == Scheduler.CurrentThread); } public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent) { return sources.Merge(maxConcurrent, Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent, IScheduler scheduler) { return new MergeObservable<TSource>(sources.ToObservable(scheduler), maxConcurrent, scheduler == Scheduler.CurrentThread); } public static IObservable<TSource> Merge<TSource>(params IObservable<TSource>[] sources) { return Merge(Scheduler.DefaultSchedulers.ConstantTimeOperations, sources); } public static IObservable<TSource> Merge<TSource>(IScheduler scheduler, params IObservable<TSource>[] sources) { return new MergeObservable<TSource>(sources.ToObservable(scheduler), scheduler == Scheduler.CurrentThread); } public static IObservable<T> Merge<T>(this IObservable<T> first, params IObservable<T>[] seconds) { return CombineSources(first, seconds).Merge(); } public static IObservable<T> Merge<T>(this IObservable<T> first, IObservable<T> second, IScheduler scheduler) { return Merge<T>(scheduler, first, second); } public static IObservable<T> Merge<T>(this IObservable<IObservable<T>> sources) { return new MergeObservable<T>(sources, isRequiredSubscribeOnCurrentThread: false); } public static IObservable<T> Merge<T>(this IObservable<IObservable<T>> sources, int maxConcurrent) { return new MergeObservable<T>(sources, maxConcurrent, isRequiredSubscribeOnCurrentThread: false); } public static IObservable<TResult> Zip<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector) { return new ZipObservable<TLeft, TRight, TResult>(left, right, selector); } public static IObservable<IList<T>> Zip<T>(this IEnumerable<IObservable<T>> sources) { return Zip(sources.ToArray()); } public static IObservable<IList<T>> Zip<T>(params IObservable<T>[] sources) { return new ZipObservable<T>(sources); } public static IObservable<TR> Zip<T1, T2, T3, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, ZipFunc<T1, T2, T3, TR> resultSelector) { return new ZipObservable<T1, T2, T3, TR>(source1, source2, source3, resultSelector); } public static IObservable<TR> Zip<T1, T2, T3, T4, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, ZipFunc<T1, T2, T3, T4, TR> resultSelector) { return new ZipObservable<T1, T2, T3, T4, TR>(source1, source2, source3, source4, resultSelector); } public static IObservable<TR> Zip<T1, T2, T3, T4, T5, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, ZipFunc<T1, T2, T3, T4, T5, TR> resultSelector) { return new ZipObservable<T1, T2, T3, T4, T5, TR>(source1, source2, source3, source4, source5, resultSelector); } public static IObservable<TR> Zip<T1, T2, T3, T4, T5, T6, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, ZipFunc<T1, T2, T3, T4, T5, T6, TR> resultSelector) { return new ZipObservable<T1, T2, T3, T4, T5, T6, TR>(source1, source2, source3, source4, source5, source6, resultSelector); } public static IObservable<TR> Zip<T1, T2, T3, T4, T5, T6, T7, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, ZipFunc<T1, T2, T3, T4, T5, T6, T7, TR> resultSelector) { return new ZipObservable<T1, T2, T3, T4, T5, T6, T7, TR>(source1, source2, source3, source4, source5, source6, source7, resultSelector); } public static IObservable<TResult> CombineLatest<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector) { return new CombineLatestObservable<TLeft, TRight, TResult>(left, right, selector); } public static IObservable<IList<T>> CombineLatest<T>(this IEnumerable<IObservable<T>> sources) { return CombineLatest(sources.ToArray()); } public static IObservable<IList<TSource>> CombineLatest<TSource>(params IObservable<TSource>[] sources) { return new CombineLatestObservable<TSource>(sources); } public static IObservable<TR> CombineLatest<T1, T2, T3, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, CombineLatestFunc<T1, T2, T3, TR> resultSelector) { return new CombineLatestObservable<T1, T2, T3, TR>(source1, source2, source3, resultSelector); } public static IObservable<TR> CombineLatest<T1, T2, T3, T4, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, CombineLatestFunc<T1, T2, T3, T4, TR> resultSelector) { return new CombineLatestObservable<T1, T2, T3, T4, TR>(source1, source2, source3, source4, resultSelector); } public static IObservable<TR> CombineLatest<T1, T2, T3, T4, T5, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, CombineLatestFunc<T1, T2, T3, T4, T5, TR> resultSelector) { return new CombineLatestObservable<T1, T2, T3, T4, T5, TR>(source1, source2, source3, source4, source5, resultSelector); } public static IObservable<TR> CombineLatest<T1, T2, T3, T4, T5, T6, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, CombineLatestFunc<T1, T2, T3, T4, T5, T6, TR> resultSelector) { return new CombineLatestObservable<T1, T2, T3, T4, T5, T6, TR>(source1, source2, source3, source4, source5, source6, resultSelector); } public static IObservable<TR> CombineLatest<T1, T2, T3, T4, T5, T6, T7, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, CombineLatestFunc<T1, T2, T3, T4, T5, T6, T7, TR> resultSelector) { return new CombineLatestObservable<T1, T2, T3, T4, T5, T6, T7, TR>(source1, source2, source3, source4, source5, source6, source7, resultSelector); } public static IObservable<TResult> ZipLatest<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector) { return new ZipLatestObservable<TLeft, TRight, TResult>(left, right, selector); } public static IObservable<IList<T>> ZipLatest<T>(this IEnumerable<IObservable<T>> sources) { return ZipLatest(sources.ToArray()); } public static IObservable<IList<TSource>> ZipLatest<TSource>(params IObservable<TSource>[] sources) { return new ZipLatestObservable<TSource>(sources); } public static IObservable<TR> ZipLatest<T1, T2, T3, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, ZipLatestFunc<T1, T2, T3, TR> resultSelector) { return new ZipLatestObservable<T1, T2, T3, TR>(source1, source2, source3, resultSelector); } public static IObservable<TR> ZipLatest<T1, T2, T3, T4, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, ZipLatestFunc<T1, T2, T3, T4, TR> resultSelector) { return new ZipLatestObservable<T1, T2, T3, T4, TR>(source1, source2, source3, source4, resultSelector); } public static IObservable<TR> ZipLatest<T1, T2, T3, T4, T5, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, ZipLatestFunc<T1, T2, T3, T4, T5, TR> resultSelector) { return new ZipLatestObservable<T1, T2, T3, T4, T5, TR>(source1, source2, source3, source4, source5, resultSelector); } public static IObservable<TR> ZipLatest<T1, T2, T3, T4, T5, T6, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, ZipLatestFunc<T1, T2, T3, T4, T5, T6, TR> resultSelector) { return new ZipLatestObservable<T1, T2, T3, T4, T5, T6, TR>(source1, source2, source3, source4, source5, source6, resultSelector); } public static IObservable<TR> ZipLatest<T1, T2, T3, T4, T5, T6, T7, TR>(this IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, ZipLatestFunc<T1, T2, T3, T4, T5, T6, T7, TR> resultSelector) { return new ZipLatestObservable<T1, T2, T3, T4, T5, T6, T7, TR>(source1, source2, source3, source4, source5, source6, source7, resultSelector); } public static IObservable<T> Switch<T>(this IObservable<IObservable<T>> sources) { return new SwitchObservable<T>(sources); } public static IObservable<TResult> WithLatestFrom<TLeft, TRight, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, TRight, TResult> selector) { return new WithLatestFromObservable<TLeft, TRight, TResult>(left, right, selector); } public static IObservable<T[]> WhenAll<T>(params IObservable<T>[] sources) { if (sources.Length == 0) { return Return(new T[0]); } return new WhenAllObservable<T>(sources); } public static IObservable<Unit> WhenAll(params IObservable<Unit>[] sources) { if (sources.Length == 0) { return ReturnUnit(); } return new WhenAllObservable(sources); } public static IObservable<T[]> WhenAll<T>(this IEnumerable<IObservable<T>> sources) { if (sources is IObservable<T>[] sources2) { return WhenAll(sources2); } return new WhenAllObservable<T>(sources); } public static IObservable<Unit> WhenAll(this IEnumerable<IObservable<Unit>> sources) { if (sources is IObservable<Unit>[] sources2) { return WhenAll(sources2); } return new WhenAllObservable(sources); } public static IObservable<T> StartWith<T>(this IObservable<T> source, T value) { return new StartWithObservable<T>(source, value); } public static IObservable<T> StartWith<T>(this IObservable<T> source, Func<T> valueFactory) { return new StartWithObservable<T>(source, valueFactory); } public static IObservable<T> StartWith<T>(this IObservable<T> source, params T[] values) { return source.StartWith(Scheduler.DefaultSchedulers.ConstantTimeOperations, values); } public static IObservable<T> StartWith<T>(this IObservable<T> source, IEnumerable<T> values) { return source.StartWith(Scheduler.DefaultSchedulers.ConstantTimeOperations, values); } public static IObservable<T> StartWith<T>(this IObservable<T> source, IScheduler scheduler, T value) { return Return(value, scheduler).Concat(source); } public static IObservable<T> StartWith<T>(this IObservable<T> source, IScheduler scheduler, IEnumerable<T> values) { T[] array = values as T[]; if (array == null) { array = values.ToArray(); } return source.StartWith(scheduler, array); } public static IObservable<T> StartWith<T>(this IObservable<T> source, IScheduler scheduler, params T[] values) { return values.ToObservable(scheduler).Concat(source); } public static IObservable<T> Synchronize<T>(this IObservable<T> source) { return new SynchronizeObservable<T>(source, new object()); } public static IObservable<T> Synchronize<T>(this IObservable<T> source, object gate) { return new SynchronizeObservable<T>(source, gate); } public static IObservable<T> ObserveOn<T>(this IObservable<T> source, IScheduler scheduler) { return new ObserveOnObservable<T>(source, scheduler); } public static IObservable<T> SubscribeOn<T>(this IObservable<T> source, IScheduler scheduler) { return new SubscribeOnObservable<T>(source, scheduler); } public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, TimeSpan dueTime) { return new DelaySubscriptionObservable<T>(source, dueTime, Scheduler.DefaultSchedulers.TimeBasedOperations); } public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, TimeSpan dueTime, IScheduler scheduler) { return new DelaySubscriptionObservable<T>(source, dueTime, scheduler); } public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, DateTimeOffset dueTime) { return new DelaySubscriptionObservable<T>(source, dueTime, Scheduler.DefaultSchedulers.TimeBasedOperations); } public static IObservable<T> DelaySubscription<T>(this IObservable<T> source, DateTimeOffset dueTime, IScheduler scheduler) { return new DelaySubscriptionObservable<T>(source, dueTime, scheduler); } public static IObservable<T> Amb<T>(params IObservable<T>[] sources) { return Amb((IEnumerable<IObservable<T>>)sources); } public static IObservable<T> Amb<T>(IEnumerable<IObservable<T>> sources) { IObservable<T> observable = Never<T>(); foreach (IObservable<T> source in sources) { observable = observable.Amb(source); } return observable; } public static IObservable<T> Amb<T>(this IObservable<T> source, IObservable<T> second) { return new AmbObservable<T>(source, second); } public static IObservable<T> AsObservable<T>(this IObservable<T> source) { if (source == null) { throw new ArgumentNullException("source"); } if (source is AsObservableObservable<T>) { return source; } return new AsObservableObservable<T>(source); } public static IObservable<T> ToObservable<T>(this IEnumerable<T> source) { return source.ToObservable(Scheduler.DefaultSchedulers.Iteration); } public static IObservable<T> ToObservable<T>(this IEnumerable<T> source, IScheduler scheduler) { return new ToObservableObservable<T>(source, scheduler); } public static IObservable<TResult> Cast<TSource, TResult>(this IObservable<TSource> source) { return new CastObservable<TSource, TResult>(source); } public static IObservable<TResult> Cast<TSource, TResult>(this IObservable<TSource> source, TResult witness) { return new CastObservable<TSource, TResult>(source); } public static IObservable<TResult> OfType<TSource, TResult>(this IObservable<TSource> source) { return new OfTypeObservable<TSource, TResult>(source); } public static IObservable<TResult> OfType<TSource, TResult>(this IObservable<TSource> source, TResult witness) { return new OfTypeObservable<TSource, TResult>(source); } public static IObservable<Unit> AsUnitObservable<T>(this IObservable<T> source) { return new AsUnitObservableObservable<T>(source); } public static IObservable<Unit> AsSingleUnitObservable<T>(this IObservable<T> source) { return new AsSingleUnitObservableObservable<T>(source); } public static IObservable<T> Create<T>(Func<IObserver<T>, IDisposable> subscribe) { if (subscribe == null) { throw new ArgumentNullException("subscribe"); } return new CreateObservable<T>(subscribe); } public static IObservable<T> Create<T>(Func<IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread) { if (subscribe == null) { throw new ArgumentNullException("subscribe"); } return new CreateObservable<T>(subscribe, isRequiredSubscribeOnCurrentThread); } public static IObservable<T> CreateWithState<T, TState>(TState state, Func<TState, IObserver<T>, IDisposable> subscribe) { if (subscribe == null) { throw new ArgumentNullException("subscribe"); } return new CreateObservable<T, TState>(state, subscribe); } public static IObservable<T> CreateWithState<T, TState>(TState state, Func<TState, IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread) { if (subscribe == null) { throw new ArgumentNullException("subscribe"); } return new CreateObservable<T, TState>(state, subscribe, isRequiredSubscribeOnCurrentThread); } public static IObservable<T> CreateSafe<T>(Func<IObserver<T>, IDisposable> subscribe) { if (subscribe == null) { throw new ArgumentNullException("subscribe"); } return new CreateSafeObservable<T>(subscribe); } public static IObservable<T> CreateSafe<T>(Func<IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread) { if (subscribe == null) { throw new ArgumentNullException("subscribe"); } return new CreateSafeObservable<T>(subscribe, isRequiredSubscribeOnCurrentThread); } public static IObservable<T> Empty<T>() { return Empty<T>(Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<T> Empty<T>(IScheduler scheduler) { if (scheduler == Scheduler.Immediate) { return ImmutableEmptyObservable<T>.Instance; } return new EmptyObservable<T>(scheduler); } public static IObservable<T> Empty<T>(T witness) { return Empty<T>(Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<T> Empty<T>(IScheduler scheduler, T witness) { return Empty<T>(scheduler); } public static IObservable<T> Never<T>() { return ImmutableNeverObservable<T>.Instance; } public static IObservable<T> Never<T>(T witness) { return ImmutableNeverObservable<T>.Instance; } public static IObservable<T> Return<T>(T value) { return Return(value, Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<T> Return<T>(T value, IScheduler scheduler) { if (scheduler == Scheduler.Immediate) { return new ImmediateReturnObservable<T>(value); } return new ReturnObservable<T>(value, scheduler); } public static IObservable<Unit> Return(Unit value) { return ImmutableReturnUnitObservable.Instance; } public static IObservable<bool> Return(bool value) { if (!value) { return ImmutableReturnFalseObservable.Instance; } return ImmutableReturnTrueObservable.Instance; } public static IObservable<Unit> ReturnUnit() { return ImmutableReturnUnitObservable.Instance; } public static IObservable<T> Throw<T>(Exception error) { return Throw<T>(error, Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<T> Throw<T>(Exception error, T witness) { return Throw<T>(error, Scheduler.DefaultSchedulers.ConstantTimeOperations); } public static IObservable<T> Throw<T>(Exception error, IScheduler scheduler) { return new ThrowObservable<T>(error, scheduler); } public static IObservable<T> Throw<T>(Exception error, IScheduler scheduler, T witness) { return Throw<T>(error, scheduler); } public static IObservable<int> Range(int start, int count) { return Range(start, count, Scheduler.DefaultSchedulers.Iteration); } public static IObservable<int> Range(int start, int count, IScheduler scheduler) { return new RangeObservable(start, count, scheduler); } public static IObservable<T> Repeat<T>(T value) { return Repeat(value, Scheduler.DefaultSchedulers.Iteration); } public static IObservable<T> Repeat<T>(T value, IScheduler scheduler) { if (scheduler == null) { throw new ArgumentNullException("scheduler"); } return new RepeatObservable<T>(value, null, scheduler); } public static IObservable<T> Repeat<T>(T value, int repeatCount) { return Repeat(value, repeatCount, Scheduler.DefaultSchedulers.Iteration); } public static IObservable<T> Repeat<T>(T value, int repeatCount, IScheduler scheduler) { if (repeatCount < 0) { throw new ArgumentOutOfRangeException("repeatCount"); } if (scheduler == null) { throw new ArgumentNullException("scheduler"); } return new RepeatObservable<T>(value, repeatCount, scheduler); } public static IObservable<T> Repeat<T>(this IObservable<T> source) { return RepeatInfinite(source).Concat(); } private static IEnumerable<IObservable<T>> RepeatInfinite<T>(IObservable<T> source) { while (true) { yield return source; } } public static IObservable<T> RepeatSafe<T>(this IObservable<T> source) { return new RepeatSafeObservable<T>(RepeatInfinite(source), source.IsRequiredSubscribeOnCurrentThread()); } public static IObservable<T> Defer<T>(Func<IObservable<T>> observableFactory) { return new DeferObservable<T>(observableFactory); } public static IObservable<T> Start<T>(Func<T> function) { return new StartObservable<T>(function, null, Scheduler.DefaultSchedulers.AsyncConversions); } public static IObservable<T> Start<T>(Func<T> function, TimeSpan timeSpan) { return new StartObservable<T>(function, timeSpan, Scheduler.DefaultSchedulers.AsyncConversions); } public static IObservable<T> Start<T>(Func<T> function, IScheduler scheduler) { return new StartObservable<T>(function, null, scheduler); } public static IObservable<T> Start<T>(Func<T> function, TimeSpan timeSpan, IScheduler scheduler) { return new StartObservable<T>(function, timeSpan, scheduler); } public static IObservable<Unit> Start(Action action) { return new StartObservable<Unit>(action, null, Scheduler.DefaultSchedulers.AsyncConversions); } public static IObservable<Unit> Start(Action action, TimeSpan timeSpan) { return new StartObservable<Unit>(action, timeSpan, Scheduler.DefaultSchedulers.AsyncConversions); } public static IObservable<Unit> Start(Action action, IScheduler scheduler) { return new StartObservable<Unit>(action, null, scheduler); } public static IObservable<Unit> Start(Action action, TimeSpan timeSpan, IScheduler scheduler) { return new StartObservable<Unit>(action, timeSpan, scheduler); } public static Func<IObservable<T>> ToAsync<T>(Func<T> function) { return ToAsync(function, Scheduler.DefaultSchedulers.AsyncConversions); } public static Func<IObservable<T>> ToAsync<T>(Func<T> function, IScheduler scheduler) { return delegate { AsyncSubject<T> subject = new AsyncSubject<T>(); scheduler.Schedule(delegate { T val = default(T); try { val = function(); } catch (Exception error) { subject.OnError(error); return; } subject.OnNext(val); subject.OnCompleted(); }); return subject.AsObservable(); }; } public static Func<IObservable<Unit>> ToAsync(Action action) { return ToAsync(action, Scheduler.DefaultSchedulers.AsyncConversions); } public static Func<IObservable<Unit>> ToAsync(Action action, IScheduler scheduler) { return delegate { AsyncSubject<Unit> subject = new AsyncSubject<Unit>(); scheduler.Schedule(delegate { try { action(); } catch (Exception error) { subject.OnError(error); return; } subject.OnNext(Unit.Default); subject.OnCompleted(); }); return subject.AsObservable(); }; } public static IObservable<TR> Select<T, TR>(this IObservable<T> source, Func<T, TR> selector) { if (source is WhereObservable<T> whereObservable) { return whereObservable.CombineSelector(selector); } return new SelectObservable<T, TR>(source, selector); } public static IObservable<TR> Select<T, TR>(this IObservable<T> source, Func<T, int, TR> selector) { return new SelectObservable<T, TR>(source, selector); } public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, bool> predicate) { if (source is WhereObservable<T> whereObservable) { return whereObservable.CombinePredicate(predicate); } if (source is ISelect<T> select) { return select.CombinePredicate(predicate); } return new WhereObservable<T>(sou
NAudio.dll
Decompiled 8 months 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.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.8.0.0")] [module: UnverifiableCode] namespace NAudio { public enum Manufacturers { Microsoft = 1, Creative = 2, Mediavision = 3, Fujitsu = 4, Artisoft = 20, TurtleBeach = 21, Ibm = 22, Vocaltec = 23, Roland = 24, DspSolutions = 25, Nec = 26, Ati = 27, Wanglabs = 28, Tandy = 29, Voyetra = 30, Antex = 31, IclPS = 32, Intel = 33, Gravis = 34, Val = 35, Interactive = 36, Yamaha = 37, Everex = 38, Echo = 39, Sierra = 40, Cat = 41, Apps = 42, DspGroup = 43, Melabs = 44, ComputerFriends = 45, Ess = 46, Audiofile = 47, Motorola = 48, Canopus = 49, Epson = 50, Truevision = 51, Aztech = 52, Videologic = 53, Scalacs = 54, Korg = 55, Apt = 56, Ics = 57, Iteratedsys = 58, Metheus = 59, Logitech = 60, Winnov = 61, Ncr = 62, Exan = 63, Ast = 64, Willowpond = 65, Sonicfoundry = 66, Vitec = 67, Moscom = 68, Siliconsoft = 69, Supermac = 73, Audiopt = 74, Speechcomp = 76, Ahead = 77, Dolby = 78, Oki = 79, Auravision = 80, Olivetti = 81, Iomagic = 82, Matsushita = 83, Controlres = 84, Xebec = 85, Newmedia = 86, Nms = 87, Lyrrus = 88, Compusic = 89, Opti = 90, Adlacc = 91, Compaq = 92, Dialogic = 93, Insoft = 94, Mptus = 95, Weitek = 96, LernoutAndHauspie = 97, Qciar = 98, Apple = 99, Digital = 100, Motu = 101, Workbit = 102, Ositech = 103, Miro = 104, Cirruslogic = 105, Isolution = 106, Horizons = 107, Concepts = 108, Vtg = 109, Radius = 110, Rockwell = 111, Xyz = 112, Opcode = 113, Voxware = 114, NorthernTelecom = 115, Apicom = 116, Grande = 117, Addx = 118, Wildcat = 119, Rhetorex = 120, Brooktree = 121, Ensoniq = 125, Fast = 126, Nvidia = 127, Oksori = 128, Diacoustics = 129, Gulbransen = 130, KayElemetrics = 131, Crystal = 132, SplashStudios = 133, Quarterdeck = 134, Tdk = 135, DigitalAudioLabs = 136, Seersys = 137, Picturetel = 138, AttMicroelectronics = 139, Osprey = 140, Mediatrix = 141, Soundesigns = 142, Aldigital = 143, SpectrumSignalProcessing = 144, Ecs = 145, Amd = 146, Coredynamics = 147, Canam = 148, Softsound = 149, Norris = 150, Ddd = 151, Euphonics = 152, Precept = 153, CrystalNet = 154, Chromatic = 155, Voiceinfo = 156, Viennasys = 157, Connectix = 158, Gadgetlabs = 159, Frontier = 160, Viona = 161, Casio = 162, Diamondmm = 163, S3 = 164, FraunhoferIis = 172 } public class MmException : Exception { 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) { switch (controlType) { case MixerControlType.Equalizer: case MixerControlType.SingleSelect: case MixerControlType.Mux: case MixerControlType.MultipleSelect: case MixerControlType.Mixer: return true; default: 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 { private SFVersion verSoundFont; private string waveTableSoundEngine; private string bankName; private string dataROM; private string creationDate; private string author; private string targetProduct; private string copyright; private string comments; private string tools; private SFVersion verROM; public SFVersion SoundFontVersion => verSoundFont; public string WaveTableSoundEngine { get { return waveTableSoundEngine; } set { waveTableSoundEngine = value; } } public string BankName { get { return bankName; } set { bankName = value; } } public string DataROM { get { return dataROM; } set { dataROM = value; } } public string CreationDate { get { return creationDate; } set { creationDate = value; } } public string Author { get { return author; } set { author = value; } } public string TargetProduct { get { return targetProduct; } set { targetProduct = value; } } public string Copyright { get { return copyright; } set { copyright = value; } } public string Comments { get { return comments; } set { comments = value; } } public string Tools { get { return tools; } set { tools = value; } } public SFVersion ROMVersion { get { return verROM; } set { verROM = value; } } internal InfoChunk(RiffChunk chunk) { bool flag = false; bool flag2 = false; bool flag3 = 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; verSoundFont = nextSubChunk.GetDataAsStructure(new SFVersionBuilder()); break; case "isng": flag2 = true; waveTableSoundEngine = nextSubChunk.GetDataAsString(); break; case "INAM": flag3 = true; bankName = nextSubChunk.GetDataAsString(); break; case "irom": dataROM = nextSubChunk.GetDataAsString(); break; case "iver": verROM = 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 wavetable sound engine information"); } if (!flag3) { 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.Sfz { internal enum SfzParseState { Initial, Region } internal class Group { } internal class Region { } internal class SfzFileReader { public SfzFileReader(string fileName) { new StringBuilder(); using StreamReader streamReader = new StreamReader(fileName); List<Region> list = new List<Region>(); Region region = null; StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = new StringBuilder(); int num = 0; string text; while ((text = streamReader.ReadLine()) != null) { num++; int num2 = text.IndexOf('/'); if (num2 != -1) { text = text.Substring(num2); } for (int i = 0; i < text.Length; i++) { char c = text[i]; if (char.IsWhiteSpace(c)) { if (stringBuilder.Length != 0) { if (stringBuilder2.Length == 0) { throw new FormatException($"Invalid Whitespace Line {num}, Char {i}"); } stringBuilder2.Append(c); } } else { if (c == '=' || c != '<') { continue; } if (text.Substring(i).StartsWith("<region>")) { if (region != null) { list.Add(region); } region = new Region(); stringBuilder.Length = 0; stringBuilder2.Length = 0; i += 7; continue; } if (!text.Substring(i).StartsWith("<group>")) { throw new FormatException($"Unrecognised section Line {num}, Char {i}"); } if (region != null) { list.Add(region); } stringBuilder.Length = 0; stringBuilder2.Length = 0; region = null; new Group(); i += 6; } } } } } } 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 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 int inputStreams; private 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; private set; } public int Alignment { get; private set; } 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 strin