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 {
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;
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){
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) {
75 r.format =
pcm_format{
false, std::endian::native,
true, num_bytes, 0, num_minor_bits};
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");
90hi_export [[nodiscard]]
inline audio_stream_format audio_stream_format_from_win32(WAVEFORMATEX
const& wave_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) {
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));
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:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
The format of a stream of audio.
Definition audio_stream_format.hpp:40
Definition pcm_format.hpp:18
Exception thrown during parsing on an error.
Definition exception_intf.hpp:48