English | 中文
wasapi_relink is a hook library that modifies the behavior of WASAPI (Windows Audio Session API) Shared streams, "grafting" them onto modern, low-latency interfaces to drastically minimize audio latency.
Many applications and games use WASAPI's Shared mode for audio playback. While it offers good compatibility, this mode only allows for a minimum buffer size of 10ms, preventing further improvement in latency.
wasapi_relink intercepts the application's audio requests and forces them to use much smaller buffers by leveraging the IAudioClient3 interface, achieving a low-latency experience similar to Exclusive mode without sacrificing Shared mode's convenience.
This tool is 100% dependent on your audio driver. The target_buffer_dur_ms setting in config is a request, not a command.
Your audio driver reports a supported buffer range (i.e. GetSharedModeEnginePeriod), and wasapi_relink will clamp the request to fit within that range, this problem is most obvious when using Realtek onboard soundcards, see below.
Most stock Realtek audio drivers (the ones from the manufacturer) lock the buffer range to 10ms exact.
If your driver does this, wasapi_relink will have no effect, as it cannot request a buffer smaller than 10ms.
You must uninstall the Realtek drivers and force Windows to install the generic "High Definition Audio Device" driver. This standard Microsoft driver typically allows a 2ms-10ms range, enabling wasapi_relink to successfully request a 2ms buffer.
Or, use a professional soundcard or external audio interface that supports low-latency.
wasapi_relink operates in two distinct modes to handle different types of applications.
Target: Applications and games that use event-driven (callback-based) audio streaming.
Method:
-
Hooks
IAudioClient::Initialize. -
Ignores the application's buffer request and instead calls
IAudioClient3::InitializeSharedAudioStreamto initialize a low-latency stream. -
This provides the application with a much smaller buffer (e.g., 2ms), dramatically reducing latency.
This is the core of the project, designed for applications that uses polling (loop-based) audio stream.
Target: Applications and games that use poll-driven streaming.
Method:
-
Hooks
IMMDevice::Activateand creates twoIAudioClient3instances. -
Instance A (Transparent): Is initialized in a regular Shared mode that the application expects.
-
Instance B (Hooker): Is initialized in
IAudioClient3's low-latency mode. This is the key: it triggers a special Windows behavior that forces the actual hardware audio engine buffer to align with this low-latency request (e.g. 2ms). -
Prefill Deception:
wasapi_relinkthen intercepts the application's silent prefill process, deceiving it into filling a much smaller buffer that matches the new hardware buffer size.
Result: At this point, the buffer requested in standard shared mode effectively acts as an intermediate buffer layer.
- Worst-case: Latency is doubled comparing to normal mode (the sum of the pre-filled buffer and the device buffer).
- Best-case: Latency is identical to the normal mode.
This library does not include its own DLL injector. You must use an external tool or stub generator.
This library is designed to work seamlessly with Special K.
It is recommended to load wasapi_relink.dll as a Special K "plug-in" (lazy mode).
Built-in Compatibility: wasapi_relink actively detects and skips hooking Special K's own audio requests, ensuring SK's sound related features are not affected.
An additional purpose of this tool is to act as a "auxiliary" library if the audio library you are using does not support IAudioClient3 low-latency initialization.
No complex injection tools are needed. Simply, early in your program’s startup, explicitly load this DLL with LoadLibrary("wasapi_relink.dll"). Its hooking behavior is automatically performed when the DLL is loaded, thereby "transparently" providing low-latency features to your existing audio library.
To facilitate use with stub generators, wasapi_relink.dll additionally exports a blank function named proxy.
This function does nothing on its own; it exists only as a definitive "entry point".
DO NOT use ole32.dll when generating DLL stubs. Doing so can cause infinite recursion during LoadLibrary/COM activation and lead to unstable or hard-to-debug behavior (e.g., repeated loader calls, crashes, or the target process hanging).
Why: ole32.dll is heavily involved in COM activation and in-process marshaling. Creating stubs that forward or re-export COM/ole32 entry points can easily create circular calls where the loader repeatedly invokes the same activation paths.
The configuration file redirect_config.toml must be placed in the same directory(or working directory) as the DLL. If an entry is not specified, default value will be used.
# Path for the log file. "" (empty string) defaults to the working directory.
log_path = ""
# Log level: Trace, Debug, Info, Warn, Error, Never
log_level = "Info"
# Log only to stdout (true) or to both stdout and file (false).
only_log_stdout = false
[playback]
# Target buffer duration in 0.1ms units (u16).
# The tool will calculate the closest buffer size *not exceeding* this duration while clamped within driver range.
# e.g., 10 = 1ms.
target_buffer_dur_ms = 10
# Force this stream into compat mode (bool)
compat = false
[capture]
target_buffer_dur_ms = 10
compat = false-
log_path(string): Where to save the log file. Non-directory value means current working directory. -
log_level(string):Trace,Debug,Info,Warn,Error,Never. Default isInfo.
See performance warning below. -
only_log_stdout(bool): Controls logging targets.true: Logs only to the standard output (stdout). No log file will be created.false(Default): Logs to both the standard output (stdout) and the file specified bylog_path.- This option is particularly useful for developers who want to monitor logs in real-time in a terminal or for applications running in containerized environments (like Docker) where capturing stdout is the standard practice.
-
[playback]/[capture]: Separate configs for output and input.-
target_buffer_dur_ms(u16): The target buffer size in units of 0.1 milliseconds. The tool will default to the driver's minimum if this is set too low or not specified. You should generally not change this from the default value unless you experience audio pops. -
compat(bool): Forces this stream to use Compat Mode.
-
Use this guide to diagnose and fix common audio issues.
Phenomenon: Sound is heavily distorted, stretched, or sounds like it's being "sliced" and played back slowly.
Cause: This is the classic sign of a Poll-driven application running in Normal Mode (compat = false). The app's polling logic is fighting the event-driven buffer. This is commonly seen in Unity games.
Solution: Set compat = true for the [playback] section.
Phenomenon: Audio playback is at the correct speed and pitch, but you hear intermittent pops, clicks, or small tearing sounds.
Cause: The buffer is too small for your system/software. Your CPU or the application cannot "feed" the audio driver new data fast enough, resulting in a buffer underrun.
Solutions (Try in order):
-
Increase Buffer: Slightly increase
target_buffer_dur_ms. If your driver's minimum is 2ms (e.g.,20), try30(3ms) or40(4ms) until the pops disappear. -
Try Compat Mode: Set
compat = true. This effectively adds a buffer layer for the application (i.e., the standard buffer from normal Shared mode). In combination with the changes made by Compat mode, this can potentially resolve the issue.
Phenomenon: The target program fails to start after loading the DLL.
Cause: This is usually a file permission issue — the DLL attempts to write its log file to a location where it lacks write access.
It commonly occurs when the target executable resides under Program Files or other protected directories.
Solution: Specify a writable location for log_path in redirect_config.toml.
For example:
log_path = "C:\\Users\\Public\\wasapi_relink.log"If you don't need logging to file, you can also disable it with only_log_stdout :
only_log_stdout = falseOr, you can entirely disable logging (not recommended):
log_level = "Never"The Windows audio engine is extremely sensitive to timing.
-
DO NOT set
log_leveltoDebugorTracefor normal use. -
The high-frequency I/O (disk writing) from detailed logging will interfere with the audio thread, especially at low buffer sizes.
-
This interference will cause audio tearing, pops, and stuttering.
-
ONLY use
Debug/Traceif you are actively debugging the tool itself and you know what you are doing.
Previous tools(REAL, LowAudioLatency and similar projects) attempted to solve this by running a separate low-latency IAudioClient3 application in the background.
-
What they got right: As said the Windows FAQ, this does trigger the special Windows behavior and forces the hardware buffer to a smaller size for all apps.
-
What they missed (The "Myth"): They assumed lowering the hardware buffer was enough. It isn't. A poll-driven application will still try to prefill its old 10ms buffer. The latency bottleneck just moves from the hardware to the application's own prefill.
wasapi_relink's Compat Mode solves both problems: it triggers the hardware change and internally hooks the application to deceive and modify its prefill to match the new, smaller hardware buffer.
wasapi_relink does not use simple VTable hooking. It hooks at the root of the COM audio system to ensure 100% capture.
-
Hook:
CoCreateInstanceEx. -
Intercept: When the app requests
CLSID_MMDeviceEnumerator(the main audio device enumerator),wasapi_relinkcreates the real one and returns a custom wrappedIMMDeviceEnumeratorto the app. -
Propagate: When the app requests device on this wrapper,
wasapi_relinkreturns a wrappedIMMDevice.3.1. Execute (Compat Mode): When the app calls
Activateon the wrappedIMMDevice, wasapi_relink executes its core Compat Mode logic (creating the two clients) and returns one wrappedIAudioClient.3.2.Execute (Normal Mode): When the app calls
Initializeon the wrappedIAudioClient, the Normal Mode logic is executed. -
This wrapper chain continues all the way down to
IAudioRenderClient, givingwasapi_relinkfull, transparent control over the entire audio stream lifecycle.
In Compat Mode, capture (mic) streams are simply forwarded. This is intentional:
- Mic latency is far less critical in Shared mode compared to effects or network latency. Due to the nature of capture streams, which don’t require a silent pre-fill buffer in their interaction with the driver, triggering Windows’ special behavior is by itself sufficient to reduce latency.
- Users with true low-latency input needs are already using
ASIOorWASAPI Exclusivemode, which this tool does not target.
This is an experimental and educational project.
Keep in mind:
- Hooking may trigger anti-cheat detections in some games.
- WASAPI internals and buffer behavior can differ between Windows builds or drivers.
- Use it responsibly — at your own risk.