1use bbx_core::StackVec;
4
5pub const MAX_FRAME_SAMPLES: usize = 1024;
8
9#[derive(Clone)]
13pub struct Frame {
14 pub samples: StackVec<f32, MAX_FRAME_SAMPLES>,
16 pub sample_rate: u32,
18 pub num_channels: usize,
20}
21
22impl Frame {
23 pub fn new(samples: &[f32], sample_rate: u32, num_channels: usize) -> Self {
29 assert!(
30 samples.len() <= MAX_FRAME_SAMPLES,
31 "Frame exceeds maximum size of {MAX_FRAME_SAMPLES} samples"
32 );
33
34 let mut stack_samples = StackVec::new();
35 for &sample in samples {
36 stack_samples.push_unchecked(sample);
37 }
38
39 Self {
40 samples: stack_samples,
41 sample_rate,
42 num_channels,
43 }
44 }
45
46 pub fn channel_samples(&self, channel: usize) -> Option<impl Iterator<Item = f32> + '_> {
50 if channel >= self.num_channels || self.num_channels == 0 {
51 return None;
52 }
53 Some(
54 self.samples
55 .as_slice()
56 .iter()
57 .skip(channel)
58 .step_by(self.num_channels)
59 .copied(),
60 )
61 }
62
63 pub fn samples_per_channel(&self) -> usize {
65 if self.num_channels == 0 {
66 0
67 } else {
68 self.samples.len() / self.num_channels
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn test_frame_new() {
79 let samples = [0.5f32, -0.5, 0.25, -0.25];
80 let frame = Frame::new(&samples, 44100, 2);
81
82 assert_eq!(frame.samples.len(), 4);
83 assert_eq!(frame.sample_rate, 44100);
84 assert_eq!(frame.num_channels, 2);
85 }
86
87 #[test]
88 fn test_channel_samples() {
89 let samples = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
90 let frame = Frame::new(&samples, 44100, 2);
91
92 let left: Vec<f32> = frame.channel_samples(0).unwrap().collect();
93 let right: Vec<f32> = frame.channel_samples(1).unwrap().collect();
94
95 assert_eq!(left, vec![1.0, 3.0, 5.0]);
96 assert_eq!(right, vec![2.0, 4.0, 6.0]);
97 }
98
99 #[test]
100 fn test_channel_samples_invalid() {
101 let samples = [1.0f32, 2.0];
102 let frame = Frame::new(&samples, 44100, 2);
103
104 assert!(frame.channel_samples(2).is_none());
105 assert!(frame.channel_samples(10).is_none());
106 }
107
108 #[test]
109 fn test_samples_per_channel() {
110 let samples = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
111 let frame = Frame::new(&samples, 44100, 2);
112
113 assert_eq!(frame.samples_per_channel(), 3);
114 }
115
116 #[test]
117 fn test_samples_per_channel_zero_channels() {
118 let frame = Frame {
119 samples: {
120 let mut s = StackVec::new();
121 s.push_unchecked(1.0);
122 s.push_unchecked(2.0);
123 s
124 },
125 sample_rate: 44100,
126 num_channels: 0,
127 };
128
129 assert_eq!(frame.samples_per_channel(), 0);
130 }
131}