diff --git a/src/dsp/helpers.rs b/src/dsp/helpers.rs index 54037d3..ce12140 100644 --- a/src/dsp/helpers.rs +++ b/src/dsp/helpers.rs @@ -269,6 +269,31 @@ pub fn crossfade(v1: F, v2: F, mix: F) -> F { v1 * (f::(1.0) - mix) + v2 * mix } +/// Linear crossfade with clipping the `v2` result. +/// +/// This crossfade actually does clip the `v2` signal to the -1.0 to 1.0 +/// range. This is useful for Dry/Wet of plugins that might go beyond the +/// normal signal range. +/// +/// * `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_clip(v1: F, v2: F, mix: F) -> F { + v1 * (f::(1.0) - mix) + (v2 * mix).min(f::(1.0)).max(f::(-1.0)) +} + + +/// Linear (f32) crossfade with driving the `v2` result through a tanh(). +/// +/// * `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_drive_tanh(v1: f32, v2: f32, mix: f32) -> f32 { + v1 * (1.0 - mix) + tanh_approx_drive(v2 * mix * 0.111, 0.95) * 0.9999 +} + /// Constant power crossfade. /// /// * `v1` - signal 1, range -1.0 to 1.0 @@ -479,6 +504,26 @@ pub fn quick_tanh(v: f32) -> f32 { num / den } +// Taken from ValleyAudio +// Copyright Dale Johnson +// https://github.dev/ValleyAudio/ValleyRackFree/tree/v2.0 +// Under GPLv3 license +pub fn tanh_approx_drive(v: f32, drive: f32) -> f32 { + let x = v * drive; + + if x < -1.25 { + -1.0 + } else if x < -0.75 { + 1.0 - (x * (-2.5 - x) - 0.5625) - 1.0 + } else if x > 1.25 { + 1.0 + } else if x > 0.75 { + x * (2.5 - x) - 0.5625 + } else { + x + } +} + /// A helper function for exponential envelopes. /// It's a bit faster than calling the `pow` function of Rust. /// diff --git a/src/dsp/node_cqnt.rs b/src/dsp/node_cqnt.rs index 347e996..4e24cdd 100644 --- a/src/dsp/node_cqnt.rs +++ b/src/dsp/node_cqnt.rs @@ -104,7 +104,7 @@ impl DspNode for CQnt { #[inline] fn process( &mut self, ctx: &mut T, _ectx: &mut NodeExecContext, - nctx: &NodeContext, + _nctx: &NodeContext, atoms: &[SAtom], inputs: &[ProcBuf], outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals) { diff --git a/src/dsp/node_pverb.rs b/src/dsp/node_pverb.rs index 24334b4..56c35ca 100644 --- a/src/dsp/node_pverb.rs +++ b/src/dsp/node_pverb.rs @@ -200,14 +200,24 @@ impl DspNode for PVerb { #[inline] fn process( &mut self, ctx: &mut T, _ectx: &mut NodeExecContext, - _nctx: &NodeContext, + nctx: &NodeContext, _atoms: &[SAtom], inputs: &[ProcBuf], outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals) { use crate::dsp::{inp, out_idx}; - let in_l = inp::PVerb::in_l(inputs); - let in_r = inp::PVerb::in_r(inputs); + let mut in_l = inp::PVerb::in_l(inputs); + let mut in_r = inp::PVerb::in_r(inputs); + + if (nctx.in_connected & 0x03) != 0x03 { + if nctx.in_connected & 0x01 == 0x01 { + println!("ONLY L"); + in_r = in_l; + } else if nctx.in_connected & 0x02 == 0x02 { + println!("ONLY R"); + in_l = in_r; + } + } let mut params = DatParams { frame: 0, @@ -226,8 +236,6 @@ impl DspNode for PVerb { }; let mix = inp::PVerb::mix(inputs); -// let out_l = out::PVerb::sig_l(outputs); -// let out_r = out::PVerb::sig_r(outputs); let out_i = out_idx::PVerb::sig_r(); let (out_l, out_r) = outputs.split_at_mut(out_i); let out_l = &mut out_l[0];