use anyhow::{ anyhow, Result, }; use byteorder::{ ByteOrder, LittleEndian, }; // This crate flitters between being very convenient and being a type labyrinth. use ffmpeg_next::{ decoder::Audio as DecodeContext, format::context::Input as DemuxContext, software::resampling::Context as ResamplingContext, util::{ channel_layout::ChannelLayout, format::sample::{ self, Sample, }, frame::Audio as FfAudioFrame, }, }; pub const SAMPLE_RATE: u32 = 48000; pub struct AudioFrame { frame: FfAudioFrame, } impl AudioFrame { pub fn data (&self) -> &[u8] { // Hard-coded because I'm only support f32 interleaved stereo &self.frame.data (0) [0..self.frame.samples () * 4 * 2] } pub fn rate (&self) -> u32 { self.frame.rate () } pub fn samples (&self) -> usize { self.frame.samples () } } impl From for AudioFrame { fn from (frame: FfAudioFrame) -> Self { Self { frame, } } } #[derive (Default)] pub struct PcmBuffers { buffers: Vec >, // Always points into the first buffer, if any consumer_cursor: usize, } impl PcmBuffers { pub fn samples_available (&self) -> usize { (self.buffers.iter ().map (|b| b.len ()).sum:: () - self.consumer_cursor) / 8 } #[warn(unused_must_use)] pub fn consume_exact (&mut self, data: &mut [f32]) -> bool { if data.len () > self.samples_available () { return false; } for x in data { if self.consumer_cursor >= self.buffers [0].len () { self.buffers.remove (0); self.consumer_cursor = 0; } *x = LittleEndian::read_f32 (&self.buffers [0][self.consumer_cursor..]); self.consumer_cursor += 4; } true } pub fn produce_bytes (&mut self, new_buffer: Vec ) { self.buffers.push (new_buffer); } } pub struct Decoder { demuxer: T, decoder: DecodeContext, resampler: ResamplingContext, dummy_frame: Option , } impl Decoder { pub fn new (demuxer: T, codec: ffmpeg_next::codec::Context) -> Result { let decoder = codec.decoder ().audio ()?; let resampler = decoder.resampler ( Sample::F32 (sample::Type::Packed), ChannelLayout::STEREO, 48000, )?; Ok (Self { demuxer, decoder, resampler, dummy_frame: None, }) } fn new_frame () -> FfAudioFrame { let mut x = FfAudioFrame::empty (); x.set_channel_layout (ChannelLayout::STEREO); x.set_format (Sample::F32 (sample::Type::Packed)); x } pub fn next (&mut self) -> Result