diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2021-01-05 12:19:54 +0100 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2021-01-05 12:20:21 +0100 |
| commit | ba4aa72654f2d57d59f6e25151315213bec21192 (patch) | |
| tree | 6ff7fe03e3ebbc4b351fae778fd1c02f2d6148de | |
| parent | 531dc28e2c09a13336b057044bf8721d4b2c4c00 (diff) | |
| parent | 2cef2e31a139e453474298b3278c98f18eba7203 (diff) | |
| download | mum-ba4aa72654f2d57d59f6e25151315213bec21192.tar.gz | |
Merge remote-tracking branch 'origin/choose-sfx' into main
| -rw-r--r-- | Cargo.lock | 35 | ||||
| -rw-r--r-- | mumd/Cargo.toml | 2 | ||||
| -rw-r--r-- | mumd/src/audio.rs | 151 | ||||
| -rw-r--r-- | mumd/src/fallback_sfx.wav (renamed from mumd/src/resources/channel_join.wav) | bin | 32002 -> 32002 bytes | |||
| -rw-r--r-- | mumd/src/resources/channel_leave.wav | bin | 32002 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/resources/connect.wav | bin | 32002 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/resources/deafen.wav | bin | 32002 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/resources/disconnect.wav | bin | 303364 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/resources/mute.wav | bin | 32002 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/resources/undeafen.wav | bin | 32002 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/resources/unmute.wav | bin | 32002 -> 0 bytes | |||
| -rw-r--r-- | mumd/src/state.rs | 3 | ||||
| -rw-r--r-- | mumlib/src/config.rs | 7 |
13 files changed, 143 insertions, 55 deletions
@@ -851,6 +851,15 @@ dependencies = [ ] [[package]] +name = "heck" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +dependencies = [ + "unicode-segmentation", +] + +[[package]] name = "hermit-abi" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1208,6 +1217,8 @@ dependencies = [ "openssl", "opus", "serde", + "strum", + "strum_macros", "tokio", "tokio-native-tls", "tokio-stream", @@ -2002,6 +2013,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] +name = "strum" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" + +[[package]] +name = "strum_macros" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "syn" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2221,6 +2250,12 @@ dependencies = [ ] [[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] name = "unicode-width" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/mumd/Cargo.toml b/mumd/Cargo.toml index 0f5edb1..4f0bc19 100644 --- a/mumd/Cargo.toml +++ b/mumd/Cargo.toml @@ -35,6 +35,8 @@ native-tls = "0.2" openssl = { version = "0.10" } opus = "0.2" serde = { version = "1.0", features = ["derive"] } +strum = "0.20" +strum_macros = "0.20" tokio = { version = "1.0", features = ["macros", "rt", "rt-multi-thread", "sync", "net", "time"] } tokio-stream = "0.1.0" tokio-native-tls = "0.3" diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs index 83818d5..680433c 100644 --- a/mumd/src/audio.rs +++ b/mumd/src/audio.rs @@ -13,49 +13,28 @@ use futures::Stream; use futures::stream::StreamExt; use futures::task::{Context, Poll}; use log::*; +use mumble_protocol::Serverbound; use mumble_protocol::voice::{VoicePacketPayload, VoicePacket}; +use mumlib::config::SoundEffect; use opus::Channels; -use std::collections::hash_map::Entry; -use std::collections::{HashMap, VecDeque}; -use std::fmt::Debug; -use std::future::{Future}; -use std::pin::Pin; -use std::sync::{Arc, Mutex}; +use std::{ + borrow::Cow, + collections::{hash_map::Entry, HashMap, VecDeque}, + convert::TryFrom, + fmt::Debug, + fs::File, + future::Future, + io::Read, + pin::Pin, + sync::{Arc, Mutex}, +}; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; use tokio::sync::watch; -use mumble_protocol::Serverbound; - -//TODO? move to mumlib -pub const EVENT_SOUNDS: &[(&[u8], NotificationEvents)] = &[ - (include_bytes!("resources/connect.wav"), NotificationEvents::ServerConnect), - ( - include_bytes!("resources/disconnect.wav"), - NotificationEvents::ServerDisconnect, - ), - ( - include_bytes!("resources/channel_join.wav"), - NotificationEvents::UserConnected, - ), - ( - include_bytes!("resources/channel_leave.wav"), - NotificationEvents::UserDisconnected, - ), - ( - include_bytes!("resources/channel_join.wav"), - NotificationEvents::UserJoinedChannel, - ), - ( - include_bytes!("resources/channel_leave.wav"), - NotificationEvents::UserLeftChannel, - ), - (include_bytes!("resources/mute.wav"), NotificationEvents::Mute), - (include_bytes!("resources/unmute.wav"), NotificationEvents::Unmute), - (include_bytes!("resources/deafen.wav"), NotificationEvents::Deafen), - (include_bytes!("resources/undeafen.wav"), NotificationEvents::Undeafen), -]; const SAMPLE_RATE: u32 = 48000; -#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, EnumIter)] pub enum NotificationEvents { ServerConnect, ServerDisconnect, @@ -69,6 +48,28 @@ pub enum NotificationEvents { Undeafen, } +impl TryFrom<&str> for NotificationEvents { + type Error = (); + fn try_from(s: &str) -> Result<Self, Self::Error> { + match s { + "server_connect" => Ok(NotificationEvents::ServerConnect), + "server_disconnect" => Ok(NotificationEvents::ServerDisconnect), + "user_connected" => Ok(NotificationEvents::UserConnected), + "user_disconnected" => Ok(NotificationEvents::UserDisconnected), + "user_joined_channel" => Ok(NotificationEvents::UserJoinedChannel), + "user_left_channel" => Ok(NotificationEvents::UserLeftChannel), + "mute" => Ok(NotificationEvents::Mute), + "unmute" => Ok(NotificationEvents::Unmute), + "deafen" => Ok(NotificationEvents::Deafen), + "undeafen" => Ok(NotificationEvents::Undeafen), + _ => { + warn!("Unknown notification event '{}' in config", s); + Err(()) + } + } + } +} + pub struct Audio { output_config: StreamConfig, _output_stream: cpal::Stream, @@ -220,10 +221,41 @@ impl Audio { output_stream.play().unwrap(); - let sounds = EVENT_SOUNDS + let mut res = Self { + output_config, + _output_stream: output_stream, + _input_stream: input_stream, + input_volume_sender, + input_channel_receiver: Arc::new(Mutex::new(Box::new(opus_stream))), + client_streams, + sounds: HashMap::new(), + output_volume_sender, + user_volumes, + play_sounds, + }; + res.load_sound_effects(&[]); + res + } + + pub fn load_sound_effects(&mut self, sound_effects: &[SoundEffect]) { + let overrides: HashMap<_, _> = sound_effects .iter() - .map(|(bytes, event)| { - let reader = hound::WavReader::new(*bytes).unwrap(); + .filter_map(|sound_effect| { + let (event, file) = (&sound_effect.event, &sound_effect.file); + if let Ok(event) = NotificationEvents::try_from(event.as_str()) { + Some((event, file)) + } else { + None + } + }) + .collect(); + + self.sounds = NotificationEvents::iter() + .map(|event| { + let bytes = overrides.get(&event) + .map(|file| get_sfx(file)) + .unwrap_or_else(get_default_sfx); + let reader = hound::WavReader::new(bytes.as_ref()).unwrap(); let spec = reader.spec(); let samples = match spec.sample_format { hound::SampleFormat::Float => reader @@ -246,24 +278,17 @@ impl Audio { .from_hz_to_hz(interp, spec.sample_rate as f64, SAMPLE_RATE as f64) .until_exhausted() // if the source audio is stereo and is being played as mono, discard the right audio - .flat_map(|e| if output_config.channels == 1 { vec![e[0]] } else { e.to_vec() }) + .flat_map( + |e| if self.output_config.channels == 1 { + vec![e[0]] + } else { + e.to_vec() + } + ) .collect::<Vec<f32>>(); - (*event, samples) + (event, samples) }) .collect(); - - Self { - output_config, - _output_stream: output_stream, - _input_stream: input_stream, - input_volume_sender, - input_channel_receiver: Arc::new(Mutex::new(Box::new(opus_stream))), - client_streams, - sounds, - output_volume_sender, - user_volumes, - play_sounds, - } } pub fn decode_packet(&self, session_id: u32, payload: VoicePacketPayload) { @@ -359,6 +384,22 @@ impl Audio { } } +// moo +fn get_sfx(file: &str) -> Cow<'static, [u8]> { + let mut buf: Vec<u8> = Vec::new(); + if let Ok(mut file) = File::open(file) { + file.read_to_end(&mut buf).unwrap(); + Cow::from(buf) + } else { + warn!("File not found: '{}'", file); + get_default_sfx() + } +} + +fn get_default_sfx() -> Cow<'static, [u8]> { + Cow::from(include_bytes!("fallback_sfx.wav").as_ref()) +} + struct StreamingNoiseGate<S: StreamingSignal> { open: usize, signal: S, diff --git a/mumd/src/resources/channel_join.wav b/mumd/src/fallback_sfx.wav Binary files differindex 82ee4d4..82ee4d4 100644 --- a/mumd/src/resources/channel_join.wav +++ b/mumd/src/fallback_sfx.wav diff --git a/mumd/src/resources/channel_leave.wav b/mumd/src/resources/channel_leave.wav Binary files differdeleted file mode 100644 index 82ee4d4..0000000 --- a/mumd/src/resources/channel_leave.wav +++ /dev/null diff --git a/mumd/src/resources/connect.wav b/mumd/src/resources/connect.wav Binary files differdeleted file mode 100644 index 82ee4d4..0000000 --- a/mumd/src/resources/connect.wav +++ /dev/null diff --git a/mumd/src/resources/deafen.wav b/mumd/src/resources/deafen.wav Binary files differdeleted file mode 100644 index 82ee4d4..0000000 --- a/mumd/src/resources/deafen.wav +++ /dev/null diff --git a/mumd/src/resources/disconnect.wav b/mumd/src/resources/disconnect.wav Binary files differdeleted file mode 100644 index fb2ca76..0000000 --- a/mumd/src/resources/disconnect.wav +++ /dev/null diff --git a/mumd/src/resources/mute.wav b/mumd/src/resources/mute.wav Binary files differdeleted file mode 100644 index 82ee4d4..0000000 --- a/mumd/src/resources/mute.wav +++ /dev/null diff --git a/mumd/src/resources/undeafen.wav b/mumd/src/resources/undeafen.wav Binary files differdeleted file mode 100644 index 82ee4d4..0000000 --- a/mumd/src/resources/undeafen.wav +++ /dev/null diff --git a/mumd/src/resources/unmute.wav b/mumd/src/resources/unmute.wav Binary files differdeleted file mode 100644 index 82ee4d4..0000000 --- a/mumd/src/resources/unmute.wav +++ /dev/null diff --git a/mumd/src/state.rs b/mumd/src/state.rs index d1f64a9..84247bc 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -573,6 +573,9 @@ impl State { if let Some(output_volume) = self.config.audio.output_volume { self.audio.set_output_volume(output_volume); } + if let Some(sound_effects) = &self.config.audio.sound_effects { + self.audio.load_sound_effects(sound_effects); + } } pub fn initialized(&self) { diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index 5987ab9..0a43253 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -47,9 +47,16 @@ impl Config { } #[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct SoundEffect { + pub event: String, + pub file: String, +} + +#[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct AudioConfig { pub input_volume: Option<f32>, pub output_volume: Option<f32>, + pub sound_effects: Option<Vec<SoundEffect>>, } #[derive(Clone, Debug, Deserialize, Serialize)] |
