using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AIGraph;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Dissonance;
using Dissonance.Audio.Capture;
using Dissonance.Audio.Playback;
using Dissonance.Config;
using ExplodesProxChat.Effects;
using ExplodesProxChat.Effects.Audio;
using ExplodesProxChat.Effects.Reverb;
using ExplodesProxChat.Effects.Reverb.Line;
using ExplodesProxChat.Effects.Reverb.Line.Presets;
using ExplodesProxChat.Noise;
using ExplodesProxChat.Spatialization;
using ExplodesProxChat.Spatialization.Fading;
using ExplodesProxChat.Voice;
using ExplodesProxChat.Voice.Handler;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ExplodesProxChat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e8444e2946601af0526eac50242e635287b0bb00")]
[assembly: AssemblyProduct("ExplodesProxChat")]
[assembly: AssemblyTitle("ExplodesProxChat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
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;
}
}
}
namespace ExplodesProxChat
{
[BepInPlugin("Explode3.ExplodesProxChat", "ExplodesProxChat", "1.0.0")]
public class ExplodesProxChat : BasePlugin
{
public static ExplodesProxChat Instance;
private DistanceSpatializationStrategy sameRootStrategy;
private DistanceSpatializationStrategy diffRootStrategy;
private ConfigEntry<float> _nothingValue;
private ConfigEntry<float> _sneakingValue;
private ConfigEntry<float> _walkingValue;
private ConfigEntry<float> _runningValue;
private ConfigEntry<float> _sameRoomDistance;
private ConfigEntry<float> _sameRoomRolloff;
private ConfigEntry<float> _diffRoomDistance;
private ConfigEntry<float> _diffRoomRolloff;
public ProxChatImpl Impl { get; private set; }
public ExplodesProxChat()
{
Instance = this;
}
public unsafe override void Load()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 0, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ProxChat loaded, now... will it work? >_<");
}
log.LogInfo(val);
Harmony.CreateAndPatchAll(typeof(Patches), "ExplodesProxChat");
INativeClassStruct val2 = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore.GetNativeClassPointer(typeof(IDissonancePlayer)));
RegisterTypeOptions val3 = new RegisterTypeOptions();
val3.set_Interfaces(new Il2CppInterfaceCollection((IEnumerable<INativeClassStruct>)(object)new INativeClassStruct[1] { val2 }));
RegisterTypeOptions val4 = val3;
((BasePlugin)this).Log.LogInfo((object)"Trying to inject ProxChatPlayer");
ClassInjector.RegisterTypeInIl2Cpp(typeof(ProxChatPlayer), val4);
((BasePlugin)this).Log.LogInfo((object)"Trying to inject VolumeUpdateComponent");
ClassInjector.RegisterTypeInIl2Cpp(typeof(VolumeUpdateComponent));
((BasePlugin)this).Log.LogInfo((object)"Trying to inject LocalTransformComponent");
ClassInjector.RegisterTypeInIl2Cpp(typeof(LocalTransformComponent));
((BasePlugin)this).Log.LogInfo((object)("Trying to inject CustomReverbFilter: " + typeof(ReverbVoiceFilterScript)));
ClassInjector.RegisterTypeInIl2Cpp(typeof(ReverbVoiceFilterScript));
((BasePlugin)this).Log.LogInfo((object)"Adding ProxChatImpl");
Impl = ((BasePlugin)this).AddComponent<ProxChatImpl>();
ConfigEntry<bool> reverbEntry = ((BasePlugin)this).Config.Bind<bool>("Effects", "Reverb", true, "Enable reverb effect");
Impl.VoiceEffectsManager.Reverb.Enable = reverbEntry.Value;
reverbEntry.SettingChanged += delegate
{
Impl.VoiceEffectsManager.Reverb.Enable = reverbEntry.Value;
};
_nothingValue = ((BasePlugin)this).Config.Bind<float>("Noises", "Nothing DB", -18f, "Decibel value at which you are ignored by sleepers.");
_sneakingValue = ((BasePlugin)this).Config.Bind<float>("Noises", "Sneaking DB", -26f, "Decibel value at which you count as sneaking for sleepers.");
_walkingValue = ((BasePlugin)this).Config.Bind<float>("Noises", "Walking DB", -21f, "Decibel value at which you count as walking for sleepers.");
_runningValue = ((BasePlugin)this).Config.Bind<float>("Noises", "Running DB", -16f, "Decibel value at which you count as running for sleepers.");
SleeperWakeUpToggle();
_sameRoomDistance = ((BasePlugin)this).Config.Bind<float>("Distances", "Distance: Same room", 12f, "Distance value");
_sameRoomRolloff = ((BasePlugin)this).Config.Bind<float>("Distances", "Rolloff: Same room", 5f, "Rolloff value");
_diffRoomDistance = ((BasePlugin)this).Config.Bind<float>("Distances", "Distance: Different room", 1f, "Distance value");
_diffRoomRolloff = ((BasePlugin)this).Config.Bind<float>("Distances", "Rolloff: Different room", 1.5f, "Rolloff value");
sameRootStrategy = new DistanceSpatializationStrategy(new ExponentialFalloffAttenuationFormula(_sameRoomDistance.Value, _sameRoomRolloff.Value));
diffRootStrategy = new DistanceSpatializationStrategy(new ExponentialFalloffAttenuationFormula(_diffRoomDistance.Value, _diffRoomRolloff.Value));
_sameRoomDistance.SettingChanged += EventSameRoom;
_sameRoomRolloff.SettingChanged += EventSameRoom;
_diffRoomDistance.SettingChanged += EventDiffRoom;
_diffRoomRolloff.SettingChanged += EventDiffRoom;
void EventDiffRoom(object? o, EventArgs eventArgs)
{
diffRootStrategy.Formula = new ExponentialFalloffAttenuationFormula(_diffRoomDistance.Value, _diffRoomRolloff.Value);
}
void EventSameRoom(object? o, EventArgs eventArgs)
{
sameRootStrategy.Formula = new ExponentialFalloffAttenuationFormula(_sameRoomDistance.Value, _sameRoomRolloff.Value);
}
}
private void SleeperWakeUpToggle()
{
ConfigEntry<bool> configEntry = ((BasePlugin)this).Config.Bind<bool>("Toggles", "Wake up sleepers", false, "Whether talking wakes up sleepers");
EnableSleepers(configEntry.Value);
configEntry.SettingChanged += delegate
{
EnableSleepers(configEntry.Value);
};
_nothingValue.SettingChanged += delegate
{
EnableSleepers(configEntry.Value);
};
_sneakingValue.SettingChanged += delegate
{
EnableSleepers(configEntry.Value);
};
_walkingValue.SettingChanged += delegate
{
EnableSleepers(configEntry.Value);
};
_runningValue.SettingChanged += delegate
{
EnableSleepers(configEntry.Value);
};
}
private void EnableSleepers(bool enable)
{
if (enable)
{
Impl.WakeUpSleepers(new NoiseLevel[4]
{
new NoiseLevel(_nothingValue.Value, (NoiseType)0),
new NoiseLevel(_sneakingValue.Value, (NoiseType)2),
new NoiseLevel(_walkingValue.Value, (NoiseType)3),
new NoiseLevel(_runningValue.Value, (NoiseType)4)
});
}
else
{
Impl.WakeUpSleepers(null);
}
}
public ProximityVoiceHandler CreatePair(PlayerAgent local, PlayerAgent player, DissonanceComms comms)
{
return new ProximityVoiceHandler(new PlayerAgentsPair(local, player), comms, new RoomSpatializationStrategy(sameRootStrategy, diffRootStrategy));
}
[HideFromIl2Cpp]
public void Reload()
{
Debug.Log(Object.op_Implicit("Reloading config from file..."));
((BasePlugin)this).Config.Reload();
}
[HideFromIl2Cpp]
public bool IsReload()
{
return Input.GetKeyDown((KeyCode)282);
}
}
public class Patches
{
[HarmonyPatch(typeof(DissonanceComms), "Start")]
[HarmonyPrefix]
public static void DissonanceCommsStartPatch(DissonanceComms __instance)
{
__instance.LocalPlayerName = SteamManager.LocalPlayerName;
}
[HarmonyPatch(typeof(SNet_SyncManager), "OnPlayerSpawnedAgent")]
[HarmonyPostfix]
public static void AddedPlayer(SNet_Player player)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
PlayerAgent local = new PlayerAgent(((Il2CppObjectBase)player.PlayerAgent).Pointer);
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Player joined");
if (player.IsLocal)
{
ExplodesProxChat.Instance.Impl.VoicePlayerManager.Start(local);
}
else
{
ExplodesProxChat.Instance.Impl.VoicePlayerManager.Joined(ProxChatImpl.GetAgentOfName(player.GetName()));
}
}
[HarmonyPatch(typeof(PlayerManager), "OnPlayerDespawned")]
[HarmonyPrefix]
public static void RemovePlayer(SNet_Player snetPlayer)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Player removed");
if (snetPlayer.IsLocal)
{
ExplodesProxChat.Instance.Impl.VoicePlayerManager.Reset();
}
else
{
ExplodesProxChat.Instance.Impl.VoicePlayerManager.Left(snetPlayer.GetName());
}
}
[HarmonyPatch(typeof(SNet_SyncManager), "OnResetSession")]
[HarmonyPrefix]
public static void ResetSession()
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Session reset");
ExplodesProxChat.Instance.Impl.VoicePlayerManager.Reset();
}
}
public class ProxChatImpl : MonoBehaviour
{
private const bool PositionalInLobby = false;
public readonly VoicePlayerManager VoicePlayerManager = new VoicePlayerManager();
private VoiceChatNoiseMaker? _voiceChatNoiseMaker;
private DissonanceComms _comms;
public VoiceEffectsManager VoiceEffectsManager { get; } = new VoiceEffectsManager();
public void Start()
{
_comms = Object.FindObjectOfType<DissonanceComms>();
VoiceSettings.Instance.VadSensitivity = (VadSensitivityLevels)1;
VoiceSettings.Instance.DenoiseAmount = (NoiseSuppressionLevels)1;
VoiceSettings.Instance.Quality = (AudioQuality)2;
VoiceSettings.Instance.FrameSize = (FrameSize)2;
VoiceSettings.Instance.ForwardErrorCorrection = false;
VoiceSettings.Instance.AecSuppressionAmount = (AecSuppressionLevels)1;
VoiceSettings.Instance.AecmRoutingMode = (AecmRoutingMode)0;
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("Using microphone: " + _comms.MicrophoneName));
VoiceEffectsManager.Start();
_comms.OnPlayerStartedSpeaking += Action<VoicePlayerState>.op_Implicit((Action<VoicePlayerState>)delegate(VoicePlayerState s)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("Speaking currently " + s.Name));
});
}
[HideFromIl2Cpp]
public void WakeUpSleepers(NoiseLevel[]? levels)
{
if (levels == null)
{
_voiceChatNoiseMaker = null;
}
else
{
_voiceChatNoiseMaker = new VoiceChatNoiseMaker(_comms, new NoiseLevels(levels, (NoiseType)8));
}
}
public void Update()
{
if (ExplodesProxChat.Instance.IsReload())
{
ExplodesProxChat.Instance.Reload();
}
VoiceEffectsManager?.Update();
_voiceChatNoiseMaker?.Update();
}
public static bool InLevel(PlayerAgent playerAgent)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Invalid comparison between Unknown and I4
if (((Component)playerAgent).gameObject.activeInHierarchy && playerAgent.IsEnabled && (int)GameStateManager.CurrentStateName == 10)
{
return ((Agent)playerAgent).CourseNode != null;
}
return false;
}
public static bool CanTrack(PlayerAgent playerAgent)
{
return InLevel(playerAgent);
}
public static PlayerAgent GetAgentOfName(string voiceName)
{
Enumerator<PlayerAgent> enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator();
while (enumerator.MoveNext())
{
PlayerAgent current = enumerator.Current;
if (current.PlayerName == voiceName)
{
return current;
}
}
throw new ArgumentException("Player with name " + voiceName + " is not in level");
}
public static PlayerAgent? TryGetAgentOfName(string voiceName)
{
Enumerator<PlayerAgent> enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator();
while (enumerator.MoveNext())
{
PlayerAgent current = enumerator.Current;
if (current.PlayerName == voiceName)
{
return current;
}
}
return null;
}
}
}
namespace ExplodesProxChat.Voice
{
public class LocalTransformComponent : MonoBehaviour
{
public Transform transform;
public PlayerAgent PlayerAgent;
public void Update()
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)transform == (Object)null) && !((Object)(object)PlayerAgent == (Object)null))
{
if (!CanTrack())
{
transform.SetPositionAndRotation(default(Vector3), Quaternion.identityQuaternion);
return;
}
Quaternion val = Quaternion.LookRotation(((Agent)PlayerAgent).TargetLookDir, new Vector3(0f, 1f, 0f));
transform.SetPositionAndRotation(((Agent)PlayerAgent).EyePosition, val);
}
}
private bool CanTrack()
{
return ProxChatImpl.CanTrack(PlayerAgent);
}
}
public class ProxChatPlayer : MonoBehaviour
{
public bool IsLocalPlayer;
public PlayerAgent Player;
public Quaternion Rotation
{
get
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
if (!CanTrack())
{
return Quaternion.identityQuaternion;
}
return Quaternion.LookRotation(((Agent)Player).TargetLookDir, new Vector3(0f, 1f, 0f));
}
}
public Vector3 Position
{
get
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (!CanTrack())
{
return default(Vector3);
}
return ((Agent)Player).EyePosition;
}
}
public string PlayerId => Player.PlayerName;
public bool IsTracking => true;
public NetworkPlayerType Type
{
get
{
if (IsLocalPlayer)
{
return (NetworkPlayerType)1;
}
return (NetworkPlayerType)2;
}
}
public ProxChatPlayer(IntPtr pointer)
: base(pointer)
{
}
public ProxChatPlayer()
: base(ClassInjector.DerivedConstructorPointer<ProxChatPlayer>())
{
ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
}
private bool CanTrack()
{
return ProxChatImpl.CanTrack(Player);
}
}
public class VoicePlayerManager
{
private readonly Dictionary<string, ProximityVoiceHandler> _proxVoiceDict = new Dictionary<string, ProximityVoiceHandler>();
private readonly List<PlayerAgent> _toBeCreated = new List<PlayerAgent>();
private GameObject _fakeLocalGameObject;
private PlayerAgent _local;
private LocalTransformComponent _localTransformComponent;
private bool _managerStarted;
private DissonanceComms comms;
public void Start(PlayerAgent local)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
if (_managerStarted)
{
return;
}
_fakeLocalGameObject = new GameObject("Fake local player");
comms = Object.FindObjectOfType<DissonanceComms>();
LeaveAllRooms();
SetupLocalPlayer(local);
_local = local;
_managerStarted = true;
foreach (PlayerAgent item in _toBeCreated)
{
Joined(item);
}
_toBeCreated.Clear();
DebugState();
}
private void SetupLocalPlayer(PlayerAgent player)
{
_localTransformComponent = _fakeLocalGameObject.AddComponent<LocalTransformComponent>();
_localTransformComponent.transform = ((Component)comms).gameObject.transform;
_localTransformComponent.PlayerAgent = player;
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("Registered local tracked player to Dissonance " + player.PlayerName));
}
public void Joined(PlayerAgent player)
{
if (((Agent)player).IsLocallyOwned)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)"Tried to make local player join");
return;
}
if (!_managerStarted)
{
_toBeCreated.Add(player);
return;
}
ProximityVoiceHandler proximityVoiceHandler = ExplodesProxChat.Instance.CreatePair(_local, player, comms);
proximityVoiceHandler.Init();
_proxVoiceDict.Add(player.PlayerName, proximityVoiceHandler);
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("Registered remote tracked player to Dissonance: " + player.PlayerName));
DebugState();
}
public void Left(string name)
{
if (!_managerStarted)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)("Failed to remove " + name + ", manager is not started"));
return;
}
if (name == SteamManager.LocalPlayerName)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)("Tried to remove local player: " + name));
return;
}
if (!_proxVoiceDict.Remove(name, out ProximityVoiceHandler value))
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)("Tried to remove absent player: " + name));
return;
}
value.Finish();
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("Removed player " + name));
DebugState();
}
public void DebugState()
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("manager started: " + _managerStarted));
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"players: ");
foreach (var (text2, proximityVoiceHandler2) in _proxVoiceDict)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("- " + text2 + " " + proximityVoiceHandler2));
}
}
public void Reset()
{
if (_managerStarted)
{
DestroyAllVoices();
_proxVoiceDict.Clear();
Object.Destroy((Object)(object)_fakeLocalGameObject);
_toBeCreated.Clear();
_managerStarted = false;
DebugState();
}
}
private void DestroyAllVoices()
{
foreach (KeyValuePair<string, ProximityVoiceHandler> item in _proxVoiceDict)
{
try
{
item.Value.Finish();
}
catch (Exception ex)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)"Couldn't destroy voice properly, probably due to object already being garaged collected");
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)ex);
}
}
}
private void LeaveAllRooms()
{
int num;
for (num = 0; num < comms.Rooms._rooms.Count; num++)
{
RoomMembership val = comms.Rooms._rooms[num];
comms.Rooms.Leave(val);
num--;
}
}
}
}
namespace ExplodesProxChat.Voice.Handler
{
public class ProximityVoiceHandler
{
private readonly DissonanceComms _comms;
private readonly GameObject _fakePlayer;
private readonly PlayerAgentsPair _playerAgentsPair;
private readonly ISpatializationStrategy _spatializationStrategy;
private ProxChatPlayer _proxChatPlayer;
private VoiceBroadcastTrigger _trigger;
private VolumeUpdateComponent _volumeUpdateComponent;
public ProximityVoiceHandler(PlayerAgentsPair pair, DissonanceComms comms, ISpatializationStrategy spatializationStrategy)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
_playerAgentsPair = pair;
_comms = comms;
_spatializationStrategy = spatializationStrategy;
_fakePlayer = new GameObject("Fake player " + pair.OtherAgent.PlayerName);
}
public void Init()
{
AddProxChatPlayer();
AddTrigger();
AddVolumeUpdate();
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Initiated prox chat handler");
}
private void AddVolumeUpdate()
{
_volumeUpdateComponent = _fakePlayer.AddComponent<VolumeUpdateComponent>();
_volumeUpdateComponent.pair = this;
}
private void AddTrigger()
{
VoiceBroadcastTrigger component = _fakePlayer.GetComponent<VoiceBroadcastTrigger>();
if ((Object)(object)component != (Object)null)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogError((object)"Old trigger is present on the object, removing now");
Object.Destroy((Object)(object)component);
}
_trigger = _fakePlayer.AddComponent<VoiceBroadcastTrigger>();
_trigger.Mode = (CommActivationMode)1;
_trigger.BroadcastPosition = true;
_trigger.ChannelType = (CommTriggerTarget)2;
_trigger.MicrophoneVolume = 4f;
}
private void AddProxChatPlayer()
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
_proxChatPlayer = _fakePlayer.AddComponent<ProxChatPlayer>();
_proxChatPlayer.Player = _playerAgentsPair.OtherAgent;
_proxChatPlayer.IsLocalPlayer = false;
_comms.TrackPlayerPosition(new IDissonancePlayer(((Il2CppObjectBase)_proxChatPlayer).Pointer));
}
public void Update()
{
if (!((Object)_fakePlayer.GetComponent<VoiceBroadcastTrigger>()).Equals((Object)(object)_trigger))
{
AddTrigger();
}
_trigger.MicrophoneVolume = _spatializationStrategy.GetFadingFactor(_playerAgentsPair) * CellSettingsManager.SettingsData.VoiceChat.MicrophoneVolume.Value * 10f;
}
public void Finish()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Destroyed voice");
_comms.StopTracking(new IDissonancePlayer(((Il2CppObjectBase)_proxChatPlayer).Pointer));
Object.Destroy((Object)(object)_fakePlayer);
}
public override string ToString()
{
return $"{"_playerAgentsPair"}: {_playerAgentsPair}, {"_trigger"}: {_trigger}, {"_proxChatPlayer"}: {_proxChatPlayer}, {"_volumeUpdateComponent"}: {_volumeUpdateComponent}";
}
}
public class VolumeUpdateComponent : MonoBehaviour
{
public ProximityVoiceHandler pair;
public void Update()
{
pair.Update();
}
public void OnEnable()
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Started volume component");
}
public void OnDestroy()
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)"Destroyed volume component");
}
}
}
namespace ExplodesProxChat.Spatialization
{
public class DistanceSpatializationStrategy : ISpatializationStrategy
{
public IAttenuationFormula Formula { get; set; }
public DistanceSpatializationStrategy(IAttenuationFormula formula)
{
Formula = formula;
}
public float GetFadingFactor(PlayerAgentsPair pair)
{
//IL_0007: 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)
return Formula.GetFading(pair.PositionA, pair.PositionB);
}
}
public interface ISpatializationStrategy
{
float GetFadingFactor(PlayerAgentsPair pair);
}
public class MuteSpatializationStrategy : ISpatializationStrategy
{
public float GetFadingFactor(PlayerAgentsPair pair)
{
return 0f;
}
}
public class PlayerAgentsPair
{
public readonly PlayerAgent LocalPlayer;
public readonly PlayerAgent OtherAgent;
public Vector3 PositionA => ((Agent)LocalPlayer).EyePosition;
public Vector3 PositionB => ((Agent)OtherAgent).EyePosition;
public PlayerAgentsPair(PlayerAgent localPlayer, PlayerAgent otherAgent)
{
LocalPlayer = localPlayer;
OtherAgent = otherAgent;
}
}
public class RoomSpatializationStrategy : ISpatializationStrategy
{
private readonly ISpatializationStrategy _doorStrategy;
private readonly ISpatializationStrategy _internalStrategy;
public RoomSpatializationStrategy(ISpatializationStrategy internalStrategy, ISpatializationStrategy doorStrategy)
{
_internalStrategy = internalStrategy;
_doorStrategy = doorStrategy;
}
public float GetFadingFactor(PlayerAgentsPair pair)
{
if (((Agent)pair.LocalPlayer).CourseNode != null && !ArePlayerInTheSameRoom(pair))
{
return _doorStrategy.GetFadingFactor(pair);
}
return _internalStrategy.GetFadingFactor(pair);
}
private static bool ArePlayerInTheSameRoom(PlayerAgentsPair pair)
{
return CanReachNodes(new List<int>(), areaID: ((Agent)pair.LocalPlayer).CourseNode.NodeID, testedNode: ((Agent)pair.OtherAgent).CourseNode);
}
private static bool CanReachNodes(ICollection<int> visited, AIG_CourseNode testedNode, int areaID)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Invalid comparison between Unknown and I4
if (testedNode.NodeID == areaID)
{
return true;
}
Enumerator<AIG_CoursePortal> enumerator = testedNode.m_portals.GetEnumerator();
while (enumerator.MoveNext())
{
AIG_CoursePortal current = enumerator.Current;
if (!current.IsTraversable && (!current.m_hasGate || (int)current.Gate.SpawnedDoor.LastStatus != 16))
{
continue;
}
AIG_CourseNode oppositeNode = current.GetOppositeNode(testedNode);
if (!visited.Contains(oppositeNode.NodeID))
{
visited.Add(oppositeNode.NodeID);
if (CanReachNodes(visited, oppositeNode, areaID))
{
return true;
}
}
}
return false;
}
}
}
namespace ExplodesProxChat.Spatialization.Fading
{
public abstract class DistanceAttenuationFormula : IAttenuationFormula
{
public float GetFading(Vector3 a, Vector3 b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = a - b;
float magnitude = ((Vector3)(ref val)).magnitude;
return GetFadingFromDistance(magnitude);
}
protected abstract float GetFadingFromDistance(float distance);
}
public class ExponentialFalloffAttenuationFormula : DistanceAttenuationFormula
{
private readonly float _radius;
private readonly float _rolloffFactor;
public ExponentialFalloffAttenuationFormula(float radius, float rolloffFactor)
{
_radius = radius;
_rolloffFactor = rolloffFactor;
}
protected override float GetFadingFromDistance(float distance)
{
return Math.Min((float)Math.Pow(distance / _radius, 0f - _rolloffFactor), 1f);
}
}
public interface IAttenuationFormula
{
float GetFading(Vector3 a, Vector3 b);
}
public class LinearFalloffAttenuationFormula : DistanceAttenuationFormula
{
private readonly float _maxDistance;
private readonly float _referenceDistance;
private readonly float _rolloffFactor;
public LinearFalloffAttenuationFormula(float referenceDistance, float maxDistance, float rolloffFactor)
{
_referenceDistance = referenceDistance;
_maxDistance = maxDistance;
_rolloffFactor = rolloffFactor;
}
protected override float GetFadingFromDistance(float distance)
{
return Math.Min(1f - _rolloffFactor * (distance - _referenceDistance) / (_maxDistance - _referenceDistance), 1f);
}
}
}
namespace ExplodesProxChat.Noise
{
public class NoiseLevel : Object
{
public readonly NoiseType AgentNoiseType;
public readonly float Limit;
public NoiseLevel(float limit, NoiseType agentNoiseType)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
Limit = limit;
AgentNoiseType = agentNoiseType;
}
public override string ToString()
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
return $"{"Limit"}: {Limit}, {"AgentNoiseType"}: {AgentNoiseType}";
}
}
public class NoiseLevels
{
private readonly NoiseType _defaultNoiseType;
private readonly IEnumerable<NoiseLevel> _noiseLevelsList;
public NoiseLevels(IEnumerable<NoiseLevel> noiseLevelsList, NoiseType defaultNoiseType)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
_noiseLevelsList = noiseLevelsList;
_defaultNoiseType = defaultNoiseType;
}
public NoiseType GetNoiseTypeForAmplitude(float amplitude)
{
//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_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
NoiseType result = _defaultNoiseType;
float num = float.MaxValue;
foreach (NoiseLevel noiseLevels in _noiseLevelsList)
{
if (!(amplitude >= noiseLevels.Limit) && !(noiseLevels.Limit > num))
{
result = noiseLevels.AgentNoiseType;
num = noiseLevels.Limit;
}
}
return result;
}
}
public class VoiceChatNoiseMaker
{
private class VoiceAverage
{
public float Amplitude;
public int Added;
}
private const float MinVolume = -220f;
private const double TimeBasedOn = 0.25;
private readonly Dictionary<string, VoiceAverage> _accumulatedVolume = new Dictionary<string, VoiceAverage>();
private readonly DissonanceComms _comms;
private readonly NoiseLevels _noiseLevels;
private float _timer;
public VoiceChatNoiseMaker(DissonanceComms comms, NoiseLevels noiseLevels)
{
_comms = comms;
_noiseLevels = noiseLevels;
}
public void Update()
{
if (SNet.IsMaster)
{
_timer += Time.deltaTime;
Accumulate();
if (!((double)_timer < 0.25))
{
MakeNoiseBasedOnAverageAmplitude();
}
}
}
private void MakeNoiseBasedOnAverageAmplitude()
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: 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)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < _comms.Players.Count; i++)
{
VoicePlayerState val = _comms.Players[i];
VoiceAverage valueOrDefault = _accumulatedVolume.GetValueOrDefault(val.Name, new VoiceAverage());
float val2 = AmplitudeTodB(valueOrDefault.Amplitude / (float)valueOrDefault.Added);
if (valueOrDefault.Added == 0)
{
val2 = float.NegativeInfinity;
}
val2 = Math.Max(val2, -220f);
NoiseType noiseTypeForAmplitude = _noiseLevels.GetNoiseTypeForAmplitude(val2);
PlayerAgent val3 = ProxChatImpl.TryGetAgentOfName(val.Name);
if ((int)noiseTypeForAmplitude != 0)
{
((BasePlugin)ExplodesProxChat.Instance).Log.LogInfo((object)("Making noise: " + ((val3 != null) ? val3.PlayerName : null) + " level is " + ((object)(NoiseType)(ref noiseTypeForAmplitude)).ToString() + " average decibels are " + val2 + " dB"));
if (val3 != null)
{
val3.ForcePlayerNoiseChange(noiseTypeForAmplitude);
}
}
}
_accumulatedVolume.Clear();
_timer = 0f;
}
private void Accumulate()
{
for (int i = 0; i < _comms.Players.Count; i++)
{
VoicePlayerState val = _comms.Players[i];
float amplitude = val.Amplitude;
VoiceAverage valueOrDefault = _accumulatedVolume.GetValueOrDefault(val.Name, new VoiceAverage());
valueOrDefault.Amplitude += amplitude;
valueOrDefault.Added++;
_accumulatedVolume[val.Name] = valueOrDefault;
}
}
private static float AmplitudeTodB(float amplitude)
{
return (float)(20.0 * Math.Log10(amplitude));
}
}
}
namespace ExplodesProxChat.Effects
{
public interface IVoiceEffect
{
void Start(VoicePlayback playback);
void Update(VoicePlayback playback, PlayerAgent agent);
}
public class MainTest
{
public static void Main()
{
ReverbAudioFilter reverbAudioFilter = new ReverbAudioFilter(48000f);
for (float num = 0f; num < 480000f; num += 0.021333333f)
{
float[] array = new float[1024];
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
reverbAudioFilter.FillData(array, 1, num);
Console.WriteLine("[{0}]", string.Join(", ", array));
}
}
}
public class VoiceEffectsManager
{
private readonly List<IVoiceEffect> _voiceEffects = new List<IVoiceEffect>();
private DissonanceComms _comms;
public RoomReverbVoiceEffect Reverb = new RoomReverbVoiceEffect();
public void Start()
{
_voiceEffects.Add(Reverb);
_comms = Object.FindObjectOfType<DissonanceComms>();
_comms.OnPlayerJoinedSession += Action<VoicePlayerState>.op_Implicit((Action<VoicePlayerState>)delegate(VoicePlayerState s)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
if (s != null && !s.IsLocalPlayer)
{
VoicePlayback voicePlayback = new VoicePlayback(((Il2CppObjectBase)new RemoteVoicePlayerState(((Il2CppObjectBase)s).Pointer)._playback).Pointer);
InitPlayback(voicePlayback);
}
});
}
private void InitPlayback(VoicePlayback voicePlayback)
{
foreach (IVoiceEffect voiceEffect in _voiceEffects)
{
voiceEffect.Start(voicePlayback);
}
}
public void Update()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
Enumerator<VoicePlayerState> enumerator = _comms._players._players.GetEnumerator();
while (enumerator.MoveNext())
{
VoicePlayerState current = enumerator.Current;
if (!current.IsLocalPlayer)
{
VoicePlayback val = new VoicePlayback(((Il2CppObjectBase)new RemoteVoicePlayerState(((Il2CppObjectBase)current).Pointer)._playback).Pointer);
PlayerAgent val2 = ProxChatImpl.TryGetAgentOfName(current.Name);
if ((Object)(object)val2 != (Object)null && (Object)(object)val != (Object)null)
{
UpdateFilters(val2, val);
}
}
}
}
private void UpdateFilters(PlayerAgent agent, VoicePlayback playback)
{
foreach (IVoiceEffect voiceEffect in _voiceEffects)
{
voiceEffect.Update(playback, agent);
}
}
}
}
namespace ExplodesProxChat.Effects.Reverb
{
public class ReverbAudioFilter
{
private List<ReverbDelayLine> _lines = new List<ReverbDelayLine>();
private readonly float _sampleRate;
private readonly StreamedAudioCache _streamedAudioCache = new StreamedAudioCache();
private IReverbLinePreset _preset = ReverbPresetsEnum.NO_REVERB;
public IReverbLinePreset Preset
{
set
{
if (!value.Equals(_preset))
{
_preset = value;
List<ReverbDelayLine> list = new List<ReverbDelayLine>();
list.Clear();
list.AddRange(value.Build(_streamedAudioCache, _sampleRate));
_lines = list;
}
}
}
public ReverbAudioFilter(float sampleRate)
{
_sampleRate = sampleRate;
}
public void FillData(IList<float> data, int channels, double dspTime)
{
double num = dspTime * (double)_sampleRate;
long num2 = (long)Math.Floor(num);
int num3 = data.Count / channels;
_streamedAudioCache.Add(data, num2, num3);
double num4 = num;
for (int i = 0; i < num3; i++)
{
foreach (ReverbDelayLine line in _lines)
{
num4 = Math.Min(line.EchoSampleBasedOnCurrent(num2), num4);
if (_streamedAudioCache.HasData(line.GetPreDelaySamples(), num3))
{
line.AddReverb(data, channels, num2 + i, i);
}
}
}
_streamedAudioCache.RemoveTooOld(num4);
}
}
public class ReverbVoiceFilterScript : MonoBehaviour
{
private bool _running;
[HideFromIl2Cpp]
public ReverbAudioFilter? Filter { get; private set; }
private void Start()
{
Filter = new ReverbAudioFilter(AudioSettings.outputSampleRate);
}
public void OnAudioFilterRead(Il2CppStructArray<float> data, int channels)
{
Filter?.FillData((IList<float>)data, channels, AudioSettings.dspTime);
}
}
public class RoomReverbVoiceEffect : IVoiceEffect
{
public bool Enable;
public void Start(VoicePlayback playback)
{
((Component)playback).gameObject.AddComponent<ReverbVoiceFilterScript>();
}
public void Update(VoicePlayback playback, PlayerAgent agent)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Expected I4, but got Unknown
ReverbVoiceFilterScript component = ((Component)playback).gameObject.GetComponent<ReverbVoiceFilterScript>();
if (!ProxChatImpl.InLevel(agent) || !Enable)
{
component.Filter.Preset = ReverbPresetsEnum.NO_REVERB;
return;
}
LG_Area area = ((Agent)agent).CourseNode.m_area;
Bounds bounds = area.m_bounds;
Vector3 size = ((Bounds)(ref bounds)).size;
bool isOutside = area.m_zone.Dimension.DimensionData.IsOutside;
ReverbAudioFilter filter = component.Filter;
LG_AreaSize size2 = area.m_size;
filter.Preset = (size2 - 1) switch
{
3 => isOutside ? ReverbPresetsEnum.HUGE : ReverbPresetsEnum.HUGE,
2 => isOutside ? ReverbPresetsEnum.LARGE : ReverbPresetsEnum.LARGE,
1 => isOutside ? ReverbPresetsEnum.MEDIUM : ReverbPresetsEnum.MEDIUM,
0 => isOutside ? ReverbPresetsEnum.SMALL : ReverbPresetsEnum.SMALL,
4 => isOutside ? ReverbPresetsEnum.TINY : ReverbPresetsEnum.TINY,
_ => ReverbPresetsEnum.NO_REVERB,
};
}
}
}
namespace ExplodesProxChat.Effects.Reverb.Line
{
public class ReverbDelayLine
{
private readonly ReverbDelayLineProperties _properties;
private readonly float _sampleRate;
private readonly StreamedAudioCache _streamedAudioCache;
private AudioData? _current;
public ReverbDelayLine(ReverbDelayLineProperties properties, StreamedAudioCache streamedAudioCache, float sampleRate)
{
_properties = properties;
_streamedAudioCache = streamedAudioCache;
_sampleRate = sampleRate;
}
public void AddReverb(IList<float> data, int channels, long currentStartSample, int currentN)
{
long num = EchoSampleBasedOnCurrent(currentStartSample);
if (_current == null || !_current.IsInRange(num))
{
_current = ((_current == null) ? _streamedAudioCache.GetDataAtSample(num) : _current.Next);
if (_current == null || !_current.IsInRange(num))
{
_current = _streamedAudioCache.GetDataAtSample(num);
}
}
if (_current != null)
{
for (int i = 0; i < channels; i++)
{
float dataAtSample = _current.GetDataAtSample(num, i, channels);
data[currentN * channels + i] += dataAtSample * _properties.WetDryMix;
}
}
}
private static void LogInfo(string info)
{
Console.WriteLine(info);
}
public long EchoSampleBasedOnCurrent(long currentStartSample)
{
double preDelaySamples = GetPreDelaySamples();
return (long)((double)currentStartSample - preDelaySamples);
}
public double GetPreDelaySamples()
{
return _properties.PreDelay * _sampleRate;
}
}
public class ReverbDelayLineProperties
{
public readonly float PreDelay;
public readonly float WetDryMix;
public ReverbDelayLineProperties(float preDelay, float wetDryMix)
{
PreDelay = preDelay;
WetDryMix = wetDryMix;
}
}
}
namespace ExplodesProxChat.Effects.Reverb.Line.Presets
{
public interface IReverbLinePreset
{
IEnumerable<ReverbDelayLine> Build(StreamedAudioCache audioCache, float sampleRate);
}
public class ListReverbLinePreset : IReverbLinePreset
{
private readonly IEnumerable<ReverbDelayLineProperties> _properties;
public ListReverbLinePreset(IEnumerable<ReverbDelayLineProperties> properties)
{
_properties = properties;
}
public IEnumerable<ReverbDelayLine> Build(StreamedAudioCache audioCache, float sampleRate)
{
StreamedAudioCache audioCache2 = audioCache;
return _properties.Select((ReverbDelayLineProperties reverbDelayLineProperties) => new ReverbDelayLine(reverbDelayLineProperties, audioCache2, sampleRate)).ToList();
}
}
public class ReverbPresetsEnum
{
public static readonly IReverbLinePreset EXTRA_HUGE = new ListReverbLinePreset(new ReverbDelayLineProperties[3]
{
new ReverbDelayLineProperties(0.3f, 0.2f),
new ReverbDelayLineProperties(0.6f, 0.1f),
new ReverbDelayLineProperties(0.9f, 0.05f)
});
public static readonly IReverbLinePreset HUGE = new ListReverbLinePreset(new ReverbDelayLineProperties[3]
{
new ReverbDelayLineProperties(0.25f, 0.1f),
new ReverbDelayLineProperties(0.4f, 0.05f),
new ReverbDelayLineProperties(0.55f, 0.02f)
});
public static readonly IReverbLinePreset LARGE = new ListReverbLinePreset(new ReverbDelayLineProperties[3]
{
new ReverbDelayLineProperties(0.2f, 0.05f),
new ReverbDelayLineProperties(0.3f, 0.02f),
new ReverbDelayLineProperties(0.4f, 0.01f)
});
public static readonly IReverbLinePreset MEDIUM = new ListReverbLinePreset(new ReverbDelayLineProperties[2]
{
new ReverbDelayLineProperties(0.1f, 0.2f),
new ReverbDelayLineProperties(0.15f, 0.1f)
});
public static readonly IReverbLinePreset SMALL = new ListReverbLinePreset(new ReverbDelayLineProperties[1]
{
new ReverbDelayLineProperties(0.05f, 0.1f)
});
public static readonly IReverbLinePreset TINY = new ListReverbLinePreset(Array.Empty<ReverbDelayLineProperties>());
public static readonly IReverbLinePreset NO_REVERB = new ListReverbLinePreset(Array.Empty<ReverbDelayLineProperties>());
}
}
namespace ExplodesProxChat.Effects.EQ
{
public class DigitalAudioFilter
{
private readonly DigitalAudioFilterProperties _properties;
public DigitalAudioFilter(DigitalAudioFilterProperties properties)
{
_properties = properties;
}
public float[] Filter(IList<float> data, int dataLength, int channelCount)
{
float[] array = new float[data.Count];
for (int i = 0; i < dataLength; i++)
{
ApplyFilter(data, array, i, channelCount);
}
return array;
}
private void ApplyFilter(IList<float> data, IList<float> resultData, int n, int channelCount)
{
int num = _properties.Ord - 1;
float[] a = _properties.A;
float[] b = _properties.B;
for (int i = 0; i < num + 1; i++)
{
if (n - i >= 0)
{
for (int j = 0; j < channelCount; j++)
{
int index = IndexFromN(n, channelCount, j);
int index2 = IndexFromN(n - i, channelCount, j);
resultData[index] += b[i] * data[index2];
}
}
}
for (int k = 0; k < num - 1; k++)
{
if (n - k - 1 >= 0)
{
for (int l = 0; l < channelCount; l++)
{
int index3 = IndexFromN(n, channelCount, l);
int index4 = IndexFromN(n - k - 1, channelCount, l);
resultData[index3] -= a[k + 1] * resultData[index4];
}
}
}
for (int m = 0; m < channelCount; m++)
{
resultData[IndexFromN(n, channelCount, m)] /= a[0];
}
}
private static int IndexFromN(int n, int channelCount, int currentChannel)
{
return n * channelCount + currentChannel;
}
}
public class DigitalAudioFilterProperties
{
public readonly float[] A;
public readonly float[] B;
public int Ord => A.Length;
public DigitalAudioFilterProperties(float[] a, float[] b)
{
A = a;
B = b;
}
public static DigitalAudioFilterProperties build(float sampleRate, float centerFrequency, float bandwidth, float bandwidthGain, float referenceGain, float boostGain)
{
double num = Math.Tan((double)(bandwidth / 2f) * Math.PI / (double)(sampleRate / 2f));
double num2 = GainExp(bandwidthGain);
double num3 = GainExp(referenceGain);
double num4 = GainExp(boostGain);
double num5 = Math.Sqrt(Math.Abs(num2 - num3));
double num6 = Math.Sqrt(Math.Abs(num4 - num2));
double num7 = num * num5 / num6;
double num8 = (Math.Pow(10.0, referenceGain / 20f) + Math.Pow(10.0, boostGain / 20f) * num7) / (1.0 + num7);
double num9 = -2.0 * Math.Pow(10.0, referenceGain / 20f) * Math.Cos((double)centerFrequency * Math.PI / (double)(sampleRate / 2f)) / (1.0 + num7);
double num10 = (Math.Pow(10.0, referenceGain / 20f) - Math.Pow(10.0, boostGain / 20f) * num7) / (1.0 + num7);
int num11 = 1;
double num12 = -2.0 * Math.Cos((double)centerFrequency * Math.PI / (double)(sampleRate / 2f)) / (1.0 + num7);
double num13 = (1.0 - num7) / (1.0 + num7);
return new DigitalAudioFilterProperties(new float[3]
{
num11,
(float)num12,
(float)num13
}, new float[3]
{
(float)num8,
(float)num9,
(float)num10
});
}
private static double GainExp(float gain)
{
return Math.Pow(Math.Pow(10.0, gain / 20f), 2.0);
}
}
public class ParametricEqualizer
{
private readonly DigitalAudioFilter[] _filters;
public ParametricEqualizer(DigitalAudioFilter[] filters)
{
_filters = filters;
}
public IList<float> Apply(IList<float> data, int dataLength, int channelCount)
{
return _filters.Aggregate(data, (IList<float> current, DigitalAudioFilter digitalAudioFilter) => digitalAudioFilter.Filter(current, dataLength, channelCount));
}
}
}
namespace ExplodesProxChat.Effects.Audio
{
public class AudioData
{
private readonly float[] _data;
private readonly int _dataLen;
private readonly long _endSample;
private readonly long _startSample;
public AudioData? Next;
public AudioData(float[] data, long startSample, int dataLen)
{
_data = data;
_startSample = startSample;
_dataLen = dataLen;
_endSample = _startSample + _dataLen;
}
public bool IsInRange(long sample)
{
if (sample >= _startSample)
{
return sample < _endSample;
}
return false;
}
public float GetDataAtSample(long sample, int currentChannel, int channels)
{
return _data[(sample - _startSample) * channels + currentChannel];
}
public bool IsOutdated(double sample)
{
return sample >= (double)_endSample;
}
public override string ToString()
{
return $"{"_data"}: {_data}, {"_startSample"}: {_startSample}, {"_dataLen"}: {_dataLen}";
}
}
public class StreamedAudioCache
{
private readonly List<AudioData> _oldData = new List<AudioData>();
public void Add(IList<float> data, long currentStartSample, int dataLen)
{
float[] array = new float[data.Count];
for (int i = 0; i < data.Count; i++)
{
array[i] = data[i];
}
AddToOldData(new AudioData(array, currentStartSample, dataLen));
}
private void AddToOldData(AudioData audioData)
{
int num = _oldData.Count - 1;
if (num > 0)
{
_oldData[num].Next = audioData;
}
_oldData.Add(audioData);
}
public void RemoveTooOld(double sample)
{
int count = 0;
for (int num = _oldData.Count - 1; num >= 0; num--)
{
if (_oldData[num].IsOutdated(sample))
{
count = num;
break;
}
}
_oldData.RemoveRange(0, count);
}
public AudioData? GetDataAtSample(long sampleTime)
{
for (int num = _oldData.Count - 1; num >= 0; num--)
{
AudioData audioData = _oldData[num];
if (audioData.IsInRange(sampleTime))
{
return audioData;
}
}
return null;
}
public bool HasData(double delay, int dataLen)
{
return (double)((_oldData.Count - 1) * dataLen) > delay;
}
}
}