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