1use rtsan_standalone::nonblocking;
2
3use crate::{AudioBlock, AudioBlockMut, BlockLayout, Sample};
4
5pub trait Ops<S: Sample> {
6 fn copy_from_block(&mut self, block: &impl AudioBlock<S>);
8 fn copy_from_block_resize(&mut self, block: &impl AudioBlock<S>);
11 fn for_each(&mut self, f: impl FnMut(&mut S));
13 fn for_each_including_non_visible(&mut self, f: impl FnMut(&mut S));
18 fn enumerate(&mut self, f: impl FnMut(u16, usize, &mut S));
21 fn enumerate_including_non_visible(&mut self, f: impl FnMut(u16, usize, &mut S));
28 fn fill_with(&mut self, sample: S);
30 fn clear(&mut self);
32}
33
34impl<S: Sample, B: AudioBlockMut<S>> Ops<S> for B {
35 #[nonblocking]
36 fn copy_from_block(&mut self, block: &impl AudioBlock<S>) {
37 assert_eq!(block.num_channels(), self.num_channels());
38 assert_eq!(block.num_frames(), self.num_frames());
39 for ch in 0..self.num_channels() {
40 for (sample_mut, sample) in self.channel_mut(ch).zip(block.channel(ch)) {
41 *sample_mut = *sample;
42 }
43 }
44 }
45
46 #[nonblocking]
47 fn copy_from_block_resize(&mut self, block: &impl AudioBlock<S>) {
48 assert!(block.num_channels() <= self.num_channels_allocated());
49 assert!(block.num_frames() <= self.num_frames_allocated());
50 self.resize(block.num_channels(), block.num_frames());
51
52 for ch in 0..self.num_channels() {
53 for (sample_mut, sample) in self.channel_mut(ch).zip(block.channel(ch)) {
54 *sample_mut = *sample;
55 }
56 }
57 }
58
59 #[nonblocking]
60 fn for_each(&mut self, mut f: impl FnMut(&mut S)) {
61 if self.num_channels() < 8 {
63 for channel in self.channels_mut() {
64 channel.for_each(&mut f);
65 }
66 } else {
67 match self.layout() {
68 BlockLayout::Sequential | BlockLayout::Stacked => {
69 for channel in self.channels_mut() {
70 channel.for_each(&mut f);
71 }
72 }
73 BlockLayout::Interleaved => {
74 for frame in 0..self.num_frames() {
75 self.frame_mut(frame).for_each(&mut f);
76 }
77 }
78 }
79 }
80 }
81
82 #[nonblocking]
83 fn for_each_including_non_visible(&mut self, mut f: impl FnMut(&mut S)) {
84 match self.layout() {
85 BlockLayout::Sequential => {
86 self.raw_data_mut(None).iter_mut().for_each(&mut f);
87 }
88 BlockLayout::Interleaved => {
89 self.raw_data_mut(None).iter_mut().for_each(&mut f);
90 }
91 BlockLayout::Stacked => {
92 for ch in 0..self.num_channels() {
93 self.raw_data_mut(Some(ch)).iter_mut().for_each(&mut f);
94 }
95 }
96 }
97 }
98
99 #[nonblocking]
100 fn enumerate(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
101 if self.num_channels() < 8 {
103 for ch in 0..self.num_channels() {
104 self.channel_mut(ch)
105 .enumerate()
106 .for_each(|(frame, sample)| f(ch, frame, sample));
107 }
108 } else {
109 match self.layout() {
110 BlockLayout::Sequential | BlockLayout::Stacked => {
111 for ch in 0..self.num_channels() {
112 self.channel_mut(ch)
113 .enumerate()
114 .for_each(|(frame, sample)| f(ch, frame, sample));
115 }
116 }
117 BlockLayout::Interleaved => {
118 for frame in 0..self.num_frames() {
119 self.frame_mut(frame)
120 .enumerate()
121 .for_each(|(ch, sample)| f(ch as u16, frame, sample));
122 }
123 }
124 }
125 }
126 }
127
128 #[nonblocking]
129 fn enumerate_including_non_visible(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
130 match self.layout() {
131 BlockLayout::Sequential => {
132 let num_frames = self.num_frames_allocated();
133 self.raw_data_mut(None)
134 .iter_mut()
135 .enumerate()
136 .for_each(|(i, sample)| {
137 let channel = i / num_frames;
138 let frame = i % num_frames;
139 f(channel as u16, frame, sample)
140 });
141 }
142 BlockLayout::Interleaved => {
143 let num_frames = self.num_frames_allocated();
144 self.raw_data_mut(None)
145 .iter_mut()
146 .enumerate()
147 .for_each(|(i, sample)| {
148 let channel = i % num_frames;
149 let frame = i / num_frames;
150 f(channel as u16, frame, sample)
151 });
152 }
153 BlockLayout::Stacked => {
154 for ch in 0..self.num_channels() {
155 self.raw_data_mut(Some(ch))
156 .iter_mut()
157 .enumerate()
158 .for_each(|(frame, sample)| f(ch, frame, sample));
159 }
160 }
161 }
162 }
163
164 #[nonblocking]
165 fn fill_with(&mut self, sample: S) {
166 self.for_each_including_non_visible(|v| *v = sample);
167 }
168
169 #[nonblocking]
170 fn clear(&mut self) {
171 self.fill_with(S::default());
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use rtsan_standalone::no_sanitize_realtime;
178
179 use crate::{
180 interleaved::InterleavedViewMut,
181 sequential::{SequentialView, SequentialViewMut},
182 stacked::StackedViewMut,
183 };
184
185 use super::*;
186
187 #[test]
188 fn test_copy_from() {
189 let mut data = [0.0; 15];
190 let mut block = InterleavedViewMut::from_slice(&mut data, 3, 5);
191 let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
192 block.copy_from_block_resize(&view);
193
194 assert_eq!(block.num_channels(), 2);
195 assert_eq!(block.num_frames(), 4);
196 assert_eq!(block.num_channels_allocated(), 3);
197 assert_eq!(block.num_frames_allocated(), 5);
198
199 assert_eq!(
200 block.channel(0).copied().collect::<Vec<_>>(),
201 vec![0.0, 1.0, 2.0, 3.0]
202 );
203 assert_eq!(
204 block.channel(1).copied().collect::<Vec<_>>(),
205 vec![4.0, 5.0, 6.0, 7.0]
206 );
207 }
208
209 #[test]
210 fn test_copy_from_exact() {
211 let mut data = [0.0; 8];
212 let mut block = InterleavedViewMut::from_slice(&mut data, 2, 4);
213 let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
214 block.copy_from_block(&view);
215
216 assert_eq!(block.num_channels(), 2);
217 assert_eq!(block.num_frames(), 4);
218 assert_eq!(block.num_channels_allocated(), 2);
219 assert_eq!(block.num_frames_allocated(), 4);
220
221 assert_eq!(
222 block.channel(0).copied().collect::<Vec<_>>(),
223 vec![0.0, 1.0, 2.0, 3.0]
224 );
225 assert_eq!(
226 block.channel(1).copied().collect::<Vec<_>>(),
227 vec![4.0, 5.0, 6.0, 7.0]
228 );
229 }
230
231 #[test]
232 #[should_panic]
233 #[no_sanitize_realtime]
234 fn test_copy_data_wrong_channels() {
235 let mut data = [0.0; 5];
236 let mut block = InterleavedViewMut::from_slice(&mut data, 1, 5);
237 let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
238 block.copy_from_block_resize(&view);
239 }
240
241 #[test]
242 #[should_panic]
243 #[no_sanitize_realtime]
244 fn test_copy_data_wrong_frames() {
245 let mut data = [0.0; 9];
246 let mut block = InterleavedViewMut::from_slice(&mut data, 3, 3);
247 let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
248 block.copy_from_block(&view);
249 }
250
251 #[test]
252 #[should_panic]
253 #[no_sanitize_realtime]
254 fn test_copy_data_exact_wrong_channels() {
255 let mut data = [0.0; 12];
256 let mut block = InterleavedViewMut::from_slice(&mut data, 3, 4);
257 let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
258 block.copy_from_block(&view);
259 }
260
261 #[test]
262 #[should_panic]
263 #[no_sanitize_realtime]
264 fn test_copy_data_exact_wrong_frames() {
265 let mut data = [0.0; 10];
266 let mut block = InterleavedViewMut::from_slice(&mut data, 2, 5);
267 let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
268 block.copy_from_block(&view);
269 }
270
271 #[test]
272 fn test_for_each() {
273 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
274 let mut block = SequentialViewMut::from_slice(&mut data, 2, 4);
275
276 let mut i = 0;
277 let mut c_exp = 0;
278 let mut f_exp = 0;
279 block.enumerate_including_non_visible(|c, f, v| {
280 assert_eq!(c, c_exp);
281 assert_eq!(f, f_exp);
282 assert_eq!(*v, i as f32);
283 if f_exp == 3 {
284 c_exp = (c_exp + 1) % 4;
285 }
286 f_exp = (f_exp + 1) % 4;
287 i += 1;
288 });
289
290 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
291 let mut block = InterleavedViewMut::from_slice(&mut data, 2, 4);
292
293 let mut i = 0;
294 let mut f_exp = 0;
295 let mut c_exp = 0;
296 block.enumerate_including_non_visible(|c, f, v| {
297 assert_eq!(c, c_exp);
298 assert_eq!(f, f_exp);
299 assert_eq!(*v, i as f32);
300 if c_exp == 3 {
301 f_exp = (f_exp + 1) % 4;
302 }
303 c_exp = (c_exp + 1) % 4;
304 i += 1;
305 });
306
307 let mut data = [[0.0, 1.0, 2.0, 3.0], [4.0, 5.0, 6.0, 7.0]];
308 let mut block = StackedViewMut::from_slice(&mut data);
309
310 let mut i = 0;
311 let mut c_exp = 0;
312 let mut f_exp = 0;
313 block.enumerate_including_non_visible(|c, f, v| {
314 assert_eq!(c, c_exp);
315 assert_eq!(f, f_exp);
316 assert_eq!(*v, i as f32);
317 if f_exp == 3 {
318 c_exp = (c_exp + 1) % 4;
319 }
320 f_exp = (f_exp + 1) % 4;
321 i += 1;
322 });
323 }
324
325 #[test]
326 fn test_clear() {
327 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
328 let mut block = SequentialViewMut::from_slice(&mut data, 2, 4);
329
330 block.fill_with(1.0);
331
332 assert_eq!(
333 block.channel(0).copied().collect::<Vec<_>>(),
334 vec![1.0, 1.0, 1.0, 1.0]
335 );
336 assert_eq!(
337 block.channel(1).copied().collect::<Vec<_>>(),
338 vec![1.0, 1.0, 1.0, 1.0]
339 );
340
341 block.clear();
342
343 assert_eq!(
344 block.channel(0).copied().collect::<Vec<_>>(),
345 vec![0.0, 0.0, 0.0, 0.0]
346 );
347 assert_eq!(
348 block.channel(1).copied().collect::<Vec<_>>(),
349 vec![0.0, 0.0, 0.0, 0.0]
350 );
351 }
352}