meadow-dsp-essentials 0.1.4

Liberally-licensed essential audio DSP library used in the Meadowlark DAW project
Documentation
#[cfg(not(feature = "std"))]
use num_traits::Float;

use core::f32::consts::{FRAC_PI_2, FRAC_PI_4};

use super::FadeCurve;

impl FadeCurve {
    /// Compute the raw gain values for both inputs.
    ///
    /// * `fade` - The fade amount, where `0.5` is center, `0.0` is fully the
    /// first input, and `1.0` is fully the second input.
    pub fn compute_gains_0_to_1_f32(&self, fade: f32) -> (f32, f32) {
        match self {
            Self::EqualPower3dB => fades_equal_power_3db_0_to_1(fade),
            Self::EqualPower6dB => fades_equal_power_6db_0_to_1(fade),
            Self::SquareRoot => fades_square_root_0_to_1(fade),
            Self::Linear => fades_linear_0_to_1(fade),
        }
    }

    /// Compute the raw gain values for both inputs.
    ///
    /// * `fade` - The fade amount, where `0.0` is center, `-1.0` is fully the
    /// first input, and `1.0` is fully the second input.
    pub fn compute_gains_neg1_to_1_f32(&self, fade: f32) -> (f32, f32) {
        match self {
            Self::EqualPower3dB => fades_equal_power_3db_neg1_to_1(fade),
            Self::EqualPower6dB => fades_equal_power_6db_neg1_to_1(fade),
            Self::SquareRoot => fades_square_root_neg1_to_1(fade),
            Self::Linear => fades_linear_neg1_to_1(fade),
        }
    }
}

/// Compute the raw gains for blending two signals using an "equal power 3dB"
/// curve. This fade curve is generally the best for most use cases.
///
/// (More specifically this a circular curve with each signal at -3dB at
/// center.)
///
/// Note, if the two signals are highly correlated (such as a wet/dry mix),
/// then [`fades_linear_0_to_1`] may provide better results.
///
/// * `fade` - The fade amount, where `0.5` is center, `0.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[0.0, 1.0]`.
#[inline]
pub fn fades_equal_power_3db_0_to_1(fade: f32) -> (f32, f32) {
    let fade = FRAC_PI_2 * fade;
    let fade_cos = fade.cos();
    let fade_sin = fade.sin();

    (fade_cos, fade_sin)
}

/// Compute the raw gains for blending two signals using an "equal power 6dB"
/// curve.
///
/// (More specifically this a circular curve with each signal at -6dB at
/// center.)
///
/// This may provide better results than [`fades_equal_power_3db_0_to_1`] in
/// some cases.
///
/// * `fade` - The fade amount, where `0.5` is center, `0.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[0.0, 1.0]`.
#[inline]
pub fn fades_equal_power_6db_0_to_1(fade: f32) -> (f32, f32) {
    let fade = FRAC_PI_2 * fade;
    let fade_cos = fade.cos();
    let fade_sin = fade.sin();

    (fade_cos * fade_cos, fade_sin * fade_sin)
}

/// Compute the raw gains for blending two signals using a quadratic curve.
///
/// This is cheaper to compute than [`fades_equal_power_3db_0_to_1`], but
/// is less accurate in its perception of constant volume.
///
/// Note, if the two signals are highly correlated (such as a wet/dry mix),
/// then [`fades_linear_0_to_1`] may provide better results.
///
/// * `fade` - The fade amount, where `0.5` is center, `0.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[0.0, 1.0]`.
#[inline]
pub fn fades_square_root_0_to_1(fade: f32) -> (f32, f32) {
    ((1.0 - fade).sqrt(), fade.sqrt())
}

/// Compute the raw gains for blending two signals using a linear curve.
///
/// This works best on signals that are highly correlated (like a wet/dry
/// mix). If the signals are not highly correlated, consider using a
/// different fade curve like [`fades_equal_power_3db_0_to_1`].
///
/// * `fade` - The fade amount, where `0.5` is center, `0.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[0.0, 1.0]`.
#[inline]
pub fn fades_linear_0_to_1(fade: f32) -> (f32, f32) {
    ((1.0 - fade), fade)
}

/// Compute the raw gains for blending two signals using an "equal power 3dB"
/// curve. This fade curve is generally the best for most use cases.
///
/// (More specifically this a circular curve with each signal at -3dB at
/// center.)
///
/// Note, if the two signals are highly correlated (such as a wet/dry mix),
/// then [`fades_linear_0_to_1`] may provide better results.
///
/// * `fade` - The fade amount, where `0.0` is center, `-1.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[-1.0, 1.0]`.
#[inline]
pub fn fades_equal_power_3db_neg1_to_1(fade: f32) -> (f32, f32) {
    let fade = FRAC_PI_4 * (fade + 1.0);
    let fade_cos = fade.cos();
    let fade_sin = fade.sin();

    (fade_cos, fade_sin)
}

/// Compute the raw gains for blending two signals using an "equal power 6dB"
/// curve.
///
/// (More specifically this a circular curve with each signal at -6dB at
/// center.)
///
/// This may provide better results than [`fades_equal_power_3db_0_to_1`] in
/// some cases.
///
/// * `fade` - The fade amount, where `0.0` is center, `-1.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[-1.0, 1.0]`.
#[inline]
pub fn fades_equal_power_6db_neg1_to_1(fade: f32) -> (f32, f32) {
    let fade = FRAC_PI_4 * (fade + 1.0);
    let fade_cos = fade.cos();
    let fade_sin = fade.sin();

    (fade_cos * fade_cos, fade_sin * fade_sin)
}

/// Compute the raw gains for blending two signals using a quadratic curve.
///
/// This is cheaper to compute than [`fades_equal_power_3db_0_to_1`], but
/// is less accurate in its perception of constant volume.
///
/// Note, if the two signals are highly correlated (such as a wet/dry mix),
/// then [`fades_linear_0_to_1`] may provide better results.
///
/// * `fade` - The fade amount, where `0.0` is center, `-1.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[-1.0, 1.0]`.
#[inline]
pub fn fades_square_root_neg1_to_1(fade: f32) -> (f32, f32) {
    let fade = (fade + 1.0) * 0.5;
    ((1.0 - fade).sqrt(), fade.sqrt())
}

/// Compute the raw gains for blending two signals using a linear curve.
///
/// This works best on signals that are highly correlated (like a wet/dry
/// mix). If the signals are not highly correlated, consider using a
/// different fade curve like [`fades_equal_power_3db_0_to_1`].
///
/// * `fade` - The fade amount, where `0.0` is center, `-1.0` is fully the
/// first signal, and `1.0` is fully the second signal.
///
/// Note, the outputs are *NOT* clamped to `[-1.0, 1.0]`.
#[inline]
pub fn fades_linear_neg1_to_1(fade: f32) -> (f32, f32) {
    let fade = (fade + 1.0) * 0.5;
    ((1.0 - fade), fade)
}