private void SendAudioData(OpusEncoder encoder, ref byte[] audio, int offset, ushort seq, uint timestamp) { byte[] packet = new byte[OpusEncoder.FrameBytes + 12]; byte[] header = new byte[12]; header[0] = 0x80; header[1] = 0x78; header[2] = (byte)(seq >> 8); header[3] = (byte)(seq >> 0); header[4] = (byte)(timestamp >> 24); header[5] = (byte)(timestamp >> 16); header[6] = (byte)(timestamp >> 8); header[7] = (byte)(timestamp >> 0); header[8] = (byte)(_ssrc >> 24); header[9] = (byte)(_ssrc >> 16); header[10] = (byte)(_ssrc >> 8); header[11] = (byte)(_ssrc >> 0); Buffer.BlockCopy(header, 0, packet, 0, 12); int frameSize = encoder.EncodeFrame(audio, offset, packet, 12); int encSize = Sodium.Encrypt(packet, 12, frameSize, packet, 12, header, _secretKey); _udpClient.Send(packet, encSize + 12); }
public bool Speak(byte[] audio, uint bitrate, AudioApplication usedFor = AudioApplication.Mixed) { while (Speaking) { Thread.Sleep(1); } Speaking = true; var encoder = new OpusEncoder((int)bitrate, usedFor, 0); int offset = 0; long nextTick = Environment.TickCount; try { while (offset + OpusEncoder.FrameBytes < audio.Length && !_stopCurrent) { SetSpeaking(true); long dist = nextTick - Environment.TickCount; if (dist <= 0) { SendAudioData(encoder, ref audio, offset, _sequence, _timestamp); nextTick += OpusEncoder.TimeBetweenFrames; offset += OpusEncoder.FrameBytes; _sequence++; _timestamp += OpusEncoder.FrameSamplesPerChannel; } else { Thread.Sleep((int)dist); } } SetSpeaking(false); _stopCurrent = false; Speaking = false; return(true); } catch { Speaking = false; return(false); } }
internal DiscordVoiceStream(DiscordVoiceSession client, int bitrate, AudioApplication application = AudioApplication.Mixed) { _session = client; _encoder = new OpusEncoder(bitrate, application, 0); _nextTick = -1; }