Random Osc in Faust, what I'm doing wrong?
-
I found a well-working example of a transient shaper in faust in the forum that I tried to modify. My goal is to add a "humanize" function whose job is to modulate the values of the transient shaper. It seems to me that the modulation is too subtle and yet I don't think I have given too low values.
Does anyone know what's wrong with my test?
FaustIDE:
https://tinyurl.com/243y8n22Code:
import("stdfaust.lib"); WINDOW = 30 / 1000; low_cutoff = hslider("v:Whetstone Transient Shaper/[2]Low Cutoff[unit:Hz]",10,10,20000,10); high_cutoff = hslider("v:Whetstone Transient Shaper/[3]High Cutoff[unit:Hz]", 20000,20,20000,10); do_monitor = button("v:Whetstone Transient Shaper/h:[4]Monitoring/[0]Monitor selected band") : ba.toggle : vbargraph("v:Whetstone Transient Shaper/h:[4]Monitoring/[1]ON[style:led]", 0, 1); attack = hslider("v:Whetstone Transient Shaper/[0]Attack[unit:dB]",0,-12,+12,0.1) : ba.db2linear : si.smoo; sustain = hslider("v:Whetstone Transient Shaper/[1]Sustain[unit:dB]",0,-12,+12,0.1) : ba.db2linear : si.smoo; humanize = checkbox("v:Whetstone Transient Shaper/[5]Humanize"); // Random LFO for humanization lfo_rate = hslider("v:Whetstone Transient Shaper/[6]LFO Rate[unit:Hz]", 0.9, 0.1, 1, 0.1); random_lfo = os.osc(lfo_rate) * 0.5 + 0.5 : * (0.9); // 90% modulation depth // Visualization of LFO lfo_display = random_lfo : vbargraph("v:Whetstone Transient Shaper/h:[7]Visualization/[0]LFO", 0, 0.3); // Modulated attack and sustain modulated_attack = attack * (1 + random_lfo * humanize); modulated_sustain = sustain * (1 + random_lfo * humanize); // Visualization of modulated attack and sustain attack_display = modulated_attack : vbargraph("v:Whetstone Transient Shaper/h:[7]Visualization/[1]Modulated Attack", 0, 2); sustain_display = modulated_sustain : vbargraph("v:Whetstone Transient Shaper/h:[7]Visualization/[2]Modulated Sustain", 0, 2); process = sp.stereoize(split_shape_merge); split_shape_merge = _ <: ( split_active_and_passive : ( // Process active part (_ <: _ * get_gain(_ : change), ba.bypass1(do_monitor != 1, *(0)) :> _), // Pass through passive part _ ) :> _ ), (lfo_display, attack_display, sustain_display) : (_, !,!,!); //split signal into two parts $active, $passive //$active is resonant low- and high-passed between low_cutoff and high_cutoff respectively. This is fed directly to output if monitoring is on //$passive is resonant high- and low-passed between low_cutoff and high_cutoff respectively split_active_and_passive = (fi.resonhp(low_cutoff, 1, 1) : fi.resonlp(high_cutoff, 1, 1)), (fi.resonlp(low_cutoff, 1, 1) + fi.resonhp(high_cutoff, 1, 1)); //$active is analyzed with RMS over N ms divided by a lag filter applied to the RMS to get a rise speed over time to get $change change = ba.slidingRMS(ba.sec2samp(WINDOW)) <: _ - si.lag_ud(WINDOW, WINDOW); //If $change is positive, $gain is modulated_attack //If $change is negative, $gain is modulated_sustain //Smooth $gain get_gain(x) = ba.if(x > 0, ba.if(humanize, modulated_attack, attack), ba.if(humanize, modulated_sustain, sustain)) : si.lag_ud(WINDOW,WINDOW);