

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
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