Coverage Report

Created: 2025-12-28 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/adhd/audio_processor/src/buffer/mod.rs
Line
Count
Source
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
use std::ops::Index;
6
use std::ops::IndexMut;
7
8
use zerocopy::AsBytes;
9
use zerocopy::FromBytes;
10
11
use crate::slice_cast::SliceCast;
12
use crate::Sample;
13
use crate::Shape;
14
15
mod debug;
16
17
/// A `MultiBuffer` holds multiple buffers of audio samples or bytes.
18
/// Each buffer typically holds a channel of audio data.
19
pub struct MultiBuffer<T> {
20
    shape: Shape,
21
    // Deinterleaved audio data.
22
    buffer: Vec<T>,
23
}
24
25
impl<T> Index<usize> for MultiBuffer<T> {
26
    type Output = [T];
27
28
0
    fn index(&self, index: usize) -> &Self::Output {
29
0
        if index >= self.shape.channels {
30
0
            panic!("index {} >= {}", index, self.shape.channels);
31
0
        }
32
0
        let start = index * self.shape.frames;
33
0
        &self.buffer[start..start + self.shape.frames]
34
0
    }
35
}
36
37
impl<T> IndexMut<usize> for MultiBuffer<T> {
38
0
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
39
0
        if index >= self.shape.channels {
40
0
            panic!("index {} >= {}", index, self.shape.channels);
41
0
        }
42
0
        let start = index * self.shape.frames;
43
0
        &mut self.buffer[start..start + self.shape.frames]
44
0
    }
45
}
46
47
impl<T> From<Vec<Vec<T>>> for MultiBuffer<T> {
48
    /// Take ownership from `vec` and create a `MultiBuffer`.
49
0
    fn from(vec: Vec<Vec<T>>) -> Self {
50
0
        let min_len = vec.iter().map(|ch| ch.len()).min().unwrap_or(0);
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<alloc::vec::Vec<alloc::vec::Vec<f32>>>>::from::{closure#0}
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<alloc::vec::Vec<alloc::vec::Vec<f32>>>>::from::{closure#0}
51
0
        let max_len = vec.iter().map(|ch| ch.len()).max().unwrap_or(0);
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<alloc::vec::Vec<alloc::vec::Vec<f32>>>>::from::{closure#1}
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<alloc::vec::Vec<alloc::vec::Vec<f32>>>>::from::{closure#1}
52
0
        assert_eq!(min_len, max_len);
53
0
        Self {
54
0
            shape: Shape {
55
0
                channels: vec.len(),
56
0
                frames: min_len,
57
0
            },
58
0
            buffer: vec.into_iter().flatten().collect::<Vec<T>>(),
59
0
        }
60
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<alloc::vec::Vec<alloc::vec::Vec<f32>>>>::from
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<alloc::vec::Vec<alloc::vec::Vec<f32>>>>::from
61
}
62
63
impl<T: Clone> MultiBuffer<T> {
64
0
    pub fn to_vecs(&self) -> Vec<Vec<T>> {
65
0
        (0..self.shape.channels)
66
0
            .map(|ch| self[ch].to_vec())
67
0
            .collect()
68
0
    }
69
}
70
71
impl<'a, T> From<MultiSlice<'a, T>> for MultiBuffer<T>
72
where
73
    T: Sample,
74
{
75
0
    fn from(s: MultiSlice<'a, T>) -> Self {
76
0
        let v: Vec<Vec<T>> = s.iter().map(|ch| ch.to_vec()).collect();
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<_> as core::convert::From<audio_processor::buffer::MultiSlice<_>>>::from::{closure#0}
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<audio_processor::buffer::MultiSlice<f32>>>::from::{closure#0}
77
0
        Self::from(v)
78
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<_> as core::convert::From<audio_processor::buffer::MultiSlice<_>>>::from
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32> as core::convert::From<audio_processor::buffer::MultiSlice<f32>>>::from
79
}
80
81
impl<'a, S: Sample> MultiBuffer<S> {
82
    /// Get a [`MultiSlice`] referencing the `MultiBuffer`
83
0
    pub fn as_multi_slice(&'a mut self) -> MultiSlice<'a, S> {
84
0
        if self.buffer.len() == 0 {
85
            // `Chunks` and `ChunksMut` don't work on empty.
86
0
            MultiSlice::from_slices((0..self.shape.channels).map(|_| &mut [][..]))
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32>>::as_multi_slice::{closure#0}
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32>>::as_multi_slice::{closure#0}
87
        } else {
88
0
            MultiSlice::from_slices(self.buffer.chunks_mut(self.shape.frames))
89
        }
90
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32>>::as_multi_slice
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32>>::as_multi_slice
91
92
    /// Create `shape.channels` buffers with each with `shape.frames` samples.
93
    /// Contents are initialized to `S::default()`.
94
0
    pub fn new(shape: Shape) -> Self {
95
0
        Self::from(vec![vec![S::default(); shape.frames]; shape.channels])
96
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32>>::new
Unexecuted instantiation: <audio_processor::buffer::MultiBuffer<f32>>::new
97
98
    /// Create `shape.channels` buffers with each with `shape.frames` samples.
99
    /// Contents are initialized to `S::EQUILIBRIUM`.
100
0
    pub fn new_equilibrium(shape: Shape) -> Self {
101
0
        Self::from(vec![vec![S::EQUILIBRIUM; shape.frames]; shape.channels])
102
0
    }
103
}
104
105
impl<'a, T: AsBytes> MultiBuffer<T> {
106
    /// Gets the bytes of this buffer.
107
0
    pub fn as_bytes(&'a self) -> &'a [u8] {
108
0
        self.buffer.as_bytes()
109
0
    }
110
}
111
112
impl<'a, T: AsBytes + FromBytes> MultiBuffer<T> {
113
    /// Gets the bytes of this buffer mutably.
114
0
    pub fn as_bytes_mut(&'a mut self) -> &'a mut [u8] {
115
0
        self.buffer.as_bytes_mut()
116
0
    }
117
}
118
119
#[cfg(test)]
120
mod buffer_tests {
121
    use zerocopy::AsBytes;
122
123
    use crate::MultiBuffer;
124
    use crate::Shape;
125
126
    #[test]
127
    fn new() {
128
        let buf = MultiBuffer::<f32>::new(Shape {
129
            channels: 2,
130
            frames: 4,
131
        });
132
        assert_eq!(buf.to_vecs(), [[0., 0., 0., 0.], [0., 0., 0., 0.]]);
133
134
        let buf = MultiBuffer::<u8>::new(Shape {
135
            channels: 2,
136
            frames: 4,
137
        });
138
        assert_eq!(buf.to_vecs(), [[0, 0, 0, 0], [0, 0, 0, 0]]);
139
    }
140
141
    #[test]
142
    fn new_equilibrium() {
143
        let buf = MultiBuffer::<f32>::new_equilibrium(Shape {
144
            channels: 2,
145
            frames: 4,
146
        });
147
        assert_eq!(buf.to_vecs(), [[0., 0., 0., 0.], [0., 0., 0., 0.]]);
148
149
        let buf = MultiBuffer::<u8>::new_equilibrium(Shape {
150
            channels: 2,
151
            frames: 4,
152
        });
153
        assert_eq!(buf.to_vecs(), [[128, 128, 128, 128], [128, 128, 128, 128]]);
154
    }
155
156
    #[test]
157
    fn as_multi_slice() {
158
        let mut buf = MultiBuffer::from(vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]]);
159
        let mut slices = buf.as_multi_slice();
160
        slices.data[0][1] = 0;
161
        slices.data[1][2] = 0;
162
        assert_eq!(buf.to_vecs(), [[1, 0, 3, 4], [5, 6, 0, 8]]);
163
    }
164
165
    #[test]
166
    fn bytes_conversion() {
167
        let mut buf = MultiBuffer::from(vec![vec![2i32], vec![-1]]);
168
        assert_eq!(buf.as_bytes(), [2i32, -1].as_bytes());
169
170
        // Clear LSB and MSB of the first sample. It should become zero.
171
        buf.as_bytes_mut()[0] = 0;
172
        buf.as_bytes_mut()[3] = 0;
173
        assert_eq!(buf.to_vecs(), vec![vec![0], vec![-1]]);
174
    }
175
}
176
177
/// A `MultiSlice` holds multiple references to buffers of audio samples or bytes.
178
/// Each slice typically references a channel of audio data.
179
pub struct MultiSlice<'a, T> {
180
    data: Vec<&'a mut [T]>,
181
}
182
183
impl<'a, T> MultiSlice<'a, T> {
184
    /// Create a `MultiSlice` referencing data owned by `slices`.
185
0
    pub fn from_slices<I>(slices: I) -> Self
186
0
    where
187
0
        I: IntoIterator<Item = &'a mut [T]>,
188
    {
189
0
        Self {
190
0
            data: slices.into_iter().collect(),
191
0
        }
192
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::from_slices::<core::iter::adapters::map::Map<core::ops::range::Range<usize>, <audio_processor::buffer::MultiBuffer<f32>>::as_multi_slice::{closure#0}>>
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::from_slices::<core::slice::iter::ChunksMut<f32>>
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::from_slices::<core::slice::iter::ChunksMut<f32>>
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::from_slices::<core::iter::adapters::map::Map<core::ops::range::Range<usize>, <audio_processor::buffer::MultiBuffer<f32>>::as_multi_slice::{closure#0}>>
193
194
    /// Create a `MultiSlice` referencing data owned by `vecs`.
195
0
    pub fn from_vecs(vecs: &'a mut [Vec<T>]) -> Self {
196
        Self {
197
0
            data: vecs.iter_mut().map(|ch| &mut ch[..]).collect(),
198
        }
199
0
    }
200
201
    /// Create a `MultiSlice` referencing data referenced by `slices`.
202
0
    pub fn from_raw(slices: Vec<&'a mut [T]>) -> Self {
203
0
        Self { data: slices }
204
0
    }
205
206
    /// Consume `self` and return the holded slices.
207
0
    pub fn into_raw(self) -> Vec<&'a mut [T]> {
208
0
        self.data
209
0
    }
210
211
    /// Returns an iterator over the slices.
212
0
    pub fn iter(&self) -> std::slice::Iter<&mut [T]> {
213
0
        self.data.iter()
214
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::iter
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::iter
215
216
    /// Returns an iterator over the mutable slices.
217
0
    pub fn iter_mut(&mut self) -> std::slice::IterMut<&'a mut [T]> {
218
0
        self.data.iter_mut()
219
0
    }
220
221
    /// Returns the number of slices
222
0
    pub fn channels(&self) -> usize {
223
0
        self.data.len()
224
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::channels
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::channels
225
226
    /// Returns the smallest len of the contained slices.
227
0
    pub fn min_len(&self) -> usize {
228
0
        self.data
229
0
            .iter()
230
0
            .map(|buf| buf.len())
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::min_len::{closure#0}
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::min_len::{closure#0}
231
0
            .min()
232
0
            .unwrap_or_default()
233
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::min_len
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::min_len
234
235
    /// Returns a `MultiSlice` referencing `slice[range]` for each contained slice.
236
0
    pub fn indexes(&mut self, range: std::ops::Range<usize>) -> MultiSlice<'_, T> {
237
0
        MultiSlice::from_raw(
238
0
            self.data
239
0
                .iter_mut()
240
0
                .map(|ch| &mut ch[range.clone()])
241
0
                .collect(),
242
        )
243
0
    }
244
245
    /// Consume self and return a `MultiSlice` referencing `slice[range]` for each contained slice.
246
0
    pub fn into_indexes(self, range: std::ops::Range<usize>) -> Self {
247
0
        MultiSlice::from_raw(
248
0
            self.data
249
0
                .into_iter()
250
0
                .map(|ch| &mut ch[range.clone()])
251
0
                .collect(),
252
        )
253
0
    }
254
255
    /// Convert to `MultiSlice<u8>`.
256
    /// This is a "view" conversion, the underlying memory is unchanged.
257
0
    pub fn into_bytes(self) -> MultiSlice<'a, u8>
258
0
    where
259
0
        T: Sample,
260
    {
261
        MultiSlice::<'a, u8> {
262
0
            data: self.data.into_iter().map(|slice| slice.cast()).collect(),
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::into_bytes::{closure#0}
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::into_bytes::{closure#0}
263
        }
264
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::into_bytes
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<f32>>::into_bytes
265
}
266
267
impl<'a, T: Clone> MultiSlice<'a, T> {
268
0
    pub fn clone_from_multi_slice(&mut self, src: &MultiSlice<T>) {
269
0
        for (to, from) in self.iter_mut().zip(src.iter()) {
270
0
            to.clone_from_slice(from)
271
        }
272
0
    }
273
}
274
275
impl<'a> MultiSlice<'a, u8> {
276
    /// Convert the `MultiSlice<u8>` to `MultiSlice<T>`.
277
    /// This is a "view" conversion, the underlying memory is unchanged.
278
    /// Panics if the size or alignment is invalid for `T`.
279
0
    pub fn into_typed<T>(self) -> MultiSlice<'a, T>
280
0
    where
281
0
        T: Sample,
282
    {
283
        MultiSlice::<'a, T> {
284
0
            data: self.data.into_iter().map(|slice| slice.cast()).collect(),
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<u8>>::into_typed::<f32>::{closure#0}
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<u8>>::into_typed::<f32>::{closure#0}
285
        }
286
0
    }
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<u8>>::into_typed::<f32>
Unexecuted instantiation: <audio_processor::buffer::MultiSlice<u8>>::into_typed::<f32>
287
}
288
289
impl<'a, T> Index<usize> for MultiSlice<'a, T> {
290
    type Output = [T];
291
292
0
    fn index(&self, index: usize) -> &Self::Output {
293
0
        self.data[index]
294
0
    }
295
}
296
297
impl<'a, T> IndexMut<usize> for MultiSlice<'a, T> {
298
0
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
299
0
        self.data[index]
300
0
    }
301
}
302
303
#[cfg(test)]
304
mod slice_tests {
305
    use crate::MultiBuffer;
306
    use crate::MultiSlice;
307
308
    #[test]
309
    fn from_vecs() {
310
        let mut vecs = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
311
        let mut slices = MultiSlice::from_vecs(&mut vecs);
312
        slices.data[0][2] = 0;
313
        slices.data[1][3] = 0;
314
        assert_eq!(vecs, [[1, 2, 0, 4], [5, 6, 7, 0]]);
315
    }
316
317
    #[test]
318
    fn slices_convertion() {
319
        let mut a0 = [1, 2, 3, 4];
320
        let mut a1 = [5, 6, 7, 8];
321
        let raw = vec![&mut a0[..], &mut a1[..]];
322
        let mut slices = MultiSlice::from_raw(raw);
323
        slices.data[0][1] = 0;
324
        slices.data[1][2] = 0;
325
        assert_eq!(slices.into_raw(), [[1, 0, 3, 4], [5, 6, 0, 8]]);
326
    }
327
328
    #[test]
329
    fn into_typed() {
330
        let mut buf = MultiBuffer::from(vec![vec![0x11u8, 0, 0, 0x11, 0, 0x22, 0x22, 0]]);
331
        assert_eq!(
332
            buf.as_multi_slice().into_typed::<i32>().into_raw(),
333
            [[0x11000011i32, 0x00222200]]
334
        );
335
        assert_eq!(
336
            buf.as_multi_slice().into_typed::<f32>().into_raw(),
337
            [[1.009744e-28, 3.134604e-39]]
338
        );
339
    }
340
341
    #[test]
342
    fn from_typed() {
343
        let mut buf = MultiBuffer::from(vec![vec![0x11000011i32, 0x00222200]]);
344
        assert_eq!(
345
            buf.as_multi_slice().into_bytes().data,
346
            [[0x11u8, 0, 0, 0x11, 0, 0x22, 0x22, 0]]
347
        );
348
349
        let mut buf: MultiBuffer<f32> = MultiBuffer::from(vec![vec![1.009744e-28, 3.134604e-39]]);
350
        assert_eq!(
351
            buf.as_multi_slice().into_bytes().data,
352
            [[0x11u8, 0, 0, 0x11, 0, 0x22, 0x22, 0]]
353
        )
354
    }
355
356
    #[test]
357
    fn identity() {
358
        let numbers = vec![
359
            vec![-1f32, std::f32::consts::LN_2],
360
            vec![std::f32::consts::PI, f32::MAX],
361
        ];
362
        let mut buf = MultiBuffer::from(numbers.clone());
363
        assert_eq!(
364
            buf.as_multi_slice()
365
                .into_bytes()
366
                .into_typed::<f32>()
367
                .into_raw(),
368
            numbers
369
        );
370
    }
371
372
    #[test]
373
    fn iter() {
374
        let ch0 = vec![1i32, 2, 3];
375
        let ch1 = vec![4i32, 5, 6, 7];
376
        let mut buf = vec![ch0.clone(), ch1.clone()];
377
        let slices = MultiSlice::from_vecs(&mut buf);
378
        let mut it = slices.iter();
379
        assert_eq!(*it.next().unwrap(), ch0);
380
        assert_eq!(*it.next().unwrap(), ch1);
381
        assert!(it.next().is_none());
382
    }
383
384
    #[test]
385
    fn iter_mut() {
386
        let mut buf = vec![vec![1i32, 2, 3], vec![4i32, 5, 6, 7]];
387
        let mut slices = MultiSlice::from_vecs(&mut buf);
388
        let mut it = slices.iter_mut();
389
390
        let ch0 = it.next().unwrap();
391
        assert_eq!(*ch0, [1, 2, 3]);
392
        ch0[0] = 0;
393
394
        let ch1 = it.next().unwrap();
395
        assert_eq!(*ch1, [4, 5, 6, 7]);
396
        ch1[1] = 0;
397
398
        assert!(it.next().is_none());
399
400
        assert_eq!(buf, vec![vec![0, 2, 3], vec![4, 0, 6, 7]]);
401
    }
402
403
    #[test]
404
    fn min_len() {
405
        let mut buf = vec![vec![1, 2, 3, 4], vec![5, 6, 7], vec![8, 9, 10, 11, 12]];
406
        assert_eq!(MultiSlice::from_vecs(&mut buf).min_len(), 3);
407
    }
408
409
    #[test]
410
    fn indexes() {
411
        let mut buf = MultiBuffer::from(vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]]);
412
413
        assert_eq!(
414
            buf.as_multi_slice().indexes(0..2).into_raw(),
415
            [[1, 2], [5, 6]]
416
        );
417
        assert_eq!(
418
            buf.as_multi_slice().indexes(2..4).into_raw(),
419
            [[3, 4], [7, 8]]
420
        );
421
422
        for ch in buf.as_multi_slice().indexes(1..3).iter_mut() {
423
            for x in ch.iter_mut() {
424
                *x = 0;
425
            }
426
        }
427
        assert_eq!(buf.to_vecs(), [[1, 0, 0, 4], [5, 0, 0, 8]]);
428
    }
429
430
    #[test]
431
    fn into_indexes() {
432
        let mut buf = MultiBuffer::from(vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]]);
433
434
        assert_eq!(
435
            buf.as_multi_slice().into_indexes(0..2).into_raw(),
436
            [[1, 2], [5, 6]]
437
        );
438
        assert_eq!(
439
            buf.as_multi_slice().into_indexes(2..4).into_raw(),
440
            [[3, 4], [7, 8]]
441
        );
442
443
        for ch in buf.as_multi_slice().into_indexes(1..3).iter_mut() {
444
            for x in ch.iter_mut() {
445
                *x = 0;
446
            }
447
        }
448
        assert_eq!(buf.to_vecs(), [[1, 0, 0, 4], [5, 0, 0, 8]]);
449
    }
450
451
    #[test]
452
    fn index() {
453
        let mut buf = MultiBuffer::from(vec![vec![1, 2], vec![3, 4]]);
454
        let mut slice = buf.as_multi_slice();
455
456
        assert_eq!(slice[0], [1, 2]);
457
        assert_eq!(slice[1], [3, 4]);
458
        slice[0][1] = 5;
459
        assert_eq!(slice[0], [1, 5]);
460
    }
461
}