Decompiled source of Concentus Unity v2.2.2

Concentus/ConcentusUnity.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Numerics;
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 ConcentusUnity.Celt;
using ConcentusUnity.Celt.Structs;
using ConcentusUnity.Common;
using ConcentusUnity.Common.CPlusPlus;
using ConcentusUnity.Enums;
using ConcentusUnity.Native;
using ConcentusUnity.Silk;
using ConcentusUnity.Silk.Enums;
using ConcentusUnity.Silk.Structs;
using ConcentusUnity.Structs;
using Microsoft.Win32.SafeHandles;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("ParityTest, PublicKey=002400000480000094000000060200000024000052534131000400000100010071a2f675c04c87e64b9be6d37f5833c5285fb4ed883780cf6d61e80aee5d77950b2f06dd45bc634f53405f2a2b7b2332f4dfdcb0554ffc97b935e7343e76e733eea44346e56ac1098c12a66de71e324f2f503f9f2e32560910e2082d6943df50db42679a330e52979bd1eefbb59485d2c7420d158f6ab6d41bdf42d2172675e1")]
[assembly: InternalsVisibleTo("TestOpusEncode, PublicKey=002400000480000094000000060200000024000052534131000400000100010071a2f675c04c87e64b9be6d37f5833c5285fb4ed883780cf6d61e80aee5d77950b2f06dd45bc634f53405f2a2b7b2332f4dfdcb0554ffc97b935e7343e76e733eea44346e56ac1098c12a66de71e324f2f503f9f2e32560910e2082d6943df50db42679a330e52979bd1eefbb59485d2c7420d158f6ab6d41bdf42d2172675e1")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Logan Stromberg (original), Zehs (fork)")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("© Xiph.Org Foundation, Skype Limited, CSIRO, Microsoft Corp.")]
[assembly: AssemblyDescription("This package is a fork of Concentus, retargeted to .NET Standard 2.1 to fix a Span<T> runtime incompatibility on Unity's modern Mono/CLR. Concentus is a portable C# implementation of the Opus audio compression codec (see https://opus-codec.org/ for more details). This package contains the Opus encoder, decoder, multistream codecs, repacketizer, as well as a port of the libspeexdsp resampler. It does NOT contain code to parse .ogg or .opus container files or to manage RTP packet streams.")]
[assembly: AssemblyFileVersion("2.2.2.0")]
[assembly: AssemblyInformationalVersion("2.2.2+2537337a4922227ba977eba57b1cf278c855264a")]
[assembly: AssemblyProduct("ConcentusUnity")]
[assembly: AssemblyTitle("ConcentusUnity")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ZehsTeam/concentus-unity")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.2.0")]
[module: UnverifiableCode]
namespace ConcentusUnity
{
	public interface IOpusDecoder : IDisposable
	{
		OpusBandwidth Bandwidth { get; }

		uint FinalRange { get; }

		int Gain { get; set; }

		int LastPacketDuration { get; }

		int NumChannels { get; }

		int Pitch { get; }

		int SampleRate { get; }

		int Decode(ReadOnlySpan<byte> in_data, Span<float> out_pcm, int frame_size, bool decode_fec = false);

		int Decode(ReadOnlySpan<byte> in_data, Span<short> out_pcm, int frame_size, bool decode_fec = false);

		void ResetState();

		string GetVersionString();
	}
	public interface IOpusEncoder : IDisposable
	{
		OpusApplication Application { get; set; }

		int Bitrate { get; set; }

		int ForceChannels { get; set; }

		OpusBandwidth MaxBandwidth { get; set; }

		OpusBandwidth Bandwidth { get; set; }

		bool UseDTX { get; set; }

		int Complexity { get; set; }

		bool UseInbandFEC { get; set; }

		int PacketLossPercent { get; set; }

		bool UseVBR { get; set; }

		bool UseConstrainedVBR { get; set; }

		OpusSignal SignalType { get; set; }

		int Lookahead { get; }

		int SampleRate { get; }

		int NumChannels { get; }

		uint FinalRange { get; }

		int LSBDepth { get; set; }

		OpusFramesize ExpertFrameDuration { get; set; }

		OpusMode ForceMode { set; }

		bool PredictionDisabled { get; set; }

		int Encode(ReadOnlySpan<short> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		int Encode(ReadOnlySpan<float> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		void ResetState();

		string GetVersionString();
	}
	public interface IOpusMultiStreamDecoder : IDisposable
	{
		OpusBandwidth Bandwidth { get; }

		uint FinalRange { get; }

		int Gain { get; set; }

		int LastPacketDuration { get; }

		int SampleRate { get; }

		int NumChannels { get; }

		int DecodeMultistream(ReadOnlySpan<byte> data, Span<float> out_pcm, int frame_size, bool decode_fec);

		int DecodeMultistream(ReadOnlySpan<byte> data, Span<short> out_pcm, int frame_size, bool decode_fec);

		void ResetState();

		string GetVersionString();
	}
	public interface IOpusMultiStreamEncoder : IDisposable
	{
		OpusApplication Application { get; set; }

		OpusBandwidth Bandwidth { get; set; }

		int Bitrate { get; set; }

		int Complexity { get; set; }

		int NumChannels { get; }

		OpusFramesize ExpertFrameDuration { get; set; }

		uint FinalRange { get; }

		OpusMode ForceMode { set; }

		int Lookahead { get; }

		int LSBDepth { get; set; }

		OpusBandwidth MaxBandwidth { get; set; }

		int PacketLossPercent { get; set; }

		bool PredictionDisabled { get; set; }

		int SampleRate { get; }

		OpusSignal SignalType { get; set; }

		bool UseConstrainedVBR { get; set; }

		bool UseDTX { get; set; }

		bool UseInbandFEC { get; set; }

		bool UseVBR { get; set; }

		int EncodeMultistream(ReadOnlySpan<float> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		int EncodeMultistream(ReadOnlySpan<short> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		void ResetState();

		string GetVersionString();
	}
	public interface IResampler : IDisposable
	{
		int InputLatency { get; }

		int InputStride { get; set; }

		int OutputLatencySamples { get; }

		TimeSpan OutputLatency { get; }

		int OutputStride { get; set; }

		int Quality { get; set; }

		void GetRateFraction(out int ratio_num, out int ratio_den);

		void GetRates(out int in_rate, out int out_rate);

		void ResetMem();

		void SkipZeroes();

		void Process(int channel_index, Span<float> input, ref int in_len, Span<float> output, ref int out_len);

		void Process(int channel_index, Span<short> input, ref int in_len, Span<short> output, ref int out_len);

		void ProcessInterleaved(Span<float> input, ref int in_len, Span<float> output, ref int out_len);

		void ProcessInterleaved(Span<short> input, ref int in_len, Span<short> output, ref int out_len);

		void SetRateFraction(int ratio_num, int ratio_den, int in_rate, int out_rate);

		void SetRates(int in_rate, int out_rate);
	}
	public static class OpusCodecFactory
	{
		private static readonly object _mutex = new object();

		private static bool _nativeLibInitialized = false;

		private static bool _isNativeLibAvailable = false;

		private static bool _userAllowNativeLib = true;

		public static bool AttemptToUseNativeLibrary
		{
			get
			{
				return _userAllowNativeLib;
			}
			set
			{
				_userAllowNativeLib = value;
			}
		}

		public static IOpusEncoder CreateEncoder(int sampleRate, int numChannels, OpusApplication application = OpusApplication.OPUS_APPLICATION_AUDIO, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusEncoder.Create(sampleRate, numChannels, application);
			}
			return new OpusEncoder(sampleRate, numChannels, application);
		}

		public static IOpusDecoder CreateDecoder(int sampleRate, int numChannels, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusDecoder.Create(sampleRate, numChannels);
			}
			return new OpusDecoder(sampleRate, numChannels);
		}

		public static IOpusMultiStreamEncoder CreateMultiStreamEncoder(int sampleRate, int numChannels, int mappingFamily, out int streams, out int coupledStreams, byte[] mapping, OpusApplication application, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusMultistreamEncoder.Create(sampleRate, numChannels, mappingFamily, out streams, out coupledStreams, mapping, application);
			}
			return OpusMSEncoder.CreateSurround(sampleRate, numChannels, mappingFamily, out streams, out coupledStreams, mapping, application);
		}

		public static IOpusMultiStreamDecoder CreateMultiStreamDecoder(int sampleRate, int numChannels, int streams, int coupledStreams, byte[] mapping, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusMultistreamDecoder.Create(sampleRate, numChannels, streams, coupledStreams, mapping);
			}
			return new OpusMSDecoder(sampleRate, numChannels, streams, coupledStreams, mapping);
		}

		private static bool NativeLibraryAvailable(TextWriter messageLogger)
		{
			lock (_mutex)
			{
				if (!_nativeLibInitialized)
				{
					try
					{
						_isNativeLibAvailable = NativeOpus.Initialize(messageLogger);
						messageLogger?.WriteLine($"Is native opus available? {_isNativeLibAvailable}");
					}
					catch (Exception ex)
					{
						messageLogger?.WriteLine(ex.ToString());
					}
					_nativeLibInitialized = true;
				}
				return _isNativeLibAvailable;
			}
		}
	}
	internal static class Analysis
	{
		private const double M_PI = 3.141592653;

		private const float cA = 0.43157974f;

		private const float cB = 0.678484f;

		private const float cC = 0.08595542f;

		private const float cE = MathF.PI / 2f;

		private const int NB_TONAL_SKIP_BANDS = 9;

		internal static float fast_atan2f(float y, float x)
		{
			if (Inlines.ABS16(x) + Inlines.ABS16(y) < 1E-09f)
			{
				x *= 1E+12f;
				y *= 1E+12f;
			}
			float num = x * x;
			float num2 = y * y;
			if (num < num2)
			{
				float num3 = (num2 + 0.678484f * num) * (num2 + 0.08595542f * num);
				if (num3 != 0f)
				{
					return (0f - x) * y * (num2 + 0.43157974f * num) / num3 + ((y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f));
				}
				if (!(y < 0f))
				{
					return MathF.PI / 2f;
				}
				return -MathF.PI / 2f;
			}
			float num4 = (num + 0.678484f * num2) * (num + 0.08595542f * num2);
			if (num4 != 0f)
			{
				return x * y * (num + 0.43157974f * num2) / num4 + ((y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f)) - ((x * y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f));
			}
			return ((y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f)) - ((x * y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f));
		}

		internal static void tonality_analysis_init(TonalityAnalysisState tonal)
		{
			tonal.Reset();
		}

		internal static void tonality_get_info(TonalityAnalysisState tonal, AnalysisInfo info_out, int len)
		{
			int num = tonal.read_pos;
			int num2 = tonal.write_pos - tonal.read_pos;
			if (num2 < 0)
			{
				num2 += 200;
			}
			if (len > 480 && num != tonal.write_pos)
			{
				num++;
				if (num == 200)
				{
					num = 0;
				}
			}
			if (num == tonal.write_pos)
			{
				num--;
			}
			if (num < 0)
			{
				num = 199;
			}
			info_out.Assign(tonal.info[num]);
			tonal.read_subframe += len / 120;
			while (tonal.read_subframe >= 4)
			{
				tonal.read_subframe -= 4;
				tonal.read_pos++;
			}
			if (tonal.read_pos >= 200)
			{
				tonal.read_pos -= 200;
			}
			num2 = Inlines.IMAX(num2 - 10, 0);
			float num3 = 0f;
			int i;
			for (i = 0; i < 200 - num2; i++)
			{
				num3 += tonal.pmusic[i];
			}
			for (; i < 200; i++)
			{
				num3 += tonal.pspeech[i];
			}
			num3 = num3 * tonal.music_confidence + (1f - num3) * tonal.speech_confidence;
			info_out.music_prob = num3;
		}

