1use cpal::{FromSample, Sample as CpalSample};
2use std::marker::PhantomData;
34/// Converts the samples data type to `O`.
5#[derive(Clone, Debug)]
6pub struct DataConverter<I, O> {
7 input: I,
8 marker: PhantomData<O>,
9}
1011impl<I, O> DataConverter<I, O> {
12/// Builds a new converter.
13#[inline]
14pub fn new(input: I) -> DataConverter<I, O> {
15 DataConverter {
16 input,
17 marker: PhantomData,
18 }
19 }
2021/// Destroys this iterator and returns the underlying iterator.
22#[inline]
23pub fn into_inner(self) -> I {
24self.input
25 }
2627/// get mutable access to the iterator
28#[inline]
29pub fn inner_mut(&mut self) -> &mut I {
30&mut self.input
31 }
32}
3334impl<I, O> Iterator for DataConverter<I, O>
35where
36I: Iterator,
37 I::Item: Sample,
38 O: FromSample<I::Item> + Sample,
39{
40type Item = O;
4142#[inline]
43fn next(&mut self) -> Option<O> {
44self.input.next().map(|s| CpalSample::from_sample(s))
45 }
4647#[inline]
48fn size_hint(&self) -> (usize, Option<usize>) {
49self.input.size_hint()
50 }
51}
5253impl<I, O> ExactSizeIterator for DataConverter<I, O>
54where
55I: ExactSizeIterator,
56 I::Item: Sample,
57 O: FromSample<I::Item> + Sample,
58{
59}
6061/// Represents a value of a single sample.
62///
63/// This trait is implemented by default on three types: `i16`, `u16` and `f32`.
64///
65/// - For `i16`, silence corresponds to the value `0`. The minimum and maximum amplitudes are
66/// represented by `i16::min_value()` and `i16::max_value()` respectively.
67/// - For `u16`, silence corresponds to the value `u16::max_value() / 2`. The minimum and maximum
68/// amplitudes are represented by `0` and `u16::max_value()` respectively.
69/// - For `f32`, silence corresponds to the value `0.0`. The minimum and maximum amplitudes are
70/// represented by `-1.0` and `1.0` respectively.
71///
72/// You can implement this trait on your own type as well if you wish so.
73///
74pub trait Sample: CpalSample {
75/// Linear interpolation between two samples.
76 ///
77 /// The result should be equal to
78 /// `first * numerator / denominator + second * (1 - numerator / denominator)`.
79fn lerp(first: Self, second: Self, numerator: u32, denominator: u32) -> Self;
80/// Multiplies the value of this sample by the given amount.
81fn amplify(self, value: f32) -> Self;
8283/// Converts the sample to an f32 value.
84fn to_f32(self) -> f32;
8586/// Calls `saturating_add` on the sample.
87fn saturating_add(self, other: Self) -> Self;
8889/// Returns the value corresponding to the absence of sound.
90fn zero_value() -> Self;
91}
9293impl Sample for u16 {
94#[inline]
95fn lerp(first: u16, second: u16, numerator: u32, denominator: u32) -> u16 {
96let a = first as i32;
97let b = second as i32;
98let n = numerator as i32;
99let d = denominator as i32;
100 (a + (b - a) * n / d) as u16
101 }
102103#[inline]
104fn amplify(self, value: f32) -> u16 {
105 ((self as f32) * value) as u16
106 }
107108#[inline]
109fn to_f32(self) -> f32 {
110// Convert u16 to f32 in the range [-1.0, 1.0]
111(self as f32 - 32768.0) / 32768.0
112}
113114#[inline]
115fn saturating_add(self, other: u16) -> u16 {
116self.saturating_add(other)
117 }
118119#[inline]
120fn zero_value() -> u16 {
12132768
122}
123}
124125impl Sample for i16 {
126#[inline]
127fn lerp(first: i16, second: i16, numerator: u32, denominator: u32) -> i16 {
128 (first as i32 + (second as i32 - first as i32) * numerator as i32 / denominator as i32)
129as i16
130 }
131132#[inline]
133fn amplify(self, value: f32) -> i16 {
134 ((self as f32) * value) as i16
135 }
136137#[inline]
138fn to_f32(self) -> f32 {
139// Convert i16 to f32 in the range [-1.0, 1.0]
140self as f32 / 32768.0
141}
142143#[inline]
144fn saturating_add(self, other: i16) -> i16 {
145self.saturating_add(other)
146 }
147148#[inline]
149fn zero_value() -> i16 {
1500
151}
152}
153154impl Sample for f32 {
155#[inline]
156fn lerp(first: f32, second: f32, numerator: u32, denominator: u32) -> f32 {
157 first + (second - first) * numerator as f32 / denominator as f32
158 }
159160#[inline]
161fn amplify(self, value: f32) -> f32 {
162self * value
163 }
164165#[inline]
166fn to_f32(self) -> f32 {
167// f32 is already in the correct format
168self
169}
170171#[inline]
172fn saturating_add(self, other: f32) -> f32 {
173self + other
174 }
175176#[inline]
177fn zero_value() -> f32 {
1780.0
179}
180}