7#include "audio_stream_format.hpp"
8#include "speaker_mapping_win32.hpp"
9#include "../macros.hpp"
12hi_export_module(hikogui.audio.audio_stream_format_win32);
14hi_export
namespace hi {
inline namespace v1 {
16hi_export [[nodiscard]]
inline bool win32_use_extensible(audio_stream_format x)
noexcept{
17 if (to_bool(x.speaker_mapping)) {
26hi_export [[nodiscard]]
inline WAVEFORMATEXTENSIBLE audio_stream_format_to_win32(audio_stream_format stream_format,
bool extensible)
noexcept{
27 hi_axiom(stream_format.holds_invariant());
28 hi_axiom(not win32_use_extensible(stream_format) or extensible);
30 auto r = WAVEFORMATEXTENSIBLE{};
33 r.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
38 r.Format.wFormatTag = stream_format.format.floating_point() ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM;
43 r.Format.nChannels = narrow_cast<WORD>(stream_format.num_channels);
44 r.Format.nSamplesPerSec = narrow_cast<DWORD>(stream_format.sample_rate);
45 r.Format.nAvgBytesPerSec = narrow_cast<DWORD>(stream_format.sample_rate * stream_format.num_channels * stream_format.format.num_bytes());
46 r.Format.nBlockAlign = narrow_cast<WORD>(stream_format.num_channels * stream_format.format.num_bytes());
47 r.Format.wBitsPerSample = narrow_cast<WORD>(stream_format.format.num_bytes() * 8);
50 r.Samples.wValidBitsPerSample = narrow_cast<WORD>(stream_format.format.num_bits());
51 r.dwChannelMask = speaker_mapping_to_win32(stream_format.speaker_mapping);
52 r.SubFormat = stream_format.format.floating_point() ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM;
56hi_export [[nodiscard]]
inline audio_stream_format audio_stream_format_from_win32(WAVEFORMATEXTENSIBLE
const& wave_format){
57 auto r = audio_stream_format{};
59 hi_check(wave_format.Format.wBitsPerSample % 8 == 0,
"wBitsPerSample is not multiple of 8");
60 hi_check(wave_format.Format.wBitsPerSample > 0,
"wBitsPerSample is 0");
61 hi_check(wave_format.Format.wBitsPerSample <= 32,
"wBitsPerSample is more than 32");
62 hi_check(wave_format.Samples.wValidBitsPerSample > 0,
"wValidBitsPerSample is 0");
64 wave_format.Samples.wValidBitsPerSample <= wave_format.Format.wBitsPerSample,
"wValidBitsPerSample > wBitsPerSample");
65 hi_check(wave_format.Format.nSamplesPerSec > 0,
"nSamplesPerSec is zero");
68 if (wave_format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) {
69 hi_check(wave_format.Format.wBitsPerSample == 32,
"wBitsPerSample is not 32");
70 r.format = pcm_format{
true, std::endian::native,
true, 4, 8, 23};
72 }
else if (wave_format.SubFormat == KSDATAFORMAT_SUBTYPE_PCM) {
73 auto const num_bytes = narrow_cast<uint8_t>(wave_format.Format.wBitsPerSample / 8);
74 auto const num_minor_bits = narrow_cast<uint8_t>(wave_format.Samples.wValidBitsPerSample - 1);
75 r.format = pcm_format{
false, std::endian::native,
true, num_bytes, 0, num_minor_bits};
77 throw parse_error(
"Unknown SubFormat");
80 hi_check(wave_format.Format.nChannels > 0,
"nChannels is zero");
81 r.num_channels = wave_format.Format.nChannels;
83 r.speaker_mapping = speaker_mapping_from_win32(wave_format.dwChannelMask);
84 hi_check(popcount(r.speaker_mapping) == 0 or popcount(r.speaker_mapping) == r.num_channels,
"nChannels is zero");
86 r.sample_rate = narrow_cast<uint32_t>(wave_format.Format.nSamplesPerSec);
90hi_export [[nodiscard]]
inline audio_stream_format audio_stream_format_from_win32(WAVEFORMATEX
const& wave_format){
91 auto r = audio_stream_format{};
92 hi_check(wave_format.wBitsPerSample > 0,
"wBitsPerSample is zero");
93 hi_check(wave_format.wBitsPerSample % 8 == 0,
"wBitsPerSample is not multiple of 8");
94 hi_check(wave_format.wBitsPerSample <= 32,
"wBitsPerSample greater than 32");
95 hi_check(wave_format.nSamplesPerSec > 0,
"nSamplesPerSec is zero");
97 hi_check(wave_format.nChannels > 0,
"nChannels is zero");
99 if (wave_format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
100 if (wave_format.cbSize < (
sizeof(WAVEFORMATEXTENSIBLE) -
sizeof(WAVEFORMATEX))) {
101 throw parse_error(std::format(
"WAVEFORMATEXTENSIBLE has incorrect size {}", wave_format.cbSize));
103 return audio_stream_format_from_win32(*std::launder(
reinterpret_cast<WAVEFORMATEXTENSIBLE
const *
>(&wave_format)));
105 }
else if (wave_format.wFormatTag == WAVE_FORMAT_PCM) {
106 hi_check(wave_format.wBitsPerSample == 32,
"wBitsPerSample is not 32");
107 r.format = pcm_format{
true, std::endian::native,
true, 4, 8, 23};
109 }
else if (wave_format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
110 auto const num_bytes = narrow_cast<uint8_t>(wave_format.wBitsPerSample / 8);
111 auto const num_minor_bits = narrow_cast<uint8_t>(wave_format.wBitsPerSample);
112 r.format = pcm_format{
false, std::endian::native,
true, num_bytes, 0, num_minor_bits};
115 throw parse_error(std::format(
"Unsupported wFormatTag {}", wave_format.wFormatTag));
118 r.sample_rate = narrow_cast<uint32_t>(wave_format.nSamplesPerSec);
120 hi_check(wave_format.nChannels > 0,
"nChannels is zero");
121 r.num_channels = wave_format.nChannels;
123 r.speaker_mapping = speaker_mapping::none;
Rules for working with win32 headers.
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20