Added AudioOutStream, exposed Clear/ClearAsync methods. Added support for cancelTokens.

This commit is contained in:
RogueException
2017-01-01 00:30:13 -04:00
parent b17a9b713f
commit fc8d2b3155
7 changed files with 57 additions and 22 deletions

View File

@@ -170,25 +170,25 @@ namespace Discord.Audio
await Discord.ApiClient.SendVoiceStateUpdateAsync(Guild.Id, null, false, false).ConfigureAwait(false);
}
public Stream CreateOpusStream(int samplesPerFrame, int bufferMillis)
public AudioOutStream CreateOpusStream(int samplesPerFrame, int bufferMillis)
{
CheckSamplesPerFrame(samplesPerFrame);
var target = new BufferedAudioTarget(ApiClient, samplesPerFrame, bufferMillis, _cancelTokenSource.Token);
return new RTPWriteStream(target, _secretKey, samplesPerFrame, _ssrc);
}
public Stream CreateDirectOpusStream(int samplesPerFrame)
public AudioOutStream CreateDirectOpusStream(int samplesPerFrame)
{
CheckSamplesPerFrame(samplesPerFrame);
var target = new DirectAudioTarget(ApiClient);
return new RTPWriteStream(target, _secretKey, samplesPerFrame, _ssrc);
}
public Stream CreatePCMStream(int samplesPerFrame, int channels, int? bitrate, int bufferMillis)
public AudioOutStream CreatePCMStream(int samplesPerFrame, int channels, int? bitrate, int bufferMillis)
{
CheckSamplesPerFrame(samplesPerFrame);
var target = new BufferedAudioTarget(ApiClient, samplesPerFrame, bufferMillis, _cancelTokenSource.Token);
return new OpusEncodeStream(target, _secretKey, channels, samplesPerFrame, _ssrc, bitrate);
}
public Stream CreateDirectPCMStream(int samplesPerFrame, int channels, int? bitrate)
public AudioOutStream CreateDirectPCMStream(int samplesPerFrame, int channels, int? bitrate)
{
CheckSamplesPerFrame(samplesPerFrame);
var target = new DirectAudioTarget(ApiClient);

View File

@@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace Discord.Audio
{
internal class RTPWriteStream : Stream
internal class RTPWriteStream : AudioOutStream
{
private readonly IAudioTarget _target;
private readonly byte[] _nonce, _secretKey;
@@ -14,10 +14,6 @@ namespace Discord.Audio
protected readonly byte[] _buffer;
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite => true;
internal RTPWriteStream(IAudioTarget target, byte[] secretKey, int samplesPerFrame, uint ssrc)
{
_target = target;
@@ -40,6 +36,7 @@ namespace Discord.Audio
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
unchecked
{
if (_nonce[3]++ == byte.MaxValue)
@@ -63,7 +60,16 @@ namespace Discord.Audio
}
public override async Task FlushAsync(CancellationToken cancellationToken)
{
await _target.FlushAsync().ConfigureAwait(false);
await _target.FlushAsync(cancellationToken).ConfigureAwait(false);
}
public override void Clear()
{
ClearAsync(CancellationToken.None).GetAwaiter().GetResult();
}
public override async Task ClearAsync(CancellationToken cancelToken)
{
await _target.ClearAsync(cancelToken).ConfigureAwait(false);
}
public override long Length { get { throw new NotSupportedException(); } }

View File

@@ -87,17 +87,25 @@ namespace Discord.Audio
Buffer.BlockCopy(data, 0, buffer, 0, count);
_queuedFrames.Enqueue(new Frame(buffer, count));
}
public async Task FlushAsync()
public async Task FlushAsync(CancellationToken cancelToken)
{
while (true)
{
cancelToken.ThrowIfCancellationRequested();
if (_queuedFrames.Count == 0)
return;
await Task.Delay(250).ConfigureAwait(false);
await Task.Delay(250, cancelToken).ConfigureAwait(false);
}
}
public Task ClearAsync(CancellationToken cancelToken)
{
Frame ignored;
do
cancelToken.ThrowIfCancellationRequested();
while (_queuedFrames.TryDequeue(out ignored));
return Task.Delay(0);
}
protected void Dispose(bool disposing)
{
if (disposing)

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
namespace Discord.Audio
{
@@ -13,7 +14,9 @@ namespace Discord.Audio
public Task SendAsync(byte[] buffer, int count)
=> _client.SendAsync(buffer, count);
public Task FlushAsync()
public Task FlushAsync(CancellationToken cancelToken)
=> Task.Delay(0);
public Task ClearAsync(CancellationToken cancelToken)
=> Task.Delay(0);
}
}

View File

@@ -1,10 +1,12 @@
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
namespace Discord.Audio
{
internal interface IAudioTarget
{
Task SendAsync(byte[] buffer, int count);
Task FlushAsync();
Task FlushAsync(CancellationToken cancelToken);
Task ClearAsync(CancellationToken cancelToken);
}
}