Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rt-audio-latency-lab

A workbench for building and measuring glitch-free, low-latency real-time audio on Windows.

Latency and dropouts are the hard part of real-time audio, and they are usually discussed by feel rather than measured. This project does the opposite. It runs a full capture, process, and playback path as the device under test, and wraps it in a harness that reports round-trip latency and xrun (dropout) counts objectively, across backends and buffer sizes, so tuning is driven by numbers instead of guesswork.

It targets WASAPI (shared and exclusive mode) and ASIO. The audio path and the DSP chain are written to be genuinely real-time-safe, and the repo documents why each decision was made, since that discipline is the whole game in audio callbacks.

Scope note: this is a measurement lab and reference engine, not a finished product. It exists to prove a design is glitch-free at a given latency and to make the trade-offs visible.


Signal path

flowchart LR
    In[Capture callback\nWASAPI / ASIO] -- lock-free ring --> Proc[DSP chain\nreal-time-safe]
    Proc -- lock-free ring --> Out[Playback callback\nWASAPI / ASIO]
    Proc -. counters .-> Meter[Latency + xrun harness]
    Meter --> Report[CSV / console report]
Loading
  • Capture and playback run on the audio thread through WASAPI (shared or exclusive) or ASIO.
  • Hand-off between threads is a lock-free single-producer/single-consumer ring buffer. No allocation, no locks, and no system calls happen inside the audio callback.
  • Processing is a pluggable DSP chain (biquad filters, gain, mixing, resampling) that runs within the callback's time budget.
  • Measurement records round-trip latency and counts underruns/overruns, then sweeps buffer sizes and sample rates to show where the design stays clean and where it breaks.

What it measures

  • Round-trip latency in frames and milliseconds, measured by loopback: emit a click, capture it back, and compute the sample offset. No reliance on a driver's self-reported figure.
  • Xruns per hour under a controlled processing load, per backend and buffer size.
  • Callback headroom: time spent in the callback versus the time available, so you can see how close to the edge a given buffer size runs.

Why the design is real-time-safe

  • The audio callback never allocates, never locks, and never blocks. Everything it needs is preallocated.
  • Cross-thread data moves through a wait-free ring buffer, so the UI and worker threads cannot stall the audio thread.
  • DSP work is bounded and measured, so a buffer is always filled before its deadline.
  • The callback takes a raw function pointer and a void*, not a std::function, so there is no captured state to allocate or indirect through on the hot path.

Design targets

What the engine is built to achieve, and what a bench run measures against. These are the specified targets, not results from a run: the numbers that belong in a results table can only come from a real machine with real hardware, and the Status list below tracks that.

Property Target
Allocation in the callback None. Every buffer preallocated before start()
Locks in the callback None. Cross-thread hand-off is a wait-free SPSC ring
Ring buffer ordering Release on producer publish, acquire on consumer read
WASAPI shared Works at the mix-format rate; latency bounded by the shared engine period
WASAPI exclusive Device period drives the buffer; handles the buffer-alignment retry
ASIO Same backend interface; built only when the SDK is present locally
Latency measurement Loopback cross-correlation against the emitted signal, not a driver self-report
Xruns Counted lock-free from the callback, reported per backend and buffer size
Callback headroom Measured as time-in-callback over time-available, per block
Sweep output CSV plus console, containing only what was actually measured

Status

  • WASAPI shared-mode capture and playback with lock-free ring buffer
  • WASAPI exclusive-mode low-latency path
  • ASIO backend
  • Pluggable real-time-safe DSP chain (biquad, gain, resample)
  • Loopback round-trip latency measurement
  • Xrun counting and buffer-size sweep
  • Bench run on real hardware, measured against the targets above

Build and run

C++17, built with CMake. ASIO support requires the Steinberg ASIO SDK (not redistributed here; drop it in third_party/asio locally). WASAPI needs no extra SDK on Windows.

cmake -B build && cmake --build build --config Release
build/Release/rt-audio-latency-lab --backend wasapi-exclusive --buffer 64 --measure
build/Release/rt-audio-latency-lab --sweep --out results.csv

Licence

MIT.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages