Move decode config into DecodeMode::Decode (#272)
Some checks failed
CI / Lint (push) Successful in 10m16s
CI / Test (beta, beta) (push) Failing after 6m11s
CI / Test (nightly, nightly) (push) Successful in 10m53s
CI / Test (stable) (push) Failing after 7s
CI / Test (true, driver tungstenite rustls, driver only) (push) Failing after 7s
CI / Test (true, gateway serenity tungstenite rustls, gateway only) (push) Failing after 6s
CI / Build docs (push) Successful in 10m0s
CI / Examples (push) Failing after 6s
Publish docs / Publish docs (push) Successful in 10m8s
CI / Test (true, Windows, windows-latest) (push) Has been cancelled
CI / Test (true, macOS, macOS-latest) (push) Has been cancelled
Some checks failed
CI / Lint (push) Successful in 10m16s
CI / Test (beta, beta) (push) Failing after 6m11s
CI / Test (nightly, nightly) (push) Successful in 10m53s
CI / Test (stable) (push) Failing after 7s
CI / Test (true, driver tungstenite rustls, driver only) (push) Failing after 7s
CI / Test (true, gateway serenity tungstenite rustls, gateway only) (push) Failing after 6s
CI / Build docs (push) Successful in 10m0s
CI / Examples (push) Failing after 6s
Publish docs / Publish docs (push) Successful in 10m8s
CI / Test (true, Windows, windows-latest) (push) Has been cancelled
CI / Test (true, macOS, macOS-latest) (push) Has been cancelled
This commit is contained in:
@@ -34,7 +34,7 @@ use serenity::{
|
||||
};
|
||||
|
||||
use songbird::{
|
||||
driver::DecodeMode,
|
||||
driver::{DecodeConfig, DecodeMode},
|
||||
model::{
|
||||
id::UserId,
|
||||
payload::{ClientDisconnect, Speaking},
|
||||
@@ -217,7 +217,8 @@ async fn main() {
|
||||
// Here, we need to configure Songbird to decode all incoming voice packets.
|
||||
// If you want, you can do this on a per-call basis---here, we need it to
|
||||
// read the audio data that other people are sending us!
|
||||
let songbird_config = Config::default().decode_mode(DecodeMode::Decode);
|
||||
let songbird_config =
|
||||
Config::default().decode_mode(DecodeMode::Decode(DecodeConfig::default()));
|
||||
|
||||
let mut client = Client::builder(&token, intents)
|
||||
.event_handler(Handler)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
use crate::driver::{Channels, DecodeMode, SampleRate};
|
||||
use crate::driver::DecodeMode;
|
||||
#[cfg(feature = "driver")]
|
||||
use crate::{
|
||||
driver::{
|
||||
@@ -61,18 +61,6 @@ pub struct Config {
|
||||
/// [User speaking state]: crate::events::CoreEvent::VoiceTick
|
||||
pub decode_mode: DecodeMode,
|
||||
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
/// Configures the channel layout for output audio when using [`DecodeMode::Decode`].
|
||||
///
|
||||
/// Defaults to [`Channels::Stereo`].
|
||||
pub decode_channels: Channels,
|
||||
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
/// Configures the sample rate for output audio when using [`DecodeMode::Decode`].
|
||||
///
|
||||
/// Defaults to [`SampleRate::Hz48000`].
|
||||
pub decode_sample_rate: SampleRate,
|
||||
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
/// Configures the amount of time after a user/SSRC is inactive before their decoder state
|
||||
/// should be removed.
|
||||
@@ -223,10 +211,6 @@ impl Default for Config {
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
decode_mode: DecodeMode::Decrypt,
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
decode_channels: Channels::Stereo,
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
decode_sample_rate: SampleRate::Hz48000,
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
decode_state_timeout: Duration::from_secs(60),
|
||||
#[cfg(all(feature = "driver", feature = "receive"))]
|
||||
playout_buffer_length: NonZeroUsize::new(5).unwrap(),
|
||||
@@ -279,22 +263,6 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "receive")]
|
||||
/// Sets this `Config`'s channel layout for output audio when using [`DecodeMode::Decode`]
|
||||
#[must_use]
|
||||
pub fn decode_channels(mut self, decode_channels: Channels) -> Self {
|
||||
self.decode_channels = decode_channels;
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "receive")]
|
||||
/// Sets this `Config`'s sample rate for output audio when using [`DecodeMode::Decode`]
|
||||
#[must_use]
|
||||
pub fn decode_sample_rate(mut self, decode_sample_rate: SampleRate) -> Self {
|
||||
self.decode_sample_rate = decode_sample_rate;
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "receive")]
|
||||
/// Sets this `Config`'s received packet decoder cleanup timer.
|
||||
#[must_use]
|
||||
|
||||
@@ -16,10 +16,16 @@ pub enum DecodeMode {
|
||||
/// Decrypts and decodes each received packet, correctly accounting for losses.
|
||||
///
|
||||
/// Larger per-packet CPU use.
|
||||
Decode,
|
||||
Decode(DecodeConfig),
|
||||
}
|
||||
|
||||
impl DecodeMode {
|
||||
/// Returns whether this mode will decrypt and decode received packets.
|
||||
#[must_use]
|
||||
pub fn should_decode(self) -> bool {
|
||||
matches!(self, DecodeMode::Decode(..))
|
||||
}
|
||||
|
||||
/// Returns whether this mode will decrypt received packets.
|
||||
#[must_use]
|
||||
pub fn should_decrypt(self) -> bool {
|
||||
@@ -27,6 +33,32 @@ impl DecodeMode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for [`DecodeMode::Decode`]
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
|
||||
pub struct DecodeConfig {
|
||||
/// Configures the channel layout for output audio.
|
||||
///
|
||||
/// Defaults to [`Channels::Stereo`].
|
||||
pub channels: Channels,
|
||||
|
||||
/// Configures the sample rate for output audio.
|
||||
///
|
||||
/// Defaults to [`SampleRate::Hz48000`].
|
||||
pub sample_rate: SampleRate,
|
||||
}
|
||||
|
||||
impl DecodeConfig {
|
||||
/// Creates a new [`DecodeConfig`] with the specified channels and sample rate.
|
||||
#[must_use]
|
||||
pub fn new(channels: Channels, sample_rate: SampleRate) -> Self {
|
||||
Self {
|
||||
channels,
|
||||
sample_rate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The channel layout of output audio when using [`DecodeMode::Decode`].
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
|
||||
#[non_exhaustive]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use super::Interconnect;
|
||||
use crate::driver::Config;
|
||||
use crate::driver::DecodeConfig;
|
||||
use dashmap::{DashMap, DashSet};
|
||||
use serenity_voice_model::id::UserId;
|
||||
|
||||
pub enum UdpRxMessage {
|
||||
SetConfig(Config),
|
||||
SetConfig(DecodeConfig),
|
||||
ReplaceInterconnect(Interconnect),
|
||||
}
|
||||
|
||||
|
||||
@@ -329,10 +329,11 @@ impl Mixer {
|
||||
|
||||
#[cfg(feature = "receive")]
|
||||
if let Some(conn) = &self.conn_active {
|
||||
conn_failure |= conn
|
||||
.udp_rx
|
||||
.send(UdpRxMessage::SetConfig(new_config))
|
||||
.is_err();
|
||||
if let crate::driver::DecodeMode::Decode(decode_config) = new_config.decode_mode
|
||||
{
|
||||
let msg = UdpRxMessage::SetConfig(decode_config);
|
||||
conn_failure |= conn.udp_rx.send(msg).is_err();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -5,7 +5,7 @@ mod ssrc_state;
|
||||
use self::{decode_sizes::*, playout_buffer::*, ssrc_state::*};
|
||||
|
||||
use super::message::*;
|
||||
use crate::driver::CryptoMode;
|
||||
use crate::driver::{CryptoMode, DecodeMode};
|
||||
use crate::{
|
||||
constants::*,
|
||||
driver::crypto::Cipher,
|
||||
@@ -65,13 +65,12 @@ impl UdpRx {
|
||||
Ok(UdpRxMessage::ReplaceInterconnect(i)) => {
|
||||
*interconnect = i;
|
||||
},
|
||||
Ok(UdpRxMessage::SetConfig(c)) => {
|
||||
let old_coder = (self.config.decode_channels, self.config.decode_sample_rate);
|
||||
let new_coder = (c.decode_channels, c.decode_sample_rate);
|
||||
self.config = c;
|
||||
|
||||
if old_coder != new_coder {
|
||||
self.decoder_map.values_mut().for_each(|v| v.reconfigure_decoder(&self.config));
|
||||
Ok(UdpRxMessage::SetConfig(new_config)) => {
|
||||
if let DecodeMode::Decode(old_config) = &mut self.config.decode_mode {
|
||||
if *old_config != new_config {
|
||||
*old_config = new_config;
|
||||
self.decoder_map.values_mut().for_each(|v| v.reconfigure_decoder(new_config));
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(flume::RecvError::Disconnected) => break,
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::{
|
||||
driver::{
|
||||
tasks::error::{Error, Result},
|
||||
Channels,
|
||||
DecodeConfig,
|
||||
DecodeMode,
|
||||
},
|
||||
events::context_data::{RtpData, VoiceData},
|
||||
@@ -29,29 +30,28 @@ pub struct SsrcState {
|
||||
impl SsrcState {
|
||||
pub fn new(pkt: &RtpPacket<'_>, crypto_mode: CryptoMode, config: &Config) -> Self {
|
||||
let playout_capacity = config.playout_buffer_length.get() + config.playout_spike_length;
|
||||
let (sample_rate, channels) = match config.decode_mode {
|
||||
DecodeMode::Decode(config) => (config.sample_rate, config.channels),
|
||||
DecodeMode::Decrypt | DecodeMode::Pass => Default::default(),
|
||||
};
|
||||
|
||||
Self {
|
||||
playout_buffer: PlayoutBuffer::new(playout_capacity, pkt.get_sequence().0),
|
||||
crypto_mode,
|
||||
decoder: OpusDecoder::new(
|
||||
config.decode_sample_rate.into(),
|
||||
config.decode_channels.into(),
|
||||
)
|
||||
decoder: OpusDecoder::new(sample_rate.into(), channels.into())
|
||||
.expect("Failed to create new Opus decoder for source."),
|
||||
decode_size: PacketDecodeSize::TwentyMillis,
|
||||
prune_time: Instant::now() + config.decode_state_timeout,
|
||||
disconnected: false,
|
||||
channels: config.decode_channels,
|
||||
channels,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reconfigure_decoder(&mut self, config: &Config) {
|
||||
self.decoder = OpusDecoder::new(
|
||||
config.decode_sample_rate.into(),
|
||||
config.decode_channels.into(),
|
||||
)
|
||||
pub fn reconfigure_decoder(&mut self, config: DecodeConfig) {
|
||||
self.decoder = OpusDecoder::new(config.sample_rate.into(), config.channels.into())
|
||||
.expect("Failed to create new Opus decoder for source.");
|
||||
self.channels = config.decode_channels;
|
||||
|
||||
self.channels = config.channels;
|
||||
}
|
||||
|
||||
pub fn store_packet(&mut self, packet: StoredPacket, config: &Config) {
|
||||
@@ -80,8 +80,7 @@ impl SsrcState {
|
||||
decoded_voice: None,
|
||||
};
|
||||
|
||||
let should_decode = config.decode_mode == DecodeMode::Decode;
|
||||
|
||||
let should_decode = config.decode_mode.should_decode();
|
||||
if let Some((packet, decrypted)) = pkt {
|
||||
let rtp = RtpPacket::new(&packet).unwrap();
|
||||
let extensions = rtp.get_extension() != 0;
|
||||
|
||||
@@ -32,12 +32,12 @@ pub struct VoiceData {
|
||||
///
|
||||
/// Valid audio data (`Some(audio)` where `audio.len >= 0`) typically contains 20ms of 16-bit PCM audio
|
||||
/// using native endianness. This defaults to stereo audio at 48kHz, and can be configured via
|
||||
/// [`Config::decode_channels`] and [`Config::decode_sample_rate`] -- channels are interleaved
|
||||
/// [`DecodeConfig::sample_rate`] and [`DecodeConfig::sample_rate`] -- channels are interleaved
|
||||
/// (i.e., `L, R, L, R, ...`) if stereo.
|
||||
///
|
||||
/// This value will be `None` if Songbird is not configured to decode audio.
|
||||
///
|
||||
/// [`Config::decode_channels`]: crate::Config::decode_channels
|
||||
/// [`Config::decode_sample_rate`]: crate::Config::decode_sample_rate
|
||||
/// [`DecodeConfig::decode_channels`]: crate::driver::DecodeConfig::channels
|
||||
/// [`DecodeConfig::sample_rate`]: crate::driver::DecodeConfig::sample_rate
|
||||
pub decoded_voice: Option<Vec<i16>>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user