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;
18
19#[allow(deprecated)]
20#[deprecated(note = "Use DelayReverbEffect instead.")]
21pub use basic_reverb::BasicReverbEffect;
22#[allow(deprecated)]
23#[deprecated(note = "Use DelayReverbSettings instead.")]
24pub use basic_reverb::BasicReverbSettings;
25pub use basic_reverb::{DelayReverbEffect, DelayReverbSettings};
26pub use compressor::{CompressorEffect, CompressorSettings};
27pub use convolution_reverb::{ConvolutionReverbEffect, ConvolutionReverbSettings};
28pub use diffusion_reverb::{DiffusionReverbEffect, DiffusionReverbSettings};
29pub use distortion::{DistortionEffect, DistortionSettings};
30pub use gain::{GainEffect, GainSettings};
31pub use high_pass::{HighPassFilterEffect, HighPassFilterSettings};
32pub use limiter::{LimiterEffect, LimiterSettings};
33pub use low_pass::{LowPassFilterEffect, LowPassFilterSettings};
34
35#[derive(Debug, Clone)]
37pub struct EffectContext {
38 pub sample_rate: u32,
39 pub channels: usize,
40 pub container_path: Option<String>,
41 pub impulse_response_spec: Option<ImpulseResponseSpec>,
42 pub impulse_response_tail_db: f32,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub enum AudioEffect {
48 #[serde(rename = "DelayReverbSettings")]
49 DelayReverb(DelayReverbEffect),
50 #[deprecated(note = "Use AudioEffect::DelayReverb instead.")]
51 #[serde(rename = "BasicReverbSettings")]
52 BasicReverb(DelayReverbEffect),
53 #[serde(rename = "DiffusionReverbSettings")]
54 DiffusionReverb(DiffusionReverbEffect),
55 #[serde(rename = "ConvolutionReverbSettings")]
56 ConvolutionReverb(ConvolutionReverbEffect),
57 #[serde(rename = "LowPassFilterSettings")]
58 LowPassFilter(LowPassFilterEffect),
59 #[serde(rename = "HighPassFilterSettings")]
60 HighPassFilter(HighPassFilterEffect),
61 #[serde(rename = "DistortionSettings")]
62 Distortion(DistortionEffect),
63 #[serde(rename = "GainSettings")]
64 Gain(GainEffect),
65 #[serde(rename = "CompressorSettings")]
66 Compressor(CompressorEffect),
67 #[serde(rename = "LimiterSettings")]
68 Limiter(LimiterEffect),
69}
70
71impl AudioEffect {
72 #[allow(deprecated)]
82 pub fn process(&mut self, samples: &[f32], context: &EffectContext, drain: bool) -> Vec<f32> {
83 match self {
84 AudioEffect::BasicReverb(effect) => effect.process(samples, context, drain),
85 AudioEffect::DelayReverb(effect) => effect.process(samples, context, drain),
86 AudioEffect::DiffusionReverb(effect) => effect.process(samples, context, drain),
87 AudioEffect::ConvolutionReverb(effect) => effect.process(samples, context, drain),
88 AudioEffect::LowPassFilter(effect) => effect.process(samples, context, drain),
89 AudioEffect::HighPassFilter(effect) => effect.process(samples, context, drain),
90 AudioEffect::Distortion(effect) => effect.process(samples, context, drain),
91 AudioEffect::Gain(effect) => effect.process(samples, context, drain),
92 AudioEffect::Compressor(effect) => effect.process(samples, context, drain),
93 AudioEffect::Limiter(effect) => effect.process(samples, context, drain),
94 }
95 }
96
97 #[allow(deprecated)]
99 pub fn reset_state(&mut self) {
100 match self {
101 AudioEffect::BasicReverb(effect) => effect.reset_state(),
102 AudioEffect::DelayReverb(effect) => effect.reset_state(),
103 AudioEffect::DiffusionReverb(effect) => effect.reset_state(),
104 AudioEffect::ConvolutionReverb(effect) => effect.reset_state(),
105 AudioEffect::LowPassFilter(effect) => effect.reset_state(),
106 AudioEffect::HighPassFilter(effect) => effect.reset_state(),
107 AudioEffect::Distortion(effect) => effect.reset_state(),
108 AudioEffect::Gain(effect) => effect.reset_state(),
109 AudioEffect::Compressor(effect) => effect.reset_state(),
110 AudioEffect::Limiter(effect) => effect.reset_state(),
111 }
112 }
113
114 #[allow(deprecated)]
116 pub fn warm_up(&mut self, context: &EffectContext) {
117 match self {
118 AudioEffect::BasicReverb(_) => {}
119 AudioEffect::DelayReverb(_) => {}
120 AudioEffect::DiffusionReverb(_) => {}
121 AudioEffect::ConvolutionReverb(effect) => {
122 let _ = effect.process(&[], context, false);
123 }
124 AudioEffect::LowPassFilter(_) => {}
125 AudioEffect::HighPassFilter(_) => {}
126 AudioEffect::Distortion(_) => {}
127 AudioEffect::Gain(_) => {}
128 AudioEffect::Compressor(_) => {}
129 AudioEffect::Limiter(_) => {}
130 }
131 }
132
133 pub fn as_convolution_reverb_mut(&mut self) -> Option<&mut ConvolutionReverbEffect> {
135 match self {
136 AudioEffect::ConvolutionReverb(effect) => Some(effect),
137 _ => None,
138 }
139 }
140
141 pub fn as_convolution_reverb(&self) -> Option<&ConvolutionReverbEffect> {
143 match self {
144 AudioEffect::ConvolutionReverb(effect) => Some(effect),
145 _ => None,
146 }
147 }
148
149 pub fn as_diffusion_reverb_mut(&mut self) -> Option<&mut DiffusionReverbEffect> {
151 match self {
152 AudioEffect::DiffusionReverb(effect) => Some(effect),
153 _ => None,
154 }
155 }
156
157 pub fn as_diffusion_reverb(&self) -> Option<&DiffusionReverbEffect> {
159 match self {
160 AudioEffect::DiffusionReverb(effect) => Some(effect),
161 _ => None,
162 }
163 }
164
165 #[allow(deprecated)]
167 pub fn as_delay_reverb_mut(&mut self) -> Option<&mut DelayReverbEffect> {
168 match self {
169 AudioEffect::DelayReverb(effect) => Some(effect),
170 AudioEffect::BasicReverb(effect) => Some(effect),
171 _ => None,
172 }
173 }
174
175 #[allow(deprecated)]
177 pub fn as_delay_reverb(&self) -> Option<&DelayReverbEffect> {
178 match self {
179 AudioEffect::DelayReverb(effect) => Some(effect),
180 AudioEffect::BasicReverb(effect) => Some(effect),
181 _ => None,
182 }
183 }
184
185 #[deprecated(note = "Use as_delay_reverb_mut instead.")]
187 #[allow(deprecated)]
188 pub fn as_basic_reverb_mut(&mut self) -> Option<&mut BasicReverbEffect> {
189 self.as_delay_reverb_mut()
190 }
191
192 #[deprecated(note = "Use as_delay_reverb instead.")]
194 #[allow(deprecated)]
195 pub fn as_basic_reverb(&self) -> Option<&BasicReverbEffect> {
196 self.as_delay_reverb()
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn audio_effect_serde_roundtrip_variants() {
206 let effects = vec![
207 AudioEffect::DelayReverb(DelayReverbEffect::default()),
208 AudioEffect::DiffusionReverb(DiffusionReverbEffect::default()),
209 AudioEffect::ConvolutionReverb(ConvolutionReverbEffect::default()),
210 AudioEffect::LowPassFilter(LowPassFilterEffect::default()),
211 AudioEffect::HighPassFilter(HighPassFilterEffect::default()),
212 AudioEffect::Distortion(DistortionEffect::default()),
213 AudioEffect::Gain(GainEffect::default()),
214 AudioEffect::Compressor(CompressorEffect::default()),
215 AudioEffect::Limiter(LimiterEffect::default()),
216 ];
217
218 let json = serde_json::to_string(&effects).expect("serialize effects");
219 let decoded: Vec<AudioEffect> = serde_json::from_str(&json).expect("deserialize effects");
220 assert_eq!(decoded.len(), effects.len());
221 }
222
223 #[test]
224 fn audio_effect_serde_accepts_aliases() {
225 let json = r#"
226 [
227 {"ConvolutionReverbSettings":{"enabled":true,"wet_dry":0.25}},
228 {"DelayReverbSettings":{"enabled":true,"dry_wet":0.5}},
229 {"BasicReverbSettings":{"enabled":true,"dry_wet":0.5}},
230 {"DiffusionReverbSettings":{"enabled":true,"dry_wet":0.35}},
231 {"LowPassFilterSettings":{"enabled":true,"freq":800,"bandwidth":0.7}},
232 {"HighPassFilterSettings":{"enabled":true,"frequency_hz":1200,"q":0.9}},
233 {"DistortionSettings":{"enabled":true,"gain":2.0,"threshold":0.4}},
234 {"GainSettings":{"enabled":true,"gain":1.25}},
235 {"CompressorSettings":{"enabled":true,"threshold":-12.0,"ratio":2.0,
236 "attack":5.0,"release":50.0,"makeup_db":3.0}},
237 {"LimiterSettings":{"enabled":true,"threshold_db":-3.0,"knee_width":2.0,
238 "attack_ms":3.0,"release_ms":30.0}}
239 ]
240 "#;
241
242 let decoded: Vec<AudioEffect> = serde_json::from_str(json).expect("deserialize effects");
243 assert_eq!(decoded.len(), 10);
244 }
245}