//! Reverse operation: reverse frame order while preserving channel layout. /// Reverse sample data in-place, preserving channel order within each frame. /// /// For stereo audio, this reverses the order of L/R frame pairs without /// swapping L and R within a frame. pub fn apply_reverse(samples: &mut [f32], channels: u16) { let ch = channels as usize; if ch == 0 || samples.is_empty() { return; } let num_frames = samples.len() / ch; // Swap frames from outside in for i in 0..num_frames / 2 { let j = num_frames - 1 - i; for c in 0..ch { samples.swap(i * ch + c, j * ch + c); } } } #[cfg(test)] mod tests { use super::*; #[test] fn reverse_mono() { let mut samples = vec![1.0, 2.0, 3.0, 4.0, 5.0]; apply_reverse(&mut samples, 1); assert_eq!(samples, vec![5.0, 4.0, 3.0, 2.0, 1.0]); } #[test] fn reverse_stereo() { // 3 frames: [L0,R0, L1,R1, L2,R2] let mut samples = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; apply_reverse(&mut samples, 2); // Reversed frames: [L2,R2, L1,R1, L0,R0] assert_eq!(samples, vec![5.0, 6.0, 3.0, 4.0, 1.0, 2.0]); } #[test] fn reverse_single_frame() { let mut samples = vec![1.0, 2.0]; apply_reverse(&mut samples, 2); assert_eq!(samples, vec![1.0, 2.0]); } #[test] fn reverse_empty() { let mut samples: Vec = vec![]; apply_reverse(&mut samples, 1); assert!(samples.is_empty()); } #[test] fn reverse_double_is_identity() { let original = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; let mut samples = original.clone(); apply_reverse(&mut samples, 2); apply_reverse(&mut samples, 2); assert_eq!(samples, original); } }