1use std::borrow::Cow;
4use std::ops::Range;
5
6use crate::grid::Extent;
7
8#[derive(Clone, Debug, PartialEq)]
9pub struct Buffer {
10 pub rate: u32,
11 pub start: i64,
13 pub planes: Vec<Vec<f64>>,
14}
15
16impl Buffer {
17 pub fn silence(rate: u32, width: usize, len: usize) -> Buffer {
18 Buffer {
19 rate,
20 start: 0,
21 planes: vec![vec![0.0; len]; width],
22 }
23 }
24
25 pub fn empty(rate: u32, width: usize, capacity: usize, start: i64) -> Buffer {
26 Buffer {
27 rate,
28 start,
29 planes: (0..width.max(1))
30 .map(|_| Vec::with_capacity(capacity))
31 .collect(),
32 }
33 }
34
35 pub fn mono(rate: u32, samples: Vec<f64>) -> Buffer {
36 Buffer {
37 rate,
38 start: 0,
39 planes: vec![samples],
40 }
41 }
42
43 pub fn of_planes(rate: u32, planes: Vec<Vec<f64>>) -> Buffer {
44 let len = planes.iter().map(Vec::len).min().unwrap_or(0);
45 Buffer {
46 rate,
47 start: 0,
48 planes: planes
49 .into_iter()
50 .map(|mut p| {
51 p.truncate(len);
52 p
53 })
54 .collect(),
55 }
56 }
57
58 pub fn width(&self) -> usize {
59 self.planes.len()
60 }
61
62 pub fn plane(&self, c: usize) -> &[f64] {
63 &self.planes[c]
64 }
65
66 pub fn plane_mut(&mut self, c: usize) -> &mut [f64] {
67 &mut self.planes[c]
68 }
69
70 pub fn slices(&self) -> Vec<&[f64]> {
71 self.planes.iter().map(Vec::as_slice).collect()
72 }
73
74 pub fn len(&self) -> usize {
75 self.planes.iter().map(Vec::len).min().unwrap_or(0)
76 }
77
78 pub fn is_empty(&self) -> bool {
79 self.len() == 0
80 }
81
82 pub fn at(&self, c: usize, i: usize) -> f64 {
83 self.planes[c][i]
84 }
85
86 pub fn origin_secs(&self) -> f64 {
87 self.start as f64 / f64::from(self.rate)
88 }
89
90 pub fn end(&self) -> i64 {
91 self.start + self.len() as i64
92 }
93
94 pub fn extent(&self) -> Extent {
95 Extent::new(self.start, self.end())
96 }
97
98 pub fn capacity(&self) -> usize {
99 self.planes[0].capacity()
100 }
101
102 pub fn push(&mut self, c: usize, value: f64) {
103 self.planes[c].push(value);
104 }
105
106 pub fn forget_before(&mut self, from: i64) {
107 let gone = (from - self.start).clamp(0, self.len() as i64) as usize;
108 if gone == 0 {
109 return;
110 }
111 for plane in &mut self.planes {
112 plane.drain(..gone);
113 }
114 self.start += gone as i64;
115 }
116
117 pub fn within(&self, support: Extent) -> SampleView<'_> {
119 SampleView {
120 planes: &self.planes,
121 base: self.start,
122 support,
123 period: None,
124 offset: 0,
125 }
126 }
127
128 pub fn over(&self, over: Extent, support: Extent) -> Buffer {
130 let view = self.within(support);
131 let planes = match !over.is_empty() && self.extent().intersect(over) == over {
132 true => self
133 .planes
134 .iter()
135 .map(|p| p[(over.start - self.start) as usize..][..over.len()].to_vec())
136 .collect(),
137 false => (0..self.width())
138 .map(|c| (over.start..over.end).map(|n| view.at(c, n)).collect())
139 .collect(),
140 };
141 let mut out = Buffer::of_planes(self.rate, planes);
142 out.start = over.start;
143 out
144 }
145
146 pub fn plane_slice(&self, c: usize, range: Range<usize>) -> Cow<'_, [f64]> {
147 let plane = self.plane(c);
148 if range.end <= plane.len() {
149 return Cow::Borrowed(&plane[range]);
150 }
151 let mut out = vec![0.0; range.len()];
152 let held = plane.len().clamp(range.start, range.end) - range.start;
153 out[..held].copy_from_slice(&plane[range.start.min(plane.len())..][..held]);
154 Cow::Owned(out)
155 }
156
157 pub fn as_f32(&self, c: usize) -> Vec<f32> {
159 self.plane(c).iter().map(|&x| x as f32).collect()
160 }
161}
162
163#[derive(Clone, Copy, Debug)]
166pub struct SampleView<'a> {
167 planes: &'a [Vec<f64>],
168 base: i64,
169 support: Extent,
170 period: Option<i64>,
171 offset: i64,
173}
174
175impl<'a> SampleView<'a> {
176 pub fn folded(self, period: Option<i64>) -> SampleView<'a> {
177 SampleView { period, ..self }
178 }
179
180 pub fn shifted(self, by: i64) -> SampleView<'a> {
181 SampleView {
182 offset: self.offset + by,
183 ..self
184 }
185 }
186
187 fn fold(&self, k: i64) -> i64 {
188 let k = k.saturating_add(self.offset);
189 match self.period {
190 Some(n) if self.support.contains(k) => k.rem_euclid(n),
191 _ => k,
192 }
193 }
194
195 pub fn get(&self, c: usize, k: i64) -> Option<f64> {
197 let k = self.fold(k);
198 let plane = &self.planes[c];
199 let held = k
200 .checked_sub(self.base)
201 .and_then(|at| usize::try_from(at).ok())
202 .and_then(|at| plane.get(at));
203 match held {
204 Some(v) => Some(*v),
205 None => (!self.support.contains(k)).then_some(0.0),
206 }
207 }
208
209 pub fn run(&self, c: usize, k: i64, len: usize) -> Option<&'a [f64]> {
211 if self.period.is_some() {
212 return None;
213 }
214 let at = usize::try_from(k.checked_add(self.offset)?.checked_sub(self.base)?).ok()?;
215 self.planes.get(c)?.get(at..at.checked_add(len)?)
216 }
217
218 pub fn at(&self, c: usize, k: i64) -> f64 {
220 let k = self.fold(k);
221 let plane = &self.planes[c];
222 if let Some(held) = k
223 .checked_sub(self.base)
224 .and_then(|at| usize::try_from(at).ok())
225 .and_then(|at| plane.get(at))
226 {
227 return *held;
228 }
229 if !self.support.contains(k) {
230 return 0.0;
231 }
232 panic!(
233 "sample {k} is not held: this node holds [{}, {}) and is nonzero over [{}, {})",
234 self.base,
235 self.base + plane.len() as i64,
236 self.support.start,
237 self.support.end
238 )
239 }
240}