Skip to content

feat(mic): client microphone passthrough (Steam Streaming Microphone) rebased onto v1.17.0#293

Open
vladbogun1 wants to merge 6 commits into
Nonary:masterfrom
vladbogun1:feat/mic
Open

feat(mic): client microphone passthrough (Steam Streaming Microphone) rebased onto v1.17.0#293
vladbogun1 wants to merge 6 commits into
Nonary:masterfrom
vladbogun1:feat/mic

Conversation

@vladbogun1

Copy link
Copy Markdown

Client microphone passthrough (Steam Streaming Microphone) on current base

This ports the Steam Streaming Microphone client-mic passthrough from
xenstalker02/Vibepollo (which sits ~1.5 minor versions behind)
onto the current Vibepollo base (branched from v1.17.0). All credit for the original mic implementation and
protocol goes to @xenstalker02; this PR is a clean-room rebase of just the mic feature onto the newest code,
dropping the unrelated rebranding/installer/playnite churn.

What it does

Receives an Opus-encoded microphone stream from a compatible Moonlight client over the encrypted control
stream (0x3003), decodes + jitter-buffers it, and renders it into the Steam Streaming Microphone virtual
render endpoint so host apps (Discord, etc.) can read it as a normal mic input.

Changes (mic-only)

  • config.{h,cpp}: mic_sink, mic_capture_device, mic_buffer_ms, mic_buffer_packets (with sane defaults — no config edit required).
  • stream.{h,cpp}: 0x3003 packet type, session_t::mic jitter-buffer state, init_mic_passthrough() (lazy init on first packet), IDX_MIC_AUDIO_DATA handler via server->map(), get_mic_status(). Kept the v1.17.0 decode_control_packet/control_packet_view_t model.
  • platform/common.h: audio_control_t mic interface (switch_capture_to, snapshot_capture_defaults, restore_capture_from, restore_default_render_if_virtual, init/release_mic_redirect_device) with safe non-Windows defaults.
  • platform/windows/audio.cpp: WASAPI default-capture switch + render-restore guard, merged with v1.17.0's reset_default_device_impl(bool, preferred) and jthread pending-restore.
  • New: platform/windows/mic_write.{cpp,h} (WASAPI render to the Steam mic endpoint) + vibepollo_vmic.{cpp,h}; wired into windows.cmake.

Testing

  • ✅ Compiles green on the Windows CI (unsigned installer artifact produced).
  • Runtime-verified end-to-end: built installer deployed on a real host (Windows 11, RTX 5070 Ti); a Steam-Deck Moonlight fork with client mic capture streams audio that arrives at Microphone (Steam Streaming Microphone) on the host and is usable in Discord.
  • Requires Steam running on the host (the virtual render endpoint is provided by Steam) and a client that sends mic.

Notes for review

  • platform/windows/PolicyConfig.h already exists in the base.
  • A small .github/workflows/mic-ci.yml (windows-only workflow_dispatch) was added as a dev build helper and can be dropped on merge.
  • The Steam-Deck client side (matching moonlight-qt mic fork on the newest base) is being prepared as a separate effort.

vladbogun1 and others added 6 commits June 28, 2026 23:56
…ring

Port of xenstalker02/Vibepollo Steam Streaming Microphone passthrough onto
newest Nonary/Vibepollo base (v1.17.0). This checkpoint adds the standalone
mic engine files and wires them into the Windows build. Shared-file hunks
(stream.cpp routing, platform/windows/audio.cpp WASAPI) still to port.

New files (copied from xen/master):
- src/platform/windows/mic_write.{cpp,h}
- src/platform/windows/vibepollo_vmic.{cpp,h}

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hand-merged xenstalker02/Vibepollo mic passthrough onto the newest Nonary
base (v1.17.0). Mic-only changes; rebranding/installer/playnite churn dropped.

Resolved via git apply --3way + manual conflict resolution:
- config.{h,cpp}: mic_sink / mic_capture_device / mic_buffer_ms / mic_buffer_packets
  (kept install_steam_drivers, unlike xen)
- stream.{h,cpp}: 0x3003 mic packet type, session_t::mic jitter-buffer state,
  init_mic_passthrough(), IDX_MIC_AUDIO_DATA handler via server->map(),
  get_mic_status(); kept v1.17.0 decode_control_packet/control_packet_view_t model
- platform/common.h: audio_control_t mic interface (switch_capture_to,
  snapshot_capture_defaults, restore_capture_from, restore_default_render_if_virtual,
  init/release_mic_redirect_device) with safe non-Windows defaults
- platform/windows/audio.cpp: WASAPI capture-switch + render-restore; region-4
  reconstructed to keep v1.17.0 jthread pending-restore + add xen render guard,
  adapted to 2-arg reset_default_device_impl
- new files: platform/windows/mic_write.{cpp,h} (WASAPI render to Steam Streaming
  Microphone) + vibepollo_vmic.{cpp,h}; wired into windows.cmake
- nvhttp/audio.cpp: kept v1.17.0 (HDR + safe parsing)

Web UI mic status card (confighttp) intentionally deferred — not needed for the
audio path. Builds unsigned via mic-ci.yml (workflow_dispatch, Windows only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
stream.cpp teardown used xen-only proc::is_placebo_app() and
system_tray::update_tray_idle() (absent in v1.17.0). Revert to v1.17.0's
update_tray_pausing/stopped. Non-mic churn pulled in by full-file 3way.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dio.cpp

xen mic code used unqualified to_utf8/from_utf8 (resolved via a using-decl in
xen's tree); v1.17.0 needs explicit utf_utils:: qualification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-Werror=cpp made the 'include winsock2.h before windows.h' warning fatal;
mmdeviceapi.h/Audioclient.h pull windows.h. Mirrors v1.17.0 audio.cpp order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant