diff --git a/crates/steam_audio/src/iir.rs b/crates/steam_audio/src/iir.rs index 5ea38ec..6dc663f 100644 --- a/crates/steam_audio/src/iir.rs +++ b/crates/steam_audio/src/iir.rs @@ -1,10 +1,14 @@ use crate::delay::Delay; use biquad::*; +/// Represents a biquad IIR filter, that can be used to carry out various filtering operations on RealSignals. Such a +/// filter is essentially a recurrence relation: sample N of the filtered output signal depends on samples N, N-1, and +/// N-2 of the input, as well as samples N-1 and N-2 of the _output_. #[derive(Copy, Clone, Debug)] pub struct IIR(DirectForm1); impl IIR { + /// Creates a low-shelf filter (controls the amplitude of all frequencies below the cutoff). pub fn new_low_shelf(high_cutoff: f32, gain: f32, sample_rate: i32) -> Self { // Port note: The IIR crate used assumes gain is in dB. // This does create some extra work that will hopefully be optimized away... @@ -20,6 +24,7 @@ impl IIR { IIR(DirectForm1::::new(coefficients.unwrap())) } + /// Creates a high-shelf filter (controls the amplitude of all frequencies above the cutoff). pub fn new_high_shelf(low_cutoff: f32, gain: f32, sample_rate: i32) -> Self { // Port note: The IIR crate used assumes gain is in dB. // This does create some extra work that will hopefully be optimized away... @@ -35,6 +40,7 @@ impl IIR { IIR(DirectForm1::::new(coefficients.unwrap())) } + /// Creates a peaking filter (controls the amplitude of all frequencies between the cutoffs). pub fn new_peaking(low_cutoff: f32, high_cutoff: f32, gain: f32, sample_rate: i32) -> Self { // Port note: The IIR crate used assumes gain is in dB. // This does create some extra work that will hopefully be optimized away... @@ -57,14 +63,20 @@ impl IIR { /// when the filter doesn't change between frames. If the filter _does_ change, the caller must implement /// crossfading or some other approach to ensure smoothness. pub struct IIRFilterer { - filter: IIR, // The IIR filter to apply. - xm1: f32, // Input value from 1 sample ago. - xm2: f32, // Input value from 2 samples ago. - ym1: f32, // Output value from 1 sample ago. - ym2: f32, // Output value from 2 samples ago. + /// The IIR filter to apply. + filter: IIR, + /// Input value from 1 sample ago. + xm1: f32, + /// Input value from 2 samples ago. + xm2: f32, + /// Output value from 1 sample ago. + ym1: f32, + /// Output value from 2 samples ago. + ym2: f32, } impl IIRFilterer { + // todo: With Phonon you can change the filterer at runtime. Let's see if we can get away with not doing that pub fn new(filter: IIR) -> Self { Self { filter, @@ -75,6 +87,7 @@ impl IIRFilterer { } } + /// Applies the filter to an entire buffer of input, using SIMD operations. pub fn apply(&self, size: usize, input: &[f32], output: &mut [f32]) { //self.filter }