mirror of
https://github.com/RustAudio/rodio
synced 2024-12-12 21:22:36 +00:00
Add set_volume to Handle
This commit is contained in:
parent
b088c15740
commit
338114d93e
7 changed files with 95 additions and 3 deletions
|
@ -6,7 +6,8 @@ fn main() {
|
||||||
let endpoint = rodio::get_default_endpoint().unwrap();
|
let endpoint = rodio::get_default_endpoint().unwrap();
|
||||||
|
|
||||||
let file = std::fs::File::open("examples/beep.wav").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);
|
std::thread::sleep_ms(1000);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ pub fn convert_and_write<I, S>(mut samples: I, output: &mut UnknownTypeBuffer)
|
||||||
/// Trait for containers that contain PCM data.
|
/// Trait for containers that contain PCM data.
|
||||||
pub trait Sample: cpal::Sample {
|
pub trait Sample: cpal::Sample {
|
||||||
fn lerp(first: Self, second: Self, numerator: u32, denominator: u32) -> Self;
|
fn lerp(first: Self, second: Self, numerator: u32, denominator: u32) -> Self;
|
||||||
|
fn amplify(self, value: f32) -> Self;
|
||||||
|
|
||||||
fn zero_value() -> 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
|
(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]
|
#[inline]
|
||||||
fn zero_value() -> u16 {
|
fn zero_value() -> u16 {
|
||||||
32768
|
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
|
(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]
|
#[inline]
|
||||||
fn zero_value() -> i16 {
|
fn zero_value() -> i16 {
|
||||||
0
|
0
|
||||||
|
@ -123,6 +134,11 @@ impl Sample for f32 {
|
||||||
first + (second - first) * numerator as f32 / denominator as f32
|
first + (second - first) * numerator as f32 / denominator as f32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn amplify(self, value: f32) -> f32 {
|
||||||
|
self * value
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero_value() -> f32 {
|
fn zero_value() -> f32 {
|
||||||
0.0
|
0.0
|
||||||
|
@ -345,6 +361,43 @@ impl<I> Iterator for SamplesRateConverter<I> where I: Iterator, I::Item: Sample
|
||||||
impl<I> ExactSizeIterator for SamplesRateConverter<I>
|
impl<I> ExactSizeIterator for SamplesRateConverter<I>
|
||||||
where I: ExactSizeIterator, I::Item: Sample + Clone {}
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Sample;
|
use super::Sample;
|
||||||
|
|
|
@ -12,6 +12,9 @@ pub trait Decoder {
|
||||||
/// Appends data to the voice. Returns the number of nanoseconds after which new data will need
|
/// Appends data to the voice. Returns the number of nanoseconds after which new data will need
|
||||||
/// to have been submitted.
|
/// to have been submitted.
|
||||||
fn write(&mut self) -> u64;
|
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.
|
/// Builds a new `Decoder` from a data stream by determining the correct format.
|
||||||
|
|
|
@ -63,4 +63,8 @@ impl Decoder for VorbisDecoder {
|
||||||
|
|
||||||
len as u64 * 1000000000 / self.voice.get_samples_rate().0 as u64
|
len as u64 * 1000000000 / self.voice.get_samples_rate().0 as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_volume(&mut self, _: f32) {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
use std::cmp;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use super::Decoder;
|
use super::Decoder;
|
||||||
use super::conversions;
|
use super::conversions;
|
||||||
|
@ -8,7 +9,7 @@ use hound::WavReader;
|
||||||
use hound::WavSpec;
|
use hound::WavSpec;
|
||||||
|
|
||||||
pub struct WavDecoder {
|
pub struct WavDecoder {
|
||||||
reader: Box<Iterator<Item=i16> + Send>,
|
reader: conversions::AmplifierIterator<Box<Iterator<Item=i16> + Send>>,
|
||||||
voice: Voice,
|
voice: Voice,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ impl WavDecoder {
|
||||||
voice.get_samples_rate());
|
voice.get_samples_rate());
|
||||||
|
|
||||||
Ok(WavDecoder {
|
Ok(WavDecoder {
|
||||||
reader: Box::new(reader),
|
reader: conversions::AmplifierIterator::new(Box::new(reader), 1.0),
|
||||||
voice: voice,
|
voice: voice,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -108,6 +109,8 @@ fn is_wave<R>(mut data: R) -> bool where R: Read + Seek {
|
||||||
impl Decoder for WavDecoder {
|
impl Decoder for WavDecoder {
|
||||||
fn write(&mut self) -> u64 {
|
fn write(&mut self) -> u64 {
|
||||||
let (min, _) = self.reader.size_hint();
|
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 {
|
if min == 0 {
|
||||||
// finished
|
// finished
|
||||||
|
@ -127,4 +130,8 @@ impl Decoder for WavDecoder {
|
||||||
|
|
||||||
duration
|
duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_volume(&mut self, value: f32) {
|
||||||
|
self.reader.set_amplification(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,12 @@ pub struct Handle<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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]
|
#[inline]
|
||||||
pub fn stop(self) {
|
pub fn stop(self) {
|
||||||
let commands = self.engine.commands.lock().unwrap();
|
let commands = self.engine.commands.lock().unwrap();
|
||||||
|
@ -70,6 +76,7 @@ impl<'a> Handle<'a> {
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Play(usize, Box<Decoder + Send>),
|
Play(usize, Box<Decoder + Send>),
|
||||||
Stop(usize),
|
Stop(usize),
|
||||||
|
SetVolume(usize, f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn background(rx: Receiver<Command>) {
|
fn background(rx: Receiver<Command>) {
|
||||||
|
@ -86,6 +93,14 @@ fn background(rx: Receiver<Command>) {
|
||||||
Command::Stop(id) => {
|
Command::Stop(id) => {
|
||||||
sounds.retain(|&(id2, _)| id2 != 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);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,15 @@ lazy_static! {
|
||||||
pub struct Handle(engine::Handle<'static>);
|
pub struct Handle(engine::Handle<'static>);
|
||||||
|
|
||||||
impl Handle {
|
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.
|
/// Stops the sound.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stop(self) {
|
pub fn stop(self) {
|
||||||
|
|
Loading…
Reference in a new issue