audio_device/wasapi/
sample.rs1use std::mem;
2use windows_sys::Windows::Win32::CoreAudio as core;
3use windows_sys::Windows::Win32::Multimedia as mm;
4
5use super::ClientConfig;
6
7pub unsafe trait Sample: Copy {
9 const MID: Self;
11
12 fn mix_format(config: ClientConfig) -> mm::WAVEFORMATEXTENSIBLE;
15
16 unsafe fn is_compatible_with(mix_format: *const mm::WAVEFORMATEX) -> bool;
18}
19
20unsafe impl Sample for i16 {
21 const MID: Self = 0;
22
23 fn mix_format(config: ClientConfig) -> mm::WAVEFORMATEXTENSIBLE {
24 let avg_bytes_per_sec =
25 config.channels as u32 * config.sample_rate * mem::size_of::<Self>() as u32;
26 let bits_per_sample = mem::size_of::<Self>() as u16 * 8;
27 let block_align = config.channels as u16 * mem::size_of::<Self>() as u16;
28
29 mm::WAVEFORMATEXTENSIBLE {
30 Format: mm::WAVEFORMATEX {
31 wFormatTag: mm::WAVE_FORMAT_PCM as u16,
32 nChannels: config.channels,
33 nSamplesPerSec: config.sample_rate,
34 nAvgBytesPerSec: avg_bytes_per_sec,
35 nBlockAlign: block_align,
36 wBitsPerSample: bits_per_sample,
37 cbSize: 0,
38 },
39 Samples: mm::WAVEFORMATEXTENSIBLE_0 {
40 wValidBitsPerSample: 0,
41 },
42 dwChannelMask: 0,
43 SubFormat: windows::Guid::zeroed(),
44 }
45 }
46
47 unsafe fn is_compatible_with(mix_format: *const mm::WAVEFORMATEX) -> bool {
48 let bits_per_sample = (*mix_format).wBitsPerSample;
49
50 match (*mix_format).wFormatTag as u32 {
51 mm::WAVE_FORMAT_PCM => {
52 assert!((*mix_format).cbSize == 0);
53 bits_per_sample == 16
54 }
55 _ => false,
56 }
57 }
58}
59
60unsafe impl Sample for f32 {
61 const MID: Self = 0.0;
62
63 fn mix_format(config: ClientConfig) -> mm::WAVEFORMATEXTENSIBLE {
64 let avg_bytes_per_sec =
65 config.channels as u32 * config.sample_rate * mem::size_of::<Self>() as u32;
66 let bits_per_sample = mem::size_of::<Self>() as u16 * 8;
67 let block_align = config.channels as u16 * mem::size_of::<Self>() as u16;
68 let cb_size = mem::size_of::<mm::WAVEFORMATEXTENSIBLE>() as u16
69 - mem::size_of::<mm::WAVEFORMATEX>() as u16;
70
71 mm::WAVEFORMATEXTENSIBLE {
72 Format: mm::WAVEFORMATEX {
73 wFormatTag: core::WAVE_FORMAT_EXTENSIBLE as u16,
74 nChannels: config.channels,
75 nSamplesPerSec: config.sample_rate,
76 nAvgBytesPerSec: avg_bytes_per_sec,
77 nBlockAlign: block_align,
78 wBitsPerSample: bits_per_sample,
79 cbSize: cb_size,
80 },
81 Samples: mm::WAVEFORMATEXTENSIBLE_0 {
82 wValidBitsPerSample: bits_per_sample,
83 },
84 dwChannelMask: 0,
85 SubFormat: mm::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
86 }
87 }
88
89 unsafe fn is_compatible_with(mix_format: *const mm::WAVEFORMATEX) -> bool {
90 let bits_per_sample = (*mix_format).wBitsPerSample;
91
92 match (*mix_format).wFormatTag as u32 {
93 core::WAVE_FORMAT_EXTENSIBLE => {
94 debug_assert_eq! {
95 (*mix_format).cbSize as usize,
96 mem::size_of::<mm::WAVEFORMATEXTENSIBLE>() - mem::size_of::<mm::WAVEFORMATEX>()
97 };
98
99 let mix_format = mix_format as *const mm::WAVEFORMATEXTENSIBLE;
100 bits_per_sample == 32
101 && matches!((*mix_format).SubFormat, mm::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
102 }
103 _ => false,
104 }
105 }
106}