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

This commit is contained in:
Gnome!
2025-02-23 13:02:29 +00:00
committed by GnomedDev
parent 8956352f13
commit e8c134664b
8 changed files with 68 additions and 68 deletions

View File

@@ -34,7 +34,7 @@ use serenity::{
}; };
use songbird::{ use songbird::{
driver::DecodeMode, driver::{DecodeConfig, DecodeMode},
model::{ model::{
id::UserId, id::UserId,
payload::{ClientDisconnect, Speaking}, payload::{ClientDisconnect, Speaking},
@@ -217,7 +217,8 @@ async fn main() {
// Here, we need to configure Songbird to decode all incoming voice packets. // 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 // 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! // 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) let mut client = Client::builder(&token, intents)
.event_handler(Handler) .event_handler(Handler)

View File

@@ -1,5 +1,5 @@
#[cfg(all(feature = "driver", feature = "receive"))] #[cfg(all(feature = "driver", feature = "receive"))]
use crate::driver::{Channels, DecodeMode, SampleRate}; use crate::driver::DecodeMode;
#[cfg(feature = "driver")] #[cfg(feature = "driver")]
use crate::{ use crate::{
driver::{ driver::{
@@ -61,18 +61,6 @@ pub struct Config {
/// [User speaking state]: crate::events::CoreEvent::VoiceTick /// [User speaking state]: crate::events::CoreEvent::VoiceTick
pub decode_mode: DecodeMode, 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"))] #[cfg(all(feature = "driver", feature = "receive"))]
/// Configures the amount of time after a user/SSRC is inactive before their decoder state /// Configures the amount of time after a user/SSRC is inactive before their decoder state
/// should be removed. /// should be removed.
@@ -223,10 +211,6 @@ impl Default for Config {
#[cfg(all(feature = "driver", feature = "receive"))] #[cfg(all(feature = "driver", feature = "receive"))]
decode_mode: DecodeMode::Decrypt, decode_mode: DecodeMode::Decrypt,
#[cfg(all(feature = "driver", feature = "receive"))] #[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), decode_state_timeout: Duration::from_secs(60),
#[cfg(all(feature = "driver", feature = "receive"))] #[cfg(all(feature = "driver", feature = "receive"))]
playout_buffer_length: NonZeroUsize::new(5).unwrap(), playout_buffer_length: NonZeroUsize::new(5).unwrap(),
@@ -279,22 +263,6 @@ impl Config {
self 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")] #[cfg(feature = "receive")]
/// Sets this `Config`'s received packet decoder cleanup timer. /// Sets this `Config`'s received packet decoder cleanup timer.
#[must_use] #[must_use]

View File

@@ -16,10 +16,16 @@ pub enum DecodeMode {
/// Decrypts and decodes each received packet, correctly accounting for losses. /// Decrypts and decodes each received packet, correctly accounting for losses.
/// ///
/// Larger per-packet CPU use. /// Larger per-packet CPU use.
Decode, Decode(DecodeConfig),
} }
impl DecodeMode { 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. /// Returns whether this mode will decrypt received packets.
#[must_use] #[must_use]
pub fn should_decrypt(self) -> bool { 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`]. /// The channel layout of output audio when using [`DecodeMode::Decode`].
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
#[non_exhaustive] #[non_exhaustive]

View File

@@ -1,12 +1,12 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use super::Interconnect; use super::Interconnect;
use crate::driver::Config; use crate::driver::DecodeConfig;
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap, DashSet};
use serenity_voice_model::id::UserId; use serenity_voice_model::id::UserId;
pub enum UdpRxMessage { pub enum UdpRxMessage {
SetConfig(Config), SetConfig(DecodeConfig),
ReplaceInterconnect(Interconnect), ReplaceInterconnect(Interconnect),
} }

View File

@@ -329,10 +329,11 @@ impl Mixer {
#[cfg(feature = "receive")] #[cfg(feature = "receive")]
if let Some(conn) = &self.conn_active { if let Some(conn) = &self.conn_active {
conn_failure |= conn if let crate::driver::DecodeMode::Decode(decode_config) = new_config.decode_mode
.udp_rx {
.send(UdpRxMessage::SetConfig(new_config)) let msg = UdpRxMessage::SetConfig(decode_config);
.is_err(); conn_failure |= conn.udp_rx.send(msg).is_err();
}
} }
Ok(()) Ok(())

View File

@@ -5,7 +5,7 @@ mod ssrc_state;
use self::{decode_sizes::*, playout_buffer::*, ssrc_state::*}; use self::{decode_sizes::*, playout_buffer::*, ssrc_state::*};
use super::message::*; use super::message::*;
use crate::driver::CryptoMode; use crate::driver::{CryptoMode, DecodeMode};
use crate::{ use crate::{
constants::*, constants::*,
driver::crypto::Cipher, driver::crypto::Cipher,
@@ -65,13 +65,12 @@ impl UdpRx {
Ok(UdpRxMessage::ReplaceInterconnect(i)) => { Ok(UdpRxMessage::ReplaceInterconnect(i)) => {
*interconnect = i; *interconnect = i;
}, },
Ok(UdpRxMessage::SetConfig(c)) => { Ok(UdpRxMessage::SetConfig(new_config)) => {
let old_coder = (self.config.decode_channels, self.config.decode_sample_rate); if let DecodeMode::Decode(old_config) = &mut self.config.decode_mode {
let new_coder = (c.decode_channels, c.decode_sample_rate); if *old_config != new_config {
self.config = c; *old_config = new_config;
self.decoder_map.values_mut().for_each(|v| v.reconfigure_decoder(new_config));
if old_coder != new_coder { }
self.decoder_map.values_mut().for_each(|v| v.reconfigure_decoder(&self.config));
} }
}, },
Err(flume::RecvError::Disconnected) => break, Err(flume::RecvError::Disconnected) => break,

View File

@@ -3,6 +3,7 @@ use crate::{
driver::{ driver::{
tasks::error::{Error, Result}, tasks::error::{Error, Result},
Channels, Channels,
DecodeConfig,
DecodeMode, DecodeMode,
}, },
events::context_data::{RtpData, VoiceData}, events::context_data::{RtpData, VoiceData},
@@ -29,29 +30,28 @@ pub struct SsrcState {
impl SsrcState { impl SsrcState {
pub fn new(pkt: &RtpPacket<'_>, crypto_mode: CryptoMode, config: &Config) -> Self { pub fn new(pkt: &RtpPacket<'_>, crypto_mode: CryptoMode, config: &Config) -> Self {
let playout_capacity = config.playout_buffer_length.get() + config.playout_spike_length; 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 { Self {
playout_buffer: PlayoutBuffer::new(playout_capacity, pkt.get_sequence().0), playout_buffer: PlayoutBuffer::new(playout_capacity, pkt.get_sequence().0),
crypto_mode, crypto_mode,
decoder: OpusDecoder::new( decoder: OpusDecoder::new(sample_rate.into(), channels.into())
config.decode_sample_rate.into(),
config.decode_channels.into(),
)
.expect("Failed to create new Opus decoder for source."), .expect("Failed to create new Opus decoder for source."),
decode_size: PacketDecodeSize::TwentyMillis, decode_size: PacketDecodeSize::TwentyMillis,
prune_time: Instant::now() + config.decode_state_timeout, prune_time: Instant::now() + config.decode_state_timeout,
disconnected: false, disconnected: false,
channels: config.decode_channels, channels,
} }
} }
pub fn reconfigure_decoder(&mut self, config: &Config) { pub fn reconfigure_decoder(&mut self, config: DecodeConfig) {
self.decoder = OpusDecoder::new( self.decoder = OpusDecoder::new(config.sample_rate.into(), config.channels.into())
config.decode_sample_rate.into(),
config.decode_channels.into(),
)
.expect("Failed to create new Opus decoder for source."); .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) { pub fn store_packet(&mut self, packet: StoredPacket, config: &Config) {
@@ -80,8 +80,7 @@ impl SsrcState {
decoded_voice: None, 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 { if let Some((packet, decrypted)) = pkt {
let rtp = RtpPacket::new(&packet).unwrap(); let rtp = RtpPacket::new(&packet).unwrap();
let extensions = rtp.get_extension() != 0; let extensions = rtp.get_extension() != 0;

View File

@@ -32,12 +32,12 @@ pub struct VoiceData {
/// ///
/// Valid audio data (`Some(audio)` where `audio.len >= 0`) typically contains 20ms of 16-bit PCM audio /// 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 /// 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. /// (i.e., `L, R, L, R, ...`) if stereo.
/// ///
/// This value will be `None` if Songbird is not configured to decode audio. /// This value will be `None` if Songbird is not configured to decode audio.
/// ///
/// [`Config::decode_channels`]: crate::Config::decode_channels /// [`DecodeConfig::decode_channels`]: crate::driver::DecodeConfig::channels
/// [`Config::decode_sample_rate`]: crate::Config::decode_sample_rate /// [`DecodeConfig::sample_rate`]: crate::driver::DecodeConfig::sample_rate
pub decoded_voice: Option<Vec<i16>>, pub decoded_voice: Option<Vec<i16>>,
} }