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