//! Iterators over audio.
use std::fmt::Debug;
mod append;
mod append_zeros;
mod convert_to_mono;
mod gain;
mod prepend_zeros;
mod scale;
mod select_channels;
mod skip_frames;
mod sum;
mod take_frames;
mod waveform_source;
pub use append::Append;
pub use append_zeros::AppendZeros;
pub use convert_to_mono::ConvertToMono;
pub use gain::Gain;
pub use prepend_zeros::PrependZeros;
pub use scale::Scale;
pub use select_channels::SelectChannels;
pub use skip_frames::SkipFrames;
pub use sum::Sum;
pub use take_frames::TakeFrames;
pub use waveform_source::WaveformSource;
use crate::backend::Error;
use crate::backend::Signal;
use crate::backend::Waveform;
/// A sample iterator created by an audio decoder.
pub trait Source: Signal + Iterator<Item = f32> + Debug {
/// Append one [`Source`] after another [`Source`].
///
/// Both Sources are required to have the same frame rate and number
/// of channels.
///
/// # Examples
///
/// ```
/// use babycat::assertions::assert_debug;
/// use babycat::{decoder::SymphoniaDecoder, Source, Signal, Waveform};
///
/// // Load the FIRST audio file as a source.
/// let f1 = "audio-for-tests/circus-of-freaks/track.flac";
/// let mut d1 = SymphoniaDecoder::from_file(f1).unwrap();
/// assert_debug(
/// &d1,
/// "SymphoniaDecoder { 2491247 frames, 2 channels, 44100 hz, 56s 490ms }"
/// );
///
/// // Load the SECOND audio file as a source.
/// let f2 = "audio-for-tests/andreas-theme/track.flac";
/// let mut d2 = SymphoniaDecoder::from_file(f2).unwrap();
/// assert_debug(
/// &d2,
/// "SymphoniaDecoder { 9586415 frames, 2 channels, 44100 hz, 3m 37s 379ms }"
/// );
///
/// // Append the second audio file AFTER the first audio file.
/// // The new length (in frames) is the sum of the two audio files' lengths.
/// let d1_d2 = d1.append(d2).unwrap();
///
/// // Test that it works.
/// assert_debug(
/// &d1_d2,
/// "Append { 2491247 + 9586415 = 12077662 frames, 2 channels, 44100 hz, 4m 33s 869ms }"
/// );
/// ```
#[inline]
fn append<S2: Source + Sized>(self, second: S2) -> Result<Append<Self, S2>, Error>
where
Self: Sized,
{
Append::new(self, second)
}
/// Pad the *beginning* of the [`Source`] with silence.
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
///
/// // Set up a 3-frame, 2-channel `Source`.
/// let frame_rate_hz = 44100;
/// let num_channels = 2;
/// let inp = vec![-1.0, -0.5, 0.1, 0.1, 0.5, 1.0];
/// let source = WaveformSource::from_interleaved_samples(
/// frame_rate_hz, num_channels, &inp
/// );
///
/// // Prepend 3 frames (6 samples) of silent zero values.
/// let out = source.prepend_zeros(3);
///
/// // Test that it works.
/// let out_samples = out.collect_interleaved_samples();
/// assert_eq!(
/// &out_samples,
/// &[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, -0.5, 0.1, 0.1, 0.5, 1.0],
/// );
/// ```
#[inline]
fn prepend_zeros(self, num_frames: usize) -> PrependZeros<Self>
where
Self: Sized,
{
PrependZeros::new(self, num_frames)
}
/// Pad the *end* of the [`Source`] with silence.
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
///
/// // Set up a 3-frame, 2-channel `Source`.
/// let frame_rate_hz = 44100;
/// let num_channels = 2;
/// let inp = vec![-1.0, -0.5, 0.1, 0.1, 0.5, 1.0];
/// let source = WaveformSource::from_interleaved_samples(
/// frame_rate_hz, num_channels, &inp
/// );
///
/// // Append 3 frames (6 samples) of silent zero values.
/// let out = source.append_zeros(3);
///
/// // Test that it works.
/// let out_samples = out.collect_interleaved_samples();
/// assert_eq!(
/// &out_samples,
/// &[-1.0, -0.5, 0.1, 0.1, 0.5, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
/// );
/// ```
#[inline]
fn append_zeros(self, num_frames: usize) -> AppendZeros<Self>
where
Self: Sized,
{
AppendZeros::new(self, num_frames)
}
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
///
/// // Set up a 3-frame, 2-channel `Source`.
/// let frame_rate_hz = 44100;
/// let num_channels = 2;
/// let inp = vec![-1.0, -0.5, 0.0, 0.0, 0.5, 1.0];
/// let source = WaveformSource::from_interleaved_samples(
/// frame_rate_hz, num_channels, &inp
/// );
///
/// // Alter the audio's gain by -10 dbFS.
/// let out = source.gain_dbfs(-10.0);
///
/// // Test that it works.
/// let out_samples = out.collect_interleaved_samples();
/// assert_eq!(
/// &out_samples,
/// &[-0.31622776, -0.15811388, 0.0, 0.0, 0.15811388, 0.31622776],
/// );
/// ```
#[inline]
fn gain_dbfs(self, dbfs: f32) -> Gain<Self>
where
Self: Sized,
{
Gain::new(self, dbfs)
}
/// Multiply each sample by a constant factor.
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
///
/// // Set up a 3-frame, 2-channel `Source`.
/// let frame_rate_hz = 44100;
/// let num_channels = 2;
/// let inp = vec![-1.0, -0.5, 0.0, 0.0, 0.5, 1.0];
/// let source = WaveformSource::from_interleaved_samples(
/// frame_rate_hz, num_channels, &inp
/// );
///
/// // Multiply each sample by 0.25.
/// let out = source.scale(0.25);
///
/// // Test that it works.
/// let out_samples = out.collect_interleaved_samples();
/// assert_eq!(
/// out_samples,
/// &[-0.25, -0.125, 0.0, 0.0, 0.125, 0.25],
/// );
/// ```
#[inline]
fn scale(self, constant: f32) -> Scale<Self>
where
Self: Sized,
{
Scale::new(self, constant)
}
/// Skip the first `n` frames.
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
///
/// let frame_rate_hz = 44100;
/// let num_channels = 2;
/// let inp = vec![-1.0, 1.0, -0.5, 0.5, -0.0, 0.0, -0.5, 0.5, -1.0, 1.0];
/// let source = WaveformSource::from_interleaved_samples(
/// frame_rate_hz, num_channels, &inp
/// );
///
/// // Skip the first 2 frames in the `Source`.
/// let out = source.skip_frames(2);
///
/// // Test that it works.
/// let out_samples = out.collect_interleaved_samples();
/// assert_eq!(
/// out_samples,
/// &[-0.0, 0.0, -0.5, 0.5, -1.0, 1.0],
/// );
/// ```
#[inline]
fn skip_frames(self, num_frames: usize) -> SkipFrames<Self>
where
Self: Sized,
{
SkipFrames::new(self, num_frames)
}
#[inline]
fn sum<S2: Source + Sized>(self, second: S2) -> Sum<Self, S2>
where
Self: Sized,
{
Sum::new(self, second, 0)
}
#[inline]
fn sum_with_frame_offset<S2: Source + Sized>(
self,
second: S2,
offset_frames: usize,
) -> Sum<Self, S2>
where
Self: Sized,
{
Sum::new(self, second, offset_frames)
}
/// Take the first `n` frames.
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
///
/// let frame_rate_hz = 44100;
/// let num_channels = 2;
/// let inp = vec![-1.0, 1.0, -0.5, 0.5, -0.0, 0.0, -0.5, 0.5, -1.0, 1.0];
/// let source = WaveformSource::from_interleaved_samples(
/// frame_rate_hz, num_channels, &inp
/// );
///
/// // Take the first 3 frames.
/// let out = source.take_frames(3);
/// let out_samples = out.collect_interleaved_samples();
/// assert_eq!(
/// out_samples,
/// &[-1.0, 1.0, -0.5, 0.5, -0.0, 0.0],
/// );
/// ```
#[inline]
fn take_frames(self, num_frames: usize) -> TakeFrames<Self>
where
Self: Sized,
{
TakeFrames::new(self, num_frames)
}
/// Select an interval of frames between `[start_idx, end_idx)`
/// (including `start_idx` and excluding `end_idx`).
///
/// # Examples
/// ```
/// use babycat::{Source, WaveformSource};
/// let inp = vec![-1.0, 1.0, -0.5, 0.5, -0.0, 0.0, -0.5, 0.5, -1.0, 1.0];
///
///
/// // Select frames 1-3.
/// let source = WaveformSource::from_interleaved_samples(44100, 2, &inp);
/// let selected = source.select_frames(1, 3);
/// let out = selected.collect_interleaved_samples();
/// assert_eq!(out, &[-0.5, 0.5, -0.0, 0.0]);
///
///
/// // Select the first 2 frames.
/// let source = WaveformSource::from_interleaved_samples(44100, 2, &inp);
/// let selected = source.select_frames(0, 2);
/// let out = selected.collect_interleaved_samples();
/// assert_eq!(out, &[-1.0, 1.0, -0.5, 0.5]);
///
///
/// // Skip the first 2 frames and select the remainder.
/// let source = WaveformSource::from_interleaved_samples(44100, 2, &inp);
/// let selected = source.select_frames(2, 0);
/// let out = selected.collect_interleaved_samples();
/// assert_eq!(out, &[-0.0, 0.0, -0.5, 0.5, -1.0, 1.0]);
///
///
/// // Select all of the frames.
/// let source = WaveformSource::from_interleaved_samples(44100, 2, &inp);
/// let selected = source.select_frames(0, 0);
/// let out = selected.collect_interleaved_samples();
/// assert_eq!(out, &[-1.0, 1.0, -0.5, 0.5, -0.0, 0.0, -0.5, 0.5, -1.0, 1.0]);
/// ```
#[inline]
fn select_frames<'a>(self, start_frame_idx: usize, end_frame_idx: usize) -> Box<dyn Source + 'a>
where
Self: 'a + Sized,
{
match (start_frame_idx, end_frame_idx) {
(0, 0) => Box::new(self),
(_, 0) => Box::new(self.skip_frames(start_frame_idx)),
(0, _) => Box::new(self.take_frames(end_frame_idx)),
(_, _) => Box::new(
self.skip_frames(start_frame_idx)
.take_frames(end_frame_idx.saturating_sub(start_frame_idx)),
),
}
}
/// Select the first `n` channels.
///
/// # Examples
/// ```
/// use babycat::{Source, Waveform};
///
/// // Create a 4-frame, 3-channel `Source`.
/// let frame_rate_hz: u32 = 44100;
/// let num_channels: u16 = 3;
/// let interleaved_samples = vec![-1.0, 1.0, 0.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, -1.0, 1.0, 0.0];
/// let s = Waveform::new(frame_rate_hz, num_channels, interleaved_samples).into_source();
///
/// // Select the first 2 channels out of a 3-channel `Source`.
/// let output_samples = s.select_first_channels(2).collect_interleaved_samples();
///
/// // Test that it works.
/// assert_eq!(
/// output_samples,
/// &[-1.0, 1.0, -0.5, 0.5, -0.5, 0.5, -1.0, 1.0],
/// );
/// ```
#[inline]
fn select_first_channels(self, selected_num_channels: u16) -> SelectChannels<Self>
where
Self: Sized,
{
SelectChannels::new(self, selected_num_channels)
}
/// Average the samples in each channel to produce a 1-channel monophonic [`Source`].
///
/// # Examples
/// ```
/// use babycat::{Source, Waveform};
///
/// let interleaved_samples = vec![-1.0, 0.5, -0.5, 0.25, -0.25, 0.125];
/// let s = Waveform::new(44100, 2, interleaved_samples).into_source();
///
/// let output_samples = s.convert_to_mono().collect_interleaved_samples();
///
/// assert_eq!(
/// output_samples,
/// &[-0.25, -0.125, -0.0625],
/// );
/// ```
#[inline]
fn convert_to_mono(self) -> ConvertToMono<Self>
where
Self: Sized,
{
ConvertToMono::new(self)
}
/// Return a [`Vec<f32>`](std::vec::Vec) of collected interleaved samples.
#[inline]
fn collect_interleaved_samples(self) -> Vec<f32>
where
Self: Sized,
{
self.collect()
}
/// Collect all samples into memory and return a [`Waveform`].
///
/// # Examples
/// ```
/// use babycat::assertions::assert_debug;
/// use babycat::{decoder::SymphoniaDecoder, Source, Signal};
///
/// // Decode an audio file into a `SymphoniaDecoder` iterator.
/// let mut decoder = SymphoniaDecoder::from_file("audio-for-tests/circus-of-freaks/track.flac").unwrap();
/// assert_debug(
/// &decoder,
/// "SymphoniaDecoder { 2491247 frames, 2 channels, 44100 hz, 56s 490ms }"
/// );
///
/// // Convert the `SymphoniaDecoder` iterator into a `Waveform` struct,
/// // which loads all of the audio samples into memory.
/// let waveform = decoder.to_waveform();
/// assert_debug(
/// &waveform,
/// "Waveform { 2491247 frames, 2 channels, 44100 hz, 56s 490ms }"
/// );
/// ```
#[inline]
fn to_waveform(self) -> Waveform
where
Self: Sized,
{
let frame_rate_hz = self.frame_rate_hz();
let num_channels = self.num_channels();
let interleaved_samples = self.collect_interleaved_samples();
Waveform::new(frame_rate_hz, num_channels, interleaved_samples)
}
/// Collect all samples and return a [`WaveformSource`].
///
/// # Examples
/// ```
/// use babycat::assertions::assert_debug;
/// use babycat::{decoder::SymphoniaDecoder, Source, Signal};
///
/// // Decode an audio file into a `SymphoniaDecoder` iterator.
/// let mut decoder = SymphoniaDecoder::from_file("audio-for-tests/circus-of-freaks/track.flac").unwrap();
/// assert_debug(
/// &decoder,
/// "SymphoniaDecoder { 2491247 frames, 2 channels, 44100 hz, 56s 490ms }"
/// );
///
/// // Convert the `SymphoniaDecoder` iterator into a `WaveformSource` iterator,
/// // which loads all of the audio samples into memory.
/// let waveform_source = decoder.to_waveform_source();
/// assert_debug(
/// &waveform_source,
/// "WaveformSource { 2491247 frames, 2 channels, 44100 hz, 56s 490ms }"
/// );
///
#[inline]
fn to_waveform_source(self) -> WaveformSource
where
Self: Sized,
{
let waveform = self.to_waveform();
waveform.into_source()
}
}
impl Source for Box<dyn Source + '_> {}
impl Signal for Box<dyn Source + '_> {
#[inline]
fn frame_rate_hz(&self) -> u32 {
(&**self).frame_rate_hz()
}
#[inline]
fn num_channels(&self) -> u16 {
(&**self).num_channels()
}
#[inline]
fn num_frames_estimate(&self) -> Option<usize> {
(&**self).num_frames_estimate()
}
}