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
{