1use rtsan_standalone::nonblocking;
2
3use core::{marker::PhantomData, ptr::NonNull};
4
5use crate::{AudioBlock, Sample, iter::StridedSampleIter};
6
7pub struct InterleavedView<'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> InterleavedView<'a, S> {
35 #[nonblocking]
45 pub fn from_slice(data: &'a [S], num_channels: u16, num_frames: usize) -> Self {
46 assert_eq!(data.len(), num_channels as usize * num_frames);
47 Self {
48 data,
49 num_channels,
50 num_frames,
51 num_channels_allocated: num_channels,
52 num_frames_allocated: num_frames,
53 }
54 }
55
56 #[nonblocking]
73 pub fn from_slice_limited(
74 data: &'a [S],
75 num_channels_visible: u16,
76 num_frames_visible: usize,
77 num_channels_allocated: u16,
78 num_frames_allocated: usize,
79 ) -> Self {
80 assert_eq!(
81 data.len(),
82 num_channels_allocated as usize * num_frames_allocated
83 );
84 assert!(num_channels_visible <= num_channels_allocated);
85 assert!(num_frames_visible <= num_frames_allocated);
86 Self {
87 data,
88 num_channels: num_channels_visible,
89 num_frames: num_frames_visible,
90 num_channels_allocated,
91 num_frames_allocated,
92 }
93 }
94
95 #[nonblocking]
104 pub unsafe fn from_ptr(ptr: *const S, num_channels: u16, num_frames: usize) -> Self {
105 Self {
106 data: unsafe { std::slice::from_raw_parts(ptr, num_channels as usize * num_frames) },
107 num_channels,
108 num_frames,
109 num_channels_allocated: num_channels,
110 num_frames_allocated: num_frames,
111 }
112 }
113
114 #[nonblocking]
123 pub unsafe fn from_ptr_limited(
124 ptr: *const S,
125 num_channels_visible: u16,
126 num_frames_visible: usize,
127 num_channels_allocated: u16,
128 num_frames_allocated: usize,
129 ) -> Self {
130 assert!(num_channels_visible <= num_channels_allocated);
131 assert!(num_frames_visible <= num_frames_allocated);
132 Self {
133 data: unsafe {
134 std::slice::from_raw_parts(
135 ptr,
136 num_channels_allocated as usize * num_frames_allocated,
137 )
138 },
139 num_channels: num_channels_visible,
140 num_frames: num_frames_visible,
141 num_channels_allocated,
142 num_frames_allocated,
143 }
144 }
145}
146
147impl<S: Sample> AudioBlock<S> for InterleavedView<'_, S> {
148 #[nonblocking]
149 fn num_channels(&self) -> u16 {
150 self.num_channels
151 }
152
153 #[nonblocking]
154 fn num_frames(&self) -> usize {
155 self.num_frames
156 }
157
158 #[nonblocking]
159 fn num_channels_allocated(&self) -> u16 {
160 self.num_channels_allocated
161 }
162
163 #[nonblocking]
164 fn num_frames_allocated(&self) -> usize {
165 self.num_frames_allocated
166 }
167
168 #[nonblocking]
169 fn sample(&self, channel: u16, frame: usize) -> S {
170 assert!(channel < self.num_channels);
171 assert!(frame < self.num_frames);
172 unsafe {
173 *self
174 .data
175 .get_unchecked(frame * self.num_channels_allocated as usize + channel as usize)
176 }
177 }
178
179 #[nonblocking]
180 fn channel(&self, channel: u16) -> impl Iterator<Item = &S> {
181 assert!(channel < self.num_channels);
182 self.data
183 .iter()
184 .skip(channel as usize)
185 .step_by(self.num_channels_allocated as usize)
186 .take(self.num_frames)
187 }
188
189 #[nonblocking]
190 fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
191 let num_channels = self.num_channels as usize;
192 let num_frames = self.num_frames;
193 let stride = self.num_channels_allocated as usize;
194 let data_ptr = self.data.as_ptr();
195
196 (0..num_channels).map(move |channel_idx| {
197 let start_ptr = if self.data.is_empty() {
202 NonNull::dangling().as_ptr() } else {
204 unsafe { data_ptr.add(channel_idx) }
207 };
208
209 StridedSampleIter::<'_, S> {
210 ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), stride,
215 remaining: num_frames, _marker: PhantomData,
217 }
218 })
219 }
220
221 #[nonblocking]
222 fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
223 assert!(frame < self.num_frames);
224 self.data
225 .iter()
226 .skip(frame * self.num_channels_allocated as usize)
227 .take(self.num_channels as usize)
228 }
229
230 #[nonblocking]
231 fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
232 let num_channels = self.num_channels as usize;
233 let num_channels_allocated = self.num_channels_allocated as usize;
234 self.data
235 .chunks(num_channels_allocated)
236 .take(self.num_frames)
237 .map(move |channel_chunk| channel_chunk.iter().take(num_channels))
238 }
239
240 #[nonblocking]
241 fn frame_slice(&self, frame: usize) -> Option<&[S]> {
242 assert!(frame < self.num_frames);
243 let start = frame * self.num_channels_allocated as usize;
244 let end = start + self.num_channels as usize;
245 Some(&self.data[start..end])
246 }
247
248 #[nonblocking]
249 fn view(&self) -> impl AudioBlock<S> {
250 InterleavedView::from_slice_limited(
251 self.data,
252 self.num_channels,
253 self.num_frames,
254 self.num_channels_allocated,
255 self.num_frames_allocated,
256 )
257 }
258
259 #[nonblocking]
260 fn layout(&self) -> crate::BlockLayout {
261 crate::BlockLayout::Interleaved
262 }
263
264 #[nonblocking]
265 fn raw_data(&self, _: Option<u16>) -> &[S] {
266 self.data
267 }
268}
269
270#[cfg(test)]
271mod tests {
272 use rtsan_standalone::no_sanitize_realtime;
273
274 use super::*;
275
276 #[test]
277 fn test_samples() {
278 let data = vec![0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0];
279 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
280
281 for ch in 0..block.num_channels() {
282 for f in 0..block.num_frames() {
283 assert_eq!(
284 block.sample(ch, f),
285 (ch as usize * block.num_frames() + f) as f32
286 );
287 }
288 }
289 }
290
291 #[test]
292 fn test_channel() {
293 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
294 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
295
296 let channel = block.channel(0).copied().collect::<Vec<_>>();
297 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
298 let channel = block.channel(1).copied().collect::<Vec<_>>();
299 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
300 }
301
302 #[test]
303 fn test_channels() {
304 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
305 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
306
307 let mut channels_iter = block.channels();
308 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
309 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
310
311 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
312 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
313 assert!(channels_iter.next().is_none());
314 }
315
316 #[test]
317 fn test_frame() {
318 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
319 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
320
321 let channel = block.frame(0).copied().collect::<Vec<_>>();
322 assert_eq!(channel, vec![0.0, 1.0]);
323 let channel = block.frame(1).copied().collect::<Vec<_>>();
324 assert_eq!(channel, vec![2.0, 3.0]);
325 let channel = block.frame(2).copied().collect::<Vec<_>>();
326 assert_eq!(channel, vec![4.0, 5.0]);
327 let channel = block.frame(3).copied().collect::<Vec<_>>();
328 assert_eq!(channel, vec![6.0, 7.0]);
329 let channel = block.frame(4).copied().collect::<Vec<_>>();
330 assert_eq!(channel, vec![8.0, 9.0]);
331 }
332
333 #[test]
334 fn test_frames() {
335 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
336 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
337
338 let mut frames_iter = block.frames();
339 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
340 assert_eq!(channel, vec![0.0, 1.0]);
341 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
342 assert_eq!(channel, vec![2.0, 3.0]);
343 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
344 assert_eq!(channel, vec![4.0, 5.0]);
345 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
346 assert_eq!(channel, vec![6.0, 7.0]);
347 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
348 assert_eq!(channel, vec![8.0, 9.0]);
349 assert!(frames_iter.next().is_none());
350 }
351
352 #[test]
353 fn test_from_slice() {
354 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
355 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
356 assert_eq!(block.num_channels(), 2);
357 assert_eq!(block.num_channels_allocated, 2);
358 assert_eq!(block.num_frames(), 5);
359 assert_eq!(block.num_frames_allocated, 5);
360 assert_eq!(
361 block.channel(0).copied().collect::<Vec<_>>(),
362 vec![0.0, 2.0, 4.0, 6.0, 8.0]
363 );
364 assert_eq!(
365 block.channel(1).copied().collect::<Vec<_>>(),
366 vec![1.0, 3.0, 5.0, 7.0, 9.0]
367 );
368 assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
369 assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
370 assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
371 assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
372 assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
373 }
374
375 #[test]
376 fn test_view() {
377 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
378 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
379 let view = block.view();
380 assert_eq!(
381 view.channel(0).copied().collect::<Vec<_>>(),
382 vec![0.0, 2.0, 4.0, 6.0, 8.0]
383 );
384 assert_eq!(
385 view.channel(1).copied().collect::<Vec<_>>(),
386 vec![1.0, 3.0, 5.0, 7.0, 9.0]
387 );
388 }
389
390 #[test]
391 fn test_limited() {
392 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];
393
394 let block = InterleavedView::from_slice_limited(&data, 2, 3, 3, 4);
395
396 assert_eq!(block.num_channels(), 2);
397 assert_eq!(block.num_frames(), 3);
398 assert_eq!(block.num_channels_allocated, 3);
399 assert_eq!(block.num_frames_allocated, 4);
400
401 for i in 0..block.num_channels() {
402 assert_eq!(block.channel(i).count(), 3);
403 }
404 for i in 0..block.num_frames() {
405 assert_eq!(block.frame(i).count(), 2);
406 }
407 }
408
409 #[test]
410 fn test_from_raw() {
411 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
412 let block = unsafe { InterleavedView::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
413 assert_eq!(block.num_channels(), 2);
414 assert_eq!(block.num_channels_allocated, 2);
415 assert_eq!(block.num_frames(), 5);
416 assert_eq!(block.num_frames_allocated, 5);
417 assert_eq!(
418 block.channel(0).copied().collect::<Vec<_>>(),
419 vec![0.0, 2.0, 4.0, 6.0, 8.0]
420 );
421 assert_eq!(
422 block.channel(1).copied().collect::<Vec<_>>(),
423 vec![1.0, 3.0, 5.0, 7.0, 9.0]
424 );
425 assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
426 assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
427 assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
428 assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
429 assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
430 }
431
432 #[test]
433 fn test_from_raw_limited() {
434 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];
435
436 let block = unsafe { InterleavedView::from_ptr_limited(data.as_ptr(), 2, 3, 3, 4) };
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_slice() {
453 let data = [1.0, 1.0, 0.0, 2.0, 2.0, 0.0, 3.0, 3.0, 0.0, 0.0, 0.0, 0.0];
454 let block = InterleavedView::<f32>::from_slice_limited(&data, 2, 3, 3, 4);
455 assert!(block.channel_slice(0).is_none());
456
457 assert_eq!(block.frame_slice(0).unwrap(), &[1.0; 2]);
458 assert_eq!(block.frame_slice(1).unwrap(), &[2.0; 2]);
459 assert_eq!(block.frame_slice(2).unwrap(), &[3.0; 2]);
460 }
461
462 #[test]
463 #[should_panic]
464 #[no_sanitize_realtime]
465 fn test_slice_out_of_bounds() {
466 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];
467 let block = InterleavedView::<f32>::from_slice_limited(&data, 2, 3, 3, 4);
468 block.frame_slice(5);
469 }
470
471 #[test]
472 fn test_raw_data() {
473 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
474 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
475
476 assert_eq!(block.layout(), crate::BlockLayout::Interleaved);
477
478 assert_eq!(
479 block.raw_data(None),
480 &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
481 );
482 }
483}