mirror of
https://github.com/RustAudio/rodio
synced 2024-11-10 14:14:21 +00:00
Merge pull request #164 from frazar/master
Refactor code with `cargo fmt`
This commit is contained in:
commit
6ab1c2a6b9
38 changed files with 673 additions and 473 deletions
|
@ -6,10 +6,12 @@ use std::time::Duration;
|
|||
|
||||
fn main() {
|
||||
let device = rodio::default_output_device().unwrap();
|
||||
let mut sink = rodio::SpatialSink::new(&device,
|
||||
[-10.0, 0.0, 0.0],
|
||||
[1.0, 0.0, 0.0],
|
||||
[-1.0, 0.0, 0.0]);
|
||||
let mut sink = rodio::SpatialSink::new(
|
||||
&device,
|
||||
[-10.0, 0.0, 0.0],
|
||||
[1.0, 0.0, 0.0],
|
||||
[-1.0, 0.0, 0.0],
|
||||
);
|
||||
|
||||
let file = std::fs::File::open("examples/music.ogg").unwrap();
|
||||
let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
|
||||
|
|
|
@ -26,7 +26,8 @@ pub struct SamplesBuffer<S> {
|
|||
}
|
||||
|
||||
impl<S> SamplesBuffer<S>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
/// Builds a new `SamplesBuffer`.
|
||||
///
|
||||
|
@ -38,16 +39,19 @@ impl<S> SamplesBuffer<S>
|
|||
/// This is because the calculation of the duration would overflow.
|
||||
///
|
||||
pub fn new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S>
|
||||
where D: Into<Vec<S>>
|
||||
where
|
||||
D: Into<Vec<S>>,
|
||||
{
|
||||
assert!(channels != 0);
|
||||
assert!(sample_rate != 0);
|
||||
|
||||
let data = data.into();
|
||||
let duration_ns = 1_000_000_000u64.checked_mul(data.len() as u64).unwrap() /
|
||||
sample_rate as u64 / channels as u64;
|
||||
let duration = Duration::new(duration_ns / 1_000_000_000,
|
||||
(duration_ns % 1_000_000_000) as u32);
|
||||
let duration_ns = 1_000_000_000u64.checked_mul(data.len() as u64).unwrap()
|
||||
/ sample_rate as u64 / channels as u64;
|
||||
let duration = Duration::new(
|
||||
duration_ns / 1_000_000_000,
|
||||
(duration_ns % 1_000_000_000) as u32,
|
||||
);
|
||||
|
||||
SamplesBuffer {
|
||||
data: data.into_iter(),
|
||||
|
@ -59,7 +63,8 @@ impl<S> SamplesBuffer<S>
|
|||
}
|
||||
|
||||
impl<S> Source for SamplesBuffer<S>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -83,7 +88,8 @@ impl<S> Source for SamplesBuffer<S>
|
|||
}
|
||||
|
||||
impl<S> Iterator for SamplesBuffer<S>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ use cpal;
|
|||
/// Iterator that converts from a certain channel count to another.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ChannelCountConverter<I>
|
||||
where I: Iterator
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
input: I,
|
||||
from: cpal::ChannelCount,
|
||||
|
@ -13,7 +14,8 @@ pub struct ChannelCountConverter<I>
|
|||
}
|
||||
|
||||
impl<I> ChannelCountConverter<I>
|
||||
where I: Iterator
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
/// Initializes the iterator.
|
||||
///
|
||||
|
@ -22,8 +24,9 @@ impl<I> ChannelCountConverter<I>
|
|||
/// Panicks if `from` or `to` are equal to 0.
|
||||
///
|
||||
#[inline]
|
||||
pub fn new(input: I, from: cpal::ChannelCount, to: cpal::ChannelCount)
|
||||
-> ChannelCountConverter<I> {
|
||||
pub fn new(
|
||||
input: I, from: cpal::ChannelCount, to: cpal::ChannelCount,
|
||||
) -> ChannelCountConverter<I> {
|
||||
assert!(from >= 1);
|
||||
assert!(to >= 1);
|
||||
|
||||
|
@ -44,8 +47,9 @@ impl<I> ChannelCountConverter<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for ChannelCountConverter<I>
|
||||
where I: Iterator,
|
||||
I::Item: Clone
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -79,20 +83,20 @@ impl<I> Iterator for ChannelCountConverter<I>
|
|||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (min, max) = self.input.size_hint();
|
||||
|
||||
let min = (min / self.from as usize) * self.to as usize +
|
||||
self.next_output_sample_pos as usize;
|
||||
let min =
|
||||
(min / self.from as usize) * self.to as usize + self.next_output_sample_pos as usize;
|
||||
let max = max.map(|max| {
|
||||
(max / self.from as usize) * self.to as usize +
|
||||
self.next_output_sample_pos as usize
|
||||
});
|
||||
(max / self.from as usize) * self.to as usize + self.next_output_sample_pos as usize
|
||||
});
|
||||
|
||||
(min, max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ExactSizeIterator for ChannelCountConverter<I>
|
||||
where I: ExactSizeIterator,
|
||||
I::Item: Clone
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
I::Item: Clone,
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
use cpal::Sample as CpalSample;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -27,9 +26,10 @@ impl<I, O> DataConverter<I, O> {
|
|||
}
|
||||
|
||||
impl<I, O> Iterator for DataConverter<I, O>
|
||||
where I: Iterator,
|
||||
I::Item: Sample,
|
||||
O: Sample
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Sample,
|
||||
O: Sample,
|
||||
{
|
||||
type Item = O;
|
||||
|
||||
|
@ -45,9 +45,10 @@ impl<I, O> Iterator for DataConverter<I, O>
|
|||
}
|
||||
|
||||
impl<I, O> ExactSizeIterator for DataConverter<I, O>
|
||||
where I: ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
O: Sample
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
O: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -105,8 +106,8 @@ impl Sample for u16 {
|
|||
impl Sample for i16 {
|
||||
#[inline]
|
||||
fn lerp(first: i16, second: i16, numerator: u32, denominator: u32) -> 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]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
use conversions::Sample;
|
||||
use cpal;
|
||||
|
||||
|
@ -7,7 +6,8 @@ use std::mem;
|
|||
/// Iterator that converts from a certain sample rate to another.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SampleRateConverter<I>
|
||||
where I: Iterator
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
/// The iterator that gives us samples.
|
||||
input: I,
|
||||
|
@ -29,8 +29,9 @@ pub struct SampleRateConverter<I>
|
|||
}
|
||||
|
||||
impl<I> SampleRateConverter<I>
|
||||
where I: Iterator,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Sample,
|
||||
{
|
||||
///
|
||||
///
|
||||
|
@ -39,9 +40,10 @@ impl<I> SampleRateConverter<I>
|
|||
/// Panicks if `from` or `to` are equal to 0.
|
||||
///
|
||||
#[inline]
|
||||
pub fn new(mut input: I, from: cpal::SampleRate, to: cpal::SampleRate,
|
||||
num_channels: cpal::ChannelCount)
|
||||
-> SampleRateConverter<I> {
|
||||
pub fn new(
|
||||
mut input: I, from: cpal::SampleRate, to: cpal::SampleRate,
|
||||
num_channels: cpal::ChannelCount,
|
||||
) -> SampleRateConverter<I> {
|
||||
let from = from.0;
|
||||
let to = to.0;
|
||||
|
||||
|
@ -52,7 +54,11 @@ impl<I> SampleRateConverter<I>
|
|||
let gcd = {
|
||||
#[inline]
|
||||
fn gcd(a: u32, b: u32) -> u32 {
|
||||
if b == 0 { a } else { gcd(b, a % b) }
|
||||
if b == 0 {
|
||||
a
|
||||
} else {
|
||||
gcd(b, a % b)
|
||||
}
|
||||
}
|
||||
|
||||
gcd(from, to)
|
||||
|
@ -108,8 +114,9 @@ impl<I> SampleRateConverter<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for SampleRateConverter<I>
|
||||
where I: Iterator,
|
||||
I::Item: Sample + Clone
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Sample + Clone,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -137,11 +144,10 @@ impl<I> Iterator for SampleRateConverter<I>
|
|||
self.next_input_frame();
|
||||
}
|
||||
self.current_frame_pos_in_chunk = 0;
|
||||
|
||||
} else {
|
||||
// Finding the position of the first sample of the linear interpolation.
|
||||
let req_left_sample = (self.from * self.next_output_frame_pos_in_chunk / self.to) %
|
||||
self.from;
|
||||
let req_left_sample =
|
||||
(self.from * self.next_output_frame_pos_in_chunk / self.to) % self.from;
|
||||
|
||||
// Advancing `self.current_frame`, `self.next_frame` and
|
||||
// `self.current_frame_pos_in_chunk` until the latter variable
|
||||
|
@ -157,11 +163,10 @@ impl<I> Iterator for SampleRateConverter<I>
|
|||
// `self.next_frame`.
|
||||
let mut result = None;
|
||||
let numerator = (self.from * self.next_output_frame_pos_in_chunk) % self.to;
|
||||
for (off, (cur, next)) in
|
||||
self.current_frame
|
||||
.iter()
|
||||
.zip(self.next_frame.iter())
|
||||
.enumerate()
|
||||
for (off, (cur, next)) in self.current_frame
|
||||
.iter()
|
||||
.zip(self.next_frame.iter())
|
||||
.enumerate()
|
||||
{
|
||||
let sample = Sample::lerp(cur.clone(), next.clone(), numerator, self.to);
|
||||
|
||||
|
@ -175,7 +180,6 @@ impl<I> Iterator for SampleRateConverter<I>
|
|||
// Incrementing the counter for the next iteration.
|
||||
self.next_output_frame_pos_in_chunk += 1;
|
||||
|
||||
|
||||
if result.is_some() {
|
||||
result
|
||||
} else {
|
||||
|
@ -206,19 +210,19 @@ impl<I> Iterator for SampleRateConverter<I>
|
|||
samples_after_chunk
|
||||
};
|
||||
// removing the samples of the current chunk that have not yet been read
|
||||
let samples_after_chunk = samples_after_chunk
|
||||
.saturating_sub(self.from
|
||||
.saturating_sub(self.current_frame_pos_in_chunk + 2) as
|
||||
usize *
|
||||
self.current_frame.capacity());
|
||||
let samples_after_chunk = samples_after_chunk.saturating_sub(
|
||||
self.from
|
||||
.saturating_sub(self.current_frame_pos_in_chunk + 2) as usize
|
||||
* self.current_frame.capacity(),
|
||||
);
|
||||
// calculating the number of samples after the transformation
|
||||
// TODO: this is wrong here \|/
|
||||
let samples_after_chunk = samples_after_chunk * self.to as usize / self.from as usize;
|
||||
|
||||
// `samples_current_chunk` will contain the number of samples remaining to be output
|
||||
// for the chunk currently being processed
|
||||
let samples_current_chunk = (self.to - self.next_output_frame_pos_in_chunk) as usize *
|
||||
self.current_frame.capacity();
|
||||
let samples_current_chunk = (self.to - self.next_output_frame_pos_in_chunk) as usize
|
||||
* self.current_frame.capacity();
|
||||
|
||||
samples_current_chunk + samples_after_chunk + self.output_buffer.len()
|
||||
};
|
||||
|
@ -233,8 +237,9 @@ impl<I> Iterator for SampleRateConverter<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for SampleRateConverter<I>
|
||||
where I: ExactSizeIterator,
|
||||
I::Item: Sample + Clone
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
I::Item: Sample + Clone,
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::mem;
|
||||
use std::time::Duration;
|
||||
|
@ -9,7 +8,8 @@ use claxon::FlacReader;
|
|||
|
||||
/// Decoder for the Flac format.
|
||||
pub struct FlacDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
reader: FlacReader<R>,
|
||||
current_block: Vec<i32>,
|
||||
|
@ -21,7 +21,8 @@ pub struct FlacDecoder<R>
|
|||
}
|
||||
|
||||
impl<R> FlacDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
/// Attempts to decode the data as Flac.
|
||||
pub fn new(mut data: R) -> Result<FlacDecoder<R>, R> {
|
||||
|
@ -33,20 +34,22 @@ impl<R> FlacDecoder<R>
|
|||
let spec = reader.streaminfo();
|
||||
|
||||
Ok(FlacDecoder {
|
||||
reader: reader,
|
||||
current_block: Vec::with_capacity(spec.max_block_size as usize *
|
||||
spec.channels as usize),
|
||||
current_block_channel_len: 1,
|
||||
current_block_off: 0,
|
||||
bits_per_sample: spec.bits_per_sample,
|
||||
sample_rate: spec.sample_rate,
|
||||
channels: spec.channels as u16,
|
||||
})
|
||||
reader: reader,
|
||||
current_block: Vec::with_capacity(
|
||||
spec.max_block_size as usize * spec.channels as usize,
|
||||
),
|
||||
current_block_channel_len: 1,
|
||||
current_block_off: 0,
|
||||
bits_per_sample: spec.bits_per_sample,
|
||||
sample_rate: spec.sample_rate,
|
||||
channels: spec.channels as u16,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Source for FlacDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -70,7 +73,8 @@ impl<R> Source for FlacDecoder<R>
|
|||
}
|
||||
|
||||
impl<R> Iterator for FlacDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
type Item = i16;
|
||||
|
||||
|
@ -79,9 +83,9 @@ impl<R> Iterator for FlacDecoder<R>
|
|||
loop {
|
||||
if self.current_block_off < self.current_block.len() {
|
||||
// Read from current block.
|
||||
let real_offset = (self.current_block_off % self.channels as usize) *
|
||||
self.current_block_channel_len +
|
||||
self.current_block_off / self.channels as usize;
|
||||
let real_offset = (self.current_block_off % self.channels as usize)
|
||||
* self.current_block_channel_len
|
||||
+ self.current_block_off / self.channels as usize;
|
||||
let raw_val = self.current_block[real_offset];
|
||||
self.current_block_off += 1;
|
||||
let real_val = if self.bits_per_sample == 16 {
|
||||
|
@ -110,7 +114,8 @@ impl<R> Iterator for FlacDecoder<R>
|
|||
|
||||
/// Returns true if the stream contains Flac data, then resets it to where it was.
|
||||
fn is_flac<R>(mut data: R) -> bool
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
|
||||
|
||||
|
|
|
@ -18,14 +18,17 @@ mod wav;
|
|||
///
|
||||
/// Supports WAV, Vorbis and Flac.
|
||||
#[cfg(any(feature = "wav", feature = "flac", feature = "vorbis"))]
|
||||
pub struct Decoder<R>(DecoderImpl<R>) where R: Read + Seek;
|
||||
pub struct Decoder<R>(DecoderImpl<R>)
|
||||
where
|
||||
R: Read + Seek;
|
||||
|
||||
#[cfg(not(any(feature = "wav", feature = "flac", feature = "vorbis")))]
|
||||
pub struct Decoder<R>(::std::marker::PhantomData<R>);
|
||||
|
||||
#[cfg(any(feature = "wav", feature = "flac", feature = "vorbis"))]
|
||||
enum DecoderImpl<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
#[cfg(feature = "wav")]
|
||||
Wav(wav::WavDecoder<R>),
|
||||
|
@ -36,7 +39,8 @@ enum DecoderImpl<R>
|
|||
}
|
||||
|
||||
impl<R> Decoder<R>
|
||||
where R: Read + Seek + Send + 'static
|
||||
where
|
||||
R: Read + Seek + Send + 'static,
|
||||
{
|
||||
/// Builds a new decoder.
|
||||
///
|
||||
|
@ -73,16 +77,20 @@ impl<R> Decoder<R>
|
|||
|
||||
#[cfg(not(any(feature = "wav", feature = "flac", feature = "vorbis")))]
|
||||
impl<R> Iterator for Decoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
type Item = i16;
|
||||
|
||||
fn next(&mut self) -> Option<i16> { None }
|
||||
fn next(&mut self) -> Option<i16> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "wav", feature = "flac", feature = "vorbis"))]
|
||||
impl<R> Iterator for Decoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
type Item = i16;
|
||||
|
||||
|
@ -113,17 +121,27 @@ impl<R> Iterator for Decoder<R>
|
|||
|
||||
#[cfg(not(any(feature = "wav", feature = "flac", feature = "vorbis")))]
|
||||
impl<R> Source for Decoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
fn current_frame_len(&self) -> Option<usize> { Some(0) }
|
||||
fn channels(&self) -> u16 { 0 }
|
||||
fn sample_rate(&self) -> u32 { 1 }
|
||||
fn total_duration(&self) -> Option<Duration> { Some(Duration::default()) }
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
Some(0)
|
||||
}
|
||||
fn channels(&self) -> u16 {
|
||||
0
|
||||
}
|
||||
fn sample_rate(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
fn total_duration(&self) -> Option<Duration> {
|
||||
Some(Duration::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "wav", feature = "flac", feature = "vorbis"))]
|
||||
impl<R> Source for Decoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -8,14 +8,16 @@ use lewton::inside_ogg::OggStreamReader;
|
|||
|
||||
/// Decoder for an OGG file that contains Vorbis sound format.
|
||||
pub struct VorbisDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
stream_reader: OggStreamReader<R>,
|
||||
current_data: vec::IntoIter<i16>,
|
||||
}
|
||||
|
||||
impl<R> VorbisDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
/// Attempts to decode the data as ogg/vorbis.
|
||||
pub fn new(data: R) -> Result<VorbisDecoder<R>, ()> {
|
||||
|
@ -37,14 +39,15 @@ impl<R> VorbisDecoder<R>
|
|||
};
|
||||
|
||||
Ok(VorbisDecoder {
|
||||
stream_reader: stream_reader,
|
||||
current_data: data.into_iter(),
|
||||
})
|
||||
stream_reader: stream_reader,
|
||||
current_data: data.into_iter(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Source for VorbisDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -68,7 +71,8 @@ impl<R> Source for VorbisDecoder<R>
|
|||
}
|
||||
|
||||
impl<R> Iterator for VorbisDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
type Item = i16;
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ use hound::WavReader;
|
|||
|
||||
/// Decoder for the WAV format.
|
||||
pub struct WavDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
reader: SamplesIterator<R>,
|
||||
sample_rate: u32,
|
||||
|
@ -15,7 +16,8 @@ pub struct WavDecoder<R>
|
|||
}
|
||||
|
||||
impl<R> WavDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
/// Attempts to decode the data as WAV.
|
||||
pub fn new(mut data: R) -> Result<WavDecoder<R>, R> {
|
||||
|
@ -31,22 +33,24 @@ impl<R> WavDecoder<R>
|
|||
};
|
||||
|
||||
Ok(WavDecoder {
|
||||
reader: reader,
|
||||
sample_rate: spec.sample_rate,
|
||||
channels: spec.channels,
|
||||
})
|
||||
reader: reader,
|
||||
sample_rate: spec.sample_rate,
|
||||
channels: spec.channels,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct SamplesIterator<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
reader: WavReader<R>,
|
||||
samples_read: u32,
|
||||
}
|
||||
|
||||
impl<R> Iterator for SamplesIterator<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
type Item = i16;
|
||||
|
||||
|
@ -68,12 +72,14 @@ impl<R> Iterator for SamplesIterator<R>
|
|||
}
|
||||
|
||||
impl<R> ExactSizeIterator for SamplesIterator<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
}
|
||||
|
||||
impl<R> Source for WavDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -98,7 +104,8 @@ impl<R> Source for WavDecoder<R>
|
|||
}
|
||||
|
||||
impl<R> Iterator for WavDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
type Item = i16;
|
||||
|
||||
|
@ -114,13 +121,15 @@ impl<R> Iterator for WavDecoder<R>
|
|||
}
|
||||
|
||||
impl<R> ExactSizeIterator for WavDecoder<R>
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns true if the stream contains WAV data, then resets it to where it was.
|
||||
fn is_wave<R>(mut data: R) -> bool
|
||||
where R: Read + Seek
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//! Queue that plays sounds one after the other.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
|
||||
use source::Source;
|
||||
|
@ -17,16 +17,18 @@ use Sample;
|
|||
/// added to the mixer will be converted to these values.
|
||||
///
|
||||
/// After creating a mixer, you can add new sounds with the controller.
|
||||
pub fn mixer<S>(channels: u16, sample_rate: u32)
|
||||
-> (Arc<DynamicMixerController<S>>, DynamicMixer<S>)
|
||||
where S: Sample + Send + 'static
|
||||
pub fn mixer<S>(
|
||||
channels: u16, sample_rate: u32,
|
||||
) -> (Arc<DynamicMixerController<S>>, DynamicMixer<S>)
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
let input = Arc::new(DynamicMixerController {
|
||||
has_pending: AtomicBool::new(false),
|
||||
pending_sources: Mutex::new(Vec::new()),
|
||||
channels: channels,
|
||||
sample_rate: sample_rate,
|
||||
});
|
||||
has_pending: AtomicBool::new(false),
|
||||
pending_sources: Mutex::new(Vec::new()),
|
||||
channels: channels,
|
||||
sample_rate: sample_rate,
|
||||
});
|
||||
|
||||
let output = DynamicMixer {
|
||||
current_sources: Vec::with_capacity(16),
|
||||
|
@ -45,12 +47,14 @@ pub struct DynamicMixerController<S> {
|
|||
}
|
||||
|
||||
impl<S> DynamicMixerController<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
/// Adds a new source to mix to the existing ones.
|
||||
#[inline]
|
||||
pub fn add<T>(&self, source: T)
|
||||
where T: Source<Item = S> + Send + 'static
|
||||
where
|
||||
T: Source<Item = S> + Send + 'static,
|
||||
{
|
||||
let uniform_source = UniformSourceIterator::new(source, self.channels, self.sample_rate);
|
||||
self.pending_sources
|
||||
|
@ -71,7 +75,8 @@ pub struct DynamicMixer<S> {
|
|||
}
|
||||
|
||||
impl<S> Source for DynamicMixer<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -95,7 +100,8 @@ impl<S> Source for DynamicMixer<S>
|
|||
}
|
||||
|
||||
impl<S> Iterator for DynamicMixer<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::Weak;
|
||||
|
@ -8,9 +8,9 @@ use std::thread::Builder;
|
|||
use cpal::Device;
|
||||
use cpal::EventLoop;
|
||||
use cpal::Sample as CpalSample;
|
||||
use cpal::UnknownTypeOutputBuffer;
|
||||
use cpal::StreamId;
|
||||
use cpal::StreamData;
|
||||
use cpal::StreamId;
|
||||
use cpal::UnknownTypeOutputBuffer;
|
||||
use dynamic_mixer;
|
||||
use source::Source;
|
||||
|
||||
|
@ -18,7 +18,8 @@ use source::Source;
|
|||
///
|
||||
/// The playing uses a background thread.
|
||||
pub fn play_raw<S>(device: &Device, source: S)
|
||||
where S: Source<Item = f32> + Send + 'static
|
||||
where
|
||||
S: Source<Item = f32> + Send + 'static,
|
||||
{
|
||||
lazy_static! {
|
||||
static ref ENGINE: Arc<Engine> = {
|
||||
|
@ -72,30 +73,34 @@ fn audio_callback(engine: &Arc<Engine>, stream_id: StreamId, buffer: StreamData)
|
|||
};
|
||||
|
||||
match buffer {
|
||||
StreamData::Output { buffer: UnknownTypeOutputBuffer::U16(mut buffer) } => {
|
||||
for d in buffer.iter_mut() {
|
||||
*d = mixer_rx.next().map(|s| s.to_u16()).unwrap_or(u16::max_value() / 2);
|
||||
}
|
||||
StreamData::Output {
|
||||
buffer: UnknownTypeOutputBuffer::U16(mut buffer),
|
||||
} => for d in buffer.iter_mut() {
|
||||
*d = mixer_rx
|
||||
.next()
|
||||
.map(|s| s.to_u16())
|
||||
.unwrap_or(u16::max_value() / 2);
|
||||
},
|
||||
StreamData::Output { buffer: UnknownTypeOutputBuffer::I16(mut buffer) } => {
|
||||
for d in buffer.iter_mut() {
|
||||
*d = mixer_rx.next().map(|s| s.to_i16()).unwrap_or(0i16);
|
||||
}
|
||||
StreamData::Output {
|
||||
buffer: UnknownTypeOutputBuffer::I16(mut buffer),
|
||||
} => for d in buffer.iter_mut() {
|
||||
*d = mixer_rx.next().map(|s| s.to_i16()).unwrap_or(0i16);
|
||||
},
|
||||
StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => {
|
||||
for d in buffer.iter_mut() {
|
||||
*d = mixer_rx.next().unwrap_or(0f32);
|
||||
}
|
||||
StreamData::Output {
|
||||
buffer: UnknownTypeOutputBuffer::F32(mut buffer),
|
||||
} => for d in buffer.iter_mut() {
|
||||
*d = mixer_rx.next().unwrap_or(0f32);
|
||||
},
|
||||
StreamData::Input { buffer: _ } => {
|
||||
panic!("Can't play an input stream!");
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Builds a new sink that targets a given device.
|
||||
fn start<S>(engine: &Arc<Engine>, device: &Device, source: S)
|
||||
where S: Source<Item = f32> + Send + 'static
|
||||
where
|
||||
S: Source<Item = f32> + Send + 'static,
|
||||
{
|
||||
let mut stream_to_start = None;
|
||||
|
||||
|
@ -131,17 +136,26 @@ fn start<S>(engine: &Arc<Engine>, device: &Device, source: S)
|
|||
|
||||
// Adds a new stream to the engine.
|
||||
// TODO: handle possible errors here
|
||||
fn new_output_stream(engine: &Arc<Engine>, device: &Device) -> (Arc<dynamic_mixer::DynamicMixerController<f32>>, StreamId) {
|
||||
fn new_output_stream(
|
||||
engine: &Arc<Engine>, device: &Device,
|
||||
) -> (Arc<dynamic_mixer::DynamicMixerController<f32>>, StreamId) {
|
||||
// Determine the format to use for the new stream.
|
||||
let format = device.default_output_format()
|
||||
.expect("The device doesn't support any format!?");
|
||||
let format = device
|
||||
.default_output_format()
|
||||
.expect("The device doesn't support any format!?");
|
||||
|
||||
let stream_id = engine.events_loop.build_output_stream(device, &format).unwrap();
|
||||
let (mixer_tx, mixer_rx) = {
|
||||
dynamic_mixer::mixer::<f32>(format.channels, format.sample_rate.0)
|
||||
};
|
||||
let stream_id = engine
|
||||
.events_loop
|
||||
.build_output_stream(device, &format)
|
||||
.unwrap();
|
||||
let (mixer_tx, mixer_rx) =
|
||||
{ dynamic_mixer::mixer::<f32>(format.channels, format.sample_rate.0) };
|
||||
|
||||
engine.dynamic_mixers.lock().unwrap().insert(stream_id.clone(), mixer_rx);
|
||||
engine
|
||||
.dynamic_mixers
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(stream_id.clone(), mixer_rx);
|
||||
|
||||
(mixer_tx, stream_id)
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
|
||||
#![cfg_attr(test, deny(missing_docs))]
|
||||
|
||||
extern crate cgmath;
|
||||
#[cfg(feature = "flac")]
|
||||
extern crate claxon;
|
||||
extern crate cpal;
|
||||
|
@ -92,9 +93,9 @@ extern crate hound;
|
|||
extern crate lazy_static;
|
||||
#[cfg(feature = "vorbis")]
|
||||
extern crate lewton;
|
||||
extern crate cgmath;
|
||||
|
||||
pub use cpal::{Device, default_output_device, default_input_device, devices, output_devices, input_devices};
|
||||
pub use cpal::{default_input_device, default_output_device, devices, input_devices,
|
||||
output_devices, Device};
|
||||
|
||||
pub use conversions::Sample;
|
||||
pub use decoder::Decoder;
|
||||
|
@ -119,7 +120,8 @@ pub mod source;
|
|||
/// Plays a sound once. Returns a `Sink` that can be used to control the sound.
|
||||
#[inline]
|
||||
pub fn play_once<R>(device: &Device, input: R) -> Result<Sink, decoder::DecoderError>
|
||||
where R: Read + Seek + Send + 'static
|
||||
where
|
||||
R: Read + Seek + Send + 'static,
|
||||
{
|
||||
let input = decoder::Decoder::new(input)?;
|
||||
let sink = Sink::new(device);
|
||||
|
|
36
src/queue.rs
36
src/queue.rs
|
@ -1,12 +1,12 @@
|
|||
//! Queue that plays sounds one after the other.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
|
||||
use source::Empty;
|
||||
|
@ -27,12 +27,13 @@ use Sample;
|
|||
/// - If you pass `false`, then the queue will report that it has finished playing.
|
||||
///
|
||||
pub fn queue<S>(keep_alive_if_empty: bool) -> (Arc<SourcesQueueInput<S>>, SourcesQueueOutput<S>)
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
let input = Arc::new(SourcesQueueInput {
|
||||
next_sounds: Mutex::new(Vec::new()),
|
||||
keep_alive_if_empty: AtomicBool::new(keep_alive_if_empty),
|
||||
});
|
||||
next_sounds: Mutex::new(Vec::new()),
|
||||
keep_alive_if_empty: AtomicBool::new(keep_alive_if_empty),
|
||||
});
|
||||
|
||||
let output = SourcesQueueOutput {
|
||||
current: Box::new(Empty::<S>::new()) as Box<_>,
|
||||
|
@ -54,12 +55,14 @@ pub struct SourcesQueueInput<S> {
|
|||
}
|
||||
|
||||
impl<S> SourcesQueueInput<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
/// Adds a new source to the end of the queue.
|
||||
#[inline]
|
||||
pub fn append<T>(&self, source: T)
|
||||
where T: Source<Item = S> + Send + 'static
|
||||
where
|
||||
T: Source<Item = S> + Send + 'static,
|
||||
{
|
||||
self.next_sounds
|
||||
.lock()
|
||||
|
@ -72,7 +75,8 @@ impl<S> SourcesQueueInput<S>
|
|||
/// The `Receiver` will be signalled when the sound has finished playing.
|
||||
#[inline]
|
||||
pub fn append_with_signal<T>(&self, source: T) -> Receiver<()>
|
||||
where T: Source<Item = S> + Send + 'static
|
||||
where
|
||||
T: Source<Item = S> + Send + 'static,
|
||||
{
|
||||
let (tx, rx) = mpsc::channel();
|
||||
self.next_sounds
|
||||
|
@ -104,7 +108,8 @@ pub struct SourcesQueueOutput<S> {
|
|||
}
|
||||
|
||||
impl<S> Source for SourcesQueueOutput<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -155,7 +160,8 @@ impl<S> Source for SourcesQueueOutput<S>
|
|||
}
|
||||
|
||||
impl<S> Iterator for SourcesQueueOutput<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
|
@ -182,7 +188,8 @@ impl<S> Iterator for SourcesQueueOutput<S>
|
|||
}
|
||||
|
||||
impl<S> SourcesQueueOutput<S>
|
||||
where S: Sample + Send + 'static
|
||||
where
|
||||
S: Sample + Send + 'static,
|
||||
{
|
||||
// Called when `current` is empty and we must jump to the next element.
|
||||
// Returns `Ok` if the sound should continue playing, or an error if it should stop.
|
||||
|
@ -200,7 +207,10 @@ impl<S> SourcesQueueOutput<S>
|
|||
if self.input.keep_alive_if_empty.load(Ordering::Acquire) {
|
||||
// Play a short silence in order to avoid spinlocking.
|
||||
let silence = Zero::<S>::new(1, 44000); // TODO: meh
|
||||
(Box::new(silence.take_duration(Duration::from_millis(10))) as Box<_>, None)
|
||||
(
|
||||
Box::new(silence.take_duration(Duration::from_millis(10))) as Box<_>,
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
|
|
20
src/sink.rs
20
src/sink.rs
|
@ -1,17 +1,16 @@
|
|||
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::time::Duration;
|
||||
|
||||
use play_raw;
|
||||
use queue;
|
||||
use source::Done;
|
||||
use Device;
|
||||
use Sample;
|
||||
use Source;
|
||||
use source::Done;
|
||||
use play_raw;
|
||||
use queue;
|
||||
|
||||
/// Handle to an device that outputs sounds.
|
||||
///
|
||||
|
@ -56,9 +55,10 @@ impl Sink {
|
|||
/// Appends a sound to the queue of sounds to play.
|
||||
#[inline]
|
||||
pub fn append<S>(&self, source: S)
|
||||
where S: Source + Send + 'static,
|
||||
S::Item: Sample,
|
||||
S::Item: Send
|
||||
where
|
||||
S: Source + Send + 'static,
|
||||
S::Item: Sample,
|
||||
S::Item: Send,
|
||||
{
|
||||
let controls = self.controls.clone();
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `Amplify` object.
|
||||
pub fn amplify<I>(input: I, factor: f32) -> Amplify<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
Amplify {
|
||||
input: input,
|
||||
|
@ -48,8 +49,9 @@ impl<I> Amplify<I> {
|
|||
}
|
||||
|
||||
impl<I> Iterator for Amplify<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -65,14 +67,16 @@ impl<I> Iterator for Amplify<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for Amplify<I>
|
||||
where I: Source + ExactSizeIterator,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source + ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I> Source for Amplify<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -7,7 +7,8 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `BltFilter` object.
|
||||
pub fn low_pass<I>(input: I, freq: u32) -> BltFilter<I>
|
||||
where I: Source<Item = f32>
|
||||
where
|
||||
I: Source<Item = f32>,
|
||||
{
|
||||
BltFilter {
|
||||
input: input,
|
||||
|
@ -58,7 +59,8 @@ impl<I> BltFilter<I> {
|
|||
}
|
||||
|
||||
impl<I> Iterator for BltFilter<I>
|
||||
where I: Source<Item = f32>
|
||||
where
|
||||
I: Source<Item = f32>,
|
||||
{
|
||||
type Item = f32;
|
||||
|
||||
|
@ -99,12 +101,14 @@ impl<I> Iterator for BltFilter<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for BltFilter<I>
|
||||
where I: Source<Item = f32> + ExactSizeIterator
|
||||
where
|
||||
I: Source<Item = f32> + ExactSizeIterator,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I> Source for BltFilter<I>
|
||||
where I: Source<Item = f32>
|
||||
where
|
||||
I: Source<Item = f32>,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -8,8 +8,9 @@ use Source;
|
|||
/// Internal function that builds a `Buffered` object.
|
||||
#[inline]
|
||||
pub fn buffered<I>(input: I) -> Buffered<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let total_duration = input.total_duration();
|
||||
let first_frame = extract(input);
|
||||
|
@ -23,8 +24,9 @@ pub fn buffered<I>(input: I) -> Buffered<I>
|
|||
|
||||
/// Iterator that at the same time extracts data from the iterator and stores it in a buffer.
|
||||
pub struct Buffered<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
/// Immutable reference to the next frame of data. Cannot be `Frame::Input`.
|
||||
current_frame: Arc<Frame<I>>,
|
||||
|
@ -37,8 +39,9 @@ pub struct Buffered<I>
|
|||
}
|
||||
|
||||
enum Frame<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
/// Data that has already been extracted from the iterator. Also contains a pointer to the
|
||||
/// next frame.
|
||||
|
@ -53,8 +56,9 @@ enum Frame<I>
|
|||
}
|
||||
|
||||
struct FrameData<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
data: Vec<I::Item>,
|
||||
channels: u16,
|
||||
|
@ -64,8 +68,9 @@ struct FrameData<I>
|
|||
|
||||
/// Builds a frame from the input iterator.
|
||||
fn extract<I>(mut input: I) -> Arc<Frame<I>>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let frame_len = input.current_frame_len();
|
||||
|
||||
|
@ -75,7 +80,7 @@ fn extract<I>(mut input: I) -> Arc<Frame<I>>
|
|||
|
||||
let channels = input.channels();
|
||||
let rate = input.sample_rate();
|
||||
let data : Vec<I::Item> = input
|
||||
let data: Vec<I::Item> = input
|
||||
.by_ref()
|
||||
.take(cmp::min(frame_len.unwrap_or(32768), 32768))
|
||||
.collect();
|
||||
|
@ -85,16 +90,17 @@ fn extract<I>(mut input: I) -> Arc<Frame<I>>
|
|||
}
|
||||
|
||||
Arc::new(Frame::Data(FrameData {
|
||||
data: data,
|
||||
channels: channels,
|
||||
rate: rate,
|
||||
next: Mutex::new(Arc::new(Frame::Input(Mutex::new(Some(input))))),
|
||||
}))
|
||||
data: data,
|
||||
channels: channels,
|
||||
rate: rate,
|
||||
next: Mutex::new(Arc::new(Frame::Input(Mutex::new(Some(input))))),
|
||||
}))
|
||||
}
|
||||
|
||||
impl<I> Buffered<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
/// Advances to the next frame.
|
||||
fn next_frame(&mut self) {
|
||||
|
@ -123,8 +129,9 @@ impl<I> Buffered<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for Buffered<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -148,7 +155,6 @@ impl<I> Iterator for Buffered<I>
|
|||
&Frame::Input(_) => unreachable!(),
|
||||
};
|
||||
|
||||
|
||||
if advance_frame {
|
||||
self.next_frame();
|
||||
}
|
||||
|
@ -168,8 +174,9 @@ impl<I> Iterator for Buffered<I>
|
|||
}*/
|
||||
|
||||
impl<I> Source for Buffered<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -205,8 +212,9 @@ impl<I> Source for Buffered<I>
|
|||
}
|
||||
|
||||
impl<I> Clone for Buffered<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn clone(&self) -> Buffered<I> {
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use std::time::Duration;
|
||||
use Sample;
|
||||
use Source;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Combines channels in input into a single mono source, then plays that mono sound
|
||||
/// to each channel at the volume given for that channel.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ChannelVolume<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
input: I,
|
||||
// Channel number is used as index for amplification value.
|
||||
|
@ -18,12 +19,14 @@ pub struct ChannelVolume<I>
|
|||
}
|
||||
|
||||
impl<I> ChannelVolume<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
pub fn new(mut input: I, channel_volumes: Vec<f32>) -> ChannelVolume<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let mut sample = I::Item::zero_value();
|
||||
for _ in 0 .. input.channels() {
|
||||
|
@ -47,8 +50,9 @@ impl<I> ChannelVolume<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for ChannelVolume<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -80,14 +84,16 @@ impl<I> Iterator for ChannelVolume<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for ChannelVolume<I>
|
||||
where I: Source + ExactSizeIterator,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source + ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I> Source for ChannelVolume<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -5,8 +5,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `Delay` object.
|
||||
pub fn delay<I>(input: I, duration: Duration) -> Delay<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let duration_ns = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
|
||||
let samples = duration_ns * input.sample_rate() as u64 * input.channels() as u64 / 1000000000;
|
||||
|
@ -21,8 +22,9 @@ pub fn delay<I>(input: I, duration: Duration) -> Delay<I>
|
|||
/// A source that delays the given source by a certain amount.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Delay<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
input: I,
|
||||
remaining_samples: usize,
|
||||
|
@ -30,8 +32,9 @@ pub struct Delay<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for Delay<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
|
@ -40,7 +43,6 @@ impl<I> Iterator for Delay<I>
|
|||
if self.remaining_samples >= 1 {
|
||||
self.remaining_samples -= 1;
|
||||
Some(Sample::zero_value())
|
||||
|
||||
} else {
|
||||
self.input.next()
|
||||
}
|
||||
|
@ -49,13 +51,17 @@ impl<I> Iterator for Delay<I>
|
|||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (min, max) = self.input.size_hint();
|
||||
(min + self.remaining_samples, max.map(|v| v + self.remaining_samples))
|
||||
(
|
||||
min + self.remaining_samples,
|
||||
max.map(|v| v + self.remaining_samples),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Source for Delay<I>
|
||||
where I: Iterator + Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Iterator + Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use Sample;
|
||||
use Source;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::Duration;
|
||||
|
||||
/// WHen the inner source is empty this decrements an AtomicUsize
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Done<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
input: I,
|
||||
signal: Arc<AtomicUsize>,
|
||||
|
@ -16,18 +17,24 @@ pub struct Done<I>
|
|||
}
|
||||
|
||||
impl<I> Done<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
pub fn new(input: I, signal: Arc<AtomicUsize>) -> Done<I> {
|
||||
Done { input, signal, signal_sent: false }
|
||||
Done {
|
||||
input,
|
||||
signal,
|
||||
signal_sent: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Source> Iterator for Done<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -43,8 +50,9 @@ impl<I: Source> Iterator for Done<I>
|
|||
}
|
||||
|
||||
impl<I> Source for Done<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
use Sample;
|
||||
use Source;
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
use Sample;
|
||||
use Source;
|
||||
|
||||
/// An empty source.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -25,7 +24,8 @@ impl<S> Iterator for Empty<S> {
|
|||
}
|
||||
|
||||
impl<S> Source for Empty<S>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -5,8 +5,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `FadeIn` object.
|
||||
pub fn fadein<I>(input: I, duration: Duration) -> FadeIn<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let duration = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
|
||||
|
||||
|
@ -20,8 +21,9 @@ pub fn fadein<I>(input: I, duration: Duration) -> FadeIn<I>
|
|||
/// Filter that modifies each sample by a given value.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FadeIn<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
input: I,
|
||||
remaining_ns: f32,
|
||||
|
@ -29,8 +31,9 @@ pub struct FadeIn<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for FadeIn<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -41,8 +44,8 @@ impl<I> Iterator for FadeIn<I>
|
|||
}
|
||||
|
||||
let factor = 1.0 - self.remaining_ns / self.total_ns;
|
||||
self.remaining_ns -= 1000000000.0 /
|
||||
(self.input.sample_rate() as f32 * self.channels() as f32);
|
||||
self.remaining_ns -=
|
||||
1000000000.0 / (self.input.sample_rate() as f32 * self.channels() as f32);
|
||||
self.input.next().map(|value| value.amplify(factor))
|
||||
}
|
||||
|
||||
|
@ -53,14 +56,16 @@ impl<I> Iterator for FadeIn<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for FadeIn<I>
|
||||
where I: Source + ExactSizeIterator,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source + ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I> Source for FadeIn<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
use source::FromIter;
|
||||
use source::from_iter;
|
||||
use source::FromIter;
|
||||
|
||||
/// Builds a source that chains sources built from a factory.
|
||||
///
|
||||
|
@ -10,7 +9,8 @@ use source::from_iter;
|
|||
///
|
||||
/// If the `factory` closure returns `None`, then the sound ends.
|
||||
pub fn from_factory<F, S>(factory: F) -> FromIter<FromFactoryIter<F>>
|
||||
where F: FnMut() -> Option<S>
|
||||
where
|
||||
F: FnMut() -> Option<S>,
|
||||
{
|
||||
from_iter(FromFactoryIter { factory: factory })
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ pub struct FromFactoryIter<F> {
|
|||
}
|
||||
|
||||
impl<F, S> Iterator for FromFactoryIter<F>
|
||||
where F: FnMut() -> Option<S>
|
||||
where
|
||||
F: FnMut() -> Option<S>,
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ use Source;
|
|||
///
|
||||
/// If the `iterator` produces `None`, then the sound ends.
|
||||
pub fn from_iter<I>(iterator: I) -> FromIter<I::IntoIter>
|
||||
where I: IntoIterator
|
||||
where
|
||||
I: IntoIterator,
|
||||
{
|
||||
let mut iterator = iterator.into_iter();
|
||||
let first_source = iterator.next();
|
||||
|
@ -25,7 +26,8 @@ pub fn from_iter<I>(iterator: I) -> FromIter<I::IntoIter>
|
|||
/// A source that chains sources provided by an iterator.
|
||||
#[derive(Clone)]
|
||||
pub struct FromIter<I>
|
||||
where I: Iterator
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
// The iterator that provides sources.
|
||||
iterator: I,
|
||||
|
@ -34,9 +36,10 @@ pub struct FromIter<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for FromIter<I>
|
||||
where I: Iterator,
|
||||
I::Item: Iterator + Source,
|
||||
<I::Item as Iterator>::Item: Sample
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Iterator + Source,
|
||||
<I::Item as Iterator>::Item: Sample,
|
||||
{
|
||||
type Item = <I::Item as Iterator>::Item;
|
||||
|
||||
|
@ -68,9 +71,10 @@ impl<I> Iterator for FromIter<I>
|
|||
}
|
||||
|
||||
impl<I> Source for FromIter<I>
|
||||
where I: Iterator,
|
||||
I::Item: Iterator + Source,
|
||||
<I::Item as Iterator>::Item: Sample
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Iterator + Source,
|
||||
<I::Item as Iterator>::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -137,19 +141,20 @@ impl<I> Source for FromIter<I>
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use buffer::SamplesBuffer;
|
||||
use source::Source;
|
||||
use source::from_iter;
|
||||
use source::Source;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let mut rx =
|
||||
from_iter((0 .. 2).map(|n| if n == 0 {
|
||||
SamplesBuffer::new(1, 48000, vec![10i16, -10, 10, -10])
|
||||
} else if n == 1 {
|
||||
SamplesBuffer::new(2, 96000, vec![5i16, 5, 5, 5])
|
||||
} else {
|
||||
unreachable!()
|
||||
}));
|
||||
let mut rx = from_iter((0 .. 2).map(|n| {
|
||||
if n == 0 {
|
||||
SamplesBuffer::new(1, 48000, vec![10i16, -10, 10, -10])
|
||||
} else if n == 1 {
|
||||
SamplesBuffer::new(2, 96000, vec![5i16, 5, 5, 5])
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}));
|
||||
|
||||
assert_eq!(rx.channels(), 1);
|
||||
assert_eq!(rx.sample_rate(), 48000);
|
||||
|
|
|
@ -8,10 +8,11 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `Mix` object.
|
||||
pub fn mix<I1, I2>(input1: I1, input2: I2) -> Mix<I1, I2>
|
||||
where I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample
|
||||
where
|
||||
I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample,
|
||||
{
|
||||
let channels = input1.channels();
|
||||
let rate = input1.sample_rate();
|
||||
|
@ -25,20 +26,22 @@ pub fn mix<I1, I2>(input1: I1, input2: I2) -> Mix<I1, I2>
|
|||
/// Filter that modifies each sample by a given value.
|
||||
#[derive(Clone)]
|
||||
pub struct Mix<I1, I2>
|
||||
where I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample
|
||||
where
|
||||
I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample,
|
||||
{
|
||||
input1: UniformSourceIterator<I1, I1::Item>,
|
||||
input2: UniformSourceIterator<I2, I1::Item>,
|
||||
}
|
||||
|
||||
impl<I1, I2> Iterator for Mix<I1, I2>
|
||||
where I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample
|
||||
where
|
||||
I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample,
|
||||
{
|
||||
type Item = I1::Item;
|
||||
|
||||
|
@ -71,18 +74,20 @@ impl<I1, I2> Iterator for Mix<I1, I2>
|
|||
}
|
||||
|
||||
impl<I1, I2> ExactSizeIterator for Mix<I1, I2>
|
||||
where I1: Source + ExactSizeIterator,
|
||||
I1::Item: Sample,
|
||||
I2: Source + ExactSizeIterator,
|
||||
I2::Item: Sample
|
||||
where
|
||||
I1: Source + ExactSizeIterator,
|
||||
I1::Item: Sample,
|
||||
I2: Source + ExactSizeIterator,
|
||||
I2::Item: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I1, I2> Source for Mix<I1, I2>
|
||||
where I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample
|
||||
where
|
||||
I1: Source,
|
||||
I1::Item: Sample,
|
||||
I2: Source,
|
||||
I2::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -12,8 +12,8 @@ pub use self::delay::Delay;
|
|||
pub use self::done::Done;
|
||||
pub use self::empty::Empty;
|
||||
pub use self::fadein::FadeIn;
|
||||
pub use self::from_factory::{FromFactoryIter, from_factory};
|
||||
pub use self::from_iter::{FromIter, from_iter};
|
||||
pub use self::from_factory::{from_factory, FromFactoryIter};
|
||||
pub use self::from_iter::{from_iter, FromIter};
|
||||
pub use self::mix::Mix;
|
||||
pub use self::pausable::Pausable;
|
||||
pub use self::periodic::PeriodicAccess;
|
||||
|
@ -30,6 +30,7 @@ pub use self::zero::Zero;
|
|||
mod amplify;
|
||||
mod blt;
|
||||
mod buffered;
|
||||
mod channel_volume;
|
||||
mod delay;
|
||||
mod done;
|
||||
mod empty;
|
||||
|
@ -42,7 +43,6 @@ mod periodic;
|
|||
mod repeat;
|
||||
mod samples_converter;
|
||||
mod sine;
|
||||
mod channel_volume;
|
||||
mod spatial;
|
||||
mod speed;
|
||||
mod stoppable;
|
||||
|
@ -118,7 +118,8 @@ mod zero;
|
|||
/// channels can potentially change.
|
||||
///
|
||||
pub trait Source: Iterator
|
||||
where Self::Item: Sample
|
||||
where
|
||||
Self::Item: Sample,
|
||||
{
|
||||
/// Returns the number of samples before the current frame ends. `None` means "infinite" or
|
||||
/// "until the sound ends".
|
||||
|
@ -142,7 +143,8 @@ pub trait Source: Iterator
|
|||
/// Stores the source in a buffer in addition to returning it. This iterator can be cloned.
|
||||
#[inline]
|
||||
fn buffered(self) -> Buffered<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
buffered::buffered(self)
|
||||
}
|
||||
|
@ -150,9 +152,10 @@ pub trait Source: Iterator
|
|||
/// Mixes this source with another one.
|
||||
#[inline]
|
||||
fn mix<S>(self, other: S) -> Mix<Self, S>
|
||||
where Self: Sized,
|
||||
S: Source,
|
||||
S::Item: Sample
|
||||
where
|
||||
Self: Sized,
|
||||
S: Source,
|
||||
S::Item: Sample,
|
||||
{
|
||||
mix::mix(self, other)
|
||||
}
|
||||
|
@ -163,7 +166,8 @@ pub trait Source: Iterator
|
|||
/// proportional to the size of the sound.
|
||||
#[inline]
|
||||
fn repeat_infinite(self) -> Repeat<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
repeat::repeat(self)
|
||||
}
|
||||
|
@ -171,7 +175,8 @@ pub trait Source: Iterator
|
|||
/// Takes a certain duration of this source and then stops.
|
||||
#[inline]
|
||||
fn take_duration(self, duration: Duration) -> TakeDuration<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
take::take_duration(self, duration)
|
||||
}
|
||||
|
@ -182,7 +187,8 @@ pub trait Source: Iterator
|
|||
/// source.
|
||||
#[inline]
|
||||
fn delay(self, duration: Duration) -> Delay<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
delay::delay(self, duration)
|
||||
}
|
||||
|
@ -190,7 +196,8 @@ pub trait Source: Iterator
|
|||
/// Amplifies the sound by the given value.
|
||||
#[inline]
|
||||
fn amplify(self, value: f32) -> Amplify<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
amplify::amplify(self, value)
|
||||
}
|
||||
|
@ -198,7 +205,8 @@ pub trait Source: Iterator
|
|||
/// Fades in the sound.
|
||||
#[inline]
|
||||
fn fade_in(self, duration: Duration) -> FadeIn<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fadein::fadein(self, duration)
|
||||
}
|
||||
|
@ -206,8 +214,9 @@ pub trait Source: Iterator
|
|||
/// Calls the `access` closure on `Self` every time `period` elapsed.
|
||||
#[inline]
|
||||
fn periodic_access<F>(self, period: Duration, access: F) -> PeriodicAccess<Self, F>
|
||||
where Self: Sized,
|
||||
F: FnMut(&mut Self)
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(&mut Self),
|
||||
{
|
||||
periodic::periodic(self, period, access)
|
||||
}
|
||||
|
@ -215,7 +224,8 @@ pub trait Source: Iterator
|
|||
/// Changes the play speed of the sound. Does not adjust the samples, only the play speed.
|
||||
#[inline]
|
||||
fn speed(self, ratio: f32) -> Speed<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
speed::speed(self, ratio)
|
||||
}
|
||||
|
@ -234,7 +244,8 @@ pub trait Source: Iterator
|
|||
/// ```
|
||||
#[inline]
|
||||
fn reverb(self, duration: Duration, amplitude: f32) -> Mix<Self, Delay<Amplify<Self>>>
|
||||
where Self: Sized + Clone
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
{
|
||||
let echo = self.clone().amplify(amplitude).delay(duration);
|
||||
self.mix(echo)
|
||||
|
@ -243,8 +254,9 @@ pub trait Source: Iterator
|
|||
/// Converts the samples of this source to another type.
|
||||
#[inline]
|
||||
fn convert_samples<D>(self) -> SamplesConverter<Self, D>
|
||||
where Self: Sized,
|
||||
D: Sample
|
||||
where
|
||||
Self: Sized,
|
||||
D: Sample,
|
||||
{
|
||||
SamplesConverter::new(self)
|
||||
}
|
||||
|
@ -253,7 +265,8 @@ pub trait Source: Iterator
|
|||
// TODO: add example
|
||||
#[inline]
|
||||
fn pausable(self, initially_paused: bool) -> Pausable<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
pausable::pausable(self, initially_paused)
|
||||
}
|
||||
|
@ -262,7 +275,8 @@ pub trait Source: Iterator
|
|||
// TODO: add example
|
||||
#[inline]
|
||||
fn stoppable(self) -> Stoppable<Self>
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
stoppable::stoppable(self)
|
||||
}
|
||||
|
@ -271,15 +285,17 @@ pub trait Source: Iterator
|
|||
/// **Warning**: Probably buggy.
|
||||
#[inline]
|
||||
fn low_pass(self, freq: u32) -> BltFilter<Self>
|
||||
where Self: Sized,
|
||||
Self: Source<Item = f32>
|
||||
where
|
||||
Self: Sized,
|
||||
Self: Source<Item = f32>,
|
||||
{
|
||||
blt::low_pass(self, freq)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Source for Box<Source<Item = S>>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -303,7 +319,8 @@ impl<S> Source for Box<Source<Item = S>>
|
|||
}
|
||||
|
||||
impl<S> Source for Box<Source<Item = S> + Send>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -327,7 +344,8 @@ impl<S> Source for Box<Source<Item = S> + Send>
|
|||
}
|
||||
|
||||
impl<S> Source for Box<Source<Item = S> + Send + Sync>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -46,8 +46,9 @@ impl<I> Pausable<I> {
|
|||
}
|
||||
|
||||
impl<I> Iterator for Pausable<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -67,8 +68,9 @@ impl<I> Iterator for Pausable<I>
|
|||
}
|
||||
|
||||
impl<I> Source for Pausable<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -5,8 +5,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `PeriodicAccess` object.
|
||||
pub fn periodic<I, F>(source: I, period: Duration, modifier: F) -> PeriodicAccess<I, F>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
// TODO: handle the fact that the samples rate can change
|
||||
// TODO: generally, just wrong
|
||||
|
@ -38,9 +39,10 @@ pub struct PeriodicAccess<I, F> {
|
|||
}
|
||||
|
||||
impl<I, F> Iterator for PeriodicAccess<I, F>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
F: FnMut(&mut I)
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
F: FnMut(&mut I),
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -62,9 +64,10 @@ impl<I, F> Iterator for PeriodicAccess<I, F>
|
|||
}
|
||||
|
||||
impl<I, F> Source for PeriodicAccess<I, F>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
F: FnMut(&mut I)
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
F: FnMut(&mut I),
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -7,8 +7,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `Repeat` object.
|
||||
pub fn repeat<I>(input: I) -> Repeat<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let input = input.buffered();
|
||||
Repeat {
|
||||
|
@ -20,16 +21,18 @@ pub fn repeat<I>(input: I) -> Repeat<I>
|
|||
/// A source that repeats the given source.
|
||||
#[derive(Clone)]
|
||||
pub struct Repeat<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
inner: Buffered<I>,
|
||||
next: Buffered<I>,
|
||||
}
|
||||
|
||||
impl<I> Iterator for Repeat<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
|
@ -51,8 +54,9 @@ impl<I> Iterator for Repeat<I>
|
|||
}
|
||||
|
||||
impl<I> Source for Repeat<I>
|
||||
where I: Iterator + Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Iterator + Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -12,18 +12,20 @@ use Source;
|
|||
/// channels and samples rate have been passed to `new`.
|
||||
#[derive(Clone)]
|
||||
pub struct SamplesConverter<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
inner: I,
|
||||
dest: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<I, D> SamplesConverter<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
#[inline]
|
||||
pub fn new(input: I) -> SamplesConverter<I, D> {
|
||||
|
@ -35,9 +37,10 @@ impl<I, D> SamplesConverter<I, D>
|
|||
}
|
||||
|
||||
impl<I, D> Iterator for SamplesConverter<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
type Item = D;
|
||||
|
||||
|
@ -53,16 +56,18 @@ impl<I, D> Iterator for SamplesConverter<I, D>
|
|||
}
|
||||
|
||||
impl<I, D> ExactSizeIterator for SamplesConverter<I, D>
|
||||
where I: Source + ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source + ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I, D> Source for SamplesConverter<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
use Source;
|
||||
use std::time::Duration;
|
||||
use Source;
|
||||
|
||||
/// An infinite source that produces a sine.
|
||||
///
|
||||
|
|
|
@ -1,37 +1,44 @@
|
|||
use Sample;
|
||||
use Source;
|
||||
use cgmath::{InnerSpace, Point3};
|
||||
use source::ChannelVolume;
|
||||
use std::fmt::Debug;
|
||||
use std::time::Duration;
|
||||
use Sample;
|
||||
use Source;
|
||||
|
||||
/// Combines channels in input into a single mono source, then plays that mono sound
|
||||
/// to each channel at the volume given for that channel.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Spatial<I>
|
||||
where I: Source,
|
||||
I::Item: Sample + Debug
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample + Debug,
|
||||
{
|
||||
input: ChannelVolume<I>,
|
||||
}
|
||||
|
||||
impl<I> Spatial<I>
|
||||
where I: Source,
|
||||
I::Item: Sample + Debug
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample + Debug,
|
||||
{
|
||||
pub fn new(input: I, emitter_position: [f32; 3], left_ear: [f32; 3], right_ear: [f32; 3])
|
||||
-> Spatial<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
pub fn new(
|
||||
input: I, emitter_position: [f32; 3], left_ear: [f32; 3], right_ear: [f32; 3],
|
||||
) -> Spatial<I>
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
let mut ret = Spatial { input: ChannelVolume::new(input, vec![0.0, 0.0]) };
|
||||
let mut ret = Spatial {
|
||||
input: ChannelVolume::new(input, vec![0.0, 0.0]),
|
||||
};
|
||||
ret.set_positions(emitter_position, left_ear, right_ear);
|
||||
ret
|
||||
}
|
||||
|
||||
/// Sets the position of the emitter and ears in the 3D world.
|
||||
pub fn set_positions(&mut self, emitter_pos: [f32; 3], left_ear: [f32; 3],
|
||||
right_ear: [f32; 3]) {
|
||||
pub fn set_positions(
|
||||
&mut self, emitter_pos: [f32; 3], left_ear: [f32; 3], right_ear: [f32; 3],
|
||||
) {
|
||||
let emitter_position = Point3::from(emitter_pos);
|
||||
let left_ear = Point3::from(left_ear);
|
||||
let right_ear = Point3::from(right_ear);
|
||||
|
@ -50,8 +57,9 @@ impl<I> Spatial<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for Spatial<I>
|
||||
where I: Source,
|
||||
I::Item: Sample + Debug
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample + Debug,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -67,14 +75,16 @@ impl<I> Iterator for Spatial<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for Spatial<I>
|
||||
where I: Source + ExactSizeIterator,
|
||||
I::Item: Sample + Debug
|
||||
where
|
||||
I: Source + ExactSizeIterator,
|
||||
I::Item: Sample + Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I> Source for Spatial<I>
|
||||
where I: Source,
|
||||
I::Item: Sample + Debug
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample + Debug,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -5,8 +5,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `Speed` object.
|
||||
pub fn speed<I>(input: I, factor: f32) -> Speed<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
Speed {
|
||||
input: input,
|
||||
|
@ -17,16 +18,18 @@ pub fn speed<I>(input: I, factor: f32) -> Speed<I>
|
|||
/// Filter that modifies each sample by a given value.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Speed<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
input: I,
|
||||
factor: f32,
|
||||
}
|
||||
|
||||
impl<I> Iterator for Speed<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -42,14 +45,16 @@ impl<I> Iterator for Speed<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for Speed<I>
|
||||
where I: Source + ExactSizeIterator,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source + ExactSizeIterator,
|
||||
I::Item: Sample,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I> Source for Speed<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -72,8 +77,10 @@ impl<I> Source for Speed<I>
|
|||
if let Some(duration) = self.input.total_duration() {
|
||||
let as_ns = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
|
||||
let new_val = (as_ns as f32 / self.factor) as u64;
|
||||
Some(Duration::new(new_val / 1000000000, (new_val % 1000000000) as u32))
|
||||
|
||||
Some(Duration::new(
|
||||
new_val / 1000000000,
|
||||
(new_val % 1000000000) as u32,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -44,8 +44,9 @@ impl<I> Stoppable<I> {
|
|||
}
|
||||
|
||||
impl<I> Iterator for Stoppable<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
|
@ -65,8 +66,9 @@ impl<I> Iterator for Stoppable<I>
|
|||
}
|
||||
|
||||
impl<I> Source for Stoppable<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -5,8 +5,9 @@ use Source;
|
|||
|
||||
/// Internal function that builds a `Repeat` object.
|
||||
pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
TakeDuration {
|
||||
input: input,
|
||||
|
@ -18,8 +19,9 @@ pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I>
|
|||
/// A source that repeats the given source.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TakeDuration<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
input: I,
|
||||
remaining_duration: Duration,
|
||||
|
@ -27,8 +29,9 @@ pub struct TakeDuration<I>
|
|||
}
|
||||
|
||||
impl<I> TakeDuration<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
/// Returns the duration elapsed for each sample extracted.
|
||||
#[inline]
|
||||
|
@ -40,8 +43,9 @@ impl<I> TakeDuration<I>
|
|||
}
|
||||
|
||||
impl<I> Iterator for TakeDuration<I>
|
||||
where I: Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
|
@ -50,12 +54,10 @@ impl<I> Iterator for TakeDuration<I>
|
|||
|
||||
if self.remaining_duration <= duration_per_sample {
|
||||
None
|
||||
|
||||
} else {
|
||||
if let Some(sample) = self.input.next() {
|
||||
self.remaining_duration = self.remaining_duration - duration_per_sample;
|
||||
Some(sample)
|
||||
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -66,15 +68,16 @@ impl<I> Iterator for TakeDuration<I>
|
|||
}
|
||||
|
||||
impl<I> Source for TakeDuration<I>
|
||||
where I: Iterator + Source,
|
||||
I::Item: Sample
|
||||
where
|
||||
I: Iterator + Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
let remaining_nanosecs = self.remaining_duration.as_secs() * 1000000000 +
|
||||
self.remaining_duration.subsec_nanos() as u64;
|
||||
let remaining_samples = remaining_nanosecs * self.input.sample_rate() as u64 *
|
||||
self.channels() as u64 / 1000000000;
|
||||
let remaining_nanosecs = self.remaining_duration.as_secs() * 1000000000
|
||||
+ self.remaining_duration.subsec_nanos() as u64;
|
||||
let remaining_samples = remaining_nanosecs * self.input.sample_rate() as u64
|
||||
* self.channels() as u64 / 1000000000;
|
||||
|
||||
if let Some(value) = self.input.current_frame_len() {
|
||||
if (value as u64) < remaining_samples {
|
||||
|
@ -105,7 +108,6 @@ impl<I> Source for TakeDuration<I>
|
|||
} else {
|
||||
Some(self.requested_duration)
|
||||
}
|
||||
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -17,9 +17,10 @@ use Source;
|
|||
/// channels and samples rate have been passed to `new`.
|
||||
#[derive(Clone)]
|
||||
pub struct UniformSourceIterator<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
inner: Option<DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D>>,
|
||||
target_channels: u16,
|
||||
|
@ -28,13 +29,15 @@ pub struct UniformSourceIterator<I, D>
|
|||
}
|
||||
|
||||
impl<I, D> UniformSourceIterator<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
#[inline]
|
||||
pub fn new(input: I, target_channels: u16, target_sample_rate: u32)
|
||||
-> UniformSourceIterator<I, D> {
|
||||
pub fn new(
|
||||
input: I, target_channels: u16, target_sample_rate: u32,
|
||||
) -> UniformSourceIterator<I, D> {
|
||||
let total_duration = input.total_duration();
|
||||
let input = UniformSourceIterator::bootstrap(input, target_channels, target_sample_rate);
|
||||
|
||||
|
@ -47,8 +50,9 @@ impl<I, D> UniformSourceIterator<I, D>
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn bootstrap(input: I, target_channels: u16, target_sample_rate: u32)
|
||||
-> DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D> {
|
||||
fn bootstrap(
|
||||
input: I, target_channels: u16, target_sample_rate: u32,
|
||||
) -> DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D> {
|
||||
let frame_len = input.current_frame_len();
|
||||
|
||||
let from_channels = input.channels();
|
||||
|
@ -58,10 +62,12 @@ impl<I, D> UniformSourceIterator<I, D>
|
|||
iter: input,
|
||||
n: frame_len,
|
||||
};
|
||||
let input = SampleRateConverter::new(input,
|
||||
cpal::SampleRate(from_sample_rate),
|
||||
cpal::SampleRate(target_sample_rate),
|
||||
from_channels);
|
||||
let input = SampleRateConverter::new(
|
||||
input,
|
||||
cpal::SampleRate(from_sample_rate),
|
||||
cpal::SampleRate(target_sample_rate),
|
||||
from_channels,
|
||||
);
|
||||
let input = ChannelCountConverter::new(input, from_channels, target_channels);
|
||||
let input = DataConverter::new(input);
|
||||
|
||||
|
@ -70,9 +76,10 @@ impl<I, D> UniformSourceIterator<I, D>
|
|||
}
|
||||
|
||||
impl<I, D> Iterator for UniformSourceIterator<I, D>
|
||||
where I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
type Item = D;
|
||||
|
||||
|
@ -105,9 +112,10 @@ impl<I, D> Iterator for UniformSourceIterator<I, D>
|
|||
}
|
||||
|
||||
impl<I, D> Source for UniformSourceIterator<I, D>
|
||||
where I: Iterator + Source,
|
||||
I::Item: Sample,
|
||||
D: Sample
|
||||
where
|
||||
I: Iterator + Source,
|
||||
I::Item: Sample,
|
||||
D: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
@ -137,7 +145,8 @@ struct Take<I> {
|
|||
}
|
||||
|
||||
impl<I> Iterator for Take<I>
|
||||
where I: Iterator
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
|
@ -150,7 +159,6 @@ impl<I> Iterator for Take<I>
|
|||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
} else {
|
||||
self.iter.next()
|
||||
}
|
||||
|
@ -169,7 +177,6 @@ impl<I> Iterator for Take<I>
|
|||
};
|
||||
|
||||
(lower, upper)
|
||||
|
||||
} else {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
@ -177,6 +184,7 @@ impl<I> Iterator for Take<I>
|
|||
}
|
||||
|
||||
impl<I> ExactSizeIterator for Take<I>
|
||||
where I: ExactSizeIterator
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
use Sample;
|
||||
use Source;
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
use Sample;
|
||||
use Source;
|
||||
|
||||
/// An infinite source that produces zero.
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -24,7 +23,8 @@ impl<S> Zero<S> {
|
|||
}
|
||||
|
||||
impl<S> Iterator for Zero<S>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
|
@ -35,7 +35,8 @@ impl<S> Iterator for Zero<S>
|
|||
}
|
||||
|
||||
impl<S> Source for Zero<S>
|
||||
where S: Sample
|
||||
where
|
||||
S: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
|
||||
use Device;
|
||||
use Sample;
|
||||
use Sink;
|
||||
use Source;
|
||||
use source::Spatial;
|
||||
use std::f32;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
use Device;
|
||||
use Sample;
|
||||
use Sink;
|
||||
use Source;
|
||||
|
||||
pub struct SpatialSink {
|
||||
sink: Sink,
|
||||
|
@ -23,16 +22,16 @@ struct SoundPositions {
|
|||
impl SpatialSink {
|
||||
/// Builds a new `SpatialSink`.
|
||||
#[inline]
|
||||
pub fn new(device: &Device, emitter_position: [f32; 3], left_ear: [f32; 3],
|
||||
right_ear: [f32; 3])
|
||||
-> SpatialSink {
|
||||
pub fn new(
|
||||
device: &Device, emitter_position: [f32; 3], left_ear: [f32; 3], right_ear: [f32; 3],
|
||||
) -> SpatialSink {
|
||||
SpatialSink {
|
||||
sink: Sink::new(device),
|
||||
positions: Arc::new(Mutex::new(SoundPositions {
|
||||
emitter_position,
|
||||
left_ear,
|
||||
right_ear,
|
||||
})),
|
||||
emitter_position,
|
||||
left_ear,
|
||||
right_ear,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,19 +53,21 @@ impl SpatialSink {
|
|||
/// Appends a sound to the queue of sounds to play.
|
||||
#[inline]
|
||||
pub fn append<S>(&self, source: S)
|
||||
where S: Source + Send + 'static,
|
||||
S::Item: Sample + Send + Debug
|
||||
where
|
||||
S: Source + Send + 'static,
|
||||
S::Item: Sample + Send + Debug,
|
||||
{
|
||||
let positions = self.positions.clone();
|
||||
let pos_lock = self.positions.lock().unwrap();
|
||||
let source = Spatial::new(source,
|
||||
pos_lock.emitter_position,
|
||||
pos_lock.left_ear,
|
||||
pos_lock.right_ear)
|
||||
.periodic_access(Duration::from_millis(10), move |i| {
|
||||
let pos = positions.lock().unwrap();
|
||||
i.set_positions(pos.emitter_position, pos.left_ear, pos.right_ear);
|
||||
});
|
||||
let source = Spatial::new(
|
||||
source,
|
||||
pos_lock.emitter_position,
|
||||
pos_lock.left_ear,
|
||||
pos_lock.right_ear,
|
||||
).periodic_access(Duration::from_millis(10), move |i| {
|
||||
let pos = positions.lock().unwrap();
|
||||
i.set_positions(pos.emitter_position, pos.left_ear, pos.right_ear);
|
||||
});
|
||||
self.sink.append(source);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue