use anyhow::Result;
use bytes::Bytes;
use super::stream::{FileWindows, PcmWindows, WindowSpec};
const PULL_SAMPLES: usize = 32_000;
pub struct AudioChunks {
src: FileWindows,
pending: Vec<f32>,
chunk: Vec<f32>,
chunk_samples: usize,
eof: bool,
}
impl AudioChunks {
pub fn from_bytes(
data: Bytes,
chunk_samples: usize,
max_audio_secs: Option<f64>,
) -> Result<Self> {
let chunk_samples = chunk_samples.max(1);
Ok(Self {
src: FileWindows::from_bytes(
data,
WindowSpec::new(0, PULL_SAMPLES, 0),
max_audio_secs,
)?,
pending: Vec::with_capacity(chunk_samples + PULL_SAMPLES),
chunk: Vec::with_capacity(chunk_samples),
chunk_samples,
eof: false,
})
}
pub fn total_16k_samples(&self) -> usize {
self.src.total_16k_samples()
}
pub fn next_chunk(&mut self) -> Result<Option<&[f32]>> {
while !self.eof && self.pending.len() < self.chunk_samples {
match self.src.next_window().map_err(anyhow::Error::from)? {
Some(w) => self.pending.extend_from_slice(w.samples),
None => self.eof = true,
}
}
if self.pending.is_empty() {
return Ok(None);
}
let take = self.chunk_samples.min(self.pending.len());
self.chunk.clear();
self.chunk.extend_from_slice(&self.pending[..take]);
self.pending.drain(..take);
Ok(Some(&self.chunk))
}
}