diff --git a/src/Discord.Net/Audio/OpusEncoder.cs b/src/Discord.Net/Audio/OpusEncoder.cs
index c5e033a2b..fbb6a0729 100644
--- a/src/Discord.Net/Audio/OpusEncoder.cs
+++ b/src/Discord.Net/Audio/OpusEncoder.cs
@@ -8,7 +8,7 @@ namespace Discord.Audio
private readonly IntPtr _ptr;
/// Gets the bit rate of the encoder.
- public const int BitRate = 16;
+ public const int BitsPerSample = 16;
/// Gets the input sampling rate of the encoder.
public int InputSamplingRate { get; private set; }
/// Gets the number of channels of the encoder.
@@ -21,6 +21,8 @@ namespace Discord.Audio
public int SampleSize { get; private set; }
/// Gets the bytes per frame.
public int FrameSize { get; private set; }
+ /// Gets the bit rate in kbit/s.
+ public int? BitRate { get; private set; }
/// Gets the coding mode of the encoder.
public Opus.Application Application { get; private set; }
@@ -28,9 +30,10 @@ namespace Discord.Audio
/// Sampling rate of the input signal (Hz). Supported Values: 8000, 12000, 16000, 24000, or 48000.
/// Number of channels (1 or 2) in input signal.
/// Length, in milliseconds, that each frame takes. Supported Values: 2.5, 5, 10, 20, 40, 60
+ /// Bitrate (kbit/s) used for this encoder. Supported Values: 1-512. Null will use the recommended bitrate.
/// Coding mode.
/// A new OpusEncoder
- public OpusEncoder(int samplingRate, int channels, int frameLength, Opus.Application application)
+ public OpusEncoder(int samplingRate, int channels, int frameLength, int? bitrate, Opus.Application application)
{
if (samplingRate != 8000 && samplingRate != 12000 &&
samplingRate != 16000 && samplingRate != 24000 &&
@@ -38,14 +41,17 @@ namespace Discord.Audio
throw new ArgumentOutOfRangeException(nameof(samplingRate));
if (channels != 1 && channels != 2)
throw new ArgumentOutOfRangeException(nameof(channels));
+ if (bitrate != null && (bitrate < 1 || bitrate > 512))
+ throw new ArgumentOutOfRangeException(nameof(bitrate));
InputSamplingRate = samplingRate;
InputChannels = channels;
Application = application;
FrameLength = frameLength;
- SampleSize = (BitRate / 8) * channels;
+ SampleSize = (BitsPerSample / 8) * channels;
SamplesPerFrame = samplingRate / 1000 * FrameLength;
FrameSize = SamplesPerFrame * SampleSize;
+ BitRate = bitrate;
Opus.Error error;
_ptr = Opus.CreateEncoder(samplingRate, channels, (int)application, out error);
@@ -53,6 +59,8 @@ namespace Discord.Audio
throw new InvalidOperationException($"Error occured while creating encoder: {error}");
SetForwardErrorCorrection(true);
+ if (bitrate != null)
+ SetBitrate(bitrate.Value);
}
/// Produces Opus encoded audio from PCM samples.
@@ -85,6 +93,17 @@ namespace Discord.Audio
throw new Exception("Encoder error: " + ((Opus.Error)result).ToString());
}
+ /// Gets or sets whether Forward Error Correction is enabled.
+ public void SetBitrate(int value)
+ {
+ if (disposed)
+ throw new ObjectDisposedException(nameof(OpusEncoder));
+
+ var result = Opus.EncoderCtl(_ptr, Opus.Ctl.SetBitrateRequest, value * 1000);
+ if (result < 0)
+ throw new Exception("Encoder error: " + ((Opus.Error)result).ToString());
+ }
+
#region IDisposable
private bool disposed;
public void Dispose()
diff --git a/src/Discord.Net/DiscordWSClientConfig.cs b/src/Discord.Net/DiscordWSClientConfig.cs
index 5e8a59d0b..64c092d9c 100644
--- a/src/Discord.Net/DiscordWSClientConfig.cs
+++ b/src/Discord.Net/DiscordWSClientConfig.cs
@@ -30,6 +30,9 @@ namespace Discord
/// Gets or sets the max buffer length (in milliseconds) for outgoing voice packets. This value is the target maximum but is not guaranteed, the buffer will often go slightly above this value.
public int VoiceBufferLength { get { return _voiceBufferLength; } set { SetValue(ref _voiceBufferLength, value); } }
private int _voiceBufferLength = 1000;
+ /// Gets or sets the bitrate used (in kbit/s, between 1 and 512 inclusively) for outgoing voice packets. A null value will use default Opus settings.
+ public int? VoiceBitrate { get { return _voiceBitrate; } set { SetValue(ref _voiceBitrate, value); } }
+ private int? _voiceBitrate = null;
//Experimental Features
/// (Experimental) Enables the voice websocket and UDP client and specifies how it will be used. Any option other than Disabled requires the opus .dll or .so be in the local lib/ folder.
diff --git a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs
index 4402c4d03..fa416d038 100644
--- a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs
+++ b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs
@@ -53,7 +53,7 @@ namespace Discord.Net.WebSockets
_targetAudioBufferLength = client.Config.VoiceBufferLength / 20; //20 ms frames
_encodingBuffer = new byte[MaxOpusSize];
_ssrcMapping = new ConcurrentDictionary();
- _encoder = new OpusEncoder(48000, 1, 20, Opus.Application.Audio);
+ _encoder = new OpusEncoder(48000, 1, 20, client.Config.VoiceBitrate, Opus.Application.Audio);
_sendBuffer = new VoiceBuffer((int)Math.Ceiling(client.Config.VoiceBufferLength / (double)_encoder.FrameLength), _encoder.FrameSize);
}