1declare name "Compressor"; 2declare category "Guitar Effects"; 3 4/* Compressor unit. */ 5 6//declare name "compressor -- compressor/limiter unit"; 7declare author "Albert Graef"; 8declare version "1.0"; 9 10import("stdfaust.lib"); 11import("guitarix.lib"); 12rd = library("reducemaps.lib"); 13 14/* Controls. */ 15 16// partition the controls into these three groups 17comp_group(x) = hgroup("1-compression", x); 18env_group(x) = vgroup("2-envelop", x); 19gain_group(x) = vgroup("3-gain", x); 20 21// compressor controls: ratio, threshold and knee size 22ratio = nentry("ratio[name:Ratio]", 2, 1, 20, 0.1); 23threshold = nentry("threshold[name:Threshold]", -20, -96, 10, 0.1); 24knee = nentry("knee[name:Knee]", 3, 0, 20, 0.1); 25 26// attack and release controls; clamped to a minimum of 1 sample 27attack = hslider("attack[name:Attack]", 0.002, 0, 1, 0.001) : max(1/ma.SR); 28release = hslider("release[name:Release]", 0.5, 0, 10, 0.01) : max(1/ma.SR); 29 30// gain controls: make-up gain, compression gain meter 31makeup_gain = gain_group(hslider("makeup gain[name:Makeup]", 0, -96, 96, 0.1)); 32gain(x) = attach(x, x : gain_group(hbargraph("gain", -96, 0))); 33 34t = 0.1; 35g = exp(-1/(ma.SR*t)); 36env = abs : *(1-g) : + ~ *(g); 37rms = sqr : *(1-g) : + ~ *(g) : sqrt; 38sqr(x) = x*x; 39 40/* Compute the envelop of a stereo signal. Replace env with rms ba.if you want to 41 use the RMS value instead. */ 42 43//env2(x,y) = max(env(x),env(y)); 44env2(x) = max(env(x)); 45 46/* Compute the compression factor for the current input level. The gain is 47 always 0 dB ba.if we're below the reduced threshold, threshold-knee. Beyond 48 the real threshold value the level is scaled by 1/ratio. Between these two 49 extremes we return a convex combination of those factors. This is also 50 known as "soft-knee" compression: the compression kicks in gradually at 51 threshold-knee and reaches its full value at threshold. For special 52 effects, you can also achieve old-school "hard-knee" compression by setting 53 the knee value to fi.zero. Also note that, before computing the gain, the 54 input level is first smoothed out using a 1 fi.pole IIR to prevent clicks when 55 the input level changes abruptly. The attack and release times of this 56 filter are configured with the corresponding envelop controls of the 57 compressor. */ 58 59compress(env) = level*(1-r)/r 60with { 61 // the (filtered) input level above the threshold 62 level = env : h ~ _ : ba.linear2db : (_-threshold+knee) : max(0) 63 with { 64 h(x,y) = f*x+(1-f)*y with { f = (x<y)*ga+(x>=y)*gr; }; 65 ga = exp(-1/(ma.SR*attack)); 66 gr = exp(-1/(ma.SR*release)); 67 }; 68 // the knee factor, clamped to 0..1; we add a small perturbation in 69 // the denominator to prevent infinities and nan when knee<<1 70 p = level/(knee+eps) : max(0) : min(1) with { eps = 0.001; }; 71 // the actual compression ratio 72 r = 1-p+p*ratio; 73}; 74 75vmeter1(x) = attach(x, envelop(x) : vbargraph("v1[nomidi][log]", 0, 40)); 76 77envelop = abs : max ~ (1.0/ma.SR) : rd.maxn(2048); // : max(ba.db2linear(-70)) : ba.linear2db; 78 79process(x) = g(x)*x 80with { 81 //g = env2(x) : compress : gain : +(makeup_gain) : ba.db2linear ; 82 g = add_dc : env : compress : vmeter1 : ba.db2linear ; 83}; 84