use crate::error::{Error, Result};
use crate::time::{AudioDuration, AudioTimestamp};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChunkBoundary {
SpeechStart,
SpeechEnd,
Continuation,
Silence,
}
#[derive(Debug, Clone)]
pub struct ProcessedChunk {
pub samples: Vec<f32>,
pub start_boundary: ChunkBoundary,
pub end_boundary: ChunkBoundary,
pub start_time: AudioTimestamp,
pub end_time: AudioTimestamp,
pub speech_ratio: f32,
pub energy: f32,
pub snr_db: Option<f32>,
pub has_clipping: bool,
pub overlap_prev: Option<Vec<f32>>,
pub overlap_next: Option<Vec<f32>>,
pub overlap_ms: u32,
}
impl ProcessedChunk {
pub fn duration(&self) -> Result<AudioDuration> {
self.end_time
.duration_since(self.start_time)
.ok_or_else(|| {
Error::Processing("invalid chunk times: end_time precedes start_time".into())
})
}
#[must_use]
pub fn is_speech(&self) -> bool {
self.speech_ratio > 0.5
}
#[must_use]
pub fn is_silence(&self) -> bool {
self.start_boundary == ChunkBoundary::Silence && self.end_boundary == ChunkBoundary::Silence
}
pub fn samples_without_overlap(&self) -> &[f32] {
&self.samples
}
#[must_use]
pub fn total_samples_with_overlap(&self) -> usize {
let prev_overlap = self.overlap_prev.as_ref().map_or(0, Vec::len);
let next_overlap = self.overlap_next.as_ref().map_or(0, Vec::len);
self.samples.len() + prev_overlap + next_overlap
}
}