use std::{ io::Cursor, }; use anyhow::{ anyhow, Result, }; use byteorder::{ LittleEndian, ReadBytesExt, }; // 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 AudioFrame, }, }; pub const SAMPLE_RATE: u32 = 48000; #[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 } #[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 = self.buffers [0][self.consumer_cursor]; self.consumer_cursor += 1; } true } pub fn produce (&mut self, new_buffer: Vec ) { self.buffers.push (new_buffer); } pub fn produce_bytes (&mut self, new_buffer: &[u8]) { let mut b = vec! [0.0f32; new_buffer.len () / 4]; let mut rdr = Cursor::new (new_buffer); rdr.read_f32_into:: (&mut b).unwrap (); self.produce (b); } } #[derive (Default)] pub struct SharedState { pub pcm_buffers: PcmBuffers, pub quit: bool, } pub struct Decoder { pub input_ctx: DemuxContext, pub decoder: DecodeContext, pub resampler: ResamplingContext, best_stream_idx: usize, dummy_frame: Option , } impl Decoder { pub fn new (filename: &str) -> Result { let input_ctx = ffmpeg_next::format::input (&filename)?; let stream = input_ctx .streams () .best (ffmpeg_next::media::Type::Audio) .ok_or_else (|| anyhow! ("can't find good audio stream"))?; let best_stream_idx = stream.index (); let decoder = stream.codec ().decoder ().audio ()?; let resampler = decoder.resampler ( Sample::F32 (sample::Type::Packed), ChannelLayout::STEREO, 48000, )?; Ok (Self { input_ctx, decoder, resampler, best_stream_idx, dummy_frame: None, }) } fn new_frame () -> AudioFrame { let mut x = AudioFrame::empty (); x.set_channel_layout (ChannelLayout::STEREO); x.set_format (Sample::F32 (sample::Type::Packed)); x } pub fn next (&mut self) -> Result