Phase 1 of the Windows port, stacked on PR #2 (Phase 0) — base is windows-port-phase0.
Replaces the Phase 0 no-op CpalBackend stub with a real cpal/WASAPI backend, preserving the exact PipeWire AudioBackend contract so the mixer/encoder/jitter pipeline is unchanged.
Playback: 200 ms stereo ring prefilled to PLAYBACK_TARGET_SAMPLES; output callback drains it (silence on underrun), owning thread feeds it from rx. ring_fill is the exact delta-maintained occupancy counter (clock-paced production preserved).
cpal::Stream is !Send: each stream lives on its own owning thread; the struct holds only the running flag + JoinHandle. stop() flips the flag and joins.
Generic over F32/I16/U16; device by name else default; 48 kHz-only (clear error otherwise, resampling = Phase 1.1).
Adds cpal = "0.15" under cfg(windows).
Verification: temporarily compiled cpal_impl against real cpal on Linux/ALSA -> build + clippy clean, 6/6 cpal_impl unit tests pass; reverted to windows-only gating. Shipped Linux state green (316/316). Runtime/WASAPI end-to-end is unverified and pending a Windows host (M2).
Flags: new dep cpal (windows-only); touches the RT audio callback (wait-free: try_pop + atomic add/sub).
Co-Authored-By: Claude Opus 4.8
Generated with Claude Code
Phase 1 of the Windows port, **stacked on PR #2 (Phase 0)** — base is `windows-port-phase0`.
Replaces the Phase 0 no-op `CpalBackend` stub with a real cpal/WASAPI backend, preserving the exact PipeWire `AudioBackend` contract so the mixer/encoder/jitter pipeline is unchanged.
- **Capture**: input stream -> downmix to mono -> 960-sample (20 ms) i16 frames -> tx
- **Playback**: 200 ms stereo ring prefilled to `PLAYBACK_TARGET_SAMPLES`; output callback drains it (silence on underrun), owning thread feeds it from rx. `ring_fill` is the exact delta-maintained occupancy counter (clock-paced production preserved).
- `cpal::Stream` is `!Send`: each stream lives on its own owning thread; the struct holds only the running flag + JoinHandle. `stop()` flips the flag and joins.
- Generic over F32/I16/U16; device by name else default; **48 kHz-only** (clear error otherwise, resampling = Phase 1.1).
- Adds `cpal = "0.15"` under `cfg(windows)`.
**Verification:** temporarily compiled `cpal_impl` against real cpal on Linux/ALSA -> build + clippy clean, 6/6 cpal_impl unit tests pass; reverted to windows-only gating. Shipped Linux state green (316/316). **Runtime/WASAPI end-to-end is unverified** and pending a Windows host (M2).
Flags: new dep `cpal` (windows-only); touches the RT audio callback (wait-free: `try_pop` + atomic add/sub).
Co-Authored-By: Claude Opus 4.8
Generated with Claude Code
Replace the Phase 0 no-op CpalBackend stub with a working cpal backend
(WASAPI on Windows), preserving the exact PipeWire AudioBackend contract
so the mixer/encoder/jitter pipeline is unchanged.
- Capture: input stream -> downmix to mono -> 960-sample (20ms) i16 frames
-> tx, matching the encoder/jitter frame size.
- Playback: 200ms stereo ring prefilled to PLAYBACK_TARGET_SAMPLES; the
output callback drains it (silence on underrun) while the owning thread
feeds it from rx. ring_fill is the exact delta-maintained occupancy
counter (fetch_add on push, fetch_sub on pop), preserving the clock-paced
production design (not ringbuf's stale occupied_len).
- cpal::Stream is !Send, but AudioBackend is Send+Sync and shared via Arc,
so each stream lives on its own owning thread (built/played/dropped
there); the struct holds only the running flag + JoinHandle. stop()
flips the flag and joins.
- Generic over F32/I16/U16 sample formats; device selected by name else
default; requires a native 48kHz config (clear error otherwise, no
resampling yet). Mirrors the PipeWire drain_loop and playout-health line.
- Cargo.toml: add cpal 0.15 under cfg(windows).
Verified by temporarily compiling cpal_impl against real cpal on Linux/ALSA:
build + clippy clean, 6/6 cpal_impl unit tests pass. Reverted to windows-only
gating; shipped Linux state green (316/316). Runtime/WASAPI end-to-end is
unverified and pending a Windows host (plan M2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Phase 1 of the Windows port, stacked on PR #2 (Phase 0) — base is
windows-port-phase0.Replaces the Phase 0 no-op
CpalBackendstub with a real cpal/WASAPI backend, preserving the exact PipeWireAudioBackendcontract so the mixer/encoder/jitter pipeline is unchanged.PLAYBACK_TARGET_SAMPLES; output callback drains it (silence on underrun), owning thread feeds it from rx.ring_fillis the exact delta-maintained occupancy counter (clock-paced production preserved).cpal::Streamis!Send: each stream lives on its own owning thread; the struct holds only the running flag + JoinHandle.stop()flips the flag and joins.cpal = "0.15"undercfg(windows).Verification: temporarily compiled
cpal_implagainst real cpal on Linux/ALSA -> build + clippy clean, 6/6 cpal_impl unit tests pass; reverted to windows-only gating. Shipped Linux state green (316/316). Runtime/WASAPI end-to-end is unverified and pending a Windows host (M2).Flags: new dep
cpal(windows-only); touches the RT audio callback (wait-free:try_pop+ atomic add/sub).Co-Authored-By: Claude Opus 4.8
Generated with Claude Code
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.