Audio bugfixes and improvements.

This commit is contained in:
RogueException
2017-04-08 17:12:10 -03:00
parent 424216b793
commit e92cfd20ac
9 changed files with 98 additions and 163 deletions

View File

@@ -38,14 +38,14 @@ namespace Discord.Audio.Streams
private bool _isPreloaded;
private int _silenceFrames;
public BufferedWriteStream(AudioStream next, IAudioClient client, int samplesPerFrame, int bufferMillis, CancellationToken cancelToken, int maxFrameSize = 1500)
: this(next, client as AudioClient, samplesPerFrame, bufferMillis, cancelToken, null, maxFrameSize) { }
internal BufferedWriteStream(AudioStream next, AudioClient client, int samplesPerFrame, int bufferMillis, CancellationToken cancelToken, Logger logger, int maxFrameSize = 1500)
public BufferedWriteStream(AudioStream next, IAudioClient client, int bufferMillis, CancellationToken cancelToken, int maxFrameSize = 1500)
: this(next, client as AudioClient, bufferMillis, cancelToken, null, maxFrameSize) { }
internal BufferedWriteStream(AudioStream next, AudioClient client, int bufferMillis, CancellationToken cancelToken, Logger logger, int maxFrameSize = 1500)
{
//maxFrameSize = 1275 was too limiting at 128kbps,2ch,60ms
_next = next;
_client = client;
_ticksPerFrame = samplesPerFrame / 48;
_ticksPerFrame = OpusEncoder.FrameSamples / 48;
_logger = logger;
_queueLength = (bufferMillis + (_ticksPerFrame - 1)) / _ticksPerFrame; //Round up

View File

@@ -9,14 +9,14 @@ namespace Discord.Audio.Streams
public const int SampleRate = OpusEncodeStream.SampleRate;
private readonly AudioStream _next;
private readonly byte[] _buffer;
private readonly OpusDecoder _decoder;
private readonly byte[] _buffer;
public OpusDecodeStream(AudioStream next, int channels = OpusConverter.MaxChannels, int bufferSize = 5760 * 2 * sizeof(short))
public OpusDecodeStream(AudioStream next)
{
_next = next;
_buffer = new byte[bufferSize];
_decoder = new OpusDecoder(SampleRate, channels);
_buffer = new byte[OpusConverter.FrameBytes];
_decoder = new OpusDecoder();
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)

View File

@@ -12,18 +12,13 @@ namespace Discord.Audio.Streams
private readonly AudioStream _next;
private readonly OpusEncoder _encoder;
private readonly byte[] _buffer;
private int _frameSize;
private byte[] _partialFrameBuffer;
private int _partialFramePos;
public OpusEncodeStream(AudioStream next, int channels, int samplesPerFrame, int bitrate, AudioApplication application, int bufferSize = 4000)
public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application)
{
_next = next;
_encoder = new OpusEncoder(SampleRate, channels, bitrate, application);
_frameSize = samplesPerFrame * channels * 2;
_buffer = new byte[bufferSize];
_partialFrameBuffer = new byte[_frameSize];
_encoder = new OpusEncoder(bitrate, application);
_buffer = new byte[OpusConverter.FrameBytes];
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
@@ -31,20 +26,31 @@ namespace Discord.Audio.Streams
//Assume threadsafe
while (count > 0)
{
if (_partialFramePos + count >= _frameSize)
if (_partialFramePos == 0 && count >= OpusConverter.FrameBytes)
{
int partialSize = _frameSize - _partialFramePos;
Buffer.BlockCopy(buffer, offset, _partialFrameBuffer, _partialFramePos, partialSize);
//We have enough data and no partial frames. Pass the buffer directly to the encoder
int encFrameSize = _encoder.EncodeFrame(buffer, offset, _buffer, 0);
await _next.WriteAsync(_buffer, 0, encFrameSize, cancellationToken).ConfigureAwait(false);
offset += OpusConverter.FrameBytes;
count -= OpusConverter.FrameBytes;
}
else if (_partialFramePos + count >= OpusConverter.FrameBytes)
{
//We have enough data to complete a previous partial frame.
int partialSize = OpusConverter.FrameBytes - _partialFramePos;
Buffer.BlockCopy(buffer, offset, _buffer, _partialFramePos, partialSize);
int encFrameSize = _encoder.EncodeFrame(_buffer, 0, _buffer, 0);
await _next.WriteAsync(_buffer, 0, encFrameSize, cancellationToken).ConfigureAwait(false);
offset += partialSize;
count -= partialSize;
_partialFramePos = 0;
int encFrameSize = _encoder.EncodeFrame(_partialFrameBuffer, 0, _frameSize, _buffer, 0);
await _next.WriteAsync(_buffer, 0, encFrameSize, cancellationToken).ConfigureAwait(false);
}
else
{
Buffer.BlockCopy(buffer, offset, _partialFrameBuffer, _partialFramePos, count);
//Not enough data to build a complete frame, store this part for later
Buffer.BlockCopy(buffer, offset, _buffer, _partialFramePos, count);
_partialFramePos += count;
break;
}

View File

@@ -9,15 +9,12 @@ namespace Discord.Audio.Streams
{
private readonly AudioStream _next;
private readonly byte[] _header;
private int _samplesPerFrame;
protected readonly byte[] _buffer;
private uint _ssrc, _timestamp = 0;
protected readonly byte[] _buffer;
public RTPWriteStream(AudioStream next, int samplesPerFrame, uint ssrc, int bufferSize = 4000)
public RTPWriteStream(AudioStream next, uint ssrc, int bufferSize = 4000)
{
_next = next;
_samplesPerFrame = samplesPerFrame;
_ssrc = ssrc;
_buffer = new byte[bufferSize];
_header = new byte[24];
@@ -38,7 +35,7 @@ namespace Discord.Audio.Streams
if (_header[3]++ == byte.MaxValue)
_header[2]++;
_timestamp += (uint)_samplesPerFrame;
_timestamp += (uint)OpusEncoder.FrameSamples;
_header[4] = (byte)(_timestamp >> 24);
_header[5] = (byte)(_timestamp >> 16);
_header[6] = (byte)(_timestamp >> 8);