Skip to main content

display_types/cea861/
speaker.rs

1bitflags::bitflags! {
2    /// Speaker channel presence flags, byte 1 of the Speaker Allocation Data Block.
3    ///
4    /// | Bit | Mask   | Channels                        |
5    /// |-----|--------|---------------------------------|
6    /// | 7   | `0x80` | FLW/FRW (Front Left/Right Wide) |
7    /// | 6   | `0x40` | RLC/RRC (Rear Left/Right Center)|
8    /// | 5   | `0x20` | FLC/FRC (Front Left/Right Ctr)  |
9    /// | 4   | `0x10` | BC (Back Center)                |
10    /// | 3   | `0x08` | BL/BR (Back Left/Right)         |
11    /// | 2   | `0x04` | FC (Front Center)               |
12    /// | 1   | `0x02` | LFE1 (Low-Frequency Effects 1)  |
13    /// | 0   | `0x01` | FL/FR (Front Left/Right)        |
14    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
16    pub struct SpeakerAllocationFlags: u8 {
17        /// Front Left / Front Right channels.
18        const FL_FR   = 0x01;
19        /// Low-Frequency Effects channel 1.
20        const LFE1    = 0x02;
21        /// Front Center channel.
22        const FC      = 0x04;
23        /// Back Left / Back Right channels.
24        const BL_BR   = 0x08;
25        /// Back Center channel.
26        const BC      = 0x10;
27        /// Front Left Center / Front Right Center channels.
28        const FLC_FRC = 0x20;
29        /// Rear Left Center / Rear Right Center channels.
30        const RLC_RRC = 0x40;
31        /// Front Left Wide / Front Right Wide channels.
32        const FLW_FRW = 0x80;
33    }
34}
35
36bitflags::bitflags! {
37    /// Speaker channel presence flags, byte 2 of the Speaker Allocation Data Block.
38    ///
39    /// | Bit | Mask   | Channels                           |
40    /// |-----|--------|------------------------------------|
41    /// | 7   | `0x80` | TpSiL/TpSiR (Top Side Left/Right)  |
42    /// | 6   | `0x40` | SiL/SiR (Side Left/Right)          |
43    /// | 5   | `0x20` | TpBC (Top Back Center)             |
44    /// | 4   | `0x10` | LFE2 (Low-Frequency Effects 2)     |
45    /// | 3   | `0x08` | LS/RS (Left/Right Surround)        |
46    /// | 2   | `0x04` | TpFC (Top Front Center)            |
47    /// | 1   | `0x02` | TpC (Top Center)                   |
48    /// | 0   | `0x01` | TpFL/TpFR (Top Front Left/Right)   |
49    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
51    pub struct SpeakerAllocationFlags2: u8 {
52        /// Top Front Left / Top Front Right channels.
53        const TP_FL_FR        = 0x01;
54        /// Top Center channel.
55        const TP_C            = 0x02;
56        /// Top Front Center channel.
57        const TP_FC           = 0x04;
58        /// Left Surround / Right Surround channels.
59        const LS_RS           = 0x08;
60        /// Low-Frequency Effects channel 2.
61        const LFE2            = 0x10;
62        /// Top Back Center channel.
63        const TP_BC           = 0x20;
64        /// Side Left / Side Right channels.
65        const SI_L_SI_R       = 0x40;
66        /// Top Side Left / Top Side Right channels.
67        const TP_SI_L_TP_SI_R = 0x80;
68    }
69}
70
71bitflags::bitflags! {
72    /// Speaker channel presence flags, byte 3 of the Speaker Allocation Data Block.
73    ///
74    /// | Bit | Mask   | Channels                              |
75    /// |-----|--------|---------------------------------------|
76    /// | 3   | `0x08` | TpLS/TpRS (Top Left/Right Surround)   |
77    /// | 2   | `0x04` | BtFL/BtFR (Bottom Front Left/Right)   |
78    /// | 1   | `0x02` | BtFC (Bottom Front Center)            |
79    /// | 0   | `0x01` | TpBL/TpBR (Top Back Left/Right)       |
80    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
81    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
82    pub struct SpeakerAllocationFlags3: u8 {
83        /// Top Back Left / Top Back Right channels.
84        const TP_BL_TP_BR = 0x01;
85        /// Bottom Front Center channel.
86        const BT_FC       = 0x02;
87        /// Bottom Front Left / Bottom Front Right channels.
88        const BT_FL_BT_FR = 0x04;
89        /// Top Left Surround / Top Right Surround channels.
90        const TP_LS_TP_RS = 0x08;
91    }
92}
93
94/// Decoded Speaker Allocation Data Block (standard tag `0x04`).
95#[non_exhaustive]
96#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct SpeakerAllocation {
99    /// Channels from byte 1 (core speaker channels).
100    pub channels: SpeakerAllocationFlags,
101    /// Channels from byte 2 (extended — top/surround/LFE2).
102    pub channels_2: SpeakerAllocationFlags2,
103    /// Channels from byte 3 (extended — top-back/bottom-front).
104    pub channels_3: SpeakerAllocationFlags3,
105}
106
107impl SpeakerAllocation {
108    /// Constructs a `SpeakerAllocation`.
109    pub fn new(
110        channels: SpeakerAllocationFlags,
111        channels_2: SpeakerAllocationFlags2,
112        channels_3: SpeakerAllocationFlags3,
113    ) -> Self {
114        Self {
115            channels,
116            channels_2,
117            channels_3,
118        }
119    }
120}
121
122/// Decoded Room Configuration Data Block (extended tag `0x13`).
123///
124/// Describes the number of loudspeakers in the listening room and whether
125/// individual speaker locations are provided in an accompanying
126/// Speaker Location Data Block (extended tag `0x14`).
127#[non_exhaustive]
128#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub struct RoomConfigurationBlock {
131    /// Number of loudspeakers in the room (bits 4:0).  `0` means not specified.
132    pub speaker_count: u8,
133    /// If `true`, individual speaker location entries are present in an
134    /// accompanying Speaker Location Data Block (extended tag `0x14`).
135    pub has_speaker_locations: bool,
136}
137
138impl RoomConfigurationBlock {
139    /// Constructs a `RoomConfigurationBlock`.
140    pub fn new(speaker_count: u8, has_speaker_locations: bool) -> Self {
141        Self {
142            speaker_count,
143            has_speaker_locations,
144        }
145    }
146}
147
148/// A single speaker location entry from the Speaker Location Data Block
149/// (extended tag `0x14`).
150///
151/// Each entry is two bytes: a channel assignment and a normalized distance
152/// from the listener (0 = closest, 255 = furthest).
153#[non_exhaustive]
154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
156pub struct SpeakerLocationEntry {
157    /// Channel assignment code (speaker role).
158    ///
159    /// Values follow the CTA-861-I Table 49 channel assignment codes
160    /// (e.g. `0x00` = FL/FR, `0x01` = LFE1, `0x02` = FC, etc.).
161    pub channel_assignment: u8,
162    /// Normalized distance from the listener position.
163    ///
164    /// `0` = at or very close to the listener; `255` = furthest.
165    /// The absolute distance is not encoded.
166    pub distance: u8,
167}
168
169impl SpeakerLocationEntry {
170    /// Constructs a `SpeakerLocationEntry`.
171    pub fn new(channel_assignment: u8, distance: u8) -> Self {
172        Self {
173            channel_assignment,
174            distance,
175        }
176    }
177}