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