Decompiled source of DrunkLab v1.0.0
Mods/DrunkLab.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using AudioLib; using BoneLib; using BoneLib.BoneMenu; using DrunkLab; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Bonelab; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Audio; using Il2CppSystem; using Il2CppSystem.Reflection; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using NVorbis; using NVorbis.Contracts; using NVorbis.Contracts.Ogg; using NVorbis.Ogg; using RagdollPlayer; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(DrunkLabMod), "DrunkLab", "1.0.0", "habibis_v", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("DrunkLab")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DrunkLab")] [assembly: AssemblyTitle("DrunkLab")] [assembly: AssemblyVersion("1.0.0.0")] 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 DrunkLab { public static class DrunkEffects { [CompilerGenerated] private sealed class <BlinkThenRagdoll>d__36 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public RigManager rm; private float <fadeElapsed>5__2; private int <i>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <BlinkThenRagdoll>d__36(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) GameObject? blinkQuad; switch (<>1__state) { default: return false; case 0: { <>1__state = -1; _isRagdolled = true; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { if ((Object)(object)_blinkQuad == (Object)null) { BuildBlinkQuad(main); } _blinkQuad.transform.SetParent(((Component)main).transform, false); <i>5__3 = 0; goto IL_0110; } goto IL_011c; } case 1: <>1__state = -1; _blinkQuad.SetActive(false); <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 2; return true; case 2: <>1__state = -1; <i>5__3++; goto IL_0110; case 3: <>1__state = -1; if ((Object)(object)_blinkMat != (Object)null && (Object)(object)_blinkQuad != (Object)null) { _blinkMat.color = new Color(0f, 0f, 0f, 1f); _blinkQuad.SetActive(true); } <>2__current = (object)new WaitForSeconds(2f); <>1__state = 4; return true; case 4: <>1__state = -1; ZeroRigVelocities(rm.physicsRig); <>2__current = null; <>1__state = 5; return true; case 5: <>1__state = -1; _isSlowMo = true; _slowMoTimer = 0f; MelonLogger.Msg("[DrunkLab] SlowMo started"); <>2__current = (object)new WaitForSecondsRealtime(0.2f); <>1__state = 6; return true; case 6: { <>1__state = -1; RagdollPlayerMod.UnragdollRig(rm); Health health = rm.health; Health val = ((health != null) ? ((Il2CppObjectBase)health).TryCast<Health>() : null); if ((Object)(object)val != (Object)null) { val.SetFullHealth(); } <fadeElapsed>5__2 = 0f; goto IL_02b8; } case 7: <>1__state = -1; goto IL_02b8; case 8: { <>1__state = -1; break; } IL_011c: RagdollPlayerMod.RagdollRig(rm); <>2__current = (object)new WaitForSeconds(0.7f); <>1__state = 3; return true; IL_02b8: if (<fadeElapsed>5__2 < 1f) { <fadeElapsed>5__2 += Time.unscaledDeltaTime; if ((Object)(object)_blinkMat != (Object)null) { _blinkMat.color = new Color(0f, 0f, 0f, Mathf.Lerp(1f, 0f, <fadeElapsed>5__2)); } <>2__current = null; <>1__state = 7; return true; } blinkQuad = _blinkQuad; if (blinkQuad != null) { blinkQuad.SetActive(false); } break; IL_0110: if (<i>5__3 < 3) { _blinkMat.color = new Color(0f, 0f, 0f, 1f); _blinkQuad.SetActive(true); <>2__current = (object)new WaitForSeconds(0.4f); <>1__state = 1; return true; } goto IL_011c; } if (_isSlowMo) { <>2__current = null; <>1__state = 8; return true; } _isRagdolled = false; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static float _wobbleTimer = 0f; private static float _stumbleTimer = 0f; private static float _stumbleInterval = 3f; private static float _ragdollTimer = 0f; private static float _ragdollInterval = 20f; private static bool _isRagdolled = false; private static bool _isSlowMo = false; private static float _slowMoTimer = 0f; private const float SlowMoDuration = 2f; private const float SlowMoScale = 0.15f; private static float _xPosForceL = 0f; private static float _xNegForceL = 0f; private static float _yPosForceL = 0f; private static float _yNegForceL = 0f; private static float _zPosForceL = 0f; private static float _zNegForceL = 0f; private static float _xPosForceR = 0f; private static float _xNegForceR = 0f; private static float _yPosForceR = 0f; private static float _yNegForceR = 0f; private static float _zPosForceR = 0f; private static float _zNegForceR = 0f; private static float _origSpineMult = 1f; private static float _origSlerpDamper = 1f; private static bool _savedOriginals = false; private static GameObject? _blinkQuad; private static Material? _blinkMat; private static GameObject? _vignetteQuad; private static Material? _vignetteMat; private static float _swayTime = 0f; public static void Tick(float dt) { //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_0517: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Unknown result type (might be due to invalid IL or missing references) Player.PlayLooping2D("heavybreathingclipped", "heavybreathing", 5f); float num = DrunkLabMod.DrunkLevel / 10f; RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager == (Object)null) { return; } PhysicsRig physicsRig = rigManager.physicsRig; if ((Object)(object)physicsRig == (Object)null) { return; } Hand leftHand = physicsRig.leftHand; PhysHand val = ((leftHand != null) ? leftHand.physHand : null); Hand rightHand = physicsRig.rightHand; PhysHand val2 = ((rightHand != null) ? rightHand.physHand : null); PhysTorso torso = physicsRig.torso; if (!_savedOriginals && (Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && (Object)(object)torso != (Object)null) { _xPosForceL = val.xPosForce; _xNegForceL = val.xNegForce; _yPosForceL = val.yPosForce; _yNegForceL = val.yNegForce; _zPosForceL = val.zPosForce; _zNegForceL = val.zNegForce; _xPosForceR = val2.xPosForce; _xNegForceR = val2.xNegForce; _yPosForceR = val2.yPosForce; _yNegForceR = val2.yNegForce; _zPosForceR = val2.zPosForce; _zNegForceR = val2.zNegForce; _origSpineMult = torso.spineInternalMult; _origSlerpDamper = torso._slerpDamperMult; _savedOriginals = true; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { if ((Object)(object)_blinkQuad == (Object)null) { BuildBlinkQuad(main); } if ((Object)(object)_vignetteQuad == (Object)null) { BuildVignetteQuad(main); } GameObject? vignetteQuad = _vignetteQuad; if (vignetteQuad != null) { vignetteQuad.SetActive(true); } } } if (_isSlowMo) { Time.timeScale = 0.15f; _slowMoTimer += dt / 0.15f; if (_slowMoTimer >= 2f) { _isSlowMo = false; _slowMoTimer = 0f; Time.timeScale = 1f; MelonLogger.Msg("[DrunkLab] SlowMo ending"); } } if (_isRagdolled) { return; } _wobbleTimer += dt; _stumbleTimer += dt; _ragdollTimer += dt; if ((Object)(object)torso != (Object)null) { torso.spineInternalMult = Mathf.Lerp(_origSpineMult, 0.1f, num); torso._slerpDamperMult = Mathf.Lerp(_origSlerpDamper, 0.05f, num); } if ((Object)(object)physicsRig.leftHand != (Object)null) { physicsRig.leftHand.SetGripStrength(Mathf.Lerp(1f, 0.1f, num)); } if ((Object)(object)physicsRig.rightHand != (Object)null) { physicsRig.rightHand.SetGripStrength(Mathf.Lerp(1f, 0.1f, num)); } if (_wobbleTimer >= 0.25f) { _wobbleTimer = 0f; float num2 = num * 300f; if ((Object)(object)val != (Object)null) { val.xPosForce = _xPosForceL + Random.Range(0f - num2, num2); val.xNegForce = _xNegForceL + Random.Range(0f - num2, num2); val.yPosForce = _yPosForceL + Random.Range(0f - num2, num2); val.yNegForce = _yNegForceL + Random.Range(0f - num2, num2); val.zPosForce = _zPosForceL + Random.Range(0f - num2, num2); val.zNegForce = _zNegForceL + Random.Range(0f - num2, num2); } if ((Object)(object)val2 != (Object)null) { val2.xPosForce = _xPosForceR + Random.Range(0f - num2, num2); val2.xNegForce = _xNegForceR + Random.Range(0f - num2, num2); val2.yPosForce = _yPosForceR + Random.Range(0f - num2, num2); val2.yNegForce = _yNegForceR + Random.Range(0f - num2, num2); val2.zPosForce = _zPosForceR + Random.Range(0f - num2, num2); val2.zNegForce = _zNegForceR + Random.Range(0f - num2, num2); } } _stumbleInterval = Mathf.Lerp(5f, 1.5f, num); if (_stumbleTimer >= _stumbleInterval && (Object)(object)physicsRig.rbFeet != (Object)null) { _stumbleTimer = 0f; Vector3 val3 = new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f)); Vector3 normalized = ((Vector3)(ref val3)).normalized; physicsRig.rbFeet.AddForce(normalized * num * 8f, (ForceMode)1); } if ((Object)(object)physicsRig.rbFeet != (Object)null) { _swayTime += dt; float num3 = Mathf.Lerp(0.04f, 0.1f, num); float num4 = Mathf.Lerp(0.1f, 0.3f, num); float num5 = Mathf.Sin(_swayTime * num3 * MathF.PI * 2f); Vector3 val4 = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.right : ((Component)rigManager).transform.right); val4.y = 0f; ((Vector3)(ref val4)).Normalize(); physicsRig.rbFeet.AddForce(val4 * num5 * num4, (ForceMode)2); } _ragdollInterval = Mathf.Lerp(30f, 10f, num); if (_ragdollTimer >= _ragdollInterval) { _ragdollTimer = 0f; MelonCoroutines.Start(BlinkThenRagdoll(rigManager)); } } private static GameObject MakeQuad(Camera cam, string name, float zBias = 0f) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)val).name = name; Object.DontDestroyOnLoad((Object)(object)val); foreach (Component component in val.GetComponents<Component>()) { if (((MemberInfo)((Object)component).GetIl2CppType()).Name.Contains("Collider")) { Object.Destroy((Object)(object)component); } } val.transform.SetParent(((Component)cam).transform, false); val.transform.localRotation = Quaternion.identity; float num = cam.nearClipPlane + 0.001f + zBias; float num2 = 2f * Mathf.Tan(cam.fieldOfView * 0.5f * (MathF.PI / 180f)) * num; float num3 = num2 * cam.aspect; val.transform.localPosition = new Vector3(0f, 0f, num); val.transform.localScale = new Vector3(num3, num2, 1f); return val; } private static Material MakeTransparentMat(GameObject quad) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Unlit/Transparent") ?? Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default"); Material val2 = new Material(val ?? quad.GetComponent<Renderer>().material.shader); val2.color = new Color(0f, 0f, 0f, 0f); quad.GetComponent<Renderer>().material = val2; return val2; } private static Texture2D MakeEyeTexture() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) int num = 256; Texture2D val = new Texture2D(num, num, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[num * num]; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num2 = (float)j / (float)num * 2f - 1f; float num3 = (float)i / (float)num * 2f - 1f; float num4 = Mathf.Sqrt(num2 * num2 * 0.55f + num3 * num3); float num5 = Mathf.SmoothStep(0.5f, 1f, num4); array[i * num + j] = new Color(0f, 0f, 0f, num5); } } val.SetPixels(Il2CppStructArray<Color>.op_Implicit(array)); val.Apply(); return val; } private static void BuildBlinkQuad(Camera cam) { _blinkQuad = MakeQuad(cam, "DrunkBlink"); _blinkMat = MakeTransparentMat(_blinkQuad); _blinkQuad.SetActive(false); } private static void BuildVignetteQuad(Camera cam) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) _vignetteQuad = MakeQuad(cam, "DrunkVignette", 0.0001f); _vignetteMat = MakeTransparentMat(_vignetteQuad); _vignetteMat.mainTexture = (Texture)(object)MakeEyeTexture(); _vignetteMat.color = Color.white; _vignetteQuad.SetActive(false); } [IteratorStateMachine(typeof(<BlinkThenRagdoll>d__36))] private static IEnumerator BlinkThenRagdoll(RigManager rm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <BlinkThenRagdoll>d__36(0) { rm = rm }; } private static void ZeroRigVelocities(PhysicsRig physRig) { PhysTorso torso = physRig.torso; if ((Object)(object)torso != (Object)null) { ZeroRb(torso.rbHead); ZeroRb(torso.rbNeck); ZeroRb(torso.rbChest); ZeroRb(torso.rbSpine); ZeroRb(torso.rbPelvis); } PhysLimb legLf = physRig.legLf; if ((Object)(object)legLf != (Object)null) { ZeroRb(legLf.rbUpper); ZeroRb(legLf.rbLower); ZeroRb(legLf.rbEnd); } PhysLimb legRt = physRig.legRt; if ((Object)(object)legRt != (Object)null) { ZeroRb(legRt.rbUpper); ZeroRb(legRt.rbLower); ZeroRb(legRt.rbEnd); } Hand leftHand = physRig.leftHand; ZeroRb((leftHand != null) ? leftHand.rb : null); Hand rightHand = physRig.rightHand; ZeroRb((rightHand != null) ? rightHand.rb : null); } private static void ZeroRb(Rigidbody? rb) { //IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rb == (Object)null)) { Vector3 velocity = (rb.angularVelocity = Vector3.zero); rb.velocity = velocity; } } public static void Restore() { Player.StopAll(); if (!_savedOriginals) { return; } Time.timeScale = 1f; _isRagdolled = false; _isSlowMo = false; _slowMoTimer = 0f; GameObject? blinkQuad = _blinkQuad; if (blinkQuad != null) { blinkQuad.SetActive(false); } GameObject? vignetteQuad = _vignetteQuad; if (vignetteQuad != null) { vignetteQuad.SetActive(false); } RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager != (Object)null) { PhysicsRig physicsRig = rigManager.physicsRig; object obj; if (physicsRig == null) { obj = null; } else { Hand leftHand = physicsRig.leftHand; obj = ((leftHand != null) ? leftHand.physHand : null); } PhysHand val = (PhysHand)obj; object obj2; if (physicsRig == null) { obj2 = null; } else { Hand rightHand = physicsRig.rightHand; obj2 = ((rightHand != null) ? rightHand.physHand : null); } PhysHand val2 = (PhysHand)obj2; PhysTorso val3 = ((physicsRig != null) ? physicsRig.torso : null); if ((Object)(object)val3 != (Object)null) { val3.spineInternalMult = _origSpineMult; val3._slerpDamperMult = _origSlerpDamper; } if (physicsRig != null) { Hand leftHand2 = physicsRig.leftHand; if (leftHand2 != null) { leftHand2.SetGripStrength(1f); } } if (physicsRig != null) { Hand rightHand2 = physicsRig.rightHand; if (rightHand2 != null) { rightHand2.SetGripStrength(1f); } } if ((Object)(object)val != (Object)null) { val.xPosForce = _xPosForceL; val.xNegForce = _xNegForceL; val.yPosForce = _yPosForceL; val.yNegForce = _yNegForceL; val.zPosForce = _zPosForceL; val.zNegForce = _zNegForceL; } if ((Object)(object)val2 != (Object)null) { val2.xPosForce = _xPosForceR; val2.xNegForce = _xNegForceR; val2.yPosForce = _yPosForceR; val2.yNegForce = _yNegForceR; val2.zPosForce = _zPosForceR; val2.zNegForce = _zNegForceR; } } _savedOriginals = false; _wobbleTimer = (_stumbleTimer = (_ragdollTimer = (_swayTime = 0f))); MelonLogger.Msg("[DrunkLab] Sobered up."); } } public class DrunkLabMod : MelonMod { public static bool IsDrunk = false; public static float DrunkLevel = 5f; private static bool _built; public override void OnInitializeMelon() { Hooking.OnUIRigCreated += BuildMenu; ((MelonBase)this).LoggerInstance.Msg("DrunkLab loaded."); } private static void BuildMenu() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (_built) { return; } _built = true; Page val = Page.Root.CreatePage("DrunkLab", Color.yellow, 0, true); val.CreateBool("Drunk Mode", Color.green, false, (Action<bool>)delegate(bool v) { IsDrunk = v; if (!v) { DrunkEffects.Restore(); } }); val.CreateFloat("Drunk Level", Color.yellow, 5f, 1f, 1f, 10f, (Action<float>)delegate(float v) { DrunkLevel = v; }); } public override void OnUpdate() { if (IsDrunk && !((Object)(object)Player.RigManager == (Object)null)) { DrunkEffects.Tick(Time.deltaTime); } } } } namespace AudioLib { internal class AudioLibMod : MelonMod { public override void OnInitializeMelon() { Directory.CreateDirectory(Loader.SoundsDirectory); ((MelonBase)this).LoggerInstance.Msg("AudioLib v1.0.0 ready."); ((MelonBase)this).LoggerInstance.Msg("Drop OGG files in: " + Loader.SoundsDirectory); Loader.PreloadAll(); Hooking.OnLevelLoaded += delegate { Loader.PreloadAll(); }; } } internal static class Loader { private static readonly Dictionary<string, AudioClip> _cache = new Dictionary<string, AudioClip>(); public static readonly string SoundsDirectory = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "UserData", "AudioLib", "sounds")); public static AudioClip? GetClip(string fileName) { string key = fileName.Replace(".ogg", "").Replace(".OGG", "").ToLower(); if (_cache.TryGetValue(key, out AudioClip value)) { return value; } string text = FindFile(fileName); if (text == null) { MelonLogger.Error("[AudioLib] '" + fileName + "' not found in " + SoundsDirectory); MelonLogger.Msg("[AudioLib] Available files:"); string[] files = Directory.GetFiles(SoundsDirectory, "*.ogg"); foreach (string path in files) { MelonLogger.Msg(" - " + Path.GetFileName(path)); } return null; } AudioClip val = OggDecoder.Load(text); if ((Object)(object)val != (Object)null) { _cache[key] = val; } return val; } public static void PreloadAll() { if (!Directory.Exists(SoundsDirectory)) { Directory.CreateDirectory(SoundsDirectory); return; } string[] files = Directory.GetFiles(SoundsDirectory, "*.ogg"); foreach (string text in files) { string key = Path.GetFileNameWithoutExtension(text).ToLower(); if (!_cache.ContainsKey(key)) { AudioClip val = OggDecoder.Load(text); if ((Object)(object)val != (Object)null) { _cache[key] = val; MelonLogger.Msg("[AudioLib] Preloaded: " + Path.GetFileName(text)); } } } } public static bool Preload(string fileName) { return (Object)(object)GetClip(fileName) != (Object)null; } public static void ClearCache() { _cache.Clear(); MelonLogger.Msg("[AudioLib] Cache cleared."); } private static string? FindFile(string fileName) { string text = Path.Combine(SoundsDirectory, fileName); if (File.Exists(text)) { return text; } string text2 = Path.Combine(SoundsDirectory, fileName + ".ogg"); if (File.Exists(text2)) { return text2; } string[] files = Directory.GetFiles(SoundsDirectory, "*.ogg"); foreach (string text3 in files) { if (string.Equals(Path.GetFileNameWithoutExtension(text3), Path.GetFileNameWithoutExtension(fileName), StringComparison.OrdinalIgnoreCase)) { return text3; } } return null; } } internal static class OggDecoder { internal static AudioClip? Load(string filePath) { if (!File.Exists(filePath)) { MelonLogger.Error("[AudioLib] File not found: " + filePath); return null; } try { using VorbisReader vorbisReader = new VorbisReader(filePath); int channels = vorbisReader.Channels; int sampleRate = vorbisReader.SampleRate; List<float> list = new List<float>(); float[] array = new float[channels * sampleRate / 10]; int num; while ((num = vorbisReader.ReadSamples(array, 0, array.Length)) > 0) { for (int i = 0; i < num; i++) { list.Add(array[i]); } } float[] array2 = list.ToArray(); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); AudioClip val = AudioClip.Create(fileNameWithoutExtension, array2.Length / channels, channels, sampleRate, false); val.SetData(Il2CppStructArray<float>.op_Implicit(array2), 0); MelonLogger.Msg($"[AudioLib] Decoded '{fileNameWithoutExtension}' — {channels}ch @ {sampleRate}Hz, {list.Count} samples"); return val; } catch (Exception ex) { MelonLogger.Error("[AudioLib] Failed to decode '" + filePath + "': " + ex.Message); return null; } } } internal static class Player { public static void Play2D(string fileName, float volume = 1f, float pitch = 1f) { AudioClip clip = Loader.GetClip(fileName); if (!((Object)(object)clip == (Object)null)) { AudioSource val = SourcePool.Get(); Configure(val, clip, volume, pitch, 0f, loop: false); val.Play(); } } public static void Play2DDelayed(string fileName, float delay, float volume = 1f, float pitch = 1f) { AudioClip clip = Loader.GetClip(fileName); if (!((Object)(object)clip == (Object)null)) { AudioSource val = SourcePool.Get(); Configure(val, clip, volume, pitch, 0f, loop: false); val.PlayDelayed(delay); } } public static void Play3D(string fileName, Vector3 position, float volume = 1f, float pitch = 1f, float minDist = 1f, float maxDist = 20f) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) AudioClip clip = Loader.GetClip(fileName); if (!((Object)(object)clip == (Object)null)) { AudioSource val = SourcePool.Get(); Configure(val, clip, volume, pitch, 1f, loop: false); val.minDistance = minDist; val.maxDistance = maxDist; ((Component)val).transform.position = position; val.Play(); } } public static void Play3DAttached(string fileName, Transform parent, float volume = 1f, float pitch = 1f, float minDist = 1f, float maxDist = 20f) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) AudioClip clip = Loader.GetClip(fileName); if (!((Object)(object)clip == (Object)null)) { AudioSource val = SourcePool.Get(); ((Component)val).transform.SetParent(parent, false); ((Component)val).transform.localPosition = Vector3.zero; Configure(val, clip, volume, pitch, 1f, loop: false); val.minDistance = minDist; val.maxDistance = maxDist; val.Play(); } } public static void PlayLooping2D(string fileName, string loopId, float volume = 1f, float pitch = 1f) { AudioClip clip = Loader.GetClip(fileName); if (!((Object)(object)clip == (Object)null)) { AudioSource named = SourcePool.GetNamed(loopId); Configure(named, clip, volume, pitch, 0f, loop: true); if (!named.isPlaying) { named.Play(); } } } public static void PlayLooping3D(string fileName, string loopId, Vector3 position, float volume = 1f, float pitch = 1f, float minDist = 1f, float maxDist = 20f) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) AudioClip clip = Loader.GetClip(fileName); if (!((Object)(object)clip == (Object)null)) { AudioSource named = SourcePool.GetNamed(loopId); ((Component)named).transform.position = position; Configure(named, clip, volume, pitch, 1f, loop: true); named.minDistance = minDist; named.maxDistance = maxDist; if (!named.isPlaying) { named.Play(); } } } public static void StopLooping(string loopId) { SourcePool.StopNamed(loopId); } public static void SetLoopVolume(string loopId, float volume) { SourcePool.GetNamed(loopId).volume = volume; } public static void SetLoopPitch(string loopId, float pitch) { SourcePool.GetNamed(loopId).pitch = pitch; } public static void StopAll() { SourcePool.StopAll(); } private static void Configure(AudioSource src, AudioClip clip, float volume, float pitch, float spatialBlend, bool loop) { src.clip = clip; src.volume = volume; src.pitch = pitch; src.spatialBlend = spatialBlend; src.loop = loop; src.rolloffMode = (AudioRolloffMode)1; } } internal static class SourcePool { private static GameObject? _root; private static readonly List<AudioSource> _pool = new List<AudioSource>(); private static GameObject Root { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_root == (Object)null) { _root = new GameObject("AudioLib_Pool"); Object.DontDestroyOnLoad((Object)(object)_root); } return _root; } } internal static AudioSource Get() { foreach (AudioSource item in _pool) { if ((Object)(object)item != (Object)null && !item.isPlaying) { return item; } } AudioSource val = Root.AddComponent<AudioSource>(); _pool.Add(val); return val; } internal static AudioSource GetNamed(string id) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown Transform val = Root.transform.Find(id); if ((Object)(object)val != (Object)null) { AudioSource component = ((Component)val).GetComponent<AudioSource>(); if ((Object)(object)component != (Object)null) { return component; } } GameObject val2 = new GameObject(id); val2.transform.SetParent(Root.transform); return val2.AddComponent<AudioSource>(); } internal static void StopNamed(string id) { Transform val = Root.transform.Find(id); if (val != null) { AudioSource component = ((Component)val).GetComponent<AudioSource>(); if (component != null) { component.Stop(); } } } internal static void StopAll() { foreach (AudioSource item in _pool) { if (item != null) { item.Stop(); } } for (int i = 0; i < Root.transform.childCount; i++) { AudioSource component = ((Component)Root.transform.GetChild(i)).GetComponent<AudioSource>(); if (component != null) { component.Stop(); } } } } } namespace NVorbis { internal class Codebook : ICodebook { private class FastRange : IReadOnlyList<int>, IEnumerable<int>, IEnumerable, IReadOnlyCollection<int> { [ThreadStatic] private static FastRange _cachedRange; private int _start; private int _count; public int this[int index] { get { if (index > _count) { throw new ArgumentOutOfRangeException(); } return _start + index; } } public int Count => _count; internal static FastRange Get(int start, int count) { FastRange obj = _cachedRange ?? (_cachedRange = new FastRange()); obj._start = start; obj._count = count; return obj; } private FastRange() { } public IEnumerator<int> GetEnumerator() { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private int[] _lengths; private float[] _lookupTable; private IReadOnlyList<HuffmanListNode> _overflowList; private IReadOnlyList<HuffmanListNode> _prefixList; private int _prefixBitLength; private int _maxBits; public float this[int entry, int dim] => _lookupTable[entry * Dimensions + dim]; public int Dimensions { get; private set; } public int Entries { get; private set; } public int MapType { get; private set; } public void Init(IPacket packet, IHuffman huffman) { if (packet.ReadBits(24) != 5653314) { throw new InvalidDataException("Book header had invalid signature!"); } Dimensions = (int)packet.ReadBits(16); Entries = (int)packet.ReadBits(24); _lengths = new int[Entries]; InitTree(packet, huffman); InitLookupTable(packet); } private void InitTree(IPacket packet, IHuffman huffman) { int num = 0; bool flag; int num5; if (packet.ReadBit()) { int num2 = (int)packet.ReadBits(5) + 1; int num3 = 0; while (num3 < Entries) { int num4 = (int)packet.ReadBits(Utils.ilog(Entries - num3)); while (--num4 >= 0) { _lengths[num3++] = num2; } num2++; } num = 0; flag = false; num5 = num2; } else { num5 = -1; flag = packet.ReadBit(); for (int i = 0; i < Entries; i++) { if (!flag || packet.ReadBit()) { _lengths[i] = (int)packet.ReadBits(5) + 1; num++; } else { _lengths[i] = -1; } if (_lengths[i] > num5) { num5 = _lengths[i]; } } } if ((_maxBits = num5) > -1) { int[] array = null; if (flag && num >= Entries >> 2) { array = new int[Entries]; Array.Copy(_lengths, array, Entries); flag = false; } int num6 = (flag ? num : 0); int[] array2 = null; int[] array3 = null; if (!flag) { array3 = new int[Entries]; } else if (num6 != 0) { array = new int[num6]; array3 = new int[num6]; array2 = new int[num6]; } if (!ComputeCodewords(flag, array3, array, _lengths, Entries, array2)) { throw new InvalidDataException(); } IReadOnlyList<int> readOnlyList = array2; IReadOnlyList<int> value = readOnlyList ?? FastRange.Get(0, array3.Length); huffman.GenerateTable(value, array ?? _lengths, array3); _prefixList = huffman.PrefixTree; _prefixBitLength = huffman.TableBits; _overflowList = huffman.OverflowList; } } private bool ComputeCodewords(bool sparse, int[] codewords, int[] codewordLengths, int[] len, int n, int[] values) { int num = 0; uint[] array = new uint[32]; int i; for (i = 0; i < n && len[i] <= 0; i++) { } if (i == n) { return true; } AddEntry(sparse, codewords, codewordLengths, 0u, i, num++, len[i], values); for (int j = 1; j <= len[i]; j++) { array[j] = (uint)(1 << 32 - j); } for (int j = i + 1; j < n; j++) { int num2 = len[j]; if (num2 <= 0) { continue; } while (num2 > 0 && array[num2] == 0) { num2--; } if (num2 == 0) { return false; } uint num3 = array[num2]; array[num2] = 0u; AddEntry(sparse, codewords, codewordLengths, Utils.BitReverse(num3), j, num++, len[j], values); if (num2 != len[j]) { for (int num4 = len[j]; num4 > num2; num4--) { array[num4] = num3 + (uint)(1 << 32 - num4); } } } return true; } private void AddEntry(bool sparse, int[] codewords, int[] codewordLengths, uint huffCode, int symbol, int count, int len, int[] values) { if (sparse) { codewords[count] = (int)huffCode; codewordLengths[count] = len; values[count] = symbol; } else { codewords[symbol] = (int)huffCode; } } private void InitLookupTable(IPacket packet) { MapType = (int)packet.ReadBits(4); if (MapType == 0) { return; } float num = Utils.ConvertFromVorbisFloat32((uint)packet.ReadBits(32)); float num2 = Utils.ConvertFromVorbisFloat32((uint)packet.ReadBits(32)); int count = (int)packet.ReadBits(4) + 1; bool flag = packet.ReadBit(); int num3 = Entries * Dimensions; float[] array = new float[num3]; if (MapType == 1) { num3 = lookup1_values(); } uint[] array2 = new uint[num3]; for (int i = 0; i < num3; i++) { array2[i] = (uint)packet.ReadBits(count); } if (MapType == 1) { for (int j = 0; j < Entries; j++) { double num4 = 0.0; int num5 = 1; for (int k = 0; k < Dimensions; k++) { int num6 = j / num5 % num3; double num7 = (double)((float)array2[num6] * num2 + num) + num4; array[j * Dimensions + k] = (float)num7; if (flag) { num4 = num7; } num5 *= num3; } } } else { for (int l = 0; l < Entries; l++) { double num8 = 0.0; int num9 = l * Dimensions; for (int m = 0; m < Dimensions; m++) { double num10 = (double)((float)array2[num9] * num2 + num) + num8; array[l * Dimensions + m] = (float)num10; if (flag) { num8 = num10; } num9++; } } } _lookupTable = array; } private int lookup1_values() { int num = (int)Math.Floor(Math.Exp(Math.Log(Entries) / (double)Dimensions)); if (Math.Floor(Math.Pow(num + 1, Dimensions)) <= (double)Entries) { num++; } return num; } public int DecodeScalar(IPacket packet) { int index = (int)packet.TryPeekBits(_prefixBitLength, out var bitsRead); if (bitsRead == 0) { return -1; } HuffmanListNode huffmanListNode = _prefixList[index]; if (huffmanListNode != null) { packet.SkipBits(huffmanListNode.Length); return huffmanListNode.Value; } index = (int)packet.TryPeekBits(_maxBits, out var _); for (int i = 0; i < _overflowList.Count; i++) { huffmanListNode = _overflowList[i]; if (huffmanListNode.Bits == (index & huffmanListNode.Mask)) { packet.SkipBits(huffmanListNode.Length); return huffmanListNode.Value; } } return -1; } } internal abstract class DataPacket : IPacket { [Flags] protected enum PacketFlags : byte { IsResync = 1, IsEndOfStream = 2, IsShort = 4, User0 = 8, User1 = 0x10, User2 = 0x20, User3 = 0x40, User4 = 0x80 } private ulong _bitBucket; private int _bitCount; private byte _overflowBits; private PacketFlags _packetFlags; private int _readBits; public int ContainerOverheadBits { get; set; } public long? GranulePosition { get; set; } public bool IsResync { get { return GetFlag(PacketFlags.IsResync); } set { SetFlag(PacketFlags.IsResync, value); } } public bool IsShort { get { return GetFlag(PacketFlags.IsShort); } private set { SetFlag(PacketFlags.IsShort, value); } } public bool IsEndOfStream { get { return GetFlag(PacketFlags.IsEndOfStream); } set { SetFlag(PacketFlags.IsEndOfStream, value); } } public int BitsRead => _readBits; public int BitsRemaining => TotalBits - _readBits; protected abstract int TotalBits { get; } private bool GetFlag(PacketFlags flag) { return _packetFlags.HasFlag(flag); } private void SetFlag(PacketFlags flag, bool value) { if (value) { _packetFlags |= flag; } else { _packetFlags &= (PacketFlags)(byte)(~(int)flag); } } protected abstract int ReadNextByte(); public virtual void Done() { } public virtual void Reset() { _bitBucket = 0uL; _bitCount = 0; _overflowBits = 0; _readBits = 0; } ulong IPacket.ReadBits(int count) { if (count == 0) { return 0uL; } int bitsRead; ulong result = TryPeekBits(count, out bitsRead); SkipBits(count); return result; } public ulong TryPeekBits(int count, out int bitsRead) { switch (count) { default: throw new ArgumentOutOfRangeException("count"); case 0: bitsRead = 0; return 0uL; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: break; } while (_bitCount < count) { int num = ReadNextByte(); if (num == -1) { bitsRead = _bitCount; return _bitBucket; } _bitBucket = (ulong)((long)(num & 0xFF) << _bitCount) | _bitBucket; _bitCount += 8; if (_bitCount > 64) { _overflowBits = (byte)(num >> 72 - _bitCount); } } ulong num2 = _bitBucket; if (count < 64) { num2 &= (ulong)((1L << count) - 1); } bitsRead = count; return num2; } public void SkipBits(int count) { if (count <= 0) { return; } if (_bitCount > count) { if (count > 63) { _bitBucket = 0uL; } else { _bitBucket >>= count; } if (_bitCount > 64) { int num = _bitCount - 64; _bitBucket |= (ulong)_overflowBits << _bitCount - count - num; if (num > count) { _overflowBits = (byte)(_overflowBits >> count); } } _bitCount -= count; _readBits += count; return; } if (_bitCount == count) { _bitBucket = 0uL; _bitCount = 0; _readBits += count; return; } count -= _bitCount; _readBits += _bitCount; _bitCount = 0; _bitBucket = 0uL; while (count > 8) { if (ReadNextByte() == -1) { count = 0; IsShort = true; break; } count -= 8; _readBits += 8; } if (count > 0) { int num2 = ReadNextByte(); if (num2 == -1) { IsShort = true; return; } _bitBucket = (ulong)(num2 >> count); _bitCount = 8 - count; _readBits += count; } } } internal static class Extensions { public static int Read(this IPacket packet, byte[] buffer, int index, int count) { if (index < 0 || index >= buffer.Length) { throw new ArgumentOutOfRangeException("index"); } if (count < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("count"); } for (int i = 0; i < count; i++) { int bitsRead; byte b = (byte)packet.TryPeekBits(8, out bitsRead); if (bitsRead == 0) { return i; } buffer[index++] = b; packet.SkipBits(8); } return count; } public static byte[] ReadBytes(this IPacket packet, int count) { byte[] array = new byte[count]; int num = packet.Read(array, 0, count); if (num < count) { byte[] array2 = new byte[num]; Buffer.BlockCopy(array, 0, array2, 0, num); return array2; } return array; } public static bool ReadBit(this IPacket packet) { return packet.ReadBits(1) == 1; } public static byte PeekByte(this IPacket packet) { int bitsRead; return (byte)packet.TryPeekBits(8, out bitsRead); } public static byte ReadByte(this IPacket packet) { return (byte)packet.ReadBits(8); } public static short ReadInt16(this IPacket packet) { return (short)packet.ReadBits(16); } public static int ReadInt32(this IPacket packet) { return (int)packet.ReadBits(32); } public static long ReadInt64(this IPacket packet) { return (long)packet.ReadBits(64); } public static ushort ReadUInt16(this IPacket packet) { return (ushort)packet.ReadBits(16); } public static uint ReadUInt32(this IPacket packet) { return (uint)packet.ReadBits(32); } public static ulong ReadUInt64(this IPacket packet) { return packet.ReadBits(64); } public static void SkipBytes(this IPacket packet, int count) { packet.SkipBits(count * 8); } } internal class Factory : IFactory { public IHuffman CreateHuffman() { return new Huffman(); } public IMdct CreateMdct() { return new Mdct(); } public ICodebook CreateCodebook() { return new Codebook(); } public IFloor CreateFloor(IPacket packet) { return (int)packet.ReadBits(16) switch { 0 => new Floor0(), 1 => new Floor1(), _ => throw new InvalidDataException("Invalid floor type!"), }; } public IMapping CreateMapping(IPacket packet) { if (packet.ReadBits(16) != 0L) { throw new InvalidDataException("Invalid mapping type!"); } return new Mapping(); } public IMode CreateMode() { return new Mode(); } public IResidue CreateResidue(IPacket packet) { return (int)packet.ReadBits(16) switch { 0 => new Residue0(), 1 => new Residue1(), 2 => new Residue2(), _ => throw new InvalidDataException("Invalid residue type!"), }; } } internal class Floor0 : IFloor { private class Data : IFloorData { internal float[] Coeff; internal float Amp; public bool ExecuteChannel { get { if (ForceEnergy || Amp > 0f) { return !ForceNoEnergy; } return false; } } public bool ForceEnergy { get; set; } public bool ForceNoEnergy { get; set; } } private int _order; private int _rate; private int _bark_map_size; private int _ampBits; private int _ampOfs; private int _ampDiv; private ICodebook[] _books; private int _bookBits; private Dictionary<int, float[]> _wMap; private Dictionary<int, int[]> _barkMaps; public void Init(IPacket packet, int channels, int block0Size, int block1Size, ICodebook[] codebooks) { _order = (int)packet.ReadBits(8); _rate = (int)packet.ReadBits(16); _bark_map_size = (int)packet.ReadBits(16); _ampBits = (int)packet.ReadBits(6); _ampOfs = (int)packet.ReadBits(8); _books = new ICodebook[(int)packet.ReadBits(4) + 1]; if (_order < 1 || _rate < 1 || _bark_map_size < 1 || _books.Length == 0) { throw new InvalidDataException(); } _ampDiv = (1 << _ampBits) - 1; for (int i = 0; i < _books.Length; i++) { int num = (int)packet.ReadBits(8); if (num < 0 || num >= codebooks.Length) { throw new InvalidDataException(); } ICodebook codebook = codebooks[num]; if (codebook.MapType == 0 || codebook.Dimensions < 1) { throw new InvalidDataException(); } _books[i] = codebook; } _bookBits = Utils.ilog(_books.Length); _barkMaps = new Dictionary<int, int[]> { [block0Size] = SynthesizeBarkCurve(block0Size / 2), [block1Size] = SynthesizeBarkCurve(block1Size / 2) }; _wMap = new Dictionary<int, float[]> { [block0Size] = SynthesizeWDelMap(block0Size / 2), [block1Size] = SynthesizeWDelMap(block1Size / 2) }; } private int[] SynthesizeBarkCurve(int n) { float num = (float)_bark_map_size / toBARK(_rate / 2); int[] array = new int[n + 1]; for (int i = 0; i < n - 1; i++) { array[i] = Math.Min(_bark_map_size - 1, (int)Math.Floor(toBARK((float)_rate / 2f / (float)n * (float)i) * num)); } array[n] = -1; return array; } private static float toBARK(double lsp) { return (float)(13.1 * Math.Atan(0.00074 * lsp) + 2.24 * Math.Atan(1.85E-08 * lsp * lsp) + 0.0001 * lsp); } private float[] SynthesizeWDelMap(int n) { float num = (float)(Math.PI / (double)_bark_map_size); float[] array = new float[n]; for (int i = 0; i < n; i++) { array[i] = 2f * (float)Math.Cos(num * (float)i); } return array; } public IFloorData Unpack(IPacket packet, int blockSize, int channel) { Data data = new Data { Coeff = new float[_order + 1] }; data.Amp = packet.ReadBits(_ampBits); if (data.Amp > 0f) { Array.Clear(data.Coeff, 0, data.Coeff.Length); data.Amp = data.Amp / (float)_ampDiv * (float)_ampOfs; uint num = (uint)packet.ReadBits(_bookBits); if (num >= _books.Length) { data.Amp = 0f; return data; } ICodebook codebook = _books[num]; int i = 0; while (i < _order) { int num2 = codebook.DecodeScalar(packet); if (num2 == -1) { data.Amp = 0f; return data; } int num3 = 0; for (; i < _order; i++) { if (num3 >= codebook.Dimensions) { break; } data.Coeff[i] = codebook[num2, num3]; num3++; } } float num4 = 0f; int num5 = 0; while (num5 < _order) { int num6 = 0; while (num5 < _order && num6 < codebook.Dimensions) { data.Coeff[num5] += num4; num5++; num6++; } num4 = data.Coeff[num5 - 1]; } } return data; } public void Apply(IFloorData floorData, int blockSize, float[] residue) { if (!(floorData is Data data)) { throw new ArgumentException("Incorrect packet data!"); } int num = blockSize / 2; if (data.Amp > 0f) { int[] array = _barkMaps[blockSize]; float[] array2 = _wMap[blockSize]; int num2 = 0; for (num2 = 0; num2 < _order; num2++) { data.Coeff[num2] = 2f * (float)Math.Cos(data.Coeff[num2]); } num2 = 0; while (num2 < num) { int num3 = array[num2]; float num4 = 0.5f; float num5 = 0.5f; float num6 = array2[num3]; int i; for (i = 1; i < _order; i += 2) { num5 *= num6 - data.Coeff[i - 1]; num4 *= num6 - data.Coeff[i]; } if (i == _order) { num5 *= num6 - data.Coeff[i - 1]; num4 *= num4 * (4f - num6 * num6); num5 *= num5; } else { num4 *= num4 * (2f - num6); num5 *= num5 * (2f + num6); } num5 = data.Amp / (float)Math.Sqrt(num4 + num5) - (float)_ampOfs; num5 = (float)Math.Exp(num5 * 0.11512925f); residue[num2] *= num5; while (array[++num2] == num3) { residue[num2] *= num5; } } } else { Array.Clear(residue, 0, num); } } } internal class Floor1 : IFloor { private class Data : IFloorData { internal int[] Posts = new int[64]; internal int PostCount; public bool ExecuteChannel { get { if (ForceEnergy || PostCount > 0) { return !ForceNoEnergy; } return false; } } public bool ForceEnergy { get; set; } public bool ForceNoEnergy { get; set; } } private int[] _partitionClass; private int[] _classDimensions; private int[] _classSubclasses; private int[] _xList; private int[] _classMasterBookIndex; private int[] _hNeigh; private int[] _lNeigh; private int[] _sortIdx; private int _multiplier; private int _range; private int _yBits; private ICodebook[] _classMasterbooks; private ICodebook[][] _subclassBooks; private int[][] _subclassBookIndex; private static readonly int[] _rangeLookup = new int[4] { 256, 128, 86, 64 }; private static readonly int[] _yBitsLookup = new int[4] { 8, 7, 7, 6 }; private static readonly float[] inverse_dB_table = new float[256] { 1.0649863E-07f, 1.1341951E-07f, 1.2079015E-07f, 1.2863978E-07f, 1.369995E-07f, 1.459025E-07f, 1.5538409E-07f, 1.6548181E-07f, 1.7623574E-07f, 1.8768856E-07f, 1.998856E-07f, 2.128753E-07f, 2.2670913E-07f, 2.4144197E-07f, 2.5713223E-07f, 2.7384212E-07f, 2.9163792E-07f, 3.1059022E-07f, 3.307741E-07f, 3.5226967E-07f, 3.7516213E-07f, 3.995423E-07f, 4.255068E-07f, 4.5315863E-07f, 4.8260745E-07f, 5.1397E-07f, 5.4737063E-07f, 5.829419E-07f, 6.208247E-07f, 6.611694E-07f, 7.041359E-07f, 7.4989464E-07f, 7.98627E-07f, 8.505263E-07f, 9.057983E-07f, 9.646621E-07f, 1.0273513E-06f, 1.0941144E-06f, 1.1652161E-06f, 1.2409384E-06f, 1.3215816E-06f, 1.4074654E-06f, 1.4989305E-06f, 1.5963394E-06f, 1.7000785E-06f, 1.8105592E-06f, 1.9282195E-06f, 2.053526E-06f, 2.1869757E-06f, 2.3290977E-06f, 2.4804558E-06f, 2.6416496E-06f, 2.813319E-06f, 2.9961443E-06f, 3.1908505E-06f, 3.39821E-06f, 3.619045E-06f, 3.8542307E-06f, 4.1047006E-06f, 4.371447E-06f, 4.6555283E-06f, 4.958071E-06f, 5.280274E-06f, 5.623416E-06f, 5.988857E-06f, 6.3780467E-06f, 6.7925284E-06f, 7.2339453E-06f, 7.704048E-06f, 8.2047E-06f, 8.737888E-06f, 9.305725E-06f, 9.910464E-06f, 1.0554501E-05f, 1.1240392E-05f, 1.1970856E-05f, 1.2748789E-05f, 1.3577278E-05f, 1.4459606E-05f, 1.5399271E-05f, 1.6400005E-05f, 1.7465769E-05f, 1.8600793E-05f, 1.9809577E-05f, 2.1096914E-05f, 2.2467912E-05f, 2.3928002E-05f, 2.5482977E-05f, 2.7139005E-05f, 2.890265E-05f, 3.078091E-05f, 3.2781227E-05f, 3.4911533E-05f, 3.718028E-05f, 3.9596467E-05f, 4.2169668E-05f, 4.491009E-05f, 4.7828602E-05f, 5.0936775E-05f, 5.424693E-05f, 5.7772202E-05f, 6.152657E-05f, 6.552491E-05f, 6.9783084E-05f, 7.4317984E-05f, 7.914758E-05f, 8.429104E-05f, 8.976875E-05f, 9.560242E-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, 0.00015820454f, 0.00016848555f, 0.00017943469f, 0.00019109536f, 0.00020351382f, 0.0002167393f, 0.00023082423f, 0.00024582449f, 0.00026179955f, 0.00027881275f, 0.00029693157f, 0.00031622787f, 0.00033677815f, 0.00035866388f, 0.00038197188f, 0.00040679457f, 0.00043323037f, 0.0004613841f, 0.0004913675f, 0.00052329927f, 0.0005573062f, 0.0005935231f, 0.0006320936f, 0.0006731706f, 0.000716917f, 0.0007635063f, 0.00081312325f, 0.00086596457f, 0.00092223985f, 0.0009821722f, 0.0010459992f, 0.0011139743f, 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, 0.0019632196f, 0.0020908006f, 0.0022266726f, 0.0023713743f, 0.0025254795f, 0.0026895993f, 0.0028643848f, 0.0030505287f, 0.003248769f, 0.0034598925f, 0.0036847359f, 0.0039241905f, 0.0041792067f, 0.004450795f, 0.004740033f, 0.005048067f, 0.0053761187f, 0.005725489f, 0.0060975635f, 0.0064938175f, 0.0069158226f, 0.0073652514f, 0.007843887f, 0.008353627f, 0.008896492f, 0.009474637f, 0.010090352f, 0.01074608f, 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, 0.014722068f, 0.015678791f, 0.016697686f, 0.017782796f, 0.018938422f, 0.020169148f, 0.021479854f, 0.022875736f, 0.02436233f, 0.025945531f, 0.027631618f, 0.029427277f, 0.031339627f, 0.03337625f, 0.035545226f, 0.037855156f, 0.0403152f, 0.042935107f, 0.045725275f, 0.048696756f, 0.05186135f, 0.05523159f, 0.05882085f, 0.062643364f, 0.06671428f, 0.07104975f, 0.075666964f, 0.08058423f, 0.08582105f, 0.09139818f, 0.097337745f, 0.1036633f, 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, 0.14201812f, 0.15124726f, 0.16107617f, 0.1715438f, 0.18269168f, 0.19456401f, 0.20720787f, 0.22067343f, 0.23501402f, 0.25028655f, 0.26655158f, 0.28387362f, 0.3023213f, 0.32196787f, 0.34289113f, 0.36517414f, 0.3889052f, 0.41417846f, 0.44109413f, 0.4697589f, 0.50028646f, 0.53279793f, 0.5674221f, 0.6042964f, 0.64356697f, 0.6853896f, 0.72993004f, 0.777365f, 0.8278826f, 0.88168305f, 0.9389798f, 1f }; public void Init(IPacket packet, int channels, int block0Size, int block1Size, ICodebook[] codebooks) { int num = -1; _partitionClass = new int[(uint)packet.ReadBits(5)]; for (int i = 0; i < _partitionClass.Length; i++) { _partitionClass[i] = (int)packet.ReadBits(4); if (_partitionClass[i] > num) { num = _partitionClass[i]; } } _classDimensions = new int[++num]; _classSubclasses = new int[num]; _classMasterbooks = new ICodebook[num]; _classMasterBookIndex = new int[num]; _subclassBooks = new ICodebook[num][]; _subclassBookIndex = new int[num][]; for (int j = 0; j < num; j++) { _classDimensions[j] = (int)packet.ReadBits(3) + 1; _classSubclasses[j] = (int)packet.ReadBits(2); if (_classSubclasses[j] > 0) { _classMasterBookIndex[j] = (int)packet.ReadBits(8); _classMasterbooks[j] = codebooks[_classMasterBookIndex[j]]; } _subclassBooks[j] = new ICodebook[1 << _classSubclasses[j]]; _subclassBookIndex[j] = new int[_subclassBooks[j].Length]; for (int k = 0; k < _subclassBooks[j].Length; k++) { int num2 = (int)packet.ReadBits(8) - 1; if (num2 >= 0) { _subclassBooks[j][k] = codebooks[num2]; } _subclassBookIndex[j][k] = num2; } } _multiplier = (int)packet.ReadBits(2); _range = _rangeLookup[_multiplier]; _yBits = _yBitsLookup[_multiplier]; _multiplier++; int num3 = (int)packet.ReadBits(4); List<int> list = new List<int>(); list.Add(0); list.Add(1 << num3); for (int l = 0; l < _partitionClass.Length; l++) { int num4 = _partitionClass[l]; for (int m = 0; m < _classDimensions[num4]; m++) { list.Add((int)packet.ReadBits(num3)); } } _xList = list.ToArray(); _lNeigh = new int[list.Count]; _hNeigh = new int[list.Count]; _sortIdx = new int[list.Count]; _sortIdx[0] = 0; _sortIdx[1] = 1; for (int n = 2; n < _lNeigh.Length; n++) { _lNeigh[n] = 0; _hNeigh[n] = 1; _sortIdx[n] = n; for (int num5 = 2; num5 < n; num5++) { int num6 = _xList[num5]; if (num6 < _xList[n]) { if (num6 > _xList[_lNeigh[n]]) { _lNeigh[n] = num5; } } else if (num6 < _xList[_hNeigh[n]]) { _hNeigh[n] = num5; } } } for (int num7 = 0; num7 < _sortIdx.Length - 1; num7++) { for (int num8 = num7 + 1; num8 < _sortIdx.Length; num8++) { if (_xList[num7] == _xList[num8]) { throw new InvalidDataException(); } if (_xList[_sortIdx[num7]] > _xList[_sortIdx[num8]]) { int num9 = _sortIdx[num7]; _sortIdx[num7] = _sortIdx[num8]; _sortIdx[num8] = num9; } } } } public IFloorData Unpack(IPacket packet, int blockSize, int channel) { Data data = new Data(); if (packet.ReadBit()) { int num = 2; data.Posts[0] = (int)packet.ReadBits(_yBits); data.Posts[1] = (int)packet.ReadBits(_yBits); for (int i = 0; i < _partitionClass.Length; i++) { int num2 = _partitionClass[i]; int num3 = _classDimensions[num2]; int num4 = _classSubclasses[num2]; int num5 = (1 << num4) - 1; uint num6 = 0u; if (num4 > 0 && (num6 = (uint)_classMasterbooks[num2].DecodeScalar(packet)) == uint.MaxValue) { num = 0; break; } for (int j = 0; j < num3; j++) { ICodebook codebook = _subclassBooks[num2][num6 & num5]; num6 >>= num4; if (codebook != null && (data.Posts[num] = codebook.DecodeScalar(packet)) == -1) { num = 0; i = _partitionClass.Length; break; } num++; } } data.PostCount = num; } return data; } public void Apply(IFloorData floorData, int blockSize, float[] residue) { if (!(floorData is Data data)) { throw new ArgumentException("Incorrect packet data!", "packetData"); } int num = blockSize / 2; if (data.PostCount > 0) { bool[] array = UnwrapPosts(data); int num2 = 0; int num3 = data.Posts[0] * _multiplier; for (int i = 1; i < data.PostCount; i++) { int num4 = _sortIdx[i]; if (array[num4]) { int num5 = _xList[num4]; int num6 = data.Posts[num4] * _multiplier; if (num2 < num) { RenderLineMulti(num2, num3, Math.Min(num5, num), num6, residue); } num2 = num5; num3 = num6; } if (num2 >= num) { break; } } if (num2 < num) { RenderLineMulti(num2, num3, num, num3, residue); } } else { Array.Clear(residue, 0, num); } } private bool[] UnwrapPosts(Data data) { bool[] array = new bool[64]; array[0] = true; array[1] = true; int[] array2 = new int[64]; array2[0] = data.Posts[0]; array2[1] = data.Posts[1]; for (int i = 2; i < data.PostCount; i++) { int num = _lNeigh[i]; int num2 = _hNeigh[i]; int num3 = RenderPoint(_xList[num], array2[num], _xList[num2], array2[num2], _xList[i]); int num4 = data.Posts[i]; int num5 = _range - num3; int num6 = num3; int num7 = ((num5 >= num6) ? (num6 * 2) : (num5 * 2)); if (num4 != 0) { array[num] = true; array[num2] = true; array[i] = true; if (num4 >= num7) { if (num5 > num6) { array2[i] = num4 - num6 + num3; } else { array2[i] = num3 - num4 + num5 - 1; } } else if (num4 % 2 == 1) { array2[i] = num3 - (num4 + 1) / 2; } else { array2[i] = num3 + num4 / 2; } } else { array[i] = false; array2[i] = num3; } } for (int j = 0; j < data.PostCount; j++) { data.Posts[j] = array2[j]; } return array; } private int RenderPoint(int x0, int y0, int x1, int y1, int X) { int num = y1 - y0; int num2 = x1 - x0; int num3 = Math.Abs(num) * (X - x0) / num2; if (num < 0) { return y0 - num3; } return y0 + num3; } private void RenderLineMulti(int x0, int y0, int x1, int y1, float[] v) { int num = y1 - y0; int num2 = x1 - x0; int num3 = Math.Abs(num); int num4 = 1 - ((num >> 31) & 1) * 2; int num5 = num / num2; int num6 = x0; int num7 = y0; int num8 = -num2; v[x0] *= inverse_dB_table[y0]; num3 -= Math.Abs(num5) * num2; while (++num6 < x1) { num7 += num5; num8 += num3; if (num8 >= 0) { num8 -= num2; num7 += num4; } v[num6] *= inverse_dB_table[num7]; } } } internal class Huffman : IHuffman, IComparer<HuffmanListNode> { private const int MAX_TABLE_BITS = 10; public int TableBits { get; private set; } public IReadOnlyList<HuffmanListNode> PrefixTree { get; private set; } public IReadOnlyList<HuffmanListNode> OverflowList { get; private set; } public void GenerateTable(IReadOnlyList<int> values, int[] lengthList, int[] codeList) { HuffmanListNode[] array = new HuffmanListNode[lengthList.Length]; int num = 0; for (int i = 0; i < array.Length; i++) { array[i] = new HuffmanListNode { Value = values[i], Length = ((lengthList[i] <= 0) ? 99999 : lengthList[i]), Bits = codeList[i], Mask = (1 << lengthList[i]) - 1 }; if (lengthList[i] > 0 && num < lengthList[i]) { num = lengthList[i]; } } Array.Sort(array, 0, array.Length, this); int num2 = ((num > 10) ? 10 : num); List<HuffmanListNode> list = new List<HuffmanListNode>(1 << num2); List<HuffmanListNode> list2 = null; for (int j = 0; j < array.Length && array[j].Length < 99999; j++) { int length = array[j].Length; if (length > num2) { list2 = new List<HuffmanListNode>(array.Length - j); for (; j < array.Length && array[j].Length < 99999; j++) { list2.Add(array[j]); } continue; } int num3 = 1 << num2 - length; HuffmanListNode huffmanListNode = array[j]; for (int k = 0; k < num3; k++) { int num4 = (k << length) | huffmanListNode.Bits; while (list.Count <= num4) { list.Add(null); } list[num4] = huffmanListNode; } } while (list.Count < 1 << num2) { list.Add(null); } TableBits = num2; PrefixTree = list; OverflowList = list2; } int IComparer<HuffmanListNode>.Compare(HuffmanListNode x, HuffmanListNode y) { int num = x.Length - y.Length; if (num == 0) { return x.Bits - y.Bits; } return num; } } [Obsolete("Moved to NVorbis.Contracts.IContainerReader", true)] internal interface IContainerReader : NVorbis.Contracts.IContainerReader, IDisposable { [Obsolete("Use Streams.Select(s => s.StreamSerial).ToArray() instead.", true)] int[] StreamSerials { get; } [Obsolete("No longer supported.", true)] int PagesRead { get; } [Obsolete("Moved to NewStreamCallback.", true)] event EventHandler<NewStreamEventArgs> NewStream; [Obsolete("Renamed to TryInit().", true)] bool Init(); [Obsolete("No longer supported.", true)] int GetTotalPageCount(); } [Obsolete("Moved to NVorbis.Contracts.IPacketProvider", true)] internal interface IPacketProvider : NVorbis.Contracts.IPacketProvider { [Obsolete("Moved to per-stream IStreamStats instance on IStreamDecoder.Stats or VorbisReader.Stats.", true)] long ContainerBits { get; } [Obsolete("No longer supported.", true)] event EventHandler ParameterChange; [Obsolete("No longer supported.", true)] int GetTotalPageCount(); [Obsolete("Getting a packet by index is no longer supported.", true)] DataPacket GetPacket(int packetIndex); [Obsolete("Moved to long SeekTo(long, int, GetPacketGranuleCount)", true)] DataPacket FindPacket(long granulePos, Func<DataPacket, DataPacket, int> packetGranuleCountCallback); [Obsolete("Seeking to a specified packet is no longer supported. See SeekTo(...) instead.", true)] void SeekToPacket(DataPacket packet, int preRoll); } [Obsolete("Moved to NVorbis.Contracts.IStreamStats", true)] internal interface IVorbisStreamStatus : IStreamStats { [Obsolete("No longer supported.", true)] TimeSpan PageLatency { get; } [Obsolete("No longer supported.", true)] TimeSpan PacketLatency { get; } [Obsolete("No longer supported.", true)] TimeSpan SecondLatency { get; } [Obsolete("No longer supported.", true)] int PagesRead { get; } [Obsolete("No longer supported.", true)] int TotalPages { get; } [Obsolete("Use IStreamDecoder.HasClipped instead. VorbisReader.HasClipped will return the same value for the stream it is handling.", true)] bool Clipped { get; } } internal class Mapping : IMapping { private IMdct _mdct; private int[] _couplingAngle; private int[] _couplingMangitude; private IFloor[] _submapFloor; private IResidue[] _submapResidue; private IFloor[] _channelFloor; private IResidue[] _channelResidue; public void Init(IPacket packet, int channels, IFloor[] floors, IResidue[] residues, IMdct mdct) { int num = 1; if (packet.ReadBit()) { num += (int)packet.ReadBits(4); } int num2 = 0; if (packet.ReadBit()) { num2 = (int)packet.ReadBits(8) + 1; } int count = Utils.ilog(channels - 1); _couplingAngle = new int[num2]; _couplingMangitude = new int[num2]; for (int i = 0; i < num2; i++) { int num3 = (int)packet.ReadBits(count); int num4 = (int)packet.ReadBits(count); if (num3 == num4 || num3 > channels - 1 || num4 > channels - 1) { throw new InvalidDataException("Invalid magnitude or angle in mapping header!"); } _couplingAngle[i] = num4; _couplingMangitude[i] = num3; } if (packet.ReadBits(2) != 0L) { throw new InvalidDataException("Reserved bits not 0 in mapping header."); } int[] array = new int[channels]; if (num > 1) { for (int j = 0; j < channels; j++) { array[j] = (int)packet.ReadBits(4); if (array[j] > num) { throw new InvalidDataException("Invalid channel mux submap index in mapping header!"); } } } _submapFloor = new IFloor[num]; _submapResidue = new IResidue[num]; for (int k = 0; k < num; k++) { packet.SkipBits(8); int num5 = (int)packet.ReadBits(8); if (num5 >= floors.Length) { throw new InvalidDataException("Invalid floor number in mapping header!"); } int num6 = (int)packet.ReadBits(8); if (num6 >= residues.Length) { throw new InvalidDataException("Invalid residue number in mapping header!"); } _submapFloor[k] = floors[num5]; _submapResidue[k] = residues[num6]; } _channelFloor = new IFloor[channels]; _channelResidue = new IResidue[channels]; for (int l = 0; l < channels; l++) { _channelFloor[l] = _submapFloor[array[l]]; _channelResidue[l] = _submapResidue[array[l]]; } _mdct = mdct; } public void DecodePacket(IPacket packet, int blockSize, int channels, float[][] buffer) { int num = blockSize >> 1; IFloorData[] array = new IFloorData[_channelFloor.Length]; bool[] array2 = new bool[_channelFloor.Length]; for (int i = 0; i < _channelFloor.Length; i++) { array[i] = _channelFloor[i].Unpack(packet, blockSize, i); array2[i] = !array[i].ExecuteChannel; Array.Clear(buffer[i], 0, num); } for (int j = 0; j < _couplingAngle.Length; j++) { if (array[_couplingAngle[j]].ExecuteChannel || array[_couplingMangitude[j]].ExecuteChannel) { array[_couplingAngle[j]].ForceEnergy = true; array[_couplingMangitude[j]].ForceEnergy = true; } } for (int k = 0; k < _submapFloor.Length; k++) { for (int l = 0; l < _channelFloor.Length; l++) { if (_submapFloor[k] != _channelFloor[l] || _submapResidue[k] != _channelResidue[l]) { array[l].ForceNoEnergy = true; } } _submapResidue[k].Decode(packet, array2, blockSize, buffer); } for (int num2 = _couplingAngle.Length - 1; num2 >= 0; num2--) { if (array[_couplingAngle[num2]].ExecuteChannel || array[_couplingMangitude[num2]].ExecuteChannel) { float[] array3 = buffer[_couplingMangitude[num2]]; float[] array4 = buffer[_couplingAngle[num2]]; for (int m = 0; m < num; m++) { float num3 = array3[m]; float num4 = array4[m]; float num5; float num6; if (num3 > 0f) { if (num4 > 0f) { num5 = num3; num6 = num3 - num4; } else { num6 = num3; num5 = num3 + num4; } } else if (num4 > 0f) { num5 = num3; num6 = num3 + num4; } else { num6 = num3; num5 = num3 - num4; } array3[m] = num5; array4[m] = num6; } } } for (int n = 0; n < _channelFloor.Length; n++) { if (array[n].ExecuteChannel) { _channelFloor[n].Apply(array[n], blockSize, buffer[n]); _mdct.Reverse(buffer[n], blockSize); } else { Array.Clear(buffer[n], num, num); } } } } internal class Mdct : IMdct { private class MdctImpl { private readonly int _n; private readonly int _n2; private readonly int _n4; private readonly int _n8; private readonly int _ld; private readonly float[] _a; private readonly float[] _b; private readonly float[] _c; private readonly ushort[] _bitrev; public MdctImpl(int n) { _n = n; _n2 = n >> 1; _n4 = _n2 >> 1; _n8 = _n4 >> 1; _ld = Utils.ilog(n) - 1; _a = new float[_n2]; _b = new float[_n2]; _c = new float[_n4]; int num; int num2 = (num = 0); while (num2 < _n4) { _a[num] = (float)Math.Cos((float)(4 * num2) * MathF.PI / (float)n); _a[num + 1] = (float)(0.0 - Math.Sin((float)(4 * num2) * MathF.PI / (float)n)); _b[num] = (float)Math.Cos((float)(num + 1) * MathF.PI / (float)n / 2f) * 0.5f; _b[num + 1] = (float)Math.Sin((float)(num + 1) * MathF.PI / (float)n / 2f) * 0.5f; num2++; num += 2; } num2 = (num = 0); while (num2 < _n8) { _c[num] = (float)Math.Cos((float)(2 * (num + 1)) * MathF.PI / (float)n); _c[num + 1] = (float)(0.0 - Math.Sin((float)(2 * (num + 1)) * MathF.PI / (float)n)); num2++; num += 2; } _bitrev = new ushort[_n8]; for (int i = 0; i < _n8; i++) { _bitrev[i] = (ushort)(Utils.BitReverse((uint)i, _ld - 3) << 2); } } internal void CalcReverse(float[] buffer) { float[] array = new float[_n2]; int num = _n2 - 2; int num2 = 0; int i = 0; for (int n = _n2; i != n; i += 4) { array[num + 1] = buffer[i] * _a[num2] - buffer[i + 2] * _a[num2 + 1]; array[num] = buffer[i] * _a[num2 + 1] + buffer[i + 2] * _a[num2]; num -= 2; num2 += 2; } i = _n2 - 3; while (num >= 0) { array[num + 1] = (0f - buffer[i + 2]) * _a[num2] - (0f - buffer[i]) * _a[num2 + 1]; array[num] = (0f - buffer[i + 2]) * _a[num2 + 1] + (0f - buffer[i]) * _a[num2]; num -= 2; num2 += 2; i -= 4; } float[] array2 = array; int num3 = _n2 - 8; int num4 = _n4; int num5 = 0; int num6 = _n4; int num7 = 0; while (num3 >= 0) { float num8 = array2[num4 + 1] - array2[num5 + 1]; float num9 = array2[num4] - array2[num5]; buffer[num6 + 1] = array2[num4 + 1] + array2[num5 + 1]; buffer[num6] = array2[num4] + array2[num5]; buffer[num7 + 1] = num8 * _a[num3 + 4] - num9 * _a[num3 + 5]; buffer[num7] = num9 * _a[num3 + 4] + num8 * _a[num3 + 5]; num8 = array2[num4 + 3] - array2[num5 + 3]; num9 = array2[num4 + 2] - array2[num5 + 2]; buffer[num6 + 3] = array2[num4 + 3] + array2[num5 + 3]; buffer[num6 + 2] = array2[num4 + 2] + array2[num5 + 2]; buffer[num7 + 3] = num8 * _a[num3] - num9 * _a[num3 + 1]; buffer[num7 + 2] = num9 * _a[num3] + num8 * _a[num3 + 1]; num3 -= 8; num6 += 4; num7 += 4; num4 += 4; num5 += 4; } int n2 = _n >> 4; int num10 = _n2 - 1; _ = _n4; step3_iter0_loop(n2, buffer, num10 - 0, -_n8); step3_iter0_loop(_n >> 4, buffer, _n2 - 1 - _n4, -_n8); int lim = _n >> 5; int num11 = _n2 - 1; _ = _n8; step3_inner_r_loop(lim, buffer, num11 - 0, -(_n >> 4), 16); step3_inner_r_loop(_n >> 5, buffer, _n2 - 1 - _n8, -(_n >> 4), 16); step3_inner_r_loop(_n >> 5, buffer, _n2 - 1 - _n8 * 2, -(_n >> 4), 16); step3_inner_r_loop(_n >> 5, buffer, _n2 - 1 - _n8 * 3, -(_n >> 4), 16); int j; for (j = 2; j < _ld - 3 >> 1; j++) { int num12 = _n >> j + 2; int num13 = num12 >> 1; int num14 = 1 << j + 1; for (int k = 0; k < num14; k++) { step3_inner_r_loop(_n >> j + 4, buffer, _n2 - 1 - num12 * k, -num13, 1 << j + 3); } } for (; j < _ld - 6; j++) { int num15 = _n >> j + 2; int num16 = 1 << j + 3; int num17 = num15 >> 1; int num18 = _n >> j + 6; int n3 = 1 << j + 1; int num19 = _n2 - 1; int num20 = 0; for (int num21 = num18; num21 > 0; num21--) { step3_inner_s_loop(n3, buffer, num19, -num17, num20, num16, num15); num20 += num16 * 4; num19 -= 8; } } step3_inner_s_loop_ld654(_n >> 5, buffer, _n2 - 1, _n); int num22 = 0; int num23 = _n4 - 4; int num24 = _n2 - 4; while (num23 >= 0) { int num25 = _bitrev[num22]; array2[num24 + 3] = buffer[num25]; array2[num24 + 2] = buffer[num25 + 1]; array2[num23 + 3] = buffer[num25 + 2]; array2[num23 + 2] = buffer[num25 + 3]; num25 = _bitrev[num22 + 1]; array2[num24 + 1] = buffer[num25]; array2[num24] = buffer[num25 + 1]; array2[num23 + 1] = buffer[num25 + 2]; array2[num23] = buffer[num25 + 3]; num23 -= 4; num24 -= 4; num22 += 2; } int num26 = 0; int num27 = 0; int num28 = _n2 - 4; while (num27 < num28) { float num29 = array2[num27] - array2[num28 + 2]; float num30 = array2[num27 + 1] + array2[num28 + 3]; float num31 = _c[num26 + 1] * num29 + _c[num26] * num30; float num32 = _c[num26 + 1] * num30 - _c[num26] * num29; float num33 = array2[num27] + array2[num28 + 2]; float num34 = array2[num27 + 1] - array2[num28 + 3]; array2[num27] = num33 + num31; array2[num27 + 1] = num34 + num32; array2[num28 + 2] = num33 - num31; array2[num28 + 3] = num32 - num34; num29 = array2[num27 + 2] - array2[num28]; num30 = array2[num27 + 3] + array2[num28 + 1]; num31 = _c[num26 + 3] * num29 + _c[num26 + 2] * num30; num32 = _c[num26 + 3] * num30 - _c[num26 + 2] * num29; num33 = array2[num27 + 2] + array2[num28]; num34 = array2[num27 + 3] - array2[num28 + 1]; array2[num27 + 2] = num33 + num31; array2[num27 + 3] = num34 + num32; array2[num28] = num33 - num31; array2[num28 + 1] = num32 - num34; num26 += 4; num27 += 4; num28 -= 4; } int num35 = _n2 - 8; int num36 = _n2 - 8; int num37 = 0; int num38 = _n2 - 4; int num39 = _n2; int num40 = _n - 4; while (num36 >= 0) { float num41 = array[num36 + 6] * _b[num35 + 7] - array[num36 + 7] * _b[num35 + 6]; float num42 = (0f - array[num36 + 6]) * _b[num35 + 6] - array[num36 + 7] * _b[num35 + 7]; buffer[num37] = num41; buffer[num38 + 3] = 0f - num41; buffer[num39] = num42; buffer[num40 + 3] = num42; float num43 = array[num36 + 4] * _b[num35 + 5] - array[num36 + 5] * _b[num35 + 4]; float num44 = (0f - array[num36 + 4]) * _b[num35 + 4] - array[num36 + 5] * _b[num35 + 5]; buffer[num37 + 1] = num43; buffer[num38 + 2] = 0f - num43; buffer[num39 + 1] = num44; buffer[num40 + 2] = num44; num41 = array[num36 + 2] * _b[num35 + 3] - array[num36 + 3] * _b[num35 + 2]; num42 = (0f - array[num36 + 2]) * _b[num35 + 2] - array[num36 + 3] * _b[num35 + 3]; buffer[num37 + 2] = num41; buffer[num38 + 1] = 0f - num41; buffer[num39 + 2] = num42; buffer[num40 + 1] = num42; num43 = array[num36] * _b[num35 + 1] - array[num36 + 1] * _b[num35]; num44 = (0f - array[num36]) * _b[num35] - array[num36 + 1] * _b[num35 + 1]; buffer[num37 + 3] = num43; buffer[num38] = 0f - num43; buffer[num39 + 3] = num44; buffer[num40] = num44; num35 -= 8; num36 -= 8; num37 += 4; num39 += 4; num38 -= 4; num40 -= 4; } } private void step3_iter0_loop(int n, float[] e, int i_off, int k_off) { int num = i_off; int num2 = num + k_off; int num3 = 0; for (int num4 = n >> 2; num4 > 0; num4--) { float num5 = e[num] - e[num2]; float num6 = e[num - 1] - e[num2 - 1]; e[num] += e[num2]; e[num - 1] += e[num2 - 1]; e[num2] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 1] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += 8; num5 = e[num - 2] - e[num2 - 2]; num6 = e[num - 3] - e[num2 - 3]; e[num - 2] += e[num2 - 2]; e[num - 3] += e[num2 - 3]; e[num2 - 2] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 3] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += 8; num5 = e[num - 4] - e[num2 - 4]; num6 = e[num - 5] - e[num2 - 5]; e[num - 4] += e[num2 - 4]; e[num - 5] += e[num2 - 5]; e[num2 - 4] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 5] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += 8; num5 = e[num - 6] - e[num2 - 6]; num6 = e[num - 7] - e[num2 - 7]; e[num - 6] += e[num2 - 6]; e[num - 7] += e[num2 - 7]; e[num2 - 6] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 7] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += 8; num -= 8; num2 -= 8; } } private void step3_inner_r_loop(int lim, float[] e, int d0, int k_off, int k1) { int num = d0; int num2 = num + k_off; int num3 = 0; for (int num4 = lim >> 2; num4 > 0; num4--) { float num5 = e[num] - e[num2]; float num6 = e[num - 1] - e[num2 - 1]; e[num] += e[num2]; e[num - 1] += e[num2 - 1]; e[num2] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 1] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += k1; num5 = e[num - 2] - e[num2 - 2]; num6 = e[num - 3] - e[num2 - 3]; e[num - 2] += e[num2 - 2]; e[num - 3] += e[num2 - 3]; e[num2 - 2] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 3] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += k1; num5 = e[num - 4] - e[num2 - 4]; num6 = e[num - 5] - e[num2 - 5]; e[num - 4] += e[num2 - 4]; e[num - 5] += e[num2 - 5]; e[num2 - 4] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 5] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += k1; num5 = e[num - 6] - e[num2 - 6]; num6 = e[num - 7] - e[num2 - 7]; e[num - 6] += e[num2 - 6]; e[num - 7] += e[num2 - 7]; e[num2 - 6] = num5 * _a[num3] - num6 * _a[num3 + 1]; e[num2 - 7] = num6 * _a[num3] + num5 * _a[num3 + 1]; num3 += k1; num -= 8; num2 -= 8; } } private void step3_inner_s_loop(int n, float[] e, int i_off, int k_off, int a, int a_off, int k0) { float num = _a[a]; float num2 = _a[a + 1]; float num3 = _a[a + a_off]; float num4 = _a[a + a_off + 1]; float num5 = _a[a + a_off * 2]; float num6 = _a[a + a_off * 2 + 1]; float num7 = _a[a + a_off * 3]; float num8 = _a[a + a_off * 3 + 1]; int num9 = i_off; int num10 = num9 + k_off; for (int num11 = n; num11 > 0; num11--) { float num12 = e[num9] - e[num10]; float num13 = e[num9 - 1] - e[num10 - 1]; e[num9] += e[num10]; e[num9 - 1] += e[num10 - 1]; e[num10] = num12 * num - num13 * num2; e[num10 - 1] = num13 * num + num12 * num2; num12 = e[num9 - 2] - e[num10 - 2]; num13 = e[num9 - 3] - e[num10 - 3]; e[num9 - 2] += e[num10 - 2]; e[num9 - 3] += e[num10 - 3]; e[num10 - 2] = num12 * num3 - num13 * num4; e[num10 - 3] = num13 * num3 + num12 * num4; num12 = e[num9 - 4] - e[num10 - 4]; num13 = e[num9 - 5] - e[num10 - 5]; e[num9 - 4] += e[num10 - 4]; e[num9 - 5] += e[num10 - 5]; e[num10 - 4] = num12 * num5 - num13 * num6; e[num10 - 5] = num13 * num5 + num12 * num6; num12 = e[num9 - 6] - e[num10 - 6]; num13 = e[num9 - 7] - e[num10 - 7]; e[num9 - 6] += e[num10 - 6]; e[num9 - 7] += e[num10 - 7]; e[num10 - 6] = num12 * num7 - num13 * num8; e[num10 - 7] = num13 * num7 + num12 * num8; num9 -= k0; num10 -= k0; } } private void step3_inner_s_loop_ld654(int n, float[] e, int i_off, int base_n) { int num = base_n >> 3; float num2 = _a[num]; int num3 = i_off; int num4 = num3 - 16 * n; while (num3 > num4) { float num5 = e[num3] - e[num3 - 8]; float num6 = e[num3 - 1] - e[num3 - 9]; e[num3] += e[num3 - 8]; e[num3 - 1] += e[num3 - 9]; e[num3 - 8] = num5; e[num3 - 9] = num6; num5 = e[num3 - 2] - e[num3 - 10]; num6 = e[num3 - 3] - e[num3 - 11]; e[num3 - 2] += e[num3 - 10]; e[num3 - 3] += e[num3 - 11]; e[num3 - 10] = (num5 + num6) * num2; e[num3 - 11] = (num6 - num5) * num2; num5 = e[num3 - 12] - e[num3 - 4]; num6 = e[num3 - 5] - e[num3 - 13]; e[num3 - 4] += e[num3 - 12]; e[num3 - 5] += e[num3 - 13]; e[num3 - 12] = num6; e[num3 - 13] = num5; num5 = e[num3 - 14] - e[num3 - 6]; num6 = e[num3 - 7] - e[num3 - 15]; e[num3 - 6] += e[num3 - 14]; e[num3 - 7] += e[num3 - 15]; e[num3 - 14] = (num5 + num6) * num2; e[num3 - 15] = (num5 - num6) * num2; iter_54(e, num3); iter_54(e, num3 - 8); num3 -= 16; } } private void iter_54(float[] e, int z) { float num = e[z] - e[z - 4]; float num2 = e[z] + e[z - 4]; float num3 = e[z - 2] + e[z - 6]; float num4 = e[z - 2] - e[z - 6]; e[z] = num2 + num3; e[z - 2] = num2 - num3; float num5 = e[z - 3] - e[z - 7]; e[z - 4] = num + num5; e[z - 6] = num - num5; float num6 = e[z - 1] - e[z - 5]; float num7 = e[z - 1] + e[z - 5]; float num8 = e[z - 3] + e[z - 7]; e[z - 1] = num7 + num8; e[z - 3] = num7 - num8; e[z - 5] = num6 - num4; e[z - 7] = num6 + num4; } } private const float M_PI = MathF.PI; private Dictionary<int, MdctImpl> _setupCache = new Dictionary<int, MdctImpl>(); public void Reverse(float[] samples, int sampleCount) { if (!_setupCache.TryGetValue(sampleCount, out var value)) { value = new MdctImpl(sampleCount); _setupCache[sampleCount] = value; } value.CalcReverse(samples); } } internal class Mode : IMode { private struct OverlapInfo { public int PacketStartIndex; public int PacketTotalLength; public int PacketValidLength; } private const float M_PI2 = MathF.PI / 2f; private int _channels; private bool _blockFlag; private int _blockSize; private IMapping _mapping; private float[][] _windows; private OverlapInfo[] _overlapInfo; public void Init(IPacket packet, int channels, int block0Size, int block1Size, IMapping[] mappings) { _channels = channels; _blockFlag = packet.ReadBit(); if (packet.ReadBits(32) != 0L) { throw new InvalidDataException("Mode header had invalid window or transform type!"); } int num = (int)packet.ReadBits(8); if (num >= mappings.Length) { throw new InvalidDataException("Mode header had invalid mapping index!"); } _mapping = mappings[num]; if (_blockFlag) { _blockSize = block1Size; _windows = new float[4][] { CalcWindow(block0Size, block1Size, block0Size), CalcWindow(block1Size, block1Size, block0Size), CalcWindow(block0Size, block1Size, block1Size), CalcWindow(block1Size, block1Size, block1Size) }; _overlapInfo = new OverlapInfo[4] { CalcOverlap(block0Size, block1Size, block0Size), CalcOverlap(block1Size, block1Size, block0Size), CalcOverlap(block0Size, block1Size, block1Size), CalcOverlap(block1Size, block1Size, block1Size) }; } else { _blockSize = block0Size; _windows = new float[1][] { CalcWindow(block0Size, block0Size, block0Size) }; } } private static float[] CalcWindow(int prevBlockSize, int blockSize, int nextBlockSize) { float[] array = new float[blockSize]; int num = prevBlockSize / 2; int num2 = nextBlockSize / 2; int num3 = blockSize / 4 - num / 2; int num4 = blockSize - blockSize / 4 - num2 / 2; for (int i = 0; i < num; i++) { float num5 = (float)Math.Sin(((double)i + 0.5) / (double)num * 1.5707963705062866); num5 *= num5; array[num3 + i] = (float)Math.Sin(num5 * (MathF.PI / 2f)); } for (int j = num3 + num; j < num4; j++) { array[j] = 1f; } for (int k = 0; k < num2; k++) { float num6 = (float)Math.Sin(((double)(num2 - k) - 0.5) / (double)num2 * 1.5707963705062866); num6 *= num6; array[num4 + k] = (float)Math.Sin(num6 * (MathF.PI / 2f)); } return array; } private static OverlapInfo CalcOverlap(int prevBlockSize, int blockSize, int nextBlockSize) { int num = prevBlockSize / 4; int num2 = nextBlockSize / 4; int packetStartIndex = blockSize / 4 - num; int num3 = blockSize / 4 * 3 + num2; int packetValidLength = num3 - num2 * 2; OverlapInfo result = default(OverlapInfo); result.PacketStartIndex = packetStartIndex; result.PacketValidLength = packetValidLength; result.PacketTotalLength = num3; return result; } private bool GetPacketInfo(IPacket packet, out int windowIndex, out int packetStartIndex, out int packetValidLength, out int packetTotalLength) { if (packet.IsShort) { windowIndex = 0; packetStartIndex = 0; packetValidLength = 0; packetTotalLength = 0; return false; } if (_blockFlag) { bool flag = packet.ReadBit(); bool flag2 = packet.ReadBit(); windowIndex = (flag ? 1 : 0) + (flag2 ? 2 : 0); OverlapInfo overlapInfo = _overlapInfo[windowIndex]; packetStartIndex = overlapInfo.PacketStartIndex; packetValidLength = overlapInfo.PacketValidLength; packetTotalLength = overlapInfo.PacketTotalLength; } else { windowIndex = 0; packetStartIndex = 0; packetValidLength = _blockSize / 2; packetTotalLength = _blockSize; } return true; } public bool Decode(IPacket packet, float[][] buffer, out int packetStartindex, out int packetValidLength, out int packetTotalLength) { if (GetPacketInfo(packet, out var windowIndex, out packetStartindex, out packetValidLength, out packetTotalLength)) { _mapping.DecodePacket(packet, _blockSize, _channels, buffer); float[] array = _windows[windowIndex]; for (int i = 0; i < _blockSize; i++) { for (int j = 0; j < _channels; j++) { buffer[j][i] *= array[i]; } } return true; } return false; } public int GetPacketSampleCount(IPacket packet) { GetPacketInfo(packet, out var _, out var packetStartIndex, out var packetValidLength, out var _); return packetValidLength - packetStartIndex; } } [Serializable] internal class NewStreamEventArgs : EventArgs { public IStreamDecoder StreamDecoder { get; } public bool IgnoreStream { get; set; } public NewStreamEventArgs(IStreamDecoder streamDecoder) { StreamDecoder = streamDecoder ?? throw new ArgumentNullException("streamDecoder"); } } internal class Residue0 : IResidue { private int _channels; private int _begin; private int _end; private int _partitionSize; private int _classifications; private int _maxStages; private ICodebook[][] _books; private ICodebook _classBook; private int[] _cascade; private int[][] _decodeMap; private static int icount(int v) { int num = 0; while (v != 0) { num += v & 1; v >>= 1; } return num; } public virtual void Init(IPacket packet, int channels, ICodebook[] codebooks) { _begin = (int)packet.ReadBits(24); _end = (int)packet.ReadBits(24); _partitionSize = (int)packet.ReadBits(24) + 1; _classifications = (int)packet.ReadBits(6) + 1; _classBook = codebooks[(uint)packet.ReadBits(8)]; _cascade = new int[_classifications]; int num = 0; for (int i = 0; i < _classifications; i++) { int num2 = (int)packet.ReadBits(3); if (packet.ReadBit()) { _cascade[i] = ((int)packet.ReadBits(5) << 3) | num2; } else { _cascade[i] = num2; } num += icount(_cascade[i]); } int[] array = new int[num]; for (int j = 0; j < num; j++) { array[j] = (int)packet.ReadBits(8); if (codebooks[array[j]].MapType == 0) { throw new InvalidDataException(); } } int entries = _classBook.Entries; int num3 = _classBook.Dimensions; int num4 = 1; while (num3 > 0) { num4 *= _classifications; if (num4 > entries) { throw new InvalidDataException(); } num3--; } _books = new ICodebook[_classifications][]; num = 0; int num5 = 0; for (int k = 0; k < _classifications; k++) { int num6 = Utils.ilog(_cascade[k]); _books[k] = new ICodebook[num6]; if (num6 <= 0) { continue; } num5 = Math.Max(num5, num6); for (int l = 0; l < num6; l++) { if ((_cascade[k] & (1 << l)) > 0) { _books[k][l] = codebooks[array[num++]]; } } } _maxStages = num5; _decodeMap = new int[num4][]; for (int m = 0; m < num4; m++) { int num7 = m; int num8 = num4 / _classifications; _decodeMap[m] = new int[_classBook.Dimensions]; for (int n = 0; n < _classBook.Dimensions; n++) { int num9 = num7 / num8; num7 -= num9 * num8; num8 /= _classifications; _decodeMap[m][n] = num9; } } _channels = channels; } public virtual void Decode(IPacket packet, bool[] doNotDecodeChannel, int blockSize, float[][] buffer) { int num = ((_end < blockSize / 2) ? _end : (blockSize / 2)) - _begin; if (num <= 0 || Array.IndexOf(doNotDecodeChannel, value: false) == -1) { return; } int num2 = num / _partitionSize; int num3 = (num2 + _classBook.Dimensions - 1) / _classBook.Dimensions; int[,][] array = new int[_channels, num3][]; for (int i = 0; i < _maxStages; i++) { int j = 0; int num4 = 0; while (j < num2) { if (i == 0) { for (int k = 0; k < _channels; k++) { int num5 = _classBook.DecodeScalar(packet); if (num5 >= 0 && num5 < _decodeMap.Length) { array[k, num4] = _decodeMap[num5]; continue; } j = num2; i = _maxStages; break; } } int num6 = 0; for (; j < num2; j++) { if (num6 >= _classBook.Dimensions) { break; } int offset = _begin + j * _partitionSize; for (int l = 0; l < _channels; l++) { int num7 = array[l, num4][num6]; if ((_cascade[num7] & (1 << i)) != 0) { ICodebook codebook = _books[num7][i]; if (codebook != null && WriteVectors(codebook, packet, buffer, l, offset, _partitionSize)) { j = num2; i = _maxStages; break; } } } num6++; } num4++; } } } protected virtual bool WriteVectors(ICodebook codebook, IPacket packet, float[][] residue, int channel, int offset, int partitionSize) { float[] array = residue[channel]; int num = partitionSize / codebook.Dimensions; int[] array2 = new int[num]; for (int i = 0; i < num; i++) { if ((array2[i] = codebook.DecodeScalar(packet)) == -1) { return true; } } for (int j = 0; j < codebook.Dimensions; j++) { int num2 = 0; while (num2 < num) { array[offset] += codebook[array2[num2], j]; num2++; offset++; } } return false; } } internal class Residue1 : Residue0 { protected override bool WriteVectors(ICodebook codebook, IPacket packet, float[][] residue, int channel, int offset, int partitionSize) { float[] array = residue[channel]; int num = 0; while (num < partitionSize) { int num2 = codebook.DecodeScalar(packet); if (num2 == -1) { return true; } for (int i = 0; i < codebook.Dimensions; i++) { array[offset + num] += codebook[num2, i]; num++; } } return false; } } internal class Residue2 : Residue0 { private int _channels; public override void Init(IPacket packet, int channels, ICodebook[] codebooks) { _channels = channels; base.Init(packet, 1, codebooks); } public override void Decode(IPacket packet, bool[] doNotDecodeChannel, int blockSize, float[][] buffer) { base.Decode(packet, doNotDecodeChannel, blockSize * _channels, buffer); } protected override bool WriteVectors(ICodebook codebook, IPacket packet, float[][] residue, int channel, int offset, int partitionSize) { int num = 0; offset /= _channels; int num2 = 0; while (num2 < partitionSize) { int num3 = codebook.DecodeScalar(packet); if (num3 == -1) { return true; } int num4 = 0; while (num4 < codebook.Dimensions) { residue[num][offset] += codebook[num3, num4]; if (++num == _channels) { num = 0; offset++; } num4++; num2++; } } return false; } } internal sealed class StreamDecoder : IStreamDecoder, IDisposable { private NVorbis.Contracts.IPacketProvider _packetProvider; private IFactory _factory; private StreamStats _stats; private byte _channels; private int _sampleRate; private int _block0Size; private int _block1Size; private IMode[] _modes; private int _modeFieldBits; private string _vendor; private string[] _comments; private ITagData _tags; private long _currentPosition; private bool _hasClipped; private bool _hasPosition; private bool _eosFound; private float[][] _nextPacketBuf; private float[][] _prevPacketBuf; private int _prevPacketStart; private int _prevPacketEnd; private int _prevPacketStop; private static readonly byte[] PacketSignatureStream = new byte[11] { 1, 118, 111, 114, 98, 105, 115, 0, 0, 0, 0 }; private static readonly byte[] PacketSignatureComments = new byte[7] { 3, 118, 111, 114, 98, 105, 115 }; private static readonly byte[] PacketSignatureBooks = new byte[7] { 5, 118, 111, 114, 98, 105, 115 }; internal static Func<IFactory> CreateFactory { get; set; } = () => new Factory(); public int Channels => _channels; public int SampleRate => _sampleRate; public int UpperBitrate { get; private set; } public int NominalBitrate { get; private set; } public int LowerBitrate { get; private set; } public ITagData Tags => _tags ?? (_tags = new TagData(_vendor, _comments)); public TimeSpan TotalTime => TimeSpan.FromSeconds((double)TotalSamples / (double)_sampleRate); public long TotalSamples => (_packetProvider ?? throw new ObjectDisposedException("StreamDecoder")).GetGranuleCount(); public TimeSpan TimePosition { get { return TimeSpan.FromSeconds((double)_currentPosition / (double)_sampleRate); } set { SeekTo(value); } } public long SamplePosition { get { return _currentPosition; } set { SeekTo(value); } } public bool ClipSamples { get; set; } public bool HasClipped => _hasClipped; public bool IsEndOfStream { get { if (_eosFound) { return _prevPacketBuf == null; } return false; } } public IStreamStats Stats => _stats; public StreamDecoder(NVorbis.Contracts.IPacketProvider packetProvider) : this(packetProvider, new Factory()) { } internal StreamDecoder(NVorbis.Contracts.IPacketProvider packetProvider, IFactory factory) { _packetProvider = packetProvider ?? throw new ArgumentNullException("packetProvider"); _factory = factory ?? throw new ArgumentNullException("factory"); _stats = new StreamStats(); _currentPosition = 0L; ClipSamples = true; IPacket packet = _packetProvider.PeekNextPacket(); if (!ProcessHeaderPackets(packet)) { _packetProvider = null; packet.Reset(); throw GetInvalidStreamException(packet); } } private static Exception GetInvalidStreamException(IPacket packet) { try { ulong num = packet.ReadBits(64); if (num == 7233173838382854223L) { return new ArgumentException("Found OPUS bitstream."); } if ((num & 0xFF) == 127) { return new ArgumentException("Found FLAC bitstream."); } switch (num) { case 2314885909937746003uL: return new ArgumentException("Found Speex bitstream."); case 28254585843050854uL: return new ArgumentException("Found Skeleton metadata bitstream."); default: if ((num & 0xFFFFFFFFFFFF00L) == 27428895509214208L) { return new ArgumentException("Found Theora bitsream."); } return new ArgumentException("Could not find Vorbis data to decode."); } } finally { packet.Reset(); } } private bool ProcessHeaderPackets(IPacket packet) { if (!ProcessHeaderPacket(packet, LoadStreamHeader, delegate { _packetProvider.GetNextPacket().Done(); })) { return false; } if (!ProcessHeaderPacket(_packetProvider.GetNextPacket(), LoadComments, delegate(IPacket pkt) { pkt.Done(); })) { return false; } if (!ProcessHeaderPacket(_packetProvider.GetNextPacket(), LoadBooks, delegate(IPacket pkt) { pkt.Done(); })) { return false; } _currentPosition = 0L; ResetDecoder(); return true; } private static bool ProcessHeaderPacket(IPacket packet, Func<IPacket, bool> processAction, Action<IPacket> doneAction) { if (packet != null) { try { return processAction(packet); } finally { doneAction(packet); } } return false; } private static bool ValidateHeader(IPacket packet, byte[] expected) { for (int i = 0; i < expected.Length; i++) { if (expected[i] != packet.ReadBits(8)) { return false; } } return true; } private static string ReadString(IPacket packet) { int num = (int)packet.ReadBits(32); if (num == 0) { return string.Empty; } byte[] array = new byte[num]; if (packet.Read(array, 0, num) < num) { throw new InvalidDataException("Could not read full string!"); } return Encoding.UTF8.GetString(array); } private bool LoadStreamHeader(IPacket packet) { if (!ValidateHeader(packet, PacketSignatureStream)) { return false; } _channels = (byte)packet.ReadBits(8); _sampleRate = (int)packet.ReadBits(32); UpperBitrate = (int)packet.ReadBits(32); NominalBitrate = (int)packet.ReadBits(32); LowerBitrate = (int)packet.ReadBits(32); _block0Size = 1 << (int)packet.ReadBits(4); _block1Size = 1 << (int)packet.ReadBits(4); if (NominalBitrate == 0 && UpperBitrate > 0 && LowerBitrate > 0) { NominalBitrate = (UpperBitrate + LowerBitrate) / 2; } _stats.SetSampleRate(_sampleRate); _stats.AddPacket(-1, packet.BitsRead, packet.BitsRemaining, packet.ContainerOverheadBits); return true; } private bool LoadComments(IPacket packet) { if (!ValidateHeader(packet, PacketSignatureComments)) { return false; }