Class WasapiRecorder
Modern WASAPI audio recorder with zero-copy buffer access, MMCSS thread priority, process-specific loopback capture, and IAsyncEnumerable support. Created via WasapiRecorderBuilder.
public class WasapiRecorder : IDisposable, IAsyncDisposable, IWaveLatency
- Inheritance
-
WasapiRecorder
- Implements
- Inherited Members
Properties
AcousticEchoCancellationControl
Gets the acoustic echo cancellation (AEC) reference control for this capture stream, or null if the endpoint does not support controlling the AEC reference endpoint. Use it to change the render endpoint used as the echo cancellation reference stream while recording.
public AcousticEchoCancellationControl AcousticEchoCancellationControl { get; }
Property Value
Remarks
Only available after StartRecording() (or CaptureAsync(CancellationToken)) has initialized the audio client. Returns null before then. Requires Windows 11 build 22621 or later.
AverageLatency
The steady-state latency from a sample being queued for output to it being emitted by the audio hardware, assuming uninterrupted playback. This is a property of the buffer configuration and the driver, not of the current playback state.
public TimeSpan AverageLatency { get; }
Property Value
Remarks
Uses LatencyMilliseconds once the audio client has been initialised (so it reflects the actual engine period — including any reduction from IAudioClient3 low-latency mode), falling back to the requested buffer length before then.
CaptureState
Current capture state.
public CaptureState CaptureState { get; }
Property Value
CurrentLatency
The time that has elapsed since the sample currently emerging from the hardware was queued for output. In steady state this is approximately equal to AverageLatency; it differs during start-up, after an underrun, or when the host is filling buffers irregularly. Implementations that cannot meaningfully distinguish from the average are permitted to return AverageLatency.
public TimeSpan CurrentLatency { get; }
Property Value
Remarks
Derived from IAudioClient::GetCurrentPadding: on a capture stream this is the
count of frames already captured but not yet read by the host. Falls back to
AverageLatency when not recording or before the audio client is up.
DeviceFriendlyName
The friendly name of the device this recorder was created on (e.g. "Microphone (USB Audio Device)"), captured at construction. Useful for display and logging. Null when there is no fixed capture endpoint — see DeviceId.
public string DeviceFriendlyName { get; }
Property Value
DeviceId
The endpoint ID of the device this recorder was created on, captured at construction — the same string accepted by GetDevice(string). Persist it to reopen the same physical device later (for example after the endpoint is disabled and re-enabled).
public string DeviceId { get; }
Property Value
Remarks
Null when there is no fixed capture endpoint — that is, process-loopback capture (WithProcessLoopback(uint, ProcessLoopbackMode)) or when following the default device with automatic stream routing (WithDefaultDeviceStreamRouting()), where Windows may transparently reroute the stream at any time. To discover the current default endpoint in the routing case, resolve it yourself via GetDefaultAudioEndpoint(DataFlow, Role) and track changes with an MMDeviceNotificationClient.
LatencyMilliseconds
The effective latency in milliseconds in use after recording has been initialized. In standard mode this is the configured buffer length; in IAudioClient3 low-latency mode it is derived from the engine period the device granted, so it is typically much smaller. Zero before StartRecording() (or CaptureAsync(CancellationToken)) has initialized the audio client.
public int LatencyMilliseconds { get; }
Property Value
LowLatencyActive
Whether IAudioClient3 low-latency shared mode is actually in use after recording has been initialized. This is only ever true when WithLowLatency(bool) was requested and the device, share mode, and capture format allowed it. When low latency was requested but could not be honoured, capture silently falls back to standard shared mode and this remains false — check it to find out what you actually got.
public bool LowLatencyActive { get; }
Property Value
LowLatencyUnavailableReason
When low latency was requested via WithLowLatency(bool) but could not be honoured, a short human-readable explanation of why (e.g. the requested capture format did not match the device mix format). Null when low latency is active or was never requested.
public string LowLatencyUnavailableReason { get; }
Property Value
WaveFormat
The capture format.
public WaveFormat WaveFormat { get; }
Property Value
Methods
CaptureAsync(CancellationToken)
Capture audio as an async enumerable. Each yielded AudioBuffer contains a copy of the captured data (safe to store/process asynchronously). Use the DataAvailable event for zero-copy processing instead.
public IAsyncEnumerable<AudioBuffer> CaptureAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationToken
Returns
Dispose()
Dispose
public void Dispose()
DisposeAsync()
Async dispose.
public ValueTask DisposeAsync()
Returns
StartRecording()
Start recording.
public void StartRecording()
StopRecording()
Stop recording.
public void StopRecording()
Events
DataAvailable
Fired when captured audio data is available. The buffer span is only valid for the duration of the callback — copy it if you need to keep it. The handler also receives the packet's WASAPI device and QPC positions for timestamping.
public event CaptureDataAvailableHandler DataAvailable
Event Type
RecordingStopped
Fired when recording stops, either by request or due to an error.
public event EventHandler<StoppedEventArgs> RecordingStopped