Discord.Net.WebSockets.VoiceSocket.SendVoiceAsync C# (CSharp) Method

SendVoiceAsync() private method

private SendVoiceAsync ( CancellationToken cancelToken ) : Task
cancelToken System.Threading.CancellationToken
return Task
        private async Task SendVoiceAsync(CancellationToken cancelToken)
        {
            try
            {
                while (!cancelToken.IsCancellationRequested && State != ConnectionState.Connected)
                    await Task.Delay(1).ConfigureAwait(false);

                if (cancelToken.IsCancellationRequested)
                    return;

                byte[] frame = new byte[_encoder.FrameSize];
                byte[] encodedFrame = new byte[MaxOpusSize];
                byte[] voicePacket, pingPacket, nonce = null;
                uint timestamp = 0;
                double nextTicks = 0.0, nextPingTicks = 0.0;
                long ticksPerSeconds = Stopwatch.Frequency;
                double ticksPerMillisecond = Stopwatch.Frequency / 1000.0;
                double ticksPerFrame = ticksPerMillisecond * _encoder.FrameLength;
                double spinLockThreshold = 3 * ticksPerMillisecond;
                uint samplesPerFrame = (uint)_encoder.SamplesPerFrame;
                Stopwatch sw = Stopwatch.StartNew();

                if (_isEncrypted)
                {
                    nonce = new byte[24];
                    voicePacket = new byte[MaxOpusSize + 12 + 16];
                }
                else
                    voicePacket = new byte[MaxOpusSize + 12];

                pingPacket = new byte[8];

                int rtpPacketLength = 0;
                voicePacket[0] = 0x80; //Flags;
                voicePacket[1] = 0x78; //Payload Type
                voicePacket[8] = (byte)(_ssrc >> 24);
                voicePacket[9] = (byte)(_ssrc >> 16);
                voicePacket[10] = (byte)(_ssrc >> 8);
                voicePacket[11] = (byte)(_ssrc >> 0);

                if (_isEncrypted)
                    Buffer.BlockCopy(voicePacket, 0, nonce, 0, 12);

                bool hasFrame = false;
                while (!cancelToken.IsCancellationRequested)
                {
                    if (!hasFrame && _sendBuffer.Pop(frame))
                    {
                        ushort sequence = unchecked(_sequence++);
                        voicePacket[2] = (byte)(sequence >> 8);
                        voicePacket[3] = (byte)(sequence >> 0);
                        voicePacket[4] = (byte)(timestamp >> 24);
                        voicePacket[5] = (byte)(timestamp >> 16);
                        voicePacket[6] = (byte)(timestamp >> 8);
                        voicePacket[7] = (byte)(timestamp >> 0);

                        //Encode
                        int encodedLength = _encoder.EncodeFrame(frame, 0, encodedFrame);

                        //Encrypt
                        if (_isEncrypted)
                        {
                            Buffer.BlockCopy(voicePacket, 2, nonce, 2, 6); //Update nonce
                            int ret = SecretBox.Encrypt(encodedFrame, encodedLength, voicePacket, 12, nonce, _secretKey);
                            if (ret != 0)
                                continue;
                            rtpPacketLength = encodedLength + 12 + 16;
                        }
                        else
                        {
                            Buffer.BlockCopy(encodedFrame, 0, voicePacket, 12, encodedLength);
                            rtpPacketLength = encodedLength + 12;
                        }

                        timestamp = unchecked(timestamp + samplesPerFrame);
                        hasFrame = true;
                    }

                    long currentTicks = sw.ElapsedTicks;
                    double ticksToNextFrame = nextTicks - currentTicks;
                    if (ticksToNextFrame <= 0.0)
                    {
                        if (hasFrame)
                        {
                            try
                            {
                                await _udp.SendAsync(voicePacket, rtpPacketLength, _endpoint).ConfigureAwait(false);
                            }
                            catch (SocketException ex)
                            {
                                Logger.Error("Failed to send UDP packet.", ex);
                            }
                            hasFrame = false;
                        }
                        nextTicks += ticksPerFrame;

                        //Is it time to send out another ping?
                        if (currentTicks > nextPingTicks)
                        {
                            //Increment in LE
                            for (int i = 0; i < 8; i++)
                            {
                                var b = pingPacket[i];
                                if (b == byte.MaxValue)
                                    pingPacket[i] = 0;
                                else
                                {
                                    pingPacket[i] = (byte)(b + 1);
                                    break;
                                }
                            }
                            await _udp.SendAsync(pingPacket, pingPacket.Length, _endpoint).ConfigureAwait(false);
                            nextPingTicks = currentTicks + 5 * ticksPerSeconds;
                        }
                    }
                    else
                    {
                        if (hasFrame)
                        {
                            int time = (int)Math.Floor(ticksToNextFrame / ticksPerMillisecond);
                            if (time > 0)
                                await Task.Delay(time).ConfigureAwait(false);
                        }
                        else
                            await Task.Delay(1).ConfigureAwait(false); //Give as much time to the encrypter as possible
                    }
                }
            }
            catch (OperationCanceledException) { }
            catch (InvalidOperationException) { } //Includes ObjectDisposedException
        }
#if !NETSTANDARD1_3