Skip to content

Commit 233ee86

Browse files
yeah-its-gloriasooda
authored andcommitted
feat(wasapi): enable resampling when necessary (RustAudio#1097)
This allows non-native sample rates to be resampled by the WASAPI server. (cherry picked from commit 6627959)
1 parent 5c34a88 commit 233ee86

2 files changed

Lines changed: 15 additions & 44 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
- Backport: **WASAPI**: Allow non-native sample rates to be used via as-necessary resampling in the WASAPI server process.
4+
15
# Version 0.14.1 (2022-10-23)
26

37
- Support the 0.6.1 release of `alsa-rs`

src/host/wasapi/device.rs

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use std::ffi::c_void;
2222
use windows::core::Interface;
2323
use windows::core::GUID;
2424
use windows::Win32::Devices::Properties;
25-
use windows::Win32::Foundation;
2625
use windows::Win32::Media::Audio::IAudioRenderClient;
2726
use windows::Win32::Media::{Audio, KernelStreaming, Multimedia};
2827
use windows::Win32::System::Com;
@@ -36,6 +35,10 @@ use crate::{traits::DeviceTrait, BuildStreamError, StreamError};
3635
pub type SupportedInputConfigs = std::vec::IntoIter<SupportedStreamConfigRange>;
3736
pub type SupportedOutputConfigs = std::vec::IntoIter<SupportedStreamConfigRange>;
3837

38+
const DEFAULT_FLAGS: u32 = Audio::AUDCLNT_STREAMFLAGS_EVENTCALLBACK
39+
| Audio::AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
40+
| Audio::AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
41+
3942
/// Wrapper because of that stupid decision to remove `Send` and `Sync` from raw pointers.
4043
#[derive(Clone)]
4144
struct IAudioClientWrapper(Audio::IAudioClient);
@@ -195,48 +198,12 @@ unsafe fn data_flow_from_immendpoint(endpoint: &Audio::IMMEndpoint) -> Audio::ED
195198

196199
// Given the audio client and format, returns whether or not the format is supported.
197200
pub unsafe fn is_format_supported(
198-
client: &Audio::IAudioClient,
199-
waveformatex_ptr: *const Audio::WAVEFORMATEX,
201+
_client: &Audio::IAudioClient,
202+
_waveformatex_ptr: *const Audio::WAVEFORMATEX,
200203
) -> Result<bool, SupportedStreamConfigsError> {
201-
// Check if the given format is supported.
202-
let is_supported = |waveformatex_ptr, mut closest_waveformatex_ptr| {
203-
let result = client.IsFormatSupported(
204-
Audio::AUDCLNT_SHAREMODE_SHARED,
205-
waveformatex_ptr,
206-
&mut closest_waveformatex_ptr,
207-
);
208-
// `IsFormatSupported` can return `S_FALSE` (which means that a compatible format
209-
// has been found, but not an exact match) so we also treat this as unsupported.
210-
match result {
211-
Audio::AUDCLNT_E_DEVICE_INVALIDATED => {
212-
Err(SupportedStreamConfigsError::DeviceNotAvailable)
213-
}
214-
r if r.is_err() => Ok(false),
215-
Foundation::S_FALSE => Ok(false),
216-
_ => Ok(true),
217-
}
218-
};
219-
220-
// First we want to retrieve a pointer to the `WAVEFORMATEX`.
221-
// Although `GetMixFormat` writes the format to a given `WAVEFORMATEX` pointer,
222-
// the pointer itself may actually point to a `WAVEFORMATEXTENSIBLE` structure.
223-
// We check the wFormatTag to determine this and get a pointer to the correct type.
224-
match (*waveformatex_ptr).wFormatTag as u32 {
225-
Audio::WAVE_FORMAT_PCM | Multimedia::WAVE_FORMAT_IEEE_FLOAT => {
226-
let mut closest_waveformatex = *waveformatex_ptr;
227-
let closest_waveformatex_ptr = &mut closest_waveformatex as *mut _;
228-
is_supported(waveformatex_ptr, closest_waveformatex_ptr)
229-
}
230-
KernelStreaming::WAVE_FORMAT_EXTENSIBLE => {
231-
let waveformatextensible_ptr = waveformatex_ptr as *const Audio::WAVEFORMATEXTENSIBLE;
232-
let mut closest_waveformatextensible = *waveformatextensible_ptr;
233-
let closest_waveformatextensible_ptr = &mut closest_waveformatextensible as *mut _;
234-
let closest_waveformatex_ptr =
235-
closest_waveformatextensible_ptr as *mut Audio::WAVEFORMATEX;
236-
is_supported(waveformatex_ptr, closest_waveformatex_ptr)
237-
}
238-
_ => Ok(false),
239-
}
204+
// Checking formats is not needed for shared mode with auto-conversion, therefore this check has been removed until someone implements WASAPI exclusive mode support
205+
// I used an NAudio issue as reference: https://github.com/naudio/NAudio/issues/819
206+
Ok(true)
240207
}
241208

242209
// Get a cpal Format from a WAVEFORMATEX.
@@ -622,7 +589,7 @@ impl Device {
622589
let buffer_duration =
623590
buffer_size_to_duration(&config.buffer_size, config.sample_rate.0);
624591

625-
let mut stream_flags = Audio::AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
592+
let mut stream_flags = DEFAULT_FLAGS;
626593

627594
if self.data_flow() == Audio::eRender {
628595
stream_flags |= Audio::AUDCLNT_STREAMFLAGS_LOOPBACK;
@@ -758,7 +725,7 @@ impl Device {
758725
audio_client
759726
.Initialize(
760727
share_mode,
761-
Audio::AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
728+
DEFAULT_FLAGS,
762729
buffer_duration,
763730
0,
764731
&format_attempt.Format,

0 commit comments

Comments
 (0)