No description
  • Rust 62.9%
  • Svelte 34.7%
  • JavaScript 1.6%
  • HTML 0.5%
  • TypeScript 0.3%
Find a file
2026-11-14 18:16:39 +03:00
.vscode Initial commit 2026-11-14 17:45:14 +03:00
src Rebrand app as WntrMixer and apply supplied icons 2026-11-14 18:16:39 +03:00
src-tauri Rebrand app as WntrMixer and apply supplied icons 2026-11-14 18:16:39 +03:00
static Rebrand app as WntrMixer and apply supplied icons 2026-11-14 18:16:39 +03:00
.gitignore Initial commit 2026-11-14 17:45:14 +03:00
bun.lock Initial commit 2026-11-14 17:45:14 +03:00
package.json Rebrand app as WntrMixer and apply supplied icons 2026-11-14 18:16:39 +03:00
README.md Rebrand app as WntrMixer and apply supplied icons 2026-11-14 18:16:39 +03:00
svelte.config.js Initial commit 2026-11-14 17:45:14 +03:00
tsconfig.json Initial commit 2026-11-14 17:45:14 +03:00
vite.config.js Initial commit 2026-11-14 17:45:14 +03:00

WntrMixer

Version: 0.1.2 · Source repository

Windows audio mixer using Rust / WASAPI (CPAL), Svelte 5 and Tauri 2.

Run

bun run tauri dev

Device routing

Source or destination Device
Windows default playback CABLE Input
Spotify and browser playback CABLE-A Input
System strip input CABLE Output
Music / browser strip input CABLE-A Output
Microphone strip input Physical microphone
Mix A output Physical headphones
Mix B output CABLE-B Input
Discord / game microphone CABLE-B Output

By default, system audio goes to A, music to A and B, and microphone to B. Each input has volume, mute and independent sends to A/B. Each output has a master volume. Mixer, Applications and Help are separate tabs. Controls apply live. Changing a device while running restarts the audio graph automatically, retaining volume, mute and sends. Failed switches attempt to restore the previous devices. Disconnecting every input or output stops the mixer. Refresh devices can update the available choices while running without changing the live routing. Select "Not connected" to disable an input or output. Settings persist locally, including migration of the previous A/B cable roles. Audio starts automatically once per application launch using saved routing and controls. Unavailable saved devices produce an error instead of silently substituting another device. After correcting the selection, use Start mixer.

The internal bus names A/B are independent of the cable names: bus A monitors headphones; bus B feeds CABLE-B for voice chat.

OBS

  • Desktop Audio: CABLE Input (playback capture).
  • Desktop Audio 2: CABLE-A Input (playback capture).
  • Mic/Aux: CABLE-B Output (input capture).

Assign sources to separate tracks in Advanced Audio Properties and enable these tracks in recording settings using a format that supports multiple audio tracks.

Turn off the Music / browser B send to exclude music from the virtual microphone. This also excludes music from voice chat. The A send remains independent.

OBS captures the first two sources BEFORE Mixer processing: our volume and mute do not affect these raw tracks. The microphone track receives mix B. Music excluded from B is also excluded from voice chat. A simultaneous clean microphone track in OBS and microphone plus music in Discord requires another output path (for example, a fourth cable), or direct physical microphone capture in OBS, which bypasses Mixer controls.

Keep Windows "Listen to this device" disabled. Do not monitor OBS sources back into CABLE Input, which can cause duplicate audio or feedback.

Current limitations

Three inputs, two independent outputs, Float32 mono/stereo, 0-100% volume, pre-mute input meters, post-master output meters and clipping indication. Basic linear sample-rate interpolation compensates for buffer drift. Target queue: approximately 40 ms per connection plus WASAPI/driver latency.

EQ, a band-limited resampler, automatic device reconnection and a background service are not implemented. Device keys use names plus a duplicate occurrence number; renamed devices need to be selected again. Direct same-cable feedback loops and duplicate device selections are rejected.

Validation

  • bun run check
  • bun run build
  • cargo test --offline --manifest-path src-tauri/Cargo.toml
  • cargo run --offline --manifest-path src-tauri/Cargo.toml --example devices

