use super::error::SampleSourceError;
pub trait SampleSource: Send + Sync {
fn next_sample(&mut self) -> Result<Option<f32>, SampleSourceError>;
fn channel_count(&self) -> u16;
fn sample_rate(&self) -> u32;
fn bits_per_sample(&self) -> u16;
fn sample_format(&self) -> crate::audio::SampleFormat;
fn duration(&self) -> Option<std::time::Duration>;
}
impl SampleSource for Box<dyn SampleSource> {
fn next_sample(&mut self) -> Result<Option<f32>, SampleSourceError> {
(**self).next_sample()
}
fn channel_count(&self) -> u16 {
(**self).channel_count()
}
fn sample_rate(&self) -> u32 {
(**self).sample_rate()
}
fn bits_per_sample(&self) -> u16 {
(**self).bits_per_sample()
}
fn sample_format(&self) -> crate::audio::SampleFormat {
(**self).sample_format()
}
fn duration(&self) -> Option<std::time::Duration> {
(**self).duration()
}
}
pub trait ChannelMappedSampleSource: Send + Sync {
fn next_sample(&mut self) -> Result<Option<f32>, SampleSourceError>;
fn next_frame(&mut self, output: &mut [f32]) -> Result<Option<usize>, SampleSourceError> {
let channel_count = self.source_channel_count() as usize;
if output.len() < channel_count {
return Err(SampleSourceError::SampleConversionFailed(format!(
"Output buffer too small: need {} samples",
channel_count
)));
}
for out in output.iter_mut().take(channel_count) {
match self.next_sample()? {
Some(sample) => *out = sample,
None => return Ok(None),
}
}
Ok(Some(channel_count))
}
fn read_frames(
&mut self,
output: &mut [f32],
max_frames: usize,
) -> Result<usize, SampleSourceError> {
let channel_count = self.source_channel_count() as usize;
debug_assert!(
output.len() >= max_frames * channel_count,
"read_frames: output buffer too small ({} < {})",
output.len(),
max_frames * channel_count,
);
let mut frames_read = 0;
for frame_idx in 0..max_frames {
let offset = frame_idx * channel_count;
match self.next_frame(&mut output[offset..offset + channel_count]) {
Ok(Some(_)) => frames_read += 1,
Ok(None) | Err(_) => break,
}
}
Ok(frames_read)
}
fn channel_mappings(&self) -> &[Vec<String>];
fn source_channel_count(&self) -> u16;
fn is_exhausted(&self) -> Option<bool> {
None
}
}
#[cfg(test)]
pub trait SampleSourceTestExt {
fn is_finished(&self) -> bool;
}