This is my reverb in FAUST, what do you think?
-
Ideas:
- Adjust gain curve to be more "exponential" for natural decay
- Add smoothing to crossover frequencies to prevent zipper noise
- Increase filter orders for steeper cutoffs
- Use fractional delays for smoother modulation (?)
import("stdfaust.lib"); // Early Reflections earlyReflections = par(i, 4, de.delay(ma.SR, delayTime(i)) * gain(i)) with { delayTime(i) = ba.take(i+1, (13, 17, 19, 23)) * 1.5; gain(i) = ba.take(i+1, (0.7, 0.6, 0.5, 0.4)); }; FDN = si.bus(2) : (preDelay, preDelay) <: (earlyReflections, earlyReflections, MIMO_Network ~ MATRIX) :> par(i, 2, (+:applyFilters)) with { // User-controllable parameters decayMs = hslider("Decay[unit:ms][style:knob]", 1000, 100, 10000, 1); preDelayMs = hslider("Pre-Delay[unit:ms][style:knob]", 20, 0, 200, 1); modDepth = hslider("Modulation Depth[unit:%][style:knob]", 0.5, 0, 2, 0.01) : *(0.01); modRate = hslider("Modulation Rate[unit:Hz][style:knob]", 0.5, 0.1, 2, 0.1); // // High crossover scales with decay time - longer reverbs need lower high crossover highCrossover = min(12000, max(2000, 8000 - (decayMs - 1000) * 0.4)); // Low crossover is related to high crossover but stays within reasonable bounds lowCrossover = min(500, max(100, highCrossover * 0.06)); // Decay ratios adapt based on decay time // Longer reverbs typically have more low-end build-up, so we reduce low decay ratio lowDecayRatio = max(0.4, min(1.2, 1.0 - (decayMs - 1000) * 0.0001)); // High frequencies decay faster in longer reverbs highDecayRatio = max(0.3, min(1.0, 0.8 - (decayMs - 1000) * 0.0002)); // Pre-delay maxPreDelay = 200; preDelay = de.sdelay(ma.SR * maxPreDelay / 1000, 512, preDelayMs * ma.SR / 1000); // Calculate decay factor based on milliseconds and frequency band calcDecayFactor(delayLengthSamples, decayMs, ratio) = pow(0.001, delayLengthSamples / (decayMs * ratio * ma.SR / 1000.0)); // Matrix MATRIX = ro.hadamard(16) : par(i, 16, *(1/4)); // Network MIMO_Network(fb1, fb2, fb3, fb4, fb5, fb6, fb7, fb8, fb9, fb10, fb11, fb12, fb13, fb14, fb15, fb16, in1, in2) = par(i, 16, DEL(i)) with { baseDelays = (3797, 3541, 3323, 3109, 2939, 2801, 2693, 2593, 2503, 2423, 2351, 2287, 2237, 2179, 2131, 2083); DEL(i) = de.fdelay(5000, modulatedDelay(i), fb(i) + input(i)) : multiband_decay with { delay = baseDelays : ba.selectn(16, i); modulatedDelay(i) = delay + os.osc(modRate + 0.01*i) * delay * modDepth; fb(i) = ba.selectn(16, i, fb1, fb2, fb3, fb4, fb5, fb6, fb7, fb8, fb9, fb10, fb11, fb12, fb13, fb14, fb15, fb16); input(i) = select2(i < 2, 0, ba.selectn(2, i, in1, in2)); // Multi-band decay using automatic parameters multiband_decay = _ <: ( fi.lowpass(2, lowCrossover) * calcDecayFactor(delay, decayMs, lowDecayRatio), fi.bandpass(2, lowCrossover, highCrossover) * calcDecayFactor(delay, decayMs, 1.0), fi.highpass(2, highCrossover) * calcDecayFactor(delay, decayMs, highDecayRatio) ) :> _; }; }; // Apply filters to each channel (oh! I see colours, that's so trippy :P) applyFilters = fi.lowpass(1, highCrossover * 1.5) : fi.highpass(1, lowCrossover * 0.5); }; process = FDN;
-
@Mighty23 if you use filterbank, you can be passing an argument to the function and decide on the number of bands that way.
https://faustlibraries.grame.fr/libs/filters/#fifilterbank
Also, your reverb will behave differently on different sampling rates because you're hardcoding the delay times in samples.
Modulation is also super expensive, and even if it's off, you're still running the calculations. You can bypass that using the hidden enable primitive (with ondemand coming soon)
modulatedDelay(i) = delay + enable(os.osc(modRate + 0.01*i) * delay * modDepth, modDepth>0);
-
@aaronventure Thanks for all these tips. I think I'll keep the post updated.