Audio bugfixes and improvements.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user