Improve the VoiceNext queue
Created by: WamWooWam
Summary
Fixes #537 (closed) by limiting the size of the VoiceNext packet queue, and modifying the queue to store PCM instead of encoded Opus.
Details
I've switched out the ConcurrentQueue
for a System.Threading.Channels.Channel
to limit number of packets that can be in the queue at any one time, defaulting to 25 packets or about 500ms of audio. This means that you have control over the buffer within VoiceNext, and also means that when you stop writing data, the audio will actually stop on Discord's end too. You can now pause audio!
This means that the entire VoiceNext pipeline is now asynchronous, which unfortunately doesn't play nicely with System.IO.Stream
, and as such we decided it would be best to refactor this. As such, VoiceTransmitStream
is no longer a subclass of System.IO.Stream
, and has been renamed to VoiceTransmitSink
to avoid confusion, but the functionality is much the same. That said, this is a breaking change, as you can no longer synchronously send data to VoiceNext.
I also made the queue store PCM audio, instead of compressed Opus, which potentially fixes some threading issues (OpusEncoders aren't thread safe) and also spreads out the CPU load of encoding packets to the time they're actually sent. And let's be real, if you can't encode 20ms of Opus audio in under 20ms, something's gone wrong.
Oh I also fixed UdpPing, because it would always return zero.
This also reduces the memory usage of VoiceNext by quite a fair bit, even if we are storing PCM data.
Changes proposed
- Rename
VoiceTransmitStream
toVoiceTransmitSink
- Limit the size of the VoiceNext queue
- Make the VoiceNext queue store PCM data.
- Add an extension method to replicate
CopyToAsync
functionality onVoiceTransmitSink
- Fix the test bot, because capturing stderr then not reading it causes ffmpeg to get quite sad
- Fix the
UdpPing
property onVoiceNextConnection
always returning 0. - Repeat myself adnauseam.