diff --git a/src/Discord.Net.Core/Audio/IAudioClient.cs b/src/Discord.Net.Core/Audio/IAudioClient.cs index 7373a8e4d..9be8ceef5 100644 --- a/src/Discord.Net.Core/Audio/IAudioClient.cs +++ b/src/Discord.Net.Core/Audio/IAudioClient.cs @@ -28,8 +28,8 @@ namespace Discord.Audio /// Creates a new outgoing stream accepting Opus-encoded data. This is a direct stream with no internal timer. AudioOutStream CreateDirectOpusStream(); /// Creates a new outgoing stream accepting PCM (raw) data. - AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate = null, int bufferMillis = 1000); + AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate = null, int bufferMillis = 1000, int packetLoss = 30); /// Creates a new direct outgoing stream accepting PCM (raw) data. This is a direct stream with no internal timer. - AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate = null); + AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate = null, int packetLoss = 30); } } diff --git a/src/Discord.Net.WebSocket/Audio/AudioClient.cs b/src/Discord.Net.WebSocket/Audio/AudioClient.cs index 0ca45a557..1f33b3cc5 100644 --- a/src/Discord.Net.WebSocket/Audio/AudioClient.cs +++ b/src/Discord.Net.WebSocket/Audio/AudioClient.cs @@ -153,20 +153,20 @@ namespace Discord.Audio var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header return new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header (external input), passes } - public AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate, int bufferMillis) + public AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate, int bufferMillis, int packetLoss) { var outputStream = new OutputStream(ApiClient); //Ignores header var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header var rtpWriter = new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header, passes var bufferedStream = new BufferedWriteStream(rtpWriter, this, bufferMillis, _connection.CancelToken, _audioLogger); //Ignores header, generates header - return new OpusEncodeStream(bufferedStream, bitrate ?? (96 * 1024), application); //Generates header + return new OpusEncodeStream(bufferedStream, bitrate ?? (96 * 1024), application, packetLoss); //Generates header } - public AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate) + public AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate, int packetLoss) { var outputStream = new OutputStream(ApiClient); //Ignores header var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header var rtpWriter = new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header, passes - return new OpusEncodeStream(rtpWriter, bitrate ?? (96 * 1024), application); //Generates header + return new OpusEncodeStream(rtpWriter, bitrate ?? (96 * 1024), application, packetLoss); //Generates header } internal async Task CreateInputStreamAsync(ulong userId) diff --git a/src/Discord.Net.WebSocket/Audio/Opus/OpusEncoder.cs b/src/Discord.Net.WebSocket/Audio/Opus/OpusEncoder.cs index a12854d69..1ff5a5d9a 100644 --- a/src/Discord.Net.WebSocket/Audio/Opus/OpusEncoder.cs +++ b/src/Discord.Net.WebSocket/Audio/Opus/OpusEncoder.cs @@ -17,7 +17,7 @@ namespace Discord.Audio public AudioApplication Application { get; } public int BitRate { get;} - public OpusEncoder(int bitrate, AudioApplication application) + public OpusEncoder(int bitrate, AudioApplication application, int packetLoss) { if (bitrate < 1 || bitrate > DiscordVoiceAPIClient.MaxBitrate) throw new ArgumentOutOfRangeException(nameof(bitrate)); @@ -48,7 +48,7 @@ namespace Discord.Audio _ptr = CreateEncoder(SamplingRate, Channels, (int)opusApplication, out var error); CheckError(error); CheckError(EncoderCtl(_ptr, OpusCtl.SetSignal, (int)opusSignal)); - CheckError(EncoderCtl(_ptr, OpusCtl.SetPacketLossPercent, 30)); //% + CheckError(EncoderCtl(_ptr, OpusCtl.SetPacketLossPercent, packetLoss)); //% CheckError(EncoderCtl(_ptr, OpusCtl.SetInbandFEC, 1)); //True CheckError(EncoderCtl(_ptr, OpusCtl.SetBitrate, bitrate)); } diff --git a/src/Discord.Net.WebSocket/Audio/Streams/OpusEncodeStream.cs b/src/Discord.Net.WebSocket/Audio/Streams/OpusEncodeStream.cs index a7779a84c..f5883ad4b 100644 --- a/src/Discord.Net.WebSocket/Audio/Streams/OpusEncodeStream.cs +++ b/src/Discord.Net.WebSocket/Audio/Streams/OpusEncodeStream.cs @@ -8,18 +8,18 @@ namespace Discord.Audio.Streams public class OpusEncodeStream : AudioOutStream { public const int SampleRate = 48000; - + private readonly AudioStream _next; private readonly OpusEncoder _encoder; private readonly byte[] _buffer; private int _partialFramePos; private ushort _seq; private uint _timestamp; - - public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application) + + public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application, int packetLoss) { _next = next; - _encoder = new OpusEncoder(bitrate, application); + _encoder = new OpusEncoder(bitrate, application, packetLoss); _buffer = new byte[OpusConverter.FrameBytes]; } @@ -38,7 +38,7 @@ namespace Discord.Audio.Streams offset += OpusConverter.FrameBytes; count -= OpusConverter.FrameBytes; _seq++; - _timestamp += OpusConverter.FrameBytes; + _timestamp += OpusConverter.FrameSamplesPerChannel; } else if (_partialFramePos + count >= OpusConverter.FrameBytes) { @@ -53,7 +53,7 @@ namespace Discord.Audio.Streams count -= partialSize; _partialFramePos = 0; _seq++; - _timestamp += OpusConverter.FrameBytes; + _timestamp += OpusConverter.FrameSamplesPerChannel; } else {