use crate::{
context::SAMPLE_RATE,
dsp::{filters::Biquad, filters::BiquadKind},
effects::EffectRenderTrait,
};
use fyrox_core::{reflect::prelude::*, visitor::prelude::*};
macro_rules! define_filter_effect {
($(#[$attr:meta])* $name:ident, $kind:expr) => {
$(#[$attr])*
#[derive(Clone, Reflect, Visit, Debug, PartialEq)]
pub struct $name {
/// Cutoff frequency in Hertz.
#[reflect(setter = "set_cutoff_frequency_hz")]
cutoff_frequency_hz: f32,
#[reflect(setter = "set_gain")]
gain: f32,
#[reflect(setter = "set_quality")]
quality: f32,
#[reflect(hidden)]
left: Biquad,
#[reflect(hidden)]
right: Biquad,
}
impl Default for $name {
fn default() -> Self {
let mut filter = Self {
cutoff_frequency_hz: 2200.0,
gain: 1.0,
quality: 0.5,
left: Default::default(),
right: Default::default(),
};
filter.update();
filter
}
}
impl EffectRenderTrait for $name {
fn render(&mut self, input: &[(f32, f32)], output: &mut [(f32, f32)]) {
for ((input_left, input_right), (output_left, output_right)) in input.iter().zip(output) {
*output_left = self.left.feed(*input_left);
*output_right = self.right.feed(*input_right);
}
}
}
impl $name {
#[inline]
pub fn set_gain(&mut self, gain: f32) {
self.gain = gain;
self.update();
}
#[inline]
pub fn gain(&self) -> f32 {
self.gain
}
#[inline]
pub fn set_cutoff_frequency_hz(&mut self, freq: f32) {
self.cutoff_frequency_hz = freq;
self.update();
}
#[inline]
pub fn cutoff_frequency_hz(&self) -> f32 {
self.cutoff_frequency_hz
}
#[inline]
pub fn set_quality(&mut self, quality: f32) {
self.quality = quality;
self.update();
}
#[inline]
pub fn quality(&self) -> f32 {
self.quality
}
fn update(&mut self) {
self.left.tune(
$kind,
self.cutoff_frequency_hz / SAMPLE_RATE as f32,
self.gain,
self.quality
);
self.right.tune(
$kind,
self.cutoff_frequency_hz / SAMPLE_RATE as f32,
self.gain,
self.quality
)
}
}
};
}
define_filter_effect!(
LowPassFilterEffect,
BiquadKind::LowPass
);
define_filter_effect!(
HighPassFilterEffect,
BiquadKind::HighPass
);
define_filter_effect!(
BandPassFilterEffect,
BiquadKind::BandPass
);
define_filter_effect!(
AllPassFilterEffect,
BiquadKind::AllPass
);
define_filter_effect!(
LowShelfFilterEffect,
BiquadKind::LowShelf
);
define_filter_effect!(
HighShelfFilterEffect,
BiquadKind::HighShelf
);