use std::mem;
use windows_sys::Windows::Win32::CoreAudio as core;
use windows_sys::Windows::Win32::Multimedia as mm;
use super::ClientConfig;
pub unsafe trait Sample: Copy {
const MID: Self;
fn mix_format(config: ClientConfig) -> mm::WAVEFORMATEXTENSIBLE;
unsafe fn is_compatible_with(mix_format: *const mm::WAVEFORMATEX) -> bool;
}
unsafe impl Sample for i16 {
const MID: Self = 0;
fn mix_format(config: ClientConfig) -> mm::WAVEFORMATEXTENSIBLE {
let avg_bytes_per_sec =
config.channels as u32 * config.sample_rate * mem::size_of::<Self>() as u32;
let bits_per_sample = mem::size_of::<Self>() as u16 * 8;
let block_align = config.channels as u16 * mem::size_of::<Self>() as u16;
mm::WAVEFORMATEXTENSIBLE {
Format: mm::WAVEFORMATEX {
wFormatTag: mm::WAVE_FORMAT_PCM as u16,
nChannels: config.channels,
nSamplesPerSec: config.sample_rate,
nAvgBytesPerSec: avg_bytes_per_sec,
nBlockAlign: block_align,
wBitsPerSample: bits_per_sample,
cbSize: 0,
},
Samples: mm::WAVEFORMATEXTENSIBLE_0 {
wValidBitsPerSample: 0,
},
dwChannelMask: 0,
SubFormat: windows::Guid::zeroed(),
}
}
unsafe fn is_compatible_with(mix_format: *const mm::WAVEFORMATEX) -> bool {
let bits_per_sample = (*mix_format).wBitsPerSample;
match (*mix_format).wFormatTag as u32 {
mm::WAVE_FORMAT_PCM => {
assert!((*mix_format).cbSize == 0);
bits_per_sample == 16
}
_ => false,
}
}
}
unsafe impl Sample for f32 {
const MID: Self = 0.0;
fn mix_format(config: ClientConfig) -> mm::WAVEFORMATEXTENSIBLE {
let avg_bytes_per_sec =
config.channels as u32 * config.sample_rate * mem::size_of::<Self>() as u32;
let bits_per_sample = mem::size_of::<Self>() as u16 * 8;
let block_align = config.channels as u16 * mem::size_of::<Self>() as u16;
let cb_size = mem::size_of::<mm::WAVEFORMATEXTENSIBLE>() as u16
- mem::size_of::<mm::WAVEFORMATEX>() as u16;
mm::WAVEFORMATEXTENSIBLE {
Format: mm::WAVEFORMATEX {
wFormatTag: core::WAVE_FORMAT_EXTENSIBLE as u16,
nChannels: config.channels,
nSamplesPerSec: config.sample_rate,
nAvgBytesPerSec: avg_bytes_per_sec,
nBlockAlign: block_align,
wBitsPerSample: bits_per_sample,
cbSize: cb_size,
},
Samples: mm::WAVEFORMATEXTENSIBLE_0 {
wValidBitsPerSample: bits_per_sample,
},
dwChannelMask: 0,
SubFormat: mm::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
}
}
unsafe fn is_compatible_with(mix_format: *const mm::WAVEFORMATEX) -> bool {
let bits_per_sample = (*mix_format).wBitsPerSample;
match (*mix_format).wFormatTag as u32 {
core::WAVE_FORMAT_EXTENSIBLE => {
debug_assert_eq! {
(*mix_format).cbSize as usize,
mem::size_of::<mm::WAVEFORMATEXTENSIBLE>() - mem::size_of::<mm::WAVEFORMATEX>()
};
let mix_format = mix_format as *const mm::WAVEFORMATEXTENSIBLE;
bits_per_sample == 32
&& matches!((*mix_format).SubFormat, mm::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
}
_ => false,
}
}
}