| @@ -136,7 +136,7 @@ namespace Discord.Audio | |||||
| var outputStream = new OutputStream(ApiClient); | var outputStream = new OutputStream(ApiClient); | ||||
| var sodiumEncrypter = new SodiumEncryptStream(outputStream, _secretKey); | var sodiumEncrypter = new SodiumEncryptStream(outputStream, _secretKey); | ||||
| var rtpWriter = new RTPWriteStream(sodiumEncrypter, samplesPerFrame, _ssrc); | var rtpWriter = new RTPWriteStream(sodiumEncrypter, samplesPerFrame, _ssrc); | ||||
| return new BufferedWriteStream(rtpWriter, samplesPerFrame, bufferMillis, _connection.CancelToken, _audioLogger); | |||||
| return new BufferedWriteStream(rtpWriter, this, samplesPerFrame, bufferMillis, _connection.CancelToken, _audioLogger); | |||||
| } | } | ||||
| public AudioOutStream CreateDirectOpusStream(int samplesPerFrame) | public AudioOutStream CreateDirectOpusStream(int samplesPerFrame) | ||||
| { | { | ||||
| @@ -151,7 +151,7 @@ namespace Discord.Audio | |||||
| var outputStream = new OutputStream(ApiClient); | var outputStream = new OutputStream(ApiClient); | ||||
| var sodiumEncrypter = new SodiumEncryptStream(outputStream, _secretKey); | var sodiumEncrypter = new SodiumEncryptStream(outputStream, _secretKey); | ||||
| var rtpWriter = new RTPWriteStream(sodiumEncrypter, samplesPerFrame, _ssrc); | var rtpWriter = new RTPWriteStream(sodiumEncrypter, samplesPerFrame, _ssrc); | ||||
| var bufferedStream = new BufferedWriteStream(rtpWriter, samplesPerFrame, bufferMillis, _connection.CancelToken, _audioLogger); | |||||
| var bufferedStream = new BufferedWriteStream(rtpWriter, this, samplesPerFrame, bufferMillis, _connection.CancelToken, _audioLogger); | |||||
| return new OpusEncodeStream(bufferedStream, channels, samplesPerFrame, bitrate ?? (96 * 1024), application); | return new OpusEncodeStream(bufferedStream, channels, samplesPerFrame, bitrate ?? (96 * 1024), application); | ||||
| } | } | ||||
| public AudioOutStream CreateDirectPCMStream(AudioApplication application, int samplesPerFrame, int channels, int? bitrate) | public AudioOutStream CreateDirectPCMStream(AudioApplication application, int samplesPerFrame, int channels, int? bitrate) | ||||
| @@ -25,6 +25,7 @@ namespace Discord.Audio.Streams | |||||
| private static readonly byte[] _silenceFrame = new byte[0]; | private static readonly byte[] _silenceFrame = new byte[0]; | ||||
| private readonly AudioClient _client; | |||||
| private readonly AudioOutStream _next; | private readonly AudioOutStream _next; | ||||
| private readonly CancellationTokenSource _cancelTokenSource; | private readonly CancellationTokenSource _cancelTokenSource; | ||||
| private readonly CancellationToken _cancelToken; | private readonly CancellationToken _cancelToken; | ||||
| @@ -37,12 +38,13 @@ namespace Discord.Audio.Streams | |||||
| private bool _isPreloaded; | private bool _isPreloaded; | ||||
| private int _silenceFrames; | private int _silenceFrames; | ||||
| public BufferedWriteStream(AudioOutStream next, int samplesPerFrame, int bufferMillis, CancellationToken cancelToken, int maxFrameSize = 1500) | |||||
| : this(next, samplesPerFrame, bufferMillis, cancelToken, null, maxFrameSize) { } | |||||
| internal BufferedWriteStream(AudioOutStream next, int samplesPerFrame, int bufferMillis, CancellationToken cancelToken, Logger logger, int maxFrameSize = 1500) | |||||
| public BufferedWriteStream(AudioOutStream next, IAudioClient client, int samplesPerFrame, int bufferMillis, CancellationToken cancelToken, int maxFrameSize = 1500) | |||||
| : this(next, client as AudioClient, samplesPerFrame, bufferMillis, cancelToken, null, maxFrameSize) { } | |||||
| internal BufferedWriteStream(AudioOutStream next, AudioClient client, int samplesPerFrame, int bufferMillis, CancellationToken cancelToken, Logger logger, int maxFrameSize = 1500) | |||||
| { | { | ||||
| //maxFrameSize = 1275 was too limiting at 128kbps,2ch,60ms | //maxFrameSize = 1275 was too limiting at 128kbps,2ch,60ms | ||||
| _next = next; | _next = next; | ||||
| _client = client; | |||||
| _ticksPerFrame = samplesPerFrame / 48; | _ticksPerFrame = samplesPerFrame / 48; | ||||
| _logger = logger; | _logger = logger; | ||||
| _queueLength = (bufferMillis + (_ticksPerFrame - 1)) / _ticksPerFrame; //Round up | _queueLength = (bufferMillis + (_ticksPerFrame - 1)) / _ticksPerFrame; //Round up | ||||
| @@ -78,7 +80,7 @@ namespace Discord.Audio.Streams | |||||
| Frame frame; | Frame frame; | ||||
| if (_queuedFrames.TryDequeue(out frame)) | if (_queuedFrames.TryDequeue(out frame)) | ||||
| { | { | ||||
| await _next.SetSpeakingAsync(true).ConfigureAwait(false); | |||||
| await _client.ApiClient.SendSetSpeaking(true).ConfigureAwait(false); | |||||
| await _next.WriteAsync(frame.Buffer, 0, frame.Bytes).ConfigureAwait(false); | await _next.WriteAsync(frame.Buffer, 0, frame.Bytes).ConfigureAwait(false); | ||||
| _bufferPool.Enqueue(frame.Buffer); | _bufferPool.Enqueue(frame.Buffer); | ||||
| _queueLock.Release(); | _queueLock.Release(); | ||||
| @@ -95,7 +97,7 @@ namespace Discord.Audio.Streams | |||||
| if (_silenceFrames++ < MaxSilenceFrames) | if (_silenceFrames++ < MaxSilenceFrames) | ||||
| await _next.WriteAsync(_silenceFrame, 0, _silenceFrame.Length).ConfigureAwait(false); | await _next.WriteAsync(_silenceFrame, 0, _silenceFrame.Length).ConfigureAwait(false); | ||||
| else | else | ||||
| await _next.SetSpeakingAsync(false).ConfigureAwait(false); | |||||
| await _client.ApiClient.SendSetSpeaking(false).ConfigureAwait(false); | |||||
| nextTick += _ticksPerFrame; | nextTick += _ticksPerFrame; | ||||
| } | } | ||||
| #if DEBUG | #if DEBUG | ||||
| @@ -6,8 +6,6 @@ namespace Discord.Audio.Streams | |||||
| ///<summary> Wraps an IAudioClient, sending voice data on write. </summary> | ///<summary> Wraps an IAudioClient, sending voice data on write. </summary> | ||||
| public class OutputStream : AudioOutStream | public class OutputStream : AudioOutStream | ||||
| { | { | ||||
| private bool _isSpeaking; | |||||
| private readonly DiscordVoiceAPIClient _client; | private readonly DiscordVoiceAPIClient _client; | ||||
| public OutputStream(IAudioClient client) | public OutputStream(IAudioClient client) | ||||
| : this((client as AudioClient).ApiClient) { } | : this((client as AudioClient).ApiClient) { } | ||||
| @@ -16,14 +14,6 @@ namespace Discord.Audio.Streams | |||||
| _client = client; | _client = client; | ||||
| } | } | ||||
| public async Task SetSpeakingAsync(bool isSpeaking) | |||||
| { | |||||
| if (_isSpeaking != isSpeaking) | |||||
| { | |||||
| await _client.SendSetSpeaking(isSpeaking).ConfigureAwait(false); | |||||
| _isSpeaking = isSpeaking; | |||||
| } | |||||
| } | |||||
| public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) | public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) | ||||
| { | { | ||||
| cancelToken.ThrowIfCancellationRequested(); | cancelToken.ThrowIfCancellationRequested(); | ||||