cpal/samples_formats.rs
1use std::{fmt::Display, mem};
2#[cfg(target_os = "emscripten")]
3use wasm_bindgen::prelude::*;
4
5pub use dasp_sample::{FromSample, Sample, I24, I48, U24, U48};
6
7/// Format that each sample has. Usually, this corresponds to the sampling
8/// depth of the audio source. For example, 16 bit quantized samples can be
9/// encoded in `i16` or `u16`. Note that the sampling depth is not directly
10/// visible for formats where [`is_float`] is true.
11///
12/// Also note that the backend must support the encoding of the quantized
13/// samples in the given format, as there is no generic transformation from one
14/// format into the other done inside the frontend-library code. You can query
15/// the supported formats by using [`supported_input_configs`].
16///
17/// A good rule of thumb is to use [`SampleFormat::I16`] as this covers typical
18/// music (WAV, MP3) as well as typical audio input devices on most platforms,
19///
20/// [`is_float`]: SampleFormat::is_float
21/// [`supported_input_configs`]: crate::Device::supported_input_configs
22#[cfg_attr(target_os = "emscripten", wasm_bindgen)]
23#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[non_exhaustive]
25pub enum SampleFormat {
26 /// `i8` with a valid range of `i8::MIN..=i8::MAX` with `0` being the origin.
27 I8,
28
29 /// `i16` with a valid range of `i16::MIN..=i16::MAX` with `0` being the origin.
30 I16,
31
32 /// `I24` with a valid range of '-(1 << 23)..(1 << 23)' with `0` being the origin
33 I24,
34
35 /// `i32` with a valid range of `i32::MIN..=i32::MAX` with `0` being the origin.
36 I32,
37
38 // /// `I48` with a valid range of '-(1 << 47)..(1 << 47)' with `0` being the origin
39 // I48,
40 /// `i64` with a valid range of `i64::MIN..=i64::MAX` with `0` being the origin.
41 I64,
42
43 /// `u8` with a valid range of `u8::MIN..=u8::MAX` with `1 << 7 == 128` being the origin.
44 U8,
45
46 /// `u16` with a valid range of `u16::MIN..=u16::MAX` with `1 << 15 == 32768` being the origin.
47 U16,
48
49 /// `U24` with a valid range of '0..16777216' with `1 << 23 == 8388608` being the origin
50 // U24,
51
52 /// `u32` with a valid range of `u32::MIN..=u32::MAX` with `1 << 31` being the origin.
53 U32,
54
55 /// `U48` with a valid range of '0..(1 << 48)' with `1 << 47` being the origin
56 // U48,
57
58 /// `u64` with a valid range of `u64::MIN..=u64::MAX` with `1 << 63` being the origin.
59 U64,
60
61 /// `f32` with a valid range of `-1.0..1.0` with `0.0` being the origin.
62 F32,
63
64 /// `f64` with a valid range of `-1.0..1.0` with `0.0` being the origin.
65 F64,
66}
67
68impl SampleFormat {
69 /// Returns the size in bytes of a sample of this format. This corresponds to
70 /// the internal size of the rust primitives that are used to represent this
71 /// sample format (e.g., i24 has size of i32).
72 #[inline]
73 #[must_use]
74 pub fn sample_size(&self) -> usize {
75 match *self {
76 SampleFormat::I8 | SampleFormat::U8 => mem::size_of::<i8>(),
77 SampleFormat::I16 | SampleFormat::U16 => mem::size_of::<i16>(),
78 SampleFormat::I24 => mem::size_of::<i32>(),
79 // SampleFormat::U24 => mem::size_of::<i32>(),
80 SampleFormat::I32 | SampleFormat::U32 => mem::size_of::<i32>(),
81
82 // SampleFormat::I48 => mem::size_of::<i64>(),
83 // SampleFormat::U48 => mem::size_of::<i64>(),
84 SampleFormat::I64 | SampleFormat::U64 => mem::size_of::<i64>(),
85 SampleFormat::F32 => mem::size_of::<f32>(),
86 SampleFormat::F64 => mem::size_of::<f64>(),
87 }
88 }
89
90 #[inline]
91 #[must_use]
92 pub fn is_int(&self) -> bool {
93 matches!(
94 *self,
95 SampleFormat::I8
96 | SampleFormat::I16
97 | SampleFormat::I24
98 | SampleFormat::I32
99 // | SampleFormat::I48
100 | SampleFormat::I64
101 )
102 }
103
104 #[inline]
105 #[must_use]
106 pub fn is_uint(&self) -> bool {
107 matches!(
108 *self,
109 SampleFormat::U8
110 | SampleFormat::U16
111 // | SampleFormat::U24
112 | SampleFormat::U32
113 // | SampleFormat::U48
114 | SampleFormat::U64
115 )
116 }
117
118 #[inline]
119 #[must_use]
120 pub fn is_float(&self) -> bool {
121 matches!(*self, SampleFormat::F32 | SampleFormat::F64)
122 }
123}
124
125impl Display for SampleFormat {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 match *self {
128 SampleFormat::I8 => "i8",
129 SampleFormat::I16 => "i16",
130 SampleFormat::I24 => "i24",
131 SampleFormat::I32 => "i32",
132 // SampleFormat::I48 => "i48",
133 SampleFormat::I64 => "i64",
134 SampleFormat::U8 => "u8",
135 SampleFormat::U16 => "u16",
136 // SampleFormat::U24 => "u24",
137 SampleFormat::U32 => "u32",
138 // SampleFormat::U48 => "u48",
139 SampleFormat::U64 => "u64",
140 SampleFormat::F32 => "f32",
141 SampleFormat::F64 => "f64",
142 }
143 .fmt(f)
144 }
145}
146
147pub trait SizedSample: Sample {
148 const FORMAT: SampleFormat;
149}
150
151impl SizedSample for i8 {
152 const FORMAT: SampleFormat = SampleFormat::I8;
153}
154
155impl SizedSample for i16 {
156 const FORMAT: SampleFormat = SampleFormat::I16;
157}
158
159impl SizedSample for I24 {
160 const FORMAT: SampleFormat = SampleFormat::I24;
161}
162
163impl SizedSample for i32 {
164 const FORMAT: SampleFormat = SampleFormat::I32;
165}
166
167// impl SizedSample for I48 {
168// const FORMAT: SampleFormat = SampleFormat::I48;
169// }
170
171impl SizedSample for i64 {
172 const FORMAT: SampleFormat = SampleFormat::I64;
173}
174
175impl SizedSample for u8 {
176 const FORMAT: SampleFormat = SampleFormat::U8;
177}
178
179impl SizedSample for u16 {
180 const FORMAT: SampleFormat = SampleFormat::U16;
181}
182
183// impl SizedSample for U24 {
184// const FORMAT: SampleFormat = SampleFormat::U24;
185// }
186
187impl SizedSample for u32 {
188 const FORMAT: SampleFormat = SampleFormat::U32;
189}
190
191// impl SizedSample for U48 {
192// const FORMAT: SampleFormat = SampleFormat::U48;
193// }
194
195impl SizedSample for u64 {
196 const FORMAT: SampleFormat = SampleFormat::U64;
197}
198
199impl SizedSample for f32 {
200 const FORMAT: SampleFormat = SampleFormat::F32;
201}
202
203impl SizedSample for f64 {
204 const FORMAT: SampleFormat = SampleFormat::F64;
205}