1use rtsan_standalone::nonblocking;
2
3use crate::{AudioBlock, Sample};
4
5pub struct AudioBlockMonoView<'a, S: Sample> {
26 data: &'a [S],
27 num_frames: usize,
28 num_frames_allocated: usize,
29}
30
31impl<'a, S: Sample> AudioBlockMonoView<'a, S> {
32 #[nonblocking]
47 pub fn from_slice(data: &'a [S]) -> Self {
48 let num_frames = data.len();
49 Self {
50 data,
51 num_frames,
52 num_frames_allocated: num_frames,
53 }
54 }
55
56 #[nonblocking]
81 pub fn from_slice_limited(
82 data: &'a [S],
83 num_frames_visible: usize,
84 num_frames_allocated: usize,
85 ) -> Self {
86 assert_eq!(data.len(), num_frames_allocated);
87 assert!(num_frames_visible <= num_frames_allocated);
88 Self {
89 data,
90 num_frames: num_frames_visible,
91 num_frames_allocated,
92 }
93 }
94
95 #[nonblocking]
114 pub unsafe fn from_ptr(ptr: *const S, num_frames: usize) -> Self {
115 Self {
116 data: unsafe { std::slice::from_raw_parts(ptr, num_frames) },
117 num_frames,
118 num_frames_allocated: num_frames,
119 }
120 }
121
122 #[nonblocking]
131 pub unsafe fn from_ptr_limited(
132 ptr: *const S,
133 num_frames_visible: usize,
134 num_frames_allocated: usize,
135 ) -> Self {
136 assert!(num_frames_visible <= num_frames_allocated);
137 Self {
138 data: unsafe { std::slice::from_raw_parts(ptr, num_frames_allocated) },
139 num_frames: num_frames_visible,
140 num_frames_allocated,
141 }
142 }
143
144 #[nonblocking]
150 pub fn sample(&self, frame: usize) -> S {
151 assert!(frame < self.num_frames);
152 unsafe { *self.data.get_unchecked(frame) }
153 }
154
155 #[nonblocking]
159 pub fn samples(&self) -> &[S] {
160 &self.data[..self.num_frames]
161 }
162
163 #[nonblocking]
165 pub fn raw_data(&self) -> &[S] {
166 self.data
167 }
168
169 #[nonblocking]
170 pub fn view(&self) -> AudioBlockMonoView<'_, S> {
171 AudioBlockMonoView::from_slice_limited(
172 self.data,
173 self.num_frames,
174 self.num_frames_allocated,
175 )
176 }
177}
178
179impl<S: Sample> AudioBlock<S> for AudioBlockMonoView<'_, S> {
180 type PlanarView = [S; 0];
181
182 #[nonblocking]
183 fn num_channels(&self) -> u16 {
184 1
185 }
186
187 #[nonblocking]
188 fn num_frames(&self) -> usize {
189 self.num_frames
190 }
191
192 #[nonblocking]
193 fn num_channels_allocated(&self) -> u16 {
194 1
195 }
196
197 #[nonblocking]
198 fn num_frames_allocated(&self) -> usize {
199 self.num_frames_allocated
200 }
201
202 #[nonblocking]
203 fn layout(&self) -> crate::BlockLayout {
204 crate::BlockLayout::Sequential
205 }
206
207 #[nonblocking]
208 fn sample(&self, channel: u16, frame: usize) -> S {
209 assert_eq!(channel, 0, "AudioBlockMonoView only has channel 0");
210 self.sample(frame)
211 }
212
213 #[nonblocking]
214 fn channel_iter(&self, channel: u16) -> impl Iterator<Item = &S> {
215 assert_eq!(channel, 0, "AudioBlockMonoView only has channel 0");
216 self.samples().iter()
217 }
218
219 #[nonblocking]
220 fn channels_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
221 core::iter::once(self.samples().iter())
222 }
223
224 #[nonblocking]
225 fn frame_iter(&self, frame: usize) -> impl Iterator<Item = &S> {
226 assert!(frame < self.num_frames);
227 core::iter::once(&self.data[frame])
228 }
229
230 #[nonblocking]
231 fn frames_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
232 self.data.iter().take(self.num_frames).map(core::iter::once)
233 }
234
235 #[nonblocking]
236 fn as_view(&self) -> impl AudioBlock<S> {
237 self.view()
238 }
239}
240
241impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockMonoView<'_, S> {
242 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
243 writeln!(f, "AudioBlockMonoView {{")?;
244 writeln!(f, " num_frames: {}", self.num_frames)?;
245 writeln!(f, " num_frames_allocated: {}", self.num_frames_allocated)?;
246 writeln!(f, " samples: {:?}", self.samples())?;
247 writeln!(f, "}}")?;
248 Ok(())
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255 use rtsan_standalone::no_sanitize_realtime;
256
257 #[test]
258 fn test_from_slice() {
259 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
260 let block = AudioBlockMonoView::from_slice(&data);
261 assert_eq!(block.num_frames(), 5);
262 assert_eq!(block.num_frames_allocated(), 5);
263 assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
264 }
265
266 #[test]
267 fn test_from_slice_limited() {
268 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
269 let block = AudioBlockMonoView::from_slice_limited(&data, 3, 5);
270 assert_eq!(block.num_frames(), 3);
271 assert_eq!(block.num_frames_allocated(), 5);
272 assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
273 assert_eq!(block.raw_data(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
274 }
275
276 #[test]
277 fn test_from_ptr() {
278 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
279 let block = unsafe { AudioBlockMonoView::from_ptr(data.as_ptr(), 5) };
280 assert_eq!(block.num_frames(), 5);
281 assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
282 }
283
284 #[test]
285 fn test_from_ptr_limited() {
286 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
287 let block = unsafe { AudioBlockMonoView::from_ptr_limited(data.as_ptr(), 3, 5) };
288 assert_eq!(block.num_frames(), 3);
289 assert_eq!(block.num_frames_allocated(), 5);
290 assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
291 }
292
293 #[test]
294 fn test_sample_access() {
295 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
296 let block = AudioBlockMonoView::from_slice(&data);
297 assert_eq!(block.sample(0), 1.0);
298 assert_eq!(block.sample(2), 3.0);
299 assert_eq!(block.sample(4), 5.0);
300 }
301
302 #[test]
303 fn test_samples_iter() {
304 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
305 let block = AudioBlockMonoView::from_slice(&data);
306 assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
307 }
308
309 #[test]
310 fn test_audio_block_trait() {
311 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
312 let block = AudioBlockMonoView::from_slice(&data);
313
314 assert_eq!(block.num_channels(), 1);
315 assert_eq!(block.num_frames(), 5);
316
317 let channel: Vec<f32> = block.channel_iter(0).copied().collect();
319 assert_eq!(channel, vec![1.0, 2.0, 3.0, 4.0, 5.0]);
320
321 let frame: Vec<f32> = block.frame_iter(2).copied().collect();
323 assert_eq!(frame, vec![3.0]);
324 }
325
326 #[test]
327 fn test_view() {
328 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
329 let block = AudioBlockMonoView::from_slice(&data);
330 let view = block.view();
331 assert_eq!(view.num_frames(), 5);
332 assert_eq!(view.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
333 }
334
335 #[test]
336 #[should_panic]
337 #[no_sanitize_realtime]
338 fn test_sample_out_of_bounds() {
339 let data = [1.0, 2.0, 3.0];
340 let block = AudioBlockMonoView::from_slice(&data);
341 let _ = block.sample(10);
342 }
343
344 #[test]
345 #[should_panic]
346 #[no_sanitize_realtime]
347 fn test_wrong_channel() {
348 let data = [1.0, 2.0, 3.0];
349 let block = AudioBlockMonoView::from_slice(&data);
350 let _ = block.channel_iter(1);
351 }
352}