1use rtsan_standalone::nonblocking;
2
3use crate::{AudioBlock, Sample};
4
5pub struct MonoView<'a, S: Sample> {
26 data: &'a [S],
27 num_frames: usize,
28 num_frames_allocated: usize,
29}
30
31impl<'a, S: Sample> MonoView<'a, S> {
32 #[nonblocking]
47 pub fn from_slice(data: &'a [S]) -> Self {
48 let num_frames = data.len();
49 Self {
50 data,
51 num_frames,
52 num_frames_allocated: num_frames,
53 }
54 }
55
56 #[nonblocking]
81 pub fn from_slice_limited(
82 data: &'a [S],
83 num_frames_visible: usize,
84 num_frames_allocated: usize,
85 ) -> Self {
86 assert_eq!(data.len(), num_frames_allocated);
87 assert!(num_frames_visible <= num_frames_allocated);
88 Self {
89 data,
90 num_frames: num_frames_visible,
91 num_frames_allocated,
92 }
93 }
94
95 #[nonblocking]
114 pub unsafe fn from_ptr(ptr: *const S, num_frames: usize) -> Self {
115 Self {
116 data: unsafe { std::slice::from_raw_parts(ptr, num_frames) },
117 num_frames,
118 num_frames_allocated: num_frames,
119 }
120 }
121
122 #[nonblocking]
131 pub unsafe fn from_ptr_limited(
132 ptr: *const S,
133 num_frames_visible: usize,
134 num_frames_allocated: usize,
135 ) -> Self {
136 assert!(num_frames_visible <= num_frames_allocated);
137 Self {
138 data: unsafe { std::slice::from_raw_parts(ptr, num_frames_allocated) },
139 num_frames: num_frames_visible,
140 num_frames_allocated,
141 }
142 }
143
144 #[nonblocking]
150 pub fn sample(&self, frame: usize) -> S {
151 assert!(frame < self.num_frames);
152 unsafe { *self.data.get_unchecked(frame) }
153 }
154
155 #[nonblocking]
159 pub fn samples(&self) -> &[S] {
160 &self.data[..self.num_frames]
161 }
162
163 #[nonblocking]
165 pub fn raw_data(&self) -> &[S] {
166 self.data
167 }
168
169 #[nonblocking]
170 pub fn view(&self) -> MonoView<'_, S> {
171 MonoView::from_slice_limited(self.data, self.num_frames, self.num_frames_allocated)
172 }
173}
174
175impl<S: Sample> AudioBlock<S> for MonoView<'_, S> {
176 type PlanarView = [S; 0];
177
178 #[nonblocking]
179 fn num_channels(&self) -> u16 {
180 1
181 }
182
183 #[nonblocking]
184 fn num_frames(&self) -> usize {
185 self.num_frames
186 }
187
188 #[nonblocking]
189 fn num_channels_allocated(&self) -> u16 {
190 1
191 }
192
193 #[nonblocking]
194 fn num_frames_allocated(&self) -> usize {
195 self.num_frames_allocated
196 }
197
198 #[nonblocking]
199 fn layout(&self) -> crate::BlockLayout {
200 crate::BlockLayout::Sequential
201 }
202
203 #[nonblocking]
204 fn sample(&self, channel: u16, frame: usize) -> S {
205 assert_eq!(channel, 0, "audio_blocks::MonoView only has channel 0");
206 self.sample(frame)
207 }
208
209 #[nonblocking]
210 fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S> {
211 assert_eq!(channel, 0, "audio_blocks::MonoView only has channel 0");
212 self.samples().iter()
213 }
214
215 #[nonblocking]
216 fn channels_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
217 core::iter::once(self.samples().iter())
218 }
219
220 #[nonblocking]
221 fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S> {
222 assert!(frame < self.num_frames);
223 core::iter::once(&self.data[frame])
224 }
225
226 #[nonblocking]
227 fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
228 self.data.iter().take(self.num_frames).map(core::iter::once)
229 }
230
231 #[nonblocking]
232 fn as_view(&self) -> impl AudioBlock<S> {
233 self.view()
234 }
235}
236
237impl<S: Sample + core::fmt::Debug> core::fmt::Debug for MonoView<'_, S> {
238 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
239 writeln!(f, "audio_blocks::MonoView {{")?;
240 writeln!(f, " num_frames: {}", self.num_frames)?;
241 writeln!(f, " num_frames_allocated: {}", self.num_frames_allocated)?;
242 writeln!(f, " samples: {:?}", self.samples())?;
243 writeln!(f, "}}")?;
244 Ok(())
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251 use rtsan_standalone::no_sanitize_realtime;
252
253 #[test]
254 fn test_from_slice() {
255 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
256 let block = MonoView::from_slice(&data);
257 assert_eq!(block.num_frames(), 5);
258 assert_eq!(block.num_frames_allocated(), 5);
259 assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
260 }
261
262 #[test]
263 fn test_from_slice_limited() {
264 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
265 let block = MonoView::from_slice_limited(&data, 3, 5);
266 assert_eq!(block.num_frames(), 3);
267 assert_eq!(block.num_frames_allocated(), 5);
268 assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
269 assert_eq!(block.raw_data(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
270 }
271
272 #[test]
273 fn test_from_ptr() {
274 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
275 let block = unsafe { MonoView::from_ptr(data.as_ptr(), 5) };
276 assert_eq!(block.num_frames(), 5);
277 assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
278 }
279
280 #[test]
281 fn test_from_ptr_limited() {
282 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
283 let block = unsafe { MonoView::from_ptr_limited(data.as_ptr(), 3, 5) };
284 assert_eq!(block.num_frames(), 3);
285 assert_eq!(block.num_frames_allocated(), 5);
286 assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
287 }
288
289 #[test]
290 fn test_sample_access() {
291 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
292 let block = MonoView::from_slice(&data);
293 assert_eq!(block.sample(0), 1.0);
294 assert_eq!(block.sample(2), 3.0);
295 assert_eq!(block.sample(4), 5.0);
296 }
297
298 #[test]
299 fn test_samples_iter() {
300 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
301 let block = MonoView::from_slice(&data);
302 assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
303 }
304
305 #[test]
306 fn test_audio_blocks_trait() {
307 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
308 let block = MonoView::from_slice(&data);
309
310 assert_eq!(block.num_channels(), 1);
311 assert_eq!(block.num_frames(), 5);
312
313 let channel: Vec<f32> = block.channel_iter(0).copied().collect();
315 assert_eq!(channel, vec![1.0, 2.0, 3.0, 4.0, 5.0]);
316
317 let frame: Vec<f32> = block.frame_iter(2).copied().collect();
319 assert_eq!(frame, vec![3.0]);
320 }
321
322 #[test]
323 fn test_view() {
324 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
325 let block = MonoView::from_slice(&data);
326 let view = block.view();
327 assert_eq!(view.num_frames(), 5);
328 assert_eq!(view.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
329 }
330
331 #[test]
332 #[should_panic]
333 #[no_sanitize_realtime]
334 fn test_sample_out_of_bounds() {
335 let data = [1.0, 2.0, 3.0];
336 let block = MonoView::from_slice(&data);
337 let _ = block.sample(10);
338 }
339
340 #[test]
341 #[should_panic]
342 #[no_sanitize_realtime]
343 fn test_wrong_channel() {
344 let data = [1.0, 2.0, 3.0];
345 let block = MonoView::from_slice(&data);
346 let _ = block.channel_iter(1);
347 }
348}