104 lines
3.8 KiB
Text
104 lines
3.8 KiB
Text
|
|
// eoc-delay.dsp — Stereo delay effect for the EOC rack.
|
||
|
|
//
|
||
|
|
// Parameters (7):
|
||
|
|
// time [250ms, 1-2000ms] delay time (ms) when sync=0
|
||
|
|
// feedback [0.3, 0-0.95] feedback amount
|
||
|
|
// lp_cutoff [8000, 500-20000] LP filter cutoff on feedback path (Hz)
|
||
|
|
// ping_pong [0.0, 0-1] 0=normal stereo, 1=full ping-pong L<->R
|
||
|
|
// spread [0.5, 0-1] stereo width of delay tails
|
||
|
|
// sync [0] nentry: 0=free, 1=half, 2=quarter, 3=eighth (120bpm)
|
||
|
|
// mix [0.3, 0-1] dry/wet mix
|
||
|
|
|
||
|
|
import("stdfaust.lib");
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// UI
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
time = hslider("time[unit:ms]", 250, 1, 2000, 0.1);
|
||
|
|
feedback = hslider("feedback", 0.3, 0, 0.95, 0.001);
|
||
|
|
lp_cutoff = hslider("lp_cutoff[unit:Hz]", 8000, 500, 20000, 1);
|
||
|
|
ping_pong = hslider("ping_pong", 0.0, 0, 1, 0.001);
|
||
|
|
spread = hslider("spread", 0.5, 0, 1, 0.001);
|
||
|
|
sync = nentry("sync", 0, 0, 3, 1);
|
||
|
|
mix = hslider("mix", 0.3, 0, 1, 0.001);
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Derived delay time: free or tempo-synced at 120bpm
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bpm = 120.0;
|
||
|
|
beat_ms = 60000.0 / bpm;
|
||
|
|
|
||
|
|
sync_time_ms =
|
||
|
|
ba.if(sync < 0.5, time,
|
||
|
|
ba.if(sync < 1.5, beat_ms * 2.0,
|
||
|
|
ba.if(sync < 2.5, beat_ms,
|
||
|
|
beat_ms * 0.5)));
|
||
|
|
|
||
|
|
// Fixed max delay: 96000 samples (1s at 96kHz, covers all tempos for eighth notes at 30bpm+)
|
||
|
|
max_delay_samp = 96000;
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Stereo ping-pong delay.
|
||
|
|
// Uses f ~ (_, _) pattern for stereo feedback loop.
|
||
|
|
// de.delay used for variable delay (no LP on feedback path inside the loop —
|
||
|
|
// LP is applied to the whole wet signal for efficiency).
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
dSamp = int(sync_time_ms * float(ma.SR) / 1000.0);
|
||
|
|
|
||
|
|
delayCore(inL, inR, fbL, fbR) = wetL, wetR
|
||
|
|
with {
|
||
|
|
pp = ping_pong;
|
||
|
|
fb = feedback;
|
||
|
|
mixL = inL + (fbL * (1.0 - pp) + fbR * pp) * fb;
|
||
|
|
mixR = inR + (fbR * (1.0 - pp) + fbL * pp) * fb;
|
||
|
|
wetL = de.delay(max_delay_samp, dSamp, mixL);
|
||
|
|
wetR = de.delay(max_delay_samp, dSamp, mixR);
|
||
|
|
};
|
||
|
|
|
||
|
|
stereoDelay = (_, _) : delayCore ~ (_, _);
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Post-delay LP filter (tone shaping on the feedback tail)
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
delayLP(x) = fi.lowpass(1, lp_cutoff, x);
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Mid-side stereo spread
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
msSpread(inL, inR) = outL, outR
|
||
|
|
with {
|
||
|
|
w = spread;
|
||
|
|
mid = (inL + inR) * 0.5;
|
||
|
|
side = (inL - inR) * 0.5;
|
||
|
|
outL = mid + side * w * 2.0;
|
||
|
|
outR = mid - side * w * 2.0;
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Main process: dry/wet mix
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
// Delay + LP + spread on two signals
|
||
|
|
delayAndProcess(inL, inR) = wideL, wideR
|
||
|
|
with {
|
||
|
|
wetL0 = stereoDelay(inL, inR) : _,!;
|
||
|
|
wetR0 = stereoDelay(inL, inR) : !,_;
|
||
|
|
wetL1 = delayLP(wetL0);
|
||
|
|
wetR1 = delayLP(wetR0);
|
||
|
|
wideL = msSpread(wetL1, wetR1) : _,!;
|
||
|
|
wideR = msSpread(wetL1, wetR1) : !,_;
|
||
|
|
};
|
||
|
|
|
||
|
|
process(inL, inR) = outL, outR
|
||
|
|
with {
|
||
|
|
wideL = delayAndProcess(inL, inR) : _,!;
|
||
|
|
wideR = delayAndProcess(inL, inR) : !,_;
|
||
|
|
outL = inL * (1.0 - mix) + wideL * mix;
|
||
|
|
outR = inR * (1.0 - mix) + wideR * mix;
|
||
|
|
};
|