Skip to main content

audio_engine_core/
config.rs

1use serde::{Deserialize, Serialize};
2
3pub use crate::processor::SaturationType;
4
5/// Resampling quality preset, trading CPU cost for stopband attenuation and
6/// transition-band sharpness.
7#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Default)]
8pub enum ResampleQuality {
9    /// Fastest, lowest fidelity.
10    Low,
11    /// Balanced quality suitable for general playback.
12    Standard,
13    /// High quality; the default.
14    #[default]
15    High,
16    /// Maximum quality (SoX VHQ), highest CPU cost.
17    UltraHigh,
18}
19
20/// Phase response for the resampling filter.
21#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
22pub enum PhaseResponse {
23    /// Linear phase: symmetric impulse, no phase distortion, higher latency.
24    #[default]
25    Linear,
26    /// Minimum phase: lowest latency, some phase distortion.
27    Minimum,
28    /// Maximum phase: energy concentrated toward the end of the impulse.
29    Maximum,
30}
31
32impl PhaseResponse {
33    /// Convert to soxr phase_response value.
34    pub fn to_soxr_value(&self) -> f64 {
35        match self {
36            PhaseResponse::Minimum => 0.0,
37            PhaseResponse::Linear => 50.0,
38            PhaseResponse::Maximum => 100.0,
39        }
40    }
41}
42
43/// Loudness normalization reference mode: which measured gain to apply.
44#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
45pub enum NormalizationMode {
46    /// Normalize each track to its own integrated loudness.
47    #[default]
48    Track,
49    /// Normalize using album-wide integrated loudness (preserves intra-album dynamics).
50    Album,
51    /// Normalize toward a streaming-style target.
52    Streaming,
53    /// Apply ReplayGain track gain.
54    ReplayGainTrack,
55    /// Apply ReplayGain album gain.
56    ReplayGainAlbum,
57}
58
59/// EBU R128 loudness normalization settings.
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct LoudnessConfig {
62    /// Target integrated loudness in LUFS.
63    pub target_lufs: f64,
64    /// True-peak ceiling in dBTP applied after gain.
65    pub true_peak_limit_db: f64,
66    /// Gain-change smoothing time constant in milliseconds.
67    pub smoothing_time_ms: f64,
68    /// Which reference gain to apply (see [`NormalizationMode`]).
69    pub mode: NormalizationMode,
70    /// Whether normalization is active.
71    pub enabled: bool,
72    /// Reference loudness for ReplayGain conversion, in LUFS.
73    pub replaygain_reference_lufs: f64,
74}
75
76impl Default for LoudnessConfig {
77    fn default() -> Self {
78        Self {
79            target_lufs: -12.0,
80            true_peak_limit_db: -0.5,
81            smoothing_time_ms: 200.0,
82            mode: NormalizationMode::Track,
83            enabled: true,
84            replaygain_reference_lufs: -18.0,
85        }
86    }
87}
88
89/// Harmonic saturation settings (tube/tape/transistor coloration).
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct SaturationConfig {
92    /// Saturation character.
93    pub sat_type: SaturationType,
94    /// Drive amount (0.0–2.0); higher adds more harmonics.
95    pub drive: f64,
96    /// Linear threshold above which saturation engages.
97    pub threshold: f64,
98    /// Dry/wet blend (0.0 = dry, 1.0 = fully saturated).
99    pub mix: f64,
100    /// Input gain in dB applied before saturation.
101    pub input_gain_db: f64,
102    /// Output gain in dB applied after saturation, for level compensation.
103    pub output_gain_db: f64,
104    /// Whether saturation is active.
105    pub enabled: bool,
106}
107
108impl Default for SaturationConfig {
109    fn default() -> Self {
110        Self {
111            sat_type: SaturationType::Tube,
112            drive: 0.25,
113            threshold: 0.88,
114            mix: 0.2,
115            input_gain_db: 0.0,
116            output_gain_db: 0.0,
117            enabled: true,
118        }
119    }
120}
121
122/// Dynamic loudness compensation settings (ISO 226 / Fletcher-Munson).
123///
124/// Boosts perceptually weak frequency bands at low listening levels so the
125/// tonal balance stays consistent as volume drops.
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct DynamicLoudnessConfig {
128    /// Reference listening level in dB at which no compensation is applied.
129    pub ref_volume_db: f64,
130    /// Width in dB of the transition region around the reference level.
131    pub transition_db: f64,
132    /// Compensation strength multiplier (1.0 = full ISO 226 curve).
133    pub strength: f64,
134    /// Pre-gain in dB applied before compensation.
135    pub pre_gain_db: f64,
136    /// Whether dynamic loudness compensation is active.
137    pub enabled: bool,
138}
139
140impl Default for DynamicLoudnessConfig {
141    fn default() -> Self {
142        Self {
143            ref_volume_db: -15.0,
144            transition_db: 25.0,
145            strength: 1.0,
146            pre_gain_db: -3.0,
147            enabled: false,
148        }
149    }
150}
151
152/// Bauer-style binaural crossfeed settings for headphone listening.
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct CrossfeedConfig {
155    /// Whether crossfeed is active.
156    pub enabled: bool,
157    /// Blend amount from 0.0 (off) to 1.0 (maximum crossfeed).
158    pub mix: f64,
159}
160
161impl Default for CrossfeedConfig {
162    fn default() -> Self {
163        Self {
164            enabled: false,
165            mix: 0.3,
166        }
167    }
168}
169
170/// Dither and noise-shaping settings applied at the final bit-depth reduction.
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct DitherConfig {
173    /// Whether dithering is active.
174    pub enabled: bool,
175    /// Noise-shaping curve used to push quantization noise out of audible bands.
176    pub noise_shaper_curve: crate::processor::NoiseShaperCurve,
177}
178
179impl Default for DitherConfig {
180    fn default() -> Self {
181        Self {
182            enabled: true,
183            noise_shaper_curve: crate::processor::NoiseShaperCurve::Lipshitz5,
184        }
185    }
186}