1use core::mem::MaybeUninit;
2use rtsan_standalone::nonblocking;
3use std::marker::PhantomData;
4
5use crate::{AudioBlock, Sample};
6
7pub struct StackedView<'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]>> StackedView<'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
95impl<S: Sample, V: AsRef<[S]>> AudioBlock<S> for StackedView<'_, S, V> {
96 #[nonblocking]
97 fn num_frames(&self) -> usize {
98 self.num_frames
99 }
100
101 #[nonblocking]
102 fn num_channels(&self) -> u16 {
103 self.num_channels
104 }
105
106 #[nonblocking]
107 fn num_channels_allocated(&self) -> u16 {
108 self.num_channels_allocated
109 }
110
111 #[nonblocking]
112 fn num_frames_allocated(&self) -> usize {
113 self.num_frames_allocated
114 }
115
116 #[nonblocking]
117 fn sample(&self, channel: u16, frame: usize) -> S {
118 assert!(channel < self.num_channels);
119 assert!(frame < self.num_frames);
120 unsafe {
121 *self
122 .data
123 .get_unchecked(channel as usize)
124 .as_ref()
125 .get_unchecked(frame)
126 }
127 }
128
129 #[nonblocking]
130 fn channel(&self, channel: u16) -> impl Iterator<Item = &S> {
131 assert!(channel < self.num_channels);
132 unsafe {
133 self.data
134 .get_unchecked(channel as usize)
135 .as_ref()
136 .iter()
137 .take(self.num_frames)
138 }
139 }
140
141 #[nonblocking]
142 fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
143 let num_frames = self.num_frames; self.data
145 .iter()
146 .take(self.num_channels as usize)
148 .map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
150 }
151
152 #[nonblocking]
153 fn channel_slice(&self, channel: u16) -> Option<&[S]> {
154 assert!(channel < self.num_channels);
155 Some(&self.data[channel as usize].as_ref()[..self.num_frames])
156 }
157
158 #[nonblocking]
159 fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
160 assert!(frame < self.num_frames);
161 self.data
162 .iter()
163 .take(self.num_channels as usize)
164 .map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
165 }
166
167 #[nonblocking]
168 fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &'_ S> + '_> + '_ {
169 let num_channels = self.num_channels as usize;
170 let num_frames = self.num_frames;
171 let data_slice: &[V] = self.data;
172
173 (0..num_frames).map(move |frame_idx| {
174 data_slice[..num_channels]
176 .iter() .map(move |channel_view: &V| {
178 let channel_slice: &[S] = channel_view.as_ref();
180 &channel_slice[frame_idx]
183 })
186 })
187 }
188
189 #[nonblocking]
190 fn view(&self) -> impl AudioBlock<S> {
191 StackedView::<S, V>::from_slice_limited(self.data, self.num_channels, self.num_frames)
192 }
193
194 #[nonblocking]
195 fn layout(&self) -> crate::BlockLayout {
196 crate::BlockLayout::Stacked
197 }
198
199 #[nonblocking]
200 fn raw_data(&self, stacked_ch: Option<u16>) -> &[S] {
201 let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
202 assert!(ch < self.num_channels_allocated);
203 unsafe { self.data.get_unchecked(ch as usize).as_ref() }
204 }
205}
206
207pub struct StackedPtrAdapter<'a, S: Sample, const MAX_CHANNELS: usize> {
245 data: [MaybeUninit<&'a [S]>; MAX_CHANNELS],
246 num_channels: u16,
247}
248
249impl<'a, S: Sample, const MAX_CHANNELS: usize> StackedPtrAdapter<'a, S, MAX_CHANNELS> {
250 #[nonblocking]
260 #[nonblocking]
261 pub unsafe fn from_ptr(ptr: *const *const S, num_channels: u16, num_frames: usize) -> Self {
262 assert!(
263 num_channels as usize <= MAX_CHANNELS,
264 "num_channels exceeds MAX_CHANNELS"
265 );
266
267 let mut data: [core::mem::MaybeUninit<&'a [S]>; MAX_CHANNELS] =
268 unsafe { core::mem::MaybeUninit::uninit().assume_init() }; let ptr_slice: &[*const S] =
272 unsafe { core::slice::from_raw_parts(ptr, num_channels as usize) };
273
274 for ch in 0..num_channels as usize {
275 data[ch].write(unsafe { core::slice::from_raw_parts(ptr_slice[ch], num_frames) });
277 }
278
279 Self { data, num_channels }
280 }
281
282 #[inline]
287 pub fn data_slice(&self) -> &[&'a [S]] {
288 let initialized_part: &[MaybeUninit<&'a [S]>] = &self.data[..self.num_channels as usize];
289 unsafe {
290 core::slice::from_raw_parts(
291 initialized_part.as_ptr() as *const &'a [S],
292 self.num_channels as usize,
293 )
294 }
295 }
296
297 #[nonblocking]
307 pub fn stacked_view(&self) -> StackedView<'a, S, &[S]> {
308 StackedView::from_slice(self.data_slice())
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use rtsan_standalone::no_sanitize_realtime;
315
316 use super::*;
317
318 #[test]
319 fn test_samples() {
320 let ch1 = &[0.0, 1.0, 2.0, 3.0, 4.0];
321 let ch2 = &[5.0, 6.0, 7.0, 8.0, 9.0];
322 let data = [ch1, ch2];
323 let block = StackedView::from_slice(&data);
324
325 for ch in 0..block.num_channels() {
326 for f in 0..block.num_frames() {
327 assert_eq!(
328 block.sample(ch, f),
329 (ch as usize * block.num_frames() + f) as f32
330 );
331 }
332 }
333 }
334
335 #[test]
336 fn test_channel() {
337 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
338 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
339 let data = vec![ch1, ch2];
340 let block = StackedView::from_slice(&data);
341
342 let channel = block.channel(0).copied().collect::<Vec<_>>();
343 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
344 let channel = block.channel(1).copied().collect::<Vec<_>>();
345 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
346 }
347
348 #[test]
349 fn test_channels() {
350 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
351 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
352 let data = vec![ch1, ch2];
353 let block = StackedView::from_slice(&data);
354
355 let mut channels_iter = block.channels();
356 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
357 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
358
359 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
360 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
361 assert!(channels_iter.next().is_none());
362 }
363
364 #[test]
365 fn test_frame() {
366 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
367 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
368 let data = vec![ch1.as_slice(), ch2.as_slice()];
369 let block = StackedView::from_slice(&data);
370
371 let channel = block.frame(0).copied().collect::<Vec<_>>();
372 assert_eq!(channel, vec![0.0, 1.0]);
373 let channel = block.frame(1).copied().collect::<Vec<_>>();
374 assert_eq!(channel, vec![2.0, 3.0]);
375 let channel = block.frame(2).copied().collect::<Vec<_>>();
376 assert_eq!(channel, vec![4.0, 5.0]);
377 let channel = block.frame(3).copied().collect::<Vec<_>>();
378 assert_eq!(channel, vec![6.0, 7.0]);
379 let channel = block.frame(4).copied().collect::<Vec<_>>();
380 assert_eq!(channel, vec![8.0, 9.0]);
381 }
382
383 #[test]
384 fn test_frames() {
385 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
386 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
387 let data = vec![ch1.as_slice(), ch2.as_slice()];
388 let block = StackedView::from_slice(&data);
389
390 let mut frames_iter = block.frames();
391 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
392 assert_eq!(channel, vec![0.0, 1.0]);
393 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
394 assert_eq!(channel, vec![2.0, 3.0]);
395 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
396 assert_eq!(channel, vec![4.0, 5.0]);
397 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
398 assert_eq!(channel, vec![6.0, 7.0]);
399 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
400 assert_eq!(channel, vec![8.0, 9.0]);
401 assert!(frames_iter.next().is_none());
402 }
403
404 #[test]
405 fn test_from_vec() {
406 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]];
407 let block = StackedView::from_slice(&vec);
408 assert_eq!(block.num_channels(), 2);
409 assert_eq!(block.num_frames(), 5);
410 assert_eq!(
411 block.channel(0).copied().collect::<Vec<_>>(),
412 vec![0.0, 2.0, 4.0, 6.0, 8.0]
413 );
414 assert_eq!(
415 block.channel(1).copied().collect::<Vec<_>>(),
416 vec![1.0, 3.0, 5.0, 7.0, 9.0]
417 );
418 assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
419 assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
420 assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
421 assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
422 assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
423 }
424
425 #[test]
426 fn test_view() {
427 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]];
428 let block = StackedView::from_slice(&vec);
429 let view = block.view();
430 assert_eq!(
431 view.channel(0).copied().collect::<Vec<_>>(),
432 vec![0.0, 2.0, 4.0, 6.0, 8.0]
433 );
434 assert_eq!(
435 view.channel(1).copied().collect::<Vec<_>>(),
436 vec![1.0, 3.0, 5.0, 7.0, 9.0]
437 );
438 }
439
440 #[test]
441 fn test_limited() {
442 let data = vec![vec![0.0; 4]; 3];
443
444 let block = StackedView::from_slice_limited(&data, 2, 3);
445
446 assert_eq!(block.num_channels(), 2);
447 assert_eq!(block.num_frames(), 3);
448 assert_eq!(block.num_channels_allocated, 3);
449 assert_eq!(block.num_frames_allocated, 4);
450
451 for i in 0..block.num_channels() {
452 assert_eq!(block.channel(i).count(), 3);
453 }
454 for i in 0..block.num_frames() {
455 assert_eq!(block.frame(i).count(), 2);
456 }
457 }
458
459 #[test]
460 fn test_pointer() {
461 unsafe {
462 let num_channels = 2;
463 let num_frames = 5;
464 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]];
465
466 let ptr_vec: Vec<*const f32> =
467 vec.iter_mut().map(|inner_vec| inner_vec.as_ptr()).collect();
468 let ptr = ptr_vec.as_ptr();
469
470 let adapter = StackedPtrAdapter::<_, 16>::from_ptr(ptr, num_channels, num_frames);
471 let stacked = adapter.stacked_view();
472
473 assert_eq!(
474 stacked.channel(0).copied().collect::<Vec<_>>(),
475 vec![0.0, 2.0, 4.0, 6.0, 8.0]
476 );
477
478 assert_eq!(
479 stacked.channel(1).copied().collect::<Vec<_>>(),
480 vec![1.0, 3.0, 5.0, 7.0, 9.0]
481 );
482 }
483 }
484
485 #[test]
486 fn test_slice() {
487 let data = [[1.0; 4], [2.0; 4], [0.0; 4]];
488 let block = StackedView::from_slice_limited(&data, 2, 3);
489
490 assert!(block.frame_slice(0).is_none());
491
492 assert_eq!(block.channel_slice(0).unwrap(), &[1.0; 3]);
493 assert_eq!(block.channel_slice(1).unwrap(), &[2.0; 3]);
494 }
495
496 #[test]
497 #[should_panic]
498 #[no_sanitize_realtime]
499 fn test_slice_out_of_bounds() {
500 let data = [[1.0; 4], [2.0; 4], [0.0; 4]];
501 let block = StackedView::from_slice_limited(&data, 2, 3);
502
503 block.channel_slice(2);
504 }
505
506 #[test]
507 fn test_raw_data() {
508 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]];
509 let block = StackedView::from_slice(&vec);
510
511 assert_eq!(block.layout(), crate::BlockLayout::Stacked);
512
513 assert_eq!(block.raw_data(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
514 assert_eq!(block.raw_data(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
515 }
516}