		internal static void tonality_analysis<T>(TonalityAnalysisState tonal, CeltMode celt_mode, ReadOnlySpan<T> x, int len, int offset, int c1, int c2, int C, int lsb_depth, Downmix.downmix_func<T> downmix)
		{
			int num = 480;
			int num2 = 240;
			float[] angle = tonal.angle;
			float[] d_angle = tonal.d_angle;
			float[] d2_angle = tonal.d2_angle;
			float[] array = new float[18];
			float[] array2 = new float[18];
			float[] array3 = new float[8];
			float[] array4 = new float[25];
			float num3 = 97.40909f;
			float num4 = 0f;
			float[] array5 = new float[2];
			int num5 = 0;
			float num6 = 0f;
			tonal.last_transition++;
			float num7 = 1f / (float)Inlines.IMIN(20, 1 + tonal.count);
			float num8 = 1f / (float)Inlines.IMIN(50, 1 + tonal.count);
			float num9 = 1f / (float)Inlines.IMIN(1000, 1 + tonal.count);
			if (tonal.count < 4)
			{
				tonal.music_prob = 0.5f;
			}
			FFTState st = celt_mode.mdct.kfft[0];
			if (tonal.count == 0)
			{
				tonal.mem_fill = 240;
			}
			downmix(x, tonal.inmem, tonal.mem_fill, Inlines.IMIN(len, 720 - tonal.mem_fill), offset, c1, c2, C);
			if (tonal.mem_fill + len < 720)
			{
				tonal.mem_fill += len;
				return;
			}
			AnalysisInfo analysisInfo = tonal.info[tonal.write_pos++];
			if (tonal.write_pos >= 200)
			{
				tonal.write_pos -= 200;
			}
			int[] array6 = new int[960];
			int[] array7 = new int[960];
			float[] array8 = new float[240];
			float[] array9 = new float[240];
			for (int i = 0; i < num2; i++)
			{
				float num10 = Tables.analysis_window[i];
				array6[2 * i] = (int)(num10 * (float)tonal.inmem[i]);
				array6[2 * i + 1] = (int)(num10 * (float)tonal.inmem[num2 + i]);
				array6[2 * (num - i - 1)] = (int)(num10 * (float)tonal.inmem[num - i - 1]);
				array6[2 * (num - i - 1) + 1] = (int)(num10 * (float)tonal.inmem[num + num2 - i - 1]);
			}
			Arrays.MemMoveInt(tonal.inmem, 480, 0, 240);
			int num11 = len - (720 - tonal.mem_fill);
			downmix(x, tonal.inmem, 240, num11, offset + 720 - tonal.mem_fill, c1, c2, C);
			tonal.mem_fill = 240 + num11;
			KissFFT.opus_fft(st, array6, array7);
			for (int i = 1; i < num2; i++)
			{
				float x2 = (float)array7[2 * i] + (float)array7[2 * (num - i)];
				float y = (float)array7[2 * i + 1] - (float)array7[2 * (num - i) + 1];
				float x3 = (float)array7[2 * i + 1] + (float)array7[2 * (num - i) + 1];
				float y2 = (float)array7[2 * (num - i)] - (float)array7[2 * i];
				float num12 = 1f / (2f * MathF.PI) * fast_atan2f(y, x2);
				float num13 = num12 - angle[i];
				float num14 = num13 - d_angle[i];
				float num15 = 1f / (2f * MathF.PI) * fast_atan2f(y2, x3);
				float num16 = num15 - num12;
				float num17 = num16 - num13;
				float num18 = num14 - (float)Math.Floor(0.5f + num14);
				array9[i] = Inlines.ABS16(num18);
				num18 *= num18;
				num18 *= num18;
				float num19 = num17 - (float)Math.Floor(0.5f + num17);
				array9[i] += Inlines.ABS16(num19);
				num19 *= num19;
				num19 *= num19;
				float num20 = 0.25f * (d2_angle[i] + 2f * num18 + num19);
				array8[i] = 1f / (1f + 640f * num3 * num20) - 0.015f;
				angle[i] = num15;
				d_angle[i] = num16;
				d2_angle[i] = num19;
			}
			float num21 = 0f;
			float num22 = 0f;
			analysisInfo.activity = 0f;
			float num23 = 0f;
			float num24 = 0f;
			if (tonal.count == 0)
			{
				for (int j = 0; j < 18; j++)
				{
					tonal.lowE[j] = 1E+10f;
					tonal.highE[j] = -1E+10f;
				}
			}
			float num25 = 0f;
			float num26 = 0f;
			for (int j = 0; j < 18; j++)
			{
				float num27 = 0f;
				float num28 = 0f;
				float num29 = 0f;
				for (int i = Tables.tbands[j]; i < Tables.tbands[j + 1]; i++)
				{
					float num30 = (float)array7[2 * i] * (float)array7[2 * i] + (float)array7[2 * (num - i)] * (float)array7[2 * (num - i)] + (float)array7[2 * i + 1] * (float)array7[2 * i + 1] + (float)array7[2 * (num - i) + 1] * (float)array7[2 * (num - i) + 1];
					num30 *= 5.55E-17f;
					num27 += num30;
					num28 += num30 * array8[i];
					num29 += num30 * 2f * (0.5f - array9[i]);
				}
				tonal.E[tonal.E_count][j] = num27;
				num23 += num29 / (1E-15f + num27);
				num26 += (float)Math.Sqrt(num27 + 1E-10f);
				array2[j] = (float)Math.Log(num27 + 1E-10f);
				tonal.lowE[j] = Inlines.MIN32(array2[j], tonal.lowE[j] + 0.01f);
				tonal.highE[j] = Inlines.MAX32(array2[j], tonal.highE[j] - 0.1f);
				if (tonal.highE[j] < tonal.lowE[j] + 1f)
				{
					tonal.highE[j] += 0.5f;
					tonal.lowE[j] -= 0.5f;
				}
				num25 += (array2[j] - tonal.lowE[j]) / (1E-15f + tonal.highE[j] - tonal.lowE[j]);
				float num32;
				float num31 = (num32 = 0f);
				for (int i = 0; i < 8; i++)
				{
					num31 += (float)Math.Sqrt(tonal.E[i][j]);
					num32 += tonal.E[i][j];
				}
				float num33 = Inlines.MIN16(0.99f, num31 / (float)Math.Sqrt(1E-15 + (double)(8f * num32)));
				num33 *= num33;
				num33 *= num33;
				num24 += num33;
				array[j] = Inlines.MAX16(num28 / (1E-15f + num27), num33 * tonal.prev_band_tonality[j]);
				num21 += array[j];
				if (j >= 9)
				{
					num21 -= array[j - 18 + 9];
				}
				num22 = Inlines.MAX16(num22, (1f + 0.03f * (float)(j - 18)) * num21);
				num4 += array[j] * (float)(j - 8);
				tonal.prev_band_tonality[j] = array[j];
			}
			float num34 = 0f;
			num5 = 0;
			num6 = 0f;
			float num35 = 0.00057f / (float)(1 << Inlines.IMAX(0, lsb_depth - 8));
			num35 *= 134217730f;
			num35 *= num35;
			for (int j = 0; j < 21; j++)
			{
				float num36 = 0f;
				int num37 = Tables.extra_bands[j];
				int num38 = Tables.extra_bands[j + 1];
				for (int i = num37; i < num38; i++)
				{
					float num39 = (float)array7[2 * i] * (float)array7[2 * i] + (float)array7[2 * (num - i)] * (float)array7[2 * (num - i)] + (float)array7[2 * i + 1] * (float)array7[2 * i + 1] + (float)array7[2 * (num - i) + 1] * (float)array7[2 * (num - i) + 1];
					num36 += num39;
				}
				num6 = Inlines.MAX32(num6, num36);
				tonal.meanE[j] = Inlines.MAX32((1f - num9) * tonal.meanE[j], num36);
				num36 = Inlines.MAX32(num36, tonal.meanE[j]);
				num34 = Inlines.MAX32(0.05f * num34, num36);
				if ((double)num36 > 0.1 * (double)num34 && num36 * 1E+09f > num6 && num36 > num35 * (float)(num38 - num37))
				{
					num5 = j;
				}
			}
			if (tonal.count <= 2)
			{
				num5 = 20;
			}
			num26 = 20f * (float)Math.Log10(num26);
			tonal.Etracker = Inlines.MAX32(tonal.Etracker - 0.03f, num26);
			tonal.lowECount *= 1f - num8;
			if (num26 < tonal.Etracker - 30f)
			{
				tonal.lowECount += num8;
			}
			for (int i = 0; i < 8; i++)
			{
				float num40 = 0f;
				for (int j = 0; j < 16; j++)
				{
					num40 += Tables.dct_table[i * 16 + j] * array2[j];
				}
				array3[i] = num40;
			}
			num24 /= 18f;
			num25 /= 18f;
			if (tonal.count < 10)
			{
				num25 = 0.5f;
			}
			num23 /= 18f;
			analysisInfo.activity = num23 + (1f - num23) * num25;
			num21 = num22 / 9f;
			num21 = (tonal.prev_tonality = Inlines.MAX16(num21, tonal.prev_tonality * 0.8f));
			num4 /= 64f;
			analysisInfo.tonality_slope = num4;
			tonal.E_count = (tonal.E_count + 1) % 8;
			tonal.count++;
			analysisInfo.tonality = num21;
			for (int i = 0; i < 4; i++)
			{
				array4[i] = -0.12299f * (array3[i] + tonal.mem[i + 24]) + 0.49195f * (tonal.mem[i] + tonal.mem[i + 16]) + 0.69693f * tonal.mem[i + 8] - 1.4349f * tonal.cmean[i];
			}
			for (int i = 0; i < 4; i++)
			{
				tonal.cmean[i] = (1f - num7) * tonal.cmean[i] + num7 * array3[i];
			}
			for (int i = 0; i < 4; i++)
			{
				array4[4 + i] = 0.63246f * (array3[i] - tonal.mem[i + 24]) + 0.31623f * (tonal.mem[i] - tonal.mem[i + 16]);
			}
			for (int i = 0; i < 3; i++)
			{
				array4[8 + i] = 0.53452f * (array3[i] + tonal.mem[i + 24]) - 0.26726f * (tonal.mem[i] + tonal.mem[i + 16]) - 0.53452f * tonal.mem[i + 8];
			}
			if (tonal.count > 5)
			{
				for (int i = 0; i < 9; i++)
				{
					tonal.std[i] = (1f - num7) * tonal.std[i] + num7 * array4[i] * array4[i];
				}
			}
			for (int i = 0; i < 8; i++)
			{
				tonal.mem[i + 24] = tonal.mem[i + 16];
				tonal.mem[i + 16] = tonal.mem[i + 8];
				tonal.mem[i + 8] = tonal.mem[i];
				tonal.mem[i] = array3[i];
			}
			for (int i = 0; i < 9; i++)
			{
				array4[11 + i] = (float)Math.Sqrt(tonal.std[i]);
			}
			array4[20] = analysisInfo.tonality;
			array4[21] = analysisInfo.activity;
			array4[22] = num24;
			array4[23] = analysisInfo.tonality_slope;
			array4[24] = tonal.lowECount;
			MultiLayerPerceptron.mlp_process(Tables.net, array4, array5);
			array5[0] = 0.5f * (array5[0] + 1f);
			array5[0] = 0.01f + 1.21f * array5[0] * array5[0] - 0.23f * (float)Math.Pow(array5[0], 10.0);
			array5[1] = 0.5f * array5[1] + 0.5f;
			array5[0] = array5[1] * array5[0] + (1f - array5[1]) * 0.5f;
			float num41 = 5E-05f * array5[1];
			float num42 = 0.05f;
			float num43 = Inlines.MAX16(0.05f, Inlines.MIN16(0.95f, array5[0]));
			float num44 = Inlines.MAX16(0.05f, Inlines.MIN16(0.95f, tonal.music_prob));
			num42 = 0.01f + 0.05f * Inlines.ABS16(num43 - num44) / (num43 * (1f - num44) + num44 * (1f - num43));
			float num45 = (1f - tonal.music_prob) * (1f - num41) + tonal.music_prob * num41;
			float num46 = tonal.music_prob * (1f - num41) + (1f - tonal.music_prob) * num41;
			num45 *= (float)Math.Pow(1f - array5[0], num42);
			num46 *= (float)Math.Pow(array5[0], num42);
			tonal.music_prob = num46 / (num45 + num46);
			analysisInfo.music_prob = tonal.music_prob;
			float num47 = 1E-20f;
			float num48 = (float)Math.Pow(1f - array5[0], num42);
			float num49 = (float)Math.Pow(array5[0], num42);
			if (tonal.count == 1)
			{
				tonal.pspeech[0] = 0.5f;
				tonal.pmusic[0] = 0.5f;
			}
			float num50 = tonal.pspeech[0] + tonal.pspeech[1];
			float num51 = tonal.pmusic[0] + tonal.pmusic[1];
			tonal.pspeech[0] = num50 * (1f - num41) * num48;
			tonal.pmusic[0] = num51 * (1f - num41) * num49;
			for (int i = 1; i < 199; i++)
			{
				tonal.pspeech[i] = tonal.pspeech[i + 1] * num48;
				tonal.pmusic[i] = tonal.pmusic[i + 1] * num49;
			}
			tonal.pspeech[199] = num51 * num41 * num48;
			tonal.pmusic[199] = num50 * num41 * num49;
			for (int i = 0; i < 200; i++)
			{
				num47 += tonal.pspeech[i] + tonal.pmusic[i];
			}
			num47 = 1f / num47;
			for (int i = 0; i < 200; i++)
			{
				tonal.pspeech[i] *= num47;
				tonal.pmusic[i] *= num47;
			}
			num47 = tonal.pmusic[0];
			for (int i = 1; i < 200; i++)
			{
				num47 += tonal.pspeech[i];
			}
			if ((double)array5[1] > 0.75)
			{
				if ((double)tonal.music_prob > 0.9)
				{
					float num52 = 1f / (float)(++tonal.music_confidence_count);
					tonal.music_confidence_count = Inlines.IMIN(tonal.music_confidence_count, 500);
					tonal.music_confidence += num52 * Inlines.MAX16(-0.2f, array5[0] - tonal.music_confidence);
				}
				if ((double)tonal.music_prob < 0.1)
				{
					float num53 = 1f / (float)(++tonal.speech_confidence_count);
					tonal.speech_confidence_count = Inlines.IMIN(tonal.speech_confidence_count, 500);
					tonal.speech_confidence += num53 * Inlines.MIN16(0.2f, array5[0] - tonal.speech_confidence);
				}
			}
			else
			{
				if (tonal.music_confidence_count == 0)
				{
					tonal.music_confidence = 0.9f;
				}
				if (tonal.speech_confidence_count == 0)
				{
					tonal.speech_confidence = 0.1f;
				}
			}
			if (tonal.last_music != ((tonal.music_prob > 0.5f) ? 1 : 0))
			{
				tonal.last_transition = 0;
			}
			tonal.last_music = ((tonal.music_prob > 0.5f) ? 1 : 0);
			analysisInfo.bandwidth = num5;
			analysisInfo.noisiness = num23;
			analysisInfo.valid = 1;
		}

		internal static void run_analysis<T>(TonalityAnalysisState analysis, CeltMode celt_mode, ReadOnlySpan<T> analysis_pcm, int analysis_frame_size, int frame_size, int c1, int c2, int C, int Fs, int lsb_depth, Downmix.downmix_func<T> downmix, AnalysisInfo analysis_info)
		{
			if (!analysis_pcm.IsEmpty)
			{
				analysis_frame_size = Inlines.IMIN(195 * Fs / 100, analysis_frame_size);
				int num = analysis_frame_size - analysis.analysis_offset;
				int num2 = analysis.analysis_offset;
				do
				{
					tonality_analysis(analysis, celt_mode, analysis_pcm, Inlines.IMIN(480, num), num2, c1, c2, C, lsb_depth, downmix);
					num2 += 480;
					num -= 480;
				}
				while (num > 0);
				analysis.analysis_offset = analysis_frame_size;
				analysis.analysis_offset -= frame_size;
			}
			analysis_info.valid = 0;
			tonality_get_info(analysis, analysis_info, frame_size);
		}
	}
	internal static class CodecHelpers
	{
		private const int MAX_DYNAMIC_FRAMESIZE = 24;

		internal static byte gen_toc(OpusMode mode, int framerate, OpusBandwidth bandwidth, int channels)
		{
			int num = 0;
			while (framerate < 400)
			{
				framerate <<= 1;
				num++;
			}
			byte b;
			switch (mode)
			{
			case OpusMode.MODE_SILK_ONLY:
				b = (byte)((int)(bandwidth - 1101) << 5);
				b |= (byte)(num - 2 << 3);
				break;
			case OpusMode.MODE_CELT_ONLY:
			{
				int num2 = (int)(bandwidth - 1102);
				if (num2 < 0)
				{
					num2 = 0;
				}
				b = 128;
				b |= (byte)(num2 << 5);
				b |= (byte)(num << 3);
				break;
			}
			default:
				b = 96;
				b |= (byte)((int)(bandwidth - 1104) << 4);
				b |= (byte)(num - 2 << 3);
				break;
			}
			return (byte)(b | (byte)(((channels == 2) ? 1u : 0u) << 2));
		}

		internal static void hp_cutoff(ReadOnlySpan<short> input, int input_ptr, int cutoff_Hz, Span<short> output, int output_ptr, int[] hp_mem, int len, int channels, int Fs)
		{
			int[] array = new int[3];
			int[] array2 = new int[2];
			int num = Inlines.silk_DIV32_16(Inlines.silk_SMULBB(2471, cutoff_Hz), Fs / 1000);
			int num2 = (array[0] = 268435456 - Inlines.silk_MUL(471, num));
			array[1] = Inlines.silk_LSHIFT(-num2, 1);
			array[2] = num2;
			int num3 = Inlines.silk_RSHIFT(num2, 6);
			array2[0] = Inlines.silk_SMULWW(num3, Inlines.silk_SMULWW(num, num) - 8388608);
			array2[1] = Inlines.silk_SMULWW(num3, num3);
			Filters.silk_biquad_alt(input, input_ptr, array, array2, hp_mem, 0, output, output_ptr, len, channels);
			if (channels == 2)
			{
				Filters.silk_biquad_alt(input, input_ptr + 1, array, array2, hp_mem, 2, output, output_ptr + 1, len, channels);
			}
		}

		internal static void dc_reject(ReadOnlySpan<short> input, int input_ptr, int cutoff_Hz, Span<short> output, int output_ptr, int[] hp_mem, int len, int channels, int Fs)
		{
			int shift = Inlines.celt_ilog2(Fs / (cutoff_Hz * 3));
			for (int i = 0; i < channels; i++)
			{
				for (int j = 0; j < len; j++)
				{
					int num = Inlines.SHL32(Inlines.EXTEND32(input[channels * j + i + input_ptr]), 15);
					int num2 = num - hp_mem[2 * i];
					hp_mem[2 * i] += Inlines.PSHR32(num - hp_mem[2 * i], shift);
					int a = num2 - hp_mem[2 * i + 1];
					hp_mem[2 * i + 1] += Inlines.PSHR32(num2 - hp_mem[2 * i + 1], shift);
					output[channels * j + i + output_ptr] = Inlines.EXTRACT16(Inlines.SATURATE(Inlines.PSHR32(a, 15), 32767));
				}
			}
		}

		internal static void stereo_fade(short[] pcm_buf, int g1, int g2, int overlap48, int frame_size, int channels, int[] window, int Fs)
		{
			int num = 48000 / Fs;
			int num2 = overlap48 / num;
			g1 = 32767 - g1;
			g2 = 32767 - g2;
			int i;
			for (i = 0; i < num2; i++)
			{
				int num3 = Inlines.MULT16_16_Q15(window[i * num], window[i * num]);
				int a = Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num3, g2), 32767 - num3, g1), 15);
				int b = Inlines.EXTRACT16(Inlines.HALF32(pcm_buf[i * channels] - pcm_buf[i * channels + 1]));
				b = Inlines.MULT16_16_Q15(a, b);
				pcm_buf[i * channels] = (short)(pcm_buf[i * channels] - b);
				pcm_buf[i * channels + 1] = (short)(pcm_buf[i * channels + 1] + b);
			}
			for (; i < frame_size; i++)
			{
				int b2 = Inlines.EXTRACT16(Inlines.HALF32(pcm_buf[i * channels] - pcm_buf[i * channels + 1]));
				b2 = Inlines.MULT16_16_Q15(g2, b2);
				pcm_buf[i * channels] = (short)(pcm_buf[i * channels] - b2);
				pcm_buf[i * channels + 1] = (short)(pcm_buf[i * channels + 1] + b2);
			}
		}

		internal static void gain_fade(short[] buffer, int buf_ptr, int g1, int g2, int overlap48, int frame_size, int channels, int[] window, int Fs)
		{
			int num = 48000 / Fs;
			int num2 = overlap48 / num;
			if (channels == 1)
			{
				for (int i = 0; i < num2; i++)
				{
					int num3 = Inlines.MULT16_16_Q15(window[i * num], window[i * num]);
					int a = Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num3, g2), 32767 - num3, g1), 15);
					buffer[buf_ptr + i] = (short)Inlines.MULT16_16_Q15(a, buffer[buf_ptr + i]);
				}
			}
			else
			{
				for (int i = 0; i < num2; i++)
				{
					int num4 = Inlines.MULT16_16_Q15(window[i * num], window[i * num]);
					int a2 = Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num4, g2), 32767 - num4, g1), 15);
					buffer[buf_ptr + i * 2] = (short)Inlines.MULT16_16_Q15(a2, buffer[buf_ptr + i * 2]);
					buffer[buf_ptr + i * 2 + 1] = (short)Inlines.MULT16_16_Q15(a2, buffer[buf_ptr + i * 2 + 1]);
				}
			}
			int num5 = 0;
			do
			{
				for (int i = num2; i < frame_size; i++)
				{
					buffer[buf_ptr + i * channels + num5] = (short)Inlines.MULT16_16_Q15(g2, buffer[buf_ptr + i * channels + num5]);
				}
			}
			while (++num5 < channels);
		}

		internal static float transient_boost(Span<float> E, int E_ptr, float[] E_1, int LM, int maxM)
		{
			float num = 0f;
			float num2 = 0f;
			int num3 = Inlines.IMIN(maxM, (1 << LM) + 1);
			for (int i = E_ptr; i < num3 + E_ptr; i++)
			{
				num += E[i];
				num2 += E_1[i];
			}
			float num4 = num * num2 / (float)(num3 * num3);
			return Inlines.MIN16(1f, (float)Math.Sqrt(Inlines.MAX16(0f, 0.05f * (num4 - 2f))));
		}

		internal static int transient_viterbi(float[] E, float[] E_1, int N, int frame_cost, int rate)
		{
			float[][] array = Arrays.InitTwoDimensionalArray<float>(24, 16);
			int[][] array2 = Arrays.InitTwoDimensionalArray<int>(24, 16);
			float num = ((rate < 80) ? 0f : ((rate <= 160) ? (((float)rate - 80f) / 80f) : 1f));
			for (int i = 0; i < 16; i++)
			{
				array2[0][i] = -1;
				array[0][i] = 1E+10f;
			}
			for (int i = 0; i < 4; i++)
			{
				array[0][1 << i] = (float)(frame_cost + rate * (1 << i)) * (1f + num * transient_boost(E, 0, E_1, i, N + 1));
				array2[0][1 << i] = i;
			}
			for (int i = 1; i < N; i++)
			{
				for (int j = 2; j < 16; j++)
				{
					array[i][j] = array[i - 1][j - 1];
					array2[i][j] = j - 1;
				}
				for (int j = 0; j < 4; j++)
				{
					array2[i][1 << j] = 1;
					float num2 = array[i - 1][1];
					for (int k = 1; k < 4; k++)
					{
						float num3 = array[i - 1][(1 << k + 1) - 1];
						if (num3 < num2)
						{
							array2[i][1 << j] = (1 << k + 1) - 1;
							num2 = num3;
						}
					}
					float num4 = (float)(frame_cost + rate * (1 << j)) * (1f + num * transient_boost(E, i, E_1, j, N - i + 1));
					array[i][1 << j] = num2;
					if (N - i < 1 << j)
					{
						array[i][1 << j] += num4 * (float)(N - i) / (float)(1 << j);
					}
					else
					{
						array[i][1 << j] += num4;
					}
				}
			}
			int num5 = 1;
			float num6 = array[N - 1][1];
			for (int i = 2; i < 16; i++)
			{
				if (array[N - 1][i] < num6)
				{
					num6 = array[N - 1][i];
					num5 = i;
				}
			}
			for (int i = N - 1; i >= 0; i--)
			{
				num5 = array2[i][num5];
			}
			return num5;
		}

		internal static int optimize_framesize<T>(ReadOnlySpan<T> x, int len, int C, int Fs, int bitrate, int tonality, float[] mem, int buffering, Downmix.downmix_func<T> downmix)
		{
			float[] array = new float[28];
			float[] array2 = new float[27];
			int num = 0;
			int num2 = Fs / 400;
			int[] array3 = new int[num2];
			array[0] = mem[0];
			array2[0] = 1f / (1f + mem[0]);
			int num3;
			int num4;
			if (buffering != 0)
			{
				num3 = 2 * num2 - buffering;
				len -= num3;
				array[1] = mem[1];
				array2[1] = 1f / (1f + mem[1]);
				array[2] = mem[2];
				array2[2] = 1f / (1f + mem[2]);
				num4 = 3;
			}
			else
			{
				num4 = 1;
				num3 = 0;
			}
			int num5 = Inlines.IMIN(len / num2, 24);
			int num6 = 0;
			int i;
			for (i = 0; i < num5; i++)
			{
				float num7 = 1f;
				downmix(x, array3, 0, num2, i * num2 + num3, 0, -2, C);
				if (i == 0)
				{
					num6 = array3[0];
				}
				for (int j = 0; j < num2; j++)
				{
					int num8 = array3[j];
					num7 += (float)(num8 - num6) * (float)(num8 - num6);
					num6 = num8;
				}
				array[i + num4] = num7;
				array2[i + num4] = 1f / num7;
			}
			array[i + num4] = array[i + num4 - 1];
			if (buffering != 0)
			{
				num5 = Inlines.IMIN(24, num5 + 2);
			}
			num = transient_viterbi(array, array2, num5, (int)((1f + 0.5f * (float)tonality) * (float)(60 * C + 40)), bitrate / 400);
			mem[0] = array[1 << num];
			if (buffering != 0)
			{
				mem[1] = array[(1 << num) + 1];
				mem[2] = array[(1 << num) + 2];
			}
			return num;
		}

		internal static int frame_size_select(int frame_size, OpusFramesize variable_duration, int Fs)
		{
			if (frame_size < Fs / 400)
			{
				return -1;
			}
			int num;
			switch (variable_duration)
			{
			case OpusFramesize.OPUS_FRAMESIZE_ARG:
				num = frame_size;
				break;
			case OpusFramesize.OPUS_FRAMESIZE_VARIABLE:
				num = Fs / 50;
				break;
			case OpusFramesize.OPUS_FRAMESIZE_2_5_MS:
			case OpusFramesize.OPUS_FRAMESIZE_5_MS:
			case OpusFramesize.OPUS_FRAMESIZE_10_MS:
			case OpusFramesize.OPUS_FRAMESIZE_20_MS:
			case OpusFramesize.OPUS_FRAMESIZE_40_MS:
			case OpusFramesize.OPUS_FRAMESIZE_60_MS:
				num = Inlines.IMIN(3 * Fs / 50, Fs / 400 << (int)(variable_duration - 5001));
				break;
			default:
				return -1;
			}
			if (num > frame_size)
			{
				return -1;
			}
			if (400 * num != Fs && 200 * num != Fs && 100 * num != Fs && 50 * num != Fs && 25 * num != Fs && 50 * num != 3 * Fs)
			{
				return -1;
			}
			return num;
		}

		internal static int compute_frame_size<T>(ReadOnlySpan<T> analysis_pcm, int frame_size, OpusFramesize variable_duration, int C, int Fs, int bitrate_bps, int delay_compensation, Downmix.downmix_func<T> downmix, float[] subframe_mem, bool analysis_enabled)
		{
			if (analysis_enabled && variable_duration == OpusFramesize.OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs / 200)
			{
				int num = 3;
				num = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps, 0, subframe_mem, delay_compensation, downmix);
				while (Fs / 400 << num > frame_size)
				{
					num--;
				}
				frame_size = Fs / 400 << num;
			}
			else
			{
				frame_size = frame_size_select(frame_size, variable_duration, Fs);
			}
			if (frame_size < 0)
			{
				return -1;
			}
			return frame_size;
		}

		internal static int compute_stereo_width(ReadOnlySpan<short> pcm, int pcm_ptr, int frame_size, int Fs, StereoWidthState mem)
		{
			int num = Fs / frame_size;
			int a = 32767 - 819175 / Inlines.IMAX(50, num);
			int num3;
			int num4;
			int num2 = (num3 = (num4 = 0));
			for (int i = 0; i < frame_size - 3; i += 4)
			{
				int num5 = 0;
				int num6 = 0;
				int num7 = 0;
				int num8 = pcm_ptr + 2 * i;
				int num9 = pcm[num8];
				int num10 = pcm[num8 + 1];
				num5 = Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 = Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 = Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num9 = pcm[num8 + 2];
				num10 = pcm[num8 + 3];
				num5 += Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 += Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 += Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num9 = pcm[num8 + 4];
				num10 = pcm[num8 + 5];
				num5 += Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 += Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 += Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num9 = pcm[num8 + 6];
				num10 = pcm[num8 + 7];
				num5 += Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 += Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 += Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num2 += Inlines.SHR32(num5, 10);
				num3 += Inlines.SHR32(num6, 10);
				num4 += Inlines.SHR32(num7, 10);
			}
			mem.XX += Inlines.MULT16_32_Q15(a, num2 - mem.XX);
			mem.XY += Inlines.MULT16_32_Q15(a, num3 - mem.XY);
			mem.YY += Inlines.MULT16_32_Q15(a, num4 - mem.YY);
			mem.XX = Inlines.MAX32(0, mem.XX);
			mem.XY = Inlines.MAX32(0, mem.XY);
			mem.YY = Inlines.MAX32(0, mem.YY);
			if (Inlines.MAX32(mem.XX, mem.YY) > 210)
			{
				int num11 = Inlines.celt_sqrt(mem.XX);
				int num12 = Inlines.celt_sqrt(mem.YY);
				int num13 = Inlines.celt_sqrt(num11);
				int num14 = Inlines.celt_sqrt(num12);
				mem.XY = Inlines.MIN32(mem.XY, num11 * num12);
				int num15 = Inlines.SHR32(Inlines.frac_div32(mem.XY, 1 + Inlines.MULT16_16(num11, num12)), 16);
				int b = 32767 * Inlines.ABS16(num13 - num14) / (1 + num13 + num14);
				int num16 = Inlines.MULT16_16_Q15(Inlines.celt_sqrt(1073741824 - Inlines.MULT16_16(num15, num15)), b);
				mem.smoothed_width += (num16 - mem.smoothed_width) / num;
				mem.max_follower = Inlines.MAX16(mem.max_follower - 655 / num, mem.smoothed_width);
			}
			else
			{
				int num16 = 0;
				int num15 = 32767;
				int b = 0;
			}
			return Inlines.EXTRACT16(Inlines.MIN32(32767, 20 * mem.max_follower));
		}

		internal static void smooth_fade(Span<short> in1, int in1_ptr, Span<short> in2, int in2_ptr, Span<short> output, int output_ptr, int overlap, int channels, int[] window, int Fs)
		{
			int num = 48000 / Fs;
			for (int i = 0; i < channels; i++)
			{
				for (int j = 0; j < overlap; j++)
				{
					int num2 = Inlines.MULT16_16_Q15(window[j * num], window[j * num]);
					output[output_ptr + j * channels + i] = (short)Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num2, in2[in2_ptr + j * channels + i]), 32767 - num2, in1[in1_ptr + j * channels + i]), 15);
				}
			}
		}

		internal static string opus_strerror(int error)
		{
			string[] array = new string[8] { "success", "invalid argument", "buffer too small", "internal error", "corrupted stream", "request not implemented", "invalid state", "memory allocation failed" };
			if (error > 0 || error < -7)
			{
				return "unknown error";
			}
			return array[-error];
		}

		internal static string GetVersionString()
		{
			return "Concentus 2.1.2";
		}
	}
	internal static class Downmix
	{
		internal delegate void downmix_func<T>(ReadOnlySpan<T> _x, Span<int> sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C);

		internal static void downmix_float(ReadOnlySpan<float> x, Span<int> sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C)
		{
			for (int i = 0; i < subframe; i++)
			{
				sub[sub_ptr + i] = Inlines.FLOAT2INT16(x[(i + offset) * C + c1]);
			}
			if (c2 > -1)
			{
				for (int i = 0; i < subframe; i++)
				{
					sub[sub_ptr + i] += Inlines.FLOAT2INT16(x[(i + offset) * C + c2]);
				}
			}
			else if (c2 == -2)
			{
				for (int j = 1; j < C; j++)
				{
					int num = j;
					for (int i = 0; i < subframe; i++)
					{
						sub[sub_ptr + i] += Inlines.FLOAT2INT16(x[(i + offset) * C + num]);
					}
				}
			}
			int num2 = 4096;
			num2 = ((C != -2) ? (num2 / 2) : (num2 / C));
			for (int i = 0; i < subframe; i++)
			{
				sub[sub_ptr + i] *= num2;
			}
		}

		internal static void downmix_int(ReadOnlySpan<short> x, Span<int> sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C)
		{
			for (int i = 0; i < subframe; i++)
			{
				sub[i + sub_ptr] = x[(i + offset) * C + c1];
			}
			if (c2 > -1)
			{
				for (int i = 0; i < subframe; i++)
				{
					sub[i + sub_ptr] += x[(i + offset) * C + c2];
				}
			}
			else if (c2 == -2)
			{
				for (int j = 1; j < C; j++)
				{
					for (int i = 0; i < subframe; i++)
					{
						sub[i + sub_ptr] += x[(i + offset) * C + j];
					}
				}
			}
			int num = 4096;
			num = ((C != -2) ? (num / 2) : (num / C));
			for (int i = 0; i < subframe; i++)
			{
				sub[i + sub_ptr] *= num;
			}
		}
	}
	internal static class MultiLayerPerceptron
	{
		private const int MAX_NEURONS = 100;

		internal static float tansig_approx(float x)
		{
			float num = 1f;
			if (!(x < 8f))
			{
				return 1f;
			}
			if (!(x > -8f))
			{
				return -1f;
			}
			if (x < 0f)
			{
				x = 0f - x;
				num = -1f;
			}
			int num2 = (int)Math.Floor(0.5f + 25f * x);
			x -= 0.04f * (float)num2;
			float num3 = Tables.tansig_table[num2];
			float num4 = 1f - num3 * num3;
			num3 += x * num4 * (1f - num3 * x);
			return num * num3;
		}

		internal static void mlp_process(MLP m, float[] input, float[] output)
		{
			float[] array = new float[100];
			float[] weights = m.weights;
			int num = 0;
			for (int i = 0; i < m.topo[1]; i++)
			{
				float num2 = weights[num];
				num++;
				for (int j = 0; j < m.topo[0]; j++)
				{
					num2 += input[j] * weights[num];
					num++;
				}
				array[i] = tansig_approx(num2);
			}
			for (int i = 0; i < m.topo[2]; i++)
			{
				float num3 = weights[num];
				num++;
				for (int k = 0; k < m.topo[1]; k++)
				{
					num3 += array[k] * weights[num];
					num++;
				}
				output[i] = tansig_approx(num3);
			}
		}
	}
	internal static class OpusCompare
	{
		private const int NBANDS = 21;

		private const int NFREQS = 240;

		private const int TEST_WIN_SIZE = 480;

		private const int TEST_WIN_STEP = 120;

		private static readonly int[] BANDS = new int[22]
		{
			0, 2, 4, 6, 8, 10, 12, 14, 16, 20,
			24, 28, 32, 40, 48, 56, 68, 80, 96, 120,
			156, 200
		};

		private static void band_energy(Pointer<float> _out, Pointer<float> _ps, Pointer<int> _bands, int _nbands, Pointer<float> _in, int _nchannels, int _nframes, int _window_sz, int _step, int _downsample)
		{
			Pointer<float> pointer = ConcentusUnity.Common.CPlusPlus.Pointer.Malloc<float>((3 + _nchannels) * _window_sz);
			Pointer<float> pointer2 = pointer.Point(_window_sz);
			Pointer<float> pointer3 = pointer2.Point(_window_sz);
			Pointer<float> pointer4 = pointer3.Point(_window_sz);
			int num = _window_sz / 2;
			for (int i = 0; i < _window_sz; i++)
			{
				pointer[i] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * 2.0 / (double)(_window_sz - 1) * (double)i));
			}
			for (int i = 0; i < _window_sz; i++)
			{
				pointer2[i] = (float)Math.Cos(Math.PI * 2.0 / (double)_window_sz * (double)i);
			}
			for (int i = 0; i < _window_sz; i++)
			{
				pointer3[i] = (float)Math.Sin(Math.PI * 2.0 / (double)_window_sz * (double)i);
			}
			for (int j = 0; j < _nframes; j++)
			{
				for (int k = 0; k < _nchannels; k++)
				{
					for (int l = 0; l < _window_sz; l++)
					{
						pointer4[k * _window_sz + l] = pointer[l] * _in[(j * _step + l) * _nchannels + k];
					}
				}
				int i;
				for (int m = (i = 0); m < _nbands; m++)
				{
					float[] array = new float[2];
					for (; i < _bands[m + 1]; i++)
					{
						for (int k = 0; k < _nchannels; k++)
						{
							int num2 = 0;
							float num4;
							float num3 = (num4 = 0f);
							for (int l = 0; l < _window_sz; l++)
							{
								num3 += pointer2[num2] * pointer4[k * _window_sz + l];
								num4 -= pointer3[num2] * pointer4[k * _window_sz + l];
								num2 += i;
								if (num2 >= _window_sz)
								{
									num2 -= _window_sz;
								}
							}
							num3 *= (float)_downsample;
							num4 *= (float)_downsample;
							_ps[(j * num + i) * _nchannels + k] = num3 * num3 + num4 * num4 + 100000f;
							array[k] += _ps[(j * num + i) * _nchannels + k];
						}
					}
					if (_out != null)
					{
						_out[(j * _nbands + m) * _nchannels] = array[0] / (float)(_bands[m + 1] - _bands[m]);
						if (_nchannels == 2)
						{
							_out[(j * _nbands + m) * _nchannels + 1] = array[1] / (float)(_bands[m + 1] - _bands[m]);
						}
					}
				}
			}
		}

		internal static float compare(float[] x, float[] y, int nchannels, int rate = 48000)
		{
			int num = x.Length;
			int num2 = y.Length;
			int num3 = 21;
			int num4 = 240;
			if (rate != 8000 && rate != 12000 && rate != 16000 && rate != 24000 && rate != 48000)
			{
				throw new ArgumentException("Sampling rate must be 8000, 12000, 16000, 24000, or 48000\n");
			}
			int num5;
			if (rate != 48000)
			{
				num5 = 48000 / rate;
				switch (rate)
				{
				case 8000:
					num3 = 13;
					break;
				case 12000:
					num3 = 15;
					break;
				case 16000:
					num3 = 17;
					break;
				case 24000:
					num3 = 19;
					break;
				}
				num4 = 240 / num5;
			}
			else
			{
				num5 = 1;
			}
			if (num != num2 * num5)
			{
				throw new ArgumentException("Sample counts do not match");
			}
			if (num < 480)
			{
				throw new ArgumentException("Insufficient sample data");
			}
			int num6 = (num - 480 + 120) / 120;
			Pointer<float> pointer = ConcentusUnity.Common.CPlusPlus.Pointer.Malloc<float>(num6 * 21 * nchannels);
			Pointer<float> pointer2 = ConcentusUnity.Common.CPlusPlus.Pointer.Malloc<float>(num6 * 240 * nchannels);
			Pointer<float> pointer3 = ConcentusUnity.Common.CPlusPlus.Pointer.Malloc<float>(num6 * num4 * nchannels);
			band_energy(pointer, pointer2, BANDS.GetPointer(), 21, x.GetPointer(), nchannels, num6, 480, 120, 1);
			band_energy(null, pointer3, BANDS.GetPointer(), num3, y.GetPointer(), nchannels, num6, 480 / num5, 120 / num5, num5);
			for (int i = 0; i < num6; i++)
			{
				int j;
				for (j = 1; j < 21; j++)
				{
					for (int k = 0; k < nchannels; k++)
					{
						pointer[(i * 21 + j) * nchannels + k] += 0.1f * pointer[(i * 21 + j - 1) * nchannels + k];
					}
				}
				j = 20;
				while (j-- > 0)
				{
					for (int k = 0; k < nchannels; k++)
					{
						pointer[(i * 21 + j) * nchannels + k] += 0.03f * pointer[(i * 21 + j + 1) * nchannels + k];
					}
				}
				if (i > 0)
				{
					for (j = 0; j < 21; j++)
					{
						for (int k = 0; k < nchannels; k++)
						{
							pointer[(i * 21 + j) * nchannels + k] += 0.5f * pointer[((i - 1) * 21 + j) * nchannels + k];
						}
					}
				}
				if (nchannels == 2)
				{
					for (j = 0; j < 21; j++)
					{
						float num7 = pointer[(i * 21 + j) * nchannels];
						float num8 = pointer[(i * 21 + j) * nchannels + 1];
						pointer[(i * 21 + j) * nchannels] += 0.01f * num8;
						pointer[(i * 21 + j) * nchannels + 1] += 0.01f * num7;
					}
				}
				for (j = 0; j < num3; j++)
				{
					for (int l = BANDS[j]; l < BANDS[j + 1]; l++)
					{
						for (int k = 0; k < nchannels; k++)
						{
							pointer2[(i * 240 + l) * nchannels + k] += 0.1f * pointer[(i * 21 + j) * nchannels + k];
							pointer3[(i * num4 + l) * nchannels + k] += 0.1f * pointer[(i * 21 + j) * nchannels + k];
						}
					}
				}
			}
			for (int j = 0; j < num3; j++)
			{
				for (int l = BANDS[j]; l < BANDS[j + 1]; l++)
				{
					for (int k = 0; k < nchannels; k++)
					{
						float num9 = pointer2[l * nchannels + k];
						float num10 = pointer3[l * nchannels + k];
						for (int i = 1; i < num6; i++)
						{
							float num11 = pointer2[(i * 240 + l) * nchannels + k];
							float num12 = pointer3[(i * num4 + l) * nchannels + k];
							pointer2[(i * 240 + l) * nchannels + k] += num9;
							pointer3[(i * num4 + l) * nchannels + k] += num10;
							num9 = num11;
							num10 = num12;
						}
					}
				}
			}
			int num13 = rate switch
			{
				48000 => BANDS[21], 
				12000 => BANDS[num3], 
				_ => BANDS[num3] - 3, 
			};
			double num14 = 0.0;
			for (int i = 0; i < num6; i++)
			{
				double num15 = 0.0;
				for (int j = 0; j < num3; j++)
				{
					double num16 = 0.0;
					for (int l = BANDS[j]; l < BANDS[j + 1] && l < num13; l++)
					{
						for (int k = 0; k < nchannels; k++)
						{
							float num17 = pointer3[(i * num4 + l) * nchannels + k] / pointer2[(i * 240 + l) * nchannels + k];
							float num18 = num17 - (float)Math.Log(num17) - 1f;
							if (l >= 79 && l <= 81)
							{
								num18 *= 0.1f;
							}
							if (l == 80)
							{
								num18 *= 0.1f;
							}
							num16 += (double)num18;
						}
					}
					num16 /= (double)((BANDS[j + 1] - BANDS[j]) * nchannels);
					num15 += num16 * num16;
				}
				num15 /= 21.0;
				num15 *= num15;
				num14 += num15 * num15;
			}
			num14 = Math.Pow(num14 / (double)num6, 0.0625);
			float result = (float)(100.0 * (1.0 - 0.5 * Math.Log(1.0 + num14) / Math.Log(1.13)));
			_ = 0f;
			return result;
		}
	}
	internal static class OpusConstants
	{
		internal const int OPUS_AUTO = -1000;

		internal const int OPUS_BITRATE_MAX = -1;

		internal const int NB_FRAMES = 8;

		internal const int NB_TBANDS = 18;

		internal const int NB_TOT_BANDS = 21;

		internal const int NB_TONAL_SKIP_BANDS = 9;

		internal const int ANALYSIS_BUF_SIZE = 720;

		internal const int DETECT_SIZE = 200;

		internal const int MAX_ENCODER_BUFFER = 480;
	}
	public class OpusException : Exception
	{
		public int OpusErrorCode { get; private set; }

		internal OpusException()
			: base("Unknown error")
		{
			OpusErrorCode = -100;
		}

		internal OpusException(string message)
			: base(message)
		{
			OpusErrorCode = -100;
		}

		internal OpusException(int opusError)
			: base(CodecHelpers.opus_strerror(opusError))
		{
			OpusErrorCode = opusError;
		}

		internal OpusException(string message, int opusError)
			: base(message)
		{
			OpusErrorCode = opusError;
		}
	}
	internal static class OpusMultistream
	{
		internal static int validate_layout(ChannelLayout layout)
		{
			int num = layout.nb_streams + layout.nb_coupled_streams;
			if (num > 255)
			{
				return 0;
			}
			for (int i = 0; i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] >= num && layout.mapping[i] != byte.MaxValue)
				{
					return 0;
				}
			}
			return 1;
		}

		internal static int get_left_channel(ChannelLayout layout, int stream_id, int prev)
		{
			for (int i = ((prev >= 0) ? (prev + 1) : 0); i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] == stream_id * 2)
				{
					return i;
				}
			}
			return -1;
		}

		internal static int get_right_channel(ChannelLayout layout, int stream_id, int prev)
		{
			for (int i = ((prev >= 0) ? (prev + 1) : 0); i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] == stream_id * 2 + 1)
				{
					return i;
				}
			}
			return -1;
		}

		internal static int get_mono_channel(ChannelLayout layout, int stream_id, int prev)
		{
			for (int i = ((prev >= 0) ? (prev + 1) : 0); i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] == stream_id + layout.nb_coupled_streams)
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal static class Tables
	{
		internal static readonly float[] dct_table = new float[128]
		{
			0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f,
			0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.351851f, 0.33833f, 0.311806f, 0.2733f,
			0.224292f, 0.166664f, 0.102631f, 0.034654f, -0.034654f, -0.102631f, -0.166664f, -0.224292f, -0.2733f, -0.311806f,
			-0.33833f, -0.351851f, 0.34676f, 0.293969f, 0.196424f, 0.068975f, -0.068975f, -0.196424f, -0.293969f, -0.34676f,
			-0.34676f, -0.293969f, -0.196424f, -0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.34676f, 0.33833f, 0.224292f,
			0.034654f, -0.166664f, -0.311806f, -0.351851f, -0.2733f, -0.102631f, 0.102631f, 0.2733f, 0.351851f, 0.311806f,
			0.166664f, -0.034654f, -0.224292f, -0.33833f, 0.326641f, 0.135299f, -0.135299f, -0.326641f, -0.326641f, -0.135299f,
			0.135299f, 0.326641f, 0.326641f, 0.135299f, -0.135299f, -0.326641f, -0.326641f, -0.135299f, 0.135299f, 0.326641f,
			0.311806f, 0.034654f, -0.2733f, -0.33833f, -0.102631f, 0.224292f, 0.351851f, 0.166664f, -0.166664f, -0.351851f,
			-0.224292f, 0.102631f, 0.33833f, 0.2733f, -0.034654f, -0.311806f, 0.293969f, -0.068975f, -0.34676f, -0.196424f,
			0.196424f, 0.34676f, 0.068975f, -0.293969f, -0.293969f, 0.068975f, 0.34676f, 0.196424f, -0.196424f, -0.34676f,
			-0.068975f, 0.293969f, 0.2733f, -0.166664f, -0.33833f, 0.034654f, 0.351851f, 0.102631f, -0.311806f, -0.224292f,
			0.224292f, 0.311806f, -0.102631f, -0.351851f, -0.034654f, 0.33833f, 0.166664f, -0.2733f
		};

		internal static readonly float[] analysis_window = new float[240]
		{
			4.3E-05f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f, 0.003466f, 0.004278f,
			0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f, 0.012329f, 0.013815f, 0.015385f, 0.017037f,
			0.018772f, 0.02059f, 0.02249f, 0.024472f, 0.026535f, 0.028679f, 0.030904f, 0.03321f, 0.035595f, 0.03806f,
			0.040604f, 0.043227f, 0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f,
			0.070297f, 0.07368f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f, 0.099373f, 0.103323f,
			0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.12408f, 0.128428f, 0.132839f, 0.137313f, 0.141849f, 0.146447f,
			0.151105f, 0.155823f, 0.1606f, 0.165435f, 0.170327f, 0.175276f, 0.18028f, 0.18534f, 0.190453f, 0.195619f,
			0.200838f, 0.206107f, 0.211427f, 0.216797f, 0.222215f, 0.22768f, 0.233193f, 0.238751f, 0.244353f, 0.25f,
			0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.29067f, 0.296632f, 0.302628f, 0.308658f,
			0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.33928f, 0.345492f, 0.351729f, 0.357992f, 0.36428f, 0.37059f,
			0.376923f, 0.383277f, 0.389651f, 0.396044f, 0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f,
			0.441231f, 0.447736f, 0.454249f, 0.46077f, 0.467298f, 0.473832f, 0.48037f, 0.486912f, 0.493455f, 0.5f,
			0.506545f, 0.513088f, 0.51963f, 0.526168f, 0.532702f, 0.53923f, 0.545751f, 0.552264f, 0.558769f, 0.565263f,
			0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f, 0.610349f, 0.616723f, 0.623077f, 0.62941f,
			0.63572f, 0.642008f, 0.648271f, 0.654508f, 0.66072f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f,
			0.697372f, 0.703368f, 0.70933f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.75f,
			0.755647f, 0.761249f, 0.766807f, 0.77232f, 0.777785f, 0.783203f, 0.788573f, 0.793893f, 0.799162f, 0.804381f,
			0.809547f, 0.81466f, 0.81972f, 0.824724f, 0.829673f, 0.834565f, 0.8394f, 0.844177f, 0.848895f, 0.853553f,
			0.858151f, 0.862687f, 0.867161f, 0.871572f, 0.87592f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f,
			0.900627f, 0.904508f, 0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.92632f, 0.929703f, 0.933013f,
			0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f, 0.959396f, 0.96194f,
			0.964405f, 0.96679f, 0.969096f, 0.971321f, 0.973465f, 0.975528f, 0.97751f, 0.97941f, 0.981228f, 0.982963f,
			0.984615f, 0.986185f, 0.987671f, 0.989074f, 0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f,
			0.996534f, 0.997261f, 0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1f
		};

		internal static readonly int[] tbands = new int[19]
		{
			2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
			28, 32, 40, 48, 56, 68, 80, 96, 120
		};

		internal static readonly int[] extra_bands = new int[22]
		{
			1, 2, 4, 6, 8, 10, 12, 14, 16, 20,
			24, 28, 32, 40, 48, 56, 68, 80, 96, 120,
			160, 200
		};

		internal static readonly float[] weights = new float[422]
		{
			-0.0941125f,
			-0.302976f,
			-0.603555f,
			-0.19393f,
			-0.185983f,
			-0.601617f,
			-0.0465317f,
			-0.114563f,
			-0.103599f,
			-0.618938f,
			-0.317859f,
			-0.169949f,
			-0.0702885f,
			0.148065f,
			0.409524f,
			0.548432f,
			0.367649f,
			-0.494393f,
			0.764306f,
			-1.83957f,
			0.170849f,
			12.786f,
			-1.08848f,
			-1.27284f,
			-16.2606f,
			24.1773f,
			-5.57454f,
			-0.17276f,
			-0.163388f,
			-0.224421f,
			-0.0948944f,
			-0.0728695f,
			-0.26557f,
			-0.100283f,
			-0.0515459f,
			-0.146142f,
			-0.120674f,
			-0.180655f,
			0.12857f,
			0.442138f,
			-0.493735f,
			0.167767f,
			0.206699f,
			-0.197567f,
			0.417999f,
			1.50364f,
			-0.773341f,
			-10.0401f,
			0.401872f,
			2.97966f,
			15.2165f,
			-1.88905f,
			-1.19254f,
			0.0285397f,
			-0.00405139f,
			0.0707565f,
			0.00825699f,
			-0.0927269f,
			-0.010393f,
			-0.00428882f,
			-0.00489743f,
			-0.0709731f,
			-0.00255992f,
			0.0395619f,
			0.226424f,
			0.0325231f,
			0.162175f,
			-0.100118f,
			0.485789f,
			0.12697f,
			0.285937f,
			0.0155637f,
			0.10546f,
			3.05558f,
			1.15059f,
			-1.00904f,
			-1.83088f,
			3.31766f,
			-3.42516f,
			-0.119135f,
			-0.0405654f,
			0.00690068f,
			0.0179877f,
			-0.0382487f,
			0.00597941f,
			-0.0183611f,
			0.00190395f,
			-0.144322f,
			-0.0435671f,
			0.000990594f,
			0.221087f,
			0.142405f,
			0.484066f,
			0.404395f,
			0.511955f,
			-0.237255f,
			0.241742f,
			0.35045f,
			-0.699428f,
			10.3993f,
			2.6507f,
			-2.43459f,
			-4.18838f,
			1.05928f,
			1.71067f,
			0.00667811f,
			-0.0721335f,
			-0.0397346f,
			0.0362704f,
			-0.11496f,
			-0.0235776f,
			0.0082161f,
			-0.0141741f,
			-0.0329699f,
			-0.0354253f,
			0.00277404f,
			-0.290654f,
			-1.14767f,
			-0.319157f,
			-0.686544f,
			0.36897f,
			0.478899f,
			0.182579f,
			-0.411069f,
			0.881104f,
			-4.60683f,
			1.4697f,
			325f / (356f * MathF.E),
			-1.81905f,
			-30.1699f,
			5.55225f,
			0.0019508f,
			-0.123576f,
			-0.0727332f,
			-0.0641597f,
			-0.0534458f,
			-0.108166f,
			-0.0937368f,
			-0.0697883f,
			-0.0275475f,
			-0.192309f,
			-0.110074f,
			0.285375f,
			-0.405597f,
			0.0926724f,
			-0.287881f,
			-0.851193f,
			-0.099493f,
			-0.233764f,
			-1.2852f,
			1.13611f,
			3.12168f,
			-0.0699f,
			-1.86216f,
			2.65292f,
			-7.31036f,
			2.44776f,
			-0.00111802f,
			-0.0632786f,
			-0.0376296f,
			-0.149851f,
			0.142963f,
			0.184368f,
			0.123433f,
			0.0756158f,
			0.117312f,
			0.0933395f,
			0.0692163f,
			0.0842592f,
			0.0704683f,
			0.0589963f,
			0.0942205f,
			-0.448862f,
			0.0262677f,
			0.270352f,
			-0.262317f,
			0.172586f,
			2.00227f,
			-0.159216f,
			0.038422f,
			10.2073f,
			4.15536f,
			-2.3407f,
			-0.0550265f,
			0.00964792f,
			-0.141336f,
			0.0274501f,
			0.0343921f,
			-0.0487428f,
			0.0950172f,
			-0.00775017f,
			-0.0372492f,
			-0.00548121f,
			-0.0663695f,
			0.0960506f,
			-0.200008f,
			-0.0412827f,
			0.58728f,
			0.0515787f,
			0.337254f,
			0.855024f,
			0.668371f,
			-0.114904f,
			-3.62962f,
			-0.467477f,
			-0.215472f,
			2.61537f,
			0.406117f,
			-1.36373f,
			0.0425394f,
			0.12208f,
			0.0934502f,
			0.123055f,
			0.0340935f,
			-0.142466f,
			0.035037f,
			-0.0490666f,
			0.0733208f,
			0.0576672f,
			0.123984f,
			-0.0517194f,
			-0.253018f,
			0.590565f,
			0.145849f,
			0.315185f,
			0.221534f,
			-0.149081f,
			0.216161f,
			-0.349575f,
			24.5664f,
			-0.994196f,
			0.614289f,
			-18.7905f,
			-2.83277f,
			-0.716801f,
			-0.347201f,
			0.479515f,
			-0.246027f,
			0.0758683f,
			0.137293f,
			-0.17781f,
			0.118751f,
			-0.00108329f,
			-0.237334f,
			0.355732f,
			-0.12991f,
			-0.0547627f,
			-0.318576f,
			-0.325524f,
			0.180494f,
			-0.0625604f,
			0.141219f,
			0.344064f,
			0.37658f,
			-0.591772f,
			5.8427f,
			-0.38075f,
			0.221894f,
			-1.41934f,
			-1879430f,
			1.34114f,
			0.0283355f,
			-0.0447856f,
			-0.0211466f,
			-0.0256927f,
			0.0139618f,
			0.0207934f,
			-0.0107666f,
			0.0110969f,
			0.0586069f,
			-0.0253545f,
			-0.0328433f,
			0.11872f,
			-0.216943f,
			0.145748f,
			0.119808f,
			-0.0915211f,
			-0.120647f,
			-0.0787719f,
			-0.143644f,
			-0.595116f,
			-1.152f,
			-1.25335f,
			-1.17092f,
			4.34023f,
			-975268f,
			-1.37033f,
			-0.0401123f,
			0.210602f,
			-0.136656f,
			0.135962f,
			-0.0523293f,
			0.0444604f,
			0.0143928f,
			0.00412666f,
			-0.0193003f,
			0.218452f,
			-0.110204f,
			-2.02563f,
			0.918238f,
			-2.45362f,
			1.19542f,
			-0.061362f,
			-1.92243f,
			0.308111f,
			0.49764f,
			0.912356f,
			0.209272f,
			-2.34525f,
			2.19326f,
			-6.47121f,
			1.69771f,
			-0.725123f,
			0.0118929f,
			0.0377944f,
			0.0554003f,
			0.0226452f,
			-0.0704421f,
			-0.0300309f,
			0.0122978f,
			-0.0041782f,
			-0.0686612f,
			0.0313115f,
			0.039111f,
			0.364111f,
			-0.0945548f,
			0.0229876f,
			-0.17414f,
			0.329795f,
			0.114714f,
			0.30022f,
			0.106997f,
			0.132355f,
			5.79932f,
			0.908058f,
			-0.905324f,
			-3.3561f,
			0.190647f,
			0.184211f,
			-0.673648f,
			0.231807f,
			-0.0586222f,
			0.230752f,
			-0.438277f,
			0.245857f,
			-0.17215f,
			0.0876383f,
			-0.720512f,
			0.162515f,
			0.0170571f,
			0.101781f,
			0.388477f,
			1.32931f,
			1.08548f,
			-0.936301f,
			-2.36958f,
			-6.71988f,
			-3.44376f,
			2.13818f,
			14.2318f,
			4.91459f,
			-3.09052f,
			-9.69191f,
			-0.768234f,
			1.79604f,
			0.0549653f,
			0.163399f,
			0.0797025f,
			0.0343933f,
			-0.0555876f,
			-0.00505673f,
			0.0187258f,
			0.0326628f,
			0.0231486f,
			0.15573f,
			0.0476223f,
			-0.254824f,
			1.60155f,
			-0.801221f,
			2.55496f,
			0.737629f,
			-1.36249f,
			-0.695463f,
			-2.44301f,
			-1.73188f,
			3.95279f,
			1.89068f,
			0.486087f,
			-11.3343f,
			3941600f,
			-0.381439f,
			0.12115f,
			-0.906927f,
			2.93878f,
			1.6388f,
			0.882811f,
			0.874344f,
			1.21726f,
			-0.874545f,
			0.321706f,
			0.785055f,
			0.946558f,
			-0.575066f,
			-3.46553f,
			0.884905f,
			0.0924047f,
			-9.90712f,
			0.391338f,
			0.160103f,
			-2.04954f,
			4.1455f,
			0.0684029f,
			-0.144761f,
			-0.285282f,
			0.379244f,
			-1.1584f,
			-0.0277241f,
			-9.85f,
			-4.82386f,
			3.71333f,
			3.87308f,
			3.52558f
		};

		internal static readonly int[] topo = new int[3] { 25, 15, 2 };

		internal static readonly MLP net = new MLP
		{
			layers = 3,
			topo = topo,
			weights = weights
		};

		internal static readonly float[] tansig_table = new float[201]
		{
			0f, 0.039979f, 0.07983f, 0.119427f, 0.158649f, 0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f,
			0.379949f, 0.413644f, 0.446244f, 0.4777f, 0.507977f, 0.53705f, 0.5649f, 0.591519f, 0.616909f, 0.641077f,
			0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f, 0.761594f, 0.777888f, 0.793199f, 0.807569f, 0.82104f,
			0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f, 0.885352f, 0.893698f, 0.901468f, 0.908698f, 0.91542f,
			0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f, 0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.96109f,
			0.964028f, 0.966747f, 0.969265f, 0.971594f, 0.973749f, 0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f,
			0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f, 0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.99202f,
			0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f, 0.995055f, 0.995434f, 0.995784f, 0.996108f, 0.996407f,
			0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.99759f, 0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f,
			0.998508f, 0.998623f, 0.998728f, 0.998826f, 0.998916f, 0.999f, 0.999076f, 0.999147f, 0.999213f, 0.999273f,
			0.999329f, 0.999381f, 0.999428f, 0.999472f, 0.999513f, 0.99955f, 0.999585f, 0.999617f, 0.999646f, 0.999673f,
			0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f, 0.999798f, 0.999813f, 0.999828f, 0.999841f, 0.999853f,
			0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f, 0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f,
			0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f, 0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.99997f,
			0.999973f, 0.999975f, 0.999977f, 0.999978f, 0.99998f, 0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f,
			0.999988f, 0.999989f, 0.99999f, 0.99999f, 0.999991f, 0.999992f, 0.999992f, 0.999993f, 0.999994f, 0.999994f,
			0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f, 0.999996f, 0.999997f, 0.999997f, 0.999997f, 0.999997f,
			0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f,
			0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f,
			1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f,
			1f
		};

		internal static readonly int[] mono_voice_bandwidth_thresholds = new int[8] { 11000, 1000, 14000, 1000, 17000, 1000, 21000, 2000 };

		internal static readonly int[] mono_music_bandwidth_thresholds = new int[8] { 12000, 1000, 15000, 1000, 18000, 2000, 22000, 2000 };

		internal static readonly int[] stereo_voice_bandwidth_thresholds = new int[8] { 11000, 1000, 14000, 1000, 21000, 2000, 28000, 2000 };

		internal static readonly int[] stereo_music_bandwidth_thresholds = new int[8] { 12000, 1000, 18000, 2000, 21000, 2000, 30000, 2000 };

		internal const int stereo_voice_threshold = 30000;

		internal const int stereo_music_threshold = 30000;

		internal static readonly int[][] mode_thresholds = new int[2][]
		{
			new int[2] { 64000, 16000 },
			new int[2] { 36000, 16000 }
		};
	}
	public static class ResamplerFactory
	{
		public static IResampler CreateResampler(int numChannels, int inRate, int outRate, int quality, TextWriter logger = null)
		{
			return CreateResampler(numChannels, inRate, outRate, inRate, outRate, quality, logger);
		}

		public static IResampler CreateResampler(int numChannels, int ratioNum, int ratioDen, int inRate, int outRate, int quality, TextWriter logger = null)
		{
			if (numChannels <= 0)
			{
				throw new ArgumentOutOfRangeException("numChannels");
			}
			if (ratioNum <= 0)
			{
				throw new ArgumentOutOfRangeException("ratioNum");
			}
			if (ratioDen <= 0)
			{
				throw new ArgumentOutOfRangeException("ratioDen");
			}
			if (inRate <= 0)
			{
				throw new ArgumentOutOfRangeException("inRate");
			}
			if (outRate <= 0)
			{
				throw new ArgumentOutOfRangeException("outRate");
			}
			if (quality < 0 || quality > 10)
			{
				throw new ArgumentOutOfRangeException("quality", "Quality must be between 0 and 10");
			}
			return new SpeexResampler(numChannels, ratioNum, ratioDen, inRate, outRate, quality);
		}
	}
}
namespace ConcentusUnity.Silk
{
	internal static class ApplySineWindow
	{
		private static readonly short[] freq_table_Q16 = new short[27]
		{
			12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, 3885,
			3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, 2313, 2214,
			2123, 2038, 1961, 1889, 1822, 1760, 1702
		};

		internal static void silk_apply_sine_window(short[] px_win, int px_win_ptr, short[] px, int px_ptr, int win_type, int length)
		{
			int num = (length >> 2) - 4;
			int num2 = freq_table_Q16[num];
			int num3 = Inlines.silk_SMULWB(num2, -num2);
			int num4;
			int num5;
			if (win_type == 1)
			{
				num4 = 0;
				num5 = num2 + Inlines.silk_RSHIFT(length, 3);
			}
			else
			{
				num4 = 65536;
				num5 = 65536 + Inlines.silk_RSHIFT(num3, 1) + Inlines.silk_RSHIFT(length, 4);
			}
			for (num = 0; num < length; num += 4)
			{
				int num6 = px_win_ptr + num;
				int num7 = px_ptr + num;
				px_win[num6] = (short)Inlines.silk_SMULWB(Inlines.silk_RSHIFT(num4 + num5, 1), px[num7]);
				px_win[num6 + 1] = (short)Inlines.silk_SMULWB(num5, px[num7 + 1]);
				num4 = Inlines.silk_SMULWB(num5, num3) + Inlines.silk_LSHIFT(num5, 1) - num4 + 1;
				num4 = Inlines.silk_min(num4, 65536);
				px_win[num6 + 2] = (short)Inlines.silk_SMULWB(Inlines.silk_RSHIFT(num4 + num5, 1), px[num7 + 2]);
				px_win[num6 + 3] = (short)Inlines.silk_SMULWB(num4, px[num7 + 3]);
				num5 = Inlines.silk_SMULWB(num4, num3) + Inlines.silk_LSHIFT(num4, 1) - num5;
				num5 = Inlines.silk_min(num5, 65536);
			}
		}
	}
	internal static class BurgModified
	{
		private const int MAX_FRAME_SIZE = 384;

