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