bwavfile/
common_format.rs

1/// Format tags, UUIDs and utilities
2
3use uuid::Uuid;
4
5/// Format tag for integer LPCM
6pub const WAVE_TAG_PCM: u16 = 0x0001;
7
8/// Format tag for float LPCM
9pub const WAVE_TAG_FLOAT: u16 = 0x0003;
10
11/// Format tag for MPEG1
12pub const WAVE_TAG_MPEG: u16 = 0x0050;
13
14/// Format tag indicating extended format
15pub const WAVE_TAG_EXTENDED: u16 = 0xFFFE;
16
17/* RC 2361 ยง4:
18
19 WAVE Format IDs are converted to GUIDs by inserting the hexadecimal
20   value of the WAVE Format ID into the XXXXXXXX part of the following
21   template: {XXXXXXXX-0000-0010-8000-00AA00389B71}. For example, a WAVE
22   Format ID of 123 has the GUID value of {00000123-0000-0010-8000-
23   00AA00389B71}.
24
25*/
26
27/// Extended format UUID for integer PCM
28pub const WAVE_UUID_PCM: Uuid = Uuid::from_bytes([
29    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71,
30]);
31
32/// Extended format UUID for float PCM
33pub const WAVE_UUID_FLOAT: Uuid = Uuid::from_bytes([
34    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71,
35]);
36
37/// Extended format UUID for MPEG1 data
38pub const WAVE_UUID_MPEG: Uuid = Uuid::from_bytes([
39    0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71,
40]);
41
42/// Extended format for integer Ambisonic B-Format
43pub const WAVE_UUID_BFORMAT_PCM: Uuid = Uuid::from_bytes([
44    0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00,
45]);
46
47/// Extended format for float Ambisonic B-Format
48pub const WAVE_UUID_BFORMAT_FLOAT: Uuid = Uuid::from_bytes([
49    0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00,
50]);
51
52/// Generate an extended format UUID for the given basic format tag from [WaveFmt::tag].
53fn uuid_from_basic_tag(tag: u16) -> Uuid {
54    let tail: [u8; 6] = [0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71];
55    Uuid::from_fields_le(tag as u32, 0x0000, 0x0010, &tail).unwrap()
56}
57
58/// Sample format of the Wave file.
59#[derive(Debug, Copy, Clone, PartialEq)]
60pub enum CommonFormat {
61    /// Integer linear PCM
62    IntegerPCM,
63
64    /// IEEE Floating-point Linear PCM
65    IeeeFloatPCM,
66
67    /// MPEG
68    Mpeg,
69
70    /// Ambisonic B-Format Linear PCM
71    AmbisonicBFormatIntegerPCM,
72
73    /// Ambisonic B-Format Float PCM
74    AmbisonicBFormatIeeeFloatPCM,
75
76    /// An unknown format identified by a basic format tag.
77    UnknownBasic(u16),
78
79    /// An unknown format identified by an extension UUID.
80    UnknownExtended(Uuid),
81}
82
83impl CommonFormat {
84    /// Resolve a tag and Uuid to a `CommonFormat`.
85    pub fn make(basic: u16, uuid: Option<Uuid>) -> Self {
86        match (basic, uuid) {
87            (WAVE_TAG_PCM, _) => Self::IntegerPCM,
88            (WAVE_TAG_FLOAT, _) => Self::IeeeFloatPCM,
89            (WAVE_TAG_MPEG, _) => Self::Mpeg,
90            (WAVE_TAG_EXTENDED, Some(WAVE_UUID_PCM)) => Self::IntegerPCM,
91            (WAVE_TAG_EXTENDED, Some(WAVE_UUID_FLOAT)) => Self::IeeeFloatPCM,
92            (WAVE_TAG_EXTENDED, Some(WAVE_UUID_BFORMAT_PCM)) => Self::AmbisonicBFormatIntegerPCM,
93            (WAVE_TAG_EXTENDED, Some(WAVE_UUID_BFORMAT_FLOAT)) => Self::AmbisonicBFormatIeeeFloatPCM,
94            (WAVE_TAG_EXTENDED, Some(x)) => CommonFormat::UnknownExtended(x),
95            (x, _) => CommonFormat::UnknownBasic(x),
96        }
97    }
98
99    /// Get the appropriate tag and `Uuid` for the callee.
100    ///
101    /// If there is no appropriate tag for the format of the callee, the
102    /// returned tag will be 0xFFFE and the `Uuid` will describe the format.
103    pub fn take(self) -> (u16, Uuid) {
104        match self {
105            Self::IntegerPCM => (WAVE_TAG_PCM, WAVE_UUID_PCM),
106            Self::IeeeFloatPCM => (WAVE_TAG_FLOAT, WAVE_UUID_FLOAT),
107            Self::Mpeg => (WAVE_TAG_MPEG, WAVE_UUID_MPEG),
108            Self::AmbisonicBFormatIntegerPCM => (WAVE_TAG_EXTENDED, WAVE_UUID_BFORMAT_PCM),
109            Self::AmbisonicBFormatIeeeFloatPCM => (WAVE_TAG_EXTENDED, WAVE_UUID_BFORMAT_FLOAT),
110            Self::UnknownBasic(x) => (x, uuid_from_basic_tag(x)),
111            Self::UnknownExtended(x) => (WAVE_TAG_EXTENDED, x),
112        }
113    }
114}