HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
pcm_format.hpp
1// Copyright Take Vos 2022.
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 <bit>
10#include <cstdint>
11#include <string>
12#include <format>
13
14namespace hi::inline v1 {
15
17public:
18 constexpr pcm_format() noexcept = default;
19 constexpr pcm_format(pcm_format&&) noexcept = default;
20 constexpr pcm_format(pcm_format const&) noexcept = default;
21 constexpr pcm_format& operator=(pcm_format&&) noexcept = default;
22 constexpr pcm_format& operator=(pcm_format const&) noexcept = default;
23 [[nodiscard]] friend constexpr bool operator==(pcm_format const&, pcm_format const&) noexcept = default;
24
25 [[nodiscard]] friend constexpr auto operator<=>(pcm_format const &lhs, pcm_format const &rhs) noexcept
26 {
27 if (hilet tmp = lhs._floating_point <=> rhs._floating_point; tmp != std::strong_ordering::equal) {
28 return tmp;
29 }
30 if (hilet tmp = lhs._num_major_bits <=> rhs._num_major_bits; tmp != std::strong_ordering::equal) {
31 return tmp;
32 }
33 if (hilet tmp = lhs._num_minor_bits <=> rhs._num_minor_bits; tmp != std::strong_ordering::equal) {
34 return tmp;
35 }
36 if (hilet tmp = lhs._num_bytes <=> rhs._num_bytes; tmp != std::strong_ordering::equal) {
37 return tmp;
38 }
39 if (hilet tmp = lhs._lsb <=> rhs._lsb; tmp != std::strong_ordering::equal) {
40 return tmp;
41 }
42 return lhs._lsb <=> rhs._lsb;
43 }
44
45 [[nodiscard]] constexpr friend bool equal_except_bit_depth(pcm_format const& lhs, pcm_format const& rhs) noexcept
46 {
47 return lhs._floating_point == rhs._floating_point;
48 }
49
62 constexpr pcm_format(
63 bool floating_point,
64 std::endian endian,
65 bool lsb,
66 uint8_t num_bytes,
67 uint8_t num_major_bits,
68 uint8_t num_minor_bits) noexcept :
69 _floating_point(floating_point),
70 _little_endian(endian == std::endian::little),
71 _lsb(lsb),
72 _num_bytes(num_bytes - 1),
73 _num_major_bits(num_major_bits),
74 _num_minor_bits(num_minor_bits)
75 {
76 hi_assert(num_bytes >= 1 and num_bytes <= 8);
77 hi_assert(num_major_bits >= 0 and num_major_bits <= 15);
78 hi_assert(num_minor_bits >= 1 and num_minor_bits <= 63);
79 }
80
81 [[nodiscard]] constexpr static pcm_format float32() noexcept
82 {
83 return pcm_format{true, std::endian::native, true, 4, 8, 23};
84 }
85
86 [[nodiscard]] constexpr static pcm_format float32_le() noexcept
87 {
88 return pcm_format{true, std::endian::little, true, 4, 8, 23};
89 }
90
91 [[nodiscard]] constexpr static pcm_format float32_be() noexcept
92 {
93 return pcm_format{true, std::endian::big, true, 4, 8, 23};
94 }
95
96 [[nodiscard]] constexpr static pcm_format sint24() noexcept
97 {
98 return pcm_format{false, std::endian::native, true, 3, 0, 23};
99 }
100
101 [[nodiscard]] constexpr static pcm_format sint24_le() noexcept
102 {
103 return pcm_format{false, std::endian::little, true, 3, 0, 23};
104 }
105
106 [[nodiscard]] constexpr static pcm_format sint24_be() noexcept
107 {
108 return pcm_format{false, std::endian::big, true, 3, 0, 23};
109 }
110
111 [[nodiscard]] constexpr static pcm_format sint16() noexcept
112 {
113 return pcm_format{false, std::endian::native, true, 2, 0, 15};
114 }
115
116 [[nodiscard]] constexpr static pcm_format sint16_le() noexcept
117 {
118 return pcm_format{false, std::endian::little, true, 2, 0, 15};
119 }
120
121 [[nodiscard]] constexpr static pcm_format sint16_be() noexcept
122 {
123 return pcm_format{false, std::endian::big, true, 2, 0, 15};
124 }
125
126 [[nodiscard]] constexpr bool empty() const noexcept
127 {
128 return _num_minor_bits == 0;
129 }
130
131 constexpr explicit operator bool() const noexcept
132 {
133 return not empty();
134 }
135
136 [[nodiscard]] constexpr bool floating_point() const noexcept
137 {
138 hi_axiom(not empty());
139 return _floating_point;
140 }
141
142 [[nodiscard]] constexpr bool fixed_point() const noexcept
143 {
144 hi_axiom(not empty());
145 return not floating_point();
146 }
147
148 [[nodiscard]] constexpr std::endian endian() const noexcept
149 {
150 hi_axiom(not empty());
151 return _little_endian ? std::endian::little : std::endian::big;
152 }
153
158 uint8_t num_bytes() const noexcept
159 {
160 hi_axiom(not empty());
161 return narrow_cast<uint8_t>(_num_bytes + 1);
162 }
163
166 [[nodiscard]] constexpr bool lsb() const noexcept
167 {
168 hi_axiom(not empty());
169 return _lsb;
170 }
171
174 [[nodiscard]] constexpr bool msb() const noexcept
175 {
176 hi_axiom(not empty());
177 return not lsb();
178 }
179
188 uint8_t num_bits() const noexcept
189 {
190 hi_axiom(not empty());
191 return narrow_cast<uint8_t>(_num_major_bits + _num_minor_bits + 1);
192 }
193
203 [[nodiscard]] uint8_t num_exponent_bits() const noexcept
204 {
205 hi_axiom(floating_point());
206 return _num_major_bits;
207 }
208
216 [[nodiscard]] uint8_t num_mantissa_bits() const noexcept
217 {
218 hi_axiom(floating_point());
219 return _num_minor_bits;
220 }
221
233 [[nodiscard]] uint8_t num_integral_bits() const noexcept
234 {
235 hi_axiom(fixed_point());
236 return _num_major_bits;
237 }
238
250 [[nodiscard]] uint8_t num_fraction_bits() const noexcept
251 {
252 hi_axiom(fixed_point());
253 return _num_minor_bits;
254 }
255
256 [[nodiscard]] friend std::string to_string(pcm_format const& rhs) noexcept
257 {
258 if (rhs.floating_point()) {
259 if (rhs.endian() == std::endian::native) {
260 return std::format("float-{}", rhs.num_bits());
261 } else {
262 return std::format("float-{}_{}", rhs.num_bits(), rhs.endian() == std::endian::little ? "le" : "be");
263 }
264
265 } else if (rhs.num_integral_bits() == 0) {
266 if (rhs.endian() == std::endian::native) {
267 return std::format("int-{}", rhs.num_bits());
268 } else {
269 return std::format("int-{}_{}", rhs.num_bits(), rhs.endian() == std::endian::little ? "le" : "be");
270 }
271
272 } else {
273 if (rhs.endian() == std::endian::native) {
274 return std::format("Q{}.{}", rhs.num_integral_bits(), rhs.num_fraction_bits());
275 } else {
276 return std::format(
277 "Q{}.{}_{}",
278 rhs.num_integral_bits(),
279 rhs.num_fraction_bits(),
280 rhs.endian() == std::endian::little ? "le" : "be");
281 }
282 }
283 }
284
285private:
286 uint16_t _floating_point : 1 = 0;
287 uint16_t _little_endian : 1 = 0;
288 uint16_t _lsb : 1 = 0;
289 uint16_t _num_bytes : 3 = 0;
290 uint16_t _num_major_bits : 4 = 0;
291 uint16_t _num_minor_bits : 6 = 0;
292};
293
294} // namespace hi::inline v1
295
296template<typename CharT>
297struct std::formatter<hi::pcm_format, CharT> : std::formatter<std::string_view, CharT> {
298 auto format(hi::pcm_format const& t, auto& fc)
299 {
300 return std::formatter<std::string_view, CharT>::format(to_string(t), fc);
301 }
302};
Utilities to assert and bound check.
#define hi_axiom(expression)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
#define hi_assert(expression)
Assert if expression is true.
Definition assert.hpp:86
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
The HikoGUI namespace.
Definition ascii.hpp:19
Definition pcm_format.hpp:16
uint8_t num_bytes() const noexcept
The number of bytes a sample is stored in.
Definition pcm_format.hpp:158
constexpr bool lsb() const noexcept
The sample is stored in the least-significant-bits of the storage.
Definition pcm_format.hpp:166
uint8_t num_mantissa_bits() const noexcept
The number of bits in the mantissa.
Definition pcm_format.hpp:216
uint8_t num_exponent_bits() const noexcept
The number of bits in the exponent.
Definition pcm_format.hpp:203
uint8_t num_fraction_bits() const noexcept
The number of fractional bits.
Definition pcm_format.hpp:250
uint8_t num_integral_bits() const noexcept
The number of integral bits.
Definition pcm_format.hpp:233
constexpr pcm_format(bool floating_point, std::endian endian, bool lsb, uint8_t num_bytes, uint8_t num_major_bits, uint8_t num_minor_bits) noexcept
Construct a PCM format.
Definition pcm_format.hpp:62
constexpr bool msb() const noexcept
The sample is stored in the most-significant-bits of the storage.
Definition pcm_format.hpp:174
uint8_t num_bits() const noexcept
The number of least significant bits of the storage that is used by the sample.
Definition pcm_format.hpp:188
T to_string(T... args)