Handle the volume in the engine core instead of the decoders

This commit is contained in:
Pierre Krieger 2015-09-27 10:04:32 +02:00
parent 92a4567f08
commit bc6f78de4c
4 changed files with 13 additions and 31 deletions

View file

@ -9,9 +9,6 @@ mod wav;
/// Trait for objects that produce an audio stream.
pub trait Decoder: Iterator /*+ ExactSizeIterator*/ { // TODO: should be exact size, but not enforced yet
/// Changes the volume of the sound.
fn set_volume(&mut self, f32);
/// Returns the total duration of the second in milliseconds.
fn get_total_duration_ms(&self) -> u32;
}

View file

@ -7,7 +7,7 @@ use cpal::{self, Endpoint, Voice};
use vorbis;
pub struct VorbisDecoder {
reader: conversions::AmplifierIterator<Box<Iterator<Item=f32> + Send>>,
reader: Box<Iterator<Item=f32> + Send>,
}
impl VorbisDecoder {
@ -31,16 +31,12 @@ impl VorbisDecoder {
});
Ok(VorbisDecoder {
reader: conversions::AmplifierIterator::new(Box::new(reader), 1.0),
reader: Box::new(reader),
})
}
}
impl Decoder for VorbisDecoder {
fn set_volume(&mut self, value: f32) {
self.reader.set_amplification(value);
}
fn get_total_duration_ms(&self) -> u32 {
unimplemented!()
}

View file

@ -7,7 +7,7 @@ use cpal::{self, Endpoint, Voice};
use hound::WavReader;
pub struct WavDecoder {
reader: conversions::AmplifierIterator<Box<Iterator<Item=f32> + Send>>,
reader: Box<Iterator<Item=f32> + Send>,
total_duration_ms: u32,
}
@ -31,7 +31,7 @@ impl WavDecoder {
let reader = conversions::DataConverter::new(reader);
Ok(WavDecoder {
reader: conversions::AmplifierIterator::new(Box::new(reader), 1.0),
reader: Box::new(reader),
total_duration_ms: total_duration_ms,
})
}
@ -78,10 +78,6 @@ fn is_wave<R>(mut data: R) -> bool where R: Read + Seek {
}
impl Decoder for WavDecoder {
fn set_volume(&mut self, value: f32) {
self.reader.set_amplification(value);
}
fn get_total_duration_ms(&self) -> u32 {
self.total_duration_ms
}

View file

@ -75,13 +75,6 @@ pub struct Handle<'a> {
impl<'a> Handle<'a> {
#[inline]
pub fn set_volume(&self, value: f32) {
// we try to touch the decoder directly from this thread
if let Ok(mut decoder) = self.decoder.try_lock() {
decoder.set_volume(value);
}
// if `try_lock` failed, that means that the decoder is in use
// therefore we use the backup plan of sending a message
let commands = self.engine.commands.lock().unwrap();
commands.send(Command::SetVolume(self.decoder.clone(), value)).unwrap();
}
@ -120,8 +113,8 @@ pub enum Command {
}
fn background(rx: Receiver<Command>) {
// for each endpoint name, stores the voice and the list of sounds
let mut voices: HashMap<String, (Voice, Vec<Arc<Mutex<Decoder<Item=f32> + Send>>>)> = HashMap::new();
// for each endpoint name, stores the voice and the list of sounds with their volume
let mut voices: HashMap<String, (Voice, Vec<(Arc<Mutex<Decoder<Item=f32> + Send>>, f32)>)> = HashMap::new();
// list of sounds to stop playing
let mut sounds_to_remove: Vec<Arc<Mutex<Decoder<Item=f32> + Send>>> = Vec::new();
@ -140,14 +133,14 @@ fn background(rx: Receiver<Command>) {
(voice, Vec::new())
});
entry.1.push(decoder);
entry.1.push((decoder, 1.0));
},
Command::Stop(decoder) => {
let decoder = &*decoder as *const _;
for (_, &mut (_, ref mut sounds)) in voices.iter_mut() {
sounds.retain(|dec| {
&**dec as *const _ != decoder
&*dec.0 as *const _ != decoder
})
}
},
@ -156,9 +149,9 @@ fn background(rx: Receiver<Command>) {
let decoder = &*decoder as *const _;
for (_, &mut (_, ref mut sounds)) in voices.iter_mut() {
if let Some(d) = sounds.iter_mut()
.find(|dec| &***dec as *const _ != decoder)
.find(|dec| &*dec.0 as *const _ == decoder)
{
d.lock().unwrap().set_volume(volume);
d.1 = volume;
}
}
},
@ -169,7 +162,7 @@ fn background(rx: Receiver<Command>) {
for decoder in mem::replace(&mut sounds_to_remove, Vec::new()) {
let decoder = &*decoder as *const _;
for (_, &mut (_, ref mut sounds)) in voices.iter_mut() {
sounds.retain(|dec| &**dec as *const _ != decoder);
sounds.retain(|dec| &*dec.0 as *const _ != decoder);
}
}
@ -180,14 +173,14 @@ fn background(rx: Receiver<Command>) {
let num_sounds = sounds.len() as f32;
let samples_iter = (0..).map(|_| {
// FIXME: locking is slow
sounds.iter().map(|s| s.lock().unwrap().next().unwrap_or(0.0) / num_sounds)
sounds.iter().map(|s| s.0.lock().unwrap().next().unwrap_or(0.0) * s.1 / num_sounds)
.fold(0.0, |a, b| a + b)
});
// starting the output
{
let mut buffer = {
let samples_to_write = voice.get_samples_rate().0 * voice.get_channels() as u32;
let samples_to_write = voice.get_samples_rate().0 * voice.get_channels() as u32 * 17 / 1000;
voice.append_data(samples_to_write as usize)
};