1use std::time::Duration;
14
15use crate::source::SeekError;
16use crate::{Sample, Source};
17
18#[derive(Debug, Clone)]
20pub struct SamplesBuffer<S> {
21 data: Vec<S>,
22 pos: usize,
23 channels: u16,
24 sample_rate: u32,
25 duration: Duration,
26}
27
28impl<S> SamplesBuffer<S>
29where
30 S: Sample,
31{
32 pub fn new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S>
42 where
43 D: Into<Vec<S>>,
44 {
45 assert!(channels != 0);
46 assert!(sample_rate != 0);
47
48 let data = data.into();
49 let duration_ns = 1_000_000_000u64.checked_mul(data.len() as u64).unwrap()
50 / sample_rate as u64
51 / channels as u64;
52 let duration = Duration::new(
53 duration_ns / 1_000_000_000,
54 (duration_ns % 1_000_000_000) as u32,
55 );
56
57 SamplesBuffer {
58 data,
59 pos: 0,
60 channels,
61 sample_rate,
62 duration,
63 }
64 }
65}
66
67impl<S> Source for SamplesBuffer<S>
68where
69 S: Sample,
70{
71 #[inline]
72 fn current_frame_len(&self) -> Option<usize> {
73 None
74 }
75
76 #[inline]
77 fn channels(&self) -> u16 {
78 self.channels
79 }
80
81 #[inline]
82 fn sample_rate(&self) -> u32 {
83 self.sample_rate
84 }
85
86 #[inline]
87 fn total_duration(&self) -> Option<Duration> {
88 Some(self.duration)
89 }
90
91 #[inline]
97 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
98 let curr_channel = self.pos % self.channels() as usize;
99 let new_pos = pos.as_secs_f32() * self.sample_rate() as f32 * self.channels() as f32;
100 let new_pos = new_pos as usize;
102 let new_pos = new_pos.min(self.data.len());
103
104 let new_pos = new_pos.next_multiple_of(self.channels() as usize);
106 let new_pos = new_pos - curr_channel;
107
108 self.pos = new_pos;
109 Ok(())
110 }
111}
112
113impl<S> Iterator for SamplesBuffer<S>
114where
115 S: Sample,
116{
117 type Item = S;
118
119 #[inline]
120 fn next(&mut self) -> Option<S> {
121 let sample = self.data.get(self.pos)?;
122 self.pos += 1;
123 Some(*sample)
124 }
125
126 #[inline]
127 fn size_hint(&self) -> (usize, Option<usize>) {
128 (self.data.len(), Some(self.data.len()))
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use crate::buffer::SamplesBuffer;
135 use crate::source::Source;
136
137 #[test]
138 fn basic() {
139 let _ = SamplesBuffer::new(1, 44100, vec![0i16, 0, 0, 0, 0, 0]);
140 }
141
142 #[test]
143 #[should_panic]
144 fn panic_if_zero_channels() {
145 SamplesBuffer::new(0, 44100, vec![0i16, 0, 0, 0, 0, 0]);
146 }
147
148 #[test]
149 #[should_panic]
150 fn panic_if_zero_sample_rate() {
151 SamplesBuffer::new(1, 0, vec![0i16, 0, 0, 0, 0, 0]);
152 }
153
154 #[test]
155 fn duration_basic() {
156 let buf = SamplesBuffer::new(2, 2, vec![0i16, 0, 0, 0, 0, 0]);
157 let dur = buf.total_duration().unwrap();
158 assert_eq!(dur.as_secs(), 1);
159 assert_eq!(dur.subsec_nanos(), 500_000_000);
160 }
161
162 #[test]
163 fn iteration() {
164 let mut buf = SamplesBuffer::new(1, 44100, vec![1i16, 2, 3, 4, 5, 6]);
165 assert_eq!(buf.next(), Some(1));
166 assert_eq!(buf.next(), Some(2));
167 assert_eq!(buf.next(), Some(3));
168 assert_eq!(buf.next(), Some(4));
169 assert_eq!(buf.next(), Some(5));
170 assert_eq!(buf.next(), Some(6));
171 assert_eq!(buf.next(), None);
172 }
173
174 #[cfg(test)]
175 mod try_seek {
176 use super::*;
177 use std::time::Duration;
178
179 #[test]
180 fn channel_order_stays_correct() {
181 const SAMPLE_RATE: u32 = 100;
182 const CHANNELS: u16 = 2;
183 let mut buf = SamplesBuffer::new(
184 CHANNELS,
185 SAMPLE_RATE,
186 (0..2000i16).into_iter().collect::<Vec<_>>(),
187 );
188 buf.try_seek(Duration::from_secs(5)).unwrap();
189 assert_eq!(
190 buf.next(),
191 Some(5i16 * SAMPLE_RATE as i16 * CHANNELS as i16)
192 );
193
194 assert!(buf.next().is_some_and(|s| s % 2 == 1));
195 assert!(buf.next().is_some_and(|s| s % 2 == 0));
196
197 buf.try_seek(Duration::from_secs(6)).unwrap();
198 assert!(buf.next().is_some_and(|s| s % 2 == 1),);
199 }
200 }
201}