mirror of
https://github.com/RustAudio/rodio
synced 2024-12-13 13:42:34 +00:00
commit
0b82c9077c
21 changed files with 195 additions and 111 deletions
|
@ -15,7 +15,9 @@ fn main() {
|
|||
thread::sleep(Duration::from_millis(1500));
|
||||
|
||||
let file = std::fs::File::open("examples/beep2.wav").unwrap();
|
||||
rodio::play_once(&endpoint, BufReader::new(file)).unwrap().detach();
|
||||
rodio::play_once(&endpoint, BufReader::new(file))
|
||||
.unwrap()
|
||||
.detach();
|
||||
println!("Started beep2");
|
||||
|
||||
thread::sleep(Duration::from_millis(1500));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! The `SamplesBuffer` struct can be used to treat a list of values as a `Source`.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//!
|
||||
//! ```
|
||||
//! use rodio::buffer::SamplesBuffer;
|
||||
//! let _ = SamplesBuffer::new(1, 44100, vec![1i16, 2, 3, 4, 5, 6]);
|
||||
|
@ -25,7 +25,9 @@ pub struct SamplesBuffer<S> {
|
|||
duration: Duration,
|
||||
}
|
||||
|
||||
impl<S> SamplesBuffer<S> where S: Sample {
|
||||
impl<S> SamplesBuffer<S>
|
||||
where S: Sample
|
||||
{
|
||||
/// Builds a new `SamplesBuffer`.
|
||||
///
|
||||
/// # Panic
|
||||
|
@ -42,8 +44,10 @@ impl<S> SamplesBuffer<S> where S: Sample {
|
|||
assert!(samples_rate != 0);
|
||||
|
||||
let data = data.into();
|
||||
let duration_ns = 1_000_000_000u64.checked_mul(data.len() as u64).unwrap() / samples_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() /
|
||||
samples_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(),
|
||||
|
@ -54,7 +58,9 @@ impl<S> SamplesBuffer<S> where S: Sample {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Source for SamplesBuffer<S> where S: Sample {
|
||||
impl<S> Source for SamplesBuffer<S>
|
||||
where S: Sample
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
None
|
||||
|
@ -76,7 +82,9 @@ impl<S> Source for SamplesBuffer<S> where S: Sample {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Iterator for SamplesBuffer<S> where S: Sample {
|
||||
impl<S> Iterator for SamplesBuffer<S>
|
||||
where S: Sample
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -84,8 +84,9 @@ impl<I> Iterator for ChannelsCountConverter<I>
|
|||
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)
|
||||
}
|
||||
|
|
|
@ -64,8 +64,14 @@ impl<I> SamplesRateConverter<I>
|
|||
debug_assert_eq!(from, gcd);
|
||||
(Vec::new(), Vec::new())
|
||||
} else {
|
||||
let first = input.by_ref().take(num_channels as usize).collect::<Vec<_>>();
|
||||
let next = input.by_ref().take(num_channels as usize).collect::<Vec<_>>();
|
||||
let first = input
|
||||
.by_ref()
|
||||
.take(num_channels as usize)
|
||||
.collect::<Vec<_>>();
|
||||
let next = input
|
||||
.by_ref()
|
||||
.take(num_channels as usize)
|
||||
.collect::<Vec<_>>();
|
||||
(first, next)
|
||||
};
|
||||
|
||||
|
@ -153,7 +159,10 @@ impl<I> Iterator for SamplesRateConverter<I>
|
|||
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() {
|
||||
self.current_frame
|
||||
.iter()
|
||||
.zip(self.next_frame.iter())
|
||||
.enumerate() {
|
||||
let sample = Sample::lerp(cur.clone(), next.clone(), numerator, self.to);
|
||||
|
||||
if off == 0 {
|
||||
|
@ -197,10 +206,11 @@ impl<I> Iterator for SamplesRateConverter<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;
|
||||
|
|
|
@ -32,15 +32,15 @@ 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,
|
||||
samples_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,
|
||||
samples_rate: spec.sample_rate,
|
||||
channels: spec.channels as u16,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,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 {
|
||||
|
@ -98,7 +100,7 @@ impl<R> Iterator for FlacDecoder<R>
|
|||
Ok(Some(block)) => {
|
||||
self.current_block_channel_len = (block.len() / block.channels()) as usize;
|
||||
self.current_block = block.into_buffer();
|
||||
},
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,9 @@ impl<R> VorbisDecoder<R>
|
|||
};
|
||||
|
||||
Ok(VorbisDecoder {
|
||||
stream_reader: stream_reader,
|
||||
current_data: data.into_iter(),
|
||||
})
|
||||
stream_reader: stream_reader,
|
||||
current_data: data.into_iter(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,13 +76,19 @@ impl<R> Iterator for VorbisDecoder<R>
|
|||
fn next(&mut self) -> Option<i16> {
|
||||
if let Some(sample) = self.current_data.next() {
|
||||
if self.current_data.len() == 0 {
|
||||
if let Some(data) = self.stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
|
||||
if let Some(data) = self.stream_reader
|
||||
.read_dec_packet_itl()
|
||||
.ok()
|
||||
.and_then(|v| v) {
|
||||
self.current_data = data.into_iter();
|
||||
}
|
||||
}
|
||||
return Some(sample);
|
||||
} else {
|
||||
if let Some(data) = self.stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
|
||||
if let Some(data) = self.stream_reader
|
||||
.read_dec_packet_itl()
|
||||
.ok()
|
||||
.and_then(|v| v) {
|
||||
self.current_data = data.into_iter();
|
||||
}
|
||||
return self.current_data.next();
|
||||
|
|
|
@ -31,10 +31,10 @@ impl<R> WavDecoder<R>
|
|||
};
|
||||
|
||||
Ok(WavDecoder {
|
||||
reader: reader,
|
||||
samples_rate: spec.sample_rate,
|
||||
channels: spec.channels,
|
||||
})
|
||||
reader: reader,
|
||||
samples_rate: spec.sample_rate,
|
||||
channels: spec.channels,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,15 +17,17 @@ 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, samples_rate: u32) -> (Arc<DynamicMixerController<S>>, DynamicMixer<S>)
|
||||
pub fn mixer<S>(channels: u16,
|
||||
samples_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,
|
||||
samples_rate: samples_rate,
|
||||
});
|
||||
has_pending: AtomicBool::new(false),
|
||||
pending_sources: Mutex::new(Vec::new()),
|
||||
channels: channels,
|
||||
samples_rate: samples_rate,
|
||||
});
|
||||
|
||||
let output = DynamicMixer {
|
||||
current_sources: Vec::with_capacity(16),
|
||||
|
@ -43,15 +45,20 @@ pub struct DynamicMixerController<S> {
|
|||
samples_rate: u32,
|
||||
}
|
||||
|
||||
impl<S> DynamicMixerController<S> where S: Sample + Send + 'static {
|
||||
impl<S> DynamicMixerController<S>
|
||||
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
|
||||
{
|
||||
let uniform_source = UniformSourceIterator::new(source, self.channels, self.samples_rate);
|
||||
self.pending_sources.lock().unwrap().push(Box::new(uniform_source) as Box<_>);
|
||||
self.has_pending.store(true, Ordering::SeqCst); // TODO: can we relax this ordering?
|
||||
self.pending_sources
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push(Box::new(uniform_source) as Box<_>);
|
||||
self.has_pending.store(true, Ordering::SeqCst); // TODO: can we relax this ordering?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +71,9 @@ pub struct DynamicMixer<S> {
|
|||
input: Arc<DynamicMixerController<S>>,
|
||||
}
|
||||
|
||||
impl<S> Source for DynamicMixer<S> where S: Sample + Send + 'static {
|
||||
impl<S> Source for DynamicMixer<S>
|
||||
where S: Sample + Send + 'static
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
None
|
||||
|
@ -86,15 +95,18 @@ impl<S> Source for DynamicMixer<S> where S: Sample + Send + 'static {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Iterator for DynamicMixer<S> where S: Sample + Send + 'static {
|
||||
impl<S> Iterator for DynamicMixer<S>
|
||||
where S: Sample + Send + 'static
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<S> {
|
||||
if self.input.has_pending.load(Ordering::SeqCst) { // TODO: relax ordering?
|
||||
if self.input.has_pending.load(Ordering::SeqCst) {
|
||||
// TODO: relax ordering?
|
||||
let mut pending = self.input.pending_sources.lock().unwrap();
|
||||
self.current_sources.extend(pending.drain(..));
|
||||
self.input.has_pending.store(false, Ordering::SeqCst); // TODO: relax ordering?
|
||||
self.input.has_pending.store(false, Ordering::SeqCst); // TODO: relax ordering?
|
||||
}
|
||||
|
||||
if self.current_sources.is_empty() {
|
||||
|
|
|
@ -77,7 +77,7 @@ impl Engine {
|
|||
e.insert(Arc::downgrade(&mixer));
|
||||
voice_to_start = Some(voice);
|
||||
mixer
|
||||
},
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
if let Some(m) = e.get().upgrade() {
|
||||
m.clone()
|
||||
|
@ -87,7 +87,7 @@ impl Engine {
|
|||
voice_to_start = Some(voice);
|
||||
mixer
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -100,10 +100,12 @@ impl Engine {
|
|||
}
|
||||
|
||||
// TODO: handle possible errors here
|
||||
fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>)
|
||||
fn new_voice(endpoint: &Endpoint,
|
||||
events_loop: &Arc<EventLoop>)
|
||||
-> (Arc<dynamic_mixer::DynamicMixerController<f32>>, Voice) {
|
||||
// Determine the format to use for the new voice.
|
||||
let format = endpoint.get_supported_formats_list()
|
||||
let format = endpoint
|
||||
.get_supported_formats_list()
|
||||
.unwrap()
|
||||
.fold(None, |f1, f2| {
|
||||
if f1.is_none() {
|
||||
|
@ -113,8 +115,7 @@ fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>)
|
|||
let f1 = f1.unwrap();
|
||||
|
||||
// We privilege f32 formats to avoid a conversion.
|
||||
if f2.data_type == cpal::SampleFormat::F32 &&
|
||||
f1.data_type != cpal::SampleFormat::F32 {
|
||||
if f2.data_type == cpal::SampleFormat::F32 && f1.data_type != cpal::SampleFormat::F32 {
|
||||
return Some(f2);
|
||||
}
|
||||
|
||||
|
@ -132,8 +133,7 @@ fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>)
|
|||
})
|
||||
.expect("The endpoint doesn't support any format!?");
|
||||
|
||||
let (voice, stream) = Voice::new(&endpoint, &format, events_loop)
|
||||
.unwrap();
|
||||
let (voice, stream) = Voice::new(&endpoint, &format, events_loop).unwrap();
|
||||
|
||||
let (mixer_tx, mut mixer_rx) = {
|
||||
dynamic_mixer::mixer::<f32>(format.channels.len() as u16, format.samples_rate.0)
|
||||
|
|
44
src/queue.rs
44
src/queue.rs
|
@ -26,14 +26,13 @@ use Sample;
|
|||
/// a new sound.
|
||||
/// - 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>)
|
||||
pub fn queue<S>(keep_alive_if_empty: bool) -> (Arc<SourcesQueueInput<S>>, SourcesQueueOutput<S>)
|
||||
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,13 +53,18 @@ pub struct SourcesQueueInput<S> {
|
|||
keep_alive_if_empty: AtomicBool,
|
||||
}
|
||||
|
||||
impl<S> SourcesQueueInput<S> where S: Sample + Send + 'static {
|
||||
impl<S> SourcesQueueInput<S>
|
||||
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
|
||||
{
|
||||
self.next_sounds.lock().unwrap().push((Box::new(source) as Box<_>, None));
|
||||
self.next_sounds
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push((Box::new(source) as Box<_>, None));
|
||||
}
|
||||
|
||||
/// Adds a new source to the end of the queue.
|
||||
|
@ -71,7 +75,10 @@ impl<S> SourcesQueueInput<S> where S: Sample + Send + 'static {
|
|||
where T: Source<Item = S> + Send + 'static
|
||||
{
|
||||
let (tx, rx) = mpsc::channel();
|
||||
self.next_sounds.lock().unwrap().push((Box::new(source) as Box<_>, Some(tx)));
|
||||
self.next_sounds
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push((Box::new(source) as Box<_>, Some(tx)));
|
||||
rx
|
||||
}
|
||||
|
||||
|
@ -79,7 +86,8 @@ impl<S> SourcesQueueInput<S> where S: Sample + Send + 'static {
|
|||
///
|
||||
/// See also the constructor.
|
||||
pub fn set_keep_alive_if_empty(&self, keep_alive_if_empty: bool) {
|
||||
self.keep_alive_if_empty.store(keep_alive_if_empty, Ordering::Release);
|
||||
self.keep_alive_if_empty
|
||||
.store(keep_alive_if_empty, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +103,9 @@ pub struct SourcesQueueOutput<S> {
|
|||
input: Arc<SourcesQueueInput<S>>,
|
||||
}
|
||||
|
||||
impl<S> Source for SourcesQueueOutput<S> where S: Sample + Send + 'static {
|
||||
impl<S> Source for SourcesQueueOutput<S>
|
||||
where S: Sample + Send + 'static
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
// This function is non-trivial because the boundary between two sounds in the queue should
|
||||
|
@ -144,7 +154,9 @@ impl<S> Source for SourcesQueueOutput<S> where S: Sample + Send + 'static {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Iterator for SourcesQueueOutput<S> where S: Sample + Send + 'static {
|
||||
impl<S> Iterator for SourcesQueueOutput<S>
|
||||
where S: Sample + Send + 'static
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
#[inline]
|
||||
|
@ -169,7 +181,9 @@ impl<S> Iterator for SourcesQueueOutput<S> where S: Sample + Send + 'static {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> SourcesQueueOutput<S> where S: Sample + Send + 'static {
|
||||
impl<S> SourcesQueueOutput<S>
|
||||
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.
|
||||
//
|
||||
|
@ -185,7 +199,7 @@ impl<S> SourcesQueueOutput<S> where S: Sample + Send + 'static {
|
|||
if next.len() == 0 {
|
||||
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
|
||||
let silence = Zero::<S>::new(1, 44000); // TODO: meh
|
||||
(Box::new(silence.take_duration(Duration::from_millis(10))) as Box<_>, None)
|
||||
} else {
|
||||
return Err(());
|
||||
|
@ -208,7 +222,7 @@ mod tests {
|
|||
use source::Source;
|
||||
|
||||
#[test]
|
||||
#[ignore] // FIXME: samples rate and channel not updated immediately after transition
|
||||
#[ignore] // FIXME: samples rate and channel not updated immediately after transition
|
||||
fn basic() {
|
||||
let (tx, mut rx) = queue::queue(false);
|
||||
|
||||
|
@ -252,7 +266,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // TODO: not yet implemented
|
||||
#[ignore] // TODO: not yet implemented
|
||||
fn no_delay_when_added() {
|
||||
let (tx, mut rx) = queue::queue(true);
|
||||
|
||||
|
|
17
src/sink.rs
17
src/sink.rs
|
@ -58,14 +58,15 @@ impl Sink {
|
|||
.pausable(false)
|
||||
.amplify(1.0)
|
||||
.stoppable()
|
||||
.periodic_access(Duration::from_millis(5), move |src| {
|
||||
if stopped.load(Ordering::SeqCst) {
|
||||
src.stop();
|
||||
} else {
|
||||
src.inner_mut().set_factor(*volume.lock().unwrap());
|
||||
src.inner_mut().inner_mut().set_paused(pause.load(Ordering::SeqCst));
|
||||
}
|
||||
})
|
||||
.periodic_access(Duration::from_millis(5),
|
||||
move |src| if stopped.load(Ordering::SeqCst) {
|
||||
src.stop();
|
||||
} else {
|
||||
src.inner_mut().set_factor(*volume.lock().unwrap());
|
||||
src.inner_mut()
|
||||
.inner_mut()
|
||||
.set_paused(pause.load(Ordering::SeqCst));
|
||||
})
|
||||
.convert_samples();
|
||||
|
||||
*self.sleep_until_end.lock().unwrap() = Some(self.queue_tx.append_with_signal(source));
|
||||
|
|
|
@ -55,7 +55,9 @@ impl<I> Iterator for Amplify<I>
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
self.input.next().map(|value| value.amplify(self.factor))
|
||||
self.input
|
||||
.next()
|
||||
.map(|value| value.amplify(self.factor))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -75,14 +75,17 @@ fn extract<I>(mut input: I) -> Arc<Frame<I>>
|
|||
|
||||
let channels = input.channels();
|
||||
let rate = input.samples_rate();
|
||||
let data = input.by_ref().take(cmp::min(frame_len.unwrap_or(32768), 32768)).collect();
|
||||
let data = input
|
||||
.by_ref()
|
||||
.take(cmp::min(frame_len.unwrap_or(32768), 32768))
|
||||
.collect();
|
||||
|
||||
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>
|
||||
|
|
|
@ -9,8 +9,7 @@ pub fn delay<I>(input: I, duration: Duration) -> Delay<I>
|
|||
I::Item: Sample
|
||||
{
|
||||
let duration_ns = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
|
||||
let samples = duration_ns * input.samples_rate() as u64 * input.channels() as u64 /
|
||||
1000000000;
|
||||
let samples = duration_ns * input.samples_rate() as u64 * input.channels() as u64 / 1000000000;
|
||||
|
||||
Delay {
|
||||
input: input,
|
||||
|
@ -60,7 +59,9 @@ impl<I> Source for Delay<I>
|
|||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
self.input.current_frame_len().map(|val| val + self.remaining_samples)
|
||||
self.input
|
||||
.current_frame_len()
|
||||
.map(|val| val + self.remaining_samples)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -75,6 +76,8 @@ impl<I> Source for Delay<I>
|
|||
|
||||
#[inline]
|
||||
fn total_duration(&self) -> Option<Duration> {
|
||||
self.input.total_duration().map(|val| val + self.requested_duration)
|
||||
self.input
|
||||
.total_duration()
|
||||
.map(|val| val + self.requested_duration)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ impl<S> Iterator for Empty<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Source for Empty<S> where S: Sample {
|
||||
impl<S> Source for Empty<S>
|
||||
where S: Sample
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
None
|
||||
|
|
|
@ -11,9 +11,7 @@ use source::FromIter;
|
|||
pub fn from_factory<F, S>(factory: F) -> FromIter<FromFactoryIter<F>>
|
||||
where F: FnMut() -> Option<S>
|
||||
{
|
||||
from_iter(FromFactoryIter {
|
||||
factory: factory,
|
||||
})
|
||||
from_iter(FromFactoryIter { factory: factory })
|
||||
}
|
||||
|
||||
/// Internal type used by `from_factory`.
|
||||
|
|
|
@ -24,7 +24,9 @@ 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 {
|
||||
pub struct FromIter<I>
|
||||
where I: Iterator
|
||||
{
|
||||
// The iterator that provides sources.
|
||||
iterator: I,
|
||||
// Is only ever `None` if the first element of the iterator is `None`.
|
||||
|
@ -140,15 +142,14 @@ mod tests {
|
|||
|
||||
#[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 {
|
||||
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.samples_rate(), 48000);
|
||||
|
@ -157,7 +158,8 @@ mod tests {
|
|||
assert_eq!(rx.next(), Some(10));
|
||||
assert_eq!(rx.next(), Some(-10));
|
||||
/*assert_eq!(rx.channels(), 2);
|
||||
assert_eq!(rx.samples_rate(), 96000);*/ // FIXME: not working
|
||||
assert_eq!(rx.samples_rate(), 96000);*/
|
||||
// FIXME: not working
|
||||
assert_eq!(rx.next(), Some(5));
|
||||
assert_eq!(rx.next(), Some(5));
|
||||
assert_eq!(rx.next(), Some(5));
|
||||
|
|
|
@ -235,7 +235,8 @@ 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)
|
||||
}
|
||||
|
@ -259,7 +260,9 @@ pub trait Source: Iterator
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Source for Box<Source<Item = S>> where S: Sample {
|
||||
impl<S> Source for Box<Source<Item = S>>
|
||||
where S: Sample
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
(**self).current_frame_len()
|
||||
|
@ -281,7 +284,9 @@ impl<S> Source for Box<Source<Item = S>> where S: Sample {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Source for Box<Source<Item = S> + Send> where S: Sample {
|
||||
impl<S> Source for Box<Source<Item = S> + Send>
|
||||
where S: Sample
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
(**self).current_frame_len()
|
||||
|
@ -303,7 +308,9 @@ impl<S> Source for Box<Source<Item = S> + Send> where S: Sample {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Source for Box<Source<Item = S> + Send + Sync> where S: Sample {
|
||||
impl<S> Source for Box<Source<Item = S> + Send + Sync>
|
||||
where S: Sample
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
(**self).current_frame_len()
|
||||
|
|
|
@ -6,7 +6,7 @@ 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,
|
||||
I::Item: Sample
|
||||
{
|
||||
// TODO: handle the fact that the samples rate can change
|
||||
// TODO: generally, just wrong
|
||||
|
|
|
@ -86,7 +86,14 @@ impl<I, D> Iterator for UniformSourceIterator<I, D>
|
|||
return Some(value);
|
||||
}
|
||||
|
||||
let input = self.inner.take().unwrap().into_inner().into_inner().into_inner().iter;
|
||||
let input = self.inner
|
||||
.take()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.into_inner()
|
||||
.into_inner()
|
||||
.iter;
|
||||
|
||||
let mut input =
|
||||
UniformSourceIterator::bootstrap(input, self.target_channels, self.target_samples_rate);
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@ impl<S> Zero<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Iterator for Zero<S> where S: Sample {
|
||||
impl<S> Iterator for Zero<S>
|
||||
where S: Sample
|
||||
{
|
||||
type Item = S;
|
||||
|
||||
#[inline]
|
||||
|
@ -31,7 +33,9 @@ impl<S> Iterator for Zero<S> where S: Sample {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Source for Zero<S> where S: Sample {
|
||||
impl<S> Source for Zero<S>
|
||||
where S: Sample
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
None
|
||||
|
|
Loading…
Reference in a new issue