Explicit hardware test (stop Mixer and other CABLE-A sources first):

cargo test --offline --manifest-path src-tauri/Cargo.toml virtual_cable_roundtrip -- --ignored --nocapture

This sends a quiet test tone into CABLE-A, routes it through Mixer to CABLE-B, and checks volume, B-send exclusion, restoration and mute. It does not use physical speakers or a microphone. Other applications listening to CABLE-B may receive the test tone.

Application volume

The Applications panel is a single list across all playback devices. Applications enter the list only after being observed Active during the current Mixer run. Idle applications present at startup stay hidden until they become active. Once seen, an application stays listed until Mixer exits, including when it becomes idle or its sessions expire. No-session rows show "No session".

Sessions from the same executable are grouped across playback devices. Volume and mute changes apply to all of an application's current sessions, regardless of its output device. If no sessions exist, changes are retained for the next session. Newly discovered sessions inherit the latest controls set here during this Mixer run. Existing sessions continue to reflect external Windows Volume Mixer changes. Apps with inaccessible process metadata use a process-ID fallback.

The panel shows application icons, names, activity, peak meters, volume and mute. Mixed session levels are marked until a common value is selected. If an icon cannot be read, the row uses a letter placeholder.

Changes apply before cable capture, so OBS recordings receive the changed level. This panel works even when the Mixer audio graph is stopped. Session discovery runs approximately once per second; meters and activity refresh more frequently. The service runs on a separate COM thread and is not accessed by audio callbacks. Visibility history and new-session control preferences last for the current Mixer process only. Application levels themselves are managed by Windows. The panel does not reroute applications or provide per-application EQ. Display names supplied by Windows/apps retain their language.

Read-only Windows integration check: cargo test --offline --manifest-path src-tauri/Cargo.toml enumerate_application_sessions -- --ignored --nocapture

Isolated session control check (creates its own silent sessions only): cargo test --offline --manifest-path src-tauri/Cargo.toml isolated_session_volume_and_mute -- --ignored --nocapture

The interface uses a neutral stone palette with custom segmented dBFS meters and matching volume sliders. Setup instructions are in Help. OBS Mode has been removed; use each source's B send to control the virtual microphone mix.

Tray and login startup

Closing the main window hides it from the taskbar without stopping the audio graph or application session service. Left-click the tray icon, or use Open Mixer from its right-click menu, to restore the window. Quit Mixer stops the audio graph and exits the process. Launching Mixer again brings the existing instance forward instead of opening a second audio engine.

Start with Windows is available in the header and tray menu. It registers or removes login startup for the current Windows account using the official Tauri autostart plugin. The initial OS setting is preserved; startup is never enabled automatically. The checkbox reflects the registered OS value.

Login startup passes --autostart, keeps the window hidden in the tray (without a taskbar flash), and starts the audio graph using saved devices and controls. A webview reload does not restart audio that was manually stopped during the same application run. Use an installed release build for startup: registering a development executable points Windows at the build directory and its webview expects the development server.

Ordinary launches show the window. A duplicate --autostart launch leaves the existing window state unchanged; a normal duplicate launch restores it. Enabled startup registrations are refreshed to include --autostart when this version opens. Disabled startup registrations remain disabled.

Branding and installer identity

Application name: WntrMixer. The identifier com.wntro.mixer, internal executable name and autostart registration key remain stable to retain existing settings. The tray uses static/icon-tray.png, embedded and resized to 32 px in memory. The app and favicon use static/icon.png. The Windows multi-resolution icon is src-tauri/icons/icon.ico (16, 24, 32, 48, 64, 128 and 256 px). Only the original PNG files and the necessary ICO are referenced.

The MSI upgrade code is pinned to the original mixer value 418a6ab6-ada2-5f12-a8fe-02f512692786 so renaming does not change MSI identity. NSIS setup.exe uses the product name for its uninstall registration. When moving from the old mixer-branded NSIS installation, uninstall that version once without deleting application data, then install WntrMixer. Subsequent WntrMixer updates can be installed normally.