using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Concentus.Celt; using Concentus.Celt.Structs; using Concentus.Common; using Concentus.Common.CPlusPlus; using Concentus.Enums; using Concentus.Silk; using Concentus.Silk.Enums; using Concentus.Silk.Structs; using Concentus.Structs; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace ValheimVoip { internal sealed class VoiceCapture : MonoBehaviour { private const int MicrophoneBufferSeconds = 1; private VoiceNetwork _network; private AudioClip _microphoneClip; private string _device; private int _lastPosition; private float[] _frameBuffer; private float[] _scratch; private readonly OpusVoiceCodec _codec = new OpusVoiceCodec(); public void Initialize(VoiceNetwork network) { _network = network; } private void Update() { if (!VoiceRuntimeSettings.Enabled || (Object)(object)ZNet.instance == (Object)null || !IsInWorld()) { StopMicrophone(); } else if (ShouldTransmit()) { EnsureMicrophone(); CaptureAvailableFrames(); } } private static bool IsInWorld() { return (Object)(object)Player.m_localPlayer != (Object)null && ZRoutedRpc.instance != null; } private static bool ShouldTransmit() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) return VoiceSettings.VoiceActivation.Value || Input.GetKey(VoiceSettings.PushToTalkKeyCode); } private void EnsureMicrophone() { if ((!((Object)(object)_microphoneClip != (Object)null) || !Microphone.IsRecording(_device)) && Microphone.devices.Length != 0) { _device = Microphone.devices[0]; int sampleRate = VoiceRuntimeSettings.SampleRate; _microphoneClip = Microphone.Start(_device, true, 1, sampleRate); _lastPosition = 0; int num = sampleRate * VoiceRuntimeSettings.FrameMilliseconds / 1000; _frameBuffer = new float[num]; _scratch = new float[_microphoneClip.samples]; } } private void StopMicrophone() { if (!((Object)(object)_microphoneClip == (Object)null)) { if (Microphone.IsRecording(_device)) { Microphone.End(_device); } _microphoneClip = null; _lastPosition = 0; } } private void CaptureAvailableFrames() { if ((Object)(object)_microphoneClip == (Object)null) { return; } int position = Microphone.GetPosition(_device); if (position >= 0 && position != _lastPosition) { int num = ((position > _lastPosition) ? (position - _lastPosition) : (_microphoneClip.samples - _lastPosition + position)); while (num >= _frameBuffer.Length) { ReadFrame(_lastPosition, _frameBuffer); _lastPosition = (_lastPosition + _frameBuffer.Length) % _microphoneClip.samples; num -= _frameBuffer.Length; TrySendFrame(_frameBuffer); } } } private void ReadFrame(int startPosition, float[] destination) { if (startPosition + destination.Length <= _microphoneClip.samples) { _microphoneClip.GetData(destination, startPosition); return; } _microphoneClip.GetData(_scratch, 0); for (int i = 0; i < destination.Length; i++) { destination[i] = _scratch[(startPosition + i) % _microphoneClip.samples]; } } private void TrySendFrame(float[] frame) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!VoiceSettings.VoiceActivation.Value || !(AudioMath.Rms(frame, frame.Length) < VoiceSettings.VoiceActivationThreshold.Value)) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { VoicePacket voicePacket = new VoicePacket(); voicePacket.SpeakerId = localPlayer.GetPlayerID(); voicePacket.SpeakerPosition = ((Component)localPlayer).transform.position; voicePacket.SampleRate = VoiceRuntimeSettings.SampleRate; voicePacket.Samples = frame.Length; voicePacket.OpusPayload = _codec.Encode(frame, frame.Length, VoiceRuntimeSettings.SampleRate); VoicePacket packet = voicePacket; _network.Send(packet); } } } } internal sealed class VoiceClient { public void Send(VoicePacket packet) { if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { return; } if (ZNet.instance.IsServer()) { VoiceServer instance = VoiceServer.Instance; if ((Object)(object)instance != (Object)null) { instance.Relay(ZNet.GetUID(), packet); } return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null) { ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "ValheimVoip_VoiceFrame", new object[1] { packet.ToPackage() }); } } public void ApplyServerSettings(long senderPeerId, ZPackage package) { if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer == null || serverPeer.m_uid != senderPeerId) { VoiceLog.WarningRateLimited("voice-settings-unauthorized", "Ignored voice settings package from non-server peer " + senderPeerId + ".", 30f); return; } try { if (VoiceRuntimeSettings.ApplyServerPackage(package, out var summary)) { ValheimVoipPlugin.Log.LogInfo((object)("Applied server voice settings: " + summary)); } else { VoiceLog.InfoRateLimited("voice-settings-unchanged", "Received server voice settings: " + summary, 60f); } } catch (Exception ex) { VoiceLog.WarningRateLimited("voice-settings-malformed", "Dropped malformed voice settings package from server peer " + senderPeerId + ": " + ex.Message, 10f); } } public void OnRpcUnavailable() { VoiceRuntimeSettings.ClearServerSettings(); } } internal sealed class VoicePlayback : MonoBehaviour { private sealed class SpeakerPlayback { private readonly object _lock = new object(); private readonly Queue _samples = new Queue(); private readonly GameObject _sourceObject; private AudioClip _clip; private int _bufferedSamples; private int _sampleRate; private int _underflowEvents; private int _droppedSamples; private float _nextBufferLog; public readonly long SpeakerId; public readonly AudioSource Source; public readonly OpusVoiceCodec Codec = new OpusVoiceCodec(); public float LastPacketTime { get; private set; } private int BufferedSamples { get { lock (_lock) { return _bufferedSamples; } } } public SpeakerPlayback(long speakerId, GameObject sourceObject, int sampleRate) { SpeakerId = speakerId; _sourceObject = sourceObject; Source = sourceObject.AddComponent(); Source.playOnAwake = false; Source.spatialBlend = 1f; Source.rolloffMode = (AudioRolloffMode)1; Source.dopplerLevel = 0f; EnsureSampleRate(sampleRate); } public void EnsureSampleRate(int sampleRate) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00d8: Expected O, but got Unknown sampleRate = Mathf.Max(8000, sampleRate); if (!((Object)(object)_clip != (Object)null) || _sampleRate != sampleRate) { _sampleRate = sampleRate; lock (_lock) { _samples.Clear(); _bufferedSamples = 0; } if (Source.isPlaying) { Source.Stop(); } _clip = AudioClip.Create("voip-stream-" + SpeakerId, _sampleRate, 1, _sampleRate, true, new PCMReaderCallback(OnAudioRead), new PCMSetPositionCallback(OnAudioSetPosition)); Source.clip = _clip; Source.loop = true; } } public void UpdateSource(Vector3 position) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) LastPacketTime = Time.time; ((Component)Source).transform.position = position; Source.maxDistance = VoiceRuntimeSettings.ProximityMeters; Source.minDistance = VoiceRuntimeSettings.FullVolumeMeters; Source.volume = VoiceSettings.PlaybackVolume.Value; } public void Enqueue(float[] decodedSamples) { if (decodedSamples == null || decodedSamples.Length == 0) { return; } int num = Mathf.Max(1, _sampleRate * VoiceSettings.EffectiveMaxJitterBufferMilliseconds / 1000); int num2 = 0; lock (_lock) { foreach (float item in decodedSamples) { _samples.Enqueue(item); } _bufferedSamples += decodedSamples.Length; while (_bufferedSamples > num && _samples.Count > 0) { _samples.Dequeue(); _bufferedSamples--; num2++; } _droppedSamples += num2; } } public void UpdatePlayback() { int num = Mathf.Max(1, _sampleRate * VoiceSettings.EffectiveJitterBufferMilliseconds / 1000); if (!Source.isPlaying && BufferedSamples >= num) { Source.Play(); VoiceLog.InfoRateLimited("voice-jitter-start-" + SpeakerId, "Started jitter-buffered playback for " + SpeakerId + " with " + BufferedSamples + " queued samples.", 10f); } if (Time.time >= _nextBufferLog) { int underflowEvents; int droppedSamples; lock (_lock) { underflowEvents = _underflowEvents; droppedSamples = _droppedSamples; _underflowEvents = 0; _droppedSamples = 0; } _nextBufferLog = Time.time + 10f; if (underflowEvents > 0) { ValheimVoipPlugin.Log.LogWarning((object)("Voice jitter buffer underflow for " + SpeakerId + " (" + underflowEvents + " silent samples in the last window).")); } if (droppedSamples > 0) { ValheimVoipPlugin.Log.LogWarning((object)("Voice jitter buffer dropped " + droppedSamples + " old samples for " + SpeakerId + " to stay within the max buffer.")); } } } public void Destroy() { if ((Object)(object)_sourceObject != (Object)null) { Object.Destroy((Object)(object)_sourceObject); } } private void OnAudioRead(float[] data) { lock (_lock) { for (int i = 0; i < data.Length; i++) { if (_samples.Count > 0) { data[i] = _samples.Dequeue(); _bufferedSamples--; } else { data[i] = 0f; _underflowEvents++; } } } } private void OnAudioSetPosition(int position) { } } private const float SpeakerIdleDestroySeconds = 10f; private readonly Dictionary _speakers = new Dictionary(); public void Play(VoicePacket packet) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (packet.OpusPayload == null || packet.OpusPayload.Length == 0 || packet.Samples <= 0) { return; } SpeakerPlayback speaker = GetSpeaker(packet.SpeakerId, packet.SampleRate); speaker.UpdateSource(packet.SpeakerPosition); try { speaker.Enqueue(speaker.Codec.Decode(packet.OpusPayload, packet.Samples, packet.SampleRate)); } catch (Exception ex) { VoiceLog.WarningRateLimited("voice-decode-failed-" + packet.SpeakerId, "Dropped undecodable voice frame from " + packet.SpeakerId + ": " + ex.Message, 5f); } } private void Update() { List list = null; foreach (KeyValuePair speaker in _speakers) { speaker.Value.UpdatePlayback(); if (Time.time - speaker.Value.LastPacketTime > 10f) { if (list == null) { list = new List(); } list.Add(speaker.Key); } } if (list == null) { return; } foreach (long item in list) { if (_speakers.TryGetValue(item, out var value)) { value.Destroy(); _speakers.Remove(item); } } } private SpeakerPlayback GetSpeaker(long speakerId, int sampleRate) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown if (_speakers.TryGetValue(speakerId, out var value) && value != null) { value.EnsureSampleRate(sampleRate); return value; } GameObject val = new GameObject("VOIP Speaker " + speakerId); Object.DontDestroyOnLoad((Object)(object)val); value = new SpeakerPlayback(speakerId, val, sampleRate); _speakers[speakerId] = value; return value; } private void OnDestroy() { foreach (SpeakerPlayback value in _speakers.Values) { value.Destroy(); } _speakers.Clear(); } } internal sealed class VoiceServer : MonoBehaviour { private const float SettingsBroadcastInterval = 10f; private float _nextSettingsBroadcast; internal static VoiceServer Instance { get; private set; } private void Awake() { Instance = this; } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && Time.time >= _nextSettingsBroadcast) { BroadcastServerSettings(); _nextSettingsBroadcast = Time.time + 10f; } } public void Relay(long senderPeerId, VoicePacket packet) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null) { return; } float proximityMeters = VoiceRuntimeSettings.ProximityMeters; float num = proximityMeters * proximityMeters; foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers()) { if (connectedPeer != null && connectedPeer.m_uid != senderPeerId) { Vector3 val = connectedPeer.GetRefPos() - packet.SpeakerPosition; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { ZRoutedRpc.instance.InvokeRoutedRPC(connectedPeer.m_uid, "ValheimVoip_VoiceFrame", new object[1] { packet.ToPackage() }); } } } } private static void BroadcastServerSettings() { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ValheimVoip_Settings", new object[1] { VoiceRuntimeSettings.CreateServerPackage() }); VoiceLog.InfoRateLimited("voice-settings-broadcast", "Broadcasting server voice settings: " + VoiceRuntimeSettings.CreateServerSummary(), 60f); } } } internal static class AudioMath { public static float Rms(float[] samples, int count) { if (count <= 0) { return 0f; } double num = 0.0; for (int i = 0; i < count; i++) { num += (double)(samples[i] * samples[i]); } return (float)Math.Sqrt(num / (double)count); } } internal sealed class OpusVoiceCodec { private const int Channels = 1; private const int MaxOpusPacketBytes = 1275; private OpusEncoder _encoder; private OpusDecoder _decoder; private int _encoderSampleRate; private int _decoderSampleRate; private int _bitrate; private int _complexity; private short[] _encodeBuffer; private short[] _decodeBuffer; private byte[] _packetBuffer; public byte[] Encode(float[] samples, int count, int sampleRate) { EnsureEncoder(sampleRate, count); for (int i = 0; i < count; i++) { float num = Math.Max(-1f, Math.Min(1f, samples[i])); _encodeBuffer[i] = (short)Math.Round(num * 32767f); } int num2 = _encoder.Encode(_encodeBuffer, 0, count, _packetBuffer, 0, _packetBuffer.Length); byte[] array = new byte[num2]; Buffer.BlockCopy(_packetBuffer, 0, array, 0, num2); return array; } public float[] Decode(byte[] payload, int samples, int sampleRate) { EnsureDecoder(sampleRate, samples); int num = _decoder.Decode(payload, 0, payload.Length, _decodeBuffer, 0, samples); float[] array = new float[num]; for (int i = 0; i < num; i++) { array[i] = (float)_decodeBuffer[i] / 32768f; } return array; } private void EnsureEncoder(int sampleRate, int frameSamples) { int opusBitrate = VoiceRuntimeSettings.OpusBitrate; int opusComplexity = VoiceRuntimeSettings.OpusComplexity; if (_encoder == null || _encoderSampleRate != sampleRate || _bitrate != opusBitrate || _complexity != opusComplexity) { _encoder = new OpusEncoder(sampleRate, 1, OpusApplication.OPUS_APPLICATION_VOIP); _encoder.Bitrate = opusBitrate; _encoder.Complexity = opusComplexity; _encoder.SignalType = OpusSignal.OPUS_SIGNAL_VOICE; _encoder.UseVBR = true; _encoder.UseConstrainedVBR = true; _encoderSampleRate = sampleRate; _bitrate = opusBitrate; _complexity = opusComplexity; } if (_encodeBuffer == null || _encodeBuffer.Length < frameSamples) { _encodeBuffer = new short[frameSamples]; } if (_packetBuffer == null) { _packetBuffer = new byte[1275]; } } private void EnsureDecoder(int sampleRate, int frameSamples) { if (_decoder == null || _decoderSampleRate != sampleRate) { _decoder = new OpusDecoder(sampleRate, 1); _decoderSampleRate = sampleRate; } if (_decodeBuffer == null || _decodeBuffer.Length < frameSamples) { _decodeBuffer = new short[frameSamples]; } } } [BepInPlugin("de.valheim.voip", "Valheim VOIP", "0.1.0")] public sealed class ValheimVoipPlugin : BaseUnityPlugin { public const string ModGuid = "de.valheim.voip"; public const string ModName = "Valheim VOIP"; public const string ModVersion = "0.1.0"; private GameObject _runnerObject; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; VoiceSettings.Bind(((BaseUnityPlugin)this).Config); _runnerObject = new GameObject("Valheim VOIP"); Object.DontDestroyOnLoad((Object)(object)_runnerObject); VoiceNetwork voiceNetwork = _runnerObject.AddComponent(); VoiceServer server = _runnerObject.AddComponent(); VoiceClient client = new VoiceClient(); VoicePlayback playback = _runnerObject.AddComponent(); VoiceCapture voiceCapture = _runnerObject.AddComponent(); voiceNetwork.Initialize(client, server, playback); voiceCapture.Initialize(voiceNetwork); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim VOIP 0.1.0 loaded"); } private void OnDestroy() { if ((Object)(object)_runnerObject != (Object)null) { Object.Destroy((Object)(object)_runnerObject); } } } internal static class VoiceLog { private static readonly Dictionary NextLogTimeByKey = new Dictionary(); public static void InfoRateLimited(string key, string message, float intervalSeconds) { if (ShouldLog(key, intervalSeconds)) { ValheimVoipPlugin.Log.LogInfo((object)message); } } public static void WarningRateLimited(string key, string message, float intervalSeconds) { if (ShouldLog(key, intervalSeconds)) { ValheimVoipPlugin.Log.LogWarning((object)message); } } private static bool ShouldLog(string key, float intervalSeconds) { float time = Time.time; if (NextLogTimeByKey.TryGetValue(key, out var value) && time < value) { return false; } NextLogTimeByKey[key] = time + Mathf.Max(1f, intervalSeconds); return true; } } internal sealed class VoiceNetwork : MonoBehaviour { internal const string VoiceFrameRpcName = "ValheimVoip_VoiceFrame"; internal const string SettingsRpcName = "ValheimVoip_Settings"; private VoiceClient _client; private VoiceServer _server; private VoicePlayback _playback; private bool _registered; private ZRoutedRpc _registeredRpc; public void Initialize(VoiceClient client, VoiceServer server, VoicePlayback playback) { _client = client; _server = server; _playback = playback; } private void Update() { if (ZRoutedRpc.instance == null) { _registered = false; _registeredRpc = null; if (_client != null) { _client.OnRpcUnavailable(); } } else if (!_registered || _registeredRpc != ZRoutedRpc.instance) { ZRoutedRpc.instance.Register("ValheimVoip_VoiceFrame", (Action)OnVoiceFrame); ZRoutedRpc.instance.Register("ValheimVoip_Settings", (Action)OnSettings); _registered = true; _registeredRpc = ZRoutedRpc.instance; ValheimVoipPlugin.Log.LogInfo((object)"Voice RPC registered"); } } public void Send(VoicePacket packet) { _client.Send(packet); } private void OnVoiceFrame(long senderPeerId, ZPackage package) { if (!VoiceRuntimeSettings.Enabled) { return; } VoicePacket voicePacket; try { voicePacket = VoicePacket.FromPackage(package); } catch (Exception ex) { VoiceLog.WarningRateLimited("voice-packet-malformed-" + senderPeerId, "Dropped malformed voice packet from peer " + senderPeerId + ": " + ex.Message, 5f); return; } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { _server.Relay(senderPeerId, voicePacket); if ((Object)(object)Player.m_localPlayer != (Object)null && voicePacket.SpeakerId != Player.m_localPlayer.GetPlayerID()) { _playback.Play(voicePacket); } } else if (!((Object)(object)Player.m_localPlayer != (Object)null) || voicePacket.SpeakerId != Player.m_localPlayer.GetPlayerID()) { _playback.Play(voicePacket); } } private void OnSettings(long senderPeerId, ZPackage package) { _client.ApplyServerSettings(senderPeerId, package); } } internal sealed class VoicePacket { public long SpeakerId; public Vector3 SpeakerPosition; public int SampleRate; public int Samples; public byte[] OpusPayload; public ZPackage ToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(SpeakerId); val.Write(SpeakerPosition); val.Write(SampleRate); val.Write(Samples); val.Write(OpusPayload); return val; } public static VoicePacket FromPackage(ZPackage package) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) VoicePacket voicePacket = new VoicePacket(); voicePacket.SpeakerId = package.ReadLong(); voicePacket.SpeakerPosition = package.ReadVector3(); voicePacket.SampleRate = package.ReadInt(); voicePacket.Samples = package.ReadInt(); voicePacket.OpusPayload = package.ReadByteArray(); return voicePacket; } } internal static class VoiceRuntimeSettings { private static bool _hasServerSettings; private static bool _enabled; private static float _proximityMeters; private static float _fullVolumeMeters; private static int _sampleRate; private static int _frameMilliseconds; private static int _opusBitrate; private static int _opusComplexity; private static string _lastAppliedSummary = string.Empty; public static bool Enabled => _hasServerSettings ? _enabled : VoiceSettings.Enabled.Value; public static float ProximityMeters => _hasServerSettings ? _proximityMeters : VoiceSettings.ProximityMeters.Value; public static float FullVolumeMeters => _hasServerSettings ? _fullVolumeMeters : VoiceSettings.FullVolumeMeters.Value; public static int SampleRate => _hasServerSettings ? _sampleRate : VoiceSettings.EffectiveSampleRate; public static int FrameMilliseconds => _hasServerSettings ? _frameMilliseconds : VoiceSettings.EffectiveFrameMilliseconds; public static int OpusBitrate => _hasServerSettings ? _opusBitrate : VoiceSettings.EffectiveOpusBitrate; public static int OpusComplexity => _hasServerSettings ? _opusComplexity : VoiceSettings.EffectiveOpusComplexity; public static void ClearServerSettings() { if (_hasServerSettings) { VoiceLog.InfoRateLimited("voice-settings-cleared", "Cleared server voice settings; using local config until the server syncs again.", 10f); } _hasServerSettings = false; _lastAppliedSummary = string.Empty; } public static ZPackage CreateServerPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(1); val.Write(VoiceSettings.Enabled.Value); val.Write(VoiceSettings.ProximityMeters.Value); val.Write(VoiceSettings.FullVolumeMeters.Value); val.Write(VoiceSettings.EffectiveSampleRate); val.Write(VoiceSettings.EffectiveFrameMilliseconds); val.Write(VoiceSettings.EffectiveOpusBitrate); val.Write(VoiceSettings.EffectiveOpusComplexity); return val; } public static bool ApplyServerPackage(ZPackage package, out string summary) { summary = string.Empty; int num = package.ReadInt(); if (num != 1) { VoiceLog.WarningRateLimited("voice-settings-version", "Ignored unsupported voice settings package version " + num + ".", 30f); return false; } _enabled = package.ReadBool(); _proximityMeters = Mathf.Max(1f, package.ReadSingle()); _fullVolumeMeters = Mathf.Clamp(package.ReadSingle(), 0.1f, _proximityMeters); _sampleRate = SanitizeSampleRate(package.ReadInt()); _frameMilliseconds = SanitizeFrameMilliseconds(package.ReadInt()); _opusBitrate = Mathf.Clamp(package.ReadInt(), 6000, 128000); _opusComplexity = Mathf.Clamp(package.ReadInt(), 0, 10); _hasServerSettings = true; summary = CreateSummary(_enabled, _proximityMeters, _fullVolumeMeters, _sampleRate, _frameMilliseconds, _opusBitrate, _opusComplexity); bool result = summary != _lastAppliedSummary; _lastAppliedSummary = summary; return result; } public static string CreateServerSummary() { return CreateSummary(VoiceSettings.Enabled.Value, VoiceSettings.ProximityMeters.Value, VoiceSettings.FullVolumeMeters.Value, VoiceSettings.EffectiveSampleRate, VoiceSettings.EffectiveFrameMilliseconds, VoiceSettings.EffectiveOpusBitrate, VoiceSettings.EffectiveOpusComplexity); } private static string CreateSummary(bool enabled, float proximityMeters, float fullVolumeMeters, int sampleRate, int frameMilliseconds, int opusBitrate, int opusComplexity) { return "enabled=" + enabled + ", proximity=" + proximityMeters.ToString("0.#") + "m, fullVolume=" + fullVolumeMeters.ToString("0.#") + "m, sampleRate=" + sampleRate + ", frameMs=" + frameMilliseconds + ", bitrate=" + opusBitrate + ", complexity=" + opusComplexity; } private static int SanitizeSampleRate(int rate) { if (rate == 8000 || rate == 12000 || rate == 16000 || rate == 24000 || rate == 48000) { return rate; } return 16000; } private static int SanitizeFrameMilliseconds(int ms) { if (ms == 20 || ms == 40 || ms == 60) { return ms; } return 60; } } internal static class VoiceSettings { public static ConfigEntry Enabled { get; private set; } public static ConfigEntry PushToTalkKey { get; private set; } public static ConfigEntry VoiceActivation { get; private set; } public static ConfigEntry VoiceActivationThreshold { get; private set; } public static ConfigEntry ProximityMeters { get; private set; } public static ConfigEntry FullVolumeMeters { get; private set; } public static ConfigEntry PlaybackVolume { get; private set; } public static ConfigEntry SampleRate { get; private set; } public static ConfigEntry FrameMilliseconds { get; private set; } public static ConfigEntry JitterBufferMilliseconds { get; private set; } public static ConfigEntry MaxJitterBufferMilliseconds { get; private set; } public static ConfigEntry OpusBitrate { get; private set; } public static ConfigEntry OpusComplexity { get; private set; } public static KeyCode PushToTalkKeyCode { get { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) KeyCode result; return (KeyCode)((!Enum.TryParse(PushToTalkKey.Value, ignoreCase: true, out result)) ? 118 : ((int)result)); } } public static int EffectiveSampleRate { get { int value = SampleRate.Value; if (value == 8000 || value == 12000 || value == 16000 || value == 24000 || value == 48000) { return value; } return 16000; } } public static int EffectiveFrameMilliseconds { get { int value = FrameMilliseconds.Value; if (value == 20 || value == 40 || value == 60) { return value; } return 60; } } public static int EffectiveOpusComplexity => Mathf.Clamp(OpusComplexity.Value, 0, 10); public static int EffectiveOpusBitrate => Mathf.Clamp(OpusBitrate.Value, 6000, 128000); public static int EffectiveJitterBufferMilliseconds => Mathf.Clamp(JitterBufferMilliseconds.Value, 20, 1000); public static int EffectiveMaxJitterBufferMilliseconds => Mathf.Clamp(MaxJitterBufferMilliseconds.Value, EffectiveJitterBufferMilliseconds, 2000); public static void Bind(ConfigFile config) { Enabled = config.Bind("General", "Enabled", true, "Enable proximity voice chat."); PushToTalkKey = config.Bind("Input", "PushToTalkKey", "V", "Unity KeyCode name used for push-to-talk."); VoiceActivation = config.Bind("Input", "VoiceActivation", false, "Transmit when the microphone level exceeds the configured threshold."); VoiceActivationThreshold = config.Bind("Input", "VoiceActivationThreshold", 0.015f, "RMS threshold used when voice activation is enabled."); ProximityMeters = config.Bind("Proximity", "ProximityMeters", 35f, "Maximum distance in meters for receiving voice."); FullVolumeMeters = config.Bind("Proximity", "FullVolumeMeters", 6f, "Distance in meters where playback is still full volume."); PlaybackVolume = config.Bind("Audio", "PlaybackVolume", 1f, "Master playback volume for received voice."); SampleRate = config.Bind("Audio", "SampleRate", 16000, "Microphone sample rate. Opus supports 8000, 12000, 16000, 24000, and 48000."); FrameMilliseconds = config.Bind("Audio", "FrameMilliseconds", 60, "Captured audio duration per network packet. Opus supports 20, 40, or 60 here."); JitterBufferMilliseconds = config.Bind("Audio", "JitterBufferMilliseconds", 120, "Target playback buffer before received voice starts."); MaxJitterBufferMilliseconds = config.Bind("Audio", "MaxJitterBufferMilliseconds", 500, "Maximum queued playback audio before old samples are dropped."); OpusBitrate = config.Bind("Opus", "Bitrate", 24000, "Target Opus bitrate in bits per second."); OpusComplexity = config.Bind("Opus", "Complexity", 5, "Opus encoder complexity from 0 to 10."); } } } namespace Concentus.Celt { internal static class Bands { public class band_ctx { public int encode; public CeltMode m; public int i; public int intensity; public int spread; public int tf_change; public EntropyCoder ec; public int remaining_bits; public int[][] bandE; public uint seed; } public class split_ctx { public int inv; public int imid; public int iside; public int delta; public int itheta; public int qalloc; } private static readonly byte[] bit_interleave_table = new byte[16] { 0, 1, 1, 1, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3 }; private static readonly byte[] bit_deinterleave_table = new byte[16] { 0, 3, 12, 15, 48, 51, 60, 63, 192, 195, 204, 207, 240, 243, 252, 255 }; internal static int hysteresis_decision(int val, int[] thresholds, int[] hysteresis, int N, int prev) { int i; for (i = 0; i < N && val >= thresholds[i]; i++) { } if (i > prev && val < thresholds[prev] + hysteresis[prev]) { i = prev; } if (i < prev && val > thresholds[prev - 1] - hysteresis[prev - 1]) { i = prev; } return i; } internal static uint celt_lcg_rand(uint seed) { return 1664525 * seed + 1013904223; } internal static int bitexact_cos(int x) { int num = 4096 + x * x >> 13; int num2 = num; num2 = 32767 - num2 + Inlines.FRAC_MUL16(num2, -7651 + Inlines.FRAC_MUL16(num2, 8277 + Inlines.FRAC_MUL16(-626, num2))); return 1 + num2; } internal static int bitexact_log2tan(int isin, int icos) { int num = Inlines.EC_ILOG((uint)icos); int num2 = Inlines.EC_ILOG((uint)isin); icos <<= 15 - num; isin <<= 15 - num2; return (num2 - num) * 2048 + Inlines.FRAC_MUL16(isin, Inlines.FRAC_MUL16(isin, -2597) + 7932) - Inlines.FRAC_MUL16(icos, Inlines.FRAC_MUL16(icos, -2597) + 7932); } internal static void compute_band_energies(CeltMode m, int[][] X, int[][] bandE, int end, int C, int LM) { short[] eBands = m.eBands; int num = m.shortMdctSize << LM; int num2 = 0; do { for (int i = 0; i < end; i++) { int num3 = 0; int num4 = 0; num3 = Inlines.celt_maxabs32(X[num2], eBands[i] << LM, eBands[i + 1] - eBands[i] << LM); if (num3 > 0) { int num5 = Inlines.celt_ilog2(num3) - 14 + ((m.logN[i] >> 3) + LM + 1 >> 1); int num6 = eBands[i] << LM; if (num5 > 0) { do { num4 = Inlines.MAC16_16(num4, Inlines.EXTRACT16(Inlines.SHR32(X[num2][num6], num5)), Inlines.EXTRACT16(Inlines.SHR32(X[num2][num6], num5))); } while (++num6 < eBands[i + 1] << LM); } else { do { num4 = Inlines.MAC16_16(num4, Inlines.EXTRACT16(Inlines.SHL32(X[num2][num6], -num5)), Inlines.EXTRACT16(Inlines.SHL32(X[num2][num6], -num5))); } while (++num6 < eBands[i + 1] << LM); } bandE[num2][i] = 1 + Inlines.VSHR32(Inlines.celt_sqrt(num4), -num5); } else { bandE[num2][i] = 1; } } } while (++num2 < C); } internal static void normalise_bands(CeltMode m, int[][] freq, int[][] X, int[][] bandE, int end, int C, int M) { short[] eBands = m.eBands; int num = 0; do { int num2 = 0; do { int num3 = Inlines.celt_zlog2(bandE[num][num2]) - 13; int a = Inlines.VSHR32(bandE[num][num2], num3); int b = Inlines.EXTRACT16(Inlines.celt_rcp(Inlines.SHL32(a, 3))); int num4 = M * eBands[num2]; do { X[num][num4] = Inlines.MULT16_16_Q15(Inlines.VSHR32(freq[num][num4], num3 - 1), b); } while (++num4 < M * eBands[num2 + 1]); } while (++num2 < end); } while (++num < C); } internal static void denormalise_bands(CeltMode m, int[] X, int[] freq, int freq_ptr, int[] bandLogE, int bandLogE_ptr, int start, int end, int M, int downsample, int silence) { short[] eBands = m.eBands; int num = M * m.shortMdctSize; int num2 = M * eBands[end]; if (downsample != 1) { num2 = Inlines.IMIN(num2, num / downsample); } if (silence != 0) { num2 = 0; start = (end = 0); } int num3 = freq_ptr; int num4 = M * eBands[start]; for (int i = 0; i < M * eBands[start]; i++) { freq[num3++] = 0; } for (int i = start; i < end; i++) { int num5 = M * eBands[i]; int num6 = M * eBands[i + 1]; int num7 = Inlines.ADD16(bandLogE[bandLogE_ptr + i], Inlines.SHL16(Tables.eMeans[i], 6)); int num8 = 16 - (num7 >> 10); int b; if (num8 > 31) { num8 = 0; b = 0; } else { b = Inlines.celt_exp2_frac(num7 & 0x3FF); } if (num8 < 0) { if (num8 < -2) { b = 32767; num8 = -2; } do { freq[num3] = Inlines.SHR32(Inlines.MULT16_16(X[num4], b), -num8); } while (++num5 < num6); } else { do { freq[num3++] = Inlines.SHR32(Inlines.MULT16_16(X[num4++], b), num8); } while (++num5 < num6); } } Arrays.MemSetWithOffset(freq, 0, freq_ptr + num2, num - num2); } internal static void anti_collapse(CeltMode m, int[][] X_, byte[] collapse_masks, int LM, int C, int size, int start, int end, int[] logE, int[] prev1logE, int[] prev2logE, int[] pulses, uint seed) { for (int i = start; i < end; i++) { int num = m.eBands[i + 1] - m.eBands[i]; int a = Inlines.celt_udiv(1 + pulses[i], m.eBands[i + 1] - m.eBands[i]) >> LM; int b = Inlines.SHR32(Inlines.celt_exp2(-Inlines.SHL16(a, 7)), 1); int a2 = Inlines.MULT16_32_Q15((short)16384, Inlines.MIN32(32767, b)); int num2 = num << LM; int num3 = Inlines.celt_ilog2(num2) >> 1; num2 = Inlines.SHL32(num2, 7 - num3 << 1); int a3 = Inlines.celt_rsqrt_norm(num2); int num4 = 0; do { int num5 = 0; int a4 = prev1logE[num4 * m.nbEBands + i]; int num6 = prev2logE[num4 * m.nbEBands + i]; if (C == 1) { a4 = Inlines.MAX16(a4, prev1logE[m.nbEBands + i]); num6 = Inlines.MAX16(num6, prev2logE[m.nbEBands + i]); } int b2 = Inlines.EXTEND32(logE[num4 * m.nbEBands + i]) - Inlines.EXTEND32(Inlines.MIN16(a4, num6)); b2 = Inlines.MAX32(0, b2); int b4; if (b2 < 16384) { int b3 = Inlines.SHR32(Inlines.celt_exp2((short)(-Inlines.EXTRACT16(b2))), 1); b4 = 2 * Inlines.MIN16(16383, b3); } else { b4 = 0; } if (LM == 3) { b4 = Inlines.MULT16_16_Q14(23170, Inlines.MIN32(23169, b4)); } b4 = Inlines.SHR16(Inlines.MIN16(a2, b4), 1); b4 = Inlines.SHR32(Inlines.MULT16_16_Q15(a3, b4), num3); int num7 = m.eBands[i] << LM; for (int j = 0; j < 1 << LM; j++) { if ((collapse_masks[i * C + num4] & (1 << j)) == 0) { int num8 = num7 + j; for (int k = 0; k < num; k++) { seed = celt_lcg_rand(seed); X_[num4][num8 + (k << LM)] = (((seed & 0x8000u) != 0) ? b4 : (-b4)); } num5 = 1; } } if (num5 != 0) { VQ.renormalise_vector(X_[num4], num7, num << LM, 32767); } } while (++num4 < C); } } internal static void intensity_stereo(CeltMode m, int[] X, int X_ptr, int[] Y, int Y_ptr, int[][] bandE, int bandID, int N) { int shift = Inlines.celt_zlog2(Inlines.MAX32(bandE[0][bandID], bandE[1][bandID])) - 13; int num = Inlines.VSHR32(bandE[0][bandID], shift); int num2 = Inlines.VSHR32(bandE[1][bandID], shift); int b = 1 + Inlines.celt_sqrt(1 + Inlines.MULT16_16(num, num) + Inlines.MULT16_16(num2, num2)); int a = Inlines.DIV32_16(Inlines.SHL32(num, 14), b); int a2 = Inlines.DIV32_16(Inlines.SHL32(num2, 14), b); for (int i = 0; i < N; i++) { int b2 = X[X_ptr + i]; int b3 = Y[Y_ptr + i]; X[X_ptr + i] = Inlines.EXTRACT16(Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(a, b2), a2, b3), 14)); } } private static void stereo_split(int[] X, int X_ptr, int[] Y, int Y_ptr, int N) { for (int i = 0; i < N; i++) { int num = Inlines.MULT16_16(23170, X[X_ptr + i]); int num2 = Inlines.MULT16_16(23170, Y[Y_ptr + i]); X[X_ptr + i] = Inlines.EXTRACT16(Inlines.SHR32(Inlines.ADD32(num, num2), 15)); Y[Y_ptr + i] = Inlines.EXTRACT16(Inlines.SHR32(Inlines.SUB32(num2, num), 15)); } } private static void stereo_merge(int[] X, int X_ptr, int[] Y, int Y_ptr, int mid, int N) { Kernels.dual_inner_prod(Y, Y_ptr, X, X_ptr, Y, Y_ptr, N, out var xy, out var xy2); xy = Inlines.MULT16_32_Q15(mid, xy); int num = Inlines.SHR16(mid, 1); int num2 = Inlines.MULT16_16(num, num) + xy2 - 2 * xy; int num3 = Inlines.MULT16_16(num, num) + xy2 + 2 * xy; if (num3 < 161061 || num2 < 161061) { Array.Copy(X, X_ptr, Y, Y_ptr, N); return; } int num4 = Inlines.celt_ilog2(num2) >> 1; int num5 = Inlines.celt_ilog2(num3) >> 1; int x = Inlines.VSHR32(num2, num4 - 7 << 1); int a = Inlines.celt_rsqrt_norm(x); x = Inlines.VSHR32(num3, num5 - 7 << 1); int a2 = Inlines.celt_rsqrt_norm(x); if (num4 < 7) { num4 = 7; } if (num5 < 7) { num5 = 7; } for (int i = 0; i < N; i++) { int a3 = Inlines.MULT16_16_P15(mid, X[X_ptr + i]); int b = Y[Y_ptr + i]; X[X_ptr + i] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MULT16_16(a, Inlines.SUB16(a3, b)), num4 + 1)); Y[Y_ptr + i] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MULT16_16(a2, Inlines.ADD16(a3, b)), num5 + 1)); } } internal static int spreading_decision(CeltMode m, int[][] X, ref int average, int last_decision, ref int hf_average, ref int tapset_decision, int update_hf, int end, int C, int M) { int num = 0; int num2 = 0; short[] eBands = m.eBands; int num3 = 0; if (M * (eBands[end] - eBands[end - 1]) <= 8) { return 0; } int num4 = 0; do { for (int i = 0; i < end; i++) { int num5 = 0; int[] array = new int[3]; int[] array2 = array; int[] array3 = X[num4]; int num6 = M * eBands[i]; int num7 = M * (eBands[i + 1] - eBands[i]); if (num7 <= 8) { continue; } for (int j = num6; j < num7 + num6; j++) { int num8 = Inlines.MULT16_16(Inlines.MULT16_16_Q15(array3[j], array3[j]), num7); if (num8 < 2048) { array2[0]++; } if (num8 < 512) { array2[1]++; } if (num8 < 128) { array2[2]++; } } if (i > m.nbEBands - 4) { num3 += Inlines.celt_udiv(32 * (array2[1] + array2[0]), num7); } num5 = ((2 * array2[2] >= num7) ? 1 : 0) + ((2 * array2[1] >= num7) ? 1 : 0) + ((2 * array2[0] >= num7) ? 1 : 0); num += num5 * 256; num2++; } } while (++num4 < C); if (update_hf != 0) { if (num3 != 0) { num3 = Inlines.celt_udiv(num3, C * (4 - m.nbEBands + end)); } hf_average = hf_average + num3 >> 1; num3 = hf_average; if (tapset_decision == 2) { num3 += 4; } else if (tapset_decision == 0) { num3 -= 4; } if (num3 > 22) { tapset_decision = 2; } else if (num3 > 18) { tapset_decision = 1; } else { tapset_decision = 0; } } num = Inlines.celt_udiv(num, num2); num = 3 * (average = num + average >> 1) + ((3 - last_decision << 7) + 64) + 2 >> 2; return (num < 80) ? 3 : ((num < 256) ? 2 : ((num < 384) ? 1 : 0)); } internal static void deinterleave_hadamard(int[] X, int X_ptr, int N0, int stride, int hadamard) { int num = N0 * stride; int[] array = new int[num]; if (hadamard != 0) { int num2 = stride - 2; for (int i = 0; i < stride; i++) { for (int j = 0; j < N0; j++) { array[Tables.ordery_table[num2 + i] * N0 + j] = X[j * stride + i + X_ptr]; } } } else { for (int i = 0; i < stride; i++) { for (int j = 0; j < N0; j++) { array[i * N0 + j] = X[j * stride + i + X_ptr]; } } } Array.Copy(array, 0, X, X_ptr, num); } internal static void interleave_hadamard(int[] X, int X_ptr, int N0, int stride, int hadamard) { int num = N0 * stride; int[] array = new int[num]; if (hadamard != 0) { int num2 = stride - 2; for (int i = 0; i < stride; i++) { for (int j = 0; j < N0; j++) { array[j * stride + i] = X[Tables.ordery_table[num2 + i] * N0 + j + X_ptr]; } } } else { for (int i = 0; i < stride; i++) { for (int j = 0; j < N0; j++) { array[j * stride + i] = X[i * N0 + j + X_ptr]; } } } Array.Copy(array, 0, X, X_ptr, num); } internal static void haar1(int[] X, int X_ptr, int N0, int stride) { N0 >>= 1; for (int i = 0; i < stride; i++) { for (int j = 0; j < N0; j++) { int num = X_ptr + i + stride * 2 * j; int a = Inlines.MULT16_16(23170, X[num]); int b = Inlines.MULT16_16(23170, X[num + stride]); X[num] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.ADD32(a, b), 15)); X[num + stride] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.SUB32(a, b), 15)); } } } internal static void haar1ZeroOffset(int[] X, int N0, int stride) { N0 >>= 1; for (int i = 0; i < stride; i++) { for (int j = 0; j < N0; j++) { int num = i + stride * 2 * j; int a = Inlines.MULT16_16(23170, X[num]); int b = Inlines.MULT16_16(23170, X[num + stride]); X[num] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.ADD32(a, b), 15)); X[num + stride] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.SUB32(a, b), 15)); } } } internal static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo) { short[] array = new short[8] { 16384, 17866, 19483, 21247, 23170, 25267, 27554, 30048 }; int num = 2 * N - 1; if (stereo != 0 && N == 2) { num--; } int b2 = Inlines.celt_sudiv(b + num * offset, num); b2 = Inlines.IMIN(b - pulse_cap - 32, b2); b2 = Inlines.IMIN(64, b2); if (b2 < 4) { return 1; } int num2 = array[b2 & 7] >> 14 - (b2 >> 3); return num2 + 1 >> 1 << 1; } internal static void compute_theta(band_ctx ctx, split_ctx sctx, int[] X, int X_ptr, int[] Y, int Y_ptr, int N, ref int b, int B, int B0, int LM, int stereo, ref int fill) { int num = 0; int num2 = 0; int encode = ctx.encode; CeltMode m = ctx.m; int i = ctx.i; int intensity = ctx.intensity; EntropyCoder ec = ctx.ec; int[][] bandE = ctx.bandE; int num3 = m.logN[i] + LM * 8; int offset = (num3 >> 1) - ((stereo != 0 && N == 2) ? 16 : 4); int num4 = compute_qn(N, b, offset, num3, stereo); if (stereo != 0 && i >= intensity) { num4 = 1; } if (encode != 0) { num = VQ.stereo_itheta(X, X_ptr, Y, Y_ptr, stereo, N); } int num5 = (int)ec.tell_frac(); if (num4 != 1) { if (encode != 0) { num = num * num4 + 8192 >> 14; } if (stereo != 0 && N > 2) { int num6 = 3; int num7 = num; int num8 = num4 / 2; uint ft = (uint)(num6 * (num8 + 1) + num8); if (encode != 0) { ec.encode((uint)((num7 <= num8) ? (num6 * num7) : (num7 - 1 - num8 + (num8 + 1) * num6)), (uint)((num7 <= num8) ? (num6 * (num7 + 1)) : (num7 - num8 + (num8 + 1) * num6)), ft); } else { int num9 = (int)ec.decode(ft); num7 = ((num9 >= (num8 + 1) * num6) ? (num8 + 1 + (num9 - (num8 + 1) * num6)) : (num9 / num6)); ec.dec_update((uint)((num7 <= num8) ? (num6 * num7) : (num7 - 1 - num8 + (num8 + 1) * num6)), (uint)((num7 <= num8) ? (num6 * (num7 + 1)) : (num7 - num8 + (num8 + 1) * num6)), ft); num = num7; } } else if (B0 > 1 || stereo != 0) { if (encode != 0) { ec.enc_uint((uint)num, (uint)(num4 + 1)); } else { num = (int)ec.dec_uint((uint)(num4 + 1)); } } else { int num9 = 1; int num10 = ((num4 >> 1) + 1) * ((num4 >> 1) + 1); if (encode != 0) { num9 = ((num <= num4 >> 1) ? (num + 1) : (num4 + 1 - num)); int num11 = ((num <= num4 >> 1) ? (num * (num + 1) >> 1) : (num10 - ((num4 + 1 - num) * (num4 + 2 - num) >> 1))); ec.encode((uint)num11, (uint)(num11 + num9), (uint)num10); } else { int num11 = 0; int num12 = (int)ec.decode((uint)num10); if (num12 < (num4 >> 1) * ((num4 >> 1) + 1) >> 1) { num = (int)(Inlines.isqrt32((uint)(8 * num12 + 1)) - 1) >> 1; num9 = num + 1; num11 = num * (num + 1) >> 1; } else { num = (int)(2 * (num4 + 1) - Inlines.isqrt32((uint)(8 * (num10 - num12 - 1) + 1))) >> 1; num9 = num4 + 1 - num; num11 = num10 - ((num4 + 1 - num) * (num4 + 2 - num) >> 1); } ec.dec_update((uint)num11, (uint)(num11 + num9), (uint)num10); } } num = Inlines.celt_udiv(num * 16384, num4); if (encode != 0 && stereo != 0) { if (num == 0) { intensity_stereo(m, X, X_ptr, Y, Y_ptr, bandE, i, N); } else { stereo_split(X, X_ptr, Y, Y_ptr, N); } } } else if (stereo != 0) { if (encode != 0) { num2 = ((num > 8192) ? 1 : 0); if (num2 != 0) { for (int j = 0; j < N; j++) { Y[Y_ptr + j] = -Y[Y_ptr + j]; } } intensity_stereo(m, X, X_ptr, Y, Y_ptr, bandE, i, N); } if (b > 16 && ctx.remaining_bits > 16) { if (encode != 0) { ec.enc_bit_logp(num2, 2u); } else { num2 = ec.dec_bit_logp(2u); } } else { num2 = 0; } num = 0; } int num13 = (int)ec.tell_frac() - num5; b -= num13; int num14; int num15; int delta; switch (num) { case 0: num14 = 32767; num15 = 0; fill &= (1 << B) - 1; delta = -16384; break; case 16384: num14 = 0; num15 = 32767; fill &= (1 << B) - 1 << B; delta = 16384; break; default: num14 = bitexact_cos((short)num); num15 = bitexact_cos((short)(16384 - num)); delta = Inlines.FRAC_MUL16(N - 1 << 7, bitexact_log2tan(num15, num14)); break; } sctx.inv = num2; sctx.imid = num14; sctx.iside = num15; sctx.delta = delta; sctx.itheta = num; sctx.qalloc = num13; } internal static uint quant_band_n1(band_ctx ctx, int[] X, int X_ptr, int[] Y, int Y_ptr, int b, int[] lowband_out, int lowband_out_ptr) { int num = ((ctx.encode == 0) ? 1 : 0); int[] array = X; int num2 = X_ptr; int encode = ctx.encode; EntropyCoder ec = ctx.ec; int num3 = ((Y != null) ? 1 : 0); int num4 = 0; do { int num5 = 0; if (ctx.remaining_bits >= 8) { if (encode != 0) { num5 = ((array[num2] < 0) ? 1 : 0); ec.enc_bits((uint)num5, 1u); } else { num5 = (int)ec.dec_bits(1u); } ctx.remaining_bits -= 8; b -= 8; } if (num != 0) { array[num2] = ((num5 != 0) ? (-16384) : 16384); } array = Y; num2 = Y_ptr; } while (++num4 < 1 + num3); if (lowband_out != null) { lowband_out[lowband_out_ptr] = Inlines.SHR16(X[X_ptr], 4); } return 1u; } internal static uint quant_partition(band_ctx ctx, int[] X, int X_ptr, int N, int b, int B, int[] lowband, int lowband_ptr, int LM, int gain, int fill) { int num = 0; int num2 = 0; int num3 = B; int num4 = 0; int num5 = 0; uint result = 0u; int num6 = ((ctx.encode == 0) ? 1 : 0); int num7 = 0; int encode = ctx.encode; CeltMode m = ctx.m; int i = ctx.i; int spread = ctx.spread; EntropyCoder ec = ctx.ec; byte[] bits = m.cache.bits; int num8 = m.cache.index[(LM + 1) * m.nbEBands + i]; if (LM != -1 && b > bits[num8 + bits[num8]] + 12 && N > 2) { split_ctx split_ctx = new split_ctx(); int lowband_ptr2 = 0; N >>= 1; num7 = X_ptr + N; LM--; if (B == 1) { fill = (fill & 1) | (fill << 1); } B = B + 1 >> 1; compute_theta(ctx, split_ctx, X, X_ptr, X, num7, N, ref b, B, num3, LM, 0, ref fill); num = split_ctx.imid; num2 = split_ctx.iside; int num9 = split_ctx.delta; int itheta = split_ctx.itheta; int qalloc = split_ctx.qalloc; num4 = num; num5 = num2; if (num3 > 1 && ((uint)itheta & 0x3FFFu) != 0) { num9 = ((itheta <= 8192) ? Inlines.IMIN(0, num9 + (N << 3 >> 5 - LM)) : (num9 - (num9 >> 4 - LM))); } int num10 = Inlines.IMAX(0, Inlines.IMIN(b, (b - num9) / 2)); int num11 = b - num10; ctx.remaining_bits -= qalloc; if (lowband != null) { lowband_ptr2 = lowband_ptr + N; } int remaining_bits = ctx.remaining_bits; if (num10 >= num11) { result = quant_partition(ctx, X, X_ptr, N, num10, B, lowband, lowband_ptr, LM, Inlines.MULT16_16_P15(gain, num4), fill); remaining_bits = num10 - (remaining_bits - ctx.remaining_bits); if (remaining_bits > 24 && itheta != 0) { num11 += remaining_bits - 24; } result |= quant_partition(ctx, X, num7, N, num11, B, lowband, lowband_ptr2, LM, Inlines.MULT16_16_P15(gain, num5), fill >> B) << (num3 >> 1); } else { result = quant_partition(ctx, X, num7, N, num11, B, lowband, lowband_ptr2, LM, Inlines.MULT16_16_P15(gain, num5), fill >> B) << (num3 >> 1); remaining_bits = num11 - (remaining_bits - ctx.remaining_bits); if (remaining_bits > 24 && itheta != 16384) { num10 += remaining_bits - 24; } result |= quant_partition(ctx, X, X_ptr, N, num10, B, lowband, lowband_ptr, LM, Inlines.MULT16_16_P15(gain, num4), fill); } } else { int num12 = Rate.bits2pulses(m, i, LM, b); int num13 = Rate.pulses2bits(m, i, LM, num12); ctx.remaining_bits -= num13; while (ctx.remaining_bits < 0 && num12 > 0) { ctx.remaining_bits += num13; num12--; num13 = Rate.pulses2bits(m, i, LM, num12); ctx.remaining_bits -= num13; } if (num12 != 0) { int k = Rate.get_pulses(num12); result = ((encode == 0) ? VQ.alg_unquant(X, X_ptr, N, k, spread, B, ec, gain) : VQ.alg_quant(X, X_ptr, N, k, spread, B, ec)); } else if (num6 != 0) { uint num14 = (uint)((int)(1L << B) - 1); fill &= (int)num14; if (fill == 0) { Arrays.MemSetWithOffset(X, 0, X_ptr, N); } else { if (lowband == null) { for (int j = 0; j < N; j++) { ctx.seed = celt_lcg_rand(ctx.seed); X[X_ptr + j] = (int)ctx.seed >> 20; } result = num14; } else { for (int j = 0; j < N; j++) { ctx.seed = celt_lcg_rand(ctx.seed); int num15 = 4; num15 = (((ctx.seed & 0x8000u) != 0) ? num15 : (-num15)); X[X_ptr + j] = lowband[lowband_ptr + j] + num15; } result = (uint)fill; } VQ.renormalise_vector(X, X_ptr, N, gain); } } } return result; } internal static uint quant_band(band_ctx ctx, int[] X, int X_ptr, int N, int b, int B, int[] lowband, int lowband_ptr, int LM, int[] lowband_out, int lowband_out_ptr, int gain, int[] lowband_scratch, int lowband_scratch_ptr, int fill) { int n = N; int num = B; int num2 = 0; int num3 = 0; uint num4 = 0u; int num5 = ((ctx.encode == 0) ? 1 : 0); int encode = ctx.encode; int num6 = ctx.tf_change; int hadamard = ((num == 1) ? 1 : 0); n = Inlines.celt_udiv(n, B); if (N == 1) { return quant_band_n1(ctx, X, X_ptr, null, 0, b, lowband_out, lowband_out_ptr); } if (num6 > 0) { num3 = num6; } if (lowband_scratch != null && lowband != null && (num3 != 0 || ((n & 1) == 0 && num6 < 0) || num > 1)) { Array.Copy(lowband, lowband_ptr, lowband_scratch, lowband_scratch_ptr, N); lowband = lowband_scratch; lowband_ptr = lowband_scratch_ptr; } for (int i = 0; i < num3; i++) { if (encode != 0) { haar1(X, X_ptr, N >> i, 1 << i); } if (lowband != null) { haar1(lowband, lowband_ptr, N >> i, 1 << i); } fill = bit_interleave_table[fill & 0xF] | (bit_interleave_table[fill >> 4] << 2); } B >>= num3; n <<= num3; while ((n & 1) == 0 && num6 < 0) { if (encode != 0) { haar1(X, X_ptr, n, B); } if (lowband != null) { haar1(lowband, lowband_ptr, n, B); } fill |= fill << B; B <<= 1; n >>= 1; num2++; num6++; } num = B; int num7 = n; if (num > 1) { if (encode != 0) { deinterleave_hadamard(X, X_ptr, n >> num3, num << num3, hadamard); } if (lowband != null) { deinterleave_hadamard(lowband, lowband_ptr, n >> num3, num << num3, hadamard); } } num4 = quant_partition(ctx, X, X_ptr, N, b, B, lowband, lowband_ptr, LM, gain, fill); if (num5 != 0) { if (num > 1) { interleave_hadamard(X, X_ptr, n >> num3, num << num3, hadamard); } n = num7; B = num; for (int i = 0; i < num2; i++) { B >>= 1; n <<= 1; num4 |= num4 >> B; haar1(X, X_ptr, n, B); } for (int i = 0; i < num3; i++) { num4 = bit_deinterleave_table[num4]; haar1(X, X_ptr, N >> i, 1 << i); } B <<= num3; if (lowband_out != null) { int a = Inlines.celt_sqrt(Inlines.SHL32(N, 22)); for (int j = 0; j < N; j++) { lowband_out[lowband_out_ptr + j] = Inlines.MULT16_16_Q15(a, X[X_ptr + j]); } } num4 &= (uint)((1 << B) - 1); } return num4; } internal static uint quant_band_stereo(band_ctx ctx, int[] X, int X_ptr, int[] Y, int Y_ptr, int N, int b, int B, int[] lowband, int lowband_ptr, int LM, int[] lowband_out, int lowband_out_ptr, int[] lowband_scratch, int lowband_scratch_ptr, int fill) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; uint num6 = 0u; int num7 = ((ctx.encode == 0) ? 1 : 0); split_ctx split_ctx = new split_ctx(); int encode = ctx.encode; EntropyCoder ec = ctx.ec; if (N == 1) { return quant_band_n1(ctx, X, X_ptr, Y, Y_ptr, b, lowband_out, lowband_out_ptr); } int fill2 = fill; compute_theta(ctx, split_ctx, X, X_ptr, Y, Y_ptr, N, ref b, B, B, LM, 1, ref fill); num3 = split_ctx.inv; num = split_ctx.imid; num2 = split_ctx.iside; int delta = split_ctx.delta; int itheta = split_ctx.itheta; int qalloc = split_ctx.qalloc; num4 = num; num5 = num2; if (N == 2) { int num8 = 0; int num9 = b; int num10 = 0; if (itheta != 0 && itheta != 16384) { num10 = 8; } num9 -= num10; int num11 = ((itheta > 8192) ? 1 : 0); ctx.remaining_bits -= qalloc + num10; int[] array; int num12; int[] array2; if (num11 != 0) { array = Y; num12 = Y_ptr; array2 = X; int num13 = X_ptr; } else { array = X; num12 = X_ptr; array2 = Y; int num13 = Y_ptr; } if (num10 != 0) { if (encode != 0) { num8 = ((array[num12] * array2[Y_ptr + 1] - array[num12 + 1] * array2[Y_ptr] < 0) ? 1 : 0); ec.enc_bits((uint)num8, 1u); } else { num8 = (int)ec.dec_bits(1u); } } num8 = 1 - 2 * num8; num6 = quant_band(ctx, array, num12, N, num9, B, lowband, lowband_ptr, LM, lowband_out, lowband_out_ptr, 32767, lowband_scratch, lowband_scratch_ptr, fill2); array2[Y_ptr] = -num8 * array[num12 + 1]; array2[Y_ptr + 1] = num8 * array[num12]; if (num7 != 0) { X[X_ptr] = Inlines.MULT16_16_Q15(num4, X[X_ptr]); X[X_ptr + 1] = Inlines.MULT16_16_Q15(num4, X[X_ptr + 1]); Y[Y_ptr] = Inlines.MULT16_16_Q15(num5, Y[Y_ptr]); Y[Y_ptr + 1] = Inlines.MULT16_16_Q15(num5, Y[Y_ptr + 1]); int a = X[X_ptr]; X[X_ptr] = Inlines.SUB16(a, Y[Y_ptr]); Y[Y_ptr] = Inlines.ADD16(a, Y[Y_ptr]); a = X[X_ptr + 1]; X[X_ptr + 1] = Inlines.SUB16(a, Y[Y_ptr + 1]); Y[Y_ptr + 1] = Inlines.ADD16(a, Y[Y_ptr + 1]); } } else { int num9 = Inlines.IMAX(0, Inlines.IMIN(b, (b - delta) / 2)); int num10 = b - num9; ctx.remaining_bits -= qalloc; int remaining_bits = ctx.remaining_bits; if (num9 >= num10) { num6 = quant_band(ctx, X, X_ptr, N, num9, B, lowband, lowband_ptr, LM, lowband_out, lowband_out_ptr, 32767, lowband_scratch, lowband_scratch_ptr, fill); remaining_bits = num9 - (remaining_bits - ctx.remaining_bits); if (remaining_bits > 24 && itheta != 0) { num10 += remaining_bits - 24; } num6 |= quant_band(ctx, Y, Y_ptr, N, num10, B, null, 0, LM, null, 0, num5, null, 0, fill >> B); } else { num6 = quant_band(ctx, Y, Y_ptr, N, num10, B, null, 0, LM, null, 0, num5, null, 0, fill >> B); remaining_bits = num10 - (remaining_bits - ctx.remaining_bits); if (remaining_bits > 24 && itheta != 16384) { num9 += remaining_bits - 24; } num6 |= quant_band(ctx, X, X_ptr, N, num9, B, lowband, lowband_ptr, LM, lowband_out, lowband_out_ptr, 32767, lowband_scratch, lowband_scratch_ptr, fill); } } if (num7 != 0) { if (N != 2) { stereo_merge(X, X_ptr, Y, Y_ptr, num4, N); } if (num3 != 0) { for (int i = Y_ptr; i < N + Y_ptr; i++) { Y[i] = (short)(-Y[i]); } } } return num6; } internal static void quant_all_bands(int encode, CeltMode m, int start, int end, int[] X_, int[] Y_, byte[] collapse_masks, int[][] bandE, int[] pulses, int shortBlocks, int spread, int dual_stereo, int intensity, int[] tf_res, int total_bits, int balance, EntropyCoder ec, int LM, int codedBands, ref uint seed) { short[] eBands = m.eBands; int num = 1; int num2 = ((Y_ == null) ? 1 : 2); int num3 = ((encode == 0) ? 1 : 0); band_ctx band_ctx = new band_ctx(); int num4 = 1 << LM; int num5 = ((shortBlocks == 0) ? 1 : num4); int num6 = num4 * eBands[start]; int[] array = new int[num2 * (num4 * eBands[m.nbEBands - 1] - num6)]; int num7 = num4 * eBands[m.nbEBands - 1] - num6; int[] lowband_scratch = X_; int lowband_scratch_ptr = num4 * eBands[m.nbEBands - 1]; int num8 = 0; band_ctx.bandE = bandE; band_ctx.ec = ec; band_ctx.encode = encode; band_ctx.intensity = intensity; band_ctx.m = m; band_ctx.seed = seed; band_ctx.spread = spread; for (int i = start; i < end; i++) { int num9 = -1; int num10 = 0; int num11 = 0; band_ctx.i = i; int num12 = ((i == end - 1) ? 1 : 0); int[] x = X_; int x_ptr = num4 * eBands[i]; int[] array2; if (Y_ != null) { array2 = Y_; num10 = num4 * eBands[i]; } else { array2 = null; } int num13 = num4 * eBands[i + 1] - num4 * eBands[i]; int num14 = (int)ec.tell_frac(); if (i != start) { balance -= num14; } int num15 = (band_ctx.remaining_bits = total_bits - num14 - 1); int num17; if (i <= codedBands - 1) { int num16 = Inlines.celt_sudiv(balance, Inlines.IMIN(3, codedBands - i)); num17 = Inlines.IMAX(0, Inlines.IMIN(16383, Inlines.IMIN(num15 + 1, pulses[i] + num16))); } else { num17 = 0; } if (num3 != 0 && num4 * eBands[i] - num13 >= num4 * eBands[start] && (num != 0 || num8 == 0)) { num8 = i; } num11 = (band_ctx.tf_change = tf_res[i]); if (i >= m.effEBands) { x = array; x_ptr = 0; if (Y_ != null) { array2 = array; num10 = 0; } lowband_scratch = null; } if (i == end - 1) { lowband_scratch = null; } uint num21; uint num20; if (num8 != 0 && (spread != 3 || num5 > 1 || num11 < 0)) { num9 = Inlines.IMAX(0, num4 * eBands[num8] - num6 - num13); int num18 = num8; while (num4 * eBands[--num18] > num9 + num6) { } int num19 = num8 - 1; while (num4 * eBands[++num19] < num9 + num6 + num13) { } num21 = (num20 = 0u); int num22 = num18; do { num21 |= collapse_masks[num22 * num2]; num20 |= collapse_masks[num22 * num2 + num2 - 1]; } while (++num22 < num19); } else { num21 = (num20 = (uint)((1 << num5) - 1)); } if (dual_stereo != 0 && i == intensity) { dual_stereo = 0; if (num3 != 0) { for (int j = 0; j < num4 * eBands[i] - num6; j++) { array[j] = Inlines.HALF32(array[j] + array[num7 + j]); } } } if (dual_stereo != 0) { num21 = quant_band(band_ctx, x, x_ptr, num13, num17 / 2, num5, (num9 != -1) ? array : null, num9, LM, (num12 != 0) ? null : array, num4 * eBands[i] - num6, 32767, lowband_scratch, lowband_scratch_ptr, (int)num21); num20 = quant_band(band_ctx, array2, num10, num13, num17 / 2, num5, (num9 != -1) ? array : null, num7 + num9, LM, (num12 != 0) ? null : array, num7 + (num4 * eBands[i] - num6), 32767, lowband_scratch, lowband_scratch_ptr, (int)num20); } else { num21 = ((array2 == null) ? quant_band(band_ctx, x, x_ptr, num13, num17, num5, (num9 != -1) ? array : null, num9, LM, (num12 != 0) ? null : array, num4 * eBands[i] - num6, 32767, lowband_scratch, lowband_scratch_ptr, (int)(num21 | num20)) : quant_band_stereo(band_ctx, x, x_ptr, array2, num10, num13, num17, num5, (num9 != -1) ? array : null, num9, LM, (num12 != 0) ? null : array, num4 * eBands[i] - num6, lowband_scratch, lowband_scratch_ptr, (int)(num21 | num20))); num20 = num21; } collapse_masks[i * num2] = (byte)(num21 & 0xFFu); collapse_masks[i * num2 + num2 - 1] = (byte)(num20 & 0xFFu); balance += pulses[i] + num14; num = ((num17 > num13 << 3) ? 1 : 0); } seed = band_ctx.seed; } } internal class CeltCommon { private static readonly byte[] inv_table = new byte[128] { 255, 255, 156, 110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 }; private static readonly short[][] gains = new short[3][] { new short[3] { 10048, 7112, 4248 }, new short[3] { 15200, 8784, 0 }, new short[3] { 26208, 3280, 0 } }; private static readonly sbyte[][] tf_select_table = new sbyte[4][] { new sbyte[8] { 0, -1, 0, -1, 0, -1, 0, -1 }, new sbyte[8] { 0, -1, 0, -2, 1, 0, 1, -1 }, new sbyte[8] { 0, -2, 0, -3, 2, 0, 1, -1 }, new sbyte[8] { 0, -2, 0, -3, 3, 0, 1, -1 } }; internal static int compute_vbr(CeltMode mode, AnalysisInfo analysis, int base_target, int LM, int bitrate, int lastCodedBands, int C, int intensity, int constrained_vbr, int stereo_saving, int tot_boost, int tf_estimate, int pitch_change, int maxDepth, OpusFramesize variable_duration, int lfe, int has_surround_mask, int surround_masking, int temporal_vbr) { int nbEBands = mode.nbEBands; short[] eBands = mode.eBands; int num = ((lastCodedBands != 0) ? lastCodedBands : nbEBands); int num2 = eBands[num] << LM; if (C == 2) { num2 += eBands[Inlines.IMIN(intensity, num)] << LM; } int num3 = base_target; if (analysis.enabled && analysis.valid != 0 && (double)analysis.activity < 0.4) { num3 -= (int)((float)(num2 << 3) * (0.4f - analysis.activity)); } if (C == 2) { int num4 = Inlines.IMIN(intensity, num); int num5 = (eBands[num4] << LM) - num4; int a = Inlines.DIV32_16(Inlines.MULT16_16(26214, num5), num2); stereo_saving = Inlines.MIN16(stereo_saving, 256); num3 -= Inlines.MIN32(Inlines.MULT16_32_Q15(a, num3), Inlines.SHR32(Inlines.MULT16_16(stereo_saving - 26, num5 << 3), 8)); } num3 += tot_boost - (16 << LM); int num6 = ((variable_duration == OpusFramesize.OPUS_FRAMESIZE_VARIABLE) ? 328 : 655); num3 += Inlines.SHL32(Inlines.MULT16_32_Q15(tf_estimate - num6, num3), 1); if (analysis.enabled && analysis.valid != 0 && lfe == 0) { float num7 = Inlines.MAX16(0f, analysis.tonality - 0.15f) - 0.09f; int num8 = num3 + (int)((float)(num2 << 3) * 1.2f * num7); if (pitch_change != 0) { num8 += (int)((float)(num2 << 3) * 0.8f); } num3 = num8; } if (has_surround_mask != 0 && lfe == 0) { int b = num3 + Inlines.SHR32(Inlines.MULT16_16(surround_masking, num2 << 3), 10); num3 = Inlines.IMAX(num3 / 4, b); } int num9 = eBands[nbEBands - 2] << LM; int a2 = Inlines.SHR32(Inlines.MULT16_16(C * num9 << 3, maxDepth), 10); a2 = Inlines.IMAX(a2, num3 >> 2); num3 = Inlines.IMIN(num3, a2); if ((has_surround_mask == 0 || lfe != 0) && (constrained_vbr != 0 || bitrate < 64000)) { int a3 = Inlines.MAX16(0, bitrate - 32000); if (constrained_vbr != 0) { a3 = Inlines.MIN16(a3, 21955); } num3 = base_target + Inlines.MULT16_32_Q15(a3, num3 - base_target); } if (has_surround_mask == 0 && tf_estimate < 3277) { int b2 = Inlines.MULT16_16_Q15(3329, Inlines.IMAX(0, Inlines.IMIN(32000, 96000 - bitrate))); int a4 = Inlines.SHR32(Inlines.MULT16_16(temporal_vbr, b2), 10); num3 += Inlines.MULT16_32_Q15(a4, num3); } return Inlines.IMIN(2 * base_target, num3); } internal static int transient_analysis(int[][] input, int len, int C, out int tf_estimate, out int tf_chan) { int num = 0; int num2 = 0; tf_chan = 0; int[] array = new int[len]; int num3 = len / 2; for (int i = 0; i < C; i++) { int num4 = 0; int a = 0; int num5 = 0; for (int j = 0; j < len; j++) { int num6 = Inlines.SHR32(input[i][j], 12); int num7 = Inlines.ADD32(a, num6); a = num5 + num7 - Inlines.SHL32(num6, 1); num5 = num6 - Inlines.SHR32(num7, 1); array[j] = Inlines.EXTRACT16(Inlines.SHR32(num7, 2)); } Arrays.MemSet(array, 0, 12); int num8 = 0; num8 = 14 - Inlines.celt_ilog2(1 + Inlines.celt_maxabs32(array, 0, len)); if (num8 != 0) { for (int j = 0; j < len; j++) { array[j] = Inlines.SHL16(array[j], num8); } } int num9 = 0; a = 0; for (int j = 0; j < num3; j++) { int num10 = Inlines.PSHR32(Inlines.MULT16_16(array[2 * j], array[2 * j]) + Inlines.MULT16_16(array[2 * j + 1], array[2 * j + 1]), 16); num9 += num10; array[j] = a + Inlines.PSHR32(num10 - a, 4); a = array[j]; } a = 0; int a2 = 0; for (int j = num3 - 1; j >= 0; j--) { array[j] = a + Inlines.PSHR32(array[j] - a, 3); a = array[j]; a2 = Inlines.MAX16(a2, a); } num9 = Inlines.MULT16_16(Inlines.celt_sqrt(num9), Inlines.celt_sqrt(Inlines.MULT16_16(a2, num3 >> 1))); int b = Inlines.SHL32(num3, 20) / Inlines.ADD32(1, Inlines.SHR32(num9, 1)); num4 = 0; for (int j = 12; j < num3 - 5; j += 4) { int num11 = Inlines.MAX32(0, Inlines.MIN32(127, Inlines.MULT16_32_Q15(array[j] + 1, b))); num4 += inv_table[num11]; } num4 = 64 * num4 * 4 / (6 * (num3 - 17)); if (num4 > num2) { tf_chan = i; num2 = num4; } } num = ((num2 > 200) ? 1 : 0); int b2 = Inlines.MAX16(0, Inlines.celt_sqrt(27 * num2) - 42); tf_estimate = Inlines.celt_sqrt(Inlines.MAX32(0, Inlines.SHL32(Inlines.MULT16_16(113, Inlines.MIN16(163, b2)), 14) - 37312528)); return num; } internal static int patch_transient_decision(int[][] newE, int[][] oldE, int nbEBands, int start, int end, int C) { int a = 0; int[] array = new int[26]; if (C == 1) { array[start] = oldE[0][start]; for (int i = start + 1; i < end; i++) { array[i] = Inlines.MAX16(array[i - 1] - 1024, oldE[0][i]); } } else { array[start] = Inlines.MAX16(oldE[0][start], oldE[1][start]); for (int i = start + 1; i < end; i++) { array[i] = Inlines.MAX16(array[i - 1] - 1024, Inlines.MAX16(oldE[0][i], oldE[1][i])); } } for (int i = end - 2; i >= start; i--) { array[i] = Inlines.MAX16(array[i], array[i + 1] - 1024); } int num = 0; do { for (int i = Inlines.IMAX(2, start); i < end - 1; i++) { int a2 = Inlines.MAX16(0, newE[num][i]); int b = Inlines.MAX16(0, array[i]); a = Inlines.ADD32(a, Inlines.MAX16(0, Inlines.SUB16(a2, b))); } } while (++num < C); a = Inlines.DIV32(a, C * (end - 1 - Inlines.IMAX(2, start))); return (a > 1024) ? 1 : 0; } internal static void compute_mdcts(CeltMode mode, int shortBlocks, int[][] input, int[][] output, int C, int CC, int LM, int upsample) { int overlap = mode.overlap; int num; int num2; int shift; if (shortBlocks != 0) { num = shortBlocks; num2 = mode.shortMdctSize; shift = mode.maxLM; } else { num = 1; num2 = mode.shortMdctSize << LM; shift = mode.maxLM - LM; } int num3 = 0; do { for (int i = 0; i < num; i++) { MDCT.clt_mdct_forward(mode.mdct, input[num3], i * num2, output[num3], i, mode.window, overlap, shift, num); } } while (++num3 < CC); if (CC == 2 && C == 1) { for (int j = 0; j < num * num2; j++) { output[0][j] = Inlines.ADD32(Inlines.HALF32(output[0][j]), Inlines.HALF32(output[1][j])); } } if (upsample == 1) { return; } num3 = 0; do { int num4 = num * num2 / upsample; for (int j = 0; j < num4; j++) { output[num3][j] *= upsample; } Arrays.MemSetWithOffset(output[num3], 0, num4, num * num2 - num4); } while (++num3 < C); } internal static void celt_preemphasis(short[] pcmp, int pcmp_ptr, int[] inp, int inp_ptr, int N, int CC, int upsample, int[] coef, ref int mem, int clip) { int a = coef[0]; int num = mem; if (coef[1] == 0 && upsample == 1 && clip == 0) { for (int i = 0; i < N; i++) { int num2 = pcmp[pcmp_ptr + CC * i]; inp[inp_ptr + i] = Inlines.SHL32(num2, 12) - num; num = Inlines.SHR32(Inlines.MULT16_16(a, num2), 3); } mem = num; return; } int num3 = N / upsample; if (upsample != 1) { Arrays.MemSetWithOffset(inp, 0, inp_ptr, N); } for (int i = 0; i < num3; i++) { inp[inp_ptr + i * upsample] = pcmp[pcmp_ptr + CC * i]; } for (int i = 0; i < N; i++) { int num2 = inp[inp_ptr + i]; inp[inp_ptr + i] = Inlines.SHL32(num2, 12) - num; num = Inlines.SHR32(Inlines.MULT16_16(a, num2), 3); } mem = num; } internal static void celt_preemphasis(short[] pcmp, int[] inp, int inp_ptr, int N, int CC, int upsample, int[] coef, BoxedValue mem, int clip) { int a = coef[0]; int num = mem.Val; if (coef[1] == 0 && upsample == 1 && clip == 0) { for (int i = 0; i < N; i++) { int num2 = pcmp[CC * i]; inp[inp_ptr + i] = Inlines.SHL32(num2, 12) - num; num = Inlines.SHR32(Inlines.MULT16_16(a, num2), 3); } mem.Val = num; return; } int num3 = N / upsample; if (upsample != 1) { Arrays.MemSetWithOffset(inp, 0, inp_ptr, N); } for (int i = 0; i < num3; i++) { inp[inp_ptr + i * upsample] = pcmp[CC * i]; } for (int i = 0; i < N; i++) { int num2 = inp[inp_ptr + i]; inp[inp_ptr + i] = Inlines.SHL32(num2, 12) - num; num = Inlines.SHR32(Inlines.MULT16_16(a, num2), 3); } mem.Val = num; } internal static int l1_metric(int[] tmp, int N, int LM, int bias) { int num = 0; for (int i = 0; i < N; i++) { num += Inlines.EXTEND32(Inlines.ABS32(tmp[i])); } return Inlines.MAC16_32_Q15(num, LM * bias, num); } internal static int tf_analysis(CeltMode m, int len, int isTransient, int[] tf_res, int lambda, int[][] X, int N0, int LM, out int tf_sum, int tf_estimate, int tf_chan) { int[] array = new int[2]; int num = 0; int bias = Inlines.MULT16_16_Q14(1311, Inlines.MAX16(-4096, 8192 - tf_estimate)); int[] array2 = new int[len]; int[] array3 = new int[m.eBands[len] - m.eBands[len - 1] << LM]; int[] array4 = new int[m.eBands[len] - m.eBands[len - 1] << LM]; int[] array5 = new int[len]; int[] array6 = new int[len]; tf_sum = 0; for (int i = 0; i < len; i++) { int num2 = 0; int num3 = m.eBands[i + 1] - m.eBands[i] << LM; int num4 = ((m.eBands[i + 1] - m.eBands[i] == 1) ? 1 : 0); Array.Copy(X[tf_chan], m.eBands[i] << LM, array3, 0, num3); int num5 = l1_metric(array3, num3, (isTransient != 0) ? LM : 0, bias); int num6 = num5; if (isTransient != 0 && num4 == 0) { Array.Copy(array3, 0, array4, 0, num3); Bands.haar1ZeroOffset(array4, num3 >> LM, 1 << LM); num5 = l1_metric(array4, num3, LM + 1, bias); if (num5 < num6) { num6 = num5; num2 = -1; } } for (int j = 0; j < LM + ((isTransient == 0 && num4 == 0) ? 1 : 0); j++) { int lM = ((isTransient == 0) ? (j + 1) : (LM - j - 1)); Bands.haar1ZeroOffset(array3, num3 >> j, 1 << j); num5 = l1_metric(array3, num3, lM, bias); if (num5 < num6) { num6 = num5; num2 = j + 1; } } if (isTransient != 0) { array2[i] = 2 * num2; } else { array2[i] = -2 * num2; } tf_sum += ((isTransient != 0) ? LM : 0) - array2[i] / 2; if (num4 != 0 && (array2[i] == 0 || array2[i] == -2 * LM)) { array2[i]--; } } num = 0; int num7; int num8; for (int k = 0; k < 2; k++) { num7 = 0; num8 = ((isTransient == 0) ? lambda : 0); for (int i = 1; i < len; i++) { int num9 = Inlines.IMIN(num7, num8 + lambda); int num10 = Inlines.IMIN(num7 + lambda, num8); num7 = num9 + Inlines.abs(array2[i] - 2 * Tables.tf_select_table[LM][4 * isTransient + 2 * k]); num8 = num10 + Inlines.abs(array2[i] - 2 * Tables.tf_select_table[LM][4 * isTransient + 2 * k + 1]); } num7 = Inlines.IMIN(num7, num8); array[k] = num7; } if (array[1] < array[0] && isTransient != 0) { num = 1; } num7 = 0; num8 = ((isTransient == 0) ? lambda : 0); for (int i = 1; i < len; i++) { int num11 = num7; int num12 = num8 + lambda; int num9; if (num11 < num12) { num9 = num11; array5[i] = 0; } else { num9 = num12; array5[i] = 1; } num11 = num7 + lambda; num12 = num8; int num10; if (num11 < num12) { num10 = num11; array6[i] = 0; } else { num10 = num12; array6[i] = 1; } num7 = num9 + Inlines.abs(array2[i] - 2 * Tables.tf_select_table[LM][4 * isTransient + 2 * num]); num8 = num10 + Inlines.abs(array2[i] - 2 * Tables.tf_select_table[LM][4 * isTransient + 2 * num + 1]); } tf_res[len - 1] = ((num7 >= num8) ? 1 : 0); for (int i = len - 2; i >= 0; i--) { if (tf_res[i + 1] == 1) { tf_res[i] = array6[i + 1]; } else { tf_res[i] = array5[i + 1]; } } return num; } internal static void tf_encode(int start, int end, int isTransient, int[] tf_res, int LM, int tf_select, EntropyCoder enc) { uint num = enc.storage * 8; uint num2 = (uint)enc.tell(); int num3 = ((isTransient != 0) ? 2 : 4); int num4 = ((LM > 0 && num2 + num3 + 1 <= num) ? 1 : 0); num -= (uint)num4; int num5; int num6 = (num5 = 0); for (int i = start; i < end; i++) { if (num2 + num3 <= num) { enc.enc_bit_logp(tf_res[i] ^ num6, (uint)num3); num2 = (uint)enc.tell(); num6 = tf_res[i]; num5 |= num6; } else { tf_res[i] = num6; } num3 = ((isTransient != 0) ? 4 : 5); } if (num4 != 0 && Tables.tf_select_table[LM][4 * isTransient + num5] != Tables.tf_select_table[LM][4 * isTransient + 2 + num5]) { enc.enc_bit_logp(tf_select, 1u); } else { tf_select = 0; } for (int i = start; i < end; i++) { tf_res[i] = Tables.tf_select_table[LM][4 * isTransient + 2 * tf_select + tf_res[i]]; } } internal static int alloc_trim_analysis(CeltMode m, int[][] X, int[][] bandLogE, int end, int LM, int C, AnalysisInfo analysis, ref int stereo_saving, int tf_estimate, int intensity, int surround_trim) { int num = 0; int num2 = 1280; if (C == 2) { int num3 = 0; for (int i = 0; i < 8; i++) { int a = Kernels.celt_inner_prod(X[0], m.eBands[i] << LM, X[1], m.eBands[i] << LM, m.eBands[i + 1] - m.eBands[i] << LM); num3 = Inlines.ADD16(num3, Inlines.EXTRACT16(Inlines.SHR32(a, 18))); } num3 = Inlines.MULT16_16_Q15(4096, num3); num3 = Inlines.MIN16(1024, Inlines.ABS32(num3)); int num4 = num3; for (int i = 8; i < intensity; i++) { int a = Kernels.celt_inner_prod(X[0], m.eBands[i] << LM, X[1], m.eBands[i] << LM, m.eBands[i + 1] - m.eBands[i] << LM); num4 = Inlines.MIN16(num4, Inlines.ABS16(Inlines.EXTRACT16(Inlines.SHR32(a, 18)))); } num4 = Inlines.MIN16(1024, Inlines.ABS32(num4)); int num5 = Inlines.celt_log2(1049625 - Inlines.MULT16_16(num3, num3)); int num6 = Inlines.MAX16(Inlines.HALF16(num5), Inlines.celt_log2(1049625 - Inlines.MULT16_16(num4, num4))); num5 = Inlines.PSHR32(num5 - 6144, 2); num6 = Inlines.PSHR32(num6 - 6144, 2); num2 += Inlines.MAX16(-1024, Inlines.MULT16_16_Q15(24576, num5)); stereo_saving = Inlines.MIN16(stereo_saving + 64, -Inlines.HALF16(num6)); } int num7 = 0; do { for (int i = 0; i < end - 1; i++) { num += bandLogE[num7][i] * (2 + 2 * i - end); } } while (++num7 < C); num /= C * (end - 1); num2 -= Inlines.MAX16(Inlines.NEG16((short)512), Inlines.MIN16(512, Inlines.SHR16(num + 1024, 2) / 6)); num2 -= Inlines.SHR16(surround_trim, 2); num2 -= 2 * Inlines.SHR16(tf_estimate, 6); if (analysis.enabled && analysis.valid != 0) { num2 -= Inlines.MAX16(-512, Inlines.MIN16(512, (int)(512f * (analysis.tonality_slope + 0.05f)))); } int b = Inlines.PSHR32(num2, 8); return Inlines.IMAX(0, Inlines.IMIN(10, b)); } internal static int stereo_analysis(CeltMode m, int[][] X, int LM) { int num = 1; int num2 = 1; for (int i = 0; i < 13; i++) { for (int j = m.eBands[i] << LM; j < m.eBands[i + 1] << LM; j++) { int num3 = Inlines.EXTEND32(X[0][j]); int num4 = Inlines.EXTEND32(X[1][j]); int x = Inlines.ADD32(num3, num4); int x2 = Inlines.SUB32(num3, num4); num = Inlines.ADD32(num, Inlines.ADD32(Inlines.ABS32(num3), Inlines.ABS32(num4))); num2 = Inlines.ADD32(num2, Inlines.ADD32(Inlines.ABS32(x), Inlines.ABS32(x2))); } } num2 = Inlines.MULT16_32_Q15((short)23170, num2); int num5 = 13; if (LM <= 1) { num5 -= 8; } return (Inlines.MULT16_32_Q15((m.eBands[13] << LM + 1) + num5, num2) > Inlines.MULT16_32_Q15(m.eBands[13] << LM + 1, num)) ? 1 : 0; } internal static int median_of_5(int[] x, int x_ptr) { int num = x[x_ptr + 2]; int num3; int num2; if (x[x_ptr] > x[x_ptr + 1]) { num2 = x[x_ptr + 1]; num3 = x[x_ptr]; } else { num2 = x[x_ptr]; num3 = x[x_ptr + 1]; } int num4; int num5; if (x[x_ptr + 3] > x[x_ptr + 4]) { num4 = x[x_ptr + 4]; num5 = x[x_ptr + 3]; } else { num4 = x[x_ptr + 3]; num5 = x[x_ptr + 4]; } if (num2 > num4) { int num6 = num4; num4 = num2; num2 = num6; num6 = num5; num5 = num3; num3 = num6; } if (num > num3) { if (num3 < num4) { return Inlines.MIN16(num, num4); } return Inlines.MIN16(num5, num3); } if (num < num4) { return Inlines.MIN16(num3, num4); } return Inlines.MIN16(num, num5); } internal static int median_of_3(int[] x, int x_ptr) { int num; int num2; if (x[x_ptr] > x[x_ptr + 1]) { num = x[x_ptr + 1]; num2 = x[x_ptr]; } else { num = x[x_ptr]; num2 = x[x_ptr + 1]; } int num3 = x[x_ptr + 2]; if (num2 < num3) { return num2; } if (num < num3) { return num3; } return num; } internal static int dynalloc_analysis(int[][] bandLogE, int[][] bandLogE2, int nbEBands, int start, int end, int C, int[] offsets, int lsb_depth, short[] logN, int isTransient, int vbr, int constrained_vbr, short[] eBands, int LM, int effectiveBytes, out int tot_boost_, int lfe, int[] surround_dynalloc) { int num = 0; int[][] array = Arrays.InitTwoDimensionalArray(2, nbEBands); int[] array2 = new int[C * nbEBands]; Arrays.MemSet(offsets, 0, nbEBands); int num2 = -32666; for (int i = 0; i < end; i++) { array2[i] = Inlines.MULT16_16((short)64, logN[i]) + 512 + Inlines.SHL16(9 - lsb_depth, 10) - Inlines.SHL16(Tables.eMeans[i], 6) + Inlines.MULT16_16(6, (i + 5) * (i + 5)); } int num3 = 0; do { for (int i = 0; i < end; i++) { num2 = Inlines.MAX16(num2, bandLogE[num3][i] - array2[i]); } } while (++num3 < C); if (effectiveBytes > 50 && LM >= 1 && lfe == 0) { int num4 = 0; num3 = 0; do { int[] array3 = array[num3]; array3[0] = bandLogE2[num3][0]; for (int i = 1; i < end; i++) { if (bandLogE2[num3][i] > bandLogE2[num3][i - 1] + 512) { num4 = i; } array3[i] = Inlines.MIN16(array3[i - 1] + 1536, bandLogE2[num3][i]); } for (int i = num4 - 1; i >= 0; i--) { array3[i] = Inlines.MIN16(array3[i], Inlines.MIN16(array3[i + 1] + 2048, bandLogE2[num3][i])); } int num5 = 1024; for (int i = 2; i < end - 2; i++) { array3[i] = Inlines.MAX16(array3[i], median_of_5(bandLogE2[num3], i - 2) - num5); } int b = median_of_3(bandLogE2[num3], 0) - num5; array3[0] = Inlines.MAX16(array3[0], b); array3[1] = Inlines.MAX16(array3[1], b); b = median_of_3(bandLogE2[num3], end - 3) - num5; array3[end - 2] = Inlines.MAX16(array3[end - 2], b); array3[end - 1] = Inlines.MAX16(array3[end - 1], b); for (int i = 0; i < end; i++) { array3[i] = Inlines.MAX16(array3[i], array2[i]); } } while (++num3 < C); if (C == 2) { for (int i = start; i < end; i++) { array[1][i] = Inlines.MAX16(array[1][i], array[0][i] - 4096); array[0][i] = Inlines.MAX16(array[0][i], array[1][i] - 4096); array[0][i] = Inlines.HALF16(Inlines.MAX16(0, bandLogE[0][i] - array[0][i]) + Inlines.MAX16(0, bandLogE[1][i] - array[1][i])); } } else { for (int i = start; i < end; i++) { array[0][i] = Inlines.MAX16(0, bandLogE[0][i] - array[0][i]); } } for (int i = start; i < end; i++) { array[0][i] = Inlines.MAX16(array[0][i], surround_dynalloc[i]); } if ((vbr == 0 || constrained_vbr != 0) && isTransient == 0) { for (int i = start; i < end; i++) { array[0][i] = Inlines.HALF16(array[0][i]); } } for (int i = start; i < end; i++) { if (i < 8) { array[0][i] *= 2; } if (i >= 12) { array[0][i] = Inlines.HALF16(array[0][i]); } array[0][i] = Inlines.MIN16(array[0][i], 4096); int num6 = C * (eBands[i + 1] - eBands[i]) << LM; int num7; int num8; if (num6 < 6) { num7 = Inlines.SHR32(array[0][i], 10); num8 = num7 * num6 << 3; } else if (num6 > 48) { num7 = Inlines.SHR32(array[0][i] * 8, 10); num8 = (num7 * num6 << 3) / 8; } else { num7 = Inlines.SHR32(array[0][i] * num6 / 6, 10); num8 = num7 * 6 << 3; } if ((vbr == 0 || (constrained_vbr != 0 && isTransient == 0)) && num + num8 >> 3 >> 3 > effectiveBytes / 4) { int num9 = effectiveBytes / 4 << 3 << 3; offsets[i] = num9 - num; num = num9; break; } offsets[i] = num7; num += num8; } } tot_boost_ = num; return num2; } internal static void deemphasis(int[][] input, int[] input_ptrs, short[] pcm, int pcm_ptr, int N, int C, int downsample, int[] coef, int[] mem, int accum) { int num = 0; if (downsample == 1 && C == 2 && accum == 0) { deemphasis_stereo_simple(input, input_ptrs, pcm, pcm_ptr, N, coef[0], mem); return; } int[] array = new int[N]; int a = coef[0]; int num2 = N / downsample; int num3 = 0; do { int num4 = mem[num3]; int[] array2 = input[num3]; int num5 = input_ptrs[num3]; int num6 = pcm_ptr + num3; if (downsample > 1) { for (int i = 0; i < N; i++) { int num7 = array2[num5 + i] + num4; num4 = Inlines.MULT16_32_Q15(a, num7); array[i] = num7; } num = 1; } else if (accum != 0) { for (int i = 0; i < N; i++) { int num7 = array2[num5 + i] + num4; num4 = Inlines.MULT16_32_Q15(a, num7); pcm[num6 + i * C] = Inlines.SAT16(Inlines.ADD32(pcm[num6 + i * C], Inlines.SIG2WORD16(num7))); } } else { for (int i = 0; i < N; i++) { int num7 = array2[num5 + i] + num4; if (array2[num5 + i] > 0 && num4 > 0 && num7 < 0) { num7 = int.MaxValue; num4 = int.MaxValue; } else { num4 = Inlines.MULT16_32_Q15(a, num7); } pcm[num6 + i * C] = Inlines.SIG2WORD16(num7); } } mem[num3] = num4; if (num != 0) { for (int i = 0; i < num2; i++) { pcm[num6 + i * C] = Inlines.SIG2WORD16(array[i * downsample]); } } } while (++num3 < C); } internal static void deemphasis_stereo_simple(int[][] input, int[] input_ptrs, short[] pcm, int pcm_ptr, int N, int coef0, int[] mem) { int[] array = input[0]; int[] array2 = input[1]; int num = input_ptrs[0]; int num2 = input_ptrs[1]; int num3 = mem[0]; int num4 = mem[1]; for (int i = 0; i < N; i++) { int num5 = array[num + i] + num3; int num6 = array2[num2 + i] + num4; num3 = Inlines.MULT16_32_Q15(coef0, num5); num4 = Inlines.MULT16_32_Q15(coef0, num6); pcm[pcm_ptr + 2 * i] = Inlines.SIG2WORD16(num5); pcm[pcm_ptr + 2 * i + 1] = Inlines.SIG2WORD16(num6); } mem[0] = num3; mem[1] = num4; } internal static void celt_synthesis(CeltMode mode, int[][] X, int[][] out_syn, int[] out_syn_ptrs, int[] oldBandE, int start, int effEnd, int C, int CC, int isTransient, int LM, int downsample, int silence) { int overlap = mode.overlap; int nbEBands = mode.nbEBands; int num = mode.shortMdctSize << LM; int[] array = new int[num]; int num2 = 1 << LM; int num3; int num4; int shift; if (isTransient != 0) { num3 = num2; num4 = mode.shortMdctSize; shift = mode.maxLM; } else { num3 = 1; num4 = mode.shortMdctSize << LM; shift = mode.maxLM - LM; } if (CC == 2 && C == 1) { Bands.denormalise_bands(mode, X[0], array, 0, oldBandE, 0, start, effEnd, num2, downsample, silence); int num5 = out_syn_ptrs[1] + overlap / 2; Array.Copy(array, 0, out_syn[1], num5, num); for (int i = 0; i < num3; i++) { MDCT.clt_mdct_backward(mode.mdct, out_syn[1], num5 + i, out_syn[0], out_syn_ptrs[0] + num4 * i, mode.window, overlap, shift, num3); } for (int i = 0; i < num3; i++) { MDCT.clt_mdct_backward(mode.mdct, array, i, out_syn[1], out_syn_ptrs[1] + num4 * i, mode.window, overlap, shift, num3); } return; } if (CC == 1 && C == 2) { int num5 = out_syn_ptrs[0] + overlap / 2; Bands.denormalise_bands(mode, X[0], array, 0, oldBandE, 0, start, effEnd, num2, downsample, silence); Bands.denormalise_bands(mode, X[1], out_syn[0], num5, oldBandE, nbEBands, start, effEnd, num2, downsample, silence); for (int j = 0; j < num; j++) { array[j] = Inlines.HALF32(Inlines.ADD32(array[j], out_syn[0][num5 + j])); } for (int i = 0; i < num3; i++) { MDCT.clt_mdct_backward(mode.mdct, array, i, out_syn[0], out_syn_ptrs[0] + num4 * i, mode.window, overlap, shift, num3); } return; } int num6 = 0; do { Bands.denormalise_bands(mode, X[num6], array, 0, oldBandE, num6 * nbEBands, start, effEnd, num2, downsample, silence); for (int i = 0; i < num3; i++) { MDCT.clt_mdct_backward(mode.mdct, array, i, out_syn[num6], out_syn_ptrs[num6] + num4 * i, mode.window, overlap, shift, num3); } } while (++num6 < CC); } internal static void tf_decode(int start, int end, int isTransient, int[] tf_res, int LM, EntropyCoder dec) { uint num = dec.storage * 8; uint num2 = (uint)dec.tell(); int num3 = ((isTransient != 0) ? 2 : 4); int num4 = ((LM > 0 && num2 + num3 + 1 <= num) ? 1 : 0); num -= (uint)num4; int num5; int num6 = (num5 = 0); for (int i = start; i < end; i++) { if (num2 + num3 <= num) { num5 ^= dec.dec_bit_logp((uint)num3); num2 = (uint)dec.tell(); num6 |= num5; } tf_res[i] = num5; num3 = ((isTransient != 0) ? 4 : 5); } int num7 = 0; if (num4 != 0 && Tables.tf_select_table[LM][4 * isTransient + num6] != Tables.tf_select_table[LM][4 * isTransient + 2 + num6]) { num7 = dec.dec_bit_logp(1u); } for (int i = start; i < end; i++) { tf_res[i] = Tables.tf_select_table[LM][4 * isTransient + 2 * num7 + tf_res[i]]; } } internal static int celt_plc_pitch_search(int[][] decode_mem, int C) { int[] array = new int[1024]; Pitch.pitch_downsample(decode_mem, array, 2048, C); Pitch.pitch_search(array, 360, array, 1328, 620, out var pitch); return 720 - pitch; } internal static int resampling_factor(int rate) { return rate switch { 48000 => 1, 24000 => 2, 16000 => 3, 12000 => 4, 8000 => 6, _ => 0, }; } internal static void comb_filter_const(int[] y, int y_ptr, int[] x, int x_ptr, int T, int N, int g10, int g11, int g12) { int num = x_ptr - T; int b = x[num - 2]; int num2 = x[num - 1]; int num3 = x[num]; int num4 = x[num + 1]; for (int i = 0; i < N; i++) { int num5 = x[num + i + 2]; y[y_ptr + i] = x[x_ptr + i] + Inlines.MULT16_32_Q15(g10, num3) + Inlines.MULT16_32_Q15(g11, Inlines.ADD32(num4, num2)) + Inlines.MULT16_32_Q15(g12, Inlines.ADD32(num5, b)); b = num2; num2 = num3; num3 = num4; num4 = num5; } } internal static void comb_filter(int[] y, int y_ptr, int[] x, int x_ptr, int T0, int T1, int N, int g0, int g1, int tapset0, int tapset1, int[] window, int overlap) { if (g0 == 0 && g1 == 0) { if (x_ptr == y_ptr) { } return; } int b = Inlines.MULT16_16_P15(g0, gains[tapset0][0]); int b2 = Inlines.MULT16_16_P15(g0, gains[tapset0][1]); int b3 = Inlines.MULT16_16_P15(g0, gains[tapset0][2]); int num = Inlines.MULT16_16_P15(g1, gains[tapset1][0]); int num2 = Inlines.MULT16_16_P15(g1, gains[tapset1][1]); int num3 = Inlines.MULT16_16_P15(g1, gains[tapset1][2]); int num4 = x[x_ptr - T1 + 1]; int num5 = x[x_ptr - T1]; int num6 = x[x_ptr - T1 - 1]; int b4 = x[x_ptr - T1 - 2]; if (g0 == g1 && T0 == T1 && tapset0 == tapset1) { overlap = 0; } int i; for (i = 0; i < overlap; i++) { int num7 = x[x_ptr + i - T1 + 2]; int num8 = Inlines.MULT16_16_Q15(window[i], window[i]); y[y_ptr + i] = x[x_ptr + i] + Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15((short)(32767 - num8), b), x[x_ptr + i - T0]) + Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15((short)(32767 - num8), b2), Inlines.ADD32(x[x_ptr + i - T0 + 1], x[x_ptr + i - T0 - 1])) + Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15((short)(32767 - num8), b3), Inlines.ADD32(x[x_ptr + i - T0 + 2], x[x_ptr + i - T0 - 2])) + Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15(num8, num), num5) + Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15(num8, num2), Inlines.ADD32(num4, num6)) + Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15(num8, num3), Inlines.ADD32(num7, b4)); b4 = num6; num6 = num5; num5 = num4; num4 = num7; } if (g1 == 0) { if (x_ptr == y_ptr) { } } else { comb_filter_const(y, y_ptr + i, x, x_ptr + i, T1, N - i, num, num2, num3); } } internal static void init_caps(CeltMode m, int[] cap, int LM, int C) { for (int i = 0; i < m.nbEBands; i++) { int num = m.eBands[i + 1] - m.eBands[i] << LM; cap[i] = (m.cache.caps[m.nbEBands * (2 * LM + C - 1) + i] + 64) * C * num >> 2; } } } internal static class CeltConstants { public const int Q15ONE = 32767; public const float CELT_SIG_SCALE = 32768f; public const int SIG_SHIFT = 12; public const int NORM_SCALING = 16384; public const int DB_SHIFT = 10; public const int EPSILON = 1; public const int VERY_SMALL = 0; public const short VERY_LARGE16 = short.MaxValue; public const short Q15_ONE = short.MaxValue; public const int COMBFILTER_MAXPERIOD = 1024; public const int COMBFILTER_MINPERIOD = 15; public const int DECODE_BUFFER_SIZE = 2048; public const int BITALLOC_SIZE = 11; public const int MAX_PERIOD = 1024; public const int TOTAL_MODES = 1; public const int MAX_PSEUDO = 40; public const int LOG_MAX_PSEUDO = 6; public const int CELT_MAX_PULSES = 128; public const int MAX_FINE_BITS = 8; public const int FINE_OFFSET = 21; public const int QTHETA_OFFSET = 4; public const int QTHETA_OFFSET_TWOPHASE = 16; public const int PLC_PITCH_LAG_MAX = 720; public const int PLC_PITCH_LAG_MIN = 100; public const int LPC_ORDER = 24; } internal static class CeltLPC { internal static void celt_lpc(int[] _lpc, int[] ac, int p) { int num = ac[0]; int[] array = new int[p]; if (ac[0] != 0) { for (int i = 0; i < p; i++) { int num2 = 0; for (int j = 0; j < i; j++) { num2 += Inlines.MULT32_32_Q31(array[j], ac[i - j]); } num2 += Inlines.SHR32(ac[i + 1], 3); int num3 = -Inlines.frac_div32(Inlines.SHL32(num2, 3), num); array[i] = Inlines.SHR32(num3, 3); for (int j = 0; j < i + 1 >> 1; j++) { int num4 = array[j]; int num5 = array[i - 1 - j]; array[j] = num4 + Inlines.MULT32_32_Q31(num3, num5); array[i - 1 - j] = num5 + Inlines.MULT32_32_Q31(num3, num4); } num -= Inlines.MULT32_32_Q31(Inlines.MULT32_32_Q31(num3, num3), num); if (num < Inlines.SHR32(ac[0], 10)) { break; } } } for (int i = 0; i < p; i++) { _lpc[i] = Inlines.ROUND16(array[i], 16); } } internal static void celt_iir(int[] _x, int _x_ptr, int[] den, int[] _y, int _y_ptr, int N, int ord, int[] mem) { int[] array = new int[ord]; int[] array2 = new int[N + ord]; int i; for (i = 0; i < ord; i++) { array[i] = den[ord - i - 1]; } for (i = 0; i < ord; i++) { array2[i] = -mem[ord - i - 1]; } for (; i < N + ord; i++) { array2[i] = 0; } for (i = 0; i < N - 3; i += 4) { int sum = _x[_x_ptr + i]; int sum2 = _x[_x_ptr + i + 1]; int sum3 = _x[_x_ptr + i + 2]; int sum4 = _x[_x_ptr + i + 3]; Kernels.xcorr_kernel(array, array2, i, ref sum, ref sum2, ref sum3, ref sum4, ord); array2[i + ord] = -Inlines.ROUND16(sum, 12); _y[_y_ptr + i] = sum; sum2 = Inlines.MAC16_16(sum2, array2[i + ord], den[0]); array2[i + ord + 1] = -Inlines.ROUND16(sum2, 12); _y[_y_ptr + i + 1] = sum2; sum3 = Inlines.MAC16_16(sum3, array2[i + ord + 1], den[0]); sum3 = Inlines.MAC16_16(sum3, array2[i + ord], den[1]); array2[i + ord + 2] = -Inlines.ROUND16(sum3, 12); _y[_y_ptr + i + 2] = sum3; sum4 = Inlines.MAC16_16(sum4, array2[i + ord + 2], den[0]); sum4 = Inlines.MAC16_16(sum4, array2[i + ord + 1], den[1]); sum4 = Inlines.MAC16_16(sum4, array2[i + ord], den[2]); array2[i + ord + 3] = -Inlines.ROUND16(sum4, 12); _y[_y_ptr + i + 3] = sum4; } for (; i < N; i++) { int num = _x[_x_ptr + i]; for (int j = 0; j < ord; j++) { num -= Inlines.MULT16_16(array[j], array2[i + j]); } array2[i + ord] = Inlines.ROUND16(num, 12); _y[_y_ptr + i] = num; } for (i = 0; i < ord; i++) { mem[i] = _y[_y_ptr + N - i - 1]; } } } internal static class CeltPitchXCorr { internal static int pitch_xcorr(int[] _x, int[] _y, int[] xcorr, int len, int max_pitch) { int num = 1; int i; for (i = 0; i < max_pitch - 3; i += 4) { int sum = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; Kernels.xcorr_kernel(_x, _y, i, ref sum, ref sum2, ref sum3, ref sum4, len); xcorr[i] = sum; xcorr[i + 1] = sum2; xcorr[i + 2] = sum3; xcorr[i + 3] = sum4; sum = Inlines.MAX32(sum, sum2); sum3 = Inlines.MAX32(sum3, sum4); sum = Inlines.MAX32(sum, sum3); num = Inlines.MAX32(num, sum); } for (; i < max_pitch; i++) { num = Inlines.MAX32(num, xcorr[i] = Kernels.celt_inner_prod(_x, 0, _y, i, len)); } return num; } internal static int pitch_xcorr(short[] _x, int _x_ptr, short[] _y, int _y_ptr, int[] xcorr, int len, int max_pitch) { int num = 1; int i; for (i = 0; i < max_pitch - 3; i += 4) { int sum = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; Kernels.xcorr_kernel(_x, _x_ptr, _y, _y_ptr + i, ref sum, ref sum2, ref sum3, ref sum4, len); xcorr[i] = sum; xcorr[i + 1] = sum2; xcorr[i + 2] = sum3; xcorr[i + 3] = sum4; sum = Inlines.MAX32(sum, sum2); sum3 = Inlines.MAX32(sum3, sum4); sum = Inlines.MAX32(sum, sum3); num = Inlines.MAX32(num, sum); } for (; i < max_pitch; i++) { num = Inlines.MAX32(num, xcorr[i] = Kernels.celt_inner_prod(_x, _x_ptr, _y, _y_ptr + i, len)); } return num; } internal static int pitch_xcorr(short[] _x, short[] _y, int[] xcorr, int len, int max_pitch) { int num = 1; int i; for (i = 0; i < max_pitch - 3; i += 4) { int sum = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; Kernels.xcorr_kernel(_x, 0, _y, i, ref sum, ref sum2, ref sum3, ref sum4, len); xcorr[i] = sum; xcorr[i + 1] = sum2; xcorr[i + 2] = sum3; xcorr[i + 3] = sum4; sum = Inlines.MAX32(sum, sum2); sum3 = Inlines.MAX32(sum3, sum4); sum = Inlines.MAX32(sum, sum3); num = Inlines.MAX32(num, sum); } for (; i < max_pitch; i++) { num = Inlines.MAX32(num, xcorr[i] = Kernels.celt_inner_prod(_x, _y, i, len)); } return num; } } internal static class CWRS { internal static readonly uint[] CELT_PVQ_U_ROW = new uint[15] { 0u, 176u, 351u, 525u, 698u, 870u, 1041u, 1131u, 1178u, 1207u, 1226u, 1240u, 1248u, 1254u, 1257u }; private static uint CELT_PVQ_U(int _n, int _k) { return Tables.CELT_PVQ_U_DATA[CELT_PVQ_U_ROW[Inlines.IMIN(_n, _k)] + Inlines.IMAX(_n, _k)]; } private static uint CELT_PVQ_V(int _n, int _k) { return CELT_PVQ_U(_n, _k) + CELT_PVQ_U(_n, _k + 1); } internal static uint icwrs(int _n, int[] _y) { int num = _n - 1; uint num2 = ((_y[num] < 0) ? 1u : 0u); int num3 = Inlines.abs(_y[num]); do { num--; num2 += CELT_PVQ_U(_n - num, num3); num3 += Inlines.abs(_y[num]); if (_y[num] < 0) { num2 += CELT_PVQ_U(_n - num, num3 + 1); } } while (num > 0); return num2; } internal static void encode_pulses(int[] _y, int _n, int _k, EntropyCoder _enc) { _enc.enc_uint(icwrs(_n, _y), CELT_PVQ_V(_n, _k)); } internal static int cwrsi(int _n, int _k, uint _i, int[] _y) { int c = 0; int num = 0; uint num3; int num5; int num4; short num7; while (_n > 2) { if (_k >= _n) { uint num2 = CELT_PVQ_U_ROW[_n]; num3 = Tables.CELT_PVQ_U_DATA[num2 + _k + 1]; num4 = -((_i >= num3) ? 1 : 0); _i -= num3 & (uint)num4; num5 = _k; uint num6 = Tables.CELT_PVQ_U_DATA[num2 + _n]; if (num6 > _i) { _k = _n; do { num3 = Tables.CELT_PVQ_U_DATA[CELT_PVQ_U_ROW[--_k] + _n]; } while (num3 > _i); } else { for (num3 = Tables.CELT_PVQ_U_DATA[num2 + _k]; num3 > _i; num3 = Tables.CELT_PVQ_U_DATA[num2 + _k]) { _k--; } } _i -= num3; num7 = (short)((num5 - _k + num4) ^ num4); _y[num++] = num7; c = Inlines.MAC16_16(c, num7, num7); } else { num3 = Tables.CELT_PVQ_U_DATA[CELT_PVQ_U_ROW[_k] + _n]; uint num6 = Tables.CELT_PVQ_U_DATA[CELT_PVQ_U_ROW[_k + 1] + _n]; if (num3 <= _i && _i < num6) { _i -= num3; _y[num++] = 0; } else { num4 = -((_i >= num6) ? 1 : 0); _i -= num6 & (uint)num4; num5 = _k; do { num3 = Tables.CELT_PVQ_U_DATA[CELT_PVQ_U_ROW[--_k] + _n]; } while (num3 > _i); _i -= num3; num7 = (short)((num5 - _k + num4) ^ num4); _y[num++] = num7; c = Inlines.MAC16_16(c, num7, num7); } } _n--; } num3 = (uint)(2 * _k + 1); num4 = -((_i >= num3) ? 1 : 0); _i -= num3 & (uint)num4; num5 = _k; _k = (int)(_i + 1 >> 1); if (_k != 0) { _i -= (uint)(2 * _k - 1); } num7 = (short)((num5 - _k + num4) ^ num4); _y[num++] = num7; c = Inlines.MAC16_16(c, num7, num7); num4 = (int)(0 - _i); num7 = (short)(_y[num] = (short)((_k + num4) ^ num4)); return Inlines.MAC16_16(c, num7, num7); } internal static int decode_pulses(int[] _y, int _n, int _k, EntropyCoder _dec) { return cwrsi(_n, _k, _dec.dec_uint(CELT_PVQ_V(_n, _k)), _y); } } internal static class Kernels { internal static void celt_fir(short[] x, int x_ptr, short[] num, short[] y, int y_ptr, int N, int ord, short[] mem) { short[] array = new short[ord]; short[] array2 = new short[N + ord]; int i; for (i = 0; i < ord; i++) { array[i] = num[ord - i - 1]; } for (i = 0; i < ord; i++) { array2[i] = mem[ord - i - 1]; } for (i = 0; i < N; i++) { array2[i + ord] = x[x_ptr + i]; } for (i = 0; i < ord; i++) { mem[i] = x[x_ptr + N - i - 1]; } for (i = 0; i < N - 3; i += 4) { int sum = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; xcorr_kernel(array, 0, array2, i, ref sum, ref sum2, ref sum3, ref sum4, ord); y[y_ptr + i] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i]), Inlines.PSHR32(sum, 12))); y[y_ptr + i + 1] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i + 1]), Inlines.PSHR32(sum2, 12))); y[y_ptr + i + 2] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i + 2]), Inlines.PSHR32(sum3, 12))); y[y_ptr + i + 3] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i + 3]), Inlines.PSHR32(sum4, 12))); } for (; i < N; i++) { int num2 = 0; for (int j = 0; j < ord; j++) { num2 = Inlines.MAC16_16(num2, array[j], array2[i + j]); } y[y_ptr + i] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i]), Inlines.PSHR32(num2, 12))); } } internal static void celt_fir(int[] x, int x_ptr, int[] num, int num_ptr, int[] y, int y_ptr, int N, int ord, int[] mem) { int[] array = new int[ord]; int[] array2 = new int[N + ord]; int i; for (i = 0; i < ord; i++) { array[i] = num[num_ptr + ord - i - 1]; } for (i = 0; i < ord; i++) { array2[i] = mem[ord - i - 1]; } for (i = 0; i < N; i++) { array2[i + ord] = x[x_ptr + i]; } for (i = 0; i < ord; i++) { mem[i] = x[x_ptr + N - i - 1]; } for (i = 0; i < N - 3; i += 4) { int sum = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; xcorr_kernel(array, array2, i, ref sum, ref sum2, ref sum3, ref sum4, ord); y[y_ptr + i] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i]), Inlines.PSHR32(sum, 12))); y[y_ptr + i + 1] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i + 1]), Inlines.PSHR32(sum2, 12))); y[y_ptr + i + 2] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i + 2]), Inlines.PSHR32(sum3, 12))); y[y_ptr + i + 3] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i + 3]), Inlines.PSHR32(sum4, 12))); } for (; i < N; i++) { int num2 = 0; for (int j = 0; j < ord; j++) { num2 = Inlines.MAC16_16(num2, array[j], array2[i + j]); } y[y_ptr + i] = Inlines.SATURATE16(Inlines.ADD32(Inlines.EXTEND32(x[x_ptr + i]), Inlines.PSHR32(num2, 12))); } } internal static void xcorr_kernel(short[] x, int x_ptr, short[] y, int y_ptr, ref int sum0, ref int sum1, ref int sum2, ref int sum3, int len) { short b = 0; short b2 = y[y_ptr++]; short b3 = y[y_ptr++]; short b4 = y[y_ptr++]; int i; for (i = 0; i < len - 3; i += 4) { short a = x[x_ptr++]; b = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b2); sum1 = Inlines.MAC16_16(sum1, a, b3); sum2 = Inlines.MAC16_16(sum2, a, b4); sum3 = Inlines.MAC16_16(sum3, a, b); a = x[x_ptr++]; b2 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b3); sum1 = Inlines.MAC16_16(sum1, a, b4); sum2 = Inlines.MAC16_16(sum2, a, b); sum3 = Inlines.MAC16_16(sum3, a, b2); a = x[x_ptr++]; b3 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b4); sum1 = Inlines.MAC16_16(sum1, a, b); sum2 = Inlines.MAC16_16(sum2, a, b2); sum3 = Inlines.MAC16_16(sum3, a, b3); a = x[x_ptr++]; b4 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b); sum1 = Inlines.MAC16_16(sum1, a, b2); sum2 = Inlines.MAC16_16(sum2, a, b3); sum3 = Inlines.MAC16_16(sum3, a, b4); } if (i++ < len) { short a = x[x_ptr++]; b = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b2); sum1 = Inlines.MAC16_16(sum1, a, b3); sum2 = Inlines.MAC16_16(sum2, a, b4); sum3 = Inlines.MAC16_16(sum3, a, b); } if (i++ < len) { short a = x[x_ptr++]; b2 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b3); sum1 = Inlines.MAC16_16(sum1, a, b4); sum2 = Inlines.MAC16_16(sum2, a, b); sum3 = Inlines.MAC16_16(sum3, a, b2); } if (i < len) { short a = x[x_ptr++]; b3 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b4); sum1 = Inlines.MAC16_16(sum1, a, b); sum2 = Inlines.MAC16_16(sum2, a, b2); sum3 = Inlines.MAC16_16(sum3, a, b3); } } internal static void xcorr_kernel(int[] x, int[] y, int y_ptr, ref int sum0, ref int sum1, ref int sum2, ref int sum3, int len) { int num = 0; int b = 0; int b2 = y[y_ptr++]; int b3 = y[y_ptr++]; int b4 = y[y_ptr++]; int i; for (i = 0; i < len - 3; i += 4) { int a = x[num++]; b = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b2); sum1 = Inlines.MAC16_16(sum1, a, b3); sum2 = Inlines.MAC16_16(sum2, a, b4); sum3 = Inlines.MAC16_16(sum3, a, b); a = x[num++]; b2 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b3); sum1 = Inlines.MAC16_16(sum1, a, b4); sum2 = Inlines.MAC16_16(sum2, a, b); sum3 = Inlines.MAC16_16(sum3, a, b2); a = x[num++]; b3 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b4); sum1 = Inlines.MAC16_16(sum1, a, b); sum2 = Inlines.MAC16_16(sum2, a, b2); sum3 = Inlines.MAC16_16(sum3, a, b3); a = x[num++]; b4 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b); sum1 = Inlines.MAC16_16(sum1, a, b2); sum2 = Inlines.MAC16_16(sum2, a, b3); sum3 = Inlines.MAC16_16(sum3, a, b4); } if (i++ < len) { int a = x[num++]; b = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b2); sum1 = Inlines.MAC16_16(sum1, a, b3); sum2 = Inlines.MAC16_16(sum2, a, b4); sum3 = Inlines.MAC16_16(sum3, a, b); } if (i++ < len) { int a = x[num++]; b2 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b3); sum1 = Inlines.MAC16_16(sum1, a, b4); sum2 = Inlines.MAC16_16(sum2, a, b); sum3 = Inlines.MAC16_16(sum3, a, b2); } if (i < len) { int a = x[num++]; b3 = y[y_ptr++]; sum0 = Inlines.MAC16_16(sum0, a, b4); sum1 = Inlines.MAC16_16(sum1, a, b); sum2 = Inlines.MAC16_16(sum2, a, b2); sum3 = Inlines.MAC16_16(sum3, a, b3); } } internal static int celt_inner_prod(short[] x, int x_ptr, short[] y, int y_ptr, int N) { int num = 0; for (int i = 0; i < N; i++) { num = Inlines.MAC16_16(num, x[x_ptr + i], y[y_ptr + i]); } return num; } internal static int celt_inner_prod(short[] x, short[] y, int y_ptr, int N) { int num = 0; for (int i = 0; i < N; i++) { num = Inlines.MAC16_16(num, x[i], y[y_ptr + i]); } return num; } internal static int celt_inner_prod(int[] x, int x_ptr, int[] y, int y_ptr, int N) { int num = 0; for (int i = 0; i < N; i++) { num = Inlines.MAC16_16(num, x[x_ptr + i], y[y_ptr + i]); } return num; } internal static void dual_inner_prod(int[] x, int x_ptr, int[] y01, int y01_ptr, int[] y02, int y02_ptr, int N, out int xy1, out int xy2) { int num = 0; int num2 = 0; for (int i = 0; i < N; i++) { num = Inlines.MAC16_16(num, x[x_ptr + i], y01[y01_ptr + i]); num2 = Inlines.MAC16_16(num2, x[x_ptr + i], y02[y02_ptr + i]); } xy1 = num; xy2 = num2; } } internal static class KissFFT { internal const int MAXFACTORS = 8; private static ThreadLocal fstrides = new ThreadLocal(() => new int[8]); internal static int S_MUL(int a, int b) { return Inlines.MULT16_32_Q15(b, a); } internal static int S_MUL(int a, short b) { return Inlines.MULT16_32_Q15(b, a); } internal static int HALF_OF(int x) { return x >> 1; } internal static void kf_bfly2(int[] Fout, int fout_ptr, int m, int N) { short b = 23170; for (int i = 0; i < N; i++) { int num = fout_ptr + 8; int num2 = Fout[num]; int num3 = Fout[num + 1]; Fout[num] = Fout[fout_ptr] - num2; Fout[num + 1] = Fout[fout_ptr + 1] - num3; Fout[fout_ptr] += num2; Fout[fout_ptr + 1] += num3; num2 = S_MUL(Fout[num + 2] + Fout[num + 3], b); num3 = S_MUL(Fout[num + 3] - Fout[num + 2], b); Fout[num + 2] = Fout[fout_ptr + 2] - num2; Fout[num + 3] = Fout[fout_ptr + 3] - num3; Fout[fout_ptr + 2] += num2; Fout[fout_ptr + 3] += num3; num2 = Fout[num + 5]; num3 = -Fout[num + 4]; Fout[num + 4] = Fout[fout_ptr + 4] - num2; Fout[num + 5] = Fout[fout_ptr + 5] - num3; Fout[fout_ptr + 4] += num2; Fout[fout_ptr + 5] += num3; num2 = S_MUL(Fout[num + 7] - Fout[num + 6], b); num3 = S_MUL(-Fout[num + 7] - Fout[num + 6], b); Fout[num + 6] = Fout[fout_ptr + 6] - num2; Fout[num + 7] = Fout[fout_ptr + 7] - num3; Fout[fout_ptr + 6] += num2; Fout[fout_ptr + 7] += num3; fout_ptr += 16; } } internal static void kf_bfly4(int[] Fout, int fout_ptr, int fstride, FFTState st, int m, int N, int mm) { if (m == 1) { for (int i = 0; i < N; i++) { int num = Fout[fout_ptr] - Fout[fout_ptr + 4]; int num2 = Fout[fout_ptr + 1] - Fout[fout_ptr + 5]; Fout[fout_ptr] += Fout[fout_ptr + 4]; Fout[fout_ptr + 1] += Fout[fout_ptr + 5]; int num3 = Fout[fout_ptr + 2] + Fout[fout_ptr + 6]; int num4 = Fout[fout_ptr + 3] + Fout[fout_ptr + 7]; Fout[fout_ptr + 4] = Fout[fout_ptr] - num3; Fout[fout_ptr + 5] = Fout[fout_ptr + 1] - num4; Fout[fout_ptr] += num3; Fout[fout_ptr + 1] += num4; num3 = Fout[fout_ptr + 2] - Fout[fout_ptr + 6]; num4 = Fout[fout_ptr + 3] - Fout[fout_ptr + 7]; Fout[fout_ptr + 2] = num + num4; Fout[fout_ptr + 3] = num2 - num3; Fout[fout_ptr + 6] = num - num4; Fout[fout_ptr + 7] = num2 + num3; fout_ptr += 8; } return; } int num5 = fout_ptr; for (int i = 0; i < N; i++) { fout_ptr = num5 + 2 * i * mm; int num6 = fout_ptr + 2 * m; int num7 = fout_ptr + 4 * m; int num8 = fout_ptr + 6 * m; int num10; int num9; int num11 = (num10 = (num9 = 0)); for (int j = 0; j < m; j++) { int num = S_MUL(Fout[num6], st.twiddles[num9]) - S_MUL(Fout[num6 + 1], st.twiddles[num9 + 1]); int num2 = S_MUL(Fout[num6], st.twiddles[num9 + 1]) + S_MUL(Fout[num6 + 1], st.twiddles[num9]); int num3 = S_MUL(Fout[num7], st.twiddles[num10]) - S_MUL(Fout[num7 + 1], st.twiddles[num10 + 1]); int num4 = S_MUL(Fout[num7], st.twiddles[num10 + 1]) + S_MUL(Fout[num7 + 1], st.twiddles[num10]); int num12 = S_MUL(Fout[num8], st.twiddles[num11]) - S_MUL(Fout[num8 + 1], st.twiddles[num11 + 1]); int num13 = S_MUL(Fout[num8], st.twiddles[num11 + 1]) + S_MUL(Fout[num8 + 1], st.twiddles[num11]); int num14 = Fout[fout_ptr] - num3; int num15 = Fout[fout_ptr + 1] - num4; Fout[fout_ptr] += num3; Fout[fout_ptr + 1] += num4; int num16 = num + num12; int num17 = num2 + num13; int num18 = num - num12; int num19 = num2 - num13; Fout[num7] = Fout[fout_ptr] - num16; Fout[num7 + 1] = Fout[fout_ptr + 1] - num17; num9 += fstride * 2; num10 += fstride * 4; num11 += fstride * 6; Fout[fout_ptr] += num16; Fout[fout_ptr + 1] += num17; Fout[num6] = num14 + num19; Fout[num6 + 1] = num15 - num18; Fout[num8] = num14 - num19; Fout[num8 + 1] = num15 + num18; fout_ptr += 2; num6 += 2; num7 += 2; num8 += 2; } } } internal static void kf_bfly3(int[] Fout, int fout_ptr, int fstride, FFTState st, int m, int N, int mm) { int num = 2 * m; int num2 = 4 * m; int num3 = fout_ptr; for (int i = 0; i < N; i++) { fout_ptr = num3 + 2 * i * mm; int num4; int num5 = (num4 = 0); int num6 = m; do { int num7 = S_MUL(Fout[fout_ptr + num], st.twiddles[num5]) - S_MUL(Fout[fout_ptr + num + 1], st.twiddles[num5 + 1]); int num8 = S_MUL(Fout[fout_ptr + num], st.twiddles[num5 + 1]) + S_MUL(Fout[fout_ptr + num + 1], st.twiddles[num5]); int num9 = S_MUL(Fout[fout_ptr + num2], st.twiddles[num4]) - S_MUL(Fout[fout_ptr + num2 + 1], st.twiddles[num4 + 1]); int num10 = S_MUL(Fout[fout_ptr + num2], st.twiddles[num4 + 1]) + S_MUL(Fout[fout_ptr + num2 + 1], st.twiddles[num4]); int num11 = num7 + num9; int num12 = num8 + num10; int a = num7 - num9; int a2 = num8 - num10; num5 += fstride * 2; num4 += fstride * 4; Fout[fout_ptr + num] = Fout[fout_ptr] - HALF_OF(num11); Fout[fout_ptr + num + 1] = Fout[fout_ptr + 1] - HALF_OF(num12); a = S_MUL(a, -28378); a2 = S_MUL(a2, -28378); Fout[fout_ptr] += num11; Fout[fout_ptr + 1] += num12; Fout[fout_ptr + num2] = Fout[fout_ptr + num] + a2; Fout[fout_ptr + num2 + 1] = Fout[fout_ptr + num + 1] - a; Fout[fout_ptr + num] -= a2; Fout[fout_ptr + num + 1] += a; fout_ptr += 2; } while (--num6 != 0); } } internal static void kf_bfly5(int[] Fout, int fout_ptr, int fstride, FFTState st, int m, int N, int mm) { int num = fout_ptr; short b = 10126; short b2 = -31164; short b3 = -26510; short b4 = -19261; for (int i = 0; i < N; i++) { int num4; int num3; int num2; int num5 = (num4 = (num3 = (num2 = 0))); fout_ptr = num + 2 * i * mm; int num6 = fout_ptr; int num7 = fout_ptr + 2 * m; int num8 = fout_ptr + 4 * m; int num9 = fout_ptr + 6 * m; int num10 = fout_ptr + 8 * m; for (int j = 0; j < m; j++) { int num11 = Fout[num6]; int num12 = Fout[num6 + 1]; int num13 = S_MUL(Fout[num7], st.twiddles[num5]) - S_MUL(Fout[num7 + 1], st.twiddles[num5 + 1]); int num14 = S_MUL(Fout[num7], st.twiddles[num5 + 1]) + S_MUL(Fout[num7 + 1], st.twiddles[num5]); int num15 = S_MUL(Fout[num8], st.twiddles[num4]) - S_MUL(Fout[num8 + 1], st.twiddles[num4 + 1]); int num16 = S_MUL(Fout[num8], st.twiddles[num4 + 1]) + S_MUL(Fout[num8 + 1], st.twiddles[num4]); int num17 = S_MUL(Fout[num9], st.twiddles[num3]) - S_MUL(Fout[num9 + 1], st.twiddles[num3 + 1]); int num18 = S_MUL(Fout[num9], st.twiddles[num3 + 1]) + S_MUL(Fout[num9 + 1], st.twiddles[num3]); int num19 = S_MUL(Fout[num10], st.twiddles[num2]) - S_MUL(Fout[num10 + 1], st.twiddles[num2 + 1]); int num20 = S_MUL(Fout[num10], st.twiddles[num2 + 1]) + S_MUL(Fout[num10 + 1], st.twiddles[num2]); num5 += 2 * fstride; num4 += 4 * fstride; num3 += 6 * fstride; num2 += 8 * fstride; int num21 = num13 + num19; int num22 = num14 + num20; int a = num13 - num19; int a2 = num14 - num20; int num23 = num15 + num17; int num24 = num16 + num18; int a3 = num15 - num17; int a4 = num16 - num18; Fout[num6] += num21 + num23; Fout[num6 + 1] += num22 + num24; int num25 = num11 + S_MUL(num21, b) + S_MUL(num23, b3); int num26 = num12 + S_MUL(num22, b) + S_MUL(num24, b3); int num27 = S_MUL(a2, b2) + S_MUL(a4, b4); int num28 = -S_MUL(a, b2) - S_MUL(a3, b4); Fout[num7] = num25 - num27; Fout[num7 + 1] = num26 - num28; Fout[num10] = num25 + num27; Fout[num10 + 1] = num26 + num28; int num29 = num11 + S_MUL(num21, b3) + S_MUL(num23, b); int num30 = num12 + S_MUL(num22, b3) + S_MUL(num24, b); int num31 = -S_MUL(a2, b4) + S_MUL(a4, b2); int num32 = S_MUL(a, b4) - S_MUL(a3, b2); Fout[num8] = num29 + num31; Fout[num8 + 1] = num30 + num32; Fout[num9] = num29 - num31; Fout[num9 + 1] = num30 - num32; num6 += 2; num7 += 2; num8 += 2; num9 += 2; num10 += 2; } } } internal static void opus_fft_impl(FFTState st, int[] fout, int fout_ptr) { int[] value = fstrides.Value; int num = ((st.shift > 0) ? st.shift : 0); value[0] = 1; int num2 = 0; int num4; do { int num3 = st.factors[2 * num2]; num4 = st.factors[2 * num2 + 1]; value[num2 + 1] = value[num2] * num3; num2++; } while (num4 != 1); num4 = st.factors[2 * num2 - 1]; for (int num5 = num2 - 1; num5 >= 0; num5--) { int num6 = ((num5 == 0) ? 1 : st.factors[2 * num5 - 1]); switch (st.factors[2 * num5]) { case 2: kf_bfly2(fout, fout_ptr, num4, value[num5]); break; case 4: kf_bfly4(fout, fout_ptr, value[num5] << num, st, num4, value[num5], num6); break; case 3: kf_bfly3(fout, fout_ptr, value[num5] << num, st, num4, value[num5], num6); break; case 5: kf_bfly5(fout, fout_ptr, value[num5] << num, st, num4, value[num5], num6); break; } num4 = num6; } } internal static void opus_fft(FFTState st, int[] fin, int[] fout) { int shift = st.scale_shift - 1; short scale = st.scale; for (int i = 0; i < st.nfft; i++) { fout[2 * st.bitrev[i]] = Inlines.SHR32(Inlines.MULT16_32_Q16(scale, fin[2 * i]), shift); fout[2 * st.bitrev[i] + 1] = Inlines.SHR32(Inlines.MULT16_32_Q16(scale, fin[2 * i + 1]), shift); } opus_fft_impl(st, fout, 0); } } internal static class Laplace { private const int LAPLACE_LOG_MINP = 0; private const uint LAPLACE_MINP = 1u; private const int LAPLACE_NMIN = 16; internal static uint ec_laplace_get_freq1(uint fs0, int decay) { uint num = 32736 - fs0; return (uint)(num * (16384 - decay) >> 15); } internal static void ec_laplace_encode(EntropyCoder enc, ref int value, uint fs, int decay) { int num = value; uint num2 = 0u; if (num != 0) { int num3 = 0 - ((num < 0) ? 1 : 0); num = (num + num3) ^ num3; num2 = fs; fs = ec_laplace_get_freq1(fs, decay); int num4 = 1; while (fs != 0 && num4 < num) { fs *= 2; num2 += fs + 2; fs = (uint)(fs * decay >> 15); num4++; } if (fs == 0) { int num5 = (int)(32768 - num2 + 1 - 1); num5 = num5 - num3 >> 1; int num6 = Inlines.IMIN(num - num4, num5 - 1); num2 += (uint)(2 * num6 + 1 + num3); fs = Inlines.IMIN(1u, 32768 - num2); value = (num4 + num6 + num3) ^ num3; } else { fs++; num2 += (uint)(int)(fs & ~num3); } } enc.encode_bin(num2, num2 + fs, 15u); } internal static int ec_laplace_decode(EntropyCoder dec, uint fs, int decay) { int num = 0; uint num2 = dec.decode_bin(15u); uint num3 = 0u; if (num2 >= fs) { num++; num3 = fs; fs = ec_laplace_get_freq1(fs, decay) + 1; while (fs > 1 && num2 >= num3 + 2 * fs) { fs *= 2; num3 += fs; fs = (uint)((fs - 2) * decay >> 15); fs++; num++; } if (fs <= 1) { int num4 = (int)(num2 - num3) >> 1; num += num4; num3 += (uint)(2 * num4); } if (num2 < num3 + fs) { num = -num; } else { num3 += fs; } } dec.dec_update(num3, Inlines.IMIN(num3 + fs, 32768u), 32768u); return num; } } internal static class MDCT { internal static void clt_mdct_forward(MDCTLookup l, int[] input, int input_ptr, int[] output, int output_ptr, int[] window, int overlap, int shift, int stride) { FFTState fFTState = l.kfft[shift]; int num = 0; int shift2 = fFTState.scale_shift - 1; int scale = fFTState.scale; int num2 = l.n; short[] trig = l.trig; int i; for (i = 0; i < shift; i++) { num2 >>= 1; num += num2; } int num3 = num2 >> 1; int num4 = num2 >> 2; int[] array = new int[num3]; int[] array2 = new int[num4 * 2]; int num5 = input_ptr + (overlap >> 1); int num6 = input_ptr + num3 - 1 + (overlap >> 1); int num7 = 0; int num8 = overlap >> 1; int num9 = (overlap >> 1) - 1; for (i = 0; i < overlap + 3 >> 2; i++) { array[num7++] = Inlines.MULT16_32_Q15(window[num9], input[num5 + num3]) + Inlines.MULT16_32_Q15(window[num8], input[num6]); array[num7++] = Inlines.MULT16_32_Q15(window[num8], input[num5]) - Inlines.MULT16_32_Q15(window[num9], input[num6 - num3]); num5 += 2; num6 -= 2; num8 += 2; num9 -= 2; } num8 = 0; num9 = overlap - 1; for (; i < num4 - (overlap + 3 >> 2); i++) { array[num7++] = input[num6]; array[num7++] = input[num5]; num5 += 2; num6 -= 2; } for (; i < num4; i++) { array[num7++] = Inlines.MULT16_32_Q15(window[num9], input[num6]) - Inlines.MULT16_32_Q15(window[num8], input[num5 - num3]); array[num7++] = Inlines.MULT16_32_Q15(window[num9], input[num5]) + Inlines.MULT16_32_Q15(window[num8], input[num6 + num3]); num5 += 2; num6 -= 2; num8 += 2; num9 -= 2; } num7 = 0; int num10 = num; for (i = 0; i < num4; i++) { short b = trig[num10 + i]; short b2 = trig[num10 + num4 + i]; int a = array[num7++]; int a2 = array[num7++]; int b3 = KissFFT.S_MUL(a, b) - KissFFT.S_MUL(a2, b2); int b4 = KissFFT.S_MUL(a2, b) + KissFFT.S_MUL(a, b2); array2[2 * fFTState.bitrev[i]] = Inlines.PSHR32(Inlines.MULT16_32_Q16(scale, b3), shift2); array2[2 * fFTState.bitrev[i] + 1] = Inlines.PSHR32(Inlines.MULT16_32_Q16(scale, b4), shift2); } KissFFT.opus_fft_impl(fFTState, array2, 0); int num11 = 0; int num12 = output_ptr; int num13 = output_ptr + stride * (num3 - 1); num10 = num; for (i = 0; i < num4; i++) { int b3 = KissFFT.S_MUL(array2[num11 + 1], trig[num10 + num4 + i]) - KissFFT.S_MUL(array2[num11], trig[num10 + i]); int b4 = KissFFT.S_MUL(array2[num11], trig[num10 + num4 + i]) + KissFFT.S_MUL(array2[num11 + 1], trig[num10 + i]); output[num12] = b3; output[num13] = b4; num11 += 2; num12 += 2 * stride; num13 -= 2 * stride; } } internal static void clt_mdct_backward(MDCTLookup l, int[] input, int input_ptr, int[] output, int output_ptr, int[] window, int overlap, int shift, int stride) { int num = 0; int num2 = l.n; for (int i = 0; i < shift; i++) { num2 >>= 1; num += num2; } int num3 = num2 >> 1; int num4 = num2 >> 2; int num5 = input_ptr + stride * (num3 - 1); int num6 = output_ptr + (overlap >> 1); short[] bitrev = l.kfft[shift].bitrev; int num7 = 0; for (int i = 0; i < num4; i++) { int num8 = bitrev[num7++]; int num9 = num6 + 2 * num8; output[num9 + 1] = KissFFT.S_MUL(input[num5], l.trig[num + i]) + KissFFT.S_MUL(input[input_ptr], l.trig[num + num4 + i]); output[num9] = KissFFT.S_MUL(input[input_ptr], l.trig[num + i]) - KissFFT.S_MUL(input[num5], l.trig[num + num4 + i]); input_ptr += 2 * stride; num5 -= 2 * stride; } KissFFT.opus_fft_impl(l.kfft[shift], output, output_ptr + (overlap >> 1)); int num10 = output_ptr + (overlap >> 1); int num11 = output_ptr + (overlap >> 1) + num3 - 2; int num12 = num; int num13 = num12 + num4 - 1; int num14 = num12 + num3 - 1; for (int i = 0; i < num4 + 1 >> 1; i++) { int a = output[num10 + 1]; int a2 = output[num10]; short b = l.trig[num12 + i]; short b2 = l.trig[num12 + num4 + i]; int num15 = KissFFT.S_MUL(a, b) + KissFFT.S_MUL(a2, b2); int num16 = KissFFT.S_MUL(a, b2) - KissFFT.S_MUL(a2, b); a = output[num11 + 1]; a2 = output[num11]; output[num10] = num15; output[num11 + 1] = num16; b = l.trig[num13 - i]; b2 = l.trig[num14 - i]; num15 = KissFFT.S_MUL(a, b) + KissFFT.S_MUL(a2, b2); num16 = KissFFT.S_MUL(a, b2) - KissFFT.S_MUL(a2, b); output[num11] = num15; output[num10 + 1] = num16; num10 += 2; num11 -= 2; } int num17 = output_ptr + overlap - 1; num11 = output_ptr; int num18 = 0; int num19 = overlap - 1; for (int i = 0; i < overlap / 2; i++) { int b3 = output[num17]; int b4 = output[num11]; output[num11++] = Inlines.MULT16_32_Q15(window[num19], b4) - Inlines.MULT16_32_Q15(window[num18], b3); output[num17--] = Inlines.MULT16_32_Q15(window[num18], b4) + Inlines.MULT16_32_Q15(window[num19], b3); num18++; num19--; } } } internal static class Pitch { private static readonly int[] second_check = new int[16] { 0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2 }; internal static void find_best_pitch(int[] xcorr, int[] y, int len, int max_pitch, int[] best_pitch, int yshift, int maxcorr) { int num = 1; int shift = Inlines.celt_ilog2(maxcorr) - 14; int num2 = -1; int a = -1; int num3 = 0; int b = 0; best_pitch[0] = 0; best_pitch[1] = 1; for (int i = 0; i < len; i++) { num = Inlines.ADD32(num, Inlines.SHR32(Inlines.MULT16_16(y[i], y[i]), yshift)); } for (int j = 0; j < max_pitch; j++) { if (xcorr[j] > 0) { int num4 = Inlines.EXTRACT16(Inlines.VSHR32(xcorr[j], shift)); int num5 = Inlines.MULT16_16_Q15(num4, num4); if (Inlines.MULT16_32_Q15(num5, b) > Inlines.MULT16_32_Q15(a, num)) { if (Inlines.MULT16_32_Q15(num5, num3) > Inlines.MULT16_32_Q15(num2, num)) { a = num2; b = num3; best_pitch[1] = best_pitch[0]; num2 = num5; num3 = num; best_pitch[0] = j; } else { a = num5; b = num; best_pitch[1] = j; } } } num += Inlines.SHR32(Inlines.MULT16_16(y[j + len], y[j + len]), yshift) - Inlines.SHR32(Inlines.MULT16_16(y[j], y[j]), yshift); num = Inlines.MAX32(1, num); } } internal static void celt_fir5(int[] x, int[] num, int[] y, int N, int[] mem) { int a = num[0]; int a2 = num[1]; int a3 = num[2]; int a4 = num[3]; int a5 = num[4]; int num2 = mem[0]; int num3 = mem[1]; int num4 = mem[2]; int num5 = mem[3]; int num6 = mem[4]; for (int i = 0; i < N; i++) { int c = Inlines.SHL32(Inlines.EXTEND32(x[i]), 12); c = Inlines.MAC16_16(c, a, num2); c = Inlines.MAC16_16(c, a2, num3); c = Inlines.MAC16_16(c, a3, num4); c = Inlines.MAC16_16(c, a4, num5); c = Inlines.MAC16_16(c, a5, num6); num6 = num5; num5 = num4; num4 = num3; num3 = num2; num2 = x[i]; y[i] = Inlines.ROUND16(c, 12); } mem[0] = num2; mem[1] = num3; mem[2] = num4; mem[3] = num5; mem[4] = num6; } internal static void pitch_downsample(int[][] x, int[] x_lp, int len, int C) { int[] array = new int[5]; int b = 32767; int[] array2 = new int[4]; int[] array3 = new int[5]; int[] mem = array3; int[] array4 = new int[5]; int a = 26214; int num = Inlines.celt_maxabs32(x[0], 0, len); if (C == 2) { int b2 = Inlines.celt_maxabs32(x[1], 0, len); num = Inlines.MAX32(num, b2); } if (num < 1) { num = 1; } int num2 = Inlines.celt_ilog2(num) - 10; if (num2 < 0) { num2 = 0; } if (C == 2) { num2++; } int num3 = len >> 1; for (int i = 1; i < num3; i++) { x_lp[i] = Inlines.SHR32(Inlines.HALF32(Inlines.HALF32(x[0][2 * i - 1] + x[0][2 * i + 1]) + x[0][2 * i]), num2); } x_lp[0] = Inlines.SHR32(Inlines.HALF32(Inlines.HALF32(x[0][1]) + x[0][0]), num2); if (C == 2) { for (int i = 1; i < num3; i++) { x_lp[i] += Inlines.SHR32(Inlines.HALF32(Inlines.HALF32(x[1][2 * i - 1] + x[1][2 * i + 1]) + x[1][2 * i]), num2); } x_lp[0] += Inlines.SHR32(Inlines.HALF32(Inlines.HALF32(x[1][1]) + x[1][0]), num2); } Autocorrelation._celt_autocorr(x_lp, array, null, 0, 4, num3); array[0] += Inlines.SHR32(array[0], 13); for (int i = 1; i <= 4; i++) { array[i] -= Inlines.MULT16_32_Q15(2 * i * i, array[i]); } CeltLPC.celt_lpc(array2, array, 4); for (int i = 0; i < 4; i++) { b = Inlines.MULT16_16_Q15(29491, b); array2[i] = Inlines.MULT16_16_Q15(array2[i], b); } array4[0] = array2[0] + 3277; array4[1] = array2[1] + Inlines.MULT16_16_Q15(a, array2[0]); array4[2] = array2[2] + Inlines.MULT16_16_Q15(a, array2[1]); array4[3] = array2[3] + Inlines.MULT16_16_Q15(a, array2[2]); array4[4] = Inlines.MULT16_16_Q15(a, array2[3]); celt_fir5(x_lp, array4, x_lp, num3, mem); } internal static void pitch_search(int[] x_lp, int x_lp_ptr, int[] y, int len, int max_pitch, out int pitch) { int[] array = new int[2]; int[] array2 = array; int num = 0; int num2 = len + max_pitch; int[] array3 = new int[len >> 2]; int[] array4 = new int[num2 >> 2]; int[] array5 = new int[max_pitch >> 1]; for (int i = 0; i < len >> 2; i++) { array3[i] = x_lp[x_lp_ptr + 2 * i]; } for (int i = 0; i < num2 >> 2; i++) { array4[i] = y[2 * i]; } int a = Inlines.celt_maxabs32(array3, 0, len >> 2); int b = Inlines.celt_maxabs32(array4, 0, num2 >> 2); num = Inlines.celt_ilog2(Inlines.MAX32(1, Inlines.MAX32(a, b))) - 11; if (num > 0) { for (int i = 0; i < len >> 2; i++) { array3[i] = Inlines.SHR16(array3[i], num); } for (int i = 0; i < num2 >> 2; i++) { array4[i] = Inlines.SHR16(array4[i], num); } num *= 2; } else { num = 0; } int maxcorr = CeltPitchXCorr.pitch_xcorr(array3, array4, array5, len >> 2, max_pitch >> 2); find_best_pitch(array5, array4, len >> 2, max_pitch >> 2, array2, 0, maxcorr); maxcorr = 1; for (int j = 0; j < max_pitch >> 1; j++) { array5[j] = 0; if (Inlines.abs(j - 2 * array2[0]) <= 2 || Inlines.abs(j - 2 * array2[1]) <= 2) { int num3 = 0; for (int i = 0; i < len >> 1; i++) { num3 += Inlines.SHR32(Inlines.MULT16_16(x_lp[x_lp_ptr + i], y[j + i]), num); } array5[j] = Inlines.MAX32(-1, num3); maxcorr = Inlines.MAX32(maxcorr, num3); } } find_best_pitch(array5, y, len >> 1, max_pitch >> 1, array2, num + 1, maxcorr); int num7; if (array2[0] > 0 && array2[0] < (max_pitch >> 1) - 1) { int num4 = array5[array2[0] - 1]; int num5 = array5[array2[0]]; int num6 = array5[array2[0] + 1]; num7 = ((num6 - num4 > Inlines.MULT16_32_Q15((short)22938, num5 - num4)) ? 1 : ((num4 - num6 > Inlines.MULT16_32_Q15((short)22938, num5 - num6)) ? (-1) : 0)); } else { num7 = 0; } pitch = 2 * array2[0] - num7; } internal static int remove_doubling(int[] x, int maxperiod, int minperiod, int N, ref int T0_, int prev_period, int prev_gain) { int[] array = new int[3]; int num = minperiod; maxperiod /= 2; minperiod /= 2; T0_ /= 2; prev_period /= 2; N /= 2; int num2 = maxperiod; if (T0_ >= maxperiod) { T0_ = maxperiod - 1; } int num3; int num4 = (num3 = T0_); int[] array2 = new int[maxperiod + 1]; Kernels.dual_inner_prod(x, num2, x, num2, x, num2 - num3, N, out var xy, out var xy2); array2[0] = xy; int num5 = xy; for (int i = 1; i <= maxperiod; i++) { int num6 = num2 - i; num5 = num5 + Inlines.MULT16_16(x[num6], x[num6]) - Inlines.MULT16_16(x[num6 + N], x[num6 + N]); array2[i] = Inlines.MAX32(0, num5); } num5 = array2[num3]; int b = xy2; int num7 = num5; int num8 = 1 + Inlines.HALF32(Inlines.MULT32_32_Q31(xy, num5)); int num9 = Inlines.celt_ilog2(num8) >> 1; int x2 = Inlines.VSHR32(num8, 2 * (num9 - 7)); int num10 = Inlines.VSHR32(Inlines.MULT16_32_Q15(Inlines.celt_rsqrt_norm(x2), xy2), num9 + 1); int b2 = num10; for (int j = 2; j <= 15; j++) { int num11 = 0; int num12 = Inlines.celt_udiv(2 * num3 + j, 2 * j); if (num12 < minperiod) { break; } int num13 = ((j != 2) ? Inlines.celt_udiv(2 * second_check[j] * num3 + j, 2 * j) : ((num12 + num3 <= maxperiod) ? (num3 + num12) : num3)); Kernels.dual_inner_prod(x, num2, x, num2 - num12, x, num2 - num13, N, out xy2, out var xy3); xy2 += xy3; num5 = array2[num12] + array2[num13]; num8 = 1 + Inlines.MULT32_32_Q31(xy, num5); num9 = Inlines.celt_ilog2(num8) >> 1; x2 = Inlines.VSHR32(num8, 2 * (num9 - 7)); int num14 = Inlines.VSHR32(Inlines.MULT16_32_Q15(Inlines.celt_rsqrt_norm(x2), xy2), num9 + 1); num11 = ((Inlines.abs(num12 - prev_period) <= 1) ? prev_gain : ((Inlines.abs(num12 - prev_period) <= 2 && 5 * j * j < num3) ? Inlines.HALF16(prev_gain) : 0)); int num15 = Inlines.MAX16(9830, Inlines.MULT16_16_Q15(22938, b2) - num11); if (num12 < 3 * minperiod) { num15 = Inlines.MAX16(13107, Inlines.MULT16_16_Q15(27853, b2) - num11); } else if (num12 < 2 * minperiod) { num15 = Inlines.MAX16(16384, Inlines.MULT16_16_Q15(29491, b2) - num11); } if (num14 > num15) { b = xy2; num7 = num5; num4 = num12; num10 = num14; } } b = Inlines.MAX32(0, b); int num16 = ((num7 > b) ? Inlines.SHR32(Inlines.frac_div32(b, num7 + 1), 16) : 32767); for (int j = 0; j < 3; j++) { array[j] = Kernels.celt_inner_prod(x, num2, x, num2 - (num4 + j - 1), N); } int num17 = ((array[2] - array[0] > Inlines.MULT16_32_Q15((short)22938, array[1] - array[0])) ? 1 : ((array[0] - array[2] > Inlines.MULT16_32_Q15((short)22938, array[1] - array[2])) ? (-1) : 0)); if (num16 > num10) { num16 = num10; } T0_ = 2 * num4 + num17; if (T0_ < num) { T0_ = num; } return num16; } } internal static class QuantizeBands { private static readonly int[] pred_coef = new int[4] { 29440, 26112, 21248, 16384 }; private static readonly int[] beta_coef = new int[4] { 30147, 22282, 12124, 6554 }; private static readonly int beta_intra = 4915; private static byte[] small_energy_icdf = new byte[3] { 2, 1, 0 }; internal static int loss_distortion(int[][] eBands, int[][] oldEBands, int start, int end, int len, int C) { int num = 0; int num2 = 0; do { for (int i = start; i < end; i++) { int num3 = Inlines.SUB16(Inlines.SHR16(eBands[num2][i], 3), Inlines.SHR16(oldEBands[num2][i], 3)); num = Inlines.MAC16_16(num, num3, num3); } } while (++num2 < C); return Inlines.MIN32(200, Inlines.SHR32(num, 14)); } internal static int quant_coarse_energy_impl(CeltMode m, int start, int end, int[][] eBands, int[][] oldEBands, int budget, int tell, byte[] prob_model, int[][] error, EntropyCoder enc, int C, int LM, int intra, int max_decay, int lfe) { int num = 0; int[] array = new int[2]; int[] array2 = array; if (tell + 3 <= budget) { enc.enc_bit_logp(intra, 3u); } int a; int a2; if (intra != 0) { a = 0; a2 = beta_intra; } else { a2 = beta_coef[LM]; a = pred_coef[LM]; } for (int i = start; i < end; i++) { int num2 = 0; do { int num3 = eBands[num2][i]; int b = Inlines.MAX16(-9216, oldEBands[num2][i]); int num4 = Inlines.SHL32(Inlines.EXTEND32(num3), 7) - Inlines.PSHR32(Inlines.MULT16_16(a, b), 8) - array2[num2]; int value = num4 + 65536 >> 17; int num5 = Inlines.EXTRACT16(Inlines.MAX32(-28672, Inlines.SUB32(oldEBands[num2][i], max_decay))); if (value < 0 && num3 < num5) { value += Inlines.SHR16(Inlines.SUB16(num5, num3), 10); if (value > 0) { value = 0; } } int num6 = value; tell = enc.tell(); int num7 = budget - tell - 3 * C * (end - i); if (i != start && num7 < 30) { if (num7 < 24) { value = Inlines.IMIN(1, value); } if (num7 < 16) { value = Inlines.IMAX(-1, value); } } if (lfe != 0 && i >= 2) { value = Inlines.IMIN(value, 0); } if (budget - tell >= 15) { int num8 = 2 * Inlines.IMIN(i, 20); Laplace.ec_laplace_encode(enc, ref value, (uint)(prob_model[num8] << 7), prob_model[num8 + 1] << 6); } else if (budget - tell >= 2) { value = Inlines.IMAX(-1, Inlines.IMIN(value, 1)); enc.enc_icdf((2 * value) ^ (0 - ((value < 0) ? 1 : 0)), small_energy_icdf, 2u); } else if (budget - tell >= 1) { value = Inlines.IMIN(0, value); enc.enc_bit_logp(-value, 1u); } else { value = -1; } error[num2][i] = Inlines.PSHR32(num4, 7) - Inlines.SHL16(value, 10); num += Inlines.abs(num6 - value); int a3 = Inlines.SHL32(value, 10); int b2 = Inlines.PSHR32(Inlines.MULT16_16(a, b), 8) + array2[num2] + Inlines.SHL32(a3, 7); b2 = Inlines.MAX32(-3670016, b2); oldEBands[num2][i] = Inlines.PSHR32(b2, 7); array2[num2] = array2[num2] + Inlines.SHL32(a3, 7) - Inlines.MULT16_16(a2, Inlines.PSHR32(a3, 8)); } while (++num2 < C); } return (lfe == 0) ? num : 0; } internal static void quant_coarse_energy(CeltMode m, int start, int end, int effEnd, int[][] eBands, int[][] oldEBands, uint budget, int[][] error, EntropyCoder enc, int C, int LM, int nbAvailableBytes, int force_intra, ref int delayedIntra, int two_pass, int loss_rate, int lfe) { EntropyCoder entropyCoder = new EntropyCoder(); int num = 0; int num2 = ((force_intra != 0 || (two_pass == 0 && delayedIntra > 2 * C * (end - start) && nbAvailableBytes > (end - start) * C)) ? 1 : 0); int num3 = (int)(budget * delayedIntra * loss_rate / (C * 512)); int num4 = loss_distortion(eBands, oldEBands, start, effEnd, m.nbEBands, C); uint num5 = (uint)enc.tell(); if (num5 + 3 > budget) { two_pass = (num2 = 0); } int num6 = 16384; if (end - start > 10) { num6 = Inlines.MIN32(num6, Inlines.SHL32(nbAvailableBytes, 7)); } if (lfe != 0) { num6 = 3072; } entropyCoder.Assign(enc); int[][] array = Arrays.InitTwoDimensionalArray(C, m.nbEBands); int[][] array2 = Arrays.InitTwoDimensionalArray(C, m.nbEBands); Array.Copy(oldEBands[0], 0, array[0], 0, m.nbEBands); if (C == 2) { Array.Copy(oldEBands[1], 0, array[1], 0, m.nbEBands); } if (two_pass != 0 || num2 != 0) { num = quant_coarse_energy_impl(m, start, end, eBands, array, (int)budget, (int)num5, Tables.e_prob_model[LM][1], array2, enc, C, LM, 1, num6, lfe); } if (num2 == 0) { EntropyCoder entropyCoder2 = new EntropyCoder(); byte[] array3 = null; int num7 = (int)enc.tell_frac(); entropyCoder2.Assign(enc); uint num8 = entropyCoder.range_bytes(); uint num9 = entropyCoder2.range_bytes(); int num10 = entropyCoder2.buf_ptr + (int)num8; uint num11 = num9 - num8; if (num11 != 0) { array3 = new byte[num11]; Array.Copy(entropyCoder2.buf, num10, array3, 0, (int)num11); } enc.Assign(entropyCoder); int num12 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, (int)budget, (int)num5, Tables.e_prob_model[LM][num2], error, enc, C, LM, 0, num6, lfe); if (two_pass != 0 && (num < num12 || (num == num12 && (int)enc.tell_frac() + num3 > num7))) { enc.Assign(entropyCoder2); if (array3 != null) { Array.Copy(array3, 0, entropyCoder2.buf, num10, (int)(num9 - num8)); } Array.Copy(array[0], 0, oldEBands[0], 0, m.nbEBands); Array.Copy(array2[0], 0, error[0], 0, m.nbEBands); if (C == 2) { Array.Copy(array[1], 0, oldEBands[1], 0, m.nbEBands); Array.Copy(array2[1], 0, error[1], 0, m.nbEBands); } num2 = 1; } } else { Array.Copy(array[0], 0, oldEBands[0], 0, m.nbEBands); Array.Copy(array2[0], 0, error[0], 0, m.nbEBands); if (C == 2) { Array.Copy(array[1], 0, oldEBands[1], 0, m.nbEBands); Array.Copy(array2[1], 0, error[1], 0, m.nbEBands); } } if (num2 != 0) { delayedIntra = num4; } else { delayedIntra = Inlines.ADD32(Inlines.MULT16_32_Q15(Inlines.MULT16_16_Q15(pred_coef[LM], pred_coef[LM]), delayedIntra), num4); } } internal static void quant_fine_energy(CeltMode m, int start, int end, int[][] oldEBands, int[][] error, int[] fine_quant, EntropyCoder enc, int C) { for (int i = start; i < end; i++) { int num = 1 << fine_quant[i]; if (fine_quant[i] <= 0) { continue; } int num2 = 0; do { int num3 = error[num2][i] + 512 >> 10 - fine_quant[i]; if (num3 > num - 1) { num3 = num - 1; } if (num3 < 0) { num3 = 0; } enc.enc_bits((uint)num3, (uint)fine_quant[i]); int num4 = Inlines.SUB16(Inlines.SHR32(Inlines.SHL32(num3, 10) + 512, fine_quant[i]), 512); oldEBands[num2][i] += num4; error[num2][i] -= num4; } while (++num2 < C); } } internal static void quant_energy_finalise(CeltMode m, int start, int end, int[][] oldEBands, int[][] error, int[] fine_quant, int[] fine_priority, int bits_left, EntropyCoder enc, int C) { for (int i = 0; i < 2; i++) { for (int j = start; j < end; j++) { if (bits_left < C) { break; } if (fine_quant[j] < 8 && fine_priority[j] == i) { int num = 0; do { int num2 = ((error[num][j] >= 0) ? 1 : 0); enc.enc_bits((uint)num2, 1u); int num3 = Inlines.SHR16(Inlines.SHL16(num2, 10) - 512, fine_quant[j] + 1); oldEBands[num][j] += num3; bits_left--; } while (++num < C); } } } } internal static void unquant_coarse_energy(CeltMode m, int start, int end, int[] oldEBands, int intra, EntropyCoder dec, int C, int LM) { byte[] array = Tables.e_prob_model[LM][intra]; int[] array2 = new int[2]; int[] array3 = array2; int a; int a2; if (intra != 0) { a = 0; a2 = beta_intra; } else { a2 = beta_coef[LM]; a = pred_coef[LM]; } int num = (int)(dec.storage * 8); for (int i = start; i < end; i++) { int num2 = 0; do { int num3 = dec.tell(); int a3; if (num - num3 >= 15) { int num4 = 2 * Inlines.IMIN(i, 20); a3 = Laplace.ec_laplace_decode(dec, (uint)(array[num4] << 7), array[num4 + 1] << 6); } else if (num - num3 < 2) { a3 = ((num - num3 < 1) ? (-1) : (-dec.dec_bit_logp(1u))); } else { a3 = dec.dec_icdf(small_energy_icdf, 2u); a3 = (a3 >> 1) ^ -(a3 & 1); } int a4 = Inlines.SHL32(a3, 10); oldEBands[i + num2 * m.nbEBands] = Inlines.MAX16(-9216, oldEBands[i + num2 * m.nbEBands]); int b = Inlines.PSHR32(Inlines.MULT16_16(a, oldEBands[i + num2 * m.nbEBands]), 8) + array3[num2] + Inlines.SHL32(a4, 7); b = Inlines.MAX32(-3670016, b); oldEBands[i + num2 * m.nbEBands] = Inlines.PSHR32(b, 7); array3[num2] = array3[num2] + Inlines.SHL32(a4, 7) - Inlines.MULT16_16(a2, Inlines.PSHR32(a4, 8)); } while (++num2 < C); } } internal static void unquant_fine_energy(CeltMode m, int start, int end, int[] oldEBands, int[] fine_quant, EntropyCoder dec, int C) { for (int i = start; i < end; i++) { if (fine_quant[i] > 0) { int num = 0; do { int a = (int)dec.dec_bits((uint)fine_quant[i]); int num2 = Inlines.SUB16(Inlines.SHR32(Inlines.SHL32(a, 10) + 512, fine_quant[i]), 512); oldEBands[i + num * m.nbEBands] += num2; } while (++num < C); } } } internal static void unquant_energy_finalise(CeltMode m, int start, int end, int[] oldEBands, int[] fine_quant, int[] fine_priority, int bits_left, EntropyCoder dec, int C) { for (int i = 0; i < 2; i++) { for (int j = start; j < end; j++) { if (bits_left < C) { break; } if (fine_quant[j] < 8 && fine_priority[j] == i) { int num = 0; do { int a = (int)dec.dec_bits(1u); int num2 = Inlines.SHR16(Inlines.SHL16(a, 10) - 512, fine_quant[j] + 1); oldEBands[j + num * m.nbEBands] += num2; bits_left--; } while (++num < C); } } } } internal static void amp2Log2(CeltMode m, int effEnd, int end, int[][] bandE, int[][] bandLogE, int C) { int num = 0; do { for (int i = 0; i < effEnd; i++) { bandLogE[num][i] = Inlines.celt_log2(Inlines.SHL32(bandE[num][i], 2)) - Inlines.SHL16((int)Tables.eMeans[i], 6); } for (int i = effEnd; i < end; i++) { bandLogE[num][i] = -14336; } } while (++num < C); } internal static void amp2Log2(CeltMode m, int effEnd, int end, int[] bandE, int[] bandLogE, int bandLogE_ptr, int C) { int num = 0; do { for (int i = 0; i < effEnd; i++) { bandLogE[bandLogE_ptr + num * m.nbEBands + i] = Inlines.celt_log2(Inlines.SHL32(bandE[i + num * m.nbEBands], 2)) - Inlines.SHL16((int)Tables.eMeans[i], 6); } for (int i = effEnd; i < end; i++) { bandLogE[bandLogE_ptr + num * m.nbEBands + i] = -14336; } } while (++num < C); } } internal static class Rate { private const int ALLOC_STEPS = 6; private static readonly byte[] LOG2_FRAC_TABLE = new byte[24] { 0, 8, 13, 16, 19, 21, 23, 24, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 34, 35, 36, 36, 37, 37 }; internal static int get_pulses(int i) { return (i < 8) ? i : (8 + (i & 7) << (i >> 3) - 1); } internal static int bits2pulses(CeltMode m, int band, int LM, int bits) { LM++; byte[] bits2 = m.cache.bits; int num = m.cache.index[LM * m.nbEBands + band]; int num2 = 0; int num3 = bits2[num]; bits--; for (int i = 0; i < 6; i++) { int num4 = num2 + num3 + 1 >> 1; if (bits2[num + num4] >= bits) { num3 = num4; } else { num2 = num4; } } if (bits - ((num2 == 0) ? (-1) : bits2[num + num2]) <= bits2[num + num3] - bits) { return num2; } return num3; } internal static int pulses2bits(CeltMode m, int band, int LM, int pulses) { LM++; return (pulses != 0) ? (m.cache.bits[m.cache.index[LM * m.nbEBands + band] + pulses] + 1) : 0; } internal static int interp_bits2pulses(CeltMode m, int start, int end, int skip_start, int[] bits1, int[] bits2, int[] thresh, int[] cap, int total, out int _balance, int skip_rsv, ref int intensity, int intensity_rsv, ref int dual_stereo, int dual_stereo_rsv, int[] bits, int[] ebits, int[] fine_priority, int C, int LM, EntropyCoder ec, int encode, int prev, int signalBandwidth) { int num = -1; int num2 = C << 3; int num3 = ((C > 1) ? 1 : 0); int num4 = LM << 3; int num5 = 0; int num6 = 64; int num9; int num8; int num10; for (int i = 0; i < 6; i++) { int num7 = num5 + num6 >> 1; num8 = 0; num9 = 0; num10 = end; while (num10-- > start) { int num11 = bits1[num10] + (num7 * bits2[num10] >> 6); if (num11 >= thresh[num10] || num9 != 0) { num9 = 1; num8 += Inlines.IMIN(num11, cap[num10]); } else if (num11 >= num2) { num8 += num2; } } if (num8 > total) { num6 = num7; } else { num5 = num7; } } num8 = 0; num9 = 0; num10 = end; while (num10-- > start) { int num11 = bits1[num10] + (num5 * bits2[num10] >> 6); if (num11 < thresh[num10] && num9 == 0) { num11 = ((num11 >= num2) ? num2 : 0); } else { num9 = 1; } num8 += (bits[num10] = Inlines.IMIN(num11, cap[num10])); } num = end; int num13; int num12; while (true) { bool flag = true; num10 = num - 1; if (num10 <= skip_start) { total += skip_rsv; break; } num12 = total - num8; num13 = Inlines.celt_udiv(num12, m.eBands[num] - m.eBands[start]); num12 -= (m.eBands[num] - m.eBands[start]) * num13; int num14 = Inlines.IMAX(num12 - (m.eBands[num10] - m.eBands[start]), 0); int num15 = m.eBands[num] - m.eBands[num10]; int num16 = bits[num10] + num13 * num15 + num14; if (num16 >= Inlines.IMAX(thresh[num10], num2 + 8)) { if (encode != 0) { if (num <= start + 2 || (num16 > ((num10 < prev) ? 7 : 9) * num15 << LM << 3 >> 4 && num10 <= signalBandwidth)) { ec.enc_bit_logp(1, 1u); break; } ec.enc_bit_logp(0, 1u); } else if (ec.dec_bit_logp(1u) != 0) { break; } num8 += 8; num16 -= 8; } num8 -= bits[num10] + intensity_rsv; if (intensity_rsv > 0) { intensity_rsv = LOG2_FRAC_TABLE[num10 - start]; } num8 += intensity_rsv; if (num16 >= num2) { num8 += num2; bits[num10] = num2; } else { bits[num10] = 0; } num--; } if (intensity_rsv > 0) { if (encode != 0) { intensity = Inlines.IMIN(intensity, num); ec.enc_uint((uint)(intensity - start), (uint)(num + 1 - start)); } else { intensity = start + (int)ec.dec_uint((uint)(num + 1 - start)); } } else { intensity = 0; } if (intensity <= start) { total += dual_stereo_rsv; dual_stereo_rsv = 0; } if (dual_stereo_rsv > 0) { if (encode != 0) { ec.enc_bit_logp(dual_stereo, 1u); } else { dual_stereo = ec.dec_bit_logp(1u); } } else { dual_stereo = 0; } num12 = total - num8; num13 = Inlines.celt_udiv(num12, m.eBands[num] - m.eBands[start]); num12 -= (m.eBands[num] - m.eBands[start]) * num13; for (num10 = start; num10 < num; num10++) { bits[num10] += num13 * (m.eBands[num10 + 1] - m.eBands[num10]); } for (num10 = start; num10 < num; num10++) { int num11 = Inlines.IMIN(num12, m.eBands[num10 + 1] - m.eBands[num10]); bits[num10] += num11; num12 -= num11; } int num17 = 0; for (num10 = start; num10 < num; num10++) { int num18 = m.eBands[num10 + 1] - m.eBands[num10]; int num19 = num18 << LM; int num20 = bits[num10] + num17; int num21; if (num19 > 1) { num21 = Inlines.MAX32(num20 - cap[num10], 0); bits[num10] = num20 - num21; int num22 = C * num19 + ((C == 2 && num19 > 2 && dual_stereo == 0 && num10 < intensity) ? 1 : 0); int num23 = num22 * (m.logN[num10] + num4); int num24 = (num23 >> 1) - num22 * 21; if (num19 == 2) { num24 += num22 << 3 >> 2; } if (bits[num10] + num24 < num22 * 2 << 3) { num24 += num23 >> 2; } else if (bits[num10] + num24 < num22 * 3 << 3) { num24 += num23 >> 3; } ebits[num10] = Inlines.IMAX(0, bits[num10] + num24 + (num22 << 2)); ebits[num10] = Inlines.celt_udiv(ebits[num10], num22) >> 3; if (C * ebits[num10] > bits[num10] >> 3) { ebits[num10] = bits[num10] >> num3 >> 3; } ebits[num10] = Inlines.IMIN(ebits[num10], 8); fine_priority[num10] = ((ebits[num10] * (num22 << 3) >= bits[num10] + num24) ? 1 : 0); bits[num10] -= C * ebits[num10] << 3; } else { num21 = Inlines.MAX32(0, num20 - (C << 3)); bits[num10] = num20 - num21; ebits[num10] = 0; fine_priority[num10] = 1; } if (num21 > 0) { int num25 = Inlines.IMIN(num21 >> num3 + 3, 8 - ebits[num10]); ebits[num10] += num25; int num26 = num25 * C << 3; fine_priority[num10] = ((num26 >= num21 - num17) ? 1 : 0); num21 -= num26; } num17 = num21; } _balance = num17; for (; num10 < end; num10++) { ebits[num10] = bits[num10] >> num3 >> 3; bits[num10] = 0; fine_priority[num10] = ((ebits[num10] < 1) ? 1 : 0); } return num; } internal static int compute_allocation(CeltMode m, int start, int end, int[] offsets, int[] cap, int alloc_trim, ref int intensity, ref int dual_stereo, int total, out int balance, int[] pulses, int[] ebits, int[] fine_priority, int C, int LM, EntropyCoder ec, int encode, int prev, int signalBandwidth) { total = Inlines.IMAX(total, 0); int nbEBands = m.nbEBands; int skip_start = start; int num = ((total >= 8) ? 8 : 0); total -= num; int num2; int num3 = (num2 = 0); if (C == 2) { num3 = LOG2_FRAC_TABLE[end - start]; if (num3 > total) { num3 = 0; } else { total -= num3; num2 = ((total >= 8) ? 8 : 0); total -= num2; } } int[] array = new int[nbEBands]; int[] array2 = new int[nbEBands]; int[] array3 = new int[nbEBands]; int[] array4 = new int[nbEBands]; for (int i = start; i < end; i++) { array3[i] = Inlines.IMAX(C << 3, 3 * (m.eBands[i + 1] - m.eBands[i]) << LM << 3 >> 4); array4[i] = C * (m.eBands[i + 1] - m.eBands[i]) * (alloc_trim - 5 - LM) * (end - i - 1) * (1 << LM + 3) >> 6; if (m.eBands[i + 1] - m.eBands[i] << LM == 1) { array4[i] -= C << 3; } } int num4 = 1; int num5 = m.nbAllocVectors - 1; do { int num6 = 0; int num7 = 0; int num8 = num4 + num5 >> 1; int i = end; while (i-- > start) { int num9 = m.eBands[i + 1] - m.eBands[i]; int num10 = C * num9 * m.allocVectors[num8 * nbEBands + i] << LM >> 2; if (num10 > 0) { num10 = Inlines.IMAX(0, num10 + array4[i]); } num10 += offsets[i]; if (num10 >= array3[i] || num6 != 0) { num6 = 1; num7 += Inlines.IMIN(num10, cap[i]); } else if (num10 >= C << 3) { num7 += C << 3; } } if (num7 > total) { num5 = num8 - 1; } else { num4 = num8 + 1; } } while (num4 <= num5); num5 = num4--; for (int i = start; i < end; i++) { int num9 = m.eBands[i + 1] - m.eBands[i]; int num11 = C * num9 * m.allocVectors[num4 * nbEBands + i] << LM >> 2; int num12 = ((num5 >= m.nbAllocVectors) ? cap[i] : (C * num9 * m.allocVectors[num5 * nbEBands + i] << LM >> 2)); if (num11 > 0) { num11 = Inlines.IMAX(0, num11 + array4[i]); } if (num12 > 0) { num12 = Inlines.IMAX(0, num12 + array4[i]); } if (num4 > 0) { num11 += offsets[i]; } num12 += offsets[i]; if (offsets[i] > 0) { skip_start = i; } num12 = Inlines.IMAX(0, num12 - num11); array[i] = num11; array2[i] = num12; } return interp_bits2pulses(m, start, end, skip_start, array, array2, array3, cap, total, out balance, num, ref intensity, num3, ref dual_stereo, num2, pulses, ebits, fine_priority, C, LM, ec, encode, prev, signalBandwidth); } } internal static class Tables { internal static readonly byte[] eMeans = new byte[25] { 103, 100, 92, 85, 81, 77, 72, 70, 78, 75, 73, 71, 78, 74, 69, 72, 70, 74, 76, 71, 60, 60, 60, 60, 60 }; internal static readonly int[] ordery_table = new int[30] { 1, 0, 3, 0, 2, 1, 7, 0, 4, 3, 6, 1, 5, 2, 15, 0, 8, 7, 12, 3, 11, 4, 14, 1, 9, 6, 13, 2, 10, 5 }; internal static readonly short[] eband5ms = new short[22] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100 }; internal static readonly byte[][][] e_prob_model = new byte[4][][] { new byte[2][] { new byte[42] { 72, 127, 65, 129, 66, 128, 65, 128, 64, 128, 62, 128, 64, 128, 64, 128, 92, 78, 92, 79, 92, 78, 90, 79, 116, 41, 115, 40, 114, 40, 132, 26, 132, 26, 145, 17, 161, 12, 176, 10, 177, 11 }, new byte[42] { 24, 179, 48, 138, 54, 135, 54, 132, 53, 134, 56, 133, 55, 132, 55, 132, 61, 114, 70, 96, 74, 88, 75, 88, 87, 74, 89, 66, 91, 67, 100, 59, 108, 50, 120, 40, 122, 37, 97, 43, 78, 50 } }, new byte[2][] { new byte[42] { 83, 78, 84, 81, 88, 75, 86, 74, 87, 71, 90, 73, 93, 74, 93, 74, 109, 40, 114, 36, 117, 34, 117, 34, 143, 17, 145, 18, 146, 19, 162, 12, 165, 10, 178, 7, 189, 6, 190, 8, 177, 9 }, new byte[42] { 23, 178, 54, 115, 63, 102, 66, 98, 69, 99, 74, 89, 71, 91, 73, 91, 78, 89, 86, 80, 92, 66, 93, 64, 102, 59, 103, 60, 104, 60, 117, 52, 123, 44, 138, 35, 133, 31, 97, 38, 77, 45 } }, new byte[2][] { new byte[42] { 61, 90, 93, 60, 105, 42, 107, 41, 110, 45, 116, 38, 113, 38, 112, 38, 124, 26, 132, 27, 136, 19, 140, 20, 155, 14, 159, 16, 158, 18, 170, 13, 177, 10, 187, 8, 192, 6, 175, 9, 159, 10 }, new byte[42] { 21, 178, 59, 110, 71, 86, 75, 85, 84, 83, 91, 66, 88, 73, 87, 72, 92, 75, 98, 72, 105, 58, 107, 54, 115, 52, 114, 55, 112, 56, 129, 51, 132, 40, 150, 33, 140, 29, 98, 35, 77, 42 } }, new byte[2][] { new byte[42] { 42, 121, 96, 66, 108, 43, 111, 40, 117, 44, 123, 32, 120, 36, 119, 33, 127, 33, 134, 34, 139, 21, 147, 23, 152, 20, 158, 25, 154, 26, 166, 21, 173, 16, 184, 13, 184, 10, 150, 13, 139, 15 }, new byte[42] { 22, 178, 63, 114, 74, 82, 84, 83, 92, 82, 103, 62, 96, 72, 96, 67, 101, 73, 107, 72, 113, 55, 118, 52, 125, 52, 118, 52, 117, 55, 135, 49, 137, 39, 157, 32, 145, 29, 97, 33, 77, 40 } } }; internal static readonly sbyte[][] tf_select_table = new sbyte[4][] { new sbyte[8] { 0, -1, 0, -1, 0, -1, 0, -1 }, new sbyte[8] { 0, -1, 0, -2, 1, 0, 1, -1 }, new sbyte[8] { 0, -2, 0, -3, 2, 0, 1, -1 }, new sbyte[8] { 0, -2, 0, -3, 3, 0, 1, -1 } }; internal static readonly byte[] trim_icdf = new byte[11] { 126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0 }; internal static readonly byte[] spread_icdf = new byte[4] { 25, 23, 2, 0 }; internal static readonly byte[] tapset_icdf = new byte[3] { 2, 1, 0 }; internal static readonly byte[] band_allocation = new byte[231] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10, 0, 0, 0, 0, 0, 0, 0, 0, 110, 100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12, 0, 0, 0, 0, 0, 0, 118, 110, 103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0, 126, 119, 112, 104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12, 1, 0, 0, 134, 127, 120, 114, 103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10, 1, 144, 137, 130, 124, 113, 107, 101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1, 152, 145, 138, 132, 123, 117, 111, 105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1, 162, 155, 148, 142, 133, 127, 121, 115, 108, 102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1, 172, 165, 158, 152, 143, 137, 131, 125, 118, 112, 106, 100, 94, 87, 81, 75, 69, 63, 56, 45, 20, 200, 200, 200, 200, 200, 200, 200, 200, 198, 193, 188, 183, 178, 173, 168, 163, 158, 153, 148, 129, 104 }; internal static readonly uint[] CELT_PVQ_U_DATA = new uint[1272] { 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 3u, 5u, 7u, 9u, 11u, 13u, 15u, 17u, 19u, 21u, 23u, 25u, 27u, 29u, 31u, 33u, 35u, 37u, 39u, 41u, 43u, 45u, 47u, 49u, 51u, 53u, 55u, 57u, 59u, 61u, 63u, 65u, 67u, 69u, 71u, 73u, 75u, 77u, 79u, 81u, 83u, 85u, 87u, 89u, 91u, 93u, 95u, 97u, 99u, 101u, 103u, 105u, 107u, 109u, 111u, 113u, 115u, 117u, 119u, 121u, 123u, 125u, 127u, 129u, 131u, 133u, 135u, 137u, 139u, 141u, 143u, 145u, 147u, 149u, 151u, 153u, 155u, 157u, 159u, 161u, 163u, 165u, 167u, 169u, 171u, 173u, 175u, 177u, 179u, 181u, 183u, 185u, 187u, 189u, 191u, 193u, 195u, 197u, 199u, 201u, 203u, 205u, 207u, 209u, 211u, 213u, 215u, 217u, 219u, 221u, 223u, 225u, 227u, 229u, 231u, 233u, 235u, 237u, 239u, 241u, 243u, 245u, 247u, 249u, 251u, 253u, 255u, 257u, 259u, 261u, 263u, 265u, 267u, 269u, 271u, 273u, 275u, 277u, 279u, 281u, 283u, 285u, 287u, 289u, 291u, 293u, 295u, 297u, 299u, 301u, 303u, 305u, 307u, 309u, 311u, 313u, 315u, 317u, 319u, 321u, 323u, 325u, 327u, 329u, 331u, 333u, 335u, 337u, 339u, 341u, 343u, 345u, 347u, 349u, 351u, 13u, 25u, 41u, 61u, 85u, 113u, 145u, 181u, 221u, 265u, 313u, 365u, 421u, 481u, 545u, 613u, 685u, 761u, 841u, 925u, 1013u, 1105u, 1201u, 1301u, 1405u, 1513u, 1625u, 1741u, 1861u, 1985u, 2113u, 2245u, 2381u, 2521u, 2665u, 2813u, 2965u, 3121u, 3281u, 3445u, 3613u, 3785u, 3961u, 4141u, 4325u, 4513u, 4705u, 4901u, 5101u, 5305u, 5513u, 5725u, 5941u, 6161u, 6385u, 6613u, 6845u, 7081u, 7321u, 7565u, 7813u, 8065u, 8321u, 8581u, 8845u, 9113u, 9385u, 9661u, 9941u, 10225u, 10513u, 10805u, 11101u, 11401u, 11705u, 12013u, 12325u, 12641u, 12961u, 13285u, 13613u, 13945u, 14281u, 14621u, 14965u, 15313u, 15665u, 16021u, 16381u, 16745u, 17113u, 17485u, 17861u, 18241u, 18625u, 19013u, 19405u, 19801u, 20201u, 20605u, 21013u, 21425u, 21841u, 22261u, 22685u, 23113u, 23545u, 23981u, 24421u, 24865u, 25313u, 25765u, 26221u, 26681u, 27145u, 27613u, 28085u, 28561u, 29041u, 29525u, 30013u, 30505u, 31001u, 31501u, 32005u, 32513u, 33025u, 33541u, 34061u, 34585u, 35113u, 35645u, 36181u, 36721u, 37265u, 37813u, 38365u, 38921u, 39481u, 40045u, 40613u, 41185u, 41761u, 42341u, 42925u, 43513u, 44105u, 44701u, 45301u, 45905u, 46513u, 47125u, 47741u, 48361u, 48985u, 49613u, 50245u, 50881u, 51521u, 52165u, 52813u, 53465u, 54121u, 54781u, 55445u, 56113u, 56785u, 57461u, 58141u, 58825u, 59513u, 60205u, 60901u, 61601u, 63u, 129u, 231u, 377u, 575u, 833u, 1159u, 1561u, 2047u, 2625u, 3303u, 4089u, 4991u, 6017u, 7175u, 8473u, 9919u, 11521u, 13287u, 15225u, 17343u, 19649u, 22151u, 24857u, 27775u, 30913u, 34279u, 37881u, 41727u, 45825u, 50183u, 54809u, 59711u, 64897u, 70375u, 76153u, 82239u, 88641u, 95367u, 102425u, 109823u, 117569u, 125671u, 134137u, 142975u, 152193u, 161799u, 171801u, 182207u, 193025u, 204263u, 215929u, 228031u, 240577u, 253575u, 267033u, 280959u, 295361u, 310247u, 325625u, 341503u, 357889u, 374791u, 392217u, 410175u, 428673u, 447719u, 467321u, 487487u, 508225u, 529543u, 551449u, 573951u, 597057u, 620775u, 645113u, 670079u, 695681u, 721927u, 748825u, 776383u, 804609u, 833511u, 863097u, 893375u, 924353u, 956039u, 988441u, 1021567u, 1055425u, 1090023u, 1125369u, 1161471u, 1198337u, 1235975u, 1274393u, 1313599u, 1353601u, 1394407u, 1436025u, 1478463u, 1521729u, 1565831u, 1610777u, 1656575u, 1703233u, 1750759u, 1799161u, 1848447u, 1898625u, 1949703u, 2001689u, 2054591u, 2108417u, 2163175u, 2218873u, 2275519u, 2333121u, 2391687u, 2451225u, 2511743u, 2573249u, 2635751u, 2699257u, 2763775u, 2829313u, 2895879u, 2963481u, 3032127u, 3101825u, 3172583u, 3244409u, 3317311u, 3391297u, 3466375u, 3542553u, 3619839u, 3698241u, 3777767u, 3858425u, 3940223u, 4023169u, 4107271u, 4192537u, 4278975u, 4366593u, 4455399u, 4545401u, 4636607u, 4729025u, 4822663u, 4917529u, 5013631u, 5110977u, 5209575u, 5309433u, 5410559u, 5512961u, 5616647u, 5721625u, 5827903u, 5935489u, 6044391u, 6154617u, 6266175u, 6379073u, 6493319u, 6608921u, 6725887u, 6844225u, 6963943u, 7085049u, 7207551u, 321u, 681u, 1289u, 2241u, 3649u, 5641u, 8361u, 11969u, 16641u, 22569u, 29961u, 39041u, 50049u, 63241u, 78889u, 97281u, 118721u, 143529u, 172041u, 204609u, 241601u, 283401u, 330409u, 383041u, 441729u, 506921u, 579081u, 658689u, 746241u, 842249u, 947241u, 1061761u, 1186369u, 1321641u, 1468169u, 1626561u, 1797441u, 1981449u, 2179241u, 2391489u, 2618881u, 2862121u, 3121929u, 3399041u, 3694209u, 4008201u, 4341801u, 4695809u, 5071041u, 5468329u, 5888521u, 6332481u, 6801089u, 7295241u, 7815849u, 8363841u, 8940161u, 9545769u, 10181641u, 10848769u, 11548161u, 12280841u, 13047849u, 13850241u, 14689089u, 15565481u, 16480521u, 17435329u, 18431041u, 19468809u, 20549801u, 21675201u, 22846209u, 24064041u, 25329929u, 26645121u, 28010881u, 29428489u, 30899241u, 32424449u, 34005441u, 35643561u, 37340169u, 39096641u, 40914369u, 42794761u, 44739241u, 46749249u, 48826241u, 50971689u, 53187081u, 55473921u, 57833729u, 60268041u, 62778409u, 65366401u, 68033601u, 70781609u, 73612041u, 76526529u, 79526721u, 82614281u, 85790889u, 89058241u, 92418049u, 95872041u, 99421961u, 103069569u, 106816641u, 110664969u, 114616361u, 118672641u, 122835649u, 127107241u, 131489289u, 135983681u, 140592321u, 145317129u, 150160041u, 155123009u, 160208001u, 165417001u, 170752009u, 176215041u, 181808129u, 187533321u, 193392681u, 199388289u, 205522241u, 211796649u, 218213641u, 224775361u, 231483969u, 238341641u, 245350569u, 252512961u, 259831041u, 267307049u, 274943241u, 282741889u, 290705281u, 298835721u, 307135529u, 315607041u, 324252609u, 333074601u, 342075401u, 351257409u, 360623041u, 370174729u, 379914921u, 389846081u, 399970689u, 410291241u, 420810249u, 431530241u, 442453761u, 453583369u, 464921641u, 476471169u, 488234561u, 500214441u, 512413449u, 524834241u, 537479489u, 550351881u, 563454121u, 576788929u, 590359041u, 604167209u, 618216201u, 632508801u, 1683u, 3653u, 7183u, 13073u, 22363u, 36365u, 56695u, 85305u, 124515u, 177045u, 246047u, 335137u, 448427u, 590557u, 766727u, 982729u, 1244979u, 1560549u, 1937199u, 2383409u, 2908411u, 3522221u, 4235671u, 5060441u, 6009091u, 7095093u, 8332863u, 9737793u, 11326283u, 13115773u, 15124775u, 17372905u, 19880915u, 22670725u, 25765455u, 29189457u, 32968347u, 37129037u, 41699767u, 46710137u, 52191139u, 58175189u, 64696159u, 71789409u, 79491819u, 87841821u, 96879431u, 106646281u, 117185651u, 128542501u, 140763503u, 153897073u, 167993403u, 183104493u, 199284183u, 216588185u, 235074115u, 254801525u, 275831935u, 298228865u, 322057867u, 347386557u, 374284647u, 402823977u, 433078547u, 465124549u, 499040399u, 534906769u, 572806619u, 612825229u, 655050231u, 699571641u, 746481891u, 795875861u, 847850911u, 902506913u, 959946283u, 1020274013u, 1083597703u, 1150027593u, 1219676595u, 1292660325u, 1369097135u, 1449108145u, 1532817275u, 1620351277u, 1711839767u, 1807415257u, 1907213187u, 2011371957u, 2120032959u, 8989u, 19825u, 40081u, 75517u, 134245u, 227305u, 369305u, 579125u, 880685u, 1303777u, 1884961u, 2668525u, 3707509u, 5064793u, 6814249u, 9041957u, 11847485u, 15345233u, 19665841u, 24957661u, 31388293u, 39146185u, 48442297u, 59511829u, 72616013u, 88043969u, 106114625u, 127178701u, 151620757u, 179861305u, 212358985u, 249612805u, 292164445u, 340600625u, 395555537u, 457713341u, 527810725u, 606639529u, 695049433u, 793950709u, 904317037u, 1027188385u, 1163673953u, 1314955181u, 1482288821u, 1667010073u, 1870535785u, 2094367717u, 48639u, 108545u, 224143u, 433905u, 795455u, 1392065u, 2340495u, 3800305u, 5984767u, 9173505u, 13726991u, 20103025u, 28875327u, 40754369u, 56610575u, 77500017u, 104692735u, 139703809u, 184327311u, 240673265u, 311207743u, 398796225u, 506750351u, 638878193u, 799538175u, 993696769u, 1226990095u, 1505789553u, 1837271615u, 2229491905u, 265729u, 598417u, 1256465u, 2485825u, 4673345u, 8405905u, 14546705u, 24331777u, 39490049u, 62390545u, 96220561u, 145198913u, 214828609u, 312193553u, 446304145u, 628496897u, 872893441u, 1196924561u, 1621925137u, 2173806145u, 1462563u, 3317445u, 7059735u, 14218905u, 27298155u, 50250765u, 89129247u, 152951073u, 254831667u, 413442773u, 654862247u, 1014889769u, 1541911931u, 2300409629u, 3375210671u, 8097453u, 18474633u, 39753273u, 81270333u, 158819253u, 298199265u, 540279585u, 948062325u, 1616336765u, 45046719u, 103274625u, 224298231u, 464387817u, 921406335u, 1759885185u, 3248227095u, 251595969u, 579168825u, 1267854873u, 2653649025u, 1409933619u }; internal static readonly int[] window120 = new int[120] { 2, 20, 55, 108, 178, 266, 372, 494, 635, 792, 966, 1157, 1365, 1590, 1831, 2089, 2362, 2651, 2956, 3276, 3611, 3961, 4325, 4703, 5094, 5499, 5916, 6346, 6788, 7241, 7705, 8179, 8663, 9156, 9657, 10167, 10684, 11207, 11736, 12271, 12810, 13353, 13899, 14447, 14997, 15547, 16098, 16648, 17197, 17744, 18287, 18827, 19363, 19893, 20418, 20936, 21447, 21950, 22445, 22931, 23407, 23874, 24330, 24774, 25208, 25629, 26039, 26435, 26819, 27190, 27548, 27893, 28224, 28541, 28845, 29135, 29411, 29674, 29924, 30160, 30384, 30594, 30792, 30977, 31151, 31313, 31463, 31602, 31731, 31849, 31958, 32057, 32148, 32229, 32303, 32370, 32429, 32481, 32528, 32568, 32604, 32634, 32661, 32683, 32701, 32717, 32729, 32740, 32748, 32754, 32758, 32762, 32764, 32766, 32767, 32767, 32767, 32767, 32767, 32767 }; internal static readonly short[] logN400 = new short[21] { 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36 }; internal static readonly short[] cache_index50 = new short[105] { -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41, 82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41, 41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305, 318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240, 305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240, 240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387 }; internal static readonly byte[] cache_bits50 = new byte[392] { 40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28, 31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50, 51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65, 66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61, 64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92, 94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123, 124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94, 97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139, 142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35, 28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149, 153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225, 229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157, 166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63, 86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250, 25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180, 185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89, 110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41, 74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138, 163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214, 228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49, 90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47, 87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57, 106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187, 224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127, 182, 234 }; internal static readonly byte[] cache_caps50 = new byte[168] { 224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185, 178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240, 240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160, 160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172, 138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207, 204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185, 185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39, 207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201, 188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204, 204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175, 140, 66, 40 }; internal static readonly short[] fft_twiddles48000_960 = new short[960] { 32767, 0, 32766, -429, 32757, -858, 32743, -1287, 32724, -1715, 32698, -2143, 32667, -2570, 32631, -2998, 32588, -3425, 32541, -3851, 32488, -4277, 32429, -4701, 32364, -5125, 32295, -5548, 32219, -5971, 32138, -6393, 32051, -6813, 31960, -7231, 31863, -7650, 31760, -8067, 31652, -8481, 31539, -8895, 31419, -9306, 31294, -9716, 31165, -10126, 31030, -10532, 30889, -10937, 30743, -11340, 30592, -11741, 30436, -12141, 30274, -12540, 30107, -12935, 29936, -13328, 29758, -13718, 29577, -14107, 29390, -14493, 29197, -14875, 29000, -15257, 28797, -15635, 28590, -16010, 28379, -16384, 28162, -16753, 27940, -17119, 27714, -17484, 27482, -17845, 27246, -18205, 27006, -18560, 26760, -18911, 26510, -19260, 26257, -19606, 25997, -19947, 25734, -20286, 25466, -20621, 25194, -20952, 24918, -21281, 24637, -21605, 24353, -21926, 24063, -22242, 23770, -22555, 23473, -22865, 23171, -23171, 22866, -23472, 22557, -23769, 22244, -24063, 21927, -24352, 21606, -24636, 21282, -24917, 20954, -25194, 20622, -25465, 20288, -25733, 19949, -25997, 19607, -26255, 19261, -26509, 18914, -26760, 18561, -27004, 18205, -27246, 17846, -27481, 17485, -27713, 17122, -27940, 16755, -28162, 16385, -28378, 16012, -28590, 15636, -28797, 15258, -28999, 14878, -29197, 14494, -29389, 14108, -29576, 13720, -29757, 13329, -29934, 12937, -30107, 12540, -30274, 12142, -30435, 11744, -30592, 11342, -30743, 10939, -30889, 10534, -31030, 10127, -31164, 9718, -31294, 9307, -31418, 8895, -31537, 8482, -31652, 8067, -31759, 7650, -31862, 7233, -31960, 6815, -32051, 6393, -32138, 5973, -32219, 5549, -32294, 5127, -32364, 4703, -32429, 4278, -32487, 3852, -32541, 3426, -32588, 2999, -32630, 2572, -32667, 2144, -32698, 1716, -32724, 1287, -32742, 860, -32757, 430, -32766, 0, -32767, -429, -32766, -858, -32757, -1287, -32743, -1715, -32724, -2143, -32698, -2570, -32667, -2998, -32631, -3425, -32588, -3851, -32541, -4277, -32488, -4701, -32429, -5125, -32364, -5548, -32295, -5971, -32219, -6393, -32138, -6813, -32051, -7231, -31960, -7650, -31863, -8067, -31760, -8481, -31652, -8895, -31539, -9306, -31419, -9716, -31294, -10126, -31165, -10532, -31030, -10937, -30889, -11340, -30743, -11741, -30592, -12141, -30436, -12540, -30274, -12935, -30107, -13328, -29936, -13718, -29758, -14107, -29577, -14493, -29390, -14875, -29197, -15257, -29000, -15635, -28797, -16010, -28590, -16384, -28379, -16753, -28162, -17119, -27940, -17484, -27714, -17845, -27482, -18205, -27246, -18560, -27006, -18911, -26760, -19260, -26510, -19606, -26257, -19947, -25997, -20286, -25734, -20621, -25466, -20952, -25194, -21281, -24918, -21605, -24637, -21926, -24353, -22242, -24063, -22555, -23770, -22865, -23473, -23171, -23171, -23472, -22866, -23769, -22557, -24063, -22244, -24352, -21927, -24636, -21606, -24917, -21282, -25194, -20954, -25465, -20622, -25733, -20288, -25997, -19949, -26255, -19607, -26509, -19261, -26760, -18914, -27004, -18561, -27246, -18205, -27481, -17846, -27713, -17485, -27940, -17122, -28162, -16755, -28378, -16385, -28590, -16012, -28797, -15636, -28999, -15258, -29197, -14878, -29389, -14494, -29576, -14108, -29757, -13720, -29934, -13329, -30107, -12937, -30274, -12540, -30435, -12142, -30592, -11744, -30743, -11342, -30889, -10939, -31030, -10534, -31164, -10127, -31294, -9718, -31418, -9307, -31537, -8895, -31652, -8482, -31759, -8067, -31862, -7650, -31960, -7233, -32051, -6815, -32138, -6393, -32219, -5973, -32294, -5549, -32364, -5127, -32429, -4703, -32487, -4278, -32541, -3852, -32588, -3426, -32630, -2999, -32667, -2572, -32698, -2144, -32724, -1716, -32742, -1287, -32757, -860, -32766, -430, -32767, 0, -32766, 429, -32757, 858, -32743, 1287, -32724, 1715, -32698, 2143, -32667, 2570, -32631, 2998, -32588, 3425, -32541, 3851, -32488, 4277, -32429, 4701, -32364, 5125, -32295, 5548, -32219, 5971, -32138, 6393, -32051, 6813, -31960, 7231, -31863, 7650, -31760, 8067, -31652, 8481, -31539, 8895, -31419, 9306, -31294, 9716, -31165, 10126, -31030, 10532, -30889, 10937, -30743, 11340, -30592, 11741, -30436, 12141, -30274, 12540, -30107, 12935, -29936, 13328, -29758, 13718, -29577, 14107, -29390, 14493, -29197, 14875, -29000, 15257, -28797, 15635, -28590, 16010, -28379, 16384, -28162, 16753, -27940, 17119, -27714, 17484, -27482, 17845, -27246, 18205, -27006, 18560, -26760, 18911, -26510, 19260, -26257, 19606, -25997, 19947, -25734, 20286, -25466, 20621, -25194, 20952, -24918, 21281, -24637, 21605, -24353, 21926, -24063, 22242, -23770, 22555, -23473, 22865, -23171, 23171, -22866, 23472, -22557, 23769, -22244, 24063, -21927, 24352, -21606, 24636, -21282, 24917, -20954, 25194, -20622, 25465, -20288, 25733, -19949, 25997, -19607, 26255, -19261, 26509, -18914, 26760, -18561, 27004, -18205, 27246, -17846, 27481, -17485, 27713, -17122, 27940, -16755, 28162, -16385, 28378, -16012, 28590, -15636, 28797, -15258, 28999, -14878, 29197, -14494, 29389, -14108, 29576, -13720, 29757, -13329, 29934, -12937, 30107, -12540, 30274, -12142, 30435, -11744, 30592, -11342, 30743, -10939, 30889, -10534, 31030, -10127, 31164, -9718, 31294, -9307, 31418, -8895, 31537, -8482, 31652, -8067, 31759, -7650, 31862, -7233, 31960, -6815, 32051, -6393, 32138, -5973, 32219, -5549, 32294, -5127, 32364, -4703, 32429, -4278, 32487, -3852, 32541, -3426, 32588, -2999, 32630, -2572, 32667, -2144, 32698, -1716, 32724, -1287, 32742, -860, 32757, -430, 32766, 0, 32767, 429, 32766, 858, 32757, 1287, 32743, 1715, 32724, 2143, 32698, 2570, 32667, 2998, 32631, 3425, 32588, 3851, 32541, 4277, 32488, 4701, 32429, 5125, 32364, 5548, 32295, 5971, 32219, 6393, 32138, 6813, 32051, 7231, 31960, 7650, 31863, 8067, 31760, 8481, 31652, 8895, 31539, 9306, 31419, 9716, 31294, 10126, 31165, 10532, 31030, 10937, 30889, 11340, 30743, 11741, 30592, 12141, 30436, 12540, 30274, 12935, 30107, 13328, 29936, 13718, 29758, 14107, 29577, 14493, 29390, 14875, 29197, 15257, 29000, 15635, 28797, 16010, 28590, 16384, 28379, 16753, 28162, 17119, 27940, 17484, 27714, 17845, 27482, 18205, 27246, 18560, 27006, 18911, 26760, 19260, 26510, 19606, 26257, 19947, 25997, 20286, 25734, 20621, 25466, 20952, 25194, 21281, 24918, 21605, 24637, 21926, 24353, 22242, 24063, 22555, 23770, 22865, 23473, 23171, 23171, 23472, 22866, 23769, 22557, 24063, 22244, 24352, 21927, 24636, 21606, 24917, 21282, 25194, 20954, 25465, 20622, 25733, 20288, 25997, 19949, 26255, 19607, 26509, 19261, 26760, 18914, 27004, 18561, 27246, 18205, 27481, 17846, 27713, 17485, 27940, 17122, 28162, 16755, 28378, 16385, 28590, 16012, 28797, 15636, 28999, 15258, 29197, 14878, 29389, 14494, 29576, 14108, 29757, 13720, 29934, 13329, 30107, 12937, 30274, 12540, 30435, 12142, 30592, 11744, 30743, 11342, 30889, 10939, 31030, 10534, 31164, 10127, 31294, 9718, 31418, 9307, 31537, 8895, 31652, 8482, 31759, 8067, 31862, 7650, 31960, 7233, 32051, 6815, 32138, 6393, 32219, 5973, 32294, 5549, 32364, 5127, 32429, 4703, 32487, 4278, 32541, 3852, 32588, 3426, 32630, 2999, 32667, 2572, 32698, 2144, 32724, 1716, 32742, 1287, 32757, 860, 32766, 430 }; internal static readonly short[] fft_bitrev480 = new short[480] { 0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448, 8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456, 16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464, 24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472, 4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452, 12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460, 20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468, 28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476, 1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449, 9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457, 17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465, 25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473, 5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453, 13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461, 21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469, 29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477, 2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450, 10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458, 18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466, 26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474, 6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454, 14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462, 22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470, 30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478, 3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451, 11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459, 19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467, 27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475, 7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455, 15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463, 23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471, 31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479 }; internal static readonly short[] fft_bitrev240 = new short[240] { 0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224, 4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228, 8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232, 12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236, 1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225, 5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229, 9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233, 13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237, 2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226, 6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230, 10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234, 14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238, 3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227, 7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231, 11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235, 15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239 }; internal static readonly short[] fft_bitrev120 = new short[120] { 0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112, 4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116, 1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113, 5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117, 2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114, 6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118, 3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115, 7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119 }; internal static readonly short[] fft_bitrev60 = new short[60] { 0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56, 1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57, 2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58, 3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59 }; internal static readonly FFTState fft_state48000_960_0 = new FFTState { nfft = 480, scale = 17476, scale_shift = 8, shift = -1, factors = new short[16] { 5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0 }, bitrev = fft_bitrev480, twiddles = fft_twiddles48000_960 }; internal static readonly FFTState fft_state48000_960_1 = new FFTState { nfft = 240, scale = 17476, scale_shift = 7, shift = 1, factors = new short[16] { 5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, bitrev = fft_bitrev240, twiddles = fft_twiddles48000_960 }; internal static readonly FFTState fft_state48000_960_2 = new FFTState { nfft = 120, scale = 17476, scale_shift = 6, shift = 2, factors = new short[16] { 5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, bitrev = fft_bitrev120, twiddles = fft_twiddles48000_960 }; internal static readonly FFTState fft_state48000_960_3 = new FFTState { nfft = 60, scale = 17476, scale_shift = 5, shift = 3, factors = new short[16] { 5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, bitrev = fft_bitrev60, twiddles = fft_twiddles48000_960 }; internal static readonly short[] mdct_twiddles960 = new short[1800] { 32767, 32767, 32767, 32766, 32765, 32763, 32761, 32759, 32756, 32753, 32750, 32746, 32742, 32738, 32733, 32728, 32722, 32717, 32710, 32704, 32697, 32690, 32682, 32674, 32666, 32657, 32648, 32639, 32629, 32619, 32609, 32598, 32587, 32576, 32564, 32552, 32539, 32526, 32513, 32500, 32486, 32472, 32457, 32442, 32427, 32411, 32395, 32379, 32362, 32345, 32328, 32310, 32292, 32274, 32255, 32236, 32217, 32197, 32177, 32157, 32136, 32115, 32093, 32071, 32049, 32027, 32004, 31981, 31957, 31933, 31909, 31884, 31859, 31834, 31809, 31783, 31756, 31730, 31703, 31676, 31648, 31620, 31592, 31563, 31534, 31505, 31475, 31445, 31415, 31384, 31353, 31322, 31290, 31258, 31226, 31193, 31160, 31127, 31093, 31059, 31025, 30990, 30955, 30920, 30884, 30848, 30812, 30775, 30738, 30701, 30663, 30625, 30587, 30548, 30509, 30470, 30430, 30390, 30350, 30309, 30269, 30227, 30186, 30144, 30102, 30059, 30016, 29973, 29930, 29886, 29842, 29797, 29752, 29707, 29662, 29616, 29570, 29524, 29477, 29430, 29383, 29335, 29287, 29239, 29190, 29142, 29092, 29043, 28993, 28943, 28892, 28842, 28791, 28739, 28688, 28636, 28583, 28531, 28478, 28425, 28371, 28317, 28263, 28209, 28154, 28099, 28044, 27988, 27932, 27876, 27820, 27763, 27706, 27648, 27591, 27533, 27474, 27416, 27357, 27298, 27238, 27178, 27118, 27058, 26997, 26936, 26875, 26814, 26752, 26690, 26628, 26565, 26502, 26439, 26375, 26312, 26247, 26183, 26119, 26054, 25988, 25923, 25857, 25791, 25725, 25658, 25592, 25524, 25457, 25389, 25322, 25253, 25185, 25116, 25047, 24978, 24908, 24838, 24768, 24698, 24627, 24557, 24485, 24414, 24342, 24270, 24198, 24126, 24053, 23980, 23907, 23834, 23760, 23686, 23612, 23537, 23462, 23387, 23312, 23237, 23161, 23085, 23009, 22932, 22856, 22779, 22701, 22624, 22546, 22468, 22390, 22312, 22233, 22154, 22075, 21996, 21916, 21836, 21756, 21676, 21595, 21515, 21434, 21352, 21271, 21189, 21107, 21025, 20943, 20860, 20777, 20694, 20611, 20528, 20444, 20360, 20276, 20192, 20107, 20022, 19937, 19852, 19767, 19681, 19595, 19509, 19423, 19336, 19250, 19163, 19076, 18988, 18901, 18813, 18725, 18637, 18549, 18460, 18372, 18283, 18194, 18104, 18015, 17925, 17835, 17745, 17655, 17565, 17474, 17383, 17292, 17201, 17110, 17018, 16927, 16835, 16743, 16650, 16558, 16465, 16372, 16279, 16186, 16093, 15999, 15906, 15812, 15718, 15624, 15529, 15435, 15340, 15245, 15150, 15055, 14960, 14864, 14769, 14673, 14577, 14481, 14385, 14288, 14192, 14095, 13998, 13901, 13804, 13706, 13609, 13511, 13414, 13316, 13218, 13119, 13021, 12923, 12824, 12725, 12626, 12527, 12428, 12329, 12230, 12130, 12030, 11930, 11831, 11730, 11630, 11530, 11430, 11329, 11228, 11128, 11027, 10926, 10824, 10723, 10622, 10520, 10419, 10317, 10215, 10113, 10011, 9909, 9807, 9704, 9602, 9499, 9397, 9294, 9191, 9088, 8985, 8882, 8778, 8675, 8572, 8468, 8364, 8261, 8157, 8053, 7949, 7845, 7741, 7637, 7532, 7428, 7323, 7219, 7114, 7009, 6905, 6800, 6695, 6590, 6485, 6380, 6274, 6169, 6064, 5958, 5853, 5747, 5642, 5536, 5430, 5325, 5219, 5113, 5007, 4901, 4795, 4689, 4583, 4476, 4370, 4264, 4157, 4051, 3945, 3838, 3732, 3625, 3518, 3412, 3305, 3198, 3092, 2985, 2878, 2771, 2664, 2558, 2451, 2344, 2237, 2130, 2023, 1916, 1809, 1702, 1594, 1487, 1380, 1273, 1166, 1059, 952, 844, 737, 630, 523, 416, 308, 201, 94, -13, -121, -228, -335, -442, -550, -657, -764, -871, -978, -1086, -1193, -1300, -1407, -1514, -1621, -1728, -1835, -1942, -2049, -2157, -2263, -2370, -2477, -2584, -2691, -2798, -2905, -3012, -3118, -3225, -3332, -3439, -3545, -3652, -3758, -3865, -3971, -4078, -4184, -4290, -4397, -4503, -4609, -4715, -4821, -4927, -5033, -5139, -5245, -5351, -5457, -5562, -5668, -5774, -5879, -5985, -6090, -6195, -6301, -6406, -6511, -6616, -6721, -6826, -6931, -7036, -7140, -7245, -7349, -7454, -7558, -7663, -7767, -7871, -7975, -8079, -8183, -8287, -8390, -8494, -8597, -8701, -8804, -8907, -9011, -9114, -9217, -9319, -9422, -9525, -9627, -9730, -9832, -9934, -10037, -10139, -10241, -10342, -10444, -10546, -10647, -10748, -10850, -10951, -11052, -11153, -11253, -11354, -11455, -11555, -11655, -11756, -11856, -11955, -12055, -12155, -12254, -12354, -12453, -12552, -12651, -12750, -12849, -12947, -13046, -13144, -13242, -13340, -13438, -13536, -13633, -13731, -13828, -13925, -14022, -14119, -14216, -14312, -14409, -14505, -14601, -14697, -14793, -14888, -14984, -15079, -15174, -15269, -15364, -15459, -15553, -15647, -15741, -15835, -15929, -16023, -16116, -16210, -16303, -16396, -16488, -16581, -16673, -16766, -16858, -16949, -17041, -17133, -17224, -17315, -17406, -17497, -17587, -17678, -17768, -17858, -17948, -18037, -18127, -18216, -18305, -18394, -18483, -18571, -18659, -18747, -18835, -18923, -19010, -19098, -19185, -19271, -19358, -19444, -19531, -19617, -19702, -19788, -19873, -19959, -20043, -20128, -20213, -20297, -20381, -20465, -20549, -20632, -20715, -20798, -20881, -20963, -21046, -21128, -21210, -21291, -21373, -21454, -21535, -21616, -21696, -21776, -21856, -21936, -22016, -22095, -22174, -22253, -22331, -22410, -22488, -22566, -22643, -22721, -22798, -22875, -22951, -23028, -23104, -23180, -23256, -23331, -23406, -23481, -23556, -23630, -23704, -23778, -23852, -23925, -23998, -24071, -24144, -24216, -24288, -24360, -24432, -24503, -24574, -24645, -24716, -24786, -24856, -24926, -24995, -25064, -25133, -25202, -25270, -25339, -25406, -25474, -25541, -25608, -25675, -25742, -25808, -25874, -25939, -26005, -26070, -26135, -26199, -26264, -26327, -26391, -26455, -26518, -26581, -26643, -26705, -26767, -26829, -26891, -26952, -27013, -27073, -27133, -27193, -27253, -27312, -27372, -27430, -27489, -27547, -27605, -27663, -27720, -27777, -27834, -27890, -27946, -28002, -28058, -28113, -28168, -28223, -28277, -28331, -28385, -28438, -28491, -28544, -28596, -28649, -28701, -28752, -28803, -28854, -28905, -28955, -29006, -29055, -29105, -29154, -29203, -29251, -29299, -29347, -29395, -29442, -29489, -29535, -29582, -29628, -29673, -29719, -29764, -29808, -29853, -29897, -29941, -29984, -30027, -30070, -30112, -30154, -30196, -30238, -30279, -30320, -30360, -30400, -30440, -30480, -30519, -30558, -30596, -30635, -30672, -30710, -30747, -30784, -30821, -30857, -30893, -30929, -30964, -30999, -31033, -31068, -31102, -31135, -31168, -31201, -31234, -31266, -31298, -31330, -31361, -31392, -31422, -31453, -31483, -31512, -31541, -31570, -31599, -31627, -31655, -31682, -31710, -31737, -31763, -31789, -31815, -31841, -31866, -31891, -31915, -31939, -31963, -31986, -32010, -32032, -32055, -32077, -32099, -32120, -32141, -32162, -32182, -32202, -32222, -32241, -32260, -32279, -32297, -32315, -32333, -32350, -32367, -32383, -32399, -32415, -32431, -32446, -32461, -32475, -32489, -32503, -32517, -32530, -32542, -32555, -32567, -32579, -32590, -32601, -32612, -32622, -32632, -32641, -32651, -32659, -32668, -32676, -32684, -32692, -32699, -32706, -32712, -32718, -32724, -32729, -32734, -32739, -32743, -32747, -32751, -32754, -32757, -32760, -32762, -32764, -32765, -32767, -32767, -32767, 32767, 32767, 32765, 32761, 32756, 32750, 32742, 32732, 32722, 32710, 32696, 32681, 32665, 32647, 32628, 32608, 32586, 32562, 32538, 32512, 32484, 32455, 32425, 32393, 32360, 32326, 32290, 32253, 32214, 32174, 32133, 32090, 32046, 32001, 31954, 31906, 31856, 31805, 31753, 31700, 31645, 31588, 31530, 31471, 31411, 31349, 31286, 31222, 31156, 31089, 31020, 30951, 30880, 30807, 30733, 30658, 30582, 30504, 30425, 30345, 30263, 30181, 30096, 30011, 29924, 29836, 29747, 29656, 29564, 29471, 29377, 29281, 29184, 29086, 28987, 28886, 28784, 28681, 28577, 28471, 28365, 28257, 28147, 28037, 27925, 27812, 27698, 27583, 27467, 27349, 27231, 27111, 26990, 26868, 26744, 26620, 26494, 26367, 26239, 26110, 25980, 25849, 25717, 25583, 25449, 25313, 25176, 25038, 24900, 24760, 24619, 24477, 24333, 24189, 24044, 23898, 23751, 23602, 23453, 23303, 23152, 22999, 22846, 22692, 22537, 22380, 22223, 22065, 21906, 21746, 21585, 21423, 21261, 21097, 20933, 20767, 20601, 20434, 20265, 20096, 19927, 19756, 19584, 19412, 19239, 19065, 18890, 18714, 18538, 18361, 18183, 18004, 17824, 17644, 17463, 17281, 17098, 16915, 16731, 16546, 16361, 16175, 15988, 15800, 15612, 15423, 15234, 15043, 14852, 14661, 14469, 14276, 14083, 13889, 13694, 13499, 13303, 13107, 12910, 12713, 12515, 12317, 12118, 11918, 11718, 11517, 11316, 11115, 10913, 10710, 10508, 10304, 10100, 9896, 9691, 9486, 9281, 9075, 8869, 8662, 8455, 8248, 8040, 7832, 7623, 7415, 7206, 6996, 6787, 6577, 6366, 6156, 5945, 5734, 5523, 5311, 5100, 4888, 4675, 4463, 4251, 4038, 3825, 3612, 3399, 3185, 2972, 2758, 2544, 2330, 2116, 1902, 1688, 1474, 1260, 1045, 831, 617, 402, 188, -27, -241, -456, -670, -885, -1099, -1313, -1528, -1742, -1956, -2170, -2384, -2598, -2811, -3025, -3239, -3452, -3665, -3878, -4091, -4304, -4516, -4728, -4941, -5153, -5364, -5576, -5787, -5998, -6209, -6419, -6629, -6839, -7049, -7258, -7467, -7676, -7884, -8092, -8300, -8507, -8714, -8920, -9127, -9332, -9538, -9743, -9947, -10151, -10355, -10558, -10761, -10963, -11165, -11367, -11568, -11768, -11968, -12167, -12366, -12565, -12762, -12960, -13156, -13352, -13548, -13743, -13937, -14131, -14324, -14517, -14709, -14900, -15091, -15281, -15470, -15659, -15847, -16035, -16221, -16407, -16593, -16777, -16961, -17144, -17326, -17508, -17689, -17869, -18049, -18227, -18405, -18582, -18758, -18934, -19108, -19282, -19455, -19627, -19799, -19969, -20139, -20308, -20475, -20642, -20809, -20974, -21138, -21301, -21464, -21626, -21786, -21946, -22105, -22263, -22420, -22575, -22730, -22884, -23037, -23189, -23340, -23490, -23640, -23788, -23935, -24080, -24225, -24369, -24512, -24654, -24795, -24934, -25073, -25211, -25347, -25482, -25617, -25750, -25882, -26013, -26143, -26272, -26399, -26526, -26651, -26775, -26898, -27020, -27141, -27260, -27379, -27496, -27612, -27727, -27841, -27953, -28065, -28175, -28284, -28391, -28498, -28603, -28707, -28810, -28911, -29012, -29111, -29209, -29305, -29401, -29495, -29587, -29679, -29769, -29858, -29946, -30032, -30118, -30201, -30284, -30365, -30445, -30524, -30601, -30677, -30752, -30825, -30897, -30968, -31038, -31106, -31172, -31238, -31302, -31365, -31426, -31486, -31545, -31602, -31658, -31713, -31766, -31818, -31869, -31918, -31966, -32012, -32058, -32101, -32144, -32185, -32224, -32262, -32299, -32335, -32369, -32401, -32433, -32463, -32491, -32518, -32544, -32568, -32591, -32613, -32633, -32652, -32669, -32685, -32700, -32713, -32724, -32735, -32744, -32751, -32757, -32762, -32766, -32767, 32767, 32764, 32755, 32741, 32720, 32694, 32663, 32626, 32583, 32535, 32481, 32421, 32356, 32286, 32209, 32128, 32041, 31948, 31850, 31747, 31638, 31523, 31403, 31278, 31148, 31012, 30871, 30724, 30572, 30415, 30253, 30086, 29913, 29736, 29553, 29365, 29172, 28974, 28771, 28564, 28351, 28134, 27911, 27684, 27452, 27216, 26975, 26729, 26478, 26223, 25964, 25700, 25432, 25159, 24882, 24601, 24315, 24026, 23732, 23434, 23133, 22827, 22517, 22204, 21886, 21565, 21240, 20912, 20580, 20244, 19905, 19563, 19217, 18868, 18516, 18160, 17802, 17440, 17075, 16708, 16338, 15964, 15588, 15210, 14829, 14445, 14059, 13670, 13279, 12886, 12490, 12093, 11693, 11291, 10888, 10482, 10075, 9666, 9255, 8843, 8429, 8014, 7597, 7180, 6760, 6340, 5919, 5496, 5073, 4649, 4224, 3798, 3372, 2945, 2517, 2090, 1661, 1233, 804, 375, -54, -483, -911, -1340, -1768, -2197, -2624, -3052, -3479, -3905, -4330, -4755, -5179, -5602, -6024, -6445, -6865, -7284, -7702, -8118, -8533, -8946, -9358, -9768, -10177, -10584, -10989, -11392, -11793, -12192, -12589, -12984, -13377, -13767, -14155, -14541, -14924, -15305, -15683, -16058, -16430, -16800, -17167, -17531, -17892, -18249, -18604, -18956, -19304, -19649, -19990, -20329, -20663, -20994, -21322, -21646, -21966, -22282, -22595, -22904, -23208, -23509, -23806, -24099, -24387, -24672, -24952, -25228, -25499, -25766, -26029, -26288, -26541, -26791, -27035, -27275, -27511, -27741, -27967, -28188, -28405, -28616, -28823, -29024, -29221, -29412, -29599, -29780, -29957, -30128, -30294, -30455, -30611, -30761, -30906, -31046, -31181, -31310, -31434, -31552, -31665, -31773, -31875, -31972, -32063, -32149, -32229, -32304, -32373, -32437, -32495, -32547, -32594, -32635, -32671, -32701, -32726, -32745, -32758, -32766, 32767, 32754, 32717, 32658, 32577, 32473, 32348, 32200, 32029, 31837, 31624, 31388, 31131, 30853, 30553, 30232, 29891, 29530, 29148, 28746, 28324, 27883, 27423, 26944, 26447, 25931, 25398, 24847, 24279, 23695, 23095, 22478, 21846, 21199, 20538, 19863, 19174, 18472, 17757, 17030, 16291, 15541, 14781, 14010, 13230, 12441, 11643, 10837, 10024, 9204, 8377, 7545, 6708, 5866, 5020, 4171, 3319, 2464, 1608, 751, -107, -965, -1822, -2678, -3532, -4383, -5232, -6077, -6918, -7754, -8585, -9409, -10228, -11039, -11843, -12639, -13426, -14204, -14972, -15730, -16477, -17213, -17937, -18648, -19347, -20033, -20705, -21363, -22006, -22634, -23246, -23843, -24423, -24986, -25533, -26062, -26573, -27066, -27540, -27995, -28431, -28848, -29245, -29622, -29979, -30315, -30630, -30924, -31197, -31449, -31679, -31887, -32074, -32239, -32381, -32501, -32600, -32675, -32729, -32759 }; internal static readonly int[] intensity_thresholds = new int[21] { 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 36, 44, 50, 56, 62, 67, 72, 79, 88, 106, 134 }; internal static readonly int[] intensity_histeresis = new int[21] { 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 5, 6, 8, 8 }; } internal static class VQ { private static int[] SPREAD_FACTOR = new int[3] { 15, 10, 5 }; internal static void exp_rotation1(int[] X, int X_ptr, int len, int stride, int c, int s) { int num = X_ptr; int a = Inlines.NEG16(s); for (int i = 0; i < len - stride; i++) { int b = X[num]; int b2 = X[num + stride]; X[num + stride] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MAC16_16(Inlines.MULT16_16(c, b2), s, b), 15)); X[num] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MAC16_16(Inlines.MULT16_16(c, b), a, b2), 15)); num++; } num = X_ptr + (len - 2 * stride - 1); for (int i = len - 2 * stride - 1; i >= 0; i--) { int b = X[num]; int b2 = X[num + stride]; X[num + stride] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MAC16_16(Inlines.MULT16_16(c, b2), s, b), 15)); X[num] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MAC16_16(Inlines.MULT16_16(c, b), a, b2), 15)); num--; } } internal static void exp_rotation(int[] X, int X_ptr, int len, int dir, int stride, int K, int spread) { int i = 0; if (2 * K >= len || spread == 0) { return; } int num = SPREAD_FACTOR[spread - 1]; int num2 = Inlines.celt_div(Inlines.MULT16_16(32767, len), len + num * K); int num3 = Inlines.HALF16(Inlines.MULT16_16_Q15(num2, num2)); int num4 = Inlines.celt_cos_norm(Inlines.EXTEND32(num3)); int num5 = Inlines.celt_cos_norm(Inlines.EXTEND32(Inlines.SUB16(32767, num3))); if (len >= 8 * stride) { for (i = 1; (i * i + i) * stride + (stride >> 2) < len; i++) { } } len = Inlines.celt_udiv(len, stride); for (int j = 0; j < stride; j++) { if (dir < 0) { if (i != 0) { exp_rotation1(X, X_ptr + j * len, len, i, num5, num4); } exp_rotation1(X, X_ptr + j * len, len, 1, num4, num5); } else { exp_rotation1(X, X_ptr + j * len, len, 1, num4, (short)(-num5)); if (i != 0) { exp_rotation1(X, X_ptr + j * len, len, i, num5, (short)(-num4)); } } } } internal static void normalise_residual(int[] iy, int[] X, int X_ptr, int N, int Ryy, int gain) { int num = Inlines.celt_ilog2(Ryy) >> 1; int x = Inlines.VSHR32(Ryy, 2 * (num - 7)); int a = Inlines.MULT16_16_P15(Inlines.celt_rsqrt_norm(x), gain); int num2 = 0; do { X[X_ptr + num2] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MULT16_16(a, iy[num2]), num + 1)); } while (++num2 < N); } internal static uint extract_collapse_mask(int[] iy, int N, int B) { if (B <= 1) { return 1u; } int num = Inlines.celt_udiv(N, B); uint num2 = 0u; int num3 = 0; do { uint num4 = 0u; int num5 = 0; do { num4 |= (uint)iy[num3 * num + num5]; } while (++num5 < num); num2 |= (uint)(((num4 != 0) ? 1 : 0) << num3); } while (++num3 < B); return num2; } internal static uint alg_quant(int[] X, int X_ptr, int N, int K, int spread, int B, EntropyCoder enc) { int[] array = new int[N]; int[] array2 = new int[N]; int[] array3 = new int[N]; exp_rotation(X, X_ptr, N, 1, B, K, spread); int num = 0; int num2 = 0; do { int num3 = X_ptr + num2; array3[num2] = ((X[num3] > 0) ? 1 : (-1)); X[num3] = Inlines.ABS16(X[num3]); array2[num2] = 0; array[num2] = 0; } while (++num2 < N); int num4; int num5 = (num4 = 0); int num6 = K; if (K > N >> 1) { num2 = 0; do { num += X[X_ptr + num2]; } while (++num2 < N); if (num <= K) { X[X_ptr] = 16384; num2 = X_ptr + 1; do { X[num2] = 0; } while (++num2 < N + X_ptr); num = 16384; } int b = Inlines.EXTRACT16(Inlines.MULT16_32_Q16(K - 1, Inlines.celt_rcp(num))); num2 = 0; do { array2[num2] = Inlines.MULT16_16_Q15(X[X_ptr + num2], b); array[num2] = array2[num2]; num4 = Inlines.MAC16_16(num4, array[num2], array[num2]); num5 = Inlines.MAC16_16(num5, X[X_ptr + num2], array[num2]); array[num2] *= 2; num6 -= array2[num2]; } while (++num2 < N); } if (num6 > N + 3) { int num7 = num6; num4 = Inlines.MAC16_16(num4, num7, num7); num4 = Inlines.MAC16_16(num4, num7, array[0]); array2[0] += num6; num6 = 0; } int num8 = 1; for (int i = 0; i < num6; i++) { int b2 = -32767; int a = 0; int shift = 1 + Inlines.celt_ilog2(K - num6 + i + 1); int num9 = 0; num4 = Inlines.ADD16(num4, 1); num2 = 0; do { int num10 = Inlines.EXTRACT16(Inlines.SHR32(Inlines.ADD32(num5, Inlines.EXTEND32(X[X_ptr + num2])), shift)); int num11 = Inlines.ADD16(num4, array[num2]); num10 = Inlines.MULT16_16_Q15(num10, num10); if (Inlines.MULT16_16(a, num10) > Inlines.MULT16_16(num11, b2)) { a = num11; b2 = num10; num9 = num2; } } while (++num2 < N); num5 = Inlines.ADD32(num5, Inlines.EXTEND32(X[X_ptr + num9])); num4 = Inlines.ADD16(num4, array[num9]); array[num9] += 2 * num8; array2[num9]++; } num2 = 0; do { X[X_ptr + num2] = Inlines.MULT16_16(array3[num2], X[X_ptr + num2]); array2[num2] = ((array3[num2] < 0) ? (-array2[num2]) : array2[num2]); } while (++num2 < N); CWRS.encode_pulses(array2, N, K, enc); return extract_collapse_mask(array2, N, B); } internal static uint alg_unquant(int[] X, int X_ptr, int N, int K, int spread, int B, EntropyCoder dec, int gain) { int[] array = new int[N]; int ryy = CWRS.decode_pulses(array, N, K, dec); normalise_residual(array, X, X_ptr, N, ryy, gain); exp_rotation(X, X_ptr, N, -1, B, K, spread); return extract_collapse_mask(array, N, B); } internal static void renormalise_vector(int[] X, int X_ptr, int N, int gain) { int num = 1 + Kernels.celt_inner_prod(X, X_ptr, X, X_ptr, N); int num2 = Inlines.celt_ilog2(num) >> 1; int x = Inlines.VSHR32(num, 2 * (num2 - 7)); int a = Inlines.MULT16_16_P15(Inlines.celt_rsqrt_norm(x), gain); int num3 = X_ptr; for (int i = 0; i < N; i++) { X[num3] = Inlines.EXTRACT16(Inlines.PSHR32(Inlines.MULT16_16(a, X[num3]), num2 + 1)); num3++; } } internal static int stereo_itheta(int[] X, int X_ptr, int[] Y, int Y_ptr, int stereo, int N) { int num; int num2 = (num = 1); if (stereo != 0) { for (int i = 0; i < N; i++) { int num3 = Inlines.ADD16(Inlines.SHR16(X[X_ptr + i], 1), Inlines.SHR16(Y[Y_ptr + i], 1)); int num4 = Inlines.SUB16(Inlines.SHR16(X[X_ptr + i], 1), Inlines.SHR16(Y[Y_ptr + i], 1)); num2 = Inlines.MAC16_16(num2, num3, num3); num = Inlines.MAC16_16(num, num4, num4); } } else { num2 += Kernels.celt_inner_prod(X, X_ptr, X, X_ptr, N); num += Kernels.celt_inner_prod(Y, Y_ptr, Y, Y_ptr, N); } int x = Inlines.celt_sqrt(num2); int y = Inlines.celt_sqrt(num); return Inlines.MULT16_16_Q15(20861, Inlines.celt_atan2p(y, x)); } } } namespace Concentus.Celt.Enums { internal static class Spread { public const int SPREAD_NONE = 0; public const int SPREAD_LIGHT = 1; public const int SPREAD_NORMAL = 2; public const int SPREAD_AGGRESSIVE = 3; } } namespace Concentus.Celt.Structs { internal class AnalysisInfo { internal bool enabled = false; internal int valid = 0; internal float tonality = 0f; internal float tonality_slope = 0f; internal float noisiness = 0f; internal float activity = 0f; internal float music_prob = 0f; internal int bandwidth = 0; internal AnalysisInfo() { } internal void Assign(AnalysisInfo other) { valid = other.valid; tonality = other.tonality; tonality_slope = other.tonality_slope; noisiness = other.noisiness; activity = other.activity; music_prob = other.music_prob; bandwidth = other.bandwidth; } internal void Reset() { valid = 0; tonality = 0f; tonality_slope = 0f; noisiness = 0f; activity = 0f; music_prob = 0f; bandwidth = 0; } } internal class CeltDecoder { internal CeltMode mode = null; internal int overlap = 0; internal int channels = 0; internal int stream_channels = 0; internal int downsample = 0; internal int start = 0; internal int end = 0; internal int signalling = 0; internal uint rng = 0u; internal int error = 0; internal int last_pitch_index = 0; internal int loss_count = 0; internal int postfilter_period = 0; internal int postfilter_period_old = 0; internal int postfilter_gain = 0; internal int postfilter_gain_old = 0; internal int postfilter_tapset = 0; internal int postfilter_tapset_old = 0; internal readonly int[] preemph_memD = new int[2]; internal int[][] decode_mem = null; internal int[][] lpc = null; internal int[] oldEBands = null; internal int[] oldLogE = null; internal int[] oldLogE2 = null; internal int[] backgroundLogE = null; private void Reset() { mode = null; overlap = 0; channels = 0; stream_channels = 0; downsample = 0; start = 0; end = 0; signalling = 0; PartialReset(); } private void PartialReset() { rng = 0u; error = 0; last_pitch_index = 0; loss_count = 0; postfilter_period = 0; postfilter_period_old = 0; postfilter_gain = 0; postfilter_gain_old = 0; postfilter_tapset = 0; postfilter_tapset_old = 0; Arrays.MemSet(preemph_memD, 0, 2); decode_mem = null; lpc = null; oldEBands = null; oldLogE = null; oldLogE2 = null; backgroundLogE = null; } internal void ResetState() { PartialReset(); decode_mem = new int[channels][]; lpc = new int[channels][]; for (int i = 0; i < channels; i++) { decode_mem[i] = new int[2048 + mode.overlap]; lpc[i] = new int[24]; } oldEBands = new int[2 * mode.nbEBands]; oldLogE = new int[2 * mode.nbEBands]; oldLogE2 = new int[2 * mode.nbEBands]; backgroundLogE = new int[2 * mode.nbEBands]; for (int j = 0; j < 2 * mode.nbEBands; j++) { oldLogE[j] = (oldLogE2[j] = -28672); } } internal int celt_decoder_init(int sampling_rate, int channels) { int num = opus_custom_decoder_init(CeltMode.mode48000_960_120, channels); if (num != 0) { return num; } downsample = CeltCommon.resampling_factor(sampling_rate); if (downsample == 0) { return -1; } return 0; } private int opus_custom_decoder_init(CeltMode mode, int channels) { if (channels < 0 || channels > 2) { return -1; } if (this == null) { return -7; } Reset(); this.mode = mode; overlap = mode.overlap; stream_channels = (this.channels = channels); downsample = 1; start = 0; end = this.mode.effEBands; signalling = 1; loss_count = 0; ResetState(); return 0; } internal void celt_decode_lost(int N, int LM) { int num = channels; int[][] array = new int[2][]; int[] array2 = new int[2]; CeltMode celtMode = mode; int nbEBands = celtMode.nbEBands; int num2 = celtMode.overlap; short[] eBands = celtMode.eBands; int num3 = 0; do { array[num3] = decode_mem[num3]; array2[num3] = 2048 - N; } while (++num3 < num); if ((loss_count >= 5 || start != 0) ? true : false) { int num4 = end; int num5 = Inlines.IMAX(start, Inlines.IMIN(num4, celtMode.effEBands)); int[][] array3 = Arrays.InitTwoDimensionalArray(num, N); int num6 = ((loss_count == 0) ? 1536 : 512); num3 = 0; do { for (int i = start; i < num4; i++) { oldEBands[num3 * nbEBands + i] = Inlines.MAX16(backgroundLogE[num3 * nbEBands + i], oldEBands[num3 * nbEBands + i] - num6); } } while (++num3 < num); uint num7 = rng; for (num3 = 0; num3 < num; num3++) { for (int i = start; i < num5; i++) { int num8 = eBands[i] << LM; int num9 = eBands[i + 1] - eBands[i] << LM; for (int j = 0; j < num9; j++) { num7 = Bands.celt_lcg_rand(num7); array3[num3][num8 + j] = (int)num7 >> 20; } VQ.renormalise_vector(array3[num3], 0, num9, 32767); } } rng = num7; num3 = 0; do { Arrays.MemMove(decode_mem[num3], N, 0, 2048 - N + (num2 >> 1)); } while (++num3 < num); CeltCommon.celt_synthesis(celtMode, array3, array, array2, oldEBands, start, num5, num, num, 0, LM, downsample, 0); } else { int a = 32767; int num10; if (loss_count == 0) { num10 = (last_pitch_index = CeltCommon.celt_plc_pitch_search(decode_mem, num)); } else { num10 = last_pitch_index; a = 26214; } int[] array4 = new int[num2]; int[] array5 = new int[1024]; int[] window = celtMode.window; num3 = 0; do { int num11 = 0; int[] array6 = decode_mem[num3]; int i; for (i = 0; i < 1024; i++) { array5[i] = Inlines.ROUND16(array6[1024 + i], 12); } if (loss_count == 0) { int[] array7 = new int[25]; Autocorrelation._celt_autocorr(array5, array7, window, num2, 24, 1024); array7[0] += Inlines.SHR32(array7[0], 13); for (i = 1; i <= 24; i++) { array7[i] -= Inlines.MULT16_32_Q15(2 * i * i, array7[i]); } CeltLPC.celt_lpc(lpc[num3], array7, 24); } int num12 = Inlines.IMIN(2 * num10, 1024); int[] array8 = new int[24]; for (i = 0; i < 24; i++) { array8[i] = Inlines.ROUND16(array6[2048 - num12 - 1 - i], 12); } Kernels.celt_fir(array5, 1024 - num12, lpc[num3], 0, array5, 1024 - num12, num12, 24, array8); int num13 = 1; int num14 = 1; int shift = Inlines.IMAX(0, 2 * Inlines.celt_zlog2(Inlines.celt_maxabs16(array5, 1024 - num12, num12)) - 20); int num15 = num12 >> 1; for (i = 0; i < num15; i++) { int num16 = array5[1024 - num15 + i]; num13 += Inlines.SHR32(Inlines.MULT16_16(num16, num16), shift); num16 = array5[1024 - 2 * num15 + i]; num14 += Inlines.SHR32(Inlines.MULT16_16(num16, num16), shift); } num13 = Inlines.MIN32(num13, num14); int num6 = Inlines.celt_sqrt(Inlines.frac_div32(Inlines.SHR32(num13, 1), num14)); Arrays.MemMove(array6, N, 0, 2048 - N); int num17 = 1024 - num10; int num18 = N + num2; int a2 = Inlines.MULT16_16_Q15(a, num6); int j; i = (j = 0); while (i < num18) { if (j >= num10) { j -= num10; a2 = Inlines.MULT16_16_Q15(a2, num6); } array6[2048 - N + i] = Inlines.SHL32(Inlines.MULT16_16_Q15(a2, array5[num17 + j]), 12); int num19 = Inlines.ROUND16(array6[1024 - N + num17 + j], 12); num11 += Inlines.SHR32(Inlines.MULT16_16(num19, num19), 8); i++; j++; } array8 = new int[24]; for (i = 0; i < 24; i++) { array8[i] = Inlines.ROUND16(array6[2048 - N - 1 - i], 12); } CeltLPC.celt_iir(array6, 2048 - N, lpc[num3], array6, 2048 - N, num18, 24, array8); int num20 = 0; for (i = 0; i < num18; i++) { int num19 = Inlines.ROUND16(array6[2048 - N + i], 12); num20 += Inlines.SHR32(Inlines.MULT16_16(num19, num19), 8); } if (num11 <= Inlines.SHR32(num20, 2)) { for (i = 0; i < num18; i++) { array6[2048 - N + i] = 0; } } else if (num11 < num20) { int num21 = Inlines.celt_sqrt(Inlines.frac_div32(Inlines.SHR32(num11, 1) + 1, num20 + 1)); for (i = 0; i < num2; i++) { int a3 = 32767 - Inlines.MULT16_16_Q15(window[i], 32767 - num21); array6[2048 - N + i] = Inlines.MULT16_32_Q15(a3, array6[2048 - N + i]); } for (i = num2; i < num18; i++) { array6[2048 - N + i] = Inlines.MULT16_32_Q15(num21, array6[2048 - N + i]); } } CeltCommon.comb_filter(array4, 0, array6, 2048, postfilter_period, postfilter_period, num2, -postfilter_gain, -postfilter_gain, postfilter_tapset, postfilter_tapset, null, 0); for (i = 0; i < num2 / 2; i++) { array6[2048 + i] = Inlines.MULT16_32_Q15(window[i], array4[num2 - 1 - i]) + Inlines.MULT16_32_Q15(window[num2 - i - 1], array4[i]); } } while (++num3 < num); } loss_count++; } internal int celt_decode_with_ec(byte[] data, int data_ptr, int len, short[] pcm, int pcm_ptr, int frame_size, EntropyCoder dec, int accum) { int[][] array = new int[2][]; int[] array2 = new int[2]; int num = channels; int intensity = 0; int dual_stereo = 0; int num2 = 0; int num3 = stream_channels; CeltMode celtMode = mode; int nbEBands = celtMode.nbEBands; int num4 = celtMode.overlap; short[] eBands = celtMode.eBands; int num5 = start; int num6 = end; frame_size *= downsample; int[] array3 = oldEBands; int[] array4 = oldLogE; int[] array5 = oldLogE2; int[] array6 = backgroundLogE; int i; for (i = 0; i <= celtMode.maxLM && celtMode.shortMdctSize << i != frame_size; i++) { } if (i > celtMode.maxLM) { return -1; } int num7 = 1 << i; if (len < 0 || len > 1275 || pcm == null) { return -1; } int num8 = num7 * celtMode.shortMdctSize; int num9 = 0; do { array[num9] = decode_mem[num9]; array2[num9] = 2048 - num8; } while (++num9 < num); int num10 = num6; if (num10 > celtMode.effEBands) { num10 = celtMode.effEBands; } if (data == null || len <= 1) { celt_decode_lost(num8, i); CeltCommon.deemphasis(array, array2, pcm, pcm_ptr, num8, num, downsample, celtMode.preemph, preemph_memD, accum); return frame_size / downsample; } if (dec == null) { dec = new EntropyCoder(); dec.dec_init(data, data_ptr, (uint)len); } if (num3 == 1) { for (int j = 0; j < nbEBands; j++) { array3[j] = Inlines.MAX16(array3[j], array3[nbEBands + j]); } } int num11 = len * 8; int num12 = dec.tell(); int num13 = ((num12 >= num11) ? 1 : ((num12 == 1) ? dec.dec_bit_logp(15u) : 0)); if (num13 != 0) { num12 = len * 8; dec.nbits_total += num12 - dec.tell(); } int g = 0; int t = 0; int tapset = 0; if (num5 == 0 && num12 + 16 <= num11) { if (dec.dec_bit_logp(1u) != 0) { int num14 = (int)dec.dec_uint(6u); t = (16 << num14) + (int)dec.dec_bits((uint)(4 + num14)) - 1; int num15 = (int)dec.dec_bits(3u); if (dec.tell() + 2 <= num11) { tapset = dec.dec_icdf(Tables.tapset_icdf, 2u); } g = 3072 * (num15 + 1); } num12 = dec.tell(); } int num16; if (i > 0 && num12 + 3 <= num11) { num16 = dec.dec_bit_logp(3u); num12 = dec.tell(); } else { num16 = 0; } int shortBlocks = ((num16 != 0) ? num7 : 0); int intra = ((num12 + 3 <= num11) ? dec.dec_bit_logp(3u) : 0); QuantizeBands.unquant_coarse_energy(celtMode, num5, num6, array3, intra, dec, num3, i); int[] tf_res = new int[nbEBands]; CeltCommon.tf_decode(num5, num6, num16, tf_res, i, dec); num12 = dec.tell(); int spread = 2; if (num12 + 4 <= num11) { spread = dec.dec_icdf(Tables.spread_icdf, 5u); } int[] array7 = new int[nbEBands]; CeltCommon.init_caps(celtMode, array7, i, num3); int[] array8 = new int[nbEBands]; int num17 = 6; num11 <<= 3; num12 = (int)dec.tell_frac(); for (int j = num5; j < num6; j++) { int num18 = num3 * (eBands[j + 1] - eBands[j]) << i; int num19 = Inlines.IMIN(num18 << 3, Inlines.IMAX(48, num18)); int num20 = num17; int num21 = 0; while (num12 + (num20 << 3) < num11 && num21 < array7[j]) { int num22 = dec.dec_bit_logp((uint)num20); num12 = (int)dec.tell_frac(); if (num22 == 0) { break; } num21 += num19; num11 -= num19; num20 = 1; } array8[j] = num21; if (num21 > 0) { num17 = Inlines.IMAX(2, num17 - 1); } } int[] array9 = new int[nbEBands]; int alloc_trim = ((num12 + 48 <= num11) ? dec.dec_icdf(Tables.trim_icdf, 7u) : 5); int num23 = (len * 8 << 3) - (int)dec.tell_frac() - 1; int num24 = ((num16 != 0 && i >= 2 && num23 >= i + 2 << 3) ? 8 : 0); num23 -= num24; int[] pulses = new int[nbEBands]; int[] fine_priority = new int[nbEBands]; int balance; int codedBands = Rate.compute_allocation(celtMode, num5, num6, array8, array7, alloc_trim, ref intensity, ref dual_stereo, num23, out balance, pulses, array9, fine_priority, num3, i, dec, 0, 0, 0); QuantizeBands.unquant_fine_energy(celtMode, num5, num6, array3, array9, dec, num3); num9 = 0; do { Arrays.MemMove(decode_mem[num9], num8, 0, 2048 - num8 + num4 / 2); } while (++num9 < num); byte[] collapse_masks = new byte[num3 * nbEBands]; int[][] array10 = Arrays.InitTwoDimensionalArray(num3, num8); Bands.quant_all_bands(0, celtMode, num5, num6, array10[0], (num3 == 2) ? array10[1] : null, collapse_masks, null, pulses, shortBlocks, spread, dual_stereo, intensity, tf_res, len * 64 - num24, balance, dec, i, codedBands, ref rng); if (num24 > 0) { num2 = (int)dec.dec_bits(1u); } QuantizeBands.unquant_energy_finalise(celtMode, num5, num6, array3, array9, fine_priority, len * 8 - dec.tell(), dec, num3); if (num2 != 0) { Bands.anti_collapse(celtMode, array10, collapse_masks, i, num3, num8, num5, num6, array3, array4, array5, pulses, rng); } if (num13 != 0) { for (int j = 0; j < num3 * nbEBands; j++) { array3[j] = -28672; } } CeltCommon.celt_synthesis(celtMode, array10, array, array2, array3, num5, num10, num3, num, num16, i, downsample, num13); num9 = 0; do { postfilter_period = Inlines.IMAX(postfilter_period, 15); postfilter_period_old = Inlines.IMAX(postfilter_period_old, 15); CeltCommon.comb_filter(array[num9], array2[num9], array[num9], array2[num9], postfilter_period_old, postfilter_period, celtMode.shortMdctSize, postfilter_gain_old, postfilter_gain, postfilter_tapset_old, postfilter_tapset, celtMode.window, num4); if (i != 0) { CeltCommon.comb_filter(array[num9], array2[num9] + celtMode.shortMdctSize, array[num9], array2[num9] + celtMode.shortMdctSize, postfilter_period, t, num8 - celtMode.shortMdctSize, postfilter_gain, g, postfilter_tapset, tapset, celtMode.window, num4); } } while (++num9 < num); postfilter_period_old = postfilter_period; postfilter_gain_old = postfilter_gain; postfilter_tapset_old = postfilter_tapset; postfilter_period = t; postfilter_gain = g; postfilter_tapset = tapset; if (i != 0) { postfilter_period_old = postfilter_period; postfilter_gain_old = postfilter_gain; postfilter_tapset_old = postfilter_tapset; } if (num3 == 1) { Array.Copy(array3, 0, array3, nbEBands, nbEBands); } if (num16 == 0) { Array.Copy(array4, array5, 2 * nbEBands); Array.Copy(array3, array4, 2 * nbEBands); int num25 = ((loss_count >= 10) ? 1024 : num7); for (int j = 0; j < 2 * nbEBands; j++) { array6[j] = Inlines.MIN16(array6[j] + num25, array3[j]); } } else { for (int j = 0; j < 2 * nbEBands; j++) { array4[j] = Inlines.MIN16(array4[j], array3[j]); } } num9 = 0; do { for (int j = 0; j < num5; j++) { array3[num9 * nbEBands + j] = 0; array4[num9 * nbEBands + j] = (array5[num9 * nbEBands + j] = -28672); } for (int j = num6; j < nbEBands; j++) { array3[num9 * nbEBands + j] = 0; array4[num9 * nbEBands + j] = (array5[num9 * nbEBands + j] = -28672); } } while (++num9 < 2); rng = dec.rng; CeltCommon.deemphasis(array, array2, pcm, pcm_ptr, num8, num, downsample, celtMode.preemph, preemph_memD, accum); loss_count = 0; if (dec.tell() > 8 * len) { return -3; } if (dec.get_error() != 0) { error = 1; } return frame_size / downsample; } internal void SetStartBand(int value) { if (value < 0 || value >= mode.nbEBands) { throw new ArgumentException("Start band above max number of ebands (or negative)"); } start = value; } internal void SetEndBand(int value) { if (value < 1 || value > mode.nbEBands) { throw new ArgumentException("End band above max number of ebands (or less than 1)"); } end = value; } internal void SetChannels(int value) { if (value < 1 || value > 2) { throw new ArgumentException("Channel count must be 1 or 2"); } stream_channels = value; } internal int GetAndClearError() { int result = error; error = 0; return result; } public int GetLookahead() { return overlap / downsample; } public int GetPitch() { return postfilter_period; } public CeltMode GetMode() { return mode; } public void SetSignalling(int value) { signalling = value; } public uint GetFinalRange() { return rng; } } internal class CeltEncoder { internal CeltMode mode = null; internal int channels = 0; internal int stream_channels = 0; internal int force_intra = 0; internal int clip = 0; internal int disable_pf = 0; internal int complexity = 0; internal int upsample = 0; internal int start = 0; internal int end = 0; internal int bitrate = 0; internal int vbr = 0; internal int signalling = 0; internal int constrained_vbr = 0; internal int loss_rate = 0; internal int lsb_depth = 0; internal OpusFramesize variable_duration = (OpusFramesize)0; internal int lfe = 0; internal uint rng = 0u; internal int spread_decision = 0; internal int delayedIntra = 0; internal int tonal_average = 0; internal int lastCodedBands = 0; internal int hf_average = 0; internal int tapset_decision = 0; internal int prefilter_period = 0; internal int prefilter_gain = 0; internal int prefilter_tapset = 0; internal int consec_transient = 0; internal AnalysisInfo analysis = new AnalysisInfo(); internal readonly int[] preemph_memE = new int[2]; internal readonly int[] preemph_memD = new int[2]; internal int vbr_reservoir = 0; internal int vbr_drift = 0; internal int vbr_offset = 0; internal int vbr_count = 0; internal int overlap_max = 0; internal int stereo_saving = 0; internal int intensity = 0; internal int[] energy_mask = null; internal int spec_avg = 0; internal int[][] in_mem = null; internal int[][] prefilter_mem = null; internal int[][] oldBandE = null; internal int[][] oldLogE = null; internal int[][] oldLogE2 = null; private void Reset() { mode = null; channels = 0; stream_channels = 0; force_intra = 0; clip = 0; disable_pf = 0; complexity = 0; upsample = 0; start = 0; end = 0; bitrate = 0; vbr = 0; signalling = 0; constrained_vbr = 0; loss_rate = 0; lsb_depth = 0; variable_duration = (OpusFramesize)0; lfe = 0; PartialReset(); } private void PartialReset() { rng = 0u; spread_decision = 0; delayedIntra = 0; tonal_average = 0; lastCodedBands = 0; hf_average = 0; tapset_decision = 0; prefilter_period = 0; prefilter_gain = 0; prefilter_tapset = 0; consec_transient = 0; analysis.Reset(); preemph_memE[0] = 0; preemph_memE[1] = 0; preemph_memD[0] = 0; preemph_memD[1] = 0; vbr_reservoir = 0; vbr_drift = 0; vbr_offset = 0; vbr_count = 0; overlap_max = 0; stereo_saving = 0; intensity = 0; energy_mask = null; spec_avg = 0; in_mem = null; prefilter_mem = null; oldBandE = null; oldLogE = null; oldLogE2 = null; } internal void ResetState() { PartialReset(); in_mem = Arrays.InitTwoDimensionalArray(channels, mode.overlap); prefilter_mem = Arrays.InitTwoDimensionalArray(channels, 1024); oldBandE = Arrays.InitTwoDimensionalArray(channels, mode.nbEBands); oldLogE = Arrays.InitTwoDimensionalArray(channels, mode.nbEBands); oldLogE2 = Arrays.InitTwoDimensionalArray(channels, mode.nbEBands); for (int i = 0; i < mode.nbEBands; i++) { oldLogE[0][i] = (oldLogE2[0][i] = -28672); } if (channels == 2) { for (int i = 0; i < mode.nbEBands; i++) { oldLogE[1][i] = (oldLogE2[1][i] = -28672); } } vbr_offset = 0; delayedIntra = 1; spread_decision = 2; tonal_average = 256; hf_average = 0; tapset_decision = 0; } internal int opus_custom_encoder_init_arch(CeltMode mode, int channels) { if (channels < 0 || channels > 2) { return -1; } if (this == null || mode == null) { return -7; } Reset(); this.mode = mode; stream_channels = (this.channels = channels); upsample = 1; start = 0; end = this.mode.effEBands; signalling = 1; constrained_vbr = 1; clip = 1; bitrate = -1; vbr = 0; force_intra = 0; complexity = 5; lsb_depth = 24; ResetState(); return 0; } internal int celt_encoder_init(int sampling_rate, int channels) { int num = opus_custom_encoder_init_arch(CeltMode.mode48000_960_120, channels); if (num != 0) { return num; } upsample = CeltCommon.resampling_factor(sampling_rate); return 0; } internal int run_prefilter(int[][] input, int[][] prefilter_mem, int CC, int N, int prefilter_tapset, out int pitch, out int gain, out int qgain, int enabled, int nbAvailableBytes) { int[][] array = new int[CC][]; CeltMode celtMode = mode; int overlap = celtMode.overlap; for (int i = 0; i < CC; i++) { array[i] = new int[N + 1024]; } int num = 0; do { Array.Copy(prefilter_mem[num], 0, array[num], 0, 1024); Array.Copy(input[num], overlap, array[num], 1024, N); } while (++num < CC); int pitch2; int b; if (enabled != 0) { int[] array2 = new int[1024 + N >> 1]; Pitch.pitch_downsample(array, array2, 1024 + N, CC); Pitch.pitch_search(array2, 512, array2, N, 979, out pitch2); pitch2 = 1024 - pitch2; b = Pitch.remove_doubling(array2, 1024, 15, N, ref pitch2, prefilter_period, prefilter_gain); if (pitch2 > 1022) { pitch2 = 1022; } b = Inlines.MULT16_16_Q15(22938, b); if (loss_rate > 2) { b = Inlines.HALF32(b); } if (loss_rate > 4) { b = Inlines.HALF32(b); } if (loss_rate > 8) { b = 0; } } else { b = 0; pitch2 = 15; } int num2 = 6554; if (Inlines.abs(pitch2 - prefilter_period) * 10 > pitch2) { num2 += 6554; } if (nbAvailableBytes < 25) { num2 += 3277; } if (nbAvailableBytes < 35) { num2 += 3277; } if (prefilter_gain > 13107) { num2 -= 3277; } if (prefilter_gain > 18022) { num2 -= 3277; } num2 = Inlines.MAX16(num2, 6554); int result; int num3; if (b < num2) { b = 0; result = 0; num3 = 0; } else { if (Inlines.ABS32(b - prefilter_gain) < 3277) { b = prefilter_gain; } num3 = (b + 1536 >> 10) / 3 - 1; num3 = Inlines.IMAX(0, Inlines.IMIN(7, num3)); b = 3072 * (num3 + 1); result = 1; } num = 0; do { int num4 = celtMode.shortMdctSize - overlap; prefilter_period = Inlines.IMAX(prefilter_period, 15); Array.Copy(in_mem[num], 0, input[num], 0, overlap); if (num4 != 0) { CeltCommon.comb_filter(input[num], overlap, array[num], 1024, prefilter_period, prefilter_period, num4, -prefilter_gain, -prefilter_gain, this.prefilter_tapset, this.prefilter_tapset, null, 0); } CeltCommon.comb_filter(input[num], overlap + num4, array[num], 1024 + num4, prefilter_period, pitch2, N - num4, -prefilter_gain, -b, this.prefilter_tapset, prefilter_tapset, celtMode.window, overlap); Array.Copy(input[num], N, in_mem[num], 0, overlap); if (N > 1024) { Array.Copy(array[num], N, prefilter_mem[num], 0, 1024); continue; } Arrays.MemMove(prefilter_mem[num], N, 0, 1024 - N); Array.Copy(array[num], 1024, prefilter_mem[num], 1024 - N, N); } while (++num < CC); gain = b; pitch = pitch2; qgain = num3; return result; } internal int celt_encode_with_ec(short[] pcm, int pcm_ptr, int frame_size, byte[] compressed, int compressed_ptr, int nbCompressedBytes, EntropyCoder enc) { int num = 0; int num2 = 0; int num3 = channels; int num4 = stream_channels; int pitch = 15; int gain = 0; int dual_stereo = 0; int num5 = 0; int num6 = 0; int num7 = 0; int tf_chan = 0; int pitch_change = 0; int num8 = 0; int surround_masking = 0; int num9 = 0; int surround_trim = 0; int num10 = 510000; CeltMode celtMode = mode; int nbEBands = celtMode.nbEBands; int overlap = celtMode.overlap; short[] eBands = celtMode.eBands; int num11 = start; int num12 = end; int tf_estimate = 0; if (nbCompressedBytes < 2 || pcm == null) { return -1; } frame_size *= upsample; int i; for (i = 0; i <= celtMode.maxLM && celtMode.shortMdctSize << i != frame_size; i++) { } if (i > celtMode.maxLM) { return -1; } int num13 = 1 << i; int num14 = num13 * celtMode.shortMdctSize; int num16; int num15; if (enc == null) { num15 = 1; num16 = 0; } else { num15 = enc.tell(); num16 = num15 + 4 >> 3; } nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, 1275); int num17 = nbCompressedBytes - num16; int num19; int num20; if (vbr != 0 && bitrate != -1) { int num18 = celtMode.Fs >> 3; num19 = (bitrate * frame_size + (num18 >> 1)) / num18; num20 = num19 >> 6; } else { num19 = 0; int num21 = bitrate * frame_size; if (num15 > 1) { num21 += num15; } if (bitrate != -1) { nbCompressedBytes = Inlines.IMAX(2, Inlines.IMIN(nbCompressedBytes, (num21 + 4 * celtMode.Fs) / (8 * celtMode.Fs) - ((signalling != 0) ? 1 : 0))); } num20 = nbCompressedBytes; } if (bitrate != -1) { num10 = bitrate - (40 * num4 + 20) * ((400 >> i) - 50); } if (enc == null) { enc = new EntropyCoder(); enc.enc_init(compressed, compressed_ptr, (uint)nbCompressedBytes); } if (num19 > 0 && constrained_vbr != 0) { int num22 = num19; int num23 = Inlines.IMIN(Inlines.IMAX((num15 == 1) ? 2 : 0, num19 + num22 - vbr_reservoir >> 6), num17); if (num23 < num17) { nbCompressedBytes = num16 + num23; num17 = num23; enc.enc_shrink((uint)nbCompressedBytes); } } int num24 = nbCompressedBytes * 8; int num25 = num12; if (num25 > celtMode.effEBands) { num25 = celtMode.effEBands; } int[][] array = Arrays.InitTwoDimensionalArray(num3, num14 + overlap); int a = Inlines.MAX32(overlap_max, Inlines.celt_maxabs32(pcm, pcm_ptr, num4 * (num14 - overlap) / upsample)); overlap_max = Inlines.celt_maxabs32(pcm, pcm_ptr + num4 * (num14 - overlap) / upsample, num4 * overlap / upsample); num7 = ((Inlines.MAX32(a, overlap_max) == 0) ? 1 : 0); if (num15 == 1) { enc.enc_bit_logp(num7, 15u); } else { num7 = 0; } if (num7 != 0) { if (num19 > 0) { num20 = (nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, num16 + 2)); num24 = nbCompressedBytes * 8; num17 = 2; enc.enc_shrink((uint)nbCompressedBytes); } num15 = nbCompressedBytes * 8; enc.nbits_total += num15 - enc.tell(); } int num26 = 0; do { int num27 = 0; CeltCommon.celt_preemphasis(pcm, pcm_ptr + num26, array[num26], overlap, num14, num3, upsample, celtMode.preemph, ref preemph_memE[num26], num27); } while (++num26 < num3); int enabled = ((((lfe != 0 && num17 > 3) || num17 > 12 * num4) && num11 == 0 && num7 == 0 && disable_pf == 0 && complexity >= 5 && (consec_transient == 0 || i == 3 || variable_duration != OpusFramesize.OPUS_FRAMESIZE_VARIABLE)) ? 1 : 0); num5 = tapset_decision; int qgain; int num28 = run_prefilter(array, prefilter_mem, num3, num14, num5, out pitch, out gain, out qgain, enabled, num17); if ((gain > 13107 || prefilter_gain > 13107) && (analysis.valid == 0 || (double)analysis.tonality > 0.3) && ((double)pitch > 1.26 * (double)prefilter_period || (double)pitch < 0.79 * (double)prefilter_period)) { pitch_change = 1; } if (num28 == 0) { if (num11 == 0 && num15 + 16 <= num24) { enc.enc_bit_logp(0, 1u); } } else { enc.enc_bit_logp(1, 1u); pitch++; int num29 = Inlines.EC_ILOG((uint)pitch) - 5; enc.enc_uint((uint)num29, 6u); enc.enc_bits((uint)(pitch - (16 << num29)), (uint)(4 + num29)); pitch--; enc.enc_bits((uint)qgain, 3u); enc.enc_icdf(num5, Tables.tapset_icdf, 2u); } num2 = 0; num = 0; if (complexity >= 1 && lfe == 0) { num2 = CeltCommon.transient_analysis(array, num14 + overlap, num3, out tf_estimate, out tf_chan); } if (i > 0 && enc.tell() + 3 <= num24) { if (num2 != 0) { num = num13; } } else { num2 = 0; num8 = 1; } int[][] array2 = Arrays.InitTwoDimensionalArray(num3, num14); int[][] array3 = Arrays.InitTwoDimensionalArray(num3, nbEBands); int[][] array4 = Arrays.InitTwoDimensionalArray(num3, nbEBands); int num30 = ((num != 0 && complexity >= 8) ? 1 : 0); int[][] array5 = Arrays.InitTwoDimensionalArray(num3, nbEBands); if (num30 != 0) { CeltCommon.compute_mdcts(celtMode, 0, array, array2, num4, num3, i, upsample); Bands.compute_band_energies(celtMode, array2, array3, num25, num4, i); QuantizeBands.amp2Log2(celtMode, num25, num12, array3, array5, num4); for (int j = 0; j < nbEBands; j++) { array5[0][j] += Inlines.HALF16(Inlines.SHL16(i, 10)); } if (num4 == 2) { for (int j = 0; j < nbEBands; j++) { array5[1][j] += Inlines.HALF16(Inlines.SHL16(i, 10)); } } } CeltCommon.compute_mdcts(celtMode, num, array, array2, num4, num3, i, upsample); if (num3 == 2 && num4 == 1) { tf_chan = 0; } Bands.compute_band_energies(celtMode, array2, array3, num25, num4, i); if (lfe != 0) { for (int j = 2; j < num12; j++) { array3[0][j] = Inlines.IMIN(array3[0][j], Inlines.MULT16_32_Q15((short)3, array3[0][0])); array3[0][j] = Inlines.MAX32(array3[0][j], 1); } } QuantizeBands.amp2Log2(celtMode, num25, num12, array3, array4, num4); int[] array6 = new int[num4 * nbEBands]; if (num11 == 0 && energy_mask != null && lfe == 0) { int num31 = 0; int num32 = 0; int num33 = 0; int num34 = Inlines.IMAX(2, lastCodedBands); for (num26 = 0; num26 < num4; num26++) { for (int j = 0; j < num34; j++) { int num35 = Inlines.MAX16(Inlines.MIN16(energy_mask[nbEBands * num26 + j], 256), -2048); if (num35 > 0) { num35 = Inlines.HALF16(num35); } num31 += Inlines.MULT16_16(num35, eBands[j + 1] - eBands[j]); num33 += eBands[j + 1] - eBands[j]; num32 += Inlines.MULT16_16(num35, 1 + 2 * j - num34); } } num31 = Inlines.DIV32_16(num31, num33); num31 += 205; num32 = num32 * 6 / (num4 * (num34 - 1) * (num34 + 1) * num34); num32 = Inlines.HALF32(num32); num32 = Inlines.MAX32(Inlines.MIN32(num32, 32), -32); int k; for (k = 0; eBands[k + 1] < eBands[num34] / 2; k++) { } int num36 = 0; for (int j = 0; j < num34; j++) { int num37 = num31 + num32 * (j - k); int a2 = ((num4 != 2) ? energy_mask[j] : Inlines.MAX16(energy_mask[j], energy_mask[nbEBands + j])); a2 = Inlines.MIN16(a2, 0); a2 -= num37; if (a2 > 256) { array6[j] = a2 - 256; num36++; } } if (num36 >= 3) { num31 += 256; if (num31 > 0) { num31 = 0; num32 = 0; Arrays.MemSet(array6, 0, num34); } else { for (int j = 0; j < num34; j++) { array6[j] = Inlines.MAX16(0, array6[j] - 256); } } } num31 += 205; surround_trim = 64 * num32; surround_masking = num31; } if (lfe == 0) { int num38 = -10240; int num39 = 0; int num40 = ((num != 0) ? Inlines.HALF16(Inlines.SHL16(i, 10)) : 0); for (int j = num11; j < num12; j++) { num38 = Inlines.MAX16(num38 - 1024, array4[0][j] - num40); if (num4 == 2) { num38 = Inlines.MAX16(num38, array4[1][j] - num40); } num39 += num38; } num39 /= num12 - num11; num9 = Inlines.SUB16(num39, spec_avg); num9 = Inlines.MIN16(3072, Inlines.MAX16(-1536, num9)); spec_avg += (short)Inlines.MULT16_16_Q15(655, num9); } if (num30 == 0) { Array.Copy(array4[0], array5[0], nbEBands); if (num4 == 2) { Array.Copy(array4[1], array5[1], nbEBands); } } if (i > 0 && enc.tell() + 3 <= num24 && num2 == 0 && complexity >= 5 && lfe == 0 && CeltCommon.patch_transient_decision(array4, oldBandE, nbEBands, num11, num12, num4) != 0) { num2 = 1; num = num13; CeltCommon.compute_mdcts(celtMode, num, array, array2, num4, num3, i, upsample); Bands.compute_band_energies(celtMode, array2, array3, num25, num4, i); QuantizeBands.amp2Log2(celtMode, num25, num12, array3, array4, num4); for (int j = 0; j < nbEBands; j++) { array5[0][j] += Inlines.HALF16(Inlines.SHL16(i, 10)); } if (num4 == 2) { for (int j = 0; j < nbEBands; j++) { array5[1][j] += Inlines.HALF16(Inlines.SHL16(i, 10)); } } tf_estimate = 3277; } if (i > 0 && enc.tell() + 3 <= num24) { enc.enc_bit_logp(num2, 3u); } int[][] array7 = Arrays.InitTwoDimensionalArray(num4, num14); Bands.normalise_bands(celtMode, array2, array7, array3, num25, num4, num13); int[] array8 = new int[nbEBands]; int tf_select; if (num20 >= 15 * num4 && num11 == 0 && complexity >= 2 && lfe == 0) { int num41 = ((num20 < 40) ? 12 : ((num20 < 60) ? 6 : ((num20 >= 100) ? 3 : 4))); num41 *= 2; tf_select = CeltCommon.tf_analysis(celtMode, num25, num2, array8, num41, array7, num14, i, out var _, tf_estimate, tf_chan); for (int j = num25; j < num12; j++) { array8[j] = array8[num25 - 1]; } } else { int tf_sum = 0; for (int j = 0; j < num12; j++) { array8[j] = num2; } tf_select = 0; } int[][] error = Arrays.InitTwoDimensionalArray(num4, nbEBands); QuantizeBands.quant_coarse_energy(celtMode, num11, num12, num25, array4, oldBandE, (uint)num24, error, enc, num4, i, num17, force_intra, ref delayedIntra, (complexity >= 4) ? 1 : 0, loss_rate, lfe); CeltCommon.tf_encode(num11, num12, num2, array8, i, tf_select, enc); if (enc.tell() + 4 <= num24) { if (lfe != 0) { tapset_decision = 0; spread_decision = 2; } else if (num != 0 || complexity < 3 || num17 < 10 * num4 || num11 != 0) { if (complexity == 0) { spread_decision = 0; } else { spread_decision = 2; } } else { spread_decision = Bands.spreading_decision(celtMode, array7, ref tonal_average, spread_decision, ref hf_average, ref tapset_decision, (num28 != 0 && num == 0) ? 1 : 0, num25, num4, num13); } enc.enc_icdf(spread_decision, Tables.spread_icdf, 5u); } int[] array9 = new int[nbEBands]; int tot_boost_; int maxDepth = CeltCommon.dynalloc_analysis(array4, array5, nbEBands, num11, num12, num4, array9, lsb_depth, celtMode.logN, num2, vbr, constrained_vbr, eBands, i, num20, out tot_boost_, lfe, array6); if (lfe != 0) { array9[0] = Inlines.IMIN(8, num20 / 3); } int[] array10 = new int[nbEBands]; CeltCommon.init_caps(celtMode, array10, i, num4); int num42 = 6; num24 <<= 3; int num43 = 0; num15 = (int)enc.tell_frac(); for (int j = num11; j < num12; j++) { int num44 = num4 * (eBands[j + 1] - eBands[j]) << i; int num45 = Inlines.IMIN(num44 << 3, Inlines.IMAX(48, num44)); int num46 = num42; int num47 = 0; int num48 = 0; while (num15 + (num46 << 3) < num24 - num43 && num47 < array10[j]) { int num49 = ((num48 < array9[j]) ? 1 : 0); enc.enc_bit_logp(num49, (uint)num46); num15 = (int)enc.tell_frac(); if (num49 == 0) { break; } num47 += num45; num43 += num45; num46 = 1; num48++; } if (num48 != 0) { num42 = Inlines.IMAX(2, num42 - 1); } array9[j] = num47; } if (num4 == 2) { if (i != 0) { dual_stereo = CeltCommon.stereo_analysis(celtMode, array7, i); } intensity = Bands.hysteresis_decision(num10 / 1000, Tables.intensity_thresholds, Tables.intensity_histeresis, 21, intensity); intensity = Inlines.IMIN(num12, Inlines.IMAX(num11, intensity)); } int num50 = 5; if (num15 + 48 <= num24 - num43) { num50 = ((lfe == 0) ? CeltCommon.alloc_trim_analysis(celtMode, array7, array4, num12, i, num4, analysis, ref stereo_saving, tf_estimate, intensity, surround_trim) : 5); enc.enc_icdf(num50, Tables.trim_icdf, 7u); num15 = (int)enc.tell_frac(); } if (num19 > 0) { int num51 = celtMode.maxLM - i; nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, 1275 >> 3 - i); int num52 = num19 - (40 * num4 + 20 << 3); if (constrained_vbr != 0) { num52 += vbr_offset >> num51; } int num53 = CeltCommon.compute_vbr(celtMode, analysis, num52, i, num10, lastCodedBands, num4, intensity, constrained_vbr, stereo_saving, tot_boost_, tf_estimate, pitch_change, maxDepth, variable_duration, lfe, (energy_mask != null) ? 1 : 0, surround_masking, num9); num53 += num15; int a3 = (num15 + num43 + 64 - 1 >> 6) + 2 - num16; num17 = num53 + 32 >> 6; num17 = Inlines.IMAX(a3, num17); num17 = Inlines.IMIN(nbCompressedBytes, num17 + num16) - num16; int num54 = num53 - num19; num53 = num17 << 6; if (num7 != 0) { num17 = 2; num53 = 128; num54 = 0; } int a4; if (vbr_count < 970) { vbr_count++; a4 = Inlines.celt_rcp(Inlines.SHL32(vbr_count + 20, 16)); } else { a4 = 33; } if (constrained_vbr != 0) { vbr_reservoir += num53 - num19; } if (constrained_vbr != 0) { vbr_drift += Inlines.MULT16_32_Q15(a4, num54 * (1 << num51) - vbr_offset - vbr_drift); vbr_offset = -vbr_drift; } if (constrained_vbr != 0 && vbr_reservoir < 0) { int num55 = -vbr_reservoir / 64; num17 += ((num7 == 0) ? num55 : 0); vbr_reservoir = 0; } nbCompressedBytes = Inlines.IMIN(nbCompressedBytes, num17 + num16); enc.enc_shrink((uint)nbCompressedBytes); } int[] array11 = new int[nbEBands]; int[] pulses = new int[nbEBands]; int[] fine_priority = new int[nbEBands]; int num56 = (nbCompressedBytes * 8 << 3) - (int)enc.tell_frac() - 1; int num57 = ((num2 != 0 && i >= 2 && num56 >= i + 2 << 3) ? 8 : 0); num56 -= num57; int signalBandwidth = num12 - 1; if (analysis.enabled && analysis.valid != 0) { int b = ((num10 < 32000 * num4) ? 13 : ((num10 < 48000 * num4) ? 16 : ((num10 < 60000 * num4) ? 18 : ((num10 >= 80000 * num4) ? 20 : 19)))); signalBandwidth = Inlines.IMAX(analysis.bandwidth, b); } if (lfe != 0) { signalBandwidth = 1; } int balance; int num58 = Rate.compute_allocation(celtMode, num11, num12, array9, array10, num50, ref intensity, ref dual_stereo, num56, out balance, pulses, array11, fine_priority, num4, i, enc, 1, lastCodedBands, signalBandwidth); if (lastCodedBands != 0) { lastCodedBands = Inlines.IMIN(lastCodedBands + 1, Inlines.IMAX(lastCodedBands - 1, num58)); } else { lastCodedBands = num58; } QuantizeBands.quant_fine_energy(celtMode, num11, num12, oldBandE, error, array11, enc, num4); byte[] collapse_masks = new byte[num4 * nbEBands]; Bands.quant_all_bands(1, celtMode, num11, num12, array7[0], (num4 == 2) ? array7[1] : null, collapse_masks, array3, pulses, num, spread_decision, dual_stereo, intensity, array8, nbCompressedBytes * 64 - num57, balance, enc, i, num58, ref rng); if (num57 > 0) { num6 = ((consec_transient < 2) ? 1 : 0); enc.enc_bits((uint)num6, 1u); } QuantizeBands.quant_energy_finalise(celtMode, num11, num12, oldBandE, error, array11, fine_priority, nbCompressedBytes * 8 - enc.tell(), enc, num4); if (num7 != 0) { for (int j = 0; j < nbEBands; j++) { oldBandE[0][j] = -28672; } if (num4 == 2) { for (int j = 0; j < nbEBands; j++) { oldBandE[1][j] = -28672; } } } prefilter_period = pitch; prefilter_gain = gain; prefilter_tapset = num5; if (num3 == 2 && num4 == 1) { Array.Copy(oldBandE[0], 0, oldBandE[1], 0, nbEBands); } if (num2 == 0) { Array.Copy(oldLogE[0], 0, oldLogE2[0], 0, nbEBands); Array.Copy(oldBandE[0], 0, oldLogE[0], 0, nbEBands); if (num3 == 2) { Array.Copy(oldLogE[1], 0, oldLogE2[1], 0, nbEBands); Array.Copy(oldBandE[1], 0, oldLogE[1], 0, nbEBands); } } else { for (int j = 0; j < nbEBands; j++) { oldLogE[0][j] = Inlines.MIN16(oldLogE[0][j], oldBandE[0][j]); } if (num3 == 2) { for (int j = 0; j < nbEBands; j++) { oldLogE[1][j] = Inlines.MIN16(oldLogE[1][j], oldBandE[1][j]); } } } num26 = 0; do { for (int j = 0; j < num11; j++) { oldBandE[num26][j] = 0; oldLogE[num26][j] = (oldLogE2[num26][j] = -28672); } for (int j = num12; j < nbEBands; j++) { oldBandE[num26][j] = 0; oldLogE[num26][j] = (oldLogE2[num26][j] = -28672); } } while (++num26 < num3); if (num2 != 0 || num8 != 0) { consec_transient++; } else { consec_transient = 0; } rng = enc.rng; enc.enc_done(); if (enc.get_error() != 0) { return -3; } return nbCompressedBytes; } internal void SetComplexity(int value) { if (value < 0 || value > 10) { throw new ArgumentException("Complexity must be between 0 and 10 inclusive"); } complexity = value; } internal void SetStartBand(int value) { if (value < 0 || value >= mode.nbEBands) { throw new ArgumentException("Start band above max number of ebands (or negative)"); } start = value; } internal void SetEndBand(int value) { if (value < 1 || value > mode.nbEBands) { throw new ArgumentException("End band above max number of ebands (or less than 1)"); } end = value; } internal void SetPacketLossPercent(int value) { if (value < 0 || value > 100) { throw new ArgumentException("Packet loss must be between 0 and 100"); } loss_rate = value; } internal void SetPrediction(int value) { if (value < 0 || value > 2) { throw new ArgumentException("CELT prediction mode must be 0, 1, or 2"); } disable_pf = ((value <= 1) ? 1 : 0); force_intra = ((value == 0) ? 1 : 0); } internal void SetVBRConstraint(bool value) { constrained_vbr = (value ? 1 : 0); } internal void SetVBR(bool value) { vbr = (value ? 1 : 0); } internal void SetBitrate(int value) { if (value <= 500 && value != -1) { throw new ArgumentException("Bitrate out of range"); } value = Inlines.IMIN(value, 260000 * channels); bitrate = value; } internal void SetChannels(int value) { if (value < 1 || value > 2) { throw new ArgumentException("Channel count must be 1 or 2"); } stream_channels = value; } internal void SetLSBDepth(int value) { if (value < 8 || value > 24) { throw new ArgumentException("Bit depth must be between 8 and 24"); } lsb_depth = value; } internal int GetLSBDepth() { return lsb_depth; } internal void SetExpertFrameDuration(OpusFramesize value) { variable_duration = value; } internal void SetSignalling(int value) { signalling = value; } internal void SetAnalysis(AnalysisInfo value) { if (value == null) { throw new ArgumentNullException("AnalysisInfo"); } analysis.Assign(value); } internal CeltMode GetMode() { return mode; } internal uint GetFinalRange() { return rng; } internal void SetLFE(int value) { lfe = value; } internal void SetEnergyMask(int[] value) { energy_mask = value; } } internal class CeltMode { internal int Fs = 0; internal int overlap = 0; internal int nbEBands = 0; internal int effEBands = 0; internal int[] preemph = new int[4]; internal short[] eBands = null; internal int maxLM = 0; internal int nbShortMdcts = 0; internal int shortMdctSize = 0; internal int nbAllocVectors = 0; internal byte[] allocVectors = null; internal short[] logN = null; internal int[] window = null; internal MDCTLookup mdct = new MDCTLookup(); internal PulseCache cache = new PulseCache(); internal static readonly CeltMode mode48000_960_120 = new CeltMode { Fs = 48000, overlap = 120, nbEBands = 21, effEBands = 21, preemph = new int[4] { 27853, 0, 4096, 8192 }, eBands = Tables.eband5ms, maxLM = 3, nbShortMdcts = 8, shortMdctSize = 120, nbAllocVectors = 11, allocVectors = Tables.band_allocation, logN = Tables.logN400, window = Tables.window120, mdct = new MDCTLookup { n = 1920, maxshift = 3, kfft = new FFTState[4] { Tables.fft_state48000_960_0, Tables.fft_state48000_960_1, Tables.fft_state48000_960_2, Tables.fft_state48000_960_3 }, trig = Tables.mdct_twiddles960 }, cache = new PulseCache { size = 392, index = Tables.cache_index50, bits = Tables.cache_bits50, caps = Tables.cache_caps50 } }; private CeltMode() { } } internal class FFTState { internal int nfft = 0; internal short scale = 0; internal int scale_shift = 0; internal int shift = 0; internal short[] factors = new short[16]; internal short[] bitrev = null; internal short[] twiddles = null; } internal class MDCTLookup { internal int n = 0; internal int maxshift = 0; internal FFTState[] kfft = new FFTState[4]; internal short[] trig = null; internal MDCTLookup() { } } internal class PulseCache { internal int size = 0; internal short[] index = null; internal byte[] bits = null; internal byte[] caps = null; internal void Reset() { size = 0; index = null; bits = null; caps = null; } } } namespace Concentus.Common { internal static class Autocorrelation { private const int QC = 10; private const int QS = 14; internal static void silk_autocorr(int[] results, BoxedValue scale, short[] inputData, int inputDataSize, int correlationCount) { int num = Inlines.silk_min_int(inputDataSize, correlationCount); scale.Val = _celt_autocorr(inputData, results, num - 1, inputDataSize); } internal static int _celt_autocorr(short[] x, int[] ac, int lag, int n) { int num = n - lag; short[] array = new short[n]; short[] array2 = x; int num2 = 0; int num3 = 1 + (n << 7); if (((uint)n & (true ? 1u : 0u)) != 0) { num3 += Inlines.SHR32(Inlines.MULT16_16(array2[0], array2[0]), 9); } for (int i = n & 1; i < n; i += 2) { num3 += Inlines.SHR32(Inlines.MULT16_16(array2[i], array2[i]), 9); num3 += Inlines.SHR32(Inlines.MULT16_16(array2[i + 1], array2[i + 1]), 9); } num2 = Inlines.celt_ilog2(num3) - 30 + 10; num2 /= 2; if (num2 > 0) { for (int i = 0; i < n; i++) { array[i] = (short)Inlines.PSHR32(array2[i], num2); } array2 = array; } else { num2 = 0; } CeltPitchXCorr.pitch_xcorr(array2, array2, ac, num, lag + 1); for (int j = 0; j <= lag; j++) { int i = j + num; int num4 = 0; for (; i < n; i++) { num4 = Inlines.MAC16_16(num4, array2[i], array2[i - j]); } ac[j] += num4; } num2 = 2 * num2; if (num2 <= 0) { ac[0] += Inlines.SHL32(1, -num2); } if (ac[0] < 268435456) { int num5 = 29 - Inlines.EC_ILOG((uint)ac[0]); for (int i = 0; i <= lag; i++) { ac[i] = Inlines.SHL32(ac[i], num5); } num2 -= num5; } else if (ac[0] >= 536870912) { int num5 = 1; if (ac[0] >= 1073741824) { num5++; } for (int i = 0; i <= lag; i++) { ac[i] = Inlines.SHR32(ac[i], num5); } num2 += num5; } return num2; } internal static int _celt_autocorr(int[] x, int[] ac, int[] window, int overlap, int lag, int n) { int num = n - lag; int[] array = new int[n]; int[] array2; if (overlap == 0) { array2 = x; } else { for (int i = 0; i < n; i++) { array[i] = x[i]; } for (int i = 0; i < overlap; i++) { array[i] = Inlines.MULT16_16_Q15(x[i], window[i]); array[n - i - 1] = Inlines.MULT16_16_Q15(x[n - i - 1], window[i]); } array2 = array; } int num2 = 0; int num3 = 1 + (n << 7); if (((uint)n & (true ? 1u : 0u)) != 0) { num3 += Inlines.SHR32(Inlines.MULT16_16(array2[0], array2[0]), 9); } for (int i = n & 1; i < n; i += 2) { num3 += Inlines.SHR32(Inlines.MULT16_16(array2[i], array2[i]), 9); num3 += Inlines.SHR32(Inlines.MULT16_16(array2[i + 1], array2[i + 1]), 9); } num2 = Inlines.celt_ilog2(num3) - 30 + 10; num2 /= 2; if (num2 > 0) { for (int i = 0; i < n; i++) { array[i] = Inlines.PSHR32(array2[i], num2); } array2 = array; } else { num2 = 0; } CeltPitchXCorr.pitch_xcorr(array2, array2, ac, num, lag + 1); for (int j = 0; j <= lag; j++) { int i = j + num; int num4 = 0; for (; i < n; i++) { num4 = Inlines.MAC16_16(num4, array2[i], array2[i - j]); } ac[j] += num4; } num2 = 2 * num2; if (num2 <= 0) { ac[0] += Inlines.SHL32(1, -num2); } if (ac[0] < 268435456) { int num5 = 29 - Inlines.EC_ILOG((uint)ac[0]); for (int i = 0; i <= lag; i++) { ac[i] = Inlines.SHL32(ac[i], num5); } num2 -= num5; } else if (ac[0] >= 536870912) { int num5 = 1; if (ac[0] >= 1073741824) { num5++; } for (int i = 0; i <= lag; i++) { ac[i] = Inlines.SHR32(ac[i], num5); } num2 += num5; } return num2; } internal static void silk_warped_autocorrelation(int[] corr, BoxedValue scale, short[] input, int warping_Q16, int length, int order) { int[] array = new int[17]; long[] array2 = new long[17]; for (int i = 0; i < length; i++) { int num = Inlines.silk_LSHIFT32(input[i], 14); for (int j = 0; j < order; j += 2) { int num2 = Inlines.silk_SMLAWB(array[j], array[j + 1] - num, warping_Q16); array[j] = num; array2[j] += Inlines.silk_RSHIFT64(Inlines.silk_SMULL(num, array[0]), 18); num = Inlines.silk_SMLAWB(array[j + 1], array[j + 2] - num2, warping_Q16); array[j + 1] = num2; array2[j + 1] += Inlines.silk_RSHIFT64(Inlines.silk_SMULL(num2, array[0]), 18); } array[order] = num; array2[order] += Inlines.silk_RSHIFT64(Inlines.silk_SMULL(num, array[0]), 18); } int a = Inlines.silk_CLZ64(array2[0]) - 35; a = Inlines.silk_LIMIT(a, -22, 20); scale.Val = -(10 + a); if (a >= 0) { for (int j = 0; j < order + 1; j++) { corr[j] = (int)Inlines.silk_LSHIFT64(array2[j], a); } } else { for (int j = 0; j < order + 1; j++) { corr[j] = (int)Inlines.silk_RSHIFT64(array2[j], -a); } } } } internal class EntropyCoder { private const int EC_WINDOW_SIZE = 32; private const int EC_UINT_BITS = 8; public const int BITRES = 3; private const int EC_SYM_BITS = 8; private const int EC_CODE_BITS = 32; private const uint EC_SYM_MAX = 255u; private const uint EC_CODE_SHIFT = 23u; private const uint EC_CODE_TOP = 2147483648u; private const uint EC_CODE_BOT = 8388608u; private const int EC_CODE_EXTRA = 7; public byte[] buf; public int buf_ptr; public uint storage; public uint end_offs; public uint end_window; public int nend_bits; public int nbits_total; public uint offs; public uint rng; public uint val; public uint ext; public int rem; public int error; private static readonly uint[] correction = new uint[8] { 35733u, 38967u, 42495u, 46340u, 50535u, 55109u, 60097u, 65535u }; public EntropyCoder() { Reset(); } public void Reset() { buf = null; buf_ptr = 0; storage = 0u; end_offs = 0u; end_window = 0u; nend_bits = 0; offs = 0u; rng = 0u; val = 0u; ext = 0u; rem = 0; error = 0; } public void Assign(EntropyCoder other) { buf = other.buf; buf_ptr = other.buf_ptr; storage = other.storage; end_offs = other.end_offs; end_window = other.end_window; nend_bits = other.nend_bits; nbits_total = other.nbits_total; offs = other.offs; rng = other.rng; val = other.val; ext = other.ext; rem = other.rem; error = other.error; } internal int read_byte() { return (offs < storage) ? buf[buf_ptr + offs++] : 0; } internal int read_byte_from_end() { return (end_offs < storage) ? buf[buf_ptr + (storage - ++end_offs)] : 0; } internal int write_byte(uint _value) { if (offs + end_offs >= storage) { return -1; } buf[buf_ptr + offs++] = (byte)_value; return 0; } internal int write_byte_at_end(uint _value) { if (offs + end_offs >= storage) { return -1; } buf[buf_ptr + (storage - ++end_offs)] = (byte)_value; return 0; } internal void dec_normalize() { while (rng <= 8388608) { nbits_total += 8; rng <<= 8; int num = rem; rem = read_byte(); num = ((num << 8) | rem) >> 1; val = (uint)(int)((val << 8) + (0xFFuL & (ulong)(~num))) & 0x7FFFFFFFu; } } internal void dec_init(byte[] _buf, int _buf_ptr, uint _storage) { buf = _buf; buf_ptr = _buf_ptr; storage = _storage; end_offs = 0u; end_window = 0u; nend_bits = 0; nbits_total = 9; offs = 0u; rng = 128u; rem = read_byte(); val = rng - 1 - (uint)(rem >> 1); error = 0; dec_normalize(); } internal uint decode(uint _ft) { ext = rng / _ft; uint num = val / ext; return _ft - Inlines.EC_MINI(num + 1, _ft); } internal uint decode_bin(uint _bits) { ext = rng >> (int)_bits; uint num = val / ext; return (uint)(1 << (int)_bits) - Inlines.EC_MINI(num + 1, (uint)(1 << (int)_bits)); } internal void dec_update(uint _fl, uint _fh, uint _ft) { uint num = ext * (_ft - _fh); val -= num; rng = ((_fl != 0) ? (ext * (_fh - _fl)) : (rng - num)); dec_normalize(); } internal int dec_bit_logp(uint _logp) { uint num = rng; uint num2 = val; uint num3 = num >> (int)_logp; int num4 = ((num2 < num3) ? 1 : 0); if (num4 == 0) { val = num2 - num3; } rng = ((num4 != 0) ? num3 : (num - num3)); dec_normalize(); return num4; } internal int dec_icdf(byte[] _icdf, uint _ftb) { uint num = rng; uint num2 = val; uint num3 = num >> (int)_ftb; int num4 = -1; uint num5; do { num5 = num; num = num3 * _icdf[++num4]; } while (num2 < num); val = num2 - num; rng = num5 - num; dec_normalize(); return num4; } internal int dec_icdf(byte[] _icdf, int _icdf_offset, uint _ftb) { uint num = rng; uint num2 = val; uint num3 = num >> (int)_ftb; int num4 = _icdf_offset - 1; uint num5; do { num5 = num; num = num3 * _icdf[++num4]; } while (num2 < num); val = num2 - num; rng = num5 - num; dec_normalize(); return num4 - _icdf_offset; } internal uint dec_uint(uint _ft) { _ft--; int num = Inlines.EC_ILOG(_ft); uint num2; if (num > 8) { num -= 8; uint ft = (_ft >> num) + 1; num2 = decode(ft); dec_update(num2, num2 + 1, ft); uint num3 = (num2 << num) | dec_bits((uint)num); if (num3 <= _ft) { return num3; } error = 1; return _ft; } _ft++; num2 = decode(_ft); dec_update(num2, num2 + 1, _ft); return num2; } internal uint dec_bits(uint _bits) { uint num = end_window; int num2 = nend_bits; if ((uint)num2 < _bits) { do { num |= (uint)(read_byte_from_end() << num2); num2 += 8; } while (num2 <= 24); } uint result = num & (uint)((1 << (int)_bits) - 1); num >>= (int)_bits; num2 -= (int)_bits; end_window = num; nend_bits = num2; nbits_total += (int)_bits; return result; } internal void enc_carry_out(int _c) { if ((long)_c != 255) { int num = _c >> 8; if (rem >= 0) { error |= write_byte((uint)(rem + num)); } if (ext != 0) { uint value = (uint)(255 + num) & 0xFFu; do { error |= write_byte(value); } while (--ext != 0); } rem = _c & 0xFF; } else { ext++; } } internal void enc_normalize() { while (rng <= 8388608) { enc_carry_out((int)(val >> 23)); val = (val << 8) & 0x7FFFFFFFu; rng <<= 8; nbits_total += 8; } } internal void enc_init(byte[] _buf, int buf_ptr, uint _size) { buf = _buf; this.buf_ptr = buf_ptr; end_offs = 0u; end_window = 0u; nend_bits = 0; nbits_total = 33; offs = 0u; rng = 2147483648u; rem = -1; val = 0u; ext = 0u; storage = _size; error = 0; } internal void encode(uint _fl, uint _fh, uint _ft) { uint num = rng / _ft; if (_fl != 0) { val += rng - num * (_ft - _fl); rng = num * (_fh - _fl); } else { rng -= num * (_ft - _fh); } enc_normalize(); } internal void encode_bin(uint _fl, uint _fh, uint _bits) { uint num = rng >> (int)_bits; if (_fl != 0) { val += (uint)((int)rng - (int)num * ((1 << (int)_bits) - (int)_fl)); rng = num * (_fh - _fl); } else { rng -= (uint)((int)num * ((1 << (int)_bits) - (int)_fh)); } enc_normalize(); } internal void enc_bit_logp(int _val, uint _logp) { uint num = rng; uint num2 = val; uint num3 = num >> (int)_logp; num -= num3; if (_val != 0) { val = num2 + num; } rng = ((_val != 0) ? num3 : num); enc_normalize(); } internal void enc_icdf(int _s, byte[] _icdf, uint _ftb) { uint num = rng >> (int)_ftb; if (_s > 0) { val += rng - num * _icdf[_s - 1]; rng = num * (uint)(_icdf[_s - 1] - _icdf[_s]); } else { rng -= num * _icdf[_s]; } enc_normalize(); } internal void enc_icdf(int _s, byte[] _icdf, int icdf_ptr, uint _ftb) { uint num = rng >> (int)_ftb; if (_s > 0) { val += rng - num * _icdf[icdf_ptr + _s - 1]; rng = num * (uint)(_icdf[icdf_ptr + _s - 1] - _icdf[icdf_ptr + _s]); } else { rng -= num * _icdf[icdf_ptr + _s]; } enc_normalize(); } internal void enc_uint(uint _fl, uint _ft) { _ft--; int num = Inlines.EC_ILOG(_ft); if (num > 8) { num -= 8; uint ft = (_ft >> num) + 1; uint num2 = _fl >> num; encode(num2, num2 + 1, ft); enc_bits(_fl & (uint)((1 << num) - 1), (uint)num); } else { encode(_fl, _fl + 1, _ft + 1); } } internal void enc_bits(uint _fl, uint _bits) { uint num = end_window; int num2 = nend_bits; if (num2 + _bits > 32) { do { error |= write_byte_at_end(num & 0xFFu); num >>= 8; num2 -= 8; } while (num2 >= 8); } num |= _fl << num2; num2 += (int)_bits; end_window = num; nend_bits = num2; nbits_total += (int)_bits; } internal void enc_patch_initial_bits(uint _val, uint _nbits) { int num = (int)(8 - _nbits); uint num2 = (uint)((1 << (int)_nbits) - 1 << num); if (offs != 0) { buf[buf_ptr] = (byte)((buf[buf_ptr] & ~num2) | (_val << num)); } else if (rem >= 0) { rem = (int)((((uint)rem & ~num2) | _val) << num); } else if (rng <= (uint)(int.MinValue >>> (int)_nbits)) { val = (val & ~(num2 << 23)) | (_val << (int)(23L + (long)num)); } else { error = -1; } } internal void enc_shrink(uint _size) { Arrays.MemMove(buf, buf_ptr + (int)_size - (int)end_offs, buf_ptr + (int)storage - (int)end_offs, (int)end_offs); storage = _size; } internal uint range_bytes() { return offs; } internal int get_error() { return error; } internal int tell() { return nbits_total - Inlines.EC_ILOG(rng); } internal uint tell_frac() { int num = nbits_total << 3; int num2 = Inlines.EC_ILOG(rng); int num3 = (int)(rng >> num2 - 16); uint num4 = (uint)((num3 >> 12) - 8); num4 += (uint)((num3 > correction[num4]) ? 1 : 0); num2 = (int)((num2 << 3) + num4); return (uint)(num - num2); } internal void enc_done() { int num = 32 - Inlines.EC_ILOG(rng); uint num2 = 2147483647u >> num; uint num3 = (val + num2) & ~num2; if ((num3 | num2) >= val + rng) { num++; num2 >>= 1; num3 = (val + num2) & ~num2; } while (num > 0) { enc_carry_out((int)(num3 >> 23)); num3 = (num3 << 8) & 0x7FFFFFFFu; num -= 8; } if (rem >= 0 || ext != 0) { enc_carry_out(0); } uint num4 = end_window; int num5; for (num5 = nend_bits; num5 >= 8; num5 -= 8) { error |= write_byte_at_end(num4 & 0xFFu); num4 >>= 8; } if (error != 0) { return; } Arrays.MemSetWithOffset(buf, (byte)0, buf_ptr + (int)offs, (int)(storage - offs - end_offs)); if (num5 <= 0) { return; } if (end_offs >= storage) { error = -1; return; } num = -num; if (offs + end_offs >= storage && num < num5) { num4 &= (uint)((1 << num) - 1); error = -1; } buf[buf_ptr + storage - end_offs - 1] |= (byte)num4; } } internal static class Inlines { private const short log2_C0 = -6793; private static readonly short[] sqrt_C = new short[5] { 23175, 11561, -3011, 1699, -664 }; [Conditional("DEBUG")] public static void OpusAssert(bool condition, string message = "Unknown error") { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16SU(int a, int b) { return (short)a * (ushort)b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16SU(short a, ushort b) { return a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16SU(int a, uint b) { return a * (int)b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_32_Q16(short a, int b) { return ADD32(MULT16_16(a, SHR(b, 16)), SHR(MULT16_16SU(a, b & 0xFFFF), 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_32_Q16(int a, int b) { return ADD32(MULT16_16(a, SHR(b, 16)), SHR(MULT16_16SU(a, b & 0xFFFF), 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_32_P16(short a, int b) { return ADD32(MULT16_16(a, SHR(b, 16)), PSHR(MULT16_16SU(a, b & 0xFFFF), 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_32_P16(int a, int b) { return ADD32(MULT16_16(a, SHR(b, 16)), PSHR(MULT16_16SU(a, b & 0xFFFF), 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_32_Q15(short a, int b) { return (a * (b >> 16) << 1) + (a * (b & 0xFFFF) >> 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_32_Q15(int a, int b) { return (a * (b >> 16) << 1) + (a * (b & 0xFFFF) >> 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT32_32_Q31(int a, int b) { return ADD32(ADD32(SHL(MULT16_16(SHR(a, 16), SHR(b, 16)), 1), SHR(MULT16_16SU(SHR(a, 16), b & 0xFFFF), 15)), SHR(MULT16_16SU(SHR(b, 16), a & 0xFFFF), 15)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short QCONST16(float x, int bits) { return (short)(0.5 + (double)(x * (float)(1 << bits))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int QCONST32(float x, int bits) { return (int)(0.5 + (double)(x * (float)(1 << bits))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short NEG16(short x) { return (short)(-x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int NEG16(int x) { return -x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int NEG32(int x) { return -x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short EXTRACT16(int x) { return (short)x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int EXTEND32(short x) { return x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int EXTEND32(int x) { return x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short SHR16(short a, int shift) { return (short)(a >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SHR16(int a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short SHL16(short a, int shift) { return (short)((ushort)a << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SHL16(int a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SHR32(int a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SHL32(int a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int PSHR32(int a, int shift) { return SHR32(a + (EXTEND32(1) << shift >> 1), shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short PSHR16(short a, int shift) { return SHR16((short)(a + (1 << shift >> 1)), shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int PSHR16(int a, int shift) { return SHR32(a + (1 << shift >> 1), shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int VSHR32(int a, int shift) { return (shift > 0) ? SHR32(a, shift) : SHL32(a, -shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int SHR(int a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int SHL(int a, int shift) { return SHL32(a, shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int SHR(short a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int SHL(short a, int shift) { return SHL32(a, shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int PSHR(int a, int shift) { return SHR(a + (EXTEND32(1) << shift >> 1), shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SATURATE(int x, int a) { return (x > a) ? a : ((x < -a) ? (-a) : x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short SATURATE16(int x) { return EXTRACT16((x > 32767) ? 32767 : ((x < -32768) ? (-32768) : x)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short ROUND16(short x, short a) { return EXTRACT16(PSHR32(x, a)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ROUND16(int x, int a) { return PSHR32(x, a); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int PDIV32(int a, int b) { return a / b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short HALF16(short x) { return SHR16(x, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int HALF16(int x) { return SHR32(x, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int HALF32(int x) { return SHR32(x, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short ADD16(short a, short b) { return (short)(a + b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ADD16(int a, int b) { return a + b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short SUB16(short a, short b) { return (short)(a - b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SUB16(int a, int b) { return a - b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ADD32(int a, int b) { return a + b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SUB32(int a, int b) { return a - b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_16(short a, short b) { return (short)(a * b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_16(int a, int b) { return a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16(int a, int b) { return a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16(short a, short b) { return a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_16(short c, short a, short b) { return c + a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_16(int c, short a, short b) { return c + a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_16(int c, int a, int b) { return c + a * b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_32_Q15(int c, short a, short b) { return ADD32(c, ADD32(MULT16_16(a, SHR(b, 15)), SHR(MULT16_16(a, b & 0x7FFF), 15))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_32_Q15(int c, int a, int b) { return ADD32(c, ADD32(MULT16_16(a, SHR(b, 15)), SHR(MULT16_16(a, b & 0x7FFF), 15))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_32_Q16(int c, short a, short b) { return ADD32(c, ADD32(MULT16_16(a, SHR(b, 16)), SHR(MULT16_16SU(a, b & 0xFFFF), 16))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAC16_32_Q16(int c, int a, int b) { return ADD32(c, ADD32(MULT16_16(a, SHR(b, 16)), SHR(MULT16_16SU(a, b & 0xFFFF), 16))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_Q11_32(short a, short b) { return SHR(MULT16_16(a, b), 11); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_Q11_32(int a, int b) { return SHR(MULT16_16(a, b), 11); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_Q11(short a, short b) { return (short)SHR(MULT16_16(a, b), 11); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_Q11(int a, int b) { return SHR(MULT16_16(a, b), 11); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_Q13(short a, short b) { return (short)SHR(MULT16_16(a, b), 13); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_Q13(int a, int b) { return SHR(MULT16_16(a, b), 13); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_Q14(short a, short b) { return (short)SHR(MULT16_16(a, b), 14); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_Q14(int a, int b) { return SHR(MULT16_16(a, b), 14); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_Q15(short a, short b) { return (short)SHR(MULT16_16(a, b), 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_Q15(int a, int b) { return SHR(MULT16_16(a, b), 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_P13(short a, short b) { return (short)SHR(ADD32(4096, MULT16_16(a, b)), 13); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_P13(int a, int b) { return SHR(ADD32(4096, MULT16_16(a, b)), 13); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_P14(short a, short b) { return (short)SHR(ADD32(8192, MULT16_16(a, b)), 14); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_P14(int a, int b) { return SHR(ADD32(8192, MULT16_16(a, b)), 14); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MULT16_16_P15(short a, short b) { return (short)SHR(ADD32(16384, MULT16_16(a, b)), 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MULT16_16_P15(int a, int b) { return SHR(ADD32(16384, MULT16_16(a, b)), 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short DIV32_16(int a, short b) { return (short)(a / b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int DIV32_16(int a, int b) { return a / b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int DIV32(int a, int b) { return a / b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short SAT16(int x) { return (x > 32767) ? short.MaxValue : ((x < -32768) ? short.MinValue : ((short)x)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short SIG2WORD16(int x) { x = PSHR32(x, 12); x = MAX32(x, -32768); x = MIN32(x, 32767); return EXTRACT16(x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MIN(short a, short b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MAX(short a, short b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MIN16(short a, short b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short MAX16(short a, short b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MIN16(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAX16(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float MIN16(float a, float b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float MAX16(float a, float b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MIN(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAX(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IMIN(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint IMIN(uint a, uint b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IMAX(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MIN32(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MAX32(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float MIN32(float a, float b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float MAX32(float a, float b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ABS16(int x) { return (x < 0) ? (-x) : x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ABS16(float x) { return (x < 0f) ? (0f - x) : x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short ABS16(short x) { return (short)((x < 0) ? (-x) : x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ABS32(int x) { return (x < 0) ? (-x) : x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint celt_udiv(uint n, uint d) { return n / d; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_udiv(int n, int d) { return n / d; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_sudiv(int n, int d) { return n / d; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_div(int a, int b) { return MULT32_32_Q31(a, celt_rcp(b)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_ilog2(int x) { return EC_ILOG((uint)x) - 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_zlog2(int x) { return (x > 0) ? celt_ilog2(x) : 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_maxabs16(int[] x, int x_ptr, int len) { int num = 0; int num2 = 0; for (int i = x_ptr; i < len + x_ptr; i++) { num = MAX32(num, x[i]); num2 = MIN32(num2, x[i]); } return MAX32(EXTEND32(num), -EXTEND32(num2)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_maxabs32(int[] x, int x_ptr, int len) { int a = 0; int num = 0; for (int i = x_ptr; i < x_ptr + len; i++) { a = MAX32(a, x[i]); num = MIN32(num, x[i]); } return MAX32(a, -num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short celt_maxabs32(short[] x, int x_ptr, int len) { short a = 0; short num = 0; for (int i = x_ptr; i < x_ptr + len; i++) { a = MAX16(a, x[i]); num = MIN16(num, x[i]); } return MAX(a, (short)(-num)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int FRAC_MUL16(int a, int b) { return 16384 + (short)a * (short)b >> 15; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint isqrt32(uint _val) { uint num = 0u; int num2 = EC_ILOG(_val) - 1 >> 1; uint num3 = (uint)(1 << num2); do { uint num4 = (num << 1) + num3 << num2; if (num4 <= _val) { num += num3; _val -= num4; } num3 >>= 1; num2--; } while (num2 >= 0); return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_sqrt(int x) { if (x == 0) { return 0; } if (x >= 1073741824) { return 32767; } int num = (celt_ilog2(x) >> 1) - 7; x = VSHR32(x, 2 * num); short a = (short)(x - 32768); int a2 = ADD16(sqrt_C[0], MULT16_16_Q15(a, ADD16(sqrt_C[1], MULT16_16_Q15(a, ADD16(sqrt_C[2], MULT16_16_Q15(a, ADD16(sqrt_C[3], MULT16_16_Q15(a, sqrt_C[4])))))))); return VSHR32(a2, 7 - num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_rcp(int x) { int num = celt_ilog2(x); int b = VSHR32(x, num - 15) - 32768; int a = ADD16(30840, MULT16_16_Q15(-15420, b)); a = SUB16(a, MULT16_16_Q15(a, ADD16(MULT16_16_Q15(a, b), ADD16(a, -32768)))); a = SUB16(a, ADD16(1, MULT16_16_Q15(a, ADD16(MULT16_16_Q15(a, b), ADD16(a, -32768))))); return VSHR32(EXTEND32(a), num - 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_rsqrt_norm(int x) { int num = x - 32768; int num2 = ADD16(23557, MULT16_16_Q15(num, ADD16(-13490, MULT16_16_Q15(num, 6713)))); int num3 = MULT16_16_Q15(num2, num2); int a = SHL16(SUB16(ADD16(MULT16_16_Q15(num3, num), num3), 16384), 1); return ADD16(num2, MULT16_16_Q15(num2, MULT16_16_Q15(a, SUB16(MULT16_16_Q15(a, 12288), 16384)))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int frac_div32(int a, int b) { int shift = celt_ilog2(b) - 29; a = VSHR32(a, shift); b = VSHR32(b, shift); int a2 = ROUND16(celt_rcp(ROUND16(b, 16)), 3); int a3 = MULT16_32_Q15(a2, a); int b2 = PSHR32(a, 2) - MULT32_32_Q31(a3, b); a3 = ADD32(a3, SHL32(MULT16_32_Q15(a2, b2), 2)); if (a3 >= 536870912) { return int.MaxValue; } if (a3 <= -536870912) { return -2147483647; } return SHL32(a3, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_log2(int x) { if (x == 0) { return -32767; } int num = celt_ilog2(x); int a = VSHR32(x, num - 15) - 32768 - 16384; int a2 = ADD16(-6793, MULT16_16_Q15(a, ADD16(15746, MULT16_16_Q15(a, ADD16(-5217, MULT16_16_Q15(a, ADD16(2545, MULT16_16_Q15(a, -1401)))))))); return SHL16((short)(num - 13), 10) + SHR16(a2, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_exp2_frac(int x) { int num = SHL16(x, 4); return ADD16(16383, MULT16_16_Q15(num, ADD16(22804, MULT16_16_Q15(num, ADD16(14819, MULT16_16_Q15(10204, num)))))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_exp2(int x) { int num = SHR16(x, 10); if (num > 14) { return 2130706432; } if (num < -15) { return 0; } int x2 = (short)celt_exp2_frac((short)(x - SHL16((short)num, 10))); return VSHR32(EXTEND32(x2), -num - 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_atan01(int x) { return MULT16_16_P15(x, ADD32(32767, MULT16_16_P15(x, ADD32(-21, MULT16_16_P15(x, ADD32(-11943, MULT16_16_P15(4936, x))))))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_atan2p(int y, int x) { int num; if (y < x) { num = celt_div(SHL32(EXTEND32(y), 15), x); if (num >= 32767) { num = 32767; } return SHR32(celt_atan01(EXTRACT16(num)), 1); } num = celt_div(SHL32(EXTEND32(x), 15), y); if (num >= 32767) { num = 32767; } return 25736 - SHR16(celt_atan01(EXTRACT16(num)), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int celt_cos_norm(int x) { x &= 0x1FFFF; if (x > SHL32(EXTEND32(1), 16)) { x = SUB32(SHL32(EXTEND32(1), 17), x); } if (((uint)x & 0x7FFFu) != 0) { if (x < SHL32(EXTEND32(1), 15)) { return _celt_cos_pi_2(EXTRACT16(x)); } return NEG32(_celt_cos_pi_2(EXTRACT16(65536 - x))); } if (((uint)x & 0xFFFFu) != 0) { return 0; } if (((uint)x & 0x1FFFFu) != 0) { return -32767; } return 32767; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int _celt_cos_pi_2(int x) { int num = MULT16_16_P15(x, x); return ADD32(1, MIN32(32766, ADD32(SUB16(32767, num), MULT16_16_P15(num, ADD32(-7651, MULT16_16_P15(num, ADD32(8277, MULT16_16_P15(-626, num)))))))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short FLOAT2INT16(float x) { x *= 32768f; if (x < -32768f) { x = -32768f; } if (x > 32767f) { x = 32767f; } return (short)x; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ROR32(int a32, int rot) { return (int)silk_ROR32((uint)a32, rot); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_ROR32(uint a32, int rot) { int num = -rot; if (rot == 0) { return a32; } if (rot < 0) { return (a32 << num) | (a32 >> 32 - num); } return (a32 << 32 - rot) | (a32 >> rot); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_MUL(int a32, int b32) { return a32 * b32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_MUL_uint(uint a32, uint b32) { return a32 * b32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_MLA(int a32, int b32, int c32) { return silk_ADD32(a32, b32 * c32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_MLA_uint(uint a32, uint b32, uint c32) { return (int)silk_ADD32(a32, b32 * c32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMULTT(int a32, int b32) { return (a32 >> 16) * (b32 >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLATT(int a32, int b32, int c32) { return silk_ADD32(a32, (b32 >> 16) * (c32 >> 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_SMLALBB(long a64, short b16, short c16) { return silk_ADD64(a64, b16 * c16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_SMULL(int a32, int b32) { return (long)a32 * (long)b32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD32_ovflw(int a, int b) { return a + b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD32_ovflw(uint a, uint b) { return (int)(a + b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SUB32_ovflw(int a, int b) { return a - b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_MLA_ovflw(int a32, int b32, int c32) { return silk_ADD32_ovflw((uint)a32, (uint)(b32 * c32)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLABB_ovflw(int a32, int b32, int c32) { return silk_ADD32_ovflw(a32, (short)b32 * (short)c32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMULBB(int a32, int b32) { return (short)a32 * (short)b32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMULWB(int a32, int b32) { return (int)((long)a32 * (long)(short)b32 >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLABB(int a32, int b32, int c32) { return a32 + (short)b32 * (short)c32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_DIV32_16(int a32, int b32) { return a32 / b32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_DIV32(int a32, int b32) { return a32 / b32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_ADD16(short a, short b) { return (short)(a + b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD32(int a, int b) { return a + b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_ADD32(uint a, uint b) { return a + b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_ADD64(long a, long b) { return a + b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_SUB16(short a, short b) { return (short)(a - b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SUB32(int a, int b) { return a - b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_SUB64(long a, long b) { return a - b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SAT8(int a) { return (a > 255) ? 255 : ((a >= 0) ? a : 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SAT16(int a) { return (a > 32767) ? 32767 : ((a < -32768) ? (-32768) : a); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SAT32(long a) { return (int)((a > int.MaxValue) ? int.MaxValue : ((a < int.MinValue) ? int.MinValue : a)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_ADD_SAT16(short a16, short b16) { return (short)silk_SAT16(silk_ADD32(a16, b16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD_SAT32(int a32, int b32) { return (((uint)(a32 + b32) & 0x80000000u) != 0) ? ((((a32 | b32) & 0x80000000u) == 0) ? int.MaxValue : (a32 + b32)) : (((a32 & b32 & 0x80000000u) != 0) ? int.MinValue : (a32 + b32)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_ADD_SAT64(long a64, long b64) { return (((a64 + b64) & long.MinValue) != 0) ? ((((a64 | b64) & long.MinValue) == 0) ? long.MaxValue : (a64 + b64)) : (((a64 & b64 & long.MinValue) != 0) ? long.MinValue : (a64 + b64)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_SUB_SAT16(short a16, short b16) { return (short)silk_SAT16(silk_SUB32(a16, b16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SUB_SAT32(int a32, int b32) { return (((uint)(a32 - b32) & 0x80000000u) != 0) ? ((((a32 ^ 0x80000000u) & b32 & 0x80000000u) != 0) ? int.MaxValue : (a32 - b32)) : (((a32 & (b32 ^ 0x80000000u) & 0x80000000u) != 0) ? int.MinValue : (a32 - b32)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_SUB_SAT64(long a64, long b64) { return (((a64 - b64) & long.MinValue) != 0) ? ((((a64 ^ long.MinValue) & b64 & long.MinValue) != 0) ? long.MaxValue : (a64 - b64)) : (((a64 & (b64 ^ long.MinValue) & long.MinValue) != 0) ? long.MinValue : (a64 - b64)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static sbyte silk_ADD_POS_SAT8(sbyte a, sbyte b) { return (sbyte)((((uint)(a + b) & 0x80u) != 0) ? 127 : (a + b)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_ADD_POS_SAT16(short a, short b) { return (short)((((uint)(a + b) & 0x8000u) != 0) ? 32767 : (a + b)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD_POS_SAT32(int a, int b) { return (((a + b) & 0x80000000u) != 0) ? int.MaxValue : (a + b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_ADD_POS_SAT64(long a, long b) { return (((a + b) & long.MinValue) != 0) ? long.MaxValue : (a + b); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static sbyte silk_LSHIFT8(sbyte a, int shift) { return (sbyte)(a << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_LSHIFT16(short a, int shift) { return (short)(a << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LSHIFT32(int a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_LSHIFT64(long a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LSHIFT(int a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LSHIFT_ovflw(int a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_LSHIFT_uint(uint a, int shift) { return a << shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LSHIFT_SAT32(int a, int shift) { return silk_LSHIFT32(silk_LIMIT(a, silk_RSHIFT32(int.MinValue, shift), silk_RSHIFT32(int.MaxValue, shift)), shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static sbyte silk_RSHIFT8(sbyte a, int shift) { return (sbyte)(a >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_RSHIFT16(short a, int shift) { return (short)(a >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_RSHIFT32(int a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_RSHIFT(int a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_RSHIFT64(long a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_RSHIFT_uint(uint a, int shift) { return a >> shift; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD_LSHIFT(int a, int b, int shift) { return a + (b << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD_LSHIFT32(int a, int b, int shift) { return a + (b << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_ADD_LSHIFT_uint(uint a, uint b, int shift) { return a + (b << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD_RSHIFT(int a, int b, int shift) { return a + (b >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_ADD_RSHIFT32(int a, int b, int shift) { return a + (b >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint silk_ADD_RSHIFT_uint(uint a, uint b, int shift) { return a + (b >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SUB_LSHIFT32(int a, int b, int shift) { return a - (b << shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SUB_RSHIFT32(int a, int b, int shift) { return a - (b >> shift); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_RSHIFT_ROUND(int a, int shift) { return (shift == 1) ? ((a >> 1) + (a & 1)) : ((a >> shift - 1) + 1 >> 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_RSHIFT_ROUND64(long a, int shift) { return (shift == 1) ? ((a >> 1) + (a & 1)) : ((a >> shift - 1) + 1 >> 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_min(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_max(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float silk_min(float a, float b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float silk_max(float a, float b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SILK_CONST(float number, int scale) { return (int)((double)(number * (float)(1L << scale)) + 0.5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_min_int(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_min_16(short a, short b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_min_32(int a, int b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_min_64(long a, long b) { return (a < b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_max_int(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_max_16(short a, short b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_max_32(int a, int b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_max_64(long a, long b) { return (a > b) ? a : b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float silk_LIMIT(float a, float limit1, float limit2) { return (!(limit1 > limit2)) ? ((a > limit2) ? limit2 : ((a < limit1) ? limit1 : a)) : ((a > limit1) ? limit1 : ((a < limit2) ? limit2 : a)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LIMIT(int a, int limit1, int limit2) { return silk_LIMIT_32(a, limit1, limit2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LIMIT_int(int a, int limit1, int limit2) { return silk_LIMIT_32(a, limit1, limit2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short silk_LIMIT_16(short a, short limit1, short limit2) { return (limit1 <= limit2) ? ((a > limit2) ? limit2 : ((a < limit1) ? limit1 : a)) : ((a > limit1) ? limit1 : ((a < limit2) ? limit2 : a)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_LIMIT_32(int a, int limit1, int limit2) { return (limit1 <= limit2) ? ((a > limit2) ? limit2 : ((a < limit1) ? limit1 : a)) : ((a > limit1) ? limit1 : ((a < limit2) ? limit2 : a)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_abs(int a) { return (a > 0) ? a : (-a); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_abs_int16(int a) { return (a ^ (a >> 15)) - (a >> 15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_abs_int32(int a) { return (a ^ (a >> 31)) - (a >> 31); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_abs_int64(long a) { return (a > 0) ? a : (-a); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_sign(int a) { return (a > 0) ? 1 : ((a < 0) ? (-1) : 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_RAND(int seed) { return silk_MLA_ovflw(907633515, seed, 196314165); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMMUL(int a32, int b32) { return (int)silk_RSHIFT64(silk_SMULL(a32, b32), 32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLAWT(int a32, int b32, int c32) { return a32 + (b32 >> 16) * (c32 >> 16) + ((b32 & 0xFFFF) * (c32 >> 16) >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_DIV32_varQ(int a32, int b32, int Qres) { int num = silk_CLZ32(silk_abs(a32)) - 1; int num2 = silk_LSHIFT(a32, num); int num3 = silk_CLZ32(silk_abs(b32)) - 1; int num4 = silk_LSHIFT(b32, num3); int num5 = silk_DIV32_16(536870911, silk_RSHIFT(num4, 16)); int num6 = silk_SMULWB(num2, num5); num2 = silk_SUB32_ovflw(num2, silk_LSHIFT_ovflw(silk_SMMUL(num4, num6), 3)); num6 = silk_SMLAWB(num6, num2, num5); int num7 = 29 + num - num3 - Qres; if (num7 < 0) { return silk_LSHIFT_SAT32(num6, -num7); } if (num7 < 32) { return silk_RSHIFT(num6, num7); } return 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_INVERSE32_varQ(int b32, int Qres) { int num = silk_CLZ32(silk_abs(b32)) - 1; int num2 = silk_LSHIFT(b32, num); int num3 = silk_DIV32_16(536870911, (short)silk_RSHIFT(num2, 16)); int a = silk_LSHIFT(num3, 16); int b33 = silk_LSHIFT(536870912 - silk_SMULWB(num2, num3), 3); a = silk_SMLAWW(a, b33, num3); int num4 = 61 - num - Qres; if (num4 <= 0) { return silk_LSHIFT_SAT32(a, -num4); } if (num4 < 32) { return silk_RSHIFT(a, num4); } return 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLAWB(int a32, int b32, int c32) { return a32 + silk_SMULWB(b32, c32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMULWT(int a32, int b32) { return (a32 >> 16) * (b32 >> 16) + ((a32 & 0xFFFF) * (b32 >> 16) >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMULBT(int a32, int b32) { return (short)a32 * (b32 >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLABT(int a32, int b32, int c32) { return a32 + (short)b32 * (c32 >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_SMLAL(long a64, int b32, int c32) { return silk_ADD64(a64, (long)b32 * (long)c32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void MatrixSet(T[] Matrix_base_adr, int Matrix_ptr, int row, int column, int N, T value) { Matrix_base_adr[Matrix_ptr + row * N + column] = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MatrixGetPointer(int row, int column, int N) { return row * N + column; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T MatrixGet(T[] Matrix_base_adr, int row, int column, int N) { return Matrix_base_adr[row * N + column]; } public static T MatrixGet(T[] Matrix_base_adr, int matrix_ptr, int row, int column, int N) { return Matrix_base_adr[matrix_ptr + row * N + column]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void MatrixSet(T[] Matrix_base_adr, int row, int column, int N, T value) { Matrix_base_adr[row * N + column] = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMULWW(int a32, int b32) { return silk_MLA(silk_SMULWB(a32, b32), a32, silk_RSHIFT_ROUND(b32, 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SMLAWW(int a32, int b32, int c32) { return silk_MLA(silk_SMLAWB(a32, b32, c32), b32, silk_RSHIFT_ROUND(c32, 16)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_CLZ64(long input) { int num = (int)silk_RSHIFT64(input, 32); if (num == 0) { return 32 + silk_CLZ32((int)input); } return silk_CLZ32(num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_CLZ32(int in32) { return (in32 == 0) ? 32 : (32 - EC_ILOG((uint)in32)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void silk_CLZ_FRAC(int input, out int lz, out int frac_Q7) { frac_Q7 = silk_ROR32(input, 24 - (lz = silk_CLZ32(input))) & 0x7F; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_SQRT_APPROX(int x) { if (x <= 0) { return 0; } silk_CLZ_FRAC(x, out var lz, out var frac_Q); int num = (((lz & 1) == 0) ? 46214 : 32768); num >>= silk_RSHIFT(lz, 1); return silk_SMLAWB(num, num, silk_SMULBB(213, frac_Q)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int MUL32_FRAC_Q(int a32, int b32, int Q) { return (int)silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_lin2log(int inLin) { silk_CLZ_FRAC(inLin, out var lz, out var frac_Q); return silk_LSHIFT(31 - lz, 7) + silk_SMLAWB(frac_Q, silk_MUL(frac_Q, 128 - frac_Q), 179); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_log2lin(int inLog_Q7) { if (inLog_Q7 < 0) { return 0; } if (inLog_Q7 >= 3967) { return int.MaxValue; } int num = silk_LSHIFT(1, silk_RSHIFT(inLog_Q7, 7)); int num2 = inLog_Q7 & 0x7F; return (inLog_Q7 >= 2048) ? silk_MLA(num, silk_RSHIFT(num, 7), silk_SMLAWB(num2, silk_SMULBB(num2, 128 - num2), -174)) : silk_ADD_RSHIFT32(num, silk_MUL(num, silk_SMLAWB(num2, silk_SMULBB(num2, 128 - num2), -174)), 7); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void silk_interpolate(short[] xi, short[] x0, short[] x1, int ifact_Q2, int d) { for (int i = 0; i < d; i++) { xi[i] = (short)silk_ADD_RSHIFT(x0[i], silk_SMULBB(x1[i] - x0[i], ifact_Q2), 2); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_inner_prod_aligned_scale(short[] inVec1, short[] inVec2, int scale, int len) { int num = 0; for (int i = 0; i < len; i++) { num = silk_ADD_RSHIFT32(num, silk_SMULBB(inVec1[i], inVec2[i]), scale); } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void silk_scale_copy_vector16(short[] data_out, int data_out_ptr, short[] data_in, int data_in_ptr, int gain_Q16, int dataSize) { for (int i = 0; i < dataSize; i++) { data_out[data_out_ptr + i] = (short)silk_SMULWB(gain_Q16, data_in[data_in_ptr + i]); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void silk_scale_vector32_Q26_lshift_18(int[] data1, int data1_ptr, int gain_Q26, int dataSize) { for (int i = data1_ptr; i < data1_ptr + dataSize; i++) { data1[i] = (int)silk_RSHIFT64(silk_SMULL(data1[i], gain_Q26), 8); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_inner_prod(short[] inVec1, int inVec1_ptr, short[] inVec2, int inVec2_ptr, int len) { int num = 0; for (int i = 0; i < len; i++) { num = MAC16_16(num, inVec1[inVec1_ptr + i], inVec2[inVec2_ptr + i]); } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int silk_inner_prod_self(short[] inVec, int inVec_ptr, int len) { int num = 0; for (int i = inVec_ptr; i < inVec_ptr + len; i++) { num = MAC16_16(num, inVec[i], inVec[i]); } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long silk_inner_prod16_aligned_64(short[] inVec1, int inVec1_ptr, short[] inVec2, int inVec2_ptr, int len) { long num = 0L; for (int i = 0; i < len; i++) { num = silk_SMLALBB(num, inVec1[inVec1_ptr + i], inVec2[inVec2_ptr + i]); } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint EC_MINI(uint a, uint b) { return a + ((b - a) & (uint)((b < a) ? (-1) : 0)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int EC_CLZ(uint x) { if (x == 0) { return 0; } x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; uint num = x - ((x >> 1) & 0x55555555); num = ((num >> 2) & 0x33333333) + (num & 0x33333333); num = ((num >> 4) + num) & 0xF0F0F0Fu; num += num >> 8; num += num >> 16; num &= 0x3Fu; return (int)(1 - num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int EC_ILOG(uint x) { if (x == 0) { return 1; } x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; uint num = x - ((x >> 1) & 0x55555555); num = ((num >> 2) & 0x33333333) + (num & 0x33333333); num = ((num >> 4) + num) & 0xF0F0F0Fu; num += num >> 8; num += num >> 16; return (int)(num & 0x3F); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int abs(int a) { if (a < 0) { return -a; } return a; } } public class SpeexResampler { private class FuncDef { public double[] table; public int oversample; public static readonly double[] kaiser12_table = new double[68] { 0.99859849, 1.0, 0.99859849, 0.99440475, 0.98745105, 0.97779076, 0.9654977, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.7262997, 0.69451601, 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.343018, 0.3150649, 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, 0.0706395, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, 0.02584161, 0.02127838, 0.0173625, 0.01402878, 0.01121463, 0.00886058, 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 5.27734E-05, 1E-05, 0.0 }; public static readonly double[] kaiser10_table = new double[36] { 0.99537781, 1.0, 0.99537781, 0.98162644, 0.95908712, 0.92831446, 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, 0.56155915, 0.5011968, 0.44221549, 0.38553619, 0.33194107, 0.28205962, 0.23636152, 0.19515633, 0.15859932, 0.1267028, 0.09935205, 0.07632451, 0.05731132, 0.0419398, 0.02979584, 0.0204451, 0.01345224, 0.00839739, 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.0, 0.0 }; public static readonly double[] kaiser8_table = new double[36] { 0.99635258, 1.0, 0.99635258, 0.98548012, 0.96759014, 0.943022, 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, 0.6345175, 0.58014482, 0.52566725, 0.47185369, 0.4194115, 0.36897272, 0.32108304, 0.27619388, 0.23465776, 0.1967267, 0.1625538, 0.13219758, 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.0236949, 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.0005, 0.0 }; public static readonly double[] kaiser6_table = new double[36] { 0.99733006, 1.0, 0.99733006, 0.98935595, 0.97618418, 0.95799003, 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.0869312, 0.067226, 0.0503182, 0.03607231, 0.02432151, 0.01487334, 0.00752, 0.0 }; public FuncDef(double[] t, int os) { table = t; oversample = os; } } private class QualityMapping { public int base_length = 0; public int oversample = 0; public float downsample_bandwidth = 0f; public float upsample_bandwidth = 0f; public FuncDef window_func = null; public static readonly QualityMapping[] quality_map = new QualityMapping[11] { new QualityMapping(8, 4, 0.83f, 0.86f, new FuncDef(FuncDef.kaiser6_table, 32)), new QualityMapping(16, 4, 0.85f, 0.88f, new FuncDef(FuncDef.kaiser6_table, 32)), new QualityMapping(32, 4, 0.882f, 0.91f, new FuncDef(FuncDef.kaiser6_table, 32)), new QualityMapping(48, 8, 0.895f, 0.917f, new FuncDef(FuncDef.kaiser8_table, 32)), new QualityMapping(64, 8, 0.921f, 0.94f, new FuncDef(FuncDef.kaiser8_table, 32)), new QualityMapping(80, 16, 0.922f, 0.94f, new FuncDef(FuncDef.kaiser10_table, 32)), new QualityMapping(96, 16, 0.94f, 0.945f, new FuncDef(FuncDef.kaiser10_table, 32)), new QualityMapping(128, 16, 0.95f, 0.95f, new FuncDef(FuncDef.kaiser10_table, 32)), new QualityMapping(160, 16, 0.96f, 0.96f, new FuncDef(FuncDef.kaiser10_table, 32)), new QualityMapping(192, 32, 0.968f, 0.968f, new FuncDef(FuncDef.kaiser12_table, 64)), new QualityMapping(256, 32, 0.975f, 0.975f, new FuncDef(FuncDef.kaiser12_table, 64)) }; private QualityMapping(int bl, int os, float dsb, float usb, FuncDef wf) { base_length = bl; oversample = os; downsample_bandwidth = dsb; upsample_bandwidth = usb; window_func = wf; } } private delegate int resampler_basic_func(int channel_index, short[] input, int input_ptr, ref int in_len, short[] output, int output_ptr, ref int out_len); private const int FIXED_STACK_ALLOC = 8192; private int in_rate = 0; private int out_rate = 0; private int num_rate = 0; private int den_rate = 0; private int quality = 0; private int nb_channels = 0; private int filt_len = 0; private int mem_alloc_size = 0; private int buffer_size = 0; private int int_advance = 0; private int frac_advance = 0; private float cutoff = 0f; private int oversample = 0; private int initialised = 0; private int started = 0; private int[] last_sample = null; private int[] samp_frac_num = null; private int[] magic_samples = null; private short[] mem = null; private short[] sinc_table = null; private int sinc_table_length = 0; private resampler_basic_func resampler_ptr = null; private int in_stride = 0; private int out_stride = 0; public int Quality { get { return quality; } set { if (value > 10 || value < 0) { throw new ArgumentException("Quality must be between 0 and 10"); } if (quality != value) { quality = value; if (initialised != 0) { update_filter(); } } } } public int InputStride { get { return in_stride; } set { in_stride = value; } } public int OutputStride { get { return out_stride; } set { out_stride = value; } } public int InputLatency => filt_len / 2; public int OutputLatency => (filt_len / 2 * den_rate + (num_rate >> 1)) / num_rate; private static short WORD2INT(float x) { return (x < -32768f) ? short.MinValue : ((x > 32767f) ? short.MaxValue : ((short)x)); } private static double compute_func(float x, FuncDef func) { float num = x * (float)func.oversample; int num2 = (int)Math.Floor(num); float num3 = num - (float)num2; double num4 = -0.1666666667 * (double)num3 + 0.1666666667 * (double)(num3 * num3 * num3); double num5 = (double)num3 + 0.5 * (double)(num3 * num3) - 0.5 * (double)(num3 * num3 * num3); double num6 = -0.3333333333 * (double)num3 + 0.5 * (double)(num3 * num3) - 0.1666666667 * (double)(num3 * num3 * num3); double num7 = 1.0 - num4 - num5 - num6; return num6 * func.table[num2] + num7 * func.table[num2 + 1] + num5 * func.table[num2 + 2] + num4 * func.table[num2 + 3]; } private static short sinc(float cutoff, float x, int N, FuncDef window_func) { float num = x * cutoff; if (Math.Abs(x) < 1E-06f) { return WORD2INT(32768f * cutoff); } if (Math.Abs(x) > 0.5f * (float)N) { return 0; } return WORD2INT(32768f * cutoff * (float)Math.Sin((float)Math.PI * num) / ((float)Math.PI * num) * (float)compute_func(Math.Abs(2f * x / (float)N), window_func)); } private static void cubic_coef(short x, out short interp0, out short interp1, out short interp2, out short interp3) { short num = Inlines.MULT16_16_P15(x, x); short num2 = Inlines.MULT16_16_P15(x, num); interp0 = (short)Inlines.PSHR32(Inlines.MULT16_16(Inlines.QCONST16(-0.16667f, 15), x) + Inlines.MULT16_16(Inlines.QCONST16(0.16667f, 15), num2), 15); interp1 = Inlines.EXTRACT16(Inlines.EXTEND32(x) + Inlines.SHR32(Inlines.SUB32(Inlines.EXTEND32(num), Inlines.EXTEND32(num2)), 1)); interp3 = (short)Inlines.PSHR32(Inlines.MULT16_16(Inlines.QCONST16(-0.33333f, 15), x) + Inlines.MULT16_16(Inlines.QCONST16(0.5f, 15), num) - Inlines.MULT16_16(Inlines.QCONST16(0.16667f, 15), num2), 15); interp2 = (short)(32767 - interp0 - interp1 - interp3); if (interp2 < short.MaxValue) { interp2++; } } private int resampler_basic_direct_single(int channel_index, short[] input, int input_ptr, ref int in_len, short[] output, int output_ptr, ref int out_len) { int num = filt_len; int num2 = 0; int num3 = last_sample[channel_index]; int num4 = samp_frac_num[channel_index]; while (num3 < in_len && num2 < out_len) { int num5 = num4 * num; int num6 = input_ptr + num3; int num7 = 0; for (int i = 0; i < num; i++) { num7 += Inlines.MULT16_16(sinc_table[num5 + i], input[num6 + i]); } output[output_ptr + out_stride * num2++] = Inlines.SATURATE16(Inlines.PSHR32(num7, 15)); num3 += int_advance; num4 += frac_advance; if (num4 >= den_rate) { num4 -= den_rate; num3++; } } last_sample[channel_index] = num3; samp_frac_num[channel_index] = num4; return num2; } private int resampler_basic_interpolate_single(int channel_index, short[] input, int input_ptr, ref int in_len, short[] output, int output_ptr, ref int out_len) { int num = filt_len; int num2 = 0; int num3 = last_sample[channel_index]; int num4 = samp_frac_num[channel_index]; while (num3 < in_len && num2 < out_len) { int num5 = input_ptr + num3; int num6 = num4 * oversample / den_rate; short x = (short)Inlines.PDIV32(Inlines.SHL32(num4 * oversample % den_rate, 15), den_rate); int num7 = 0; int num8 = 0; int num9 = 0; int num10 = 0; for (int i = 0; i < num; i++) { short a = input[num5 + i]; num7 += Inlines.MULT16_16(a, sinc_table[4 + (i + 1) * oversample - num6 - 2]); num8 += Inlines.MULT16_16(a, sinc_table[4 + (i + 1) * oversample - num6 - 1]); num9 += Inlines.MULT16_16(a, sinc_table[4 + (i + 1) * oversample - num6]); num10 += Inlines.MULT16_16(a, sinc_table[4 + (i + 1) * oversample - num6 + 1]); } cubic_coef(x, out var interp, out var interp2, out var interp3, out var interp4); int a2 = Inlines.MULT16_32_Q15(interp, Inlines.SHR32(num7, 1)) + Inlines.MULT16_32_Q15(interp2, Inlines.SHR32(num8, 1)) + Inlines.MULT16_32_Q15(interp3, Inlines.SHR32(num9, 1)) + Inlines.MULT16_32_Q15(interp4, Inlines.SHR32(num10, 1)); output[output_ptr + out_stride * num2++] = Inlines.SATURATE16(Inlines.PSHR32(a2, 14)); num3 += int_advance; num4 += frac_advance; if (num4 >= den_rate) { num4 -= den_rate; num3++; } } last_sample[channel_index] = num3; samp_frac_num[channel_index] = num4; return num2; } private void update_filter() { int num = filt_len; oversample = QualityMapping.quality_map[quality].oversample; filt_len = QualityMapping.quality_map[quality].base_length; if (num_rate > den_rate) { cutoff = QualityMapping.quality_map[quality].downsample_bandwidth * (float)den_rate / (float)num_rate; filt_len = filt_len * num_rate / den_rate; filt_len = ((filt_len - 1) & -8) + 8; if (2 * den_rate < num_rate) { oversample >>= 1; } if (4 * den_rate < num_rate) { oversample >>= 1; } if (8 * den_rate < num_rate) { oversample >>= 1; } if (16 * den_rate < num_rate) { oversample >>= 1; } if (oversample < 1) { oversample = 1; } } else { cutoff = QualityMapping.quality_map[quality].upsample_bandwidth; } if (den_rate <= 16 * (oversample + 8)) { if (sinc_table == null) { sinc_table = new short[filt_len * den_rate]; } else if (sinc_table_length < filt_len * den_rate) { sinc_table = new short[filt_len * den_rate]; sinc_table_length = filt_len * den_rate; } for (int i = 0; i < den_rate; i++) { for (int j = 0; j < filt_len; j++) { sinc_table[i * filt_len + j] = sinc(cutoff, (float)(j - filt_len / 2 + 1) - (float)i / (float)den_rate, filt_len, QualityMapping.quality_map[quality].window_func); } } resampler_ptr = resampler_basic_direct_single; } else { if (sinc_table == null) { sinc_table = new short[filt_len * oversample + 8]; } else if (sinc_table_length < filt_len * oversample + 8) { sinc_table = new short[filt_len * oversample + 8]; sinc_table_length = filt_len * oversample + 8; } for (int i = -4; i < oversample * filt_len + 4; i++) { sinc_table[i + 4] = sinc(cutoff, (float)i / (float)oversample - (float)(filt_len / 2), filt_len, QualityMapping.quality_map[quality].window_func); } resampler_ptr = resampler_basic_interpolate_single; } int_advance = num_rate / den_rate; frac_advance = num_rate % den_rate; if (mem == null) { mem_alloc_size = filt_len - 1 + buffer_size; mem = new short[nb_channels * mem_alloc_size]; for (int i = 0; i < nb_channels * mem_alloc_size; i++) { mem[i] = 0; } } else if (started == 0) { mem_alloc_size = filt_len - 1 + buffer_size; mem = new short[nb_channels * mem_alloc_size]; for (int i = 0; i < nb_channels * mem_alloc_size; i++) { mem[i] = 0; } } else if (filt_len > num) { int num2 = mem_alloc_size; if (filt_len - 1 + buffer_size > mem_alloc_size) { mem_alloc_size = filt_len - 1 + buffer_size; mem = new short[nb_channels * mem_alloc_size]; } for (int i = nb_channels - 1; i >= 0; i--) { int num3 = num; num3 = num + 2 * magic_samples[i]; for (int j = num - 2 + magic_samples[i]; j >= 0; j--) { mem[i * mem_alloc_size + j + magic_samples[i]] = mem[i * num2 + j]; } for (int j = 0; j < magic_samples[i]; j++) { mem[i * mem_alloc_size + j] = 0; } magic_samples[i] = 0; if (filt_len > num3) { int j; for (j = 0; j < num3 - 1; j++) { mem[i * mem_alloc_size + (filt_len - 2 - j)] = mem[i * mem_alloc_size + (num3 - 2 - j)]; } for (; j < filt_len - 1; j++) { mem[i * mem_alloc_size + (filt_len - 2 - j)] = 0; } last_sample[i] += (filt_len - num3) / 2; } else { magic_samples[i] = (num3 - filt_len) / 2; for (int j = 0; j < filt_len - 1 + magic_samples[i]; j++) { mem[i * mem_alloc_size + j] = mem[i * mem_alloc_size + j + magic_samples[i]]; } } } } else { if (filt_len >= num) { return; } for (int i = 0; i < nb_channels; i++) { int num4 = magic_samples[i]; magic_samples[i] = (num - filt_len) / 2; for (int j = 0; j < filt_len - 1 + magic_samples[i] + num4; j++) { mem[i * mem_alloc_size + j] = mem[i * mem_alloc_size + j + magic_samples[i]]; } magic_samples[i] += num4; } } } private void speex_resampler_process_native(int channel_index, ref int in_len, short[] output, int output_ptr, ref int out_len) { int num = 0; int num2 = filt_len; int num3 = 0; int num4 = channel_index * mem_alloc_size; started = 1; num3 = resampler_ptr(channel_index, mem, num4, ref in_len, output, output_ptr, ref out_len); if (last_sample[channel_index] < in_len) { in_len = last_sample[channel_index]; } out_len = num3; last_sample[channel_index] -= in_len; int num5 = in_len; for (num = num4; num < num2 - 1 + num4; num++) { mem[num] = mem[num + num5]; } } private int speex_resampler_magic(int channel_index, short[] output, ref int output_ptr, int out_len) { int in_len = magic_samples[channel_index]; int num = channel_index * mem_alloc_size; int num2 = filt_len; speex_resampler_process_native(channel_index, ref in_len, output, output_ptr, ref out_len); magic_samples[channel_index] -= in_len; if (magic_samples[channel_index] != 0) { for (int i = num; i < magic_samples[channel_index] + num; i++) { mem[num2 - 1 + i] = mem[num2 - 1 + i + in_len]; } } output_ptr += out_len * out_stride; return out_len; } public SpeexResampler(int nb_channels, int in_rate, int out_rate, int quality) : this(nb_channels, in_rate, out_rate, in_rate, out_rate, quality) { } public SpeexResampler(int nb_channels, int ratio_num, int ratio_den, int in_rate, int out_rate, int quality) { if (quality > 10 || quality < 0) { throw new ArgumentException("Quality must be between 0 and 10"); } initialised = 0; started = 0; this.in_rate = 0; this.out_rate = 0; num_rate = 0; den_rate = 0; this.quality = -1; sinc_table_length = 0; mem_alloc_size = 0; filt_len = 0; mem = null; resampler_ptr = null; cutoff = 1f; this.nb_channels = nb_channels; in_stride = 1; out_stride = 1; buffer_size = 160; last_sample = new int[nb_channels]; magic_samples = new int[nb_channels]; samp_frac_num = new int[nb_channels]; for (int i = 0; i < nb_channels; i++) { last_sample[i] = 0; magic_samples[i] = 0; samp_frac_num[i] = 0; } Quality = quality; SetRateFraction(ratio_num, ratio_den, in_rate, out_rate); update_filter(); initialised = 1; } public void Process(int channel_index, short[] input, int input_ptr, ref int in_len, short[] output, int output_ptr, ref int out_len) { int num = in_len; int num2 = out_len; int num3 = channel_index * mem_alloc_size; int num4 = filt_len - 1; int num5 = mem_alloc_size - num4; int num6 = in_stride; if (magic_samples[channel_index] != 0) { num2 -= speex_resampler_magic(channel_index, output, ref output_ptr, num2); } if (magic_samples[channel_index] == 0) { while (num != 0 && num2 != 0) { int in_len2 = ((num > num5) ? num5 : num); int out_len2 = num2; if (input != null) { for (int i = 0; i < in_len2; i++) { mem[num3 + i + num4] = input[input_ptr + i * num6]; } } else { for (int i = 0; i < in_len2; i++) { mem[num3 + i + num4] = 0; } } speex_resampler_process_native(channel_index, ref in_len2, output, output_ptr, ref out_len2); num -= in_len2; num2 -= out_len2; output_ptr += out_len2 * out_stride; if (input != null) { input_ptr += in_len2 * num6; } } } in_len -= num; out_len -= num2; } public void Process(int channel_index, float[] input, int input_ptr, ref int in_len, float[] output, int output_ptr, ref int out_len) { int num = in_stride; int num2 = out_stride; int num3 = in_len; int num4 = out_len; int num5 = channel_index * mem_alloc_size; int num6 = mem_alloc_size - (filt_len - 1); int num7 = ((num4 < 8192) ? num4 : 8192); short[] array = new short[num7]; out_stride = 1; while (num3 != 0 && num4 != 0) { int output_ptr2 = 0; int in_len2 = ((num3 > num6) ? num6 : num3); int out_len2 = ((num4 > num7) ? num7 : num4); int num8 = 0; if (magic_samples[channel_index] != 0) { num8 = speex_resampler_magic(channel_index, array, ref output_ptr2, out_len2); out_len2 -= num8; num4 -= num8; } if (magic_samples[channel_index] == 0) { if (input != null) { for (int i = 0; i < in_len2; i++) { mem[num5 + i + filt_len - 1] = WORD2INT(input[input_ptr + i * num]); } } else { for (int i = 0; i < in_len2; i++) { mem[num5 + i + filt_len - 1] = 0; } } speex_resampler_process_native(channel_index, ref in_len2, array, output_ptr2, ref out_len2); } else { in_len2 = 0; out_len2 = 0; } for (int i = 0; i < out_len2 + num8; i++) { output[output_ptr + i * num2] = array[i]; } num3 -= in_len2; num4 -= out_len2; output_ptr += (out_len2 + num8) * num2; if (input != null) { input_ptr += in_len2 * num; } } out_stride = num2; in_len -= num3; out_len -= num4; } public void ProcessInterleaved(float[] input, int input_ptr, ref int in_len, float[] output, int output_ptr, ref int out_len) { int num = out_len; int num2 = in_len; int num3 = in_stride; int num4 = out_stride; in_stride = (out_stride = nb_channels); for (int i = 0; i < nb_channels; i++) { out_len = num; in_len = num2; if (input != null) { Process(i, input, input_ptr + i, ref in_len, output, output_ptr + i, ref out_len); } else { Process(i, null, 0, ref in_len, output, output_ptr + i, ref out_len); } } in_stride = num3; out_stride = num4; } public void ProcessInterleaved(short[] input, int input_ptr, ref int in_len, short[] output, int output_ptr, ref int out_len) { int num = out_len; int num2 = in_len; int num3 = in_stride; int num4 = out_stride; in_stride = (out_stride = nb_channels); for (int i = 0; i < nb_channels; i++) { out_len = num; in_len = num2; if (input != null) { Process(i, input, input_ptr + i, ref in_len, output, output_ptr + i, ref out_len); } else { Process(i, null, 0, ref in_len, output, output_ptr + i, ref out_len); } } in_stride = num3; out_stride = num4; } public void SkipZeroes() { for (int i = 0; i < nb_channels; i++) { last_sample[i] = filt_len / 2; } } public void ResetMem() { for (int i = 0; i < nb_channels; i++) { last_sample[i] = 0; magic_samples[i] = 0; samp_frac_num[i] = 0; } for (int i = 0; i < nb_channels * (filt_len - 1); i++) { mem[i] = 0; } } public void SetRates(int in_rate, int out_rate) { SetRateFraction(in_rate, out_rate, in_rate, out_rate); } public void GetRates(out int in_rate, out int out_rate) { in_rate = this.in_rate; out_rate = this.out_rate; } public void SetRateFraction(int ratio_num, int ratio_den, int in_rate, int out_rate) { if (this.in_rate == in_rate && this.out_rate == out_rate && num_rate == ratio_num && den_rate == ratio_den) { return; } int num = den_rate; this.in_rate = in_rate; this.out_rate = out_rate; num_rate = ratio_num; den_rate = ratio_den; for (int i = 2; i <= Inlines.IMIN(num_rate, den_rate); i++) { while (num_rate % i == 0 && den_rate % i == 0) { num_rate /= i; den_rate /= i; } } if (num > 0) { for (int j = 0; j < nb_channels; j++) { samp_frac_num[j] = samp_frac_num[j] * den_rate / num; if (samp_frac_num[j] >= den_rate) { samp_frac_num[j] = den_rate - 1; } } } if (initialised != 0) { update_filter(); } } public void GetRateFraction(out int ratio_num, out int ratio_den) { ratio_num = num_rate; ratio_den = den_rate; } } } namespace Concentus.Common.CPlusPlus { internal static class Arrays { internal static T[][] InitTwoDimensionalArray(int x, int y) { T[][] array = new T[x][]; for (int i = 0; i < x; i++) { array[i] = new T[y]; } return array; } internal static Pointer> InitTwoDimensionalArrayPointer(int x, int y) { Pointer> pointer = Pointer.Malloc>(x); for (int i = 0; i < x; i++) { pointer[i] = Pointer.Malloc(y); } return pointer; } internal static T[][][] InitThreeDimensionalArray(int x, int y, int z) { T[][][] array = new T[x][][]; for (int i = 0; i < x; i++) { array[i] = new T[y][]; for (int j = 0; j < y; j++) { array[i][j] = new T[z]; } } return array; } internal static void MemSet(T[] array, T value) { for (int i = 0; i < array.Length; i++) { array[i] = value; } } internal static void MemSet(T[] array, T value, int length) { for (int i = 0; i < length; i++) { array[i] = value; } } internal static void MemSetWithOffset(T[] array, T value, int offset, int length) { for (int i = offset; i < offset + length; i++) { array[i] = value; } } internal static void MemMove(T[] array, int src_idx, int dst_idx, int length) { if (src_idx == dst_idx || length == 0) { return; } if (src_idx + length > dst_idx || dst_idx + length > src_idx) { if (dst_idx < src_idx) { for (int i = 0; i < length; i++) { array[i + dst_idx] = array[i + src_idx]; } return; } for (int i = length - 1; i >= 0; i--) { array[i + dst_idx] = array[i + src_idx]; } } else { Array.Copy(array, src_idx, array, dst_idx, length); } } } public class BoxedValue { public T Val; public BoxedValue(T v = default(T)) { Val = v; } public override string ToString() { return (Val == null) ? "null" : Val.ToString(); } } public class Pointer { private const bool CHECK_UNINIT_MEM = false; private T[] _array; private int _offset; public int Offset => _offset; public T[] Data => _array; public T this[int index] { get { return _array[index + _offset]; } set { _array[index + _offset] = value; } } public T this[uint index] { get { return this[(int)index]; } set { this[(int)index] = value; } } public Pointer(int capacity) { _array = new T[capacity]; _offset = 0; } public Pointer(T[] buffer) { _array = buffer; _offset = 0; } public Pointer(T[] buffer, int absoluteOffset) { _array = buffer; _offset = absoluteOffset; } public Pointer Iterate(out T returnVal) { returnVal = _array[_offset]; return Point(1); } public Pointer Point(int relativeOffset) { if (relativeOffset == 0) { return this; } return new Pointer(_array, _offset + relativeOffset); } public Pointer Point(uint relativeOffset) { if (relativeOffset == 0) { return this; } return new Pointer(_array, _offset + (int)relativeOffset); } private static string invert_endianness(string hexstring) { StringBuilder stringBuilder = new StringBuilder(hexstring.Length); for (int i = 0; i < hexstring.Length / 2; i++) { stringBuilder.Append(hexstring.Substring(hexstring.Length - (i + 1) * 2, 2)); } return stringBuilder.ToString(); } private static void PrintMemCopy(E[] source, int sourceOffset, int length) { if (typeof(E) == typeof(int) || typeof(E) == typeof(uint)) { string text = string.Empty; for (int i = 0; i < length; i++) { text += invert_endianness($"{source[i + sourceOffset]:x8}"); } } else if (typeof(E) == typeof(short) || typeof(E) == typeof(ushort)) { string text = string.Empty; for (int i = 0; i < length; i++) { text += invert_endianness($"{source[i + sourceOffset]:x4}"); } } else if (typeof(E) == typeof(byte) || typeof(E) == typeof(sbyte)) { string text = string.Empty; for (int i = 0; i < length; i++) { text += invert_endianness($"{source[i + sourceOffset]:x2}"); } } } public void MemCopyTo(Pointer destination, int length) { if (destination != null) { Array.Copy(_array, _offset, destination._array, destination.Offset, length); return; } for (int i = 0; i < length; i++) { destination[i] = _array[i + _offset]; } } public void MemCopyTo(T[] destination, int offset, int length) { Array.Copy(_array, _offset, destination, offset, length); } public void MemCopyFrom(T[] source, int sourceOffset, int length) { Array.Copy(source, sourceOffset, _array, _offset, length); } public void MemSet(T value, int length) { MemSet(value, (uint)length); } public void MemSet(T value, uint length) { for (int i = _offset; i < _offset + length; i++) { _array[i] = value; } } public void MemMoveTo(Pointer other, int length) { if (_array == other._array) { MemMove(other.Offset - Offset, length); } else { MemCopyTo(other, length); } } public void MemMove(int move_dist, int length) { Arrays.MemMove(_array, _offset, _offset + move_dist, length); } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return false; } Pointer pointer = (Pointer)obj; return pointer._offset == _offset && pointer._array == _array; } public override int GetHashCode() { return _array.GetHashCode() + _offset.GetHashCode(); } } public static class Pointer { public static Pointer Malloc(int capacity) { return new Pointer(capacity); } public static Pointer GetPointer(this E[] memory, int offset = 0) { if (memory == null) { return null; } return new Pointer(memory, offset); } } } namespace Concentus { 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 = (float)Math.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; float num3; if (num < num2) { num3 = (num2 + 0.678484f * num) * (num2 + 0.08595542f * num); if (num3 != 0f) { return (0f - x) * y * (num2 + 0.43157974f * num) / num3 + ((y < 0f) ? (-(float)Math.PI / 2f) : ((float)Math.PI / 2f)); } return (y < 0f) ? (-(float)Math.PI / 2f) : ((float)Math.PI / 2f); } num3 = (num + 0.678484f * num2) * (num + 0.08595542f * num2); if (num3 != 0f) { return x * y * (num + 0.43157974f * num2) / num3 + ((y < 0f) ? (-(float)Math.PI / 2f) : ((float)Math.PI / 2f)) - ((x * y < 0f) ? (-(float)Math.PI / 2f) : ((float)Math.PI / 2f)); } return ((y < 0f) ? (-(float)Math.PI / 2f) : ((float)Math.PI / 2f)) - ((x * y < 0f) ? (-(float)Math.PI / 2f) : ((float)Math.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(TonalityAnalysisState tonal, CeltMode celt_mode, T[] x, int x_ptr, int len, int offset, int c1, int c2, int C, int lsb_depth, Downmix.downmix_func 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, x_ptr, 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.MemMove(tonal.inmem, 480, 0, 240); int num11 = len - (720 - tonal.mem_fill); downmix(x, x_ptr, 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 * (float)Math.PI) * fast_atan2f(y, x2); float num13 = num12 - angle[i]; float num14 = num13 - d_angle[i]; float num15 = 1f / (2f * (float)Math.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 num31; float num32 = (num31 = 0f); for (int i = 0; i < 8; i++) { num32 += (float)Math.Sqrt(tonal.E[i][j]); num31 += tonal.E[i][j]; } float num33 = Inlines.MIN16(0.99f, num32 / (float)Math.Sqrt(1E-15 + (double)(8f * num31))); 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 num27 = 0f; int num36 = Tables.extra_bands[j]; int num37 = Tables.extra_bands[j + 1]; for (int i = num36; i < num37; 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]; num27 += num30; } num6 = Inlines.MAX32(num6, num27); tonal.meanE[j] = Inlines.MAX32((1f - num9) * tonal.meanE[j], num27); num27 = Inlines.MAX32(num27, tonal.meanE[j]); num34 = Inlines.MAX32(0.05f * num34, num27); if ((double)num27 > 0.1 * (double)num34 && num27 * 1E+09f > num6 && num27 > num35 * (float)(num37 - num36)) { 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 num38 = 0f; for (int j = 0; j < 16; j++) { num38 += Tables.dct_table[i * 16 + j] * array2[j]; } array3[i] = num38; } 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; if (analysisInfo.enabled) { mlp.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 num39 = 5E-05f * array5[1]; float num40 = 0.05f; float num41 = Inlines.MAX16(0.05f, Inlines.MIN16(0.95f, array5[0])); float num42 = Inlines.MAX16(0.05f, Inlines.MIN16(0.95f, tonal.music_prob)); num40 = 0.01f + 0.05f * Inlines.ABS16(num41 - num42) / (num41 * (1f - num42) + num42 * (1f - num41)); float num43 = (1f - tonal.music_prob) * (1f - num39) + tonal.music_prob * num39; float num44 = tonal.music_prob * (1f - num39) + (1f - tonal.music_prob) * num39; num43 *= (float)Math.Pow(1f - array5[0], num40); num44 *= (float)Math.Pow(array5[0], num40); tonal.music_prob = num44 / (num43 + num44); analysisInfo.music_prob = tonal.music_prob; float num45 = 1E-20f; float num46 = (float)Math.Pow(1f - array5[0], num40); float num47 = (float)Math.Pow(array5[0], num40); if (tonal.count == 1) { tonal.pspeech[0] = 0.5f; tonal.pmusic[0] = 0.5f; } float num48 = tonal.pspeech[0] + tonal.pspeech[1]; float num49 = tonal.pmusic[0] + tonal.pmusic[1]; tonal.pspeech[0] = num48 * (1f - num39) * num46; tonal.pmusic[0] = num49 * (1f - num39) * num47; for (int i = 1; i < 199; i++) { tonal.pspeech[i] = tonal.pspeech[i + 1] * num46; tonal.pmusic[i] = tonal.pmusic[i + 1] * num47; } tonal.pspeech[199] = num49 * num39 * num46; tonal.pmusic[199] = num48 * num39 * num47; for (int i = 0; i < 200; i++) { num45 += tonal.pspeech[i] + tonal.pmusic[i]; } num45 = 1f / num45; for (int i = 0; i < 200; i++) { tonal.pspeech[i] *= num45; tonal.pmusic[i] *= num45; } num45 = tonal.pmusic[0]; for (int i = 1; i < 200; i++) { num45 += tonal.pspeech[i]; } if ((double)array5[1] > 0.75) { if ((double)tonal.music_prob > 0.9) { float num50 = 1f / (float)(++tonal.music_confidence_count); tonal.music_confidence_count = Inlines.IMIN(tonal.music_confidence_count, 500); tonal.music_confidence += num50 * Inlines.MAX16(-0.2f, array5[0] - tonal.music_confidence); } if ((double)tonal.music_prob < 0.1) { float num50 = 1f / (float)(++tonal.speech_confidence_count); tonal.speech_confidence_count = Inlines.IMIN(tonal.speech_confidence_count, 500); tonal.speech_confidence += num50 * 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); } else { analysisInfo.music_prob = 0f; } analysisInfo.bandwidth = num5; analysisInfo.noisiness = num23; analysisInfo.valid = 1; } internal static void run_analysis(TonalityAnalysisState analysis, CeltMode celt_mode, T[] analysis_pcm, int analysis_pcm_ptr, int analysis_frame_size, int frame_size, int c1, int c2, int C, int Fs, int lsb_depth, Downmix.downmix_func downmix, AnalysisInfo analysis_info) { if (analysis_pcm != null) { 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, analysis_pcm_ptr, 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); } } public 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(short[] input, int input_ptr, int cutoff_Hz, 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(short[] input, int input_ptr, int cutoff_Hz, 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 b = Inlines.EXTRACT16(Inlines.HALF32(pcm_buf[i * channels] - pcm_buf[i * channels + 1])); b = Inlines.MULT16_16_Q15(g2, b); pcm_buf[i * channels] = (short)(pcm_buf[i * channels] - b); pcm_buf[i * channels + 1] = (short)(pcm_buf[i * channels + 1] + b); } } 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 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 * 2] = (short)Inlines.MULT16_16_Q15(a, buffer[buf_ptr + i * 2]); buffer[buf_ptr + i * 2 + 1] = (short)Inlines.MULT16_16_Q15(a, buffer[buf_ptr + i * 2 + 1]); } } int num4 = 0; do { for (int i = num2; i < frame_size; i++) { buffer[buf_ptr + i * channels + num4] = (short)Inlines.MULT16_16_Q15(g2, buffer[buf_ptr + i * channels + num4]); } } while (++num4 < channels); } internal static float transient_boost(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(24, 16); int[][] array2 = Arrays.InitTwoDimensionalArray(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[] x, int x_ptr, int len, int C, int Fs, int bitrate, int tonality, float[] mem, int buffering, Downmix.downmix_func 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, x_ptr, 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; if (variable_duration == OpusFramesize.OPUS_FRAMESIZE_ARG) { num = frame_size; } else if (variable_duration == OpusFramesize.OPUS_FRAMESIZE_VARIABLE) { num = Fs / 50; } else { if (variable_duration < OpusFramesize.OPUS_FRAMESIZE_2_5_MS || variable_duration > OpusFramesize.OPUS_FRAMESIZE_60_MS) { return -1; } num = Inlines.IMIN(3 * Fs / 50, Fs / 400 << (int)(variable_duration - 5001)); } 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[] analysis_pcm, int analysis_pcm_ptr, int frame_size, OpusFramesize variable_duration, int C, int Fs, int bitrate_bps, int delay_compensation, Downmix.downmix_func 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, analysis_pcm_ptr, 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(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 num2; int num4 = (num3 = (num2 = 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); num4 += Inlines.SHR32(num5, 10); num3 += Inlines.SHR32(num6, 10); num2 += Inlines.SHR32(num7, 10); } mem.XX += Inlines.MULT16_32_Q15(a, num4 - mem.XX); mem.XY += Inlines.MULT16_32_Q15(a, num3 - mem.XY); mem.YY += Inlines.MULT16_32_Q15(a, num2 - 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(short[] in1, int in1_ptr, short[] in2, int in2_ptr, 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]; } public static string GetVersionString() { return "concentus 1.1.4-fixed-parity"; } } internal static class Downmix { public delegate void downmix_func(T[] _x, int x_ptr, int[] sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C); internal static void downmix_float(float[] x, int x_ptr, int[] sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C) { int num = c1 + x_ptr; for (int i = 0; i < subframe; i++) { sub[sub_ptr + i] = Inlines.FLOAT2INT16(x[(i + offset) * C + num]); } if (c2 > -1) { int num2 = c2 + x_ptr; for (int i = 0; i < subframe; i++) { sub[sub_ptr + i] += Inlines.FLOAT2INT16(x[(i + offset) * C + num2]); } } else if (c2 == -2) { for (int j = 1; j < C; j++) { int num3 = j + x_ptr; for (int i = 0; i < subframe; i++) { sub[sub_ptr + i] += Inlines.FLOAT2INT16(x[(i + offset) * C + num3]); } } } int num4 = 4096; num4 = ((C != -2) ? (num4 / 2) : (num4 / C)); for (int i = 0; i < subframe; i++) { sub[sub_ptr + i] *= num4; } } internal static void downmix_int(short[] x, int x_ptr, 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 mlp { 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 num2 = weights[num]; num++; for (int j = 0; j < m.topo[1]; j++) { num2 += array[j] * weights[num]; num++; } output[i] = tansig_approx(num2); } } } 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 _out, Pointer _ps, Pointer _bands, int _nbands, Pointer _in, int _nchannels, int _nframes, int _window_sz, int _step, int _downsample) { Pointer pointer = Concentus.Common.CPlusPlus.Pointer.Malloc((3 + _nchannels) * _window_sz); Pointer pointer2 = pointer.Point(_window_sz); Pointer pointer3 = pointer2.Point(_window_sz); Pointer 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]; float[] array2 = array; for (; i < _bands[m + 1]; i++) { for (int k = 0; k < _nchannels; k++) { int num2 = 0; float num3; float num4 = (num3 = 0f); for (int l = 0; l < _window_sz; l++) { num4 += pointer2[num2] * pointer4[k * _window_sz + l]; num3 -= pointer3[num2] * pointer4[k * _window_sz + l]; num2 += i; if (num2 >= _window_sz) { num2 -= _window_sz; } } num4 *= (float)_downsample; num3 *= (float)_downsample; _ps[(j * num + i) * _nchannels + k] = num4 * num4 + num3 * num3 + 100000f; array2[k] += _ps[(j * num + i) * _nchannels + k]; } } if (_out != null) { _out[(j * _nbands + m) * _nchannels] = array2[0] / (float)(_bands[m + 1] - _bands[m]); if (_nchannels == 2) { _out[(j * _nbands + m) * _nchannels + 1] = array2[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 pointer = Concentus.Common.CPlusPlus.Pointer.Malloc(num6 * 21 * nchannels); Pointer pointer2 = Concentus.Common.CPlusPlus.Pointer.Malloc(num6 * 240 * nchannels); Pointer pointer3 = Concentus.Common.CPlusPlus.Pointer.Malloc(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 num19 = (float)(100.0 * (1.0 - 0.5 * Math.Log(1.0 + num14) / Math.Log(1.13))); if (num19 < 0f) { } return num19; } } public static class OpusConstants { public const int OPUS_AUTO = -1000; public const int OPUS_BITRATE_MAX = -1; public const int NB_FRAMES = 8; public const int NB_TBANDS = 18; public const int NB_TOT_BANDS = 21; public const int NB_TONAL_SKIP_BANDS = 9; public const int ANALYSIS_BUF_SIZE = 720; public const int DETECT_SIZE = 200; public const int MAX_ENCODER_BUFFER = 480; } public class OpusException : Exception { public OpusException() { } public OpusException(string message) : base(message) { } public OpusException(string message, int opus_error_code) : base(message + ": " + CodecHelpers.opus_strerror(opus_error_code)) { } } 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 { public const int stereo_voice_threshold = 30000; public const int stereo_music_threshold = 30000; 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 * (float)Math.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 static readonly int[][] mode_thresholds = new int[2][] { new int[2] { 64000, 16000 }, new int[2] { 36000, 16000 } }; } } namespace Concentus.Enums { public enum OpusApplication { OPUS_APPLICATION_UNIMPLEMENTED = 0, OPUS_APPLICATION_VOIP = 2048, OPUS_APPLICATION_AUDIO = 2049, OPUS_APPLICATION_RESTRICTED_LOWDELAY = 2051 } public enum OpusBandwidth { OPUS_BANDWIDTH_AUTO = -1000, OPUS_BANDWIDTH_NARROWBAND = 1101, OPUS_BANDWIDTH_MEDIUMBAND = 1102, OPUS_BANDWIDTH_WIDEBAND = 1103, OPUS_BANDWIDTH_SUPERWIDEBAND = 1104, OPUS_BANDWIDTH_FULLBAND = 1105 } internal static class OpusBandwidthHelpers { internal static int GetOrdinal(OpusBandwidth bw) { return (int)(bw - 1101); } internal static OpusBandwidth MIN(OpusBandwidth a, OpusBandwidth b) { if (a < b) { return a; } return b; } internal static OpusBandwidth MAX(OpusBandwidth a, OpusBandwidth b) { if (a > b) { return a; } return b; } } public static class OpusControl { public const int OPUS_SET_APPLICATION_REQUEST = 4000; public const int OPUS_GET_APPLICATION_REQUEST = 4001; public const int OPUS_SET_BITRATE_REQUEST = 4002; public const int OPUS_GET_BITRATE_REQUEST = 4003; public const int OPUS_SET_MAX_BANDWIDTH_REQUEST = 4004; public const int OPUS_GET_MAX_BANDWIDTH_REQUEST = 4005; public const int OPUS_SET_VBR_REQUEST = 4006; public const int OPUS_GET_VBR_REQUEST = 4007; public const int OPUS_SET_BANDWIDTH_REQUEST = 4008; public const int OPUS_GET_BANDWIDTH_REQUEST = 4009; public const int OPUS_SET_COMPLEXITY_REQUEST = 4010; public const int OPUS_GET_COMPLEXITY_REQUEST = 4011; public const int OPUS_SET_INBAND_FEC_REQUEST = 4012; public const int OPUS_GET_INBAND_FEC_REQUEST = 4013; public const int OPUS_SET_PACKET_LOSS_PERC_REQUEST = 4014; public const int OPUS_GET_PACKET_LOSS_PERC_REQUEST = 4015; public const int OPUS_SET_DTX_REQUEST = 4016; public const int OPUS_GET_DTX_REQUEST = 4017; public const int OPUS_SET_VBR_CONSTRAINT_REQUEST = 4020; public const int OPUS_GET_VBR_CONSTRAINT_REQUEST = 4021; public const int OPUS_SET_FORCE_CHANNELS_REQUEST = 4022; public const int OPUS_GET_FORCE_CHANNELS_REQUEST = 4023; public const int OPUS_SET_SIGNAL_REQUEST = 4024; public const int OPUS_GET_SIGNAL_REQUEST = 4025; public const int OPUS_GET_LOOKAHEAD_REQUEST = 4027; public const int OPUS_GET_SAMPLE_RATE_REQUEST = 4029; public const int OPUS_GET_FINAL_RANGE_REQUEST = 4031; public const int OPUS_GET_PITCH_REQUEST = 4033; public const int OPUS_SET_GAIN_REQUEST = 4034; public const int OPUS_GET_GAIN_REQUEST = 4045; public const int OPUS_SET_LSB_DEPTH_REQUEST = 4036; public const int OPUS_GET_LSB_DEPTH_REQUEST = 4037; public const int OPUS_GET_LAST_PACKET_DURATION_REQUEST = 4039; public const int OPUS_SET_EXPERT_FRAME_DURATION_REQUEST = 4040; public const int OPUS_GET_EXPERT_FRAME_DURATION_REQUEST = 4041; public const int OPUS_SET_PREDICTION_DISABLED_REQUEST = 4042; public const int OPUS_GET_PREDICTION_DISABLED_REQUEST = 4043; public const int OPUS_RESET_STATE = 4028; public const int OPUS_SET_VOICE_RATIO_REQUEST = 11018; public const int OPUS_GET_VOICE_RATIO_REQUEST = 11019; public const int OPUS_SET_FORCE_MODE_REQUEST = 11002; } public static class OpusError { public const int OPUS_OK = 0; public const int OPUS_BAD_ARG = -1; public const int OPUS_BUFFER_TOO_SMALL = -2; public const int OPUS_INTERNAL_ERROR = -3; public const int OPUS_INVALID_PACKET = -4; public const int OPUS_UNIMPLEMENTED = -5; public const int OPUS_INVALID_STATE = -6; public const int OPUS_ALLOC_FAIL = -7; } public enum OpusFramesize { OPUS_FRAMESIZE_ARG = 5000, OPUS_FRAMESIZE_2_5_MS = 5001, OPUS_FRAMESIZE_5_MS = 5002, OPUS_FRAMESIZE_10_MS = 5003, OPUS_FRAMESIZE_20_MS = 5004, OPUS_FRAMESIZE_40_MS = 5005, OPUS_FRAMESIZE_60_MS = 5006, OPUS_FRAMESIZE_VARIABLE = 5010 } public enum OpusMode { MODE_AUTO = -1000, MODE_SILK_ONLY = 1000, MODE_HYBRID = 1001, MODE_CELT_ONLY = 1002 } public enum OpusSignal { OPUS_SIGNAL_AUTO = -1000, OPUS_SIGNAL_VOICE = 3001, OPUS_SIGNAL_MUSIC = 3002 } } namespace Concentus.Structs { internal class ChannelLayout { internal int nb_channels; internal int nb_streams; internal int nb_coupled_streams; internal readonly byte[] mapping = new byte[256]; internal void Reset() { nb_channels = 0; nb_streams = 0; nb_coupled_streams = 0; Arrays.MemSet(mapping, (byte)0); } } internal class MLP { internal int layers; internal int[] topo; internal float[] weights; } public class OpusDecoder { internal int channels; internal int Fs; internal readonly DecControlState DecControl = new DecControlState(); internal int decode_gain; internal int stream_channels; internal OpusBandwidth bandwidth; internal OpusMode mode; internal OpusMode prev_mode; internal int frame_size; internal int prev_redundancy; internal int last_packet_duration; internal uint rangeFinal; internal SilkDecoder SilkDecoder = new SilkDecoder(); internal CeltDecoder Celt_Decoder = new CeltDecoder(); private static readonly byte[] SILENCE = new byte[2] { 255, 255 }; public OpusBandwidth Bandwidth => bandwidth; public uint FinalRange => rangeFinal; public int SampleRate => Fs; public int NumChannels => channels; public int Pitch { get { if (prev_mode == OpusMode.MODE_CELT_ONLY) { return Celt_Decoder.GetPitch(); } return DecControl.prevPitchLag; } } public int Gain { get { return decode_gain; } set { if (value < -32768 || value > 32767) { throw new ArgumentException("Gain must be within the range of a signed int16"); } decode_gain = value; } } public int LastPacketDuration => last_packet_duration; internal OpusDecoder() { } internal void Reset() { channels = 0; Fs = 0; DecControl.Reset(); decode_gain = 0; PartialReset(); } internal void PartialReset() { stream_channels = 0; bandwidth = (OpusBandwidth)0; mode = (OpusMode)0; prev_mode = (OpusMode)0; frame_size = 0; prev_redundancy = 0; last_packet_duration = 0; rangeFinal = 0u; } public static OpusDecoder Create(int Fs, int channels) { return new OpusDecoder(Fs, channels); } public OpusDecoder(int Fs, int channels) { if (Fs != 48000 && Fs != 24000 && Fs != 16000 && Fs != 12000 && Fs != 8000) { throw new ArgumentException("Sample rate is invalid (must be 8/12/16/24/48 Khz)"); } if (channels != 1 && channels != 2) { throw new ArgumentException("Number of channels must be 1 or 2"); } int num = opus_decoder_init(Fs, channels); switch (num) { case -1: throw new ArgumentException("OPUS_BAD_ARG when creating decoder"); default: throw new OpusException("Error while initializing decoder", num); case 0: break; } } internal int opus_decoder_init(int Fs, int channels) { if ((Fs != 48000 && Fs != 24000 && Fs != 16000 && Fs != 12000 && Fs != 8000) || (channels != 1 && channels != 2)) { return -1; } Reset(); SilkDecoder silkDecoder = SilkDecoder; CeltDecoder celt_Decoder = Celt_Decoder; stream_channels = (this.channels = channels); this.Fs = Fs; DecControl.API_sampleRate = this.Fs; DecControl.nChannelsAPI = this.channels; if (DecodeAPI.silk_InitDecoder(silkDecoder) != 0) { return -3; } if (celt_Decoder.celt_decoder_init(Fs, channels) != 0) { return -3; } celt_Decoder.SetSignalling(0); prev_mode = (OpusMode)0; frame_size = Fs / 400; return 0; } internal int opus_decode_frame(byte[] data, int data_ptr, int len, short[] pcm, int pcm_ptr, int frame_size, int decode_fec) { int num = 0; int num2 = 0; EntropyCoder entropyCoder = new EntropyCoder(); short[] array = null; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; uint num7 = 0u; SilkDecoder silkDecoder = SilkDecoder; CeltDecoder celt_Decoder = Celt_Decoder; int num8 = Fs / 50; int num9 = num8 >> 1; int num10 = num9 >> 1; int num11 = num10 >> 1; if (frame_size < num11) { return -2; } frame_size = Inlines.IMIN(frame_size, Fs / 25 * 3); if (len <= 1) { data = null; frame_size = Inlines.IMIN(frame_size, this.frame_size); } int num12; OpusMode opusMode; if (data != null) { num12 = this.frame_size; opusMode = mode; entropyCoder.dec_init(data, data_ptr, (uint)len); } else { num12 = frame_size; opusMode = prev_mode; if (opusMode == (OpusMode)0) { for (int i = pcm_ptr; i < pcm_ptr + num12 * channels; i++) { pcm[i] = 0; } return num12; } if (num12 > num8) { do { int num13 = opus_decode_frame(null, 0, 0, pcm, pcm_ptr, Inlines.IMIN(num12, num8), 0); if (num13 < 0) { return num13; } pcm_ptr += num13 * channels; num12 -= num13; } while (num12 > 0); return frame_size; } if (num12 < num8) { if (num12 > num9) { num12 = num9; } else if (opusMode != OpusMode.MODE_SILK_ONLY && num12 > num10 && num12 < num9) { num12 = num10; } } } int num14 = ((opusMode != OpusMode.MODE_CELT_ONLY && frame_size >= num9) ? 1 : 0); int num15 = 0; int num16 = 0; if (data != null && prev_mode > (OpusMode)0 && ((opusMode == OpusMode.MODE_CELT_ONLY && prev_mode != OpusMode.MODE_CELT_ONLY && prev_redundancy == 0) || (opusMode != OpusMode.MODE_CELT_ONLY && prev_mode == OpusMode.MODE_CELT_ONLY))) { num3 = 1; if (opusMode == OpusMode.MODE_CELT_ONLY) { num16 = num10 * channels; } else { num15 = num10 * channels; } } short[] array2 = new short[num16]; if (num3 != 0 && opusMode == OpusMode.MODE_CELT_ONLY) { array = array2; opus_decode_frame(null, 0, 0, array, 0, Inlines.IMIN(num10, num12), 0); } if (num12 > frame_size) { return -1; } frame_size = num12; int num17 = ((opusMode != OpusMode.MODE_CELT_ONLY && num14 == 0) ? (Inlines.IMAX(num9, frame_size) * channels) : 0); short[] array3 = new short[num17]; if (opusMode != OpusMode.MODE_CELT_ONLY) { int num18 = 0; short[] array4; if (num14 != 0) { array4 = pcm; num18 = pcm_ptr; } else { array4 = array3; num18 = 0; } if (prev_mode == OpusMode.MODE_CELT_ONLY) { DecodeAPI.silk_InitDecoder(silkDecoder); } DecControl.payloadSize_ms = Inlines.IMAX(10, 1000 * num12 / Fs); if (data != null) { DecControl.nChannelsInternal = stream_channels; if (opusMode == OpusMode.MODE_SILK_ONLY) { if (bandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) { DecControl.internalSampleRate = 8000; } else if (bandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { DecControl.internalSampleRate = 12000; } else if (bandwidth == OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { DecControl.internalSampleRate = 16000; } else { DecControl.internalSampleRate = 16000; } } else { DecControl.internalSampleRate = 16000; } } int num19 = ((data == null) ? 1 : (2 * decode_fec)); int num20 = 0; do { int newPacketFlag = ((num20 == 0) ? 1 : 0); if (DecodeAPI.silk_Decode(silkDecoder, DecControl, num19, newPacketFlag, entropyCoder, array4, num18, out var nSamplesOut) != 0) { if (num19 == 0) { return -3; } nSamplesOut = frame_size; Arrays.MemSetWithOffset(array4, (short)0, num18, frame_size * channels); } num18 += nSamplesOut * channels; num20 += nSamplesOut; } while (num20 < frame_size); } int startBand = 0; if (decode_fec == 0 && opusMode != OpusMode.MODE_CELT_ONLY && data != null && entropyCoder.tell() + 17 + 20 * ((mode == OpusMode.MODE_HYBRID) ? 1 : 0) <= 8 * len) { num4 = ((opusMode != OpusMode.MODE_HYBRID) ? 1 : entropyCoder.dec_bit_logp(12u)); if (num4 != 0) { num6 = entropyCoder.dec_bit_logp(1u); num5 = ((opusMode == OpusMode.MODE_HYBRID) ? ((int)(entropyCoder.dec_uint(256u) + 2)) : (len - (entropyCoder.tell() + 7 >> 3))); len -= num5; if (len * 8 < entropyCoder.tell()) { len = 0; num5 = 0; num4 = 0; } entropyCoder.storage = (uint)(entropyCoder.storage - num5); } } if (opusMode != OpusMode.MODE_CELT_ONLY) { startBand = 17; } int endBand = 21; switch (bandwidth) { case OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND: endBand = 13; break; case OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND: case OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND: endBand = 17; break; case OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND: endBand = 19; break; case OpusBandwidth.OPUS_BANDWIDTH_FULLBAND: endBand = 21; break; } celt_Decoder.SetEndBand(endBand); celt_Decoder.SetChannels(stream_channels); if (num4 != 0) { num3 = 0; num15 = 0; } short[] array5 = new short[num15]; if (num3 != 0 && opusMode != OpusMode.MODE_CELT_ONLY) { array = array5; opus_decode_frame(null, 0, 0, array, 0, Inlines.IMIN(num10, num12), 0); } int num21 = ((num4 != 0) ? (num10 * channels) : 0); short[] array6 = new short[num21]; if (num4 != 0 && num6 != 0) { celt_Decoder.SetStartBand(0); celt_Decoder.celt_decode_with_ec(data, data_ptr + len, num5, array6, 0, num10, null, 0); num7 = celt_Decoder.GetFinalRange(); } celt_Decoder.SetStartBand(startBand); if (opusMode != OpusMode.MODE_SILK_ONLY) { int num22 = Inlines.IMIN(num8, frame_size); if (opusMode != prev_mode && prev_mode > (OpusMode)0 && prev_redundancy == 0) { celt_Decoder.ResetState(); } num2 = celt_Decoder.celt_decode_with_ec((decode_fec != 0) ? null : data, data_ptr, len, pcm, pcm_ptr, num22, entropyCoder, num14); } else { if (num14 == 0) { for (int i = pcm_ptr; i < frame_size * channels + pcm_ptr; i++) { pcm[i] = 0; } } if (prev_mode == OpusMode.MODE_HYBRID && (num4 == 0 || num6 == 0 || prev_redundancy == 0)) { celt_Decoder.SetStartBand(0); celt_Decoder.celt_decode_with_ec(SILENCE, 0, 2, pcm, pcm_ptr, num11, null, num14); } } if (opusMode != OpusMode.MODE_CELT_ONLY && num14 == 0) { for (int i = 0; i < frame_size * channels; i++) { pcm[pcm_ptr + i] = Inlines.SAT16(Inlines.ADD32(pcm[pcm_ptr + i], array3[i])); } } int[] window = celt_Decoder.GetMode().window; if (num4 != 0 && num6 == 0) { celt_Decoder.ResetState(); celt_Decoder.SetStartBand(0); celt_Decoder.celt_decode_with_ec(data, data_ptr + len, num5, array6, 0, num10, null, 0); num7 = celt_Decoder.GetFinalRange(); CodecHelpers.smooth_fade(pcm, pcm_ptr + channels * (frame_size - num11), array6, channels * num11, pcm, pcm_ptr + channels * (frame_size - num11), num11, channels, window, Fs); } if (num4 != 0 && num6 != 0) { for (int j = 0; j < channels; j++) { for (int i = 0; i < num11; i++) { pcm[channels * i + j + pcm_ptr] = array6[channels * i + j]; } } CodecHelpers.smooth_fade(array6, channels * num11, pcm, pcm_ptr + channels * num11, pcm, pcm_ptr + channels * num11, num11, channels, window, Fs); } if (num3 != 0) { if (num12 >= num10) { for (int i = 0; i < channels * num11; i++) { pcm[i] = array[i]; } CodecHelpers.smooth_fade(array, channels * num11, pcm, pcm_ptr + channels * num11, pcm, pcm_ptr + channels * num11, num11, channels, window, Fs); } else { CodecHelpers.smooth_fade(array, 0, pcm, pcm_ptr, pcm, pcm_ptr, num11, channels, window, Fs); } } if (decode_gain != 0) { int b = Inlines.celt_exp2(Inlines.MULT16_16_P15(21771, decode_gain)); for (int i = pcm_ptr; i < pcm_ptr + frame_size * channels; i++) { int x = Inlines.MULT16_32_P16(pcm[i], b); pcm[i] = (short)Inlines.SATURATE(x, 32767); } } if (len <= 1) { rangeFinal = 0u; } else { rangeFinal = entropyCoder.rng ^ num7; } prev_mode = opusMode; prev_redundancy = ((num4 != 0 && num6 == 0) ? 1 : 0); return (num2 < 0) ? num2 : num12; } internal int opus_decode_native(byte[] data, int data_ptr, int len, short[] pcm_out, int pcm_out_ptr, int frame_size, int decode_fec, int self_delimited, out int packet_offset, int soft_clip) { packet_offset = 0; short[] array = new short[48]; if (decode_fec < 0 || decode_fec > 1) { return -1; } if ((decode_fec != 0 || len == 0 || data == null) && frame_size % (Fs / 400) != 0) { return -1; } if (len == 0 || data == null) { int num = 0; do { int num2 = opus_decode_frame(null, 0, 0, pcm_out, pcm_out_ptr + num * channels, frame_size - num, 0); if (num2 < 0) { return num2; } num += num2; } while (num < frame_size); last_packet_duration = num; return num; } if (len < 0) { return -1; } OpusMode encoderMode = OpusPacketInfo.GetEncoderMode(data, data_ptr); OpusBandwidth opusBandwidth = OpusPacketInfo.GetBandwidth(data, data_ptr); int numSamplesPerFrame = OpusPacketInfo.GetNumSamplesPerFrame(data, data_ptr, Fs); int numEncodedChannels = OpusPacketInfo.GetNumEncodedChannels(data, data_ptr); byte out_toc; int payload_offset; int num3 = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, self_delimited, out out_toc, null, null, 0, array, 0, out payload_offset, out packet_offset); if (num3 < 0) { return num3; } data_ptr += payload_offset; if (decode_fec != 0) { int packet_offset2; if (frame_size < numSamplesPerFrame || encoderMode == OpusMode.MODE_CELT_ONLY || mode == OpusMode.MODE_CELT_ONLY) { return opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size, 0, 0, out packet_offset2, soft_clip); } int num4 = last_packet_duration; int num2; if (frame_size - numSamplesPerFrame != 0) { num2 = opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size - numSamplesPerFrame, 0, 0, out packet_offset2, soft_clip); if (num2 < 0) { last_packet_duration = num4; return num2; } } mode = encoderMode; bandwidth = opusBandwidth; this.frame_size = numSamplesPerFrame; stream_channels = numEncodedChannels; num2 = opus_decode_frame(data, data_ptr, array[0], pcm_out, pcm_out_ptr + channels * (frame_size - numSamplesPerFrame), numSamplesPerFrame, 1); if (num2 < 0) { return num2; } last_packet_duration = frame_size; return frame_size; } if (num3 * numSamplesPerFrame > frame_size) { return -2; } mode = encoderMode; bandwidth = opusBandwidth; this.frame_size = numSamplesPerFrame; stream_channels = numEncodedChannels; int num5 = 0; for (int i = 0; i < num3; i++) { int num2 = opus_decode_frame(data, data_ptr, array[i], pcm_out, pcm_out_ptr + num5 * channels, frame_size - num5, 0); if (num2 < 0) { return num2; } data_ptr += array[i]; num5 += num2; } last_packet_duration = num5; return num5; } public int Decode(byte[] in_data, int in_data_offset, int len, short[] out_pcm, int out_pcm_offset, int frame_size, bool decode_fec = false) { if (frame_size <= 0) { throw new ArgumentException("Frame size must be > 0"); } try { int packet_offset; int num = opus_decode_native(in_data, in_data_offset, len, out_pcm, out_pcm_offset, frame_size, decode_fec ? 1 : 0, 0, out packet_offset, 0); if (num < 0) { if (num == -1) { throw new ArgumentException("OPUS_BAD_ARG while decoding"); } throw new OpusException("An error occurred during decoding", num); } return num; } catch (ArgumentException ex) { throw new OpusException("Internal error during decoding: " + ex.Message); } } public int Decode(byte[] in_data, int in_data_offset, int len, float[] out_pcm, int out_pcm_offset, int frame_size, bool decode_fec = false) { if (frame_size <= 0) { throw new ArgumentException("Frame size must be > 0"); } if (in_data != null && len > 0 && !decode_fec) { int numSamples = OpusPacketInfo.GetNumSamples(this, in_data, in_data_offset, len); if (numSamples <= 0) { throw new OpusException("An invalid packet was provided (unable to parse # of samples)"); } frame_size = Inlines.IMIN(frame_size, numSamples); } short[] array = new short[frame_size * channels]; try { int packet_offset; int num = opus_decode_native(in_data, in_data_offset, len, array, 0, frame_size, decode_fec ? 1 : 0, 0, out packet_offset, 0); if (num < 0) { if (num == -1) { throw new ArgumentException("OPUS_BAD_ARG when decoding"); } throw new OpusException("An error occurred during decoding", num); } if (num > 0) { for (int i = 0; i < num * channels; i++) { out_pcm[out_pcm_offset + i] = 3.0517578E-05f * (float)array[i]; } } return num; } catch (ArgumentException ex) { throw new OpusException("Internal error during decoding: " + ex.Message); } } public void ResetState() { PartialReset(); Celt_Decoder.ResetState(); DecodeAPI.silk_InitDecoder(SilkDecoder); stream_channels = channels; frame_size = Fs / 400; } } public class OpusEncoder { internal readonly EncControlState silk_mode = new EncControlState(); internal OpusApplication application; internal int channels; internal int delay_compensation; internal int force_channels; internal OpusSignal signal_type; internal OpusBandwidth user_bandwidth; internal OpusBandwidth max_bandwidth; internal OpusMode user_forced_mode; internal int voice_ratio; internal int Fs; internal int use_vbr; internal int vbr_constraint; internal OpusFramesize variable_duration; internal int bitrate_bps; internal int user_bitrate_bps; internal int lsb_depth; internal int encoder_buffer; internal int lfe; internal readonly TonalityAnalysisState analysis = new TonalityAnalysisState(); internal int stream_channels; internal short hybrid_stereo_width_Q14; internal int variable_HP_smth2_Q15; internal int prev_HB_gain; internal readonly int[] hp_mem = new int[4]; internal OpusMode mode; internal OpusMode prev_mode; internal int prev_channels; internal int prev_framesize; internal OpusBandwidth bandwidth; internal int silk_bw_switch; internal int first; internal int[] energy_masking; internal readonly StereoWidthState width_mem = new StereoWidthState(); internal readonly short[] delay_buffer = new short[960]; internal OpusBandwidth detected_bandwidth; internal uint rangeFinal; internal readonly SilkEncoder SilkEncoder = new SilkEncoder(); internal readonly CeltEncoder Celt_Encoder = new CeltEncoder(); public OpusApplication Application { get { return application; } set { if (first == 0 && application != value) { throw new ArgumentException("Application cannot be changed after encoding has started"); } application = value; } } public int Bitrate { get { return user_bitrate_to_bitrate(prev_framesize, 1276); } set { if (value != -1000 && value != -1) { if (value <= 0) { throw new ArgumentException("Bitrate must be positive"); } if (value <= 500) { value = 500; } else if (value > 300000 * channels) { value = 300000 * channels; } } user_bitrate_bps = value; } } public int ForceChannels { get { return force_channels; } set { if ((value < 1 || value > channels) && value != -1000) { throw new ArgumentException("Force channels must be <= num. of channels"); } force_channels = value; } } public OpusBandwidth MaxBandwidth { get { return max_bandwidth; } set { max_bandwidth = value; if (max_bandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) { silk_mode.maxInternalSampleRate = 8000; } else if (max_bandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { silk_mode.maxInternalSampleRate = 12000; } else { silk_mode.maxInternalSampleRate = 16000; } } } public OpusBandwidth Bandwidth { get { return bandwidth; } set { user_bandwidth = value; if (user_bandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) { silk_mode.maxInternalSampleRate = 8000; } else if (user_bandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { silk_mode.maxInternalSampleRate = 12000; } else { silk_mode.maxInternalSampleRate = 16000; } } } public bool UseDTX { get { return silk_mode.useDTX != 0; } set { silk_mode.useDTX = (value ? 1 : 0); } } public int Complexity { get { return silk_mode.complexity; } set { if (value < 0 || value > 10) { throw new ArgumentException("Complexity must be between 0 and 10"); } silk_mode.complexity = value; Celt_Encoder.SetComplexity(value); } } public bool UseInbandFEC { get { return silk_mode.useInBandFEC != 0; } set { silk_mode.useInBandFEC = (value ? 1 : 0); } } public int PacketLossPercent { get { return silk_mode.packetLossPercentage; } set { if (value < 0 || value > 100) { throw new ArgumentException("Packet loss must be between 0 and 100"); } silk_mode.packetLossPercentage = value; Celt_Encoder.SetPacketLossPercent(value); } } public bool UseVBR { get { return use_vbr != 0; } set { use_vbr = (value ? 1 : 0); silk_mode.useCBR = ((!value) ? 1 : 0); } } public bool UseConstrainedVBR { get { return vbr_constraint != 0; } set { vbr_constraint = (value ? 1 : 0); } } public OpusSignal SignalType { get { return signal_type; } set { signal_type = value; } } public int Lookahead { get { int num = Fs / 400; if (application != OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY) { num += delay_compensation; } return num; } } public int SampleRate => Fs; public int NumChannels => channels; public uint FinalRange => rangeFinal; public int LSBDepth { get { return lsb_depth; } set { if (value < 8 || value > 24) { throw new ArgumentException("LSB depth must be between 8 and 24"); } lsb_depth = value; } } public OpusFramesize ExpertFrameDuration { get { return variable_duration; } set { variable_duration = value; Celt_Encoder.SetExpertFrameDuration(value); } } public OpusMode ForceMode { get { return user_forced_mode; } set { user_forced_mode = value; } } public bool IsLFE { get { return lfe != 0; } set { lfe = (value ? 1 : 0); Celt_Encoder.SetLFE(value ? 1 : 0); } } public bool PredictionDisabled { get { return silk_mode.reducedDependency != 0; } set { silk_mode.reducedDependency = (value ? 1 : 0); } } public bool EnableAnalysis { get { return analysis.enabled; } set { analysis.enabled = value; } } internal OpusEncoder() { } internal void Reset() { silk_mode.Reset(); application = OpusApplication.OPUS_APPLICATION_UNIMPLEMENTED; channels = 0; delay_compensation = 0; force_channels = 0; signal_type = (OpusSignal)0; user_bandwidth = (OpusBandwidth)0; max_bandwidth = (OpusBandwidth)0; user_forced_mode = (OpusMode)0; voice_ratio = 0; Fs = 0; use_vbr = 0; vbr_constraint = 0; variable_duration = (OpusFramesize)0; bitrate_bps = 0; user_bitrate_bps = 0; lsb_depth = 0; encoder_buffer = 0; lfe = 0; analysis.Reset(); PartialReset(); } internal void PartialReset() { stream_channels = 0; hybrid_stereo_width_Q14 = 0; variable_HP_smth2_Q15 = 0; prev_HB_gain = 0; Arrays.MemSet(hp_mem, 0, 4); mode = (OpusMode)0; prev_mode = (OpusMode)0; prev_channels = 0; prev_framesize = 0; bandwidth = (OpusBandwidth)0; silk_bw_switch = 0; first = 0; energy_masking = null; width_mem.Reset(); Arrays.MemSet(delay_buffer, (short)0, 960); detected_bandwidth = (OpusBandwidth)0; rangeFinal = 0u; } public void ResetState() { EncControlState encStatus = new EncControlState(); analysis.Reset(); PartialReset(); Celt_Encoder.ResetState(); EncodeAPI.silk_InitEncoder(SilkEncoder, encStatus); stream_channels = channels; hybrid_stereo_width_Q14 = 16384; prev_HB_gain = 32767; first = 1; mode = OpusMode.MODE_HYBRID; bandwidth = OpusBandwidth.OPUS_BANDWIDTH_FULLBAND; variable_HP_smth2_Q15 = Inlines.silk_LSHIFT(Inlines.silk_lin2log(60), 8); } public static OpusEncoder Create(int Fs, int channels, OpusApplication application) { return new OpusEncoder(Fs, channels, application); } public OpusEncoder(int Fs, int channels, OpusApplication application) { if (Fs != 48000 && Fs != 24000 && Fs != 16000 && Fs != 12000 && Fs != 8000) { throw new ArgumentException("Sample rate is invalid (must be 8/12/16/24/48 Khz)"); } if (channels != 1 && channels != 2) { throw new ArgumentException("Number of channels must be 1 or 2"); } int num = opus_init_encoder(Fs, channels, application); switch (num) { case -1: throw new ArgumentException("OPUS_BAD_ARG when creating encoder"); default: throw new OpusException("Error while initializing encoder", num); case 0: break; } } internal int opus_init_encoder(int Fs, int channels, OpusApplication application) { if ((Fs != 48000 && Fs != 24000 && Fs != 16000 && Fs != 12000 && Fs != 8000) || (channels != 1 && channels != 2) || application == OpusApplication.OPUS_APPLICATION_UNIMPLEMENTED) { return -1; } Reset(); SilkEncoder silkEncoder = SilkEncoder; CeltEncoder celt_Encoder = Celt_Encoder; stream_channels = (this.channels = channels); this.Fs = Fs; if (EncodeAPI.silk_InitEncoder(silkEncoder, silk_mode) != 0) { return -3; } silk_mode.nChannelsAPI = channels; silk_mode.nChannelsInternal = channels; silk_mode.API_sampleRate = this.Fs; silk_mode.maxInternalSampleRate = 16000; silk_mode.minInternalSampleRate = 8000; silk_mode.desiredInternalSampleRate = 16000; silk_mode.payloadSize_ms = 20; silk_mode.bitRate = 25000; silk_mode.packetLossPercentage = 0; silk_mode.complexity = 9; silk_mode.useInBandFEC = 0; silk_mode.useDTX = 0; silk_mode.useCBR = 0; silk_mode.reducedDependency = 0; if (celt_Encoder.celt_encoder_init(Fs, channels) != 0) { return -3; } celt_Encoder.SetSignalling(0); celt_Encoder.SetComplexity(silk_mode.complexity); use_vbr = 1; vbr_constraint = 1; user_bitrate_bps = -1000; bitrate_bps = 3000 + Fs * channels; this.application = application; signal_type = OpusSignal.OPUS_SIGNAL_AUTO; user_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_AUTO; max_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_FULLBAND; force_channels = -1000; user_forced_mode = OpusMode.MODE_AUTO; voice_ratio = -1; encoder_buffer = this.Fs / 100; lsb_depth = 24; variable_duration = OpusFramesize.OPUS_FRAMESIZE_ARG; delay_compensation = this.Fs / 250; hybrid_stereo_width_Q14 = 16384; prev_HB_gain = 32767; variable_HP_smth2_Q15 = Inlines.silk_LSHIFT(Inlines.silk_lin2log(60), 8); first = 1; mode = OpusMode.MODE_HYBRID; bandwidth = OpusBandwidth.OPUS_BANDWIDTH_FULLBAND; Analysis.tonality_analysis_init(analysis); return 0; } internal int user_bitrate_to_bitrate(int frame_size, int max_data_bytes) { if (frame_size == 0) { frame_size = Fs / 400; } if (user_bitrate_bps == -1000) { return 60 * Fs / frame_size + Fs * channels; } if (user_bitrate_bps == -1) { return max_data_bytes * 8 * Fs / frame_size; } return user_bitrate_bps; } internal int opus_encode_native(short[] pcm, int pcm_ptr, int frame_size, byte[] data, int data_ptr, int out_data_bytes, int lsb_depth, T[] analysis_pcm, int analysis_pcm_ptr, int analysis_size, int c1, int c2, int analysis_channels, Downmix.downmix_func downmix, int float_api) { int num = 0; EntropyCoder entropyCoder = new EntropyCoder(); int num2 = 0; int startBand = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; uint num7 = 0u; AnalysisInfo analysisInfo = new AnalysisInfo(); int num8 = -1; int read_subframe = -1; int num9 = Inlines.IMIN(1276, out_data_bytes); rangeFinal = 0u; if ((variable_duration == (OpusFramesize)0 && 400 * frame_size != Fs && 200 * frame_size != Fs && 100 * frame_size != Fs && 50 * frame_size != Fs && 25 * frame_size != Fs && 50 * frame_size != 3 * Fs) || 400 * frame_size < Fs || num9 <= 0) { return -1; } SilkEncoder silkEncoder = SilkEncoder; CeltEncoder celt_Encoder = Celt_Encoder; int num10 = ((application != OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY) ? delay_compensation : 0); lsb_depth = Inlines.IMIN(lsb_depth, this.lsb_depth); CeltMode celtMode = celt_Encoder.GetMode(); voice_ratio = -1; if (analysis.enabled) { analysisInfo.valid = 0; if (silk_mode.complexity >= 7 && Fs == 48000) { num8 = analysis.read_pos; read_subframe = analysis.read_subframe; Analysis.run_analysis(analysis, celtMode, (analysis_pcm != null) ? analysis_pcm : null, analysis_pcm_ptr, analysis_size, frame_size, c1, c2, analysis_channels, Fs, lsb_depth, downmix, analysisInfo); } detected_bandwidth = (OpusBandwidth)0; if (analysisInfo.valid != 0) { if (signal_type == OpusSignal.OPUS_SIGNAL_AUTO) { voice_ratio = (int)Math.Floor(0.5f + 100f * (1f - analysisInfo.music_prob)); } int num11 = analysisInfo.bandwidth; if (num11 <= 12) { detected_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } else if (num11 <= 14) { detected_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND; } else if (num11 <= 16) { detected_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } else if (num11 <= 18) { detected_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND; } else { detected_bandwidth = OpusBandwidth.OPUS_BANDWIDTH_FULLBAND; } } } int num12 = ((channels == 2 && force_channels != 1) ? CodecHelpers.compute_stereo_width(pcm, pcm_ptr, frame_size, Fs, width_mem) : 0); int num13 = num10; bitrate_bps = user_bitrate_to_bitrate(frame_size, num9); int num14 = Fs / frame_size; if (use_vbr == 0) { int num15 = 3 * Fs / frame_size; int num16 = Inlines.IMIN((3 * bitrate_bps / 8 + num15 / 2) / num15, num9); bitrate_bps = num16 * num15 * 8 / 3; num9 = num16; } if (num9 < 3 || bitrate_bps < 3 * num14 * 8 || (num14 < 50 && (num9 * num14 < 300 || bitrate_bps < 2400))) { OpusMode opusMode = mode; OpusBandwidth opusBandwidth = ((bandwidth == (OpusBandwidth)0) ? OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND : bandwidth); if (opusMode == (OpusMode)0) { opusMode = OpusMode.MODE_SILK_ONLY; } if (num14 > 100) { opusMode = OpusMode.MODE_CELT_ONLY; } if (num14 < 50) { opusMode = OpusMode.MODE_SILK_ONLY; } if (opusMode == OpusMode.MODE_SILK_ONLY && opusBandwidth > OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { opusBandwidth = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } else if (opusMode == OpusMode.MODE_CELT_ONLY && opusBandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { opusBandwidth = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } else if (opusMode == OpusMode.MODE_HYBRID && opusBandwidth <= OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) { opusBandwidth = OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND; } data[data_ptr] = CodecHelpers.gen_toc(opusMode, num14, opusBandwidth, stream_channels); num = 1; if (use_vbr == 0) { num = OpusRepacketizer.PadPacket(data, data_ptr, num, num9); if (num == 0) { num = num9; } } return num; } int num17 = num14 * num9 * 8; int num18 = bitrate_bps - (40 * channels + 20) * (Fs / frame_size - 50); int num19; if (signal_type == OpusSignal.OPUS_SIGNAL_VOICE) { num19 = 127; } else if (signal_type == OpusSignal.OPUS_SIGNAL_MUSIC) { num19 = 0; } else if (voice_ratio < 0) { num19 = ((application != OpusApplication.OPUS_APPLICATION_VOIP) ? 48 : 115); } else { num19 = voice_ratio * 327 >> 8; if (application == OpusApplication.OPUS_APPLICATION_AUDIO) { num19 = Inlines.IMIN(num19, 115); } } if (force_channels != -1000 && channels == 2) { stream_channels = force_channels; } else if (channels == 2) { int num20 = 30000 + (0 >> 14); num20 = ((stream_channels != 2) ? (num20 + 1000) : (num20 - 1000)); stream_channels = ((num18 <= num20) ? 1 : 2); } else { stream_channels = channels; } num18 = bitrate_bps - (40 * stream_channels + 20) * (Fs / frame_size - 50); if (application == OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY) { mode = OpusMode.MODE_CELT_ONLY; } else if (user_forced_mode == OpusMode.MODE_AUTO) { int num21 = Inlines.MULT16_32_Q15(32767 - num12, Tables.mode_thresholds[0][0]) + Inlines.MULT16_32_Q15(num12, Tables.mode_thresholds[1][0]); int num22 = Inlines.MULT16_32_Q15(32767 - num12, Tables.mode_thresholds[1][1]) + Inlines.MULT16_32_Q15(num12, Tables.mode_thresholds[1][1]); int num23 = num22 + (num19 * num19 * (num21 - num22) >> 14); if (application == OpusApplication.OPUS_APPLICATION_VOIP) { num23 += 8000; } if (prev_mode == OpusMode.MODE_CELT_ONLY) { num23 -= 4000; } else if (prev_mode > (OpusMode)0) { num23 += 4000; } mode = ((num18 >= num23) ? OpusMode.MODE_CELT_ONLY : OpusMode.MODE_SILK_ONLY); if (silk_mode.useInBandFEC != 0 && silk_mode.packetLossPercentage > 128 - num19 >> 4) { mode = OpusMode.MODE_SILK_ONLY; } if (silk_mode.useDTX != 0 && num19 > 100) { mode = OpusMode.MODE_SILK_ONLY; } } else { mode = user_forced_mode; } if (mode != OpusMode.MODE_CELT_ONLY && frame_size < Fs / 100) { mode = OpusMode.MODE_CELT_ONLY; } if (lfe != 0) { mode = OpusMode.MODE_CELT_ONLY; } if (num9 < ((num14 > 50) ? 12000 : 8000) * frame_size / (Fs * 8)) { mode = OpusMode.MODE_CELT_ONLY; } if (stream_channels == 1 && prev_channels == 2 && silk_mode.toMono == 0 && mode != OpusMode.MODE_CELT_ONLY && prev_mode != OpusMode.MODE_CELT_ONLY) { silk_mode.toMono = 1; stream_channels = 2; } else { silk_mode.toMono = 0; } if (prev_mode > (OpusMode)0 && ((mode != OpusMode.MODE_CELT_ONLY && prev_mode == OpusMode.MODE_CELT_ONLY) || (mode == OpusMode.MODE_CELT_ONLY && prev_mode != OpusMode.MODE_CELT_ONLY))) { num3 = 1; num5 = ((mode != OpusMode.MODE_CELT_ONLY) ? 1 : 0); if (num5 == 0) { if (frame_size >= Fs / 100) { mode = prev_mode; num6 = 1; } else { num3 = 0; } } } if (silk_bw_switch != 0) { num3 = 1; num5 = 1; silk_bw_switch = 0; num2 = 1; } if (num3 != 0) { num4 = Inlines.IMIN(257, num9 * (Fs / 200) / (frame_size + Fs / 200)); if (use_vbr != 0) { num4 = Inlines.IMIN(num4, bitrate_bps / 1600); } } if (mode != OpusMode.MODE_CELT_ONLY && prev_mode == OpusMode.MODE_CELT_ONLY) { EncControlState encStatus = new EncControlState(); EncodeAPI.silk_InitEncoder(silkEncoder, encStatus); num2 = 1; } if (mode == OpusMode.MODE_CELT_ONLY || first != 0 || silk_mode.allowBandwidthSwitch != 0) { int[] array = new int[8]; OpusBandwidth opusBandwidth2 = OpusBandwidth.OPUS_BANDWIDTH_FULLBAND; int num24 = num18; if (mode != OpusMode.MODE_CELT_ONLY) { num24 = num24 * (45 + silk_mode.complexity) / 50; if (use_vbr == 0) { num24 -= 1000; } } int[] array2; int[] array3; if (channels == 2 && force_channels != 1) { array2 = Tables.stereo_voice_bandwidth_thresholds; array3 = Tables.stereo_music_bandwidth_thresholds; } else { array2 = Tables.mono_voice_bandwidth_thresholds; array3 = Tables.mono_music_bandwidth_thresholds; } for (int i = 0; i < 8; i++) { array[i] = array3[i] + (num19 * num19 * (array2[i] - array3[i]) >> 14); } int num23; do { num23 = array[2 * (int)(opusBandwidth2 - 1102)]; int num25 = array[2 * (int)(opusBandwidth2 - 1102) + 1]; if (first == 0) { num23 = ((bandwidth < opusBandwidth2) ? (num23 + num25) : (num23 - num25)); } } while (num24 < num23 && --opusBandwidth2 > OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND); bandwidth = opusBandwidth2; if (first == 0 && mode != OpusMode.MODE_CELT_ONLY && silk_mode.inWBmodeWithoutVariableLP == 0 && bandwidth > OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } } if (bandwidth > max_bandwidth) { bandwidth = max_bandwidth; } if (user_bandwidth != OpusBandwidth.OPUS_BANDWIDTH_AUTO) { bandwidth = user_bandwidth; } if (mode != OpusMode.MODE_CELT_ONLY && num17 < 15000) { bandwidth = OpusBandwidthHelpers.MIN(bandwidth, OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND); } if (Fs <= 24000 && bandwidth > OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND; } if (Fs <= 16000 && bandwidth > OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } if (Fs <= 12000 && bandwidth > OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND; } if (Fs <= 8000 && bandwidth > OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } if (detected_bandwidth != 0 && user_bandwidth == OpusBandwidth.OPUS_BANDWIDTH_AUTO) { detected_bandwidth = OpusBandwidthHelpers.MAX(b: (num18 <= 18000 * stream_channels && mode == OpusMode.MODE_CELT_ONLY) ? OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND : ((num18 <= 24000 * stream_channels && mode == OpusMode.MODE_CELT_ONLY) ? OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND : ((num18 <= 30000 * stream_channels) ? OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND : ((num18 > 44000 * stream_channels) ? OpusBandwidth.OPUS_BANDWIDTH_FULLBAND : OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND))), a: detected_bandwidth); bandwidth = OpusBandwidthHelpers.MIN(bandwidth, detected_bandwidth); } celt_Encoder.SetLSBDepth(lsb_depth); if (mode == OpusMode.MODE_CELT_ONLY && bandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } if (lfe != 0) { bandwidth = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } if (frame_size > Fs / 50 && (mode == OpusMode.MODE_CELT_ONLY || bandwidth > OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND)) { if (analysis.enabled && num8 != -1) { analysis.read_pos = num8; analysis.read_subframe = read_subframe; } int num26 = ((frame_size > Fs / 25) ? 3 : 2); int num27 = Inlines.IMIN(1276, (out_data_bytes - 3) / num26); byte[] data2 = new byte[num26 * num27]; OpusRepacketizer opusRepacketizer = new OpusRepacketizer(); OpusMode opusMode2 = user_forced_mode; OpusBandwidth opusBandwidth3 = user_bandwidth; int num28 = force_channels; user_forced_mode = mode; user_bandwidth = bandwidth; force_channels = stream_channels; int toMono = silk_mode.toMono; if (toMono != 0) { force_channels = 1; } else { prev_channels = stream_channels; } for (int i = 0; i < num26; i++) { silk_mode.toMono = 0; if (num6 != 0 && i == num26 - 1) { user_forced_mode = OpusMode.MODE_CELT_ONLY; } int num29 = opus_encode_native(pcm, pcm_ptr + i * (channels * Fs / 50), Fs / 50, data2, i * num27, num27, lsb_depth, null, 0, 0, c1, c2, analysis_channels, downmix, float_api); if (num29 < 0) { return -3; } num = opusRepacketizer.AddPacket(data2, i * num27, num29); if (num < 0) { return -3; } } int maxlen = ((use_vbr == 0) ? Inlines.IMIN(3 * bitrate_bps / (1200 / num26), out_data_bytes) : out_data_bytes); num = opusRepacketizer.opus_repacketizer_out_range_impl(0, num26, data, data_ptr, maxlen, 0, (use_vbr == 0) ? 1 : 0); if (num < 0) { return -3; } user_forced_mode = opusMode2; user_bandwidth = opusBandwidth3; force_channels = num28; silk_mode.toMono = toMono; return num; } OpusBandwidth opusBandwidth4 = bandwidth; if (mode == OpusMode.MODE_SILK_ONLY && opusBandwidth4 > OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { mode = OpusMode.MODE_HYBRID; } if (mode == OpusMode.MODE_HYBRID && opusBandwidth4 <= OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { mode = OpusMode.MODE_SILK_ONLY; } int num30 = Inlines.IMIN(num9 - num4, bitrate_bps * frame_size / (Fs * 8)) - 1; data_ptr++; entropyCoder.enc_init(data, data_ptr, (uint)(num9 - 1)); short[] array4 = new short[(num13 + frame_size) * channels]; Array.Copy(delay_buffer, (encoder_buffer - num13) * channels, array4, 0, num13 * channels); variable_HP_smth2_Q15 = Inlines.silk_SMLAWB(b32: ((mode != OpusMode.MODE_CELT_ONLY) ? silkEncoder.state_Fxx[0].variable_HP_smth1_Q15 : Inlines.silk_LSHIFT(Inlines.silk_lin2log(60), 8)) - variable_HP_smth2_Q15, a32: variable_HP_smth2_Q15, c32: 983); int cutoff_Hz = Inlines.silk_log2lin(Inlines.silk_RSHIFT(variable_HP_smth2_Q15, 8)); if (application == OpusApplication.OPUS_APPLICATION_VOIP) { CodecHelpers.hp_cutoff(pcm, pcm_ptr, cutoff_Hz, array4, num13 * channels, hp_mem, frame_size, channels, Fs); } else { CodecHelpers.dc_reject(pcm, pcm_ptr, 3, array4, num13 * channels, hp_mem, frame_size, channels, Fs); } int num31 = 32767; if (mode != OpusMode.MODE_CELT_ONLY) { short[] array5 = new short[channels * frame_size]; int num32 = 8 * num30 * num14; if (mode == OpusMode.MODE_HYBRID) { silk_mode.bitRate = stream_channels * (5000 + ((Fs == 100 * frame_size) ? 1000 : 0)); if (opusBandwidth4 == OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) { silk_mode.bitRate += (num32 - silk_mode.bitRate) * 2 / 3; } else { silk_mode.bitRate += (num32 - silk_mode.bitRate) * 3 / 5; } if (silk_mode.bitRate > num32 * 4 / 5) { silk_mode.bitRate = num32 * 4 / 5; } if (energy_masking == null) { int num33 = num32 - silk_mode.bitRate; int num34 = ((opusBandwidth4 == OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600); num31 = Inlines.SHL32(num33, 9) / Inlines.SHR32(num33 + stream_channels * num34, 6); num31 = ((num31 < 28086) ? (num31 + 4681) : 32767); } } else { silk_mode.bitRate = num32; } if (energy_masking != null && use_vbr != 0 && lfe == 0) { int num35 = 0; int num36 = 17; short a = 16000; if (bandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) { num36 = 13; a = 8000; } else if (bandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { num36 = 15; a = 12000; } for (int j = 0; j < channels; j++) { for (int i = 0; i < num36; i++) { int num37 = Inlines.MAX16(Inlines.MIN16(energy_masking[21 * j + i], 512), -2048); if (num37 > 0) { num37 = Inlines.HALF16(num37); } num35 += num37; } } int num38 = num35 / num36 * channels; num38 += 205; int a2 = Inlines.PSHR32(Inlines.MULT16_16(a, num38), 10); a2 = Inlines.MAX32(a2, -2 * silk_mode.bitRate / 3); if (bandwidth == OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND || bandwidth == OpusBandwidth.OPUS_BANDWIDTH_FULLBAND) { silk_mode.bitRate += 3 * a2 / 5; } else { silk_mode.bitRate += a2; } num30 += a2 * frame_size / (8 * Fs); } silk_mode.payloadSize_ms = 1000 * frame_size / Fs; silk_mode.nChannelsAPI = channels; silk_mode.nChannelsInternal = stream_channels; switch (opusBandwidth4) { case OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND: silk_mode.desiredInternalSampleRate = 8000; break; case OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND: silk_mode.desiredInternalSampleRate = 12000; break; default: silk_mode.desiredInternalSampleRate = 16000; break; } if (mode == OpusMode.MODE_HYBRID) { silk_mode.minInternalSampleRate = 16000; } else { silk_mode.minInternalSampleRate = 8000; } if (mode == OpusMode.MODE_SILK_ONLY) { int num39 = num17; silk_mode.maxInternalSampleRate = 16000; if (num14 > 50) { num39 = num39 * 2 / 3; } if (num39 < 13000) { silk_mode.maxInternalSampleRate = 12000; silk_mode.desiredInternalSampleRate = Inlines.IMIN(12000, silk_mode.desiredInternalSampleRate); } if (num39 < 9600) { silk_mode.maxInternalSampleRate = 8000; silk_mode.desiredInternalSampleRate = Inlines.IMIN(8000, silk_mode.desiredInternalSampleRate); } } else { silk_mode.maxInternalSampleRate = 16000; } silk_mode.useCBR = ((use_vbr == 0) ? 1 : 0); int num40 = Inlines.IMIN(1275, num9 - 1 - num4); silk_mode.maxBits = num40 * 8; if (mode == OpusMode.MODE_HYBRID) { silk_mode.maxBits = silk_mode.maxBits * 9 / 10; } if (silk_mode.useCBR != 0) { silk_mode.maxBits = silk_mode.bitRate * frame_size / (Fs * 8) * 8; silk_mode.bitRate = Inlines.IMAX(1, silk_mode.bitRate - 2000); } if (num2 != 0) { BoxedValue nBytesOut = new BoxedValue(0); int num41 = channels * (encoder_buffer - delay_compensation - Fs / 400); CodecHelpers.gain_fade(delay_buffer, num41, 0, 32767, celtMode.overlap, Fs / 400, channels, celtMode.window, Fs); Arrays.MemSet(delay_buffer, (short)0, num41); Array.Copy(delay_buffer, 0, array5, 0, encoder_buffer * channels); EncodeAPI.silk_Encode(silkEncoder, silk_mode, array5, encoder_buffer, null, nBytesOut, 1); } Array.Copy(array4, num13 * channels, array5, 0, frame_size * channels); BoxedValue boxedValue = new BoxedValue(num40); num = EncodeAPI.silk_Encode(silkEncoder, silk_mode, array5, frame_size, entropyCoder, boxedValue, 0); num40 = boxedValue.Val; if (num != 0) { return -3; } if (num40 == 0) { rangeFinal = 0u; data[data_ptr - 1] = CodecHelpers.gen_toc(mode, Fs / frame_size, opusBandwidth4, stream_channels); return 1; } if (mode == OpusMode.MODE_SILK_ONLY) { if (silk_mode.internalSampleRate == 8000) { opusBandwidth4 = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } else if (silk_mode.internalSampleRate == 12000) { opusBandwidth4 = OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND; } else if (silk_mode.internalSampleRate == 16000) { opusBandwidth4 = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } } silk_mode.opusCanSwitch = silk_mode.switchReady; if (silk_mode.opusCanSwitch != 0) { num3 = 1; num5 = 0; silk_bw_switch = 1; } } int endBand = 21; switch (opusBandwidth4) { case OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND: endBand = 13; break; case OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND: case OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND: endBand = 17; break; case OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND: endBand = 19; break; case OpusBandwidth.OPUS_BANDWIDTH_FULLBAND: endBand = 21; break; } celt_Encoder.SetEndBand(endBand); celt_Encoder.SetChannels(stream_channels); celt_Encoder.SetBitrate(-1); int num43; if (mode != OpusMode.MODE_SILK_ONLY) { int prediction = 2; celt_Encoder.SetVBR(value: false); if (silk_mode.reducedDependency != 0) { prediction = 0; } celt_Encoder.SetPrediction(prediction); if (mode == OpusMode.MODE_HYBRID) { int num42 = entropyCoder.tell() + 7 >> 3; if (num3 != 0) { num42 += ((mode != OpusMode.MODE_HYBRID) ? 1 : 3); } num43 = ((use_vbr == 0) ? ((num42 > num30) ? num42 : num30) : (num42 + num30 - silk_mode.bitRate * frame_size / (8 * Fs))); } else if (use_vbr != 0) { int num44 = 0; if (analysis.enabled && variable_duration == OpusFramesize.OPUS_FRAMESIZE_VARIABLE && frame_size != Fs / 50) { num44 = (60 * stream_channels + 40) * (Fs / frame_size - 50); if (analysisInfo.valid != 0) { num44 = (int)((float)num44 * (1f + 0.5f * analysisInfo.tonality)); } } celt_Encoder.SetVBR(value: true); celt_Encoder.SetVBRConstraint(vbr_constraint != 0); celt_Encoder.SetBitrate(bitrate_bps + num44); num43 = num9 - 1 - num4; } else { num43 = num30; } } else { num43 = 0; } short[] array6 = new short[channels * Fs / 400]; if (mode != OpusMode.MODE_SILK_ONLY && mode != prev_mode && prev_mode > (OpusMode)0) { Array.Copy(delay_buffer, (encoder_buffer - num13 - Fs / 400) * channels, array6, 0, channels * Fs / 400); } if (channels * (encoder_buffer - (frame_size + num13)) > 0) { Arrays.MemMove(delay_buffer, channels * frame_size, 0, channels * (encoder_buffer - frame_size - num13)); Array.Copy(array4, 0, delay_buffer, channels * (encoder_buffer - frame_size - num13), (frame_size + num13) * channels); } else { Array.Copy(array4, (frame_size + num13 - encoder_buffer) * channels, delay_buffer, 0, encoder_buffer * channels); } if (prev_HB_gain < 32767 || num31 < 32767) { CodecHelpers.gain_fade(array4, 0, prev_HB_gain, num31, celtMode.overlap, frame_size, channels, celtMode.window, Fs); } prev_HB_gain = num31; if (mode != OpusMode.MODE_HYBRID || stream_channels == 1) { silk_mode.stereoWidth_Q14 = Inlines.IMIN(16384, 2 * Inlines.IMAX(0, num18 - 30000)); } if (energy_masking == null && channels == 2 && (hybrid_stereo_width_Q14 < 16384 || silk_mode.stereoWidth_Q14 < 16384)) { int num45 = hybrid_stereo_width_Q14; int stereoWidth_Q = silk_mode.stereoWidth_Q14; num45 = ((num45 == 16384) ? 32767 : Inlines.SHL16(num45, 1)); stereoWidth_Q = ((stereoWidth_Q == 16384) ? 32767 : Inlines.SHL16(stereoWidth_Q, 1)); CodecHelpers.stereo_fade(array4, num45, stereoWidth_Q, celtMode.overlap, frame_size, channels, celtMode.window, Fs); hybrid_stereo_width_Q14 = (short)silk_mode.stereoWidth_Q14; } if (mode != OpusMode.MODE_CELT_ONLY && entropyCoder.tell() + 17 + 20 * ((mode == OpusMode.MODE_HYBRID) ? 1 : 0) <= 8 * (num9 - 1)) { if (mode == OpusMode.MODE_HYBRID && (num3 != 0 || entropyCoder.tell() + 37 <= 8 * num43)) { entropyCoder.enc_bit_logp(num3, 12u); } if (num3 != 0) { entropyCoder.enc_bit_logp(num5, 1u); int a3 = ((mode != OpusMode.MODE_HYBRID) ? (num9 - 1 - (entropyCoder.tell() + 7 >> 3)) : (num9 - 1 - num43)); num4 = Inlines.IMIN(a3, bitrate_bps / 1600); num4 = Inlines.IMIN(257, Inlines.IMAX(2, num4)); if (mode == OpusMode.MODE_HYBRID) { entropyCoder.enc_uint((uint)(num4 - 2), 256u); } } } else { num3 = 0; } if (num3 == 0) { silk_bw_switch = 0; num4 = 0; } if (mode != OpusMode.MODE_CELT_ONLY) { startBand = 17; } if (mode == OpusMode.MODE_SILK_ONLY) { num = entropyCoder.tell() + 7 >> 3; entropyCoder.enc_done(); num43 = num; } else { num43 = Inlines.IMIN(num9 - 1 - num4, num43); entropyCoder.enc_shrink((uint)num43); } if ((analysis.enabled && num3 != 0) || mode != OpusMode.MODE_SILK_ONLY) { analysisInfo.enabled = analysis.enabled; celt_Encoder.SetAnalysis(analysisInfo); } if (num3 != 0 && num5 != 0) { celt_Encoder.SetStartBand(0); celt_Encoder.SetVBR(value: false); int num46 = celt_Encoder.celt_encode_with_ec(array4, 0, Fs / 200, data, data_ptr + num43, num4, null); if (num46 < 0) { return -3; } num7 = celt_Encoder.GetFinalRange(); celt_Encoder.ResetState(); } celt_Encoder.SetStartBand(startBand); if (mode != OpusMode.MODE_SILK_ONLY) { if (mode != prev_mode && prev_mode > (OpusMode)0) { byte[] compressed = new byte[2]; celt_Encoder.ResetState(); celt_Encoder.celt_encode_with_ec(array6, 0, Fs / 400, compressed, 0, 2, null); celt_Encoder.SetPrediction(0); } if (entropyCoder.tell() <= 8 * num43) { num = celt_Encoder.celt_encode_with_ec(array4, 0, frame_size, null, 0, num43, entropyCoder); if (num < 0) { return -3; } } } if (num3 != 0 && num5 == 0) { byte[] compressed = new byte[2]; int num47 = Fs / 200; int num48 = Fs / 400; celt_Encoder.ResetState(); celt_Encoder.SetStartBand(0); celt_Encoder.SetPrediction(0); celt_Encoder.celt_encode_with_ec(array4, channels * (frame_size - num47 - num48), num48, compressed, 0, 2, null); int num46 = celt_Encoder.celt_encode_with_ec(array4, channels * (frame_size - num47), num47, data, data_ptr + num43, num4, null); if (num46 < 0) { return -3; } num7 = celt_Encoder.GetFinalRange(); } data_ptr--; data[data_ptr] = CodecHelpers.gen_toc(mode, Fs / frame_size, opusBandwidth4, stream_channels); rangeFinal = entropyCoder.rng ^ num7; if (num6 != 0) { prev_mode = OpusMode.MODE_CELT_ONLY; } else { prev_mode = mode; } prev_channels = stream_channels; prev_framesize = frame_size; first = 0; if (entropyCoder.tell() > (num9 - 1) * 8) { if (num9 < 2) { return -2; } data[data_ptr + 1] = 0; num = 1; rangeFinal = 0u; } else if (mode == OpusMode.MODE_SILK_ONLY && num3 == 0) { while (num > 2 && data[data_ptr + num] == 0) { num--; } } num += 1 + num4; if (use_vbr == 0) { if (OpusRepacketizer.PadPacket(data, data_ptr, num, num9) != 0) { return -3; } num = num9; } return num; } public int Encode(short[] in_pcm, int pcm_offset, int frame_size, byte[] out_data, int out_data_offset, int max_data_bytes) { if (out_data_offset + max_data_bytes > out_data.Length) { throw new ArgumentException($"Output buffer is too small: Stated size is {max_data_bytes} bytes, actual size is {out_data.Length - out_data_offset} bytes"); } int num2 = CodecHelpers.compute_frame_size(delay_compensation: (application != OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY) ? delay_compensation : 0, analysis_pcm: in_pcm, analysis_pcm_ptr: pcm_offset, frame_size: frame_size, variable_duration: variable_duration, C: channels, Fs: Fs, bitrate_bps: bitrate_bps, downmix: Downmix.downmix_int, subframe_mem: analysis.subframe_mem, analysis_enabled: analysis.enabled); if (pcm_offset + num2 > in_pcm.Length) { throw new ArgumentException($"Not enough samples provided in input signal: Expected {num2} samples, found {in_pcm.Length - pcm_offset}"); } try { int num3 = opus_encode_native(in_pcm, pcm_offset, num2, out_data, out_data_offset, max_data_bytes, 16, in_pcm, pcm_offset, frame_size, 0, -2, channels, Downmix.downmix_int, 0); if (num3 < 0) { if (num3 == -1) { throw new ArgumentException("OPUS_BAD_ARG while encoding"); } throw new OpusException("An error occurred during encoding", num3); } return num3; } catch (OutOfMemoryException ex) { throw new OpusException("Internal error during encoding: " + ex.Message); } } public int Encode(float[] in_pcm, int pcm_offset, int frame_size, byte[] out_data, int out_data_offset, int max_data_bytes) { if (out_data_offset + max_data_bytes > out_data.Length) { throw new ArgumentException($"Output buffer is too small: Stated size is {max_data_bytes} bytes, actual size is {out_data.Length - out_data_offset} bytes"); } int num2 = CodecHelpers.compute_frame_size(delay_compensation: (application != OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY) ? delay_compensation : 0, analysis_pcm: in_pcm, analysis_pcm_ptr: pcm_offset, frame_size: frame_size, variable_duration: variable_duration, C: channels, Fs: Fs, bitrate_bps: bitrate_bps, downmix: Downmix.downmix_float, subframe_mem: analysis.subframe_mem, analysis_enabled: analysis.enabled); if (pcm_offset + num2 > in_pcm.Length) { throw new ArgumentException($"Not enough samples provided in input signal: Expected {num2} samples, found {in_pcm.Length - pcm_offset}"); } short[] array = new short[num2 * channels]; for (int i = 0; i < num2 * channels; i++) { array[i] = Inlines.FLOAT2INT16(in_pcm[pcm_offset + i]); } try { int num3 = opus_encode_native(array, 0, num2, out_data, out_data_offset, max_data_bytes, 16, in_pcm, pcm_offset, frame_size, 0, -2, channels, Downmix.downmix_float, 1); if (num3 < 0) { if (num3 == -1) { throw new ArgumentException("OPUS_BAD_ARG while decoding"); } throw new OpusException("An error occurred during encoding", num3); } return num3; } catch (OutOfMemoryException ex) { throw new OpusException("Internal error during encoding: " + ex.Message); } } internal void SetEnergyMask(int[] value) { energy_masking = value; Celt_Encoder.SetEnergyMask(value); } internal CeltMode GetCeltMode() { return Celt_Encoder.GetMode(); } } public class OpusMSDecoder { internal delegate void opus_copy_channel_out_func(T[] dst, int dst_ptr, int dst_stride, int dst_channel, short[] src, int src_ptr, int src_stride, int frame_size); internal ChannelLayout layout = new ChannelLayout(); internal OpusDecoder[] decoders = null; public OpusBandwidth Bandwidth { get { if (decoders == null || decoders.Length == 0) { throw new InvalidOperationException("Decoder not initialized"); } return decoders[0].Bandwidth; } } public int SampleRate { get { if (decoders == null || decoders.Length == 0) { throw new InvalidOperationException("Decoder not initialized"); } return decoders[0].SampleRate; } } public int Gain { get { if (decoders == null || decoders.Length == 0) { return -6; } return decoders[0].Gain; } set { for (int i = 0; i < layout.nb_streams; i++) { decoders[i].Gain = value; } } } public int LastPacketDuration { get { if (decoders == null || decoders.Length == 0) { return -6; } return decoders[0].LastPacketDuration; } } public uint FinalRange { get { uint num = 0u; for (int i = 0; i < layout.nb_streams; i++) { num ^= decoders[i].FinalRange; } return num; } } private OpusMSDecoder(int nb_streams, int nb_coupled_streams) { decoders = new OpusDecoder[nb_streams]; for (int i = 0; i < nb_streams; i++) { decoders[i] = new OpusDecoder(); } } internal int opus_multistream_decoder_init(int Fs, int channels, int streams, int coupled_streams, byte[] mapping) { int num = 0; if (channels > 255 || channels < 1 || coupled_streams > streams || streams < 1 || coupled_streams < 0 || streams > 255 - coupled_streams) { throw new ArgumentException("Invalid channel or coupled stream count"); } layout.nb_channels = channels; layout.nb_streams = streams; layout.nb_coupled_streams = coupled_streams; int i; for (i = 0; i < layout.nb_channels; i++) { layout.mapping[i] = mapping[i]; } if (OpusMultistream.validate_layout(layout) == 0) { throw new ArgumentException("Invalid surround channel layout"); } for (i = 0; i < layout.nb_coupled_streams; i++) { int num2 = decoders[num].opus_decoder_init(Fs, 2); if (num2 != 0) { return num2; } num++; } for (; i < layout.nb_streams; i++) { int num2 = decoders[num].opus_decoder_init(Fs, 1); if (num2 != 0) { return num2; } num++; } return 0; } public OpusMSDecoder(int Fs, int channels, int streams, int coupled_streams, byte[] mapping) : this(streams, coupled_streams) { if (channels > 255 || channels < 1 || coupled_streams > streams || streams < 1 || coupled_streams < 0 || streams > 255 - coupled_streams) { throw new ArgumentException("Invalid channel / stream configuration"); } int num = opus_multistream_decoder_init(Fs, channels, streams, coupled_streams, mapping); switch (num) { case -1: throw new ArgumentException("Bad argument while creating MS decoder"); default: throw new OpusException("Could not create MS decoder", num); case 0: break; } } internal static int opus_multistream_packet_validate(byte[] data, int data_ptr, int len, int nb_streams, int Fs) { short[] sizes = new short[48]; int num = 0; for (int i = 0; i < nb_streams; i++) { if (len <= 0) { return -4; } byte out_toc; int payload_offset; int packet_offset; int num2 = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, (i != nb_streams - 1) ? 1 : 0, out out_toc, null, null, 0, sizes, 0, out payload_offset, out packet_offset); if (num2 < 0) { return num2; } int numSamples = OpusPacketInfo.GetNumSamples(data, data_ptr, packet_offset, Fs); if (i != 0 && num != numSamples) { return -4; } num = numSamples; data_ptr += packet_offset; len -= packet_offset; } return num; } internal int opus_multistream_decode_native(byte[] data, int data_ptr, int len, T[] pcm, int pcm_ptr, opus_copy_channel_out_func copy_channel_out, int frame_size, int decode_fec, int soft_clip) { int num = 0; int sampleRate = SampleRate; frame_size = Inlines.IMIN(frame_size, sampleRate / 25 * 3); short[] array = new short[2 * frame_size]; int num2 = 0; if (len == 0) { num = 1; } if (len < 0) { return -1; } if (num == 0 && len < 2 * layout.nb_streams - 1) { return -4; } if (num == 0) { int num3 = opus_multistream_packet_validate(data, data_ptr, len, layout.nb_streams, sampleRate); if (num3 < 0) { return num3; } if (num3 > frame_size) { return -2; } } for (int i = 0; i < layout.nb_streams; i++) { OpusDecoder opusDecoder = decoders[num2++]; if (num == 0 && len <= 0) { return -3; } int packet_offset; int num3 = opusDecoder.opus_decode_native(data, data_ptr, len, array, 0, frame_size, decode_fec, (i != layout.nb_streams - 1) ? 1 : 0, out packet_offset, soft_clip); data_ptr += packet_offset; len -= packet_offset; if (num3 <= 0) { return num3; } frame_size = num3; if (i < layout.nb_coupled_streams) { int prev = -1; int num4; while ((num4 = OpusMultistream.get_left_channel(layout, i, prev)) != -1) { copy_channel_out(pcm, pcm_ptr, layout.nb_channels, num4, array, 0, 2, frame_size); prev = num4; } prev = -1; while ((num4 = OpusMultistream.get_right_channel(layout, i, prev)) != -1) { copy_channel_out(pcm, pcm_ptr, layout.nb_channels, num4, array, 1, 2, frame_size); prev = num4; } } else { int prev = -1; int num4; while ((num4 = OpusMultistream.get_mono_channel(layout, i, prev)) != -1) { copy_channel_out(pcm, pcm_ptr, layout.nb_channels, num4, array, 0, 1, frame_size); prev = num4; } } } for (int j = 0; j < layout.nb_channels; j++) { if (layout.mapping[j] == byte.MaxValue) { copy_channel_out(pcm, pcm_ptr, layout.nb_channels, j, null, 0, 0, frame_size); } } return frame_size; } internal static void opus_copy_channel_out_float(float[] dst, int dst_ptr, int dst_stride, int dst_channel, short[] src, int src_ptr, int src_stride, int frame_size) { if (src != null) { for (int i = 0; i < frame_size; i++) { dst[i * dst_stride + dst_channel + dst_ptr] = 3.0517578E-05f * (float)src[i * src_stride + src_ptr]; } } else { for (int i = 0; i < frame_size; i++) { dst[i * dst_stride + dst_channel + dst_ptr] = 0f; } } } internal static void opus_copy_channel_out_short(short[] dst, int dst_ptr, int dst_stride, int dst_channel, short[] src, int src_ptr, int src_stride, int frame_size) { if (src != null) { for (int i = 0; i < frame_size; i++) { dst[i * dst_stride + dst_channel + dst_ptr] = src[i * src_stride + src_ptr]; } } else { for (int i = 0; i < frame_size; i++) { dst[i * dst_stride + dst_channel + dst_ptr] = 0; } } } public int DecodeMultistream(byte[] data, int data_offset, int len, short[] out_pcm, int out_pcm_offset, int frame_size, int decode_fec) { return opus_multistream_decode_native(data, data_offset, len, out_pcm, out_pcm_offset, opus_copy_channel_out_short, frame_size, decode_fec, 0); } public int DecodeMultistream(byte[] data, int data_offset, int len, float[] out_pcm, int out_pcm_offset, int frame_size, int decode_fec) { return opus_multistream_decode_native(data, data_offset, len, out_pcm, out_pcm_offset, opus_copy_channel_out_float, frame_size, decode_fec, 0); } public void ResetState() { for (int i = 0; i < layout.nb_streams; i++) { decoders[i].ResetState(); } } public OpusDecoder GetMultistreamDecoderState(int streamId) { return decoders[streamId]; } } public class OpusMSEncoder { internal delegate void opus_copy_channel_in_func(short[] dst, int dst_ptr, int dst_stride, T[] src, int src_ptr, int src_stride, int src_channel, int frame_size); private const int MS_FRAME_TMP = 3832; internal readonly ChannelLayout layout = new ChannelLayout(); internal int lfe_stream = 0; internal OpusApplication application = OpusApplication.OPUS_APPLICATION_AUDIO; internal OpusFramesize variable_duration = (OpusFramesize)0; internal int surround = 0; internal int bitrate_bps = 0; internal readonly float[] subframe_mem = new float[3]; internal readonly OpusEncoder[] encoders = null; internal readonly int[] window_mem = null; internal readonly int[] preemph_mem = null; private static readonly int[] diff_table = new int[9] { 512, 300, 165, 87, 45, 23, 11, 6, 3 }; public int Bitrate { get { int num = 0; int num2 = 0; for (int i = 0; i < layout.nb_streams; i++) { OpusEncoder opusEncoder = encoders[num2++]; num += opusEncoder.Bitrate; } return num; } set { if (value < 0 && value != -1000 && value != -1) { throw new ArgumentException("Invalid bitrate"); } bitrate_bps = value; } } public OpusApplication Application { get { return encoders[0].Application; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].Application = value; } } } public int ForceChannels { get { return encoders[0].ForceChannels; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].ForceChannels = value; } } } public OpusBandwidth MaxBandwidth { get { return encoders[0].MaxBandwidth; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].MaxBandwidth = value; } } } public OpusBandwidth Bandwidth { get { return encoders[0].Bandwidth; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].Bandwidth = value; } } } public bool UseDTX { get { return encoders[0].UseDTX; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].UseDTX = value; } } } public int Complexity { get { return encoders[0].Complexity; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].Complexity = value; } } } public OpusMode ForceMode { get { return encoders[0].ForceMode; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].ForceMode = value; } } } public bool UseInbandFEC { get { return encoders[0].UseInbandFEC; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].UseInbandFEC = value; } } } public int PacketLossPercent { get { return encoders[0].PacketLossPercent; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].PacketLossPercent = value; } } } public bool UseVBR { get { return encoders[0].UseVBR; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].UseVBR = value; } } } public bool UseConstrainedVBR { get { return encoders[0].UseConstrainedVBR; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].UseConstrainedVBR = value; } } } public OpusSignal SignalType { get { return encoders[0].SignalType; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].SignalType = value; } } } public int Lookahead => encoders[0].Lookahead; public int SampleRate => encoders[0].SampleRate; public uint FinalRange { get { uint num = 0u; int num2 = 0; for (int i = 0; i < layout.nb_streams; i++) { num ^= encoders[num2++].FinalRange; } return num; } } public int LSBDepth { get { return encoders[0].LSBDepth; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].LSBDepth = value; } } } public bool PredictionDisabled { get { return encoders[0].PredictionDisabled; } set { for (int i = 0; i < layout.nb_streams; i++) { encoders[i].PredictionDisabled = value; } } } public OpusFramesize ExpertFrameDuration { get { return variable_duration; } set { variable_duration = value; } } private OpusMSEncoder(int nb_streams, int nb_coupled_streams) { if (nb_streams < 1 || nb_coupled_streams > nb_streams || nb_coupled_streams < 0) { throw new ArgumentException("Invalid channel count in MS encoder"); } encoders = new OpusEncoder[nb_streams]; for (int i = 0; i < nb_streams; i++) { encoders[i] = new OpusEncoder(); } window_mem = new int[nb_streams * 120]; preemph_mem = new int[nb_streams]; } public void ResetState() { subframe_mem[0] = (subframe_mem[1] = (subframe_mem[2] = 0f)); if (surround != 0) { Arrays.MemSet(preemph_mem, 0, layout.nb_channels); Arrays.MemSet(window_mem, 0, layout.nb_channels * 120); } int num = 0; for (int i = 0; i < layout.nb_streams; i++) { OpusEncoder opusEncoder = encoders[num++]; opusEncoder.ResetState(); } } internal static int validate_encoder_layout(ChannelLayout layout) { for (int i = 0; i < layout.nb_streams; i++) { if (i < layout.nb_coupled_streams) { if (OpusMultistream.get_left_channel(layout, i, -1) == -1) { return 0; } if (OpusMultistream.get_right_channel(layout, i, -1) == -1) { return 0; } } else if (OpusMultistream.get_mono_channel(layout, i, -1) == -1) { return 0; } } return 1; } internal static void channel_pos(int channels, int[] pos) { switch (channels) { case 4: pos[0] = 1; pos[1] = 3; pos[2] = 1; pos[3] = 3; break; default: if (channels != 6) { switch (channels) { case 7: pos[0] = 1; pos[1] = 2; pos[2] = 3; pos[3] = 1; pos[4] = 3; pos[5] = 2; pos[6] = 0; break; case 8: pos[0] = 1; pos[1] = 2; pos[2] = 3; pos[3] = 1; pos[4] = 3; pos[5] = 1; pos[6] = 3; pos[7] = 0; break; } break; } goto case 3; case 3: case 5: pos[0] = 1; pos[1] = 2; pos[2] = 3; pos[3] = 1; pos[4] = 3; pos[5] = 0; break; } } internal static int logSum(int a, int b) { int num; int num2; if (a > b) { num = a; num2 = Inlines.SUB32(Inlines.EXTEND32(a), Inlines.EXTEND32(b)); } else { num = b; num2 = Inlines.SUB32(Inlines.EXTEND32(b), Inlines.EXTEND32(a)); } if (num2 >= 8192) { return num; } int num3 = Inlines.SHR32(num2, 9); int a2 = Inlines.SHL16(num2 - Inlines.SHL16(num3, 9), 6); return num + diff_table[num3] + Inlines.MULT16_16_Q15(a2, Inlines.SUB16(diff_table[num3 + 1], diff_table[num3])); } internal static void surround_analysis(CeltMode celt_mode, T[] pcm, int pcm_ptr, int[] bandLogE, int[] mem, int[] preemph_mem, int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in) { int[] array = new int[8]; int[] array2 = array; int[][] array3 = Arrays.InitTwoDimensionalArray(1, 21); int[][] array4 = Arrays.InitTwoDimensionalArray(3, 21); int num = CeltCommon.resampling_factor(rate); int num2 = len * num; int i; for (i = 0; i < celt_mode.maxLM && celt_mode.shortMdctSize << i != num2; i++) { } int[] array5 = new int[num2 + overlap]; short[] array6 = new short[len]; int[][] array7 = Arrays.InitTwoDimensionalArray(1, num2); channel_pos(channels, array2); for (int j = 0; j < 3; j++) { for (int k = 0; k < 21; k++) { array4[j][k] = -28672; } } for (int j = 0; j < channels; j++) { Array.Copy(mem, j * overlap, array5, 0, overlap); copy_channel_in(array6, 0, 1, pcm, pcm_ptr, channels, j, len); BoxedValue boxedValue = new BoxedValue(preemph_mem[j]); CeltCommon.celt_preemphasis(array6, array5, overlap, num2, 1, num, celt_mode.preemph, boxedValue, 0); preemph_mem[j] = boxedValue.Val; MDCT.clt_mdct_forward(celt_mode.mdct, array5, 0, array7[0], 0, celt_mode.window, overlap, celt_mode.maxLM - i, 1); if (num != 1) { int k; for (k = 0; k < len; k++) { array7[0][k] *= num; } for (; k < num2; k++) { array7[0][k] = 0; } } Bands.compute_band_energies(celt_mode, array7, array3, 21, 1, i); QuantizeBands.amp2Log2(celt_mode, 21, 21, array3[0], bandLogE, 21 * j, 1); for (int k = 1; k < 21; k++) { bandLogE[21 * j + k] = Inlines.MAX16(bandLogE[21 * j + k], bandLogE[21 * j + k - 1] - 1024); } for (int k = 19; k >= 0; k--) { bandLogE[21 * j + k] = Inlines.MAX16(bandLogE[21 * j + k], bandLogE[21 * j + k + 1] - 2048); } if (array2[j] == 1) { for (int k = 0; k < 21; k++) { array4[0][k] = logSum(array4[0][k], bandLogE[21 * j + k]); } } else if (array2[j] == 3) { for (int k = 0; k < 21; k++) { array4[2][k] = logSum(array4[2][k], bandLogE[21 * j + k]); } } else if (array2[j] == 2) { for (int k = 0; k < 21; k++) { array4[0][k] = logSum(array4[0][k], bandLogE[21 * j + k] - 512); array4[2][k] = logSum(array4[2][k], bandLogE[21 * j + k] - 512); } } Array.Copy(array5, num2, mem, j * overlap, overlap); } for (int k = 0; k < 21; k++) { array4[1][k] = Inlines.MIN32(array4[0][k], array4[2][k]); } int num3 = Inlines.HALF16(Inlines.celt_log2(32768 / (channels - 1))); for (int j = 0; j < 3; j++) { for (int k = 0; k < 21; k++) { array4[j][k] += num3; } } for (int j = 0; j < channels; j++) { if (array2[j] != 0) { int[] array8 = array4[array2[j] - 1]; for (int k = 0; k < 21; k++) { bandLogE[21 * j + k] -= array8[k]; } } else { for (int k = 0; k < 21; k++) { bandLogE[21 * j + k] = 0; } } } } internal int opus_multistream_encoder_init(int Fs, int channels, int streams, int coupled_streams, byte[] mapping, OpusApplication application, int surround) { if (channels > 255 || channels < 1 || coupled_streams > streams || streams < 1 || coupled_streams < 0 || streams > 255 - coupled_streams) { return -1; } layout.nb_channels = channels; layout.nb_streams = streams; layout.nb_coupled_streams = coupled_streams; subframe_mem[0] = (subframe_mem[1] = (subframe_mem[2] = 0f)); if (surround == 0) { lfe_stream = -1; } bitrate_bps = -1000; this.application = application; variable_duration = OpusFramesize.OPUS_FRAMESIZE_ARG; int i; for (i = 0; i < layout.nb_channels; i++) { layout.mapping[i] = mapping[i]; } if (OpusMultistream.validate_layout(layout) == 0 || validate_encoder_layout(layout) == 0) { return -1; } int num = 0; for (i = 0; i < layout.nb_coupled_streams; i++) { int num2 = encoders[num].opus_init_encoder(Fs, 2, application); if (num2 != 0) { return num2; } if (i == lfe_stream) { encoders[num].IsLFE = true; } num++; } for (; i < layout.nb_streams; i++) { int num2 = encoders[num].opus_init_encoder(Fs, 1, application); if (i == lfe_stream) { encoders[num].IsLFE = true; } if (num2 != 0) { return num2; } num++; } if (surround != 0) { Arrays.MemSet(preemph_mem, 0, channels); Arrays.MemSet(window_mem, 0, channels * 120); } this.surround = surround; return 0; } internal int opus_multistream_surround_encoder_init(int Fs, int channels, int mapping_family, out int streams, out int coupled_streams, byte[] mapping, OpusApplication application) { streams = 0; coupled_streams = 0; if (channels > 255 || channels < 1) { return -1; } lfe_stream = -1; if (mapping_family == 0) { switch (channels) { case 1: streams = 1; coupled_streams = 0; mapping[0] = 0; break; case 2: streams = 1; coupled_streams = 1; mapping[0] = 0; mapping[1] = 1; break; default: return -5; } } else if (mapping_family == 1 && channels <= 8 && channels >= 1) { streams = VorbisLayout.vorbis_mappings[channels - 1].nb_streams; coupled_streams = VorbisLayout.vorbis_mappings[channels - 1].nb_coupled_streams; for (int i = 0; i < channels; i++) { mapping[i] = VorbisLayout.vorbis_mappings[channels - 1].mapping[i]; } if (channels >= 6) { lfe_stream = streams - 1; } } else { if (mapping_family != 255) { return -5; } streams = channels; coupled_streams = 0; for (byte b = 0; b < channels; b++) { mapping[b] = b; } } return opus_multistream_encoder_init(Fs, channels, streams, coupled_streams, mapping, application, (channels > 2 && mapping_family == 1) ? 1 : 0); } public static OpusMSEncoder Create(int Fs, int channels, int streams, int coupled_streams, byte[] mapping, OpusApplication application) { if (channels > 255 || channels < 1 || coupled_streams > streams || streams < 1 || coupled_streams < 0 || streams > 255 - coupled_streams) { throw new ArgumentException("Invalid channel / stream configuration"); } OpusMSEncoder opusMSEncoder = new OpusMSEncoder(streams, coupled_streams); int num = opusMSEncoder.opus_multistream_encoder_init(Fs, channels, streams, coupled_streams, mapping, application, 0); return num switch { -1 => throw new ArgumentException("OPUS_BAD_ARG when creating MS encoder"), 0 => opusMSEncoder, _ => throw new OpusException("Could not create MS encoder", num), }; } internal static void GetStreamCount(int channels, int mapping_family, BoxedValue nb_streams, BoxedValue nb_coupled_streams) { switch (mapping_family) { case 0: switch (channels) { case 1: nb_streams.Val = 1; nb_coupled_streams.Val = 0; break; case 2: nb_streams.Val = 1; nb_coupled_streams.Val = 1; break; default: throw new ArgumentException("More than 2 channels requires custom mappings"); } return; case 1: if (channels <= 8 && channels >= 1) { nb_streams.Val = VorbisLayout.vorbis_mappings[channels - 1].nb_streams; nb_coupled_streams.Val = VorbisLayout.vorbis_mappings[channels - 1].nb_coupled_streams; return; } break; } if (mapping_family == 255) { nb_streams.Val = channels; nb_coupled_streams.Val = 0; return; } throw new ArgumentException("Invalid mapping family"); } public static OpusMSEncoder CreateSurround(int Fs, int channels, int mapping_family, out int streams, out int coupled_streams, byte[] mapping, OpusApplication application) { if (channels > 255 || channels < 1 || application == OpusApplication.OPUS_APPLICATION_UNIMPLEMENTED) { throw new ArgumentException("Invalid channel count or application"); } BoxedValue boxedValue = new BoxedValue(0); BoxedValue boxedValue2 = new BoxedValue(0); GetStreamCount(channels, mapping_family, boxedValue, boxedValue2); OpusMSEncoder opusMSEncoder = new OpusMSEncoder(boxedValue.Val, boxedValue2.Val); int num = opusMSEncoder.opus_multistream_surround_encoder_init(Fs, channels, mapping_family, out streams, out coupled_streams, mapping, application); return num switch { -1 => throw new ArgumentException("Bad argument passed to CreateSurround"), 0 => opusMSEncoder, _ => throw new OpusException("Could not create multistream encoder", num), }; } internal int surround_rate_allocation(int[] out_rates, int frame_size) { int num = 0; OpusEncoder opusEncoder = encoders[0]; int sampleRate = opusEncoder.SampleRate; int num2 = ((bitrate_bps <= layout.nb_channels * 40000) ? (bitrate_bps / layout.nb_channels / 2) : 20000); num2 += 60 * (sampleRate / frame_size - 50); int num3 = 3500 + 60 * (sampleRate / frame_size - 50); int num4 = 512; int num5 = 32; int num6; if (bitrate_bps == -1000) { num6 = sampleRate + 60 * sampleRate / frame_size; } else if (bitrate_bps == -1) { num6 = 300000; } else { int num7 = ((lfe_stream != -1) ? 1 : 0); int nb_coupled_streams = layout.nb_coupled_streams; int num8 = layout.nb_streams - nb_coupled_streams - num7; int num9 = (num8 << 8) + num4 * nb_coupled_streams + num7 * num5; num6 = 256 * (bitrate_bps - num3 * num7 - num2 * (nb_coupled_streams + num8)) / num9; } for (int i = 0; i < layout.nb_streams; i++) { if (i < layout.nb_coupled_streams) { out_rates[i] = num2 + (num6 * num4 >> 8); } else if (i != lfe_stream) { out_rates[i] = num2 + num6; } else { out_rates[i] = num3 + (num6 * num5 >> 8); } out_rates[i] = Inlines.IMAX(out_rates[i], 500); num += out_rates[i]; } return num; } internal int opus_multistream_encode_native(opus_copy_channel_in_func copy_channel_in, T[] pcm, int pcm_ptr, int analysis_frame_size, byte[] data, int data_ptr, int max_data_bytes, int lsb_depth, Downmix.downmix_func downmix, int float_api) { byte[] data2 = new byte[3832]; OpusRepacketizer opusRepacketizer = new OpusRepacketizer(); int[] array = new int[256]; int[] array2 = new int[42]; int[] mem = null; int[] array3 = null; if (surround != 0) { array3 = preemph_mem; mem = window_mem; } int num = 0; int sampleRate = encoders[num].SampleRate; int num2 = (encoders[num].UseVBR ? 1 : 0); CeltMode celtMode = encoders[num].GetCeltMode(); int c = layout.nb_streams + layout.nb_coupled_streams; int lookahead = encoders[num].Lookahead; lookahead -= sampleRate / 400; int num3 = CodecHelpers.compute_frame_size(pcm, pcm_ptr, analysis_frame_size, variable_duration, c, sampleRate, bitrate_bps, lookahead, downmix, subframe_mem, encoders[num].analysis.enabled); if (400 * num3 < sampleRate) { return -1; } if (400 * num3 != sampleRate && 200 * num3 != sampleRate && 100 * num3 != sampleRate && 50 * num3 != sampleRate && 25 * num3 != sampleRate && 50 * num3 != 3 * sampleRate) { return -1; } int num4 = layout.nb_streams * 2 - 1; if (max_data_bytes < num4) { return -2; } short[] array4 = new short[2 * num3]; int[] array5 = new int[21 * layout.nb_channels]; if (surround != 0) { surround_analysis(celtMode, pcm, pcm_ptr, array5, mem, array3, num3, 120, layout.nb_channels, sampleRate, copy_channel_in); } int num5 = surround_rate_allocation(array, num3); if (num2 == 0) { if (bitrate_bps == -1000) { max_data_bytes = Inlines.IMIN(max_data_bytes, 3 * num5 / (24 * sampleRate / num3)); } else if (bitrate_bps != -1) { max_data_bytes = Inlines.IMIN(max_data_bytes, Inlines.IMAX(num4, 3 * bitrate_bps / (24 * sampleRate / num3))); } } for (int i = 0; i < layout.nb_streams; i++) { OpusEncoder opusEncoder = encoders[num]; num++; opusEncoder.Bitrate = array[i]; if (surround != 0) { int num6 = bitrate_bps; if (num3 * 50 < sampleRate) { num6 -= 60 * (sampleRate / num3 - 50) * layout.nb_channels; } if (num6 > 10000 * layout.nb_channels) { opusEncoder.Bandwidth = OpusBandwidth.OPUS_BANDWIDTH_FULLBAND; } else if (num6 > 7000 * layout.nb_channels) { opusEncoder.Bandwidth = OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND; } else if (num6 > 5000 * layout.nb_channels) { opusEncoder.Bandwidth = OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND; } else { opusEncoder.Bandwidth = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } if (i < layout.nb_coupled_streams) { opusEncoder.ForceMode = OpusMode.MODE_CELT_ONLY; opusEncoder.ForceChannels = 2; } } } num = 0; int num7 = 0; for (int i = 0; i < layout.nb_streams; i++) { opusRepacketizer.Reset(); OpusEncoder opusEncoder = encoders[num]; int c2; int c3; if (i < layout.nb_coupled_streams) { int num8 = OpusMultistream.get_left_channel(layout, i, -1); int num9 = OpusMultistream.get_right_channel(layout, i, -1); copy_channel_in(array4, 0, 2, pcm, pcm_ptr, layout.nb_channels, num8, num3); copy_channel_in(array4, 1, 2, pcm, pcm_ptr, layout.nb_channels, num9, num3); num++; if (surround != 0) { for (int j = 0; j < 21; j++) { array2[j] = array5[21 * num8 + j]; array2[21 + j] = array5[21 * num9 + j]; } } c2 = num8; c3 = num9; } else { int num10 = OpusMultistream.get_mono_channel(layout, i, -1); copy_channel_in(array4, 0, 1, pcm, pcm_ptr, layout.nb_channels, num10, num3); num++; if (surround != 0) { for (int j = 0; j < 21; j++) { array2[j] = array5[21 * num10 + j]; } } c2 = num10; c3 = -1; } if (surround != 0) { opusEncoder.SetEnergyMask(array2); } int num11 = max_data_bytes - num7; num11 -= Inlines.IMAX(0, 2 * (layout.nb_streams - i - 1) - 1); num11 = Inlines.IMIN(num11, 3832); if (i != layout.nb_streams - 1) { num11 -= ((num11 <= 253) ? 1 : 2); } if (num2 == 0 && i == layout.nb_streams - 1) { opusEncoder.Bitrate = num11 * (8 * sampleRate / num3); } int num12 = opusEncoder.opus_encode_native(array4, 0, num3, data2, 0, num11, lsb_depth, pcm, pcm_ptr, analysis_frame_size, c2, c3, layout.nb_channels, downmix, float_api); if (num12 < 0) { return num12; } opusRepacketizer.AddPacket(data2, 0, num12); num12 = opusRepacketizer.opus_repacketizer_out_range_impl(0, opusRepacketizer.GetNumFrames(), data, data_ptr, max_data_bytes - num7, (i != layout.nb_streams - 1) ? 1 : 0, (num2 == 0 && i == layout.nb_streams - 1) ? 1 : 0); data_ptr += num12; num7 += num12; } return num7; } internal static void opus_copy_channel_in_float(short[] dst, int dst_ptr, int dst_stride, float[] src, int src_ptr, int src_stride, int src_channel, int frame_size) { for (int i = 0; i < frame_size; i++) { dst[dst_ptr + i * dst_stride] = Inlines.FLOAT2INT16(src[i * src_stride + src_channel + src_ptr]); } } internal static void opus_copy_channel_in_short(short[] dst, int dst_ptr, int dst_stride, short[] src, int src_ptr, int src_stride, int src_channel, int frame_size) { for (int i = 0; i < frame_size; i++) { dst[dst_ptr + i * dst_stride] = src[i * src_stride + src_channel + src_ptr]; } } public int EncodeMultistream(short[] pcm, int pcm_offset, int frame_size, byte[] outputBuffer, int outputBuffer_offset, int max_data_bytes) { return opus_multistream_encode_native(opus_copy_channel_in_short, pcm, pcm_offset, frame_size, outputBuffer, outputBuffer_offset, max_data_bytes, 16, Downmix.downmix_int, 0); } public int EncodeMultistream(float[] pcm, int pcm_offset, int frame_size, byte[] outputBuffer, int outputBuffer_offset, int max_data_bytes) { return opus_multistream_encode_native(opus_copy_channel_in_float, pcm, pcm_offset, frame_size, outputBuffer, outputBuffer_offset, max_data_bytes, 16, Downmix.downmix_float, 1); } public OpusEncoder GetMultistreamEncoderState(int streamId) { if (streamId >= layout.nb_streams) { throw new ArgumentException("Requested stream doesn't exist"); } return encoders[streamId]; } } public class OpusPacketInfo { public readonly byte TOCByte; public readonly IList Frames; public readonly int PayloadOffset; private OpusPacketInfo(byte toc, IList frames, int payloadOffset) { TOCByte = toc; Frames = frames; PayloadOffset = payloadOffset; } public static OpusPacketInfo ParseOpusPacket(byte[] packet, int packet_offset, int len) { int numFrames = GetNumFrames(packet, packet_offset, len); byte[][] array = new byte[numFrames][]; int[] array2 = new int[numFrames]; short[] array3 = new short[numFrames]; byte out_toc; int payload_offset; int packet_offset2; int num = opus_packet_parse_impl(packet, packet_offset, len, 0, out out_toc, array, array2, 0, array3, 0, out payload_offset, out packet_offset2); if (num < 0) { throw new OpusException("An error occurred while parsing the packet", num); } IList list = new List(); for (int i = 0; i < numFrames; i++) { byte[] array4 = new byte[array3[i]]; Array.Copy(array[i], array2[i], array4, 0, array4.Length); list.Add(array4); } return new OpusPacketInfo(out_toc, list, payload_offset); } public static int GetNumSamplesPerFrame(byte[] packet, int packet_offset, int Fs) { int num; if ((packet[packet_offset] & 0x80u) != 0) { num = (packet[packet_offset] >> 3) & 3; return (Fs << num) / 400; } if ((packet[packet_offset] & 0x60) == 96) { return ((packet[packet_offset] & 8u) != 0) ? (Fs / 50) : (Fs / 100); } num = (packet[packet_offset] >> 3) & 3; if (num == 3) { return Fs * 60 / 1000; } return (Fs << num) / 100; } public static OpusBandwidth GetBandwidth(byte[] packet, int packet_offset) { OpusBandwidth opusBandwidth; if ((packet[packet_offset] & 0x80) == 0) { opusBandwidth = (((packet[packet_offset] & 0x60) != 96) ? ((OpusBandwidth)(1101 + ((packet[packet_offset] >> 5) & 3))) : (((packet[packet_offset] & 0x10u) != 0) ? OpusBandwidth.OPUS_BANDWIDTH_FULLBAND : OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND)); } else { opusBandwidth = (OpusBandwidth)(1102 + ((packet[packet_offset] >> 5) & 3)); if (opusBandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { opusBandwidth = OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND; } } return opusBandwidth; } public static int GetNumEncodedChannels(byte[] packet, int packet_offset) { return ((packet[packet_offset] & 4) == 0) ? 1 : 2; } public static int GetNumFrames(byte[] packet, int packet_offset, int len) { if (len < 1) { return -1; } switch (packet[packet_offset] & 3) { case 0: return 1; default: return 2; case 3: if (len < 2) { return -4; } return packet[packet_offset + 1] & 0x3F; } } public static int GetNumSamples(byte[] packet, int packet_offset, int len, int Fs) { int numFrames = GetNumFrames(packet, packet_offset, len); if (numFrames < 0) { return numFrames; } int num = numFrames * GetNumSamplesPerFrame(packet, packet_offset, Fs); if (num * 25 > Fs * 3) { return -4; } return num; } public static int GetNumSamples(OpusDecoder dec, byte[] packet, int packet_offset, int len) { return GetNumSamples(packet, packet_offset, len, dec.Fs); } public static OpusMode GetEncoderMode(byte[] packet, int packet_offset) { if ((packet[packet_offset] & 0x80u) != 0) { return OpusMode.MODE_CELT_ONLY; } if ((packet[packet_offset] & 0x60) == 96) { return OpusMode.MODE_HYBRID; } return OpusMode.MODE_SILK_ONLY; } internal static int encode_size(int size, byte[] data, int data_ptr) { if (size < 252) { data[data_ptr] = (byte)size; return 1; } data[data_ptr] = (byte)(252 + (size & 3)); data[data_ptr + 1] = (byte)(size - data[data_ptr] >> 2); return 2; } internal static int parse_size(byte[] data, int data_ptr, int len, BoxedValue size) { if (len < 1) { size.Val = -1; return -1; } if (data[data_ptr] < 252) { size.Val = data[data_ptr]; return 1; } if (len < 2) { size.Val = -1; return -1; } size.Val = (short)(4 * data[data_ptr + 1] + data[data_ptr]); return 2; } internal static int opus_packet_parse_impl(byte[] data, int data_ptr, int len, int self_delimited, out byte out_toc, byte[][] frames, int[] frames_ptrs, int frames_ptr, short[] sizes, int sizes_ptr, out int payload_offset, out int packet_offset) { int num = 0; int num2 = data_ptr; out_toc = 0; payload_offset = 0; packet_offset = 0; if (sizes == null || len < 0) { return -1; } if (len == 0) { return -4; } int numSamplesPerFrame = GetNumSamplesPerFrame(data, data_ptr, 48000); int num3 = 0; byte b = data[data_ptr++]; len--; int num4 = len; int num5; switch (b & 3) { case 0: num5 = 1; break; case 1: num5 = 2; num3 = 1; if (self_delimited == 0) { if (((uint)len & (true ? 1u : 0u)) != 0) { return -4; } num4 = len / 2; sizes[sizes_ptr] = (short)num4; } break; case 2: { num5 = 2; BoxedValue boxedValue = new BoxedValue(sizes[sizes_ptr]); int num8 = parse_size(data, data_ptr, len, boxedValue); sizes[sizes_ptr] = boxedValue.Val; len -= num8; if (sizes[sizes_ptr] < 0 || sizes[sizes_ptr] > len) { return -4; } data_ptr += num8; num4 = len - sizes[sizes_ptr]; break; } default: { if (len < 1) { return -4; } byte b2 = data[data_ptr++]; num5 = b2 & 0x3F; if (num5 <= 0 || numSamplesPerFrame * num5 > 5760) { return -4; } len--; if ((b2 & 0x40u) != 0) { int num6; do { if (len <= 0) { return -4; } num6 = data[data_ptr++]; len--; int num7 = ((num6 == 255) ? 254 : num6); len -= num7; num += num7; } while (num6 == 255); } if (len < 0) { return -4; } num3 = (((b2 & 0x80) == 0) ? 1 : 0); if (num3 == 0) { num4 = len; for (int i = 0; i < num5 - 1; i++) { BoxedValue boxedValue = new BoxedValue(sizes[sizes_ptr + i]); int num8 = parse_size(data, data_ptr, len, boxedValue); sizes[sizes_ptr + i] = boxedValue.Val; len -= num8; if (sizes[sizes_ptr + i] < 0 || sizes[sizes_ptr + i] > len) { return -4; } data_ptr += num8; num4 -= num8 + sizes[sizes_ptr + i]; } if (num4 < 0) { return -4; } } else if (self_delimited == 0) { num4 = len / num5; if (num4 * num5 != len) { return -4; } for (int i = 0; i < num5 - 1; i++) { sizes[sizes_ptr + i] = (short)num4; } } break; } } if (self_delimited != 0) { BoxedValue boxedValue = new BoxedValue(sizes[sizes_ptr + num5 - 1]); int num8 = parse_size(data, data_ptr, len, boxedValue); sizes[sizes_ptr + num5 - 1] = boxedValue.Val; len -= num8; if (sizes[sizes_ptr + num5 - 1] < 0 || sizes[sizes_ptr + num5 - 1] > len) { return -4; } data_ptr += num8; if (num3 != 0) { if (sizes[sizes_ptr + num5 - 1] * num5 > len) { return -4; } for (int i = 0; i < num5 - 1; i++) { sizes[sizes_ptr + i] = sizes[sizes_ptr + num5 - 1]; } } else if (num8 + sizes[sizes_ptr + num5 - 1] > num4) { return -4; } } else { if (num4 > 1275) { return -4; } sizes[sizes_ptr + num5 - 1] = (short)num4; } payload_offset = data_ptr - num2; for (int i = 0; i < num5; i++) { if (frames != null) { frames[frames_ptr + i] = data; } if (frames_ptrs != null) { frames_ptrs[frames_ptr + i] = data_ptr; } data_ptr += sizes[sizes_ptr + i]; } packet_offset = num + (data_ptr - num2); out_toc = b; return num5; } } public class OpusRepacketizer { internal byte toc = 0; internal int nb_frames = 0; internal readonly byte[][] frames = new byte[48][]; internal readonly int[] frames_ptrs = new int[48]; internal readonly short[] len = new short[48]; internal int framesize = 0; public void Reset() { nb_frames = 0; } public OpusRepacketizer() { Reset(); } internal int opus_repacketizer_cat_impl(byte[] data, int data_ptr, int len, int self_delimited) { if (len < 1) { return -4; } if (nb_frames == 0) { toc = data[data_ptr]; framesize = OpusPacketInfo.GetNumSamplesPerFrame(data, data_ptr, 8000); } else if ((toc & 0xFC) != (data[data_ptr] & 0xFC)) { return -4; } int numFrames = OpusPacketInfo.GetNumFrames(data, data_ptr, len); if (numFrames < 1) { return -4; } if ((numFrames + nb_frames) * framesize > 960) { return -4; } byte out_toc; int payload_offset; int num = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, self_delimited, out out_toc, frames, frames_ptrs, nb_frames, this.len, nb_frames, out payload_offset, out payload_offset); if (num < 1) { return num; } nb_frames += numFrames; return 0; } public int AddPacket(byte[] data, int data_offset, int len) { return opus_repacketizer_cat_impl(data, data_offset, len, 0); } public int GetNumFrames() { return nb_frames; } internal int opus_repacketizer_out_range_impl(int begin, int end, byte[] data, int data_ptr, int maxlen, int self_delimited, int pad) { if (begin < 0 || begin >= end || end > nb_frames) { return -1; } int num = end - begin; int num2 = ((self_delimited != 0) ? (1 + ((len[num - 1] >= 252) ? 1 : 0)) : 0); int num3 = data_ptr; switch (num) { case 1: num2 += len[0] + 1; if (num2 > maxlen) { return -2; } data[num3++] = (byte)(toc & 0xFCu); break; case 2: if (len[1] == len[0]) { num2 += 2 * len[0] + 1; if (num2 > maxlen) { return -2; } data[num3++] = (byte)((toc & 0xFCu) | 1u); break; } num2 += len[0] + len[1] + 2 + ((len[0] >= 252) ? 1 : 0); if (num2 > maxlen) { return -2; } data[num3++] = (byte)((toc & 0xFCu) | 2u); num3 += OpusPacketInfo.encode_size(len[0], data, num3); break; } if (num > 2 || (pad != 0 && num2 < maxlen)) { int num4 = 0; num3 = data_ptr; num2 = ((self_delimited != 0) ? (1 + ((len[num - 1] >= 252) ? 1 : 0)) : 0); int num5 = 0; for (int i = 1; i < num; i++) { if (len[i] != len[0]) { num5 = 1; break; } } if (num5 != 0) { num2 += 2; for (int i = 0; i < num - 1; i++) { num2 += 1 + ((len[i] >= 252) ? 1 : 0) + len[i]; } num2 += len[num - 1]; if (num2 > maxlen) { return -2; } data[num3++] = (byte)((toc & 0xFCu) | 3u); data[num3++] = (byte)((uint)num | 0x80u); } else { num2 += num * len[0] + 2; if (num2 > maxlen) { return -2; } data[num3++] = (byte)((toc & 0xFCu) | 3u); data[num3++] = (byte)num; } num4 = ((pad != 0) ? (maxlen - num2) : 0); if (num4 != 0) { data[data_ptr + 1] |= 64; int num6 = (num4 - 1) / 255; for (int i = 0; i < num6; i++) { data[num3++] = byte.MaxValue; } data[num3++] = (byte)(num4 - 255 * num6 - 1); num2 += num4; } if (num5 != 0) { for (int i = 0; i < num - 1; i++) { num3 += OpusPacketInfo.encode_size(len[i], data, num3); } } } if (self_delimited != 0) { int num7 = OpusPacketInfo.encode_size(len[num - 1], data, num3); num3 += num7; } for (int i = begin; i < num + begin; i++) { if (frames[i] == data) { Arrays.MemMove(data, frames_ptrs[i], num3, len[i]); } else { Array.Copy(frames[i], frames_ptrs[i], data, num3, len[i]); } num3 += len[i]; } if (pad != 0) { while (num3 < data_ptr + maxlen) { data[num3++] = 0; } } return num2; } public int CreatePacket(int begin, int end, byte[] data, int data_offset, int maxlen) { return opus_repacketizer_out_range_impl(begin, end, data, data_offset, maxlen, 0, 0); } public int CreatePacket(byte[] data, int data_offset, int maxlen) { return opus_repacketizer_out_range_impl(0, nb_frames, data, data_offset, maxlen, 0, 0); } public static int PadPacket(byte[] data, int data_offset, int len, int new_len) { OpusRepacketizer opusRepacketizer = new OpusRepacketizer(); if (len < 1) { return -1; } if (len == new_len) { return 0; } if (len > new_len) { return -1; } opusRepacketizer.Reset(); Arrays.MemMove(data, data_offset, data_offset + new_len - len, len); opusRepacketizer.AddPacket(data, data_offset + new_len - len, len); int num = opusRepacketizer.opus_repacketizer_out_range_impl(0, opusRepacketizer.nb_frames, data, data_offset, new_len, 0, 1); if (num > 0) { return 0; } return num; } public static int UnpadPacket(byte[] data, int data_offset, int len) { if (len < 1) { return -1; } OpusRepacketizer opusRepacketizer = new OpusRepacketizer(); opusRepacketizer.Reset(); int num = opusRepacketizer.AddPacket(data, data_offset, len); if (num < 0) { return num; } return opusRepacketizer.opus_repacketizer_out_range_impl(0, opusRepacketizer.nb_frames, data, data_offset, len, 0, 0); } public static int PadMultistreamPacket(byte[] data, int data_offset, int len, int new_len, int nb_streams) { short[] sizes = new short[48]; if (len < 1) { return -1; } if (len == new_len) { return 0; } if (len > new_len) { return -1; } int num = new_len - len; for (int i = 0; i < nb_streams - 1; i++) { if (len <= 0) { return -4; } byte out_toc; int payload_offset; int packet_offset; int num2 = OpusPacketInfo.opus_packet_parse_impl(data, data_offset, len, 1, out out_toc, null, null, 0, sizes, 0, out payload_offset, out packet_offset); if (num2 < 0) { return num2; } data_offset += packet_offset; len -= packet_offset; } return PadPacket(data, data_offset, len, len + num); } public static int UnpadMultistreamPacket(byte[] data, int data_offset, int len, int nb_streams) { short[] sizes = new short[48]; OpusRepacketizer opusRepacketizer = new OpusRepacketizer(); if (len < 1) { return -1; } int num = data_offset; int num2 = 0; for (int i = 0; i < nb_streams; i++) { int self_delimited = ((i != nb_streams) ? 1 : 0) - 1; if (len <= 0) { return -4; } opusRepacketizer.Reset(); int num3 = OpusPacketInfo.opus_packet_parse_impl(data, data_offset, len, self_delimited, out var _, null, null, 0, sizes, 0, out var _, out var packet_offset); if (num3 < 0) { return num3; } num3 = opusRepacketizer.opus_repacketizer_cat_impl(data, data_offset, packet_offset, self_delimited); if (num3 < 0) { return num3; } num3 = opusRepacketizer.opus_repacketizer_out_range_impl(0, opusRepacketizer.nb_frames, data, num, len, self_delimited, 0); if (num3 < 0) { return num3; } num2 += num3; num += num3; data_offset += packet_offset; len -= packet_offset; } return num2; } } internal class StereoWidthState { internal int XX; internal int XY; internal int YY; internal int smoothed_width; internal int max_follower; internal void Reset() { XX = 0; XY = 0; YY = 0; smoothed_width = 0; max_follower = 0; } } internal class TonalityAnalysisState { internal bool enabled = false; internal readonly float[] angle = new float[240]; internal readonly float[] d_angle = new float[240]; internal readonly float[] d2_angle = new float[240]; internal readonly int[] inmem = new int[720]; internal int mem_fill; internal readonly float[] prev_band_tonality = new float[18]; internal float prev_tonality; internal readonly float[][] E = Arrays.InitTwoDimensionalArray(8, 18); internal readonly float[] lowE = new float[18]; internal readonly float[] highE = new float[18]; internal readonly float[] meanE = new float[21]; internal readonly float[] mem = new float[32]; internal readonly float[] cmean = new float[8]; internal readonly float[] std = new float[9]; internal float music_prob; internal float Etracker; internal float lowECount; internal int E_count; internal int last_music; internal int last_transition; internal int count; internal readonly float[] subframe_mem = new float[3]; internal int analysis_offset; internal readonly float[] pspeech = new float[200]; internal readonly float[] pmusic = new float[200]; internal float speech_confidence; internal float music_confidence; internal int speech_confidence_count; internal int music_confidence_count; internal int write_pos; internal int read_pos; internal int read_subframe; internal readonly AnalysisInfo[] info = new AnalysisInfo[200]; internal TonalityAnalysisState() { for (int i = 0; i < 200; i++) { info[i] = new AnalysisInfo(); } } internal void Reset() { Arrays.MemSet(angle, 0f, 240); Arrays.MemSet(d_angle, 0f, 240); Arrays.MemSet(d2_angle, 0f, 240); Arrays.MemSet(inmem, 0, 720); mem_fill = 0; Arrays.MemSet(prev_band_tonality, 0f, 18); prev_tonality = 0f; for (int i = 0; i < 8; i++) { Arrays.MemSet(E[i], 0f, 18); } Arrays.MemSet(lowE, 0f, 18); Arrays.MemSet(highE, 0f, 18); Arrays.MemSet(meanE, 0f, 21); Arrays.MemSet(mem, 0f, 32); Arrays.MemSet(cmean, 0f, 8); Arrays.MemSet(std, 0f, 9); music_prob = 0f; Etracker = 0f; lowECount = 0f; E_count = 0; last_music = 0; last_transition = 0; count = 0; Arrays.MemSet(subframe_mem, 0f, 3); analysis_offset = 0; Arrays.MemSet(pspeech, 0f, 200); Arrays.MemSet(pmusic, 0f, 200); speech_confidence = 0f; music_confidence = 0f; speech_confidence_count = 0; music_confidence_count = 0; write_pos = 0; read_pos = 0; read_subframe = 0; for (int i = 0; i < 200; i++) { info[i].Reset(); } } } internal class VorbisLayout { internal int nb_streams; internal int nb_coupled_streams; internal byte[] mapping; internal static readonly VorbisLayout[] vorbis_mappings; internal VorbisLayout(int streams, int coupled_streams, byte[] map) { nb_streams = streams; nb_coupled_streams = coupled_streams; mapping = map; } static VorbisLayout() { VorbisLayout[] array = new VorbisLayout[8]; byte[] map = new byte[1]; array[0] = new VorbisLayout(1, 0, map); array[1] = new VorbisLayout(1, 1, new byte[2] { 0, 1 }); array[2] = new VorbisLayout(2, 1, new byte[3] { 0, 2, 1 }); array[3] = new VorbisLayout(2, 2, new byte[4] { 0, 1, 2, 3 }); array[4] = new VorbisLayout(3, 2, new byte[5] { 0, 4, 1, 2, 3 }); array[5] = new VorbisLayout(4, 2, new byte[6] { 0, 4, 1, 2, 3, 5 }); array[6] = new VorbisLayout(4, 3, new byte[7] { 0, 4, 1, 2, 3, 5, 6 }); array[7] = new VorbisLayout(5, 3, new byte[8] { 0, 6, 1, 2, 3, 4, 5, 7 }); vorbis_mappings = array; } } } namespace Concentus.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(BoxedValue res_nrg, BoxedValue 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.MemSet(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); } } } Array.Copy(array, array2, 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(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, 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.MemMove(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); Array.Copy(sCNG.CNG_synth_state, array2, 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)); } Array.Copy(array2, length, sCNG.CNG_synth_state, 0, 16); } else { Arrays.MemSet(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, 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(silk_enc_map(pulses[i]), array, 8u); } } } num += 16; } } internal static void silk_decode_signs(EntropyCoder psRangeDec, 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(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, BoxedValue 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, int lostFlag, int newPacketFlag, EntropyCoder psRangeDec, short[] samplesOut, int samplesOut_ptr, out int nSamplesOut) { int num = 0; int num2 = SilkError.SILK_NO_ERROR; BoxedValue boxedValue = new BoxedValue(0); int[] array = new int[2]; int[] array2 = new int[2]; int[] array3 = array2; 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.MemSet(psDec.sStereo.pred_prev_Q13, (short)0, 2); Arrays.MemSet(psDec.sStereo.sSide, (short)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(1u); } channel_state[i].LBRR_flag = psRangeDec.dec_bit_logp(1u); } for (int i = 0; i < decControl.nChannelsInternal; i++) { Arrays.MemSet(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(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, array3); if (channel_state[1].LBRR_flags[j] == 0) { BoxedValue boxedValue2 = new BoxedValue(num); Stereo.silk_stereo_decode_mid_only(psRangeDec, boxedValue2); num = boxedValue2.Val; } } DecodeIndices.silk_decode_indices(condCoding: (j > 0 && channel_state[i].LBRR_flags[j - 1] != 0) ? 2 : 0, psDec: channel_state[i], psRangeDec: psRangeDec, FrameIndex: j, decode_LBRR: 1); DecodePulses.silk_decode_pulses(psRangeDec, 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, array3); 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)) { BoxedValue boxedValue2 = new BoxedValue(num); Stereo.silk_stereo_decode_mid_only(psRangeDec, boxedValue2); num = boxedValue2.Val; } else { num = 0; } } else { for (int i = 0; i < 2; i++) { array3[i] = psDec.sStereo.pred_prev_Q13[i]; } } } if (decControl.nChannelsInternal == 2 && num == 0 && psDec.prev_decode_only_middle == 1) { Arrays.MemSet(psDec.channel_state[1].outBuf, (short)0, 480); Arrays.MemSet(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); short[] array4; if (num5 != 0) { array4 = samplesOut; array[0] = samplesOut_ptr; array[1] = samplesOut_ptr + channel_state[0].frame_length + 2; } else { short[] array5 = new short[decControl.nChannelsInternal * (channel_state[0].frame_length + 2)]; array4 = array5; 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 condCoding2 = ((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, array4, array[i] + 2, boxedValue, lostFlag, condCoding2); } else { Arrays.MemSetWithOffset(array4, (short)0, array[i] + 2, boxedValue.Val); } channel_state[i].nFramesDecoded++; } if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 2) { Stereo.silk_stereo_MS_to_LR(psDec.sStereo, array4, array[0], array4, array[1], array3, channel_state[0].fs_kHz, boxedValue.Val); } else { Array.Copy(psDec.sStereo.sMid, 0, array4, array[0], 2); Array.Copy(array4, array[0] + boxedValue.Val, psDec.sStereo.sMid, 0, 2); } nSamplesOut = Inlines.silk_DIV32(boxedValue.Val * decControl.API_sampleRate, Inlines.silk_SMULBB(channel_state[0].fs_kHz, 1000)); short[] array7; int num8; if (decControl.nChannelsAPI == 2) { short[] array6 = new short[nSamplesOut]; array7 = array6; num8 = 0; } else { array7 = samplesOut; num8 = samplesOut_ptr; } if (num5 != 0) { short[] array8 = new short[decControl.nChannelsInternal * (channel_state[0].frame_length + 2)]; Array.Copy(samplesOut, samplesOut_ptr, array8, 0, decControl.nChannelsInternal * (channel_state[0].frame_length + 2)); array4 = array8; 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, array7, num8, array4, array[i] + 1, boxedValue.Val); if (decControl.nChannelsAPI == 2) { int num9 = samplesOut_ptr + i; for (int j = 0; j < nSamplesOut; j++) { samplesOut[num9 + 2 * j] = array7[num8 + j]; } } } if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 1) { if (num3 != 0) { num2 += Resampler.silk_resampler(channel_state[1].resampler_state, array7, num8, array4, array[0] + 1, boxedValue.Val); for (int j = 0; j < nSamplesOut; j++) { samplesOut[samplesOut_ptr + 1 + 2 * j] = array7[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[] array9 = new int[3] { 6, 4, 3 }; decControl.prevPitchLag = channel_state[0].lagPrev * array9[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, 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]); } Array.Copy(psDec.sLPC_Q14_buf, array4, 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) { Array.Copy(xq, xq_ptr, psDec.outBuf, psDec.ltp_mem_length, 2 * psDec.subfr_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)); } Array.Copy(array4, psDec.subfr_length, array4, 0, 16); num4 += psDec.subfr_length; num5 += psDec.subfr_length; } Array.Copy(array4, 0, psDec.sLPC_Q14_buf, 0, 16); } } internal static class DecodeIndices { internal static void silk_decode_indices(SilkChannelDecoder psDec, EntropyCoder psRangeDec, int FrameIndex, int decode_LBRR, int condCoding) { short[] array = new short[psDec.LPC_order]; byte[] pred_Q = new byte[psDec.LPC_order]; int num = ((decode_LBRR == 0 && psDec.VAD_flags[FrameIndex] == 0) ? psRangeDec.dec_icdf(Tables.silk_type_offset_no_VAD_iCDF, 8u) : (psRangeDec.dec_icdf(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(Tables.silk_delta_gain_iCDF, 8u); } else { psDec.indices.GainsIndices[0] = (sbyte)Inlines.silk_LSHIFT(psRangeDec.dec_icdf(Tables.silk_gain_iCDF[psDec.indices.signalType], 8u), 3); psDec.indices.GainsIndices[0] += (sbyte)psRangeDec.dec_icdf(Tables.silk_uniform8_iCDF, 8u); } for (int i = 1; i < psDec.nb_subfr; i++) { psDec.indices.GainsIndices[i] = (sbyte)psRangeDec.dec_icdf(Tables.silk_delta_gain_iCDF, 8u); } psDec.indices.NLSFIndices[0] = (sbyte)psRangeDec.dec_icdf(psDec.psNLSF_CB.CB1_iCDF, (psDec.indices.signalType >> 1) * psDec.psNLSF_CB.nVectors, 8u); NLSF.silk_NLSF_unpack(array, pred_Q, psDec.psNLSF_CB, psDec.indices.NLSFIndices[0]); for (int i = 0; i < psDec.psNLSF_CB.order; i++) { num = psRangeDec.dec_icdf(psDec.psNLSF_CB.ec_iCDF, array[i], 8u); switch (num) { case 0: num -= psRangeDec.dec_icdf(Tables.silk_NLSF_EXT_iCDF, 8u); break; case 8: num += psRangeDec.dec_icdf(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(Tables.silk_NLSF_interpolation_factor_iCDF, 8u); } else { psDec.indices.NLSFInterpCoef_Q2 = 4; } if (psDec.indices.signalType == 2) { int num2 = 1; if (condCoding == 2 && psDec.ec_prevSignalType == 2) { int num3 = (short)psRangeDec.dec_icdf(Tables.silk_pitch_delta_iCDF, 8u); if (num3 > 0) { num3 -= 9; psDec.indices.lagIndex = (short)(psDec.ec_prevLagIndex + num3); num2 = 0; } } if (num2 != 0) { psDec.indices.lagIndex = (short)(psRangeDec.dec_icdf(Tables.silk_pitch_lag_iCDF, 8u) * Inlines.silk_RSHIFT(psDec.fs_kHz, 1)); psDec.indices.lagIndex += (short)psRangeDec.dec_icdf(psDec.pitch_lag_low_bits_iCDF, 8u); } psDec.ec_prevLagIndex = psDec.indices.lagIndex; psDec.indices.contourIndex = (sbyte)psRangeDec.dec_icdf(psDec.pitch_contour_iCDF, 8u); psDec.indices.PERIndex = (sbyte)psRangeDec.dec_icdf(Tables.silk_LTP_per_index_iCDF, 8u); for (int j = 0; j < psDec.nb_subfr; j++) { psDec.indices.LTPIndex[j] = (sbyte)psRangeDec.dec_icdf(Tables.silk_LTP_gain_iCDF_ptrs[psDec.indices.PERIndex], 8u); } if (condCoding == 0) { psDec.indices.LTP_scaleIndex = (sbyte)psRangeDec.dec_icdf(Tables.silk_LTPscale_iCDF, 8u); } else { psDec.indices.LTP_scaleIndex = 0; } } psDec.ec_prevSignalType = psDec.indices.signalType; psDec.indices.Seed = (sbyte)psRangeDec.dec_icdf(Tables.silk_uniform4_iCDF, 8u); } } internal class DecodeParameters { internal static void silk_decode_parameters(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, int condCoding) { short[] array = new short[psDec.LPC_order]; short[] array2 = new short[psDec.LPC_order]; BoxedValue boxedValue = new BoxedValue(psDec.LastGainIndex); GainQuantization.silk_gains_dequant(psDecCtrl.Gains_Q16, psDec.indices.GainsIndices, boxedValue, (condCoding == 2) ? 1 : 0, psDec.nb_subfr); psDec.LastGainIndex = boxedValue.Val; NLSF.silk_NLSF_decode(array, psDec.indices.NLSFIndices, psDec.psNLSF_CB); NLSF.silk_NLSF2A(psDecCtrl.PredCoef_Q12[1], array, psDec.LPC_order); if (psDec.first_frame_after_reset == 1) { psDec.indices.NLSFInterpCoef_Q2 = 4; } if (psDec.indices.NLSFInterpCoef_Q2 < 4) { for (int i = 0; i < psDec.LPC_order; i++) { array2[i] = (short)(psDec.prevNLSF_Q15[i] + Inlines.silk_RSHIFT(Inlines.silk_MUL(psDec.indices.NLSFInterpCoef_Q2, array[i] - psDec.prevNLSF_Q15[i]), 2)); } NLSF.silk_NLSF2A(psDecCtrl.PredCoef_Q12[0], array2, psDec.LPC_order); } else { Array.Copy(psDecCtrl.PredCoef_Q12[1], psDecCtrl.PredCoef_Q12[0], psDec.LPC_order); } Array.Copy(array, psDec.prevNLSF_Q15, psDec.LPC_order); if (psDec.lossCnt != 0) { BWExpander.silk_bwexpander(psDecCtrl.PredCoef_Q12[0], psDec.LPC_order, 63570); BWExpander.silk_bwexpander(psDecCtrl.PredCoef_Q12[1], psDec.LPC_order, 63570); } if (psDec.indices.signalType == 2) { DecodePitch.silk_decode_pitch(psDec.indices.lagIndex, psDec.indices.contourIndex, psDecCtrl.pitchL, psDec.fs_kHz, psDec.nb_subfr); sbyte[][] array3 = Tables.silk_LTP_vq_ptrs_Q7[psDec.indices.PERIndex]; int num; for (int j = 0; j < psDec.nb_subfr; j++) { num = psDec.indices.LTPIndex[j]; for (int i = 0; i < 5; i++) { psDecCtrl.LTPCoef_Q14[j * 5 + i] = (short)Inlines.silk_LSHIFT(array3[num][i], 7); } } num = psDec.indices.LTP_scaleIndex; psDecCtrl.LTP_scale_Q14 = Tables.silk_LTPScales_table_Q14[num]; } else { Arrays.MemSet(psDecCtrl.pitchL, 0, psDec.nb_subfr); Arrays.MemSet(psDecCtrl.LTPCoef_Q14, (short)0, 5 * psDec.nb_subfr); psDec.indices.PERIndex = 0; psDecCtrl.LTP_scale_Q14 = 0; } } } internal static class DecodePitch { internal static void silk_decode_pitch(short lagIndex, sbyte contourIndex, int[] pitch_lags, int Fs_kHz, int nb_subfr) { sbyte[][] array = ((Fs_kHz == 8) ? ((nb_subfr != 4) ? Tables.silk_CB_lags_stage2_10_ms : Tables.silk_CB_lags_stage2) : ((nb_subfr != 4) ? Tables.silk_CB_lags_stage3_10_ms : Tables.silk_CB_lags_stage3)); int num = Inlines.silk_SMULBB(2, Fs_kHz); int limit = Inlines.silk_SMULBB(18, Fs_kHz); int num2 = num + lagIndex; for (int i = 0; i < nb_subfr; i++) { pitch_lags[i] = num2 + array[i][contourIndex]; pitch_lags[i] = Inlines.silk_LIMIT(pitch_lags[i], num, limit); } } } internal static class DecodePulses { internal static void silk_decode_pulses(EntropyCoder psRangeDec, short[] pulses, int signalType, int quantOffsetType, int frame_length) { int[] array = new int[20]; int[] array2 = new int[20]; int num = psRangeDec.dec_icdf(Tables.silk_rate_levels_iCDF[signalType >> 1], 8u); int num2 = Inlines.silk_RSHIFT(frame_length, 4); if (num2 * 16 < frame_length) { num2++; } for (int i = 0; i < num2; i++) { array2[i] = 0; array[i] = psRangeDec.dec_icdf(Tables.silk_pulses_per_block_iCDF[num], 8u); while (array[i] == 17) { array2[i]++; array[i] = psRangeDec.dec_icdf(Tables.silk_pulses_per_block_iCDF[9], (array2[i] == 10) ? 1 : 0, 8u); } } for (int i = 0; i < num2; i++) { if (array[i] > 0) { ShellCoder.silk_shell_decoder(pulses, Inlines.silk_SMULBB(i, 16), psRangeDec, array[i]); } else { Arrays.MemSetWithOffset(pulses, (short)0, Inlines.silk_SMULBB(i, 16), 16); } } for (int i = 0; i < num2; i++) { if (array2[i] <= 0) { continue; } int num3 = array2[i]; int num4 = Inlines.silk_SMULBB(i, 16); for (int j = 0; j < 16; j++) { int num5 = pulses[num4 + j]; for (int k = 0; k < num3; k++) { num5 = Inlines.silk_LSHIFT(num5, 1); num5 += psRangeDec.dec_icdf(Tables.silk_lsb_iCDF, 8u); } pulses[num4 + j] = (short)num5; } array[i] |= num3 << 5; } CodeSigns.silk_decode_signs(psRangeDec, pulses, frame_length, signalType, quantOffsetType, array); } } internal static class EncodeAPI { internal static int silk_InitEncoder(SilkEncoder encState, EncControlState encStatus) { int num = SilkError.SILK_NO_ERROR; encState.Reset(); for (int i = 0; i < 2; i++) { num += SilkEncoder.silk_init_encoder(encState.state_Fxx[i]); } encState.nChannelsAPI = 1; encState.nChannelsInternal = 1; return num + silk_QueryEncoder(encState, encStatus); } internal static int silk_QueryEncoder(SilkEncoder encState, EncControlState encStatus) { int sILK_NO_ERROR = SilkError.SILK_NO_ERROR; SilkChannelEncoder silkChannelEncoder = encState.state_Fxx[0]; encStatus.Reset(); encStatus.nChannelsAPI = encState.nChannelsAPI; encStatus.nChannelsInternal = encState.nChannelsInternal; encStatus.API_sampleRate = silkChannelEncoder.API_fs_Hz; encStatus.maxInternalSampleRate = silkChannelEncoder.maxInternal_fs_Hz; encStatus.minInternalSampleRate = silkChannelEncoder.minInternal_fs_Hz; encStatus.desiredInternalSampleRate = silkChannelEncoder.desiredInternal_fs_Hz; encStatus.payloadSize_ms = silkChannelEncoder.PacketSize_ms; encStatus.bitRate = silkChannelEncoder.TargetRate_bps; encStatus.packetLossPercentage = silkChannelEncoder.PacketLoss_perc; encStatus.complexity = silkChannelEncoder.Complexity; encStatus.useInBandFEC = silkChannelEncoder.useInBandFEC; encStatus.useDTX = silkChannelEncoder.useDTX; encStatus.useCBR = silkChannelEncoder.useCBR; encStatus.internalSampleRate = Inlines.silk_SMULBB(silkChannelEncoder.fs_kHz, 1000); encStatus.allowBandwidthSwitch = silkChannelEncoder.allow_bandwidth_switch; encStatus.inWBmodeWithoutVariableLP = ((silkChannelEncoder.fs_kHz == 16 && silkChannelEncoder.sLP.mode == 0) ? 1 : 0); return sILK_NO_ERROR; } internal static int silk_Encode(SilkEncoder psEnc, EncControlState encControl, short[] samplesIn, int nSamplesIn, EntropyCoder psRangeEnc, BoxedValue nBytesOut, int prefillFlag) { int sILK_NO_ERROR = SilkError.SILK_NO_ERROR; int payloadSize_ms = 0; int complexity = 0; int num = 0; int[] array = new int[2]; nBytesOut.Val = 0; if (encControl.reducedDependency != 0) { psEnc.state_Fxx[0].first_frame_after_reset = 1; psEnc.state_Fxx[1].first_frame_after_reset = 1; } psEnc.state_Fxx[0].nFramesEncoded = (psEnc.state_Fxx[1].nFramesEncoded = 0); sILK_NO_ERROR += encControl.check_control_input(); if (sILK_NO_ERROR != SilkError.SILK_NO_ERROR) { return sILK_NO_ERROR; } encControl.switchReady = 0; if (encControl.nChannelsInternal > psEnc.nChannelsInternal) { sILK_NO_ERROR += SilkEncoder.silk_init_encoder(psEnc.state_Fxx[1]); Arrays.MemSet(psEnc.sStereo.pred_prev_Q13, (short)0, 2); Arrays.MemSet(psEnc.sStereo.sSide, (short)0, 2); psEnc.sStereo.mid_side_amp_Q0[0] = 0; psEnc.sStereo.mid_side_amp_Q0[1] = 1; psEnc.sStereo.mid_side_amp_Q0[2] = 0; psEnc.sStereo.mid_side_amp_Q0[3] = 1; psEnc.sStereo.width_prev_Q14 = 0; psEnc.sStereo.smth_width_Q14 = 16384; if (psEnc.nChannelsAPI == 2) { psEnc.state_Fxx[1].resampler_state.Assign(psEnc.state_Fxx[0].resampler_state); Array.Copy(psEnc.state_Fxx[0].In_HP_State, psEnc.state_Fxx[1].In_HP_State, 2); } } int num2 = ((encControl.payloadSize_ms != psEnc.state_Fxx[0].PacketSize_ms || psEnc.nChannelsInternal != encControl.nChannelsInternal) ? 1 : 0); psEnc.nChannelsAPI = encControl.nChannelsAPI; psEnc.nChannelsInternal = encControl.nChannelsInternal; int num3 = Inlines.silk_DIV32(100 * nSamplesIn, encControl.API_sampleRate); int num4 = ((num3 <= 1) ? 1 : (num3 >> 1)); int num5 = 0; if (prefillFlag != 0) { if (num3 != 1) { return SilkError.SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; } for (int i = 0; i < encControl.nChannelsInternal; i++) { sILK_NO_ERROR += SilkEncoder.silk_init_encoder(psEnc.state_Fxx[i]); } payloadSize_ms = encControl.payloadSize_ms; encControl.payloadSize_ms = 10; complexity = encControl.complexity; encControl.complexity = 0; for (int i = 0; i < encControl.nChannelsInternal; i++) { psEnc.state_Fxx[i].controlled_since_last_payload = 0; psEnc.state_Fxx[i].prefillFlag = 1; } } else { if (num3 * encControl.API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0) { return SilkError.SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; } if (1000 * nSamplesIn > encControl.payloadSize_ms * encControl.API_sampleRate) { return SilkError.SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; } } int targetRate_bps = Inlines.silk_RSHIFT32(encControl.bitRate, encControl.nChannelsInternal - 1); for (int i = 0; i < encControl.nChannelsInternal; i++) { int force_fs_kHz = ((i == 1) ? psEnc.state_Fxx[0].fs_kHz : 0); sILK_NO_ERROR += psEnc.state_Fxx[i].silk_control_encoder(encControl, targetRate_bps, psEnc.allowBandwidthSwitch, i, force_fs_kHz); if (sILK_NO_ERROR != SilkError.SILK_NO_ERROR) { return sILK_NO_ERROR; } if (psEnc.state_Fxx[i].first_frame_after_reset != 0 || num2 != 0) { for (int j = 0; j < psEnc.state_Fxx[0].nFramesPerPacket; j++) { psEnc.state_Fxx[i].LBRR_flags[j] = 0; } } psEnc.state_Fxx[i].inDTX = psEnc.state_Fxx[i].useDTX; } int num6 = 10 * num3 * psEnc.state_Fxx[0].fs_kHz; int num7 = Inlines.silk_DIV32_16(num6 * psEnc.state_Fxx[0].API_fs_Hz, (short)(psEnc.state_Fxx[0].fs_kHz * 1000)); short[] array2 = new short[num7]; int num8 = 0; while (true) { bool flag = true; int a = psEnc.state_Fxx[0].frame_length - psEnc.state_Fxx[0].inputBufIx; a = Inlines.silk_min(a, num6); num = Inlines.silk_DIV32_16(a * psEnc.state_Fxx[0].API_fs_Hz, psEnc.state_Fxx[0].fs_kHz * 1000); if (encControl.nChannelsAPI == 2 && encControl.nChannelsInternal == 2) { int nFramesEncoded = psEnc.state_Fxx[0].nFramesEncoded; for (int i = 0; i < num; i++) { array2[i] = samplesIn[num8 + 2 * i]; } if (psEnc.nPrevChannelsInternal == 1 && nFramesEncoded == 0) { psEnc.state_Fxx[1].resampler_state.Assign(psEnc.state_Fxx[0].resampler_state); } sILK_NO_ERROR += Resampler.silk_resampler(psEnc.state_Fxx[0].resampler_state, psEnc.state_Fxx[0].inputBuf, psEnc.state_Fxx[0].inputBufIx + 2, array2, 0, num); psEnc.state_Fxx[0].inputBufIx += a; a = psEnc.state_Fxx[1].frame_length - psEnc.state_Fxx[1].inputBufIx; a = Inlines.silk_min(a, 10 * num3 * psEnc.state_Fxx[1].fs_kHz); for (int i = 0; i < num; i++) { array2[i] = samplesIn[num8 + 2 * i + 1]; } sILK_NO_ERROR += Resampler.silk_resampler(psEnc.state_Fxx[1].resampler_state, psEnc.state_Fxx[1].inputBuf, psEnc.state_Fxx[1].inputBufIx + 2, array2, 0, num); psEnc.state_Fxx[1].inputBufIx += a; } else if (encControl.nChannelsAPI == 2 && encControl.nChannelsInternal == 1) { for (int i = 0; i < num; i++) { int a2 = samplesIn[num8 + 2 * i] + samplesIn[num8 + 2 * i + 1]; array2[i] = (short)Inlines.silk_RSHIFT_ROUND(a2, 1); } sILK_NO_ERROR += Resampler.silk_resampler(psEnc.state_Fxx[0].resampler_state, psEnc.state_Fxx[0].inputBuf, psEnc.state_Fxx[0].inputBufIx + 2, array2, 0, num); if (psEnc.nPrevChannelsInternal == 2 && psEnc.state_Fxx[0].nFramesEncoded == 0) { sILK_NO_ERROR += Resampler.silk_resampler(psEnc.state_Fxx[1].resampler_state, psEnc.state_Fxx[1].inputBuf, psEnc.state_Fxx[1].inputBufIx + 2, array2, 0, num); for (int i = 0; i < psEnc.state_Fxx[0].frame_length; i++) { psEnc.state_Fxx[0].inputBuf[psEnc.state_Fxx[0].inputBufIx + i + 2] = (short)Inlines.silk_RSHIFT(psEnc.state_Fxx[0].inputBuf[psEnc.state_Fxx[0].inputBufIx + i + 2] + psEnc.state_Fxx[1].inputBuf[psEnc.state_Fxx[1].inputBufIx + i + 2], 1); } } psEnc.state_Fxx[0].inputBufIx += a; } else { Array.Copy(samplesIn, num8, array2, 0, num); sILK_NO_ERROR += Resampler.silk_resampler(psEnc.state_Fxx[0].resampler_state, psEnc.state_Fxx[0].inputBuf, psEnc.state_Fxx[0].inputBufIx + 2, array2, 0, num); psEnc.state_Fxx[0].inputBufIx += a; } num8 += num * encControl.nChannelsAPI; nSamplesIn -= num; psEnc.allowBandwidthSwitch = 0; if (psEnc.state_Fxx[0].inputBufIx < psEnc.state_Fxx[0].frame_length) { break; } if (psEnc.state_Fxx[0].nFramesEncoded == 0 && prefillFlag == 0) { byte[] array3 = new byte[2]; byte[] array4 = array3; array4[0] = (byte)(256 - Inlines.silk_RSHIFT(256, (psEnc.state_Fxx[0].nFramesPerPacket + 1) * encControl.nChannelsInternal)); psRangeEnc.enc_icdf(0, array4, 8u); for (int i = 0; i < encControl.nChannelsInternal; i++) { int num9 = 0; for (int j = 0; j < psEnc.state_Fxx[i].nFramesPerPacket; j++) { num9 |= Inlines.silk_LSHIFT(psEnc.state_Fxx[i].LBRR_flags[j], j); } psEnc.state_Fxx[i].LBRR_flag = ((num9 > 0) ? ((sbyte)1) : ((sbyte)0)); if (num9 != 0 && psEnc.state_Fxx[i].nFramesPerPacket > 1) { psRangeEnc.enc_icdf(num9 - 1, Tables.silk_LBRR_flags_iCDF_ptr[psEnc.state_Fxx[i].nFramesPerPacket - 2], 8u); } } for (int j = 0; j < psEnc.state_Fxx[0].nFramesPerPacket; j++) { for (int i = 0; i < encControl.nChannelsInternal; i++) { if (psEnc.state_Fxx[i].LBRR_flags[j] == 0) { continue; } if (encControl.nChannelsInternal == 2 && i == 0) { Stereo.silk_stereo_encode_pred(psRangeEnc, psEnc.sStereo.predIx[j]); if (psEnc.state_Fxx[1].LBRR_flags[j] == 0) { Stereo.silk_stereo_encode_mid_only(psRangeEnc, psEnc.sStereo.mid_only_flags[j]); } } EncodeIndices.silk_encode_indices(condCoding: (j > 0 && psEnc.state_Fxx[i].LBRR_flags[j - 1] != 0) ? 2 : 0, psEncC: psEnc.state_Fxx[i], psRangeEnc: psRangeEnc, FrameIndex: j, encode_LBRR: 1); EncodePulses.silk_encode_pulses(psRangeEnc, psEnc.state_Fxx[i].indices_LBRR[j].signalType, psEnc.state_Fxx[i].indices_LBRR[j].quantOffsetType, psEnc.state_Fxx[i].pulses_LBRR[j], psEnc.state_Fxx[i].frame_length); } } for (int i = 0; i < encControl.nChannelsInternal; i++) { Arrays.MemSet(psEnc.state_Fxx[i].LBRR_flags, 0, 3); } psEnc.nBitsUsedLBRR = psRangeEnc.tell(); } HPVariableCutoff.silk_HP_variable_cutoff(psEnc.state_Fxx); int num10 = Inlines.silk_DIV32_16(Inlines.silk_MUL(encControl.bitRate, encControl.payloadSize_ms), 1000); if (prefillFlag == 0) { num10 -= psEnc.nBitsUsedLBRR; } num10 = Inlines.silk_DIV32_16(num10, psEnc.state_Fxx[0].nFramesPerPacket); targetRate_bps = ((encControl.payloadSize_ms != 10) ? Inlines.silk_SMULBB(num10, 50) : Inlines.silk_SMULBB(num10, 100)); targetRate_bps -= Inlines.silk_DIV32_16(Inlines.silk_MUL(psEnc.nBitsExceeded, 1000), 500); if (prefillFlag == 0 && psEnc.state_Fxx[0].nFramesEncoded > 0) { int a3 = psRangeEnc.tell() - psEnc.nBitsUsedLBRR - num10 * psEnc.state_Fxx[0].nFramesEncoded; targetRate_bps -= Inlines.silk_DIV32_16(Inlines.silk_MUL(a3, 1000), 500); } targetRate_bps = Inlines.silk_LIMIT(targetRate_bps, encControl.bitRate, 5000); if (encControl.nChannelsInternal == 2) { BoxedValue boxedValue = new BoxedValue(psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded]); Stereo.silk_stereo_LR_to_MS(psEnc.sStereo, psEnc.state_Fxx[0].inputBuf, 2, psEnc.state_Fxx[1].inputBuf, 2, psEnc.sStereo.predIx[psEnc.state_Fxx[0].nFramesEncoded], boxedValue, array, targetRate_bps, psEnc.state_Fxx[0].speech_activity_Q8, encControl.toMono, psEnc.state_Fxx[0].fs_kHz, psEnc.state_Fxx[0].frame_length); psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded] = boxedValue.Val; if (boxedValue.Val == 0) { if (psEnc.prev_decode_only_middle == 1) { psEnc.state_Fxx[1].sShape.Reset(); psEnc.state_Fxx[1].sPrefilt.Reset(); psEnc.state_Fxx[1].sNSQ.Reset(); Arrays.MemSet(psEnc.state_Fxx[1].prev_NLSFq_Q15, (short)0, 16); Arrays.MemSet(psEnc.state_Fxx[1].sLP.In_LP_State, 0, 2); psEnc.state_Fxx[1].prevLag = 100; psEnc.state_Fxx[1].sNSQ.lagPrev = 100; psEnc.state_Fxx[1].sShape.LastGainIndex = 10; psEnc.state_Fxx[1].prevSignalType = 0; psEnc.state_Fxx[1].sNSQ.prev_gain_Q16 = 65536; psEnc.state_Fxx[1].first_frame_after_reset = 1; } psEnc.state_Fxx[1].silk_encode_do_VAD(); } else { psEnc.state_Fxx[1].VAD_flags[psEnc.state_Fxx[0].nFramesEncoded] = 0; } if (prefillFlag == 0) { Stereo.silk_stereo_encode_pred(psRangeEnc, psEnc.sStereo.predIx[psEnc.state_Fxx[0].nFramesEncoded]); if (psEnc.state_Fxx[1].VAD_flags[psEnc.state_Fxx[0].nFramesEncoded] == 0) { Stereo.silk_stereo_encode_mid_only(psRangeEnc, psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded]); } } } else { Array.Copy(psEnc.sStereo.sMid, psEnc.state_Fxx[0].inputBuf, 2); Array.Copy(psEnc.state_Fxx[0].inputBuf, psEnc.state_Fxx[0].frame_length, psEnc.sStereo.sMid, 0, 2); } psEnc.state_Fxx[0].silk_encode_do_VAD(); for (int i = 0; i < encControl.nChannelsInternal; i++) { int num11 = encControl.maxBits; if (num4 == 2 && num5 == 0) { num11 = num11 * 3 / 5; } else if (num4 == 3) { switch (num5) { case 0: num11 = num11 * 2 / 5; break; case 1: num11 = num11 * 3 / 4; break; } } int useCBR = ((encControl.useCBR != 0 && num5 == num4 - 1) ? 1 : 0); int num12; if (encControl.nChannelsInternal == 1) { num12 = targetRate_bps; } else { num12 = array[i]; if (i == 0 && array[1] > 0) { useCBR = 0; num11 -= encControl.maxBits / (num4 * 2); } } if (num12 > 0) { psEnc.state_Fxx[i].silk_control_SNR(num12); int condCoding2 = ((psEnc.state_Fxx[0].nFramesEncoded - i > 0) ? ((i > 0 && psEnc.prev_decode_only_middle != 0) ? 1 : 2) : 0); sILK_NO_ERROR += psEnc.state_Fxx[i].silk_encode_frame(nBytesOut, psRangeEnc, condCoding2, num11, useCBR); } psEnc.state_Fxx[i].controlled_since_last_payload = 0; psEnc.state_Fxx[i].inputBufIx = 0; psEnc.state_Fxx[i].nFramesEncoded++; } psEnc.prev_decode_only_middle = psEnc.sStereo.mid_only_flags[psEnc.state_Fxx[0].nFramesEncoded - 1]; if (nBytesOut.Val > 0 && psEnc.state_Fxx[0].nFramesEncoded == psEnc.state_Fxx[0].nFramesPerPacket) { int num13 = 0; for (int i = 0; i < encControl.nChannelsInternal; i++) { for (int j = 0; j < psEnc.state_Fxx[i].nFramesPerPacket; j++) { num13 = Inlines.silk_LSHIFT(num13, 1); num13 |= psEnc.state_Fxx[i].VAD_flags[j]; } num13 = Inlines.silk_LSHIFT(num13, 1); num13 |= psEnc.state_Fxx[i].LBRR_flag; } if (prefillFlag == 0) { psRangeEnc.enc_patch_initial_bits((uint)num13, (uint)((psEnc.state_Fxx[0].nFramesPerPacket + 1) * encControl.nChannelsInternal)); } if (psEnc.state_Fxx[0].inDTX != 0 && (encControl.nChannelsInternal == 1 || psEnc.state_Fxx[1].inDTX != 0)) { nBytesOut.Val = 0; } psEnc.nBitsExceeded += nBytesOut.Val * 8; psEnc.nBitsExceeded -= Inlines.silk_DIV32_16(Inlines.silk_MUL(encControl.bitRate, encControl.payloadSize_ms), 1000); psEnc.nBitsExceeded = Inlines.silk_LIMIT(psEnc.nBitsExceeded, 0, 10000); int num14 = Inlines.silk_SMLAWB(13, 3188, psEnc.timeSinceSwitchAllowed_ms); if (psEnc.state_Fxx[0].speech_activity_Q8 < num14) { psEnc.allowBandwidthSwitch = 1; psEnc.timeSinceSwitchAllowed_ms = 0; } else { psEnc.allowBandwidthSwitch = 0; psEnc.timeSinceSwitchAllowed_ms += encControl.payloadSize_ms; } } if (nSamplesIn == 0) { break; } num5++; } psEnc.nPrevChannelsInternal = encControl.nChannelsInternal; encControl.allowBandwidthSwitch = psEnc.allowBandwidthSwitch; encControl.inWBmodeWithoutVariableLP = ((psEnc.state_Fxx[0].fs_kHz == 16 && psEnc.state_Fxx[0].sLP.mode == 0) ? 1 : 0); encControl.internalSampleRate = Inlines.silk_SMULBB(psEnc.state_Fxx[0].fs_kHz, 1000); encControl.stereoWidth_Q14 = ((encControl.toMono == 0) ? psEnc.sStereo.smth_width_Q14 : 0); if (prefillFlag != 0) { encControl.payloadSize_ms = payloadSize_ms; encControl.complexity = complexity; for (int i = 0; i < encControl.nChannelsInternal; i++) { psEnc.state_Fxx[i].controlled_since_last_payload = 0; psEnc.state_Fxx[i].prefillFlag = 0; } } return sILK_NO_ERROR; } } internal static class EncodeIndices { internal static void silk_encode_indices(SilkChannelEncoder psEncC, EntropyCoder psRangeEnc, int FrameIndex, int encode_LBRR, int condCoding) { short[] array = new short[16]; byte[] pred_Q = new byte[16]; SideInfoIndices sideInfoIndices = ((encode_LBRR == 0) ? psEncC.indices : psEncC.indices_LBRR[FrameIndex]); int num = 2 * sideInfoIndices.signalType + sideInfoIndices.quantOffsetType; if (encode_LBRR != 0 || num >= 2) { psRangeEnc.enc_icdf(num - 2, Tables.silk_type_offset_VAD_iCDF, 8u); } else { psRangeEnc.enc_icdf(num, Tables.silk_type_offset_no_VAD_iCDF, 8u); } if (condCoding == 2) { psRangeEnc.enc_icdf(sideInfoIndices.GainsIndices[0], Tables.silk_delta_gain_iCDF, 8u); } else { psRangeEnc.enc_icdf(Inlines.silk_RSHIFT(sideInfoIndices.GainsIndices[0], 3), Tables.silk_gain_iCDF[sideInfoIndices.signalType], 8u); psRangeEnc.enc_icdf(sideInfoIndices.GainsIndices[0] & 7, Tables.silk_uniform8_iCDF, 8u); } for (int i = 1; i < psEncC.nb_subfr; i++) { psRangeEnc.enc_icdf(sideInfoIndices.GainsIndices[i], Tables.silk_delta_gain_iCDF, 8u); } psRangeEnc.enc_icdf(sideInfoIndices.NLSFIndices[0], psEncC.psNLSF_CB.CB1_iCDF, (sideInfoIndices.signalType >> 1) * psEncC.psNLSF_CB.nVectors, 8u); NLSF.silk_NLSF_unpack(array, pred_Q, psEncC.psNLSF_CB, sideInfoIndices.NLSFIndices[0]); for (int i = 0; i < psEncC.psNLSF_CB.order; i++) { if (sideInfoIndices.NLSFIndices[i + 1] >= 4) { psRangeEnc.enc_icdf(8, psEncC.psNLSF_CB.ec_iCDF, array[i], 8u); psRangeEnc.enc_icdf(sideInfoIndices.NLSFIndices[i + 1] - 4, Tables.silk_NLSF_EXT_iCDF, 8u); } else if (sideInfoIndices.NLSFIndices[i + 1] <= -4) { psRangeEnc.enc_icdf(0, psEncC.psNLSF_CB.ec_iCDF, array[i], 8u); psRangeEnc.enc_icdf(-sideInfoIndices.NLSFIndices[i + 1] - 4, Tables.silk_NLSF_EXT_iCDF, 8u); } else { psRangeEnc.enc_icdf(sideInfoIndices.NLSFIndices[i + 1] + 4, psEncC.psNLSF_CB.ec_iCDF, array[i], 8u); } } if (psEncC.nb_subfr == 4) { psRangeEnc.enc_icdf(sideInfoIndices.NLSFInterpCoef_Q2, Tables.silk_NLSF_interpolation_factor_iCDF, 8u); } if (sideInfoIndices.signalType == 2) { int num2 = 1; if (condCoding == 2 && psEncC.ec_prevSignalType == 2) { int num3 = sideInfoIndices.lagIndex - psEncC.ec_prevLagIndex; if (num3 < -8 || num3 > 11) { num3 = 0; } else { num3 += 9; num2 = 0; } psRangeEnc.enc_icdf(num3, Tables.silk_pitch_delta_iCDF, 8u); } if (num2 != 0) { int num4 = Inlines.silk_DIV32_16(sideInfoIndices.lagIndex, Inlines.silk_RSHIFT(psEncC.fs_kHz, 1)); int s = sideInfoIndices.lagIndex - Inlines.silk_SMULBB(num4, Inlines.silk_RSHIFT(psEncC.fs_kHz, 1)); psRangeEnc.enc_icdf(num4, Tables.silk_pitch_lag_iCDF, 8u); psRangeEnc.enc_icdf(s, psEncC.pitch_lag_low_bits_iCDF, 8u); } psEncC.ec_prevLagIndex = sideInfoIndices.lagIndex; psRangeEnc.enc_icdf(sideInfoIndices.contourIndex, psEncC.pitch_contour_iCDF, 8u); psRangeEnc.enc_icdf(sideInfoIndices.PERIndex, Tables.silk_LTP_per_index_iCDF, 8u); for (int j = 0; j < psEncC.nb_subfr; j++) { psRangeEnc.enc_icdf(sideInfoIndices.LTPIndex[j], Tables.silk_LTP_gain_iCDF_ptrs[sideInfoIndices.PERIndex], 8u); } if (condCoding == 0) { psRangeEnc.enc_icdf(sideInfoIndices.LTP_scaleIndex, Tables.silk_LTPscale_iCDF, 8u); } } psEncC.ec_prevSignalType = sideInfoIndices.signalType; psRangeEnc.enc_icdf(sideInfoIndices.Seed, Tables.silk_uniform4_iCDF, 8u); } } internal static class EncodePulses { internal static int combine_and_check(int[] pulses_comb, int pulses_comb_ptr, int[] pulses_in, int pulses_in_ptr, int max_pulses, int len) { for (int i = 0; i < len; i++) { int num = 2 * i + pulses_in_ptr; int num2 = pulses_in[num] + pulses_in[num + 1]; if (num2 > max_pulses) { return 1; } pulses_comb[pulses_comb_ptr + i] = num2; } return 0; } internal static int combine_and_check(int[] pulses_comb, int[] pulses_in, int max_pulses, int len) { for (int i = 0; i < len; i++) { int num = pulses_in[2 * i] + pulses_in[2 * i + 1]; if (num > max_pulses) { return 1; } pulses_comb[i] = num; } return 0; } internal static void silk_encode_pulses(EntropyCoder psRangeEnc, int signalType, int quantOffsetType, sbyte[] pulses, int frame_length) { int num = 0; int[] array = new int[8]; Arrays.MemSet(array, 0, 8); int num2 = Inlines.silk_RSHIFT(frame_length, 4); if (num2 * 16 < frame_length) { num2++; Arrays.MemSetWithOffset(pulses, (sbyte)0, frame_length, 16); } int[] array2 = new int[num2 * 16]; for (int i = 0; i < num2 * 16; i += 4) { array2[i] = Inlines.silk_abs(pulses[i]); array2[i + 1] = Inlines.silk_abs(pulses[i + 1]); array2[i + 2] = Inlines.silk_abs(pulses[i + 2]); array2[i + 3] = Inlines.silk_abs(pulses[i + 3]); } int[] array3 = new int[num2]; int[] array4 = new int[num2]; int num3 = 0; for (int i = 0; i < num2; i++) { array4[i] = 0; while (true) { bool flag = true; int num4 = combine_and_check(array, 0, array2, num3, Tables.silk_max_pulses_table[0], 8); num4 += combine_and_check(array, array, Tables.silk_max_pulses_table[1], 4); num4 += combine_and_check(array, array, Tables.silk_max_pulses_table[2], 2); if (num4 + combine_and_check(array3, i, array, 0, Tables.silk_max_pulses_table[3], 1) != 0) { array4[i]++; for (int j = num3; j < num3 + 16; j++) { array2[j] = Inlines.silk_RSHIFT(array2[j], 1); } continue; } break; } num3 += 16; } int num5 = int.MaxValue; for (int j = 0; j < 9; j++) { byte[] array5 = Tables.silk_pulses_per_block_BITS_Q5[j]; int num6 = Tables.silk_rate_levels_BITS_Q5[signalType >> 1][j]; for (int i = 0; i < num2; i++) { num6 = ((array4[i] <= 0) ? (num6 + array5[array3[i]]) : (num6 + array5[17])); } if (num6 < num5) { num5 = num6; num = j; } } psRangeEnc.enc_icdf(num, Tables.silk_rate_levels_iCDF[signalType >> 1], 8u); for (int i = 0; i < num2; i++) { if (array4[i] == 0) { psRangeEnc.enc_icdf(array3[i], Tables.silk_pulses_per_block_iCDF[num], 8u); continue; } psRangeEnc.enc_icdf(17, Tables.silk_pulses_per_block_iCDF[num], 8u); for (int j = 0; j < array4[i] - 1; j++) { psRangeEnc.enc_icdf(17, Tables.silk_pulses_per_block_iCDF[9], 8u); } psRangeEnc.enc_icdf(array3[i], Tables.silk_pulses_per_block_iCDF[9], 8u); } for (int i = 0; i < num2; i++) { if (array3[i] > 0) { ShellCoder.silk_shell_encoder(psRangeEnc, array2, i * 16); } } for (int i = 0; i < num2; i++) { if (array4[i] <= 0) { continue; } int num7 = i * 16; int num8 = array4[i] - 1; for (int j = 0; j < 16; j++) { int num9 = (sbyte)Inlines.silk_abs(pulses[num7 + j]); int s; for (int num10 = num8; num10 > 0; num10--) { s = Inlines.silk_RSHIFT(num9, num10) & 1; psRangeEnc.enc_icdf(s, Tables.silk_lsb_iCDF, 8u); } s = num9 & 1; psRangeEnc.enc_icdf(s, Tables.silk_lsb_iCDF, 8u); } } CodeSigns.silk_encode_signs(psRangeEnc, pulses, frame_length, signalType, quantOffsetType, array3); } } internal static class Filters { private const int QA = 24; private static readonly short A_fb1_20 = 10788; private static readonly short A_fb1_21 = -24290; private static readonly int A_LIMIT = 16773022; internal static void silk_warped_LPC_analysis_filter(int[] state, int[] res_Q2, short[] coef_Q13, int coef_Q13_ptr, short[] input, int input_ptr, short lambda_Q16, int length, int order) { for (int i = 0; i < length; i++) { int num = Inlines.silk_SMLAWB(state[0], state[1], lambda_Q16); state[0] = Inlines.silk_LSHIFT(input[input_ptr + i], 14); int num2 = Inlines.silk_SMLAWB(state[1], state[2] - num, lambda_Q16); state[1] = num; int a = Inlines.silk_RSHIFT(order, 1); a = Inlines.silk_SMLAWB(a, num, coef_Q13[coef_Q13_ptr]); for (int j = 2; j < order; j += 2) { num = Inlines.silk_SMLAWB(state[j], state[j + 1] - num2, lambda_Q16); state[j] = num2; a = Inlines.silk_SMLAWB(a, num2, coef_Q13[coef_Q13_ptr + j - 1]); num2 = Inlines.silk_SMLAWB(state[j + 1], state[j + 2] - num, lambda_Q16); state[j + 1] = num; a = Inlines.silk_SMLAWB(a, num, coef_Q13[coef_Q13_ptr + j]); } state[order] = num2; a = Inlines.silk_SMLAWB(a, num2, coef_Q13[coef_Q13_ptr + order - 1]); res_Q2[i] = Inlines.silk_LSHIFT(input[input_ptr + i], 2) - Inlines.silk_RSHIFT_ROUND(a, 9); } } internal static void silk_prefilter(SilkChannelEncoder psEnc, SilkEncoderControl psEncCtrl, int[] xw_Q3, short[] x, int x_ptr) { SilkPrefilterState sPrefilt = psEnc.sPrefilt; short[] array = new short[2]; int num = x_ptr; int num2 = 0; int lag = sPrefilt.lagPrev; int[] array2 = new int[psEnc.subfr_length]; int[] array3 = new int[psEnc.subfr_length]; for (int i = 0; i < psEnc.nb_subfr; i++) { if (psEnc.indices.signalType == 2) { lag = psEncCtrl.pitchL[i]; } int num3 = Inlines.silk_SMULWB(psEncCtrl.HarmShapeGain_Q14[i], 16384 - psEncCtrl.HarmBoost_Q14[i]); int num4 = Inlines.silk_RSHIFT(num3, 2); num4 |= Inlines.silk_LSHIFT(Inlines.silk_RSHIFT(num3, 1), 16); int tilt_Q = psEncCtrl.Tilt_Q14[i]; int lF_shp_Q = psEncCtrl.LF_shp_Q14[i]; int coef_Q13_ptr = i * 16; silk_warped_LPC_analysis_filter(sPrefilt.sAR_shp, array3, psEncCtrl.AR1_Q13, coef_Q13_ptr, x, num, (short)psEnc.warping_Q16, psEnc.subfr_length, psEnc.shapingLPCOrder); array[0] = (short)Inlines.silk_RSHIFT_ROUND(psEncCtrl.GainsPre_Q14[i], 4); int a = Inlines.silk_SMLABB(3355443, psEncCtrl.HarmBoost_Q14[i], num3); a = Inlines.silk_SMLABB(a, psEncCtrl.coding_quality_Q14, 410); a = Inlines.silk_SMULWB(a, -psEncCtrl.GainsPre_Q14[i]); a = Inlines.silk_RSHIFT_ROUND(a, 14); array[1] = (short)Inlines.silk_SAT16(a); array2[0] = Inlines.silk_MLA(Inlines.silk_MUL(array3[0], array[0]), sPrefilt.sHarmHP_Q2, array[1]); for (int j = 1; j < psEnc.subfr_length; j++) { array2[j] = Inlines.silk_MLA(Inlines.silk_MUL(array3[j], array[0]), array3[j - 1], array[1]); } sPrefilt.sHarmHP_Q2 = array3[psEnc.subfr_length - 1]; silk_prefilt(sPrefilt, array2, xw_Q3, num2, num4, tilt_Q, lF_shp_Q, lag, psEnc.subfr_length); num += psEnc.subfr_length; num2 += psEnc.subfr_length; } sPrefilt.lagPrev = psEncCtrl.pitchL[psEnc.nb_subfr - 1]; } private static void silk_prefilt(SilkPrefilterState P, int[] st_res_Q12, int[] xw_Q3, int xw_Q3_ptr, int HarmShapeFIRPacked_Q12, int Tilt_Q14, int LF_shp_Q14, int lag, int length) { short[] sLTP_shp = P.sLTP_shp; int num = P.sLTP_shp_buf_idx; int num2 = P.sLF_AR_shp_Q12; int num3 = P.sLF_MA_shp_Q12; for (int i = 0; i < length; i++) { int a; if (lag > 0) { int num4 = lag + num; a = Inlines.silk_SMULBB(sLTP_shp[(num4 - 1 - 1) & 0x1FF], HarmShapeFIRPacked_Q12); a = Inlines.silk_SMLABT(a, sLTP_shp[(num4 - 1) & 0x1FF], HarmShapeFIRPacked_Q12); a = Inlines.silk_SMLABB(a, sLTP_shp[(num4 - 1 + 1) & 0x1FF], HarmShapeFIRPacked_Q12); } else { a = 0; } int a2 = Inlines.silk_SMULWB(num2, Tilt_Q14); int a3 = Inlines.silk_SMLAWB(Inlines.silk_SMULWT(num2, LF_shp_Q14), num3, LF_shp_Q14); num2 = Inlines.silk_SUB32(st_res_Q12[i], Inlines.silk_LSHIFT(a2, 2)); num3 = Inlines.silk_SUB32(num2, Inlines.silk_LSHIFT(a3, 2)); num = (num - 1) & 0x1FF; sLTP_shp[num] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(num3, 12)); xw_Q3[xw_Q3_ptr + i] = Inlines.silk_RSHIFT_ROUND(Inlines.silk_SUB32(num3, a), 9); } P.sLF_AR_shp_Q12 = num2; P.sLF_MA_shp_Q12 = num3; P.sLTP_shp_buf_idx = num; } internal static void silk_biquad_alt(short[] input, int input_ptr, int[] B_Q28, int[] A_Q28, int[] S, short[] output, int output_ptr, int len, int stride) { int b = -A_Q28[0] & 0x3FFF; int c = Inlines.silk_RSHIFT(-A_Q28[0], 14); int b2 = -A_Q28[1] & 0x3FFF; int c2 = Inlines.silk_RSHIFT(-A_Q28[1], 14); for (int i = 0; i < len; i++) { int c3 = input[input_ptr + i * stride]; int num = Inlines.silk_LSHIFT(Inlines.silk_SMLAWB(S[0], B_Q28[0], c3), 2); S[0] = S[1] + Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWB(num, b), 14); S[0] = Inlines.silk_SMLAWB(S[0], num, c); S[0] = Inlines.silk_SMLAWB(S[0], B_Q28[1], c3); S[1] = Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWB(num, b2), 14); S[1] = Inlines.silk_SMLAWB(S[1], num, c2); S[1] = Inlines.silk_SMLAWB(S[1], B_Q28[2], c3); output[output_ptr + i * stride] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT(num + 16384 - 1, 14)); } } internal static void silk_biquad_alt(short[] input, int input_ptr, int[] B_Q28, int[] A_Q28, int[] S, int S_ptr, short[] output, int output_ptr, int len, int stride) { int b = -A_Q28[0] & 0x3FFF; int c = Inlines.silk_RSHIFT(-A_Q28[0], 14); int b2 = -A_Q28[1] & 0x3FFF; int c2 = Inlines.silk_RSHIFT(-A_Q28[1], 14); for (int i = 0; i < len; i++) { int num = S_ptr + 1; int c3 = input[input_ptr + i * stride]; int num2 = Inlines.silk_LSHIFT(Inlines.silk_SMLAWB(S[S_ptr], B_Q28[0], c3), 2); S[S_ptr] = S[num] + Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWB(num2, b), 14); S[S_ptr] = Inlines.silk_SMLAWB(S[S_ptr], num2, c); S[S_ptr] = Inlines.silk_SMLAWB(S[S_ptr], B_Q28[1], c3); S[num] = Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWB(num2, b2), 14); S[num] = Inlines.silk_SMLAWB(S[num], num2, c2); S[num] = Inlines.silk_SMLAWB(S[num], B_Q28[2], c3); output[output_ptr + i * stride] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT(num2 + 16384 - 1, 14)); } } internal static void silk_ana_filt_bank_1(short[] input, int input_ptr, int[] S, short[] outL, short[] outH, int outH_ptr, int N) { int num = Inlines.silk_RSHIFT(N, 1); for (int i = 0; i < num; i++) { int a = Inlines.silk_LSHIFT(input[input_ptr + 2 * i], 10); int num2 = Inlines.silk_SUB32(a, S[0]); int b = Inlines.silk_SMLAWB(num2, num2, A_fb1_21); int b2 = Inlines.silk_ADD32(S[0], b); S[0] = Inlines.silk_ADD32(a, b); a = Inlines.silk_LSHIFT(input[input_ptr + 2 * i + 1], 10); num2 = Inlines.silk_SUB32(a, S[1]); b = Inlines.silk_SMULWB(num2, A_fb1_20); int a2 = Inlines.silk_ADD32(S[1], b); S[1] = Inlines.silk_ADD32(a, b); outL[i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_ADD32(a2, b2), 11)); outH[outH_ptr + i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SUB32(a2, b2), 11)); } } 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_LP_interpolate_filter_taps(int[] B_Q28, int[] A_Q28, int ind, int fac_Q16) { if (ind < 4) { if (fac_Q16 > 0) { if (fac_Q16 < 32768) { for (int i = 0; i < 3; i++) { B_Q28[i] = Inlines.silk_SMLAWB(Tables.silk_Transition_LP_B_Q28[ind][i], Tables.silk_Transition_LP_B_Q28[ind + 1][i] - Tables.silk_Transition_LP_B_Q28[ind][i], fac_Q16); } for (int j = 0; j < 2; j++) { A_Q28[j] = Inlines.silk_SMLAWB(Tables.silk_Transition_LP_A_Q28[ind][j], Tables.silk_Transition_LP_A_Q28[ind + 1][j] - Tables.silk_Transition_LP_A_Q28[ind][j], fac_Q16); } } else { for (int i = 0; i < 3; i++) { B_Q28[i] = Inlines.silk_SMLAWB(Tables.silk_Transition_LP_B_Q28[ind + 1][i], Tables.silk_Transition_LP_B_Q28[ind + 1][i] - Tables.silk_Transition_LP_B_Q28[ind][i], fac_Q16 - 65536); } for (int j = 0; j < 2; j++) { A_Q28[j] = Inlines.silk_SMLAWB(Tables.silk_Transition_LP_A_Q28[ind + 1][j], Tables.silk_Transition_LP_A_Q28[ind + 1][j] - Tables.silk_Transition_LP_A_Q28[ind][j], fac_Q16 - 65536); } } } else { Array.Copy(Tables.silk_Transition_LP_B_Q28[ind], 0, B_Q28, 0, 3); Array.Copy(Tables.silk_Transition_LP_A_Q28[ind], 0, A_Q28, 0, 2); } } else { Array.Copy(Tables.silk_Transition_LP_B_Q28[4], 0, B_Q28, 0, 3); Array.Copy(Tables.silk_Transition_LP_A_Q28[4], 0, A_Q28, 0, 2); } } internal static void silk_LPC_analysis_filter(short[] output, int output_ptr, short[] input, int input_ptr, short[] B, int B_ptr, int len, int d) { short[] array = new short[16]; short[] array2 = new short[16]; for (int i = 0; i < d; i++) { array2[i] = (short)(-B[B_ptr + i]); } for (int i = 0; i < d; i++) { array[i] = input[input_ptr + d - i - 1]; } Kernels.celt_fir(input, input_ptr + d, array2, output, output_ptr + d, len - d, d, array); for (int i = output_ptr; i < output_ptr + d; i++) { output[i] = 0; } } internal static int LPC_inverse_pred_gain_QA(int[][] A_QA, int order) { int[] array = A_QA[order & 1]; int a = 1073741824; int num2; int num3; for (int num = order - 1; num > 0; num--) { if (array[num] > A_LIMIT || array[num] < -A_LIMIT) { return 0; } num2 = -Inlines.silk_LSHIFT(array[num], 7); num3 = 1073741824 - Inlines.silk_SMMUL(num2, num2); int num4 = 32 - Inlines.silk_CLZ32(Inlines.silk_abs(num3)); int b = Inlines.silk_INVERSE32_varQ(num3, num4 + 30); a = Inlines.silk_LSHIFT(Inlines.silk_SMMUL(a, num3), 2); int[] array2 = array; array = A_QA[num & 1]; for (int i = 0; i < num; i++) { int a2 = array2[i] - Inlines.MUL32_FRAC_Q(array2[num - i - 1], num2, 31); array[i] = Inlines.MUL32_FRAC_Q(a2, b, num4); } } if (array[0] > A_LIMIT || array[0] < -A_LIMIT) { return 0; } num2 = -Inlines.silk_LSHIFT(array[0], 7); num3 = 1073741824 - Inlines.silk_SMMUL(num2, num2); return Inlines.silk_LSHIFT(Inlines.silk_SMMUL(a, num3), 2); } internal static int silk_LPC_inverse_pred_gain(short[] A_Q12, int order) { int[][] array = new int[2][] { new int[order], new int[order] }; int num = 0; int[] array2 = array[order & 1]; for (int i = 0; i < order; i++) { num += A_Q12[i]; array2[i] = Inlines.silk_LSHIFT32(A_Q12[i], 12); } if (num >= 4096) { return 0; } return LPC_inverse_pred_gain_QA(array, order); } } internal static class FindLPC { internal static void silk_find_LPC(SilkChannelEncoder psEncC, short[] NLSF_Q15, short[] x, int minInvGain_Q30) { int[] a_Q = new int[16]; BoxedValue boxedValue = new BoxedValue(0); BoxedValue boxedValue2 = new BoxedValue(0); int[] a_Q2 = new int[16]; short[] array = new short[16]; short[] array2 = new short[16]; int num = psEncC.subfr_length + psEncC.predictLPCOrder; psEncC.indices.NLSFInterpCoef_Q2 = 4; BurgModified.silk_burg_modified(boxedValue, boxedValue2, a_Q, x, 0, minInvGain_Q30, num, psEncC.nb_subfr, psEncC.predictLPCOrder); int num2 = boxedValue.Val; int num3 = boxedValue2.Val; if (psEncC.useInterpolatedNLSFs != 0 && psEncC.first_frame_after_reset == 0 && psEncC.nb_subfr == 4) { BurgModified.silk_burg_modified(boxedValue, boxedValue2, a_Q2, x, 2 * num, minInvGain_Q30, num, 2, psEncC.predictLPCOrder); int val = boxedValue.Val; int val2 = boxedValue2.Val; int num4 = val2 - num3; if (num4 >= 0) { if (num4 < 32) { num2 -= Inlines.silk_RSHIFT(val, num4); } } else { num2 = Inlines.silk_RSHIFT(num2, -num4) - val; num3 = val2; } NLSF.silk_A2NLSF(NLSF_Q15, a_Q2, psEncC.predictLPCOrder); short[] array3 = new short[2 * num]; for (int num5 = 3; num5 >= 0; num5--) { Inlines.silk_interpolate(array2, psEncC.prev_NLSFq_Q15, NLSF_Q15, num5, psEncC.predictLPCOrder); NLSF.silk_NLSF2A(array, array2, psEncC.predictLPCOrder); Filters.silk_LPC_analysis_filter(array3, 0, x, 0, array, 0, 2 * num, psEncC.predictLPCOrder); SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, array3, psEncC.predictLPCOrder, num - psEncC.predictLPCOrder); SumSqrShift.silk_sum_sqr_shift(out var energy2, out var shift2, array3, psEncC.predictLPCOrder + num, num - psEncC.predictLPCOrder); num4 = shift - shift2; int num6; if (num4 >= 0) { energy2 = Inlines.silk_RSHIFT(energy2, num4); num6 = -shift; } else { energy = Inlines.silk_RSHIFT(energy, -num4); num6 = -shift2; } int num7 = Inlines.silk_ADD32(energy, energy2); num4 = num6 - num3; int num8 = ((num4 >= 0) ? ((Inlines.silk_RSHIFT(num7, num4) < num2) ? 1 : 0) : ((-num4 < 32) ? ((num7 < Inlines.silk_RSHIFT(num2, -num4)) ? 1 : 0) : 0)); if (num8 == 1) { num2 = num7; num3 = num6; psEncC.indices.NLSFInterpCoef_Q2 = (sbyte)num5; } } } if (psEncC.indices.NLSFInterpCoef_Q2 == 4) { NLSF.silk_A2NLSF(NLSF_Q15, a_Q, psEncC.predictLPCOrder); } } } internal static class FindLTP { private const int LTP_CORRS_HEAD_ROOM = 2; internal static void silk_find_LTP(short[] b_Q14, int[] WLTP, BoxedValue LTPredCodGain_Q7, short[] r_lpc, int[] lag, int[] Wght_Q15, int subfr_length, int nb_subfr, int mem_offset, int[] corr_rshifts) { int[] array = new int[5]; int[] array2 = new int[5]; int[] array3 = new int[4]; int[] array4 = new int[4]; int[] array5 = new int[4]; int[] array6 = new int[5]; int[] array7 = new int[4]; int num = 0; int num2 = 0; int num3 = mem_offset; int num5; int a3; for (int i = 0; i < nb_subfr; i++) { int x_ptr = num3 - (lag[i] + 2); SumSqrShift.silk_sum_sqr_shift(out array7[i], out var shift, r_lpc, num3, subfr_length); int num4 = Inlines.silk_CLZ32(array7[i]); if (num4 < 2) { array7[i] = Inlines.silk_RSHIFT_ROUND(array7[i], 2 - num4); shift += 2 - num4; } corr_rshifts[i] = shift; BoxedValue boxedValue = new BoxedValue(corr_rshifts[i]); CorrelateMatrix.silk_corrMatrix(r_lpc, x_ptr, subfr_length, 5, 2, WLTP, num2, boxedValue); corr_rshifts[i] = boxedValue.Val; CorrelateMatrix.silk_corrVector(r_lpc, x_ptr, r_lpc, num3, subfr_length, 5, array6, corr_rshifts[i]); if (corr_rshifts[i] > shift) { array7[i] = Inlines.silk_RSHIFT(array7[i], corr_rshifts[i] - shift); } int a = 1; a = Inlines.silk_SMLAWB(a, array7[i], 1092); a = Inlines.silk_SMLAWB(a, Inlines.MatrixGet(WLTP, num2, 0, 0, 5), 1092); a = Inlines.silk_SMLAWB(a, Inlines.MatrixGet(WLTP, num2, 4, 4, 5), 1092); RegularizeCorrelations.silk_regularize_correlations(WLTP, num2, array7, i, a, 5); LinearAlgebra.silk_solve_LDL(WLTP, num2, 5, array6, array); silk_fit_LTP(array, b_Q14, num); array4[i] = ResidualEnergy.silk_residual_energy16_covar(b_Q14, num, WLTP, num2, array6, array7[i], 5, 14); num5 = Inlines.silk_min_int(corr_rshifts[i], 2); int a2 = Inlines.silk_LSHIFT_SAT32(Inlines.silk_SMULWB(array4[i], Wght_Q15[i]), 1 + num5) + Inlines.silk_RSHIFT(Inlines.silk_SMULWB(subfr_length, 655), corr_rshifts[i] - num5); a2 = Inlines.silk_max(a2, 1); a3 = Inlines.silk_DIV32(Inlines.silk_LSHIFT(Wght_Q15[i], 16), a2); a3 = Inlines.silk_RSHIFT(a3, 31 + corr_rshifts[i] - num5 - 26); int num6 = 0; for (int j = num2; j < num2 + 25; j++) { num6 = Inlines.silk_max(WLTP[j], num6); } int num7 = Inlines.silk_CLZ32(num6) - 1 - 3; if (8 + num7 < 31) { a3 = Inlines.silk_min_32(a3, Inlines.silk_LSHIFT(1, 8 + num7)); } Inlines.silk_scale_vector32_Q26_lshift_18(WLTP, num2, a3, 25); array5[i] = Inlines.MatrixGet(WLTP, num2, 2, 2, 5); num3 += subfr_length; num += 5; num2 += 25; } int num8 = 0; for (int i = 0; i < nb_subfr; i++) { num8 = Inlines.silk_max_int(corr_rshifts[i], num8); } if (LTPredCodGain_Q7 != null) { int a4 = 0; int num9 = 0; for (int i = 0; i < nb_subfr; i++) { num9 = Inlines.silk_ADD32(num9, Inlines.silk_RSHIFT(Inlines.silk_ADD32(Inlines.silk_SMULWB(array7[i], Wght_Q15[i]), 1), 1 + (num8 - corr_rshifts[i]))); a4 = Inlines.silk_ADD32(a4, Inlines.silk_RSHIFT(Inlines.silk_ADD32(Inlines.silk_SMULWB(array4[i], Wght_Q15[i]), 1), 1 + (num8 - corr_rshifts[i]))); } a4 = Inlines.silk_max(a4, 1); int inLin = Inlines.silk_DIV32_varQ(num9, a4, 16); LTPredCodGain_Q7.Val = Inlines.silk_SMULBB(3, Inlines.silk_lin2log(inLin) - 2048); } num = 0; for (int i = 0; i < nb_subfr; i++) { array3[i] = 0; for (int j = num; j < num + 5; j++) { array3[i] += b_Q14[j]; } num += 5; } int num10 = 0; int num11 = 0; for (int i = 0; i < nb_subfr; i++) { num10 = Inlines.silk_max_32(num10, Inlines.silk_abs(array3[i])); num11 = Inlines.silk_max_32(num11, 32 - Inlines.silk_CLZ32(array5[i]) + corr_rshifts[i] - num8); } num5 = num11 + 32 - Inlines.silk_CLZ32(num10) - 14; num5 -= 29 + num8; num5 = Inlines.silk_max_int(num5, 0); int num12 = num8 + num5; a3 = Inlines.silk_RSHIFT(262, num8 + num5) + 1; int num13 = 0; for (int i = 0; i < nb_subfr; i++) { a3 = Inlines.silk_ADD32(a3, Inlines.silk_RSHIFT(array5[i], num12 - corr_rshifts[i])); num13 = Inlines.silk_ADD32(num13, Inlines.silk_LSHIFT(Inlines.silk_SMULWW(Inlines.silk_RSHIFT(array5[i], num12 - corr_rshifts[i]), array3[i]), 2)); } int a5 = Inlines.silk_DIV32_varQ(num13, a3, 12); num = 0; for (int i = 0; i < nb_subfr; i++) { a3 = ((2 - corr_rshifts[i] <= 0) ? Inlines.silk_LSHIFT_SAT32(array5[i], corr_rshifts[i] - 2) : Inlines.silk_RSHIFT(array5[i], 2 - corr_rshifts[i])); int a6 = Inlines.silk_MUL(Inlines.silk_DIV32(6710887, Inlines.silk_RSHIFT(6710887, 10) + a3), Inlines.silk_LSHIFT_SAT32(Inlines.silk_SUB_SAT32(a5, Inlines.silk_RSHIFT(array3[i], 2)), 4)); a3 = 0; for (int j = 0; j < 5; j++) { array2[j] = Inlines.silk_max_16(b_Q14[num + j], 1638); a3 += array2[j]; } a3 = Inlines.silk_DIV32(a6, a3); for (int j = 0; j < 5; j++) { b_Q14[num + j] = (short)Inlines.silk_LIMIT_32(b_Q14[num + j] + Inlines.silk_SMULWB(Inlines.silk_LSHIFT_SAT32(a3, 4), array2[j]), -16000, 28000); } num += 5; } } internal static void silk_fit_LTP(int[] LTP_coefs_Q16, short[] LTP_coefs_Q14, int LTP_coefs_Q14_ptr) { for (int i = 0; i < 5; i++) { LTP_coefs_Q14[LTP_coefs_Q14_ptr + i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(LTP_coefs_Q16[i], 2)); } } } internal static class FindPitchLags { internal static void silk_find_pitch_lags(SilkChannelEncoder psEnc, SilkEncoderControl psEncCtrl, short[] res, short[] x, int x_ptr) { int[] array = new int[17]; short[] rc_Q = new short[16]; int[] array2 = new int[16]; short[] array3 = new short[16]; int num = psEnc.la_pitch + psEnc.frame_length + psEnc.ltp_mem_length; int num2 = x_ptr - psEnc.ltp_mem_length; short[] array4 = new short[psEnc.pitch_LPC_win_length]; int num3 = num2 + num - psEnc.pitch_LPC_win_length; int num4 = 0; ApplySineWindow.silk_apply_sine_window(array4, num4, x, num3, 1, psEnc.la_pitch); num4 += psEnc.la_pitch; num3 += psEnc.la_pitch; Array.Copy(x, num3, array4, num4, psEnc.pitch_LPC_win_length - Inlines.silk_LSHIFT(psEnc.la_pitch, 1)); num4 += psEnc.pitch_LPC_win_length - Inlines.silk_LSHIFT(psEnc.la_pitch, 1); num3 += psEnc.pitch_LPC_win_length - Inlines.silk_LSHIFT(psEnc.la_pitch, 1); ApplySineWindow.silk_apply_sine_window(array4, num4, x, num3, 2, psEnc.la_pitch); BoxedValue boxedValue = new BoxedValue(0); Autocorrelation.silk_autocorr(array, boxedValue, array4, psEnc.pitch_LPC_win_length, psEnc.pitchEstimationLPCOrder + 1); int val = boxedValue.Val; array[0] = Inlines.silk_SMLAWB(array[0], array[0], 66) + 1; int a = Schur.silk_schur(rc_Q, array, psEnc.pitchEstimationLPCOrder); psEncCtrl.predGain_Q16 = Inlines.silk_DIV32_varQ(array[0], Inlines.silk_max_int(a, 1), 16); K2A.silk_k2a(array2, rc_Q, psEnc.pitchEstimationLPCOrder); for (int i = 0; i < psEnc.pitchEstimationLPCOrder; i++) { array3[i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT(array2[i], 12)); } BWExpander.silk_bwexpander(array3, psEnc.pitchEstimationLPCOrder, 64881); Filters.silk_LPC_analysis_filter(res, 0, x, num2, array3, 0, num, psEnc.pitchEstimationLPCOrder); if (psEnc.indices.signalType != 0 && psEnc.first_frame_after_reset == 0) { int a2 = 4915; a2 = Inlines.silk_SMLABB(a2, -32, psEnc.pitchEstimationLPCOrder); a2 = Inlines.silk_SMLAWB(a2, -209714, psEnc.speech_activity_Q8); a2 = Inlines.silk_SMLABB(a2, -1228, Inlines.silk_RSHIFT(psEnc.prevSignalType, 1)); a2 = Inlines.silk_SMLAWB(a2, -1637, psEnc.input_tilt_Q15); a2 = Inlines.silk_SAT16(a2); BoxedValue boxedValue2 = new BoxedValue(psEnc.indices.lagIndex); BoxedValue boxedValue3 = new BoxedValue(psEnc.indices.contourIndex); BoxedValue boxedValue4 = new BoxedValue(psEnc.LTPCorr_Q15); if (PitchAnalysisCore.silk_pitch_analysis_core(res, psEncCtrl.pitchL, boxedValue2, boxedValue3, boxedValue4, psEnc.prevLag, psEnc.pitchEstimationThreshold_Q16, a2, psEnc.fs_kHz, psEnc.pitchEstimationComplexity, psEnc.nb_subfr) == 0) { psEnc.indices.signalType = 2; } else { psEnc.indices.signalType = 1; } psEnc.indices.lagIndex = boxedValue2.Val; psEnc.indices.contourIndex = boxedValue3.Val; psEnc.LTPCorr_Q15 = boxedValue4.Val; } else { Arrays.MemSet(psEncCtrl.pitchL, 0, 4); psEnc.indices.lagIndex = 0; psEnc.indices.contourIndex = 0; psEnc.LTPCorr_Q15 = 0; } } } internal static class FindPredCoefs { internal static void silk_find_pred_coefs(SilkChannelEncoder psEnc, SilkEncoderControl psEncCtrl, short[] res_pitch, short[] x, int x_ptr, int condCoding) { int[] array = new int[4]; int[] array2 = new int[4]; int[] array3 = new int[4]; short[] array4 = new short[16]; int[] corr_rshifts = new int[4]; int num = 33554431; for (int i = 0; i < psEnc.nb_subfr; i++) { num = Inlines.silk_min(num, psEncCtrl.Gains_Q16[i]); } for (int i = 0; i < psEnc.nb_subfr; i++) { array[i] = Inlines.silk_DIV32_varQ(num, psEncCtrl.Gains_Q16[i], 14); array[i] = Inlines.silk_max(array[i], 363); int a = Inlines.silk_SMULWB(array[i], array[i]); array3[i] = Inlines.silk_RSHIFT(a, 1); array2[i] = Inlines.silk_DIV32(65536, array[i]); } short[] array5 = new short[psEnc.nb_subfr * psEnc.predictLPCOrder + psEnc.frame_length]; if (psEnc.indices.signalType == 2) { int[] array6 = new int[psEnc.nb_subfr * 5 * 5]; BoxedValue boxedValue = new BoxedValue(psEncCtrl.LTPredCodGain_Q7); FindLTP.silk_find_LTP(psEncCtrl.LTPCoef_Q14, array6, boxedValue, res_pitch, psEncCtrl.pitchL, array3, psEnc.subfr_length, psEnc.nb_subfr, psEnc.ltp_mem_length, corr_rshifts); psEncCtrl.LTPredCodGain_Q7 = boxedValue.Val; BoxedValue boxedValue2 = new BoxedValue(psEnc.indices.PERIndex); BoxedValue boxedValue3 = new BoxedValue(psEnc.sum_log_gain_Q7); QuantizeLTPGains.silk_quant_LTP_gains(psEncCtrl.LTPCoef_Q14, psEnc.indices.LTPIndex, boxedValue2, boxedValue3, array6, psEnc.mu_LTP_Q9, psEnc.LTPQuantLowComplexity, psEnc.nb_subfr); psEnc.indices.PERIndex = boxedValue2.Val; psEnc.sum_log_gain_Q7 = boxedValue3.Val; LTPScaleControl.silk_LTP_scale_ctrl(psEnc, psEncCtrl, condCoding); LTPAnalysisFilter.silk_LTP_analysis_filter(array5, x, x_ptr - psEnc.predictLPCOrder, psEncCtrl.LTPCoef_Q14, psEncCtrl.pitchL, array, psEnc.subfr_length, psEnc.nb_subfr, psEnc.predictLPCOrder); } else { int num2 = x_ptr - psEnc.predictLPCOrder; int num3 = 0; for (int i = 0; i < psEnc.nb_subfr; i++) { Inlines.silk_scale_copy_vector16(array5, num3, x, num2, array[i], psEnc.subfr_length + psEnc.predictLPCOrder); num3 += psEnc.subfr_length + psEnc.predictLPCOrder; num2 += psEnc.subfr_length; } Arrays.MemSet(psEncCtrl.LTPCoef_Q14, (short)0, psEnc.nb_subfr * 5); psEncCtrl.LTPredCodGain_Q7 = 0; psEnc.sum_log_gain_Q7 = 0; } int minInvGain_Q; if (psEnc.first_frame_after_reset != 0) { minInvGain_Q = 10737418; } else { minInvGain_Q = Inlines.silk_log2lin(Inlines.silk_SMLAWB(2048, psEncCtrl.LTPredCodGain_Q7, 21845)); minInvGain_Q = Inlines.silk_DIV32_varQ(minInvGain_Q, Inlines.silk_SMULWW(10000, Inlines.silk_SMLAWB(65536, 196608, psEncCtrl.coding_quality_Q14)), 14); } FindLPC.silk_find_LPC(psEnc, array4, array5, minInvGain_Q); NLSF.silk_process_NLSFs(psEnc, psEncCtrl.PredCoef_Q12, array4, psEnc.prev_NLSFq_Q15); ResidualEnergy.silk_residual_energy(psEncCtrl.ResNrg, psEncCtrl.ResNrgQ, array5, psEncCtrl.PredCoef_Q12, array2, psEnc.subfr_length, psEnc.nb_subfr, psEnc.predictLPCOrder); Array.Copy(array4, psEnc.prev_NLSFq_Q15, 16); } } internal static class GainQuantization { private static readonly int OFFSET = 2090; private static readonly int SCALE_Q16 = 2251; private static readonly int INV_SCALE_Q16 = 1907825; internal static void silk_gains_quant(sbyte[] ind, int[] gain_Q16, BoxedValue prev_ind, int conditional, int nb_subfr) { for (int i = 0; i < nb_subfr; i++) { ind[i] = (sbyte)Inlines.silk_SMULWB(SCALE_Q16, Inlines.silk_lin2log(gain_Q16[i]) - OFFSET); if (ind[i] < prev_ind.Val) { ind[i]++; } ind[i] = (sbyte)Inlines.silk_LIMIT_int(ind[i], 0, 63); if (i == 0 && conditional == 0) { ind[i] = (sbyte)Inlines.silk_LIMIT_int(ind[i], prev_ind.Val + -4, 63); prev_ind.Val = ind[i]; } else { ind[i] -= prev_ind.Val; int num = 8 + prev_ind.Val; if (ind[i] > num) { ind[i] = (sbyte)(num + Inlines.silk_RSHIFT(ind[i] - num + 1, 1)); } ind[i] = (sbyte)Inlines.silk_LIMIT_int(ind[i], -4, 36); if (ind[i] > num) { prev_ind.Val += (sbyte)(Inlines.silk_LSHIFT(ind[i], 1) - num); } else { prev_ind.Val += ind[i]; } ind[i] -= -4; } gain_Q16[i] = Inlines.silk_log2lin(Inlines.silk_min_32(Inlines.silk_SMULWB(INV_SCALE_Q16, prev_ind.Val) + OFFSET, 3967)); } } internal static void silk_gains_dequant(int[] gain_Q16, sbyte[] ind, BoxedValue prev_ind, int conditional, int nb_subfr) { for (int i = 0; i < nb_subfr; i++) { if (i == 0 && conditional == 0) { prev_ind.Val = (sbyte)Inlines.silk_max_int(ind[i], prev_ind.Val - 16); } else { int num = ind[i] + -4; int num2 = 8 + prev_ind.Val; if (num > num2) { prev_ind.Val += (sbyte)(Inlines.silk_LSHIFT(num, 1) - num2); } else { prev_ind.Val += (sbyte)num; } } prev_ind.Val = (sbyte)Inlines.silk_LIMIT_int(prev_ind.Val, 0, 63); gain_Q16[i] = Inlines.silk_log2lin(Inlines.silk_min_32(Inlines.silk_SMULWB(INV_SCALE_Q16, prev_ind.Val) + OFFSET, 3967)); } } internal static int silk_gains_ID(sbyte[] ind, int nb_subfr) { int num = 0; for (int i = 0; i < nb_subfr; i++) { num = Inlines.silk_ADD_LSHIFT32(ind[i], num, 8); } return num; } } internal static class HPVariableCutoff { internal static void silk_HP_variable_cutoff(SilkChannelEncoder[] state_Fxx) { SilkChannelEncoder silkChannelEncoder = state_Fxx[0]; if (silkChannelEncoder.prevSignalType == 2) { int inLin = Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(Inlines.silk_MUL(silkChannelEncoder.fs_kHz, 1000), 16), silkChannelEncoder.prevLag); int num = Inlines.silk_lin2log(inLin) - 2048; int num2 = silkChannelEncoder.input_quality_bands_Q15[0]; num = Inlines.silk_SMLAWB(num, Inlines.silk_SMULWB(Inlines.silk_LSHIFT(-num2, 2), num2), num - (Inlines.silk_lin2log(3932160) - 2048)); int num3 = num - Inlines.silk_RSHIFT(silkChannelEncoder.variable_HP_smth1_Q15, 8); if (num3 < 0) { num3 = Inlines.silk_MUL(num3, 3); } num3 = Inlines.silk_LIMIT_32(num3, -51, 51); silkChannelEncoder.variable_HP_smth1_Q15 = Inlines.silk_SMLAWB(silkChannelEncoder.variable_HP_smth1_Q15, Inlines.silk_SMULBB(silkChannelEncoder.speech_activity_Q8, num3), 6554); silkChannelEncoder.variable_HP_smth1_Q15 = Inlines.silk_LIMIT_32(silkChannelEncoder.variable_HP_smth1_Q15, Inlines.silk_LSHIFT(Inlines.silk_lin2log(60), 8), Inlines.silk_LSHIFT(Inlines.silk_lin2log(100), 8)); } } } internal static class K2A { internal static void silk_k2a(int[] A_Q24, short[] rc_Q15, int order) { int[] array = new int[16]; for (int i = 0; i < order; i++) { for (int j = 0; j < i; j++) { array[j] = A_Q24[j]; } for (int j = 0; j < i; j++) { A_Q24[j] = Inlines.silk_SMLAWB(A_Q24[j], Inlines.silk_LSHIFT(array[i - j - 1], 1), rc_Q15[i]); } A_Q24[i] = -Inlines.silk_LSHIFT(rc_Q15[i], 9); } } internal static void silk_k2a_Q16(int[] A_Q24, int[] rc_Q16, int order) { int[] array = new int[16]; for (int i = 0; i < order; i++) { for (int j = 0; j < i; j++) { array[j] = A_Q24[j]; } for (int j = 0; j < i; j++) { A_Q24[j] = Inlines.silk_SMLAWW(A_Q24[j], array[i - j - 1], rc_Q16[i]); } A_Q24[i] = -Inlines.silk_LSHIFT(rc_Q16[i], 8); } } } internal static class LinearAlgebra { internal static void silk_solve_LDL(int[] A, int A_ptr, int M, int[] b, int[] x_Q16) { int[] l_Q = new int[M * M]; int[] array = new int[16]; int[] inv_D = new int[32]; silk_LDL_factorize(A, A_ptr, M, l_Q, inv_D); silk_LS_SolveFirst(l_Q, M, b, array); silk_LS_divide_Q16(array, inv_D, M); silk_LS_SolveLast(l_Q, M, array, x_Q16); } private static void silk_LDL_factorize(int[] A, int A_ptr, int M, int[] L_Q16, int[] inv_D) { int[] array = new int[M]; int[] array2 = new int[M]; int num = 1; int num2 = Inlines.silk_max_32(Inlines.silk_SMMUL(Inlines.silk_ADD_SAT32(A[A_ptr], A[A_ptr + Inlines.silk_SMULBB(M, M) - 1]), 21475), 512); for (int i = 0; i < M; i++) { if (num != 1) { break; } num = 0; for (int j = 0; j < M; j++) { int[] array3 = L_Q16; int num3 = Inlines.MatrixGetPointer(j, 0, M); int num4 = 0; for (int k = 0; k < j; k++) { array[k] = Inlines.silk_SMULWW(array2[k], array3[num3 + k]); num4 = Inlines.silk_SMLAWW(num4, array[k], array3[num3 + k]); } num4 = Inlines.silk_SUB32(Inlines.MatrixGet(A, A_ptr, j, j, M), num4); if (num4 < num2) { num4 = Inlines.silk_SUB32(Inlines.silk_SMULBB(i + 1, num2), num4); for (int k = 0; k < M; k++) { Inlines.MatrixSet(A, A_ptr, k, k, M, Inlines.silk_ADD32(Inlines.MatrixGet(A, A_ptr, k, k, M), num4)); } num = 1; break; } array2[j] = num4; int num5 = Inlines.silk_INVERSE32_varQ(num4, 36); int b = Inlines.silk_LSHIFT(num5, 4); int a = Inlines.silk_SUB32(16777216, Inlines.silk_SMULWW(num4, b)); int num6 = Inlines.silk_SMULWW(a, b); inv_D[j * 2] = num5; inv_D[j * 2 + 1] = num6; Inlines.MatrixSet(L_Q16, j, j, M, 65536); array3 = A; num3 = Inlines.MatrixGetPointer(j, 0, M) + A_ptr; int num7 = Inlines.MatrixGetPointer(j + 1, 0, M); for (int k = j + 1; k < M; k++) { num4 = 0; for (int l = 0; l < j; l++) { num4 = Inlines.silk_SMLAWW(num4, array[l], L_Q16[num7 + l]); } num4 = Inlines.silk_SUB32(array3[num3 + k], num4); Inlines.MatrixSet(L_Q16, k, j, M, Inlines.silk_ADD32(Inlines.silk_SMMUL(num4, num6), Inlines.silk_RSHIFT(Inlines.silk_SMULWW(num4, num5), 4))); num7 += M; } } } } private static void silk_LS_divide_Q16(int[] T, int[] inv_D, int M) { for (int i = 0; i < M; i++) { int b = inv_D[i * 2]; int b2 = inv_D[i * 2 + 1]; int a = T[i]; T[i] = Inlines.silk_ADD32(Inlines.silk_SMMUL(a, b2), Inlines.silk_RSHIFT(Inlines.silk_SMULWW(a, b), 4)); } } private static void silk_LS_SolveFirst(int[] L_Q16, int M, int[] b, int[] x_Q16) { for (int i = 0; i < M; i++) { int num = Inlines.MatrixGetPointer(i, 0, M); int num2 = 0; for (int j = 0; j < i; j++) { num2 = Inlines.silk_SMLAWW(num2, L_Q16[num + j], x_Q16[j]); } x_Q16[i] = Inlines.silk_SUB32(b[i], num2); } } private static void silk_LS_SolveLast(int[] L_Q16, int M, int[] b, int[] x_Q16) { for (int num = M - 1; num >= 0; num--) { int num2 = Inlines.MatrixGetPointer(0, num, M); int num3 = 0; for (int num4 = M - 1; num4 > num; num4--) { num3 = Inlines.silk_SMLAWW(num3, L_Q16[num2 + Inlines.silk_SMULBB(num4, M)], x_Q16[num4]); } x_Q16[num] = Inlines.silk_SUB32(b[num], num3); } } } internal static class LPCInversePredGain { private const float RC_THRESHOLD = 0.9999f; private const int QA = 24; private static readonly int A_LIMIT = 16773022; internal static int LPC_inverse_pred_gain_QA(int[][] A_QA, int order) { int[] array = A_QA[order & 1]; int a = 1073741824; int num2; int num3; for (int num = order - 1; num > 0; num--) { if (array[num] > A_LIMIT || array[num] < -A_LIMIT) { return 0; } num2 = -Inlines.silk_LSHIFT(array[num], 7); num3 = 1073741824 - Inlines.silk_SMMUL(num2, num2); int num4 = 32 - Inlines.silk_CLZ32(Inlines.silk_abs(num3)); int b = Inlines.silk_INVERSE32_varQ(num3, num4 + 30); a = Inlines.silk_LSHIFT(Inlines.silk_SMMUL(a, num3), 2); int[] array2 = array; array = A_QA[num & 1]; for (int i = 0; i < num; i++) { int a2 = array2[i] - Inlines.MUL32_FRAC_Q(array2[num - i - 1], num2, 31); array[i] = Inlines.MUL32_FRAC_Q(a2, b, num4); } } if (array[0] > A_LIMIT || array[0] < -A_LIMIT) { return 0; } num2 = -Inlines.silk_LSHIFT(array[0], 7); num3 = 1073741824 - Inlines.silk_SMMUL(num2, num2); return Inlines.silk_LSHIFT(Inlines.silk_SMMUL(a, num3), 2); } internal static int silk_LPC_inverse_pred_gain(short[] A_Q12, int order) { int[][] array = Arrays.InitTwoDimensionalArray(2, 16); int num = 0; int[] array2 = array[order & 1]; for (int i = 0; i < order; i++) { num += A_Q12[i]; array2[i] = Inlines.silk_LSHIFT32(A_Q12[i], 12); } if (num >= 4096) { return 0; } return LPC_inverse_pred_gain_QA(array, order); } internal static int silk_LPC_inverse_pred_gain_Q24(int[] A_Q24, int order) { int[][] array = Arrays.InitTwoDimensionalArray(2, 16); int[] array2 = array[order & 1]; for (int i = 0; i < order; i++) { array2[i] = Inlines.silk_RSHIFT32(A_Q24[i], 0); } return LPC_inverse_pred_gain_QA(array, order); } } internal static class LTPAnalysisFilter { internal static void silk_LTP_analysis_filter(short[] LTP_res, short[] x, int x_ptr, short[] LTPCoef_Q14, int[] pitchL, int[] invGains_Q16, int subfr_length, int nb_subfr, int pre_length) { short[] array = new short[5]; int num = x_ptr; int num2 = 0; for (int i = 0; i < nb_subfr; i++) { int num3 = num - pitchL[i]; array[0] = LTPCoef_Q14[i * 5]; array[1] = LTPCoef_Q14[i * 5 + 1]; array[2] = LTPCoef_Q14[i * 5 + 2]; array[3] = LTPCoef_Q14[i * 5 + 3]; array[4] = LTPCoef_Q14[i * 5 + 4]; for (int j = 0; j < subfr_length + pre_length; j++) { int num4 = num2 + j; LTP_res[num4] = x[num + j]; int a = Inlines.silk_SMULBB(x[num3 + 2], array[0]); a = Inlines.silk_SMLABB_ovflw(a, x[num3 + 1], array[1]); a = Inlines.silk_SMLABB_ovflw(a, x[num3], array[2]); a = Inlines.silk_SMLABB_ovflw(a, x[num3 - 1], array[3]); a = Inlines.silk_SMLABB_ovflw(a, x[num3 - 2], array[4]); a = Inlines.silk_RSHIFT_ROUND(a, 14); LTP_res[num4] = (short)Inlines.silk_SAT16(x[num + j] - a); LTP_res[num4] = (short)Inlines.silk_SMULWB(invGains_Q16[i], LTP_res[num4]); num3++; } num2 += subfr_length + pre_length; num += subfr_length; } } } internal static class LTPScaleControl { internal static void silk_LTP_scale_ctrl(SilkChannelEncoder psEnc, SilkEncoderControl psEncCtrl, int condCoding) { if (condCoding == 0) { int a = psEnc.PacketLoss_perc + psEnc.nFramesPerPacket; psEnc.indices.LTP_scaleIndex = (sbyte)Inlines.silk_LIMIT(Inlines.silk_SMULWB(Inlines.silk_SMULBB(a, psEncCtrl.LTPredCodGain_Q7), 51), 0, 2); } else { psEnc.indices.LTP_scaleIndex = 0; } psEncCtrl.LTP_scale_Q14 = Tables.silk_LTPScales_table_Q14[psEnc.indices.LTP_scaleIndex]; } } internal static class NLSF { private const int MAX_STABILIZE_LOOPS = 20; private const int QA = 16; private const int BIN_DIV_STEPS_A2NLSF = 3; private const int MAX_ITERATIONS_A2NLSF = 30; private static readonly byte[] ordering16 = new byte[16] { 0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1 }; private static readonly byte[] ordering10 = new byte[10] { 0, 9, 6, 3, 4, 5, 8, 1, 2, 7 }; internal static void silk_NLSF_VQ(int[] err_Q26, short[] in_Q15, byte[] pCB_Q8, int K, int LPC_order) { int num = 0; for (int i = 0; i < K; i++) { int num2 = 0; for (int j = 0; j < LPC_order; j += 2) { int num3 = Inlines.silk_SUB_LSHIFT32(in_Q15[j], pCB_Q8[num++], 7); int a = Inlines.silk_SMULBB(num3, num3); num3 = Inlines.silk_SUB_LSHIFT32(in_Q15[j + 1], pCB_Q8[num++], 7); a = Inlines.silk_SMLABB(a, num3, num3); num2 = Inlines.silk_ADD_RSHIFT32(num2, a, 4); } err_Q26[i] = num2; } } internal static void silk_NLSF_VQ_weights_laroia(short[] pNLSFW_Q_OUT, short[] pNLSF_Q15, int D) { int b = Inlines.silk_max_int(pNLSF_Q15[0], 1); b = Inlines.silk_DIV32(131072, b); int b2 = Inlines.silk_max_int(pNLSF_Q15[1] - pNLSF_Q15[0], 1); b2 = Inlines.silk_DIV32(131072, b2); pNLSFW_Q_OUT[0] = (short)Inlines.silk_min_int(b + b2, 32767); for (int i = 1; i < D - 1; i += 2) { b = Inlines.silk_max_int(pNLSF_Q15[i + 1] - pNLSF_Q15[i], 1); b = Inlines.silk_DIV32(131072, b); pNLSFW_Q_OUT[i] = (short)Inlines.silk_min_int(b + b2, 32767); b2 = Inlines.silk_max_int(pNLSF_Q15[i + 2] - pNLSF_Q15[i + 1], 1); b2 = Inlines.silk_DIV32(131072, b2); pNLSFW_Q_OUT[i + 1] = (short)Inlines.silk_min_int(b + b2, 32767); } b = Inlines.silk_max_int(32768 - pNLSF_Q15[D - 1], 1); b = Inlines.silk_DIV32(131072, b); pNLSFW_Q_OUT[D - 1] = (short)Inlines.silk_min_int(b + b2, 32767); } internal static void silk_NLSF_residual_dequant(short[] x_Q10, sbyte[] indices, int indices_ptr, byte[] pred_coef_Q8, int quant_step_size_Q16, short order) { short a = 0; for (int num = order - 1; num >= 0; num--) { int a2 = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(a, pred_coef_Q8[num]), 8); a = Inlines.silk_LSHIFT16(indices[indices_ptr + num], 10); if (a > 0) { a = Inlines.silk_SUB16(a, 102); } else if (a < 0) { a = Inlines.silk_ADD16(a, 102); } a = (x_Q10[num] = (short)Inlines.silk_SMLAWB(a2, a, quant_step_size_Q16)); } } internal static void silk_NLSF_unpack(short[] ec_ix, byte[] pred_Q8, NLSFCodebook psNLSF_CB, int CB1_index) { byte[] ec_sel = psNLSF_CB.ec_sel; int num = CB1_index * psNLSF_CB.order / 2; for (int i = 0; i < psNLSF_CB.order; i += 2) { byte b = ec_sel[num]; num++; ec_ix[i] = (short)Inlines.silk_SMULBB(Inlines.silk_RSHIFT(b, 1) & 7, 9); pred_Q8[i] = psNLSF_CB.pred_Q8[i + (b & 1) * (psNLSF_CB.order - 1)]; ec_ix[i + 1] = (short)Inlines.silk_SMULBB(Inlines.silk_RSHIFT(b, 5) & 7, 9); pred_Q8[i + 1] = psNLSF_CB.pred_Q8[i + (Inlines.silk_RSHIFT(b, 4) & 1) * (psNLSF_CB.order - 1) + 1]; } } internal static void silk_NLSF_stabilize(short[] NLSF_Q15, short[] NDeltaMin_Q15, int L) { int num = 0; int i; for (i = 0; i < 20; i++) { int num2 = NLSF_Q15[0] - NDeltaMin_Q15[0]; num = 0; int num3; for (int j = 1; j <= L - 1; j++) { num3 = NLSF_Q15[j] - (NLSF_Q15[j - 1] + NDeltaMin_Q15[j]); if (num3 < num2) { num2 = num3; num = j; } } num3 = 32768 - (NLSF_Q15[L - 1] + NDeltaMin_Q15[L]); if (num3 < num2) { num2 = num3; num = L; } if (num2 >= 0) { return; } if (num == 0) { NLSF_Q15[0] = NDeltaMin_Q15[0]; continue; } if (num == L) { NLSF_Q15[L - 1] = (short)(32768 - NDeltaMin_Q15[L]); continue; } int num4 = 0; for (int k = 0; k < num; k++) { num4 += NDeltaMin_Q15[k]; } num4 += Inlines.silk_RSHIFT(NDeltaMin_Q15[num], 1); int num5 = 32768; for (int k = L; k > num; k--) { num5 -= NDeltaMin_Q15[k]; } num5 -= Inlines.silk_RSHIFT(NDeltaMin_Q15[num], 1); short num6 = (short)Inlines.silk_LIMIT_32(Inlines.silk_RSHIFT_ROUND(NLSF_Q15[num - 1] + NLSF_Q15[num], 1), num4, num5); NLSF_Q15[num - 1] = (short)(num6 - Inlines.silk_RSHIFT(NDeltaMin_Q15[num], 1)); NLSF_Q15[num] = (short)(NLSF_Q15[num - 1] + NDeltaMin_Q15[num]); } if (i == 20) { Sort.silk_insertion_sort_increasing_all_values_int16(NLSF_Q15, L); NLSF_Q15[0] = (short)Inlines.silk_max_int(NLSF_Q15[0], NDeltaMin_Q15[0]); for (int j = 1; j < L; j++) { NLSF_Q15[j] = (short)Inlines.silk_max_int(NLSF_Q15[j], NLSF_Q15[j - 1] + NDeltaMin_Q15[j]); } NLSF_Q15[L - 1] = (short)Inlines.silk_min_int(NLSF_Q15[L - 1], 32768 - NDeltaMin_Q15[L]); for (int j = L - 2; j >= 0; j--) { NLSF_Q15[j] = (short)Inlines.silk_min_int(NLSF_Q15[j], NLSF_Q15[j + 1] - NDeltaMin_Q15[j + 1]); } } } internal static void silk_NLSF_decode(short[] pNLSF_Q15, sbyte[] NLSFIndices, NLSFCodebook psNLSF_CB) { byte[] array = new byte[psNLSF_CB.order]; short[] ec_ix = new short[psNLSF_CB.order]; short[] array2 = new short[psNLSF_CB.order]; short[] array3 = new short[psNLSF_CB.order]; byte[] cB1_NLSF_Q = psNLSF_CB.CB1_NLSF_Q8; int num = NLSFIndices[0] * psNLSF_CB.order; for (int i = 0; i < psNLSF_CB.order; i++) { pNLSF_Q15[i] = Inlines.silk_LSHIFT16(cB1_NLSF_Q[num + i], 7); } silk_NLSF_unpack(ec_ix, array, psNLSF_CB, NLSFIndices[0]); silk_NLSF_residual_dequant(array2, NLSFIndices, 1, array, psNLSF_CB.quantStepSize_Q16, psNLSF_CB.order); silk_NLSF_VQ_weights_laroia(array3, pNLSF_Q15, psNLSF_CB.order); for (int i = 0; i < psNLSF_CB.order; i++) { int num2 = Inlines.silk_SQRT_APPROX(Inlines.silk_LSHIFT(array3[i], 16)); int a = Inlines.silk_ADD32(pNLSF_Q15[i], Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(array2[i], 14), (short)num2)); pNLSF_Q15[i] = (short)Inlines.silk_LIMIT(a, 0, 32767); } silk_NLSF_stabilize(pNLSF_Q15, psNLSF_CB.deltaMin_Q15, psNLSF_CB.order); } internal static int silk_NLSF_del_dec_quant(sbyte[] indices, short[] x_Q10, short[] w_Q5, byte[] pred_coef_Q8, short[] ec_ix, byte[] ec_rates_Q5, int quant_step_size_Q16, short inv_quant_step_size_Q6, int mu_Q20, short order) { int[] array = new int[4]; sbyte[][] array2 = new sbyte[4][]; int i; for (i = 0; i < 4; i++) { array2[i] = new sbyte[16]; } short[] array3 = new short[8]; int[] array4 = new int[8]; int[] array5 = new int[4]; int[] array6 = new int[4]; int[] array7 = new int[20]; int[] array8 = new int[20]; for (i = -10; i <= 9; i++) { int num = Inlines.silk_LSHIFT(i, 10); int num2 = Inlines.silk_ADD16((short)num, 1024); if (i > 0) { num = Inlines.silk_SUB16((short)num, 102); num2 = Inlines.silk_SUB16((short)num2, 102); } else { switch (i) { case 0: num2 = Inlines.silk_SUB16((short)num2, 102); break; case -1: num = Inlines.silk_ADD16((short)num, 102); break; default: num = Inlines.silk_ADD16((short)num, 102); num2 = Inlines.silk_ADD16((short)num2, 102); break; } } array7[i + 10] = Inlines.silk_SMULWB(num, quant_step_size_Q16); array8[i + 10] = Inlines.silk_SMULWB(num2, quant_step_size_Q16); } int num3 = 1; array4[0] = 0; array3[0] = 0; i = order - 1; int a2; while (true) { bool flag = true; int a = Inlines.silk_LSHIFT(pred_coef_Q8[i], 8); int num4 = x_Q10[i]; for (int j = 0; j < num3; j++) { int num5 = Inlines.silk_SMULWB(a, array3[j]); int b = Inlines.silk_SUB16((short)num4, (short)num5); a2 = Inlines.silk_SMULWB(inv_quant_step_size_Q6, b); a2 = Inlines.silk_LIMIT(a2, -10, 9); array2[j][i] = (sbyte)a2; int num6 = ec_ix[i] + a2; int num = array7[a2 + 10]; int num2 = array8[a2 + 10]; num = Inlines.silk_ADD16((short)num, (short)num5); num2 = Inlines.silk_ADD16((short)num2, (short)num5); array3[j] = (short)num; array3[j + num3] = (short)num2; int num7; int c; if (a2 + 1 >= 4) { if (a2 + 1 == 4) { num7 = ec_rates_Q5[num6 + 4]; c = 280; } else { num7 = Inlines.silk_SMLABB(108, 43, a2); c = Inlines.silk_ADD16((short)num7, 43); } } else if (a2 <= -4) { if (a2 == -4) { num7 = 280; c = ec_rates_Q5[num6 + 1 + 4]; } else { num7 = Inlines.silk_SMLABB(108, -43, a2); c = Inlines.silk_SUB16((short)num7, 43); } } else { num7 = ec_rates_Q5[num6 + 4]; c = ec_rates_Q5[num6 + 1 + 4]; } int a3 = array4[j]; int num8 = Inlines.silk_SUB16((short)num4, (short)num); array4[j] = Inlines.silk_SMLABB(Inlines.silk_MLA(a3, Inlines.silk_SMULBB(num8, num8), w_Q5[i]), mu_Q20, num7); num8 = Inlines.silk_SUB16((short)num4, (short)num2); array4[j + num3] = Inlines.silk_SMLABB(Inlines.silk_MLA(a3, Inlines.silk_SMULBB(num8, num8), w_Q5[i]), mu_Q20, c); } if (num3 <= 2) { for (int j = 0; j < num3; j++) { array2[j + num3][i] = (sbyte)(array2[j][i] + 1); } num3 = Inlines.silk_LSHIFT(num3, 1); for (int j = num3; j < 4; j++) { array2[j][i] = array2[j - num3][i]; } } else { if (i <= 0) { break; } for (int j = 0; j < 4; j++) { if (array4[j] > array4[j + 4]) { array6[j] = array4[j]; array5[j] = array4[j + 4]; array4[j] = array5[j]; array4[j + 4] = array6[j]; int num = array3[j]; array3[j] = array3[j + 4]; array3[j + 4] = (short)num; array[j] = j + 4; } else { array5[j] = array4[j]; array6[j] = array4[j + 4]; array[j] = j; } } while (true) { flag = true; int num9 = int.MaxValue; int num10 = 0; int num11 = 0; int num12 = 0; for (int j = 0; j < 4; j++) { if (num9 > array6[j]) { num9 = array6[j]; num11 = j; } if (num10 < array5[j]) { num10 = array5[j]; num12 = j; } } if (num9 >= num10) { break; } array[num12] = array[num11] ^ 4; array4[num12] = array4[num11 + 4]; array3[num12] = array3[num11 + 4]; array5[num12] = 0; array6[num11] = int.MaxValue; Buffer.BlockCopy(array2[num11], 0, array2[num12], 0, order); } for (int j = 0; j < 4; j++) { sbyte b2 = (sbyte)Inlines.silk_RSHIFT(array[j], 2); array2[j][i] += b2; } } i--; } a2 = 0; int num13 = int.MaxValue; for (int j = 0; j < 8; j++) { if (num13 > array4[j]) { num13 = array4[j]; a2 = j; } } for (int j = 0; j < order; j++) { indices[j] = array2[a2 & 3][j]; } indices[0] = (sbyte)(indices[0] + Inlines.silk_RSHIFT(a2, 2)); return num13; } internal static int silk_NLSF_encode(sbyte[] NLSFIndices, short[] pNLSF_Q15, NLSFCodebook psNLSF_CB, short[] pW_QW, int NLSF_mu_Q20, int nSurvivors, int signalType) { short[] array = new short[psNLSF_CB.order]; short[] array2 = new short[psNLSF_CB.order]; short[] array3 = new short[psNLSF_CB.order]; short[] array4 = new short[psNLSF_CB.order]; short[] array5 = new short[psNLSF_CB.order]; byte[] array6 = new byte[psNLSF_CB.order]; short[] ec_ix = new short[psNLSF_CB.order]; byte[] cB1_NLSF_Q = psNLSF_CB.CB1_NLSF_Q8; silk_NLSF_stabilize(pNLSF_Q15, psNLSF_CB.deltaMin_Q15, psNLSF_CB.order); int[] array7 = new int[psNLSF_CB.nVectors]; silk_NLSF_VQ(array7, pNLSF_Q15, psNLSF_CB.CB1_NLSF_Q8, psNLSF_CB.nVectors, psNLSF_CB.order); int[] array8 = new int[nSurvivors]; Sort.silk_insertion_sort_increasing(array7, array8, psNLSF_CB.nVectors, nSurvivors); int[] array9 = new int[nSurvivors]; sbyte[][] array10 = Arrays.InitTwoDimensionalArray(nSurvivors, 16); for (int i = 0; i < nSurvivors; i++) { int num = array8[i]; int num2 = num * psNLSF_CB.order; for (int j = 0; j < psNLSF_CB.order; j++) { array3[j] = Inlines.silk_LSHIFT16(cB1_NLSF_Q[num2 + j], 7); array[j] = (short)(pNLSF_Q15[j] - array3[j]); } silk_NLSF_VQ_weights_laroia(array4, array3, psNLSF_CB.order); for (int j = 0; j < psNLSF_CB.order; j++) { int b = Inlines.silk_SQRT_APPROX(Inlines.silk_LSHIFT(array4[j], 16)); array2[j] = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(array[j], b), 14); } for (int j = 0; j < psNLSF_CB.order; j++) { array5[j] = (short)Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(pW_QW[j], 5), array4[j]); } silk_NLSF_unpack(ec_ix, array6, psNLSF_CB, num); array9[i] = silk_NLSF_del_dec_quant(array10[i], array2, array5, array6, ec_ix, psNLSF_CB.ec_Rates_Q5, psNLSF_CB.quantStepSize_Q16, psNLSF_CB.invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB.order); int num3 = (signalType >> 1) * psNLSF_CB.nVectors; int inLin = ((num != 0) ? (psNLSF_CB.CB1_iCDF[num3 + num - 1] - psNLSF_CB.CB1_iCDF[num3 + num]) : (256 - psNLSF_CB.CB1_iCDF[num3 + num])); int b2 = 1024 - Inlines.silk_lin2log(inLin); array9[i] = Inlines.silk_SMLABB(array9[i], b2, Inlines.silk_RSHIFT(NLSF_mu_Q20, 2)); } int[] array11 = new int[1]; Sort.silk_insertion_sort_increasing(array9, array11, nSurvivors, 1); NLSFIndices[0] = (sbyte)array8[array11[0]]; Array.Copy(array10[array11[0]], 0, NLSFIndices, 1, psNLSF_CB.order); silk_NLSF_decode(pNLSF_Q15, NLSFIndices, psNLSF_CB); return array9[0]; } internal static void silk_NLSF2A_find_poly(int[] o, int[] cLSF, int cLSF_ptr, int dd) { o[0] = Inlines.silk_LSHIFT(1, 16); o[1] = -cLSF[cLSF_ptr]; for (int i = 1; i < dd; i++) { int num = cLSF[cLSF_ptr + 2 * i]; o[i + 1] = Inlines.silk_LSHIFT(o[i - 1], 1) - (int)Inlines.silk_RSHIFT_ROUND64(Inlines.silk_SMULL(num, o[i]), 16); for (int num2 = i; num2 > 1; num2--) { o[num2] += o[num2 - 2] - (int)Inlines.silk_RSHIFT_ROUND64(Inlines.silk_SMULL(num, o[num2 - 1]), 16); } o[1] -= num; } } internal static void silk_NLSF2A(short[] a_Q12, short[] NLSF, int d) { int[] array = new int[d]; int[] array2 = new int[d / 2 + 1]; int[] array3 = new int[d / 2 + 1]; int[] array4 = new int[d]; int num = 0; byte[] array5 = ((d == 16) ? ordering16 : ordering10); for (int i = 0; i < d; i++) { int num2 = Inlines.silk_RSHIFT(NLSF[i], 8); int b = NLSF[i] - Inlines.silk_LSHIFT(num2, 8); int num3 = Tables.silk_LSFCosTab_Q12[num2]; int a = Tables.silk_LSFCosTab_Q12[num2 + 1] - num3; array[array5[i]] = Inlines.silk_RSHIFT_ROUND(Inlines.silk_LSHIFT(num3, 8) + Inlines.silk_MUL(a, b), 4); } int num4 = Inlines.silk_RSHIFT(d, 1); silk_NLSF2A_find_poly(array2, array, 0, num4); silk_NLSF2A_find_poly(array3, array, 1, num4); for (int i = 0; i < num4; i++) { int num5 = array2[i + 1] + array2[i]; int num6 = array3[i + 1] - array3[i]; array4[i] = -num6 - num5; array4[d - i - 1] = num6 - num5; } int j; for (j = 0; j < 10; j++) { int num7 = 0; for (int i = 0; i < d; i++) { int num8 = Inlines.silk_abs(array4[i]); if (num8 > num7) { num7 = num8; num = i; } } num7 = Inlines.silk_RSHIFT_ROUND(num7, 5); if (num7 > 32767) { num7 = Inlines.silk_min(num7, 163838); int chirp_Q = 65470 - Inlines.silk_DIV32(Inlines.silk_LSHIFT(num7 - 32767, 14), Inlines.silk_RSHIFT32(Inlines.silk_MUL(num7, num + 1), 2)); Filters.silk_bwexpander_32(array4, d, chirp_Q); continue; } break; } if (j == 10) { for (int i = 0; i < d; i++) { a_Q12[i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(array4[i], 5)); array4[i] = Inlines.silk_LSHIFT(a_Q12[i], 5); } } else { for (int i = 0; i < d; i++) { a_Q12[i] = (short)Inlines.silk_RSHIFT_ROUND(array4[i], 5); } } for (j = 0; j < 16; j++) { if (Filters.silk_LPC_inverse_pred_gain(a_Q12, d) >= 107374) { break; } Filters.silk_bwexpander_32(array4, d, 65536 - Inlines.silk_LSHIFT(2, j)); for (int i = 0; i < d; i++) { a_Q12[i] = (short)Inlines.silk_RSHIFT_ROUND(array4[i], 5); } } } internal static void silk_A2NLSF_trans_poly(int[] p, int dd) { for (int i = 2; i <= dd; i++) { for (int num = dd; num > i; num--) { p[num - 2] -= p[num]; } p[i - 2] -= Inlines.silk_LSHIFT(p[i], 1); } } internal static int silk_A2NLSF_eval_poly(int[] p, int x, int dd) { int num = p[dd]; int c = Inlines.silk_LSHIFT(x, 4); if (8 == dd) { num = Inlines.silk_SMLAWW(p[7], num, c); num = Inlines.silk_SMLAWW(p[6], num, c); num = Inlines.silk_SMLAWW(p[5], num, c); num = Inlines.silk_SMLAWW(p[4], num, c); num = Inlines.silk_SMLAWW(p[3], num, c); num = Inlines.silk_SMLAWW(p[2], num, c); num = Inlines.silk_SMLAWW(p[1], num, c); num = Inlines.silk_SMLAWW(p[0], num, c); } else { for (int num2 = dd - 1; num2 >= 0; num2--) { num = Inlines.silk_SMLAWW(p[num2], num, c); } } return num; } internal static void silk_A2NLSF_init(int[] a_Q16, int[] P, int[] Q, int dd) { P[dd] = Inlines.silk_LSHIFT(1, 16); Q[dd] = Inlines.silk_LSHIFT(1, 16); for (int i = 0; i < dd; i++) { P[i] = -a_Q16[dd - i - 1] - a_Q16[dd + i]; Q[i] = -a_Q16[dd - i - 1] + a_Q16[dd + i]; } for (int i = dd; i > 0; i--) { P[i - 1] -= P[i]; Q[i - 1] += Q[i]; } silk_A2NLSF_trans_poly(P, dd); silk_A2NLSF_trans_poly(Q, dd); } internal static void silk_A2NLSF(short[] NLSF, int[] a_Q16, int d) { int[] array = new int[9]; int[] array2 = new int[9]; int[][] array3 = new int[2][] { array, array2 }; int dd = Inlines.silk_RSHIFT(d, 1); silk_A2NLSF_init(a_Q16, array, array2, dd); int[] p = array; int num = Tables.silk_LSFCosTab_Q12[0]; int num2 = silk_A2NLSF_eval_poly(p, num, dd); int num3; if (num2 < 0) { NLSF[0] = 0; p = array2; num2 = silk_A2NLSF_eval_poly(p, num, dd); num3 = 1; } else { num3 = 0; } int num4 = 1; int num5 = 0; int num6 = 0; while (true) { bool flag = true; int num7 = Tables.silk_LSFCosTab_Q12[num4]; int num8 = silk_A2NLSF_eval_poly(p, num7, dd); if ((num2 <= 0 && num8 >= num6) || (num2 >= 0 && num8 <= -num6)) { num6 = ((num8 == 0) ? 1 : 0); int num9 = -256; for (int i = 0; i < 3; i++) { int num10 = Inlines.silk_RSHIFT_ROUND(num + num7, 1); int num11 = silk_A2NLSF_eval_poly(p, num10, dd); if ((num2 <= 0 && num11 >= 0) || (num2 >= 0 && num11 <= 0)) { num7 = num10; num8 = num11; } else { num = num10; num2 = num11; num9 = Inlines.silk_ADD_RSHIFT(num9, 128, i); } } if (Inlines.silk_abs(num2) < 65536) { int num12 = num2 - num8; int a = Inlines.silk_LSHIFT(num2, 5) + Inlines.silk_RSHIFT(num12, 1); if (num12 != 0) { num9 += Inlines.silk_DIV32(a, num12); } } else { num9 += Inlines.silk_DIV32(num2, Inlines.silk_RSHIFT(num2 - num8, 5)); } NLSF[num3] = (short)Inlines.silk_min_32(Inlines.silk_LSHIFT(num4, 8) + num9, 32767); num3++; if (num3 >= d) { return; } p = array3[num3 & 1]; num = Tables.silk_LSFCosTab_Q12[num4 - 1]; num2 = Inlines.silk_LSHIFT(1 - (num3 & 2), 12); continue; } num4++; num = num7; num2 = num8; num6 = 0; if (num4 > 128) { num5++; if (num5 > 30) { break; } Filters.silk_bwexpander_32(a_Q16, d, 65536 - Inlines.silk_SMULBB(10 + num5, num5)); silk_A2NLSF_init(a_Q16, array, array2, dd); p = array; num = Tables.silk_LSFCosTab_Q12[0]; num2 = silk_A2NLSF_eval_poly(p, num, dd); if (num2 < 0) { NLSF[0] = 0; p = array2; num2 = silk_A2NLSF_eval_poly(p, num, dd); num3 = 1; } else { num3 = 0; } num4 = 1; } } NLSF[0] = (short)Inlines.silk_DIV32_16(32768, (short)(d + 1)); for (num4 = 1; num4 < d; num4++) { NLSF[num4] = (short)Inlines.silk_SMULBB(num4 + 1, NLSF[0]); } } internal static void silk_process_NLSFs(SilkChannelEncoder psEncC, short[][] PredCoef_Q12, short[] pNLSF_Q15, short[] prev_NLSFq_Q15) { short[] array = new short[16]; short[] array2 = new short[16]; short[] array3 = new short[16]; int num = Inlines.silk_SMLAWB(3146, -268434, psEncC.speech_activity_Q8); if (psEncC.nb_subfr == 2) { num = Inlines.silk_ADD_RSHIFT(num, num, 1); } silk_NLSF_VQ_weights_laroia(array2, pNLSF_Q15, psEncC.predictLPCOrder); bool flag = psEncC.useInterpolatedNLSFs == 1 && psEncC.indices.NLSFInterpCoef_Q2 < 4; if (flag) { Inlines.silk_interpolate(array, prev_NLSFq_Q15, pNLSF_Q15, psEncC.indices.NLSFInterpCoef_Q2, psEncC.predictLPCOrder); silk_NLSF_VQ_weights_laroia(array3, array, psEncC.predictLPCOrder); int c = Inlines.silk_LSHIFT(Inlines.silk_SMULBB(psEncC.indices.NLSFInterpCoef_Q2, psEncC.indices.NLSFInterpCoef_Q2), 11); for (int i = 0; i < psEncC.predictLPCOrder; i++) { array2[i] = (short)Inlines.silk_SMLAWB(Inlines.silk_RSHIFT(array2[i], 1), array3[i], c); } } silk_NLSF_encode(psEncC.indices.NLSFIndices, pNLSF_Q15, psEncC.psNLSF_CB, array2, num, psEncC.NLSF_MSVQ_Survivors, psEncC.indices.signalType); silk_NLSF2A(PredCoef_Q12[1], pNLSF_Q15, psEncC.predictLPCOrder); if (flag) { Inlines.silk_interpolate(array, prev_NLSFq_Q15, pNLSF_Q15, psEncC.indices.NLSFInterpCoef_Q2, psEncC.predictLPCOrder); silk_NLSF2A(PredCoef_Q12[0], array, psEncC.predictLPCOrder); } else { Array.Copy(PredCoef_Q12[1], 0, PredCoef_Q12[0], 0, psEncC.predictLPCOrder); } } } internal static class NoiseShapeAnalysis { internal static int warped_gain(int[] coefs_Q24, int lambda_Q16, int order) { lambda_Q16 = -lambda_Q16; int b = coefs_Q24[order - 1]; for (int num = order - 2; num >= 0; num--) { b = Inlines.silk_SMLAWB(coefs_Q24[num], b, lambda_Q16); } b = Inlines.silk_SMLAWB(16777216, b, -lambda_Q16); return Inlines.silk_INVERSE32_varQ(b, 40); } internal static void limit_warped_coefs(int[] coefs_syn_Q24, int[] coefs_ana_Q24, int lambda_Q16, int limit_Q24, int order) { int num = 0; lambda_Q16 = -lambda_Q16; for (int num2 = order - 1; num2 > 0; num2--) { coefs_syn_Q24[num2 - 1] = Inlines.silk_SMLAWB(coefs_syn_Q24[num2 - 1], coefs_syn_Q24[num2], lambda_Q16); coefs_ana_Q24[num2 - 1] = Inlines.silk_SMLAWB(coefs_ana_Q24[num2 - 1], coefs_ana_Q24[num2], lambda_Q16); } lambda_Q16 = -lambda_Q16; int a = Inlines.silk_SMLAWB(65536, -lambda_Q16, lambda_Q16); int b = Inlines.silk_SMLAWB(16777216, coefs_syn_Q24[0], lambda_Q16); int num3 = Inlines.silk_DIV32_varQ(a, b, 24); b = Inlines.silk_SMLAWB(16777216, coefs_ana_Q24[0], lambda_Q16); int num4 = Inlines.silk_DIV32_varQ(a, b, 24); for (int num2 = 0; num2 < order; num2++) { coefs_syn_Q24[num2] = Inlines.silk_SMULWW(num3, coefs_syn_Q24[num2]); coefs_ana_Q24[num2] = Inlines.silk_SMULWW(num4, coefs_ana_Q24[num2]); } for (int i = 0; i < 10; i++) { int num5 = -1; for (int num2 = 0; num2 < order; num2++) { int num6 = Inlines.silk_max(Inlines.silk_abs_int32(coefs_syn_Q24[num2]), Inlines.silk_abs_int32(coefs_ana_Q24[num2])); if (num6 > num5) { num5 = num6; num = num2; } } if (num5 <= limit_Q24) { break; } for (int num2 = 1; num2 < order; num2++) { coefs_syn_Q24[num2 - 1] = Inlines.silk_SMLAWB(coefs_syn_Q24[num2 - 1], coefs_syn_Q24[num2], lambda_Q16); coefs_ana_Q24[num2 - 1] = Inlines.silk_SMLAWB(coefs_ana_Q24[num2 - 1], coefs_ana_Q24[num2], lambda_Q16); } num3 = Inlines.silk_INVERSE32_varQ(num3, 32); num4 = Inlines.silk_INVERSE32_varQ(num4, 32); for (int num2 = 0; num2 < order; num2++) { coefs_syn_Q24[num2] = Inlines.silk_SMULWW(num3, coefs_syn_Q24[num2]); coefs_ana_Q24[num2] = Inlines.silk_SMULWW(num4, coefs_ana_Q24[num2]); } int chirp_Q = 64881 - Inlines.silk_DIV32_varQ(Inlines.silk_SMULWB(num5 - limit_Q24, Inlines.silk_SMLABB(819, 102, i)), Inlines.silk_MUL(num5, num + 1), 22); BWExpander.silk_bwexpander_32(coefs_syn_Q24, order, chirp_Q); BWExpander.silk_bwexpander_32(coefs_ana_Q24, order, chirp_Q); lambda_Q16 = -lambda_Q16; for (int num2 = order - 1; num2 > 0; num2--) { coefs_syn_Q24[num2 - 1] = Inlines.silk_SMLAWB(coefs_syn_Q24[num2 - 1], coefs_syn_Q24[num2], lambda_Q16); coefs_ana_Q24[num2 - 1] = Inlines.silk_SMLAWB(coefs_ana_Q24[num2 - 1], coefs_ana_Q24[num2], lambda_Q16); } lambda_Q16 = -lambda_Q16; a = Inlines.silk_SMLAWB(65536, -lambda_Q16, lambda_Q16); b = Inlines.silk_SMLAWB(16777216, coefs_syn_Q24[0], lambda_Q16); num3 = Inlines.silk_DIV32_varQ(a, b, 24); b = Inlines.silk_SMLAWB(16777216, coefs_ana_Q24[0], lambda_Q16); num4 = Inlines.silk_DIV32_varQ(a, b, 24); for (int num2 = 0; num2 < order; num2++) { coefs_syn_Q24[num2] = Inlines.silk_SMULWW(num3, coefs_syn_Q24[num2]); coefs_ana_Q24[num2] = Inlines.silk_SMULWW(num4, coefs_ana_Q24[num2]); } } } internal static void silk_noise_shape_analysis(SilkChannelEncoder psEnc, SilkEncoderControl psEncCtrl, short[] pitch_res, int pitch_res_ptr, short[] x, int x_ptr) { SilkShapeState sShape = psEnc.sShape; int shift = 0; int[] array = new int[17]; int[] rc_Q = new int[16]; int[] array2 = new int[16]; int[] array3 = new int[16]; int num = x_ptr - psEnc.la_shape; int num2 = psEnc.SNR_dB_Q7; psEncCtrl.input_quality_Q14 = Inlines.silk_RSHIFT(psEnc.input_quality_bands_Q15[0] + psEnc.input_quality_bands_Q15[1], 2); psEncCtrl.coding_quality_Q14 = Inlines.silk_RSHIFT(Sigmoid.silk_sigm_Q15(Inlines.silk_RSHIFT_ROUND(num2 - 2560, 4)), 1); if (psEnc.useCBR == 0) { int num3 = 256 - psEnc.speech_activity_Q8; num3 = Inlines.silk_SMULWB(Inlines.silk_LSHIFT(num3, 8), num3); num2 = Inlines.silk_SMLAWB(num2, Inlines.silk_SMULBB(-8, num3), Inlines.silk_SMULWB(16384 + psEncCtrl.input_quality_Q14, psEncCtrl.coding_quality_Q14)); } num2 = ((psEnc.indices.signalType != 2) ? Inlines.silk_SMLAWB(num2, Inlines.silk_SMLAWB(3072, -104858, psEnc.SNR_dB_Q7), 16384 - psEncCtrl.input_quality_Q14) : Inlines.silk_SMLAWB(num2, 512, psEnc.LTPCorr_Q15)); if (psEnc.indices.signalType == 2) { psEnc.indices.quantOffsetType = 0; psEncCtrl.sparseness_Q8 = 0; } else { int num4 = Inlines.silk_LSHIFT(psEnc.fs_kHz, 1); int num5 = 0; int num6 = 0; int num7 = pitch_res_ptr; for (int i = 0; i < Inlines.silk_SMULBB(5, psEnc.nb_subfr) / 2; i++) { SumSqrShift.silk_sum_sqr_shift(out var energy, out shift, pitch_res, num7, num4); energy += Inlines.silk_RSHIFT(num4, shift); int num8 = Inlines.silk_lin2log(energy); if (i > 0) { num5 += Inlines.silk_abs(num8 - num6); } num6 = num8; num7 += num4; } psEncCtrl.sparseness_Q8 = Inlines.silk_RSHIFT(Sigmoid.silk_sigm_Q15(Inlines.silk_SMULWB(num5 - 640, 6554)), 7); if (psEncCtrl.sparseness_Q8 > 192) { psEnc.indices.quantOffsetType = 0; } else { psEnc.indices.quantOffsetType = 1; } num2 = Inlines.silk_SMLAWB(num2, 65536, psEncCtrl.sparseness_Q8 - 128); } int num9 = Inlines.silk_SMULWB(psEncCtrl.predGain_Q16, 66); int a; int a2 = (a = Inlines.silk_DIV32_varQ(62259, Inlines.silk_SMLAWW(65536, num9, num9), 16)); int b = Inlines.silk_SMULWB(65536 - Inlines.silk_SMULBB(3, psEncCtrl.coding_quality_Q14), 655); a2 = Inlines.silk_SUB32(a2, b); a = Inlines.silk_ADD32(a, b); a2 = Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(a2, 14), Inlines.silk_RSHIFT(a, 2)); int num10 = ((psEnc.warping_Q16 > 0) ? Inlines.silk_SMLAWB(psEnc.warping_Q16, psEncCtrl.coding_quality_Q14, 2621) : 0); short[] array4 = new short[psEnc.shapeWinLength]; int b2; for (int i = 0; i < psEnc.nb_subfr; i++) { int num11 = psEnc.fs_kHz * 3; int num12 = Inlines.silk_RSHIFT(psEnc.shapeWinLength - num11, 1); ApplySineWindow.silk_apply_sine_window(array4, 0, x, num, 1, num12); int num13 = num12; Array.Copy(x, num + num13, array4, num13, num11); num13 += num11; ApplySineWindow.silk_apply_sine_window(array4, num13, x, num + num13, 2, num12); num += psEnc.subfr_length; BoxedValue boxedValue = new BoxedValue(shift); if (psEnc.warping_Q16 > 0) { Autocorrelation.silk_warped_autocorrelation(array, boxedValue, array4, num10, psEnc.shapeWinLength, psEnc.shapingLPCOrder); } else { Autocorrelation.silk_autocorr(array, boxedValue, array4, psEnc.shapeWinLength, psEnc.shapingLPCOrder + 1); } shift = boxedValue.Val; array[0] = Inlines.silk_ADD32(array[0], Inlines.silk_max_32(Inlines.silk_SMULWB(Inlines.silk_RSHIFT(array[0], 4), 52), 1)); int energy = Schur.silk_schur64(rc_Q, array, psEnc.shapingLPCOrder); K2A.silk_k2a_Q16(array3, rc_Q, psEnc.shapingLPCOrder); int num14 = -shift; if (((uint)num14 & (true ? 1u : 0u)) != 0) { num14--; energy >>= 1; } int a3 = Inlines.silk_SQRT_APPROX(energy); num14 >>= 1; psEncCtrl.Gains_Q16[i] = Inlines.silk_LSHIFT_SAT32(a3, 16 - num14); if (psEnc.warping_Q16 > 0) { b2 = warped_gain(array3, num10, psEnc.shapingLPCOrder); if (Inlines.silk_SMULWW(Inlines.silk_RSHIFT_ROUND(psEncCtrl.Gains_Q16[i], 1), b2) >= 1073741823) { psEncCtrl.Gains_Q16[i] = int.MaxValue; } else { psEncCtrl.Gains_Q16[i] = Inlines.silk_SMULWW(psEncCtrl.Gains_Q16[i], b2); } } BWExpander.silk_bwexpander_32(array3, psEnc.shapingLPCOrder, a); Array.Copy(array3, array2, psEnc.shapingLPCOrder); BWExpander.silk_bwexpander_32(array2, psEnc.shapingLPCOrder, a2); int a4 = LPCInversePredGain.silk_LPC_inverse_pred_gain_Q24(array3, psEnc.shapingLPCOrder); energy = LPCInversePredGain.silk_LPC_inverse_pred_gain_Q24(array2, psEnc.shapingLPCOrder); a4 = Inlines.silk_LSHIFT32(Inlines.silk_SMULWB(a4, 22938), 1); psEncCtrl.GainsPre_Q14[i] = 4915 + Inlines.silk_DIV32_varQ(a4, energy, 14); limit_warped_coefs(array3, array2, num10, 67092088, psEnc.shapingLPCOrder); for (int j = 0; j < psEnc.shapingLPCOrder; j++) { psEncCtrl.AR1_Q13[i * 16 + j] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(array2[j], 11)); psEncCtrl.AR2_Q13[i * 16 + j] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(array3[j], 11)); } } b2 = Inlines.silk_log2lin(-Inlines.silk_SMLAWB(-2048, num2, 10486)); int b3 = Inlines.silk_log2lin(Inlines.silk_SMLAWB(2048, 256, 10486)); for (int i = 0; i < psEnc.nb_subfr; i++) { psEncCtrl.Gains_Q16[i] = Inlines.silk_SMULWW(psEncCtrl.Gains_Q16[i], b2); psEncCtrl.Gains_Q16[i] = Inlines.silk_ADD_POS_SAT32(psEncCtrl.Gains_Q16[i], b3); } b2 = 65536 + Inlines.silk_RSHIFT_ROUND(Inlines.silk_MLA(3355443, psEncCtrl.coding_quality_Q14, 410), 10); for (int i = 0; i < psEnc.nb_subfr; i++) { psEncCtrl.GainsPre_Q14[i] = Inlines.silk_SMULWB(b2, psEncCtrl.GainsPre_Q14[i]); } num9 = Inlines.silk_MUL(64, Inlines.silk_SMLAWB(4096, 4096, psEnc.input_quality_bands_Q15[0] - 32768)); num9 = Inlines.silk_RSHIFT(Inlines.silk_MUL(num9, psEnc.speech_activity_Q8), 8); int num17; if (psEnc.indices.signalType == 2) { int num15 = Inlines.silk_DIV32_16(3277, psEnc.fs_kHz); for (int i = 0; i < psEnc.nb_subfr; i++) { int num16 = num15 + Inlines.silk_DIV32_16(49152, psEncCtrl.pitchL[i]); psEncCtrl.LF_shp_Q14[i] = Inlines.silk_LSHIFT(16384 - num16 - Inlines.silk_SMULWB(num9, num16), 16); psEncCtrl.LF_shp_Q14[i] |= (num16 - 16384) & 0xFFFF; } num17 = -16384 - Inlines.silk_SMULWB(49152, Inlines.silk_SMULWB(5872026, psEnc.speech_activity_Q8)); } else { int num16 = Inlines.silk_DIV32_16(21299, psEnc.fs_kHz); psEncCtrl.LF_shp_Q14[0] = Inlines.silk_LSHIFT(16384 - num16 - Inlines.silk_SMULWB(num9, Inlines.silk_SMULWB(39322, num16)), 16); psEncCtrl.LF_shp_Q14[0] |= (num16 - 16384) & 0xFFFF; for (int i = 1; i < psEnc.nb_subfr; i++) { psEncCtrl.LF_shp_Q14[i] = psEncCtrl.LF_shp_Q14[0]; } num17 = -16384; } int a5 = Inlines.silk_SMULWB(Inlines.silk_SMULWB(131072 - Inlines.silk_LSHIFT(psEncCtrl.coding_quality_Q14, 3), psEnc.LTPCorr_Q15), 6554); a5 = Inlines.silk_SMLAWB(a5, 65536 - Inlines.silk_LSHIFT(psEncCtrl.input_quality_Q14, 2), 6554); int a6; if (psEnc.indices.signalType == 2) { a6 = Inlines.silk_SMLAWB(19661, 65536 - Inlines.silk_SMULWB(262144 - Inlines.silk_LSHIFT(psEncCtrl.coding_quality_Q14, 4), psEncCtrl.input_quality_Q14), 13107); a6 = Inlines.silk_SMULWB(Inlines.silk_LSHIFT(a6, 1), Inlines.silk_SQRT_APPROX(Inlines.silk_LSHIFT(psEnc.LTPCorr_Q15, 15))); } else { a6 = 0; } for (int i = 0; i < 4; i++) { sShape.HarmBoost_smth_Q16 = Inlines.silk_SMLAWB(sShape.HarmBoost_smth_Q16, a5 - sShape.HarmBoost_smth_Q16, 26214); sShape.HarmShapeGain_smth_Q16 = Inlines.silk_SMLAWB(sShape.HarmShapeGain_smth_Q16, a6 - sShape.HarmShapeGain_smth_Q16, 26214); sShape.Tilt_smth_Q16 = Inlines.silk_SMLAWB(sShape.Tilt_smth_Q16, num17 - sShape.Tilt_smth_Q16, 26214); psEncCtrl.HarmBoost_Q14[i] = Inlines.silk_RSHIFT_ROUND(sShape.HarmBoost_smth_Q16, 2); psEncCtrl.HarmShapeGain_Q14[i] = Inlines.silk_RSHIFT_ROUND(sShape.HarmShapeGain_smth_Q16, 2); psEncCtrl.Tilt_Q14[i] = Inlines.silk_RSHIFT_ROUND(sShape.Tilt_smth_Q16, 2); } } } internal static class PitchAnalysisCore { private class silk_pe_stage3_vals { public readonly int[] Values = new int[5]; } private const int SCRATCH_SIZE = 22; private const int SF_LENGTH_4KHZ = 20; private const int SF_LENGTH_8KHZ = 40; private const int MIN_LAG_4KHZ = 8; private const int MIN_LAG_8KHZ = 16; private const int MAX_LAG_4KHZ = 72; private const int MAX_LAG_8KHZ = 143; private const int CSTRIDE_4KHZ = 65; private const int CSTRIDE_8KHZ = 132; private const int D_COMP_MIN = 13; private const int D_COMP_MAX = 147; private const int D_COMP_STRIDE = 134; internal static int silk_pitch_analysis_core(short[] frame, int[] pitch_out, BoxedValue lagIndex, BoxedValue contourIndex, BoxedValue LTPCorr_Q15, int prevLag, int search_thres1_Q16, int search_thres2_Q13, int Fs_kHz, int complexity, int nb_subfr) { int[] array = new int[6]; int[] array2 = new int[24]; int[] array3 = new int[11]; int num = (20 + nb_subfr * 5) * Fs_kHz; int num2 = (20 + nb_subfr * 5) * 4; int num3 = (20 + nb_subfr * 5) * 8; int num4 = 5 * Fs_kHz; int num5 = 2 * Fs_kHz; int num6 = 18 * Fs_kHz - 1; short[] array4 = new short[num3]; switch (Fs_kHz) { case 16: Arrays.MemSet(array, 0, 2); Resampler.silk_resampler_down2(array, array4, frame, num); break; case 12: Arrays.MemSet(array, 0, 6); Resampler.silk_resampler_down2_3(array, array4, frame, num); break; default: Array.Copy(frame, array4, num3); break; } Arrays.MemSet(array, 0, 2); short[] array5 = new short[num2]; Resampler.silk_resampler_down2(array, array5, array4, num3); for (int num7 = num2 - 1; num7 > 0; num7--) { array5[num7] = Inlines.silk_ADD_SAT16(array5[num7], array5[num7 - 1]); } SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, array5, num2); if (shift > 0) { shift = Inlines.silk_RSHIFT(shift, 1); for (int num7 = 0; num7 < num2; num7++) { array5[num7] = Inlines.silk_RSHIFT16(array5[num7], shift); } } short[] array6 = new short[nb_subfr * 132]; int[] array7 = new int[65]; Arrays.MemSet(array6, (short)0, (nb_subfr >> 1) * 65); short[] array8 = array5; int num8 = Inlines.silk_LSHIFT(20, 2); for (int i = 0; i < nb_subfr >> 1; i++) { short[] array9 = array8; int num9 = num8 - 8; CeltPitchXCorr.pitch_xcorr(array8, num8, array8, num8 - 72, array7, 40, 65); int a = array7[64]; int a2 = Inlines.silk_inner_prod_self(array8, num8, 40); a2 = Inlines.silk_ADD32(a2, Inlines.silk_inner_prod_self(array9, num9, 40)); a2 = Inlines.silk_ADD32(a2, Inlines.silk_SMULBB(40, 4000)); Inlines.MatrixSet(array6, i, 0, 65, (short)Inlines.silk_DIV32_varQ(a, a2, 14)); for (int j = 9; j <= 72; j++) { num9--; a = array7[72 - j]; a2 = Inlines.silk_ADD32(a2, Inlines.silk_SMULBB(array9[num9], array9[num9]) - Inlines.silk_SMULBB(array9[num9 + 40], array9[num9 + 40])); Inlines.MatrixSet(array6, i, j - 8, 65, (short)Inlines.silk_DIV32_varQ(a, a2, 14)); } num8 += 40; } if (nb_subfr == 4) { for (int num7 = 72; num7 >= 8; num7--) { int num10 = Inlines.MatrixGet(array6, 0, num7 - 8, 65) + Inlines.MatrixGet(array6, 1, num7 - 8, 65); num10 = Inlines.silk_SMLAWB(num10, num10, Inlines.silk_LSHIFT(-num7, 4)); array6[num7 - 8] = (short)num10; } } else { for (int num7 = 72; num7 >= 8; num7--) { int num10 = Inlines.silk_LSHIFT(array6[num7 - 8], 1); num10 = Inlines.silk_SMLAWB(num10, num10, Inlines.silk_LSHIFT(-num7, 4)); array6[num7 - 8] = (short)num10; } } int num11 = Inlines.silk_ADD_LSHIFT32(4, complexity, 1); Sort.silk_insertion_sort_decreasing_int16(array6, array2, 65, num11); int num12 = array6[0]; if (num12 < 3277) { Arrays.MemSet(pitch_out, 0, nb_subfr); LTPCorr_Q15.Val = 0; lagIndex.Val = 0; contourIndex.Val = 0; return 1; } int num13 = Inlines.silk_SMULWB(search_thres1_Q16, num12); for (int num7 = 0; num7 < num11; num7++) { if (array6[num7] > num13) { array2[num7] = Inlines.silk_LSHIFT(array2[num7] + 8, 1); continue; } num11 = num7; break; } short[] array10 = new short[134]; for (int num7 = 13; num7 < 147; num7++) { array10[num7 - 13] = 0; } for (int num7 = 0; num7 < num11; num7++) { array10[array2[num7] - 13] = 1; } for (int num7 = 146; num7 >= 16; num7--) { array10[num7 - 13] += (short)(array10[num7 - 1 - 13] + array10[num7 - 2 - 13]); } num11 = 0; for (int num7 = 16; num7 < 144; num7++) { if (array10[num7 + 1 - 13] > 0) { array2[num11] = num7; num11++; } } for (int num7 = 146; num7 >= 16; num7--) { array10[num7 - 13] += (short)(array10[num7 - 1 - 13] + array10[num7 - 2 - 13] + array10[num7 - 3 - 13]); } int num14 = 0; for (int num7 = 16; num7 < 147; num7++) { if (array10[num7 - 13] > 0) { array10[num14] = (short)(num7 - 2); num14++; } } SumSqrShift.silk_sum_sqr_shift(out energy, out shift, array4, num3); if (shift > 0) { shift = Inlines.silk_RSHIFT(shift, 1); for (int num7 = 0; num7 < num3; num7++) { array4[num7] = Inlines.silk_RSHIFT16(array4[num7], shift); } } Arrays.MemSet(array6, (short)0, nb_subfr * 132); array8 = array4; num8 = 160; for (int i = 0; i < nb_subfr; i++) { int a3 = Inlines.silk_ADD32(Inlines.silk_inner_prod(array8, num8, array8, num8, 40), 1); for (int k = 0; k < num14; k++) { int j = array10[k]; short[] array9 = array8; int num9 = num8 - j; int a = Inlines.silk_inner_prod(array8, num8, array9, num9, 40); if (a > 0) { int b = Inlines.silk_inner_prod_self(array9, num9, 40); Inlines.MatrixSet(array6, i, j - 14, 132, (short)Inlines.silk_DIV32_varQ(a, Inlines.silk_ADD32(a3, b), 14)); } else { Inlines.MatrixSet(array6, i, j - 14, 132, (short)0); } } num8 += 40; } int a4 = int.MinValue; int num15 = int.MinValue; int num16 = 0; int num17 = -1; int num18; if (prevLag > 0) { switch (Fs_kHz) { case 12: prevLag = Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(prevLag, 1), 3); break; case 16: prevLag = Inlines.silk_RSHIFT(prevLag, 1); break; } num18 = Inlines.silk_lin2log(prevLag); } else { num18 = 0; } int num19; sbyte[][] array11; if (nb_subfr == 4) { array11 = Tables.silk_CB_lags_stage2; num19 = ((Fs_kHz != 8 || complexity <= 0) ? 3 : 11); } else { array11 = Tables.silk_CB_lags_stage2_10_ms; num19 = 3; } for (int i = 0; i < num11; i++) { int j = array2[i]; for (int k = 0; k < num19; k++) { array3[k] = 0; for (int num7 = 0; num7 < nb_subfr; num7++) { int num20 = j + array11[num7][k]; array3[k] += Inlines.MatrixGet(array6, num7, num20 - 14, 132); } } int num21 = int.MinValue; int num22 = 0; for (int num7 = 0; num7 < num19; num7++) { if (array3[num7] > num21) { num21 = array3[num7]; num22 = num7; } } int num23 = Inlines.silk_lin2log(j); int num24 = num21 - Inlines.silk_RSHIFT(Inlines.silk_SMULBB(nb_subfr * 1638, num23), 7); if (prevLag > 0) { int num25 = num23 - num18; num25 = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(num25, num25), 7); int a5 = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(nb_subfr * 1638, LTPCorr_Q15.Val), 15); a5 = Inlines.silk_DIV32(Inlines.silk_MUL(a5, num25), num25 + 64); num24 -= a5; } if (num24 > num15 && num21 > Inlines.silk_SMULBB(nb_subfr, search_thres2_Q13) && Tables.silk_CB_lags_stage2[0][num22] <= 16) { num15 = num24; a4 = num21; num17 = j; num16 = num22; } } if (num17 == -1) { Arrays.MemSet(pitch_out, 0, nb_subfr); LTPCorr_Q15.Val = 0; lagIndex.Val = 0; contourIndex.Val = 0; return 1; } LTPCorr_Q15.Val = Inlines.silk_LSHIFT(Inlines.silk_DIV32_16(a4, nb_subfr), 2); if (Fs_kHz > 8) { SumSqrShift.silk_sum_sqr_shift(out energy, out shift, frame, num); short[] array13; if (shift > 0) { short[] array12 = new short[num]; shift = Inlines.silk_RSHIFT(shift, 1); for (int num7 = 0; num7 < num; num7++) { array12[num7] = Inlines.silk_RSHIFT16(frame[num7], shift); } array13 = array12; } else { array13 = frame; } int num26 = num16; num17 = Inlines.silk_LIMIT_int(Fs_kHz switch { 12 => Inlines.silk_RSHIFT(Inlines.silk_SMULBB(num17, 3), 1), 16 => Inlines.silk_LSHIFT(num17, 1), _ => Inlines.silk_SMULBB(num17, 3), }, num5, num6); int num27 = Inlines.silk_max_int(num17 - 2, num5); int num28 = Inlines.silk_min_int(num17 + 2, num6); int num29 = num17; num16 = 0; a4 = int.MinValue; for (int i = 0; i < nb_subfr; i++) { pitch_out[i] = num17 + 2 * Tables.silk_CB_lags_stage2[i][num26]; } if (nb_subfr == 4) { num19 = Tables.silk_nb_cbk_searchs_stage3[complexity]; array11 = Tables.silk_CB_lags_stage3; } else { num19 = 12; array11 = Tables.silk_CB_lags_stage3_10_ms; } silk_pe_stage3_vals[] array14 = new silk_pe_stage3_vals[nb_subfr * num19]; silk_pe_stage3_vals[] array15 = new silk_pe_stage3_vals[nb_subfr * num19]; for (int l = 0; l < nb_subfr * num19; l++) { array14[l] = new silk_pe_stage3_vals(); array15[l] = new silk_pe_stage3_vals(); } silk_P_Ana_calc_corr_st3(array15, array13, num27, num4, nb_subfr, complexity); silk_P_Ana_calc_energy_st3(array14, array13, num27, num4, nb_subfr, complexity); int num30 = 0; int a6 = Inlines.silk_DIV32_16(1638, num17); array8 = array13; num8 = 20 * Fs_kHz; int a3 = Inlines.silk_ADD32(Inlines.silk_inner_prod_self(array8, num8, nb_subfr * num4), 1); for (int j = num27; j <= num28; j++) { for (int k = 0; k < num19; k++) { int a = 0; energy = a3; for (int i = 0; i < nb_subfr; i++) { a = Inlines.silk_ADD32(a, Inlines.MatrixGet(array15, i, k, num19).Values[num30]); energy = Inlines.silk_ADD32(energy, Inlines.MatrixGet(array14, i, k, num19).Values[num30]); } int num21; if (a > 0) { num21 = Inlines.silk_DIV32_varQ(a, energy, 14); int b2 = 32767 - Inlines.silk_MUL(a6, k); num21 = Inlines.silk_SMULWB(num21, b2); } else { num21 = 0; } if (num21 > a4 && j + Tables.silk_CB_lags_stage3[0][k] <= num6) { a4 = num21; num29 = j; num16 = k; } } num30++; } for (int i = 0; i < nb_subfr; i++) { pitch_out[i] = num29 + array11[i][num16]; pitch_out[i] = Inlines.silk_LIMIT(pitch_out[i], num5, 18 * Fs_kHz); } lagIndex.Val = (short)(num29 - num5); contourIndex.Val = (sbyte)num16; } else { for (int i = 0; i < nb_subfr; i++) { pitch_out[i] = num17 + array11[i][num16]; pitch_out[i] = Inlines.silk_LIMIT(pitch_out[i], 16, 144); } lagIndex.Val = (short)(num17 - 16); contourIndex.Val = (sbyte)num16; } return 0; } private static void silk_P_Ana_calc_corr_st3(silk_pe_stage3_vals[] cross_corr_st3, short[] frame, int start_lag, int sf_length, int nb_subfr, int complexity) { sbyte[][] array; sbyte[][] array2; int num; if (nb_subfr == 4) { array = Tables.silk_Lag_range_stage3[complexity]; array2 = Tables.silk_CB_lags_stage3; num = Tables.silk_nb_cbk_searchs_stage3[complexity]; } else { array = Tables.silk_Lag_range_stage3_10_ms; array2 = Tables.silk_CB_lags_stage3_10_ms; num = 12; } int[] array3 = new int[22]; int[] array4 = new int[22]; int num2 = Inlines.silk_LSHIFT(sf_length, 2); for (int i = 0; i < nb_subfr; i++) { int num3 = 0; int num4 = array[i][0]; int num5 = array[i][1]; CeltPitchXCorr.pitch_xcorr(frame, num2, frame, num2 - start_lag - num5, array4, sf_length, num5 - num4 + 1); for (int j = num4; j <= num5; j++) { array3[num3] = array4[num5 - j]; num3++; } int num6 = array[i][0]; for (int k = 0; k < num; k++) { int num7 = array2[i][k] - num6; for (int j = 0; j < 5; j++) { Inlines.MatrixGet(cross_corr_st3, i, k, num).Values[j] = array3[num7 + j]; } } num2 += sf_length; } } private static void silk_P_Ana_calc_energy_st3(silk_pe_stage3_vals[] energies_st3, short[] frame, int start_lag, int sf_length, int nb_subfr, int complexity) { sbyte[][] array; sbyte[][] array2; int num; if (nb_subfr == 4) { array = Tables.silk_Lag_range_stage3[complexity]; array2 = Tables.silk_CB_lags_stage3; num = Tables.silk_nb_cbk_searchs_stage3[complexity]; } else { array = Tables.silk_Lag_range_stage3_10_ms; array2 = Tables.silk_CB_lags_stage3_10_ms; num = 12; } int[] array3 = new int[22]; int num2 = Inlines.silk_LSHIFT(sf_length, 2); for (int i = 0; i < nb_subfr; i++) { int num3 = 0; int num4 = num2 - (start_lag + array[i][0]); int num5 = (array3[num3] = Inlines.silk_inner_prod_self(frame, num4, sf_length)); num3++; int num6 = array[i][1] - array[i][0] + 1; for (int j = 1; j < num6; j++) { num5 -= Inlines.silk_SMULBB(frame[num4 + sf_length - j], frame[num4 + sf_length - j]); num5 = (array3[num3] = Inlines.silk_ADD_SAT32(num5, Inlines.silk_SMULBB(frame[num4 - j], frame[num4 - j]))); num3++; } int num7 = array[i][0]; for (int j = 0; j < num; j++) { int num8 = array2[i][j] - num7; for (int k = 0; k < 5; k++) { Inlines.MatrixGet(energies_st3, i, j, num).Values[k] = array3[num8 + k]; } } num2 += sf_length; } } } internal static class PLC { private const int NB_ATT = 2; private static readonly short[] HARM_ATT_Q15 = new short[2] { 32440, 31130 }; private static readonly short[] PLC_RAND_ATTENUATE_V_Q15 = new short[2] { 31130, 26214 }; private static readonly short[] PLC_RAND_ATTENUATE_UV_Q15 = new short[2] { 32440, 29491 }; internal static void silk_PLC_Reset(SilkChannelDecoder psDec) { psDec.sPLC.pitchL_Q8 = Inlines.silk_LSHIFT(psDec.frame_length, 7); psDec.sPLC.prevGain_Q16[0] = 65536; psDec.sPLC.prevGain_Q16[1] = 65536; psDec.sPLC.subfr_length = 20; psDec.sPLC.nb_subfr = 2; } internal static void silk_PLC(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, short[] frame, int frame_ptr, int lost) { if (psDec.fs_kHz != psDec.sPLC.fs_kHz) { silk_PLC_Reset(psDec); psDec.sPLC.fs_kHz = psDec.fs_kHz; } if (lost != 0) { silk_PLC_conceal(psDec, psDecCtrl, frame, frame_ptr); psDec.lossCnt++; } else { silk_PLC_update(psDec, psDecCtrl); } } internal static void silk_PLC_update(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl) { PLCStruct sPLC = psDec.sPLC; psDec.prevSignalType = psDec.indices.signalType; int num = 0; if (psDec.indices.signalType == 2) { for (int i = 0; i * psDec.subfr_length < psDecCtrl.pitchL[psDec.nb_subfr - 1] && i != psDec.nb_subfr; i++) { int num2 = 0; for (int j = 0; j < 5; j++) { num2 += psDecCtrl.LTPCoef_Q14[(psDec.nb_subfr - 1 - i) * 5 + j]; } if (num2 > num) { num = num2; Array.Copy(psDecCtrl.LTPCoef_Q14, Inlines.silk_SMULBB(psDec.nb_subfr - 1 - i, 5), sPLC.LTPCoef_Q14, 0, 5); sPLC.pitchL_Q8 = Inlines.silk_LSHIFT(psDecCtrl.pitchL[psDec.nb_subfr - 1 - i], 8); } } Arrays.MemSet(sPLC.LTPCoef_Q14, (short)0, 5); sPLC.LTPCoef_Q14[2] = (short)num; if (num < 11469) { int a = Inlines.silk_LSHIFT(11469, 10); int b = Inlines.silk_DIV32(a, Inlines.silk_max(num, 1)); for (int j = 0; j < 5; j++) { sPLC.LTPCoef_Q14[j] = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(sPLC.LTPCoef_Q14[j], b), 10); } } else if (num > 15565) { int a = Inlines.silk_LSHIFT(15565, 14); int b2 = Inlines.silk_DIV32(a, Inlines.silk_max(num, 1)); for (int j = 0; j < 5; j++) { sPLC.LTPCoef_Q14[j] = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(sPLC.LTPCoef_Q14[j], b2), 14); } } } else { sPLC.pitchL_Q8 = Inlines.silk_LSHIFT(Inlines.silk_SMULBB(psDec.fs_kHz, 18), 8); Arrays.MemSet(sPLC.LTPCoef_Q14, (short)0, 5); } Array.Copy(psDecCtrl.PredCoef_Q12[1], sPLC.prevLPC_Q12, psDec.LPC_order); sPLC.prevLTP_scale_Q14 = (short)psDecCtrl.LTP_scale_Q14; Array.Copy(psDecCtrl.Gains_Q16, psDec.nb_subfr - 2, sPLC.prevGain_Q16, 0, 2); sPLC.subfr_length = psDec.subfr_length; sPLC.nb_subfr = psDec.nb_subfr; } internal static void silk_PLC_energy(out int energy1, out int shift1, out int energy2, out int shift2, int[] exc_Q14, int[] prevGain_Q10, int subfr_length, int nb_subfr) { int num = 0; short[] array = new short[2 * subfr_length]; for (int i = 0; i < 2; i++) { for (int j = 0; j < subfr_length; j++) { array[num + j] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT(Inlines.silk_SMULWW(exc_Q14[j + (i + nb_subfr - 2) * subfr_length], prevGain_Q10[i]), 8)); } num += subfr_length; } SumSqrShift.silk_sum_sqr_shift(out energy1, out shift1, array, subfr_length); SumSqrShift.silk_sum_sqr_shift(out energy2, out shift2, array, subfr_length, subfr_length); } internal static void silk_PLC_conceal(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, short[] frame, int frame_ptr) { short[] array = new short[psDec.ltp_mem_length]; int[] array2 = new int[psDec.ltp_mem_length + psDec.frame_length]; PLCStruct sPLC = psDec.sPLC; int[] array3 = new int[2] { Inlines.silk_RSHIFT(sPLC.prevGain_Q16[0], 6), Inlines.silk_RSHIFT(sPLC.prevGain_Q16[1], 6) }; if (psDec.first_frame_after_reset != 0) { Arrays.MemSet(sPLC.prevLPC_Q12, (short)0, 16); } silk_PLC_energy(out var energy, out var shift, out var energy2, out var shift2, psDec.exc_Q14, array3, psDec.subfr_length, psDec.nb_subfr); int num = ((Inlines.silk_RSHIFT(energy, shift2) >= Inlines.silk_RSHIFT(energy2, shift)) ? Inlines.silk_max_int(0, sPLC.nb_subfr * sPLC.subfr_length - 128) : Inlines.silk_max_int(0, (sPLC.nb_subfr - 1) * sPLC.subfr_length - 128)); short[] lTPCoef_Q = sPLC.LTPCoef_Q14; short num2 = sPLC.randScale_Q14; int a = HARM_ATT_Q15[Inlines.silk_min_int(1, psDec.lossCnt)]; int b = ((psDec.prevSignalType != 2) ? PLC_RAND_ATTENUATE_UV_Q15[Inlines.silk_min_int(1, psDec.lossCnt)] : PLC_RAND_ATTENUATE_V_Q15[Inlines.silk_min_int(1, psDec.lossCnt)]); BWExpander.silk_bwexpander(sPLC.prevLPC_Q12, psDec.LPC_order, 64881); if (psDec.lossCnt == 0) { num2 = 16384; if (psDec.prevSignalType == 2) { for (int i = 0; i < 5; i++) { num2 -= lTPCoef_Q[i]; } num2 = Inlines.silk_max_16(3277, num2); num2 = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(num2, sPLC.prevLTP_scale_Q14), 14); } else { int b2 = LPCInversePredGain.silk_LPC_inverse_pred_gain(sPLC.prevLPC_Q12, psDec.LPC_order); int b3 = Inlines.silk_min_32(Inlines.silk_RSHIFT(1073741824, 3), b2); b3 = Inlines.silk_max_32(Inlines.silk_RSHIFT(1073741824, 8), b3); b3 = Inlines.silk_LSHIFT(b3, 3); b = Inlines.silk_RSHIFT(Inlines.silk_SMULWB(b3, b), 14); } } int num3 = sPLC.rand_seed; int num4 = Inlines.silk_RSHIFT_ROUND(sPLC.pitchL_Q8, 8); int num5 = psDec.ltp_mem_length; int num6 = psDec.ltp_mem_length - num4 - psDec.LPC_order - 2; Filters.silk_LPC_analysis_filter(array, num6, psDec.outBuf, num6, sPLC.prevLPC_Q12, 0, psDec.ltp_mem_length - num6, psDec.LPC_order); int a2 = Inlines.silk_INVERSE32_varQ(sPLC.prevGain_Q16[1], 46); a2 = Inlines.silk_min(a2, 1073741823); for (int i = num6 + psDec.LPC_order; i < psDec.ltp_mem_length; i++) { array2[i] = Inlines.silk_SMULWB(a2, array[i]); } for (int j = 0; j < psDec.nb_subfr; j++) { int num7 = num5 - num4 + 2; for (int i = 0; i < psDec.subfr_length; i++) { int a3 = 2; a3 = Inlines.silk_SMLAWB(a3, array2[num7], lTPCoef_Q[0]); a3 = Inlines.silk_SMLAWB(a3, array2[num7 - 1], lTPCoef_Q[1]); a3 = Inlines.silk_SMLAWB(a3, array2[num7 - 2], lTPCoef_Q[2]); a3 = Inlines.silk_SMLAWB(a3, array2[num7 - 3], lTPCoef_Q[3]); a3 = Inlines.silk_SMLAWB(a3, array2[num7 - 4], lTPCoef_Q[4]); num7++; num3 = Inlines.silk_RAND(num3); num6 = Inlines.silk_RSHIFT(num3, 25) & 0x7F; array2[num5] = Inlines.silk_LSHIFT32(Inlines.silk_SMLAWB(a3, psDec.exc_Q14[num + num6], num2), 2); num5++; } for (int k = 0; k < 5; k++) { lTPCoef_Q[k] = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(a, lTPCoef_Q[k]), 15); } num2 = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(num2, b), 15); sPLC.pitchL_Q8 = Inlines.silk_SMLAWB(sPLC.pitchL_Q8, sPLC.pitchL_Q8, 655); sPLC.pitchL_Q8 = Inlines.silk_min_32(sPLC.pitchL_Q8, Inlines.silk_LSHIFT(Inlines.silk_SMULBB(18, psDec.fs_kHz), 8)); num4 = Inlines.silk_RSHIFT_ROUND(sPLC.pitchL_Q8, 8); } int num8 = psDec.ltp_mem_length - 16; Array.Copy(psDec.sLPC_Q14_buf, 0, array2, num8, 16); for (int i = 0; i < psDec.frame_length; i++) { int num9 = num8 + 16 + i; int a4 = Inlines.silk_RSHIFT(psDec.LPC_order, 1); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 1], sPLC.prevLPC_Q12[0]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 2], sPLC.prevLPC_Q12[1]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 3], sPLC.prevLPC_Q12[2]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 4], sPLC.prevLPC_Q12[3]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 5], sPLC.prevLPC_Q12[4]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 6], sPLC.prevLPC_Q12[5]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 7], sPLC.prevLPC_Q12[6]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 8], sPLC.prevLPC_Q12[7]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 9], sPLC.prevLPC_Q12[8]); a4 = Inlines.silk_SMLAWB(a4, array2[num9 - 10], sPLC.prevLPC_Q12[9]); for (int k = 10; k < psDec.LPC_order; k++) { a4 = Inlines.silk_SMLAWB(a4, array2[num9 - k - 1], sPLC.prevLPC_Q12[k]); } array2[num9] = Inlines.silk_ADD_LSHIFT32(array2[num9], a4, 4); frame[frame_ptr + i] = (short)Inlines.silk_SAT16(Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(array2[num9], array3[1]), 8))); } Array.Copy(array2, num8 + psDec.frame_length, psDec.sLPC_Q14_buf, 0, 16); sPLC.rand_seed = num3; sPLC.randScale_Q14 = num2; for (int i = 0; i < 4; i++) { psDecCtrl.pitchL[i] = num4; } } internal static void silk_PLC_glue_frames(SilkChannelDecoder psDec, short[] frame, int frame_ptr, int length) { PLCStruct sPLC = psDec.sPLC; if (psDec.lossCnt != 0) { SumSqrShift.silk_sum_sqr_shift(out sPLC.conc_energy, out sPLC.conc_energy_shift, frame, frame_ptr, length); sPLC.last_frame_lost = 1; return; } if (psDec.sPLC.last_frame_lost != 0) { SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, frame, frame_ptr, length); if (shift > sPLC.conc_energy_shift) { sPLC.conc_energy = Inlines.silk_RSHIFT(sPLC.conc_energy, shift - sPLC.conc_energy_shift); } else if (shift < sPLC.conc_energy_shift) { energy = Inlines.silk_RSHIFT(energy, sPLC.conc_energy_shift - shift); } if (energy > sPLC.conc_energy) { int num = Inlines.silk_CLZ32(sPLC.conc_energy); num--; sPLC.conc_energy = Inlines.silk_LSHIFT(sPLC.conc_energy, num); energy = Inlines.silk_RSHIFT(energy, Inlines.silk_max_32(24 - num, 0)); int x = Inlines.silk_DIV32(sPLC.conc_energy, Inlines.silk_max(energy, 1)); int num2 = Inlines.silk_LSHIFT(Inlines.silk_SQRT_APPROX(x), 4); int a = Inlines.silk_DIV32_16(65536 - num2, length); a = Inlines.silk_LSHIFT(a, 2); for (int i = frame_ptr; i < frame_ptr + length; i++) { frame[i] = (short)Inlines.silk_SMULWB(num2, frame[i]); num2 += a; if (num2 > 65536) { break; } } } } sPLC.last_frame_lost = 0; } } internal static class ProcessGains { internal static void silk_process_gains(SilkChannelEncoder psEnc, SilkEncoderControl psEncCtrl, int condCoding) { SilkShapeState sShape = psEnc.sShape; if (psEnc.indices.signalType == 2) { int c = -Sigmoid.silk_sigm_Q15(Inlines.silk_RSHIFT_ROUND(psEncCtrl.LTPredCodGain_Q7 - 1536, 4)); for (int i = 0; i < psEnc.nb_subfr; i++) { psEncCtrl.Gains_Q16[i] = Inlines.silk_SMLAWB(psEncCtrl.Gains_Q16[i], psEncCtrl.Gains_Q16[i], c); } } int b = Inlines.silk_DIV32_16(Inlines.silk_log2lin(Inlines.silk_SMULWB(8894 - psEnc.SNR_dB_Q7, 21627)), psEnc.subfr_length); for (int i = 0; i < psEnc.nb_subfr; i++) { int a = psEncCtrl.ResNrg[i]; int num = Inlines.silk_SMULWW(a, b); num = ((psEncCtrl.ResNrgQ[i] > 0) ? Inlines.silk_RSHIFT_ROUND(num, psEncCtrl.ResNrgQ[i]) : ((num < Inlines.silk_RSHIFT(int.MaxValue, -psEncCtrl.ResNrgQ[i])) ? Inlines.silk_LSHIFT(num, -psEncCtrl.ResNrgQ[i]) : int.MaxValue)); int num2 = psEncCtrl.Gains_Q16[i]; int num3 = Inlines.silk_ADD_SAT32(num, Inlines.silk_SMMUL(num2, num2)); if (num3 < 32767) { num3 = Inlines.silk_SMLAWW(Inlines.silk_LSHIFT(num, 16), num2, num2); num2 = Inlines.silk_SQRT_APPROX(num3); num2 = Inlines.silk_min(num2, 8388607); psEncCtrl.Gains_Q16[i] = Inlines.silk_LSHIFT_SAT32(num2, 8); } else { num2 = Inlines.silk_SQRT_APPROX(num3); num2 = Inlines.silk_min(num2, 32767); psEncCtrl.Gains_Q16[i] = Inlines.silk_LSHIFT_SAT32(num2, 16); } } Array.Copy(psEncCtrl.Gains_Q16, psEncCtrl.GainsUnq_Q16, psEnc.nb_subfr); psEncCtrl.lastGainIndexPrev = sShape.LastGainIndex; BoxedValue boxedValue = new BoxedValue(sShape.LastGainIndex); GainQuantization.silk_gains_quant(psEnc.indices.GainsIndices, psEncCtrl.Gains_Q16, boxedValue, (condCoding == 2) ? 1 : 0, psEnc.nb_subfr); sShape.LastGainIndex = boxedValue.Val; if (psEnc.indices.signalType == 2) { if (psEncCtrl.LTPredCodGain_Q7 + Inlines.silk_RSHIFT(psEnc.input_tilt_Q15, 8) > 128) { psEnc.indices.quantOffsetType = 0; } else { psEnc.indices.quantOffsetType = 1; } } int b2 = Tables.silk_Quantization_Offsets_Q10[psEnc.indices.signalType >> 1][psEnc.indices.quantOffsetType]; psEncCtrl.Lambda_Q10 = 1229 + Inlines.silk_SMULBB(-50, psEnc.nStatesDelayedDecision) + Inlines.silk_SMULWB(-52428, psEnc.speech_activity_Q8) + Inlines.silk_SMULWB(-409, psEncCtrl.input_quality_Q14) + Inlines.silk_SMULWB(-818, psEncCtrl.coding_quality_Q14) + Inlines.silk_SMULWB(52429, b2); } } internal static class QuantizeLTPGains { internal static void silk_quant_LTP_gains(short[] B_Q14, sbyte[] cbk_index, BoxedValue periodicity_index, BoxedValue sum_log_gain_Q7, int[] W_Q18, int mu_Q9, int lowComplexity, int nb_subfr) { sbyte[] array = new sbyte[4]; int num = int.MaxValue; int val = 0; sbyte[][] cb_Q; for (int i = 0; i < 3; i++) { int num2 = 51; byte[] cl_Q = Tables.silk_LTP_gain_BITS_Q5_ptrs[i]; cb_Q = Tables.silk_LTP_vq_ptrs_Q7[i]; byte[] cb_gain_Q = Tables.silk_LTP_vq_gain_ptrs_Q7[i]; int l = Tables.silk_LTP_vq_sizes[i]; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = sum_log_gain_Q7.Val; for (int j = 0; j < nb_subfr; j++) { int max_gain_Q = Inlines.silk_log2lin(5333 - num6 + 896) - num2; BoxedValue boxedValue = new BoxedValue(array[j]); BoxedValue boxedValue2 = new BoxedValue(0); BoxedValue boxedValue3 = new BoxedValue(0); VQ_WMat_EC.silk_VQ_WMat_EC(boxedValue, boxedValue2, boxedValue3, B_Q14, num4, W_Q18, num3, cb_Q, cb_gain_Q, cl_Q, mu_Q9, max_gain_Q, l); int val2 = boxedValue2.Val; int val3 = boxedValue3.Val; array[j] = boxedValue.Val; num5 = Inlines.silk_ADD_POS_SAT32(num5, val2); num6 = Inlines.silk_max(0, num6 + Inlines.silk_lin2log(num2 + val3) - 896); num4 += 5; num3 += 25; } num5 = Inlines.silk_min(2147483646, num5); if (num5 < num) { num = num5; periodicity_index.Val = (sbyte)i; Array.Copy(array, 0, cbk_index, 0, nb_subfr); val = num6; } if (lowComplexity != 0 && num5 < Tables.silk_LTP_gain_middle_avg_RD_Q14) { break; } } cb_Q = Tables.silk_LTP_vq_ptrs_Q7[periodicity_index.Val]; for (int j = 0; j < nb_subfr; j++) { for (int i = 0; i < 5; i++) { B_Q14[j * 5 + i] = (short)Inlines.silk_LSHIFT(cb_Q[cbk_index[j]][i], 7); } } sum_log_gain_Q7.Val = val; } } internal static class RegularizeCorrelations { internal static void silk_regularize_correlations(int[] XX, int XX_ptr, int[] xx, int xx_ptr, int noise, int D) { for (int i = 0; i < D; i++) { Inlines.MatrixSet(XX, XX_ptr, i, i, D, Inlines.silk_ADD32(Inlines.MatrixGet(XX, XX_ptr, i, i, D), noise)); } xx[xx_ptr] += noise; } } internal static class Resampler { private const int USE_silk_resampler_copy = 0; private const int USE_silk_resampler_private_up2_HQ_wrapper = 1; private const int USE_silk_resampler_private_IIR_FIR = 2; private const int USE_silk_resampler_private_down_FIR = 3; private const int ORDER_FIR = 4; private static int rateID(int R) { return ((R >> 12) - ((R > 16000) ? 1 : 0) >> ((R > 24000) ? 1 : 0)) - 1; } internal static int silk_resampler_init(SilkResamplerState S, int Fs_Hz_in, int Fs_Hz_out, int forEnc) { S.Reset(); if (forEnc != 0) { if ((Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000) || (Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000)) { return -1; } S.inputDelay = Tables.delay_matrix_enc[rateID(Fs_Hz_in), rateID(Fs_Hz_out)]; } else { if ((Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000) || (Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000)) { return -1; } S.inputDelay = Tables.delay_matrix_dec[rateID(Fs_Hz_in), rateID(Fs_Hz_out)]; } S.Fs_in_kHz = Inlines.silk_DIV32_16(Fs_Hz_in, 1000); S.Fs_out_kHz = Inlines.silk_DIV32_16(Fs_Hz_out, 1000); S.batchSize = S.Fs_in_kHz * 10; int num = 0; if (Fs_Hz_out > Fs_Hz_in) { if (Fs_Hz_out == Inlines.silk_MUL(Fs_Hz_in, 2)) { S.resampler_function = 1; } else { S.resampler_function = 2; num = 1; } } else if (Fs_Hz_out < Fs_Hz_in) { S.resampler_function = 3; if (Inlines.silk_MUL(Fs_Hz_out, 4) == Inlines.silk_MUL(Fs_Hz_in, 3)) { S.FIR_Fracs = 3; S.FIR_Order = 18; S.Coefs = Tables.silk_Resampler_3_4_COEFS; } else if (Inlines.silk_MUL(Fs_Hz_out, 3) == Inlines.silk_MUL(Fs_Hz_in, 2)) { S.FIR_Fracs = 2; S.FIR_Order = 18; S.Coefs = Tables.silk_Resampler_2_3_COEFS; } else if (Inlines.silk_MUL(Fs_Hz_out, 2) == Fs_Hz_in) { S.FIR_Fracs = 1; S.FIR_Order = 24; S.Coefs = Tables.silk_Resampler_1_2_COEFS; } else if (Inlines.silk_MUL(Fs_Hz_out, 3) == Fs_Hz_in) { S.FIR_Fracs = 1; S.FIR_Order = 36; S.Coefs = Tables.silk_Resampler_1_3_COEFS; } else if (Inlines.silk_MUL(Fs_Hz_out, 4) == Fs_Hz_in) { S.FIR_Fracs = 1; S.FIR_Order = 36; S.Coefs = Tables.silk_Resampler_1_4_COEFS; } else { if (Inlines.silk_MUL(Fs_Hz_out, 6) != Fs_Hz_in) { return -1; } S.FIR_Fracs = 1; S.FIR_Order = 36; S.Coefs = Tables.silk_Resampler_1_6_COEFS; } } else { S.resampler_function = 0; } S.invRatio_Q16 = Inlines.silk_LSHIFT32(Inlines.silk_DIV32(Inlines.silk_LSHIFT32(Fs_Hz_in, 14 + num), Fs_Hz_out), 2); while (Inlines.silk_SMULWW(S.invRatio_Q16, Fs_Hz_out) < Inlines.silk_LSHIFT32(Fs_Hz_in, num)) { S.invRatio_Q16++; } return 0; } internal static int silk_resampler(SilkResamplerState S, short[] output, int output_ptr, short[] input, int input_ptr, int inLen) { int num = S.Fs_in_kHz - S.inputDelay; short[] delayBuf = S.delayBuf; Array.Copy(input, input_ptr, delayBuf, S.inputDelay, num); switch (S.resampler_function) { case 1: silk_resampler_private_up2_HQ(S.sIIR, output, output_ptr, delayBuf, 0, S.Fs_in_kHz); silk_resampler_private_up2_HQ(S.sIIR, output, output_ptr + S.Fs_out_kHz, input, input_ptr + num, inLen - S.Fs_in_kHz); break; case 2: silk_resampler_private_IIR_FIR(S, output, output_ptr, delayBuf, 0, S.Fs_in_kHz); silk_resampler_private_IIR_FIR(S, output, output_ptr + S.Fs_out_kHz, input, input_ptr + num, inLen - S.Fs_in_kHz); break; case 3: silk_resampler_private_down_FIR(S, output, output_ptr, delayBuf, 0, S.Fs_in_kHz); silk_resampler_private_down_FIR(S, output, output_ptr + S.Fs_out_kHz, input, input_ptr + num, inLen - S.Fs_in_kHz); break; default: Array.Copy(delayBuf, 0, output, output_ptr, S.Fs_in_kHz); Array.Copy(input, input_ptr + num, output, output_ptr + S.Fs_out_kHz, inLen - S.Fs_in_kHz); break; } Array.Copy(input, input_ptr + inLen - S.inputDelay, delayBuf, 0, S.inputDelay); return SilkError.SILK_NO_ERROR; } internal static void silk_resampler_down2(int[] S, short[] output, short[] input, int inLen) { int num = Inlines.silk_RSHIFT32(inLen, 1); for (int i = 0; i < num; i++) { int a = Inlines.silk_LSHIFT(input[2 * i], 10); int num2 = Inlines.silk_SUB32(a, S[0]); int b = Inlines.silk_SMLAWB(num2, num2, -25727); int a2 = Inlines.silk_ADD32(S[0], b); S[0] = Inlines.silk_ADD32(a, b); a = Inlines.silk_LSHIFT(input[2 * i + 1], 10); num2 = Inlines.silk_SUB32(a, S[1]); b = Inlines.silk_SMULWB(num2, 9872); a2 = Inlines.silk_ADD32(a2, S[1]); a2 = Inlines.silk_ADD32(a2, b); S[1] = Inlines.silk_ADD32(a, b); output[i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a2, 11)); } } internal static void silk_resampler_down2_3(int[] S, short[] output, short[] input, int inLen) { int[] array = new int[484]; int num = 0; int num2 = 0; Array.Copy(S, 0, array, 0, 4); int num3; while (true) { bool flag = true; num3 = Inlines.silk_min(inLen, 480); silk_resampler_private_AR2(S, 4, array, 4, input, num, Tables.silk_Resampler_2_3_COEFS_LQ, num3); int num4 = 0; for (int num5 = num3; num5 > 2; num5 -= 3) { int a = Inlines.silk_SMULWB(array[num4], Tables.silk_Resampler_2_3_COEFS_LQ[2]); a = Inlines.silk_SMLAWB(a, array[num4 + 1], Tables.silk_Resampler_2_3_COEFS_LQ[3]); a = Inlines.silk_SMLAWB(a, array[num4 + 2], Tables.silk_Resampler_2_3_COEFS_LQ[5]); a = Inlines.silk_SMLAWB(a, array[num4 + 3], Tables.silk_Resampler_2_3_COEFS_LQ[4]); output[num2++] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 6)); a = Inlines.silk_SMULWB(array[num4 + 1], Tables.silk_Resampler_2_3_COEFS_LQ[4]); a = Inlines.silk_SMLAWB(a, array[num4 + 2], Tables.silk_Resampler_2_3_COEFS_LQ[5]); a = Inlines.silk_SMLAWB(a, array[num4 + 3], Tables.silk_Resampler_2_3_COEFS_LQ[3]); a = Inlines.silk_SMLAWB(a, array[num4 + 4], Tables.silk_Resampler_2_3_COEFS_LQ[2]); output[num2++] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 6)); num4 += 3; } num += num3; inLen -= num3; if (inLen > 0) { Array.Copy(array, num3, array, 0, 4); continue; } break; } Array.Copy(array, num3, S, 0, 4); } internal static void silk_resampler_private_AR2(int[] S, int S_ptr, int[] out_Q8, int out_Q8_ptr, short[] input, int input_ptr, short[] A_Q14, int len) { for (int i = 0; i < len; i++) { int num = Inlines.silk_LSHIFT(out_Q8[out_Q8_ptr + i] = Inlines.silk_ADD_LSHIFT32(S[S_ptr], input[input_ptr + i], 8), 2); S[S_ptr] = Inlines.silk_SMLAWB(S[S_ptr + 1], num, A_Q14[0]); S[S_ptr + 1] = Inlines.silk_SMULWB(num, A_Q14[1]); } } internal static int silk_resampler_private_down_FIR_INTERPOL(short[] output, int output_ptr, int[] buf, short[] FIR_Coefs, int FIR_Coefs_ptr, int FIR_Order, int FIR_Fracs, int max_index_Q16, int index_increment_Q16) { switch (FIR_Order) { case 18: { for (int i = 0; i < max_index_Q16; i += index_increment_Q16) { int num = Inlines.silk_RSHIFT(i, 16); int num2 = Inlines.silk_SMULWB(i & 0xFFFF, FIR_Fracs); int num3 = FIR_Coefs_ptr + 9 * num2; int a = Inlines.silk_SMULWB(buf[num], FIR_Coefs[num3]); a = Inlines.silk_SMLAWB(a, buf[num + 1], FIR_Coefs[num3 + 1]); a = Inlines.silk_SMLAWB(a, buf[num + 2], FIR_Coefs[num3 + 2]); a = Inlines.silk_SMLAWB(a, buf[num + 3], FIR_Coefs[num3 + 3]); a = Inlines.silk_SMLAWB(a, buf[num + 4], FIR_Coefs[num3 + 4]); a = Inlines.silk_SMLAWB(a, buf[num + 5], FIR_Coefs[num3 + 5]); a = Inlines.silk_SMLAWB(a, buf[num + 6], FIR_Coefs[num3 + 6]); a = Inlines.silk_SMLAWB(a, buf[num + 7], FIR_Coefs[num3 + 7]); a = Inlines.silk_SMLAWB(a, buf[num + 8], FIR_Coefs[num3 + 8]); num3 = FIR_Coefs_ptr + 9 * (FIR_Fracs - 1 - num2); a = Inlines.silk_SMLAWB(a, buf[num + 17], FIR_Coefs[num3]); a = Inlines.silk_SMLAWB(a, buf[num + 16], FIR_Coefs[num3 + 1]); a = Inlines.silk_SMLAWB(a, buf[num + 15], FIR_Coefs[num3 + 2]); a = Inlines.silk_SMLAWB(a, buf[num + 14], FIR_Coefs[num3 + 3]); a = Inlines.silk_SMLAWB(a, buf[num + 13], FIR_Coefs[num3 + 4]); a = Inlines.silk_SMLAWB(a, buf[num + 12], FIR_Coefs[num3 + 5]); a = Inlines.silk_SMLAWB(a, buf[num + 11], FIR_Coefs[num3 + 6]); a = Inlines.silk_SMLAWB(a, buf[num + 10], FIR_Coefs[num3 + 7]); a = Inlines.silk_SMLAWB(a, buf[num + 9], FIR_Coefs[num3 + 8]); output[output_ptr++] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 6)); } break; } case 24: { for (int i = 0; i < max_index_Q16; i += index_increment_Q16) { int num = Inlines.silk_RSHIFT(i, 16); int a = Inlines.silk_SMULWB(Inlines.silk_ADD32(buf[num], buf[num + 23]), FIR_Coefs[FIR_Coefs_ptr]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 1], buf[num + 22]), FIR_Coefs[FIR_Coefs_ptr + 1]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 2], buf[num + 21]), FIR_Coefs[FIR_Coefs_ptr + 2]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 3], buf[num + 20]), FIR_Coefs[FIR_Coefs_ptr + 3]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 4], buf[num + 19]), FIR_Coefs[FIR_Coefs_ptr + 4]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 5], buf[num + 18]), FIR_Coefs[FIR_Coefs_ptr + 5]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 6], buf[num + 17]), FIR_Coefs[FIR_Coefs_ptr + 6]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 7], buf[num + 16]), FIR_Coefs[FIR_Coefs_ptr + 7]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 8], buf[num + 15]), FIR_Coefs[FIR_Coefs_ptr + 8]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 9], buf[num + 14]), FIR_Coefs[FIR_Coefs_ptr + 9]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 10], buf[num + 13]), FIR_Coefs[FIR_Coefs_ptr + 10]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 11], buf[num + 12]), FIR_Coefs[FIR_Coefs_ptr + 11]); output[output_ptr++] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 6)); } break; } case 36: { for (int i = 0; i < max_index_Q16; i += index_increment_Q16) { int num = Inlines.silk_RSHIFT(i, 16); int a = Inlines.silk_SMULWB(Inlines.silk_ADD32(buf[num], buf[num + 35]), FIR_Coefs[FIR_Coefs_ptr]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 1], buf[num + 34]), FIR_Coefs[FIR_Coefs_ptr + 1]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 2], buf[num + 33]), FIR_Coefs[FIR_Coefs_ptr + 2]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 3], buf[num + 32]), FIR_Coefs[FIR_Coefs_ptr + 3]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 4], buf[num + 31]), FIR_Coefs[FIR_Coefs_ptr + 4]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 5], buf[num + 30]), FIR_Coefs[FIR_Coefs_ptr + 5]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 6], buf[num + 29]), FIR_Coefs[FIR_Coefs_ptr + 6]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 7], buf[num + 28]), FIR_Coefs[FIR_Coefs_ptr + 7]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 8], buf[num + 27]), FIR_Coefs[FIR_Coefs_ptr + 8]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 9], buf[num + 26]), FIR_Coefs[FIR_Coefs_ptr + 9]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 10], buf[num + 25]), FIR_Coefs[FIR_Coefs_ptr + 10]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 11], buf[num + 24]), FIR_Coefs[FIR_Coefs_ptr + 11]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 12], buf[num + 23]), FIR_Coefs[FIR_Coefs_ptr + 12]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 13], buf[num + 22]), FIR_Coefs[FIR_Coefs_ptr + 13]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 14], buf[num + 21]), FIR_Coefs[FIR_Coefs_ptr + 14]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 15], buf[num + 20]), FIR_Coefs[FIR_Coefs_ptr + 15]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 16], buf[num + 19]), FIR_Coefs[FIR_Coefs_ptr + 16]); a = Inlines.silk_SMLAWB(a, Inlines.silk_ADD32(buf[num + 17], buf[num + 18]), FIR_Coefs[FIR_Coefs_ptr + 17]); output[output_ptr++] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 6)); } break; } } return output_ptr; } internal static void silk_resampler_private_down_FIR(SilkResamplerState S, short[] output, int output_ptr, short[] input, int input_ptr, int inLen) { int[] array = new int[S.batchSize + S.FIR_Order]; Array.Copy(S.sFIR_i32, array, S.FIR_Order); int invRatio_Q = S.invRatio_Q16; int num; while (true) { bool flag = true; num = Inlines.silk_min(inLen, S.batchSize); silk_resampler_private_AR2(S.sIIR, 0, array, S.FIR_Order, input, input_ptr, S.Coefs, num); int max_index_Q = Inlines.silk_LSHIFT32(num, 16); output_ptr = silk_resampler_private_down_FIR_INTERPOL(output, output_ptr, array, S.Coefs, 2, S.FIR_Order, S.FIR_Fracs, max_index_Q, invRatio_Q); input_ptr += num; inLen -= num; if (inLen > 1) { Array.Copy(array, num, array, 0, S.FIR_Order); continue; } break; } Array.Copy(array, num, S.sFIR_i32, 0, S.FIR_Order); } internal static int silk_resampler_private_IIR_FIR_INTERPOL(short[] output, int output_ptr, short[] buf, int max_index_Q16, int index_increment_Q16) { for (int i = 0; i < max_index_Q16; i += index_increment_Q16) { int num = Inlines.silk_SMULWB(i & 0xFFFF, 12); int num2 = i >> 16; int a = Inlines.silk_SMULBB(buf[num2], Tables.silk_resampler_frac_FIR_12[num, 0]); a = Inlines.silk_SMLABB(a, buf[num2 + 1], Tables.silk_resampler_frac_FIR_12[num, 1]); a = Inlines.silk_SMLABB(a, buf[num2 + 2], Tables.silk_resampler_frac_FIR_12[num, 2]); a = Inlines.silk_SMLABB(a, buf[num2 + 3], Tables.silk_resampler_frac_FIR_12[num, 3]); a = Inlines.silk_SMLABB(a, buf[num2 + 4], Tables.silk_resampler_frac_FIR_12[11 - num, 3]); a = Inlines.silk_SMLABB(a, buf[num2 + 5], Tables.silk_resampler_frac_FIR_12[11 - num, 2]); a = Inlines.silk_SMLABB(a, buf[num2 + 6], Tables.silk_resampler_frac_FIR_12[11 - num, 1]); a = Inlines.silk_SMLABB(a, buf[num2 + 7], Tables.silk_resampler_frac_FIR_12[11 - num, 0]); output[output_ptr++] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 15)); } return output_ptr; } internal static void silk_resampler_private_IIR_FIR(SilkResamplerState S, short[] output, int output_ptr, short[] input, int input_ptr, int inLen) { short[] array = new short[2 * S.batchSize + 8]; Array.Copy(S.sFIR_i16, 0, array, 0, 8); int invRatio_Q = S.invRatio_Q16; int num; while (true) { bool flag = true; num = Inlines.silk_min(inLen, S.batchSize); silk_resampler_private_up2_HQ(S.sIIR, array, 8, input, input_ptr, num); int max_index_Q = Inlines.silk_LSHIFT32(num, 17); output_ptr = silk_resampler_private_IIR_FIR_INTERPOL(output, output_ptr, array, max_index_Q, invRatio_Q); input_ptr += num; inLen -= num; if (inLen > 0) { Array.Copy(array, num << 1, array, 0, 8); continue; } break; } Array.Copy(array, num << 1, S.sFIR_i16, 0, 8); } internal static void silk_resampler_private_up2_HQ(int[] S, short[] output, int output_ptr, short[] input, int input_ptr, int len) { for (int i = 0; i < len; i++) { int a = Inlines.silk_LSHIFT(input[input_ptr + i], 10); int a2 = Inlines.silk_SUB32(a, S[0]); int b = Inlines.silk_SMULWB(a2, Tables.silk_resampler_up2_hq_0[0]); int a3 = Inlines.silk_ADD32(S[0], b); S[0] = Inlines.silk_ADD32(a, b); a2 = Inlines.silk_SUB32(a3, S[1]); b = Inlines.silk_SMULWB(a2, Tables.silk_resampler_up2_hq_0[1]); int a4 = Inlines.silk_ADD32(S[1], b); S[1] = Inlines.silk_ADD32(a3, b); a2 = Inlines.silk_SUB32(a4, S[2]); b = Inlines.silk_SMLAWB(a2, a2, Tables.silk_resampler_up2_hq_0[2]); a3 = Inlines.silk_ADD32(S[2], b); S[2] = Inlines.silk_ADD32(a4, b); output[output_ptr + 2 * i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a3, 10)); a2 = Inlines.silk_SUB32(a, S[3]); b = Inlines.silk_SMULWB(a2, Tables.silk_resampler_up2_hq_1[0]); a3 = Inlines.silk_ADD32(S[3], b); S[3] = Inlines.silk_ADD32(a, b); a2 = Inlines.silk_SUB32(a3, S[4]); b = Inlines.silk_SMULWB(a2, Tables.silk_resampler_up2_hq_1[1]); a4 = Inlines.silk_ADD32(S[4], b); S[4] = Inlines.silk_ADD32(a3, b); a2 = Inlines.silk_SUB32(a4, S[5]); b = Inlines.silk_SMLAWB(a2, a2, Tables.silk_resampler_up2_hq_1[2]); a3 = Inlines.silk_ADD32(S[5], b); S[5] = Inlines.silk_ADD32(a4, b); output[output_ptr + 2 * i + 1] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a3, 10)); } } } internal static class ResidualEnergy { internal static void silk_residual_energy(int[] nrgs, int[] nrgsQ, short[] x, short[][] a_Q12, int[] gains, int subfr_length, int nb_subfr, int LPC_order) { int num = 0; int num2 = LPC_order + subfr_length; short[] array = new short[2 * num2]; for (int i = 0; i < nb_subfr >> 1; i++) { Filters.silk_LPC_analysis_filter(array, 0, x, num, a_Q12[i], 0, 2 * num2, LPC_order); int num3 = LPC_order; for (int j = 0; j < 2; j++) { SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, array, num3, subfr_length); nrgs[i * 2 + j] = energy; nrgsQ[i * 2 + j] = -shift; num3 += num2; } num += 2 * num2; } for (int i = 0; i < nb_subfr; i++) { int num4 = Inlines.silk_CLZ32(nrgs[i]) - 1; int num5 = Inlines.silk_CLZ32(gains[i]) - 1; int num6 = Inlines.silk_LSHIFT32(gains[i], num5); num6 = Inlines.silk_SMMUL(num6, num6); nrgs[i] = Inlines.silk_SMMUL(num6, Inlines.silk_LSHIFT32(nrgs[i], num4)); nrgsQ[i] += num4 + 2 * num5 - 32 - 32; } } internal static int silk_residual_energy16_covar(short[] c, int c_ptr, int[] wXX, int wXX_ptr, int[] wXx, int wxx, int D, int cQ) { int[] array = new int[D]; int num = 16 - cQ; int a = num; int num2 = 0; for (int i = c_ptr; i < c_ptr + D; i++) { num2 = Inlines.silk_max_32(num2, Inlines.silk_abs(c[i])); } a = Inlines.silk_min_int(a, Inlines.silk_CLZ32(num2) - 17); int a2 = Inlines.silk_max_32(wXX[wXX_ptr], wXX[wXX_ptr + D * D - 1]); a = Inlines.silk_min_int(a, Inlines.silk_CLZ32(Inlines.silk_MUL(D, Inlines.silk_RSHIFT(Inlines.silk_SMULWB(a2, num2), 4))) - 5); a = Inlines.silk_max_int(a, 0); for (int i = 0; i < D; i++) { array[i] = Inlines.silk_LSHIFT(c[c_ptr + i], a); } num -= a; int num3 = 0; for (int i = 0; i < D; i++) { num3 = Inlines.silk_SMLAWB(num3, wXx[i], array[i]); } int a3 = Inlines.silk_RSHIFT(wxx, 1 + num) - num3; int num4 = 0; for (int i = 0; i < D; i++) { num3 = 0; int num5 = wXX_ptr + i * D; for (int j = i + 1; j < D; j++) { num3 = Inlines.silk_SMLAWB(num3, wXX[num5 + j], array[j]); } num3 = Inlines.silk_SMLAWB(num3, Inlines.silk_RSHIFT(wXX[num5 + i], 1), array[i]); num4 = Inlines.silk_SMLAWB(num4, num3, array[i]); } a3 = Inlines.silk_ADD_LSHIFT32(a3, num4, num); if (a3 < 1) { return 1; } if (a3 > Inlines.silk_RSHIFT(int.MaxValue, num + 2)) { return 1073741823; } return Inlines.silk_LSHIFT(a3, num + 1); } } internal static class Schur { internal static int silk_schur(short[] rc_Q15, int[] c, int order) { int[][] array = Arrays.InitTwoDimensionalArray(17, 2); int num = Inlines.silk_CLZ32(c[0]); int i; if (num < 2) { for (i = 0; i < order + 1; i++) { array[i][0] = (array[i][1] = Inlines.silk_RSHIFT(c[i], 1)); } } else if (num > 2) { num -= 2; for (i = 0; i < order + 1; i++) { array[i][0] = (array[i][1] = Inlines.silk_LSHIFT(c[i], num)); } } else { for (i = 0; i < order + 1; i++) { array[i][0] = (array[i][1] = c[i]); } } for (i = 0; i < order; i++) { if (Inlines.silk_abs_int32(array[i + 1][0]) >= array[0][1]) { if (array[i + 1][0] > 0) { rc_Q15[i] = -32440; } else { rc_Q15[i] = 32440; } i++; break; } int a = -Inlines.silk_DIV32_16(array[i + 1][0], Inlines.silk_max_32(Inlines.silk_RSHIFT(array[0][1], 15), 1)); a = Inlines.silk_SAT16(a); rc_Q15[i] = (short)a; for (int j = 0; j < order - i; j++) { int num2 = array[j + i + 1][0]; int num3 = array[j][1]; array[j + i + 1][0] = Inlines.silk_SMLAWB(num2, Inlines.silk_LSHIFT(num3, 1), a); array[j][1] = Inlines.silk_SMLAWB(num3, Inlines.silk_LSHIFT(num2, 1), a); } } for (; i < order; i++) { rc_Q15[i] = 0; } return Inlines.silk_max_32(1, array[0][1]); } internal static int silk_schur64(int[] rc_Q16, int[] c, int order) { int[][] array = Arrays.InitTwoDimensionalArray(17, 2); if (c[0] <= 0) { Arrays.MemSet(rc_Q16, 0, order); return 0; } int i; for (i = 0; i < order + 1; i++) { array[i][0] = (array[i][1] = c[i]); } for (i = 0; i < order; i++) { if (Inlines.silk_abs_int32(array[i + 1][0]) >= array[0][1]) { if (array[i + 1][0] > 0) { rc_Q16[i] = -64881; } else { rc_Q16[i] = 64881; } i++; break; } int num = Inlines.silk_DIV32_varQ(-array[i + 1][0], array[0][1], 31); rc_Q16[i] = Inlines.silk_RSHIFT_ROUND(num, 15); for (int j = 0; j < order - i; j++) { int num2 = array[j + i + 1][0]; int num3 = array[j][1]; array[j + i + 1][0] = num2 + Inlines.silk_SMMUL(Inlines.silk_LSHIFT(num3, 1), num); array[j][1] = num3 + Inlines.silk_SMMUL(Inlines.silk_LSHIFT(num2, 1), num); } } for (; i < order; i++) { rc_Q16[i] = 0; } return Inlines.silk_max_32(1, array[0][1]); } } internal static class ShellCoder { internal static void combine_pulses(int[] output, int[] input, int input_ptr, int len) { for (int i = 0; i < len; i++) { output[i] = input[input_ptr + 2 * i] + input[input_ptr + 2 * i + 1]; } } internal static void combine_pulses(int[] output, int[] input, int len) { for (int i = 0; i < len; i++) { output[i] = input[2 * i] + input[2 * i + 1]; } } internal static void encode_split(EntropyCoder psRangeEnc, int p_child1, int p, byte[] shell_table) { if (p > 0) { psRangeEnc.enc_icdf(p_child1, shell_table, Tables.silk_shell_code_table_offsets[p], 8u); } } internal static void decode_split(short[] p_child1, int child1_ptr, short[] p_child2, int p_child2_ptr, EntropyCoder psRangeDec, int p, byte[] shell_table) { if (p > 0) { p_child1[child1_ptr] = (short)psRangeDec.dec_icdf(shell_table, Tables.silk_shell_code_table_offsets[p], 8u); p_child2[p_child2_ptr] = (short)(p - p_child1[child1_ptr]); } else { p_child1[child1_ptr] = 0; p_child2[p_child2_ptr] = 0; } } internal static void silk_shell_encoder(EntropyCoder psRangeEnc, int[] pulses0, int pulses0_ptr) { int[] array = new int[8]; int[] array2 = new int[4]; int[] array3 = new int[2]; int[] array4 = new int[1]; combine_pulses(array, pulses0, pulses0_ptr, 8); combine_pulses(array2, array, 4); combine_pulses(array3, array2, 2); combine_pulses(array4, array3, 1); encode_split(psRangeEnc, array3[0], array4[0], Tables.silk_shell_code_table3); encode_split(psRangeEnc, array2[0], array3[0], Tables.silk_shell_code_table2); encode_split(psRangeEnc, array[0], array2[0], Tables.silk_shell_code_table1); encode_split(psRangeEnc, pulses0[pulses0_ptr], array[0], Tables.silk_shell_code_table0); encode_split(psRangeEnc, pulses0[pulses0_ptr + 2], array[1], Tables.silk_shell_code_table0); encode_split(psRangeEnc, array[2], array2[1], Tables.silk_shell_code_table1); encode_split(psRangeEnc, pulses0[pulses0_ptr + 4], array[2], Tables.silk_shell_code_table0); encode_split(psRangeEnc, pulses0[pulses0_ptr + 6], array[3], Tables.silk_shell_code_table0); encode_split(psRangeEnc, array2[2], array3[1], Tables.silk_shell_code_table2); encode_split(psRangeEnc, array[4], array2[2], Tables.silk_shell_code_table1); encode_split(psRangeEnc, pulses0[pulses0_ptr + 8], array[4], Tables.silk_shell_code_table0); encode_split(psRangeEnc, pulses0[pulses0_ptr + 10], array[5], Tables.silk_shell_code_table0); encode_split(psRangeEnc, array[6], array2[3], Tables.silk_shell_code_table1); encode_split(psRangeEnc, pulses0[pulses0_ptr + 12], array[6], Tables.silk_shell_code_table0); encode_split(psRangeEnc, pulses0[pulses0_ptr + 14], array[7], Tables.silk_shell_code_table0); } internal static void silk_shell_decoder(short[] pulses0, int pulses0_ptr, EntropyCoder psRangeDec, int pulses4) { short[] array = new short[8]; short[] array2 = new short[4]; short[] array3 = new short[2]; decode_split(array3, 0, array3, 1, psRangeDec, pulses4, Tables.silk_shell_code_table3); decode_split(array2, 0, array2, 1, psRangeDec, array3[0], Tables.silk_shell_code_table2); decode_split(array, 0, array, 1, psRangeDec, array2[0], Tables.silk_shell_code_table1); decode_split(pulses0, pulses0_ptr, pulses0, pulses0_ptr + 1, psRangeDec, array[0], Tables.silk_shell_code_table0); decode_split(pulses0, pulses0_ptr + 2, pulses0, pulses0_ptr + 3, psRangeDec, array[1], Tables.silk_shell_code_table0); decode_split(array, 2, array, 3, psRangeDec, array2[1], Tables.silk_shell_code_table1); decode_split(pulses0, pulses0_ptr + 4, pulses0, pulses0_ptr + 5, psRangeDec, array[2], Tables.silk_shell_code_table0); decode_split(pulses0, pulses0_ptr + 6, pulses0, pulses0_ptr + 7, psRangeDec, array[3], Tables.silk_shell_code_table0); decode_split(array2, 2, array2, 3, psRangeDec, array3[1], Tables.silk_shell_code_table2); decode_split(array, 4, array, 5, psRangeDec, array2[2], Tables.silk_shell_code_table1); decode_split(pulses0, pulses0_ptr + 8, pulses0, pulses0_ptr + 9, psRangeDec, array[4], Tables.silk_shell_code_table0); decode_split(pulses0, pulses0_ptr + 10, pulses0, pulses0_ptr + 11, psRangeDec, array[5], Tables.silk_shell_code_table0); decode_split(array, 6, array, 7, psRangeDec, array2[3], Tables.silk_shell_code_table1); decode_split(pulses0, pulses0_ptr + 12, pulses0, pulses0_ptr + 13, psRangeDec, array[6], Tables.silk_shell_code_table0); decode_split(pulses0, pulses0_ptr + 14, pulses0, pulses0_ptr + 15, psRangeDec, array[7], Tables.silk_shell_code_table0); } } internal static class Sigmoid { private static readonly int[] sigm_LUT_slope_Q10 = new int[6] { 237, 153, 73, 30, 12, 7 }; private static readonly int[] sigm_LUT_pos_Q15 = new int[6] { 16384, 23955, 28861, 31213, 32178, 32548 }; private static readonly int[] sigm_LUT_neg_Q15 = new int[6] { 16384, 8812, 3906, 1554, 589, 219 }; internal static int silk_sigm_Q15(int in_Q5) { int num; if (in_Q5 < 0) { in_Q5 = -in_Q5; if (in_Q5 >= 192) { return 0; } num = Inlines.silk_RSHIFT(in_Q5, 5); return sigm_LUT_neg_Q15[num] - Inlines.silk_SMULBB(sigm_LUT_slope_Q10[num], in_Q5 & 0x1F); } if (in_Q5 >= 192) { return 32767; } num = Inlines.silk_RSHIFT(in_Q5, 5); return sigm_LUT_pos_Q15[num] + Inlines.silk_SMULBB(sigm_LUT_slope_Q10[num], in_Q5 & 0x1F); } } internal static class SilkConstants { public const int ENCODER_NUM_CHANNELS = 2; public const int DECODER_NUM_CHANNELS = 2; public const int MAX_FRAMES_PER_PACKET = 3; public const int MIN_TARGET_RATE_BPS = 5000; public const int MAX_TARGET_RATE_BPS = 80000; public const int TARGET_RATE_TAB_SZ = 8; public const int LBRR_NB_MIN_RATE_BPS = 12000; public const int LBRR_MB_MIN_RATE_BPS = 14000; public const int LBRR_WB_MIN_RATE_BPS = 16000; public const int NB_SPEECH_FRAMES_BEFORE_DTX = 10; public const int MAX_CONSECUTIVE_DTX = 20; public const int MAX_FS_KHZ = 16; public const int MAX_API_FS_KHZ = 48; public const int TYPE_NO_VOICE_ACTIVITY = 0; public const int TYPE_UNVOICED = 1; public const int TYPE_VOICED = 2; public const int CODE_INDEPENDENTLY = 0; public const int CODE_INDEPENDENTLY_NO_LTP_SCALING = 1; public const int CODE_CONDITIONALLY = 2; public const int STEREO_QUANT_TAB_SIZE = 16; public const int STEREO_QUANT_SUB_STEPS = 5; public const int STEREO_INTERP_LEN_MS = 8; public const float STEREO_RATIO_SMOOTH_COEF = 0.01f; public const int PITCH_EST_MIN_LAG_MS = 2; public const int PITCH_EST_MAX_LAG_MS = 18; public const int MAX_NB_SUBFR = 4; public const int LTP_MEM_LENGTH_MS = 20; public const int SUB_FRAME_LENGTH_MS = 5; public const int MAX_SUB_FRAME_LENGTH = 80; public const int MAX_FRAME_LENGTH_MS = 20; public const int MAX_FRAME_LENGTH = 320; public const int LA_PITCH_MS = 2; public const int LA_PITCH_MAX = 32; public const int MAX_FIND_PITCH_LPC_ORDER = 16; public const int FIND_PITCH_LPC_WIN_MS = 24; public const int FIND_PITCH_LPC_WIN_MS_2_SF = 14; public const int FIND_PITCH_LPC_WIN_MAX = 384; public const int LA_SHAPE_MS = 5; public const int LA_SHAPE_MAX = 80; public const int SHAPE_LPC_WIN_MAX = 240; public const int MIN_QGAIN_DB = 2; public const int MAX_QGAIN_DB = 88; public const int N_LEVELS_QGAIN = 64; public const int MAX_DELTA_GAIN_QUANT = 36; public const int MIN_DELTA_GAIN_QUANT = -4; public const short OFFSET_VL_Q10 = 32; public const short OFFSET_VH_Q10 = 100; public const short OFFSET_UVL_Q10 = 100; public const short OFFSET_UVH_Q10 = 240; public const int QUANT_LEVEL_ADJUST_Q10 = 80; public const int MAX_LPC_STABILIZE_ITERATIONS = 16; public const float MAX_PREDICTION_POWER_GAIN = 10000f; public const float MAX_PREDICTION_POWER_GAIN_AFTER_RESET = 100f; public const int SILK_MAX_ORDER_LPC = 16; public const int MAX_LPC_ORDER = 16; public const int MIN_LPC_ORDER = 10; public const int LTP_ORDER = 5; public const int NB_LTP_CBKS = 3; public const int USE_HARM_SHAPING = 1; public const int MAX_SHAPE_LPC_ORDER = 16; public const int HARM_SHAPE_FIR_TAPS = 3; public const int MAX_DEL_DEC_STATES = 4; public const int LTP_BUF_LENGTH = 512; public const int LTP_MASK = 511; public const int DECISION_DELAY = 32; public const int DECISION_DELAY_MASK = 31; public const int SHELL_CODEC_FRAME_LENGTH = 16; public const int LOG2_SHELL_CODEC_FRAME_LENGTH = 4; public const int MAX_NB_SHELL_BLOCKS = 20; public const int N_RATE_LEVELS = 10; public const int SILK_MAX_PULSES = 16; public const int MAX_MATRIX_SIZE = 16; public const int VAD_N_BANDS = 4; public const int VAD_INTERNAL_SUBFRAMES_LOG2 = 2; public const int VAD_INTERNAL_SUBFRAMES = 4; public const int VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 = 1024; public const int VAD_NOISE_LEVELS_BIAS = 50; public const int VAD_NEGATIVE_OFFSET_Q5 = 128; public const int VAD_SNR_FACTOR_Q16 = 45000; public const int VAD_SNR_SMOOTH_COEF_Q18 = 4096; public const int LSF_COS_TAB_SZ = 128; public const int NLSF_W_Q = 2; public const int NLSF_VQ_MAX_VECTORS = 32; public const int NLSF_VQ_MAX_SURVIVORS = 32; public const int NLSF_QUANT_MAX_AMPLITUDE = 4; public const int NLSF_QUANT_MAX_AMPLITUDE_EXT = 10; public const float NLSF_QUANT_LEVEL_ADJ = 0.1f; public const int NLSF_QUANT_DEL_DEC_STATES_LOG2 = 2; public const int NLSF_QUANT_DEL_DEC_STATES = 4; public const int TRANSITION_TIME_MS = 5120; public const int TRANSITION_NB = 3; public const int TRANSITION_NA = 2; public const int TRANSITION_INT_NUM = 5; public const int TRANSITION_FRAMES = 256; public const int TRANSITION_INT_STEPS = 64; public const int BWE_AFTER_LOSS_Q16 = 63570; public const int CNG_BUF_MASK_MAX = 255; public const int CNG_GAIN_SMTH_Q16 = 4634; public const int CNG_NLSF_SMTH_Q16 = 16348; public const int PE_MAX_FS_KHZ = 16; public const int PE_MAX_NB_SUBFR = 4; public const int PE_SUBFR_LENGTH_MS = 5; public const int PE_LTP_MEM_LENGTH_MS = 20; public const int PE_MAX_FRAME_LENGTH_MS = 40; public const int PE_MAX_FRAME_LENGTH = 640; public const int PE_MAX_FRAME_LENGTH_ST_1 = 160; public const int PE_MAX_FRAME_LENGTH_ST_2 = 320; public const int PE_MAX_LAG_MS = 18; public const int PE_MIN_LAG_MS = 2; public const int PE_MAX_LAG = 288; public const int PE_MIN_LAG = 32; public const int PE_D_SRCH_LENGTH = 24; public const int PE_NB_STAGE3_LAGS = 5; public const int PE_NB_CBKS_STAGE2 = 3; public const int PE_NB_CBKS_STAGE2_EXT = 11; public const int PE_NB_CBKS_STAGE3_MAX = 34; public const int PE_NB_CBKS_STAGE3_MID = 24; public const int PE_NB_CBKS_STAGE3_MIN = 16; public const int PE_NB_CBKS_STAGE3_10MS = 12; public const int PE_NB_CBKS_STAGE2_10MS = 3; public const float PE_SHORTLAG_BIAS = 0.2f; public const float PE_PREVLAG_BIAS = 0.2f; public const float PE_FLATCONTOUR_BIAS = 0.05f; public const int SILK_PE_MIN_COMPLEX = 0; public const int SILK_PE_MID_COMPLEX = 1; public const int SILK_PE_MAX_COMPLEX = 2; public const float BWE_COEF = 0.99f; public const int V_PITCH_GAIN_START_MIN_Q14 = 11469; public const int V_PITCH_GAIN_START_MAX_Q14 = 15565; public const int MAX_PITCH_LAG_MS = 18; public const int RAND_BUF_SIZE = 128; public const int RAND_BUF_MASK = 127; public const int LOG2_INV_LPC_GAIN_HIGH_THRES = 3; public const int LOG2_INV_LPC_GAIN_LOW_THRES = 8; public const int PITCH_DRIFT_FAC_Q16 = 655; public const int SILK_RESAMPLER_MAX_FIR_ORDER = 36; public const int SILK_RESAMPLER_MAX_IIR_ORDER = 6; public const int RESAMPLER_DOWN_ORDER_FIR0 = 18; public const int RESAMPLER_DOWN_ORDER_FIR1 = 24; public const int RESAMPLER_DOWN_ORDER_FIR2 = 36; public const int RESAMPLER_ORDER_FIR_12 = 8; public const int RESAMPLER_MAX_BATCH_SIZE_MS = 10; public const int RESAMPLER_MAX_FS_KHZ = 48; public const int RESAMPLER_MAX_BATCH_SIZE_IN = 480; public const int SILK_MAX_FRAMES_PER_PACKET = 3; internal static readonly int NSQ_LPC_BUF_LENGTH = Math.Max(16, 32); } internal static class Sort { internal static void silk_insertion_sort_increasing(int[] a, int[] idx, int L, int K) { for (int i = 0; i < K; i++) { idx[i] = i; } for (int i = 1; i < K; i++) { int num = a[i]; int num2 = i - 1; while (num2 >= 0 && num < a[num2]) { a[num2 + 1] = a[num2]; idx[num2 + 1] = idx[num2]; num2--; } a[num2 + 1] = num; idx[num2 + 1] = i; } for (int i = K; i < L; i++) { int num = a[i]; if (num < a[K - 1]) { int num2 = K - 2; while (num2 >= 0 && num < a[num2]) { a[num2 + 1] = a[num2]; idx[num2 + 1] = idx[num2]; num2--; } a[num2 + 1] = num; idx[num2 + 1] = i; } } } internal static void silk_insertion_sort_increasing_all_values_int16(short[] a, int L) { for (int i = 1; i < L; i++) { short num = a[i]; int num2 = i - 1; while (num2 >= 0 && num < a[num2]) { a[num2 + 1] = a[num2]; num2--; } a[num2 + 1] = num; } } internal static void silk_insertion_sort_decreasing_int16(short[] a, int[] idx, int L, int K) { for (int i = 0; i < K; i++) { idx[i] = i; } for (int i = 1; i < K; i++) { short num = a[i]; int num2 = i - 1; while (num2 >= 0 && num > a[num2]) { a[num2 + 1] = a[num2]; idx[num2 + 1] = idx[num2]; num2--; } a[num2 + 1] = num; idx[num2 + 1] = i; } for (int i = K; i < L; i++) { short num = a[i]; if (num > a[K - 1]) { int num2 = K - 2; while (num2 >= 0 && num > a[num2]) { a[num2 + 1] = a[num2]; idx[num2 + 1] = idx[num2]; num2--; } a[num2 + 1] = num; idx[num2 + 1] = i; } } } } internal static class Stereo { internal static void silk_stereo_decode_pred(EntropyCoder psRangeDec, int[] pred_Q13) { int[][] array = Arrays.InitTwoDimensionalArray(2, 3); int num = psRangeDec.dec_icdf(Tables.silk_stereo_pred_joint_iCDF, 8u); array[0][2] = Inlines.silk_DIV32_16(num, 5); array[1][2] = num - 5 * array[0][2]; for (num = 0; num < 2; num++) { array[num][0] = psRangeDec.dec_icdf(Tables.silk_uniform3_iCDF, 8u); array[num][1] = psRangeDec.dec_icdf(Tables.silk_uniform5_iCDF, 8u); } for (num = 0; num < 2; num++) { array[num][0] += 3 * array[num][2]; int num2 = Tables.silk_stereo_pred_quant_Q13[array[num][0]]; int b = Inlines.silk_SMULWB(Tables.silk_stereo_pred_quant_Q13[array[num][0] + 1] - num2, 6554); pred_Q13[num] = Inlines.silk_SMLABB(num2, b, 2 * array[num][1] + 1); } pred_Q13[0] -= pred_Q13[1]; } internal static void silk_stereo_decode_mid_only(EntropyCoder psRangeDec, BoxedValue decode_only_mid) { decode_only_mid.Val = psRangeDec.dec_icdf(Tables.silk_stereo_only_code_mid_iCDF, 8u); } internal static void silk_stereo_encode_pred(EntropyCoder psRangeEnc, sbyte[][] ix) { int s = 5 * ix[0][2] + ix[1][2]; psRangeEnc.enc_icdf(s, Tables.silk_stereo_pred_joint_iCDF, 8u); for (s = 0; s < 2; s++) { psRangeEnc.enc_icdf(ix[s][0], Tables.silk_uniform3_iCDF, 8u); psRangeEnc.enc_icdf(ix[s][1], Tables.silk_uniform5_iCDF, 8u); } } internal static void silk_stereo_encode_mid_only(EntropyCoder psRangeEnc, sbyte mid_only_flag) { psRangeEnc.enc_icdf(mid_only_flag, Tables.silk_stereo_only_code_mid_iCDF, 8u); } internal static int silk_stereo_find_predictor(BoxedValue ratio_Q14, short[] x, short[] y, int[] mid_res_amp_Q0, int mid_res_amp_Q0_ptr, int length, int smooth_coef_Q16) { SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, x, length); SumSqrShift.silk_sum_sqr_shift(out var energy2, out var shift2, y, length); int num = Inlines.silk_max_int(shift, shift2); num += num & 1; energy2 = Inlines.silk_RSHIFT32(energy2, num - shift2); energy = Inlines.silk_RSHIFT32(energy, num - shift); energy = Inlines.silk_max_int(energy, 1); int a = Inlines.silk_inner_prod_aligned_scale(x, y, num, length); int a2 = Inlines.silk_DIV32_varQ(a, energy, 13); a2 = Inlines.silk_LIMIT(a2, -16384, 16384); int num2 = Inlines.silk_SMULWB(a2, a2); smooth_coef_Q16 = Inlines.silk_max_int(smooth_coef_Q16, Inlines.silk_abs(num2)); num = Inlines.silk_RSHIFT(num, 1); mid_res_amp_Q0[mid_res_amp_Q0_ptr] = Inlines.silk_SMLAWB(mid_res_amp_Q0[mid_res_amp_Q0_ptr], Inlines.silk_LSHIFT(Inlines.silk_SQRT_APPROX(energy), num) - mid_res_amp_Q0[mid_res_amp_Q0_ptr], smooth_coef_Q16); energy2 = Inlines.silk_SUB_LSHIFT32(energy2, Inlines.silk_SMULWB(a, a2), 4); energy2 = Inlines.silk_ADD_LSHIFT32(energy2, Inlines.silk_SMULWB(energy, num2), 6); mid_res_amp_Q0[mid_res_amp_Q0_ptr + 1] = Inlines.silk_SMLAWB(mid_res_amp_Q0[mid_res_amp_Q0_ptr + 1], Inlines.silk_LSHIFT(Inlines.silk_SQRT_APPROX(energy2), num) - mid_res_amp_Q0[mid_res_amp_Q0_ptr + 1], smooth_coef_Q16); ratio_Q14.Val = Inlines.silk_DIV32_varQ(mid_res_amp_Q0[mid_res_amp_Q0_ptr + 1], Inlines.silk_max(mid_res_amp_Q0[mid_res_amp_Q0_ptr], 1), 14); ratio_Q14.Val = Inlines.silk_LIMIT(ratio_Q14.Val, 0, 32767); return a2; } internal static void silk_stereo_LR_to_MS(StereoEncodeState state, short[] x1, int x1_ptr, short[] x2, int x2_ptr, sbyte[][] ix, BoxedValue mid_only_flag, int[] mid_side_rates_bps, int total_rate_bps, int prev_speech_act_Q8, int toMono, int fs_kHz, int frame_length) { int[] array = new int[2]; BoxedValue boxedValue = new BoxedValue(0); BoxedValue boxedValue2 = new BoxedValue(0); int num = x1_ptr - 2; short[] array2 = new short[frame_length + 2]; for (int i = 0; i < frame_length + 2; i++) { int a = x1[x1_ptr + i - 2] + x2[x2_ptr + i - 2]; int a2 = x1[x1_ptr + i - 2] - x2[x2_ptr + i - 2]; x1[num + i] = (short)Inlines.silk_RSHIFT_ROUND(a, 1); array2[i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a2, 1)); } Array.Copy(state.sMid, 0, x1, num, 2); Array.Copy(state.sSide, array2, 2); Array.Copy(x1, num + frame_length, state.sMid, 0, 2); Array.Copy(array2, frame_length, state.sSide, 0, 2); short[] array3 = new short[frame_length]; short[] array4 = new short[frame_length]; for (int i = 0; i < frame_length; i++) { int a = Inlines.silk_RSHIFT_ROUND(Inlines.silk_ADD_LSHIFT32(x1[num + i] + x1[num + i + 2], x1[num + i + 1], 1), 2); array3[i] = (short)a; array4[i] = (short)(x1[num + i + 1] - a); } short[] array5 = new short[frame_length]; short[] array6 = new short[frame_length]; for (int i = 0; i < frame_length; i++) { int a = Inlines.silk_RSHIFT_ROUND(Inlines.silk_ADD_LSHIFT32(array2[i] + array2[i + 2], array2[i + 1], 1), 2); array5[i] = (short)a; array6[i] = (short)(array2[i + 1] - a); } int num2 = ((frame_length == 10 * fs_kHz) ? 1 : 0); int b = ((num2 != 0) ? 328 : 655); b = Inlines.silk_SMULWB(Inlines.silk_SMULBB(prev_speech_act_Q8, prev_speech_act_Q8), b); array[0] = silk_stereo_find_predictor(boxedValue, array3, array5, state.mid_side_amp_Q0, 0, frame_length, b); array[1] = silk_stereo_find_predictor(boxedValue2, array4, array6, state.mid_side_amp_Q0, 2, frame_length, b); int a3 = Inlines.silk_SMLABB(boxedValue2.Val, boxedValue.Val, 3); a3 = Inlines.silk_min(a3, 65536); total_rate_bps -= ((num2 != 0) ? 1200 : 600); if (total_rate_bps < 1) { total_rate_bps = 1; } int num3 = Inlines.silk_SMLABB(2000, fs_kHz, 900); int num4 = Inlines.silk_MUL(3, a3); mid_side_rates_bps[0] = Inlines.silk_DIV32_varQ(total_rate_bps, 851968 + num4, 19); int a4; if (mid_side_rates_bps[0] < num3) { mid_side_rates_bps[0] = num3; mid_side_rates_bps[1] = total_rate_bps - mid_side_rates_bps[0]; a4 = Inlines.silk_DIV32_varQ(Inlines.silk_LSHIFT(mid_side_rates_bps[1], 1) - num3, Inlines.silk_SMULWB(65536 + num4, num3), 16); a4 = Inlines.silk_LIMIT(a4, 0, 16384); } else { mid_side_rates_bps[1] = total_rate_bps - mid_side_rates_bps[0]; a4 = 16384; } state.smth_width_Q14 = (short)Inlines.silk_SMLAWB(state.smth_width_Q14, a4 - state.smth_width_Q14, b); mid_only_flag.Val = 0; if (toMono != 0) { a4 = 0; array[0] = 0; array[1] = 0; silk_stereo_quant_pred(array, ix); } else if (state.width_prev_Q14 == 0 && (8 * total_rate_bps < 13 * num3 || Inlines.silk_SMULWB(a3, state.smth_width_Q14) < 819)) { array[0] = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(state.smth_width_Q14, array[0]), 14); array[1] = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(state.smth_width_Q14, array[1]), 14); silk_stereo_quant_pred(array, ix); a4 = 0; array[0] = 0; array[1] = 0; mid_side_rates_bps[0] = total_rate_bps; mid_side_rates_bps[1] = 0; mid_only_flag.Val = 1; } else if (state.width_prev_Q14 != 0 && (8 * total_rate_bps < 11 * num3 || Inlines.silk_SMULWB(a3, state.smth_width_Q14) < 328)) { array[0] = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(state.smth_width_Q14, array[0]), 14); array[1] = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(state.smth_width_Q14, array[1]), 14); silk_stereo_quant_pred(array, ix); a4 = 0; array[0] = 0; array[1] = 0; } else if (state.smth_width_Q14 > 15565) { silk_stereo_quant_pred(array, ix); a4 = 16384; } else { array[0] = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(state.smth_width_Q14, array[0]), 14); array[1] = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(state.smth_width_Q14, array[1]), 14); silk_stereo_quant_pred(array, ix); a4 = state.smth_width_Q14; } if (mid_only_flag.Val == 1) { state.silent_side_len += (short)(frame_length - 8 * fs_kHz); if (state.silent_side_len < 5 * fs_kHz) { mid_only_flag.Val = 0; } else { state.silent_side_len = 10000; } } else { state.silent_side_len = 0; } if (mid_only_flag.Val == 0 && mid_side_rates_bps[1] < 1) { mid_side_rates_bps[1] = 1; mid_side_rates_bps[0] = Inlines.silk_max_int(1, total_rate_bps - mid_side_rates_bps[1]); } int num5 = -state.pred_prev_Q13[0]; int num6 = -state.pred_prev_Q13[1]; int num7 = Inlines.silk_LSHIFT(state.width_prev_Q14, 10); int b2 = Inlines.silk_DIV32_16(65536, 8 * fs_kHz); int num8 = -Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULBB(array[0] - state.pred_prev_Q13[0], b2), 16); int num9 = -Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULBB(array[1] - state.pred_prev_Q13[1], b2), 16); int num10 = Inlines.silk_LSHIFT(Inlines.silk_SMULWB(a4 - state.width_prev_Q14, b2), 10); for (int i = 0; i < 8 * fs_kHz; i++) { num5 += num8; num6 += num9; num7 += num10; int a = Inlines.silk_LSHIFT(Inlines.silk_ADD_LSHIFT(x1[num + i] + x1[num + i + 2], x1[num + i + 1], 1), 9); a = Inlines.silk_SMLAWB(Inlines.silk_SMULWB(num7, array2[i + 1]), a, num5); a = Inlines.silk_SMLAWB(a, Inlines.silk_LSHIFT(x1[num + i + 1], 11), num6); x2[x2_ptr + i - 1] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 8)); } num5 = -array[0]; num6 = -array[1]; num7 = Inlines.silk_LSHIFT(a4, 10); for (int i = 8 * fs_kHz; i < frame_length; i++) { int a = Inlines.silk_LSHIFT(Inlines.silk_ADD_LSHIFT(x1[num + i] + x1[num + i + 2], x1[num + i + 1], 1), 9); a = Inlines.silk_SMLAWB(Inlines.silk_SMULWB(num7, array2[i + 1]), a, num5); a = Inlines.silk_SMLAWB(a, Inlines.silk_LSHIFT(x1[num + i + 1], 11), num6); x2[x2_ptr + i - 1] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a, 8)); } state.pred_prev_Q13[0] = (short)array[0]; state.pred_prev_Q13[1] = (short)array[1]; state.width_prev_Q14 = (short)a4; } internal static void silk_stereo_MS_to_LR(StereoDecodeState state, short[] x1, int x1_ptr, short[] x2, int x2_ptr, int[] pred_Q13, int fs_kHz, int frame_length) { Array.Copy(state.sMid, 0, x1, x1_ptr, 2); Array.Copy(state.sSide, 0, x2, x2_ptr, 2); Array.Copy(x1, x1_ptr + frame_length, state.sMid, 0, 2); Array.Copy(x2, x2_ptr + frame_length, state.sSide, 0, 2); int num = state.pred_prev_Q13[0]; int num2 = state.pred_prev_Q13[1]; int b = Inlines.silk_DIV32_16(65536, 8 * fs_kHz); int num3 = Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULBB(pred_Q13[0] - state.pred_prev_Q13[0], b), 16); int num4 = Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULBB(pred_Q13[1] - state.pred_prev_Q13[1], b), 16); for (int i = 0; i < 8 * fs_kHz; i++) { num += num3; num2 += num4; int b2 = Inlines.silk_LSHIFT(Inlines.silk_ADD_LSHIFT(x1[x1_ptr + i] + x1[x1_ptr + i + 2], x1[x1_ptr + i + 1], 1), 9); b2 = Inlines.silk_SMLAWB(Inlines.silk_LSHIFT(x2[x2_ptr + i + 1], 8), b2, num); b2 = Inlines.silk_SMLAWB(b2, Inlines.silk_LSHIFT(x1[x1_ptr + i + 1], 11), num2); x2[x2_ptr + i + 1] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(b2, 8)); } num = pred_Q13[0]; num2 = pred_Q13[1]; for (int i = 8 * fs_kHz; i < frame_length; i++) { int b2 = Inlines.silk_LSHIFT(Inlines.silk_ADD_LSHIFT(x1[x1_ptr + i] + x1[x1_ptr + i + 2], x1[x1_ptr + i + 1], 1), 9); b2 = Inlines.silk_SMLAWB(Inlines.silk_LSHIFT(x2[x2_ptr + i + 1], 8), b2, num); b2 = Inlines.silk_SMLAWB(b2, Inlines.silk_LSHIFT(x1[x1_ptr + i + 1], 11), num2); x2[x2_ptr + i + 1] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(b2, 8)); } state.pred_prev_Q13[0] = (short)pred_Q13[0]; state.pred_prev_Q13[1] = (short)pred_Q13[1]; for (int i = 0; i < frame_length; i++) { int b2 = x1[x1_ptr + i + 1] + x2[x2_ptr + i + 1]; int a = x1[x1_ptr + i + 1] - x2[x2_ptr + i + 1]; x1[x1_ptr + i + 1] = (short)Inlines.silk_SAT16(b2); x2[x2_ptr + i + 1] = (short)Inlines.silk_SAT16(a); } } internal static void silk_stereo_quant_pred(int[] pred_Q13, sbyte[][] ix) { int num = 0; Arrays.MemSet(ix[0], (sbyte)0, 3); Arrays.MemSet(ix[1], (sbyte)0, 3); for (int i = 0; i < 2; i++) { int num2 = int.MaxValue; sbyte b = 0; while (b < 15) { int num3 = Tables.silk_stereo_pred_quant_Q13[b]; int b2 = Inlines.silk_SMULWB(Tables.silk_stereo_pred_quant_Q13[b + 1] - num3, 6554); sbyte b3 = 0; while (b3 < 5) { int num4 = Inlines.silk_SMLABB(num3, b2, 2 * b3 + 1); int num5 = Inlines.silk_abs(pred_Q13[i] - num4); if (num5 < num2) { num2 = num5; num = num4; ix[i][0] = b; ix[i][1] = b3; b3++; continue; } goto end_IL_00b1; } b++; continue; end_IL_00b1: break; } ix[i][2] = (sbyte)Inlines.silk_DIV32_16(ix[i][0], 3); ix[i][0] = (sbyte)(ix[i][0] - (sbyte)(ix[i][2] * 3)); pred_Q13[i] = num; } pred_Q13[0] -= pred_Q13[1]; } } internal static class SumSqrShift { internal static void silk_sum_sqr_shift(out int energy, out int shift, short[] x, int x_ptr, int len) { int num = 0; int num2 = 0; len--; int i; for (i = 0; i < len; i += 2) { num = Inlines.silk_SMLABB_ovflw(num, x[x_ptr + i], x[x_ptr + i]); num = Inlines.silk_SMLABB_ovflw(num, x[x_ptr + i + 1], x[x_ptr + i + 1]); if (num < 0) { num = (int)Inlines.silk_RSHIFT_uint((uint)num, 2); num2 = 2; i += 2; break; } } for (; i < len; i += 2) { int a = Inlines.silk_SMULBB(x[x_ptr + i], x[x_ptr + i]); a = Inlines.silk_SMLABB_ovflw(a, x[x_ptr + i + 1], x[x_ptr + i + 1]); num = (int)Inlines.silk_ADD_RSHIFT_uint((uint)num, (uint)a, num2); if (num < 0) { num = (int)Inlines.silk_RSHIFT_uint((uint)num, 2); num2 += 2; } } if (i == len) { int a = Inlines.silk_SMULBB(x[x_ptr + i], x[x_ptr + i]); num = (int)Inlines.silk_ADD_RSHIFT_uint((uint)num, (uint)a, num2); } if ((num & 0xC0000000u) != 0) { num = (int)Inlines.silk_RSHIFT_uint((uint)num, 2); num2 += 2; } shift = num2; energy = num; } internal static void silk_sum_sqr_shift(out int energy, out int shift, short[] x, int len) { int num = 0; int num2 = 0; len--; int i; for (i = 0; i < len; i += 2) { num = Inlines.silk_SMLABB_ovflw(num, x[i], x[i]); num = Inlines.silk_SMLABB_ovflw(num, x[i + 1], x[i + 1]); if (num < 0) { num = (int)Inlines.silk_RSHIFT_uint((uint)num, 2); num2 = 2; i += 2; break; } } for (; i < len; i += 2) { int a = Inlines.silk_SMULBB(x[i], x[i]); a = Inlines.silk_SMLABB_ovflw(a, x[i + 1], x[i + 1]); num = (int)Inlines.silk_ADD_RSHIFT_uint((uint)num, (uint)a, num2); if (num < 0) { num = (int)Inlines.silk_RSHIFT_uint((uint)num, 2); num2 += 2; } } if (i == len) { int a = Inlines.silk_SMULBB(x[i], x[i]); num = (int)Inlines.silk_ADD_RSHIFT_uint((uint)num, (uint)a, num2); } if ((num & 0xC0000000u) != 0) { num = (int)Inlines.silk_RSHIFT_uint((uint)num, 2); num2 += 2; } shift = num2; energy = num; } } internal static class Tables { public const short silk_resampler_down2_0 = 9872; public const short silk_resampler_down2_1 = -25727; internal static readonly short[] silk_LSFCosTab_Q12 = new short[129] { 8192, 8190, 8182, 8170, 8152, 8130, 8104, 8072, 8034, 7994, 7946, 7896, 7840, 7778, 7714, 7644, 7568, 7490, 7406, 7318, 7226, 7128, 7026, 6922, 6812, 6698, 6580, 6458, 6332, 6204, 6070, 5934, 5792, 5648, 5502, 5352, 5198, 5040, 4880, 4718, 4552, 4382, 4212, 4038, 3862, 3684, 3502, 3320, 3136, 2948, 2760, 2570, 2378, 2186, 1990, 1794, 1598, 1400, 1202, 1002, 802, 602, 402, 202, 0, -202, -402, -602, -802, -1002, -1202, -1400, -1598, -1794, -1990, -2186, -2378, -2570, -2760, -2948, -3136, -3320, -3502, -3684, -3862, -4038, -4212, -4382, -4552, -4718, -4880, -5040, -5198, -5352, -5502, -5648, -5792, -5934, -6070, -6204, -6332, -6458, -6580, -6698, -6812, -6922, -7026, -7128, -7226, -7318, -7406, -7490, -7568, -7644, -7714, -7778, -7840, -7896, -7946, -7994, -8034, -8072, -8104, -8130, -8152, -8170, -8182, -8190, -8192 }; internal static readonly byte[][] silk_gain_iCDF = new byte[3][] { new byte[8] { 224, 112, 44, 15, 3, 2, 1, 0 }, new byte[8] { 254, 237, 192, 132, 70, 23, 4, 0 }, new byte[8] { 255, 252, 226, 155, 61, 11, 2, 0 } }; internal static readonly byte[] silk_delta_gain_iCDF = new byte[41] { 250, 245, 234, 203, 71, 50, 42, 38, 35, 33, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; internal static readonly byte[] silk_LTP_per_index_iCDF = new byte[3] { 179, 99, 0 }; internal static readonly byte[] silk_LTP_gain_iCDF_0 = new byte[8] { 71, 56, 43, 30, 21, 12, 6, 0 }; internal static readonly byte[] silk_LTP_gain_iCDF_1 = new byte[16] { 199, 165, 144, 124, 109, 96, 84, 71, 61, 51, 42, 32, 23, 15, 8, 0 }; internal static readonly byte[] silk_LTP_gain_iCDF_2 = new byte[32] { 241, 225, 211, 199, 187, 175, 164, 153, 142, 132, 123, 114, 105, 96, 88, 80, 72, 64, 57, 50, 44, 38, 33, 29, 24, 20, 16, 12, 9, 5, 2, 0 }; internal static readonly short silk_LTP_gain_middle_avg_RD_Q14 = 12304; internal static readonly byte[] silk_LTP_gain_BITS_Q5_0 = new byte[8] { 15, 131, 138, 138, 155, 155, 173, 173 }; internal static readonly byte[] silk_LTP_gain_BITS_Q5_1 = new byte[16] { 69, 93, 115, 118, 131, 138, 141, 138, 150, 150, 155, 150, 155, 160, 166, 160 }; internal static readonly byte[] silk_LTP_gain_BITS_Q5_2 = new byte[32] { 131, 128, 134, 141, 141, 141, 145, 145, 145, 150, 155, 155, 155, 155, 160, 160, 160, 160, 166, 166, 173, 173, 182, 192, 182, 192, 192, 192, 205, 192, 205, 224 }; internal static readonly byte[][] silk_LTP_gain_iCDF_ptrs = new byte[3][] { silk_LTP_gain_iCDF_0, silk_LTP_gain_iCDF_1, silk_LTP_gain_iCDF_2 }; internal static readonly byte[][] silk_LTP_gain_BITS_Q5_ptrs = new byte[3][] { silk_LTP_gain_BITS_Q5_0, silk_LTP_gain_BITS_Q5_1, silk_LTP_gain_BITS_Q5_2 }; internal static readonly sbyte[][] silk_LTP_gain_vq_0 = new sbyte[8][] { new sbyte[5] { 4, 6, 24, 7, 5 }, new sbyte[5] { 0, 0, 2, 0, 0 }, new sbyte[5] { 12, 28, 41, 13, -4 }, new sbyte[5] { -9, 15, 42, 25, 14 }, new sbyte[5] { 1, -2, 62, 41, -9 }, new sbyte[5] { -10, 37, 65, -4, 3 }, new sbyte[5] { -6, 4, 66, 7, -8 }, new sbyte[5] { 16, 14, 38, -3, 33 } }; internal static readonly sbyte[][] silk_LTP_gain_vq_1 = new sbyte[16][] { new sbyte[5] { 13, 22, 39, 23, 12 }, new sbyte[5] { -1, 36, 64, 27, -6 }, new sbyte[5] { -7, 10, 55, 43, 17 }, new sbyte[5] { 1, 1, 8, 1, 1 }, new sbyte[5] { 6, -11, 74, 53, -9 }, new sbyte[5] { -12, 55, 76, -12, 8 }, new sbyte[5] { -3, 3, 93, 27, -4 }, new sbyte[5] { 26, 39, 59, 3, -8 }, new sbyte[5] { 2, 0, 77, 11, 9 }, new sbyte[5] { -8, 22, 44, -6, 7 }, new sbyte[5] { 40, 9, 26, 3, 9 }, new sbyte[5] { -7, 20, 101, -7, 4 }, new sbyte[5] { 3, -8, 42, 26, 0 }, new sbyte[5] { -15, 33, 68, 2, 23 }, new sbyte[5] { -2, 55, 46, -2, 15 }, new sbyte[5] { 3, -1, 21, 16, 41 } }; internal static readonly sbyte[][] silk_LTP_gain_vq_2 = new sbyte[32][] { new sbyte[5] { -6, 27, 61, 39, 5 }, new sbyte[5] { -11, 42, 88, 4, 1 }, new sbyte[5] { -2, 60, 65, 6, -4 }, new sbyte[5] { -1, -5, 73, 56, 1 }, new sbyte[5] { -9, 19, 94, 29, -9 }, new sbyte[5] { 0, 12, 99, 6, 4 }, new sbyte[5] { 8, -19, 102, 46, -13 }, new sbyte[5] { 3, 2, 13, 3, 2 }, new sbyte[5] { 9, -21, 84, 72, -18 }, new sbyte[5] { -11, 46, 104, -22, 8 }, new sbyte[5] { 18, 38, 48, 23, 0 }, new sbyte[5] { -16, 70, 83, -21, 11 }, new sbyte[5] { 5, -11, 117, 22, -8 }, new sbyte[5] { -6, 23, 117, -12, 3 }, new sbyte[5] { 3, -8, 95, 28, 4 }, new sbyte[5] { -10, 15, 77, 60, -15 }, new sbyte[5] { -1, 4, 124, 2, -4 }, new sbyte[5] { 3, 38, 84, 24, -25 }, new sbyte[5] { 2, 13, 42, 13, 31 }, new sbyte[5] { 21, -4, 56, 46, -1 }, new sbyte[5] { -1, 35, 79, -13, 19 }, new sbyte[5] { -7, 65, 88, -9, -14 }, new sbyte[5] { 20, 4, 81, 49, -29 }, new sbyte[5] { 20, 0, 75, 3, -17 }, new sbyte[5] { 5, -9, 44, 92, -8 }, new sbyte[5] { 1, -3, 22, 69, 31 }, new sbyte[5] { -6, 95, 41, -12, 5 }, new sbyte[5] { 39, 67, 16, -4, 1 }, new sbyte[5] { 0, -6, 120, 55, -36 }, new sbyte[5] { -13, 44, 122, 4, -24 }, new sbyte[5] { 81, 5, 11, 3, 7 }, new sbyte[5] { 2, 0, 9, 10, 88 } }; internal static readonly sbyte[][][] silk_LTP_vq_ptrs_Q7 = new sbyte[3][][] { silk_LTP_gain_vq_0, silk_LTP_gain_vq_1, silk_LTP_gain_vq_2 }; internal static readonly byte[] silk_LTP_gain_vq_0_gain = new byte[8] { 46, 2, 90, 87, 93, 91, 82, 98 }; internal static readonly byte[] silk_LTP_gain_vq_1_gain = new byte[16] { 109, 120, 118, 12, 113, 115, 117, 119, 99, 59, 87, 111, 63, 111, 112, 80 }; internal static readonly byte[] silk_LTP_gain_vq_2_gain = new byte[32] { 126, 124, 125, 124, 129, 121, 126, 23, 132, 127, 127, 127, 126, 127, 122, 133, 130, 134, 101, 118, 119, 145, 126, 86, 124, 120, 123, 119, 170, 173, 107, 109 }; internal static readonly byte[][] silk_LTP_vq_gain_ptrs_Q7 = new byte[3][] { silk_LTP_gain_vq_0_gain, silk_LTP_gain_vq_1_gain, silk_LTP_gain_vq_2_gain }; internal static readonly sbyte[] silk_LTP_vq_sizes = new sbyte[3] { 8, 16, 32 }; internal static readonly byte[] silk_NLSF_CB1_NB_MB_Q8 = new byte[320] { 12, 35, 60, 83, 108, 132, 157, 180, 206, 228, 15, 32, 55, 77, 101, 125, 151, 175, 201, 225, 19, 42, 66, 89, 114, 137, 162, 184, 209, 230, 12, 25, 50, 72, 97, 120, 147, 172, 200, 223, 26, 44, 69, 90, 114, 135, 159, 180, 205, 225, 13, 22, 53, 80, 106, 130, 156, 180, 205, 228, 15, 25, 44, 64, 90, 115, 142, 168, 196, 222, 19, 24, 62, 82, 100, 120, 145, 168, 190, 214, 22, 31, 50, 79, 103, 120, 151, 170, 203, 227, 21, 29, 45, 65, 106, 124, 150, 171, 196, 224, 30, 49, 75, 97, 121, 142, 165, 186, 209, 229, 19, 25, 52, 70, 93, 116, 143, 166, 192, 219, 26, 34, 62, 75, 97, 118, 145, 167, 194, 217, 25, 33, 56, 70, 91, 113, 143, 165, 196, 223, 21, 34, 51, 72, 97, 117, 145, 171, 196, 222, 20, 29, 50, 67, 90, 117, 144, 168, 197, 221, 22, 31, 48, 66, 95, 117, 146, 168, 196, 222, 24, 33, 51, 77, 116, 134, 158, 180, 200, 224, 21, 28, 70, 87, 106, 124, 149, 170, 194, 217, 26, 33, 53, 64, 83, 117, 152, 173, 204, 225, 27, 34, 65, 95, 108, 129, 155, 174, 210, 225, 20, 26, 72, 99, 113, 131, 154, 176, 200, 219, 34, 43, 61, 78, 93, 114, 155, 177, 205, 229, 23, 29, 54, 97, 124, 138, 163, 179, 209, 229, 30, 38, 56, 89, 118, 129, 158, 178, 200, 231, 21, 29, 49, 63, 85, 111, 142, 163, 193, 222, 27, 48, 77, 103, 133, 158, 179, 196, 215, 232, 29, 47, 74, 99, 124, 151, 176, 198, 220, 237, 33, 42, 61, 76, 93, 121, 155, 174, 207, 225, 29, 53, 87, 112, 136, 154, 170, 188, 208, 227, 24, 30, 52, 84, 131, 150, 166, 186, 203, 229, 37, 48, 64, 84, 104, 118, 156, 177, 201, 230 }; internal static readonly byte[] silk_NLSF_CB1_iCDF_NB_MB = new byte[64] { 212, 178, 148, 129, 108, 96, 85, 82, 79, 77, 61, 59, 57, 56, 51, 49, 48, 45, 42, 41, 40, 38, 36, 34, 31, 30, 21, 12, 10, 3, 1, 0, 255, 245, 244, 236, 233, 225, 217, 203, 190, 176, 175, 161, 149, 136, 125, 114, 102, 91, 81, 71, 60, 52, 43, 35, 28, 20, 19, 18, 12, 11, 5, 0 }; internal static readonly byte[] silk_NLSF_CB2_SELECT_NB_MB = new byte[160] { 16, 0, 0, 0, 0, 99, 66, 36, 36, 34, 36, 34, 34, 34, 34, 83, 69, 36, 52, 34, 116, 102, 70, 68, 68, 176, 102, 68, 68, 34, 65, 85, 68, 84, 36, 116, 141, 152, 139, 170, 132, 187, 184, 216, 137, 132, 249, 168, 185, 139, 104, 102, 100, 68, 68, 178, 218, 185, 185, 170, 244, 216, 187, 187, 170, 244, 187, 187, 219, 138, 103, 155, 184, 185, 137, 116, 183, 155, 152, 136, 132, 217, 184, 184, 170, 164, 217, 171, 155, 139, 244, 169, 184, 185, 170, 164, 216, 223, 218, 138, 214, 143, 188, 218, 168, 244, 141, 136, 155, 170, 168, 138, 220, 219, 139, 164, 219, 202, 216, 137, 168, 186, 246, 185, 139, 116, 185, 219, 185, 138, 100, 100, 134, 100, 102, 34, 68, 68, 100, 68, 168, 203, 221, 218, 168, 167, 154, 136, 104, 70, 164, 246, 171, 137, 139, 137, 155, 218, 219, 139 }; internal static readonly byte[] silk_NLSF_CB2_iCDF_NB_MB = new byte[72] { 255, 254, 253, 238, 14, 3, 2, 1, 0, 255, 254, 252, 218, 35, 3, 2, 1, 0, 255, 254, 250, 208, 59, 4, 2, 1, 0, 255, 254, 246, 194, 71, 10, 2, 1, 0, 255, 252, 236, 183, 82, 8, 2, 1, 0, 255, 252, 235, 180, 90, 17, 2, 1, 0, 255, 248, 224, 171, 97, 30, 4, 1, 0, 255, 254, 236, 173, 95, 37, 7, 1, 0 }; internal static readonly byte[] silk_NLSF_CB2_BITS_NB_MB_Q5 = new byte[72] { 255, 255, 255, 131, 6, 145, 255, 255, 255, 255, 255, 236, 93, 15, 96, 255, 255, 255, 255, 255, 194, 83, 25, 71, 221, 255, 255, 255, 255, 162, 73, 34, 66, 162, 255, 255, 255, 210, 126, 73, 43, 57, 173, 255, 255, 255, 201, 125, 71, 48, 58, 130, 255, 255, 255, 166, 110, 73, 57, 62, 104, 210, 255, 255, 251, 123, 65, 55, 68, 100, 171, 255 }; internal static readonly byte[] silk_NLSF_PRED_NB_MB_Q8 = new byte[18] { 179, 138, 140, 148, 151, 149, 153, 151, 163, 116, 67, 82, 59, 92, 72, 100, 89, 92 }; internal static readonly short[] silk_NLSF_DELTA_MIN_NB_MB_Q15 = new short[11] { 250, 3, 6, 3, 3, 3, 4, 3, 3, 3, 461 }; internal static readonly NLSFCodebook silk_NLSF_CB_NB_MB = new NLSFCodebook { nVectors = 32, order = 10, quantStepSize_Q16 = 11796, invQuantStepSize_Q6 = 356, CB1_NLSF_Q8 = silk_NLSF_CB1_NB_MB_Q8, CB1_iCDF = silk_NLSF_CB1_iCDF_NB_MB, pred_Q8 = silk_NLSF_PRED_NB_MB_Q8, ec_sel = silk_NLSF_CB2_SELECT_NB_MB, ec_iCDF = silk_NLSF_CB2_iCDF_NB_MB, ec_Rates_Q5 = silk_NLSF_CB2_BITS_NB_MB_Q5, deltaMin_Q15 = silk_NLSF_DELTA_MIN_NB_MB_Q15 }; internal static readonly byte[] silk_NLSF_CB1_WB_Q8 = new byte[512] { 7, 23, 38, 54, 69, 85, 100, 116, 131, 147, 162, 178, 193, 208, 223, 239, 13, 25, 41, 55, 69, 83, 98, 112, 127, 142, 157, 171, 187, 203, 220, 236, 15, 21, 34, 51, 61, 78, 92, 106, 126, 136, 152, 167, 185, 205, 225, 240, 10, 21, 36, 50, 63, 79, 95, 110, 126, 141, 157, 173, 189, 205, 221, 237, 17, 20, 37, 51, 59, 78, 89, 107, 123, 134, 150, 164, 184, 205, 224, 240, 10, 15, 32, 51, 67, 81, 96, 112, 129, 142, 158, 173, 189, 204, 220, 236, 8, 21, 37, 51, 65, 79, 98, 113, 126, 138, 155, 168, 179, 192, 209, 218, 12, 15, 34, 55, 63, 78, 87, 108, 118, 131, 148, 167, 185, 203, 219, 236, 16, 19, 32, 36, 56, 79, 91, 108, 118, 136, 154, 171, 186, 204, 220, 237, 11, 28, 43, 58, 74, 89, 105, 120, 135, 150, 165, 180, 196, 211, 226, 241, 6, 16, 33, 46, 60, 75, 92, 107, 123, 137, 156, 169, 185, 199, 214, 225, 11, 19, 30, 44, 57, 74, 89, 105, 121, 135, 152, 169, 186, 202, 218, 234, 12, 19, 29, 46, 57, 71, 88, 100, 120, 132, 148, 165, 182, 199, 216, 233, 17, 23, 35, 46, 56, 77, 92, 106, 123, 134, 152, 167, 185, 204, 222, 237, 14, 17, 45, 53, 63, 75, 89, 107, 115, 132, 151, 171, 188, 206, 221, 240, 9, 16, 29, 40, 56, 71, 88, 103, 119, 137, 154, 171, 189, 205, 222, 237, 16, 19, 36, 48, 57, 76, 87, 105, 118, 132, 150, 167, 185, 202, 218, 236, 12, 17, 29, 54, 71, 81, 94, 104, 126, 136, 149, 164, 182, 201, 221, 237, 15, 28, 47, 62, 79, 97, 115, 129, 142, 155, 168, 180, 194, 208, 223, 238, 8, 14, 30, 45, 62, 78, 94, 111, 127, 143, 159, 175, 192, 207, 223, 239, 17, 30, 49, 62, 79, 92, 107, 119, 132, 145, 160, 174, 190, 204, 220, 235, 14, 19, 36, 45, 61, 76, 91, 108, 121, 138, 154, 172, 189, 205, 222, 238, 12, 18, 31, 45, 60, 76, 91, 107, 123, 138, 154, 171, 187, 204, 221, 236, 13, 17, 31, 43, 53, 70, 83, 103, 114, 131, 149, 167, 185, 203, 220, 237, 17, 22, 35, 42, 58, 78, 93, 110, 125, 139, 155, 170, 188, 206, 224, 240, 8, 15, 34, 50, 67, 83, 99, 115, 131, 146, 162, 178, 193, 209, 224, 239, 13, 16, 41, 66, 73, 86, 95, 111, 128, 137, 150, 163, 183, 206, 225, 241, 17, 25, 37, 52, 63, 75, 92, 102, 119, 132, 144, 160, 175, 191, 212, 231, 19, 31, 49, 65, 83, 100, 117, 133, 147, 161, 174, 187, 200, 213, 227, 242, 18, 31, 52, 68, 88, 103, 117, 126, 138, 149, 163, 177, 192, 207, 223, 239, 16, 29, 47, 61, 76, 90, 106, 119, 133, 147, 161, 176, 193, 209, 224, 240, 15, 21, 35, 50, 61, 73, 86, 97, 110, 119, 129, 141, 175, 198, 218, 237 }; internal static readonly byte[] silk_NLSF_CB1_iCDF_WB = new byte[64] { 225, 204, 201, 184, 183, 175, 158, 154, 153, 135, 119, 115, 113, 110, 109, 99, 98, 95, 79, 68, 52, 50, 48, 45, 43, 32, 31, 27, 18, 10, 3, 0, 255, 251, 235, 230, 212, 201, 196, 182, 167, 166, 163, 151, 138, 124, 110, 104, 90, 78, 76, 70, 69, 57, 45, 34, 24, 21, 11, 6, 5, 4, 3, 0 }; internal static readonly byte[] silk_NLSF_CB2_SELECT_WB = new byte[256] { 0, 0, 0, 0, 0, 0, 0, 1, 100, 102, 102, 68, 68, 36, 34, 96, 164, 107, 158, 185, 180, 185, 139, 102, 64, 66, 36, 34, 34, 0, 1, 32, 208, 139, 141, 191, 152, 185, 155, 104, 96, 171, 104, 166, 102, 102, 102, 132, 1, 0, 0, 0, 0, 16, 16, 0, 80, 109, 78, 107, 185, 139, 103, 101, 208, 212, 141, 139, 173, 153, 123, 103, 36, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 0, 0, 0, 32, 68, 135, 123, 119, 119, 103, 69, 98, 68, 103, 120, 118, 118, 102, 71, 98, 134, 136, 157, 184, 182, 153, 139, 134, 208, 168, 248, 75, 189, 143, 121, 107, 32, 49, 34, 34, 34, 0, 17, 2, 210, 235, 139, 123, 185, 137, 105, 134, 98, 135, 104, 182, 100, 183, 171, 134, 100, 70, 68, 70, 66, 66, 34, 131, 64, 166, 102, 68, 36, 2, 1, 0, 134, 166, 102, 68, 34, 34, 66, 132, 212, 246, 158, 139, 107, 107, 87, 102, 100, 219, 125, 122, 137, 118, 103, 132, 114, 135, 137, 105, 171, 106, 50, 34, 164, 214, 141, 143, 185, 151, 121, 103, 192, 34, 0, 0, 0, 0, 0, 1, 208, 109, 74, 187, 134, 249, 159, 137, 102, 110, 154, 118, 87, 101, 119, 101, 0, 2, 0, 36, 36, 66, 68, 35, 96, 164, 102, 100, 36, 0, 2, 33, 167, 138, 174, 102, 100, 84, 2, 2, 100, 107, 120, 119, 36, 197, 24, 0 }; internal static readonly byte[] silk_NLSF_CB2_iCDF_WB = new byte[72] { 255, 254, 253, 244, 12, 3, 2, 1, 0, 255, 254, 252, 224, 38, 3, 2, 1, 0, 255, 254, 251, 209, 57, 4, 2, 1, 0, 255, 254, 244, 195, 69, 4, 2, 1, 0, 255, 251, 232, 184, 84, 7, 2, 1, 0, 255, 254, 240, 186, 86, 14, 2, 1, 0, 255, 254, 239, 178, 91, 30, 5, 1, 0, 255, 248, 227, 177, 100, 19, 2, 1, 0 }; internal static readonly byte[] silk_NLSF_CB2_BITS_WB_Q5 = new byte[72] { 255, 255, 255, 156, 4, 154, 255, 255, 255, 255, 255, 227, 102, 15, 92, 255, 255, 255, 255, 255, 213, 83, 24, 72, 236, 255, 255, 255, 255, 150, 76, 33, 63, 214, 255, 255, 255, 190, 121, 77, 43, 55, 185, 255, 255, 255, 245, 137, 71, 43, 59, 139, 255, 255, 255, 255, 131, 66, 50, 66, 107, 194, 255, 255, 166, 116, 76, 55, 53, 125, 255, 255 }; internal static readonly byte[] silk_NLSF_PRED_WB_Q8 = new byte[30] { 175, 148, 160, 176, 178, 173, 174, 164, 177, 174, 196, 182, 198, 192, 182, 68, 62, 66, 60, 72, 117, 85, 90, 118, 136, 151, 142, 160, 142, 155 }; internal static readonly short[] silk_NLSF_DELTA_MIN_WB_Q15 = new short[17] { 100, 3, 40, 3, 3, 3, 5, 14, 14, 10, 11, 3, 8, 9, 7, 3, 347 }; internal static readonly NLSFCodebook silk_NLSF_CB_WB = new NLSFCodebook { nVectors = 32, order = 16, quantStepSize_Q16 = 9830, invQuantStepSize_Q6 = 427, CB1_NLSF_Q8 = silk_NLSF_CB1_WB_Q8, CB1_iCDF = silk_NLSF_CB1_iCDF_WB, pred_Q8 = silk_NLSF_PRED_WB_Q8, ec_sel = silk_NLSF_CB2_SELECT_WB, ec_iCDF = silk_NLSF_CB2_iCDF_WB, ec_Rates_Q5 = silk_NLSF_CB2_BITS_WB_Q5, deltaMin_Q15 = silk_NLSF_DELTA_MIN_WB_Q15 }; internal static readonly int[] silk_TargetRate_table_NB = new int[8] { 0, 8000, 9400, 11500, 13500, 17500, 25000, 80000 }; internal static readonly int[] silk_TargetRate_table_MB = new int[8] { 0, 9000, 12000, 14500, 18500, 24500, 35500, 80000 }; internal static readonly int[] silk_TargetRate_table_WB = new int[8] { 0, 10500, 14000, 17000, 21500, 28500, 42000, 80000 }; internal static readonly short[] silk_SNR_table_Q1 = new short[8] { 18, 29, 38, 40, 46, 52, 62, 84 }; internal static readonly short[] silk_stereo_pred_quant_Q13 = new short[16] { -13732, -10050, -8266, -7526, -6500, -5000, -2950, -820, 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732 }; internal static readonly byte[] silk_stereo_pred_joint_iCDF = new byte[25] { 249, 247, 246, 245, 244, 234, 210, 202, 201, 200, 197, 174, 82, 59, 56, 55, 54, 46, 22, 12, 11, 10, 9, 7, 0 }; internal static readonly byte[] silk_stereo_only_code_mid_iCDF = new byte[2] { 64, 0 }; internal static readonly byte[] silk_LBRR_flags_2_iCDF = new byte[3] { 203, 150, 0 }; internal static readonly byte[] silk_LBRR_flags_3_iCDF = new byte[7] { 215, 195, 166, 125, 110, 82, 0 }; internal static readonly byte[][] silk_LBRR_flags_iCDF_ptr = new byte[2][] { silk_LBRR_flags_2_iCDF, silk_LBRR_flags_3_iCDF }; internal static readonly byte[] silk_lsb_iCDF = new byte[2] { 120, 0 }; internal static readonly byte[] silk_LTPscale_iCDF = new byte[3] { 128, 64, 0 }; internal static readonly byte[] silk_type_offset_VAD_iCDF = new byte[4] { 232, 158, 10, 0 }; internal static readonly byte[] silk_type_offset_no_VAD_iCDF = new byte[2] { 230, 0 }; internal static readonly byte[] silk_NLSF_interpolation_factor_iCDF = new byte[5] { 243, 221, 192, 181, 0 }; internal static readonly short[][] silk_Quantization_Offsets_Q10 = new short[2][] { new short[2] { 100, 240 }, new short[2] { 32, 100 } }; internal static readonly short[] silk_LTPScales_table_Q14 = new short[3] { 15565, 12288, 8192 }; internal static readonly byte[] silk_uniform3_iCDF = new byte[3] { 171, 85, 0 }; internal static readonly byte[] silk_uniform4_iCDF = new byte[4] { 192, 128, 64, 0 }; internal static readonly byte[] silk_uniform5_iCDF = new byte[5] { 205, 154, 102, 51, 0 }; internal static readonly byte[] silk_uniform6_iCDF = new byte[6] { 213, 171, 128, 85, 43, 0 }; internal static readonly byte[] silk_uniform8_iCDF = new byte[8] { 224, 192, 160, 128, 96, 64, 32, 0 }; internal static readonly byte[] silk_NLSF_EXT_iCDF = new byte[7] { 100, 40, 16, 7, 3, 1, 0 }; internal static readonly int[][] silk_Transition_LP_B_Q28 = new int[5][] { new int[3] { 250767114, 501534038, 250767114 }, new int[3] { 209867381, 419732057, 209867381 }, new int[3] { 170987846, 341967853, 170987846 }, new int[3] { 131531482, 263046905, 131531482 }, new int[3] { 89306658, 178584282, 89306658 } }; internal static readonly int[][] silk_Transition_LP_A_Q28 = new int[5][] { new int[2] { 506393414, 239854379 }, new int[2] { 411067935, 169683996 }, new int[2] { 306733530, 116694253 }, new int[2] { 185807084, 77959395 }, new int[2] { 35497197, 57401098 } }; internal static readonly byte[] silk_pitch_lag_iCDF = new byte[32] { 253, 250, 244, 233, 212, 182, 150, 131, 120, 110, 98, 85, 72, 60, 49, 40, 32, 25, 19, 15, 13, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; internal static readonly byte[] silk_pitch_delta_iCDF = new byte[21] { 210, 208, 206, 203, 199, 193, 183, 168, 142, 104, 74, 52, 37, 27, 20, 14, 10, 6, 4, 2, 0 }; internal static readonly byte[] silk_pitch_contour_iCDF = new byte[34] { 223, 201, 183, 167, 152, 138, 124, 111, 98, 88, 79, 70, 62, 56, 50, 44, 39, 35, 31, 27, 24, 21, 18, 16, 14, 12, 10, 8, 6, 4, 3, 2, 1, 0 }; internal static readonly byte[] silk_pitch_contour_NB_iCDF = new byte[11] { 188, 176, 155, 138, 119, 97, 67, 43, 26, 10, 0 }; internal static readonly byte[] silk_pitch_contour_10_ms_iCDF = new byte[12] { 165, 119, 80, 61, 47, 35, 27, 20, 14, 9, 4, 0 }; internal static readonly byte[] silk_pitch_contour_10_ms_NB_iCDF = new byte[3] { 113, 63, 0 }; internal static readonly byte[] silk_max_pulses_table = new byte[4] { 8, 10, 12, 16 }; internal static readonly byte[][] silk_pulses_per_block_iCDF = new byte[10][] { new byte[18] { 125, 51, 26, 18, 15, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, new byte[18] { 198, 105, 45, 22, 15, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, new byte[18] { 213, 162, 116, 83, 59, 43, 32, 24, 18, 15, 12, 9, 7, 6, 5, 3, 2, 0 }, new byte[18] { 239, 187, 116, 59, 28, 16, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, new byte[18] { 250, 229, 188, 135, 86, 51, 30, 19, 13, 10, 8, 6, 5, 4, 3, 2, 1, 0 }, new byte[18] { 249, 235, 213, 185, 156, 128, 103, 83, 66, 53, 42, 33, 26, 21, 17, 13, 10, 0 }, new byte[18] { 254, 249, 235, 206, 164, 118, 77, 46, 27, 16, 10, 7, 5, 4, 3, 2, 1, 0 }, new byte[18] { 255, 253, 249, 239, 220, 191, 156, 119, 85, 57, 37, 23, 15, 10, 6, 4, 2, 0 }, new byte[18] { 255, 253, 251, 246, 237, 223, 203, 179, 152, 124, 98, 75, 55, 40, 29, 21, 15, 0 }, new byte[18] { 255, 254, 253, 247, 220, 162, 106, 67, 42, 28, 18, 12, 9, 6, 4, 3, 2, 0 } }; internal static readonly byte[][] silk_pulses_per_block_BITS_Q5 = new byte[9][] { new byte[18] { 31, 57, 107, 160, 205, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, new byte[18] { 69, 47, 67, 111, 166, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, new byte[18] { 82, 74, 79, 95, 109, 128, 145, 160, 173, 205, 205, 205, 224, 255, 255, 224, 255, 224 }, new byte[18] { 125, 74, 59, 69, 97, 141, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, new byte[18] { 173, 115, 85, 73, 76, 92, 115, 145, 173, 205, 224, 224, 255, 255, 255, 255, 255, 255 }, new byte[18] { 166, 134, 113, 102, 101, 102, 107, 118, 125, 138, 145, 155, 166, 182, 192, 192, 205, 150 }, new byte[18] { 224, 182, 134, 101, 83, 79, 85, 97, 120, 145, 173, 205, 224, 255, 255, 255, 255, 255 }, new byte[18] { 255, 224, 192, 150, 120, 101, 92, 89, 93, 102, 118, 134, 160, 182, 192, 224, 224, 224 }, new byte[18] { 255, 224, 224, 182, 155, 134, 118, 109, 104, 102, 106, 111, 118, 131, 145, 160, 173, 131 } }; internal static readonly byte[][] silk_rate_levels_iCDF = new byte[2][] { new byte[9] { 241, 190, 178, 132, 87, 74, 41, 14, 0 }, new byte[9] { 223, 193, 157, 140, 106, 57, 39, 18, 0 } }; internal static readonly byte[][] silk_rate_levels_BITS_Q5 = new byte[2][] { new byte[9] { 131, 74, 141, 79, 80, 138, 95, 104, 134 }, new byte[9] { 95, 99, 91, 125, 93, 76, 123, 115, 123 } }; internal static readonly byte[] silk_shell_code_table0 = new byte[152] { 128, 0, 214, 42, 0, 235, 128, 21, 0, 244, 184, 72, 11, 0, 248, 214, 128, 42, 7, 0, 248, 225, 170, 80, 25, 5, 0, 251, 236, 198, 126, 54, 18, 3, 0, 250, 238, 211, 159, 82, 35, 15, 5, 0, 250, 231, 203, 168, 128, 88, 53, 25, 6, 0, 252, 238, 216, 185, 148, 108, 71, 40, 18, 4, 0, 253, 243, 225, 199, 166, 128, 90, 57, 31, 13, 3, 0, 254, 246, 233, 212, 183, 147, 109, 73, 44, 23, 10, 2, 0, 255, 250, 240, 223, 198, 166, 128, 90, 58, 33, 16, 6, 1, 0, 255, 251, 244, 231, 210, 181, 146, 110, 75, 46, 25, 12, 5, 1, 0, 255, 253, 248, 238, 221, 196, 164, 128, 92, 60, 35, 18, 8, 3, 1, 0, 255, 253, 249, 242, 229, 208, 180, 146, 110, 76, 48, 27, 14, 7, 3, 1, 0 }; internal static readonly byte[] silk_shell_code_table1 = new byte[152] { 129, 0, 207, 50, 0, 236, 129, 20, 0, 245, 185, 72, 10, 0, 249, 213, 129, 42, 6, 0, 250, 226, 169, 87, 27, 4, 0, 251, 233, 194, 130, 62, 20, 4, 0, 250, 236, 207, 160, 99, 47, 17, 3, 0, 255, 240, 217, 182, 131, 81, 41, 11, 1, 0, 255, 254, 233, 201, 159, 107, 61, 20, 2, 1, 0, 255, 249, 233, 206, 170, 128, 86, 50, 23, 7, 1, 0, 255, 250, 238, 217, 186, 148, 108, 70, 39, 18, 6, 1, 0, 255, 252, 243, 226, 200, 166, 128, 90, 56, 30, 13, 4, 1, 0, 255, 252, 245, 231, 209, 180, 146, 110, 76, 47, 25, 11, 4, 1, 0, 255, 253, 248, 237, 219, 194, 163, 128, 93, 62, 37, 19, 8, 3, 1, 0, 255, 254, 250, 241, 226, 205, 177, 145, 111, 79, 51, 30, 15, 6, 2, 1, 0 }; internal static readonly byte[] silk_shell_code_table2 = new byte[152] { 129, 0, 203, 54, 0, 234, 129, 23, 0, 245, 184, 73, 10, 0, 250, 215, 129, 41, 5, 0, 252, 232, 173, 86, 24, 3, 0, 253, 240, 200, 129, 56, 15, 2, 0, 253, 244, 217, 164, 94, 38, 10, 1, 0, 253, 245, 226, 189, 132, 71, 27, 7, 1, 0, 253, 246, 231, 203, 159, 105, 56, 23, 6, 1, 0, 255, 248, 235, 213, 179, 133, 85, 47, 19, 5, 1, 0, 255, 254, 243, 221, 194, 159, 117, 70, 37, 12, 2, 1, 0, 255, 254, 248, 234, 208, 171, 128, 85, 48, 22, 8, 2, 1, 0, 255, 254, 250, 240, 220, 189, 149, 107, 67, 36, 16, 6, 2, 1, 0, 255, 254, 251, 243, 227, 201, 166, 128, 90, 55, 29, 13, 5, 2, 1, 0, 255, 254, 252, 246, 234, 213, 183, 147, 109, 73, 43, 22, 10, 4, 2, 1, 0 }; internal static readonly byte[] silk_shell_code_table3 = new byte[152] { 130, 0, 200, 58, 0, 231, 130, 26, 0, 244, 184, 76, 12, 0, 249, 214, 130, 43, 6, 0, 252, 232, 173, 87, 24, 3, 0, 253, 241, 203, 131, 56, 14, 2, 0, 254, 246, 221, 167, 94, 35, 8, 1, 0, 254, 249, 232, 193, 130, 65, 23, 5, 1, 0, 255, 251, 239, 211, 162, 99, 45, 15, 4, 1, 0, 255, 251, 243, 223, 186, 131, 74, 33, 11, 3, 1, 0, 255, 252, 245, 230, 202, 158, 105, 57, 24, 8, 2, 1, 0, 255, 253, 247, 235, 214, 179, 132, 84, 44, 19, 7, 2, 1, 0, 255, 254, 250, 240, 223, 196, 159, 112, 69, 36, 15, 6, 2, 1, 0, 255, 254, 253, 245, 231, 209, 176, 136, 93, 55, 27, 11, 3, 2, 1, 0, 255, 254, 253, 252, 239, 221, 194, 158, 117, 76, 42, 18, 4, 3, 2, 1, 0 }; internal static readonly byte[] silk_shell_code_table_offsets = new byte[17] { 0, 0, 2, 5, 9, 14, 20, 27, 35, 44, 54, 65, 77, 90, 104, 119, 135 }; internal static readonly byte[] silk_sign_iCDF = new byte[42] { 254, 49, 67, 77, 82, 93, 99, 198, 11, 18, 24, 31, 36, 45, 255, 46, 66, 78, 87, 94, 104, 208, 14, 21, 32, 42, 51, 66, 255, 94, 104, 109, 112, 115, 118, 248, 53, 69, 80, 88, 95, 102 }; internal static readonly sbyte[,] delay_matrix_enc = new sbyte[5, 3] { { 6, 0, 3 }, { 0, 7, 3 }, { 0, 1, 10 }, { 0, 2, 6 }, { 18, 10, 12 } }; internal static readonly sbyte[,] delay_matrix_dec = new sbyte[3, 5] { { 4, 0, 2, 0, 0 }, { 0, 9, 4, 7, 4 }, { 0, 3, 12, 7, 7 } }; internal static readonly short[] silk_Resampler_3_4_COEFS = new short[29] { -20694, -13867, -49, 64, 17, -157, 353, -496, 163, 11047, 22205, -39, 6, 91, -170, 186, 23, -896, 6336, 19928, -19, -36, 102, -89, -24, 328, -951, 2568, 15909 }; internal static readonly short[] silk_Resampler_2_3_COEFS = new short[20] { -14457, -14019, 64, 128, -122, 36, 310, -768, 584, 9267, 17733, 12, 128, 18, -142, 288, -117, -865, 4123, 14459 }; internal static readonly short[] silk_Resampler_1_2_COEFS = new short[14] { 616, -14323, -10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024 }; internal static readonly short[] silk_Resampler_1_3_COEFS = new short[20] { 16102, -15162, -13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271 }; internal static readonly short[] silk_Resampler_1_4_COEFS = new short[20] { 22500, -15099, 3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464 }; internal static readonly short[] silk_Resampler_1_6_COEFS = new short[20] { 27540, -15257, 17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455 }; internal static readonly short[] silk_Resampler_2_3_COEFS_LQ = new short[6] { -2797, -6507, 4697, 10739, 1567, 8276 }; internal static readonly short[,] silk_resampler_frac_FIR_12 = new short[12, 4] { { 189, -600, 617, 30567 }, { 117, -159, -1070, 29704 }, { 52, 221, -2392, 28276 }, { -4, 529, -3350, 26341 }, { -48, 758, -3956, 23973 }, { -80, 905, -4235, 21254 }, { -99, 972, -4222, 18278 }, { -107, 967, -3957, 15143 }, { -103, 896, -3487, 11950 }, { -91, 773, -2865, 8798 }, { -71, 611, -2143, 5784 }, { -46, 425, -1375, 2996 } }; internal static readonly short[] silk_resampler_up2_hq_0 = new short[3] { 1746, 14986, -26453 }; internal static readonly short[] silk_resampler_up2_hq_1 = new short[3] { 6854, 25769, -9994 }; internal static readonly sbyte[][] silk_CB_lags_stage2_10_ms = new sbyte[2][] { new sbyte[3] { 0, 1, 0 }, new sbyte[3] { 0, 0, 1 } }; internal static readonly sbyte[][] silk_CB_lags_stage3_10_ms = new sbyte[2][] { new sbyte[12] { 0, 0, 1, -1, 1, -1, 2, -2, 2, -2, 3, -3 }, new sbyte[12] { 0, 1, 0, 1, -1, 2, -1, 2, -2, 3, -2, 3 } }; internal static readonly sbyte[][] silk_CB_lags_stage2 = new sbyte[4][] { new sbyte[11] { 0, 2, -1, -1, -1, 0, 0, 1, 1, 0, 1 }, new sbyte[11] { 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, new sbyte[11] { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, new sbyte[11] { 0, -1, 2, 1, 0, 1, 1, 0, 0, -1, -1 } }; internal static readonly sbyte[][] silk_CB_lags_stage3 = new sbyte[4][] { new sbyte[34] { 0, 0, 1, -1, 0, 1, -1, 0, -1, 1, -2, 2, -2, -2, 2, -3, 2, 3, -3, -4, 3, -4, 4, 4, -5, 5, -6, -5, 6, -7, 6, 5, 8, -9 }, new sbyte[34] { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 1, -1, 0, 1, -1, -1, 1, -1, 2, 1, -1, 2, -2, -2, 2, -2, 2, 2, 3, -3 }, new sbyte[34] { 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, -1, 1, 0, 0, 2, 1, -1, 2, -1, -1, 2, -1, 2, 2, -1, 3, -2, -2, -2, 3 }, new sbyte[34] { 0, 1, 0, 0, 1, 0, 1, -1, 2, -1, 2, -1, 2, 3, -2, 3, -2, -2, 4, 4, -3, 5, -3, -4, 6, -4, 6, 5, -5, 8, -6, -5, -7, 9 } }; internal static readonly sbyte[][] silk_Lag_range_stage3_10_ms = new sbyte[2][] { new sbyte[2] { -3, 7 }, new sbyte[2] { -2, 7 } }; internal static readonly sbyte[][][] silk_Lag_range_stage3 = new sbyte[3][][] { new sbyte[4][] { new sbyte[2] { -5, 8 }, new sbyte[2] { -1, 6 }, new sbyte[2] { -1, 6 }, new sbyte[2] { -4, 10 } }, new sbyte[4][] { new sbyte[2] { -6, 10 }, new sbyte[2] { -2, 6 }, new sbyte[2] { -1, 6 }, new sbyte[2] { -5, 10 } }, new sbyte[4][] { new sbyte[2] { -9, 12 }, new sbyte[2] { -3, 7 }, new sbyte[2] { -2, 7 }, new sbyte[2] { -7, 13 } } }; internal static readonly sbyte[] silk_nb_cbk_searchs_stage3 = new sbyte[3] { 16, 24, 34 }; } internal class TuningParameters { internal const int BITRESERVOIR_DECAY_TIME_MS = 500; internal const float FIND_PITCH_WHITE_NOISE_FRACTION = 0.001f; internal const float FIND_PITCH_BANDWIDTH_EXPANSION = 0.99f; internal const float FIND_LPC_COND_FAC = 1E-05f; internal const float FIND_LTP_COND_FAC = 1E-05f; internal const float LTP_DAMPING = 0.05f; internal const float LTP_SMOOTHING = 0.1f; internal const float MU_LTP_QUANT_NB = 0.03f; internal const float MU_LTP_QUANT_MB = 0.025f; internal const float MU_LTP_QUANT_WB = 0.02f; internal const float MAX_SUM_LOG_GAIN_DB = 250f; internal const float VARIABLE_HP_SMTH_COEF1 = 0.1f; internal const float VARIABLE_HP_SMTH_COEF2 = 0.015f; internal const float VARIABLE_HP_MAX_DELTA_FREQ = 0.4f; internal const int VARIABLE_HP_MIN_CUTOFF_HZ = 60; internal const int VARIABLE_HP_MAX_CUTOFF_HZ = 100; internal const float SPEECH_ACTIVITY_DTX_THRES = 0.05f; internal const float LBRR_SPEECH_ACTIVITY_THRES = 0.3f; internal const float BG_SNR_DECR_dB = 2f; internal const float HARM_SNR_INCR_dB = 2f; internal const float SPARSE_SNR_INCR_dB = 2f; internal const float SPARSENESS_THRESHOLD_QNT_OFFSET = 0.75f; internal const float WARPING_MULTIPLIER = 0.015f; internal const float SHAPE_WHITE_NOISE_FRACTION = 5E-05f; internal const float BANDWIDTH_EXPANSION = 0.95f; internal const float LOW_RATE_BANDWIDTH_EXPANSION_DELTA = 0.01f; internal const float LOW_RATE_HARMONIC_BOOST = 0.1f; internal const float LOW_INPUT_QUALITY_HARMONIC_BOOST = 0.1f; internal const float HARMONIC_SHAPING = 0.3f; internal const float HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING = 0.2f; internal const float HP_NOISE_COEF = 0.25f; internal const float HARM_HP_NOISE_COEF = 0.35f; internal const float INPUT_TILT = 0.05f; internal const float HIGH_RATE_INPUT_TILT = 0.1f; internal const float LOW_FREQ_SHAPING = 4f; internal const float LOW_QUALITY_LOW_FREQ_SHAPING_DECR = 0.5f; internal const float SUBFR_SMTH_COEF = 0.4f; internal const float LAMBDA_OFFSET = 1.2f; internal const float LAMBDA_SPEECH_ACT = -0.2f; internal const float LAMBDA_DELAYED_DECISIONS = -0.05f; internal const float LAMBDA_INPUT_QUALITY = -0.1f; internal const float LAMBDA_CODING_QUALITY = -0.2f; internal const float LAMBDA_QUANT_OFFSET = 0.8f; internal const int REDUCE_BITRATE_10_MS_BPS = 2200; internal const int MAX_BANDWIDTH_SWITCH_DELAY_MS = 5000; } internal static class VoiceActivityDetection { private static readonly int[] tiltWeights = new int[4] { 30000, 6000, -12000, -12000 }; internal static int silk_VAD_Init(SilkVADState psSilk_VAD) { int result = 0; psSilk_VAD.Reset(); for (int i = 0; i < 4; i++) { psSilk_VAD.NoiseLevelBias[i] = Inlines.silk_max_32(Inlines.silk_DIV32_16(50, (short)(i + 1)), 1); } for (int i = 0; i < 4; i++) { psSilk_VAD.NL[i] = Inlines.silk_MUL(100, psSilk_VAD.NoiseLevelBias[i]); psSilk_VAD.inv_NL[i] = Inlines.silk_DIV32(int.MaxValue, psSilk_VAD.NL[i]); } psSilk_VAD.counter = 15; for (int i = 0; i < 4; i++) { psSilk_VAD.NrgRatioSmth_Q8[i] = 25600; } return result; } internal static int silk_VAD_GetSA_Q8(SilkChannelEncoder psEncC, short[] pIn, int pIn_ptr) { int num = 0; int[] array = new int[4]; int[] array2 = new int[4]; int[] array3 = new int[4]; int result = 0; SilkVADState sVAD = psEncC.sVAD; int num2 = Inlines.silk_RSHIFT(psEncC.frame_length, 1); int num3 = Inlines.silk_RSHIFT(psEncC.frame_length, 2); int num4 = Inlines.silk_RSHIFT(psEncC.frame_length, 3); array3[0] = 0; array3[1] = num4 + num3; array3[2] = array3[1] + num4; array3[3] = array3[2] + num3; short[] array4 = new short[array3[3] + num2]; Filters.silk_ana_filt_bank_1(pIn, pIn_ptr, sVAD.AnaState, array4, array4, array3[3], psEncC.frame_length); Filters.silk_ana_filt_bank_1(array4, 0, sVAD.AnaState1, array4, array4, array3[2], num2); Filters.silk_ana_filt_bank_1(array4, 0, sVAD.AnaState2, array4, array4, array3[1], num3); array4[num4 - 1] = (short)Inlines.silk_RSHIFT(array4[num4 - 1], 1); short hPstate = array4[num4 - 1]; for (int num5 = num4 - 1; num5 > 0; num5--) { array4[num5 - 1] = (short)Inlines.silk_RSHIFT(array4[num5 - 1], 1); array4[num5] -= array4[num5 - 1]; } array4[0] -= sVAD.HPstate; sVAD.HPstate = hPstate; for (int i = 0; i < 4; i++) { num4 = Inlines.silk_RSHIFT(psEncC.frame_length, Inlines.silk_min_int(4 - i, 3)); int num6 = Inlines.silk_RSHIFT(num4, 2); int num7 = 0; array[i] = sVAD.XnrgSubfr[i]; for (int j = 0; j < 4; j++) { num = 0; for (int num5 = 0; num5 < num6; num5++) { int num8 = Inlines.silk_RSHIFT(array4[array3[i] + num5 + num7], 3); num = Inlines.silk_SMLABB(num, num8, num8); } if (j < 3) { array[i] = Inlines.silk_ADD_POS_SAT32(array[i], num); } else { array[i] = Inlines.silk_ADD_POS_SAT32(array[i], Inlines.silk_RSHIFT(num, 1)); } num7 += num6; } sVAD.XnrgSubfr[i] = num; } silk_VAD_GetNoiseLevels(array, sVAD); num = 0; int num9 = 0; int num10; for (int i = 0; i < 4; i++) { num10 = array[i] - sVAD.NL[i]; if (num10 > 0) { if ((array[i] & 0xFF800000u) == 0) { array2[i] = Inlines.silk_DIV32(Inlines.silk_LSHIFT(array[i], 8), sVAD.NL[i] + 1); } else { array2[i] = Inlines.silk_DIV32(array[i], Inlines.silk_RSHIFT(sVAD.NL[i], 8) + 1); } int num11 = Inlines.silk_lin2log(array2[i]) - 1024; num = Inlines.silk_SMLABB(num, num11, num11); if (num10 < 1048576) { num11 = Inlines.silk_SMULWB(Inlines.silk_LSHIFT(Inlines.silk_SQRT_APPROX(num10), 6), num11); } num9 = Inlines.silk_SMLAWB(num9, tiltWeights[i], num11); } else { array2[i] = 256; } } num = Inlines.silk_DIV32_16(num, 4); int b = (short)(3 * Inlines.silk_SQRT_APPROX(num)); int num12 = Sigmoid.silk_sigm_Q15(Inlines.silk_SMULWB(45000, b) - 128); psEncC.input_tilt_Q15 = Inlines.silk_LSHIFT(Sigmoid.silk_sigm_Q15(num9) - 16384, 1); num10 = 0; for (int i = 0; i < 4; i++) { num10 += (i + 1) * Inlines.silk_RSHIFT(array[i] - sVAD.NL[i], 4); } if (num10 <= 0) { num12 = Inlines.silk_RSHIFT(num12, 1); } else if (num10 < 32768) { num10 = ((psEncC.frame_length != 10 * psEncC.fs_kHz) ? Inlines.silk_LSHIFT_SAT32(num10, 15) : Inlines.silk_LSHIFT_SAT32(num10, 16)); num10 = Inlines.silk_SQRT_APPROX(num10); num12 = Inlines.silk_SMULWB(32768 + num10, num12); } psEncC.speech_activity_Q8 = Inlines.silk_min_int(Inlines.silk_RSHIFT(num12, 7), 255); int num13 = Inlines.silk_SMULWB(4096, Inlines.silk_SMULWB(num12, num12)); if (psEncC.frame_length == 10 * psEncC.fs_kHz) { num13 >>= 1; } for (int i = 0; i < 4; i++) { sVAD.NrgRatioSmth_Q8[i] = Inlines.silk_SMLAWB(sVAD.NrgRatioSmth_Q8[i], array2[i] - sVAD.NrgRatioSmth_Q8[i], num13); int num11 = 3 * (Inlines.silk_lin2log(sVAD.NrgRatioSmth_Q8[i]) - 1024); psEncC.input_quality_bands_Q15[i] = Sigmoid.silk_sigm_Q15(Inlines.silk_RSHIFT(num11 - 2048, 4)); } return result; } internal static void silk_VAD_GetNoiseLevels(int[] pX, SilkVADState psSilk_VAD) { int b = ((psSilk_VAD.counter < 1000) ? Inlines.silk_DIV32_16(32767, (short)(Inlines.silk_RSHIFT(psSilk_VAD.counter, 4) + 1)) : 0); for (int i = 0; i < 4; i++) { int num = psSilk_VAD.NL[i]; int num2 = Inlines.silk_ADD_POS_SAT32(pX[i], psSilk_VAD.NoiseLevelBias[i]); int num3 = Inlines.silk_DIV32(int.MaxValue, num2); int a = ((num2 <= Inlines.silk_LSHIFT(num, 3)) ? ((num2 >= num) ? Inlines.silk_SMULWB(Inlines.silk_SMULWW(num3, num), 2048) : 1024) : 128); a = Inlines.silk_max_int(a, b); psSilk_VAD.inv_NL[i] = Inlines.silk_SMLAWB(psSilk_VAD.inv_NL[i], num3 - psSilk_VAD.inv_NL[i], a); num = Inlines.silk_DIV32(int.MaxValue, psSilk_VAD.inv_NL[i]); num = Inlines.silk_min(num, 16777215); psSilk_VAD.NL[i] = num; } psSilk_VAD.counter++; } } internal static class VQ_WMat_EC { internal static void silk_VQ_WMat_EC(BoxedValue ind, BoxedValue rate_dist_Q14, BoxedValue gain_Q7, short[] in_Q14, int in_Q14_ptr, int[] W_Q18, int W_Q18_ptr, sbyte[][] cb_Q7, byte[] cb_gain_Q7, byte[] cl_Q5, int mu_Q9, int max_gain_Q7, int L) { int num = 0; short[] array = new short[5]; rate_dist_Q14.Val = int.MaxValue; for (int i = 0; i < L; i++) { sbyte[] array2 = cb_Q7[num++]; int num2 = cb_gain_Q7[i]; array[0] = (short)(in_Q14[in_Q14_ptr] - Inlines.silk_LSHIFT(array2[0], 7)); array[1] = (short)(in_Q14[in_Q14_ptr + 1] - Inlines.silk_LSHIFT(array2[1], 7)); array[2] = (short)(in_Q14[in_Q14_ptr + 2] - Inlines.silk_LSHIFT(array2[2], 7)); array[3] = (short)(in_Q14[in_Q14_ptr + 3] - Inlines.silk_LSHIFT(array2[3], 7)); array[4] = (short)(in_Q14[in_Q14_ptr + 4] - Inlines.silk_LSHIFT(array2[4], 7)); int a = Inlines.silk_SMULBB(mu_Q9, cl_Q5[i]); a = Inlines.silk_ADD_LSHIFT32(a, Inlines.silk_max(Inlines.silk_SUB32(num2, max_gain_Q7), 0), 10); int a2 = Inlines.silk_SMULWB(W_Q18[W_Q18_ptr + 1], array[1]); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 2], array[2]); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 3], array[3]); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 4], array[4]); a2 = Inlines.silk_LSHIFT(a2, 1); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr], array[0]); a = Inlines.silk_SMLAWB(a, a2, array[0]); a2 = Inlines.silk_SMULWB(W_Q18[W_Q18_ptr + 7], array[2]); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 8], array[3]); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 9], array[4]); a2 = Inlines.silk_LSHIFT(a2, 1); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 6], array[1]); a = Inlines.silk_SMLAWB(a, a2, array[1]); a2 = Inlines.silk_SMULWB(W_Q18[W_Q18_ptr + 13], array[3]); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 14], array[4]); a2 = Inlines.silk_LSHIFT(a2, 1); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 12], array[2]); a = Inlines.silk_SMLAWB(a, a2, array[2]); a2 = Inlines.silk_SMULWB(W_Q18[W_Q18_ptr + 19], array[4]); a2 = Inlines.silk_LSHIFT(a2, 1); a2 = Inlines.silk_SMLAWB(a2, W_Q18[W_Q18_ptr + 18], array[3]); a = Inlines.silk_SMLAWB(a, a2, array[3]); a2 = Inlines.silk_SMULWB(W_Q18[W_Q18_ptr + 24], array[4]); a = Inlines.silk_SMLAWB(a, a2, array[4]); if (a < rate_dist_Q14.Val) { rate_dist_Q14.Val = a; ind.Val = (sbyte)i; gain_Q7.Val = num2; } } } } } namespace Concentus.Silk.Enums { internal static class DecoderAPIFlag { public const int FLAG_DECODE_NORMAL = 0; public const int FLAG_PACKET_LOST = 1; public const int FLAG_DECODE_LBRR = 2; } internal static class SilkError { internal static int SILK_NO_ERROR = 0; internal static int SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES = -101; internal static int SILK_ENC_FS_NOT_SUPPORTED = -102; internal static int SILK_ENC_PACKET_SIZE_NOT_SUPPORTED = -103; internal static int SILK_ENC_PAYLOAD_BUF_TOO_SHORT = -104; internal static int SILK_ENC_INVALID_LOSS_RATE = -105; internal static int SILK_ENC_INVALID_COMPLEXITY_SETTING = -106; internal static int SILK_ENC_INVALID_INBAND_FEC_SETTING = -107; internal static int SILK_ENC_INVALID_DTX_SETTING = -108; internal static int SILK_ENC_INVALID_CBR_SETTING = -109; internal static int SILK_ENC_INTERNAL_ERROR = -110; internal static int SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR = -111; internal static int SILK_DEC_INVALID_SAMPLING_FREQUENCY = -200; internal static int SILK_DEC_PAYLOAD_TOO_LARGE = -201; internal static int SILK_DEC_PAYLOAD_ERROR = -202; internal static int SILK_DEC_INVALID_FRAME_SIZE = -203; } } namespace Concentus.Silk.Structs { internal class CNGState { internal readonly int[] CNG_exc_buf_Q14 = new int[320]; internal readonly short[] CNG_smth_NLSF_Q15 = new short[16]; internal readonly int[] CNG_synth_state = new int[16]; internal int CNG_smth_Gain_Q16 = 0; internal int rand_seed = 0; internal int fs_kHz = 0; internal void Reset() { Arrays.MemSet(CNG_exc_buf_Q14, 0, 320); Arrays.MemSet(CNG_smth_NLSF_Q15, (short)0, 16); Arrays.MemSet(CNG_synth_state, 0, 16); CNG_smth_Gain_Q16 = 0; rand_seed = 0; fs_kHz = 0; } } internal class DecControlState { internal int nChannelsAPI = 0; internal int nChannelsInternal = 0; internal int API_sampleRate = 0; internal int internalSampleRate = 0; internal int payloadSize_ms = 0; internal int prevPitchLag = 0; internal void Reset() { nChannelsAPI = 0; nChannelsInternal = 0; API_sampleRate = 0; internalSampleRate = 0; payloadSize_ms = 0; prevPitchLag = 0; } } internal class EncControlState { internal int nChannelsAPI = 0; internal int nChannelsInternal = 0; internal int API_sampleRate = 0; internal int maxInternalSampleRate = 0; internal int minInternalSampleRate = 0; internal int desiredInternalSampleRate = 0; internal int payloadSize_ms = 0; internal int bitRate = 0; internal int packetLossPercentage = 0; internal int complexity = 0; internal int useInBandFEC = 0; internal int useDTX = 0; internal int useCBR = 0; internal int maxBits = 0; internal int toMono = 0; internal int opusCanSwitch = 0; internal int reducedDependency = 0; internal int internalSampleRate = 0; internal int allowBandwidthSwitch = 0; internal int inWBmodeWithoutVariableLP = 0; internal int stereoWidth_Q14 = 0; internal int switchReady = 0; internal void Reset() { nChannelsAPI = 0; nChannelsInternal = 0; API_sampleRate = 0; maxInternalSampleRate = 0; minInternalSampleRate = 0; desiredInternalSampleRate = 0; payloadSize_ms = 0; bitRate = 0; packetLossPercentage = 0; complexity = 0; useInBandFEC = 0; useDTX = 0; useCBR = 0; maxBits = 0; toMono = 0; opusCanSwitch = 0; reducedDependency = 0; internalSampleRate = 0; allowBandwidthSwitch = 0; inWBmodeWithoutVariableLP = 0; stereoWidth_Q14 = 0; switchReady = 0; } internal int check_control_input() { if ((API_sampleRate != 8000 && API_sampleRate != 12000 && API_sampleRate != 16000 && API_sampleRate != 24000 && API_sampleRate != 32000 && API_sampleRate != 44100 && API_sampleRate != 48000) || (desiredInternalSampleRate != 8000 && desiredInternalSampleRate != 12000 && desiredInternalSampleRate != 16000) || (maxInternalSampleRate != 8000 && maxInternalSampleRate != 12000 && maxInternalSampleRate != 16000) || (minInternalSampleRate != 8000 && minInternalSampleRate != 12000 && minInternalSampleRate != 16000) || minInternalSampleRate > desiredInternalSampleRate || maxInternalSampleRate < desiredInternalSampleRate || minInternalSampleRate > maxInternalSampleRate) { return SilkError.SILK_ENC_FS_NOT_SUPPORTED; } if (payloadSize_ms != 10 && payloadSize_ms != 20 && payloadSize_ms != 40 && payloadSize_ms != 60) { return SilkError.SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; } if (packetLossPercentage < 0 || packetLossPercentage > 100) { return SilkError.SILK_ENC_INVALID_LOSS_RATE; } if (useDTX < 0 || useDTX > 1) { return SilkError.SILK_ENC_INVALID_DTX_SETTING; } if (useCBR < 0 || useCBR > 1) { return SilkError.SILK_ENC_INVALID_CBR_SETTING; } if (useInBandFEC < 0 || useInBandFEC > 1) { return SilkError.SILK_ENC_INVALID_INBAND_FEC_SETTING; } if (nChannelsAPI < 1 || nChannelsAPI > 2) { return SilkError.SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; } if (nChannelsInternal < 1 || nChannelsInternal > 2) { return SilkError.SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; } if (nChannelsInternal > nChannelsAPI) { return SilkError.SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; } if (complexity < 0 || complexity > 10) { return SilkError.SILK_ENC_INVALID_COMPLEXITY_SETTING; } return SilkError.SILK_NO_ERROR; } } internal class NLSFCodebook { internal short nVectors = 0; internal short order = 0; internal short quantStepSize_Q16 = 0; internal short invQuantStepSize_Q6 = 0; internal byte[] CB1_NLSF_Q8 = null; internal byte[] CB1_iCDF = null; internal byte[] pred_Q8 = null; internal byte[] ec_sel = null; internal byte[] ec_iCDF = null; internal byte[] ec_Rates_Q5 = null; internal short[] deltaMin_Q15 = null; internal void Reset() { nVectors = 0; order = 0; quantStepSize_Q16 = 0; invQuantStepSize_Q6 = 0; CB1_NLSF_Q8 = null; CB1_iCDF = null; pred_Q8 = null; ec_sel = null; ec_iCDF = null; ec_Rates_Q5 = null; deltaMin_Q15 = null; } } internal class PLCStruct { internal int pitchL_Q8 = 0; internal readonly short[] LTPCoef_Q14 = new short[5]; internal readonly short[] prevLPC_Q12 = new short[16]; internal int last_frame_lost = 0; internal int rand_seed = 0; internal short randScale_Q14 = 0; internal int conc_energy = 0; internal int conc_energy_shift = 0; internal short prevLTP_scale_Q14 = 0; internal readonly int[] prevGain_Q16 = new int[2]; internal int fs_kHz = 0; internal int nb_subfr = 0; internal int subfr_length = 0; internal void Reset() { pitchL_Q8 = 0; Arrays.MemSet(LTPCoef_Q14, (short)0, 5); Arrays.MemSet(prevLPC_Q12, (short)0, 16); last_frame_lost = 0; rand_seed = 0; randScale_Q14 = 0; conc_energy = 0; conc_energy_shift = 0; prevLTP_scale_Q14 = 0; Arrays.MemSet(prevGain_Q16, 0, 2); fs_kHz = 0; nb_subfr = 0; subfr_length = 0; } } internal class SideInfoIndices { internal readonly sbyte[] GainsIndices = new sbyte[4]; internal readonly sbyte[] LTPIndex = new sbyte[4]; internal readonly sbyte[] NLSFIndices = new sbyte[17]; internal short lagIndex = 0; internal sbyte contourIndex = 0; internal sbyte signalType = 0; internal sbyte quantOffsetType = 0; internal sbyte NLSFInterpCoef_Q2 = 0; internal sbyte PERIndex = 0; internal sbyte LTP_scaleIndex = 0; internal sbyte Seed = 0; internal void Reset() { Arrays.MemSet(GainsIndices, (sbyte)0, 4); Arrays.MemSet(LTPIndex, (sbyte)0, 4); Arrays.MemSet(NLSFIndices, (sbyte)0, 17); lagIndex = 0; contourIndex = 0; signalType = 0; quantOffsetType = 0; NLSFInterpCoef_Q2 = 0; PERIndex = 0; LTP_scaleIndex = 0; Seed = 0; } internal void Assign(SideInfoIndices other) { Array.Copy(other.GainsIndices, GainsIndices, 4); Array.Copy(other.LTPIndex, LTPIndex, 4); Array.Copy(other.NLSFIndices, NLSFIndices, 17); lagIndex = other.lagIndex; contourIndex = other.contourIndex; signalType = other.signalType; quantOffsetType = other.quantOffsetType; NLSFInterpCoef_Q2 = other.NLSFInterpCoef_Q2; PERIndex = other.PERIndex; LTP_scaleIndex = other.LTP_scaleIndex; Seed = other.Seed; } } internal class SilkChannelDecoder { internal int prev_gain_Q16 = 0; internal readonly int[] exc_Q14 = new int[320]; internal readonly int[] sLPC_Q14_buf = new int[16]; internal readonly short[] outBuf = new short[480]; internal int lagPrev = 0; internal sbyte LastGainIndex = 0; internal int fs_kHz = 0; internal int fs_API_hz = 0; internal int nb_subfr = 0; internal int frame_length = 0; internal int subfr_length = 0; internal int ltp_mem_length = 0; internal int LPC_order = 0; internal readonly short[] prevNLSF_Q15 = new short[16]; internal int first_frame_after_reset = 0; internal byte[] pitch_lag_low_bits_iCDF; internal byte[] pitch_contour_iCDF; internal int nFramesDecoded = 0; internal int nFramesPerPacket = 0; internal int ec_prevSignalType = 0; internal short ec_prevLagIndex = 0; internal readonly int[] VAD_flags = new int[3]; internal int LBRR_flag = 0; internal readonly int[] LBRR_flags = new int[3]; internal readonly SilkResamplerState resampler_state = new SilkResamplerState(); internal NLSFCodebook psNLSF_CB = null; internal readonly SideInfoIndices indices = new SideInfoIndices(); internal readonly CNGState sCNG = new CNGState(); internal int lossCnt = 0; internal int prevSignalType = 0; internal readonly PLCStruct sPLC = new PLCStruct(); internal void Reset() { prev_gain_Q16 = 0; Arrays.MemSet(exc_Q14, 0, 320); Arrays.MemSet(sLPC_Q14_buf, 0, 16); Arrays.MemSet(outBuf, (short)0, 480); lagPrev = 0; LastGainIndex = 0; fs_kHz = 0; fs_API_hz = 0; nb_subfr = 0; frame_length = 0; subfr_length = 0; ltp_mem_length = 0; LPC_order = 0; Arrays.MemSet(prevNLSF_Q15, (short)0, 16); first_frame_after_reset = 0; pitch_lag_low_bits_iCDF = null; pitch_contour_iCDF = null; nFramesDecoded = 0; nFramesPerPacket = 0; ec_prevSignalType = 0; ec_prevLagIndex = 0; Arrays.MemSet(VAD_flags, 0, 3); LBRR_flag = 0; Arrays.MemSet(LBRR_flags, 0, 3); resampler_state.Reset(); psNLSF_CB = null; indices.Reset(); sCNG.Reset(); lossCnt = 0; prevSignalType = 0; sPLC.Reset(); } internal int silk_init_decoder() { Reset(); first_frame_after_reset = 1; prev_gain_Q16 = 65536; silk_CNG_Reset(); silk_PLC_Reset(); return 0; } private void silk_CNG_Reset() { int num = Inlines.silk_DIV32_16(32767, LPC_order + 1); int num2 = 0; for (int i = 0; i < LPC_order; i++) { num2 += num; sCNG.CNG_smth_NLSF_Q15[i] = (short)num2; } sCNG.CNG_smth_Gain_Q16 = 0; sCNG.rand_seed = 3176576; } private void silk_PLC_Reset() { sPLC.pitchL_Q8 = Inlines.silk_LSHIFT(frame_length, 7); sPLC.prevGain_Q16[0] = 65536; sPLC.prevGain_Q16[1] = 65536; sPLC.subfr_length = 20; sPLC.nb_subfr = 2; } internal int silk_decoder_set_fs(int fs_kHz, int fs_API_Hz) { int num = 0; subfr_length = Inlines.silk_SMULBB(5, fs_kHz); int num2 = Inlines.silk_SMULBB(nb_subfr, subfr_length); if (this.fs_kHz != fs_kHz || fs_API_hz != fs_API_Hz) { num += Resampler.silk_resampler_init(resampler_state, Inlines.silk_SMULBB(fs_kHz, 1000), fs_API_Hz, 0); fs_API_hz = fs_API_Hz; } if (this.fs_kHz != fs_kHz || num2 != frame_length) { if (fs_kHz == 8) { if (nb_subfr == 4) { pitch_contour_iCDF = Tables.silk_pitch_contour_NB_iCDF; } else { pitch_contour_iCDF = Tables.silk_pitch_contour_10_ms_NB_iCDF; } } else if (nb_subfr == 4) { pitch_contour_iCDF = Tables.silk_pitch_contour_iCDF; } else { pitch_contour_iCDF = Tables.silk_pitch_contour_10_ms_iCDF; } if (this.fs_kHz != fs_kHz) { ltp_mem_length = Inlines.silk_SMULBB(20, fs_kHz); if (fs_kHz == 8 || fs_kHz == 12) { LPC_order = 10; psNLSF_CB = Tables.silk_NLSF_CB_NB_MB; } else { LPC_order = 16; psNLSF_CB = Tables.silk_NLSF_CB_WB; } switch (fs_kHz) { case 16: pitch_lag_low_bits_iCDF = Tables.silk_uniform8_iCDF; break; case 12: pitch_lag_low_bits_iCDF = Tables.silk_uniform6_iCDF; break; case 8: pitch_lag_low_bits_iCDF = Tables.silk_uniform4_iCDF; break; } first_frame_after_reset = 1; lagPrev = 100; LastGainIndex = 10; prevSignalType = 0; Arrays.MemSet(outBuf, (short)0, 480); Arrays.MemSet(sLPC_Q14_buf, 0, 16); } this.fs_kHz = fs_kHz; frame_length = num2; } return num; } internal int silk_decode_frame(EntropyCoder psRangeDec, short[] pOut, int pOut_ptr, BoxedValue pN, int lostFlag, int condCoding) { SilkDecoderControl silkDecoderControl = new SilkDecoderControl(); int result = 0; int num = frame_length; silkDecoderControl.LTP_scale_Q14 = 0; if (lostFlag == 0 || (lostFlag == 2 && LBRR_flags[nFramesDecoded] == 1)) { short[] pulses = new short[(num + 16 - 1) & -16]; DecodeIndices.silk_decode_indices(this, psRangeDec, nFramesDecoded, lostFlag, condCoding); DecodePulses.silk_decode_pulses(psRangeDec, pulses, indices.signalType, indices.quantOffsetType, frame_length); DecodeParameters.silk_decode_parameters(this, silkDecoderControl, condCoding); DecodeCore.silk_decode_core(this, silkDecoderControl, pOut, pOut_ptr, pulses); PLC.silk_PLC(this, silkDecoderControl, pOut, pOut_ptr, 0); lossCnt = 0; prevSignalType = indices.signalType; first_frame_after_reset = 0; } else { PLC.silk_PLC(this, silkDecoderControl, pOut, pOut_ptr, 1); } int num2 = ltp_mem_length - frame_length; Arrays.MemMove(outBuf, frame_length, 0, num2); Array.Copy(pOut, pOut_ptr, outBuf, num2, frame_length); CNG.silk_CNG(this, silkDecoderControl, pOut, pOut_ptr, num); PLC.silk_PLC_glue_frames(this, pOut, pOut_ptr, num); lagPrev = silkDecoderControl.pitchL[nb_subfr - 1]; pN.Val = num; return result; } } internal class SilkChannelEncoder { internal readonly int[] In_HP_State = new int[2]; internal int variable_HP_smth1_Q15 = 0; internal int variable_HP_smth2_Q15 = 0; internal readonly SilkLPState sLP = new SilkLPState(); internal readonly SilkVADState sVAD = new SilkVADState(); internal readonly SilkNSQState sNSQ = new SilkNSQState(); internal readonly short[] prev_NLSFq_Q15 = new short[16]; internal int speech_activity_Q8 = 0; internal int allow_bandwidth_switch = 0; internal sbyte LBRRprevLastGainIndex = 0; internal sbyte prevSignalType = 0; internal int prevLag = 0; internal int pitch_LPC_win_length = 0; internal int max_pitch_lag = 0; internal int API_fs_Hz = 0; internal int prev_API_fs_Hz = 0; internal int maxInternal_fs_Hz = 0; internal int minInternal_fs_Hz = 0; internal int desiredInternal_fs_Hz = 0; internal int fs_kHz = 0; internal int nb_subfr = 0; internal int frame_length = 0; internal int subfr_length = 0; internal int ltp_mem_length = 0; internal int la_pitch = 0; internal int la_shape = 0; internal int shapeWinLength = 0; internal int TargetRate_bps = 0; internal int PacketSize_ms = 0; internal int PacketLoss_perc = 0; internal int frameCounter = 0; internal int Complexity = 0; internal int nStatesDelayedDecision = 0; internal int useInterpolatedNLSFs = 0; internal int shapingLPCOrder = 0; internal int predictLPCOrder = 0; internal int pitchEstimationComplexity = 0; internal int pitchEstimationLPCOrder = 0; internal int pitchEstimationThreshold_Q16 = 0; internal int LTPQuantLowComplexity = 0; internal int mu_LTP_Q9 = 0; internal int sum_log_gain_Q7 = 0; internal int NLSF_MSVQ_Survivors = 0; internal int first_frame_after_reset = 0; internal int controlled_since_last_payload = 0; internal int warping_Q16 = 0; internal int useCBR = 0; internal int prefillFlag = 0; internal byte[] pitch_lag_low_bits_iCDF = null; internal byte[] pitch_contour_iCDF = null; internal NLSFCodebook psNLSF_CB = null; internal readonly int[] input_quality_bands_Q15 = new int[4]; internal int input_tilt_Q15 = 0; internal int SNR_dB_Q7 = 0; internal readonly sbyte[] VAD_flags = new sbyte[3]; internal sbyte LBRR_flag = 0; internal readonly int[] LBRR_flags = new int[3]; internal readonly SideInfoIndices indices = new SideInfoIndices(); internal readonly sbyte[] pulses = new sbyte[320]; internal readonly short[] inputBuf = new short[322]; internal int inputBufIx = 0; internal int nFramesPerPacket = 0; internal int nFramesEncoded = 0; internal int nChannelsAPI = 0; internal int nChannelsInternal = 0; internal int channelNb = 0; internal int frames_since_onset = 0; internal int ec_prevSignalType = 0; internal short ec_prevLagIndex = 0; internal readonly SilkResamplerState resampler_state = new SilkResamplerState(); internal int useDTX = 0; internal int inDTX = 0; internal int noSpeechCounter = 0; internal int useInBandFEC = 0; internal int LBRR_enabled = 0; internal int LBRR_GainIncreases = 0; internal readonly SideInfoIndices[] indices_LBRR = new SideInfoIndices[3]; internal readonly sbyte[][] pulses_LBRR = Arrays.InitTwoDimensionalArray(3, 320); internal readonly SilkShapeState sShape = new SilkShapeState(); internal readonly SilkPrefilterState sPrefilt = new SilkPrefilterState(); internal readonly short[] x_buf = new short[720]; internal int LTPCorr_Q15 = 0; internal SilkChannelEncoder() { for (int i = 0; i < 3; i++) { indices_LBRR[i] = new SideInfoIndices(); } } internal void Reset() { Arrays.MemSet(In_HP_State, 0, 2); variable_HP_smth1_Q15 = 0; variable_HP_smth2_Q15 = 0; sLP.Reset(); sVAD.Reset(); sNSQ.Reset(); Arrays.MemSet(prev_NLSFq_Q15, (short)0, 16); speech_activity_Q8 = 0; allow_bandwidth_switch = 0; LBRRprevLastGainIndex = 0; prevSignalType = 0; prevLag = 0; pitch_LPC_win_length = 0; max_pitch_lag = 0; API_fs_Hz = 0; prev_API_fs_Hz = 0; maxInternal_fs_Hz = 0; minInternal_fs_Hz = 0; desiredInternal_fs_Hz = 0; fs_kHz = 0; nb_subfr = 0; frame_length = 0; subfr_length = 0; ltp_mem_length = 0; la_pitch = 0; la_shape = 0; shapeWinLength = 0; TargetRate_bps = 0; PacketSize_ms = 0; PacketLoss_perc = 0; frameCounter = 0; Complexity = 0; nStatesDelayedDecision = 0; useInterpolatedNLSFs = 0; shapingLPCOrder = 0; predictLPCOrder = 0; pitchEstimationComplexity = 0; pitchEstimationLPCOrder = 0; pitchEstimationThreshold_Q16 = 0; LTPQuantLowComplexity = 0; mu_LTP_Q9 = 0; sum_log_gain_Q7 = 0; NLSF_MSVQ_Survivors = 0; first_frame_after_reset = 0; controlled_since_last_payload = 0; warping_Q16 = 0; useCBR = 0; prefillFlag = 0; pitch_lag_low_bits_iCDF = null; pitch_contour_iCDF = null; psNLSF_CB = null; Arrays.MemSet(input_quality_bands_Q15, 0, 4); input_tilt_Q15 = 0; SNR_dB_Q7 = 0; Arrays.MemSet(VAD_flags, (sbyte)0, 3); LBRR_flag = 0; Arrays.MemSet(LBRR_flags, 0, 3); indices.Reset(); Arrays.MemSet(pulses, (sbyte)0, 320); Arrays.MemSet(inputBuf, (short)0, 322); inputBufIx = 0; nFramesPerPacket = 0; nFramesEncoded = 0; nChannelsAPI = 0; nChannelsInternal = 0; channelNb = 0; frames_since_onset = 0; ec_prevSignalType = 0; ec_prevLagIndex = 0; resampler_state.Reset(); useDTX = 0; inDTX = 0; noSpeechCounter = 0; useInBandFEC = 0; LBRR_enabled = 0; LBRR_GainIncreases = 0; for (int i = 0; i < 3; i++) { indices_LBRR[i].Reset(); Arrays.MemSet(pulses_LBRR[i], (sbyte)0, 320); } sShape.Reset(); sPrefilt.Reset(); Arrays.MemSet(x_buf, (short)0, 720); LTPCorr_Q15 = 0; } internal int silk_control_encoder(EncControlState encControl, int TargetRate_bps, int allow_bw_switch, int channelNb, int force_fs_kHz) { int result = SilkError.SILK_NO_ERROR; useDTX = encControl.useDTX; useCBR = encControl.useCBR; API_fs_Hz = encControl.API_sampleRate; maxInternal_fs_Hz = encControl.maxInternalSampleRate; minInternal_fs_Hz = encControl.minInternalSampleRate; desiredInternal_fs_Hz = encControl.desiredInternalSampleRate; useInBandFEC = encControl.useInBandFEC; nChannelsAPI = encControl.nChannelsAPI; nChannelsInternal = encControl.nChannelsInternal; allow_bandwidth_switch = allow_bw_switch; this.channelNb = channelNb; if (controlled_since_last_payload != 0 && prefillFlag == 0) { if (API_fs_Hz != prev_API_fs_Hz && fs_kHz > 0) { result = silk_setup_resamplers(fs_kHz); } return result; } int num = silk_control_audio_bandwidth(encControl); if (force_fs_kHz != 0) { num = force_fs_kHz; } result = silk_setup_resamplers(num); result = silk_setup_fs(num, encControl.payloadSize_ms); result = silk_setup_complexity(encControl.complexity); PacketLoss_perc = encControl.packetLossPercentage; result = silk_setup_LBRR(TargetRate_bps); controlled_since_last_payload = 1; return result; } private int silk_setup_resamplers(int fs_kHz) { int num = 0; if (this.fs_kHz != fs_kHz || prev_API_fs_Hz != API_fs_Hz) { if (this.fs_kHz == 0) { num += Resampler.silk_resampler_init(resampler_state, API_fs_Hz, fs_kHz * 1000, 1); } else { SilkResamplerState silkResamplerState = null; int num2 = Inlines.silk_LSHIFT(nb_subfr * 5, 1) + 5; int inLen = num2 * this.fs_kHz; silkResamplerState = new SilkResamplerState(); num += Resampler.silk_resampler_init(silkResamplerState, Inlines.silk_SMULBB(this.fs_kHz, 1000), API_fs_Hz, 0); int num3 = num2 * Inlines.silk_DIV32_16(API_fs_Hz, 1000); short[] array = new short[num3]; num += Resampler.silk_resampler(silkResamplerState, array, 0, x_buf, 0, inLen); num += Resampler.silk_resampler_init(resampler_state, API_fs_Hz, Inlines.silk_SMULBB(fs_kHz, 1000), 1); num += Resampler.silk_resampler(resampler_state, x_buf, 0, array, 0, num3); } } prev_API_fs_Hz = API_fs_Hz; return num; } private int silk_setup_fs(int fs_kHz, int PacketSize_ms) { int result = SilkError.SILK_NO_ERROR; if (PacketSize_ms != this.PacketSize_ms) { if (PacketSize_ms != 10 && PacketSize_ms != 20 && PacketSize_ms != 40 && PacketSize_ms != 60) { result = SilkError.SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; } if (PacketSize_ms <= 10) { nFramesPerPacket = 1; nb_subfr = ((PacketSize_ms != 10) ? 1 : 2); frame_length = Inlines.silk_SMULBB(PacketSize_ms, fs_kHz); pitch_LPC_win_length = Inlines.silk_SMULBB(14, fs_kHz); if (this.fs_kHz == 8) { pitch_contour_iCDF = Tables.silk_pitch_contour_10_ms_NB_iCDF; } else { pitch_contour_iCDF = Tables.silk_pitch_contour_10_ms_iCDF; } } else { nFramesPerPacket = Inlines.silk_DIV32_16(PacketSize_ms, 20); nb_subfr = 4; frame_length = Inlines.silk_SMULBB(20, fs_kHz); pitch_LPC_win_length = Inlines.silk_SMULBB(24, fs_kHz); if (this.fs_kHz == 8) { pitch_contour_iCDF = Tables.silk_pitch_contour_NB_iCDF; } else { pitch_contour_iCDF = Tables.silk_pitch_contour_iCDF; } } this.PacketSize_ms = PacketSize_ms; TargetRate_bps = 0; } if (this.fs_kHz != fs_kHz) { sShape.Reset(); sPrefilt.Reset(); sNSQ.Reset(); Arrays.MemSet(prev_NLSFq_Q15, (short)0, 16); Arrays.MemSet(sLP.In_LP_State, 0, 2); inputBufIx = 0; nFramesEncoded = 0; TargetRate_bps = 0; prevLag = 100; first_frame_after_reset = 1; sPrefilt.lagPrev = 100; sShape.LastGainIndex = 10; sNSQ.lagPrev = 100; sNSQ.prev_gain_Q16 = 65536; prevSignalType = 0; this.fs_kHz = fs_kHz; if (this.fs_kHz == 8) { if (nb_subfr == 4) { pitch_contour_iCDF = Tables.silk_pitch_contour_NB_iCDF; } else { pitch_contour_iCDF = Tables.silk_pitch_contour_10_ms_NB_iCDF; } } else if (nb_subfr == 4) { pitch_contour_iCDF = Tables.silk_pitch_contour_iCDF; } else { pitch_contour_iCDF = Tables.silk_pitch_contour_10_ms_iCDF; } if (this.fs_kHz == 8 || this.fs_kHz == 12) { predictLPCOrder = 10; psNLSF_CB = Tables.silk_NLSF_CB_NB_MB; } else { predictLPCOrder = 16; psNLSF_CB = Tables.silk_NLSF_CB_WB; } subfr_length = 5 * fs_kHz; frame_length = Inlines.silk_SMULBB(subfr_length, nb_subfr); ltp_mem_length = Inlines.silk_SMULBB(20, fs_kHz); la_pitch = Inlines.silk_SMULBB(2, fs_kHz); max_pitch_lag = Inlines.silk_SMULBB(18, fs_kHz); if (nb_subfr == 4) { pitch_LPC_win_length = Inlines.silk_SMULBB(24, fs_kHz); } else { pitch_LPC_win_length = Inlines.silk_SMULBB(14, fs_kHz); } if (this.fs_kHz == 16) { mu_LTP_Q9 = 10; pitch_lag_low_bits_iCDF = Tables.silk_uniform8_iCDF; } else if (this.fs_kHz == 12) { mu_LTP_Q9 = 13; pitch_lag_low_bits_iCDF = Tables.silk_uniform6_iCDF; } else { mu_LTP_Q9 = 15; pitch_lag_low_bits_iCDF = Tables.silk_uniform4_iCDF; } } return result; } private int silk_setup_complexity(int Complexity) { int result = 0; if (Complexity < 2) { pitchEstimationComplexity = 0; pitchEstimationThreshold_Q16 = 52429; pitchEstimationLPCOrder = 6; shapingLPCOrder = 8; la_shape = 3 * fs_kHz; nStatesDelayedDecision = 1; useInterpolatedNLSFs = 0; LTPQuantLowComplexity = 1; NLSF_MSVQ_Survivors = 2; warping_Q16 = 0; } else if (Complexity < 4) { pitchEstimationComplexity = 1; pitchEstimationThreshold_Q16 = 49807; pitchEstimationLPCOrder = 8; shapingLPCOrder = 10; la_shape = 5 * fs_kHz; nStatesDelayedDecision = 1; useInterpolatedNLSFs = 0; LTPQuantLowComplexity = 0; NLSF_MSVQ_Survivors = 4; warping_Q16 = 0; } else if (Complexity < 6) { pitchEstimationComplexity = 1; pitchEstimationThreshold_Q16 = 48497; pitchEstimationLPCOrder = 10; shapingLPCOrder = 12; la_shape = 5 * fs_kHz; nStatesDelayedDecision = 2; useInterpolatedNLSFs = 1; LTPQuantLowComplexity = 0; NLSF_MSVQ_Survivors = 8; warping_Q16 = fs_kHz * 983; } else if (Complexity < 8) { pitchEstimationComplexity = 1; pitchEstimationThreshold_Q16 = 47186; pitchEstimationLPCOrder = 12; shapingLPCOrder = 14; la_shape = 5 * fs_kHz; nStatesDelayedDecision = 3; useInterpolatedNLSFs = 1; LTPQuantLowComplexity = 0; NLSF_MSVQ_Survivors = 16; warping_Q16 = fs_kHz * 983; } else { pitchEstimationComplexity = 2; pitchEstimationThreshold_Q16 = 45875; pitchEstimationLPCOrder = 16; shapingLPCOrder = 16; la_shape = 5 * fs_kHz; nStatesDelayedDecision = 4; useInterpolatedNLSFs = 1; LTPQuantLowComplexity = 0; NLSF_MSVQ_Survivors = 32; warping_Q16 = fs_kHz * 983; } pitchEstimationLPCOrder = Inlines.silk_min_int(pitchEstimationLPCOrder, predictLPCOrder); shapeWinLength = 5 * fs_kHz + 2 * la_shape; this.Complexity = Complexity; return result; } private int silk_setup_LBRR(int TargetRate_bps) { int sILK_NO_ERROR = SilkError.SILK_NO_ERROR; int lBRR_enabled = LBRR_enabled; LBRR_enabled = 0; if (useInBandFEC != 0 && PacketLoss_perc > 0) { int a = ((fs_kHz == 8) ? 12000 : ((fs_kHz != 12) ? 16000 : 14000)); a = Inlines.silk_SMULWB(Inlines.silk_MUL(a, 125 - Inlines.silk_min(PacketLoss_perc, 25)), 655); if (TargetRate_bps > a) { if (lBRR_enabled == 0) { LBRR_GainIncreases = 7; } else { LBRR_GainIncreases = Inlines.silk_max_int(7 - Inlines.silk_SMULWB(PacketLoss_perc, 26214), 2); } LBRR_enabled = 1; } } return sILK_NO_ERROR; } internal int silk_control_audio_bandwidth(EncControlState encControl) { int num = fs_kHz; int num2 = Inlines.silk_SMULBB(num, 1000); if (num2 == 0) { num2 = Inlines.silk_min(desiredInternal_fs_Hz, API_fs_Hz); num = Inlines.silk_DIV32_16(num2, 1000); } else if (num2 > API_fs_Hz || num2 > maxInternal_fs_Hz || num2 < minInternal_fs_Hz) { num2 = API_fs_Hz; num2 = Inlines.silk_min(num2, maxInternal_fs_Hz); num2 = Inlines.silk_max(num2, minInternal_fs_Hz); num = Inlines.silk_DIV32_16(num2, 1000); } else { if (sLP.transition_frame_no >= 256) { sLP.mode = 0; } if (allow_bandwidth_switch != 0 || encControl.opusCanSwitch != 0) { if (Inlines.silk_SMULBB(fs_kHz, 1000) > desiredInternal_fs_Hz) { if (sLP.mode == 0) { sLP.transition_frame_no = 256; Arrays.MemSet(sLP.In_LP_State, 0, 2); } if (encControl.opusCanSwitch != 0) { sLP.mode = 0; num = ((fs_kHz == 16) ? 12 : 8); } else if (sLP.transition_frame_no <= 0) { encControl.switchReady = 1; encControl.maxBits -= encControl.maxBits * 5 / (encControl.payloadSize_ms + 5); } else { sLP.mode = -2; } } else if (Inlines.silk_SMULBB(fs_kHz, 1000) < desiredInternal_fs_Hz) { if (encControl.opusCanSwitch != 0) { num = ((fs_kHz == 8) ? 12 : 16); sLP.transition_frame_no = 0; Arrays.MemSet(sLP.In_LP_State, 0, 2); sLP.mode = 1; } else if (sLP.mode == 0) { encControl.switchReady = 1; encControl.maxBits -= encControl.maxBits * 5 / (encControl.payloadSize_ms + 5); } else { sLP.mode = 1; } } else if (sLP.mode < 0) { sLP.mode = 1; } } } return num; } internal int silk_control_SNR(int TargetRate_bps) { int sILK_NO_ERROR = SilkError.SILK_NO_ERROR; TargetRate_bps = Inlines.silk_LIMIT(TargetRate_bps, 5000, 80000); if (TargetRate_bps != this.TargetRate_bps) { this.TargetRate_bps = TargetRate_bps; int[] array = ((fs_kHz == 8) ? Tables.silk_TargetRate_table_NB : ((fs_kHz != 12) ? Tables.silk_TargetRate_table_WB : Tables.silk_TargetRate_table_MB)); if (nb_subfr == 2) { TargetRate_bps -= 2200; } for (int i = 1; i < 8; i++) { if (TargetRate_bps <= array[i]) { int a = Inlines.silk_DIV32(Inlines.silk_LSHIFT(TargetRate_bps - array[i - 1], 6), array[i] - array[i - 1]); SNR_dB_Q7 = Inlines.silk_LSHIFT(Tables.silk_SNR_table_Q1[i - 1], 6) + Inlines.silk_MUL(a, Tables.silk_SNR_table_Q1[i] - Tables.silk_SNR_table_Q1[i - 1]); break; } } } return sILK_NO_ERROR; } internal void silk_encode_do_VAD() { VoiceActivityDetection.silk_VAD_GetSA_Q8(this, inputBuf, 1); if (speech_activity_Q8 < 13) { indices.signalType = 0; noSpeechCounter++; if (noSpeechCounter < 10) { inDTX = 0; } else if (noSpeechCounter > 30) { noSpeechCounter = 10; inDTX = 0; } VAD_flags[nFramesEncoded] = 0; } else { noSpeechCounter = 0; inDTX = 0; indices.signalType = 1; VAD_flags[nFramesEncoded] = 1; } } internal int silk_encode_frame(BoxedValue pnBytesOut, EntropyCoder psRangeEnc, int condCoding, int maxBits, int useCBR) { SilkEncoderControl silkEncoderControl = new SilkEncoderControl(); int result = 0; EntropyCoder entropyCoder = new EntropyCoder(); EntropyCoder entropyCoder2 = new EntropyCoder(); SilkNSQState silkNSQState = new SilkNSQState(); SilkNSQState silkNSQState2 = new SilkNSQState(); sbyte lastGainIndex = 0; int num3; int num2; int num; int num4 = (num3 = (num2 = (num = 0))); indices.Seed = (sbyte)(frameCounter++ & 3); int num5 = ltp_mem_length; sLP.silk_LP_variable_cutoff(inputBuf, 1, frame_length); Array.Copy(inputBuf, 1, x_buf, num5 + 5 * fs_kHz, frame_length); if (prefillFlag == 0) { short[] array = new short[la_pitch + frame_length + ltp_mem_length]; int pitch_res_ptr = ltp_mem_length; FindPitchLags.silk_find_pitch_lags(this, silkEncoderControl, array, x_buf, num5); NoiseShapeAnalysis.silk_noise_shape_analysis(this, silkEncoderControl, array, pitch_res_ptr, x_buf, num5); FindPredCoefs.silk_find_pred_coefs(this, silkEncoderControl, array, x_buf, num5, condCoding); ProcessGains.silk_process_gains(this, silkEncoderControl, condCoding); int[] array2 = new int[frame_length]; Filters.silk_prefilter(this, silkEncoderControl, array2, x_buf, num5); silk_LBRR_encode(silkEncoderControl, array2, condCoding); int num6 = 6; short num7 = 256; int num8 = 0; int num9 = 0; int num10 = GainQuantization.silk_gains_ID(indices.GainsIndices, nb_subfr); int num11 = -1; int num12 = -1; entropyCoder.Assign(psRangeEnc); silkNSQState.Assign(sNSQ); sbyte seed = indices.Seed; short num13 = ec_prevLagIndex; int num14 = ec_prevSignalType; byte[] array3 = new byte[1275]; int num15 = 0; while (true) { bool flag = true; int num16; if (num10 == num11) { num16 = num4; } else if (num10 == num12) { num16 = num3; } else { if (num15 > 0) { psRangeEnc.Assign(entropyCoder); sNSQ.Assign(silkNSQState); indices.Seed = seed; ec_prevLagIndex = num13; ec_prevSignalType = num14; } if (nStatesDelayedDecision > 1 || warping_Q16 > 0) { sNSQ.silk_NSQ_del_dec(this, indices, array2, pulses, silkEncoderControl.PredCoef_Q12, silkEncoderControl.LTPCoef_Q14, silkEncoderControl.AR2_Q13, silkEncoderControl.HarmShapeGain_Q14, silkEncoderControl.Tilt_Q14, silkEncoderControl.LF_shp_Q14, silkEncoderControl.Gains_Q16, silkEncoderControl.pitchL, silkEncoderControl.Lambda_Q10, silkEncoderControl.LTP_scale_Q14); } else { sNSQ.silk_NSQ(this, indices, array2, pulses, silkEncoderControl.PredCoef_Q12, silkEncoderControl.LTPCoef_Q14, silkEncoderControl.AR2_Q13, silkEncoderControl.HarmShapeGain_Q14, silkEncoderControl.Tilt_Q14, silkEncoderControl.LF_shp_Q14, silkEncoderControl.Gains_Q16, silkEncoderControl.pitchL, silkEncoderControl.Lambda_Q10, silkEncoderControl.LTP_scale_Q14); } EncodeIndices.silk_encode_indices(this, psRangeEnc, nFramesEncoded, 0, condCoding); EncodePulses.silk_encode_pulses(psRangeEnc, indices.signalType, indices.quantOffsetType, pulses, frame_length); num16 = psRangeEnc.tell(); if (useCBR == 0 && num15 == 0 && num16 <= maxBits) { break; } } if (num15 == num6) { if (num8 != 0 && (num10 == num11 || num16 > maxBits)) { psRangeEnc.Assign(entropyCoder2); Array.Copy(array3, 0, psRangeEnc.buf, psRangeEnc.buf_ptr, (int)entropyCoder2.offs); sNSQ.Assign(silkNSQState2); sShape.LastGainIndex = lastGainIndex; } break; } if (num16 > maxBits) { if (num8 == 0 && num15 >= 2) { silkEncoderControl.Lambda_Q10 = Inlines.silk_ADD_RSHIFT32(silkEncoderControl.Lambda_Q10, silkEncoderControl.Lambda_Q10, 1); num9 = 0; num12 = -1; } else { num9 = 1; num3 = num16; num = num7; num12 = num10; } } else { if (num16 >= maxBits - 5) { break; } num8 = 1; num4 = num16; num2 = num7; if (num10 != num11) { num11 = num10; entropyCoder2.Assign(psRangeEnc); Array.Copy(psRangeEnc.buf, psRangeEnc.buf_ptr, array3, 0, (int)psRangeEnc.offs); silkNSQState2.Assign(sNSQ); lastGainIndex = sShape.LastGainIndex; } } if ((num8 & num9) == 0) { int a = Inlines.silk_log2lin(Inlines.silk_LSHIFT(num16 - maxBits, 7) / frame_length + 2048); a = Inlines.silk_min_32(a, 131072); if (num16 > maxBits) { a = Inlines.silk_max_32(a, 85197); } num7 = (short)Inlines.silk_SMULWB(a, num7); } else { num7 = (short)(num2 + Inlines.silk_DIV32_16(Inlines.silk_MUL(num - num2, maxBits - num4), num3 - num4)); if (num7 > Inlines.silk_ADD_RSHIFT32(num2, num - num2, 2)) { num7 = (short)Inlines.silk_ADD_RSHIFT32(num2, num - num2, 2); } else if (num7 < Inlines.silk_SUB_RSHIFT32(num, num - num2, 2)) { num7 = (short)Inlines.silk_SUB_RSHIFT32(num, num - num2, 2); } } for (int i = 0; i < nb_subfr; i++) { silkEncoderControl.Gains_Q16[i] = Inlines.silk_LSHIFT_SAT32(Inlines.silk_SMULWB(silkEncoderControl.GainsUnq_Q16[i], num7), 8); } sShape.LastGainIndex = silkEncoderControl.lastGainIndexPrev; BoxedValue boxedValue = new BoxedValue(sShape.LastGainIndex); GainQuantization.silk_gains_quant(indices.GainsIndices, silkEncoderControl.Gains_Q16, boxedValue, (condCoding == 2) ? 1 : 0, nb_subfr); sShape.LastGainIndex = boxedValue.Val; num10 = GainQuantization.silk_gains_ID(indices.GainsIndices, nb_subfr); num15++; } } Arrays.MemMove(x_buf, frame_length, 0, ltp_mem_length + 5 * fs_kHz); if (prefillFlag != 0) { pnBytesOut.Val = 0; return result; } prevLag = silkEncoderControl.pitchL[nb_subfr - 1]; prevSignalType = indices.signalType; first_frame_after_reset = 0; pnBytesOut.Val = Inlines.silk_RSHIFT(psRangeEnc.tell() + 7, 3); return result; } internal void silk_LBRR_encode(SilkEncoderControl thisCtrl, int[] xfw_Q3, int condCoding) { int[] array = new int[nb_subfr]; SideInfoIndices sideInfoIndices = indices_LBRR[nFramesEncoded]; SilkNSQState silkNSQState = new SilkNSQState(); if (LBRR_enabled != 0 && speech_activity_Q8 > 77) { LBRR_flags[nFramesEncoded] = 1; silkNSQState.Assign(sNSQ); sideInfoIndices.Assign(indices); Array.Copy(thisCtrl.Gains_Q16, array, nb_subfr); if (nFramesEncoded == 0 || LBRR_flags[nFramesEncoded - 1] == 0) { LBRRprevLastGainIndex = sShape.LastGainIndex; sideInfoIndices.GainsIndices[0] = (sbyte)(sideInfoIndices.GainsIndices[0] + LBRR_GainIncreases); sideInfoIndices.GainsIndices[0] = (sbyte)Inlines.silk_min_int(sideInfoIndices.GainsIndices[0], 63); } BoxedValue boxedValue = new BoxedValue(LBRRprevLastGainIndex); GainQuantization.silk_gains_dequant(thisCtrl.Gains_Q16, sideInfoIndices.GainsIndices, boxedValue, (condCoding == 2) ? 1 : 0, nb_subfr); LBRRprevLastGainIndex = boxedValue.Val; if (nStatesDelayedDecision > 1 || warping_Q16 > 0) { silkNSQState.silk_NSQ_del_dec(this, sideInfoIndices, xfw_Q3, pulses_LBRR[nFramesEncoded], thisCtrl.PredCoef_Q12, thisCtrl.LTPCoef_Q14, thisCtrl.AR2_Q13, thisCtrl.HarmShapeGain_Q14, thisCtrl.Tilt_Q14, thisCtrl.LF_shp_Q14, thisCtrl.Gains_Q16, thisCtrl.pitchL, thisCtrl.Lambda_Q10, thisCtrl.LTP_scale_Q14); } else { silkNSQState.silk_NSQ(this, sideInfoIndices, xfw_Q3, pulses_LBRR[nFramesEncoded], thisCtrl.PredCoef_Q12, thisCtrl.LTPCoef_Q14, thisCtrl.AR2_Q13, thisCtrl.HarmShapeGain_Q14, thisCtrl.Tilt_Q14, thisCtrl.LF_shp_Q14, thisCtrl.Gains_Q16, thisCtrl.pitchL, thisCtrl.Lambda_Q10, thisCtrl.LTP_scale_Q14); } Array.Copy(array, thisCtrl.Gains_Q16, nb_subfr); } } } internal class SilkDecoder { internal readonly SilkChannelDecoder[] channel_state = new SilkChannelDecoder[2]; internal readonly StereoDecodeState sStereo = new StereoDecodeState(); internal int nChannelsAPI = 0; internal int nChannelsInternal = 0; internal int prev_decode_only_middle = 0; internal SilkDecoder() { for (int i = 0; i < 2; i++) { channel_state[i] = new SilkChannelDecoder(); } } internal void Reset() { for (int i = 0; i < 2; i++) { channel_state[i].Reset(); } sStereo.Reset(); nChannelsAPI = 0; nChannelsInternal = 0; prev_decode_only_middle = 0; } } internal class SilkDecoderControl { internal readonly int[] pitchL = new int[4]; internal readonly int[] Gains_Q16 = new int[4]; internal readonly short[][] PredCoef_Q12 = Arrays.InitTwoDimensionalArray(2, 16); internal readonly short[] LTPCoef_Q14 = new short[20]; internal int LTP_scale_Q14 = 0; internal void Reset() { Arrays.MemSet(pitchL, 0, 4); Arrays.MemSet(Gains_Q16, 0, 4); Arrays.MemSet(PredCoef_Q12[0], (short)0, 16); Arrays.MemSet(PredCoef_Q12[1], (short)0, 16); Arrays.MemSet(LTPCoef_Q14, (short)0, 20); LTP_scale_Q14 = 0; } } internal class SilkEncoder { internal readonly SilkChannelEncoder[] state_Fxx = new SilkChannelEncoder[2]; internal readonly StereoEncodeState sStereo = new StereoEncodeState(); internal int nBitsUsedLBRR = 0; internal int nBitsExceeded = 0; internal int nChannelsAPI = 0; internal int nChannelsInternal = 0; internal int nPrevChannelsInternal = 0; internal int timeSinceSwitchAllowed_ms = 0; internal int allowBandwidthSwitch = 0; internal int prev_decode_only_middle = 0; internal SilkEncoder() { for (int i = 0; i < 2; i++) { state_Fxx[i] = new SilkChannelEncoder(); } } internal void Reset() { for (int i = 0; i < 2; i++) { state_Fxx[i].Reset(); } sStereo.Reset(); nBitsUsedLBRR = 0; nBitsExceeded = 0; nChannelsAPI = 0; nChannelsInternal = 0; nPrevChannelsInternal = 0; timeSinceSwitchAllowed_ms = 0; allowBandwidthSwitch = 0; prev_decode_only_middle = 0; } internal static int silk_init_encoder(SilkChannelEncoder psEnc) { int num = 0; psEnc.Reset(); psEnc.variable_HP_smth1_Q15 = Inlines.silk_LSHIFT(Inlines.silk_lin2log(3932160) - 2048, 8); psEnc.variable_HP_smth2_Q15 = psEnc.variable_HP_smth1_Q15; psEnc.first_frame_after_reset = 1; return num + VoiceActivityDetection.silk_VAD_Init(psEnc.sVAD); } } internal class SilkEncoderControl { internal readonly int[] Gains_Q16 = new int[4]; internal readonly short[][] PredCoef_Q12 = Arrays.InitTwoDimensionalArray(2, 16); internal readonly short[] LTPCoef_Q14 = new short[20]; internal int LTP_scale_Q14 = 0; internal readonly int[] pitchL = new int[4]; internal readonly short[] AR1_Q13 = new short[64]; internal readonly short[] AR2_Q13 = new short[64]; internal readonly int[] LF_shp_Q14 = new int[4]; internal readonly int[] GainsPre_Q14 = new int[4]; internal readonly int[] HarmBoost_Q14 = new int[4]; internal readonly int[] Tilt_Q14 = new int[4]; internal readonly int[] HarmShapeGain_Q14 = new int[4]; internal int Lambda_Q10 = 0; internal int input_quality_Q14 = 0; internal int coding_quality_Q14 = 0; internal int sparseness_Q8 = 0; internal int predGain_Q16 = 0; internal int LTPredCodGain_Q7 = 0; internal readonly int[] ResNrg = new int[4]; internal readonly int[] ResNrgQ = new int[4]; internal readonly int[] GainsUnq_Q16 = new int[4]; internal sbyte lastGainIndexPrev = 0; internal void Reset() { Arrays.MemSet(Gains_Q16, 0, 4); Arrays.MemSet(PredCoef_Q12[0], (short)0, 16); Arrays.MemSet(PredCoef_Q12[1], (short)0, 16); Arrays.MemSet(LTPCoef_Q14, (short)0, 20); LTP_scale_Q14 = 0; Arrays.MemSet(pitchL, 0, 4); Arrays.MemSet(AR1_Q13, (short)0, 64); Arrays.MemSet(AR2_Q13, (short)0, 64); Arrays.MemSet(LF_shp_Q14, 0, 4); Arrays.MemSet(GainsPre_Q14, 0, 4); Arrays.MemSet(HarmBoost_Q14, 0, 4); Arrays.MemSet(Tilt_Q14, 0, 4); Arrays.MemSet(HarmShapeGain_Q14, 0, 4); Lambda_Q10 = 0; input_quality_Q14 = 0; coding_quality_Q14 = 0; sparseness_Q8 = 0; predGain_Q16 = 0; LTPredCodGain_Q7 = 0; Arrays.MemSet(ResNrg, 0, 4); Arrays.MemSet(ResNrgQ, 0, 4); Arrays.MemSet(GainsUnq_Q16, 0, 4); lastGainIndexPrev = 0; } } internal class SilkLPState { internal readonly int[] In_LP_State = new int[2]; internal int transition_frame_no = 0; internal int mode = 0; internal void Reset() { In_LP_State[0] = 0; In_LP_State[1] = 0; transition_frame_no = 0; mode = 0; } internal void silk_LP_variable_cutoff(short[] frame, int frame_ptr, int frame_length) { int[] b_Q = new int[3]; int[] a_Q = new int[2]; int num = 0; int num2 = 0; if (mode != 0) { num = Inlines.silk_LSHIFT(256 - transition_frame_no, 10); num2 = Inlines.silk_RSHIFT(num, 16); num -= Inlines.silk_LSHIFT(num2, 16); Filters.silk_LP_interpolate_filter_taps(b_Q, a_Q, num2, num); transition_frame_no = Inlines.silk_LIMIT(transition_frame_no + mode, 0, 256); Filters.silk_biquad_alt(frame, frame_ptr, b_Q, a_Q, In_LP_State, frame, frame_ptr, frame_length, 1); } } } internal class SilkNSQState { private class NSQ_del_dec_struct { internal readonly int[] sLPC_Q14 = new int[80 + SilkConstants.NSQ_LPC_BUF_LENGTH]; internal readonly int[] RandState = new int[32]; internal readonly int[] Q_Q10 = new int[32]; internal readonly int[] Xq_Q14 = new int[32]; internal readonly int[] Pred_Q15 = new int[32]; internal readonly int[] Shape_Q14 = new int[32]; internal int[] sAR2_Q14; internal int LF_AR_Q14 = 0; internal int Seed = 0; internal int SeedInit = 0; internal int RD_Q10 = 0; internal NSQ_del_dec_struct(int shapingOrder) { sAR2_Q14 = new int[shapingOrder]; } internal void PartialCopyFrom(NSQ_del_dec_struct other, int q14Offset) { Buffer.BlockCopy(other.sLPC_Q14, q14Offset * 4, sLPC_Q14, q14Offset * 4, (80 + SilkConstants.NSQ_LPC_BUF_LENGTH - q14Offset) * 4); Buffer.BlockCopy(other.RandState, 0, RandState, 0, 128); Buffer.BlockCopy(other.Q_Q10, 0, Q_Q10, 0, 128); Buffer.BlockCopy(other.Xq_Q14, 0, Xq_Q14, 0, 128); Buffer.BlockCopy(other.Pred_Q15, 0, Pred_Q15, 0, 128); Buffer.BlockCopy(other.Shape_Q14, 0, Shape_Q14, 0, 128); Buffer.BlockCopy(other.sAR2_Q14, 0, sAR2_Q14, 0, sAR2_Q14.Length * 4); LF_AR_Q14 = other.LF_AR_Q14; Seed = other.Seed; SeedInit = other.SeedInit; RD_Q10 = other.RD_Q10; } internal void Assign(NSQ_del_dec_struct other) { PartialCopyFrom(other, 0); } } private struct NSQ_sample_struct { internal int Q_Q10; internal int RD_Q10; internal int xq_Q14; internal int LF_AR_Q14; internal int sLTP_shp_Q14; internal int LPC_exc_Q14; } internal readonly short[] xq = new short[640]; internal readonly int[] sLTP_shp_Q14 = new int[640]; internal readonly int[] sLPC_Q14 = new int[80 + SilkConstants.NSQ_LPC_BUF_LENGTH]; internal readonly int[] sAR2_Q14 = new int[16]; internal int sLF_AR_shp_Q14 = 0; internal int lagPrev = 0; internal int sLTP_buf_idx = 0; internal int sLTP_shp_buf_idx = 0; internal int rand_seed = 0; internal int prev_gain_Q16 = 0; internal int rewhite_flag = 0; internal void Reset() { Arrays.MemSet(xq, (short)0, 640); Arrays.MemSet(sLTP_shp_Q14, 0, 640); Arrays.MemSet(sLPC_Q14, 0, 80 + SilkConstants.NSQ_LPC_BUF_LENGTH); Arrays.MemSet(sAR2_Q14, 0, 16); sLF_AR_shp_Q14 = 0; lagPrev = 0; sLTP_buf_idx = 0; sLTP_shp_buf_idx = 0; rand_seed = 0; prev_gain_Q16 = 0; rewhite_flag = 0; } internal void Assign(SilkNSQState other) { sLF_AR_shp_Q14 = other.sLF_AR_shp_Q14; lagPrev = other.lagPrev; sLTP_buf_idx = other.sLTP_buf_idx; sLTP_shp_buf_idx = other.sLTP_shp_buf_idx; rand_seed = other.rand_seed; prev_gain_Q16 = other.prev_gain_Q16; rewhite_flag = other.rewhite_flag; Array.Copy(other.xq, xq, 640); Array.Copy(other.sLTP_shp_Q14, sLTP_shp_Q14, 640); Array.Copy(other.sLPC_Q14, sLPC_Q14, 80 + SilkConstants.NSQ_LPC_BUF_LENGTH); Array.Copy(other.sAR2_Q14, sAR2_Q14, 16); } internal void silk_NSQ(SilkChannelEncoder psEncC, SideInfoIndices psIndices, int[] x_Q3, sbyte[] pulses, short[][] PredCoef_Q12, short[] LTPCoef_Q14, short[] AR2_Q13, int[] HarmShapeGain_Q14, int[] Tilt_Q14, int[] LF_shp_Q14, int[] Gains_Q16, int[] pitchL, int Lambda_Q10, int LTP_scale_Q14) { int num = 0; int num2 = 0; rand_seed = psIndices.Seed; int num3 = lagPrev; int offset_Q = Tables.silk_Quantization_Offsets_Q10[psIndices.signalType >> 1][psIndices.quantOffsetType]; int num4 = ((psIndices.NLSFInterpCoef_Q2 != 4) ? 1 : 0); int[] sLTP_Q = new int[psEncC.ltp_mem_length + psEncC.frame_length]; short[] array = new short[psEncC.ltp_mem_length + psEncC.frame_length]; int[] x_sc_Q = new int[psEncC.subfr_length]; sLTP_shp_buf_idx = psEncC.ltp_mem_length; sLTP_buf_idx = psEncC.ltp_mem_length; int num5 = psEncC.ltp_mem_length; for (int i = 0; i < psEncC.nb_subfr; i++) { int num6 = (i >> 1) | (1 - num4); int b_Q14_ptr = i * 5; int aR_shp_Q13_ptr = i * 16; int num7 = Inlines.silk_RSHIFT(HarmShapeGain_Q14[i], 2); num7 |= Inlines.silk_LSHIFT(Inlines.silk_RSHIFT(HarmShapeGain_Q14[i], 1), 16); rewhite_flag = 0; if (psIndices.signalType == 2) { num3 = pitchL[i]; if ((i & (3 - Inlines.silk_LSHIFT(num4, 1))) == 0) { int num8 = psEncC.ltp_mem_length - num3 - psEncC.predictLPCOrder - 2; Filters.silk_LPC_analysis_filter(array, num8, xq, num8 + i * psEncC.subfr_length, PredCoef_Q12[num6], 0, psEncC.ltp_mem_length - num8, psEncC.predictLPCOrder); rewhite_flag = 1; sLTP_buf_idx = psEncC.ltp_mem_length; } } silk_nsq_scale_states(psEncC, x_Q3, num2, x_sc_Q, array, sLTP_Q, i, LTP_scale_Q14, Gains_Q16, pitchL, psIndices.signalType); silk_noise_shape_quantizer(psIndices.signalType, x_sc_Q, pulses, num, xq, num5, sLTP_Q, PredCoef_Q12[num6], LTPCoef_Q14, b_Q14_ptr, AR2_Q13, aR_shp_Q13_ptr, num3, num7, Tilt_Q14[i], LF_shp_Q14[i], Gains_Q16[i], Lambda_Q10, offset_Q, psEncC.subfr_length, psEncC.shapingLPCOrder, psEncC.predictLPCOrder); num2 += psEncC.subfr_length; num += psEncC.subfr_length; num5 += psEncC.subfr_length; } lagPrev = pitchL[psEncC.nb_subfr - 1]; Arrays.MemMove(xq, psEncC.frame_length, 0, psEncC.ltp_mem_length); Arrays.MemMove(sLTP_shp_Q14, psEncC.frame_length, 0, psEncC.ltp_mem_length); } private void silk_noise_shape_quantizer(int signalType, int[] x_sc_Q10, sbyte[] pulses, int pulses_ptr, short[] xq, int xq_ptr, int[] sLTP_Q15, short[] a_Q12, short[] b_Q14, int b_Q14_ptr, short[] AR_shp_Q13, int AR_shp_Q13_ptr, int lag, int HarmShapeFIRPacked_Q14, int Tilt_Q14, int LF_shp_Q14, int Gain_Q16, int Lambda_Q10, int offset_Q10, int length, int shapingLPCOrder, int predictLPCOrder) { int num = sLTP_shp_buf_idx - lag + 1; int num2 = sLTP_buf_idx - lag + 2; int b = Inlines.silk_RSHIFT(Gain_Q16, 6); int num3 = SilkConstants.NSQ_LPC_BUF_LENGTH - 1; for (int i = 0; i < length; i++) { rand_seed = Inlines.silk_RAND(rand_seed); int a = Inlines.silk_RSHIFT(predictLPCOrder, 1); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3], a_Q12[0]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 1], a_Q12[1]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 2], a_Q12[2]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 3], a_Q12[3]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 4], a_Q12[4]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 5], a_Q12[5]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 6], a_Q12[6]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 7], a_Q12[7]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 8], a_Q12[8]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 9], a_Q12[9]); if (predictLPCOrder == 16) { a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 10], a_Q12[10]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 11], a_Q12[11]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 12], a_Q12[12]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 13], a_Q12[13]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 14], a_Q12[14]); a = Inlines.silk_SMLAWB(a, sLPC_Q14[num3 - 15], a_Q12[15]); } int a2; if (signalType == 2) { a2 = 2; a2 = Inlines.silk_SMLAWB(a2, sLTP_Q15[num2], b_Q14[b_Q14_ptr]); a2 = Inlines.silk_SMLAWB(a2, sLTP_Q15[num2 - 1], b_Q14[b_Q14_ptr + 1]); a2 = Inlines.silk_SMLAWB(a2, sLTP_Q15[num2 - 2], b_Q14[b_Q14_ptr + 2]); a2 = Inlines.silk_SMLAWB(a2, sLTP_Q15[num2 - 3], b_Q14[b_Q14_ptr + 3]); a2 = Inlines.silk_SMLAWB(a2, sLTP_Q15[num2 - 4], b_Q14[b_Q14_ptr + 4]); num2++; } else { a2 = 0; } int num4 = sLPC_Q14[num3]; int num5 = sAR2_Q14[0]; sAR2_Q14[0] = num4; int a3 = Inlines.silk_RSHIFT(shapingLPCOrder, 1); a3 = Inlines.silk_SMLAWB(a3, num4, AR_shp_Q13[AR_shp_Q13_ptr]); for (int j = 2; j < shapingLPCOrder; j += 2) { num4 = sAR2_Q14[j - 1]; sAR2_Q14[j - 1] = num5; a3 = Inlines.silk_SMLAWB(a3, num5, AR_shp_Q13[AR_shp_Q13_ptr + j - 1]); num5 = sAR2_Q14[j]; sAR2_Q14[j] = num4; a3 = Inlines.silk_SMLAWB(a3, num4, AR_shp_Q13[AR_shp_Q13_ptr + j]); } sAR2_Q14[shapingLPCOrder - 1] = num5; a3 = Inlines.silk_SMLAWB(a3, num5, AR_shp_Q13[AR_shp_Q13_ptr + shapingLPCOrder - 1]); a3 = Inlines.silk_LSHIFT32(a3, 1); a3 = Inlines.silk_SMLAWB(a3, sLF_AR_shp_Q14, Tilt_Q14); int a4 = Inlines.silk_SMULWB(sLTP_shp_Q14[sLTP_shp_buf_idx - 1], LF_shp_Q14); a4 = Inlines.silk_SMLAWT(a4, sLF_AR_shp_Q14, LF_shp_Q14); num5 = Inlines.silk_SUB32(Inlines.silk_LSHIFT32(a, 2), a3); num5 = Inlines.silk_SUB32(num5, a4); if (lag > 0) { int a5 = Inlines.silk_SMULWB(Inlines.silk_ADD32(sLTP_shp_Q14[num], sLTP_shp_Q14[num - 2]), HarmShapeFIRPacked_Q14); a5 = Inlines.silk_SMLAWT(a5, sLTP_shp_Q14[num - 1], HarmShapeFIRPacked_Q14); a5 = Inlines.silk_LSHIFT(a5, 1); num++; num4 = Inlines.silk_SUB32(a2, a5); num5 = Inlines.silk_ADD_LSHIFT32(num4, num5, 1); num5 = Inlines.silk_RSHIFT_ROUND(num5, 3); } else { num5 = Inlines.silk_RSHIFT_ROUND(num5, 2); } int num6 = Inlines.silk_SUB32(x_sc_Q10[i], num5); if (rand_seed < 0) { num6 = -num6; } num6 = Inlines.silk_LIMIT_32(num6, -31744, 30720); int a6 = Inlines.silk_SUB32(num6, offset_Q10); int num7 = Inlines.silk_RSHIFT(a6, 10); int num8; int a7; int a8; if (num7 > 0) { a6 = Inlines.silk_SUB32(Inlines.silk_LSHIFT(num7, 10), 80); a6 = Inlines.silk_ADD32(a6, offset_Q10); num8 = Inlines.silk_ADD32(a6, 1024); a7 = Inlines.silk_SMULBB(a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(num8, Lambda_Q10); } else { switch (num7) { case 0: a6 = offset_Q10; num8 = Inlines.silk_ADD32(a6, 944); a7 = Inlines.silk_SMULBB(a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(num8, Lambda_Q10); break; case -1: num8 = offset_Q10; a6 = Inlines.silk_SUB32(num8, 944); a7 = Inlines.silk_SMULBB(-a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(num8, Lambda_Q10); break; default: a6 = Inlines.silk_ADD32(Inlines.silk_LSHIFT(num7, 10), 80); a6 = Inlines.silk_ADD32(a6, offset_Q10); num8 = Inlines.silk_ADD32(a6, 1024); a7 = Inlines.silk_SMULBB(-a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(-num8, Lambda_Q10); break; } } int num9 = Inlines.silk_SUB32(num6, a6); a7 = Inlines.silk_SMLABB(a7, num9, num9); num9 = Inlines.silk_SUB32(num6, num8); a8 = Inlines.silk_SMLABB(a8, num9, num9); if (a8 < a7) { a6 = num8; } pulses[pulses_ptr + i] = (sbyte)Inlines.silk_RSHIFT_ROUND(a6, 10); int num10 = Inlines.silk_LSHIFT(a6, 4); if (rand_seed < 0) { num10 = -num10; } int a9 = Inlines.silk_ADD_LSHIFT32(num10, a2, 1); int num11 = Inlines.silk_ADD_LSHIFT32(a9, a, 4); xq[xq_ptr + i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(num11, b), 8)); num3++; sLPC_Q14[num3] = num11; int a10 = (sLF_AR_shp_Q14 = Inlines.silk_SUB_LSHIFT32(num11, a3, 2)); sLTP_shp_Q14[sLTP_shp_buf_idx] = Inlines.silk_SUB_LSHIFT32(a10, a4, 2); sLTP_Q15[sLTP_buf_idx] = Inlines.silk_LSHIFT(a9, 1); sLTP_shp_buf_idx++; sLTP_buf_idx++; rand_seed = Inlines.silk_ADD32_ovflw(rand_seed, pulses[pulses_ptr + i]); } Array.Copy(sLPC_Q14, length, sLPC_Q14, 0, SilkConstants.NSQ_LPC_BUF_LENGTH); } private void silk_nsq_scale_states(SilkChannelEncoder psEncC, int[] x_Q3, int x_Q3_ptr, int[] x_sc_Q10, short[] sLTP, int[] sLTP_Q15, int subfr, int LTP_scale_Q14, int[] Gains_Q16, int[] pitchL, int signal_type) { int num = pitchL[subfr]; int num2 = Inlines.silk_INVERSE32_varQ(Inlines.silk_max(Gains_Q16[subfr], 1), 47); int num3 = ((Gains_Q16[subfr] == prev_gain_Q16) ? 65536 : Inlines.silk_DIV32_varQ(prev_gain_Q16, Gains_Q16[subfr], 16)); int b = Inlines.silk_RSHIFT_ROUND(num2, 8); for (int i = 0; i < psEncC.subfr_length; i++) { x_sc_Q10[i] = Inlines.silk_SMULWW(x_Q3[x_Q3_ptr + i], b); } prev_gain_Q16 = Gains_Q16[subfr]; if (rewhite_flag != 0) { if (subfr == 0) { num2 = Inlines.silk_LSHIFT(Inlines.silk_SMULWB(num2, LTP_scale_Q14), 2); } for (int i = sLTP_buf_idx - num - 2; i < sLTP_buf_idx; i++) { sLTP_Q15[i] = Inlines.silk_SMULWB(num2, sLTP[i]); } } if (num3 == 65536) { return; } for (int i = sLTP_shp_buf_idx - psEncC.ltp_mem_length; i < sLTP_shp_buf_idx; i++) { sLTP_shp_Q14[i] = Inlines.silk_SMULWW(num3, sLTP_shp_Q14[i]); } if (signal_type == 2 && rewhite_flag == 0) { for (int i = sLTP_buf_idx - num - 2; i < sLTP_buf_idx; i++) { sLTP_Q15[i] = Inlines.silk_SMULWW(num3, sLTP_Q15[i]); } } sLF_AR_shp_Q14 = Inlines.silk_SMULWW(num3, sLF_AR_shp_Q14); for (int i = 0; i < SilkConstants.NSQ_LPC_BUF_LENGTH; i++) { sLPC_Q14[i] = Inlines.silk_SMULWW(num3, sLPC_Q14[i]); } for (int i = 0; i < 16; i++) { sAR2_Q14[i] = Inlines.silk_SMULWW(num3, sAR2_Q14[i]); } } internal void silk_NSQ_del_dec(SilkChannelEncoder psEncC, SideInfoIndices psIndices, int[] x_Q3, sbyte[] pulses, short[][] PredCoef_Q12, short[] LTPCoef_Q14, short[] AR2_Q13, int[] HarmShapeGain_Q14, int[] Tilt_Q14, int[] LF_shp_Q14, int[] Gains_Q16, int[] pitchL, int Lambda_Q10, int LTP_scale_Q14) { int num = 0; int num2 = 0; int num3 = lagPrev; NSQ_del_dec_struct[] array = new NSQ_del_dec_struct[psEncC.nStatesDelayedDecision]; for (int i = 0; i < psEncC.nStatesDelayedDecision; i++) { array[i] = new NSQ_del_dec_struct(psEncC.shapingLPCOrder); } NSQ_del_dec_struct nSQ_del_dec_struct; for (int j = 0; j < psEncC.nStatesDelayedDecision; j++) { nSQ_del_dec_struct = array[j]; nSQ_del_dec_struct.Seed = (j + psIndices.Seed) & 3; nSQ_del_dec_struct.SeedInit = nSQ_del_dec_struct.Seed; nSQ_del_dec_struct.RD_Q10 = 0; nSQ_del_dec_struct.LF_AR_Q14 = sLF_AR_shp_Q14; nSQ_del_dec_struct.Shape_Q14[0] = sLTP_shp_Q14[psEncC.ltp_mem_length - 1]; Array.Copy(sLPC_Q14, nSQ_del_dec_struct.sLPC_Q14, SilkConstants.NSQ_LPC_BUF_LENGTH); Array.Copy(sAR2_Q14, nSQ_del_dec_struct.sAR2_Q14, psEncC.shapingLPCOrder); } int offset_Q = Tables.silk_Quantization_Offsets_Q10[psIndices.signalType >> 1][psIndices.quantOffsetType]; int num4 = 0; int num5 = Inlines.silk_min_int(32, psEncC.subfr_length); if (psIndices.signalType == 2) { for (int j = 0; j < psEncC.nb_subfr; j++) { num5 = Inlines.silk_min_int(num5, pitchL[j] - 2 - 1); } } else if (num3 > 0) { num5 = Inlines.silk_min_int(num5, num3 - 2 - 1); } int num6 = ((psIndices.NLSFInterpCoef_Q2 != 4) ? 1 : 0); int[] sLTP_Q = new int[psEncC.ltp_mem_length + psEncC.frame_length]; short[] array2 = new short[psEncC.ltp_mem_length + psEncC.frame_length]; int[] array3 = new int[psEncC.subfr_length]; int[] delayedGain_Q = new int[32]; int num7 = psEncC.ltp_mem_length; sLTP_shp_buf_idx = psEncC.ltp_mem_length; sLTP_buf_idx = psEncC.ltp_mem_length; int num8 = 0; int rD_Q; int num11; int num12; for (int j = 0; j < psEncC.nb_subfr; j++) { int num9 = (j >> 1) | (1 - num6); int num10 = Inlines.silk_RSHIFT(HarmShapeGain_Q14[j], 2); num10 |= Inlines.silk_LSHIFT(Inlines.silk_RSHIFT(HarmShapeGain_Q14[j], 1), 16); rewhite_flag = 0; if (psIndices.signalType == 2) { num3 = pitchL[j]; if ((j & (3 - Inlines.silk_LSHIFT(num6, 1))) == 0) { if (j == 2) { rD_Q = array[0].RD_Q10; num11 = 0; for (int k = 1; k < psEncC.nStatesDelayedDecision; k++) { if (array[k].RD_Q10 < rD_Q) { rD_Q = array[k].RD_Q10; num11 = k; } } for (int k = 0; k < psEncC.nStatesDelayedDecision; k++) { if (k != num11) { array[k].RD_Q10 += 134217727; } } nSQ_del_dec_struct = array[num11]; num12 = num4 + num5; for (int k = 0; k < num5; k++) { num12 = (num12 - 1) & 0x1F; pulses[num + k - num5] = (sbyte)Inlines.silk_RSHIFT_ROUND(nSQ_del_dec_struct.Q_Q10[num12], 10); xq[num7 + k - num5] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(nSQ_del_dec_struct.Xq_Q14[num12], Gains_Q16[1]), 14)); sLTP_shp_Q14[sLTP_shp_buf_idx - num5 + k] = nSQ_del_dec_struct.Shape_Q14[num12]; } num8 = 0; } int num13 = psEncC.ltp_mem_length - num3 - psEncC.predictLPCOrder - 2; Filters.silk_LPC_analysis_filter(array2, num13, xq, num13 + j * psEncC.subfr_length, PredCoef_Q12[num9], 0, psEncC.ltp_mem_length - num13, psEncC.predictLPCOrder); sLTP_buf_idx = psEncC.ltp_mem_length; rewhite_flag = 1; } } silk_nsq_del_dec_scale_states(psEncC, array, x_Q3, num2, array3, array2, sLTP_Q, j, psEncC.nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices.signalType, num5); BoxedValue boxedValue = new BoxedValue(num4); silk_noise_shape_quantizer_del_dec(array, psIndices.signalType, array3, pulses, num, xq, num7, sLTP_Q, delayedGain_Q, PredCoef_Q12[num9], LTPCoef_Q14, j * 5, AR2_Q13, j * 16, num3, num10, Tilt_Q14[j], LF_shp_Q14[j], Gains_Q16[j], Lambda_Q10, offset_Q, psEncC.subfr_length, num8++, psEncC.shapingLPCOrder, psEncC.predictLPCOrder, psEncC.warping_Q16, psEncC.nStatesDelayedDecision, boxedValue, num5); num4 = boxedValue.Val; num2 += psEncC.subfr_length; num += psEncC.subfr_length; num7 += psEncC.subfr_length; } rD_Q = array[0].RD_Q10; num11 = 0; for (int j = 1; j < psEncC.nStatesDelayedDecision; j++) { if (array[j].RD_Q10 < rD_Q) { rD_Q = array[j].RD_Q10; num11 = j; } } nSQ_del_dec_struct = array[num11]; psIndices.Seed = (sbyte)nSQ_del_dec_struct.SeedInit; num12 = num4 + num5; int b = Inlines.silk_RSHIFT32(Gains_Q16[psEncC.nb_subfr - 1], 6); for (int k = 0; k < num5; k++) { num12 = (num12 - 1) & 0x1F; pulses[num + k - num5] = (sbyte)Inlines.silk_RSHIFT_ROUND(nSQ_del_dec_struct.Q_Q10[num12], 10); xq[num7 + k - num5] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(nSQ_del_dec_struct.Xq_Q14[num12], b), 8)); sLTP_shp_Q14[sLTP_shp_buf_idx - num5 + k] = nSQ_del_dec_struct.Shape_Q14[num12]; } Array.Copy(nSQ_del_dec_struct.sLPC_Q14, psEncC.subfr_length, sLPC_Q14, 0, SilkConstants.NSQ_LPC_BUF_LENGTH); Array.Copy(nSQ_del_dec_struct.sAR2_Q14, 0, sAR2_Q14, 0, psEncC.shapingLPCOrder); sLF_AR_shp_Q14 = nSQ_del_dec_struct.LF_AR_Q14; lagPrev = pitchL[psEncC.nb_subfr - 1]; Arrays.MemMove(xq, psEncC.frame_length, 0, psEncC.ltp_mem_length); Arrays.MemMove(sLTP_shp_Q14, psEncC.frame_length, 0, psEncC.ltp_mem_length); } private void silk_noise_shape_quantizer_del_dec(NSQ_del_dec_struct[] psDelDec, int signalType, int[] x_Q10, sbyte[] pulses, int pulses_ptr, short[] xq, int xq_ptr, int[] sLTP_Q15, int[] delayedGain_Q10, short[] a_Q12, short[] b_Q14, int b_Q14_ptr, short[] AR_shp_Q13, int AR_shp_Q13_ptr, int lag, int HarmShapeFIRPacked_Q14, int Tilt_Q14, int LF_shp_Q14, int Gain_Q16, int Lambda_Q10, int offset_Q10, int length, int subfr, int shapingLPCOrder, int predictLPCOrder, int warping_Q16, int nStatesDelayedDecision, BoxedValue smpl_buf_idx, int decisionDelay) { NSQ_sample_struct[] array = new NSQ_sample_struct[2 * nStatesDelayedDecision]; for (int i = 0; i < 2 * nStatesDelayedDecision; i++) { array[i] = default(NSQ_sample_struct); } int num = sLTP_shp_buf_idx - lag + 1; int num2 = sLTP_buf_idx - lag + 2; int num3 = Inlines.silk_RSHIFT(Gain_Q16, 6); for (int j = 0; j < length; j++) { int a; if (signalType == 2) { a = 2; a = Inlines.silk_SMLAWB(a, sLTP_Q15[num2], b_Q14[b_Q14_ptr]); a = Inlines.silk_SMLAWB(a, sLTP_Q15[num2 - 1], b_Q14[b_Q14_ptr + 1]); a = Inlines.silk_SMLAWB(a, sLTP_Q15[num2 - 2], b_Q14[b_Q14_ptr + 2]); a = Inlines.silk_SMLAWB(a, sLTP_Q15[num2 - 3], b_Q14[b_Q14_ptr + 3]); a = Inlines.silk_SMLAWB(a, sLTP_Q15[num2 - 4], b_Q14[b_Q14_ptr + 4]); a = Inlines.silk_LSHIFT(a, 1); num2++; } else { a = 0; } int a2; if (lag > 0) { a2 = Inlines.silk_SMULWB(Inlines.silk_ADD32(sLTP_shp_Q14[num], sLTP_shp_Q14[num - 2]), HarmShapeFIRPacked_Q14); a2 = Inlines.silk_SMLAWT(a2, sLTP_shp_Q14[num - 1], HarmShapeFIRPacked_Q14); a2 = Inlines.silk_SUB_LSHIFT32(a, a2, 2); num++; } else { a2 = 0; } NSQ_del_dec_struct nSQ_del_dec_struct; for (int k = 0; k < nStatesDelayedDecision; k++) { nSQ_del_dec_struct = psDelDec[k]; int[] array2 = nSQ_del_dec_struct.sAR2_Q14; int num4 = 2 * k; int num5 = num4 + 1; nSQ_del_dec_struct.Seed = Inlines.silk_RAND(nSQ_del_dec_struct.Seed); int num6 = SilkConstants.NSQ_LPC_BUF_LENGTH - 1 + j; int a3 = Inlines.silk_RSHIFT(predictLPCOrder, 1); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6], a_Q12[0]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 1], a_Q12[1]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 2], a_Q12[2]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 3], a_Q12[3]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 4], a_Q12[4]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 5], a_Q12[5]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 6], a_Q12[6]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 7], a_Q12[7]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 8], a_Q12[8]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 9], a_Q12[9]); if (predictLPCOrder == 16) { a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 10], a_Q12[10]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 11], a_Q12[11]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 12], a_Q12[12]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 13], a_Q12[13]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 14], a_Q12[14]); a3 = Inlines.silk_SMLAWB(a3, nSQ_del_dec_struct.sLPC_Q14[num6 - 15], a_Q12[15]); } a3 = Inlines.silk_LSHIFT(a3, 4); int num7 = Inlines.silk_SMLAWB(nSQ_del_dec_struct.sLPC_Q14[num6], array2[0], warping_Q16); int num8 = Inlines.silk_SMLAWB(array2[0], array2[1] - num7, warping_Q16); array2[0] = num7; int a4 = Inlines.silk_RSHIFT(shapingLPCOrder, 1); a4 = Inlines.silk_SMLAWB(a4, num7, AR_shp_Q13[AR_shp_Q13_ptr]); for (int l = 2; l < shapingLPCOrder; l += 2) { num7 = Inlines.silk_SMLAWB(array2[l - 1], array2[l] - num8, warping_Q16); array2[l - 1] = num8; a4 = Inlines.silk_SMLAWB(a4, num8, AR_shp_Q13[AR_shp_Q13_ptr + l - 1]); num8 = Inlines.silk_SMLAWB(array2[l], array2[l + 1] - num7, warping_Q16); array2[l] = num7; a4 = Inlines.silk_SMLAWB(a4, num7, AR_shp_Q13[AR_shp_Q13_ptr + l]); } array2[shapingLPCOrder - 1] = num8; a4 = Inlines.silk_SMLAWB(a4, num8, AR_shp_Q13[AR_shp_Q13_ptr + shapingLPCOrder - 1]); a4 = Inlines.silk_LSHIFT(a4, 1); a4 = Inlines.silk_SMLAWB(a4, nSQ_del_dec_struct.LF_AR_Q14, Tilt_Q14); a4 = Inlines.silk_LSHIFT(a4, 2); int a5 = Inlines.silk_SMULWB(nSQ_del_dec_struct.Shape_Q14[smpl_buf_idx.Val], LF_shp_Q14); a5 = Inlines.silk_SMLAWT(a5, nSQ_del_dec_struct.LF_AR_Q14, LF_shp_Q14); a5 = Inlines.silk_LSHIFT(a5, 2); num8 = Inlines.silk_ADD32(a4, a5); num7 = Inlines.silk_ADD32(a2, a3); num8 = Inlines.silk_SUB32(num7, num8); num8 = Inlines.silk_RSHIFT_ROUND(num8, 4); int num9 = Inlines.silk_SUB32(x_Q10[j], num8); if (nSQ_del_dec_struct.Seed < 0) { num9 = -num9; } num9 = Inlines.silk_LIMIT_32(num9, -31744, 30720); int a6 = Inlines.silk_SUB32(num9, offset_Q10); int num10 = Inlines.silk_RSHIFT(a6, 10); int num11; int a7; int a8; if (num10 > 0) { a6 = Inlines.silk_SUB32(Inlines.silk_LSHIFT(num10, 10), 80); a6 = Inlines.silk_ADD32(a6, offset_Q10); num11 = Inlines.silk_ADD32(a6, 1024); a7 = Inlines.silk_SMULBB(a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(num11, Lambda_Q10); } else { switch (num10) { case 0: a6 = offset_Q10; num11 = Inlines.silk_ADD32(a6, 944); a7 = Inlines.silk_SMULBB(a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(num11, Lambda_Q10); break; case -1: num11 = offset_Q10; a6 = Inlines.silk_SUB32(num11, 944); a7 = Inlines.silk_SMULBB(-a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(num11, Lambda_Q10); break; default: a6 = Inlines.silk_ADD32(Inlines.silk_LSHIFT(num10, 10), 80); a6 = Inlines.silk_ADD32(a6, offset_Q10); num11 = Inlines.silk_ADD32(a6, 1024); a7 = Inlines.silk_SMULBB(-a6, Lambda_Q10); a8 = Inlines.silk_SMULBB(-num11, Lambda_Q10); break; } } int num12 = Inlines.silk_SUB32(num9, a6); a7 = Inlines.silk_RSHIFT(Inlines.silk_SMLABB(a7, num12, num12), 10); num12 = Inlines.silk_SUB32(num9, num11); a8 = Inlines.silk_RSHIFT(Inlines.silk_SMLABB(a8, num12, num12), 10); if (a7 < a8) { array[num4].RD_Q10 = Inlines.silk_ADD32(nSQ_del_dec_struct.RD_Q10, a7); array[num5].RD_Q10 = Inlines.silk_ADD32(nSQ_del_dec_struct.RD_Q10, a8); array[num4].Q_Q10 = a6; array[num5].Q_Q10 = num11; } else { array[num4].RD_Q10 = Inlines.silk_ADD32(nSQ_del_dec_struct.RD_Q10, a8); array[num5].RD_Q10 = Inlines.silk_ADD32(nSQ_del_dec_struct.RD_Q10, a7); array[num4].Q_Q10 = num11; array[num5].Q_Q10 = a6; } int num13 = Inlines.silk_LSHIFT32(array[num4].Q_Q10, 4); if (nSQ_del_dec_struct.Seed < 0) { num13 = -num13; } int num14 = Inlines.silk_ADD32(num13, a); int num15 = Inlines.silk_ADD32(num14, a3); int num16 = Inlines.silk_SUB32(num15, a4); array[num4].sLTP_shp_Q14 = Inlines.silk_SUB32(num16, a5); array[num4].LF_AR_Q14 = num16; array[num4].LPC_exc_Q14 = num14; array[num4].xq_Q14 = num15; num13 = Inlines.silk_LSHIFT32(array[num5].Q_Q10, 4); if (nSQ_del_dec_struct.Seed < 0) { num13 = -num13; } num14 = Inlines.silk_ADD32(num13, a); num15 = Inlines.silk_ADD32(num14, a3); num16 = Inlines.silk_SUB32(num15, a4); array[num5].sLTP_shp_Q14 = Inlines.silk_SUB32(num16, a5); array[num5].LF_AR_Q14 = num16; array[num5].LPC_exc_Q14 = num14; array[num5].xq_Q14 = num15; } smpl_buf_idx.Val = (smpl_buf_idx.Val - 1) & 0x1F; int num17 = (smpl_buf_idx.Val + decisionDelay) & 0x1F; int rD_Q = array[0].RD_Q10; int num18 = 0; for (int k = 1; k < nStatesDelayedDecision; k++) { if (array[k * 2].RD_Q10 < rD_Q) { rD_Q = array[k * 2].RD_Q10; num18 = k; } } int num19 = psDelDec[num18].RandState[num17]; for (int k = 0; k < nStatesDelayedDecision; k++) { if (psDelDec[k].RandState[num17] != num19) { int num20 = k * 2; array[num20].RD_Q10 = Inlines.silk_ADD32(array[num20].RD_Q10, 134217727); array[num20 + 1].RD_Q10 = Inlines.silk_ADD32(array[num20 + 1].RD_Q10, 134217727); } } int rD_Q2 = array[0].RD_Q10; rD_Q = array[1].RD_Q10; int num21 = 0; int num22 = 0; for (int k = 1; k < nStatesDelayedDecision; k++) { int num20 = k * 2; if (array[num20].RD_Q10 > rD_Q2) { rD_Q2 = array[num20].RD_Q10; num21 = k; } if (array[num20 + 1].RD_Q10 < rD_Q) { rD_Q = array[num20 + 1].RD_Q10; num22 = k; } } if (rD_Q < rD_Q2) { psDelDec[num21].PartialCopyFrom(psDelDec[num22], j); ref NSQ_sample_struct reference = ref array[num21 * 2]; reference = array[num22 * 2 + 1]; } nSQ_del_dec_struct = psDelDec[num18]; if (subfr > 0 || j >= decisionDelay) { pulses[pulses_ptr + j - decisionDelay] = (sbyte)Inlines.silk_RSHIFT_ROUND(nSQ_del_dec_struct.Q_Q10[num17], 10); xq[xq_ptr + j - decisionDelay] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(nSQ_del_dec_struct.Xq_Q14[num17], delayedGain_Q10[num17]), 8)); sLTP_shp_Q14[sLTP_shp_buf_idx - decisionDelay] = nSQ_del_dec_struct.Shape_Q14[num17]; sLTP_Q15[sLTP_buf_idx - decisionDelay] = nSQ_del_dec_struct.Pred_Q15[num17]; } sLTP_shp_buf_idx++; sLTP_buf_idx++; for (int k = 0; k < nStatesDelayedDecision; k++) { nSQ_del_dec_struct = psDelDec[k]; int num4 = k * 2; nSQ_del_dec_struct.LF_AR_Q14 = array[num4].LF_AR_Q14; nSQ_del_dec_struct.sLPC_Q14[SilkConstants.NSQ_LPC_BUF_LENGTH + j] = array[num4].xq_Q14; nSQ_del_dec_struct.Xq_Q14[smpl_buf_idx.Val] = array[num4].xq_Q14; nSQ_del_dec_struct.Q_Q10[smpl_buf_idx.Val] = array[num4].Q_Q10; nSQ_del_dec_struct.Pred_Q15[smpl_buf_idx.Val] = Inlines.silk_LSHIFT32(array[num4].LPC_exc_Q14, 1); nSQ_del_dec_struct.Shape_Q14[smpl_buf_idx.Val] = array[num4].sLTP_shp_Q14; nSQ_del_dec_struct.Seed = Inlines.silk_ADD32_ovflw(nSQ_del_dec_struct.Seed, Inlines.silk_RSHIFT_ROUND(array[num4].Q_Q10, 10)); nSQ_del_dec_struct.RandState[smpl_buf_idx.Val] = nSQ_del_dec_struct.Seed; nSQ_del_dec_struct.RD_Q10 = array[num4].RD_Q10; } delayedGain_Q10[smpl_buf_idx.Val] = num3; } for (int k = 0; k < nStatesDelayedDecision; k++) { NSQ_del_dec_struct nSQ_del_dec_struct = psDelDec[k]; Buffer.BlockCopy(nSQ_del_dec_struct.sLPC_Q14, length * 4, nSQ_del_dec_struct.sLPC_Q14, 0, SilkConstants.NSQ_LPC_BUF_LENGTH * 4); } } private void silk_nsq_del_dec_scale_states(SilkChannelEncoder psEncC, NSQ_del_dec_struct[] psDelDec, int[] x_Q3, int x_Q3_ptr, int[] x_sc_Q10, short[] sLTP, int[] sLTP_Q15, int subfr, int nStatesDelayedDecision, int LTP_scale_Q14, int[] Gains_Q16, int[] pitchL, int signal_type, int decisionDelay) { int num = pitchL[subfr]; int num2 = Inlines.silk_INVERSE32_varQ(Inlines.silk_max(Gains_Q16[subfr], 1), 47); int num3 = ((Gains_Q16[subfr] == prev_gain_Q16) ? 65536 : Inlines.silk_DIV32_varQ(prev_gain_Q16, Gains_Q16[subfr], 16)); int b = Inlines.silk_RSHIFT_ROUND(num2, 8); for (int i = 0; i < psEncC.subfr_length; i++) { x_sc_Q10[i] = Inlines.silk_SMULWW(x_Q3[x_Q3_ptr + i], b); } prev_gain_Q16 = Gains_Q16[subfr]; if (rewhite_flag != 0) { if (subfr == 0) { num2 = Inlines.silk_LSHIFT(Inlines.silk_SMULWB(num2, LTP_scale_Q14), 2); } for (int i = sLTP_buf_idx - num - 2; i < sLTP_buf_idx; i++) { sLTP_Q15[i] = Inlines.silk_SMULWB(num2, sLTP[i]); } } if (num3 == 65536) { return; } for (int i = sLTP_shp_buf_idx - psEncC.ltp_mem_length; i < sLTP_shp_buf_idx; i++) { sLTP_shp_Q14[i] = Inlines.silk_SMULWW(num3, sLTP_shp_Q14[i]); } if (signal_type == 2 && rewhite_flag == 0) { for (int i = sLTP_buf_idx - num - 2; i < sLTP_buf_idx - decisionDelay; i++) { sLTP_Q15[i] = Inlines.silk_SMULWW(num3, sLTP_Q15[i]); } } for (int j = 0; j < nStatesDelayedDecision; j++) { NSQ_del_dec_struct nSQ_del_dec_struct = psDelDec[j]; nSQ_del_dec_struct.LF_AR_Q14 = Inlines.silk_SMULWW(num3, nSQ_del_dec_struct.LF_AR_Q14); for (int i = 0; i < SilkConstants.NSQ_LPC_BUF_LENGTH; i++) { nSQ_del_dec_struct.sLPC_Q14[i] = Inlines.silk_SMULWW(num3, nSQ_del_dec_struct.sLPC_Q14[i]); } for (int i = 0; i < psEncC.shapingLPCOrder; i++) { nSQ_del_dec_struct.sAR2_Q14[i] = Inlines.silk_SMULWW(num3, nSQ_del_dec_struct.sAR2_Q14[i]); } for (int i = 0; i < 32; i++) { nSQ_del_dec_struct.Pred_Q15[i] = Inlines.silk_SMULWW(num3, nSQ_del_dec_struct.Pred_Q15[i]); nSQ_del_dec_struct.Shape_Q14[i] = Inlines.silk_SMULWW(num3, nSQ_del_dec_struct.Shape_Q14[i]); } } } } internal class SilkPrefilterState { internal readonly short[] sLTP_shp = new short[512]; internal readonly int[] sAR_shp = new int[17]; internal int sLTP_shp_buf_idx = 0; internal int sLF_AR_shp_Q12 = 0; internal int sLF_MA_shp_Q12 = 0; internal int sHarmHP_Q2 = 0; internal int rand_seed = 0; internal int lagPrev = 0; internal SilkPrefilterState() { } internal void Reset() { Arrays.MemSet(sLTP_shp, (short)0, 512); Arrays.MemSet(sAR_shp, 0, 17); sLTP_shp_buf_idx = 0; sLF_AR_shp_Q12 = 0; sLF_MA_shp_Q12 = 0; sHarmHP_Q2 = 0; rand_seed = 0; lagPrev = 0; } } internal class SilkResamplerState { internal readonly int[] sIIR = new int[6]; internal readonly int[] sFIR_i32 = new int[36]; internal readonly short[] sFIR_i16 = new short[36]; internal readonly short[] delayBuf = new short[48]; internal int resampler_function = 0; internal int batchSize = 0; internal int invRatio_Q16 = 0; internal int FIR_Order = 0; internal int FIR_Fracs = 0; internal int Fs_in_kHz = 0; internal int Fs_out_kHz = 0; internal int inputDelay = 0; internal short[] Coefs = null; internal void Reset() { Arrays.MemSet(sIIR, 0, 6); Arrays.MemSet(sFIR_i32, 0, 36); Arrays.MemSet(sFIR_i16, (short)0, 36); Arrays.MemSet(delayBuf, (short)0, 48); resampler_function = 0; batchSize = 0; invRatio_Q16 = 0; FIR_Order = 0; FIR_Fracs = 0; Fs_in_kHz = 0; Fs_out_kHz = 0; inputDelay = 0; Coefs = null; } internal void Assign(SilkResamplerState other) { resampler_function = other.resampler_function; batchSize = other.batchSize; invRatio_Q16 = other.invRatio_Q16; FIR_Order = other.FIR_Order; FIR_Fracs = other.FIR_Fracs; Fs_in_kHz = other.Fs_in_kHz; Fs_out_kHz = other.Fs_out_kHz; inputDelay = other.inputDelay; Coefs = other.Coefs; Array.Copy(other.sIIR, sIIR, 6); Array.Copy(other.sFIR_i32, sFIR_i32, 36); Array.Copy(other.sFIR_i16, sFIR_i16, 36); Array.Copy(other.delayBuf, delayBuf, 48); } } internal class SilkShapeState { internal sbyte LastGainIndex = 0; internal int HarmBoost_smth_Q16 = 0; internal int HarmShapeGain_smth_Q16 = 0; internal int Tilt_smth_Q16 = 0; internal void Reset() { LastGainIndex = 0; HarmBoost_smth_Q16 = 0; HarmShapeGain_smth_Q16 = 0; Tilt_smth_Q16 = 0; } } internal class SilkVADState { internal readonly int[] AnaState = new int[2]; internal readonly int[] AnaState1 = new int[2]; internal readonly int[] AnaState2 = new int[2]; internal readonly int[] XnrgSubfr = new int[4]; internal readonly int[] NrgRatioSmth_Q8 = new int[4]; internal short HPstate = 0; internal readonly int[] NL = new int[4]; internal readonly int[] inv_NL = new int[4]; internal readonly int[] NoiseLevelBias = new int[4]; internal int counter = 0; internal void Reset() { Arrays.MemSet(AnaState, 0, 2); Arrays.MemSet(AnaState1, 0, 2); Arrays.MemSet(AnaState2, 0, 2); Arrays.MemSet(XnrgSubfr, 0, 4); Arrays.MemSet(NrgRatioSmth_Q8, 0, 4); HPstate = 0; Arrays.MemSet(NL, 0, 4); Arrays.MemSet(inv_NL, 0, 4); Arrays.MemSet(NoiseLevelBias, 0, 4); counter = 0; } } internal class StereoDecodeState { internal readonly short[] pred_prev_Q13 = new short[2]; internal readonly short[] sMid = new short[2]; internal readonly short[] sSide = new short[2]; internal void Reset() { Arrays.MemSet(pred_prev_Q13, (short)0, 2); Arrays.MemSet(sMid, (short)0, 2); Arrays.MemSet(sSide, (short)0, 2); } } internal class StereoEncodeState { internal readonly short[] pred_prev_Q13 = new short[2]; internal readonly short[] sMid = new short[2]; internal readonly short[] sSide = new short[2]; internal readonly int[] mid_side_amp_Q0 = new int[4]; internal short smth_width_Q14 = 0; internal short width_prev_Q14 = 0; internal short silent_side_len = 0; internal readonly sbyte[][][] predIx = Arrays.InitThreeDimensionalArray(3, 2, 3); internal readonly sbyte[] mid_only_flags = new sbyte[3]; internal void Reset() { Arrays.MemSet(pred_prev_Q13, (short)0, 2); Arrays.MemSet(sMid, (short)0, 2); Arrays.MemSet(sSide, (short)0, 2); Arrays.MemSet(mid_side_amp_Q0, 0, 4); smth_width_Q14 = 0; width_prev_Q14 = 0; silent_side_len = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { Arrays.MemSet(predIx[i][j], (sbyte)0, 3); } } Arrays.MemSet(mid_only_flags, (sbyte)0, 3); } } internal class TOCStruct { internal int VADFlag = 0; internal readonly int[] VADFlags = new int[3]; internal int inbandFECFlag = 0; internal void Reset() { VADFlag = 0; Arrays.MemSet(VADFlags, 0, 3); inbandFECFlag = 0; } } }