The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of Clear Comms v1.4.0
plugins/ClearComms.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using ClearComms; using HarmonyLib; using Microsoft.CodeAnalysis; using NAudio.Wave; using NAudio.Wave.SampleProviders; using Photon.Voice; using Photon.Voice.Unity; using Unity.Mathematics; using UnityEngine; using UnityEngine.Localization; using Zorro.Settings; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ClearComms")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0+e4a7505563773067bec30e4807073ee06272d2ff")] [assembly: AssemblyProduct("ClearComms")] [assembly: AssemblyTitle("ClearComms")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.0.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] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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; } } } public class AudioResampler { public static float[] Resample(float[] inputSamples, int originalSampleRate, int newSampleRate) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (originalSampleRate == newSampleRate) { return inputSamples; } BufferedWaveProvider val = new BufferedWaveProvider(WaveFormat.CreateIeeeFloatWaveFormat(originalSampleRate, 1)); byte[] array = new byte[inputSamples.Length * 4]; Buffer.BlockCopy(inputSamples, 0, array, 0, array.Length); val.AddSamples(array, 0, array.Length); ISampleProvider val2 = WaveExtensionMethods.ToSampleProvider((IWaveProvider)(object)val); WdlResamplingSampleProvider val3 = new WdlResamplingSampleProvider(val2, newSampleRate); float[] array2 = new float[inputSamples.Length * 2]; int newSize = val3.Read(array2, 0, array2.Length); Array.Resize(ref array2, newSize); return array2; } } [HarmonyPatch(typeof(LocalizedText), "InitPlatformSpecificTables")] public static class LocalizedTextPatch { [HarmonyPrefix] public static void Prefix() { LocalizedText.MAIN_TABLE.Add("CLEARCOMMS_ENABLENOISEFILTERING", new List<string> { "(Clear Comms) ENABLE NOISE FILTERING", "(Clear Comms) ACTIVER LE FILTRAGE DU BRUIT", "(Clear Comms) ABILITA FILTRO RUMORE", "(Clear Comms) GERÄUSCHFILTERUNG AKTIVIEREN", "(Clear Comms) HABILITAR FILTRADO DE RUIDO", "(Clear Comms) ACTIVAR FILTRADO DE RUIDO", "(Clear Comms) ATIVAR FILTRAGEM DE RUÍDO", "(Clear Comms) ВКЛЮЧИТЬ ФИЛЬТР ШУМА", "(Clear Comms) Увімкнути фільтрування шуму", "(Clear Comms) 启用噪声过滤", "(Clear Comms) 啟用雜訊過濾功能", "(Clear Comms) ノイズフィルタリングを有効にする", "(Clear Comms) 소음 필터링 활성화", "(Clear Comms) WŁĄCZ FILTR SZUMÓW", "(Clear Comms) GÜRÜLTÜ FİLTRELEMESİNİ ETKİNLEŞTİR" }); LocalizedText.MAIN_TABLE.Add("CLEARCOMMS_NOISEFILTERINGSTRENGTH", new List<string> { "(Clear Comms) NOISE FILTERING STRENGTH", "(Clear Comms) PUISSANCE DE FILTRAGE DU BRUIT", "(Clear Comms) POTENZA DI FILTRAGGIO DEL RUMORE", "(Clear Comms) GERÄUSCHFILTERSTÄRKE", "(Clear Comms) INTENSIDAD DEL FILTRO DE RUIDO", "(Clear Comms) INTENSIDAD DEL FILTRADO DE RUIDO", "(Clear Comms) INTENSIDADE DA FILTRAGEM DE RUÍDO", "(Clear Comms) СИЛА ФИЛЬТРАЦИИ ШУМА", "(Clear Comms) СИЛА ФІЛЬТРУВАННЯ ШУМУ", "(Clear Comms) 噪声滤波强度", "(Clear Comms) 噪音過濾強度", "(Clear Comms) ノイズフィルタリング強度", "(Clear Comms) 노이즈 필터링 강도", "(Clear Comms) SILNIK FILTRUJĄCY HAŁAS", "(Clear Comms) GÜRÜLTÜ FİLTRELEME GÜCÜ" }); LocalizedText.MAIN_TABLE.Add("CLEARCOMMS_PREVIEWMICROPHONEOUTPUT", new List<string> { "(Clear Comms) PREVIEW MICROPHONE OUTPUT", "(Clear Comms) APERÇU SORTIE MICROPHONE", "(Clear Comms) ANTEPRIMA USCITA MICROFONO", "(Clear Comms) VORSCHAU MIKROFON-AUSGANG", "(Clear Comms) VISTA PREVIA DE LA SALIDA DEL MICRÓFONO", "(Clear Comms) VISUALIZAR SALIDA DE MICRÓFONO", "(Clear Comms) VISUALIZAÇÃO DA SAÍDA DO MICROFONE", "(Clear Comms) ПРЕДВАРИТЕЛЬНЫЙ ПРОСЛУШИВАНИЕ ВЫХОДА МИК", "(Clear Comms) ПЕРЕДПРЕГЛЯД ВИХІД МІКРОФОНА", "(Clear Comms) 预览麦克风输出", "(Clear Comms) 預覽麥克風輸出", "(Clear Comms) マイク出力のプレビュー", "(Clear Comms) 마이크 출력 미리보기", "(Clear Comms) PRZEGLĄD WYJŚCIA MIKROFONU", "(Clear Comms) MİKROFON ÇIKIŞINI ÖN İZLE" }); Plugin.Log.LogInfo((object)"[ClearComms] Inserted custom text localization strings"); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public static class SettingsHandlerPatch { [HarmonyPostfix] public static void Postfix(SettingsHandler __instance) { __instance.AddSetting((Setting)(object)new NoiseFilteringSetting()); __instance.AddSetting((Setting)(object)new NoiseFilteringStrengthSetting()); __instance.AddSetting((Setting)(object)new PreviewMicrophoneOutputSetting()); Plugin.Log.LogInfo((object)"[ClearComms] Injected custom settings"); } } public class NoiseFilteringSetting : CustomLocalizedOffOnSetting, IExposedSetting { public override void ApplyValue() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 OffOnMode val = (OffOnMode)((EnumSetting<OffOnMode>)(object)this).GetValue(); if ((int)val != 0) { if ((int)val == 1) { RNNNoiseProcessorFloat.GlobalEnable(); RNNNoiseProcessorShort.GlobalEnable(); } else { Plugin.Log.LogWarning((object)"Unknown value for NoiseFilteringSetting. Defaulting to off."); RNNNoiseProcessorFloat.GlobalDisable(); RNNNoiseProcessorShort.GlobalDisable(); } } else { RNNNoiseProcessorFloat.GlobalDisable(); RNNNoiseProcessorShort.GlobalDisable(); } } protected override OffOnMode GetDefaultValue() { return (OffOnMode)1; } public override List<LocalizedString> GetLocalizedChoices() { return null; } public string GetDisplayName() { return "CLEARCOMMS_ENABLENOISEFILTERING"; } public string GetCategory() { return "Audio"; } } public class PreviewMicrophoneOutputSetting : CustomLocalizedOffOnSetting, IExposedSetting { public override void ApplyValue() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 OffOnMode val = (OffOnMode)((EnumSetting<OffOnMode>)(object)this).GetValue(); if ((int)val != 0) { if ((int)val == 1) { Recorder_RestartRecording_PlaybackPatch.enableDebugEchoMode(); } else { Plugin.Log.LogWarning((object)"Unknown value for PreviewMicrophoneOutputSetting. Defaulting to disable DebugEchoMode."); Recorder_RestartRecording_PlaybackPatch.disableDebugEchoMode(); } } else { Recorder_RestartRecording_PlaybackPatch.disableDebugEchoMode(); } Traverse val2 = Traverse.Create(typeof(VoiceClientHandler)); Recorder value = val2.Field("m_LocalRecorder").GetValue<Recorder>(); if (value != null) { Plugin.Log.LogInfo((object)"Recorder already exists--restarting recording."); value.RestartRecording(); } } protected override OffOnMode GetDefaultValue() { return (OffOnMode)0; } public override List<LocalizedString> GetLocalizedChoices() { return null; } public string GetDisplayName() { return "CLEARCOMMS_PREVIEWMICROPHONEOUTPUT"; } public string GetCategory() { return "Audio"; } } public class NoiseFilteringStrengthSetting : FloatSetting, IExposedSetting { public override void ApplyValue() { RNNoise.GlobalNoiseFilteringStrength = ((FloatSetting)this).Value; } protected override float GetDefaultValue() { return 1f; } protected override float2 GetMinMaxValue() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return new float2(0f, 1f); } public string GetDisplayName() { return "CLEARCOMMS_NOISEFILTERINGSTRENGTH"; } public string GetCategory() { return "Audio"; } } 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 ClearComms { [BepInPlugin("ClearComms", "ClearComms", "1.4.0")] public class Plugin : BaseUnityPlugin { private Harmony _harmony; public const string Id = "ClearComms"; internal static ManualLogSource Log { get; private set; } public static string Name => "ClearComms"; public static string Version => "1.4.0"; private void Awake() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)("Plugin " + Name + " loading...")); _harmony = new Harmony("ClearComms"); _harmony.PatchAll(); Log.LogInfo((object)("Plugin " + Name + " finished loading.")); } private void OnDestroy() { _harmony.UnpatchSelf(); Log.LogInfo((object)("Plugin " + Name + " unloaded.")); } } [HarmonyPatch(typeof(Recorder), "RestartRecording")] public static class Recorder_RestartRecording_PlaybackPatch { public static int sampleRate = 48000; private static bool debugEchoMode = false; [HarmonyPrefix] public static void Prefix(Recorder __instance) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected I4, but got Unknown if (!((Object)(object)__instance == (Object)null)) { __instance.DebugEchoMode = debugEchoMode; WebRtcAudioDsp val = ((Component)__instance).gameObject.GetComponent<WebRtcAudioDsp>(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogDebug((object)"Added WebRtcAudioDsp component to Recorder game object"); val = ((Component)__instance).gameObject.AddComponent<WebRtcAudioDsp>(); } val.AGC = false; val.NoiseSuppression = false; val.AEC = false; Plugin.Log.LogDebug((object)"Disabled WebRTC native filtering (AGC, NoiseSuppression, and AEC)"); sampleRate = (int)__instance.SamplingRate; Plugin.Log.LogDebug((object)$"Set static (global) sample rate to {sampleRate}"); } } public static void enableDebugEchoMode() { debugEchoMode = true; } public static void disableDebugEchoMode() { debugEchoMode = false; } } [HarmonyPatch] public static class VoiceClientHijackShortType { public static MethodInfo TargetMethod() { return typeof(VoiceClient).GetMethod("CreateLocalVoiceAudio").MakeGenericMethod(typeof(short)); } [HarmonyPostfix] public static void Postfix(ref LocalVoiceAudio<short> __result) { Plugin.Log.LogInfo((object)"[ClearComms] Injecting RNNoise pre processing stage, short type"); ((LocalVoiceFramed<short>)(object)__result).AddPreProcessor(new IProcessor<short>[1] { new RNNNoiseProcessorShort() }); } } [HarmonyPatch] public static class VoiceClientHijackFloatType { public static MethodInfo TargetMethod() { return typeof(VoiceClient).GetMethod("CreateLocalVoiceAudio").MakeGenericMethod(typeof(float)); } [HarmonyPostfix] public static void Postfix(ref LocalVoiceAudio<float> __result) { Plugin.Log.LogInfo((object)"[ClearComms] Injecting RNNoise pre processing stage, float type"); ((LocalVoiceFramed<float>)(object)__result).AddPreProcessor(new IProcessor<float>[1] { new RNNNoiseProcessorFloat() }); } } public class RNNNoiseProcessorFloat : IProcessor<float>, IDisposable { private RNNoise rnnoiseInstance; private static bool globalEnable = true; public RNNNoiseProcessorFloat() { Plugin.Log.LogDebug((object)"Created new RNNoiseProcessorFloat object"); rnnoiseInstance = new RNNoise(); } public float[] Process(float[] buf) { if (!globalEnable) { return buf; } return rnnoiseInstance.ProcessSamples(buf); } public void Dispose() { Plugin.Log.LogDebug((object)"Disposing RNNoiseProcessorFloat"); rnnoiseInstance.Dispose(); } public static void GlobalEnable() { Plugin.Log.LogDebug((object)"RNNoiseProcessorFloat globalEnable set to true"); globalEnable = true; } public static void GlobalDisable() { Plugin.Log.LogDebug((object)"RNNoiseProcessorFloat globalEnable set to false"); globalEnable = false; } } public class RNNNoiseProcessorShort : IProcessor<short>, IDisposable { private RNNoise rnnoiseInstance; private static bool globalEnable = true; public RNNNoiseProcessorShort() { Plugin.Log.LogDebug((object)"Created new RNNoiseProcessorShort object"); rnnoiseInstance = new RNNoise(); } public short[] Process(short[] buf) { if (!globalEnable) { return buf; } float[] array = new float[buf.Length]; for (int i = 0; i < buf.Length; i++) { array[i] = (float)buf[i] / 32767f; } array = rnnoiseInstance.ProcessSamples(array); short[] array2 = new short[buf.Length]; for (int j = 0; j < buf.Length; j++) { array2[j] = (short)(array[j] * 32767f); } return array2; } public void Dispose() { Plugin.Log.LogDebug((object)"Disposing RNNoiseProcessorShort"); rnnoiseInstance.Dispose(); } public static void GlobalEnable() { Plugin.Log.LogDebug((object)"RNNoiseProcessorShort globalEnable set to true"); globalEnable = true; } public static void GlobalDisable() { Plugin.Log.LogDebug((object)"RNNoiseProcessorShort globalEnable set to false"); globalEnable = false; } } public class RNNoise : IDisposable { private IntPtr denoiseState; public static float GlobalNoiseFilteringStrength { get; set; } = 1f; [DllImport("librnnoise-0.dll", CallingConvention = CallingConvention.Cdecl)] private static extern int rnnoise_get_size(); public static int get_size() { return rnnoise_get_size(); } [DllImport("librnnoise-0.dll", CallingConvention = CallingConvention.Cdecl)] private static extern int rnnoise_get_frame_size(); public static int get_frame_size() { return rnnoise_get_frame_size(); } [DllImport("librnnoise-0.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr rnnoise_create(IntPtr model); [DllImport("librnnoise-0.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void rnnoise_destroy(IntPtr st); [DllImport("librnnoise-0.dll", CallingConvention = CallingConvention.Cdecl)] private unsafe static extern float rnnoise_process_frame(IntPtr st, float* outFrame, float* inFrame); public RNNoise() { denoiseState = rnnoise_create(IntPtr.Zero); } public void Dispose() { Plugin.Log.LogDebug((object)"Disposing RNNoise object"); rnnoise_destroy(denoiseState); } public float[] ProcessSamples(float[] buf) { int frame_size = get_frame_size(); int num = 0; int num2 = buf.Length; float[] array = new float[buf.Length]; while (num2 > 0) { float[] array2 = new float[frame_size]; if (num2 < frame_size) { for (int i = 0; i < num2; i++) { array2[i] = buf[i + num]; } for (int j = num2; j < frame_size; j++) { array2[j] = 0f; } } else { for (int k = 0; k < frame_size; k++) { array2[k] = buf[k + num]; } } float[] array3 = ProcessFrame(array2); for (int l = 0; l < ((num2 < frame_size) ? num2 : frame_size); l++) { array[l + num] = array3[l]; } num += frame_size; num2 -= frame_size; } for (int m = 0; m < buf.Length; m++) { array[m] = Mathf.Lerp(buf[m], array[m], GlobalNoiseFilteringStrength); } return array; } public unsafe float[] ProcessFrame(float[] input) { int frame_size = get_frame_size(); if (input.Length != frame_size) { throw new ArgumentException($"Input frame size does not match RNNoise frame length of {frame_size} floats!"); } for (int i = 0; i < frame_size; i++) { input[i] *= 32767f; } float[] array = new float[frame_size]; fixed (float* inFrame = input) { fixed (float* outFrame = array) { float num = rnnoise_process_frame(denoiseState, outFrame, inFrame); } } for (int j = 0; j < frame_size; j++) { array[j] /= 32767f; array[j] = MathF.Max(-1f, MathF.Min(1f, array[j] * 1.2f)); } return array; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }