Docs: Added where missing corrected where wrong

Specifically the documentation for
 - UniformSourceIterator was incomplete it did not mention that it can
   change the sample type
This commit is contained in:
github-actions[bot] 2024-09-16 18:52:19 +02:00
parent 70c236c7ac
commit 22d90e71d8
No known key found for this signature in database
GPG key ID: F687E89FC7894F98
17 changed files with 98 additions and 44 deletions

View file

@ -23,6 +23,7 @@ mod mp3;
#[cfg(feature = "symphonia")]
mod read_seek_source;
#[cfg(feature = "symphonia")]
/// Symphonia decoders types
pub mod symphonia;
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
mod vorbis;
@ -36,11 +37,15 @@ pub struct Decoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
/// Source of audio samples from decoding a file that never ends. When the
/// end of the file is reached the decoder starts again from the beginning.
///
/// Supports MP3, WAV, Vorbis and Flac.
pub struct LoopedDecoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
// can not really reduce the size of the VorbisDecoder. There are not any
// Cannot really reduce the size of the VorbisDecoder. There are not any
// arrays just a lot of struct fields.
#[allow(clippy::large_enum_variant)]
enum DecoderImpl<R>
@ -239,6 +244,10 @@ where
#[cfg(not(feature = "symphonia"))]
Err(DecoderError::UnrecognizedFormat)
}
/// Builds a new looped decoder.
///
/// Attempts to automatically detect the format of the source of data.
pub fn new_looped(data: R) -> Result<LoopedDecoder<R>, DecoderError> {
Self::new(data).map(LoopedDecoder::new)
}
@ -329,6 +338,7 @@ where
}
}
#[allow(missing_docs)] // Reason: will be removed, see: #612
#[derive(Debug)]
pub enum Mp4Type {
Mp4,

View file

@ -210,12 +210,16 @@ impl Source for SymphoniaDecoder {
#[derive(Debug, thiserror::Error)]
pub enum SeekError {
/// Could not get next packet while refining seek position
#[error("Could not get next packet while refining seek position: {0:?}")]
Refining(symphonia::core::errors::Error),
/// Format reader failed to seek
#[error("Format reader failed to seek: {0:?}")]
BaseSeek(symphonia::core::errors::Error),
/// Decoding failed retrying on the next packet failed
#[error("Decoding failed retrying on the next packet failed: {0:?}")]
Retrying(symphonia::core::errors::Error),
/// Decoding failed on multiple consecutive packets
#[error("Decoding failed on multiple consecutive packets: {0:?}")]
Decoding(symphonia::core::errors::Error),
}

View file

@ -27,6 +27,11 @@ where
input_fadeout.mix(input_fadein)
}
/// Mixes one sound fading out with another sound fading in for the given
/// duration.
///
/// Only the crossfaded portion (beginning of fadeout, beginning of fadein) is
/// covered.
pub type Crossfade<I1, I2> = Mix<TakeDuration<I1>, FadeIn<TakeDuration<I2>>>;
#[cfg(test)]

View file

@ -6,7 +6,7 @@ use crate::{Sample, Source};
use super::SeekError;
/// When the inner source is empty this decrements an `AtomicUsize`.
/// When the inner source is empty this decrements a `AtomicUsize`.
#[derive(Debug, Clone)]
pub struct Done<I> {
input: I,
@ -15,6 +15,8 @@ pub struct Done<I> {
}
impl<I> Done<I> {
/// When the inner source is empty the AtomicUsize passed in is decremented.
/// If it was zero it will overflow negatively.
#[inline]
pub fn new(input: I, signal: Arc<AtomicUsize>) -> Done<I> {
Done {

View file

@ -17,6 +17,8 @@ impl<S> Default for Empty<S> {
}
impl<S> Empty<S> {
/// An empty source that immediately ends without ever returning a sample to
/// play
#[inline]
pub fn new() -> Empty<S> {
Empty(PhantomData)

View file

@ -13,9 +13,15 @@ pub struct EmptyCallback<S> {
impl<S> EmptyCallback<S> {
#[inline]
/// Create an empty source which executes a callback function.
/// Example use-case:
///
/// Detect and do something when the source before this one has ended.
pub fn new(callback: Box<dyn Send + Fn()>) -> EmptyCallback<S> {
EmptyCallback {
#[allow(missing_docs)] // See: https://github.com/RustAudio/rodio/issues/615
phantom_data: PhantomData,
#[allow(missing_docs)] // See: https://github.com/RustAudio/rodio/issues/615
callback,
}
}

View file

@ -360,6 +360,9 @@ where
stoppable::stoppable(self)
}
/// Adds a method [`Skippable::skip`] for skipping this source. Skipping
/// makes Source::next() return None. Which in turn makes the Sink skip to
/// the next source.
fn skippable(self) -> Skippable<Self>
where
Self: Sized,
@ -374,7 +377,7 @@ where
/// in the position returned by [`get_pos`](TrackPosition::get_pos).
///
/// This can get confusing when using [`get_pos()`](TrackPosition::get_pos)
/// together with [`Source::try_seek()`] as the the latter does take all
/// together with [`Source::try_seek()`] as the latter does take all
/// speedup's and delay's into account. Its recommended therefore to apply
/// track_position after speedup's and delay's.
fn track_position(self) -> TrackPosition<Self>
@ -455,22 +458,32 @@ where
// We might add decoders requiring new error types, without non_exhaustive
// this would break users builds
/// Occurs when try_seek fails because the underlying decoder has an error or
/// does not support seeking.
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum SeekError {
#[error("Streaming is not supported by source: {underlying_source}")]
/// On of the underlying sources does not support seeking
#[error("Seeking is not supported by source: {underlying_source}")]
NotSupported { underlying_source: &'static str },
#[cfg(feature = "symphonia")]
/// The symphonia decoder ran into an issue
#[error("Error seeking: {0}")]
SymphoniaDecoder(#[from] crate::decoder::symphonia::SeekError),
#[cfg(feature = "wav")]
#[error("Error seeking in wav source: {0}")]
/// The hound (wav) decoder ran into an issue
HoundDecoder(std::io::Error),
// Prefer adding an enum variant to using this. Its meant for end users their
// own try_seek implementations
/// Any other error probably in a custom Source
#[error("An error occurred")]
Other(Box<dyn std::error::Error + Send>),
}
impl SeekError {
/// Will the source remain playing at its position before the seek or is it
/// broken?
pub fn source_intact(&self) -> bool {
match self {
SeekError::NotSupported { .. } => true,

View file

@ -4,7 +4,7 @@ use crate::{Sample, Source};
use super::SeekError;
/// Internal function that builds a `Pausable` object.
/// Builds a `Pausable` object.
pub fn pausable<I>(source: I, paused: bool) -> Pausable<I>
where
I: Source,
@ -22,6 +22,12 @@ where
}
}
/// Wraps a source and makes it pausable by calling [`Pausable::set_paused`] on
/// this object. When the source is paused it returns zero value samples.
///
/// You can usually still use this from another source wrapping this one by
/// calling `inner_mut` on it. Similarly this provides [`Pausable::inner`] and
/// mutable/destructing variants for accessing the underlying source.
#[derive(Clone, Debug)]
pub struct Pausable<I> {
input: I,

View file

@ -17,6 +17,7 @@ pub fn track_position<I>(source: I) -> TrackPosition<I> {
}
}
/// Tracks the elapsed duration since the start of the underlying source.
#[derive(Debug)]
pub struct TrackPosition<I> {
input: I,

View file

@ -6,11 +6,8 @@ use cpal::{FromSample, Sample as CpalSample};
use super::SeekError;
/// An iterator that reads from a `Source` and converts the samples to a specific rate and
/// channels count.
///
/// It implements `Source` as well, but all the data is guaranteed to be in a single frame whose
/// channels and samples rate have been passed to `new`.
/// Wrap the input and lazily converts the samples it provides to the type
/// specified by the generic parameter D
#[derive(Clone)]
pub struct SamplesConverter<I, D> {
inner: I,
@ -18,6 +15,8 @@ pub struct SamplesConverter<I, D> {
}
impl<I, D> SamplesConverter<I, D> {
/// Wrap the input and lazily converts the samples it provides to the type
/// specified by the generic parameter D
#[inline]
pub fn new(input: I) -> SamplesConverter<I, D> {
SamplesConverter {

View file

@ -5,7 +5,9 @@ use crate::Source;
use super::SeekError;
/// Internal function that builds a `Skippable` object.
/// Wrap the source in a skippable. It allows ending the current source early by
/// calling [`Skippable::skip`]. If this source is in a queue such as the Sink
/// ending the source early is equal to skipping the source.
pub fn skippable<I>(source: I) -> Skippable<I> {
Skippable {
input: source,
@ -13,6 +15,9 @@ pub fn skippable<I>(source: I) -> Skippable<I> {
}
}
/// Wrap the source in a skippable. It allows ending the current source early by
/// calling [`Skippable::skip`]. If this source is in a queue such as the Sink
/// ending the source early is equal to skipping the source.
#[derive(Clone, Debug)]
pub struct Skippable<I> {
input: I,

View file

@ -29,6 +29,7 @@ where
I: Source,
I::Item: Sample,
{
/// Builds a new `SpatialSink`, beginning playback on a stream.
pub fn new(
input: I,
emitter_position: [f32; 3],

View file

@ -4,7 +4,7 @@ use crate::{Sample, Source};
use super::SeekError;
/// Internal function that builds a `Stoppable` object.
/// This is the same as [`skippable`](crate::source::skippable) see its docs
pub fn stoppable<I>(source: I) -> Stoppable<I> {
Stoppable {
input: source,
@ -12,6 +12,7 @@ pub fn stoppable<I>(source: I) -> Stoppable<I> {
}
}
/// This is the same as [`Skippable`](crate::source::Skippable) see its docs
#[derive(Clone, Debug)]
pub struct Stoppable<I> {
input: I,

View file

@ -91,10 +91,13 @@ where
self.input
}
/// Make the truncated source end with a FadeOut. The fadeout covers the
/// entire length of the take source.
pub fn set_filter_fadeout(&mut self) {
self.filter = Some(DurationFilter::FadeOut);
}
/// Remove any filter set.
pub fn clear_filter(&mut self) {
self.filter = None;
}

View file

@ -8,11 +8,11 @@ use crate::{Sample, Source};
use super::SeekError;
/// An iterator that reads from a `Source` and converts the samples to a specific rate and
/// channels count.
/// An iterator that reads from a `Source` and converts the samples to a
/// specific type, sample-rate and channels count.
///
/// It implements `Source` as well, but all the data is guaranteed to be in a single frame whose
/// channels and samples rate have been passed to `new`.
/// It implements `Source` as well, but all the data is guaranteed to be in a
/// single frame whose channels and samples rate have been passed to `new`.
#[derive(Clone)]
pub struct UniformSourceIterator<I, D>
where
@ -32,6 +32,8 @@ where
I::Item: Sample,
D: Sample,
{
/// Wrap a `Source` and lazily convert its samples to a specific type,
/// sample-rate and channels count.
#[inline]
pub fn new(
input: I,

View file

@ -5,7 +5,9 @@ use crate::{Sample, Source};
use super::SeekError;
/// An infinite source that produces zero.
/// An source that produces samples with value zero (silence). Depending on if
/// it where created with [`Zero::new`] or [`Zero::new_samples`] it can be never
/// ending or finite.
#[derive(Clone, Debug)]
pub struct Zero<S> {
channels: u16,
@ -15,6 +17,7 @@ pub struct Zero<S> {
}
impl<S> Zero<S> {
/// Create a new source that never ends and produces total silence.
#[inline]
pub fn new(channels: u16, sample_rate: u32) -> Zero<S> {
Zero {
@ -24,6 +27,7 @@ impl<S> Zero<S> {
marker: PhantomData,
}
}
/// Create a new source that never ends and produces total silence.
#[inline]
pub fn new_samples(channels: u16, sample_rate: u32, num_samples: usize) -> Zero<S> {
Zero {

View file

@ -29,7 +29,9 @@ impl OutputStream {
pub fn try_from_device(
device: &cpal::Device,
) -> Result<(Self, OutputStreamHandle), StreamError> {
let default_config = device.default_output_config()?;
let default_config = device
.default_output_config()
.map_err(StreamError::DefaultStreamConfigError)?;
OutputStream::try_from_device_config(device, default_config)
}
@ -42,7 +44,7 @@ impl OutputStream {
config: SupportedStreamConfig,
) -> Result<(Self, OutputStreamHandle), StreamError> {
let (mixer, _stream) = device.try_new_output_stream_config(config)?;
_stream.play()?;
_stream.play().map_err(StreamError::PlayStreamError)?;
let out = Self { mixer, _stream };
let handle = OutputStreamHandle {
mixer: Arc::downgrade(&out.mixer),
@ -130,39 +132,24 @@ impl error::Error for PlayError {
}
}
/// Errors that might occur when interfacing with audio output.
#[derive(Debug)]
pub enum StreamError {
/// Could not start playing the stream, see [cpal::PlayStreamError] for
/// details.
PlayStreamError(cpal::PlayStreamError),
/// Failed to get the stream config for device the given device. See
/// [cpal::DefaultStreamConfigError] for details
DefaultStreamConfigError(cpal::DefaultStreamConfigError),
/// Error opening stream with OS. See [cpal::BuildStreamError] for details
BuildStreamError(cpal::BuildStreamError),
/// Could not list supported stream configs for device. Maybe it
/// disconnected, for details see: [cpal::SupportedStreamConfigsError].
SupportedStreamConfigsError(cpal::SupportedStreamConfigsError),
/// Could not find any output device
NoDevice,
}
impl From<cpal::DefaultStreamConfigError> for StreamError {
fn from(err: cpal::DefaultStreamConfigError) -> Self {
Self::DefaultStreamConfigError(err)
}
}
impl From<cpal::SupportedStreamConfigsError> for StreamError {
fn from(err: cpal::SupportedStreamConfigsError) -> Self {
Self::SupportedStreamConfigsError(err)
}
}
impl From<cpal::BuildStreamError> for StreamError {
fn from(err: cpal::BuildStreamError) -> Self {
Self::BuildStreamError(err)
}
}
impl From<cpal::PlayStreamError> for StreamError {
fn from(err: cpal::PlayStreamError) -> Self {
Self::PlayStreamError(err)
}
}
impl fmt::Display for StreamError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@ -342,7 +329,10 @@ fn supported_output_formats(
) -> Result<impl Iterator<Item = cpal::SupportedStreamConfig>, StreamError> {
const HZ_44100: cpal::SampleRate = cpal::SampleRate(44_100);
let mut supported: Vec<_> = device.supported_output_configs()?.collect();
let mut supported: Vec<_> = device
.supported_output_configs()
.map_err(StreamError::SupportedStreamConfigsError)?
.collect();
supported.sort_by(|a, b| b.cmp_default_heuristics(a));
Ok(supported.into_iter().flat_map(|sf| {