private void ReceiveVoice() { if (client.Available > 0) { byte[] packet, buffer = null, nonce = null, result; packet = client.Receive(ref endpoint); int packetLength, resultLength; buffer = new byte[4000]; nonce = new byte[24]; packetLength = packet.Length; if (packet.Length > 0) { if (packetLength < 12) { return; } if (packet[0] != 0x80) { return; } if (packet[1] != 0x78) { return; } ushort sequenceNumber = (ushort)((packet[2] << 8) | packet[3] << 0); uint timDocuestamp = (uint)((packet[4] << 24) | packet[5] << 16 | packet[6] << 8 | packet[7] << 0); uint ssrc = (uint)((packet[8] << 24) | (packet[9] << 16) | (packet[10] << 8) | (packet[11] << 0)); if (packetLength < 28) { return; } Buffer.BlockCopy(packet, 0, nonce, 0, 12); var length = Convert.ToUInt64(packetLength - 12); int returnValue = SecretBox.Decrypt(packet, length, buffer, nonce, key); if (returnValue != 0) { return; } result = buffer; resultLength = packetLength - 28; if (users.ContainsValue(ssrc)) { byte[] output = new byte[1920]; decoder.DecodeFrame(result, 0, resultLength, output); float[] outputFloat = Utils.BytesToFloats(output); parent.unityInvoker.Enqueue(() => OnVoicePacketReceived(this, new DiscordVoiceArgs() { channel = channel, client = parent, packet = output, unitypacket = outputFloat, raw = result, sender = GetUserBySsrc(ssrc) })); } } } }
private void SendVoice() { byte[] buffer = voiceToSend.Dequeue(); if (buffer != null) { System.Diagnostics.Stopwatch timeToSend = System.Diagnostics.Stopwatch.StartNew(); byte[] packet = new byte[4028]; byte[] nonce = new byte[24]; packet[0] = (byte)0x80; packet[1] = (byte)0x78; packet[8] = (byte)(ssrc >> 24); packet[9] = (byte)(ssrc >> 16); packet[10] = (byte)(ssrc >> 8); packet[11] = (byte)(ssrc >> 0); sequence = unchecked (sequence++); packet[2] = (byte)(sequence >> 8); packet[3] = (byte)(sequence >> 0); packet[4] = (byte)(timestamp >> 24); packet[5] = (byte)(timestamp >> 16); packet[6] = (byte)(timestamp >> 8); packet[7] = (byte)(timestamp >> 0); byte[] opusVoice = new byte[buffer.Length]; int encodedLength = encoder.EncodeFrame(buffer, 0, opusVoice); Buffer.BlockCopy(packet, 0, nonce, 0, 12); int returnVal = SecretBox.Encrypt(opusVoice, encodedLength, packet, nonce, key); if (returnVal != 0) { return; } if (opusVoice == null) { Debug.LogError("opusVoice"); } int dataSent = client.Send(packet, encodedLength + 28); timestamp = unchecked (timestamp + (uint)encoder.SamplesPerFrame); float[] inputFloat = Utils.BytesToFloats(buffer); parent.unityInvoker.Enqueue(() => OnVoicePacketSend(this, new DiscordVoiceArgs() { channel = channel, client = parent, packet = packet, unitypacket = inputFloat, raw = buffer, sender = parent.user })); timeToSend.Stop(); if (timeToSend.ElapsedMilliseconds > 0) { Thread.Sleep(20 - (int)timeToSend.ElapsedMilliseconds); } else { Thread.Sleep(20); } } else { byte[] empty = new byte[3] { (byte)0xF8, (byte)0xFF, (byte)0xFE }; client.Send(empty, empty.Length); } }