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 frame(&self, frame: usize) -> impl Iterator<Item = &S> {
154 assert!(frame < self.num_frames);
155 self.data
156 .iter()
157 .take(self.num_channels as usize)
158 .map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
159 }
160
161 #[nonblocking]
162 fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &'_ S> + '_> + '_ {
163 let num_channels = self.num_channels as usize;
164 let num_frames = self.num_frames;
165 let data_slice: &[V] = self.data;
166
167 (0..num_frames).map(move |frame_idx| {
168 data_slice[..num_channels]
170 .iter() .map(move |channel_view: &V| {
172 let channel_slice: &[S] = channel_view.as_ref();
174 &channel_slice[frame_idx]
177 })
180 })
181 }
182
183 #[nonblocking]
184 fn view(&self) -> impl AudioBlock<S> {
185 StackedView::<S, V>::from_slice_limited(self.data, self.num_channels, self.num_frames)
186 }
187
188 #[nonblocking]
189 fn layout(&self) -> crate::BlockLayout {
190 crate::BlockLayout::Stacked
191 }
192
193 #[nonblocking]
194 fn raw_data(&self, stacked_ch: Option<u16>) -> &[S] {
195 let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
196 assert!(ch < self.num_channels_allocated);
197 unsafe { self.data.get_unchecked(ch as usize).as_ref() }
198 }
199}
200
201pub struct StackedPtrAdapter<'a, S: Sample, const MAX_CHANNELS: usize> {
239 data: [MaybeUninit<&'a [S]>; MAX_CHANNELS],
240 num_channels: u16,
241}
242
243impl<'a, S: Sample, const MAX_CHANNELS: usize> StackedPtrAdapter<'a, S, MAX_CHANNELS> {
244 #[nonblocking]
254 #[nonblocking]
255 pub unsafe fn from_ptr(ptr: *const *const S, num_channels: u16, num_frames: usize) -> Self {
256 assert!(
257 num_channels as usize <= MAX_CHANNELS,
258 "num_channels exceeds MAX_CHANNELS"
259 );
260
261 let mut data: [core::mem::MaybeUninit<&'a [S]>; MAX_CHANNELS] =
262 unsafe { core::mem::MaybeUninit::uninit().assume_init() }; let ptr_slice: &[*const S] =
266 unsafe { core::slice::from_raw_parts(ptr, num_channels as usize) };
267
268 for ch in 0..num_channels as usize {
269 data[ch].write(unsafe { core::slice::from_raw_parts(ptr_slice[ch], num_frames) });
271 }
272
273 Self { data, num_channels }
274 }
275
276 #[inline]
281 pub fn data_slice(&self) -> &[&'a [S]] {
282 let initialized_part: &[MaybeUninit<&'a [S]>] = &self.data[..self.num_channels as usize];
283 unsafe {
284 core::slice::from_raw_parts(
285 initialized_part.as_ptr() as *const &'a [S],
286 self.num_channels as usize,
287 )
288 }
289 }
290
291 #[nonblocking]
301 pub fn stacked_view(&self) -> StackedView<'a, S, &[S]> {
302 StackedView::from_slice(self.data_slice())
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn test_samples() {
312 let ch1 = &[0.0, 1.0, 2.0, 3.0, 4.0];
313 let ch2 = &[5.0, 6.0, 7.0, 8.0, 9.0];
314 let data = [ch1, ch2];
315 let block = StackedView::from_slice(&data);
316
317 for ch in 0..block.num_channels() {
318 for f in 0..block.num_frames() {
319 assert_eq!(
320 block.sample(ch, f),
321 (ch as usize * block.num_frames() + f) as f32
322 );
323 }
324 }
325 }
326
327 #[test]
328 fn test_channel() {
329 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
330 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
331 let data = vec![ch1, ch2];
332 let block = StackedView::from_slice(&data);
333
334 let channel = block.channel(0).copied().collect::<Vec<_>>();
335 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
336 let channel = block.channel(1).copied().collect::<Vec<_>>();
337 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
338 }
339
340 #[test]
341 fn test_channels() {
342 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
343 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
344 let data = vec![ch1, ch2];
345 let block = StackedView::from_slice(&data);
346
347 let mut channels_iter = block.channels();
348 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
349 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
350
351 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
352 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
353 assert!(channels_iter.next().is_none());
354 }
355
356 #[test]
357 fn test_frame() {
358 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
359 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
360 let data = vec![ch1.as_slice(), ch2.as_slice()];
361 let block = StackedView::from_slice(&data);
362
363 let channel = block.frame(0).copied().collect::<Vec<_>>();
364 assert_eq!(channel, vec![0.0, 1.0]);
365 let channel = block.frame(1).copied().collect::<Vec<_>>();
366 assert_eq!(channel, vec![2.0, 3.0]);
367 let channel = block.frame(2).copied().collect::<Vec<_>>();
368 assert_eq!(channel, vec![4.0, 5.0]);
369 let channel = block.frame(3).copied().collect::<Vec<_>>();
370 assert_eq!(channel, vec![6.0, 7.0]);
371 let channel = block.frame(4).copied().collect::<Vec<_>>();
372 assert_eq!(channel, vec![8.0, 9.0]);
373 }
374
375 #[test]
376 fn test_frames() {
377 let ch1 = vec![0.0, 2.0, 4.0, 6.0, 8.0];
378 let ch2 = vec![1.0, 3.0, 5.0, 7.0, 9.0];
379 let data = vec![ch1.as_slice(), ch2.as_slice()];
380 let block = StackedView::from_slice(&data);
381
382 let mut frames_iter = block.frames();
383 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
384 assert_eq!(channel, vec![0.0, 1.0]);
385 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
386 assert_eq!(channel, vec![2.0, 3.0]);
387 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
388 assert_eq!(channel, vec![4.0, 5.0]);
389 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
390 assert_eq!(channel, vec![6.0, 7.0]);
391 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
392 assert_eq!(channel, vec![8.0, 9.0]);
393 assert!(frames_iter.next().is_none());
394 }
395
396 #[test]
397 fn test_from_vec() {
398 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]];
399 let block = StackedView::from_slice(&vec);
400 assert_eq!(block.num_channels(), 2);
401 assert_eq!(block.num_frames(), 5);
402 assert_eq!(
403 block.channel(0).copied().collect::<Vec<_>>(),
404 vec![0.0, 2.0, 4.0, 6.0, 8.0]
405 );
406 assert_eq!(
407 block.channel(1).copied().collect::<Vec<_>>(),
408 vec![1.0, 3.0, 5.0, 7.0, 9.0]
409 );
410 assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
411 assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
412 assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
413 assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
414 assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
415 }
416
417 #[test]
418 fn test_view() {
419 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]];
420 let block = StackedView::from_slice(&vec);
421 let view = block.view();
422 assert_eq!(
423 view.channel(0).copied().collect::<Vec<_>>(),
424 vec![0.0, 2.0, 4.0, 6.0, 8.0]
425 );
426 assert_eq!(
427 view.channel(1).copied().collect::<Vec<_>>(),
428 vec![1.0, 3.0, 5.0, 7.0, 9.0]
429 );
430 }
431
432 #[test]
433 fn test_limited() {
434 let data = vec![vec![0.0; 4]; 3];
435
436 let block = StackedView::from_slice_limited(&data, 2, 3);
437
438 assert_eq!(block.num_channels(), 2);
439 assert_eq!(block.num_frames(), 3);
440 assert_eq!(block.num_channels_allocated, 3);
441 assert_eq!(block.num_frames_allocated, 4);
442
443 for i in 0..block.num_channels() {
444 assert_eq!(block.channel(i).count(), 3);
445 }
446 for i in 0..block.num_frames() {
447 assert_eq!(block.frame(i).count(), 2);
448 }
449 }
450
451 #[test]
452 fn test_pointer() {
453 unsafe {
454 let num_channels = 2;
455 let num_frames = 5;
456 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]];
457
458 let ptr_vec: Vec<*const f32> =
459 vec.iter_mut().map(|inner_vec| inner_vec.as_ptr()).collect();
460 let ptr = ptr_vec.as_ptr();
461
462 let adapter = StackedPtrAdapter::<_, 16>::from_ptr(ptr, num_channels, num_frames);
463 let stacked = adapter.stacked_view();
464
465 assert_eq!(
466 stacked.channel(0).copied().collect::<Vec<_>>(),
467 vec![0.0, 2.0, 4.0, 6.0, 8.0]
468 );
469
470 assert_eq!(
471 stacked.channel(1).copied().collect::<Vec<_>>(),
472 vec![1.0, 3.0, 5.0, 7.0, 9.0]
473 );
474 }
475 }
476
477 #[test]
478 fn test_raw_data() {
479 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]];
480 let block = StackedView::from_slice(&vec);
481
482 assert_eq!(block.layout(), crate::BlockLayout::Stacked);
483
484 assert_eq!(block.raw_data(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
485 assert_eq!(block.raw_data(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
486 }
487}