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}