Add set_volume to Handle

This commit is contained in:
Pierre Krieger 2015-09-11 13:49:07 +02:00
parent b088c15740
commit 338114d93e
7 changed files with 95 additions and 3 deletions

View file

@ -6,7 +6,8 @@ fn main() {
let endpoint = rodio::get_default_endpoint().unwrap();
let file = std::fs::File::open("examples/beep.wav").unwrap();
let beep1 = rodio::play_once(&endpoint, BufReader::new(file));
let mut beep1 = rodio::play_once(&endpoint, BufReader::new(file));
beep1.set_volume(0.2);
std::thread::sleep_ms(1000);

View file

@ -43,6 +43,7 @@ pub fn convert_and_write<I, S>(mut samples: I, output: &mut UnknownTypeBuffer)
/// Trait for containers that contain PCM data.
pub trait Sample: cpal::Sample {
fn lerp(first: Self, second: Self, numerator: u32, denominator: u32) -> Self;
fn amplify(self, value: f32) -> Self;
fn zero_value() -> Self;
@ -57,6 +58,11 @@ impl Sample for u16 {
(first as u32 + (second as u32 - first as u32) * numerator / denominator) as u16
}
#[inline]
fn amplify(self, value: f32) -> u16 {
((self as f32) * value) as u16
}
#[inline]
fn zero_value() -> u16 {
32768
@ -88,6 +94,11 @@ impl Sample for i16 {
(first as i32 + (second as i32 - first as i32) * numerator as i32 / denominator as i32) as i16
}
#[inline]
fn amplify(self, value: f32) -> i16 {
((self as f32) * value) as i16
}
#[inline]
fn zero_value() -> i16 {
0
@ -123,6 +134,11 @@ impl Sample for f32 {
first + (second - first) * numerator as f32 / denominator as f32
}
#[inline]
fn amplify(self, value: f32) -> f32 {
self * value
}
#[inline]
fn zero_value() -> f32 {
0.0
@ -345,6 +361,43 @@ impl<I> Iterator for SamplesRateConverter<I> where I: Iterator, I::Item: Sample
impl<I> ExactSizeIterator for SamplesRateConverter<I>
where I: ExactSizeIterator, I::Item: Sample + Clone {}
pub struct AmplifierIterator<I> where I: Iterator {
input: I,
amplication: f32,
}
impl<I> AmplifierIterator<I> where I: Iterator {
#[inline]
pub fn new(input: I, amplication: f32) -> AmplifierIterator<I> {
AmplifierIterator {
input: input,
amplication: amplication,
}
}
#[inline]
pub fn set_amplification(&mut self, new_value: f32) {
self.amplication = new_value;
}
}
impl<I> Iterator for AmplifierIterator<I> where I: Iterator, I::Item: Sample {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
self.input.next().map(|value| value.amplify(self.amplication))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.input.size_hint()
}
}
impl<I> ExactSizeIterator for AmplifierIterator<I>
where I: ExactSizeIterator, I::Item: Sample {}
#[cfg(test)]
mod test {
use super::Sample;

View file

@ -12,6 +12,9 @@ pub trait Decoder {
/// Appends data to the voice. Returns the number of nanoseconds after which new data will need
/// to have been submitted.
fn write(&mut self) -> u64;
/// Changes the volume of the sound.
fn set_volume(&mut self, f32);
}
/// Builds a new `Decoder` from a data stream by determining the correct format.

View file

@ -63,4 +63,8 @@ impl Decoder for VorbisDecoder {
len as u64 * 1000000000 / self.voice.get_samples_rate().0 as u64
}
fn set_volume(&mut self, _: f32) {
unimplemented!();
}
}

View file

@ -1,4 +1,5 @@
use std::io::{Read, Seek, SeekFrom};
use std::cmp;
use std::cmp::Ordering;
use super::Decoder;
use super::conversions;
@ -8,7 +9,7 @@ use hound::WavReader;
use hound::WavSpec;
pub struct WavDecoder {
reader: Box<Iterator<Item=i16> + Send>,
reader: conversions::AmplifierIterator<Box<Iterator<Item=i16> + Send>>,
voice: Voice,
}
@ -59,7 +60,7 @@ impl WavDecoder {
voice.get_samples_rate());
Ok(WavDecoder {
reader: Box::new(reader),
reader: conversions::AmplifierIterator::new(Box::new(reader), 1.0),
voice: voice,
})
}
@ -108,6 +109,8 @@ fn is_wave<R>(mut data: R) -> bool where R: Read + Seek {
impl Decoder for WavDecoder {
fn write(&mut self) -> u64 {
let (min, _) = self.reader.size_hint();
let min = cmp::min(min, 10240); // using a minimal value so that filters get applied
// quickly
if min == 0 {
// finished
@ -127,4 +130,8 @@ impl Decoder for WavDecoder {
duration
}
fn set_volume(&mut self, value: f32) {
self.reader.set_amplification(value);
}
}

View file

@ -60,6 +60,12 @@ pub struct Handle<'a> {
}
impl<'a> Handle<'a> {
#[inline]
pub fn set_volume(&mut self, value: f32) {
let commands = self.engine.commands.lock().unwrap();
commands.send(Command::SetVolume(self.id, value)).unwrap();
}
#[inline]
pub fn stop(self) {
let commands = self.engine.commands.lock().unwrap();
@ -70,6 +76,7 @@ impl<'a> Handle<'a> {
pub enum Command {
Play(usize, Box<Decoder + Send>),
Stop(usize),
SetVolume(usize, f32),
}
fn background(rx: Receiver<Command>) {
@ -86,6 +93,14 @@ fn background(rx: Receiver<Command>) {
Command::Stop(id) => {
sounds.retain(|&(id2, _)| id2 != id)
},
Command::SetVolume(id, volume) => {
if let Some(&mut (_, ref mut d)) = sounds.iter_mut()
.find(|&&mut (i, _)| i == id)
{
d.set_volume(volume);
}
},
}
}

View file

@ -22,6 +22,15 @@ lazy_static! {
pub struct Handle(engine::Handle<'static>);
impl Handle {
/// Changes the volume of the sound.
///
/// The value `1.0` is the "normal" volume (unfiltered input). Any value other than 1.0 will
/// multiply each sample by this value.
#[inline]
pub fn set_volume(&mut self, value: f32) {
self.0.set_volume(value);
}
/// Stops the sound.
#[inline]
pub fn stop(self) {