diff --git a/src/player.rs b/src/player.rs index da97fdf8..433c7a03 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,5 +1,6 @@ use eventual::{self, Async}; use portaudio; +use std::borrow::Cow; use std::sync::{mpsc, Mutex, Arc, MutexGuard}; use std::thread; use vorbis; @@ -55,7 +56,7 @@ impl Player { position_ms: 0, position_measured_at: 0, update_time: util::now_ms(), - volume: 0x8000, + volume: 0xFFFF, end_of_track: false, })); @@ -114,6 +115,21 @@ impl Player { } } +fn apply_volume(volume: u16, data: &[i16]) -> Cow<[i16]> { + // Fast path when volume is 100% + if volume == 0xFFFF { + Cow::Borrowed(data) + } else { + Cow::Owned(data.iter() + .map(|&x| { + (x as i32 + * volume as i32 + / 0xFFFF) as i16 + }) + .collect()) + } +} + impl PlayerInternal { fn run(self) { portaudio::initialize().unwrap(); @@ -247,14 +263,8 @@ impl PlayerInternal { if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay { match decoder.as_mut().unwrap().packets().next() { Some(Ok(packet)) => { - let buffer = packet.data - .iter() - .map(|&x| { - (x as i32 - * self.state.lock().unwrap().volume as i32 - / 0xFFFF) as i16 - }) - .collect::>(); + let buffer = apply_volume(self.state.lock().unwrap().volume, + &packet.data); match stream.write(&buffer) { Ok(_) => (), Err(portaudio::PaError::OutputUnderflowed) => eprintln!("Underflow"),