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}