mirror of
https://github.com/RustAudio/rodio
synced 2024-12-13 21:52:38 +00:00
Remove unnecessary 'static bound and cleanup (#356)
* Remove unnecessary 'static bound and cleanup The decoder had an unnecessary 'static bound. Additionally I noticed that there's a lot of (clippy) warnings, so I cleaned up the code a bit as well. There's a few warnings left, but a few of those require breaking changes. * Address Review Comments
This commit is contained in:
parent
e1aea73ba0
commit
181da2994b
40 changed files with 255 additions and 311 deletions
|
@ -13,8 +13,7 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::vec::IntoIter as VecIntoIter;
|
use std::vec::IntoIter as VecIntoIter;
|
||||||
|
|
||||||
use crate::source::Source;
|
use crate::{Sample, Source};
|
||||||
use crate::Sample;
|
|
||||||
|
|
||||||
/// A buffer of samples treated as a source.
|
/// A buffer of samples treated as a source.
|
||||||
pub struct SamplesBuffer<S> {
|
pub struct SamplesBuffer<S> {
|
||||||
|
@ -32,9 +31,9 @@ where
|
||||||
///
|
///
|
||||||
/// # Panic
|
/// # Panic
|
||||||
///
|
///
|
||||||
/// - Panicks if the number of channels is zero.
|
/// - Panics if the number of channels is zero.
|
||||||
/// - Panicks if the samples rate is zero.
|
/// - Panics if the samples rate is zero.
|
||||||
/// - Panicks if the length of the buffer is larger than approximatively 16 billion elements.
|
/// - Panics if the length of the buffer is larger than approximately 16 billion elements.
|
||||||
/// This is because the calculation of the duration would overflow.
|
/// This is because the calculation of the duration would overflow.
|
||||||
///
|
///
|
||||||
pub fn new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S>
|
pub fn new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S>
|
||||||
|
@ -55,9 +54,9 @@ where
|
||||||
|
|
||||||
SamplesBuffer {
|
SamplesBuffer {
|
||||||
data: data.into_iter(),
|
data: data.into_iter(),
|
||||||
channels: channels,
|
channels,
|
||||||
sample_rate: sample_rate,
|
sample_rate,
|
||||||
duration: duration,
|
duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use cpal;
|
|
||||||
|
|
||||||
/// Iterator that converts from a certain channel count to another.
|
/// Iterator that converts from a certain channel count to another.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ChannelCountConverter<I>
|
pub struct ChannelCountConverter<I>
|
||||||
|
@ -33,9 +31,9 @@ where
|
||||||
assert!(to >= 1);
|
assert!(to >= 1);
|
||||||
|
|
||||||
ChannelCountConverter {
|
ChannelCountConverter {
|
||||||
input: input,
|
input,
|
||||||
from: from,
|
from,
|
||||||
to: to,
|
to,
|
||||||
sample_repeat: None,
|
sample_repeat: None,
|
||||||
next_output_sample_pos: 0,
|
next_output_sample_pos: 0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ impl<I, O> DataConverter<I, O> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(input: I) -> DataConverter<I, O> {
|
pub fn new(input: I) -> DataConverter<I, O> {
|
||||||
DataConverter {
|
DataConverter {
|
||||||
input: input,
|
input,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::conversions::Sample;
|
use crate::conversions::Sample;
|
||||||
use cpal;
|
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ where
|
||||||
///
|
///
|
||||||
/// # Panic
|
/// # Panic
|
||||||
///
|
///
|
||||||
/// Panicks if `from` or `to` are equal to 0.
|
/// Panics if `from` or `to` are equal to 0.
|
||||||
///
|
///
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -85,7 +84,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
SampleRateConverter {
|
SampleRateConverter {
|
||||||
input: input,
|
input,
|
||||||
from: from / gcd,
|
from: from / gcd,
|
||||||
to: to / gcd,
|
to: to / gcd,
|
||||||
channels: num_channels,
|
channels: num_channels,
|
||||||
|
@ -133,7 +132,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short circuit if there are some samples waiting.
|
// Short circuit if there are some samples waiting.
|
||||||
if self.output_buffer.len() >= 1 {
|
if !self.output_buffer.is_empty() {
|
||||||
return Some(self.output_buffer.remove(0));
|
return Some(self.output_buffer.remove(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +173,7 @@ where
|
||||||
.zip(self.next_frame.iter())
|
.zip(self.next_frame.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let sample = Sample::lerp(cur.clone(), next.clone(), numerator, self.to);
|
let sample = Sample::lerp(*cur, *next, numerator, self.to);
|
||||||
|
|
||||||
if off == 0 {
|
if off == 0 {
|
||||||
result = Some(sample);
|
result = Some(sample);
|
||||||
|
@ -192,7 +191,7 @@ where
|
||||||
debug_assert!(self.next_frame.is_empty());
|
debug_assert!(self.next_frame.is_empty());
|
||||||
|
|
||||||
// draining `self.current_frame`
|
// draining `self.current_frame`
|
||||||
if self.current_frame.len() >= 1 {
|
if !self.current_frame.is_empty() {
|
||||||
let r = Some(self.current_frame.remove(0));
|
let r = Some(self.current_frame.remove(0));
|
||||||
mem::swap(&mut self.output_buffer, &mut self.current_frame);
|
mem::swap(&mut self.output_buffer, &mut self.current_frame);
|
||||||
self.current_frame.clear();
|
self.current_frame.clear();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -35,7 +36,7 @@ where
|
||||||
let spec = reader.streaminfo();
|
let spec = reader.streaminfo();
|
||||||
|
|
||||||
Ok(FlacDecoder {
|
Ok(FlacDecoder {
|
||||||
reader: reader,
|
reader,
|
||||||
current_block: Vec::with_capacity(
|
current_block: Vec::with_capacity(
|
||||||
spec.max_block_size as usize * spec.channels as usize,
|
spec.max_block_size as usize * spec.channels as usize,
|
||||||
),
|
),
|
||||||
|
@ -96,12 +97,10 @@ where
|
||||||
+ self.current_block_off / self.channels as usize;
|
+ self.current_block_off / self.channels as usize;
|
||||||
let raw_val = self.current_block[real_offset];
|
let raw_val = self.current_block[real_offset];
|
||||||
self.current_block_off += 1;
|
self.current_block_off += 1;
|
||||||
let real_val = if self.bits_per_sample == 16 {
|
let real_val = match self.bits_per_sample.cmp(&16) {
|
||||||
raw_val as i16
|
Ordering::Less => (raw_val << (16 - self.bits_per_sample)) as i16,
|
||||||
} else if self.bits_per_sample < 16 {
|
Ordering::Equal => raw_val as i16,
|
||||||
(raw_val << (16 - self.bits_per_sample)) as i16
|
Ordering::Greater => (raw_val >> (self.bits_per_sample - 16)) as i16,
|
||||||
} else {
|
|
||||||
(raw_val >> (self.bits_per_sample - 16)) as i16
|
|
||||||
};
|
};
|
||||||
return Some(real_val as i16);
|
return Some(real_val as i16);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{Read, Seek};
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::io::SeekFrom;
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -42,12 +41,12 @@ where
|
||||||
Flac(flac::FlacDecoder<R>),
|
Flac(flac::FlacDecoder<R>),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
Mp3(mp3::Mp3Decoder<R>),
|
Mp3(mp3::Mp3Decoder<R>),
|
||||||
None(::std::marker::PhantomData<R>)
|
None(::std::marker::PhantomData<R>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Decoder<R>
|
impl<R> Decoder<R>
|
||||||
where
|
where
|
||||||
R: Read + Seek + Send + 'static,
|
R: Read + Seek + Send,
|
||||||
{
|
{
|
||||||
/// Builds a new decoder.
|
/// Builds a new decoder.
|
||||||
///
|
///
|
||||||
|
@ -131,7 +130,7 @@ where
|
||||||
|
|
||||||
impl<R> LoopedDecoder<R>
|
impl<R> LoopedDecoder<R>
|
||||||
where
|
where
|
||||||
R: Read + Seek + Send + 'static,
|
R: Read + Seek + Send,
|
||||||
{
|
{
|
||||||
fn new(decoder: Decoder<R>) -> LoopedDecoder<R> {
|
fn new(decoder: Decoder<R>) -> LoopedDecoder<R> {
|
||||||
Self(decoder.0)
|
Self(decoder.0)
|
||||||
|
@ -146,30 +145,30 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<i16> {
|
fn next(&mut self) -> Option<i16> {
|
||||||
match self.0 {
|
match &mut self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref mut source) => source.next(),
|
DecoderImpl::Wav(source) => source.next(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref mut source) => source.next(),
|
DecoderImpl::Vorbis(source) => source.next(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref mut source) => source.next(),
|
DecoderImpl::Flac(source) => source.next(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref mut source) => source.next(),
|
DecoderImpl::Mp3(source) => source.next(),
|
||||||
DecoderImpl::None(_) => None,
|
DecoderImpl::None(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.size_hint(),
|
DecoderImpl::Wav(source) => source.size_hint(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.size_hint(),
|
DecoderImpl::Vorbis(source) => source.size_hint(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.size_hint(),
|
DecoderImpl::Flac(source) => source.size_hint(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.size_hint(),
|
DecoderImpl::Mp3(source) => source.size_hint(),
|
||||||
DecoderImpl::None(_) => (0, None),
|
DecoderImpl::None(_) => (0, None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,60 +180,60 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_frame_len(&self) -> Option<usize> {
|
fn current_frame_len(&self) -> Option<usize> {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.current_frame_len(),
|
DecoderImpl::Wav(source) => source.current_frame_len(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.current_frame_len(),
|
DecoderImpl::Vorbis(source) => source.current_frame_len(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.current_frame_len(),
|
DecoderImpl::Flac(source) => source.current_frame_len(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.current_frame_len(),
|
DecoderImpl::Mp3(source) => source.current_frame_len(),
|
||||||
DecoderImpl::None(_) => Some(0),
|
DecoderImpl::None(_) => Some(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn channels(&self) -> u16 {
|
fn channels(&self) -> u16 {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.channels(),
|
DecoderImpl::Wav(source) => source.channels(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.channels(),
|
DecoderImpl::Vorbis(source) => source.channels(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.channels(),
|
DecoderImpl::Flac(source) => source.channels(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.channels(),
|
DecoderImpl::Mp3(source) => source.channels(),
|
||||||
DecoderImpl::None(_) => 0,
|
DecoderImpl::None(_) => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_rate(&self) -> u32 {
|
fn sample_rate(&self) -> u32 {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.sample_rate(),
|
DecoderImpl::Wav(source) => source.sample_rate(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.sample_rate(),
|
DecoderImpl::Vorbis(source) => source.sample_rate(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.sample_rate(),
|
DecoderImpl::Flac(source) => source.sample_rate(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.sample_rate(),
|
DecoderImpl::Mp3(source) => source.sample_rate(),
|
||||||
DecoderImpl::None(_) => 1,
|
DecoderImpl::None(_) => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn total_duration(&self) -> Option<Duration> {
|
fn total_duration(&self) -> Option<Duration> {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.total_duration(),
|
DecoderImpl::Wav(source) => source.total_duration(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.total_duration(),
|
DecoderImpl::Vorbis(source) => source.total_duration(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.total_duration(),
|
DecoderImpl::Flac(source) => source.total_duration(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.total_duration(),
|
DecoderImpl::Mp3(source) => source.total_duration(),
|
||||||
DecoderImpl::None(_) => Some(Duration::default()),
|
DecoderImpl::None(_) => Some(Duration::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,15 +247,15 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<i16> {
|
fn next(&mut self) -> Option<i16> {
|
||||||
if let Some(sample) = match self.0 {
|
if let Some(sample) = match &mut self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref mut source) => source.next(),
|
DecoderImpl::Wav(source) => source.next(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref mut source) => source.next(),
|
DecoderImpl::Vorbis(source) => source.next(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref mut source) => source.next(),
|
DecoderImpl::Flac(source) => source.next(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref mut source) => source.next(),
|
DecoderImpl::Mp3(source) => source.next(),
|
||||||
DecoderImpl::None(_) => None,
|
DecoderImpl::None(_) => None,
|
||||||
} {
|
} {
|
||||||
Some(sample)
|
Some(sample)
|
||||||
|
@ -276,7 +275,9 @@ where
|
||||||
use lewton::inside_ogg::OggStreamReader;
|
use lewton::inside_ogg::OggStreamReader;
|
||||||
let mut reader = source.into_inner().into_inner();
|
let mut reader = source.into_inner().into_inner();
|
||||||
reader.seek_bytes(SeekFrom::Start(0)).ok()?;
|
reader.seek_bytes(SeekFrom::Start(0)).ok()?;
|
||||||
let mut source = vorbis::VorbisDecoder::from_stream_reader(OggStreamReader::from_ogg_reader(reader).ok()?);
|
let mut source = vorbis::VorbisDecoder::from_stream_reader(
|
||||||
|
OggStreamReader::from_ogg_reader(reader).ok()?,
|
||||||
|
);
|
||||||
let sample = source.next();
|
let sample = source.next();
|
||||||
(DecoderImpl::Vorbis(source), sample)
|
(DecoderImpl::Vorbis(source), sample)
|
||||||
}
|
}
|
||||||
|
@ -296,7 +297,7 @@ where
|
||||||
let sample = source.next();
|
let sample = source.next();
|
||||||
(DecoderImpl::Mp3(source), sample)
|
(DecoderImpl::Mp3(source), sample)
|
||||||
}
|
}
|
||||||
none @ DecoderImpl::None(_) => (none, None)
|
none @ DecoderImpl::None(_) => (none, None),
|
||||||
};
|
};
|
||||||
self.0 = decoder;
|
self.0 = decoder;
|
||||||
sample
|
sample
|
||||||
|
@ -305,15 +306,15 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => (source.size_hint().0, None),
|
DecoderImpl::Wav(source) => (source.size_hint().0, None),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => (source.size_hint().0, None),
|
DecoderImpl::Vorbis(source) => (source.size_hint().0, None),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => (source.size_hint().0, None),
|
DecoderImpl::Flac(source) => (source.size_hint().0, None),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => (source.size_hint().0, None),
|
DecoderImpl::Mp3(source) => (source.size_hint().0, None),
|
||||||
DecoderImpl::None(_) => (0, None),
|
DecoderImpl::None(_) => (0, None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,45 +326,45 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_frame_len(&self) -> Option<usize> {
|
fn current_frame_len(&self) -> Option<usize> {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.current_frame_len(),
|
DecoderImpl::Wav(source) => source.current_frame_len(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.current_frame_len(),
|
DecoderImpl::Vorbis(source) => source.current_frame_len(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.current_frame_len(),
|
DecoderImpl::Flac(source) => source.current_frame_len(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.current_frame_len(),
|
DecoderImpl::Mp3(source) => source.current_frame_len(),
|
||||||
DecoderImpl::None(_) => Some(0),
|
DecoderImpl::None(_) => Some(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn channels(&self) -> u16 {
|
fn channels(&self) -> u16 {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.channels(),
|
DecoderImpl::Wav(source) => source.channels(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.channels(),
|
DecoderImpl::Vorbis(source) => source.channels(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.channels(),
|
DecoderImpl::Flac(source) => source.channels(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.channels(),
|
DecoderImpl::Mp3(source) => source.channels(),
|
||||||
DecoderImpl::None(_) => 0,
|
DecoderImpl::None(_) => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_rate(&self) -> u32 {
|
fn sample_rate(&self) -> u32 {
|
||||||
match self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "wav")]
|
#[cfg(feature = "wav")]
|
||||||
DecoderImpl::Wav(ref source) => source.sample_rate(),
|
DecoderImpl::Wav(source) => source.sample_rate(),
|
||||||
#[cfg(feature = "vorbis")]
|
#[cfg(feature = "vorbis")]
|
||||||
DecoderImpl::Vorbis(ref source) => source.sample_rate(),
|
DecoderImpl::Vorbis(source) => source.sample_rate(),
|
||||||
#[cfg(feature = "flac")]
|
#[cfg(feature = "flac")]
|
||||||
DecoderImpl::Flac(ref source) => source.sample_rate(),
|
DecoderImpl::Flac(source) => source.sample_rate(),
|
||||||
#[cfg(feature = "mp3")]
|
#[cfg(feature = "mp3")]
|
||||||
DecoderImpl::Mp3(ref source) => source.sample_rate(),
|
DecoderImpl::Mp3(source) => source.sample_rate(),
|
||||||
DecoderImpl::None(_) => 1,
|
DecoderImpl::None(_) => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +385,7 @@ pub enum DecoderError {
|
||||||
impl fmt::Display for DecoderError {
|
impl fmt::Display for DecoderError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&DecoderError::UnrecognizedFormat => write!(f, "Unrecognized format"),
|
DecoderError::UnrecognizedFormat => write!(f, "Unrecognized format"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,7 +393,7 @@ impl fmt::Display for DecoderError {
|
||||||
impl Error for DecoderError {
|
impl Error for DecoderError {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
&DecoderError::UnrecognizedFormat => "Unrecognized format",
|
DecoderError::UnrecognizedFormat => "Unrecognized format",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,6 @@ where
|
||||||
let v = self.current_frame.data[self.current_frame_offset];
|
let v = self.current_frame.data[self.current_frame_offset];
|
||||||
self.current_frame_offset += 1;
|
self.current_frame_offset += 1;
|
||||||
|
|
||||||
return Some(v);
|
Some(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,20 +29,19 @@ where
|
||||||
Ok(Self::from_stream_reader(stream_reader))
|
Ok(Self::from_stream_reader(stream_reader))
|
||||||
}
|
}
|
||||||
pub fn from_stream_reader(mut stream_reader: OggStreamReader<R>) -> Self {
|
pub fn from_stream_reader(mut stream_reader: OggStreamReader<R>) -> Self {
|
||||||
let mut data = match stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
|
let mut data = match stream_reader.read_dec_packet_itl() {
|
||||||
Some(d) => d,
|
Ok(Some(d)) => d,
|
||||||
None => Vec::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// The first packet is always empty, therefore
|
// The first packet is always empty, therefore
|
||||||
// we need to read the second frame to get some data
|
// we need to read the second frame to get some data
|
||||||
match stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
|
if let Ok(Some(mut d)) = stream_reader.read_dec_packet_itl() {
|
||||||
Some(mut d) => data.append(&mut d),
|
data.append(&mut d);
|
||||||
None => (),
|
}
|
||||||
};
|
|
||||||
|
|
||||||
VorbisDecoder {
|
VorbisDecoder {
|
||||||
stream_reader: stream_reader,
|
stream_reader,
|
||||||
current_data: data.into_iter(),
|
current_data: data.into_iter(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,26 +85,16 @@ where
|
||||||
fn next(&mut self) -> Option<i16> {
|
fn next(&mut self) -> Option<i16> {
|
||||||
if let Some(sample) = self.current_data.next() {
|
if let Some(sample) = self.current_data.next() {
|
||||||
if self.current_data.len() == 0 {
|
if self.current_data.len() == 0 {
|
||||||
if let Some(data) = self
|
if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
|
||||||
.stream_reader
|
|
||||||
.read_dec_packet_itl()
|
|
||||||
.ok()
|
|
||||||
.and_then(|v| v)
|
|
||||||
{
|
|
||||||
self.current_data = data.into_iter();
|
self.current_data = data.into_iter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Some(sample);
|
Some(sample)
|
||||||
} else {
|
} else {
|
||||||
if let Some(data) = self
|
if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
|
||||||
.stream_reader
|
|
||||||
.read_dec_packet_itl()
|
|
||||||
.ok()
|
|
||||||
.and_then(|v| v)
|
|
||||||
{
|
|
||||||
self.current_data = data.into_iter();
|
self.current_data = data.into_iter();
|
||||||
}
|
}
|
||||||
return self.current_data.next();
|
self.current_data.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,12 @@ where
|
||||||
let reader = WavReader::new(data).unwrap();
|
let reader = WavReader::new(data).unwrap();
|
||||||
let spec = reader.spec();
|
let spec = reader.spec();
|
||||||
let reader = SamplesIterator {
|
let reader = SamplesIterator {
|
||||||
reader: reader,
|
reader,
|
||||||
samples_read: 0,
|
samples_read: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(WavDecoder {
|
Ok(WavDecoder {
|
||||||
reader: reader,
|
reader,
|
||||||
sample_rate: spec.sample_rate,
|
sample_rate: spec.sample_rate,
|
||||||
channels: spec.channels,
|
channels: spec.channels,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
//! Mixer that plays multiple sounds at the same time.
|
//! Mixer that plays multiple sounds at the same time.
|
||||||
|
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::source::Source;
|
use crate::source::{Source, UniformSourceIterator};
|
||||||
use crate::source::UniformSourceIterator;
|
|
||||||
use crate::Sample;
|
use crate::Sample;
|
||||||
|
|
||||||
/// Builds a new mixer.
|
/// Builds a new mixer.
|
||||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -20,19 +20,17 @@
|
||||||
//! use std::io::BufReader;
|
//! use std::io::BufReader;
|
||||||
//! use rodio::Source;
|
//! use rodio::Source;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! let (stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
|
||||||
//! let (stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
|
|
||||||
//!
|
//!
|
||||||
//! // Load a sound from a file, using a path relative to Cargo.toml
|
//! // Load a sound from a file, using a path relative to Cargo.toml
|
||||||
//! let file = File::open("sound.ogg").unwrap();
|
//! let file = File::open("sound.ogg").unwrap();
|
||||||
//! let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
|
//! let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
|
||||||
//! stream_handle.play_raw(source.convert_samples());
|
//! stream_handle.play_raw(source.convert_samples());
|
||||||
//!
|
//!
|
||||||
//! // The sound plays in a separate audio thread,
|
//! // The sound plays in a separate audio thread,
|
||||||
//! // so we need to keep the main thread alive while it's playing.
|
//! // so we need to keep the main thread alive while it's playing.
|
||||||
//! // Press ctrl + C to stop the process once you're done.
|
//! // Press ctrl + C to stop the process once you're done.
|
||||||
//! loop {}
|
//! loop {}
|
||||||
//! }
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Sink
|
//! ## Sink
|
||||||
|
|
14
src/queue.rs
14
src/queue.rs
|
@ -1,17 +1,11 @@
|
||||||
//! Queue that plays sounds one after the other.
|
//! Queue that plays sounds one after the other.
|
||||||
|
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::sync::mpsc;
|
use std::sync::{mpsc, Arc, Mutex};
|
||||||
use std::sync::mpsc::Receiver;
|
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::source::Empty;
|
use crate::source::{Empty, Source, Zero};
|
||||||
use crate::source::Source;
|
|
||||||
use crate::source::Zero;
|
|
||||||
use crate::Sample;
|
use crate::Sample;
|
||||||
|
|
||||||
/// Builds a new queue. It consists of an input and an output.
|
/// Builds a new queue. It consists of an input and an output.
|
||||||
|
|
18
src/sink.rs
18
src/sink.rs
|
@ -1,15 +1,10 @@
|
||||||
use crate::stream::{OutputStreamHandle, PlayError};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::queue;
|
use crate::stream::{OutputStreamHandle, PlayError};
|
||||||
use crate::source::Done;
|
use crate::{queue, source::Done, Sample, Source};
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Handle to an device that outputs sounds.
|
/// Handle to an device that outputs sounds.
|
||||||
///
|
///
|
||||||
|
@ -179,8 +174,7 @@ impl Drop for Sink {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::buffer::SamplesBuffer;
|
use crate::buffer::SamplesBuffer;
|
||||||
use crate::sink::Sink;
|
use crate::{Sink, Source};
|
||||||
use crate::source::Source;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pause_and_stop() {
|
fn test_pause_and_stop() {
|
||||||
|
@ -192,7 +186,7 @@ mod tests {
|
||||||
|
|
||||||
// Low rate to ensure immediate control.
|
// Low rate to ensure immediate control.
|
||||||
sink.append(SamplesBuffer::new(1, 1, v.clone()));
|
sink.append(SamplesBuffer::new(1, 1, v.clone()));
|
||||||
let mut src = SamplesBuffer::new(1, 1, v.clone()).convert_samples();
|
let mut src = SamplesBuffer::new(1, 1, v).convert_samples();
|
||||||
|
|
||||||
assert_eq!(queue_rx.next(), src.next());
|
assert_eq!(queue_rx.next(), src.next());
|
||||||
assert_eq!(queue_rx.next(), src.next());
|
assert_eq!(queue_rx.next(), src.next());
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Amplify` object.
|
/// Internal function that builds a `Amplify` object.
|
||||||
pub fn amplify<I>(input: I, factor: f32) -> Amplify<I>
|
pub fn amplify<I>(input: I, factor: f32) -> Amplify<I>
|
||||||
|
@ -9,10 +8,7 @@ where
|
||||||
I: Source,
|
I: Source,
|
||||||
I::Item: Sample,
|
I::Item: Sample,
|
||||||
{
|
{
|
||||||
Amplify {
|
Amplify { input, factor }
|
||||||
input: input,
|
|
||||||
factor: factor,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Filter that modifies each sample by a given value.
|
/// Filter that modifies each sample by a given value.
|
||||||
|
|
|
@ -11,8 +11,8 @@ where
|
||||||
I: Source<Item = f32>,
|
I: Source<Item = f32>,
|
||||||
{
|
{
|
||||||
BltFilter {
|
BltFilter {
|
||||||
input: input,
|
input,
|
||||||
formula: BltFormula::LowPass { freq: freq, q: 0.5 },
|
formula: BltFormula::LowPass { freq, q: 0.5 },
|
||||||
applier: None,
|
applier: None,
|
||||||
x_n1: 0.0,
|
x_n1: 0.0,
|
||||||
x_n2: 0.0,
|
x_n2: 0.0,
|
||||||
|
@ -35,7 +35,7 @@ pub struct BltFilter<I> {
|
||||||
impl<I> BltFilter<I> {
|
impl<I> BltFilter<I> {
|
||||||
/// Modifies this filter so that it becomes a low-pass filter.
|
/// Modifies this filter so that it becomes a low-pass filter.
|
||||||
pub fn to_low_pass(&mut self, freq: u32) {
|
pub fn to_low_pass(&mut self, freq: u32) {
|
||||||
self.formula = BltFormula::LowPass { freq: freq, q: 0.5 };
|
self.formula = BltFormula::LowPass { freq, q: 0.5 };
|
||||||
self.applier = None;
|
self.applier = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +135,8 @@ enum BltFormula {
|
||||||
|
|
||||||
impl BltFormula {
|
impl BltFormula {
|
||||||
fn to_applier(&self, sampling_frequency: u32) -> BltApplier {
|
fn to_applier(&self, sampling_frequency: u32) -> BltApplier {
|
||||||
match self {
|
match *self {
|
||||||
&BltFormula::LowPass { freq, q } => {
|
BltFormula::LowPass { freq, q } => {
|
||||||
let w0 = 2.0 * PI * freq as f32 / sampling_frequency as f32;
|
let w0 = 2.0 * PI * freq as f32 / sampling_frequency as f32;
|
||||||
|
|
||||||
let alpha = w0.sin() / (2.0 * q);
|
let alpha = w0.sin() / (2.0 * q);
|
||||||
|
|
|
@ -2,8 +2,7 @@ use std::cmp;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Buffered` object.
|
/// Internal function that builds a `Buffered` object.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -18,7 +17,7 @@ where
|
||||||
Buffered {
|
Buffered {
|
||||||
current_frame: first_frame,
|
current_frame: first_frame,
|
||||||
position_in_frame: 0,
|
position_in_frame: 0,
|
||||||
total_duration: total_duration,
|
total_duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,9 +89,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
Arc::new(Frame::Data(FrameData {
|
Arc::new(Frame::Data(FrameData {
|
||||||
data: data,
|
data,
|
||||||
channels: channels,
|
channels,
|
||||||
rate: rate,
|
rate,
|
||||||
next: Mutex::new(Arc::new(Frame::Input(Mutex::new(Some(input))))),
|
next: Mutex::new(Arc::new(Frame::Input(Mutex::new(Some(input))))),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -106,14 +105,14 @@ where
|
||||||
fn next_frame(&mut self) {
|
fn next_frame(&mut self) {
|
||||||
let next_frame = {
|
let next_frame = {
|
||||||
let mut next_frame_ptr = match &*self.current_frame {
|
let mut next_frame_ptr = match &*self.current_frame {
|
||||||
&Frame::Data(FrameData { ref next, .. }) => next.lock().unwrap(),
|
Frame::Data(FrameData { next, .. }) => next.lock().unwrap(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let next_frame = match &**next_frame_ptr {
|
let next_frame = match &**next_frame_ptr {
|
||||||
&Frame::Data(_) => next_frame_ptr.clone(),
|
Frame::Data(_) => next_frame_ptr.clone(),
|
||||||
&Frame::End => next_frame_ptr.clone(),
|
Frame::End => next_frame_ptr.clone(),
|
||||||
&Frame::Input(ref input) => {
|
Frame::Input(input) => {
|
||||||
let input = input.lock().unwrap().take().unwrap();
|
let input = input.lock().unwrap().take().unwrap();
|
||||||
extract(input)
|
extract(input)
|
||||||
}
|
}
|
||||||
|
@ -141,18 +140,18 @@ where
|
||||||
let advance_frame;
|
let advance_frame;
|
||||||
|
|
||||||
match &*self.current_frame {
|
match &*self.current_frame {
|
||||||
&Frame::Data(FrameData { ref data, .. }) => {
|
Frame::Data(FrameData { data, .. }) => {
|
||||||
current_sample = Some(data[self.position_in_frame].clone());
|
current_sample = Some(data[self.position_in_frame]);
|
||||||
self.position_in_frame += 1;
|
self.position_in_frame += 1;
|
||||||
advance_frame = self.position_in_frame >= data.len();
|
advance_frame = self.position_in_frame >= data.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
&Frame::End => {
|
Frame::End => {
|
||||||
current_sample = None;
|
current_sample = None;
|
||||||
advance_frame = false;
|
advance_frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
&Frame::Input(_) => unreachable!(),
|
Frame::Input(_) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if advance_frame {
|
if advance_frame {
|
||||||
|
@ -181,27 +180,27 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_frame_len(&self) -> Option<usize> {
|
fn current_frame_len(&self) -> Option<usize> {
|
||||||
match &*self.current_frame {
|
match &*self.current_frame {
|
||||||
&Frame::Data(FrameData { ref data, .. }) => Some(data.len() - self.position_in_frame),
|
Frame::Data(FrameData { data, .. }) => Some(data.len() - self.position_in_frame),
|
||||||
&Frame::End => Some(0),
|
Frame::End => Some(0),
|
||||||
&Frame::Input(_) => unreachable!(),
|
Frame::Input(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn channels(&self) -> u16 {
|
fn channels(&self) -> u16 {
|
||||||
match &*self.current_frame {
|
match *self.current_frame {
|
||||||
&Frame::Data(FrameData { channels, .. }) => channels,
|
Frame::Data(FrameData { channels, .. }) => channels,
|
||||||
&Frame::End => 1,
|
Frame::End => 1,
|
||||||
&Frame::Input(_) => unreachable!(),
|
Frame::Input(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_rate(&self) -> u32 {
|
fn sample_rate(&self) -> u32 {
|
||||||
match &*self.current_frame {
|
match *self.current_frame {
|
||||||
&Frame::Data(FrameData { rate, .. }) => rate,
|
Frame::Data(FrameData { rate, .. }) => rate,
|
||||||
&Frame::End => 44100,
|
Frame::End => 44100,
|
||||||
&Frame::Input(_) => unreachable!(),
|
Frame::Input(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,8 +219,8 @@ where
|
||||||
fn clone(&self) -> Buffered<I> {
|
fn clone(&self) -> Buffered<I> {
|
||||||
Buffered {
|
Buffered {
|
||||||
current_frame: self.current_frame.clone(),
|
current_frame: self.current_frame.clone(),
|
||||||
position_in_frame: self.position_in_frame.clone(),
|
position_in_frame: self.position_in_frame,
|
||||||
total_duration: self.total_duration.clone(),
|
total_duration: self.total_duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::{Sample, Source};
|
||||||
|
|
||||||
/// Combines channels in input into a single mono source, then plays that mono sound
|
/// Combines channels in input into a single mono source, then plays that mono sound
|
||||||
/// to each channel at the volume given for that channel.
|
/// to each channel at the volume given for that channel.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -33,7 +33,7 @@ where
|
||||||
if let Some(s) = input.next() {
|
if let Some(s) = input.next() {
|
||||||
sample = Some(
|
sample = Some(
|
||||||
sample
|
sample
|
||||||
.get_or_insert_with(|| I::Item::zero_value())
|
.get_or_insert_with(I::Item::zero_value)
|
||||||
.saturating_add(s),
|
.saturating_add(s),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -92,13 +92,13 @@ where
|
||||||
if let Some(s) = self.input.next() {
|
if let Some(s) = self.input.next() {
|
||||||
self.current_sample = Some(
|
self.current_sample = Some(
|
||||||
self.current_sample
|
self.current_sample
|
||||||
.get_or_insert_with(|| I::Item::zero_value())
|
.get_or_insert_with(I::Item::zero_value)
|
||||||
.saturating_add(s),
|
.saturating_add(s),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::source::{FadeIn, Mix, TakeDuration};
|
use crate::source::{FadeIn, Mix, TakeDuration};
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Mixes one sound fading out with another sound fading in for the given duration.
|
/// Mixes one sound fading out with another sound fading in for the given duration.
|
||||||
///
|
///
|
||||||
|
@ -32,8 +31,7 @@ mod tests {
|
||||||
use crate::buffer::SamplesBuffer;
|
use crate::buffer::SamplesBuffer;
|
||||||
fn dummysource(length: u8) -> SamplesBuffer<f32> {
|
fn dummysource(length: u8) -> SamplesBuffer<f32> {
|
||||||
let data: Vec<f32> = (1..=length).map(f32::from).collect();
|
let data: Vec<f32> = (1..=length).map(f32::from).collect();
|
||||||
let source = SamplesBuffer::new(1, 1, data);
|
SamplesBuffer::new(1, 1, data)
|
||||||
source
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Delay` object.
|
/// Internal function that builds a `Delay` object.
|
||||||
pub fn delay<I>(input: I, duration: Duration) -> Delay<I>
|
pub fn delay<I>(input: I, duration: Duration) -> Delay<I>
|
||||||
|
@ -13,7 +12,7 @@ where
|
||||||
let samples = duration_ns * input.sample_rate() as u64 / 1000000000 * input.channels() as u64;
|
let samples = duration_ns * input.sample_rate() as u64 / 1000000000 * input.channels() as u64;
|
||||||
|
|
||||||
Delay {
|
Delay {
|
||||||
input: input,
|
input,
|
||||||
remaining_samples: samples as usize,
|
remaining_samples: samples as usize,
|
||||||
requested_duration: duration,
|
requested_duration: duration,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::{Sample, Source};
|
||||||
|
|
||||||
/// When the inner source is empty this decrements an `AtomicUsize`.
|
/// When the inner source is empty this decrements an `AtomicUsize`.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Done<I> {
|
pub struct Done<I> {
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::{Sample, Source};
|
||||||
|
|
||||||
/// An empty source.
|
/// An empty source.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Empty<S>(PhantomData<S>);
|
pub struct Empty<S>(PhantomData<S>);
|
||||||
|
|
||||||
|
impl<S> Default for Empty<S> {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S> Empty<S> {
|
impl<S> Empty<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Empty<S> {
|
pub fn new() -> Empty<S> {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `FadeIn` object.
|
/// Internal function that builds a `FadeIn` object.
|
||||||
pub fn fadein<I>(input: I, duration: Duration) -> FadeIn<I>
|
pub fn fadein<I>(input: I, duration: Duration) -> FadeIn<I>
|
||||||
|
@ -12,7 +11,7 @@ where
|
||||||
let duration = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
|
let duration = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
|
||||||
|
|
||||||
FadeIn {
|
FadeIn {
|
||||||
input: input,
|
input,
|
||||||
remaining_ns: duration as f32,
|
remaining_ns: duration as f32,
|
||||||
total_ns: duration as f32,
|
total_ns: duration as f32,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::source::from_iter;
|
use crate::source::{from_iter, FromIter};
|
||||||
use crate::source::FromIter;
|
|
||||||
|
|
||||||
/// Builds a source that chains sources built from a factory.
|
/// Builds a source that chains sources built from a factory.
|
||||||
///
|
///
|
||||||
|
@ -12,7 +11,7 @@ pub fn from_factory<F, S>(factory: F) -> FromIter<FromFactoryIter<F>>
|
||||||
where
|
where
|
||||||
F: FnMut() -> Option<S>,
|
F: FnMut() -> Option<S>,
|
||||||
{
|
{
|
||||||
from_iter(FromFactoryIter { factory: factory })
|
from_iter(FromFactoryIter { factory })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal type used by `from_factory`.
|
/// Internal type used by `from_factory`.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Builds a source that chains sources provided by an iterator.
|
/// Builds a source that chains sources provided by an iterator.
|
||||||
///
|
///
|
||||||
|
@ -18,7 +17,7 @@ where
|
||||||
let first_source = iterator.next();
|
let first_source = iterator.next();
|
||||||
|
|
||||||
FromIter {
|
FromIter {
|
||||||
iterator: iterator,
|
iterator,
|
||||||
current_source: first_source,
|
current_source: first_source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +45,7 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<<I::Item as Iterator>::Item> {
|
fn next(&mut self) -> Option<<I::Item as Iterator>::Item> {
|
||||||
loop {
|
loop {
|
||||||
if let Some(ref mut src) = self.current_source {
|
if let Some(src) = &mut self.current_source {
|
||||||
if let Some(value) = src.next() {
|
if let Some(value) = src.next() {
|
||||||
return Some(value);
|
return Some(value);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +61,7 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
if let Some(ref cur) = self.current_source {
|
if let Some(cur) = &self.current_source {
|
||||||
(cur.size_hint().0, None)
|
(cur.size_hint().0, None)
|
||||||
} else {
|
} else {
|
||||||
(0, None)
|
(0, None)
|
||||||
|
@ -91,7 +90,7 @@ where
|
||||||
const THRESHOLD: usize = 10240;
|
const THRESHOLD: usize = 10240;
|
||||||
|
|
||||||
// Try the current `current_frame_len`.
|
// Try the current `current_frame_len`.
|
||||||
if let Some(ref src) = self.current_source {
|
if let Some(src) = &self.current_source {
|
||||||
if let Some(val) = src.current_frame_len() {
|
if let Some(val) = src.current_frame_len() {
|
||||||
if val != 0 {
|
if val != 0 {
|
||||||
return Some(val);
|
return Some(val);
|
||||||
|
@ -100,7 +99,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try the size hint.
|
// Try the size hint.
|
||||||
if let Some(ref src) = self.current_source {
|
if let Some(src) = &self.current_source {
|
||||||
if let Some(val) = src.size_hint().1 {
|
if let Some(val) = src.size_hint().1 {
|
||||||
if val < THRESHOLD && val != 0 {
|
if val < THRESHOLD && val != 0 {
|
||||||
return Some(val);
|
return Some(val);
|
||||||
|
@ -114,7 +113,7 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn channels(&self) -> u16 {
|
fn channels(&self) -> u16 {
|
||||||
if let Some(ref src) = self.current_source {
|
if let Some(src) = &self.current_source {
|
||||||
src.channels()
|
src.channels()
|
||||||
} else {
|
} else {
|
||||||
// Dummy value that only happens if the iterator was empty.
|
// Dummy value that only happens if the iterator was empty.
|
||||||
|
@ -124,7 +123,7 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_rate(&self) -> u32 {
|
fn sample_rate(&self) -> u32 {
|
||||||
if let Some(ref src) = self.current_source {
|
if let Some(src) = &self.current_source {
|
||||||
src.sample_rate()
|
src.sample_rate()
|
||||||
} else {
|
} else {
|
||||||
// Dummy value that only happens if the iterator was empty.
|
// Dummy value that only happens if the iterator was empty.
|
||||||
|
@ -141,8 +140,7 @@ where
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::buffer::SamplesBuffer;
|
use crate::buffer::SamplesBuffer;
|
||||||
use crate::source::from_iter;
|
use crate::source::{from_iter, Source};
|
||||||
use crate::source::Source;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic() {
|
fn basic() {
|
||||||
|
|
|
@ -2,9 +2,7 @@ use std::cmp;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::source::uniform::UniformSourceIterator;
|
use crate::source::uniform::UniformSourceIterator;
|
||||||
|
use crate::{Sample, Source};
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Mix` object.
|
/// Internal function that builds a `Mix` object.
|
||||||
pub fn mix<I1, I2>(input1: I1, input2: I2) -> Mix<I1, I2>
|
pub fn mix<I1, I2>(input1: I1, input2: I2) -> Mix<I1, I2>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Pausable` object.
|
/// Internal function that builds a `Pausable` object.
|
||||||
pub fn pausable<I>(source: I, paused: bool) -> Pausable<I>
|
pub fn pausable<I>(source: I, paused: bool) -> Pausable<I>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `PeriodicAccess` object.
|
/// Internal function that builds a `PeriodicAccess` object.
|
||||||
pub fn periodic<I, F>(source: I, period: Duration, modifier: F) -> PeriodicAccess<I, F>
|
pub fn periodic<I, F>(source: I, period: Duration, modifier: F) -> PeriodicAccess<I, F>
|
||||||
|
@ -11,12 +10,12 @@ where
|
||||||
{
|
{
|
||||||
// TODO: handle the fact that the samples rate can change
|
// TODO: handle the fact that the samples rate can change
|
||||||
// TODO: generally, just wrong
|
// TODO: generally, just wrong
|
||||||
let update_ms = period.as_secs() as u32 * 1_000 + period.subsec_nanos() / 1_000_000;
|
let update_ms = period.as_secs() as u32 * 1_000 + period.subsec_millis();
|
||||||
let update_frequency = (update_ms * source.sample_rate()) / 1000 * source.channels() as u32;
|
let update_frequency = (update_ms * source.sample_rate()) / 1000 * source.channels() as u32;
|
||||||
|
|
||||||
PeriodicAccess {
|
PeriodicAccess {
|
||||||
input: source,
|
input: source,
|
||||||
modifier: modifier,
|
modifier,
|
||||||
// Can overflow when subtracting if this is 0
|
// Can overflow when subtracting if this is 0
|
||||||
update_frequency: if update_frequency == 0 {
|
update_frequency: if update_frequency == 0 {
|
||||||
1
|
1
|
||||||
|
@ -122,11 +121,12 @@ where
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::buffer::SamplesBuffer;
|
|
||||||
use crate::source::Source;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::buffer::SamplesBuffer;
|
||||||
|
use crate::source::Source;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stereo_access() {
|
fn stereo_access() {
|
||||||
// Stereo, 1Hz audio buffer
|
// Stereo, 1Hz audio buffer
|
||||||
|
|
|
@ -2,8 +2,7 @@ use std::time::Duration;
|
||||||
|
|
||||||
use crate::source::buffered::Buffered;
|
use crate::source::buffered::Buffered;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Repeat` object.
|
/// Internal function that builds a `Repeat` object.
|
||||||
pub fn repeat<I>(input: I) -> Repeat<I>
|
pub fn repeat<I>(input: I) -> Repeat<I>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
use cpal::Sample as CpalSample;
|
use cpal::Sample as CpalSample;
|
||||||
|
|
||||||
/// An iterator that reads from a `Source` and converts the samples to a specific rate and
|
/// An iterator that reads from a `Source` and converts the samples to a specific rate and
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::Source;
|
use std::f32::consts::PI;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::Source;
|
||||||
|
|
||||||
/// An infinite source that produces a sine.
|
/// An infinite source that produces a sine.
|
||||||
///
|
///
|
||||||
/// Always has a rate of 48kHz and one channel.
|
/// Always has a rate of 48kHz and one channel.
|
||||||
|
@ -28,7 +30,7 @@ impl Iterator for SineWave {
|
||||||
fn next(&mut self) -> Option<f32> {
|
fn next(&mut self) -> Option<f32> {
|
||||||
self.num_sample = self.num_sample.wrapping_add(1);
|
self.num_sample = self.num_sample.wrapping_add(1);
|
||||||
|
|
||||||
let value = 2.0 * 3.14159265 * self.freq * self.num_sample as f32 / 48000.0;
|
let value = 2.0 * PI * self.freq * self.num_sample as f32 / 48000.0;
|
||||||
Some(value.sin())
|
Some(value.sin())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::{Sample, Source};
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::{Sample, Source};
|
||||||
|
|
||||||
const NS_PER_SECOND: u128 = 1_000_000_000;
|
const NS_PER_SECOND: u128 = 1_000_000_000;
|
||||||
|
|
||||||
/// Internal function that builds a `SkipDuration` object.
|
/// Internal function that builds a `SkipDuration` object.
|
||||||
|
@ -147,16 +148,17 @@ where
|
||||||
fn total_duration(&self) -> Option<Duration> {
|
fn total_duration(&self) -> Option<Duration> {
|
||||||
self.input.total_duration().map(|val| {
|
self.input.total_duration().map(|val| {
|
||||||
val.checked_sub(self.skipped_duration)
|
val.checked_sub(self.skipped_duration)
|
||||||
.unwrap_or(Duration::from_secs(0))
|
.unwrap_or_else(|| Duration::from_secs(0))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::buffer::SamplesBuffer;
|
use crate::buffer::SamplesBuffer;
|
||||||
use crate::source::Source;
|
use crate::source::Source;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
fn test_skip_duration_samples_left(
|
fn test_skip_duration_samples_left(
|
||||||
channels: u16,
|
channels: u16,
|
||||||
|
@ -168,7 +170,7 @@ mod tests {
|
||||||
.map(|_| 0f32)
|
.map(|_| 0f32)
|
||||||
.collect();
|
.collect();
|
||||||
let test_buffer = SamplesBuffer::new(channels, sample_rate, data);
|
let test_buffer = SamplesBuffer::new(channels, sample_rate, data);
|
||||||
let seconds_left = seconds.checked_sub(seconds_to_skip).unwrap_or(0);
|
let seconds_left = seconds.saturating_sub(seconds_to_skip);
|
||||||
|
|
||||||
let samples_left_expected = (sample_rate * channels as u32 * seconds_left) as usize;
|
let samples_left_expected = (sample_rate * channels as u32 * seconds_left) as usize;
|
||||||
let samples_left = test_buffer
|
let samples_left = test_buffer
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::source::ChannelVolume;
|
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::source::ChannelVolume;
|
||||||
|
use crate::{Sample, Source};
|
||||||
|
|
||||||
/// Combines channels in input into a single mono source, then plays that mono sound
|
/// Combines channels in input into a single mono source, then plays that mono sound
|
||||||
/// to each channel at the volume given for that channel.
|
/// to each channel at the volume given for that channel.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Speed` object.
|
/// Internal function that builds a `Speed` object.
|
||||||
pub fn speed<I>(input: I, factor: f32) -> Speed<I> {
|
pub fn speed<I>(input: I, factor: f32) -> Speed<I> {
|
||||||
Speed {
|
Speed { input, factor }
|
||||||
input: input,
|
|
||||||
factor: factor,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Filter that modifies each sample by a given value.
|
/// Filter that modifies each sample by a given value.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `Stoppable` object.
|
/// Internal function that builds a `Stoppable` object.
|
||||||
pub fn stoppable<I>(source: I) -> Stoppable<I> {
|
pub fn stoppable<I>(source: I) -> Stoppable<I> {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Sample;
|
use crate::{Sample, Source};
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// Internal function that builds a `TakeDuration` object.
|
/// Internal function that builds a `TakeDuration` object.
|
||||||
pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I>
|
pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I>
|
||||||
|
@ -12,7 +11,7 @@ where
|
||||||
TakeDuration {
|
TakeDuration {
|
||||||
current_frame_len: input.current_frame_len(),
|
current_frame_len: input.current_frame_len(),
|
||||||
duration_per_sample: TakeDuration::get_duration_per_sample(&input),
|
duration_per_sample: TakeDuration::get_duration_per_sample(&input),
|
||||||
input: input,
|
input,
|
||||||
remaining_duration: duration,
|
remaining_duration: duration,
|
||||||
requested_duration: duration,
|
requested_duration: duration,
|
||||||
filter: None,
|
filter: None,
|
||||||
|
@ -119,19 +118,17 @@ where
|
||||||
|
|
||||||
if self.remaining_duration <= self.duration_per_sample {
|
if self.remaining_duration <= self.duration_per_sample {
|
||||||
None
|
None
|
||||||
|
} else if let Some(sample) = self.input.next() {
|
||||||
|
let sample = match &self.filter {
|
||||||
|
Some(filter) => filter.apply(sample, &self),
|
||||||
|
None => sample,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.remaining_duration -= self.duration_per_sample;
|
||||||
|
|
||||||
|
Some(sample)
|
||||||
} else {
|
} else {
|
||||||
if let Some(sample) = self.input.next() {
|
None
|
||||||
let sample = match &self.filter {
|
|
||||||
Some(filter) => filter.apply(sample, &self),
|
|
||||||
None => sample,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.remaining_duration = self.remaining_duration - self.duration_per_sample;
|
|
||||||
|
|
||||||
Some(sample)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use cpal;
|
use crate::conversions::{ChannelCountConverter, DataConverter, SampleRateConverter};
|
||||||
|
use crate::{Sample, Source};
|
||||||
use crate::conversions::ChannelCountConverter;
|
|
||||||
use crate::conversions::DataConverter;
|
|
||||||
use crate::conversions::SampleRateConverter;
|
|
||||||
|
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
|
|
||||||
/// An iterator that reads from a `Source` and converts the samples to a specific rate and
|
/// An iterator that reads from a `Source` and converts the samples to a specific rate and
|
||||||
/// channels count.
|
/// channels count.
|
||||||
|
@ -45,9 +39,9 @@ where
|
||||||
|
|
||||||
UniformSourceIterator {
|
UniformSourceIterator {
|
||||||
inner: Some(input),
|
inner: Some(input),
|
||||||
target_channels: target_channels,
|
target_channels,
|
||||||
target_sample_rate: target_sample_rate,
|
target_sample_rate,
|
||||||
total_duration: total_duration,
|
total_duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +68,8 @@ where
|
||||||
from_channels,
|
from_channels,
|
||||||
);
|
);
|
||||||
let input = ChannelCountConverter::new(input, from_channels, target_channels);
|
let input = ChannelCountConverter::new(input, from_channels, target_channels);
|
||||||
let input = DataConverter::new(input);
|
|
||||||
|
|
||||||
input
|
DataConverter::new(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +151,7 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||||
if let Some(ref mut n) = self.n {
|
if let Some(n) = &mut self.n {
|
||||||
if *n != 0 {
|
if *n != 0 {
|
||||||
*n -= 1;
|
*n -= 1;
|
||||||
self.iter.next()
|
self.iter.next()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::Sample;
|
|
||||||
use crate::Source;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::{Sample, Source};
|
||||||
|
|
||||||
/// An infinite source that produces zero.
|
/// An infinite source that produces zero.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Zero<S> {
|
pub struct Zero<S> {
|
||||||
|
@ -15,8 +15,8 @@ impl<S> Zero<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(channels: u16, sample_rate: u32) -> Zero<S> {
|
pub fn new(channels: u16, sample_rate: u32) -> Zero<S> {
|
||||||
Zero {
|
Zero {
|
||||||
channels: channels,
|
channels,
|
||||||
sample_rate: sample_rate,
|
sample_rate,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use crate::source::Spatial;
|
|
||||||
use crate::stream::{OutputStreamHandle, PlayError};
|
|
||||||
use crate::Sample;
|
|
||||||
use crate::Sink;
|
|
||||||
use crate::Source;
|
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::source::Spatial;
|
||||||
|
use crate::stream::{OutputStreamHandle, PlayError};
|
||||||
|
use crate::{Sample, Sink, Source};
|
||||||
|
|
||||||
pub struct SpatialSink {
|
pub struct SpatialSink {
|
||||||
sink: Sink,
|
sink: Sink,
|
||||||
positions: Arc<Mutex<SoundPositions>>,
|
positions: Arc<Mutex<SoundPositions>>,
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
use std::slice::Iter as SliceIter;
|
use std::slice::Iter as SliceIter;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::source::Source;
|
use crate::{Sample, Source};
|
||||||
use crate::Sample;
|
|
||||||
|
|
||||||
/// A buffer of samples treated as a source.
|
/// A buffer of samples treated as a source.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -36,9 +35,9 @@ where
|
||||||
///
|
///
|
||||||
/// # Panic
|
/// # Panic
|
||||||
///
|
///
|
||||||
/// - Panicks if the number of channels is zero.
|
/// - Panics if the number of channels is zero.
|
||||||
/// - Panicks if the samples rate is zero.
|
/// - Panics if the samples rate is zero.
|
||||||
/// - Panicks if the length of the buffer is larger than approximatively 16 billion elements.
|
/// - Panics if the length of the buffer is larger than approximatively 16 billion elements.
|
||||||
/// This is because the calculation of the duration would overflow.
|
/// This is because the calculation of the duration would overflow.
|
||||||
///
|
///
|
||||||
pub fn new(channels: u16, sample_rate: u32, data: &'static [S]) -> StaticSamplesBuffer<S> {
|
pub fn new(channels: u16, sample_rate: u32, data: &'static [S]) -> StaticSamplesBuffer<S> {
|
||||||
|
@ -55,9 +54,9 @@ where
|
||||||
|
|
||||||
StaticSamplesBuffer {
|
StaticSamplesBuffer {
|
||||||
data: data.iter(),
|
data: data.iter(),
|
||||||
channels: channels,
|
channels,
|
||||||
sample_rate: sample_rate,
|
sample_rate,
|
||||||
duration: duration,
|
duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
|
use std::io::{Read, Seek};
|
||||||
|
use std::sync::{Arc, Weak};
|
||||||
|
use std::{error, fmt};
|
||||||
|
|
||||||
use crate::decoder;
|
use crate::decoder;
|
||||||
use crate::dynamic_mixer::{self, DynamicMixerController};
|
use crate::dynamic_mixer::{self, DynamicMixerController};
|
||||||
use crate::sink::Sink;
|
use crate::sink::Sink;
|
||||||
use crate::source::Source;
|
use crate::source::Source;
|
||||||
use cpal::{
|
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
traits::{DeviceTrait, HostTrait, StreamTrait},
|
use cpal::Sample;
|
||||||
Sample,
|
|
||||||
};
|
|
||||||
use std::io::{Read, Seek};
|
|
||||||
use std::sync::{Arc, Weak};
|
|
||||||
use std::{error, fmt};
|
|
||||||
|
|
||||||
/// `cpal::Stream` container. Also see the more useful `OutputStreamHandle`.
|
/// `cpal::Stream` container. Also see the more useful `OutputStreamHandle`.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue