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 view(&self) -> impl AudioBlock<S> {
242 InterleavedView::from_slice_limited(
243 self.data,
244 self.num_channels,
245 self.num_frames,
246 self.num_channels_allocated,
247 self.num_frames_allocated,
248 )
249 }
250
251 #[nonblocking]
252 fn layout(&self) -> crate::BlockLayout {
253 crate::BlockLayout::Interleaved
254 }
255
256 #[nonblocking]
257 fn raw_data(&self, _: Option<u16>) -> &[S] {
258 self.data
259 }
260}
261
262#[cfg(test)]
263mod tests {
264 use super::*;
265
266 #[test]
267 fn test_samples() {
268 let data = vec![0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0];
269 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
270
271 for ch in 0..block.num_channels() {
272 for f in 0..block.num_frames() {
273 assert_eq!(
274 block.sample(ch, f),
275 (ch as usize * block.num_frames() + f) as f32
276 );
277 }
278 }
279 }
280
281 #[test]
282 fn test_channel() {
283 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
284 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
285
286 let channel = block.channel(0).copied().collect::<Vec<_>>();
287 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
288 let channel = block.channel(1).copied().collect::<Vec<_>>();
289 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
290 }
291
292 #[test]
293 fn test_channels() {
294 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
295 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
296
297 let mut channels_iter = block.channels();
298 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
299 assert_eq!(channel, vec![0.0, 2.0, 4.0, 6.0, 8.0]);
300
301 let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
302 assert_eq!(channel, vec![1.0, 3.0, 5.0, 7.0, 9.0]);
303 assert!(channels_iter.next().is_none());
304 }
305
306 #[test]
307 fn test_frame() {
308 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
309 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
310
311 let channel = block.frame(0).copied().collect::<Vec<_>>();
312 assert_eq!(channel, vec![0.0, 1.0]);
313 let channel = block.frame(1).copied().collect::<Vec<_>>();
314 assert_eq!(channel, vec![2.0, 3.0]);
315 let channel = block.frame(2).copied().collect::<Vec<_>>();
316 assert_eq!(channel, vec![4.0, 5.0]);
317 let channel = block.frame(3).copied().collect::<Vec<_>>();
318 assert_eq!(channel, vec![6.0, 7.0]);
319 let channel = block.frame(4).copied().collect::<Vec<_>>();
320 assert_eq!(channel, vec![8.0, 9.0]);
321 }
322
323 #[test]
324 fn test_frames() {
325 let data = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
326 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
327
328 let mut frames_iter = block.frames();
329 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
330 assert_eq!(channel, vec![0.0, 1.0]);
331 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
332 assert_eq!(channel, vec![2.0, 3.0]);
333 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
334 assert_eq!(channel, vec![4.0, 5.0]);
335 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
336 assert_eq!(channel, vec![6.0, 7.0]);
337 let channel = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
338 assert_eq!(channel, vec![8.0, 9.0]);
339 assert!(frames_iter.next().is_none());
340 }
341
342 #[test]
343 fn test_from_slice() {
344 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
345 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
346 assert_eq!(block.num_channels(), 2);
347 assert_eq!(block.num_channels_allocated, 2);
348 assert_eq!(block.num_frames(), 5);
349 assert_eq!(block.num_frames_allocated, 5);
350 assert_eq!(
351 block.channel(0).copied().collect::<Vec<_>>(),
352 vec![0.0, 2.0, 4.0, 6.0, 8.0]
353 );
354 assert_eq!(
355 block.channel(1).copied().collect::<Vec<_>>(),
356 vec![1.0, 3.0, 5.0, 7.0, 9.0]
357 );
358 assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
359 assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
360 assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
361 assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
362 assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
363 }
364
365 #[test]
366 fn test_view() {
367 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
368 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
369 let view = block.view();
370 assert_eq!(
371 view.channel(0).copied().collect::<Vec<_>>(),
372 vec![0.0, 2.0, 4.0, 6.0, 8.0]
373 );
374 assert_eq!(
375 view.channel(1).copied().collect::<Vec<_>>(),
376 vec![1.0, 3.0, 5.0, 7.0, 9.0]
377 );
378 }
379
380 #[test]
381 fn test_limited() {
382 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];
383
384 let block = InterleavedView::from_slice_limited(&data, 2, 3, 3, 4);
385
386 assert_eq!(block.num_channels(), 2);
387 assert_eq!(block.num_frames(), 3);
388 assert_eq!(block.num_channels_allocated, 3);
389 assert_eq!(block.num_frames_allocated, 4);
390
391 for i in 0..block.num_channels() {
392 assert_eq!(block.channel(i).count(), 3);
393 }
394 for i in 0..block.num_frames() {
395 assert_eq!(block.frame(i).count(), 2);
396 }
397 }
398
399 #[test]
400 fn test_from_raw() {
401 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
402 let block = unsafe { InterleavedView::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
403 assert_eq!(block.num_channels(), 2);
404 assert_eq!(block.num_channels_allocated, 2);
405 assert_eq!(block.num_frames(), 5);
406 assert_eq!(block.num_frames_allocated, 5);
407 assert_eq!(
408 block.channel(0).copied().collect::<Vec<_>>(),
409 vec![0.0, 2.0, 4.0, 6.0, 8.0]
410 );
411 assert_eq!(
412 block.channel(1).copied().collect::<Vec<_>>(),
413 vec![1.0, 3.0, 5.0, 7.0, 9.0]
414 );
415 assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
416 assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
417 assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
418 assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
419 assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
420 }
421
422 #[test]
423 fn test_from_raw_limited() {
424 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];
425
426 let block = unsafe { InterleavedView::from_ptr_limited(data.as_ptr(), 2, 3, 3, 4) };
427
428 assert_eq!(block.num_channels(), 2);
429 assert_eq!(block.num_frames(), 3);
430 assert_eq!(block.num_channels_allocated, 3);
431 assert_eq!(block.num_frames_allocated, 4);
432
433 for i in 0..block.num_channels() {
434 assert_eq!(block.channel(i).count(), 3);
435 }
436 for i in 0..block.num_frames() {
437 assert_eq!(block.frame(i).count(), 2);
438 }
439 }
440
441 #[test]
442 fn test_raw_data() {
443 let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
444 let block = InterleavedView::<f32>::from_slice(&data, 2, 5);
445
446 assert_eq!(block.layout(), crate::BlockLayout::Interleaved);
447
448 assert_eq!(
449 block.raw_data(None),
450 &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
451 );
452 }
453}