Skip to main content

sva_samples/
buffer.rs

1// Concern: holds one collapse's samples as planar f64 components on a rate and origin | Non-concern: producing them (collapse.rs), measuring one (measure/) | IO: (component, index) -> f64
2
3use std::borrow::Cow;
4use std::ops::Range;
5
6#[derive(Clone, Debug, PartialEq)]
7pub struct Buffer {
8    pub rate: u32,
9    /// The grid sample the first of these stands at; sample 0 is t = 0.
10    pub start: i64,
11    pub width: usize,
12    pub planes: Vec<Vec<f64>>,
13}
14
15impl Buffer {
16    pub fn silence(rate: u32, width: usize, len: usize) -> Buffer {
17        Buffer {
18            rate,
19            start: 0,
20            width,
21            planes: vec![vec![0.0; len]; width],
22        }
23    }
24
25    pub fn mono(rate: u32, samples: Vec<f64>) -> Buffer {
26        Buffer {
27            rate,
28            start: 0,
29            width: 1,
30            planes: vec![samples],
31        }
32    }
33
34    pub fn of_planes(rate: u32, planes: Vec<Vec<f64>>) -> Buffer {
35        let len = planes.iter().map(Vec::len).min().unwrap_or(0);
36        Buffer {
37            rate,
38            start: 0,
39            width: planes.len(),
40            planes: planes
41                .into_iter()
42                .map(|mut p| {
43                    p.truncate(len);
44                    p
45                })
46                .collect(),
47        }
48    }
49
50    pub fn plane(&self, c: usize) -> &[f64] {
51        &self.planes[c]
52    }
53
54    pub fn plane_mut(&mut self, c: usize) -> &mut [f64] {
55        &mut self.planes[c]
56    }
57
58    pub fn slices(&self) -> Vec<&[f64]> {
59        self.planes.iter().map(Vec::as_slice).collect()
60    }
61
62    pub fn len(&self) -> usize {
63        self.planes.iter().map(Vec::len).min().unwrap_or(0)
64    }
65
66    pub fn is_empty(&self) -> bool {
67        self.len() == 0
68    }
69
70    pub fn at(&self, c: usize, i: usize) -> f64 {
71        self.planes[c][i]
72    }
73
74    pub fn origin_secs(&self) -> f64 {
75        self.start as f64 / f64::from(self.rate)
76    }
77
78    /// The grid samples this holds.
79    pub fn extent(&self) -> crate::Extent {
80        crate::Extent::new(self.start, self.start + self.len() as i64)
81    }
82
83    /// These samples over `over`, a node that is zero outside `support`.
84    pub fn over(&self, over: crate::Extent, support: crate::Extent) -> Buffer {
85        let window = crate::Window::of(self, support);
86        let planes = (0..self.width)
87            .map(|c| (over.start..over.end).map(|n| window.at(c, n)).collect())
88            .collect();
89        let mut out = Buffer::of_planes(self.rate, planes);
90        out.start = over.start;
91        out
92    }
93
94    pub fn window(&self, c: usize, range: Range<usize>) -> Cow<'_, [f64]> {
95        let plane = self.plane(c);
96        if range.end <= plane.len() {
97            return Cow::Borrowed(&plane[range]);
98        }
99        let mut out = vec![0.0; range.len()];
100        let held = plane.len().clamp(range.start, range.end) - range.start;
101        out[..held].copy_from_slice(&plane[range.start.min(plane.len())..][..held]);
102        Cow::Owned(out)
103    }
104
105    /// The only narrowing in the crate: a WAV file and the wasm boundary are both f32.
106    pub fn as_f32(&self, c: usize) -> Vec<f32> {
107        self.plane(c).iter().map(|&x| x as f32).collect()
108    }
109}