use crate::{adapter::AudioAdapter, frame::AudioFrame};
pub type AdapterAudioFrame<A, B> = AudioFrame<
<A as AudioAdapter>::SampleFormat,
<A as AudioAdapter>::ChannelLayout,
<A as AudioAdapter>::FrameExtra,
B,
>;
pub trait AudioResampler {
type Adapter: AudioAdapter;
type Buffer: AsRef<[u8]>;
type Error;
fn send_frame(
&mut self,
frame: &AdapterAudioFrame<Self::Adapter, Self::Buffer>,
) -> Result<(), Self::Error>;
fn receive_frame(
&mut self,
dst: &mut AdapterAudioFrame<Self::Adapter, Self::Buffer>,
) -> Result<(), Self::Error>;
fn send_eof(&mut self) -> Result<(), Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::frame::AudioFrame;
struct ALoop;
impl AudioAdapter for ALoop {
type CodecId = u32;
type SampleFormat = u32;
type ChannelLayout = u32;
type PacketExtra = ();
type FrameExtra = ();
}
#[derive(Debug, PartialEq, Eq)]
enum LoopError {
Again,
SourceChanged,
}
struct LoopResampler {
pending: bool,
}
impl AudioResampler for LoopResampler {
type Adapter = ALoop;
type Buffer = &'static [u8];
type Error = LoopError;
fn send_frame(
&mut self,
frame: &AudioFrame<u32, u32, (), &'static [u8]>,
) -> Result<(), LoopError> {
if frame.sample_rate() != 48_000 {
return Err(LoopError::SourceChanged);
}
self.pending = true;
Ok(())
}
fn receive_frame(
&mut self,
_dst: &mut AudioFrame<u32, u32, (), &'static [u8]>,
) -> Result<(), LoopError> {
if !self.pending {
return Err(LoopError::Again);
}
self.pending = false;
Ok(())
}
fn send_eof(&mut self) -> Result<(), LoopError> {
Ok(())
}
fn flush(&mut self) -> Result<(), LoopError> {
self.pending = false;
Ok(())
}
}
fn frame(rate: u32) -> AudioFrame<u32, u32, (), &'static [u8]> {
const EMPTY: &[u8] = &[];
AudioFrame::new(
rate,
1024,
2,
0,
0,
[crate::frame::Plane::new(EMPTY, 0); 8],
1,
(),
)
}
#[test]
fn the_face_is_implementable_and_signals_needs_more_by_error() {
fn _accepts<R: AudioResampler>() {}
_accepts::<LoopResampler>();
let mut r = LoopResampler { pending: false };
let mut dst = frame(48_000);
assert_eq!(r.receive_frame(&mut dst), Err(LoopError::Again));
r.send_frame(&frame(48_000)).expect("matching spec");
assert_eq!(r.receive_frame(&mut dst), Ok(()));
assert_eq!(r.receive_frame(&mut dst), Err(LoopError::Again));
}
#[test]
fn a_mid_stream_change_is_refused_by_name() {
let mut r = LoopResampler { pending: false };
r.send_frame(&frame(48_000)).expect("matching spec");
assert_eq!(
r.send_frame(&frame(44_100)),
Err(LoopError::SourceChanged),
"the face never silently reconfigures",
);
}
#[test]
fn flush_drops_the_undrained_tail() {
let mut r = LoopResampler { pending: false };
r.send_frame(&frame(48_000)).expect("matching spec");
r.flush().expect("flush");
let mut dst = frame(48_000);
assert_eq!(r.receive_frame(&mut dst), Err(LoopError::Again));
}
}