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