//! Trim operation: extract a frame range from sample data. use crate::error::CoreError; /// Trim samples to the given frame range (inclusive start, exclusive end). /// /// Operates on interleaved sample data. `start_frame` and `end_frame` are in /// frame units (not sample units), so channel count is accounted for. pub fn apply_trim( samples: &mut Vec, channels: u16, start_frame: usize, end_frame: usize, ) -> Result<(), CoreError> { let ch = channels as usize; if ch == 0 { return Err(CoreError::Internal("trim: channels must be > 0".to_string())); } let total_frames = samples.len() / ch; if start_frame >= end_frame { return Err(CoreError::Internal( "trim: start_frame must be less than end_frame".to_string(), )); } if end_frame > total_frames { return Err(CoreError::Internal(format!( "trim: end_frame ({end_frame}) exceeds total frames ({total_frames})" ))); } let start_sample = start_frame * ch; let end_sample = end_frame * ch; samples.drain(end_sample..); samples.drain(..start_sample); Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn trim_mono() { let mut samples = vec![0.1, 0.2, 0.3, 0.4, 0.5]; apply_trim(&mut samples, 1, 1, 4).unwrap(); assert_eq!(samples, vec![0.2, 0.3, 0.4]); } #[test] fn trim_stereo() { // 4 frames of stereo: [L0,R0, L1,R1, L2,R2, L3,R3] let mut samples = vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]; apply_trim(&mut samples, 2, 1, 3).unwrap(); // Should keep frames 1 and 2: [L1,R1, L2,R2] assert_eq!(samples, vec![0.3, 0.4, 0.5, 0.6]); } #[test] fn trim_full_range_is_noop() { let mut samples = vec![0.1, 0.2, 0.3]; apply_trim(&mut samples, 1, 0, 3).unwrap(); assert_eq!(samples, vec![0.1, 0.2, 0.3]); } #[test] fn trim_invalid_range() { let mut samples = vec![0.1, 0.2, 0.3]; assert!(apply_trim(&mut samples, 1, 2, 1).is_err()); } #[test] fn trim_out_of_bounds() { let mut samples = vec![0.1, 0.2, 0.3]; assert!(apply_trim(&mut samples, 1, 0, 10).is_err()); } #[test] fn trim_single_frame() { let mut samples = vec![0.1, 0.2, 0.3, 0.4, 0.5]; apply_trim(&mut samples, 1, 2, 3).unwrap(); assert_eq!(samples, vec![0.3]); } }