1use rtsan_standalone::nonblocking;
2
3use core::{marker::PhantomData, ptr::NonNull};
4
5use crate::{AudioBlock, Sample, iter::StridedSampleIter};
6
7pub struct AudioBlockSequentialView<'a, S: Sample> {
27 data: &'a [S],
28 num_channels: u16,
29 num_frames: usize,
30 num_channels_allocated: u16,
31 num_frames_allocated: usize,
32}
33
34impl<'a, S: Sample> AudioBlockSequentialView<'a, S> {
35 #[nonblocking]
45 pub fn from_slice(data: &'a [S], num_channels: u16, num_frames: usize) -> Self {
46 assert_eq!(data.len(), num_channels as usize * num_frames);
47 Self {
48 data,
49 num_channels,
50 num_frames,
51 num_channels_allocated: num_channels,
52 num_frames_allocated: num_frames,
53 }
54 }
55
56 #[nonblocking]
73 pub fn from_slice_limited(
74 data: &'a [S],
75 num_channels_visible: u16,
76 num_frames_visible: usize,
77 num_channels_allocated: u16,
78 num_frames_allocated: usize,
79 ) -> Self {
80 assert_eq!(
81 data.len(),
82 num_channels_allocated as usize * num_frames_allocated
83 );
84 Self {
85 data,
86 num_channels: num_channels_visible,
87 num_frames: num_frames_visible,
88 num_channels_allocated,
89 num_frames_allocated,
90 }
91 }
92
93 #[nonblocking]
102 pub unsafe fn from_ptr(ptr: *const S, num_channels: u16, num_frames: usize) -> Self {
103 Self {
104 data: unsafe { std::slice::from_raw_parts(ptr, num_channels as usize * num_frames) },
105 num_channels,
106 num_frames,
107 num_channels_allocated: num_channels,
108 num_frames_allocated: num_frames,
109 }
110 }
111
112 #[nonblocking]
121 pub unsafe fn from_ptr_limited(
122 ptr: *const S,
123 num_channels_visible: u16,
124 num_frames_visible: usize,
125 num_channels_allocated: u16,
126 num_frames_allocated: usize,
127 ) -> Self {
128 assert!(num_channels_visible <= num_channels_allocated);
129 assert!(num_frames_visible <= num_frames_allocated);
130 Self {
131 data: unsafe {
132 std::slice::from_raw_parts(
133 ptr,
134 num_channels_allocated as usize * num_frames_allocated,
135 )
136 },
137 num_channels: num_channels_visible,
138 num_frames: num_frames_visible,
139 num_channels_allocated,
140 num_frames_allocated,
141 }
142 }
143
144 #[nonblocking]
150 pub fn channel(&self, channel: u16) -> &[S] {
151 assert!(channel < self.num_channels);
152 let start = channel as usize * self.num_frames_allocated;
153 let end = start + self.num_frames;
154 &self.data[start..end]
155 }
156
157 #[nonblocking]
161 pub fn channels(&self) -> impl Iterator<Item = &[S]> {
162 self.data
163 .chunks(self.num_frames_allocated)
164 .take(self.num_channels as usize)
165 .map(|frame| &frame[..self.num_frames])
166 }
167
168 #[nonblocking]
173 pub fn raw_data(&self) -> &[S] {
174 &self.data
175 }
176
177 #[nonblocking]
178 pub fn view(&self) -> AudioBlockSequentialView<'_, S> {
179 AudioBlockSequentialView::from_slice_limited(
180 self.data,
181 self.num_channels,
182 self.num_frames,
183 self.num_channels_allocated,
184 self.num_frames_allocated,
185 )
186 }
187}
188
189impl<S: Sample> AudioBlock<S> for AudioBlockSequentialView<'_, S> {
190 type PlanarView = [S; 0];
191
192 #[nonblocking]
193 fn num_channels(&self) -> u16 {
194 self.num_channels
195 }
196
197 #[nonblocking]
198 fn num_frames(&self) -> usize {
199 self.num_frames
200 }
201
202 #[nonblocking]
203 fn num_channels_allocated(&self) -> u16 {
204 self.num_channels_allocated
205 }
206
207 #[nonblocking]
208 fn num_frames_allocated(&self) -> usize {
209 self.num_frames_allocated
210 }
211
212 #[nonblocking]
213 fn layout(&self) -> crate::BlockLayout {
214 crate::BlockLayout::Sequential
215 }
216
217 #[nonblocking]
218 fn sample(&self, channel: u16, frame: usize) -> S {
219 assert!(channel < self.num_channels);
220 assert!(frame < self.num_frames);
221 unsafe {
222 *self
223 .data
224 .get_unchecked(channel as usize * self.num_frames_allocated + frame)
225 }
226 }
227
228 #[nonblocking]
229 fn channel_iter(&self, channel: u16) -> impl Iterator<Item = &S> {
230 assert!(channel < self.num_channels);
231 self.data
232 .iter()
233 .skip(channel as usize * self.num_frames_allocated)
234 .take(self.num_frames)
235 }
236
237 #[nonblocking]
238 fn channels_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
239 let num_frames = self.num_frames; let num_frames_allocated = self.num_frames_allocated; self.data
243 .chunks(num_frames_allocated)
244 .take(self.num_channels as usize)
245 .map(move |channel_chunk| channel_chunk.iter().take(num_frames))
246 }
247
248 #[nonblocking]
249 fn frame_iter(&self, frame: usize) -> impl Iterator<Item = &S> {
250 assert!(frame < self.num_frames);
251 self.data
252 .iter()
253 .skip(frame)
254 .step_by(self.num_frames_allocated)
255 .take(self.num_channels as usize)
256 }
257
258 #[nonblocking]
259 fn frame_iters(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
260 let num_channels = self.num_channels as usize;
261 let num_frames = self.num_frames;
262 let stride = self.num_frames_allocated;
263 let data_ptr = self.data.as_ptr();
264
265 (0..num_frames).map(move |frame_idx| {
266 let start_ptr = if self.data.is_empty() {
271 NonNull::dangling().as_ptr() } else {
273 unsafe { data_ptr.add(frame_idx) }
276 };
277
278 StridedSampleIter::<'_, S> {
279 ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), stride,
284 remaining: num_channels, _marker: PhantomData,
286 }
287 })
288 }
289
290 #[nonblocking]
291 fn as_view(&self) -> impl AudioBlock<S> {
292 self.view()
293 }
294
295 #[nonblocking]
296 fn as_sequential_view(&self) -> Option<AudioBlockSequentialView<'_, S>> {
297 Some(self.view())
298 }
299}
300
301impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockSequentialView<'_, S> {
302 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
303 writeln!(f, "AudioBlockSequentialView {{")?;
304 writeln!(f, " num_channels: {}", self.num_channels)?;
305 writeln!(f, " num_frames: {}", self.num_frames)?;
306 writeln!(
307 f,
308 " num_channels_allocated: {}",
309 self.num_channels_allocated
310 )?;
311 writeln!(f, " num_frames_allocated: {}", self.num_frames_allocated)?;
312 writeln!(f, " channels:")?;
313
314 for (i, channel) in self.channels().enumerate() {
315 writeln!(f, " {}: {:?}", i, channel)?;
316 }
317
318 writeln!(f, " raw_data: {:?}", self.raw_data())?;
319 writeln!(f, "}}")?;
320
321 Ok(())
322 }
323}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328 use rtsan_standalone::no_sanitize_realtime;
329
330 #[test]
331 fn test_member_functions() {
332 let block = AudioBlockSequentialView::from_slice_limited(
333 &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0],
334 2,
335 3,
336 3,
337 4,
338 );
339
340 assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
342 assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
343
344 let mut channels = block.channels();
346 assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
347 assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
348 assert_eq!(channels.next(), None);
349 drop(channels);
350
351 assert_eq!(
353 block.raw_data(),
354 &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
355 );
356
357 let view = block.view();
359 assert_eq!(view.num_channels(), block.num_channels());
360 assert_eq!(view.num_frames(), block.num_frames());
361 assert_eq!(
362 view.num_channels_allocated(),
363 block.num_channels_allocated()
364 );
365 assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
366 assert_eq!(view.raw_data(), block.raw_data());
367 }
368
369 #[test]
370 fn test_samples() {
371 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
372 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
373
374 for ch in 0..block.num_channels() {
375 for f in 0..block.num_frames() {
376 assert_eq!(
377 block.sample(ch, f),
378 (ch as usize * block.num_frames() + f) as f32
379 );
380 }
381 }
382 }
383
384 #[test]
385 fn test_channel_iter() {
386 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
387 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
388
389 let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
390 assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
391 let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
392 assert_eq!(channel, vec![5.0, 6.0, 7.0, 8.0, 9.0]);
393 }
394
395 #[test]
396 fn test_channel_iters() {
397 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
398 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
399
400 let mut channels_iter = block.channels_iter();
401 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
402 assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
403
404 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
405 assert_eq!(channel, vec![5.0, 6.0, 7.0, 8.0, 9.0]);
406 assert!(channels_iter.next().is_none());
407 }
408
409 #[test]
410 fn test_frame_iter() {
411 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
412 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
413
414 let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
415 assert_eq!(channel, vec![0.0, 5.0]);
416 let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
417 assert_eq!(channel, vec![1.0, 6.0]);
418 let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
419 assert_eq!(channel, vec![2.0, 7.0]);
420 let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
421 assert_eq!(channel, vec![3.0, 8.0]);
422 let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
423 assert_eq!(channel, vec![4.0, 9.0]);
424 }
425
426 #[test]
427 fn test_frame_iters() {
428 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
429 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
430
431 let mut frames_iter = block.frame_iters();
432 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
433 assert_eq!(channel, vec![0.0, 5.0]);
434 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
435 assert_eq!(channel, vec![1.0, 6.0]);
436 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
437 assert_eq!(channel, vec![2.0, 7.0]);
438 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
439 assert_eq!(channel, vec![3.0, 8.0]);
440 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
441 assert_eq!(channel, vec![4.0, 9.0]);
442 assert!(frames_iter.next().is_none());
443 }
444
445 #[test]
446 fn test_from_slice() {
447 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
448 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
449 assert_eq!(block.num_channels(), 2);
450 assert_eq!(block.num_channels_allocated, 2);
451 assert_eq!(block.num_frames(), 5);
452 assert_eq!(block.num_frames_allocated, 5);
453 assert_eq!(
454 block.channel_iter(0).copied().collect::<Vec<_>>(),
455 vec![0.0, 1.0, 2.0, 3.0, 4.0]
456 );
457 assert_eq!(
458 block.channel_iter(1).copied().collect::<Vec<_>>(),
459 vec![5.0, 6.0, 7.0, 8.0, 9.0]
460 );
461 assert_eq!(
462 block.frame_iter(0).copied().collect::<Vec<_>>(),
463 vec![0.0, 5.0]
464 );
465 assert_eq!(
466 block.frame_iter(1).copied().collect::<Vec<_>>(),
467 vec![1.0, 6.0]
468 );
469 assert_eq!(
470 block.frame_iter(2).copied().collect::<Vec<_>>(),
471 vec![2.0, 7.0]
472 );
473 assert_eq!(
474 block.frame_iter(3).copied().collect::<Vec<_>>(),
475 vec![3.0, 8.0]
476 );
477 assert_eq!(
478 block.frame_iter(4).copied().collect::<Vec<_>>(),
479 vec![4.0, 9.0]
480 );
481 }
482
483 #[test]
484 fn test_view() {
485 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
486 let block = AudioBlockSequentialView::<f32>::from_slice(&data, 2, 5);
487 assert!(block.as_interleaved_view().is_none());
488 assert!(block.as_planar_view().is_none());
489 assert!(block.as_sequential_view().is_some());
490 let view = block.as_view();
491 assert_eq!(
492 view.channel_iter(0).copied().collect::<Vec<_>>(),
493 vec![0.0, 1.0, 2.0, 3.0, 4.0]
494 );
495 assert_eq!(
496 view.channel_iter(1).copied().collect::<Vec<_>>(),
497 vec![5.0, 6.0, 7.0, 8.0, 9.0]
498 );
499 }
500
501 #[test]
502 fn test_limited() {
503 let data = [1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0];
504
505 let block = AudioBlockSequentialView::from_slice_limited(&data, 2, 3, 3, 4);
506
507 assert_eq!(block.num_channels(), 2);
508 assert_eq!(block.num_frames(), 3);
509 assert_eq!(block.num_channels_allocated, 3);
510 assert_eq!(block.num_frames_allocated, 4);
511
512 for i in 0..block.num_channels() {
513 assert_eq!(block.channel_iter(i).count(), 3);
514 }
515 for i in 0..block.num_frames() {
516 assert_eq!(block.frame_iter(i).count(), 2);
517 }
518 }
519
520 #[test]
521 fn test_from_raw() {
522 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
523 let block = unsafe { AudioBlockSequentialView::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
524 assert_eq!(block.num_channels(), 2);
525 assert_eq!(block.num_channels_allocated, 2);
526 assert_eq!(block.num_frames(), 5);
527 assert_eq!(block.num_frames_allocated, 5);
528 assert_eq!(
529 block.channel_iter(0).copied().collect::<Vec<_>>(),
530 vec![0.0, 1.0, 2.0, 3.0, 4.0]
531 );
532 assert_eq!(
533 block.channel_iter(1).copied().collect::<Vec<_>>(),
534 vec![5.0, 6.0, 7.0, 8.0, 9.0]
535 );
536 assert_eq!(
537 block.frame_iter(0).copied().collect::<Vec<_>>(),
538 vec![0.0, 5.0]
539 );
540 assert_eq!(
541 block.frame_iter(1).copied().collect::<Vec<_>>(),
542 vec![1.0, 6.0]
543 );
544 assert_eq!(
545 block.frame_iter(2).copied().collect::<Vec<_>>(),
546 vec![2.0, 7.0]
547 );
548 assert_eq!(
549 block.frame_iter(3).copied().collect::<Vec<_>>(),
550 vec![3.0, 8.0]
551 );
552 assert_eq!(
553 block.frame_iter(4).copied().collect::<Vec<_>>(),
554 vec![4.0, 9.0]
555 );
556 }
557
558 #[test]
559 fn test_from_raw_limited() {
560 let data = [1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0];
561
562 let block =
563 unsafe { AudioBlockSequentialView::from_ptr_limited(data.as_ptr(), 2, 3, 3, 4) };
564
565 assert_eq!(block.num_channels(), 2);
566 assert_eq!(block.num_frames(), 3);
567 assert_eq!(block.num_channels_allocated, 3);
568 assert_eq!(block.num_frames_allocated, 4);
569
570 for i in 0..block.num_channels() {
571 assert_eq!(block.channel_iter(i).count(), 3);
572 }
573 for i in 0..block.num_frames() {
574 assert_eq!(block.frame_iter(i).count(), 2);
575 }
576 }
577
578 #[test]
579 #[should_panic]
580 #[no_sanitize_realtime]
581 fn test_slice_out_of_bounds() {
582 let data = [1.0, 1.0, 1.0, 0.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0];
583 let block = AudioBlockSequentialView::from_slice_limited(&data, 2, 3, 3, 4);
584
585 block.channel(2);
586 }
587}