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