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}