1#![doc = include_str!("../README.md")]
2#![no_std]
3
4mod traits;
6pub use traits::{Adapter, AdapterMut};
7
8pub mod stats;
10
11mod iterators;
13
14pub use iterators::AdapterIterators;
15
16#[cfg(any(test, feature = "test-utils"))]
17pub mod tests {
18 extern crate alloc;
19
20 use crate::{Adapter, AdapterMut};
21 use alloc::vec;
22 use alloc::vec::Vec;
23 use num_traits::{NumCast, float::FloatCore};
24
25 pub struct MinimalAdapter<U> {
28 buf: Vec<U>,
29 frames: usize,
30 channels: usize,
31 }
32
33 impl<T> MinimalAdapter<T>
34 where
35 T: Clone,
36 {
37 pub fn new_from_vec(buf: Vec<T>, channels: usize, frames: usize) -> Self {
38 Self {
39 buf,
40 frames,
41 channels,
42 }
43 }
44 }
45
46 unsafe impl<T> Adapter<T> for MinimalAdapter<T>
47 where
48 T: Clone,
49 {
50 unsafe fn read_sample_unchecked(&self, channel: usize, frame: usize) -> T {
51 let index = frame * self.channels + channel;
52 unsafe { self.buf.get_unchecked(index).clone() }
53 }
54
55 fn channels(&self) -> usize {
56 self.channels
57 }
58
59 fn frames(&self) -> usize {
60 self.frames
61 }
62 }
63
64 unsafe impl<T> AdapterMut<T> for MinimalAdapter<T>
65 where
66 T: Clone,
67 {
68 unsafe fn write_sample_unchecked(
69 &mut self,
70 channel: usize,
71 frame: usize,
72 value: &T,
73 ) -> bool {
74 let index = frame * self.channels + channel;
75 unsafe {
76 *self.buf.get_unchecked_mut(index) = value.clone();
77 }
78 false
79 }
80 }
81
82 pub fn test_adapter_mut_methods<T>(buffer: &mut dyn AdapterMut<T>)
88 where
89 T: Default + Clone + PartialEq + core::fmt::Debug + From<usize> + Into<usize>,
90 {
91 assert!(
93 buffer.channels() >= 2,
94 "Buffer must have at least 2 channels for this test"
95 );
96 assert!(
97 buffer.frames() >= 4,
98 "Buffer must have at least 4 frames for this test"
99 );
100
101 buffer.fill_with(&T::from(42));
103 assert_eq!(buffer.read_sample(0, 0), Some(T::from(42)));
104 assert_eq!(buffer.read_sample(1, 1), Some(T::from(42)));
105 assert_eq!(buffer.read_sample(buffer.channels(), 0), None);
107 assert_eq!(buffer.read_sample(0, buffer.frames()), None);
108
109 assert_eq!(buffer.write_sample(0, 0, &T::from(100)), Some(false));
111 assert_eq!(buffer.read_sample(0, 0), Some(T::from(100)));
112 assert_eq!(
114 buffer.write_sample(buffer.channels(), 0, &T::from(101)),
115 None
116 );
117 assert_eq!(buffer.write_sample(0, buffer.frames(), &T::from(102)), None);
118
119 buffer.fill_channel_with(1, &T::from(99)).unwrap();
121 assert_eq!(buffer.read_sample(1, 0), Some(T::from(99)));
122 assert_eq!(buffer.read_sample(1, 1), Some(T::from(99)));
123 assert_eq!(buffer.read_sample(0, 0), Some(T::from(100))); buffer.fill_frame_with(2, &T::from(88)).unwrap();
127 assert_eq!(buffer.read_sample(0, 2), Some(T::from(88)));
128 assert_eq!(buffer.read_sample(1, 2), Some(T::from(88)));
129 assert_eq!(buffer.read_sample(1, 1), Some(T::from(99))); buffer.fill_frames_with(0, 2, &T::from(77)).unwrap();
133 assert_eq!(buffer.read_sample(0, 0), Some(T::from(77)));
134 assert_eq!(buffer.read_sample(1, 1), Some(T::from(77)));
135 assert_eq!(buffer.read_sample(0, 2), Some(T::from(88))); for c in 0..buffer.channels() {
139 for f in 0..buffer.frames() {
140 buffer.write_sample(c, f, &T::from(c * 10 + f));
141 }
142 }
143 let mut slice_ch = vec![T::default(); 2];
147 let copied = buffer.copy_from_channel_to_slice(1, 1, &mut slice_ch);
148 assert_eq!(copied, 2);
149 assert_eq!(slice_ch, vec![T::from(11), T::from(12)]);
150
151 let mut slice_fr = vec![T::default(); 2];
153 let copied = buffer.copy_from_frame_to_slice(2, 0, &mut slice_fr);
154 assert_eq!(copied, 2);
155 assert_eq!(slice_fr, vec![T::from(2), T::from(12)]);
156
157 let slice_to_ch = vec![T::from(101), T::from(102)];
159 let (copied, clipped) = buffer.copy_from_slice_to_channel(0, 2, &slice_to_ch);
160 assert_eq!(copied, 2);
161 assert_eq!(clipped, 0);
162 assert_eq!(buffer.read_sample(0, 2), Some(T::from(101)));
163 assert_eq!(buffer.read_sample(0, 3), Some(T::from(102)));
164
165 let slice_to_fr = vec![T::from(201)];
167 let (copied, clipped) = buffer.copy_from_slice_to_frame(3, 1, &slice_to_fr);
168 assert_eq!(copied, 1);
169 assert_eq!(clipped, 0);
170 assert_eq!(buffer.read_sample(1, 3), Some(T::from(201)));
171
172 assert!(buffer.copy_sample_within(0, 0, 1, 1));
175 assert_eq!(buffer.read_sample(1, 1), Some(T::from(0)));
177
178 assert!(buffer.swap_samples(0, 1, 1, 0));
181 assert_eq!(buffer.read_sample(0, 1), Some(T::from(10)));
183 assert_eq!(buffer.read_sample(1, 0), Some(T::from(1)));
184
185 buffer.copy_frames_within(0, 1, 2).unwrap();
188 assert_eq!(buffer.read_sample(0, 1), Some(T::from(0)));
190 assert_eq!(buffer.read_sample(1, 1), Some(T::from(1)));
191 assert_eq!(buffer.read_sample(0, 2), Some(T::from(10)));
192 assert_eq!(buffer.read_sample(1, 2), Some(T::from(0)));
193 }
194
195 pub fn test_float_adapter_mut_methods<T>(buffer: &mut dyn AdapterMut<T>)
201 where
202 T: FloatCore + NumCast + Default + Clone + PartialEq + core::fmt::Debug,
203 {
204 let assert_approx_eq = |a: T, b: T, message: &str| {
206 let epsilon = NumCast::from(1e-6f64).unwrap();
207 assert!(
208 (a - b).abs() < epsilon,
209 "{} (left: {:?}, right: {:?})",
210 message,
211 a,
212 b
213 );
214 };
215
216 let assert_slice_approx_eq = |a: &[T], b: &[T], message: &str| {
217 assert_eq!(a.len(), b.len(), "{} (slice lengths differ)", message);
218 for (i, (val_a, val_b)) in a.iter().zip(b.iter()).enumerate() {
219 let msg = alloc::format!("{} (element {})", message, i);
220 assert_approx_eq(*val_a, *val_b, &msg);
221 }
222 };
223
224 assert!(
226 buffer.channels() >= 2,
227 "Buffer must have at least 2 channels for this test"
228 );
229 assert!(
230 buffer.frames() >= 4,
231 "Buffer must have at least 4 frames for this test"
232 );
233
234 buffer.fill_with(&NumCast::from(0.42f64).unwrap());
236 assert_approx_eq(
237 buffer.read_sample(0, 0).unwrap(),
238 NumCast::from(0.42f64).unwrap(),
239 "fill_with value mismatch",
240 );
241 assert_approx_eq(
242 buffer.read_sample(1, 1).unwrap(),
243 NumCast::from(0.42f64).unwrap(),
244 "fill_with value mismatch",
245 );
246 assert_eq!(buffer.read_sample(buffer.channels(), 0), None);
248 assert_eq!(buffer.read_sample(0, buffer.frames()), None);
249
250 assert_eq!(
252 buffer.write_sample(0, 0, &NumCast::from(0.1f64).unwrap()),
253 Some(false)
254 );
255 assert_approx_eq(
256 buffer.read_sample(0, 0).unwrap(),
257 NumCast::from(0.1f64).unwrap(),
258 "write_sample value mismatch",
259 );
260 assert_eq!(
262 buffer.write_sample(buffer.channels(), 0, &NumCast::from(0.101f64).unwrap()),
263 None
264 );
265 assert_eq!(
266 buffer.write_sample(0, buffer.frames(), &NumCast::from(0.102f64).unwrap()),
267 None
268 );
269
270 buffer
272 .fill_channel_with(1, &NumCast::from(0.99f64).unwrap())
273 .unwrap();
274 assert_approx_eq(
275 buffer.read_sample(1, 0).unwrap(),
276 NumCast::from(0.99f64).unwrap(),
277 "fill_channel_with value mismatch",
278 );
279 assert_approx_eq(
280 buffer.read_sample(1, 1).unwrap(),
281 NumCast::from(0.99f64).unwrap(),
282 "fill_channel_with value mismatch",
283 );
284 assert_approx_eq(
285 buffer.read_sample(0, 0).unwrap(),
286 NumCast::from(0.1f64).unwrap(),
287 "Other channel should be unaffected",
288 ); buffer
292 .fill_frame_with(2, &NumCast::from(0.88f64).unwrap())
293 .unwrap();
294 assert_approx_eq(
295 buffer.read_sample(0, 2).unwrap(),
296 NumCast::from(0.88f64).unwrap(),
297 "fill_frame_with value mismatch",
298 );
299 assert_approx_eq(
300 buffer.read_sample(1, 2).unwrap(),
301 NumCast::from(0.88f64).unwrap(),
302 "fill_frame_with value mismatch",
303 );
304 assert_approx_eq(
305 buffer.read_sample(1, 1).unwrap(),
306 NumCast::from(0.99f64).unwrap(),
307 "Other frame should be unaffected",
308 ); buffer
312 .fill_frames_with(0, 2, &NumCast::from(0.77f64).unwrap())
313 .unwrap();
314 assert_approx_eq(
315 buffer.read_sample(0, 0).unwrap(),
316 NumCast::from(0.77f64).unwrap(),
317 "fill_frames_with value mismatch",
318 );
319 assert_approx_eq(
320 buffer.read_sample(1, 1).unwrap(),
321 NumCast::from(0.77f64).unwrap(),
322 "fill_frames_with value mismatch",
323 );
324 assert_approx_eq(
325 buffer.read_sample(0, 2).unwrap(),
326 NumCast::from(0.88f64).unwrap(),
327 "Unaffected frame should be unaffected",
328 ); for c in 0..buffer.channels() {
332 for f in 0..buffer.frames() {
333 buffer.write_sample(c, f, &NumCast::from((c * 10 + f) as f64 / 100.0).unwrap());
334 }
335 }
336 let mut slice_ch = vec![T::default(); 2];
340 let copied = buffer.copy_from_channel_to_slice(1, 1, &mut slice_ch);
341 assert_eq!(copied, 2);
342 assert_slice_approx_eq(
343 &slice_ch,
344 &[
345 NumCast::from(0.11f64).unwrap(),
346 NumCast::from(0.12f64).unwrap(),
347 ],
348 "copy_from_channel_to_slice mismatch",
349 );
350
351 let mut slice_fr = vec![T::default(); 2];
353 let copied = buffer.copy_from_frame_to_slice(2, 0, &mut slice_fr);
354 assert_eq!(copied, 2);
355 assert_slice_approx_eq(
356 &slice_fr,
357 &[
358 NumCast::from(0.02f64).unwrap(),
359 NumCast::from(0.12f64).unwrap(),
360 ],
361 "copy_from_frame_to_slice mismatch",
362 );
363
364 assert!(buffer.copy_sample_within(0, 0, 1, 1));
367 assert_approx_eq(
369 buffer.read_sample(1, 1).unwrap(),
370 NumCast::from(0.0f64).unwrap(),
371 "copy_sample_within value mismatch",
372 );
373
374 assert!(buffer.swap_samples(0, 1, 1, 0));
377 assert_approx_eq(
379 buffer.read_sample(0, 1).unwrap(),
380 NumCast::from(0.10f64).unwrap(),
381 "swap_samples value mismatch on sample A",
382 );
383 assert_approx_eq(
384 buffer.read_sample(1, 0).unwrap(),
385 NumCast::from(0.01f64).unwrap(),
386 "swap_samples value mismatch on sample B",
387 );
388 }
389
390 #[test]
391 fn test_vec_adapter() {
392 let mut buffer = MinimalAdapter::new_from_vec(vec![0; 8], 2, 4);
393 test_adapter_mut_methods(&mut buffer);
394 }
395}