pub struct RoundTripLatencySession;Expand description
Self-contained round-trip latency measurement session.
RoundTripLatencySession has no fields; it acts as a namespace for the run function.
All state lives on the stack inside that call, making the session automatically torn down
when it returns — there is nothing to clean up manually.
§Thread safety
run is a blocking call designed to execute on a dedicated thread. The caller
(measure_round_trip_latency Tauri command) clones the handler reference, releases the
Mutex<AudioService> lock, and then spawns a thread that calls this function. This
means the main audio engine remains fully operational during the measurement.
Implementations§
Source§impl RoundTripLatencySession
impl RoundTripLatencySession
Sourcepub fn run(
handler: &dyn AudioHandlerTrait,
per_impulse_timeout: Duration,
stream_warmup: Duration,
) -> Result<f64, String>
pub fn run( handler: &dyn AudioHandlerTrait, per_impulse_timeout: Duration, stream_warmup: Duration, ) -> Result<f64, String>
Runs a complete round-trip latency measurement and returns the average in milliseconds.
§What this function does
- Determines a safe ring-buffer size from the handler’s configured buffer frames
(falling back to 256 if
BufferSize::Defaultis in use), then multiplies by 4 to give the streams room to breathe during warmup and calibration. - Creates a dedicated input ring buffer (
i_producer→i_consumer) and a dedicated output ring buffer (o_producer→o_consumer), both completely separate from the main loopback ring buffers. - Opens a CPAL input stream that pushes captured samples into
i_producerand a CPAL output stream that drains processed samples fromo_consumer, then starts both. - Sleeps for
stream_warmupto let the OS audio scheduler and hardware settle. - Drains all samples accumulated during warmup from
i_consumerso that calibration begins with fresh, stable ambient data. - Enters the main sample-processing loop, feeding each incoming sample to
RoundTripMeasurementState::tickuntil a terminal outcome is reached or theoverall_deadlineexpires.
The overall_deadline is set to per_impulse_timeout × IMPULSE_COUNT + 2 s to
account for calibration time and inter-impulse gaps while still guaranteeing the
function cannot block indefinitely.
§Arguments
handler— Audio I/O factory. Used only to size ring buffers and build streams; it is not the same handler instance that the main loopback uses concurrently.per_impulse_timeout— Maximum time to wait for a single echo after the impulse is emitted. Recommended: 10 s for real hardware, shorter for unit tests.stream_warmup— How long to sleep after starting streams before beginning calibration. Recommended: 1–2 s to allow ASIO/WASAPI buffers to stabilise.
§Returns
Ok(latency_ms)— Averaged round-trip latency across allIMPULSE_COUNTcycles.Err(message)— Human-readable failure reason; either a timeout, an undetectable echo (signal too quiet or output not routed to input), or an overall deadline breach.