Browse Source

Add packetLoss argument for PCM streams, change FrameBytes to FrameSamplesPerChannel in OpusEncodeStream (#677)

tags/1.0
Amir Zaidi RogueException 8 years ago
parent
commit
d088d7b05c
4 changed files with 14 additions and 14 deletions
  1. +2
    -2
      src/Discord.Net.Core/Audio/IAudioClient.cs
  2. +4
    -4
      src/Discord.Net.WebSocket/Audio/AudioClient.cs
  3. +2
    -2
      src/Discord.Net.WebSocket/Audio/Opus/OpusEncoder.cs
  4. +6
    -6
      src/Discord.Net.WebSocket/Audio/Streams/OpusEncodeStream.cs

+ 2
- 2
src/Discord.Net.Core/Audio/IAudioClient.cs View File

@@ -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);
} }
} }

+ 4
- 4
src/Discord.Net.WebSocket/Audio/AudioClient.cs View File

@@ -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)


+ 2
- 2
src/Discord.Net.WebSocket/Audio/Opus/OpusEncoder.cs View File

@@ -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));
} }


+ 6
- 6
src/Discord.Net.WebSocket/Audio/Streams/OpusEncodeStream.cs View File

@@ -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
{ {


Loading…
Cancel
Save