@@ -14,8 +14,6 @@ namespace Discord.Audio | |||||
{ | { | ||||
internal class AudioClient : IAudioClient, IDisposable | internal class AudioClient : IAudioClient, IDisposable | ||||
{ | { | ||||
public const int SampleRate = 48000; | |||||
public event Func<Task> Connected | public event Func<Task> Connected | ||||
{ | { | ||||
add { _connectedEvent.Add(value); } | add { _connectedEvent.Add(value); } | ||||
@@ -81,6 +79,7 @@ namespace Discord.Audio | |||||
ApiClient.SentGatewayMessage += async opCode => await _audioLogger.DebugAsync($"Sent {opCode}").ConfigureAwait(false); | ApiClient.SentGatewayMessage += async opCode => await _audioLogger.DebugAsync($"Sent {opCode}").ConfigureAwait(false); | ||||
ApiClient.SentDiscovery += async () => await _audioLogger.DebugAsync($"Sent Discovery").ConfigureAwait(false); | ApiClient.SentDiscovery += async () => await _audioLogger.DebugAsync($"Sent Discovery").ConfigureAwait(false); | ||||
ApiClient.SentData += async bytes => await _audioLogger.DebugAsync($"Sent {bytes} Bytes").ConfigureAwait(false); | |||||
ApiClient.ReceivedEvent += ProcessMessageAsync; | ApiClient.ReceivedEvent += ProcessMessageAsync; | ||||
ApiClient.ReceivedPacket += ProcessPacketAsync; | ApiClient.ReceivedPacket += ProcessPacketAsync; | ||||
ApiClient.Disconnected += async ex => | ApiClient.Disconnected += async ex => | ||||
@@ -185,10 +184,10 @@ namespace Discord.Audio | |||||
{ | { | ||||
return new RTPWriteStream(this, _secretKey, samplesPerFrame, _ssrc, bufferSize = 4000); | return new RTPWriteStream(this, _secretKey, samplesPerFrame, _ssrc, bufferSize = 4000); | ||||
} | } | ||||
public OpusEncodeStream CreatePCMStream(int samplesPerFrame, int? bitrate = null, int channels = 2, | |||||
public OpusEncodeStream CreatePCMStream(int samplesPerFrame, int? bitrate = null, | |||||
OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000) | OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000) | ||||
{ | { | ||||
return new OpusEncodeStream(this, _secretKey, samplesPerFrame, _ssrc, SampleRate, bitrate, channels, application, bufferSize); | |||||
return new OpusEncodeStream(this, _secretKey, samplesPerFrame, _ssrc, bitrate, application, bufferSize); | |||||
} | } | ||||
private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload) | private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload) | ||||
@@ -283,7 +282,7 @@ namespace Discord.Audio | |||||
try | try | ||||
{ | { | ||||
ip = Encoding.UTF8.GetString(packet, 4, 70 - 6).TrimEnd('\0'); | ip = Encoding.UTF8.GetString(packet, 4, 70 - 6).TrimEnd('\0'); | ||||
port = packet[68] | packet[69] << 8; | |||||
port = packet[69] | (packet[68] << 8); | |||||
} | } | ||||
catch { return; } | catch { return; } | ||||
@@ -18,7 +18,6 @@ namespace Discord.Audio | |||||
Task DisconnectAsync(); | Task DisconnectAsync(); | ||||
RTPWriteStream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000); | RTPWriteStream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000); | ||||
OpusEncodeStream CreatePCMStream(int samplesPerFrame, int? bitrate = null, int channels = 2, | |||||
OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000); | |||||
OpusEncodeStream CreatePCMStream(int samplesPerFrame, int? bitrate = null, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000); | |||||
} | } | ||||
} | } |
@@ -2,15 +2,18 @@ | |||||
{ | { | ||||
public class OpusEncodeStream : RTPWriteStream | public class OpusEncodeStream : RTPWriteStream | ||||
{ | { | ||||
public int SampleRate = 48000; | |||||
public int Channels = 2; | |||||
private readonly byte[] _buffer; | private readonly byte[] _buffer; | ||||
private readonly OpusEncoder _encoder; | private readonly OpusEncoder _encoder; | ||||
internal OpusEncodeStream(AudioClient audioClient, byte[] secretKey, int samplesPerFrame, uint ssrc, int samplingRate, int? bitrate = null, | |||||
int channels = OpusConverter.MaxChannels, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000) | |||||
internal OpusEncodeStream(AudioClient audioClient, byte[] secretKey, int samplesPerFrame, uint ssrc, int? bitrate = null, | |||||
OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000) | |||||
: base(audioClient, secretKey, samplesPerFrame, ssrc) | : base(audioClient, secretKey, samplesPerFrame, ssrc) | ||||
{ | { | ||||
_buffer = new byte[bufferSize]; | _buffer = new byte[bufferSize]; | ||||
_encoder = new OpusEncoder(samplingRate, channels); | |||||
_encoder = new OpusEncoder(SampleRate, Channels); | |||||
_encoder.SetForwardErrorCorrection(true); | _encoder.SetForwardErrorCorrection(true); | ||||
if (bitrate != null) | if (bitrate != null) | ||||
@@ -36,7 +36,7 @@ namespace Discord.Audio | |||||
unchecked | unchecked | ||||
{ | { | ||||
if (_buffer[3]++ == byte.MaxValue) | if (_buffer[3]++ == byte.MaxValue) | ||||
_buffer[4]++; | |||||
_buffer[2]++; | |||||
_timestamp += (uint)_samplesPerFrame; | _timestamp += (uint)_samplesPerFrame; | ||||
_buffer[4] = (byte)(_timestamp >> 24); | _buffer[4] = (byte)(_timestamp >> 24); | ||||
@@ -45,9 +45,9 @@ namespace Discord.Audio | |||||
_buffer[7] = (byte)(_timestamp >> 0); | _buffer[7] = (byte)(_timestamp >> 0); | ||||
} | } | ||||
Buffer.BlockCopy(buffer, 0, _nonce, 0, 12); | |||||
Buffer.BlockCopy(_buffer, 0, _nonce, 0, 12); //Copy the 12-byte header to be used for nonce | |||||
count = SecretBox.Encrypt(buffer, offset, count, _buffer, 12, _nonce, _secretKey); | count = SecretBox.Encrypt(buffer, offset, count, _buffer, 12, _nonce, _secretKey); | ||||
_audioClient.Send(_buffer, count); | |||||
_audioClient.Send(_buffer, count + 12); | |||||
} | } | ||||
public override void Flush() { } | public override void Flush() { } | ||||