		private const int QA = 25;

		private const int N_BITS_HEAD_ROOM = 2;

		private const int MIN_RSHIFTS = -16;

		private const int MAX_RSHIFTS = 7;

		internal static void silk_burg_modified(BoxedValueInt res_nrg, BoxedValueInt res_nrg_Q, int[] A_Q16, short[] x, int x_ptr, int minInvGain_Q30, int subfr_length, int nb_subfr, int D)
		{
			int[] array = new int[16];
			int[] array2 = new int[16];
			int[] array3 = new int[16];
			int[] array4 = new int[17];
			int[] array5 = new int[17];
			int[] array6 = new int[16];
			long num = Inlines.silk_inner_prod16_aligned_64(x, x_ptr, x, x_ptr, subfr_length * nb_subfr);
			int num2 = Inlines.silk_CLZ64(num);
			int num3 = 35 - num2;
			if (num3 > 7)
			{
				num3 = 7;
			}
			if (num3 < -16)
			{
				num3 = -16;
			}
			int num4 = (int)((num3 <= 0) ? Inlines.silk_LSHIFT32((int)num, -num3) : Inlines.silk_RSHIFT64(num, num3));
			array5[0] = (array4[0] = num4 + Inlines.silk_SMMUL(42950, num4) + 1);
			Arrays.MemSetInt(array, 0, 16);
			if (num3 > 0)
			{
				for (int i = 0; i < nb_subfr; i++)
				{
					int num5 = x_ptr + i * subfr_length;
					for (int j = 1; j < D + 1; j++)
					{
						array[j - 1] += (int)Inlines.silk_RSHIFT64(Inlines.silk_inner_prod16_aligned_64(x, num5, x, num5 + j, subfr_length - j), num3);
					}
				}
			}
			else
			{
				for (int i = 0; i < nb_subfr; i++)
				{
					int num5 = x_ptr + i * subfr_length;
					CeltPitchXCorr.pitch_xcorr(x, num5, x, num5 + 1, array6, subfr_length - D, D);
					for (int j = 1; j < D + 1; j++)
					{
						int k = j + subfr_length - D;
						int num6 = 0;
						for (; k < subfr_length; k++)
						{
							num6 = Inlines.MAC16_16(num6, x[num5 + k], x[num5 + k - j]);
						}
						array6[j - 1] += num6;
					}
					for (int j = 1; j < D + 1; j++)
					{
						array[j - 1] += Inlines.silk_LSHIFT32(array6[j - 1], -num3);
					}
				}
			}
			Arrays.MemCopy(array, 0, array2, 0, 16);
			array5[0] = (array4[0] = num4 + Inlines.silk_SMMUL(42950, num4) + 1);
			int num7 = 1073741824;
			int num8 = 0;
			for (int j = 0; j < D; j++)
			{
				int num9;
				int num10;
				if (num3 > -2)
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						int b = -Inlines.silk_LSHIFT32(x[num5 + j], 16 - num3);
						int b2 = -Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], 16 - num3);
						num9 = Inlines.silk_LSHIFT32(x[num5 + j], 9);
						num10 = Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], 9);
						for (int l = 0; l < j; l++)
						{
							array[l] = Inlines.silk_SMLAWB(array[l], b, x[num5 + j - l - 1]);
							array2[l] = Inlines.silk_SMLAWB(array2[l], b2, x[num5 + subfr_length - j + l]);
							int b3 = array3[l];
							num9 = Inlines.silk_SMLAWB(num9, b3, x[num5 + j - l - 1]);
							num10 = Inlines.silk_SMLAWB(num10, b3, x[num5 + subfr_length - j + l]);
						}
						num9 = Inlines.silk_LSHIFT32(-num9, 7 - num3);
						num10 = Inlines.silk_LSHIFT32(-num10, 7 - num3);
						for (int l = 0; l <= j; l++)
						{
							array4[l] = Inlines.silk_SMLAWB(array4[l], num9, x[num5 + j - l]);
							array5[l] = Inlines.silk_SMLAWB(array5[l], num10, x[num5 + subfr_length - j + l - 1]);
						}
					}
				}
				else
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						int b = -Inlines.silk_LSHIFT32(x[num5 + j], -num3);
						int b2 = -Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], -num3);
						num9 = Inlines.silk_LSHIFT32(x[num5 + j], 17);
						num10 = Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], 17);
						for (int l = 0; l < j; l++)
						{
							array[l] = Inlines.silk_MLA(array[l], b, x[num5 + j - l - 1]);
							array2[l] = Inlines.silk_MLA(array2[l], b2, x[num5 + subfr_length - j + l]);
							int c = Inlines.silk_RSHIFT_ROUND(array3[l], 8);
							num9 = Inlines.silk_MLA(num9, x[num5 + j - l - 1], c);
							num10 = Inlines.silk_MLA(num10, x[num5 + subfr_length - j + l], c);
						}
						num9 = -num9;
						num10 = -num10;
						for (int l = 0; l <= j; l++)
						{
							array4[l] = Inlines.silk_SMLAWW(array4[l], num9, Inlines.silk_LSHIFT32(x[num5 + j - l], -num3 - 1));
							array5[l] = Inlines.silk_SMLAWW(array5[l], num10, Inlines.silk_LSHIFT32(x[num5 + subfr_length - j + l - 1], -num3 - 1));
						}
					}
				}
				num9 = array[j];
				num10 = array2[j];
				int a = 0;
				int num11 = Inlines.silk_ADD32(array5[0], array4[0]);
				for (int l = 0; l < j; l++)
				{
					int b3 = array3[l];
					num2 = Inlines.silk_CLZ32(Inlines.silk_abs(b3)) - 1;
					num2 = Inlines.silk_min(7, num2);
					int c = Inlines.silk_LSHIFT32(b3, num2);
					num9 = Inlines.silk_ADD_LSHIFT32(num9, Inlines.silk_SMMUL(array2[j - l - 1], c), 7 - num2);
					num10 = Inlines.silk_ADD_LSHIFT32(num10, Inlines.silk_SMMUL(array[j - l - 1], c), 7 - num2);
					a = Inlines.silk_ADD_LSHIFT32(a, Inlines.silk_SMMUL(array5[j - l], c), 7 - num2);
					num11 = Inlines.silk_ADD_LSHIFT32(num11, Inlines.silk_SMMUL(Inlines.silk_ADD32(array5[l + 1], array4[l + 1]), c), 7 - num2);
				}
				array4[j + 1] = num9;
				array5[j + 1] = num10;
				a = Inlines.silk_ADD32(a, num10);
				a = Inlines.silk_LSHIFT32(-a, 1);
				int num12 = ((Inlines.silk_abs(a) >= num11) ? ((a > 0) ? int.MaxValue : int.MinValue) : Inlines.silk_DIV32_varQ(a, num11, 31));
				num9 = 1073741824 - Inlines.silk_SMMUL(num12, num12);
				num9 = Inlines.silk_LSHIFT(Inlines.silk_SMMUL(num7, num9), 2);
				if (num9 <= minInvGain_Q30)
				{
					num10 = 1073741824 - Inlines.silk_DIV32_varQ(minInvGain_Q30, num7, 30);
					num12 = Inlines.silk_SQRT_APPROX(num10);
					num12 = Inlines.silk_RSHIFT32(num12 + Inlines.silk_DIV32(num10, num12), 1);
					num12 = Inlines.silk_LSHIFT32(num12, 16);
					if (a < 0)
					{
						num12 = -num12;
					}
					num7 = minInvGain_Q30;
					num8 = 1;
				}
				else
				{
					num7 = num9;
				}
				for (int l = 0; l < j + 1 >> 1; l++)
				{
					num9 = array3[l];
					num10 = array3[j - l - 1];
					array3[l] = Inlines.silk_ADD_LSHIFT32(num9, Inlines.silk_SMMUL(num10, num12), 1);
					array3[j - l - 1] = Inlines.silk_ADD_LSHIFT32(num10, Inlines.silk_SMMUL(num9, num12), 1);
				}
				array3[j] = Inlines.silk_RSHIFT32(num12, 6);
				if (num8 != 0)
				{
					for (int l = j + 1; l < D; l++)
					{
						array3[l] = 0;
					}
					break;
				}
				for (int l = 0; l <= j + 1; l++)
				{
					num9 = array4[l];
					num10 = array5[j - l + 1];
					array4[l] = Inlines.silk_ADD_LSHIFT32(num9, Inlines.silk_SMMUL(num10, num12), 1);
					array5[j - l + 1] = Inlines.silk_ADD_LSHIFT32(num10, Inlines.silk_SMMUL(num9, num12), 1);
				}
			}
			if (num8 != 0)
			{
				for (int l = 0; l < D; l++)
				{
					A_Q16[l] = -Inlines.silk_RSHIFT_ROUND(array3[l], 9);
				}
				if (num3 > 0)
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						num4 -= (int)Inlines.silk_RSHIFT64(Inlines.silk_inner_prod16_aligned_64(x, num5, x, num5, D), num3);
					}
				}
				else
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						num4 -= Inlines.silk_LSHIFT32(Inlines.silk_inner_prod_self(x, num5, D), -num3);
					}
				}
				res_nrg.Val = Inlines.silk_LSHIFT(Inlines.silk_SMMUL(num7, num4), 2);
				res_nrg_Q.Val = -num3;
			}
			else
			{
				int num11 = array4[0];
				int num9 = 65536;
				for (int l = 0; l < D; l++)
				{
					int c = Inlines.silk_RSHIFT_ROUND(array3[l], 9);
					num11 = Inlines.silk_SMLAWW(num11, array4[l + 1], c);
					num9 = Inlines.silk_SMLAWW(num9, c, c);
					A_Q16[l] = -c;
				}
				res_nrg.Val = Inlines.silk_SMLAWW(num11, Inlines.silk_SMMUL(42950, num4), -num9);
				res_nrg_Q.Val = -num3;
			}
		}
	}
	internal static class BWExpander
	{
		internal static void silk_bwexpander_32(int[] ar, int d, int chirp_Q16)
		{
			int b = chirp_Q16 - 65536;
			for (int i = 0; i < d - 1; i++)
			{
				ar[i] = Inlines.silk_SMULWW(chirp_Q16, ar[i]);
				chirp_Q16 += Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, b), 16);
			}
			ar[d - 1] = Inlines.silk_SMULWW(chirp_Q16, ar[d - 1]);
		}

		internal static void silk_bwexpander(short[] ar, int d, int chirp_Q16)
		{
			int b = chirp_Q16 - 65536;
			for (int i = 0; i < d - 1; i++)
			{
				ar[i] = (short)Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, ar[i]), 16);
				chirp_Q16 += Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, b), 16);
			}
			ar[d - 1] = (short)Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, ar[d - 1]), 16);
		}
	}
	internal static class CNG
	{
		internal static void silk_CNG_exc(Span<int> exc_Q10, int exc_Q10_ptr, int[] exc_buf_Q14, int Gain_Q16, int length, ref int rand_seed)
		{
			int num;
			for (num = 255; num > length; num = Inlines.silk_RSHIFT(num, 1))
			{
			}
			int num2 = rand_seed;
			for (int i = exc_Q10_ptr; i < exc_Q10_ptr + length; i++)
			{
				num2 = Inlines.silk_RAND(num2);
				int num3 = Inlines.silk_RSHIFT(num2, 24) & num;
				exc_Q10[i] = (short)Inlines.silk_SAT16(Inlines.silk_SMULWW(exc_buf_Q14[num3], Gain_Q16 >> 4));
			}
			rand_seed = num2;
		}

		internal static void silk_CNG_Reset(SilkChannelDecoder psDec)
		{
			int num = Inlines.silk_DIV32_16(32767, (short)(psDec.LPC_order + 1));
			int num2 = 0;
			for (int i = 0; i < psDec.LPC_order; i++)
			{
				num2 += num;
				psDec.sCNG.CNG_smth_NLSF_Q15[i] = (short)num2;
			}
			psDec.sCNG.CNG_smth_Gain_Q16 = 0;
			psDec.sCNG.rand_seed = 3176576;
		}

		internal static void silk_CNG(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, Span<short> frame, int frame_ptr, int length)
		{
			short[] array = new short[psDec.LPC_order];
			CNGState sCNG = psDec.sCNG;
			if (psDec.fs_kHz != sCNG.fs_kHz)
			{
				silk_CNG_Reset(psDec);
				sCNG.fs_kHz = psDec.fs_kHz;
			}
			if (psDec.lossCnt == 0 && psDec.prevSignalType == 0)
			{
				for (int i = 0; i < psDec.LPC_order; i++)
				{
					sCNG.CNG_smth_NLSF_Q15[i] += (short)Inlines.silk_SMULWB(psDec.prevNLSF_Q15[i] - sCNG.CNG_smth_NLSF_Q15[i], 16348);
				}
				int num = 0;
				int num2 = 0;
				for (int i = 0; i < psDec.nb_subfr; i++)
				{
					if (psDecCtrl.Gains_Q16[i] > num)
					{
						num = psDecCtrl.Gains_Q16[i];
						num2 = i;
					}
				}
				Arrays.MemMoveInt(sCNG.CNG_exc_buf_Q14, 0, psDec.subfr_length, (psDec.nb_subfr - 1) * psDec.subfr_length);
				for (int i = 0; i < psDec.nb_subfr; i++)
				{
					sCNG.CNG_smth_Gain_Q16 += Inlines.silk_SMULWB(psDecCtrl.Gains_Q16[i] - sCNG.CNG_smth_Gain_Q16, 4634);
				}
			}
			if (psDec.lossCnt != 0)
			{
				int[] array2 = new int[length + 16];
				int num3 = Inlines.silk_SMULWW(psDec.sPLC.randScale_Q14, psDec.sPLC.prevGain_Q16[1]);
				if (num3 >= 2097152 || sCNG.CNG_smth_Gain_Q16 > 8388608)
				{
					num3 = Inlines.silk_SMULTT(num3, num3);
					num3 = Inlines.silk_SUB_LSHIFT32(Inlines.silk_SMULTT(sCNG.CNG_smth_Gain_Q16, sCNG.CNG_smth_Gain_Q16), num3, 5);
					num3 = Inlines.silk_LSHIFT32(Inlines.silk_SQRT_APPROX(num3), 16);
				}
				else
				{
					num3 = Inlines.silk_SMULWW(num3, num3);
					num3 = Inlines.silk_SUB_LSHIFT32(Inlines.silk_SMULWW(sCNG.CNG_smth_Gain_Q16, sCNG.CNG_smth_Gain_Q16), num3, 5);
					num3 = Inlines.silk_LSHIFT32(Inlines.silk_SQRT_APPROX(num3), 8);
				}
				silk_CNG_exc(array2, 16, sCNG.CNG_exc_buf_Q14, num3, length, ref sCNG.rand_seed);
				NLSF.silk_NLSF2A(array, sCNG.CNG_smth_NLSF_Q15, psDec.LPC_order);
				Arrays.MemCopy(sCNG.CNG_synth_state, 0, array2, 0, 16);
				for (int i = 0; i < length; i++)
				{
					int num4 = 16 + i;
					int a = Inlines.silk_RSHIFT(psDec.LPC_order, 1);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 1], array[0]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 2], array[1]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 3], array[2]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 4], array[3]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 5], array[4]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 6], array[5]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 7], array[6]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 8], array[7]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 9], array[8]);
					a = Inlines.silk_SMLAWB(a, array2[num4 - 10], array[9]);
					if (psDec.LPC_order == 16)
					{
						a = Inlines.silk_SMLAWB(a, array2[num4 - 11], array[10]);
						a = Inlines.silk_SMLAWB(a, array2[num4 - 12], array[11]);
						a = Inlines.silk_SMLAWB(a, array2[num4 - 13], array[12]);
						a = Inlines.silk_SMLAWB(a, array2[num4 - 14], array[13]);
						a = Inlines.silk_SMLAWB(a, array2[num4 - 15], array[14]);
						a = Inlines.silk_SMLAWB(a, array2[num4 - 16], array[15]);
					}
					array2[num4] = Inlines.silk_ADD_LSHIFT(array2[num4], a, 4);
					frame[frame_ptr + i] = Inlines.silk_ADD_SAT16(frame[frame_ptr + i], (short)Inlines.silk_RSHIFT_ROUND(array2[num4], 10));
				}
				Arrays.MemCopy(array2, length, sCNG.CNG_synth_state, 0, 16);
			}
			else
			{
				Arrays.MemSetInt(sCNG.CNG_synth_state, 0, psDec.LPC_order);
			}
		}
	}
	internal static class CodeSigns
	{
		private static int silk_enc_map(int a)
		{
			return Inlines.silk_RSHIFT(a, 15) + 1;
		}

		private static int silk_dec_map(int a)
		{
			return Inlines.silk_LSHIFT(a, 1) - 1;
		}

		internal static void silk_encode_signs(EntropyCoder psRangeEnc, Span<byte> encodedData, Span<sbyte> pulses, int length, int signalType, int quantOffsetType, int[] sum_pulses)
		{
			byte[] array = new byte[2];
			byte[] silk_sign_iCDF = Tables.silk_sign_iCDF;
			array[1] = 0;
			int num = 0;
			int num2 = Inlines.silk_SMULBB(7, Inlines.silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
			int num3 = num2;
			length = Inlines.silk_RSHIFT(length + 8, 4);
			for (num2 = 0; num2 < length; num2++)
			{
				int num4 = sum_pulses[num2];
				if (num4 > 0)
				{
					array[0] = silk_sign_iCDF[num3 + Inlines.silk_min(num4 & 0x1F, 6)];
					for (int i = num; i < num + 16; i++)
					{
						if (pulses[i] != 0)
						{
							psRangeEnc.enc_icdf(encodedData, silk_enc_map(pulses[i]), array, 8u);
						}
					}
				}
				num += 16;
			}
		}

		internal static void silk_decode_signs(EntropyCoder psRangeDec, ReadOnlySpan<byte> encodedData, short[] pulses, int length, int signalType, int quantOffsetType, int[] sum_pulses)
		{
			byte[] array = new byte[2];
			byte[] silk_sign_iCDF = Tables.silk_sign_iCDF;
			array[1] = 0;
			int num = 0;
			int num2 = Inlines.silk_SMULBB(7, Inlines.silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
			int num3 = num2;
			length = Inlines.silk_RSHIFT(length + 8, 4);
			for (num2 = 0; num2 < length; num2++)
			{
				int num4 = sum_pulses[num2];
				if (num4 > 0)
				{
					array[0] = silk_sign_iCDF[num3 + Inlines.silk_min(num4 & 0x1F, 6)];
					for (int i = 0; i < 16; i++)
					{
						if (pulses[num + i] > 0)
						{
							pulses[num + i] *= (short)silk_dec_map(psRangeDec.dec_icdf(encodedData, array, 8u));
						}
					}
				}
				num += 16;
			}
		}
	}
	internal static class CorrelateMatrix
	{
		internal static void silk_corrVector(short[] x, int x_ptr, short[] t, int t_ptr, int L, int order, int[] Xt, int rshifts)
		{
			int num = x_ptr + order - 1;
			if (rshifts > 0)
			{
				for (int i = 0; i < order; i++)
				{
					int num2 = 0;
					for (int j = 0; j < L; j++)
					{
						num2 += Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num + j], t[t_ptr + j]), rshifts);
					}
					Xt[i] = num2;
					num--;
				}
			}
			else
			{
				for (int i = 0; i < order; i++)
				{
					Xt[i] = Inlines.silk_inner_prod(x, num, t, t_ptr, L);
					num--;
				}
			}
		}

		internal static void silk_corrMatrix(short[] x, int x_ptr, int L, int order, int head_room, int[] XX, int XX_ptr, BoxedValueInt rshifts)
		{
			SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, x, x_ptr, L + order - 1);
			int num = Inlines.silk_max(head_room - Inlines.silk_CLZ32(energy), 0);
			energy = Inlines.silk_RSHIFT32(energy, num);
			shift += num;
			for (int i = x_ptr; i < x_ptr + order - 1; i++)
			{
				energy -= Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[i], x[i]), shift);
			}
			if (shift < rshifts.Val)
			{
				energy = Inlines.silk_RSHIFT32(energy, rshifts.Val - shift);
				shift = rshifts.Val;
			}
			Inlines.MatrixSet(XX, XX_ptr, 0, 0, order, energy);
			int num2 = x_ptr + order - 1;
			for (int j = 1; j < order; j++)
			{
				energy = Inlines.silk_SUB32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 + L - j], x[num2 + L - j]), shift));
				energy = Inlines.silk_ADD32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 - j], x[num2 - j]), shift));
				Inlines.MatrixSet(XX, XX_ptr, j, j, order, energy);
			}
			int num3 = x_ptr + order - 2;
			if (shift > 0)
			{
				for (int k = 1; k < order; k++)
				{
					energy = 0;
					for (int i = 0; i < L; i++)
					{
						energy += Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 + i], x[num3 + i]), shift);
					}
					Inlines.MatrixSet(XX, XX_ptr, k, 0, order, energy);
					Inlines.MatrixSet(XX, XX_ptr, 0, k, order, energy);
					for (int j = 1; j < order - k; j++)
					{
						energy = Inlines.silk_SUB32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 + L - j], x[num3 + L - j]), shift));
						energy = Inlines.silk_ADD32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 - j], x[num3 - j]), shift));
						Inlines.MatrixSet(XX, XX_ptr, k + j, j, order, energy);
						Inlines.MatrixSet(XX, XX_ptr, j, k + j, order, energy);
					}
					num3--;
				}
			}
			else
			{
				for (int k = 1; k < order; k++)
				{
					energy = Inlines.silk_inner_prod(x, num2, x, num3, L);
					Inlines.MatrixSet(XX, XX_ptr, k, 0, order, energy);
					Inlines.MatrixSet(XX, XX_ptr, 0, k, order, energy);
					for (int j = 1; j < order - k; j++)
					{
						energy = Inlines.silk_SUB32(energy, Inlines.silk_SMULBB(x[num2 + L - j], x[num3 + L - j]));
						energy = Inlines.silk_SMLABB(energy, x[num2 - j], x[num3 - j]);
						Inlines.MatrixSet(XX, XX_ptr, k + j, j, order, energy);
						Inlines.MatrixSet(XX, XX_ptr, j, k + j, order, energy);
					}
					num3--;
				}
			}
			rshifts.Val = shift;
		}
	}
	internal static class DecodeAPI
	{
		internal static int silk_InitDecoder(SilkDecoder decState)
		{
			decState.Reset();
			int result = SilkError.SILK_NO_ERROR;
			SilkChannelDecoder[] channel_state = decState.channel_state;
			for (int i = 0; i < 2; i++)
			{
				result = channel_state[i].silk_init_decoder();
			}
			decState.sStereo.Reset();
			decState.prev_decode_only_middle = 0;
			return result;
		}

		internal static int silk_Decode(SilkDecoder psDec, DecControlState decControl, ReadOnlySpan<byte> frameData, int lostFlag, int newPacketFlag, EntropyCoder psRangeDec, Span<short> samplesOut, int samplesOut_ptr, out int nSamplesOut)
		{
			int num = 0;
			int num2 = SilkError.SILK_NO_ERROR;
			BoxedValueInt boxedValueInt = new BoxedValueInt();
			int[] array = new int[2];
			int[] array2 = new int[2];
			SilkChannelDecoder[] channel_state = psDec.channel_state;
			nSamplesOut = 0;
			if (newPacketFlag != 0)
			{
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					channel_state[i].nFramesDecoded = 0;
				}
			}
			if (decControl.nChannelsInternal > psDec.nChannelsInternal)
			{
				num2 += channel_state[1].silk_init_decoder();
			}
			int num3 = ((decControl.nChannelsInternal == 1 && psDec.nChannelsInternal == 2 && decControl.internalSampleRate == 1000 * channel_state[0].fs_kHz) ? 1 : 0);
			if (channel_state[0].nFramesDecoded == 0)
			{
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					if (decControl.payloadSize_ms == 0)
					{
						channel_state[i].nFramesPerPacket = 1;
						channel_state[i].nb_subfr = 2;
					}
					else if (decControl.payloadSize_ms == 10)
					{
						channel_state[i].nFramesPerPacket = 1;
						channel_state[i].nb_subfr = 2;
					}
					else if (decControl.payloadSize_ms == 20)
					{
						channel_state[i].nFramesPerPacket = 1;
						channel_state[i].nb_subfr = 4;
					}
					else if (decControl.payloadSize_ms == 40)
					{
						channel_state[i].nFramesPerPacket = 2;
						channel_state[i].nb_subfr = 4;
					}
					else
					{
						if (decControl.payloadSize_ms != 60)
						{
							return SilkError.SILK_DEC_INVALID_FRAME_SIZE;
						}
						channel_state[i].nFramesPerPacket = 3;
						channel_state[i].nb_subfr = 4;
					}
					int num4 = (decControl.internalSampleRate >> 10) + 1;
					if (num4 != 8 && num4 != 12 && num4 != 16)
					{
						return SilkError.SILK_DEC_INVALID_SAMPLING_FREQUENCY;
					}
					num2 += channel_state[i].silk_decoder_set_fs(num4, decControl.API_sampleRate);
				}
			}
			if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 2 && (psDec.nChannelsAPI == 1 || psDec.nChannelsInternal == 1))
			{
				Arrays.MemSetShort(psDec.sStereo.pred_prev_Q13, 0, 2);
				Arrays.MemSetShort(psDec.sStereo.sSide, 0, 2);
				channel_state[1].resampler_state.Assign(channel_state[0].resampler_state);
			}
			psDec.nChannelsAPI = decControl.nChannelsAPI;
			psDec.nChannelsInternal = decControl.nChannelsInternal;
			if (decControl.API_sampleRate > 48000 || decControl.API_sampleRate < 8000)
			{
				return SilkError.SILK_DEC_INVALID_SAMPLING_FREQUENCY;
			}
			if (lostFlag != 1 && channel_state[0].nFramesDecoded == 0)
			{
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					for (int j = 0; j < channel_state[i].nFramesPerPacket; j++)
					{
						channel_state[i].VAD_flags[j] = psRangeDec.dec_bit_logp(frameData, 1u);
					}
					channel_state[i].LBRR_flag = psRangeDec.dec_bit_logp(frameData, 1u);
				}
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					Arrays.MemSetInt(channel_state[i].LBRR_flags, 0, 3);
					if (channel_state[i].LBRR_flag == 0)
					{
						continue;
					}
					if (channel_state[i].nFramesPerPacket == 1)
					{
						channel_state[i].LBRR_flags[0] = 1;
						continue;
					}
					int a = psRangeDec.dec_icdf(frameData, Tables.silk_LBRR_flags_iCDF_ptr[channel_state[i].nFramesPerPacket - 2], 8u) + 1;
					for (int j = 0; j < channel_state[i].nFramesPerPacket; j++)
					{
						channel_state[i].LBRR_flags[j] = Inlines.silk_RSHIFT(a, j) & 1;
					}
				}
				if (lostFlag == 0)
				{
					for (int j = 0; j < channel_state[0].nFramesPerPacket; j++)
					{
						for (int i = 0; i < decControl.nChannelsInternal; i++)
						{
							if (channel_state[i].LBRR_flags[j] == 0)
							{
								continue;
							}
							short[] pulses = new short[320];
							if (decControl.nChannelsInternal == 2 && i == 0)
							{
								Stereo.silk_stereo_decode_pred(psRangeDec, frameData, array2);
								if (channel_state[1].LBRR_flags[j] == 0)
								{
									BoxedValueInt boxedValueInt2 = new BoxedValueInt(num);
									Stereo.silk_stereo_decode_mid_only(psRangeDec, frameData, boxedValueInt2);
									num = boxedValueInt2.Val;
								}
							}
							DecodeIndices.silk_decode_indices(condCoding: (j > 0 && channel_state[i].LBRR_flags[j - 1] != 0) ? 2 : 0, psDec: channel_state[i], psRangeDec: psRangeDec, frameData: frameData, FrameIndex: j, decode_LBRR: 1);
							DecodePulses.silk_decode_pulses(psRangeDec, frameData, pulses, channel_state[i].indices.signalType, channel_state[i].indices.quantOffsetType, channel_state[i].frame_length);
						}
					}
				}
			}
			if (decControl.nChannelsInternal == 2)
			{
				if (lostFlag == 0 || (lostFlag == 2 && channel_state[0].LBRR_flags[channel_state[0].nFramesDecoded] == 1))
				{
					Stereo.silk_stereo_decode_pred(psRangeDec, frameData, array2);
					if ((lostFlag == 0 && channel_state[1].VAD_flags[channel_state[0].nFramesDecoded] == 0) || (lostFlag == 2 && channel_state[1].LBRR_flags[channel_state[0].nFramesDecoded] == 0))
					{
						BoxedValueInt boxedValueInt3 = new BoxedValueInt(num);
						Stereo.silk_stereo_decode_mid_only(psRangeDec, frameData, boxedValueInt3);
						num = boxedValueInt3.Val;
					}
					else
					{
						num = 0;
					}
				}
				else
				{
					for (int i = 0; i < 2; i++)
					{
						array2[i] = psDec.sStereo.pred_prev_Q13[i];
					}
				}
			}
			if (decControl.nChannelsInternal == 2 && num == 0 && psDec.prev_decode_only_middle == 1)
			{
				Arrays.MemSetShort(psDec.channel_state[1].outBuf, 0, 480);
				Arrays.MemSetInt(psDec.channel_state[1].sLPC_Q14_buf, 0, 16);
				psDec.channel_state[1].lagPrev = 100;
				psDec.channel_state[1].LastGainIndex = 10;
				psDec.channel_state[1].prevSignalType = 0;
				psDec.channel_state[1].first_frame_after_reset = 1;
			}
			int num5 = ((decControl.internalSampleRate * decControl.nChannelsInternal < decControl.API_sampleRate * decControl.nChannelsAPI) ? 1 : 0);
			Span<short> span;
			if (num5 != 0)
			{
				span = samplesOut;
				array[0] = samplesOut_ptr;
				array[1] = samplesOut_ptr + channel_state[0].frame_length + 2;
			}
			else
			{
				short[] array3 = new short[decControl.nChannelsInternal * (channel_state[0].frame_length + 2)];
				span = array3;
				array[0] = 0;
				array[1] = channel_state[0].frame_length + 2;
			}
			int num6 = ((lostFlag != 0) ? ((psDec.prev_decode_only_middle == 0 || (decControl.nChannelsInternal == 2 && lostFlag == 2 && channel_state[1].LBRR_flags[channel_state[1].nFramesDecoded] == 1)) ? 1 : 0) : ((num == 0) ? 1 : 0));
			for (int i = 0; i < decControl.nChannelsInternal; i++)
			{
				if (i == 0 || num6 != 0)
				{
					int num7 = channel_state[0].nFramesDecoded - i;
					int condCoding = ((num7 > 0) ? ((lostFlag == 2) ? ((channel_state[i].LBRR_flags[num7 - 1] != 0) ? 2 : 0) : ((i > 0 && psDec.prev_decode_only_middle != 0) ? 1 : 2)) : 0);
					num2 += channel_state[i].silk_decode_frame(psRangeDec, frameData, span, array[i] + 2, boxedValueInt, lostFlag, condCoding);
				}
				else
				{
					Arrays.MemSetWithOffset<short>(span, 0, array[i] + 2, boxedValueInt.Val);
				}
				channel_state[i].nFramesDecoded++;
			}
			if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 2)
			{
				Stereo.silk_stereo_MS_to_LR(psDec.sStereo, span, array[0], span, array[1], array2, channel_state[0].fs_kHz, boxedValueInt.Val);
			}
			else
			{
				psDec.sStereo.sMid.AsSpan(0, 2).CopyTo(span.Slice(array[0]));
				span.Slice(array[0] + boxedValueInt.Val, 2).CopyTo(psDec.sStereo.sMid);
			}
			nSamplesOut = Inlines.silk_DIV32(boxedValueInt.Val * decControl.API_sampleRate, Inlines.silk_SMULBB(channel_state[0].fs_kHz, 1000));
			Span<short> output;
			int num8;
			if (decControl.nChannelsAPI == 2)
			{
				short[] array4 = new short[nSamplesOut];
				output = array4;
				num8 = 0;
			}
			else
			{
				output = samplesOut;
				num8 = samplesOut_ptr;
			}
			if (num5 != 0)
			{
				short[] array5 = new short[decControl.nChannelsInternal * (channel_state[0].frame_length + 2)];
				samplesOut.Slice(samplesOut_ptr, decControl.nChannelsInternal * (channel_state[0].frame_length + 2)).CopyTo(array5);
				span = array5;
				array[0] = 0;
				array[1] = channel_state[0].frame_length + 2;
			}
			for (int i = 0; i < Inlines.silk_min(decControl.nChannelsAPI, decControl.nChannelsInternal); i++)
			{
				num2 += Resampler.silk_resampler(channel_state[i].resampler_state, output, num8, span, array[i] + 1, boxedValueInt.Val);
				if (decControl.nChannelsAPI == 2)
				{
					int num9 = samplesOut_ptr + i;
					for (int j = 0; j < nSamplesOut; j++)
					{
						samplesOut[num9 + 2 * j] = output[num8 + j];
					}
				}
			}
			if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 1)
			{
				if (num3 != 0)
				{
					num2 += Resampler.silk_resampler(channel_state[1].resampler_state, output, num8, span, array[0] + 1, boxedValueInt.Val);
					for (int j = 0; j < nSamplesOut; j++)
					{
						samplesOut[samplesOut_ptr + 1 + 2 * j] = output[num8 + j];
					}
				}
				else
				{
					for (int j = 0; j < nSamplesOut; j++)
					{
						samplesOut[samplesOut_ptr + 1 + 2 * j] = samplesOut[samplesOut_ptr + 2 * j];
					}
				}
			}
			if (channel_state[0].prevSignalType == 2)
			{
				int[] array6 = new int[3] { 6, 4, 3 };
				decControl.prevPitchLag = channel_state[0].lagPrev * array6[channel_state[0].fs_kHz - 8 >> 2];
			}
			else
			{
				decControl.prevPitchLag = 0;
			}
			if (lostFlag == 1)
			{
				for (int j = 0; j < psDec.nChannelsInternal; j++)
				{
					psDec.channel_state[j].LastGainIndex = 10;
				}
			}
			else
			{
				psDec.prev_decode_only_middle = num;
			}
			return num2;
		}
	}
	internal static class DecodeCore
	{
		internal static void silk_decode_core(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, Span<short> xq, int xq_ptr, short[] pulses)
		{
			int num = 0;
			short[] lTPCoef_Q = psDecCtrl.LTPCoef_Q14;
			short[] array = new short[psDec.ltp_mem_length];
			int[] array2 = new int[psDec.ltp_mem_length + psDec.frame_length];
			int[] array3 = new int[psDec.subfr_length];
			int[] array4 = new int[psDec.subfr_length + 16];
			int num2 = Tables.silk_Quantization_Offsets_Q10[psDec.indices.signalType >> 1][psDec.indices.quantOffsetType];
			int num3 = ((psDec.indices.NLSFInterpCoef_Q2 < 4) ? 1 : 0);
			int seed = psDec.indices.Seed;
			for (int i = 0; i < psDec.frame_length; i++)
			{
				seed = Inlines.silk_RAND(seed);
				psDec.exc_Q14[i] = Inlines.silk_LSHIFT(pulses[i], 14);
				if (psDec.exc_Q14[i] > 0)
				{
					psDec.exc_Q14[i] -= 1280;
				}
				else if (psDec.exc_Q14[i] < 0)
				{
					psDec.exc_Q14[i] += 1280;
				}
				psDec.exc_Q14[i] += num2 << 4;
				if (seed < 0)
				{
					psDec.exc_Q14[i] = -psDec.exc_Q14[i];
				}
				seed = Inlines.silk_ADD32_ovflw(seed, pulses[i]);
			}
			Arrays.MemCopy(psDec.sLPC_Q14_buf, 0, array4, 0, 16);
			int num4 = 0;
			int num5 = xq_ptr;
			int num6 = psDec.ltp_mem_length;
			for (int j = 0; j < psDec.nb_subfr; j++)
			{
				int[] array5 = array3;
				int num7 = 0;
				short[] array6 = psDecCtrl.PredCoef_Q12[j >> 1];
				int num8 = j * 5;
				int num9 = psDec.indices.signalType;
				int b = Inlines.silk_RSHIFT(psDecCtrl.Gains_Q16[j], 6);
				int a = Inlines.silk_INVERSE32_varQ(psDecCtrl.Gains_Q16[j], 47);
				int num10;
				if (psDecCtrl.Gains_Q16[j] != psDec.prev_gain_Q16)
				{
					num10 = Inlines.silk_DIV32_varQ(psDec.prev_gain_Q16, psDecCtrl.Gains_Q16[j], 16);
					for (int i = 0; i < 16; i++)
					{
						array4[i] = Inlines.silk_SMULWW(num10, array4[i]);
					}
				}
				else
				{
					num10 = 65536;
				}
				psDec.prev_gain_Q16 = psDecCtrl.Gains_Q16[j];
				if (psDec.lossCnt != 0 && psDec.prevSignalType == 2 && psDec.indices.signalType != 2 && j < 2)
				{
					Arrays.MemSetWithOffset(lTPCoef_Q, (short)0, num8, 5);
					lTPCoef_Q[num8 + 2] = 4096;
					num9 = 2;
					psDecCtrl.pitchL[j] = psDec.lagPrev;
				}
				if (num9 == 2)
				{
					num = psDecCtrl.pitchL[j];
					if (j == 0 || (j == 2 && num3 != 0))
					{
						int num11 = psDec.ltp_mem_length - num - psDec.LPC_order - 2;
						if (j == 2)
						{
							xq.Slice(xq_ptr, 2 * psDec.subfr_length).CopyTo(psDec.outBuf.AsSpan(psDec.ltp_mem_length));
						}
						Filters.silk_LPC_analysis_filter(array, num11, psDec.outBuf, num11 + j * psDec.subfr_length, array6, 0, psDec.ltp_mem_length - num11, psDec.LPC_order);
						if (j == 0)
						{
							a = Inlines.silk_LSHIFT(Inlines.silk_SMULWB(a, psDecCtrl.LTP_scale_Q14), 2);
						}
						for (int i = 0; i < num + 2; i++)
						{
							array2[num6 - i - 1] = Inlines.silk_SMULWB(a, array[psDec.ltp_mem_length - i - 1]);
						}
					}
					else if (num10 != 65536)
					{
						for (int i = 0; i < num + 2; i++)
						{
							array2[num6 - i - 1] = Inlines.silk_SMULWW(num10, array2[num6 - i - 1]);
						}
					}
				}
				if (num9 == 2)
				{
					int num12 = num6 - num + 2;
					for (int i = 0; i < psDec.subfr_length; i++)
					{
						int a2 = 2;
						a2 = Inlines.silk_SMLAWB(a2, array2[num12], lTPCoef_Q[num8]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 1], lTPCoef_Q[num8 + 1]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 2], lTPCoef_Q[num8 + 2]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 3], lTPCoef_Q[num8 + 3]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 4], lTPCoef_Q[num8 + 4]);
						num12++;
						array5[num7 + i] = Inlines.silk_ADD_LSHIFT32(psDec.exc_Q14[num4 + i], a2, 1);
						array2[num6] = Inlines.silk_LSHIFT(array5[num7 + i], 1);
						num6++;
					}
				}
				else
				{
					array5 = psDec.exc_Q14;
					num7 = num4;
				}
				for (int i = 0; i < psDec.subfr_length; i++)
				{
					int a3 = Inlines.silk_RSHIFT(psDec.LPC_order, 1);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 1], array6[0]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 2], array6[1]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 3], array6[2]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 4], array6[3]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 5], array6[4]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 6], array6[5]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 7], array6[6]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 8], array6[7]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 9], array6[8]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 10], array6[9]);
					if (psDec.LPC_order == 16)
					{
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 11], array6[10]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 12], array6[11]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 13], array6[12]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 14], array6[13]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 15], array6[14]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 16], array6[15]);
					}
					array4[16 + i] = Inlines.silk_ADD_LSHIFT32(array5[num7 + i], a3, 4);
					xq[num5 + i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(array4[16 + i], b), 8));
				}
				Arrays.MemCopy(array4, psDec.subfr_length, array4, 0, 16);
				num4 += psDec.subfr_length;
				num5 += psDec.subfr_length;
			}
			Arrays.MemCopy(array4, 0, psDec.sLPC_Q14_buf, 0, 16);
		}
	}
	internal static class DecodeIndices
	{
		internal static void silk_decode_indices(SilkChannelDecoder psDec, EntropyCoder psRangeDec, ReadOnlySpan<byte> frameData, int FrameIndex, int decode_LBRR, int condCoding)
		{
			short[] array = new short[psDec.LPC_order];
			byte[] array2 = new byte[psDec.LPC_order];
			int num = ((decode_LBRR == 0 && psDec.VAD_flags[FrameIndex] == 0) ? psRangeDec.dec_icdf(frameData, Tables.silk_type_offset_no_VAD_iCDF, 8u) : (psRangeDec.dec_icdf(frameData, Tables.silk_type_offset_VAD_iCDF, 8u) + 2));
			psDec.indices.signalType = (sbyte)Inlines.silk_RSHIFT(num, 1);
			psDec.indices.quantOffsetType = (sbyte)(num & 1);
			if (condCoding == 2)
			{
				psDec.indices.GainsIndices[0] = (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_delta_gain_iCDF, 8u);
			}
			else
			{
				psDec.indices.GainsIndices[0] = (sbyte)Inlines.silk_LSHIFT(psRangeDec.dec_icdf(frameData, Tables.silk_gain_iCDF[psDec.indices.signalType], 8u), 3);
				psDec.indices.GainsIndices[0] += (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_uniform8_iCDF, 8u);
			}
			for (int i = 1; i < psDec.nb_subfr; i++)
			{
				psDec.indices.GainsIndices[i] = (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_delta_gain_iCDF, 8u);
			}
			psDec.indices.NLSFIndices[0] = (sbyte)psRangeDec.dec_icdf(frameData, psDec.psNLSF_CB.CB1_iCDF, (psDec.indices.signalType >> 1) * psDec.psNLSF_CB.nVectors, 8u);
			NLSF.silk_NLSF_unpack(array, array2, psDec.psNLSF_CB, psDec.indices.NLSFIndices[0]);
			for (int i = 0; i < psDec.psNLSF_CB.order; i++)
			{
				num = psRangeDec.dec_icdf(frameData, psDec.psNLSF_CB.ec_iCDF, array[i], 8u);
				switch (num)
				{
				case 0:
					num -= psRangeDec.dec_icdf(frameData, Tables.silk_NLSF_EXT_iCDF, 8u);
					break;
				case 8:
					num += psRangeDec.dec_icdf(frameData, Tables.silk_NLSF_EXT_iCDF, 8u);
					break;
				}
				psDec.indices.NLSFIndices[i + 1] = (sbyte)(num - 4);
			}
			if (psDec.nb_subfr == 4)
			{
				psDec.indices.NLSFInterpCoef_Q2 = (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_NLSF_interpolation_factor_iCDF, 8u);
			}
			else
			{
				psDec.indices.NLSFInterpCoef_Q2 = 4