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