diff --git a/src/dsp/helpers.rs b/src/dsp/helpers.rs index 236e548..587ecae 100644 --- a/src/dsp/helpers.rs +++ b/src/dsp/helpers.rs @@ -249,11 +249,54 @@ impl SplitMix64 { } } +/// Linear crossfade. +/// +/// * `v1` - signal 1, range -1.0 to 1.0 +/// * `v2` - signal 2, range -1.0 to 1.0 +/// * `mix` - mix position, range 0.0 to 1.0, mid is at 0.5 #[inline] pub fn crossfade(v1: f32, v2: f32, mix: f32) -> f32 { v1 * (1.0 - mix) + v2 * mix } +/// Constant power crossfade. +/// +/// * `v1` - signal 1, range -1.0 to 1.0 +/// * `v2` - signal 2, range -1.0 to 1.0 +/// * `mix` - mix position, range 0.0 to 1.0, mid is at 0.5 +#[inline] +pub fn crossfade_cpow(v1: f32, v2: f32, mix: f32) -> f32 { + let s1 = (mix * std::f32::consts::FRAC_PI_2).sin(); + let s2 = ((1.0 - mix) * std::f32::consts::FRAC_PI_2).sin(); + v1 * s2 + v2 * s1 +} + +const CROSS_LOG_MIN : f32 = -13.815510557964274; // (0.000001_f32).ln(); +const CROSS_LOG_MAX : f32 = 0.0; // (1.0_f32).ln(); + +/// Logarithmic crossfade. +/// +/// * `v1` - signal 1, range -1.0 to 1.0 +/// * `v2` - signal 2, range -1.0 to 1.0 +/// * `mix` - mix position, range 0.0 to 1.0, mid is at 0.5 +#[inline] +pub fn crossfade_log(v1: f32, v2: f32, mix: f32) -> f32 { + let x = + (mix * (CROSS_LOG_MAX - CROSS_LOG_MIN) + CROSS_LOG_MIN) + .exp(); + crossfade(v1, v2, x) +} + +/// Exponential crossfade. +/// +/// * `v1` - signal 1, range -1.0 to 1.0 +/// * `v2` - signal 2, range -1.0 to 1.0 +/// * `mix` - mix position, range 0.0 to 1.0, mid is at 0.5 +#[inline] +pub fn crossfade_exp(v1: f32, v2: f32, mix: f32) -> f32 { + crossfade(v1, v2, mix * mix) +} + #[inline] pub fn clamp(f: f32, min: f32, max: f32) -> f32 { if f < min { min }