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