desc:Multimode RC filter
//tags: filter
//author: Tale

// Copyright (C) 2015-2022 Theo Niessink
// License: LGPL - http://www.gnu.org/licenses/lgpl.html

// This effect filters the input signal using a single 1st-order RC filter
// stage for 6 dB low/high/all-pass, and two filter stages for 12 dB or
// notch/band-pass.

// You can select the cutoff/center frequency using both the linear
// frequency slider (for typing exact values), and the logarithmic scale
// slider (for automation).

slider1:0<0,4,1{Low-Pass,High-Pass,All-Pass,Notch,Band-Pass}>Mode
slider2:1000<20,24000,1>Freq (Hz)
slider3:100<0,100,1>Scale (%)
slider4:2.0<0.0,6.0,0.01>Bandwidth (oct)
slider5:0<0,1,1{6 dB,12 dB}>Slope (dB/oct)
slider6:-120.0<-120.0,24.0,0.1>Dry (dB)
slider7:0.0<-120.0,24.0,0.1>Wet (dB)

import rc_filter.jsfx-inc

@init

function scale(x) ( 1/1200 + 1199/1200 * (exp(6*x) - 1) * /* 1/(exp(6) - 1) */ 0.0024849116568445855 );
function gain(x) ( x <= -120 ? 0 : exp(/* log(10)/20 */ 0.11512925464970228 * x) );

smooth.rc_set(0.0033);
function smooth() ( smooth.lp = this.smooth; this.smooth = smooth.rc_lp(this); );

dry.smooth = 0;
wet.smooth = 1;

min_fc = 1/60;

@slider

mode = min(max(0, slider1|0), 4);

slope0 = slider5 < 0.5;
slope1 = 1.0 - slope0;

fc1 = max(slider2 * scale(slider3 * 0.01), min_fc);

// Low/High/All-Pass
mode < 3 ? (
  rc0.a = rc1.a =
  rc2.a = rc3.rc_setf_precise(fc0 = fc1);
) :

// Notch/Band-Pass
/* mode >= 3 ? */ (
  bw = 2^(0.5 * slider4);
  rc0.a = rc1.rc_setf_precise(fc0 = max(fc1 / bw, min_fc));
  rc2.a = rc3.rc_setf_precise(fc1 = max(fc1 * bw, min_fc));
);

dry = gain(slider6);
wet = gain(slider7);

@sample

// Low-Pass
mode == 0 ? (
  left = rc0.rc_lp(spl0);
  right = rc1.rc_lp(spl1);

  left = slope0 * left + slope1 * rc2.rc_lp(left);
  right = slope0 * right + slope1 * rc3.rc_lp(right);
) :

// High-Pass
mode == 1 ? (
  left = rc0.rc_hp_precise(spl0);
  right = rc1.rc_hp_precise(spl1);

  left = slope0 * left + slope1 * rc2.rc_hp_precise(left);
  right = slope0 * right + slope1 * rc3.rc_hp_precise(right);
) :

// All-Pass
mode == 2 ? (
  left = rc0.rc_ap(spl0);
  right = rc1.rc_ap(spl1);

  left = slope0 * left + slope1 * rc2.rc_ap(left);
  right = slope0 * right + slope1 * rc3.rc_ap(right);
) :

// Notch
mode == 3 ? (
  left = rc0.rc_lp(spl0);
  right = rc1.rc_lp(spl1);

  left += rc2.rc_hp_precise(spl0);
  right += rc3.rc_hp_precise(spl1);
) :

// Band-Pass
/* mode == 4 ? */ (
  left = rc0.rc_hp_precise(spl0);
  right = rc1.rc_hp_precise(spl1);

  left = rc2.rc_lp(left);
  right = rc3.rc_lp(right);
);

spl0 = dry.smooth() * spl0 + wet.smooth() * left;
spl1 = dry.smooth * spl1 + wet.smooth * right;
