internal void PreparePacket(ReadOnlySpan <byte> pcm, ref Memory <byte> target) { var audioFormat = AudioFormat; var packetArray = ArrayPool <byte> .Shared.Rent(Rtp.CalculatePacketSize(audioFormat.SampleCountToSampleSize(audioFormat.CalculateMaximumFrameSize()), SelectedEncryptionMode)); var packet = packetArray.AsSpan(); Rtp.EncodeHeader(Sequence, Timestamp, SSRC, packet); var opus = packet.Slice(Rtp.HeaderSize, pcm.Length); Opus.Encode(pcm, ref opus); Sequence++; Timestamp += (uint)audioFormat.CalculateFrameSize(audioFormat.CalculateSampleDuration(pcm.Length)); Span <byte> nonce = new byte[Sodium.NonceSize]; switch (SelectedEncryptionMode) { case EncryptionMode.XSalsa20_Poly1305: Sodium.GenerateNonce(packet.Slice(0, Rtp.HeaderSize), nonce); break; case EncryptionMode.XSalsa20_Poly1305_Suffix: Sodium.GenerateNonce(nonce); break; case EncryptionMode.XSalsa20_Poly1305_Lite: Sodium.GenerateNonce(Nonce++, nonce); break; default: ArrayPool <byte> .Shared.Return(packetArray); throw new Exception("Unsupported encryption mode."); } Span <byte> encrypted = new byte[Sodium.CalculateTargetSize(opus)]; Sodium.Encrypt(opus, encrypted, nonce); encrypted.CopyTo(packet.Slice(Rtp.HeaderSize)); packet = packet.Slice(0, Rtp.CalculatePacketSize(encrypted.Length, SelectedEncryptionMode)); Sodium.AppendNonce(nonce, packet, SelectedEncryptionMode); target = target.Slice(0, packet.Length); packet.CopyTo(target.Span); ArrayPool <byte> .Shared.Return(packetArray); }