HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
speaker_mapping.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../assert.hpp"
8#include "../cast.hpp"
9#include "../pickle.hpp"
10#include "../text/ttauri_icon.hpp"
11#include <array>
12#include <string>
13#include <iostream>
14
15namespace tt {
16
17enum class speaker_mapping : uint64_t {
21 direct = 0x0'0000,
22
23 front_left = 0x0'0001,
24 front_right = 0x0'0002,
25 front_center = 0x0'0004,
26 low_frequency = 0x0'0008,
27 back_left = 0x0'0010,
28 back_right = 0x0'0020,
29 front_left_of_center = 0x0'0040,
30 front_right_of_center = 0x0'0080,
31 back_center = 0x0'0100,
32 side_left = 0x0'0200,
33 side_right = 0x0'0400,
34 top_center = 0x0'0800,
35 top_front_left = 0x0'1000,
36 top_front_center = 0x0'2000,
37 top_front_right = 0x0'4000,
38 top_back_left = 0x0'8000,
39 top_back_center = 0x1'0000,
40 top_back_right = 0x2'0000,
41
42 // A couple of isolated channel definitions
43 none = direct,
44 iso_0 = direct | (0ULL << 32),
45 iso_1 = direct | (1ULL << 32),
46 iso_2 = direct | (2ULL << 32),
47 iso_3 = direct | (3ULL << 32),
48 iso_4 = direct | (4ULL << 32),
49 iso_5 = direct | (5ULL << 32),
50 iso_6 = direct | (6ULL << 32),
51 iso_7 = direct | (7ULL << 32),
52 iso_8 = direct | (8ULL << 32),
53
54 // Standard
55 mono_1_0 = front_center,
56 stereo_2_0 = front_left | front_right,
57
58 // Music configuration
59 stereo_2_1 = stereo_2_0 | low_frequency,
60 stereo_3_0 = stereo_2_0 | front_center,
61 stereo_3_1 = stereo_3_0 | low_frequency,
62 quad_4_0 = stereo_2_0 | back_left | back_right,
63 quad_side_4_0 = stereo_2_0 | side_left | side_right,
64 hexagonal_6_0 = quad_4_0 | front_center | back_center,
65 hexagonal_6_1 = hexagonal_6_0 | low_frequency,
66 octagonal_8_0 = hexagonal_6_0 | side_left | side_right,
67
68 // Standard surround sound
69 surround_3_0 = stereo_2_0 | back_center,
70 surround_4_0 = surround_3_0 | front_center,
71 surround_4_1 = surround_4_0 | low_frequency,
72 surround_5_0 = quad_4_0 | front_center,
73 surround_5_1 = surround_5_0 | low_frequency,
74 surround_7_0 = surround_5_0 | side_left | side_right,
75 surround_7_1 = surround_7_0 | low_frequency,
76 surround_9_0 = surround_7_0 | top_front_left | top_front_right,
77 surround_9_1 = surround_9_0 | low_frequency,
78 surround_11_0 = surround_9_0 | front_left_of_center | front_right_of_center,
79 surround_11_1 = surround_11_0 | low_frequency,
80
81 // Surround sound with side speakers instead of left/right back speakers.
82 surround_side_5_0 = quad_side_4_0 | front_center,
83 surround_side_5_1 = surround_side_5_0 | low_frequency,
84 surround_side_6_0 = surround_side_5_0 | back_center,
85 surround_side_6_1 = surround_side_6_0 | low_frequency,
86 surround_side_7_0 = surround_side_5_0 | front_left_of_center | front_right_of_center,
87 surround_side_7_1 = surround_side_7_0 | low_frequency,
88
89 // Surround sound with extra front speakers.
90 surround_wide_6_0 = surround_4_0 | front_left_of_center | front_right_of_center,
91 surround_wide_6_1 = surround_wide_6_0 | low_frequency,
92 surround_wide_7_0 = surround_5_0 | front_left_of_center | front_right_of_center,
93 surround_wide_7_1 = surround_wide_7_0 | low_frequency,
94
95 // Surround with extra top speakers
96 surround_atmos_5_1_4 = surround_5_1 | top_front_left | top_front_right | top_back_left | top_back_right,
97 surround_atmos_7_1_4 = surround_7_1 | top_front_left | top_front_right | top_back_left | top_back_right,
98};
99
100[[nodiscard]] constexpr bool to_bool(speaker_mapping const &rhs) noexcept
101{
102 return static_cast<bool>(static_cast<uint64_t>(rhs));
103}
104
105[[nodiscard]] constexpr bool holds_invariant(speaker_mapping const &rhs) noexcept
106{
107 auto rhs_ = static_cast<uint64_t>(rhs);
108 return static_cast<uint32_t>(rhs_) ? (rhs_ >> 32) == 0 : (rhs_ >> 32) > 0;
109}
110
111[[nodiscard]] constexpr bool is_direct(speaker_mapping const &rhs) noexcept
112{
113 return static_cast<uint32_t>(static_cast<uint64_t>(rhs)) == 0;
114}
115
116[[nodiscard]] constexpr bool is_empty(speaker_mapping const &rhs) noexcept
117{
118 return to_underlying(rhs) == 0;
119}
120
121[[nodiscard]] constexpr speaker_mapping make_direct_speaker_mapping(size_t num_speakers) noexcept
122{
123 tt_axiom(num_speakers <= std::numeric_limits<uint32_t>::max());
124 ttlet r = static_cast<speaker_mapping>(num_speakers << 32);
125 tt_axiom(holds_invariant(r));
126 return r;
127}
128
129[[nodiscard]] constexpr speaker_mapping operator|(speaker_mapping const &lhs, speaker_mapping const &rhs) noexcept
130{
131 tt_axiom((is_empty(lhs) or not is_direct(lhs)) and (is_empty(rhs) or not is_direct(rhs)));
132
133 ttlet r = static_cast<speaker_mapping>(to_underlying(lhs) | to_underlying(rhs));
134 tt_axiom(holds_invariant(r));
135 return r;
136}
137
138[[nodiscard]] constexpr speaker_mapping operator&(speaker_mapping const &lhs, speaker_mapping const &rhs) noexcept
139{
140 tt_axiom(not is_direct(lhs) and not is_direct(rhs));
141
142 ttlet r = static_cast<speaker_mapping>(to_underlying(lhs) & to_underlying(rhs));
143 tt_axiom(holds_invariant(r));
144 return r;
145}
146
147constexpr speaker_mapping &operator|=(speaker_mapping &lhs, speaker_mapping const &rhs) noexcept
148{
149 return lhs = lhs | rhs;
150}
151
152constexpr speaker_mapping &operator&=(speaker_mapping &lhs, speaker_mapping const &rhs) noexcept
153{
154 return lhs = lhs & rhs;
155}
156
157[[nodiscard]] constexpr size_t num_channels(speaker_mapping const &rhs) noexcept
158{
159 if (is_direct(rhs)) {
160 return static_cast<uint64_t>(rhs) >> 32;
161 } else {
162 return std::popcount(static_cast<uint64_t>(rhs));
163 }
164}
165
166[[nodiscard]] std::string to_string(speaker_mapping rhs) noexcept;
167
168inline std::ostream &operator<<(std::ostream &lhs, speaker_mapping rhs)
169{
170 return lhs << to_string(rhs);
171}
172
174 speaker_mapping mapping;
175 ttauri_icon icon;
176 char const *name;
177};
178
179constexpr auto speaker_mappings = std::array{
180 speaker_mapping_info{speaker_mapping::mono_1_0, ttauri_icon::mono_1_0, "Mono 1.0"},
181 speaker_mapping_info{speaker_mapping::stereo_2_0, ttauri_icon::stereo_2_0, "Stereo 2.0"},
182 speaker_mapping_info{speaker_mapping::stereo_2_1, ttauri_icon::stereo_2_1, "Stereo 2.1"},
183 speaker_mapping_info{speaker_mapping::stereo_3_0, ttauri_icon::stereo_3_0, "Stereo 3.0"},
184 speaker_mapping_info{speaker_mapping::stereo_3_1, ttauri_icon::stereo_3_1, "Stereo 3.1"},
185 speaker_mapping_info{speaker_mapping::quad_4_0, ttauri_icon::quad_4_0, "Quad 4.0"},
186 speaker_mapping_info{speaker_mapping::quad_side_4_0, ttauri_icon::quad_side_4_0, "Quad 4.0 (side)"},
187 speaker_mapping_info{speaker_mapping::hexagonal_6_0, ttauri_icon::hexagonal_6_0, "Hexagonal 6.0"},
188 speaker_mapping_info{speaker_mapping::hexagonal_6_1, ttauri_icon::hexagonal_6_1, "Hexagonal 6.1"},
189 speaker_mapping_info{speaker_mapping::octagonal_8_0, ttauri_icon::octagonal_8_0, "Octagonal 8.0"},
190 speaker_mapping_info{speaker_mapping::surround_3_0, ttauri_icon::surround_3_0, "Surround 3.0"},
191 speaker_mapping_info{speaker_mapping::surround_4_0, ttauri_icon::surround_4_0, "Surround 4.0"},
192 speaker_mapping_info{speaker_mapping::surround_4_1, ttauri_icon::surround_4_1, "Surround 4.1"},
193 speaker_mapping_info{speaker_mapping::surround_5_0, ttauri_icon::surround_5_0, "Surround 5.0"},
194 speaker_mapping_info{speaker_mapping::surround_5_1, ttauri_icon::surround_5_1, "Surround 5.1"},
195 speaker_mapping_info{speaker_mapping::surround_7_0, ttauri_icon::surround_7_0, "Surround 7.0"},
196 speaker_mapping_info{speaker_mapping::surround_7_1, ttauri_icon::surround_7_1, "Surround 7.1"},
197 speaker_mapping_info{speaker_mapping::surround_9_0, ttauri_icon::surround_9_0, "Surround 9.0"},
198 speaker_mapping_info{speaker_mapping::surround_9_1, ttauri_icon::surround_9_1, "Surround 9.1"},
199 speaker_mapping_info{speaker_mapping::surround_11_0, ttauri_icon::surround_11_0, "Surround 11.0"},
200 speaker_mapping_info{speaker_mapping::surround_11_1, ttauri_icon::surround_11_1, "Surround 11.1"},
201 speaker_mapping_info{speaker_mapping::surround_side_5_0, ttauri_icon::surround_side_5_0, "Surround 5.0 (side)"},
202 speaker_mapping_info{speaker_mapping::surround_side_5_1, ttauri_icon::surround_side_5_1, "Surround 5.1 (side)"},
203 speaker_mapping_info{speaker_mapping::surround_side_6_0, ttauri_icon::surround_side_6_0, "Surround 6.0 (side)"},
204 speaker_mapping_info{speaker_mapping::surround_side_6_1, ttauri_icon::surround_side_6_1, "Surround 6.1 (side)"},
205 speaker_mapping_info{speaker_mapping::surround_side_7_0, ttauri_icon::surround_side_7_0, "Surround 7.0 (side)"},
206 speaker_mapping_info{speaker_mapping::surround_side_7_1, ttauri_icon::surround_side_7_1, "Surround 7.1 (side)"},
207 speaker_mapping_info{speaker_mapping::surround_wide_6_0, ttauri_icon::surround_wide_6_0, "Surround 6.0 (wide)"},
208 speaker_mapping_info{speaker_mapping::surround_wide_6_1, ttauri_icon::surround_wide_6_1, "Surround 6.1 (wide)"},
209 speaker_mapping_info{speaker_mapping::surround_wide_7_0, ttauri_icon::surround_wide_7_0, "Surround 7.0 (wide)"},
210 speaker_mapping_info{speaker_mapping::surround_wide_7_1, ttauri_icon::surround_wide_7_1, "Surround 7.1 (wide)"},
211 speaker_mapping_info{speaker_mapping::surround_atmos_5_1_4, ttauri_icon::surround_atmos_5_1_4, "Atmos 5.1.4"},
212 speaker_mapping_info{speaker_mapping::surround_atmos_7_1_4, ttauri_icon::surround_atmos_7_1_4, "Atmos 7.1.4"},
213};
214
215template<>
216struct pickle<speaker_mapping> {
217 [[nodiscard]] datum encode(speaker_mapping const &rhs) const noexcept
218 {
219 return datum{narrow_cast<long long>(to_underlying(rhs))};
220 }
221
222 [[nodiscard]] speaker_mapping decode(long long rhs) const
223 {
224 tt_parse_check(rhs >= 0, "Expect speaker mapping to be encoded as a natural number, got {}.", rhs);
225 return static_cast<speaker_mapping>(rhs);
226 }
227
228 [[nodiscard]] speaker_mapping decode(datum const &rhs) const
229 {
230 if (auto *i = get_if<long long>(rhs)) {
231 return decode(*i);
232 } else {
233 throw parse_error("Expect speaker mapping to be encoded as a integer, got {}", rhs);
234 }
235 }
236};
237
238} // namespace tt
@ top_center
Align to the top and horizontal-center.
constexpr alignment operator|(vertical_alignment lhs, horizontal_alignment rhs) noexcept
Combine vertical and horizontal alignment.
Definition alignment.hpp:91
Definition speaker_mapping.hpp:173
A dynamic data type.
Definition datum.hpp:213
Exception thrown during parsing on an error.
Definition exception.hpp:26
An image, in different formats.
Definition icon.hpp:19
Encode and decode a type to and from a UTF-8 string.
Definition pickle.hpp:22
T decode(datum rhs) const
Decode a UTF-8 string into a value of a given type.
datum encode(T const &rhs) const noexcept
Encode the value of a type into a UTF-8 string.
T to_string(T... args)