av_data/
audiosample.rs

1//! Audio sample format definitions.
2
3use std::fmt;
4use std::string::*;
5
6/// Audio format definition.
7#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub struct Soniton {
9    /// Bits per sample.
10    pub bits: u8,
11    /// Tells if audio format is big-endian.
12    pub be: bool,
13    /// Audio samples are packed (e.g. 20-bit audio samples) and not padded.
14    pub packed: bool,
15    /// Audio data is stored in planar format
16    /// (channels in sequence i.e. C1 C1 C1... C2 C2 C2) instead of interleaving
17    /// samples (i.e. C1 C2 C1 C2) for different channels.
18    pub planar: bool,
19    /// Audio data is in floating point format.
20    pub float: bool,
21    /// Audio data is signed (usually only 8-bit audio is unsigned).
22    pub signed: bool,
23}
24
25// TODO: make it a trait for usize?
26/// Aligns a value to a specific number of bytes.
27fn align(v: usize, a: usize) -> usize {
28    (v + a - 1) & !(a - 1)
29}
30
31/// Returns the number of bytes necessary to represent the number of bits
32/// passed as input.
33fn round_to_byte(v: usize) -> usize {
34    (v + 7) >> 3
35}
36
37impl Soniton {
38    /// Constructs a new audio format definition.
39    pub fn new(bits: u8, be: bool, packed: bool, planar: bool, float: bool, signed: bool) -> Self {
40        Soniton {
41            bits,
42            be,
43            packed,
44            planar,
45            float,
46            signed,
47        }
48    }
49
50    /// Returns the amount of bytes needed to store
51    /// the audio of requested length (in samples).
52    pub fn get_audio_size(self, length: usize, alignment: usize) -> usize {
53        let s = if self.packed {
54            round_to_byte(length * (self.bits as usize))
55        } else {
56            length * round_to_byte(self.bits as usize)
57        };
58
59        align(s, alignment)
60    }
61}
62
63impl fmt::Display for Soniton {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        let fmt = if self.float {
66            "float"
67        } else if self.signed {
68            "int"
69        } else {
70            "uint"
71        };
72        let end = if self.be { "BE" } else { "LE" };
73        write!(
74            f,
75            "({} bps, {} planar: {} packed: {} {})",
76            self.bits, end, self.packed, self.planar, fmt
77        )
78    }
79}
80
81/// Known audio channel types.
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83#[allow(clippy::upper_case_acronyms)]
84pub enum ChannelType {
85    /// Center front.
86    C,
87    /// Left front.
88    L,
89    /// Right front.
90    R,
91    /// Center surround.
92    Cs,
93    /// Left surround.
94    Ls,
95    /// Right surround.
96    Rs,
97    /// Left surround side.
98    Lss,
99    /// Right surround side.
100    Rss,
101    /// Low Frequency Effect.
102    LFE,
103    /// Left center.
104    Lc,
105    /// Right center.
106    Rc,
107    /// Left height.
108    Lh,
109    /// Right height.
110    Rh,
111    /// Center height.
112    Ch,
113    /// Second Low Frequency Effect.
114    LFE2,
115    /// Left wide.
116    Lw,
117    /// Right wide.
118    Rw,
119    /// Overhead.
120    ///
121    /// Known also as:
122    /// - Over the listener head (Oh) in DTS specification (ETSI TS 102.114)
123    /// - Top Center Surround (Ts) in SMPTE 428-3-2006 specification
124    Ov,
125    /// Left height side.
126    Lhs,
127    /// Right height side.
128    Rhs,
129    /// Center height side.
130    Chs,
131    /// Left in the plane lower then listener's ears
132    /// (DTS specification ETSI TS 102.114).
133    Ll,
134    /// Right in the plane lower then listener's ears
135    /// (DTS specification ETSI TS 102.114).
136    Rl,
137    /// Center in the plane lower then listener's ears
138    /// (DTS specification ETSI TS 102.114).
139    Cl,
140    /// Left total (SMPTE 428-3-2006 specification).
141    Lt,
142    /// Right total (SMPTE 428-3-2006 specification).
143    Rt,
144    /// Left-only downmix mode (Dolby ETSI TS 102.366 specification).
145    Lo,
146    /// Right-only downmix mode (Dolby ETSI TS 102.366 specification).
147    Ro,
148}
149
150impl ChannelType {
151    /// Tells whether the channel is some center channel.
152    pub fn is_center(self) -> bool {
153        matches!(
154            self,
155            ChannelType::C
156                | ChannelType::Ch
157                | ChannelType::Cl
158                | ChannelType::Ov
159                | ChannelType::LFE
160                | ChannelType::LFE2
161                | ChannelType::Cs
162                | ChannelType::Chs
163        )
164    }
165
166    /// Tells whether the channel is some left channel.
167    pub fn is_left(self) -> bool {
168        matches!(
169            self,
170            ChannelType::L
171                | ChannelType::Ls
172                | ChannelType::Lss
173                | ChannelType::Lc
174                | ChannelType::Lh
175                | ChannelType::Lw
176                | ChannelType::Lhs
177                | ChannelType::Ll
178                | ChannelType::Lt
179                | ChannelType::Lo
180        )
181    }
182
183    /// Tells whether the channel is some right channel.
184    pub fn is_right(self) -> bool {
185        matches!(
186            self,
187            ChannelType::R
188                | ChannelType::Rs
189                | ChannelType::Rss
190                | ChannelType::Rc
191                | ChannelType::Rh
192                | ChannelType::Rw
193                | ChannelType::Rhs
194                | ChannelType::Rl
195                | ChannelType::Rt
196                | ChannelType::Ro
197        )
198    }
199}
200
201impl fmt::Display for ChannelType {
202    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203        let name = match *self {
204            ChannelType::C => "C".to_string(),
205            ChannelType::L => "L".to_string(),
206            ChannelType::R => "R".to_string(),
207            ChannelType::Cs => "Cs".to_string(),
208            ChannelType::Ls => "Ls".to_string(),
209            ChannelType::Rs => "Rs".to_string(),
210            ChannelType::Lss => "Lss".to_string(),
211            ChannelType::Rss => "Rss".to_string(),
212            ChannelType::LFE => "LFE".to_string(),
213            ChannelType::Lc => "Lc".to_string(),
214            ChannelType::Rc => "Rc".to_string(),
215            ChannelType::Lh => "Lh".to_string(),
216            ChannelType::Rh => "Rh".to_string(),
217            ChannelType::Ch => "Ch".to_string(),
218            ChannelType::LFE2 => "LFE2".to_string(),
219            ChannelType::Lw => "Lw".to_string(),
220            ChannelType::Rw => "Rw".to_string(),
221            ChannelType::Ov => "Ov".to_string(),
222            ChannelType::Lhs => "Lhs".to_string(),
223            ChannelType::Rhs => "Rhs".to_string(),
224            ChannelType::Chs => "Chs".to_string(),
225            ChannelType::Ll => "Ll".to_string(),
226            ChannelType::Rl => "Rl".to_string(),
227            ChannelType::Cl => "Cl".to_string(),
228            ChannelType::Lt => "Lt".to_string(),
229            ChannelType::Rt => "Rt".to_string(),
230            ChannelType::Lo => "Lo".to_string(),
231            ChannelType::Ro => "Ro".to_string(),
232        };
233        write!(f, "{}", name)
234    }
235}
236
237/// An ordered sequence of channels.
238#[derive(Clone, Debug, PartialEq, Eq, Default)]
239pub struct ChannelMap {
240    ids: Vec<ChannelType>,
241}
242
243impl ChannelMap {
244    /// Creates a new sequence of channels.
245    pub fn new() -> Self {
246        ChannelMap { ids: Vec::new() }
247    }
248
249    /// Adds a single channel to the map.
250    pub fn add_channel(&mut self, ch: ChannelType) {
251        self.ids.push(ch);
252    }
253
254    /// Adds several channels to the map in order of occurrence.
255    pub fn add_channels(&mut self, chs: &[ChannelType]) {
256        for ch in chs {
257            self.ids.push(*ch);
258        }
259    }
260
261    /// Returns the total number of channels of the map.
262    pub fn len(&self) -> usize {
263        self.ids.len()
264    }
265
266    /// Tells if the channel map is empty.
267    pub fn is_empty(&self) -> bool {
268        self.ids.is_empty()
269    }
270
271    /// Gets the channel type for a requested index.
272    pub fn get_channel(&self, idx: usize) -> ChannelType {
273        self.ids[idx]
274    }
275
276    /// Tries to find the position of a determined type of channel in the map.
277    pub fn find_channel_id(&self, t: ChannelType) -> Option<u8> {
278        for i in 0..self.ids.len() {
279            if self.ids[i] as i32 == t as i32 {
280                return Some(i as u8);
281            }
282        }
283        None
284    }
285
286    /// Creates a default channel map.
287    ///
288    /// Depending on the `count` value, the channel map is defined differently.
289    ///
290    /// When `count` is 1 --> the channel map is composed by a single centered
291    /// channel.
292    ///
293    /// When `count` is 2 --> the channel map is composed by a right and a left
294    /// channel respectively.
295    ///
296    /// For other `count` values, no other implementations are given for now.
297    pub fn default_map(count: usize) -> Self {
298        use self::ChannelType::*;
299        let ids = match count {
300            1 => vec![C],
301            2 => vec![R, L],
302            _ => unimplemented!(),
303        };
304
305        ChannelMap { ids }
306    }
307}
308
309/// A set of default constant channels for general use.
310pub mod formats {
311    use super::*;
312
313    /// Predefined format for interleaved 8-bit unsigned audio.
314    pub const U8: Soniton = Soniton {
315        bits: 8,
316        be: false,
317        packed: false,
318        planar: false,
319        float: false,
320        signed: false,
321    };
322
323    /// Predefined format for interleaved 16-bit signed audio.
324    pub const S16: Soniton = Soniton {
325        bits: 16,
326        be: false,
327        packed: false,
328        planar: false,
329        float: false,
330        signed: true,
331    };
332
333    /// Predefined format for interleaved 32-bit signed audio.
334    pub const S32: Soniton = Soniton {
335        bits: 32,
336        be: false,
337        packed: false,
338        planar: false,
339        float: false,
340        signed: true,
341    };
342
343    /// Predefined format for interleaved floating points 32-bit signed audio.
344    pub const F32: Soniton = Soniton {
345        bits: 32,
346        be: false,
347        packed: false,
348        planar: false,
349        float: true,
350        signed: true,
351    };
352
353    /// Predefined format for interleaved floating points 64-bit signed audio.
354    pub const F64: Soniton = Soniton {
355        bits: 64,
356        be: false,
357        packed: false,
358        planar: false,
359        float: true,
360        signed: true,
361    };
362}
363
364#[cfg(test)]
365mod test {
366    use super::*;
367
368    #[test]
369    fn fmt() {
370        println!("{}", formats::S16);
371        println!("{}", formats::U8);
372        println!("{}", formats::F32);
373    }
374}