@bendurso
What do you think about this?
import("stdfaust.lib");
declare name "Tap Delay + Freeze mode";
declare version "0.1a";
process = (_, _) : stereo_delay with {
// Global UI group for timing controls
timing_group(x) = hgroup("[0]Timing", x);
bpm = timing_group(hslider("[0]BPM[style:knob]", 120, 40, 200, 1));
subdivision = timing_group(hslider("[1]Note Division[style:knob]", 4, 1, 16, 1));
// Global UI group for mix controls
mix_group(x) = hgroup("[1]Mix", x);
feedback = mix_group(hslider("[0]Feedback[style:knob]", 0.7, 0, 0.95, 0.01));
wet_gain = mix_group(hslider("[1]Wet/Dry[style:knob]", 0.5, 0, 1, 0.01));
// Freeze controls with smoothing
freeze = mix_group(checkbox("[2]Freeze")) : si.smoo;
freezeInputMix = mix_group(hslider("[3]Freeze Input Mix[style:knob]", 0.5, 0, 1, 0.01)) : si.smoo;
// Calculate timing based on BPM
beat_duration = 60.0 / bpm;
maxtime = beat_duration * 4;
delay_time = beat_duration / subdivision;
stereo_delay(l, r) = (dry_l + wet_l, dry_r + wet_r)
with {
// Dry paths
dry_l = l * (1 - wet_gain);
dry_r = r * (1 - wet_gain);
// Wet paths with delay network
wet_l = l * wet_gain : left_delay;
wet_r = r * wet_gain : right_delay;
// Left and right delay networks
left_delay = _ <: tap_process ~ _;
right_delay = _ <: tap_process ~ _;
// Tap process with freeze
tap_process(fb) = de.delay(ma.SR * maxtime, delaylen, processInput)
with {
delaylen = max(1, int(ma.SR * delay_time));
// Process input based on freeze state
processInput(x) = select2(freeze > 0.5,
x + (fb * feedback), // Normal operation
fb + (x * freezeInputMix) // Freeze mode
);
};
};
};