Skip to main content

max / audiofiles

1.8 KB · 66 lines History Blame Raw
1 //! Reverse operation: reverse frame order while preserving channel layout.
2
3 /// Reverse sample data in-place, preserving channel order within each frame.
4 ///
5 /// For stereo audio, this reverses the order of L/R frame pairs without
6 /// swapping L and R within a frame.
7 pub fn apply_reverse(samples: &mut [f32], channels: u16) {
8 let ch = channels as usize;
9 if ch == 0 || samples.is_empty() {
10 return;
11 }
12
13 let num_frames = samples.len() / ch;
14 // Swap frames from outside in
15 for i in 0..num_frames / 2 {
16 let j = num_frames - 1 - i;
17 for c in 0..ch {
18 samples.swap(i * ch + c, j * ch + c);
19 }
20 }
21 }
22
23 #[cfg(test)]
24 mod tests {
25 use super::*;
26
27 #[test]
28 fn reverse_mono() {
29 let mut samples = vec![1.0, 2.0, 3.0, 4.0, 5.0];
30 apply_reverse(&mut samples, 1);
31 assert_eq!(samples, vec![5.0, 4.0, 3.0, 2.0, 1.0]);
32 }
33
34 #[test]
35 fn reverse_stereo() {
36 // 3 frames: [L0,R0, L1,R1, L2,R2]
37 let mut samples = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
38 apply_reverse(&mut samples, 2);
39 // Reversed frames: [L2,R2, L1,R1, L0,R0]
40 assert_eq!(samples, vec![5.0, 6.0, 3.0, 4.0, 1.0, 2.0]);
41 }
42
43 #[test]
44 fn reverse_single_frame() {
45 let mut samples = vec![1.0, 2.0];
46 apply_reverse(&mut samples, 2);
47 assert_eq!(samples, vec![1.0, 2.0]);
48 }
49
50 #[test]
51 fn reverse_empty() {
52 let mut samples: Vec<f32> = vec![];
53 apply_reverse(&mut samples, 1);
54 assert!(samples.is_empty());
55 }
56
57 #[test]
58 fn reverse_double_is_identity() {
59 let original = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
60 let mut samples = original.clone();
61 apply_reverse(&mut samples, 2);
62 apply_reverse(&mut samples, 2);
63 assert_eq!(samples, original);
64 }
65 }
66