Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Weak Kingsley v1.0.1
NVorbis.dll
Decompiled 12 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using NVorbis.Ogg; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Andrew Ward")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © Andrew Ward 2018")] [assembly: AssemblyDescription("A fully managed implementation of a Xiph.org Foundation Ogg Vorbis decoder.")] [assembly: AssemblyFileVersion("0.8.6.0")] [assembly: AssemblyInformationalVersion("0.8.6.0")] [assembly: AssemblyProduct("NVorbis")] [assembly: AssemblyTitle("NVorbis")] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("0.8.6.0")] namespace NVorbis { internal class BufferedReadStream : Stream { private const int DEFAULT_INITIAL_SIZE = 32768; private const int DEFAULT_MAX_SIZE = 262144; private Stream _baseStream; private StreamReadBuffer _buffer; private long _readPosition; private object _localLock = new object(); private Thread _owningThread; private int _lockCount; public bool CloseBaseStream { get; set; } public bool MinimalRead { get { return _buffer.MinimalRead; } set { _buffer.MinimalRead = value; } } public int MaxBufferSize { get { return _buffer.MaxSize; } set { CheckLock(); _buffer.MaxSize = value; } } public long BufferBaseOffset => _buffer.BaseOffset; public int BufferBytesFilled => _buffer.BytesFilled; public override bool CanRead => true; public override bool CanSeek => true; public override bool CanWrite => false; public override long Length => _baseStream.Length; public override long Position { get { return _readPosition; } set { Seek(value, SeekOrigin.Begin); } } public BufferedReadStream(Stream baseStream) : this(baseStream, 32768, 262144, minimalRead: false) { } public BufferedReadStream(Stream baseStream, bool minimalRead) : this(baseStream, 32768, 262144, minimalRead) { } public BufferedReadStream(Stream baseStream, int initialSize, int maxSize) : this(baseStream, initialSize, maxSize, minimalRead: false) { } public BufferedReadStream(Stream baseStream, int initialSize, int maxBufferSize, bool minimalRead) { if (baseStream == null) { throw new ArgumentNullException("baseStream"); } if (!baseStream.CanRead) { throw new ArgumentException("baseStream"); } if (maxBufferSize < 1) { maxBufferSize = 1; } if (initialSize < 1) { initialSize = 1; } if (initialSize > maxBufferSize) { initialSize = maxBufferSize; } _baseStream = baseStream; _buffer = new StreamReadBuffer(baseStream, initialSize, maxBufferSize, minimalRead); _buffer.MaxSize = maxBufferSize; _buffer.MinimalRead = minimalRead; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { if (_buffer != null) { _buffer.Dispose(); _buffer = null; } if (CloseBaseStream) { _baseStream.Close(); } } } public void TakeLock() { Monitor.Enter(_localLock); if (++_lockCount == 1) { _owningThread = Thread.CurrentThread; } } private void CheckLock() { if (_owningThread != Thread.CurrentThread) { throw new SynchronizationLockException(); } } public void ReleaseLock() { CheckLock(); if (--_lockCount == 0) { _owningThread = null; } Monitor.Exit(_localLock); } public void Discard(int bytes) { CheckLock(); _buffer.DiscardThrough(_buffer.BaseOffset + bytes); } public void DiscardThrough(long offset) { CheckLock(); _buffer.DiscardThrough(offset); } public override void Flush() { } public override int ReadByte() { CheckLock(); int num = _buffer.ReadByte(Position); if (num > -1) { Seek(1L, SeekOrigin.Current); } return num; } public override int Read(byte[] buffer, int offset, int count) { CheckLock(); int num = _buffer.Read(Position, buffer, offset, count); Seek(num, SeekOrigin.Current); return num; } public override long Seek(long offset, SeekOrigin origin) { CheckLock(); switch (origin) { case SeekOrigin.Current: offset += Position; break; case SeekOrigin.End: offset += _baseStream.Length; break; } if (!_baseStream.CanSeek) { if (offset < _buffer.BaseOffset) { throw new InvalidOperationException("Cannot seek to before the start of the buffer!"); } if (offset >= _buffer.BufferEndOffset) { throw new InvalidOperationException("Cannot seek to beyond the end of the buffer! Discard some bytes."); } } return _readPosition = offset; } public override void SetLength(long value) { throw new NotSupportedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } } public abstract class DataPacket { [Flags] protected enum PacketFlags : byte { IsResync = 1, IsEndOfStream = 2, IsShort = 4, HasGranuleCount = 8, User1 = 0x10, User2 = 0x20, User3 = 0x40, User4 = 0x80 } private ulong _bitBucket; private int _bitCount; private int _readBits; private byte _overflowBits; private PacketFlags _packetFlags; private long _granulePosition; private long _pageGranulePosition; private int _length; private int _granuleCount; private int _pageSequenceNumber; public bool IsResync { get { return GetFlag(PacketFlags.IsResync); } internal set { SetFlag(PacketFlags.IsResync, value); } } public long GranulePosition { get { return _granulePosition; } set { _granulePosition = value; } } public long PageGranulePosition { get { return _pageGranulePosition; } internal set { _pageGranulePosition = value; } } public int Length { get { return _length; } protected set { _length = value; } } public bool IsEndOfStream { get { return GetFlag(PacketFlags.IsEndOfStream); } internal set { SetFlag(PacketFlags.IsEndOfStream, value); } } public long BitsRead => _readBits; public int? GranuleCount { get { if (GetFlag(PacketFlags.HasGranuleCount)) { return _granuleCount; } return null; } set { if (value.HasValue) { _granuleCount = value.Value; SetFlag(PacketFlags.HasGranuleCount, value: true); } else { SetFlag(PacketFlags.HasGranuleCount, value: false); } } } internal int PageSequenceNumber { get { return _pageSequenceNumber; } set { _pageSequenceNumber = value; } } internal bool IsShort { get { return GetFlag(PacketFlags.IsShort); } private set { SetFlag(PacketFlags.IsShort, value); } } protected bool GetFlag(PacketFlags flag) { return (_packetFlags & flag) == flag; } protected void SetFlag(PacketFlags flag, bool value) { if (value) { _packetFlags |= flag; } else { _packetFlags &= (PacketFlags)(byte)(~(int)flag); } } protected DataPacket(int length) { Length = length; } protected abstract int ReadNextByte(); public virtual void Done() { } public ulong TryPeekBits(int count, out int bitsRead) { ulong num = 0uL; 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 num2 = ReadNextByte(); if (num2 == -1) { bitsRead = _bitCount; num = _bitBucket; _bitBucket = 0uL; _bitCount = 0; IsShort = true; return num; } _bitBucket = (ulong)((long)(num2 & 0xFF) << _bitCount) | _bitBucket; _bitCount += 8; if (_bitCount > 64) { _overflowBits = (byte)(num2 >> 72 - _bitCount); } } num = _bitBucket; if (count < 64) { num &= (ulong)((1L << count) - 1); } bitsRead = count; return num; } 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; } } protected void ResetBitReader() { _bitBucket = 0uL; _bitCount = 0; _readBits = 0; IsShort = false; } public ulong ReadBits(int count) { if (count == 0) { return 0uL; } int bitsRead; ulong result = TryPeekBits(count, out bitsRead); SkipBits(count); return result; } public byte PeekByte() { int bitsRead; return (byte)TryPeekBits(8, out bitsRead); } public byte ReadByte() { return (byte)ReadBits(8); } public byte[] ReadBytes(int count) { List<byte> list = new List<byte>(count); while (list.Count < count) { list.Add(ReadByte()); } return list.ToArray(); } public int Read(byte[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } for (int i = 0; i < count; i++) { int bitsRead; byte b = (byte)TryPeekBits(8, out bitsRead); if (bitsRead == 0) { return i; } buffer[index++] = b; SkipBits(8); } return count; } public bool ReadBit() { return ReadBits(1) == 1; } public short ReadInt16() { return (short)ReadBits(16); } public int ReadInt32() { return (int)ReadBits(32); } public long ReadInt64() { return (long)ReadBits(64); } public ushort ReadUInt16() { return (ushort)ReadBits(16); } public uint ReadUInt32() { return (uint)ReadBits(32); } public ulong ReadUInt64() { return ReadBits(64); } public void SkipBytes(int count) { SkipBits(count * 8); } } internal static class Huffman { private const int MAX_TABLE_BITS = 10; internal static List<HuffmanListNode> BuildPrefixedLinkedList(int[] values, int[] lengthList, int[] codeList, out int tableBits, out HuffmanListNode firstOverflowNode) { 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, SortCallback); tableBits = ((num > 10) ? 10 : num); List<HuffmanListNode> list = new List<HuffmanListNode>(1 << tableBits); firstOverflowNode = null; for (int j = 0; j < array.Length && array[j].Length < 99999; j++) { if (firstOverflowNode == null) { int length = array[j].Length; if (length > tableBits) { firstOverflowNode = array[j]; continue; } int num2 = 1 << tableBits - length; HuffmanListNode huffmanListNode = array[j]; for (int k = 0; k < num2; k++) { int num3 = (k << length) | huffmanListNode.Bits; while (list.Count <= num3) { list.Add(null); } list[num3] = huffmanListNode; } } else { array[j - 1].Next = array[j]; } } while (list.Count < 1 << tableBits) { list.Add(null); } return list; } private static int SortCallback(HuffmanListNode i1, HuffmanListNode i2) { int num = i1.Length - i2.Length; if (num == 0) { return i1.Bits - i2.Bits; } return num; } } internal class HuffmanListNode { internal int Value; internal int Length; internal int Bits; internal int Mask; internal HuffmanListNode Next; } public interface IContainerReader : IDisposable { int[] StreamSerials { get; } bool CanSeek { get; } long WasteBits { get; } int PagesRead { get; } event EventHandler<NewStreamEventArgs> NewStream; bool Init(); bool FindNextStream(); int GetTotalPageCount(); } public interface IPacketProvider : IDisposable { int StreamSerial { get; } bool CanSeek { get; } long ContainerBits { get; } event EventHandler<ParameterChangeEventArgs> ParameterChange; int GetTotalPageCount(); DataPacket GetNextPacket(); DataPacket PeekNextPacket(); DataPacket GetPacket(int packetIndex); long GetGranuleCount(); DataPacket FindPacket(long granulePos, Func<DataPacket, DataPacket, int> packetGranuleCountCallback); void SeekToPacket(DataPacket packet, int preRoll); } public interface IVorbisStreamStatus { int EffectiveBitRate { get; } int InstantBitRate { get; } TimeSpan PageLatency { get; } TimeSpan PacketLatency { get; } TimeSpan SecondLatency { get; } long OverheadBits { get; } long AudioBits { get; } int PagesRead { get; } int TotalPages { get; } bool Clipped { get; } void ResetStats(); } internal class Mdct { private const float M_PI = MathF.PI; private static Dictionary<int, Mdct> _setupCache = new Dictionary<int, Mdct>(2); private int _n; private int _n2; private int _n4; private int _n8; private int _ld; private float[] _A; private float[] _B; private float[] _C; private ushort[] _bitrev; private Dictionary<int, float[]> _threadLocalBuffers = new Dictionary<int, float[]>(1); public static void Reverse(float[] samples, int sampleCount) { GetSetup(sampleCount).CalcReverse(samples); } private static Mdct GetSetup(int n) { lock (_setupCache) { if (!_setupCache.ContainsKey(n)) { _setupCache[n] = new Mdct(n); } return _setupCache[n]; } } private Mdct(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 num2; int num = (num2 = 0); while (num < _n4) { _A[num2] = (float)Math.Cos((float)(4 * num) * MathF.PI / (float)n); _A[num2 + 1] = (float)(0.0 - Math.Sin((float)(4 * num) * MathF.PI / (float)n)); _B[num2] = (float)Math.Cos((float)(num2 + 1) * MathF.PI / (float)n / 2f) * 0.5f; _B[num2 + 1] = (float)Math.Sin((float)(num2 + 1) * MathF.PI / (float)n / 2f) * 0.5f; num++; num2 += 2; } num = (num2 = 0); while (num < _n8) { _C[num2] = (float)Math.Cos((float)(2 * (num2 + 1)) * MathF.PI / (float)n); _C[num2 + 1] = (float)(0.0 - Math.Sin((float)(2 * (num2 + 1)) * MathF.PI / (float)n)); num++; num2 += 2; } _bitrev = new ushort[_n8]; for (int i = 0; i < _n8; i++) { _bitrev[i] = (ushort)(Utils.BitReverse((uint)i, _ld - 3) << 2); } } private float[] GetBuffer() { lock (_threadLocalBuffers) { if (!_threadLocalBuffers.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var value)) { value = (_threadLocalBuffers[Thread.CurrentThread.ManagedThreadId] = new float[_n2]); } return value; } } private void CalcReverse(float[] buffer) { float[] buffer2 = GetBuffer(); int num = _n2 - 2; int num2 = 0; int i = 0; for (int n = _n2; i != n; i += 4) { buffer2[num + 1] = buffer[i] * _A[num2] - buffer[i + 2] * _A[num2 + 1]; buffer2[num] = buffer[i] * _A[num2 + 1] + buffer[i + 2] * _A[num2]; num -= 2; num2 += 2; } i = _n2 - 3; while (num >= 0) { buffer2[num + 1] = (0f - buffer[i + 2]) * _A[num2] - (0f - buffer[i]) * _A[num2 + 1]; buffer2[num] = (0f - buffer[i + 2]) * _A[num2 + 1] + (0f - buffer[i]) * _A[num2]; num -= 2; num2 += 2; i -= 4; } float[] array = buffer2; int num3 = _n2 - 8; int num4 = _n4; int num5 = 0; int num6 = _n4; int num7 = 0; while (num3 >= 0) { float num8 = array[num4 + 1] - array[num5 + 1]; float num9 = array[num4] - array[num5]; buffer[num6 + 1] = array[num4 + 1] + array[num5 + 1]; buffer[num6] = array[num4] + array[num5]; buffer[num7 + 1] = num8 * _A[num3 + 4] - num9 * _A[num3 + 5]; buffer[num7] = num9 * _A[num3 + 4] + num8 * _A[num3 + 5]; num8 = array[num4 + 3] - array[num5 + 3]; num9 = array[num4 + 2] - array[num5 + 2]; buffer[num6 + 3] = array[num4 + 3] + array[num5 + 3]; buffer[num6 + 2] = array[num4 + 2] + array[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]; array[num24 + 3] = buffer[num25]; array[num24 + 2] = buffer[num25 + 1]; array[num23 + 3] = buffer[num25 + 2]; array[num23 + 2] = buffer[num25 + 3]; num25 = _bitrev[num22 + 1]; array[num24 + 1] = buffer[num25]; array[num24] = buffer[num25 + 1]; array[num23 + 1] = buffer[num25 + 2]; array[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 = array[num27] - array[num28 + 2]; float num30 = array[num27 + 1] + array[num28 + 3]; float num31 = _C[num26 + 1] * num29 + _C[num26] * num30; float num32 = _C[num26 + 1] * num30 - _C[num26] * num29; float num33 = array[num27] + array[num28 + 2]; float num34 = array[num27 + 1] - array[num28 + 3]; array[num27] = num33 + num31; array[num27 + 1] = num34 + num32; array[num28 + 2] = num33 - num31; array[num28 + 3] = num32 - num34; num29 = array[num27 + 2] - array[num28]; num30 = array[num27 + 3] + array[num28 + 1]; num31 = _C[num26 + 3] * num29 + _C[num26 + 2] * num30; num32 = _C[num26 + 3] * num30 - _C[num26 + 2] * num29; num33 = array[num27 + 2] + array[num28]; num34 = array[num27 + 3] - array[num28 + 1]; array[num27 + 2] = num33 + num31; array[num27 + 3] = num34 + num32; array[num28] = num33 - num31; array[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 = buffer2[num36 + 6] * _B[num35 + 7] - buffer2[num36 + 7] * _B[num35 + 6]; float num42 = (0f - buffer2[num36 + 6]) * _B[num35 + 6] - buffer2[num36 + 7] * _B[num35 + 7]; buffer[num37] = num41; buffer[num38 + 3] = 0f - num41; buffer[num39] = num42; buffer[num40 + 3] = num42; float num43 = buffer2[num36 + 4] * _B[num35 + 5] - buffer2[num36 + 5] * _B[num35 + 4]; float num44 = (0f - buffer2[num36 + 4]) * _B[num35 + 4] - buffer2[num36 + 5] * _B[num35 + 5]; buffer[num37 + 1] = num43; buffer[num38 + 2] = 0f - num43; buffer[num39 + 1] = num44; buffer[num40 + 2] = num44; num41 = buffer2[num36 + 2] * _B[num35 + 3] - buffer2[num36 + 3] * _B[num35 + 2]; num42 = (0f - buffer2[num36 + 2]) * _B[num35 + 2] - buffer2[num36 + 3] * _B[num35 + 3]; buffer[num37 + 2] = num41; buffer[num38 + 1] = 0f - num41; buffer[num39 + 2] = num42; buffer[num40 + 1] = num42; num43 = buffer2[num36] * _B[num35 + 1] - buffer2[num36 + 1] * _B[num35]; num44 = (0f - buffer2[num36]) * _B[num35] - buffer2[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; } } [Serializable] public class NewStreamEventArgs : EventArgs { public IPacketProvider PacketProvider { get; private set; } public bool IgnoreStream { get; set; } public NewStreamEventArgs(IPacketProvider packetProvider) { if (packetProvider == null) { throw new ArgumentNullException("packetProvider"); } PacketProvider = packetProvider; } } [Serializable] public class ParameterChangeEventArgs : EventArgs { public DataPacket FirstPacket { get; private set; } public ParameterChangeEventArgs(DataPacket firstPacket) { FirstPacket = firstPacket; } } internal class RingBuffer { private float[] _buffer; private int _start; private int _end; private int _bufLen; internal int Channels; internal int Length { get { int num = _end - _start; if (num < 0) { num += _bufLen; } return num; } } internal RingBuffer(int size) { _buffer = new float[size]; _start = (_end = 0); _bufLen = size; } internal void EnsureSize(int size) { size += Channels; if (_bufLen < size) { float[] array = new float[size]; Array.Copy(_buffer, _start, array, 0, _bufLen - _start); if (_end < _start) { Array.Copy(_buffer, 0, array, _bufLen - _start, _end); } int length = Length; _start = 0; _end = length; _buffer = array; _bufLen = size; } } internal void CopyTo(float[] buffer, int index, int count) { if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } int start = _start; RemoveItems(count); int num = (_end - start + _bufLen) % _bufLen; if (count > num) { throw new ArgumentOutOfRangeException("count"); } int num2 = Math.Min(count, _bufLen - start); Buffer.BlockCopy(_buffer, start * 4, buffer, index * 4, num2 * 4); if (num2 < count) { Buffer.BlockCopy(_buffer, 0, buffer, (index + num2) * 4, (count - num2) * 4); } } internal void RemoveItems(int count) { int num = (count + _start) % _bufLen; if (_end > _start) { if (num > _end || num < _start) { throw new ArgumentOutOfRangeException(); } } else if (num < _start && num > _end) { throw new ArgumentOutOfRangeException(); } _start = num; } internal void Clear() { _start = (_end = 0); } internal void Write(int channel, int index, int start, int switchPoint, int end, float[] pcm, float[] window) { int num; for (num = (index + start) * Channels + channel + _start; num >= _bufLen; num -= _bufLen) { } if (num < 0) { start -= index; num = channel; } while (num < _bufLen && start < switchPoint) { _buffer[num] += pcm[start] * window[start]; num += Channels; start++; } if (num >= _bufLen) { num -= _bufLen; while (start < switchPoint) { _buffer[num] += pcm[start] * window[start]; num += Channels; start++; } } while (num < _bufLen && start < end) { _buffer[num] = pcm[start] * window[start]; num += Channels; start++; } if (num >= _bufLen) { num -= _bufLen; while (start < end) { _buffer[num] = pcm[start] * window[start]; num += Channels; start++; } } _end = num; } } internal class StreamReadBuffer : IDisposable { private class StreamWrapper { internal Stream Source; internal object LockObject = new object(); internal long EofOffset = long.MaxValue; internal int RefCount = 1; } private class SavedBuffer { public byte[] Buffer; public long BaseOffset; public int End; public int DiscardCount; public long VersionSaved; } private static Dictionary<Stream, StreamWrapper> _lockObjects = new Dictionary<Stream, StreamWrapper>(); private StreamWrapper _wrapper; private int _maxSize; private byte[] _data; private long _baseOffset; private int _end; private int _discardCount; private bool _minimalRead; private long _versionCounter; private List<SavedBuffer> _savedBuffers; public bool MinimalRead { get { return _minimalRead; } set { _minimalRead = value; } } public int MaxSize { get { return _maxSize; } set { if (value < 1) { throw new ArgumentOutOfRangeException("Must be greater than zero."); } int num = 1 << (int)Math.Ceiling(Math.Log(value, 2.0)); if (num < _end) { if (num < _end - _discardCount) { throw new ArgumentOutOfRangeException("Must be greater than or equal to the number of bytes currently buffered."); } CommitDiscard(); byte[] array = new byte[num]; Buffer.BlockCopy(_data, 0, array, 0, _end); _data = array; } _maxSize = num; } } public long BaseOffset => _baseOffset + _discardCount; public int BytesFilled => _end - _discardCount; public int Length => _data.Length; internal long BufferEndOffset { get { if (_end - _discardCount > 0) { return _baseOffset + _discardCount + _maxSize; } return _wrapper.Source.Length; } } internal StreamReadBuffer(Stream source, int initialSize, int maxSize, bool minimalRead) { StreamWrapper value; lock (_lockObjects) { if (!_lockObjects.TryGetValue(source, out value)) { _lockObjects.Add(source, new StreamWrapper { Source = source }); value = _lockObjects[source]; if (source.CanSeek) { value.EofOffset = source.Length; } } else { value.RefCount++; } } initialSize = 2 << (int)Math.Log(initialSize - 1, 2.0); maxSize = 1 << (int)Math.Log(maxSize, 2.0); _wrapper = value; _data = new byte[initialSize]; _maxSize = maxSize; _minimalRead = minimalRead; _savedBuffers = new List<SavedBuffer>(); } public void Dispose() { lock (_lockObjects) { if (--_wrapper.RefCount == 0) { _lockObjects.Remove(_wrapper.Source); } } } public int Read(long offset, byte[] buffer, int index, int count) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (buffer == null) { throw new ArgumentNullException("buffer"); } if (index < 0 || index + count > buffer.Length) { throw new ArgumentOutOfRangeException("index"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (offset >= _wrapper.EofOffset) { return 0; } int srcOffset = EnsureAvailable(offset, ref count, isRecursion: false); Buffer.BlockCopy(_data, srcOffset, buffer, index, count); return count; } internal int ReadByte(long offset) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (offset >= _wrapper.EofOffset) { return -1; } int count = 1; int num = EnsureAvailable(offset, ref count, isRecursion: false); if (count == 1) { return _data[num]; } return -1; } private int EnsureAvailable(long offset, ref int count, bool isRecursion) { if (offset >= _baseOffset && offset + count < _baseOffset + _end) { return (int)(offset - _baseOffset); } if (count > _maxSize) { throw new InvalidOperationException("Not enough room in the buffer! Increase the maximum size and try again."); } _versionCounter++; if (!isRecursion) { for (int i = 0; i < _savedBuffers.Count; i++) { long num = _savedBuffers[i].BaseOffset - offset; if ((num < 0 && _savedBuffers[i].End + num > 0) || (num > 0 && count - num > 0)) { SwapBuffers(_savedBuffers[i]); return EnsureAvailable(offset, ref count, isRecursion: true); } } } while (_savedBuffers.Count > 0 && _savedBuffers[0].VersionSaved + 25 < _versionCounter) { _savedBuffers[0].Buffer = null; _savedBuffers.RemoveAt(0); } if (offset < _baseOffset && !_wrapper.Source.CanSeek) { throw new InvalidOperationException("Cannot seek before buffer on forward-only streams!"); } CalcBuffer(offset, count, out var readStart, out var readEnd); count = FillBuffer(offset, count, readStart, readEnd); return (int)(offset - _baseOffset); } private void SaveBuffer() { _savedBuffers.Add(new SavedBuffer { Buffer = _data, BaseOffset = _baseOffset, End = _end, DiscardCount = _discardCount, VersionSaved = _versionCounter }); _data = null; _end = 0; _discardCount = 0; } private void CreateNewBuffer(long offset, int count) { SaveBuffer(); _data = new byte[Math.Min(2 << (int)Math.Log(count - 1, 2.0), _maxSize)]; _baseOffset = offset; } private void SwapBuffers(SavedBuffer savedBuffer) { _savedBuffers.Remove(savedBuffer); SaveBuffer(); _data = savedBuffer.Buffer; _baseOffset = savedBuffer.BaseOffset; _end = savedBuffer.End; _discardCount = savedBuffer.DiscardCount; } private void CalcBuffer(long offset, int count, out int readStart, out int readEnd) { readStart = 0; readEnd = 0; if (offset < _baseOffset) { if (offset + _maxSize <= _baseOffset) { if (_baseOffset - (offset + _maxSize) > _maxSize) { CreateNewBuffer(offset, count); } else { EnsureBufferSize(count, copyContents: false, 0); } _baseOffset = offset; readEnd = count; } else { readEnd = (int)(offset - _baseOffset); EnsureBufferSize(Math.Min((int)(offset + _maxSize - _baseOffset), _end) - readEnd, copyContents: true, readEnd); readEnd = (int)(offset - _baseOffset) - readEnd; } } else if (offset >= _baseOffset + _maxSize) { if (offset - (_baseOffset + _maxSize) > _maxSize) { CreateNewBuffer(offset, count); } else { EnsureBufferSize(count, copyContents: false, 0); } _baseOffset = offset; readEnd = count; } else { readEnd = (int)(offset + count - _baseOffset); int num = Math.Max(readEnd - _maxSize, 0); EnsureBufferSize(readEnd - num, copyContents: true, num); readStart = _end; readEnd = (int)(offset + count - _baseOffset); } } private void EnsureBufferSize(int reqSize, bool copyContents, int copyOffset) { byte[] array = _data; if (reqSize > _data.Length) { if (reqSize > _maxSize) { if (!_wrapper.Source.CanSeek && reqSize - _discardCount > _maxSize) { throw new InvalidOperationException("Not enough room in the buffer! Increase the maximum size and try again."); } int num = reqSize - _maxSize; copyOffset += num; reqSize = _maxSize; } else { int num2; for (num2 = _data.Length; num2 < reqSize; num2 *= 2) { } reqSize = num2; } if (reqSize > _data.Length) { array = new byte[reqSize]; } } if (copyContents) { if ((copyOffset > 0 && copyOffset < _end) || (copyOffset == 0 && array != _data)) { Buffer.BlockCopy(_data, copyOffset, array, 0, _end - copyOffset); if ((_discardCount -= copyOffset) < 0) { _discardCount = 0; } } else if (copyOffset < 0 && -copyOffset < _end) { if (array != _data || _end <= -copyOffset) { Buffer.BlockCopy(_data, 0, array, -copyOffset, Math.Max(_end, Math.Min(_end, _data.Length + copyOffset))); } else { _end = copyOffset; } _discardCount = 0; } else { _end = copyOffset; _discardCount = 0; } _baseOffset += copyOffset; _end -= copyOffset; if (_end > array.Length) { _end = array.Length; } } else { _discardCount = 0; _end = 0; } _data = array; } private int FillBuffer(long offset, int count, int readStart, int readEnd) { long readOffset = _baseOffset + readStart; int readCount = readEnd - readStart; lock (_wrapper.LockObject) { readCount = PrepareStreamForRead(readCount, readOffset); ReadStream(readStart, readCount, readOffset); if (_end < readStart + readCount) { count = Math.Max(0, (int)(_baseOffset + _end - offset)); } else if (!_minimalRead && _end < _data.Length) { readCount = _data.Length - _end; readCount = PrepareStreamForRead(readCount, _baseOffset + _end); _end += _wrapper.Source.Read(_data, _end, readCount); } } return count; } private int PrepareStreamForRead(int readCount, long readOffset) { if (readCount > 0 && _wrapper.Source.Position != readOffset) { if (readOffset < _wrapper.EofOffset) { if (_wrapper.Source.CanSeek) { _wrapper.Source.Position = readOffset; } else { long num = readOffset - _wrapper.Source.Position; if (num < 0) { readCount = 0; } else { while (--num >= 0) { if (_wrapper.Source.ReadByte() == -1) { _wrapper.EofOffset = _wrapper.Source.Position; readCount = 0; break; } } } } } else { readCount = 0; } } return readCount; } private void ReadStream(int readStart, int readCount, long readOffset) { while (readCount > 0 && readOffset < _wrapper.EofOffset) { int num = _wrapper.Source.Read(_data, readStart, readCount); if (num == 0) { break; } readStart += num; readOffset += num; readCount -= num; } if (readStart > _end) { _end = readStart; } } public void DiscardThrough(long offset) { int val = (int)(offset - _baseOffset); _discardCount = Math.Max(val, _discardCount); if (_discardCount >= _data.Length) { CommitDiscard(); } } private void CommitDiscard() { if (_discardCount >= _data.Length || _discardCount >= _end) { _baseOffset += _discardCount; _end = 0; } else { Buffer.BlockCopy(_data, _discardCount, _data, 0, _end - _discardCount); _baseOffset += _discardCount; _end -= _discardCount; } _discardCount = 0; } } internal static class Utils { [StructLayout(LayoutKind.Explicit)] private struct FloatBits { [FieldOffset(0)] public float Float; [FieldOffset(0)] public uint Bits; } internal static int ilog(int x) { int num = 0; while (x > 0) { num++; x >>= 1; } return num; } internal static uint BitReverse(uint n) { return BitReverse(n, 32); } internal static uint BitReverse(uint n, int bits) { n = ((n & 0xAAAAAAAAu) >> 1) | ((n & 0x55555555) << 1); n = ((n & 0xCCCCCCCCu) >> 2) | ((n & 0x33333333) << 2); n = ((n & 0xF0F0F0F0u) >> 4) | ((n & 0xF0F0F0F) << 4); n = ((n & 0xFF00FF00u) >> 8) | ((n & 0xFF00FF) << 8); return ((n >> 16) | (n << 16)) >> 32 - bits; } internal static float ClipValue(float value, ref bool clipped) { FloatBits floatBits = default(FloatBits); floatBits.Bits = 0u; floatBits.Float = value; if ((floatBits.Bits & 0x7FFFFFFF) > 1065353215) { clipped = true; floatBits.Bits = 0x3F7FFFFF | (floatBits.Bits & 0x80000000u); } return floatBits.Float; } internal static float ConvertFromVorbisFloat32(uint bits) { int num = (int)bits >> 31; double y = (int)(((bits & 0x7FE00000) >> 21) - 788); return (float)(((bits & 0x1FFFFF) ^ num) + (num & 1)) * (float)Math.Pow(2.0, y); } internal static int Sum(Queue<int> queue) { int num = 0; for (int i = 0; i < queue.Count; i++) { int num2 = queue.Dequeue(); num += num2; queue.Enqueue(num2); } return num; } } internal class VorbisCodebook { internal int BookNum; internal int Dimensions; internal int Entries; private int[] Lengths; private float[] LookupTable; internal int MapType; private HuffmanListNode PrefixOverflowTree; private List<HuffmanListNode> PrefixList; private int PrefixBitLength; private int MaxBits; internal float this[int entry, int dim] => LookupTable[entry * Dimensions + dim]; internal static VorbisCodebook Init(VorbisStreamDecoder vorbis, DataPacket packet, int number) { VorbisCodebook vorbisCodebook = new VorbisCodebook(); vorbisCodebook.BookNum = number; vorbisCodebook.Init(packet); return vorbisCodebook; } private VorbisCodebook() { } internal void Init(DataPacket packet) { if (packet.ReadBits(24) != 5653314) { throw new InvalidDataException(); } Dimensions = (int)packet.ReadBits(16); Entries = (int)packet.ReadBits(24); Lengths = new int[Entries]; InitTree(packet); InitLookupTable(packet); } private void InitTree(DataPacket packet) { int num = 0; bool flag; 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; } else { 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 ((MaxBits = Lengths.Max()) > -1) { int num5 = 0; int[] array = null; if (flag && num >= Entries >> 2) { array = new int[Entries]; Array.Copy(Lengths, array, Entries); flag = false; } num5 = (flag ? num : 0); int num6 = num5; 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, num6, array3, array, Lengths, Entries, array2)) { throw new InvalidDataException(); } PrefixList = Huffman.BuildPrefixedLinkedList(array2 ?? Enumerable.Range(0, array3.Length).ToArray(), array ?? Lengths, array3, out PrefixBitLength, out PrefixOverflowTree); } } private bool ComputeCodewords(bool sparse, int sortedEntries, 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(DataPacket packet) { MapType = (int)packet.ReadBits(4); if (MapType == 0) { return; } float num = Utils.ConvertFromVorbisFloat32(packet.ReadUInt32()); float num2 = Utils.ConvertFromVorbisFloat32(packet.ReadUInt32()); 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; } internal int DecodeScalar(DataPacket 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 bitsRead); huffmanListNode = PrefixOverflowTree; do { if (huffmanListNode.Bits == (index & huffmanListNode.Mask)) { packet.SkipBits(huffmanListNode.Length); return huffmanListNode.Value; } } while ((huffmanListNode = huffmanListNode.Next) != null); return -1; } } internal abstract class VorbisFloor { internal abstract class PacketData { internal int BlockSize; protected abstract bool HasEnergy { get; } internal bool ForceEnergy { get; set; } internal bool ForceNoEnergy { get; set; } internal bool ExecuteChannel => (ForceEnergy | HasEnergy) & !ForceNoEnergy; } private class Floor0 : VorbisFloor { private class PacketData0 : PacketData { internal float[] Coeff; internal float Amp; protected override bool HasEnergy => Amp > 0f; } private int _order; private int _rate; private int _bark_map_size; private int _ampBits; private int _ampOfs; private int _ampDiv; private VorbisCodebook[] _books; private int _bookBits; private Dictionary<int, float[]> _wMap; private Dictionary<int, int[]> _barkMaps; private PacketData0[] _reusablePacketData; internal Floor0(VorbisStreamDecoder vorbis) : base(vorbis) { } protected override void Init(DataPacket packet) { _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 VorbisCodebook[(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 >= _vorbis.Books.Length) { throw new InvalidDataException(); } VorbisCodebook vorbisCodebook = _vorbis.Books[num]; if (vorbisCodebook.MapType == 0 || vorbisCodebook.Dimensions < 1) { throw new InvalidDataException(); } _books[i] = vorbisCodebook; } _bookBits = Utils.ilog(_books.Length); _barkMaps = new Dictionary<int, int[]>(); _barkMaps[_vorbis.Block0Size] = SynthesizeBarkCurve(_vorbis.Block0Size / 2); _barkMaps[_vorbis.Block1Size] = SynthesizeBarkCurve(_vorbis.Block1Size / 2); _wMap = new Dictionary<int, float[]>(); _wMap[_vorbis.Block0Size] = SynthesizeWDelMap(_vorbis.Block0Size / 2); _wMap[_vorbis.Block1Size] = SynthesizeWDelMap(_vorbis.Block1Size / 2); _reusablePacketData = new PacketData0[_vorbis._channels]; for (int j = 0; j < _reusablePacketData.Length; j++) { _reusablePacketData[j] = new PacketData0 { Coeff = new float[_order + 1] }; } } 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; } internal override PacketData UnpackPacket(DataPacket packet, int blockSize, int channel) { PacketData0 packetData = _reusablePacketData[channel]; packetData.BlockSize = blockSize; packetData.ForceEnergy = false; packetData.ForceNoEnergy = false; packetData.Amp = packet.ReadBits(_ampBits); if (packetData.Amp > 0f) { Array.Clear(packetData.Coeff, 0, packetData.Coeff.Length); packetData.Amp = packetData.Amp / (float)_ampDiv * (float)_ampOfs; uint num = (uint)packet.ReadBits(_bookBits); if (num >= _books.Length) { packetData.Amp = 0f; return packetData; } VorbisCodebook vorbisCodebook = _books[num]; int i = 0; while (i < _order) { int num2 = vorbisCodebook.DecodeScalar(packet); if (num2 == -1) { packetData.Amp = 0f; return packetData; } int num3 = 0; for (; i < _order; i++) { if (num3 >= vorbisCodebook.Dimensions) { break; } packetData.Coeff[i] = vorbisCodebook[num2, num3]; num3++; } } float num4 = 0f; int num5 = 0; while (num5 < _order) { int num6 = 0; while (num5 < _order && num6 < vorbisCodebook.Dimensions) { packetData.Coeff[num5] += num4; num5++; num6++; } num4 = packetData.Coeff[num5 - 1]; } } return packetData; } internal override void Apply(PacketData packetData, float[] residue) { if (!(packetData is PacketData0 packetData2)) { throw new ArgumentException("Incorrect packet data!"); } int num = packetData2.BlockSize / 2; if (packetData2.Amp > 0f) { int[] array = _barkMaps[packetData2.BlockSize]; float[] array2 = _wMap[packetData2.BlockSize]; int num2 = 0; for (num2 = 0; num2 < _order; num2++) { packetData2.Coeff[num2] = 2f * (float)Math.Cos(packetData2.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 - packetData2.Coeff[i - 1]; num4 *= num6 - packetData2.Coeff[i]; } if (i == _order) { num5 *= num6 - packetData2.Coeff[i - 1]; num4 *= num4 * (4f - num6 * num6); num5 *= num5; } else { num4 *= num4 * (2f - num6); num5 *= num5 * (2f + num6); } num5 = packetData2.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); } } } private class Floor1 : VorbisFloor { private class PacketData1 : PacketData { public int[] Posts = new int[64]; public int PostCount; protected override bool HasEnergy => PostCount > 0; } 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 VorbisCodebook[] _classMasterbooks; private VorbisCodebook[][] _subclassBooks; private int[][] _subclassBookIndex; private static int[] _rangeLookup = new int[4] { 256, 128, 86, 64 }; private static int[] _yBitsLookup = new int[4] { 8, 7, 7, 6 }; private PacketData1[] _reusablePacketData; private bool[] _stepFlags = new bool[64]; private int[] _finalY = new int[64]; 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 }; internal Floor1(VorbisStreamDecoder vorbis) : base(vorbis) { } protected override void Init(DataPacket packet) { _partitionClass = new int[(uint)packet.ReadBits(5)]; for (int i = 0; i < _partitionClass.Length; i++) { _partitionClass[i] = (int)packet.ReadBits(4); } int num = _partitionClass.Max(); _classDimensions = new int[num + 1]; _classSubclasses = new int[num + 1]; _classMasterbooks = new VorbisCodebook[num + 1]; _classMasterBookIndex = new int[num + 1]; _subclassBooks = new VorbisCodebook[num + 1][]; _subclassBookIndex = new int[num + 1][]; 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] = _vorbis.Books[_classMasterBookIndex[j]]; } _subclassBooks[j] = new VorbisCodebook[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] = _vorbis.Books[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; } } } _reusablePacketData = new PacketData1[_vorbis._channels]; for (int num10 = 0; num10 < _reusablePacketData.Length; num10++) { _reusablePacketData[num10] = new PacketData1(); } } internal override PacketData UnpackPacket(DataPacket packet, int blockSize, int channel) { PacketData1 packetData = _reusablePacketData[channel]; packetData.BlockSize = blockSize; packetData.ForceEnergy = false; packetData.ForceNoEnergy = false; packetData.PostCount = 0; Array.Clear(packetData.Posts, 0, 64); if (packet.ReadBit()) { int num = 2; packetData.Posts[0] = (int)packet.ReadBits(_yBits); packetData.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++) { VorbisCodebook vorbisCodebook = _subclassBooks[num2][num6 & num5]; num6 >>= num4; if (vorbisCodebook != null && (packetData.Posts[num] = vorbisCodebook.DecodeScalar(packet)) == -1) { num = 0; i = _partitionClass.Length; break; } num++; } } packetData.PostCount = num; } return packetData; } internal override void Apply(PacketData packetData, float[] residue) { if (!(packetData is PacketData1 packetData2)) { throw new ArgumentException("Incorrect packet data!", "packetData"); } int num = packetData2.BlockSize / 2; if (packetData2.PostCount > 0) { bool[] array = UnwrapPosts(packetData2); int num2 = 0; int num3 = packetData2.Posts[0] * _multiplier; for (int i = 1; i < packetData2.PostCount; i++) { int num4 = _sortIdx[i]; if (array[num4]) { int num5 = _xList[num4]; int num6 = packetData2.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(PacketData1 data) { Array.Clear(_stepFlags, 2, 62); _stepFlags[0] = true; _stepFlags[1] = true; Array.Clear(_finalY, 2, 62); _finalY[0] = data.Posts[0]; _finalY[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], _finalY[num], _xList[num2], _finalY[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) { _stepFlags[num] = true; _stepFlags[num2] = true; _stepFlags[i] = true; if (num4 >= num7) { if (num5 > num6) { _finalY[i] = num4 - num6 + num3; } else { _finalY[i] = num3 - num4 + num5 - 1; } } else if (num4 % 2 == 1) { _finalY[i] = num3 - (num4 + 1) / 2; } else { _finalY[i] = num3 + num4 / 2; } } else { _stepFlags[i] = false; _finalY[i] = num3; } } for (int j = 0; j < data.PostCount; j++) { data.Posts[j] = _finalY[j]; } return _stepFlags; } 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]; } } } private VorbisStreamDecoder _vorbis; internal static VorbisFloor Init(VorbisStreamDecoder vorbis, DataPacket packet) { int num = (int)packet.ReadBits(16); VorbisFloor vorbisFloor = null; switch (num) { case 0: vorbisFloor = new Floor0(vorbis); break; case 1: vorbisFloor = new Floor1(vorbis); break; } if (vorbisFloor == null) { throw new InvalidDataException(); } vorbisFloor.Init(packet); return vorbisFloor; } protected VorbisFloor(VorbisStreamDecoder vorbis) { _vorbis = vorbis; } protected abstract void Init(DataPacket packet); internal abstract PacketData UnpackPacket(DataPacket packet, int blockSize, int channel); internal abstract void Apply(PacketData packetData, float[] residue); } internal abstract class VorbisMapping { private class Mapping0 : VorbisMapping { internal Mapping0(VorbisStreamDecoder vorbis) : base(vorbis) { } protected override void Init(DataPacket packet) { 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(_vorbis._channels - 1); CouplingSteps = new CouplingStep[num2]; for (int i = 0; i < num2; i++) { int num3 = (int)packet.ReadBits(count); int num4 = (int)packet.ReadBits(count); if (num3 == num4 || num3 > _vorbis._channels - 1 || num4 > _vorbis._channels - 1) { throw new InvalidDataException(); } CouplingSteps[i] = new CouplingStep { Angle = num4, Magnitude = num3 }; } if (packet.ReadBits(2) != 0L) { throw new InvalidDataException(); } int[] array = new int[_vorbis._channels]; if (num > 1) { for (int j = 0; j < ChannelSubmap.Length; j++) { array[j] = (int)packet.ReadBits(4); if (array[j] >= num) { throw new InvalidDataException(); } } } Submaps = new Submap[num]; for (int k = 0; k < num; k++) { packet.ReadBits(8); int num5 = (int)packet.ReadBits(8); if (num5 >= _vorbis.Floors.Length) { throw new InvalidDataException(); } if ((int)packet.ReadBits(8) >= _vorbis.Residues.Length) { throw new InvalidDataException(); } Submaps[k] = new Submap { Floor = _vorbis.Floors[num5], Residue = _vorbis.Residues[num5] }; } ChannelSubmap = new Submap[_vorbis._channels]; for (int l = 0; l < ChannelSubmap.Length; l++) { ChannelSubmap[l] = Submaps[array[l]]; } } } internal class Submap { internal VorbisFloor Floor; internal VorbisResidue Residue; internal Submap() { } } internal class CouplingStep { internal int Magnitude; internal int Angle; internal CouplingStep() { } } private VorbisStreamDecoder _vorbis; internal Submap[] Submaps; internal Submap[] ChannelSubmap; internal CouplingStep[] CouplingSteps; internal static VorbisMapping Init(VorbisStreamDecoder vorbis, DataPacket packet) { int num = (int)packet.ReadBits(16); VorbisMapping vorbisMapping = null; if (num == 0) { vorbisMapping = new Mapping0(vorbis); } if (vorbisMapping == null) { throw new InvalidDataException(); } vorbisMapping.Init(packet); return vorbisMapping; } protected VorbisMapping(VorbisStreamDecoder vorbis) { _vorbis = vorbis; } protected abstract void Init(DataPacket packet); } internal class VorbisMode { private const float M_PI = MathF.PI; private const float M_PI2 = MathF.PI / 2f; private VorbisStreamDecoder _vorbis; private float[][] _windows; internal bool BlockFlag; internal int WindowType; internal int TransformType; internal VorbisMapping Mapping; internal int BlockSize; internal static VorbisMode Init(VorbisStreamDecoder vorbis, DataPacket packet) { VorbisMode vorbisMode = new VorbisMode(vorbis); vorbisMode.BlockFlag = packet.ReadBit(); vorbisMode.WindowType = (int)packet.ReadBits(16); vorbisMode.TransformType = (int)packet.ReadBits(16); int num = (int)packet.ReadBits(8); if (vorbisMode.WindowType != 0 || vorbisMode.TransformType != 0 || num >= vorbis.Maps.Length) { throw new InvalidDataException(); } vorbisMode.Mapping = vorbis.Maps[num]; vorbisMode.BlockSize = (vorbisMode.BlockFlag ? vorbis.Block1Size : vorbis.Block0Size); if (vorbisMode.BlockFlag) { vorbisMode._windows = new float[4][]; vorbisMode._windows[0] = new float[vorbis.Block1Size]; vorbisMode._windows[1] = new float[vorbis.Block1Size]; vorbisMode._windows[2] = new float[vorbis.Block1Size]; vorbisMode._windows[3] = new float[vorbis.Block1Size]; } else { vorbisMode._windows = new float[1][]; vorbisMode._windows[0] = new float[vorbis.Block0Size]; } vorbisMode.CalcWindows(); return vorbisMode; } private VorbisMode(VorbisStreamDecoder vorbis) { _vorbis = vorbis; } private void CalcWindows() { for (int i = 0; i < _windows.Length; i++) { float[] array = _windows[i]; int num = (((i & 1) == 0) ? _vorbis.Block0Size : _vorbis.Block1Size) / 2; int blockSize = BlockSize; int num2 = (((i & 2) == 0) ? _vorbis.Block0Size : _vorbis.Block1Size) / 2; int num3 = blockSize / 4 - num / 2; int num4 = blockSize - blockSize / 4 - num2 / 2; for (int j = 0; j < num; j++) { float num5 = (float)Math.Sin(((double)j + 0.5) / (double)num * 1.5707963705062866); num5 *= num5; array[num3 + j] = (float)Math.Sin(num5 * (MathF.PI / 2f)); } for (int k = num3 + num; k < num4; k++) { array[k] = 1f; } for (int l = 0; l < num2; l++) { float num6 = (float)Math.Sin(((double)(num2 - l) - 0.5) / (double)num2 * 1.5707963705062866); num6 *= num6; array[num4 + l] = (float)Math.Sin(num6 * (MathF.PI / 2f)); } } } internal float[] GetWindow(bool prev, bool next) { if (BlockFlag) { if (next) { if (prev) { return _windows[3]; } return _windows[2]; } if (prev) { return _windows[1]; } } return _windows[0]; } } public class VorbisReader : IDisposable { private int _streamIdx; private IContainerReader _containerReader; private List<VorbisStreamDecoder> _decoders; private List<int> _serials; private VorbisStreamDecoder ActiveDecoder { get { if (_decoders == null) { throw new ObjectDisposedException("VorbisReader"); } return _decoders[_streamIdx]; } } public int Channels => ActiveDecoder._channels; public int SampleRate => ActiveDecoder._sampleRate; public int UpperBitrate => ActiveDecoder._upperBitrate; public int NominalBitrate => ActiveDecoder._nominalBitrate; public int LowerBitrate => ActiveDecoder._lowerBitrate; public string Vendor => ActiveDecoder._vendor; public string[] Comments => ActiveDecoder._comments; public bool IsParameterChange => ActiveDecoder.IsParameterChange; public long ContainerOverheadBits => ActiveDecoder.ContainerBits; public bool ClipSamples { get; set; } public IVorbisStreamStatus[] Stats => _decoders.Select((VorbisStreamDecoder d) => d).Cast<IVorbisStreamStatus>().ToArray(); public int StreamIndex => _streamIdx; public int StreamCount => _decoders.Count; public TimeSpan DecodedTime { get { return TimeSpan.FromSeconds((double)ActiveDecoder.CurrentPosition / (double)SampleRate); } set { ActiveDecoder.SeekTo((long)(value.TotalSeconds * (double)SampleRate)); } } public long DecodedPosition { get { return ActiveDecoder.CurrentPosition; } set { ActiveDecoder.SeekTo(value); } } public TimeSpan TotalTime { get { VorbisStreamDecoder activeDecoder = ActiveDecoder; if (activeDecoder.CanSeek) { return TimeSpan.FromSeconds((double)activeDecoder.GetLastGranulePos() / (double)activeDecoder._sampleRate); } return TimeSpan.MaxValue; } } public long TotalSamples { get { VorbisStreamDecoder activeDecoder = ActiveDecoder; if (activeDecoder.CanSeek) { return activeDecoder.GetLastGranulePos(); } return long.MaxValue; } } private VorbisReader() { ClipSamples = true; _decoders = new List<VorbisStreamDecoder>(); _serials = new List<int>(); } public VorbisReader(string fileName) : this(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), closeStreamOnDispose: true) { } public VorbisReader(Stream stream, bool closeStreamOnDispose) : this() { BufferedReadStream bufferedReadStream = new BufferedReadStream(stream) { CloseBaseStream = closeStreamOnDispose }; ContainerReader containerReader = new ContainerReader(bufferedReadStream, closeStreamOnDispose); if (!LoadContainer(containerReader)) { bufferedReadStream.Close(); throw new InvalidDataException("Could not determine container type!"); } _containerReader = containerReader; if (_decoders.Count == 0) { throw new InvalidDataException("No Vorbis data found!"); } } public VorbisReader(IContainerReader containerReader) : this() { if (!LoadContainer(containerReader)) { throw new InvalidDataException("Container did not initialize!"); } _containerReader = containerReader; if (_decoders.Count == 0) { throw new InvalidDataException("No Vorbis data found!"); } } public VorbisReader(IPacketProvider packetProvider) : this() { NewStreamEventArgs e = new NewStreamEventArgs(packetProvider); NewStream(this, e); if (e.IgnoreStream) { throw new InvalidDataException("No Vorbis data found!"); } } private bool LoadContainer(IContainerReader containerReader) { containerReader.NewStream += NewStream; if (!containerReader.Init()) { containerReader.NewStream -= NewStream; return false; } return true; } private void NewStream(object sender, NewStreamEventArgs ea) { IPacketProvider packetProvider = ea.PacketProvider; VorbisStreamDecoder vorbisStreamDecoder = new VorbisStreamDecoder(packetProvider); if (vorbisStreamDecoder.TryInit()) { _decoders.Add(vorbisStreamDecoder); _serials.Add(packetProvider.StreamSerial); } else { ea.IgnoreStream = true; } } public void Dispose() { if (_decoders != null) { foreach (VorbisStreamDecoder decoder in _decoders) { decoder.Dispose(); } _decoders.Clear(); _decoders = null; } if (_containerReader != null) { _containerReader.NewStream -= NewStream; _containerReader.Dispose(); _containerReader = null; } } public int ReadSamples(float[] buffer, int offset, int count) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || offset + count > buffer.Length) { throw new ArgumentOutOfRangeException("count"); } count = ActiveDecoder.ReadSamples(buffer, offset, count); if (ClipSamples) { VorbisStreamDecoder vorbisStreamDecoder = _decoders[_streamIdx]; int num = 0; while (num < count) { buffer[offset] = Utils.ClipValue(buffer[offset], ref vorbisStreamDecoder._clipped); num++; offset++; } } return count; } public void ClearParameterChange() { ActiveDecoder.IsParameterChange = false; } public bool FindNextStream() { if (_containerReader == null) { return false; } return _containerReader.FindNextStream(); } public bool SwitchStreams(int index) { if (index < 0 || index >= StreamCount) { throw new ArgumentOutOfRangeException("index"); } if (_decoders == null) { throw new ObjectDisposedException("VorbisReader"); } if (_streamIdx == index) { return false; } VorbisStreamDecoder vorbisStreamDecoder = _decoders[_streamIdx]; _streamIdx = index; VorbisStreamDecoder vorbisStreamDecoder2 = _decoders[_streamIdx]; if (vorbisStreamDecoder._channels == vorbisStreamDecoder2._channels) { return vorbisStreamDecoder._sampleRate != vorbisStreamDecoder2._sampleRate; } return true; } } internal abstract class VorbisResidue { private class Residue0 : VorbisResidue { private int _begin; private int _end; private int _partitionSize; private int _classifications; private int _maxStages; private VorbisCodebook[][] _books; private VorbisCodebook _classBook; private int[] _cascade; private int[] _entryCache; private int[][] _decodeMap; private int[][][] _partWordCache; internal Residue0(VorbisStreamDecoder vorbis) : base(vorbis) { } protected override void Init(DataPacket packet) { _begin = (int)packet.ReadBits(24); _end = (int)packet.ReadBits(24); _partitionSize = (int)packet.ReadBits(24) + 1; _classifications = (int)packet.ReadBits(6) + 1; _classBook = _vorbis.Books[(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 (_vorbis.Books[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--; } num3 = _classBook.Dimensions; _books = new VorbisCodebook[_classifications][]; num = 0; int num5 = 0; for (int k = 0; k < _classifications; k++) { int num6 = Utils.ilog(_cascade[k]); _books[k] = new VorbisCodebook[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] = _vorbis.Books[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; } } _entryCache = new int[_partitionSize]; _partWordCache = new int[_vorbis._channels][][]; int num10 = ((_end - _begin) / _partitionSize + _classBook.Dimensions - 1) / _classBook.Dimensions; for (int num11 = 0; num11 < _vorbis._channels; num11++) { _partWordCache[num11] = new int[num10][]; } } internal override float[][] Decode(DataPacket packet, bool[] doNotDecode, int channels, int blockSize) { float[][] residueBuffer = GetResidueBuffer(doNotDecode.Length); int num = ((_end < blockSize / 2) ? _end : (blockSize / 2)) - _begin; if (num > 0 && doNotDecode.Contains(value: false)) { int num2 = num / _partitionSize; int length = (num2 + _classBook.Dimensions - 1) / _classBook.Dimensions; for (int i = 0; i < channels; i++) { Array.Clear(_partWordCache[i], 0, length); } for (int j = 0; j < _maxStages; j++) { int k = 0; int num3 = 0; while (k < num2) { if (j == 0) { for (int l = 0; l < channels; l++) { int num4 = _classBook.DecodeScalar(packet); if (num4 >= 0 && num4 < _decodeMap.Length) { _partWordCache[l][num3] = _decodeMap[num4]; continue; } k = num2; j = _maxStages; break; } } int num5 = 0; for (; k < num2; k++) { if (num5 >= _classBook.Dimensions) { break; } int offset = _begin + k * _partitionSize; for (int m = 0; m < channels; m++) { int num6 = _partWordCache[m][num3][num5]; if ((_cascade[num6] & (1 << j)) != 0) { VorbisCodebook vorbisCodebook = _books[num6][j]; if (vorbisCodebook != null && WriteVectors(vorbisCodebook, packet, residueBuffer, m, offset, _partitionSize)) { k = num2; j = _maxStages; break; } } } num5++; } num3++; } } } return residueBuffer; } protected virtual bool WriteVectors(VorbisCodebook codebook, DataPacket packet, float[][] residue, int channel, int offset, int partitionSize) { float[] array = residue[channel]; int num = partitionSize / codebook.Dimensions; for (int i = 0; i < num; i++) { if ((_entryCache[i] = codebook.DecodeScalar(packet)) == -1) { return true; } } for (int j = 0; j < codebook.Dimensions; j++) { int num2 = 0; while (num2 < num) { array[offset] += codebook[_entryCache[num2], j]; num2++; offset++; } } return false; } } private class Residue1 : Residue0 { internal Residue1(VorbisStreamDecoder vorbis) : base(vorbis) { } protected override bool WriteVectors(VorbisCodebook codebook, DataPacket 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; } } private class Residue2 : Residue0 { private int _channels; internal Residue2(VorbisStreamDecoder vorbis) : base(vorbis) { } internal override float[][] Decode(DataPacket packet, bool[] doNotDecode, int channels, int blockSize) { _channels = channels; return base.Decode(packet, doNotDecode, 1, blockSize * channels); } protected override bool WriteVectors(VorbisCodebook codebook, DataPacket 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; } } private VorbisStreamDecoder _vorbis; private float[][] _residue; internal static VorbisResidue Init(VorbisStreamDecoder vorbis, DataPacket packet) { int num = (int)packet.ReadBits(16); VorbisResidue vorbisResidue = null; switch (num) { case 0: vorbisResidue = new Residue0(vorbis); break; case 1: vorbisResidue = new Residue1(vorbis); break; case 2: vorbisResidue = new Residue2(vorbis); break; } if (vorbisResidue == null) { throw new InvalidDataException(); } vorbisResidue.Init(packet); return vorbisResidue; } private static int icount(int v) { int num = 0; while (v != 0) { num += v & 1; v >>= 1; } return num; } protected VorbisResidue(VorbisStreamDecoder vorbis) { _vorbis = vorbis; _residue = new float[_vorbis._channels][]; for (int i = 0; i < _vorbis._channels; i++) { _residue[i] = new float[_vorbis.Block1Size]; } } protected float[][] GetResidueBuffer(int channels) { float[][] array = _residue; if (channels < _vorbis._channels) { array = new float[channels][]; Array.Copy(_residue, array, channels); } for (int i = 0; i < channels; i++) { Array.Clear(array[i], 0, array[i].Length); } return array; } internal abstract float[][] Decode(DataPacket packet, bool[] doNotDecode, int channels, int blockSize); protected abstract void Init(DataPacket packet); } internal class VorbisStreamDecoder : IVorbisStreamStatus, IDisposable { internal int _upperBitrate; internal int _nominalBitrate; internal int _lowerBitrate; internal string _vendor; internal string[] _comments; internal int _channels; internal int _sampleRate; internal int Block0Size; internal int Block1Size; internal VorbisCodebook[] Books; internal VorbisTime[] Times; internal VorbisFloor[] Floors; internal VorbisResidue[] Residues; internal VorbisMapping[] Maps; internal VorbisMode[] Modes; private int _modeFieldBits; internal long _glueBits; internal long _metaBits; internal long _bookBits; internal long _timeHdrBits; internal long _floorHdrBits; internal long _resHdrBits; internal long _mapHdrBits; internal long _modeHdrBits; internal long _wasteHdrBits; internal long _modeBits; internal long _floorBits; internal long _resBits; internal long _wasteBits; internal long _samples; internal int _packetCount; internal Stopwatch _sw = new Stopwatch(); private IPacketProvider _packetProvider; private DataPacket _parameterChangePacket; private List<int> _pagesSeen; private int _lastPageSeen; private bool _eosFound; private object _seekLock = new object(); private float[] _prevBuffer; private RingBuffer _outputBuffer; private Queue<int> _bitsPerPacketHistory; private Queue<int> _sampleCountHistory; private int _preparedLength; internal bool _clipped; private Stack<DataPacket> _resyncQueue; private long _currentPosition; private long _reportedPosition; private VorbisMode _mode; private bool _prevFlag; private bool _nextFlag; private bool[] _noExecuteChannel; private VorbisFloor.PacketData[] _floorData; private float[][] _residue; private bool _isParameterChange; internal bool IsParameterChange { get { return _isParameterChange; } set { if (value) { throw new InvalidOperationException("Only clearing is supported!"); } _isParameterChange = value; } } internal bool CanSeek => _packetProvider.CanSeek; internal long CurrentPosition { get { return _reportedPosition; } private set { _reportedPosition = value; _currentPosition = value; _preparedLength = 0; _eosFound = false; ResetDecoder(isFullReset: false); _prevBuffer = null; } } internal long ContainerBits => _packetProvider.ContainerBits; public int EffectiveBitRate { get { if (_samples == 0L) { return 0; } double num = (double)(_currentPosition - _preparedLength) / (double)_sampleRate; return (int)((double)AudioBits / num); } } public int InstantBitRate { get { int num = _sampleCountHistory.Sum(); if (num > 0) { return (int)((long)_bitsPerPacketHistory.Sum() * (long)_sampleRate / num); } return -1; } } public TimeSpan PageLatency => TimeSpan.FromTicks(_sw.ElapsedTicks / PagesRead); public TimeSpan PacketLatency => TimeSpan.FromTicks(_sw.ElapsedTicks / _packetCount); public TimeSpan SecondLatency => TimeSpan.FromTicks(_sw.ElapsedTicks / _samples * _sampleRate); public long OverheadBits => _glueBits + _metaBits + _timeHdrBits + _wasteHdrBits + _wasteBits + _packetProvider.ContainerBits; public long AudioBits => _bookBits + _floorHdrBits + _resHdrBits + _mapHdrBits + _modeHdrBits + _modeBits + _floorBits + _resBits; public int PagesRead => _pagesSeen.IndexOf(_lastPageSeen) + 1; public int TotalPages => _packetProvider.GetTotalPageCount(); public bool Clipped => _clipped; internal VorbisStreamDecoder(IPacketProvider packetProvider) { _packetProvider = packetProvider; _packetProvider.ParameterChange += SetParametersChanging; _pagesSeen = new List<int>(); _lastPageSeen = -1; } internal bool TryInit() { if (!ProcessStreamHeader(_packetProvider.PeekNextPacket())) { return false; } _packetProvider.GetNextPacket().Done(); DataPacket nextPacket = _packetProvider.GetNextPacket(); if (!LoadComments(nextPacket)) { throw new InvalidDataException("Comment header was not readable!"); } nextPacket.Done(); nextPacket = _packetProvider.GetNextPacket(); if (!LoadBooks(nextPacket)) { throw new InvalidDataException("Book header was not readable!"); } nextPacket.Done(); InitDecoder(); return true; } private void SetParametersChanging(object sender, ParameterChangeEventArgs e) { _parameterChangePacket = e.FirstPacket; } public void Dispose() { if (_packetProvider != null) { IPacketProvider packetProvider = _packetProvider; _packetProvider = null; packetProvider.ParameterChange -= SetParametersChanging; packetProvider.Dispose(); } } private void ProcessParameterChange(DataPacket packet) { _parameterChangePacket = null; bool flag = false; bool isFullReset = false; if (ProcessStreamHeader(packet)) { packet.Done(); flag = true; isFullReset = true; packet = _packetProvider.PeekNextPacket(); if (packet == null) { throw new InvalidDataException("Couldn't get next packet!"); } } if (LoadComments(packet)) { if (flag) { _packetProvider.GetNextPacket().Done(); } else { packet.Done(); } flag = true; packet = _packetProvider.PeekNextPacket(); if (packet == null) { throw new InvalidDataException("Couldn't get next packet!"); } } if (LoadBooks(packet)) { if (flag) { _packetProvider.GetNextPacket().Done(); } else { packet.Done(); } } ResetDecoder(isFullReset); } private bool ProcessStreamHeader(DataPacket packet) { if (!packet.ReadBytes(7).SequenceEqual(new byte[7] { 1, 118, 111, 114, 98, 105, 115 })) { _glueBits += packet.Length * 8; return false; } if (!_pagesSeen.Contains(_lastPageSeen = packet.PageSequenceNumber)) { _pagesSeen.Add(_lastPageSeen); } _glueBits += 56L; long bitsRead = packet.BitsRead; if (packet.ReadInt32() != 0) { throw new InvalidDataException("Only Vorbis stream version 0 is supported."); } _channels = packet.ReadByte(); _sampleRate = packet.ReadInt32(); _upperBitrate = packet.ReadInt32(); _nominalBitrate = packet.ReadInt32(); _lowerBitrate = packet.ReadInt32(); Block0Size = 1 << (int)packet.ReadBits(4); Block1Size = 1 << (int)packet.ReadBits(4); if (_nominalBitrate == 0 && _upperBitrate > 0 && _lowerBitrate > 0) { _nominalBitrate = (_upperBitrate + _lowerBitrate) / 2; } _metaBits += packet.BitsRead - bitsRead + 8; _wasteHdrBits += 8 * packet.Length - packet.BitsRead; return true; } private bool LoadComments(DataPacket packet) { if (!packet.ReadBytes(7).SequenceEqual(new byte[7] { 3, 118, 111, 114, 98, 105, 115 })) { return false; } if (!_pagesSeen.Contains(_lastPageSeen = packet.PageSequenceNumber)) { _pagesSeen.Add(_lastPageSeen); } _glueBits += 56L; _vendor = Encoding.UTF8.GetString(packet.ReadBytes(packet.ReadInt32())); _comments = new string[packet.ReadInt32()]; for (int i = 0; i < _comments.Length; i++) { _comments[i] = Encoding.UTF8.GetString(packet.ReadBytes(packet.ReadInt32())); } _metaBits += packet.BitsRead - 56; _wasteHdrBits += 8 * packet.Length - packet.BitsRead; return true; } private bool LoadBooks(DataPacket packet) { if (!packet.ReadBytes(7).SequenceEqual(new byte[7] { 5, 118, 111, 114, 98, 105, 115 })) { return false; } if (!_pagesSeen.Contains(_lastPageSeen = packet.PageSequenceNumber)) { _pagesSeen.Add(_lastPageSeen); } long bitsRead = packet.BitsRead; _glueBits += packet.BitsRead; Books = new VorbisCodebook[packet.ReadByte() + 1]; for (int i = 0; i < Books.Length; i++) { Books[i] = VorbisCodebook.Init(this, packet, i); } _bookBits += packet.BitsRead - bitsRead; bitsRead = packet.BitsRead; Times = new VorbisTime[(int)packet.ReadBits(6) + 1]; for (int j = 0; j < Times.Length; j++) { Times[j] = VorbisTime.Init(this, packet); } _timeHdrBits += packet.BitsRead - bitsRead; bitsRead = packet.BitsRead; Floors = new VorbisFloor[(int)packet.ReadBits(6) + 1]; for (int k = 0; k < Floors.Length; k++) { Floors[k] = VorbisFloor.Init(this, packet); } _floorHdrBits += packet.BitsRead - bitsRead; bitsRead = packet.BitsRead; Residues = new VorbisResidue[(int)packet.ReadBits(6) + 1]; for (int l = 0; l < Residues.Length; l++) { Residues[l] = VorbisResidue.Init(this, packet); } _resHdrBits += packet.BitsRead - bitsRead; bitsRead = packet.BitsRead; Maps = new VorbisMapping[(int)packet.ReadBits(6) + 1]; for (int m = 0; m < Maps.Length; m++) { Maps[m] = VorbisMapping.Init(this, packet); } _mapHdrBits += packet.BitsRead - bitsRead; bitsRead = packet.BitsRead; Modes = new VorbisMode[(int)packet.ReadBits(6) + 1]; for (int n = 0; n < Modes.Length; n++) { Modes[n] = VorbisMode.Init(this, packet); } _modeHdrBits += packet.BitsRead - bitsRead; if (!packet.ReadBit()) { throw new InvalidDataException(); } _glueBits++; _wasteHdrBits += 8 * packet.Length - packet.BitsRead; _modeFieldBits = Utils.ilog(Modes.Length - 1); return true; } private void InitDecoder() { _currentPosition = 0L; _resyncQueue = new Stack<DataPacket>(); _bitsPerPacketHistory = new Queue<int>(); _sampleCountHistory = new Queue<int>(); ResetDecoder(isFullReset: true); } private void ResetDecoder(bool isFullReset) { if (_preparedLength > 0) { SaveBuffer(); } if (isFullReset) { _noExecuteChannel = new bool[_channels]; _floorData = new VorbisFloor.PacketData[_channels]; _residue = new float[_channels][]; for (int i = 0; i < _channels; i++) { _residue[i] = new float[Block1Size]; } _outputBuffer = new RingBuffer(Block1Size * 2 * _channels); _outputBuffer.Channels = _channels; } else { _outputBuffer.Clear(); } _preparedLength = 0; } private void SaveBuffer() { float[] array = new float[_preparedLength * _channels]; ReadSamples(array, 0, array.Length); _prevBuffer = array; } private bool UnpackPacket(DataPacket packet) { if (packet.ReadBit()) { return false; } int num = _modeFieldBits; _mode = Modes[(uint)packet.ReadBits(_modeFieldBits)]; if (_mode.BlockFlag) { _prevFlag = packet.ReadBit(); _nextFlag = packet.ReadBit(); num += 2; } else { _prevFlag = (_nextFlag = false); } if (packet.IsShort) { return false; } long bitsRead = packet.BitsRead; int num2 = _mode.BlockSize / 2; for (int i = 0; i < _channels; i++) { _floorData[i] = _mode.Mapping.ChannelSubmap[i].Floor.UnpackPacket(packet, _mode.BlockSize, i); _noExecuteChannel[i] = !_floorData[i].ExecuteChannel; Array.Clear(_residue[i], 0, num2); } VorbisMapping.CouplingStep[] couplingSteps = _mode.Mapping.CouplingSteps; foreach (VorbisMapping.CouplingStep couplingStep in couplingSteps) { if (_floorData[couplingStep.Angle].ExecuteChannel || _floorData[couplingStep.Magnitude].ExecuteChannel) { _floorData[couplingStep.Angle].ForceEnergy = true; _floorData[couplingStep.Magnitude].ForceEnergy = true; } } long num3 = packet.BitsRead - bitsRead; bitsRead = packet.BitsRead; VorbisMapping.Submap[] submaps = _mode.Mapping.Submaps; foreach (VorbisMapping.Submap submap in submaps) { for (int k = 0; k < _channels; k++) { if (_mode.Mapping.ChannelSubmap[k] != submap) { _floorData[k].ForceNoEnergy = true; } } float[][] array = submap.Residue.Decode(packet, _noExecuteChannel, _channels, _mode.BlockSize); for (int l = 0; l < _channels; l++) { float[] array2 = _residue[l]; float[] array3 = array[l]; for (int m = 0; m < num2; m++) { array2[m] += array3[m]; } } } _glueBits++; _modeBits += num; _floorBits += num3; _resBits += packet.BitsRead - bitsRead; _wasteBits += 8 * packet.Length - packet.BitsRead; _packetCount++; return true; } private void DecodePacket() { VorbisMapping.CouplingStep[] couplingSteps = _mode.Mapping.CouplingSteps; int num = _mode.BlockSize / 2; for (int num2 = couplingSteps.Length - 1; num2 >= 0; num2--) { if (_floorData[couplingSteps[num2].Angle].ExecuteChannel || _floorData[couplingSteps[num2].Magnitude].ExecuteChannel) { float[] array = _residue[couplingSteps[num2].Magnitude]; float[] array
WeakKingsley.dll
Decompiled 12 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.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.AI.Walker; using EntityStates.Commando; using EntityStates.Commando.CommandoWeapon; using EntityStates.TitanMonster; using HG; using HG.BlendableTypes; using HenryMod.Modules; using HenryMod.Modules.Achievements; using HenryMod.Modules.BaseStates; using HenryMod.Modules.Characters; using HenryMod.Radioport; using HenryMod.Survivors.Henry; using HenryMod.Survivors.Henry.Components; using HenryMod.Survivors.Henry.SkillStates; using NVorbis; using On.EntityStates.TitanMonster; using On.RoR2; using On.RoR2.CharacterAI; using R2API; using R2API.Utils; using Rewired; using RoR2; using RoR2.Achievements; using RoR2.Audio; using RoR2.CharacterAI; using RoR2.ConVar; using RoR2.ContentManagement; using RoR2.Orbs; using RoR2.Projectile; using RoR2.Skills; using RoR2.UI; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.EventSystems; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.PostProcessing; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("HenryMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9ed4904769a158cdcd4285d4bb7955c441e46c94")] [assembly: AssemblyProduct("HenryMod")] [assembly: AssemblyTitle("HenryMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace HenryMod { [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.weakkingsley.king", "WeakKingsley", "1.0.1")] public class HenryPlugin : BaseUnityPlugin { public const string MODUID = "com.weakkingsley.king"; public const string MODNAME = "WeakKingsley"; public const string MODVERSION = "1.0.1"; public const string DEVELOPER_PREFIX = "WEAKKINGSLEY"; public static HenryPlugin instance; private void Awake() { instance = this; Log.Init(((BaseUnityPlugin)this).Logger); Language.Init(); Stopwatch stopwatch = Stopwatch.StartNew(); new HenrySurvivor().Initialize(); Log.Info("[King] startup survivor total: " + stopwatch.ElapsedMilliseconds + " ms"); new ContentPacks().Initialize(); Log.Info("[King] startup plugin total: " + stopwatch.ElapsedMilliseconds + " ms"); } } internal static class Log { internal static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void Debug(object data) { _logSource.LogDebug(data); } internal static void Error(object data) { _logSource.LogError(data); } internal static void ErrorAssetBundle(string assetName, string bundleName) { Error("failed to load asset, " + assetName + ", because it does not exist in asset bundle, " + bundleName); } internal static void Fatal(object data) { _logSource.LogFatal(data); } internal static void Info(object data) { _logSource.LogInfo(data); } internal static void Message(object data) { _logSource.LogMessage(data); } internal static void Warning(object data) { _logSource.LogWarning(data); } } } namespace HenryMod.Radioport { public interface IRadioDecoder : IDisposable { int Channels { get; } int SampleRate { get; } double Length { get; } double Position { get; } int Read(float[] interleaved, int frames); void Seek(double seconds); } public static class RadioDecoders { public static IRadioDecoder Open(string path) { string text = Path.GetExtension(path).ToLowerInvariant(); if (text == ".wav") { return new WavDecoder(path); } if (text == ".ogg") { return new OggDecoder(path); } throw new NotSupportedException("unsupported file type " + text); } } public class WavDecoder : IRadioDecoder, IDisposable { private readonly FileStream fs; private readonly int ch; private readonly int rate; private readonly int bits; private readonly bool isFloat; private readonly long dataStart; private readonly long totalFrames; private long frame; private byte[] tmp = new byte[0]; public int Channels => ch; public int SampleRate => rate; public double Length => (double)totalFrames / (double)rate; public double Position => (double)frame / (double)rate; public WavDecoder(string path) { fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 65536); try { BinaryReader binaryReader = new BinaryReader(fs); if (new string(binaryReader.ReadChars(4)) != "RIFF") { throw new InvalidDataException("not RIFF"); } binaryReader.ReadInt32(); if (new string(binaryReader.ReadChars(4)) != "WAVE") { throw new InvalidDataException("not WAVE"); } int num = 0; long num2 = -1L; while (fs.Position + 8 <= fs.Length) { string text = new string(binaryReader.ReadChars(4)); uint num3 = binaryReader.ReadUInt32(); long position = fs.Position + num3 + (num3 & 1); if (text == "fmt ") { num = binaryReader.ReadUInt16(); ch = binaryReader.ReadUInt16(); rate = binaryReader.ReadInt32(); binaryReader.ReadInt32(); binaryReader.ReadUInt16(); bits = binaryReader.ReadUInt16(); if (num == 65534 && num3 >= 26) { binaryReader.ReadUInt16(); binaryReader.ReadUInt16(); binaryReader.ReadUInt32(); num = binaryReader.ReadUInt16(); } } else if (text == "data") { dataStart = fs.Position; num2 = Math.Min(num3, fs.Length - fs.Position); break; } fs.Position = position; } if (num2 < 0) { throw new InvalidDataException("no data chunk"); } if (ch < 1 || ch > 8 || rate < 8000 || rate > 384000) { throw new InvalidDataException("bad format " + ch + "ch " + rate + "Hz"); } isFloat = num == 3; if ((num != 1 || (bits != 8 && bits != 16 && bits != 24 && bits != 32)) && (!isFloat || bits != 32)) { throw new InvalidDataException("unsupported encoding (tag " + num + ", " + bits + " bit)"); } totalFrames = num2 / (ch * bits / 8); if (totalFrames <= 0) { throw new InvalidDataException("no audio"); } fs.Position = dataStart; } catch { fs.Dispose(); throw; } } public int Read(float[] buf, int frames) { int num = (int)Math.Min(frames, totalFrames - frame); if (num <= 0) { return 0; } int num2 = ch * bits / 8; int num3 = num * num2; if (tmp.Length < num3) { tmp = new byte[num3]; } int i; int num4; for (i = 0; i < num3; i += num4) { num4 = fs.Read(tmp, i, num3 - i); if (num4 <= 0) { break; } } num = i / num2; int num5 = num * ch; for (int j = 0; j < num5; j++) { int num6 = j * bits / 8; float num7 = ((!isFloat) ? ((bits != 16) ? ((bits != 24) ? ((bits != 32) ? ((float)(tmp[num6] - 128) / 128f) : ((float)BitConverter.ToInt32(tmp, num6) / 2.1474836E+09f)) : ((float)(((tmp[num6] << 8) | (tmp[num6 + 1] << 16) | (tmp[num6 + 2] << 24)) >> 8) / 8388608f)) : ((float)(short)(tmp[num6] | (tmp[num6 + 1] << 8)) / 32768f)) : BitConverter.ToSingle(tmp, num6)); buf[j] = (float.IsNaN(num7) ? 0f : num7); } frame += num; return num; } public void Seek(double seconds) { frame = Math.Max(0L, Math.Min(totalFrames - 1, (long)(seconds * (double)rate))); fs.Position = dataStart + frame * (ch * bits / 8); } public void Dispose() { fs.Dispose(); } } public class OggDecoder : IRadioDecoder, IDisposable { private readonly VorbisReader r; public int Channels => r.Channels; public int SampleRate => r.SampleRate; public double Length { get { try { return r.TotalTime.TotalSeconds; } catch { return 0.0; } } } public double Position { get { try { return r.DecodedTime.TotalSeconds; } catch { return 0.0; } } } public OggDecoder(string path) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown r = new VorbisReader(path); if (r.Channels < 1 || r.SampleRate < 8000) { r.Dispose(); throw new InvalidDataException("not a Vorbis stream"); } } public int Read(float[] buf, int frames) { return r.ReadSamples(buf, 0, frames * r.Channels) / r.Channels; } public void Seek(double seconds) { r.DecodedTime = TimeSpan.FromSeconds(Math.Max(0.0, Math.Min(Length - 0.05, seconds))); } public void Dispose() { r.Dispose(); } } public class RadioportAudio { private class Deck { public IRadioDecoder dec; public RadioTrack track; public float gain; public float target = 1f; public float step; public float[] src = new float[0]; public int srcCount; public int srcIdx; public double frac; public float l0; public float r0; public float l1; public float r1; public bool primed; public bool ended; } private struct WaveFormat { public short wFormatTag; public short nChannels; public int nSamplesPerSec; public int nAvgBytesPerSec; public short nBlockAlign; public short wBitsPerSample; public short cbSize; } public const int RATE = 48000; public const int FRAMES = 1024; public const int BUFFERS = 6; public float fadeIn = 0.25f; public float fadeOut = 0.35f; private readonly object gate = new object(); private Deck current; private readonly List<Deck> fading = new List<Deck>(); private int request; private float vol = 0.8f; private float volNow = 0.8f; private volatile bool running; private Thread thread; public volatile RadioTrack finished; public volatile RadioTrack failed; public volatile string failReason; public volatile bool loading; public double Position; public double Length; public float Master = 1f; public float Peak; private const int WAVE_MAPPER = -1; private const int WHDR_DONE = 1; private static readonly int HDR = ((IntPtr.Size == 8) ? 48 : 32); private static readonly int FLAGS = ((IntPtr.Size == 8) ? 24 : 16); public RadioTrack Playing { get { lock (gate) { return (current != null) ? current.track : null; } } } public float Volume { get { return vol; } set { vol = Math.Max(0f, Math.Min(1f, value)); } } public void Play(RadioTrack t) { int id; lock (gate) { id = ++request; FadeCurrentOut(); loading = true; } ThreadPool.QueueUserWorkItem(delegate { Load(t, id); }); } public void PlayNow(RadioTrack t) { int id; lock (gate) { id = ++request; FadeCurrentOut(); loading = true; } Load(t, id); } public void Seek(double seconds) { lock (gate) { if (current != null) { try { current.dec.Seek(seconds); } catch (Exception ex) { failReason = ex.Message; return; } current.srcCount = (current.srcIdx = 0); current.primed = false; current.frac = 0.0; current.gain = Math.Min(current.gain, 0.15f); current.step = 0.00034722223f; } } } public void Stop() { lock (gate) { request++; FadeCurrentOut(); loading = false; } } private void FadeCurrentOut() { if (current != null) { current.target = 0f; current.step = 1f / (Math.Max(0.02f, fadeOut) * 48000f); fading.Add(current); current = null; } } private void Load(RadioTrack t, int id) { IRadioDecoder radioDecoder = null; try { radioDecoder = RadioDecoders.Open(t.path); float[] interleaved = new float[256 * Math.Max(1, radioDecoder.Channels)]; if (radioDecoder.Read(interleaved, 256) <= 0) { throw new InvalidDataException("no audio frames"); } radioDecoder.Dispose(); radioDecoder = RadioDecoders.Open(t.path); lock (gate) { if (id != request) { radioDecoder.Dispose(); return; } current = new Deck { dec = radioDecoder, track = t, gain = 0f, target = 1f, step = 1f / (Math.Max(0.02f, fadeIn) * 48000f) }; loading = false; } } catch (Exception ex) { if (radioDecoder != null) { try { radioDecoder.Dispose(); } catch { } } lock (gate) { if (id == request) { loading = false; failReason = ex.Message; failed = t; } } } } public void StartOutput() { if (!running) { running = true; thread = new Thread(Output) { IsBackground = true, Name = "Radioport", Priority = ThreadPriority.AboveNormal }; thread.Start(); } } public void Shutdown() { running = false; } public void Render(float[] mix, int frames) { Array.Clear(mix, 0, frames * 2); lock (gate) { if (current != null) { MixDeck(current, mix, frames, isCurrent: true); } for (int i = 0; i < fading.Count; i++) { MixDeck(fading[i], mix, frames, isCurrent: false); } for (int num = fading.Count - 1; num >= 0; num--) { if (fading[num].gain <= 0f || fading[num].ended) { try { fading[num].dec.Dispose(); } catch { } fading.RemoveAt(num); } } if (current != null && current.ended) { try { current.dec.Dispose(); } catch { } finished = current.track; current = null; } if (current != null) { try { Position = current.dec.Position; Length = current.dec.Length; } catch { } } else { Position = 0.0; Length = 0.0; } } float num2 = vol * Master; float num3 = 0f; for (int j = 0; j < frames * 2; j++) { if ((j & 1) == 0) { volNow += (num2 - volNow) * 0.0015f; } float num4 = mix[j] * volNow * 0.9f; float num5 = Math.Abs(num4); if (num5 > 0.8f) { num4 = (float)Math.Sign(num4) * (0.8f + 0.2f * (float)Math.Tanh((num5 - 0.8f) / 0.2f)); } mix[j] = num4; if (num5 > num3) { num3 = Math.Abs(num4); } } Peak = num3; } private void MixDeck(Deck d, float[] mix, int frames, bool isCurrent) { if (d.ended) { return; } double num = (double)d.dec.SampleRate / 48000.0; int channels = d.dec.Channels; for (int i = 0; i < frames; i++) { if (!d.primed) { if (!NextSrc(d, channels, out d.l0, out d.r0) || !NextSrc(d, channels, out d.l1, out d.r1)) { d.ended = true; break; } d.primed = true; } d.frac += num; while (d.frac >= 1.0) { d.frac -= 1.0; d.l0 = d.l1; d.r0 = d.r1; if (!NextSrc(d, channels, out d.l1, out d.r1)) { d.ended = true; return; } } float num2 = (float)d.frac; float num3 = d.l0 + (d.l1 - d.l0) * num2; float num4 = d.r0 + (d.r1 - d.r0) * num2; if (d.gain < d.target) { d.gain = Math.Min(d.target, d.gain + d.step); } else if (d.gain > d.target) { d.gain = Math.Max(d.target, d.gain - d.step); } float num5 = d.gain * d.gain; mix[i * 2] += num3 * num5; mix[i * 2 + 1] += num4 * num5; if (!isCurrent && d.gain <= 0f) { break; } } } private bool NextSrc(Deck d, int ch, out float l, out float r) { if (d.srcIdx >= d.srcCount) { int num = 2048; if (d.src.Length < num * ch) { d.src = new float[num * ch]; } int num2; try { num2 = d.dec.Read(d.src, num); } catch (Exception ex) { failReason = ex.Message; failed = d.track; num2 = 0; } d.srcCount = num2; d.srcIdx = 0; if (num2 <= 0) { l = (r = 0f); return false; } } int num3 = d.srcIdx * ch; l = d.src[num3]; r = ((ch > 1) ? d.src[num3 + 1] : l); d.srcIdx++; return true; } private void Output() { IntPtr hwo = IntPtr.Zero; IntPtr[] array = new IntPtr[6]; IntPtr[] array2 = new IntPtr[6]; try { WaveFormat fmt = new WaveFormat { wFormatTag = 1, nChannels = 2, nSamplesPerSec = 48000, nAvgBytesPerSec = 192000, nBlockAlign = 4, wBitsPerSample = 16, cbSize = 0 }; int num = waveOutOpen(out hwo, -1, ref fmt, IntPtr.Zero, IntPtr.Zero, 0); if (num != 0) { failReason = "audio output unavailable (" + num + ")"; running = false; return; } int num2 = 4096; for (int i = 0; i < 6; i++) { array2[i] = Marshal.AllocHGlobal(num2); array[i] = Marshal.AllocHGlobal(HDR); for (int j = 0; j < HDR; j += 4) { Marshal.WriteInt32(array[i], j, 0); } Marshal.WriteIntPtr(array[i], 0, array2[i]); Marshal.WriteInt32(array[i], IntPtr.Size, num2); waveOutPrepareHeader(hwo, array[i], HDR); } float[] array3 = new float[2048]; short[] array4 = new short[2048]; bool[] array5 = new bool[6]; while (running) { bool flag = false; for (int k = 0; k < 6; k++) { if (!array5[k] || (Marshal.ReadInt32(array[k], FLAGS) & 1) != 0) { Render(array3, 1024); for (int l = 0; l < array3.Length; l++) { array4[l] = (short)Math.Max(-32768f, Math.Min(32767f, array3[l] * 32767f)); } Marshal.Copy(array4, 0, array2[k], array4.Length); waveOutWrite(hwo, array[k], HDR); array5[k] = true; flag = true; } } if (!flag) { Thread.Sleep(3); } } } catch (Exception ex) { failReason = "audio thread: " + ex.Message; } finally { if (hwo != IntPtr.Zero) { waveOutReset(hwo); for (int m = 0; m < 6; m++) { if (array[m] != IntPtr.Zero) { waveOutUnprepareHeader(hwo, array[m], HDR); } } waveOutClose(hwo); } for (int n = 0; n < 6; n++) { if (array[n] != IntPtr.Zero) { Marshal.FreeHGlobal(array[n]); } if (array2[n] != IntPtr.Zero) { Marshal.FreeHGlobal(array2[n]); } } lock (gate) { if (current != null) { current.dec.Dispose(); } foreach (Deck item in fading) { item.dec.Dispose(); } current = null; fading.Clear(); } } } [DllImport("winmm.dll")] private static extern int waveOutOpen(out IntPtr hwo, int uDeviceID, ref WaveFormat fmt, IntPtr cb, IntPtr inst, int flags); [DllImport("winmm.dll")] private static extern int waveOutPrepareHeader(IntPtr hwo, IntPtr hdr, int size); [DllImport("winmm.dll")] private static extern int waveOutUnprepareHeader(IntPtr hwo, IntPtr hdr, int size); [DllImport("winmm.dll")] private static extern int waveOutWrite(IntPtr hwo, IntPtr hdr, int size); [DllImport("winmm.dll")] private static extern int waveOutReset(IntPtr hwo); [DllImport("winmm.dll")] private static extern int waveOutClose(IntPtr hwo); } public class Glide { public float value; public float target; private float from; private float t = 1f; private float dur = 0.3f; public Glide(float v) { value = (target = (from = v)); } public void To(float v, float seconds) { if (!(Math.Abs(v - target) < 0.0001f)) { from = value; target = v; dur = Math.Max(0.001f, seconds); t = 0f; } } public bool Tick(float dt) { if (t >= 1f) { return false; } t = Math.Min(1f, t + dt / dur); float num = t * t * (3f - 2f * t); value = from + (target - from) * num; return true; } } public class RadioportController : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_TogglePauseScreen <>9__39_0; public static Action<string> <>9__40_0; internal void <Init>b__39_0(orig_TogglePauseScreen orig) { if (Time.frameCount > blockPauseUntilFrame) { orig.Invoke(); } } internal void <Awake>b__40_0(string s) { Log.Warning(s); } } public static RadioportController instance; private static ConfigEntry<bool> cfgEnabled; private static ConfigEntry<bool> cfgPauseSolo; private static ConfigEntry<bool> cfgMultiplayer; private static ConfigEntry<KeyCode> cfgKey; private static ConfigEntry<float> cfgHold; private static ConfigEntry<float> cfgDuck; private static ConfigEntry<float> cfgDuckTime; private static ConfigEntry<float> cfgVolume; private static ConfigEntry<string> cfgExtraFolder; private static ConfigEntry<string> cfgDefaultStation; private static ConfigEntry<bool> cfgShuffle; private static Font fontRegular; private static Font fontBold; private static int blockPauseUntilFrame; public RadioportUI ui; public RadioportAudio audio; public RadioportLibrary library; public RadioportModel model = new RadioportModel(); private readonly HoldTrigger hold = new HoldTrigger(); private readonly Glide duck = new Glide(1f); private string musicFolder; private bool menuOpen; private bool pausedGame; private bool pausedWwise; private float oldTimeScale = 1f; private MPEventSystem cursorSystem; private GameObject focus; private float repeatT; private int repeatDir; private float masterTimer; private Vector3 lastMouse; private string nowError; private float nowErrorT; private int duckErrors; private ulong musicOutput = ulong.MaxValue; private MusicController musicFor; private static FieldInfo musicListenerField = typeof(MusicController).GetField("musicListenerId", BindingFlags.Instance | BindingFlags.NonPublic); private readonly Dictionary<string, Texture2D> logos = new Dictionary<string, Texture2D>(); private float volRepeat; private float seekT; private int seekDir; public static void Init(AssetBundle bundle) { //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown ConfigFile config = ((BaseUnityPlugin)HenryPlugin.instance).Config; cfgEnabled = config.Bind<bool>("Radioport", "Enabled", true, "Cyberpunk-style radio for your own music (hold the key in a run)."); cfgKey = config.Bind<KeyCode>("Radioport", "Key", (KeyCode)122, "Hold this key to open the Radioport."); cfgHold = config.Bind<float>("Radioport", "HoldSeconds", 0.4f, "How long the key has to be held (0.35 - 0.5 recommended). A tap does nothing."); cfgPauseSolo = config.Bind<bool>("Radioport", "PauseInSingleplayer", true, "Pause the game while the Radioport is open (singleplayer only)."); cfgMultiplayer = config.Bind<bool>("Radioport", "AllowInMultiplayer", true, "Allow the menu in multiplayer as a local menu. It never pauses a multiplayer game."); cfgDuck = config.Bind<float>("Radioport", "GameMusicWhilePlaying", 0.25f, "Game music level while a Radioport song plays (0 = silent, 1 = untouched)."); cfgDuckTime = config.Bind<float>("Radioport", "DuckFadeSeconds", 0.3f, "How long the game music takes to fade down / back up."); cfgVolume = config.Bind<float>("Radioport", "Volume", 0.8f, "Radioport volume (also changed in the menu with A/D or Left/Right)."); cfgExtraFolder = config.Bind<string>("Radioport", "ExtraMusicFolder", "", "Optional extra folder to scan for music."); cfgDefaultStation = config.Bind<string>("Radioport", "DefaultStation", "Growl FM", "Station for songs that are not in a station folder (Edgerunners' songs are on 89.7 Growl FM in the game)."); cfgShuffle = config.Bind<bool>("Radioport", "Shuffle", false, "Shuffle the station's tracks (R in the menu)."); if (!string.IsNullOrEmpty(cfgDefaultStation.Value)) { RadioportLibrary.DefaultStation = cfgDefaultStation.Value.Trim(); } if (!cfgEnabled.Value) { return; } try { if (Object.op_Implicit((Object)(object)bundle)) { fontRegular = bundle.LoadAsset<Font>("Rajdhani-Medium"); fontBold = bundle.LoadAsset<Font>("Rajdhani-SemiBold"); } } catch (Exception ex) { Log.Warning("[Radioport] font: " + ex.Message); } object obj = <>c.<>9__39_0; if (obj == null) { hook_TogglePauseScreen val = delegate(orig_TogglePauseScreen orig) { if (Time.frameCount > blockPauseUntilFrame) { orig.Invoke(); } }; <>c.<>9__39_0 = val; obj = (object)val; } PauseManager.TogglePauseScreen += (hook_TogglePauseScreen)obj; GameObject val2 = new GameObject("Radioport"); Object.DontDestroyOnLoad((Object)val2); val2.AddComponent<RadioportController>(); } private void Awake() { instance = this; string directoryName = Path.GetDirectoryName(typeof(HenryPlugin).Assembly.Location); musicFolder = Path.Combine(directoryName, "RadioportMusic"); try { Directory.CreateDirectory(musicFolder); WriteReadme(); } catch (Exception ex) { Log.Warning("[Radioport] " + ex.Message); } library = new RadioportLibrary { log = delegate(string s) { Log.Warning(s); } }; library.roots.Add(musicFolder); library.roots.Add(Path.Combine(Paths.PluginPath, "KingMod", "RadioportMusic")); if (!string.IsNullOrEmpty(cfgExtraFolder.Value)) { library.roots.Add(cfgExtraFolder.Value); } audio = new RadioportAudio { Volume = Mathf.Clamp01(cfgVolume.Value) }; ui = new RadioportUI(fontRegular, fontBold, ((Component)this).transform); ui.SetVolume(audio.Volume); model.shuffle = cfgShuffle.Value; ui.SetShuffle(model.shuffle); focus = ((Component)ui.panel).gameObject; Rescan(); Application.quitting += OnQuit; } private void Rescan() { string keepPlayingPath = ((audio.Playing != null) ? audio.Playing.path : null); try { library.Scan(); } catch (Exception ex) { Log.Warning("[Radioport] scan failed: " + ex); } model.SetStations(library.stations, keepPlayingPath); Log.Info("[Radioport] " + library.found + " tracks in " + library.stations.Count + " stations" + ((library.skipped > 0) ? (" (" + library.skipped + " skipped, see warnings)") : "")); } private void Update() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) float unscaledDeltaTime = Time.unscaledDeltaTime; try { bool num = Object.op_Implicit((Object)(object)Run.instance) && LocalUserManager.GetFirstLocalUser() != null; bool flag = !RoR2Application.isInSinglePlayer; bool flag2 = num && (!flag || cfgMultiplayer.Value); if (menuOpen && !flag2) { CloseMenu(); } bool flag3 = Input.GetKey(cfgKey.Value) && !TypingSomewhere(); hold.holdTime = Mathf.Clamp(cfgHold.Value, 0.1f, 2f); if (flag2 && hold.Tick(flag3 && (menuOpen || !BlockedByOtherUI()), menuOpen, unscaledDeltaTime)) { if (menuOpen) { CloseMenu(); } else { OpenMenu(); } } ui.SetHold(menuOpen ? 0f : hold.Progress); ui.SetHud(flag2 && !PauseScreenUp()); if (menuOpen) { MenuInput(unscaledDeltaTime); } RadioTrack failed = audio.failed; if (failed != null) { audio.failed = null; failed.broken = true; Log.Warning("[Radioport] cannot play " + failed.path + ": " + audio.failReason); nowError = "UNREADABLE FILE"; nowErrorT = 4f; if (model.playStation >= 0 && model.Track(model.playStation, model.playTrack) == failed) { int num2 = model.Step(1); if (num2 >= 0) { PlayTrack(model.playStation, num2, fromUser: false); } else { StopRadio(); } } Refresh(); } RadioTrack finished = audio.finished; if (finished != null) { audio.finished = null; if (!finished.broken && model.playStation >= 0) { int num3 = model.Step(1); if (num3 >= 0) { PlayTrack(model.playStation, num3, fromUser: false); } else { StopRadio(); } } } masterTimer -= unscaledDeltaTime; if (masterTimer <= 0f) { masterTimer = 0.5f; audio.Master = ConVar("volume_master"); } UpdateDuck(unscaledDeltaTime); if (nowErrorT > 0f) { nowErrorT -= unscaledDeltaTime; } ui.SetPlaying(audio.Playing != null); UpdateNow(); ui.Tick(unscaledDeltaTime); } catch (Exception ex) { Log.Warning("[Radioport] " + ex); } } private void LateUpdate() { if (!menuOpen) { return; } try { MPEventSystem val = cursorSystem; if (Object.op_Implicit((Object)(object)val) && (Object)(object)((EventSystem)val).currentSelectedGameObject != (Object)(object)focus) { ((EventSystem)val).SetSelectedGameObject(focus); } } catch { } } private void OpenMenu() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Rescan(); model.CursorToPlaying(); menuOpen = true; ui.Open(); Refresh(); lastMouse = Input.mousePosition; LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); cursorSystem = ((firstLocalUser != null) ? firstLocalUser.eventSystem : null); if (Object.op_Implicit((Object)(object)cursorSystem)) { MPEventSystem obj = cursorSystem; int cursorOpenerCount = obj.cursorOpenerCount; obj.cursorOpenerCount = cursorOpenerCount + 1; MPEventSystem obj2 = cursorSystem; cursorOpenerCount = obj2.cursorOpenerForGamepadCount; obj2.cursorOpenerForGamepadCount = cursorOpenerCount + 1; } if (RoR2Application.isInSinglePlayer && cfgPauseSolo.Value && NetworkServer.active) { oldTimeScale = Time.timeScale; Time.timeScale = 0f; pausedGame = true; try { AkSoundEngine.PostEvent("Pause_All", ulong.MaxValue); pausedWwise = true; } catch { } } Click(1.15f); } private void CloseMenu() { if (!menuOpen) { return; } menuOpen = false; ui.Close(); blockPauseUntilFrame = Time.frameCount + 2; if (Object.op_Implicit((Object)(object)cursorSystem)) { cursorSystem.cursorOpenerCount = Mathf.Max(0, cursorSystem.cursorOpenerCount - 1); cursorSystem.cursorOpenerForGamepadCount = Mathf.Max(0, cursorSystem.cursorOpenerForGamepadCount - 1); if ((Object)(object)((EventSystem)cursorSystem).currentSelectedGameObject == (Object)(object)focus) { ((EventSystem)cursorSystem).SetSelectedGameObject((GameObject)null); } } cursorSystem = null; if (pausedGame) { Time.timeScale = oldTimeScale; pausedGame = false; } if (pausedWwise) { try { AkSoundEngine.PostEvent("Unpause_All", ulong.MaxValue); } catch { } pausedWwise = false; } hold.Reset(); cfgVolume.Value = audio.Volume; Click(0.85f); } private void MenuInput(float dt) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown((KeyCode)27)) { CloseMenu(); return; } Player val = null; try { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); val = ((firstLocalUser != null) ? firstLocalUser.inputPlayer : null); } catch { } if (val != null && val.GetButtonDown(15) && !Input.GetKey((KeyCode)27)) { CloseMenu(); return; } int num = 0; if (Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273)) { num = -1; } else if (Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274)) { num = 1; } else if (val != null) { float axis = val.GetAxis(13); if (axis > 0.5f) { num = -1; } else if (axis < -0.5f) { num = 1; } } if (num != 0) { if (num != repeatDir) { repeatDir = num; repeatT = 0.35f; Move(num); } else { repeatT -= dt; if (repeatT <= 0f) { repeatT = 0.075f; Move(num); } } } else { repeatDir = 0; } float y = Input.mouseScrollDelta.y; if (y > 0.1f) { Move(-1); } else if (y < -0.1f) { Move(1); } if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271) || (val != null && val.GetButtonDown(14))) { Select(); } int num2 = 0; if (Input.GetKeyDown((KeyCode)97)) { num2 = -1; } if (Input.GetKeyDown((KeyCode)100)) { num2 = 1; } int num3 = (Input.GetKey((KeyCode)276) ? (-1) : (Input.GetKey((KeyCode)275) ? 1 : 0)); if (num3 != 0 && audio.Playing != null && !audio.loading) { if (num3 != seekDir) { seekDir = num3; seekT = 0.4f; Seek((double)num3 * 10.0); } else { seekT -= dt; if (seekT <= 0f) { seekT = 0.18f; Seek((double)num3 * 10.0); } } } else { seekDir = 0; } if (Input.GetMouseButtonDown(0)) { float num4 = ui.ProgressAt(Vector2.op_Implicit(Input.mousePosition)); if (num4 >= 0f && audio.Length > 0.5) { audio.Seek((double)num4 * audio.Length); Click(1f); } } if (Input.GetKeyDown((KeyCode)114)) { model.shuffle = !model.shuffle; cfgShuffle.Value = model.shuffle; ui.SetShuffle(model.shuffle); Click(1.6f); } if (val != null && num2 == 0) { float axis2 = val.GetAxis(12); if (Mathf.Abs(axis2) > 0.5f) { if (volRepeat <= 0f) { num2 = ((axis2 > 0f) ? 1 : (-1)); volRepeat = 0.15f; } volRepeat -= dt; } else { volRepeat = 0f; } } if (num2 != 0) { audio.Volume = Mathf.Round((audio.Volume + (float)num2 * 0.05f) * 20f) / 20f; ui.SetVolume(audio.Volume); Click(1.3f); } if (Input.GetKeyDown((KeyCode)113) || (val != null && val.GetButtonDown(29))) { Skip(-1); } if (Input.GetKeyDown((KeyCode)101) || (val != null && val.GetButtonDown(30))) { Skip(1); } Vector3 mousePosition = Input.mousePosition; int num5 = ui.RowAt(Vector2.op_Implicit(mousePosition)); Vector3 val2 = mousePosition - lastMouse; if (((Vector3)(ref val2)).sqrMagnitude > 1f && num5 >= 0) { lastMouse = mousePosition; model.Build(); int num6 = SelectedRow(); if (num5 != num6) { model.Pick(num5); Refresh(num5); } } if (Input.GetMouseButtonDown(0) && num5 >= 0) { model.Build(); model.Pick(num5); Select(); } } private void Seek(double delta) { double num = audio.Position + delta; if (num >= audio.Length - 0.5) { Skip(1); return; } audio.Seek(Math.Max(0.0, num)); Click(1f); } private int SelectedRow() { return model.Build(); } private void Move(int dir) { model.Move(dir); Refresh(); Click(1f); } private void Select() { model.Activate(out var station, out var track); if (station < 0) { StopRadio(); } else if (track < 0) { if (model.playStation == station) { Refresh(); return; } int num = (model.shuffle ? (-1) : FirstPlayable(station)); if (num < 0) { List<RadioTrack> tracks = model.stations[station].tracks; List<int> list = new List<int>(); for (int i = 0; i < tracks.Count; i++) { if (!tracks[i].broken) { list.Add(i); } } if (list.Count > 0) { num = list[Random.Range(0, list.Count)]; } } if (num >= 0) { PlayTrack(station, num, fromUser: true); } } else if (!model.stations[station].tracks[track].broken) { PlayTrack(station, track, fromUser: true); } Refresh(); Click(1.6f); } private void Skip(int dir) { int num = model.Step(dir); if (num >= 0) { PlayTrack(model.playStation, num, fromUser: true, dir < 0); Refresh(); } } private int FirstPlayable(int s) { List<RadioTrack> tracks = model.stations[s].tracks; for (int i = 0; i < tracks.Count; i++) { if (!tracks[i].broken) { return i; } } return -1; } private void PlayTrack(int s, int t, bool fromUser, bool back = false) { RadioTrack radioTrack = model.Track(s, t); if (radioTrack != null) { model.Played(s, t, !back); audio.StartOutput(); audio.Play(radioTrack); model.playStation = s; model.playTrack = t; if (!menuOpen) { ui.Toast("NOW PLAYING " + radioTrack.Display); } } } private void StopRadio() { audio.Stop(); model.playStation = (model.playTrack = -1); } private void Refresh(int scrollTo = -1) { int num = model.Build(); ui.SetRows(model.rows, num, (scrollTo >= 0) ? scrollTo : num); bool empty = model.stations.Count == 0; ui.SetEmpty(empty, "Add .ogg or .wav files to\n" + musicFolder + "\n(sub folders become stations)"); } private void UpdateNow() { RadioTrack radioTrack = ((model.playStation >= 0) ? model.Track(model.playStation, model.playTrack) : null); RadioStation radioStation = ((model.playStation >= 0) ? model.stations[model.playStation] : null); string track = radioTrack?.Display; string sub = null; string timeLine = null; float progress = 0f; if (nowErrorT > 0f && radioTrack == null) { track = nowError; } if (radioTrack != null) { sub = radioStation.Display + " // TRACK " + (model.playTrack + 1) + "/" + radioStation.tracks.Count; double length = audio.Length; double position = audio.Position; if (audio.loading) { timeLine = "TUNING..."; } else if (length > 0.5) { progress = (float)(position / length); timeLine = Clock(position) + " / " + Clock(length); } if (nowErrorT > 0f) { timeLine = nowError; } } Texture logo = (Texture)(object)((radioStation != null) ? Logo(radioStation) : null); string info = ((radioStation != null) ? ("FREQ " + radioStation.frequency + " MHZ\nTRACKS: " + radioStation.tracks.Count + "\nSRC: LOCAL") : "SIGNAL: NONE\nSRC: -"); ui.SetNow(track, sub, progress, timeLine, radioStation == null, radioStation?.frequency, radioStation?.name, logo, info); } private static string Clock(double s) { int num = (int)s; return num / 60 + ":" + (num % 60).ToString("00"); } private Texture2D Logo(RadioStation st) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (st.logoPath == null) { return null; } if (logos.TryGetValue(st.logoPath, out var value)) { return value; } value = null; try { Texture2D val = new Texture2D(2, 2); if (ImageConversion.LoadImage(val, File.ReadAllBytes(st.logoPath))) { value = val; } } catch (Exception ex) { Log.Warning("[Radioport] logo " + st.logoPath + ": " + ex.Message); } logos[st.logoPath] = value; return value; } private void UpdateDuck(float dt) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) bool flag = audio.Playing != null || audio.loading; duck.To(flag ? Mathf.Clamp01(cfgDuck.Value) : 1f, Mathf.Clamp(cfgDuckTime.Value, 0.05f, 2f)); bool flag2 = duck.Tick(dt); MusicController val = MusicController.Instance; if ((Object)(object)val != (Object)(object)musicFor) { musicFor = val; musicOutput = ulong.MaxValue; flag2 = true; if (Object.op_Implicit((Object)(object)val) && musicListenerField != null) { try { musicOutput = (ulong)musicListenerField.GetValue(val); } catch { } } } if (!flag2 || musicOutput == ulong.MaxValue) { return; } try { AkSoundEngine.SetOutputVolume(musicOutput, duck.value); } catch (Exception ex) { if (duckErrors++ < 3) { Log.Warning("[Radioport] ducking: " + ex.Message); } } } private void OnQuit() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { if (musicOutput != ulong.MaxValue) { AkSoundEngine.SetOutputVolume(musicOutput, 1f); } } catch { } audio.Shutdown(); } private void OnDestroy() { OnQuit(); } private static bool TypingSomewhere() { try { if (Object.op_Implicit((Object)(object)ConsoleWindow.instance)) { return true; } } catch { } return false; } private bool BlockedByOtherUI() { try { if (PauseScreenUp()) { return true; } LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if (firstLocalUser != null && Object.op_Implicit((Object)(object)firstLocalUser.eventSystem) && Object.op_Implicit((Object)(object)((EventSystem)firstLocalUser.eventSystem).currentSelectedGameObject) && (Object)(object)((EventSystem)firstLocalUser.eventSystem).currentSelectedGameObject != (Object)(object)focus) { return true; } } catch { } return false; } private static bool PauseScreenUp() { try { return Object.op_Implicit((Object)(object)PauseManager.pauseScreenInstance); } catch { return false; } } private static float ConVar(string name) { try { BaseConVar val = (Object.op_Implicit((Object)(object)Console.instance) ? Console.instance.FindConVar(name) : null); if (val != null && float.TryParse(val.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return Mathf.Clamp01(result / 100f); } } catch { } return 1f; } private static void Click(float kind) { try { GameObject val = (Object.op_Implicit((Object)(object)RoR2Application.instance) ? ((Component)RoR2Application.instance).gameObject : null); if (Object.op_Implicit((Object)(object)val)) { Util.PlaySound((kind >= 1.5f) ? "Play_UI_menuClick" : "Play_UI_menuHover", val); } } catch { } } private void WriteReadme() { string path = Path.Combine(musicFolder, "README.txt"); if (!File.Exists(path)) { File.WriteAllText(path, "RADIOPORT - put your own music here (.ogg or .wav).\r\n\r\nFiles in this folder play on 89.7 GROWL FM (config: DefaultStation). Every sub folder becomes its own station,\r\nnamed after the folder - name it after a Night City station (Night FM, The Dirge...) and it gets that frequency.\r\nnamed after the folder. Add logo.png to a station folder to give it a logo.\r\n\r\nOptional metadata: a .json file next to the songs, either one object per song\r\n { \"title\": \"Song Name\", \"artist\": \"Artist Name\", \"station\": \"My Radio\", \"file\": \"song01.ogg\" }\r\nor a list of them [ {...}, {...} ]. Without metadata the file name is the title, the artist is \"Unknown Artist\".\r\n\r\nIn a run: hold Z to open. W/S or Up/Down move, Enter (or click) selects, A/D change the volume,\r\nLeft/Right arrows seek 10 s (or click the progress bar), Q/E previous/next track, R shuffle,\r\nZ or Escape closes. NO STATION stops the radio and brings the game music back.\r\n"); } } } public class HoldTrigger { public float holdTime = 0.4f; public float held; private bool armed = true; private bool waitRelease; public float Progress { get { if (!(holdTime > 0f)) { return 0f; } return Math.Min(1f, held / holdTime); } } public bool Tick(bool keyDown, bool menuOpen, float dt) { if (menuOpen) { held = 0f; if (waitRelease) { if (!keyDown) { waitRelease = false; } return false; } if (keyDown && armed) { armed = false; return true; } if (!keyDown) { armed = true; } return false; } if (!keyDown) { held = 0f; armed = true; waitRelease = false; return false; } if (!armed) { return false; } held += dt; if (held >= holdTime) { held = 0f; armed = false; waitRelease = true; return true; } return false; } public void Reset() { held = 0f; armed = false; waitRelease = true; } } public class RadioportModel { public readonly List<RadioStation> stations = new List<RadioStation>(); public int curStation = -1; public int curTrack = -1; public int playStation = -1; public int playTrack = -1; public bool shuffle; private readonly List<int> history = new List<int>(); private readonly Random rng = new Random(); public readonly List<RadioRow> rows = new List<RadioRow>(); private readonly List<int[]> ids = new List<int[]>(); public void SetStations(List<RadioStation> list, string keepPlayingPath) { stations.Clear(); stations.AddRange(list); playStation = (playTrack = -1); if (keepPlayingPath != null) { for (int i = 0; i < stations.Count; i++) { for (int j = 0; j < stations[i].tracks.Count; j++) { if (string.Equals(stations[i].tracks[j].path, keepPlayingPath, StringComparison.OrdinalIgnoreCase)) { playStation = i; playTrack = j; } } } } if (curStation >= stations.Count) { curStation = -1; curTrack = -1; } if (curStation >= 0 && curTrack >= stations[curStation].tracks.Count) { curTrack = -1; } } public void CursorToPlaying() { curStation = playStation; curTrack = ((playStation >= 0) ? playTrack : (-1)); } public int Build() { rows.Clear(); ids.Clear(); int result = 0; rows.Add(new RadioRow { text = "NO STATION", playing = (playStation < 0) }); ids.Add(new int[2] { -1, -1 }); for (int i = 0; i < stations.Count; i++) { if (curStation == i && curTrack < 0) { result = rows.Count; } rows.Add(new RadioRow { text = stations[i].Display, playing = (playStation == i && curStation != i) }); ids.Add(new int[2] { i, -1 }); if (curStation != i) { continue; } for (int j = 0; j < stations[i].tracks.Count; j++) { RadioTrack radioTrack = stations[i].tracks[j]; if (curTrack == j) { result = rows.Count; } rows.Add(new RadioRow { text = radioTrack.title, sub = ((radioTrack.artist == "Unknown Artist") ? null : radioTrack.artist), isTrack = true, playing = (playStation == i && playTrack == j), broken = radioTrack.broken }); ids.Add(new int[2] { i, j }); } } if (curStation >= 0 && playStation == curStation) { for (int k = 0; k < ids.Count; k++) { if (ids[k][0] == curStation && ids[k][1] < 0) { RadioRow value = rows[k]; value.playing = false; rows[k] = value; } } } return result; } public void Move(int dir) { int num = Build(); int rowIndex = Math.Max(0, Math.Min(rows.Count - 1, num + dir)); Pick(rowIndex); } public void Pick(int rowIndex) { if (rowIndex >= 0 && rowIndex < ids.Count) { curStation = ids[rowIndex][0]; curTrack = ids[rowIndex][1]; } } public void Activate(out int station, out int track) { station = curStation; track = curTrack; } public RadioTrack Track(int s, int t) { if (s < 0 || s >= stations.Count || t < 0 || t >= stations[s].tracks.Count) { return null; } return stations[s].tracks[t]; } public void Played(int station, int track, bool remember) { if (station != playStation) { history.Clear(); } else if (remember && playTrack >= 0 && playTrack != track) { history.Add(playTrack); if (history.Count > 64) { history.RemoveAt(0); } } } public int Step(int dir) { if (playStation < 0) { return -1; } List<RadioTrack> tracks = stations[playStation].tracks; if (shuffle && tracks.Count > 1) { if (dir < 0) { while (history.Count > 0) { int num = history[history.Count - 1]; history.RemoveAt(history.Count - 1); if (num < tracks.Count && !tracks[num].broken) { return num; } } } List<int> list = new List<int>(); for (int i = 0; i < tracks.Count; i++) { if (i != playTrack && !tracks[i].broken) { list.Add(i); } } if (list.Count > 0) { return list[rng.Next(list.Count)]; } } for (int j = 1; j <= tracks.Count; j++) { int num2 = ((playTrack + dir * j) % tracks.Count + tracks.Count) % tracks.Count; if (!tracks[num2].broken) { return num2; } } return -1; } } public class RadioTrack { public string path; public string title; public string artist; public string station; public bool broken; public string Display => ((artist == "Unknown Artist") ? title : (artist + " - " + title)).ToUpperInvariant(); } public class RadioStation { public string name; public string frequency; public string logoPath; public readonly List<RadioTrack> tracks = new List<RadioTrack>(); public string Display => (frequency + " " + name).ToUpperInvariant(); } [Serializable] public class RadioTrackMeta { public string title; public string artist; public string station; public string file; } [Serializable] public class RadioTrackMetaList { public RadioTrackMeta[] tracks; } public class RadioportLibrary { public const string UnknownArtist = "Unknown Artist"; public static string DefaultStation = "Growl FM"; public static readonly Dictionary<string, string> Known = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "Pacific Dreams", "88.9" }, { "Radio Vexelstrom", "89.3" }, { "Growl FM", "89.7" }, { "Royal Blue Radio", "91.9" }, { "Night FM", "92.9" }, { "Samizdat Radio", "95.2" }, { "Night City Talk Radio", "95.5" }, { "Ritual FM", "96.1" }, { "Body Heat Radio", "98.7" }, { "The Diamond Hour", "99.7" }, { "Impulse", "99.9" }, { "The Dirge", "101.9" }, { "Radio Pebkac", "103.5" }, { "Pebkac", "103.5" }, { "30 Principales", "106.9" }, { "Morro Rock Radio", "107.3" }, { "Morro Rock", "107.3" } }; public readonly List<string> roots = new List<string>(); public readonly List<RadioStation> stations = new List<RadioStation>(); public Action<string> log = delegate { }; public int skipped; public int found; public void Scan() { Dictionary<string, RadioStation> dictionary = new Dictionary<string, RadioStation>(StringComparer.OrdinalIgnoreCase); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); skipped = 0; found = 0; foreach (string root in roots) { string fullPath; try { fullPath = Path.GetFullPath(root); } catch { continue; } if (hashSet.Add(fullPath) && Directory.Exists(fullPath)) { try { ScanFolder(fullPath, null, dictionary); } catch (Exception ex) { log("[Radioport] could not scan " + fullPath + ": " + ex.Message); } } } List<RadioStation> list = new List<RadioStation>(dictionary.Values); list.RemoveAll((RadioStation s) => s.tracks.Count == 0); HashSet<string> hashSet2 = new HashSet<string>(); foreach (RadioStation item in list) { if (Known.TryGetValue(item.name, out var value) && hashSet2.Add(value)) { item.frequency = value; } } float num = 88.1f; list.Sort((RadioStation a, RadioStation b) => string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase)); foreach (RadioStation item2 in list) { if (item2.frequency != null) { continue; } string text; do { text = num.ToString("0.0", CultureInfo.InvariantCulture); num += 0.2f; if (num > 107.9f) { num = 87.5f; } } while (hashSet2.Contains(text)); hashSet2.Add(text); item2.frequency = text; } list.Sort((RadioStation a, RadioStation b) => float.Parse(a.frequency, CultureInfo.InvariantCulture).CompareTo(float.Parse(b.frequency, CultureInfo.InvariantCulture))); stations.Clear(); stations.AddRange(list); } private void ScanFolder(string dir, string folderStation, Dictionary<string, RadioStation> byName) { Dictionary<string, RadioTrackMeta> dictionary = LoadMeta(dir); string[] files; try { files = Directory.GetFiles(dir); } catch (Exception ex) { log("[Radioport] " + dir + ": " + ex.Message); return; } Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase); string[] array = files; foreach (string text in array) { string text2 = Path.GetExtension(text).ToLowerInvariant(); if (text2 != ".wav" && text2 != ".ogg") { continue; } try { string text3 = CheckHeader(text, text2); if (text3 != null) { skipped++; log("[Radioport] skipped " + text + ": " + text3); continue; } string key = Path.GetFileName(text).ToLowerInvariant(); string text4 = Path.GetFileNameWithoutExtension(text).ToLowerInvariant(); if (!dictionary.TryGetValue(key, out var value)) { dictionary.TryGetValue("stem:" + text4, out value); } RadioTrack radioTrack = new RadioTrack { path = text, title = ((value != null && !string.IsNullOrEmpty(value.title)) ? value.title.Trim() : Path.GetFileNameWithoutExtension(text)), artist = ((value != null && !string.IsNullOrEmpty(value.artist)) ? value.artist.Trim() : "Unknown Artist"), station = ((value != null && !string.IsNullOrEmpty(value.station)) ? value.station.Trim() : (folderStation ?? DefaultStation)) }; if (!byName.TryGetValue(radioTrack.station, out var value2)) { string station = radioTrack.station; RadioStation obj = new RadioStation { name = radioTrack.station }; value2 = obj; byName[station] = obj; } value2.tracks.Add(radioTrack); found++; } catch (Exception ex2) { skipped++; log("[Radioport] skipped " + text + ": " + ex2.Message); } } if (folderStation != null) { array = new string[3] { "logo.png", "logo.jpg", "logo.jpeg" }; foreach (string path in array) { string text5 = Path.Combine(dir, path); if (File.Exists(text5) && byName.TryGetValue(folderStation, out var value3) && value3.logoPath == null) { value3.logoPath = text5; break; } } } string[] directories; try { directories = Directory.GetDirectories(dir); } catch { return; } Array.Sort(directories, (IComparer<string>?)StringComparer.OrdinalIgnoreCase); array = directories; foreach (string text6 in array) { ScanFolder(text6, folderStation ?? Path.GetFileName(text6), byName); } } private Dictionary<string, RadioTrackMeta> LoadMeta(string dir) { Dictionary<string, RadioTrackMeta> dictionary = new Dictionary<string, RadioTrackMeta>(StringComparer.OrdinalIgnoreCase); string[] files; try { files = Directory.GetFiles(dir, "*.json"); } catch { return dictionary; } string[] array = files; foreach (string text in array) { try { string text2 = File.ReadAllText(text).Trim(); if (text2.Length == 0) { continue; } RadioTrackMeta[] array2 = ((text2[0] == '[') ? JsonUtility.FromJson<RadioTrackMetaList>("{\"tracks\":" + text2 + "}").tracks : ((!text2.Contains("\"tracks\"")) ? new RadioTrackMeta[1] { JsonUtility.FromJson<RadioTrackMeta>(text2) } : JsonUtility.FromJson<RadioTrackMetaList>(text2).tracks)); if (array2 == null) { continue; } RadioTrackMeta[] array3 = array2; foreach (RadioTrackMeta radioTrackMeta in array3) { if (radioTrackMeta != null) { if (!string.IsNullOrEmpty(radioTrackMeta.file)) { dictionary[Path.GetFileName(radioTrackMeta.file.Trim())] = radioTrackMeta; } else if (array2.Length == 1) { dictionary["stem:" + Path.GetFileNameWithoutExtension(text)] = radioTrackMeta; } } } } catch (Exception ex) { log("[Radioport] bad metadata " + text + ": " + ex.Message); } } return dictionary; } public static string CheckHeader(string file, string ext) { if (new FileInfo(file).Length < 64) { return "empty or too small"; } byte[] array = new byte[12]; using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (fileStream.Read(array, 0, 12) < 12) { return "too small"; } } if (ext == ".wav") { if (array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70 || array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69) { return "not a RIFF/WAVE file"; } return null; } if (array[0] != 79 || array[1] != 103 || array[2] != 103 || array[3] != 83) { return "not an Ogg file"; } return null; } } public struct RadioRow { public string text; public string sub; public bool isTrack; public bool playing; public bool broken; } public class RadioportUI { private class Row { public RectTransform rt; public GameObject selGroup; public Image selFill; public Text text; public GameObject listIcon; public GameObject barsIcon; public Image[] bars = (Image[])(object)new Image[3]; public RectTransform clip; public float textW; public float clipW; } public static readonly Color Red = new Color(1f, 0.33f, 0.29f); public static readonly Color RedLine = new Color(0.86f, 0.22f, 0.2f, 0.95f); public static readonly Color RedDim = new Color(0.62f, 0.16f, 0.15f, 0.75f); public static readonly Color Cyan = new Color(0.37f, 0.96f, 1f); public static readonly Color CyanDim = new Color(0.37f, 0.96f, 1f, 0.35f); public static readonly Color Teal = new Color(0.55f, 0.8f, 0.8f); public static readonly Color Yellow = new Color(0.95f, 0.86f, 0.42f); public static readonly Color Grey = new Color(0.72f, 0.72f, 0.72f); public static readonly Color SelFill = new Color(0.06f, 0.27f, 0.3f, 0.62f); public const float W = 600f; public const float H = 822f; public const int VisibleRows = 9; private const float ListY = 284f; private const float RowH = 48f; private const float ListW = 582f; private const int RowFont = 20; private int lastSel = -2; private float marquee; private float nowMarquee; private RectTransform nowClip; private float nowClipW = 364f; private Text shuffleText; private RectTransform progHit; public readonly GameObject root; public readonly RectTransform panel; private readonly Font font; private readonly Font bold; private readonly CanvasGroup panelGroup; private readonly CanvasGroup dimGroup; private readonly CanvasGroup hudGroup; private readonly RectTransform hudRect; private readonly Image holdFill; private readonly Image[] hudBars = (Image[])(object)new Image[4]; private readonly Text toast; private float toastT; private readonly Text nowLabel; private readonly Text trackText; private readonly Text subText; private readonly Text timeText; private readonly Text volText; private readonly Image progFill; private readonly Image[] volTicks = (Image[])(object)new Image[20]; private readonly GameObject emblemGroup; private readonly GameObject noStationGroup; private readonly Text emblemFreq; private readonly Text emblemName; private readonly RawImage logoImage; private readonly Text logoInfo; private readonly RectTransform scrollThumb; private readonly GameObject scrollGroup; private readonly GameObject emptyGroup; private readonly Text emptyHint; private readonly Row[] rows = new Row[9]; private int rowCount; private int firstRow; private int selected = -1; private int playingRow = -1; private bool playing; private float open; private float openTarget; private float openSpeed; private float time; private static Texture2D white; private static Texture2D ring; private static Texture2D scan; private bool hudShow = true; private float hold; private const float MarqueeHold = 1.4f; private const float MarqueeSpeed = 45f; public bool IsOpen => openTarget > 0.5f; public bool IsVisible => open > 0.001f; public float OpenAmount => open; public RadioportUI(Font regular, Font semiBold, Transform parent) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_0425: 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_046e: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Expected O, but got Unknown //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0573: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) //IL_061f: Unknown result type (might be due to invalid IL or missing references) //IL_0629: Expected O, but got Unknown //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Expected O, but got Unknown //IL_0670: Unknown result type (might be due to invalid IL or missing references) //IL_0686: Unknown result type (might be due to invalid IL or missing references) //IL_06df: Unknown result type (might be due to invalid IL or missing references) //IL_0707: Unknown result type (might be due to invalid IL or missing references) //IL_0740: Unknown result type (might be due to invalid IL or missing references) //IL_0774: Unknown result type (might be due to invalid IL or missing references) //IL_07d8: Unknown result type (might be due to invalid IL or missing references) //IL_0811: Unknown result type (might be due to invalid IL or missing references) //IL_0869: Unknown result type (might be due to invalid IL or missing references) //IL_088f: Unknown result type (might be due to invalid IL or missing references) //IL_08bc: Unknown result type (might be due to invalid IL or missing references) //IL_08f5: Unknown result type (might be due to invalid IL or missing references) //IL_0929: Unknown result type (might be due to invalid IL or missing references) //IL_097a: Unknown result type (might be due to invalid IL or missing references) //IL_09d4: Unknown result type (might be due to invalid IL or missing references) //IL_0a42: Unknown result type (might be due to invalid IL or missing references) //IL_0a97: Unknown result type (might be due to invalid IL or missing references) //IL_0aa1: Expected O, but got Unknown //IL_0aac: Unknown result type (might be due to invalid IL or missing references) //IL_0ad0: Expected O, but got Unknown //IL_0b12: Unknown result type (might be due to invalid IL or missing references) //IL_0b3d: Unknown result type (might be due to invalid IL or missing references) //IL_0b6a: Unknown result type (might be due to invalid IL or missing references) //IL_0b74: Expected O, but got Unknown //IL_0b7f: Unknown result type (might be due to invalid IL or missing references) //IL_0ba3: Expected O, but got Unknown //IL_0bc5: Unknown result type (might be due to invalid IL or missing references) //IL_0bff: Unknown result type (might be due to invalid IL or missing references) //IL_0c4c: Unknown result type (might be due to invalid IL or missing references) //IL_0c73: Unknown result type (might be due to invalid IL or missing references) //IL_0dc3: Unknown result type (might be due to invalid IL or missing references) //IL_0e0c: Unknown result type (might be due to invalid IL or missing references) //IL_0e13: Unknown result type (might be due to invalid IL or missing references) //IL_0e15: Unknown result type (might be due to invalid IL or missing references) //IL_0e16: Unknown result type (might be due to invalid IL or missing references) //IL_0e1c: Unknown result type (might be due to invalid IL or missing references) //IL_0e32: Unknown result type (might be due to invalid IL or missing references) //IL_0e4c: Unknown result type (might be due to invalid IL or missing references) //IL_0eb2: Unknown result type (might be due to invalid IL or missing references) //IL_0efb: Unknown result type (might be due to invalid IL or missing references) //IL_0f2e: Unknown result type (might be due to invalid IL or missing references) //IL_0f56: Unknown result type (might be due to invalid IL or missing references) //IL_0f9b: Unknown result type (might be due to invalid IL or missing references) //IL_0fca: Unknown result type (might be due to invalid IL or missing references) //IL_0fff: Unknown result type (might be due to invalid IL or missing references) //IL_103a: Unknown result type (might be due to invalid IL or missing references) font = (Object.op_Implicit((Object)(object)regular) ? regular : Resources.GetBuiltinResource<Font>("Arial.ttf")); bold = (Object.op_Implicit((Object)(object)semiBold) ? semiBold : font); MakeTextures(); root = new GameObject("RadioportCanvas", new Type[1] { typeof(RectTransform) }); if (Object.op_Implicit((Object)(object)parent)) { root.transform.SetParent(parent, false); } Canvas obj = root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 30000; CanvasScaler obj2 = root.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 1f; root.AddComponent<GraphicRaycaster>(); RectTransform val = Stretch(root.transform, "Dim"); dimGroup = ((Component)val).gameObject.AddComponent<CanvasGroup>(); Image obj3 = ((Component)val).gameObject.AddComponent<Image>(); ((Graphic)obj3).color = new Color(0.03f, 0.004f, 0.008f, 0.68f); ((Graphic)obj3).raycastTarget = true; RawImage obj4 = ((Component)Stretch((Transform)(object)val, "Tint")).gameObject.AddComponent<RawImage>(); obj4.texture = (Texture)(object)white; ((Graphic)obj4).color = new Color(0.45f, 0.03f, 0.04f, 0.16f); ((Graphic)obj4).raycastTarget = false; RawImage obj5 = ((Component)Stretch((Transform)(object)val, "Scan")).gameObject.AddComponent<RawImage>(); obj5.texture = (Texture)(object)scan; ((Graphic)obj5).color = new Color(1f, 0.3f, 0.3f, 0.05f); obj5.uvRect = new Rect(0f, 0f, 1f, 360f); ((Graphic)obj5).raycastTarget = false; panel = new GameObject("Panel", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)panel).SetParent(root.transform, false); RectTransform obj6 = panel; RectTransform obj7 = panel; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); obj7.anchorMax = val2; obj6.anchorMin = val2; panel.pivot = new Vector2(0.5f, 0.5f); panel.sizeDelta = new Vector2(600f, 822f); panelGroup = ((Component)panel).gameObject.AddComponent<CanvasGroup>(); T((Transform)(object)panel, 2f, 0f, 300f, 12f, 10, RedDim, font, (TextAnchor)0, "SYS_TCLAS_K1NG // RADIOPORT_V2"); Img((Transform)(object)panel, 0f, 14f, 600f, 36f, new Color(0.08f, 0.01f, 0.01f, 0.55f)); Frame((Transform)(object)panel, 0f, 14f, 600f, 36f, 12f, 1.5f, RedLine); Img((Transform)(object)panel, 0f, 14f, 5f, 36f, Red); T((Transform)(object)panel, 18f, 14f, 400f, 36f, 24, Red, bold, (TextAnchor)3, "RADIOPORT"); Img((Transform)(object)panel, 0f, 62f, 220f, 202f, new Color(0.04f, 0f, 0f, 0.6f)); Frame((Transform)(object)panel, 0f, 62f, 220f, 202f, 14f, 1.2f, RedDim, cutTopLeft: true); Img((Transform)(object)panel, 0f, 62f, 3f, 202f, RedLine); logoImage = new GameObject("Logo", new Type[1] { typeof(RectTransform) }).AddComponent<RawImage>(); Place(((Graphic)logoImage).rectTransform, (Transform)(object)panel, 30f, 74f, 160f, 150f); ((Graphic)logoImage).raycastTarget = false; ((Component)logoImage).gameObject.SetActive(false); emblemGroup = new GameObject("Emblem", new Type[1] { typeof(RectTransform) }); Place((RectTransform)emblemGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f); Frame(emblemGroup.transform, 34f, 84f, 152f, 118f, 10f, 1.5f, Cyan); Frame(emblemGroup.transform, 40f, 90f, 140f, 106f, 6f, 1f, CyanDim); emblemFreq = T(emblemGroup.transform, 34f, 92f, 152f, 56f, 46, Cyan, bold, (TextAnchor)4, "88.9"); emblemName = T(emblemGroup.transform, 40f, 148f, 140f, 46f, 17, Cyan, bold, (TextAnchor)1, "KING RADIO"); emblemName.horizontalOverflow = (HorizontalWrapMode)0; noStationGroup = new GameObject("NoStation", new Type[1] { typeof(RectTransform) }); Place((RectTransform)noStationGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f); RawImage obj8 = new GameObject("Ring", new Type[1] { typeof(RectTransform) }).AddComponent<RawImage>(); obj8.texture = (Texture)(object)ring; ((Graphic)obj8).color = Cyan; ((Graphic)obj8).raycastTarget = false; Place(((Graphic)obj8).rectTransform, noStationGroup.transform, 70f, 98f, 80f, 80f); Img(noStationGroup.transform, 86f, 135f, 48f, 6f, Cyan); logoInfo = T((Transform)(object)panel, 10f, 226f, 200f, 36f, 8, RedDim, font, (TextAnchor)6, ""); nowLabel = T((Transform)(object)panel, 236f, 62f, 300f, 14f, 10, RedDim, font, (TextAnchor)0, "NOW PLAYING"); nowClip = new GameObject("NowClip", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); Place(nowClip, (Transform)(object)panel, 236f, 82f, nowClipW, 34f); ((Component)nowClip).gameObject.AddComponent<RectMask2D>(); trackText = T((Transform)(object)nowClip, 0f, 0f, 3000f, 34f, 24, Red, bold, (TextAnchor)3, "NO TRACK"); subText = T((Transform)(object)panel, 236f, 138f, 364f, 18f, 14, Yellow, font, (TextAnchor)0, ""); Img((Transform)(object)panel, 236f, 166f, 364f, 2f, new Color(RedDim.r, RedDim.g, RedDim.b, 0.45f)); progFill = Img((Transform)(object)panel, 236f, 165.5f, 0f, 3f, Red); timeText = T((Transform)(object)panel, 236f, 172f, 364f, 16f, 13, Grey, font, (TextAnchor)0, ""); shuffleText = T((Transform)(object)panel, 236f, 172f, 364f, 16f, 13, CyanDim, bold, (TextAnchor)2, "SHUFFLE"); progHit = new GameObject("ProgressHit", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); Place(progHit, (Transform)(object)panel, 236f, 156f, 364f, 22f); T((Transform)(object)panel, 236f, 214f, 140f, 32f, 19, Red, bold, (TextAnchor)3, "VOLUME"); Key((Transform)(object)panel, 470f, 216f, 28f, "A"); volText = T((Transform)(object)panel, 500f, 214f, 64f, 32f, 22, Cyan, bold, (TextAnchor)4, "80%"); Key((Transform)(object)panel, 568f, 216f, 28f, "D"); for (int i = 0; i < volTicks.Length; i++) { volTicks[i] = Img((Transform)(object)panel, 236f + (float)i * 18.2f, 254f, 14f, 4f, CyanDim); } for (int j = 0; j < 9; j++) { rows[j] = MakeRow(j); } scrollGroup = new GameObject("Scroll", new Type[1] { typeof(RectTransform) }); Place((RectTransform)scrollGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f); Img(scrollGroup.transform, 594f, 284f, 2f, 432f, new Color(RedDim.r, RedDim.g, RedDim.b, 0.4f)); scrollThumb = ((Graphic)Img(scrollGroup.transform, 593f, 284f, 4f, 80f, Red)).rectTransform; emptyGroup = new GameObject("Empty", new Type[1] { typeof(RectTransform) }); Place((RectTransform)emptyGroup.transform, (Transform)(object)panel, 0f, 0f, 600f, 822f); T(emptyGroup.transform, 0f, 362f, 600f, 40f, 30, Red, bold, (TextAnchor)4, "NO TRACKS FOUND"); emptyHint = T(emptyGroup.transform, 40f, 410f, 520f, 120f, 15, Grey, font, (TextAnchor)1, ""); emptyHint.horizontalOverflow = (HorizontalWrapMode)0; emptyGroup.SetActive(false); Img((Transform)(object)panel, 0f, 740f, 600f, 1.5f, RedLine); T((Transform)(object)panel, 2f, 748f, 96f, 30f, 8, RedDim, font, (TextAnchor)0, "K1NG-OS // RADIOPORT\nLOCAL LIBRARY\nSIGNAL: OWNED"); float right = 600f; right = Hint((Transform)(object)panel, right, 750f, "PREV/NEXT", "Q", "E"); right = Hint((Transform)(object)panel, right - 14f, 750f, "SHUFFLE", "R"); Hint((Transform)(object)panel, right - 14f, 750f, "SEEK", "←", "→"); right = 600f; right = Hint((Transform)(object)panel, right, 782f, "CLOSE", "Z"); right = Hint((Transform)(object)panel, right - 14f, 782f, "SELECT", "ENTER"); Hint((Transform)(object)panel, right - 14f, 782f, "VOLUME", "A", "D"); hudRect = new GameObject("HudHint", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)hudRect).SetParent(root.transform, false); RectTransform obj9 = hudRect; RectTransform obj10 = hudRect; RectTransform obj11 = hudRect; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 0f); obj11.pivot = val3; val2 = (obj9.anchorMin = (obj10.anchorMax = val3)); hudRect.anchoredPosition = new Vector2(38f, 36f); hudRect.sizeDelta = new Vector2(400f, 34f); hudGroup = ((Component)hudRect).gameObject.AddComponent<CanvasGroup>(); hudGroup.blocksRaycasts = false; hudGroup.interactable = false; Img((Transform)(object)hudRect, 0f, 0f, 30f, 30f, new Color(0f, 0f, 0f, 0.35f)); holdFill = Img((Transform)(object)hudRect, 0f, 30f, 30f, 0f, new Color(Cyan.r, Cyan.g, Cyan.b, 0.4f)); Frame((Transform)(object)hudRect, 0f, 0f, 30f, 30f, 0f, 1.5f, Cyan); T((Transform)(object)hudRect, 0f, 0f, 30f, 30f, 19, Cyan, bold, (TextAnchor)4, "Z"); Img((Transform)(object)hudRect, 34f, 0f, 30f, 30f, new Color(0f, 0f, 0f, 0.35f)); Frame((Transform)(object)hudRect, 34f, 0f, 30f, 30f, 6f, 1.5f, Cyan); for (int k = 0; k < hudBars.Length; k++) { hudBars[k] = Img((Transform)(object)hudRect, 41 + k * 5, 24f, 3f, 8f, Cyan); } toast = T((Transform)(object)hudRect, 74f, 0f, 520f, 30f, 16, Cyan, bold, (TextAnchor)3, ""); toast.horizontalOverflow = (HorizontalWrapMode)1; open = 0f; Apply(); } public void Open() { openTarget = 1f; openSpeed = 4.5454545f; } public void Close() { openTarget = 0f; openSpeed = 5.5555553f; } public void SetHud(bool show) { hudShow = show; } public void SetHold(float p) { hold = Mathf.Clamp01(p); } public void Toast(string s) { toast.text = s; toastT = 4.5f; } public void SetPlaying(bool isPlaying) { playing = isPlaying; } public void SetRows(List<RadioRow> data, int sel, int scrollTo) { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) rowCount = data.Count; selected = sel; if (scrollTo >= 0) { if (scrollTo < firstRow) { firstRow = scrollTo; } if (scrollTo >= firstRow + 9) { firstRow = scrollTo - 9 + 1; } } firstRow = Mathf.Clamp(firstRow, 0, Mathf.Max(0, rowCount - 9)); playingRow = -1; for (int i = 0; i < 9; i++) { int num = firstRow + i; Row row = rows[i]; bool flag = num < rowCount; ((Component)row.rt).gameObject.SetActive(flag); if (flag) { RadioRow radioRow = data[num]; bool flag2 = num == sel; row.selGroup.SetActive(flag2); row.listIcon.SetActive(!radioRow.playing); row.barsIcon.SetActive(radioRow.playing); if (radioRow.playing) { playingRow = i; } float num2 = (radioRow.isTrack ? 26f : 0f); row.clipW = 498f - num2; row.clip.anchoredPosition = new Vector2(40f + num2, 0f); row.clip.sizeDelta = new Vector2(row.clipW, 42f); ((Graphic)row.text).rectTransform.anchoredPosition = Vector2.zero; row.listIcon.GetComponent<RectTransform>().anchoredPosition = new Vector2(12f + num2, -17f); row.barsIcon.GetComponent<RectTransform>().anchoredPosition = new Vector2(12f + num2, -17f); row.text.fontSize = 20; Color color = (Color)(radioRow.broken ? new Color(0.5f, 0.5f, 0.5f) : (flag2 ? Cyan : (radioRow.isTrack ? Grey : Teal))); ((Graphic)row.text).color = color; string text = radioRow.text.ToUpperInvariant(); if (radioRow.broken) { text += " <color=#ff5a4e>[UNREADABLE]</color>"; } else if (radioRow.isTrack && !string.IsNullOrEmpty(radioRow.sub)) { text = text + " <color=#" + ColorUtility.ToHtmlStringRGB(flag2 ? Yellow : (Yellow * 0.85f)) + ">// " + radioRow.sub.ToUpperInvariant() + "</color>"; } row.text.text = text; row.textW = row.text.preferredWidth; } } if (sel != lastSel) { lastSel = sel; marquee = 0f; } bool num3 = rowCount > 9; scrollGroup.SetActive(true); float num4 = 432f; float num5 = (num3 ? Mathf.Max(30f, num4 * 9f / (float)rowCount) : num4); float num6 = (num3 ? ((num4 - num5) * (float)firstRow / (float)Mathf.Max(1, rowCount - 9)) : 0f); scrollThumb.sizeDelta = new Vector2(4f, num5); scrollThumb.anchoredPosition = new Vector2(593f, 0f - (284f + num6)); } public void SetShuffle(bool on) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) ((Graphic)shuffleText).color = (Color)(on ? Cyan : new Color(Cyan.r, Cyan.g, Cyan.b, 0.22f)); shuffleText.text = (on ? "SHUFFLE ON" : "SHUFFLE OFF"); } public float ProgressAt(Vector2 screen) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_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) if (!IsOpen || !RectTransformUtility.RectangleContainsScreenPoint(progHit, screen, (Camera)null)) { return -1f; } Vector2 val = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(progHit, screen, (Camera)null, ref val); float x = val.x; Rect rect = progHit.rect; return Mathf.Clamp01(x / ((Rect)(ref rect)).width); } public void SetEmpty(bool empty, string hint) { emptyGroup.SetActive(empty); emptyHint.text = hint; } public void SetNow(string track, string sub, float progress, string timeLine, bool noStation, string freq, string stationName, Texture logo, string info) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) string text = (string.IsNullOrEmpty(track) ? "NO TRACK" : track); if (trackText.text != text) { trackText.text = text; nowMarquee = 0f; } subText.text = sub ?? ""; ((Graphic)progFill).rectTransform.sizeDelta = new Vector2(364f * Mathf.Clamp01(progress), 3f); timeText.text = timeLine ?? ""; noStationGroup.SetActive(noStation); ((Component)logoImage).gameObject.SetActive(!noStation && Object.op_Implicit((Object)(object)logo)); if (Object.op_Implicit((Object)(object)logo)) { logoImage.texture = logo; } emblemGroup.SetActive(!noStation && !Object.op_Implicit((Object)(object)logo)); emblemFreq.text = freq ?? ""; emblemName.text = (stationName ?? "").ToUpperInvariant(); logoInfo.text = info ?? ""; } public void SetVolume(float v) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) volText.text = Mathf.RoundToInt(v * 100f) + "%"; int num = Mathf.RoundToInt(v * (float)volTicks.Length); for (int i = 0; i < volTicks.Length; i++) { ((Graphic)volTicks[i]).color = (Color)((i < num) ? Cyan : new Color(Cyan.r, Cyan.g, Cyan.b, 0.16f)); } } public int RowAt(Vector2 screen) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return -1; } for (int i = 0; i < 9; i++) { if (((Component)rows[i].rt).gameObject.activeSelf && RectTransformUtility.RectangleContainsScreenPoint(rows[i].rt, screen, (Camera)null)) { return firstRow + i; } } return -1; } public bool OverPanel(Vector2 screen) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return RectTransformUtility.RectangleContainsScreenPoint(panel, screen, (Camera)null); } public void Tick(float dt) { time += dt; if (open != openTarget) { open = Mathf.MoveTowards(open, openTarget, dt * openSpeed); } if (toastT > 0f) { toastT -= dt; } marquee += dt; nowMarquee += dt; Apply(); } private void Apply() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) float num = ((openTarget > 0.5f) ? (1f - Mathf.Pow(1f - open, 3f)) : (open * open * (3f - 2f * open))); panelGroup.alpha = num; dimGroup.alpha = num; CanvasGroup obj = panelGroup; bool blocksRaycasts = (dimGroup.blocksRaycasts = open > 0.5f); obj.blocksRaycasts = blocksRaycasts; panel.anchoredPosition = new Vector2(70f * (1f - num), 0f); ((Component)panel).gameObject.SetActive(open > 0.001f); ((Component)dimGroup).gameObject.SetActive(open > 0.001f); float num2 = (hudShow ? (1f - Mathf.Clamp01(open * 3f)) : 0f); hudGroup.alpha = Mathf.MoveTowards(hudGroup.alpha, num2, 0.15f); ((Graphic)holdFill).rectTransform.sizeDelta = new Vector2(30f, 30f * hold); ((Graphic)holdFill).rectTransform.anchoredPosition = new Vector2(0f, 0f - (30f - 30f * hold)); for (int i = 0; i < hudBars.Length; i++) { float num3 = (playing ? (6f + 14f * (0.5f + 0.5f * Mathf.Sin(time * (5.3f + (float)i * 1.7f) + (float)i * 1.3f)) * (0.6f + 0.4f * Mathf.Sin(time * 2.1f + (float)i))) : (4f + (float)i * 4f)); ((Graphic)hudBars[i]).rectTransform.sizeDelta = new Vector2(3f, num3); ((Graphic)hudBars[i]).rectTransform.anchoredPosition = new Vector2((float)(41 + i * 5), 0f - (24f - num3 + 0f) + 0f - 0f); ((Graphic)hudBars[i]).rectTransform.anchoredPosition = new Vector2((float)(41 + i * 5), 0f - (25f - num3)); ((Graphic)hudBars[i]).color = (playing ? Cyan : CyanDim); } ((Graphic)toast).color = new Color(Cyan.r, Cyan.g, Cyan.b, Mathf.Clamp01(toastT) * (1f - Mathf.Clamp01(open * 3f))); if (playingRow >= 0) { for (int j = 0; j < 3; j++) { float num4 = (playing ? (4f + 10f * (0.5f + 0.5f * Mathf.Sin(time * (6f + (float)j * 2.3f) + (float)j))) : (6f + (float)j * 3f)); RectTransform rectTransform = ((Graphic)rows[playingRow].bars[j]).rectTransform; rectTransform.sizeDelta = new Vector2(3f, num4); rectTransform.anchoredPosition = new Vector2((float)j * 5f, 0f - (14f - num4)); } } for (int k = 0; k < 9; k++) { Row row = rows[k]; if (((Component)row.rt).gameObject.activeSelf) { float num5 = 0f; if (firstRow + k == selected) { num5 = 0f - Scroll(marquee, row.textW - row.clipW + 8f); } ((Graphic)row.text).rectTransform.anchoredPosition = new Vector2(num5, 0f); } } ((Graphic)trackText).rectTransform.anchoredPosition = new Vector2(0f - Scroll(nowMarquee, trackText.preferredWidth - nowClipW + 8f), 0f); if (selected >= firstRow && selected < firstRow + 9) { ((Graphic)rows[selected - firstRow].selFill).color = new Color(SelFill.r, SelFill.g, SelFill.b, SelFill.a * (0.85f + 0.15f * Mathf.Sin(time * 4f))); } } private static float Scroll(float t, float over) { if (over <= 0f) { return 0f; } float num = over / 45f; float num2 = 1.4f + num + 1.4f; t %= num2; if (t < 1.4f) { return 0f; } if (t < 1.4f + num) { float num3 = (t - 1.4f) / num; return over * (num3 * num3 * (3f - 2f * num3) * 0.25f + num3 * 0.75f); } return over; } private Row MakeRow(int i) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Expected O, but got Unknown //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Expected O, but got Unknown //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) Row row = new Row(); row.rt = new GameObject("Row" + i, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); Place(row.rt, (Transform)(object)panel, 0f, 284f + (float)i * 48f, 582f, 42f); row.selGroup = new GameObject("Sel", new Type[1] { typeof(RectTransform) }); Place((RectTransform)row.selGroup.transform, (Transform)(object)row.rt, 0f, 0f, 582f, 42f); row.selFill = Img(row.selGroup.transform, 1f, 1f, 570f, 40f, SelFill); Frame(row.selGroup.transform, 0f, 0f, 582f, 42f, 12f, 1.5f, Cyan); Img(row.selGroup.transform, 0f, 0f, 3f, 42f, Cyan); Line(row.selGroup.transform, new Vector2(552f, 13f), new Vector2(560f, 21f), 2f, Cyan); Line(row.selGroup.transform, new Vector2(560f, 21f), new Vector2(552f, 29f), 2f, Cyan); row.listIcon = new GameObject("List", new Type[1] { typeof(RectTransform) }); Place((RectTransform)row.listIcon.transform, (Transform)(object)row.rt, 12f, 17f, 16f, 12f); for (int j = 0; j < 3; j++) { Img(row.listIcon.transform, 0f, j * 5, 3f, 2f, new Color(Teal.r, Teal.g, Teal.b, 0.55f)); Img(row.listIcon.transform, 5f, j * 5, 11f, 2f, new Color(Teal.r, Teal.g, Teal.b, 0.55f)); } row.barsIcon = new GameObject("Bars", new Type[1] { typeof(RectTransform) }); Place((RectTransform)row.barsIcon.transform, (Transform)(object)row.rt, 12f, 17f, 16f, 14f); for (int k = 0; k < 3; k++) { row.bars[k] = Img(row.barsIcon.transform, k * 5, 6f, 3f, 8f, Cyan); } row.clip = new GameObject("Clip", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); Place(row.clip, (Transform)(object)row.rt, 40f, 0f, 498f, 42f); ((Component)row.clip).gameObject.AddComponent<RectMask2D>(); row.text = T((Transform)(object)row.clip, 0f, 0f, 3000f, 42f, 20, Teal, bold, (TextAnchor)3, ""); row.text.supportRichText = true; Shadow obj = ((Component)row.text).gameObject.AddComponent<Shadow>(); obj.effectColor = new Color(0f, 0f, 0f, 0.6f); obj.effectDistance = new Vector2(1f, -1f); return row; } private float Hint(Transform p, float right, float y, string label, params string[] keys) { //IL_0014: 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_0056: Unknown result type (might be due to invalid IL or missing references) Text obj = T(p, 0f, y, 200f, 24f, 16, Red, bold, (TextAnchor)3, label); float num = obj.preferredWidth + 2f; float num2 = right - num; ((Graphic)obj).rectTransform.anchoredPosition = new Vector2(num2, 0f - y); ((Graphic)obj).rectTransform.sizeDelta = new Vector2(num, 24f); for (int num3 = keys.Length - 1; num3 >= 0; num3--) { float num4 = ((keys[num3].Length > 1) ? (14f + (float)keys[num3].Length * 9f) : 24f); num2 -= num4 + 5f; Key(p, num2, y, num4, keys[num3], 24f); } return num2; } private void Key(Transform p, float x, float y, float w, string k, float h = -1f) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (h < 0f) { h = w; } Img(p, x, y, w, h, new Color(0f, 0.08f, 0.09f, 0.6f)); Frame(p, x, y, w, h, 0f, 1.4f, Cyan); T(p, x, y, w, h, (k.Length > 1) ? 13 : ((int)(h * 0.62f)), Cyan, bold, (TextAnchor)4, k); } private static void MakeTextures() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)white)) { return; } white = new Texture2D(1, 1); white.SetPixel(0, 0, Color.white); white.Apply(); ((Object)white).hideFlags = (HideFlags)61; ring = new Texture2D(128, 128, (TextureFormat)4, false); ((Object)ring).hideFlags = (HideFlags)61; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { float num = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(64f, 64f)); float num2 = Mathf.Clamp01(1f - Mathf.Abs(num - 54f) / 2.2f) + Mathf.Clamp01(1f - Mathf.Abs(num - 46f) / 1.2f) * 0.45f; ring.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Clamp01(num2))); } } ring.Apply(); scan = new Texture2D(1, 3, (TextureFormat)4, false); ((Object)scan).hideFlags = (HideFlags)61; scan.SetPixel(0, 0, Color.white); scan.SetPixel(0, 1, new Color(1f, 1f, 1f, 0f)); scan.SetPixel(0, 2, new Color(1f, 1f, 1f, 0f)); ((Texture)scan).wrapMode = (TextureWrapMode)0; ((Texture)scan).filterMode = (FilterMode)0; scan.Apply(); } private static RectTransform Stretch(Transform p, string name) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(p, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; Vector2 offsetMin = (component.offsetMax = Vector2.zero); component.offsetMin = offsetMin; return component; } private static void Place(RectTransform rt, Transform p, float x, float y, float w, float h) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) ((Transform)rt).SetParent(p, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 1f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(0f, 1f); rt.anchoredPosition = new Vector2(x, 0f - y); rt.sizeDelta = new Vector2(w, h); } private static Image Img(Transform p, float x, float y, float w, float h, Color c) { //IL_0018: 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) Image obj = new GameObject("I", new Type[1] { typeof(RectTransform) }).AddComponent<Image>(); Place(((Graphic)obj).rectTransform, p, x, y, w, h); ((Graphic)obj).color = c; ((Graphic)obj).raycastTarget = false; return obj; } private Text T(Transform p, float x, float y, float w, float h, int size, Color c, Font f, TextAnchor a, string s) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) Text obj = new GameObject("T", new Type[1] { typeof(RectTransform) }).AddComponent<Text>(); Place(((Graphic)obj).rectTransform, p, x, y, w, h); obj.font = f; obj.fontSize = size; ((Graphic)obj).color = c; obj.alignment = a; obj.text = s; ((Graphic)obj).raycastTarget = false; obj.horizontalOverflow = (HorizontalWrapMode)1; obj.verticalOverflow = (VerticalWrapMode)1; obj.supportRichText = true; return obj; } private static void Line(Transform p, Vector2 a, Vector2 b, float th, Color c) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: U