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}