aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src/audio.rs
diff options
context:
space:
mode:
Diffstat (limited to 'mumd/src/audio.rs')
-rw-r--r--mumd/src/audio.rs124
1 files changed, 7 insertions, 117 deletions
diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs
index 2e20583..785bf7c 100644
--- a/mumd/src/audio.rs
+++ b/mumd/src/audio.rs
@@ -1,69 +1,26 @@
pub mod input;
pub mod output;
+pub mod sound_effects;
pub mod transformers;
-use crate::audio::input::{AudioInputDevice, DefaultAudioInputDevice};
-use crate::audio::output::{AudioOutputDevice, ClientStream, DefaultAudioOutputDevice};
use crate::error::AudioError;
use crate::network::VoiceStreamType;
use crate::state::StatePhase;
-use dasp_interpolate::linear::Linear;
-use dasp_signal::{self as signal, Signal};
use futures_util::stream::Stream;
use futures_util::StreamExt;
-use log::*;
use mumble_protocol::voice::{VoicePacket, VoicePacketPayload};
use mumble_protocol::Serverbound;
use mumlib::config::SoundEffect;
-use std::borrow::Cow;
use std::collections::{hash_map::Entry, HashMap};
-use std::convert::TryFrom;
-use std::fmt::Debug;
-use std::fs::File;
-use std::io::Read;
use std::sync::{Arc, Mutex};
-use strum::IntoEnumIterator;
-use strum_macros::EnumIter;
use tokio::sync::watch;
-const SAMPLE_RATE: u32 = 48000;
-
-#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, EnumIter)]
-pub enum NotificationEvents {
- ServerConnect,
- ServerDisconnect,
- UserConnected,
- UserDisconnected,
- UserJoinedChannel,
- UserLeftChannel,
- Mute,
- Unmute,
- Deafen,
- Undeafen,
-}
+use self::input::{AudioInputDevice, DefaultAudioInputDevice};
+use self::output::{AudioOutputDevice, ClientStream, DefaultAudioOutputDevice};
+use self::sound_effects::NotificationEvents;
-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(())
- }
- }
- }
-}
+const SAMPLE_RATE: u32 = 48000;
pub struct AudioInput {
device: DefaultAudioInputDevice,
@@ -140,59 +97,8 @@ impl AudioOutput {
Ok(res)
}
- pub fn load_sound_effects(&mut self, sound_effects: &[SoundEffect]) {
- let overrides: HashMap<_, _> = sound_effects
- .iter()
- .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
- .into_samples::<f32>()
- .map(|e| e.unwrap())
- .collect::<Vec<_>>(),
- hound::SampleFormat::Int => reader
- .into_samples::<i16>()
- .map(|e| cpal::Sample::to_f32(&e.unwrap()))
- .collect::<Vec<_>>(),
- };
- let iter: Box<dyn Iterator<Item = f32>> = match spec.channels {
- 1 => Box::new(samples.into_iter().flat_map(|e| vec![e, e])),
- 2 => Box::new(samples.into_iter()),
- _ => unimplemented!("Only mono and stereo sound is supported. See #80."),
- };
- let mut signal = signal::from_interleaved_samples_iter::<_, [f32; 2]>(iter);
- let interp = Linear::new(Signal::next(&mut signal), Signal::next(&mut signal));
- let samples = signal
- .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 self.device.num_channels() == 1 {
- vec![e[0]]
- } else {
- e.to_vec()
- }
- })
- .collect::<Vec<f32>>();
- (event, samples)
- })
- .collect();
+ pub fn load_sound_effects(&mut self, overrides: &[SoundEffect]) {
+ self.sounds = sound_effects::load_sound_effects(overrides, self.device.num_channels());
}
pub fn decode_packet_payload(
@@ -238,19 +144,3 @@ impl AudioOutput {
self.client_streams.lock().unwrap().extend(None, samples);
}
}
-
-// 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())
-}