rustriff_lib/domain/dto/algorithmic_latency_dto.rs
1//! DTO for the algorithmic (design-inherent) latency of a single DSP processor.
2//!
3//! Produced by [`AudioLatencyMeasurementService::measure_all_dsp_algorithmic_latency`]
4//! and serialised across the Tauri IPC boundary to the developer-mode UI overlay.
5//!
6//! [`AudioLatencyMeasurementService::measure_all_dsp_algorithmic_latency`]: crate::services::audio_latency_measurement_service::AudioLatencyMeasurementService::measure_all_dsp_algorithmic_latency
7
8use serde::{Deserialize, Serialize};
9
10/// Algorithmic latency contributed by one processor in the DSP signal chain.
11///
12/// Algorithmic latency is the *design-inherent* sample delay an effect introduces —
13/// for example, a look-ahead limiter that must buffer `N` input samples before it can
14/// emit the first output sample adds `N` samples of algorithmic latency, independent
15/// of CPU speed.
16///
17/// For sample-by-sample processors such as `GainProcessor` and `ToneStackProcessor`
18/// this value is always **zero** because no sample is ever buffered or delayed.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(crate = "serde")]
21pub struct AlgorithmicLatencyDto {
22 /// Name of the DSP processor (e.g. `"Gain"`, `"Tone Stack"`, `"Master Volume"`).
23 pub processor_name: String,
24
25 /// Number of audio samples of algorithmic delay introduced by this processor.
26 ///
27 /// Zero for all current processors.
28 pub latency_samples: u32,
29
30 /// Algorithmic delay converted to milliseconds at the current output sample rate.
31 ///
32 /// Computed as `(latency_samples / sample_rate_hz) × 1000`. Zero when
33 /// `latency_samples` is zero or `sample_rate_hz` is zero.
34 pub latency_ms: f64,
35}
36
37impl AlgorithmicLatencyDto {
38 /// Creates a new entry for the named processor, converting samples to ms automatically.
39 ///
40 /// # Arguments
41 ///
42 /// * `processor_name` — Human-readable processor identifier.
43 /// * `latency_samples` — Number of samples of algorithmic delay.
44 /// * `sample_rate_hz` — Output sample rate used for the ms conversion.
45 /// If `0`, `latency_ms` is set to `0.0` to avoid a division-by-zero.
46 pub fn new(
47 processor_name: impl Into<String>,
48 latency_samples: u32,
49 sample_rate_hz: u32,
50 ) -> Self {
51 let latency_ms = if sample_rate_hz == 0 {
52 0.0
53 } else {
54 (latency_samples as f64 / sample_rate_hz as f64) * 1000.0
55 };
56
57 Self {
58 processor_name: processor_name.into(),
59 latency_samples,
60 latency_ms,
61 }
62 }
63}