audio/frame/
interleaved.rs1use core::marker;
2use core::ptr;
3use core::slice;
4
5use audio_core::Frame;
6
7use crate::channel::linear::Iter;
8
9pub(crate) struct RawInterleaved<T> {
11 ptr: ptr::NonNull<T>,
12 len: usize,
13 channels: usize,
14 frames: usize,
15}
16
17impl<T> Clone for RawInterleaved<T> {
18 #[inline]
19 fn clone(&self) -> Self {
20 *self
21 }
22}
23
24impl<T> Copy for RawInterleaved<T> {}
25
26impl<T> RawInterleaved<T> {
27 pub(crate) unsafe fn new(data: &[T], channels: usize, frames: usize) -> Self {
34 let len = data.len();
35
36 debug_assert!(
37 len % channels == 0,
38 "data provided is not aligned with the number of channels; len={}, frames={}",
39 len,
40 channels,
41 );
42
43 debug_assert!(
44 len % frames == 0,
45 "data provided is not aligned with the number of frames; len={}, frames={}",
46 len,
47 frames,
48 );
49
50 Self {
51 ptr: ptr::NonNull::new_unchecked(data.as_ptr() as *mut T),
52 len,
53 channels,
54 frames,
55 }
56 }
57
58 #[inline]
60 pub(crate) fn frames(&self) -> usize {
61 self.frames
62 }
63
64 pub(crate) unsafe fn get_sample(&self, frame: usize, channel: usize) -> Option<T>
72 where
73 T: Copy,
74 {
75 let index = channel.checked_add(self.channels.checked_mul(frame)?)?;
76
77 debug_assert!(
78 index < self.len,
79 "index `{index}` out-of-bounds",
80 index = index
81 );
82
83 if index >= self.len {
84 return None;
85 }
86
87 Some(*self.ptr.as_ptr().add(index))
88 }
89
90 pub(crate) unsafe fn iter_from_frame<'a>(self, frame: usize) -> Iter<'a, T> {
97 let data = slice::from_raw_parts(self.ptr.as_ptr() as *const _, self.len);
98 let data = self
99 .channels
100 .checked_mul(frame)
101 .and_then(|start| data.get(start..)?.get(..self.channels))
102 .unwrap_or_default();
103 Iter::new(data)
104 }
105}
106
107pub struct InterleavedFrame<'a, T> {
109 frame: usize,
110 raw: RawInterleaved<T>,
111 _marker: marker::PhantomData<&'a ()>,
112}
113
114impl<T> InterleavedFrame<'_, T> {
115 #[inline]
116 pub(crate) fn new(frame: usize, raw: RawInterleaved<T>) -> Self {
117 Self {
118 frame,
119 raw,
120 _marker: marker::PhantomData,
121 }
122 }
123}
124
125impl<T> Frame for InterleavedFrame<'_, T>
126where
127 T: Copy,
128{
129 type Sample = T;
130
131 type Frame<'this>
132 = InterleavedFrame<'this, T>
133 where
134 Self: 'this;
135
136 type Iter<'this>
137 = Iter<'this, T>
138 where
139 Self: 'this;
140
141 #[inline]
142 fn as_frame(&self) -> Self::Frame<'_> {
143 Self {
144 frame: self.frame,
145 raw: self.raw,
146 _marker: marker::PhantomData,
147 }
148 }
149
150 #[inline]
151 fn len(&self) -> usize {
152 self.raw.frames()
153 }
154
155 #[inline]
156 fn get(&self, channel: usize) -> Option<Self::Sample> {
157 unsafe { self.raw.get_sample(self.frame, channel) }
160 }
161
162 #[inline]
163 fn iter(&self) -> Self::Iter<'_> {
164 unsafe { self.raw.iter_from_frame(self.frame) }
167 }
168}
169
170pub struct InterleavedFramesIter<'a, T> {
172 frame: usize,
173 raw: RawInterleaved<T>,
174 _marker: marker::PhantomData<&'a [T]>,
175}
176
177impl<T> InterleavedFramesIter<'_, T> {
178 #[inline]
179 pub(crate) fn new(frame: usize, raw: RawInterleaved<T>) -> Self {
180 Self {
181 frame,
182 raw,
183 _marker: marker::PhantomData,
184 }
185 }
186}
187
188impl<'a, T> Iterator for InterleavedFramesIter<'a, T> {
189 type Item = InterleavedFrame<'a, T>;
190
191 #[inline]
192 fn next(&mut self) -> Option<Self::Item> {
193 if self.frame >= self.raw.frames() {
194 return None;
195 }
196
197 let frame = self.frame;
198 self.frame = self.frame.checked_add(1)?;
199
200 Some(InterleavedFrame {
201 frame,
202 raw: self.raw,
203 _marker: marker::PhantomData,
204 })
205 }
206}