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/utility.hpp"
8#include "../macros.hpp"
9#include <bit>
10#include <cstdint>
11#include <string>
12#include <format>
13
14hi_export_module(hikogui.audio.pcm_format);
15
16hi_export namespace hi { inline namespace v1 {
17
18hi_export class pcm_format {
19public:
20 constexpr pcm_format() noexcept = default;
21 constexpr pcm_format(pcm_format&&) noexcept = default;
22 constexpr pcm_format(pcm_format const&) noexcept = default;
23 constexpr pcm_format& operator=(pcm_format&&) noexcept = default;
24 constexpr pcm_format& operator=(pcm_format const&) noexcept = default;
25 [[nodiscard]] friend constexpr bool operator==(pcm_format const&, pcm_format const&) noexcept = default;
26
27 [[nodiscard]] friend constexpr auto operator<=>(pcm_format const &lhs, pcm_format const &rhs) noexcept
28 {
29 if (auto const tmp = lhs._floating_point <=> rhs._floating_point; tmp != std::strong_ordering::equal) {
30 return tmp;
31 }
32 if (auto const tmp = lhs._num_major_bits <=> rhs._num_major_bits; tmp != std::strong_ordering::equal) {
33 return tmp;
34 }
35 if (auto const tmp = lhs._num_minor_bits <=> rhs._num_minor_bits; tmp != std::strong_ordering::equal) {
36 return tmp;
37 }
38 if (auto const tmp = lhs._num_bytes <=> rhs._num_bytes; tmp != std::strong_ordering::equal) {
39 return tmp;
40 }
41 if (auto const tmp = lhs._lsb <=> rhs._lsb; tmp != std::strong_ordering::equal) {
42 return tmp;
43 }
44 return lhs._lsb <=> rhs._lsb;
45 }
46
47 [[nodiscard]] constexpr friend bool equal_except_bit_depth(pcm_format const& lhs, pcm_format const& rhs) noexcept
48 {
49 return lhs._floating_point == rhs._floating_point;
50 }
51
64 constexpr pcm_format(
65 bool floating_point,
66 std::endian endian,
67 bool lsb,
68 uint8_t num_bytes,
69 uint8_t num_major_bits,
70 uint8_t num_minor_bits) noexcept :
71 _floating_point(floating_point),
72 _little_endian(endian == std::endian::little),
73 _lsb(lsb),
74 _num_bytes(num_bytes - 1),
75 _num_major_bits(num_major_bits),
76 _num_minor_bits(num_minor_bits)
77 {
78 hi_assert(num_bytes >= 1 and num_bytes <= 8);
79 hi_assert(num_major_bits >= 0 and num_major_bits <= 15);
80 hi_assert(num_minor_bits >= 1 and num_minor_bits <= 63);
81 }
82
83 [[nodiscard]] constexpr static pcm_format float32() noexcept
84 {
85 return pcm_format{true, std::endian::native, true, 4, 8, 23};
86 }
87
88 [[nodiscard]] constexpr static pcm_format float32_le() noexcept
89 {
90 return pcm_format{true, std::endian::little, true, 4, 8, 23};
91 }
92
93 [[nodiscard]] constexpr static pcm_format float32_be() noexcept
94 {
95 return pcm_format{true, std::endian::big, true, 4, 8, 23};
96 }
97
98 [[nodiscard]] constexpr static pcm_format sint24() noexcept
99 {
100 return pcm_format{false, std::endian::native, true, 3, 0, 23};
101 }
102
103 [[nodiscard]] constexpr static pcm_format sint24_le() noexcept
104 {
105 return pcm_format{false, std::endian::little, true, 3, 0, 23};
106 }
107
108 [[nodiscard]] constexpr static pcm_format sint24_be() noexcept
109 {
110 return pcm_format{false, std::endian::big, true, 3, 0, 23};
111 }
112
113 [[nodiscard]] constexpr static pcm_format sint16() noexcept
114 {
115 return pcm_format{false, std::endian::native, true, 2, 0, 15};
116 }
117
118 [[nodiscard]] constexpr static pcm_format sint16_le() noexcept
119 {
120 return pcm_format{false, std::endian::little, true, 2, 0, 15};
121 }
122
123 [[nodiscard]] constexpr static pcm_format sint16_be() noexcept
124 {
125 return pcm_format{false, std::endian::big, true, 2, 0, 15};
126 }
127
128 [[nodiscard]] constexpr bool empty() const noexcept
129 {
130 return _num_minor_bits == 0;
131 }
132
133 constexpr explicit operator bool() const noexcept
134 {
135 return not empty();
136 }
137
138 [[nodiscard]] constexpr bool floating_point() const noexcept
139 {
140 hi_axiom(not empty());
141 return _floating_point;
142 }
143
144 [[nodiscard]] constexpr bool fixed_point() const noexcept
145 {
146 hi_axiom(not empty());
147 return not floating_point();
148 }
149
150 [[nodiscard]] constexpr std::endian endian() const noexcept
151 {
152 hi_axiom(not empty());
153 return _little_endian ? std::endian::little : std::endian::big;
154 }
155
160 uint8_t num_bytes() const noexcept
161 {
162 hi_axiom(not empty());
163 return narrow_cast<uint8_t>(_num_bytes + 1);
164 }
165
168 [[nodiscard]] constexpr bool lsb() const noexcept
169 {
170 hi_axiom(not empty());
171 return _lsb;
172 }
173
176 [[nodiscard]] constexpr bool msb() const noexcept
177 {
178 hi_axiom(not empty());
179 return not lsb();
180 }
181
190 uint8_t num_bits() const noexcept
191 {
192 hi_axiom(not empty());
193 return narrow_cast<uint8_t>(_num_major_bits + _num_minor_bits + 1);
194 }
195
205 [[nodiscard]] uint8_t num_exponent_bits() const noexcept
206 {
207 hi_axiom(floating_point());
208 return _num_major_bits;
209 }
210
218 [[nodiscard]] uint8_t num_mantissa_bits() const noexcept
219 {
220 hi_axiom(floating_point());
221 return _num_minor_bits;
222 }
223
235 [[nodiscard]] uint8_t num_integral_bits() const noexcept
236 {
237 hi_axiom(fixed_point());
238 return _num_major_bits;
239 }
240
252 [[nodiscard]] uint8_t num_fraction_bits() const noexcept
253 {
254 hi_axiom(fixed_point());
255 return _num_minor_bits;
256 }
257
258 [[nodiscard]] friend std::string to_string(pcm_format const& rhs) noexcept
259 {
260 if (rhs.floating_point()) {
261 if (rhs.endian() == std::endian::native) {
262 return std::format("float-{}", rhs.num_bits());
263 } else {
264 return std::format("float-{}_{}", rhs.num_bits(), rhs.endian() == std::endian::little ? "le" : "be");
265 }
266
267 } else if (rhs.num_integral_bits() == 0) {
268 if (rhs.endian() == std::endian::native) {
269 return std::format("int-{}", rhs.num_bits());
270 } else {
271 return std::format("int-{}_{}", rhs.num_bits(), rhs.endian() == std::endian::little ? "le" : "be");
272 }
273
274 } else {
275 if (rhs.endian() == std::endian::native) {
276 return std::format("Q{}.{}", rhs.num_integral_bits(), rhs.num_fraction_bits());
277 } else {
278 return std::format(
279 "Q{}.{}_{}",
280 rhs.num_integral_bits(),
281 rhs.num_fraction_bits(),
282 rhs.endian() == std::endian::little ? "le" : "be");
283 }
284 }
285 }
286
287private:
288 uint16_t _floating_point : 1 = 0;
289 uint16_t _little_endian : 1 = 0;
290 uint16_t _lsb : 1 = 0;
291 uint16_t _num_bytes : 3 = 0;
292 uint16_t _num_major_bits : 4 = 0;
293 uint16_t _num_minor_bits : 6 = 0;
294};
295
296}} // namespace hi::inline v1
297
298// XXX #617 MSVC bug does not handle partial specialization in modules.
299hi_export template<>
300struct std::formatter<hi::pcm_format, char> : std::formatter<std::string_view, char> {
301 auto format(hi::pcm_format const& t, auto& fc) const
302 {
303 return std::formatter<std::string_view, char>::format(to_string(t), fc);
304 }
305};
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition pcm_format.hpp:18
uint8_t num_exponent_bits() const noexcept
The number of bits in the exponent.
Definition pcm_format.hpp:205
constexpr bool msb() const noexcept
The sample is stored in the most-significant-bits of the storage.
Definition pcm_format.hpp:176
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:190
uint8_t num_fraction_bits() const noexcept
The number of fractional bits.
Definition pcm_format.hpp:252
constexpr bool lsb() const noexcept
The sample is stored in the least-significant-bits of the storage.
Definition pcm_format.hpp:168
uint8_t num_mantissa_bits() const noexcept
The number of bits in the mantissa.
Definition pcm_format.hpp:218
uint8_t num_bytes() const noexcept
The number of bytes a sample is stored in.
Definition pcm_format.hpp:160
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:64
uint8_t num_integral_bits() const noexcept
The number of integral bits.
Definition pcm_format.hpp:235
T to_string(T... args)