/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dasp_sample-0.11.0/src/lib.rs
Line | Count | Source |
1 | | //! Use the [**Sample**](./trait.Sample.html) trait to remain generic over sample types, easily |
2 | | //! access sample type conversions, apply basic audio operations and more. |
3 | | //! |
4 | | //! The **Sample** trait is the core abstraction throughout dasp on which most other abstractions |
5 | | //! are based. |
6 | | |
7 | | #![cfg_attr(not(feature = "std"), no_std)] |
8 | | #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] |
9 | | |
10 | | #[cfg(not(feature = "std"))] |
11 | | extern crate alloc; |
12 | | |
13 | | pub use conv::{Duplex, FromSample, ToSample}; |
14 | | pub use types::{I24, I48, U24, U48}; |
15 | | |
16 | | pub mod conv; |
17 | | mod ops; |
18 | | pub mod types; |
19 | | |
20 | | /// A trait for working generically across different **Sample** format types. |
21 | | /// |
22 | | /// Provides methods for converting to and from any type that implements the |
23 | | /// [`FromSample`](./trait.FromSample.html) trait and provides methods for performing signal |
24 | | /// amplitude addition and multiplication. |
25 | | /// |
26 | | /// # Example |
27 | | /// |
28 | | /// ```rust |
29 | | /// use dasp_sample::{I24, Sample}; |
30 | | /// |
31 | | /// fn main() { |
32 | | /// assert_eq!((-1.0).to_sample::<u8>(), 0); |
33 | | /// assert_eq!(0.0.to_sample::<u8>(), 128); |
34 | | /// assert_eq!(0i32.to_sample::<u32>(), 2_147_483_648); |
35 | | /// assert_eq!(I24::new(0).unwrap(), Sample::from_sample(0.0)); |
36 | | /// assert_eq!(0.0, Sample::EQUILIBRIUM); |
37 | | /// } |
38 | | /// ``` |
39 | | pub trait Sample: Copy + Clone + PartialOrd + PartialEq { |
40 | | /// When summing two samples of a signal together, it is necessary for both samples to be |
41 | | /// represented in some signed format. This associated `Addition` type represents the format to |
42 | | /// which `Self` should be converted for optimal `Addition` performance. |
43 | | /// |
44 | | /// For example, u32's optimal `Addition` type would be i32, u8's would be i8, f32's would be |
45 | | /// f32, etc. |
46 | | /// |
47 | | /// Specifying this as an associated type allows us to automatically determine the optimal, |
48 | | /// lossless Addition format type for summing any two unique `Sample` types together. |
49 | | /// |
50 | | /// As a user of the `sample` crate, you will never need to be concerned with this type unless |
51 | | /// you are defining your own unique `Sample` type(s). |
52 | | type Signed: SignedSample + Duplex<Self>; |
53 | | |
54 | | /// When multiplying two samples of a signal together, it is necessary for both samples to be |
55 | | /// represented in some signed, floating-point format. This associated `Multiplication` type |
56 | | /// represents the format to which `Self` should be converted for optimal `Multiplication` |
57 | | /// performance. |
58 | | /// |
59 | | /// For example, u32's optimal `Multiplication` type would be f32, u64's would be f64, i8's |
60 | | /// would be f32, etc. |
61 | | /// |
62 | | /// Specifying this as an associated type allows us to automatically determine the optimal, |
63 | | /// lossless Multiplication format type for multiplying any two unique `Sample` types together. |
64 | | /// |
65 | | /// As a user of the `sample` crate, you will never need to be concerned with this type unless |
66 | | /// you are defining your own unique `Sample` type(s). |
67 | | type Float: FloatSample + Duplex<Self>; |
68 | | |
69 | | /// The equilibrium value for the wave that this `Sample` type represents. This is normally the |
70 | | /// value that is equal distance from both the min and max ranges of the sample. |
71 | | /// |
72 | | /// # Example |
73 | | /// |
74 | | /// ```rust |
75 | | /// use dasp_sample::Sample; |
76 | | /// |
77 | | /// fn main() { |
78 | | /// assert_eq!(0.0, f32::EQUILIBRIUM); |
79 | | /// assert_eq!(0, i32::EQUILIBRIUM); |
80 | | /// assert_eq!(128, u8::EQUILIBRIUM); |
81 | | /// assert_eq!(32_768_u16, Sample::EQUILIBRIUM); |
82 | | /// } |
83 | | /// ``` |
84 | | /// |
85 | | /// **Note:** This will likely be changed to an "associated const" if the feature lands. |
86 | | const EQUILIBRIUM: Self; |
87 | | |
88 | | /// The multiplicative identity of the signal. |
89 | | /// |
90 | | /// In other words: A value which when used to scale/multiply the amplitude or frequency of a |
91 | | /// signal, returns the same signal. |
92 | | /// |
93 | | /// This is useful as a default, non-affecting amplitude or frequency multiplier. |
94 | | /// |
95 | | /// # Example |
96 | | /// |
97 | | /// ```rust |
98 | | /// use dasp_sample::{Sample, U48}; |
99 | | /// |
100 | | /// fn main() { |
101 | | /// assert_eq!(1.0, f32::IDENTITY); |
102 | | /// assert_eq!(1.0, i8::IDENTITY); |
103 | | /// assert_eq!(1.0, u8::IDENTITY); |
104 | | /// assert_eq!(1.0, U48::IDENTITY); |
105 | | /// } |
106 | | /// ``` |
107 | | const IDENTITY: Self::Float = <Self::Float as FloatSample>::IDENTITY; |
108 | | |
109 | | /// Convert `self` to any type that implements `FromSample<Self>`. |
110 | | /// |
111 | | /// Find more details on type-specific conversion ranges and caveats in the `conv` module. |
112 | | /// |
113 | | /// # Example |
114 | | /// |
115 | | /// ```rust |
116 | | /// use dasp_sample::Sample; |
117 | | /// |
118 | | /// fn main() { |
119 | | /// assert_eq!(0.0.to_sample::<i32>(), 0); |
120 | | /// assert_eq!(0.0.to_sample::<u8>(), 128); |
121 | | /// assert_eq!((-1.0).to_sample::<u8>(), 0); |
122 | | /// } |
123 | | /// ``` |
124 | | #[inline] |
125 | 0 | fn to_sample<S>(self) -> S |
126 | 0 | where |
127 | 0 | Self: ToSample<S>, |
128 | | { |
129 | 0 | self.to_sample_() |
130 | 0 | } |
131 | | |
132 | | /// Create a `Self` from any type that implements `ToSample<Self>`. |
133 | | /// |
134 | | /// Find more details on type-specific conversion ranges and caveats in the `conv` module. |
135 | | /// |
136 | | /// # Example |
137 | | /// |
138 | | /// ```rust |
139 | | /// use dasp_sample::{Sample, I24}; |
140 | | /// |
141 | | /// fn main() { |
142 | | /// assert_eq!(f32::from_sample(128_u8), 0.0); |
143 | | /// assert_eq!(i8::from_sample(-1.0), -128); |
144 | | /// assert_eq!(I24::from_sample(0.0), I24::new(0).unwrap()); |
145 | | /// } |
146 | | /// ``` |
147 | | |
148 | | #[inline] |
149 | 0 | fn from_sample<S>(s: S) -> Self |
150 | 0 | where |
151 | 0 | Self: FromSample<S>, |
152 | | { |
153 | 0 | FromSample::from_sample_(s) |
154 | 0 | } |
155 | | |
156 | | /// Converts `self` to the equivalent `Sample` in the associated `Signed` format. |
157 | | /// |
158 | | /// This is a simple wrapper around `Sample::to_sample` which may provide extra convenience in |
159 | | /// some cases, particularly for assisting type inference. |
160 | | /// |
161 | | /// # Example |
162 | | /// |
163 | | /// ```rust |
164 | | /// use dasp_sample::Sample; |
165 | | /// |
166 | | /// fn main() { |
167 | | /// assert_eq!(128_u8.to_signed_sample(), 0i8); |
168 | | /// } |
169 | | /// ``` |
170 | 0 | fn to_signed_sample(self) -> Self::Signed { |
171 | 0 | self.to_sample() |
172 | 0 | } |
173 | | |
174 | | /// Converts `self` to the equivalent `Sample` in the associated `Float` format. |
175 | | /// |
176 | | /// This is a simple wrapper around `Sample::to_sample` which may provide extra convenience in |
177 | | /// some cases, particularly for assisting type inference. |
178 | | /// |
179 | | /// # Example |
180 | | /// |
181 | | /// ```rust |
182 | | /// use dasp_sample::Sample; |
183 | | /// |
184 | | /// fn main() { |
185 | | /// assert_eq!(128_u8.to_float_sample(), 0.0); |
186 | | /// } |
187 | | /// ``` |
188 | 0 | fn to_float_sample(self) -> Self::Float { |
189 | 0 | self.to_sample() |
190 | 0 | } |
191 | | |
192 | | /// Adds (or "offsets") the amplitude of the `Sample` by the given signed amplitude. |
193 | | /// |
194 | | /// `Self` will be converted to `Self::Signed`, the addition will occur and then the result |
195 | | /// will be converted back to `Self`. These conversions allow us to correctly handle the |
196 | | /// addition of unsigned signal formats. |
197 | | /// |
198 | | /// # Example |
199 | | /// |
200 | | /// ```rust |
201 | | /// use dasp_sample::Sample; |
202 | | /// |
203 | | /// fn main() { |
204 | | /// assert_eq!(0.25.add_amp(0.5), 0.75); |
205 | | /// assert_eq!(192u8.add_amp(-128), 64); |
206 | | /// } |
207 | | /// ``` |
208 | | #[inline] |
209 | 0 | fn add_amp(self, amp: Self::Signed) -> Self { |
210 | 0 | let self_s = self.to_signed_sample(); |
211 | 0 | (self_s + amp).to_sample() |
212 | 0 | } |
213 | | |
214 | | /// Multiplies (or "scales") the amplitude of the `Sample` by the given float amplitude. |
215 | | /// |
216 | | /// - `amp` > 1.0 amplifies the sample. |
217 | | /// - `amp` < 1.0 attenuates the sample. |
218 | | /// - `amp` == 1.0 yields the same sample. |
219 | | /// - `amp` == 0.0 yields the `Sample::EQUILIBRIUM`. |
220 | | /// |
221 | | /// `Self` will be converted to `Self::Float`, the multiplication will occur and then the |
222 | | /// result will be converted back to `Self`. These conversions allow us to correctly handle the |
223 | | /// multiplication of integral signal formats. |
224 | | /// |
225 | | /// # Example |
226 | | /// |
227 | | /// ```rust |
228 | | /// use dasp_sample::Sample; |
229 | | /// |
230 | | /// fn main() { |
231 | | /// assert_eq!(64_i8.mul_amp(0.5), 32); |
232 | | /// assert_eq!(0.5.mul_amp(-2.0), -1.0); |
233 | | /// assert_eq!(64_u8.mul_amp(0.0), 128); |
234 | | /// } |
235 | | /// ``` |
236 | | #[inline] |
237 | 0 | fn mul_amp(self, amp: Self::Float) -> Self { |
238 | 0 | let self_f = self.to_float_sample(); |
239 | 0 | (self_f * amp).to_sample() |
240 | 0 | } |
241 | | } |
242 | | |
243 | | /// A macro used to simplify the implementation of `Sample`. |
244 | | macro_rules! impl_sample { |
245 | | ($($T:ty: |
246 | | Signed: $Addition:ty, |
247 | | Float: $Modulation:ty, |
248 | | EQUILIBRIUM: $EQUILIBRIUM:expr),*) => |
249 | | { |
250 | | $( |
251 | | impl Sample for $T { |
252 | | type Signed = $Addition; |
253 | | type Float = $Modulation; |
254 | | const EQUILIBRIUM: Self = $EQUILIBRIUM; |
255 | | } |
256 | | )* |
257 | | } |
258 | | } |
259 | | |
260 | | // Expands to `Sample` implementations for all of the following types. |
261 | | impl_sample! { |
262 | | i8: Signed: i8, Float: f32, EQUILIBRIUM: 0, |
263 | | i16: Signed: i16, Float: f32, EQUILIBRIUM: 0, |
264 | | I24: Signed: I24, Float: f32, EQUILIBRIUM: types::i24::EQUILIBRIUM, |
265 | | i32: Signed: i32, Float: f32, EQUILIBRIUM: 0, |
266 | | I48: Signed: I48, Float: f64, EQUILIBRIUM: types::i48::EQUILIBRIUM, |
267 | | i64: Signed: i64, Float: f64, EQUILIBRIUM: 0, |
268 | | u8: Signed: i8, Float: f32, EQUILIBRIUM: 128, |
269 | | u16: Signed: i16, Float: f32, EQUILIBRIUM: 32_768, |
270 | | U24: Signed: i32, Float: f32, EQUILIBRIUM: types::u24::EQUILIBRIUM, |
271 | | u32: Signed: i32, Float: f32, EQUILIBRIUM: 2_147_483_648, |
272 | | U48: Signed: i64, Float: f64, EQUILIBRIUM: types::u48::EQUILIBRIUM, |
273 | | u64: Signed: i64, Float: f64, EQUILIBRIUM: 9_223_372_036_854_775_808, |
274 | | f32: Signed: f32, Float: f32, EQUILIBRIUM: 0.0, |
275 | | f64: Signed: f64, Float: f64, EQUILIBRIUM: 0.0 |
276 | | } |
277 | | |
278 | | /// Integral and floating-point **Sample** format types whose equilibrium is at 0. |
279 | | /// |
280 | | /// **Sample**s often need to be converted to some mutual **SignedSample** type for signal |
281 | | /// addition. |
282 | | pub trait SignedSample: |
283 | | Sample<Signed = Self> |
284 | | + core::ops::Add<Output = Self> |
285 | | + core::ops::Sub<Output = Self> |
286 | | + core::ops::Neg<Output = Self> |
287 | | { |
288 | | } |
289 | | macro_rules! impl_signed_sample { ($($T:ty)*) => { $( impl SignedSample for $T {} )* } } |
290 | | impl_signed_sample!(i8 i16 I24 i32 I48 i64 f32 f64); |
291 | | |
292 | | /// Sample format types represented as floating point numbers. |
293 | | /// |
294 | | /// **Sample**s often need to be converted to some mutual **FloatSample** type for signal scaling |
295 | | /// and modulation. |
296 | | pub trait FloatSample: |
297 | | Sample<Signed = Self, Float = Self> |
298 | | + SignedSample |
299 | | + core::ops::Mul<Output = Self> |
300 | | + core::ops::Div<Output = Self> |
301 | | + Duplex<f32> |
302 | | + Duplex<f64> |
303 | | { |
304 | | /// Represents the multiplicative identity of the floating point signal. |
305 | | const IDENTITY: Self; |
306 | | /// Calculate the square root of `Self`. |
307 | | fn sample_sqrt(self) -> Self; |
308 | | } |
309 | | |
310 | | impl FloatSample for f32 { |
311 | | const IDENTITY: Self = 1.0; |
312 | | #[inline] |
313 | 0 | fn sample_sqrt(self) -> Self { |
314 | 0 | ops::f32::sqrt(self) |
315 | 0 | } |
316 | | } |
317 | | |
318 | | impl FloatSample for f64 { |
319 | | const IDENTITY: Self = 1.0; |
320 | | #[inline] |
321 | 0 | fn sample_sqrt(self) -> Self { |
322 | 0 | ops::f64::sqrt(self) |
323 | 0 | } |
324 | | } |