sample/frame.rs
1//! Use the Frame trait to remain generic over the number of channels at
2//! a single discrete moment in time.
3//!
4//! Implementations are provided for all fixed-size arrays up to 32 elements in length.
5
6use Sample;
7
8pub type Mono<S> = [S; 1];
9pub type Stereo<S> = [S; 2];
10
11/// Represents one sample from each channel at a single discrete instance in time within a
12/// PCM signal.
13///
14/// We provide implementations for `Frame` for all fixed-size arrays up to a length of 32 elements.
15pub trait Frame: Copy + Clone + PartialEq {
16 /// The type of PCM sample stored at each channel within the frame.
17 type Sample: Sample;
18 /// A typified version of a number of channels in the `Frame`, used for safely mapping frames
19 /// of the same length to other `Frame`s, perhaps with a different `Sample` associated type.
20 type NumChannels: NumChannels;
21 /// An iterator yielding the sample in each channel, starting from left (channel 0) and ending
22 /// at the right (channel NumChannels-1).
23 type Channels: Iterator<Item = Self::Sample>;
24 /// A frame type with equilavent number of channels using the associated `Sample::Signed` format.
25 type Signed: Frame<Sample = <Self::Sample as Sample>::Signed, NumChannels = Self::NumChannels>;
26 /// A frame type with equilavent number of channels using the associated `Sample::Float` format.
27 type Float: Frame<Sample = <Self::Sample as Sample>::Float, NumChannels = Self::NumChannels>;
28
29 /// The equilibrium value for the wave that this `Sample` type represents. This is normally the
30 /// value that is equal distance from both the min and max ranges of the sample.
31 ///
32 /// **NOTE:** This will likely be changed to an "associated const" if the feature lands.
33 ///
34 /// # Examples
35 ///
36 /// ```rust
37 /// extern crate sample;
38 ///
39 /// use sample::Frame;
40 /// use sample::frame::{Mono, Stereo};
41 ///
42 /// fn main() {
43 /// assert_eq!(Mono::<f32>::equilibrium(), [0.0]);
44 /// assert_eq!(Stereo::<f32>::equilibrium(), [0.0, 0.0]);
45 /// assert_eq!(<[f32; 3]>::equilibrium(), [0.0, 0.0, 0.0]);
46 /// assert_eq!(<[u8; 2]>::equilibrium(), [128u8, 128]);
47 /// }
48 /// ```
49 fn equilibrium() -> Self;
50
51 /// Create a new `Frame` where the `Sample` for each channel is produced by the given function.
52 ///
53 /// The given function should map each channel index to its respective sample.
54 fn from_fn<F>(from: F) -> Self
55 where
56 F: FnMut(usize) -> Self::Sample;
57
58 /// Create a new `Frame` from a borrowed `Iterator` yielding samples for each channel.
59 ///
60 /// Returns `None` if the given `Iterator` does not yield enough `Sample`s.
61 ///
62 /// This is necessary for the `signal::FromSamples` `Iterator`, that converts some `Iterator`
63 /// yielding `Sample`s to an `Iterator` yielding `Frame`s.
64 fn from_samples<I>(samples: &mut I) -> Option<Self>
65 where
66 I: Iterator<Item = Self::Sample>;
67
68 /// The total number of channels (and in turn samples) stored within the frame.
69 fn n_channels() -> usize;
70
71 /// Converts the frame into an iterator yielding the sample for each channel in the frame.
72 fn channels(self) -> Self::Channels;
73
74 /// Yields a reference to the `Sample` of the channel at the given index if there is one.
75 fn channel(&self, idx: usize) -> Option<&Self::Sample>;
76
77 /// Returns a pointer to the sample of the channel at the given index, without doing bounds
78 /// checking.
79 ///
80 /// Note: This is primarily a necessity for efficient `Frame::map` and `Frame::zip_map`
81 /// methods, as for those methods we can guarantee lengths of different `Frame`s to be the same
82 /// at *compile-time*.
83 unsafe fn channel_unchecked(&self, idx: usize) -> &Self::Sample;
84
85 /// Applies the given function to each sample in the `Frame` in channel order and returns the
86 /// result as a new `Frame`.
87 ///
88 /// # Example
89 ///
90 /// ```rust
91 /// extern crate sample;
92 ///
93 /// use sample::{Frame, Sample};
94 ///
95 /// fn main() {
96 /// let foo = [0i16, 0];
97 /// let bar: [u8; 2] = foo.map(Sample::to_sample);
98 /// assert_eq!(bar, [128u8, 128]);
99 /// }
100 /// ```
101 fn map<F, M>(self, map: M) -> F
102 where
103 F: Frame<NumChannels = Self::NumChannels>,
104 M: FnMut(Self::Sample) -> F::Sample;
105
106 /// Calls the given function with the pair of elements at every index and returns the
107 /// resulting Frame.
108 ///
109 /// On a `Vec` this would be akin to `.into_iter().zip(other).map(|(a, b)| ...).collect()`, though
110 /// much quicker and tailored to fixed-size arrays of samples.
111 fn zip_map<O, F, M>(self, other: O, zip_map: M) -> F
112 where
113 O: Frame<NumChannels = Self::NumChannels>,
114 F: Frame<NumChannels = Self::NumChannels>,
115 M: FnMut(Self::Sample, O::Sample) -> F::Sample;
116
117 /// Converts the frame type to the equivalent signal in its associated `Float`ing point format.
118 ///
119 /// # Example
120 ///
121 /// ```rust
122 /// extern crate sample;
123 ///
124 /// use sample::Frame;
125 ///
126 /// fn main() {
127 /// let foo = [128u8; 2];
128 /// let signed = foo.to_signed_frame();
129 /// assert_eq!(signed, [0i8; 2]);
130 /// }
131 /// ```
132 fn to_signed_frame(self) -> Self::Signed;
133
134 /// Converts the frame type to the equivalent signal in its associated `Signed` format.
135 ///
136 /// # Example
137 ///
138 /// ```rust
139 /// extern crate sample;
140 ///
141 /// use sample::Frame;
142 ///
143 /// fn main() {
144 /// let foo = [128u8; 2];
145 /// let float = foo.to_float_frame();
146 /// assert_eq!(float, [0.0; 2]);
147 /// }
148 /// ```
149 fn to_float_frame(self) -> Self::Float;
150
151 /// Offsets the amplitude of every channel in the frame by the given `offset` and yields the
152 /// resulting frame.
153 ///
154 /// # Example
155 ///
156 /// ```rust
157 /// extern crate sample;
158 ///
159 /// use sample::Frame;
160 ///
161 /// fn main() {
162 /// assert_eq!([0.25, -0.5].offset_amp(0.5), [0.75, 0.0]);
163 /// assert_eq!([0.5, -0.25].offset_amp(-0.25), [0.25, -0.5]);
164 /// assert_eq!([128u8, 192].offset_amp(-64), [64, 128]);
165 /// }
166 /// ```
167 #[inline]
168 fn offset_amp(self, offset: <Self::Sample as Sample>::Signed) -> Self {
169 self.map(|s| s.add_amp(offset))
170 }
171
172 /// Multiplies each `Sample` in the `Frame` by the given amplitude and returns the resulting
173 /// `Frame`.
174 ///
175 /// - A > 1.0 amplifies the sample.
176 /// - A < 1.0 attenuates the sample.
177 /// - A == 1.0 yields the same sample.
178 /// - A == 0.0 yields the `Sample::equilibrium`.
179 ///
180 /// # Example
181 ///
182 /// ```rust
183 /// extern crate sample;
184 ///
185 /// use sample::Frame;
186 ///
187 /// fn main() {
188 /// assert_eq!([0.1, 0.2, -0.1, -0.2].scale_amp(2.0), [0.2, 0.4, -0.2, -0.4]);
189 /// }
190 /// ```
191 #[inline]
192 fn scale_amp(self, amp: <Self::Sample as Sample>::Float) -> Self {
193 self.map(|s| s.mul_amp(amp))
194 }
195
196 /// Sums each channel in `other` with each channel in `self` and returns the resulting `Frame`.
197 ///
198 /// # Example
199 ///
200 /// ```rust
201 /// extern crate sample;
202 ///
203 /// use sample::Frame;
204 ///
205 /// fn main() {
206 /// let foo = [0.25, 0.5].add_amp([-0.75, 0.25]);
207 /// assert_eq!(foo, [-0.5, 0.75]);
208 /// }
209 /// ```
210 #[inline]
211 fn add_amp<F>(self, other: F) -> Self
212 where
213 F: Frame<Sample = <Self::Sample as Sample>::Signed, NumChannels = Self::NumChannels>,
214 {
215 self.zip_map(other, Sample::add_amp)
216 }
217
218 /// Multiplies `other` with `self` and returns the resulting `Frame`.
219 ///
220 /// # Example
221 ///
222 /// ```rust
223 /// extern crate sample;
224 ///
225 /// use sample::Frame;
226 ///
227 /// fn main() {
228 /// let foo = [0.25, 0.4].mul_amp([0.2, 0.5]);
229 /// assert_eq!(foo, [0.05, 0.2]);
230 ///
231 /// let bar = [192u8, 64].mul_amp([0.0, -2.0]);
232 /// assert_eq!(bar, [128, 0]);
233 /// }
234 /// ```
235 #[inline]
236 fn mul_amp<F>(self, other: F) -> Self
237 where
238 F: Frame<Sample = <Self::Sample as Sample>::Float, NumChannels = Self::NumChannels>,
239 {
240 self.zip_map(other, Sample::mul_amp)
241 }
242}
243
244/// An iterator that yields the sample for each channel in the frame by value.
245#[derive(Clone)]
246pub struct Channels<F> {
247 next_idx: usize,
248 frame: F,
249}
250
251/// Restricts the types that may be used as the `Frame::NumChannels` associated type.
252///
253/// `NumChannels` allows us to enforce the number of channels that a `Frame` must have in certain
254/// operations. This is particularly useful for `Frame::map` and `Frame::zip_map`, as it allows us
255/// to guarantee that the input and output frame types will retain the same number of channels at
256/// compile-time, and in turn removes the need for bounds checking.
257///
258/// This trait is implemented for types `N1`...`N32`.
259pub trait NumChannels {}
260
261macro_rules! impl_frame {
262 ($($NChan:ident $N:expr, [$($idx:expr)*],)*) => {
263 $(
264 /// A typified version of a number of channels.
265 pub struct $NChan;
266 impl NumChannels for $NChan {}
267
268 impl<S> Frame for [S; $N]
269 where
270 S: Sample,
271 {
272 type Sample = S;
273 type NumChannels = $NChan;
274 type Channels = Channels<Self>;
275 type Float = [S::Float; $N];
276 type Signed = [S::Signed; $N];
277
278 #[inline]
279 fn equilibrium() -> Self {
280 [S::equilibrium(); $N]
281 }
282
283 #[inline]
284 fn n_channels() -> usize {
285 $N
286 }
287
288 #[inline]
289 fn channels(self) -> Self::Channels {
290 Channels {
291 next_idx: 0,
292 frame: self,
293 }
294 }
295
296 #[inline]
297 fn channel(&self, idx: usize) -> Option<&Self::Sample> {
298 self.get(idx)
299 }
300
301 #[inline]
302 fn from_fn<F>(mut from: F) -> Self
303 where
304 F: FnMut(usize) -> S,
305 {
306 [$(from($idx), )*]
307 }
308
309 #[inline]
310 fn from_samples<I>(samples: &mut I) -> Option<Self>
311 where
312 I: Iterator<Item=Self::Sample>
313 {
314 Some([$( {
315 $idx;
316 match samples.next() {
317 Some(sample) => sample,
318 None => return None,
319 }
320 }, )*])
321 }
322
323 #[inline(always)]
324 unsafe fn channel_unchecked(&self, idx: usize) -> &Self::Sample {
325 self.get_unchecked(idx)
326 }
327
328 #[inline]
329 fn to_signed_frame(self) -> Self::Signed {
330 self.map(|s| s.to_sample())
331 }
332
333 #[inline]
334 fn to_float_frame(self) -> Self::Float {
335 self.map(|s| s.to_sample())
336 }
337
338 #[inline]
339 fn map<F, M>(self, mut map: M) -> F
340 where
341 F: Frame<NumChannels=Self::NumChannels>,
342 M: FnMut(Self::Sample) -> F::Sample,
343 {
344 F::from_fn(|channel_idx| {
345
346 // Here we do not require run-time bounds checking as we have asserted that
347 // the two arrays have the same number of channels at compile time with our
348 // where clause, i.e.
349 //
350 // `F: Frame<NumChannels=Self::NumChannels>`
351 unsafe { map(*self.channel_unchecked(channel_idx)) }
352 })
353 }
354
355 #[inline]
356 fn zip_map<O, F, M>(self, other: O, mut zip_map: M) -> F
357 where
358 O: Frame<NumChannels=Self::NumChannels>,
359 F: Frame<NumChannels=Self::NumChannels>,
360 M: FnMut(Self::Sample, O::Sample) -> F::Sample
361 {
362 F::from_fn(|channel_idx| {
363
364 // Here we do not require run-time bounds checking as we have asserted that the two
365 // arrays have the same number of channels at compile time with our where clause, i.e.
366 //
367 // ```
368 // O: Frame<NumChannels=Self::NumChannels>
369 // F: Frame<NumChannels=Self::NumChannels>
370 // ```
371 unsafe {
372 zip_map(*self.channel_unchecked(channel_idx),
373 *other.channel_unchecked(channel_idx))
374 }
375 })
376 }
377
378 #[inline]
379 fn scale_amp(self, amp: S::Float) -> Self {
380 [$(self[$idx].mul_amp(amp), )*]
381 }
382
383 #[inline]
384 fn add_amp<F>(self, other: F) -> Self
385 where
386 F: Frame<Sample=S::Signed, NumChannels=$NChan>,
387 {
388 // Here we do not require run-time bounds checking as we have asserted that the two
389 // arrays have the same number of channels at compile time with our where clause, i.e.
390 unsafe {
391 [$(self[$idx].add_amp(*other.channel_unchecked($idx)), )*]
392 }
393 }
394
395 }
396 )*
397 };
398}
399
400impl_frame!{
401 N1 1, [0],
402 N2 2, [0 1],
403 N3 3, [0 1 2],
404 N4 4, [0 1 2 3],
405 N5 5, [0 1 2 3 4],
406 N6 6, [0 1 2 3 4 5],
407 N7 7, [0 1 2 3 4 5 6],
408 N8 8, [0 1 2 3 4 5 6 7],
409 N9 9, [0 1 2 3 4 5 6 7 8],
410 N10 10, [0 1 2 3 4 5 6 7 8 9],
411 N11 11, [0 1 2 3 4 5 6 7 8 9 10],
412 N12 12, [0 1 2 3 4 5 6 7 8 9 10 11],
413 N13 13, [0 1 2 3 4 5 6 7 8 9 10 11 12],
414 N14 14, [0 1 2 3 4 5 6 7 8 9 10 11 12 13],
415 N15 15, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14],
416 N16 16, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15],
417 N17 17, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16],
418 N18 18, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17],
419 N19 19, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18],
420 N20 20, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19],
421 N21 21, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20],
422 N22 22, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21],
423 N23 23, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22],
424 N24 24, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23],
425 N25 25, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24],
426 N26 26, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25],
427 N27 27, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26],
428 N28 28, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27],
429 N29 29, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28],
430 N30 30, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29],
431 N31 31, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30],
432 N32 32, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31],
433}
434
435
436impl<F> Iterator for Channels<F>
437where
438 F: Frame,
439{
440 type Item = F::Sample;
441 #[inline]
442 fn next(&mut self) -> Option<Self::Item> {
443 self.frame.channel(self.next_idx).map(|&s| s).map(|s| {
444 self.next_idx += 1;
445 s
446 })
447 }
448}
449
450impl<F> ExactSizeIterator for Channels<F>
451where
452 F: Frame,
453{
454 #[inline]
455 fn len(&self) -> usize {
456 F::n_channels() - self.next_idx
457 }
458}