Add packetLoss argument for PCM streams, change FrameBytes to FrameSamplesPerChannel in OpusEncodeStream (#677)
This commit is contained in:
committed by
RogueException
parent
256af0b269
commit
d088d7b05c
@@ -28,8 +28,8 @@ namespace Discord.Audio
|
|||||||
/// <summary>Creates a new outgoing stream accepting Opus-encoded data. This is a direct stream with no internal timer.</summary>
|
/// <summary>Creates a new outgoing stream accepting Opus-encoded data. This is a direct stream with no internal timer.</summary>
|
||||||
AudioOutStream CreateDirectOpusStream();
|
AudioOutStream CreateDirectOpusStream();
|
||||||
/// <summary>Creates a new outgoing stream accepting PCM (raw) data.</summary>
|
/// <summary>Creates a new outgoing stream accepting PCM (raw) data.</summary>
|
||||||
AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate = null, int bufferMillis = 1000);
|
AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate = null, int bufferMillis = 1000, int packetLoss = 30);
|
||||||
/// <summary>Creates a new direct outgoing stream accepting PCM (raw) data. This is a direct stream with no internal timer.</summary>
|
/// <summary>Creates a new direct outgoing stream accepting PCM (raw) data. This is a direct stream with no internal timer.</summary>
|
||||||
AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate = null);
|
AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate = null, int packetLoss = 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,20 +153,20 @@ namespace Discord.Audio
|
|||||||
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
||||||
return new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header (external input), passes
|
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 outputStream = new OutputStream(ApiClient); //Ignores header
|
||||||
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
||||||
var rtpWriter = new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header, passes
|
var rtpWriter = new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header, passes
|
||||||
var bufferedStream = new BufferedWriteStream(rtpWriter, this, bufferMillis, _connection.CancelToken, _audioLogger); //Ignores header, generates header
|
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 outputStream = new OutputStream(ApiClient); //Ignores header
|
||||||
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
var sodiumEncrypter = new SodiumEncryptStream(outputStream, this); //Passes header
|
||||||
var rtpWriter = new RTPWriteStream(sodiumEncrypter, _ssrc); //Consumes header, passes
|
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)
|
internal async Task CreateInputStreamAsync(ulong userId)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Discord.Audio
|
|||||||
public AudioApplication Application { get; }
|
public AudioApplication Application { get; }
|
||||||
public int BitRate { 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)
|
if (bitrate < 1 || bitrate > DiscordVoiceAPIClient.MaxBitrate)
|
||||||
throw new ArgumentOutOfRangeException(nameof(bitrate));
|
throw new ArgumentOutOfRangeException(nameof(bitrate));
|
||||||
@@ -48,7 +48,7 @@ namespace Discord.Audio
|
|||||||
_ptr = CreateEncoder(SamplingRate, Channels, (int)opusApplication, out var error);
|
_ptr = CreateEncoder(SamplingRate, Channels, (int)opusApplication, out var error);
|
||||||
CheckError(error);
|
CheckError(error);
|
||||||
CheckError(EncoderCtl(_ptr, OpusCtl.SetSignal, (int)opusSignal));
|
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.SetInbandFEC, 1)); //True
|
||||||
CheckError(EncoderCtl(_ptr, OpusCtl.SetBitrate, bitrate));
|
CheckError(EncoderCtl(_ptr, OpusCtl.SetBitrate, bitrate));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ namespace Discord.Audio.Streams
|
|||||||
public class OpusEncodeStream : AudioOutStream
|
public class OpusEncodeStream : AudioOutStream
|
||||||
{
|
{
|
||||||
public const int SampleRate = 48000;
|
public const int SampleRate = 48000;
|
||||||
|
|
||||||
private readonly AudioStream _next;
|
private readonly AudioStream _next;
|
||||||
private readonly OpusEncoder _encoder;
|
private readonly OpusEncoder _encoder;
|
||||||
private readonly byte[] _buffer;
|
private readonly byte[] _buffer;
|
||||||
private int _partialFramePos;
|
private int _partialFramePos;
|
||||||
private ushort _seq;
|
private ushort _seq;
|
||||||
private uint _timestamp;
|
private uint _timestamp;
|
||||||
|
|
||||||
public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application)
|
public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application, int packetLoss)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_encoder = new OpusEncoder(bitrate, application);
|
_encoder = new OpusEncoder(bitrate, application, packetLoss);
|
||||||
_buffer = new byte[OpusConverter.FrameBytes];
|
_buffer = new byte[OpusConverter.FrameBytes];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ namespace Discord.Audio.Streams
|
|||||||
offset += OpusConverter.FrameBytes;
|
offset += OpusConverter.FrameBytes;
|
||||||
count -= OpusConverter.FrameBytes;
|
count -= OpusConverter.FrameBytes;
|
||||||
_seq++;
|
_seq++;
|
||||||
_timestamp += OpusConverter.FrameBytes;
|
_timestamp += OpusConverter.FrameSamplesPerChannel;
|
||||||
}
|
}
|
||||||
else if (_partialFramePos + count >= OpusConverter.FrameBytes)
|
else if (_partialFramePos + count >= OpusConverter.FrameBytes)
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ namespace Discord.Audio.Streams
|
|||||||
count -= partialSize;
|
count -= partialSize;
|
||||||
_partialFramePos = 0;
|
_partialFramePos = 0;
|
||||||
_seq++;
|
_seq++;
|
||||||
_timestamp += OpusConverter.FrameBytes;
|
_timestamp += OpusConverter.FrameSamplesPerChannel;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user