1use serde::{Deserialize, Serialize};
4
5use crate::dsp::effects::convolution_reverb::ImpulseResponseSpec;
6
7pub mod basic_reverb;
8mod biquad;
9pub mod compressor;
10pub mod convolution_reverb;
11pub mod diffusion_reverb;
12pub mod distortion;
13pub mod gain;
14pub mod high_pass;
15mod level;
16pub mod limiter;
17pub mod low_pass;
18pub mod multiband_eq;
19
20#[allow(deprecated)]
21#[deprecated(note = "Use DelayReverbEffect instead.")]
22pub use basic_reverb::BasicReverbEffect;
23#[allow(deprecated)]
24#[deprecated(note = "Use DelayReverbSettings instead.")]
25pub use basic_reverb::BasicReverbSettings;
26pub use basic_reverb::{DelayReverbEffect, DelayReverbSettings};
27pub use compressor::{CompressorEffect, CompressorSettings};
28pub use convolution_reverb::{ConvolutionReverbEffect, ConvolutionReverbSettings};
29pub use diffusion_reverb::{DiffusionReverbEffect, DiffusionReverbSettings};
30pub use distortion::{DistortionEffect, DistortionSettings};
31pub use gain::{GainEffect, GainSettings};
32pub use high_pass::{HighPassFilterEffect, HighPassFilterSettings};
33pub use limiter::{LimiterEffect, LimiterSettings};
34pub use low_pass::{LowPassFilterEffect, LowPassFilterSettings};
35pub use multiband_eq::{
36 EqPointSettings, HighEdgeFilterSettings, LowEdgeFilterSettings, MultibandEqEffect,
37 MultibandEqSettings,
38};
39
40#[derive(Debug, Clone)]
42pub struct EffectContext {
43 pub sample_rate: u32,
44 pub channels: usize,
45 pub container_path: Option<String>,
46 pub impulse_response_spec: Option<ImpulseResponseSpec>,
47 pub impulse_response_tail_db: f32,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52pub enum AudioEffect {
53 #[serde(rename = "DelayReverbSettings")]
54 DelayReverb(DelayReverbEffect),
55 #[deprecated(note = "Use AudioEffect::DelayReverb instead.")]
56 #[serde(rename = "BasicReverbSettings")]
57 BasicReverb(DelayReverbEffect),
58 #[serde(rename = "DiffusionReverbSettings")]
59 DiffusionReverb(DiffusionReverbEffect),
60 #[serde(rename = "ConvolutionReverbSettings")]
61 ConvolutionReverb(ConvolutionReverbEffect),
62 #[serde(rename = "LowPassFilterSettings")]
63 LowPassFilter(LowPassFilterEffect),
64 #[serde(rename = "HighPassFilterSettings")]
65 HighPassFilter(HighPassFilterEffect),
66 #[serde(rename = "DistortionSettings")]
67 Distortion(DistortionEffect),
68 #[serde(rename = "GainSettings")]
69 Gain(GainEffect),
70 #[serde(rename = "CompressorSettings")]
71 Compressor(CompressorEffect),
72 #[serde(rename = "LimiterSettings")]
73 Limiter(LimiterEffect),
74 #[serde(rename = "MultibandEqSettings")]
75 MultibandEq(MultibandEqEffect),
76}
77
78impl AudioEffect {
79 #[allow(deprecated)]
89 pub fn process(&mut self, samples: &[f32], context: &EffectContext, drain: bool) -> Vec<f32> {
90 match self {
91 AudioEffect::BasicReverb(effect) => effect.process(samples, context, drain),
92 AudioEffect::DelayReverb(effect) => effect.process(samples, context, drain),
93 AudioEffect::DiffusionReverb(effect) => effect.process(samples, context, drain),
94 AudioEffect::ConvolutionReverb(effect) => effect.process(samples, context, drain),
95 AudioEffect::LowPassFilter(effect) => effect.process(samples, context, drain),
96 AudioEffect::HighPassFilter(effect) => effect.process(samples, context, drain),
97 AudioEffect::Distortion(effect) => effect.process(samples, context, drain),
98 AudioEffect::Gain(effect) => effect.process(samples, context, drain),
99 AudioEffect::Compressor(effect) => effect.process(samples, context, drain),
100 AudioEffect::Limiter(effect) => effect.process(samples, context, drain),
101 AudioEffect::MultibandEq(effect) => effect.process(samples, context, drain),
102 }
103 }
104
105 #[allow(deprecated)]
107 pub fn reset_state(&mut self) {
108 match self {
109 AudioEffect::BasicReverb(effect) => effect.reset_state(),
110 AudioEffect::DelayReverb(effect) => effect.reset_state(),
111 AudioEffect::DiffusionReverb(effect) => effect.reset_state(),
112 AudioEffect::ConvolutionReverb(effect) => effect.reset_state(),
113 AudioEffect::LowPassFilter(effect) => effect.reset_state(),
114 AudioEffect::HighPassFilter(effect) => effect.reset_state(),
115 AudioEffect::Distortion(effect) => effect.reset_state(),
116 AudioEffect::Gain(effect) => effect.reset_state(),
117 AudioEffect::Compressor(effect) => effect.reset_state(),
118 AudioEffect::Limiter(effect) => effect.reset_state(),
119 AudioEffect::MultibandEq(effect) => effect.reset_state(),
120 }
121 }
122
123 #[allow(deprecated)]
125 pub fn warm_up(&mut self, context: &EffectContext) {
126 match self {
127 AudioEffect::BasicReverb(_) => {}
128 AudioEffect::DelayReverb(_) => {}
129 AudioEffect::DiffusionReverb(_) => {}
130 AudioEffect::ConvolutionReverb(effect) => {
131 let _ = effect.process(&[], context, false);
132 }
133 AudioEffect::LowPassFilter(_) => {}
134 AudioEffect::HighPassFilter(_) => {}
135 AudioEffect::Distortion(_) => {}
136 AudioEffect::Gain(_) => {}
137 AudioEffect::Compressor(_) => {}
138 AudioEffect::Limiter(_) => {}
139 AudioEffect::MultibandEq(_) => {}
140 }
141 }
142
143 pub fn as_convolution_reverb_mut(&mut self) -> Option<&mut ConvolutionReverbEffect> {
145 match self {
146 AudioEffect::ConvolutionReverb(effect) => Some(effect),
147 _ => None,
148 }
149 }
150
151 pub fn as_convolution_reverb(&self) -> Option<&ConvolutionReverbEffect> {
153 match self {
154 AudioEffect::ConvolutionReverb(effect) => Some(effect),
155 _ => None,
156 }
157 }
158
159 pub fn as_diffusion_reverb_mut(&mut self) -> Option<&mut DiffusionReverbEffect> {
161 match self {
162 AudioEffect::DiffusionReverb(effect) => Some(effect),
163 _ => None,
164 }
165 }
166
167 pub fn as_diffusion_reverb(&self) -> Option<&DiffusionReverbEffect> {
169 match self {
170 AudioEffect::DiffusionReverb(effect) => Some(effect),
171 _ => None,
172 }
173 }
174
175 #[allow(deprecated)]
177 pub fn as_delay_reverb_mut(&mut self) -> Option<&mut DelayReverbEffect> {
178 match self {
179 AudioEffect::DelayReverb(effect) => Some(effect),
180 AudioEffect::BasicReverb(effect) => Some(effect),
181 _ => None,
182 }
183 }
184
185 #[allow(deprecated)]
187 pub fn as_delay_reverb(&self) -> Option<&DelayReverbEffect> {
188 match self {
189 AudioEffect::DelayReverb(effect) => Some(effect),
190 AudioEffect::BasicReverb(effect) => Some(effect),
191 _ => None,
192 }
193 }
194
195 #[deprecated(note = "Use as_delay_reverb_mut instead.")]
197 #[allow(deprecated)]
198 pub fn as_basic_reverb_mut(&mut self) -> Option<&mut BasicReverbEffect> {
199 self.as_delay_reverb_mut()
200 }
201
202 #[deprecated(note = "Use as_delay_reverb instead.")]
204 #[allow(deprecated)]
205 pub fn as_basic_reverb(&self) -> Option<&BasicReverbEffect> {
206 self.as_delay_reverb()
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[test]
215 fn audio_effect_serde_roundtrip_variants() {
216 let effects = vec![
217 AudioEffect::DelayReverb(DelayReverbEffect::default()),
218 AudioEffect::DiffusionReverb(DiffusionReverbEffect::default()),
219 AudioEffect::ConvolutionReverb(ConvolutionReverbEffect::default()),
220 AudioEffect::LowPassFilter(LowPassFilterEffect::default()),
221 AudioEffect::HighPassFilter(HighPassFilterEffect::default()),
222 AudioEffect::Distortion(DistortionEffect::default()),
223 AudioEffect::Gain(GainEffect::default()),
224 AudioEffect::Compressor(CompressorEffect::default()),
225 AudioEffect::Limiter(LimiterEffect::default()),
226 AudioEffect::MultibandEq(MultibandEqEffect::default()),
227 ];
228
229 let json = serde_json::to_string(&effects).expect("serialize effects");
230 let decoded: Vec<AudioEffect> = serde_json::from_str(&json).expect("deserialize effects");
231 assert_eq!(decoded.len(), effects.len());
232 }
233
234 #[test]
235 fn audio_effect_serde_accepts_aliases() {
236 let json = r#"
237 [
238 {"ConvolutionReverbSettings":{"enabled":true,"wet_dry":0.25}},
239 {"DelayReverbSettings":{"enabled":true,"dry_wet":0.5}},
240 {"BasicReverbSettings":{"enabled":true,"dry_wet":0.5}},
241 {"DiffusionReverbSettings":{"enabled":true,"dry_wet":0.35}},
242 {"LowPassFilterSettings":{"enabled":true,"freq":800,"bandwidth":0.7}},
243 {"HighPassFilterSettings":{"enabled":true,"frequency_hz":1200,"q":0.9}},
244 {"DistortionSettings":{"enabled":true,"gain":2.0,"threshold":0.4}},
245 {"GainSettings":{"enabled":true,"gain":1.25}},
246 {"CompressorSettings":{"enabled":true,"threshold":-12.0,"ratio":2.0,
247 "attack":5.0,"release":50.0,"makeup_db":3.0}},
248 {"LimiterSettings":{"enabled":true,"threshold_db":-3.0,"knee_width":2.0,
249 "attack_ms":3.0,"release_ms":30.0}},
250 {"MultibandEqSettings":{
251 "enabled":true,
252 "points":[
253 {"freq_hz":120,"q":0.8,"gain_db":3.0},
254 {"freq_hz":1000,"q":1.0,"gain_db":-2.0},
255 {"freq_hz":8000,"q":0.8,"gain_db":2.5}
256 ],
257 "low_edge":{"type":"high_pass","freq_hz":60,"q":0.7},
258 "high_edge":{"type":"high_shelf","freq_hz":10000,"q":0.8,"gain_db":1.5}
259 }}
260 ]
261 "#;
262
263 let decoded: Vec<AudioEffect> = serde_json::from_str(json).expect("deserialize effects");
264 assert_eq!(decoded.len(), 11);
265 }
266}