1use core::{fmt::Debug, mem::MaybeUninit};
2use rtsan_standalone::nonblocking;
3use std::marker::PhantomData;
4
5use crate::{AudioBlock, Sample};
6
7pub struct AudioBlockPlanarView<'a, S: Sample, V: AsRef<[S]>> {
27 data: &'a [V],
28 num_channels: u16,
29 num_frames: usize,
30 num_channels_allocated: u16,
31 num_frames_allocated: usize,
32 _phantom: PhantomData<S>,
33}
34
35impl<'a, S: Sample, V: AsRef<[S]>> AudioBlockPlanarView<'a, S, V> {
36 #[nonblocking]
44 pub fn from_slice(data: &'a [V]) -> Self {
45 let num_frames_available = if data.is_empty() {
46 0
47 } else {
48 data[0].as_ref().len()
49 };
50 Self::from_slice_limited(data, data.len() as u16, num_frames_available)
51 }
52
53 #[nonblocking]
68 pub fn from_slice_limited(
69 data: &'a [V],
70 num_channels_visible: u16,
71 num_frames_visible: usize,
72 ) -> Self {
73 let num_channels_allocated = data.len() as u16;
74 let num_frames_allocated = if num_channels_allocated == 0 {
75 0
76 } else {
77 data[0].as_ref().len()
78 };
79 assert!(num_channels_visible <= num_channels_allocated);
80 assert!(num_frames_visible <= num_frames_allocated);
81 data.iter()
82 .for_each(|v| assert_eq!(v.as_ref().len(), 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 _phantom: PhantomData,
91 }
92 }
93
94 #[nonblocking]
100 pub fn channel(&self, channel: u16) -> &[S] {
101 assert!(channel < self.num_channels);
102 &self.data[channel as usize].as_ref()[..self.num_frames]
103 }
104
105 #[nonblocking]
109 pub fn channels(&self) -> impl Iterator<Item = &[S]> {
110 self.data
111 .iter()
112 .take(self.num_channels as usize)
113 .map(|channel_data| &channel_data.as_ref()[..self.num_frames])
114 }
115
116 #[nonblocking]
121 pub fn raw_data(&self) -> &[V] {
122 self.data
123 }
124
125 #[nonblocking]
126 pub fn view(&self) -> AudioBlockPlanarView<'_, S, V> {
127 AudioBlockPlanarView::from_slice_limited(self.data, self.num_channels, self.num_frames)
128 }
129}
130
131impl<S: Sample, V: AsRef<[S]>> AudioBlock<S> for AudioBlockPlanarView<'_, S, V> {
132 type PlanarView = V;
133
134 #[nonblocking]
135 fn num_channels(&self) -> u16 {
136 self.num_channels
137 }
138
139 #[nonblocking]
140 fn num_frames(&self) -> usize {
141 self.num_frames
142 }
143
144 #[nonblocking]
145 fn num_channels_allocated(&self) -> u16 {
146 self.num_channels_allocated
147 }
148
149 #[nonblocking]
150 fn num_frames_allocated(&self) -> usize {
151 self.num_frames_allocated
152 }
153
154 #[nonblocking]
155 fn layout(&self) -> crate::BlockLayout {
156 crate::BlockLayout::Planar
157 }
158
159 #[nonblocking]
160 fn sample(&self, channel: u16, frame: usize) -> S {
161 assert!(channel < self.num_channels);
162 assert!(frame < self.num_frames);
163 unsafe {
164 *self
165 .data
166 .get_unchecked(channel as usize)
167 .as_ref()
168 .get_unchecked(frame)
169 }
170 }
171
172 #[nonblocking]
173 fn channel_iter(&self, channel: u16) -> impl Iterator<Item = &S> {
174 assert!(channel < self.num_channels);
175 unsafe {
176 self.data
177 .get_unchecked(channel as usize)
178 .as_ref()
179 .iter()
180 .take(self.num_frames)
181 }
182 }
183
184 #[nonblocking]
185 fn channels_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
186 let num_frames = self.num_frames; self.data
188 .iter()
189 .take(self.num_channels as usize)
191 .map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
193 }
194
195 #[nonblocking]
196 fn frame_iter(&self, frame: usize) -> impl Iterator<Item = &S> {
197 assert!(frame < self.num_frames);
198 self.data
199 .iter()
200 .take(self.num_channels as usize)
201 .map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
202 }
203
204 #[nonblocking]
205 fn frame_iters(&self) -> impl Iterator<Item = impl Iterator<Item = &'_ S> + '_> + '_ {
206 let num_channels = self.num_channels as usize;
207 let num_frames = self.num_frames;
208 let data_slice: &[V] = self.data;
209
210 (0..num_frames).map(move |frame_idx| {
211 data_slice[..num_channels]
213 .iter() .map(move |channel_view: &V| {
215 let channel_slice: &[S] = channel_view.as_ref();
217 &channel_slice[frame_idx]
220 })
223 })
224 }
225
226 #[nonblocking]
227 fn as_view(&self) -> impl AudioBlock<S> {
228 self.view()
229 }
230
231 #[nonblocking]
232 fn as_planar_view(&self) -> Option<AudioBlockPlanarView<'_, S, Self::PlanarView>> {
233 Some(self.view())
234 }
235}
236
237impl<S: Sample + core::fmt::Debug, V: AsRef<[S]> + Debug> core::fmt::Debug
238 for AudioBlockPlanarView<'_, S, V>
239{
240 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
241 writeln!(f, "AudioBlockPlanarView {{")?;
242 writeln!(f, " num_channels: {}", self.num_channels)?;
243 writeln!(f, " num_frames: {}", self.num_frames)?;
244 writeln!(
245 f,
246 " num_channels_allocated: {}",
247 self.num_channels_allocated
248 )?;
249 writeln!(f, " num_frames_allocated: {}", self.num_frames_allocated)?;
250 writeln!(f, " channels:")?;
251
252 for (i, channel) in self.channels().enumerate() {
253 writeln!(f, " {}: {:?}", i, channel)?;
254 }
255
256 writeln!(f, " raw_data: {:?}", self.raw_data())?;
257 writeln!(f, "}}")?;
258
259 Ok(())
260 }
261}
262
263pub struct PlanarPtrAdapter<'a, S: Sample, const MAX_CHANNELS: usize> {
301 data: [MaybeUninit<&'a [S]>; MAX_CHANNELS],
302 num_channels: u16,
303}
304
305impl<'a, S: Sample, const MAX_CHANNELS: usize> PlanarPtrAdapter<'a, S, MAX_CHANNELS> {
306 #[nonblocking]
316 pub unsafe fn from_ptr(ptr: *const *const S, num_channels: u16, num_frames: usize) -> Self {
317 assert!(
318 num_channels as usize <= MAX_CHANNELS,
319 "num_channels exceeds MAX_CHANNELS"
320 );
321
322 let mut data: [core::mem::MaybeUninit<&'a [S]>; MAX_CHANNELS] =
323 unsafe { core::mem::MaybeUninit::uninit().assume_init() }; let ptr_slice: &[*const S] =
327 unsafe { core::slice::from_raw_parts(ptr, num_channels as usize) };
328
329 for ch in 0..num_channels as usize {
330 data[ch].write(unsafe { core::slice::from_raw_parts(ptr_slice[ch], num_frames) });
332 }
333
334 Self { data, num_channels }
335 }
336
337 #[inline]
342 pub fn data_slice(&self) -> &[&'a [S]] {
343 let initialized_part: &[MaybeUninit<&'a [S]>] = &self.data[..self.num_channels as usize];
344 unsafe {
345 core::slice::from_raw_parts(
346 initialized_part.as_ptr() as *const &'a [S],
347 self.num_channels as usize,
348 )
349 }
350 }
351
352 #[nonblocking]
362 pub fn planar_view(&self) -> AudioBlockPlanarView<'a, S, &[S]> {
363 AudioBlockPlanarView::from_slice(self.data_slice())
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use super::*;
370 use rtsan_standalone::no_sanitize_realtime;
371
372 #[test]
373 fn test_member_functions() {
374 let data = [
375 [0.0, 1.0, 2.0, 3.0],
376 [4.0, 5.0, 6.0, 7.0],
377 [0.0, 0.0, 0.0, 0.0],
378 ];
379 let block = AudioBlockPlanarView::from_slice_limited(&data, 2, 3);
380
381 assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
383 assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
384
385 let mut channels = block.channels();
387 assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
388 assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
389 assert_eq!(channels.next(), None);
390 drop(channels);
391
392 assert_eq!(block.raw_data()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
394 assert_eq!(block.raw_data()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
395 assert_eq!(block.raw_data()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
396
397 let view = block.view();
399 assert_eq!(view.num_channels(), block.num_channels());
400 assert_eq!(view.num_frames(), block.num_frames());
401 assert_eq!(
402 view.num_channels_allocated(),
403 block.num_channels_allocated()
404 );
405 assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
406 assert_eq!(view.raw_data(), block.raw_data());
407 }
408
409 #[test]
410 fn test_samples() {
411 let ch1 = &[0.0, 1.0, 2.0, 3.0, 4.0];
412 let ch2 = &[5.0, 6.0, 7.0, 8.0, 9.0];
413 let data = [ch1, ch2];
414 let block = AudioBlockPlanarView::from_slice(&data);
415
416 for ch in 0..block.num_channels() {
417 for f in 0..block.num_frames() {
418 assert_eq!(
419 block.sample(ch, f),
420 (ch as usize * block.num_frames() + f) as f32
421 );
422 }
423 }
424 }
425
426 #[test]
427 fn test_channel_iter() {
428 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
429 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
430 let data = vec![ch1, ch2];
431 let block = AudioBlockPlanarView::from_slice(&data);
432
433 let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
434 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
435 let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
436 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
437 }
438
439 #[test]
440 fn test_channel_iters() {
441 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
442 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
443 let data = vec![ch1, ch2];
444 let block = AudioBlockPlanarView::from_slice(&data);
445
446 let mut channels_iter = block.channels_iter();
447 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
448 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
449
450 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
451 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
452 assert!(channels_iter.next().is_none());
453 }
454
455 #[test]
456 fn test_frame_iter() {
457 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
458 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
459 let data = vec![ch1.as_slice(), ch2.as_slice()];
460 let block = AudioBlockPlanarView::from_slice(&data);
461
462 let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
463 assert_eq!(channel, vec![0.0, 1.0]);
464 let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
465 assert_eq!(channel, vec![2.0, 3.0]);
466 let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
467 assert_eq!(channel, vec![4.0, 5.0]);
468 let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
469 assert_eq!(channel, vec![6.0, 7.0]);
470 let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
471 assert_eq!(channel, vec![8.0, 9.0]);
472 }
473
474 #[test]
475 fn test_frame_iters() {
476 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
477 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
478 let data = vec![ch1.as_slice(), ch2.as_slice()];
479 let block = AudioBlockPlanarView::from_slice(&data);
480
481 let mut frames_iter = block.frame_iters();
482 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
483 assert_eq!(channel, vec![0.0, 1.0]);
484 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
485 assert_eq!(channel, vec![2.0, 3.0]);
486 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
487 assert_eq!(channel, vec![4.0, 5.0]);
488 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
489 assert_eq!(channel, vec![6.0, 7.0]);
490 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
491 assert_eq!(channel, vec![8.0, 9.0]);
492 assert!(frames_iter.next().is_none());
493 }
494
495 #[test]
496 fn test_from_vec() {
497 let vec = vec![vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
498 let block = AudioBlockPlanarView::from_slice(&vec);
499 assert_eq!(block.num_channels(), 2);
500 assert_eq!(block.num_frames(), 5);
501 assert_eq!(
502 block.channel_iter(0).copied().collect::<Vec<_>>(),
503 vec![0.0, 2.0, 4.0, 6.0, 8.0]
504 );
505 assert_eq!(
506 block.channel_iter(1).copied().collect::<Vec<_>>(),
507 vec![1.0, 3.0, 5.0, 7.0, 9.0]
508 );
509 assert_eq!(
510 block.frame_iter(0).copied().collect::<Vec<_>>(),
511 vec![0.0, 1.0]
512 );
513 assert_eq!(
514 block.frame_iter(1).copied().collect::<Vec<_>>(),
515 vec![2.0, 3.0]
516 );
517 assert_eq!(
518 block.frame_iter(2).copied().collect::<Vec<_>>(),
519 vec![4.0, 5.0]
520 );
521 assert_eq!(
522 block.frame_iter(3).copied().collect::<Vec<_>>(),
523 vec![6.0, 7.0]
524 );
525 assert_eq!(
526 block.frame_iter(4).copied().collect::<Vec<_>>(),
527 vec![8.0, 9.0]
528 );
529 }
530
531 #[test]
532 fn test_view() {
533 let vec = vec![vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
534 let block = AudioBlockPlanarView::from_slice(&vec);
535
536 assert!(block.as_interleaved_view().is_none());
537 assert!(block.as_planar_view().is_some());
538 assert!(block.as_sequential_view().is_none());
539
540 let view = block.as_view();
541 assert_eq!(
542 view.channel_iter(0).copied().collect::<Vec<_>>(),
543 vec![0.0, 2.0, 4.0, 6.0, 8.0]
544 );
545 assert_eq!(
546 view.channel_iter(1).copied().collect::<Vec<_>>(),
547 vec![1.0, 3.0, 5.0, 7.0, 9.0]
548 );
549 }
550
551 #[test]
552 fn test_limited() {
553 let data = vec![vec![0.0; 4]; 3];
554
555 let block = AudioBlockPlanarView::from_slice_limited(&data, 2, 3);
556
557 assert_eq!(block.num_channels(), 2);
558 assert_eq!(block.num_frames(), 3);
559 assert_eq!(block.num_channels_allocated, 3);
560 assert_eq!(block.num_frames_allocated, 4);
561
562 for i in 0..block.num_channels() {
563 assert_eq!(block.channel_iter(i).count(), 3);
564 }
565 for i in 0..block.num_frames() {
566 assert_eq!(block.frame_iter(i).count(), 2);
567 }
568 }
569
570 #[test]
571 fn test_pointer() {
572 unsafe {
573 let num_channels = 2;
574 let num_frames = 5;
575 let mut vec = [vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
576
577 let ptr_vec: Vec<*const f32> =
578 vec.iter_mut().map(|inner_vec| inner_vec.as_ptr()).collect();
579 let ptr = ptr_vec.as_ptr();
580
581 let adapter = PlanarPtrAdapter::<_, 16>::from_ptr(ptr, num_channels, num_frames);
582 let planar = adapter.planar_view();
583
584 assert_eq!(
585 planar.channel_iter(0).copied().collect::<Vec<_>>(),
586 vec![0.0, 2.0, 4.0, 6.0, 8.0]
587 );
588
589 assert_eq!(
590 planar.channel_iter(1).copied().collect::<Vec<_>>(),
591 vec![1.0, 3.0, 5.0, 7.0, 9.0]
592 );
593 }
594 }
595
596 #[test]
597 #[should_panic]
598 #[no_sanitize_realtime]
599 fn test_slice_out_of_bounds() {
600 let data = [[1.0; 4], [2.0; 4], [0.0; 4]];
601 let block = AudioBlockPlanarView::from_slice_limited(&data, 2, 3);
602
603 block.channel(2);
604 }
605}