Adds a direct WASAPI microphone capture path for the Windows desktop
build that opens the default communications endpoint via
IMMDeviceEnumerator -> IAudioClient2 -> SetClientProperties with
AudioCategory_Communications, turning on Windows's communications
audio processing chain (AEC, noise suppression, automatic gain
control). The communications AEC operates at the OS level and uses
the system render mix as the reference signal, so echo from our
existing CPAL playback stream is cancelled automatically with no
per-process reference plumbing.
Architecture:
- New crates/wzp-client/src/audio_wasapi.rs module (~280 lines).
Event-driven capture loop on a dedicated thread; pushes PCM into
the same lock-free AudioRing used by the CPAL path. Same public
API as audio_io::AudioCapture so downstream code is unchanged.
- New `windows-aec` feature in wzp-client that pulls in the
`windows` crate (Microsoft's official Rust COM bindings) gated to
target_os = "windows" only. Enabling the feature on non-Windows
targets is a no-op since both the module and the dep are
cfg(target_os = "windows").
- lib.rs re-exports WasapiAudioCapture as AudioCapture when the
feature is on, otherwise falls back to the CPAL AudioCapture.
AudioPlayback is always the CPAL one — no reason to swap it.
- desktop/src-tauri/Cargo.toml Windows target enables the new
feature: `features = ["audio", "windows-aec"]`.
Implementation notes:
- Uses eCommunications role (not eConsole) for GetDefaultAudioEndpoint
— the user-configured "communications" device that Teams/Zoom
pick up, and the one Windows's AEC is tuned for.
- Requests 48 kHz mono i16 with AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM +
SRC_DEFAULT_QUALITY so Windows handles any format conversion in
the audio engine instead of rejecting our format.
- Event-driven with SetEventHandle / WaitForSingleObject — no
polling, minimal CPU cost between packets.
- 200 ms wait timeout so the capture thread polls `running` often
enough for Drop to stop cleanly even if the audio engine stalls
(e.g. device unplug).
Task #24.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>