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