Inspiration
I built Echoless because I wanted to use speakers during Discord calls without sending every video, game, and stream back through my microphone.
Noise-suppression tools can remove keyboards, fans, and room noise. Speaker echo requires a different approach: the software needs a copy of the system audio so it can find and remove that same signal from the microphone input.
Echoless brings reference-based acoustic echo cancellation to the common “speakers + microphone” setup in a small, open-source desktop app.
What it does
Echoless is a real-time acoustic echo cancellation app and CLI for Windows and macOS.
It captures two live signals:
- Far-end reference: the audio currently playing through the computer.
- Near-end capture: the microphone signal containing the user’s voice, speaker echo, and room reflections.
Echoless aligns the two signals, removes the correlated speaker echo, and sends the processed voice to an existing virtual audio device. Discord or another voice app selects that virtual device as its microphone.
Users can choose among three processing engines:
- AEC3: a low-latency adaptive echo canceller based on the WebRTC AEC3 algorithm family.
- LocalVQE: an experimental CPU neural model for echo cancellation, noise suppression, and dereverberation.
- NVIDIA Maxine AEC: an RTX-accelerated engine for supported Windows systems.
Echoless also provides device checks, delay probing, live health telemetry, optional runtime and model downloads, diagnostic logs, and a standalone CLI for scripting, offline WAV processing, and troubleshooting.
How I built it
I wrote the real-time audio pipeline and CLI in Rust. The CLI owns device capture, audio processing, diagnostics, and the runtime control protocol. The Tauri desktop app generates configuration, supervises the CLI sidecar, and displays its state. Both interfaces use the same audio pipeline.
Echoless captures system audio through native platform APIs:
- Windows: WASAPI loopback capture.
- macOS: Core Audio Process Tap through a Swift helper.
The desktop interface uses Tauri v2, React, TypeScript, and Vite.
Each audio device has its own clock. The microphone, playback device, loopback capture, and virtual output can drift apart during a long session. Echoless estimates delay, resamples when necessary, and monitors clock skew to prevent clicks, dropped frames, and unstable echo cancellation.
The GUI and sidecar communicate through a structured JSONL protocol. Explicit startup, shutdown, and run-state handshakes keep model switches and engine restarts from leaving the virtual microphone in an unknown state.
Challenges we ran into
Accurate echo cancellation depends on the quality and timing of the reference signal. Even a strong processor performs poorly when the playback reference arrives late, drifts over time, or passes through a different channel layout. Echoless has to maintain alignment while handling double-talk, device changes, and varying room acoustics.
Windows and macOS expose system audio through different APIs, permissions, device models, and process lifecycles. Supporting both platforms required separate capture implementations behind a common pipeline.
I chose not to ship a kernel-level virtual microphone driver. Echoless uses established routing tools such as VB-CABLE and BlackHole, which keeps the project easier to inspect and maintain but makes first-run routing more important.
Application lifecycle became another audio problem. A failed engine restart can leave the user with a dead microphone even when the interface still looks active. Echoless uses bounded startup and recovery paths, run-specific state tracking, and diagnostics that distinguish routing failures from processor failures.
Accomplishments that we're proud of
- Built a complete reference-based audio path from native system capture and microphone input to processed virtual-device output. This turned the project into a usable voice-chat tool rather than an offline algorithm demo.
- Kept independently clocked audio devices aligned during long sessions through delay tracking, resampling, bounded buffering, and clock-skew telemetry.
- Integrated AEC3, LocalVQE, and NVIDIA Maxine AEC behind one processor boundary while preserving each engine’s sample-rate, frame-size, channel, and hardware constraints.
- Designed the GUI and sidecar lifecycle around explicit run IDs, startup and shutdown handshakes, stale-event rejection, and bounded recovery. Engine switches and restarts can fail without silently leaving the user with a dead microphone.
- Added native system-audio capture on both Windows and macOS without introducing a custom kernel driver. Echoless remains compatible with established routing tools and keeps privileged platform code to a minimum.
- Built diagnostics around the audio pipeline, including setup validation, delay probing, health events, crash logs, and validated downloads for optional models and runtimes.
- Shipped the same processing pipeline through a desktop app, an interactive CLI, and offline WAV tools, then released Echoless 1.1.0 as an open-source project.
What we learned
A good algorithm does not guarantee a good real-time audio product. Clock drift, reference alignment, device routing, buffering, and process lifetime can matter as much as the echo-cancellation model.
Engine constraints also need to appear in the product interface. When a processor requires a specific sample rate, frame size, or channel layout, the UI should prevent invalid combinations before the user starts the pipeline.
Diagnostics need to answer a practical question: did the engine fail, or did the audio go to the wrong device? Separating those failure modes saves users from debugging the wrong part of the system.
What's next for Echoless
I want to build a guided first-run setup that verifies the complete path from system audio and microphone capture to the virtual output device.
I also plan to improve device-specific diagnostics, publish repeatable quality and latency comparisons for each engine, expand the tested hardware matrix, and make calibration easier for users who do not know how desktop audio routing works.
The goal remains straightforward: let people use speakers during voice chat without making them understand the audio plumbing underneath.
Built With
- aec3
- audio-processing
- c++
- cli
- core-audio
- digital-signal-processing
- localvqe
- machine-learning
- nvidia-maxine
- react
- rnnoise
- rust
- swift
- tauri
- typescript
- wasapi
- webrtc
Log in or sign up for Devpost to join the conversation.