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    pub origin_secs: f64,
10    pub width: usize,
11    pub planes: Vec<Vec<f64>>,
12}
13
14impl Buffer {
15    pub fn silence(rate: u32, width: usize, len: usize) -> Buffer {
16        Buffer {
17            rate,
18            origin_secs: 0.0,
19            width,
20            planes: vec![vec![0.0; len]; width],
21        }
22    }
23
24    pub fn mono(rate: u32, samples: Vec<f64>) -> Buffer {
25        Buffer {
26            rate,
27            origin_secs: 0.0,
28            width: 1,
29            planes: vec![samples],
30        }
31    }
32
33    pub fn of_planes(rate: u32, planes: Vec<Vec<f64>>) -> Buffer {
34        let len = planes.iter().map(Vec::len).min().unwrap_or(0);
35        Buffer {
36            rate,
37            origin_secs: 0.0,
38            width: planes.len(),
39            planes: planes
40                .into_iter()
41                .map(|mut p| {
42                    p.truncate(len);
43                    p
44                })
45                .collect(),
46        }
47    }
48
49    pub fn plane(&self, c: usize) -> &[f64] {
50        &self.planes[c]
51    }
52
53    pub fn plane_mut(&mut self, c: usize) -> &mut [f64] {
54        &mut self.planes[c]
55    }
56
57    pub fn len(&self) -> usize {
58        self.planes.iter().map(Vec::len).min().unwrap_or(0)
59    }
60
61    pub fn is_empty(&self) -> bool {
62        self.len() == 0
63    }
64
65    pub fn at(&self, c: usize, i: usize) -> f64 {
66        self.planes[c][i]
67    }
68
69    /// The samples `over` covers, nearest grid point at each end, held to what this holds.
70    pub fn span_of(&self, over: crate::Horizon) -> Range<usize> {
71        let rate = f64::from(self.rate);
72        let at = |secs: f64| {
73            (((secs - self.origin_secs) * rate).round().max(0.0) as usize).min(self.len())
74        };
75        let start = at(over.start_secs);
76        let end = match over.end_secs.is_finite() {
77            true => at(over.end_secs).max(start),
78            false => self.len(),
79        };
80        start..end
81    }
82
83    pub fn window(&self, c: usize, range: Range<usize>) -> Cow<'_, [f64]> {
84        let plane = self.plane(c);
85        if range.end <= plane.len() {
86            return Cow::Borrowed(&plane[range]);
87        }
88        let mut out = vec![0.0; range.len()];
89        let held = plane.len().clamp(range.start, range.end) - range.start;
90        out[..held].copy_from_slice(&plane[range.start.min(plane.len())..][..held]);
91        Cow::Owned(out)
92    }
93
94    /// The only narrowing in the crate: a WAV file and the wasm boundary are both f32.
95    pub fn as_f32(&self, c: usize) -> Vec<f32> {
96        self.plane(c).iter().map(|&x| x as f32).collect()
97    }
98}