Refactoring in faustexp.ml.
[Faustine.git] / interpretor / faust-0.9.47mr3 / tools / faust2pd / examples / synth / amp.dsp
1
2 /* Stereo amplifier stage with bass, treble, gain and balance controls and a
3 dB meter. */
4
5 declare name "amp -- stereo amplifier stage";
6 declare author "Albert Graef";
7 declare version "1.0";
8
9 import("math.lib");
10 import("music.lib");
11
12 /* Fixed bass and treble frequencies. You might want to tune these for your
13 setup. */
14
15 bass_freq = 300;
16 treble_freq = 1200;
17
18 /* Bass and treble gain controls in dB. The range of +/-20 corresponds to a
19 boost/cut factor of 10. */
20
21 bass_gain = nentry("bass", 0, -20, 20, 0.1);
22 treble_gain = nentry("treble", 0, -20, 20, 0.1);
23
24 /* Gain and balance controls. */
25
26 gain = db2linear(nentry("gain", 0, -96, 96, 0.1));
27 bal = hslider("balance", 0, -1, 1, 0.001);
28
29 /* Balance a stereo signal by attenuating the left channel if balance is on
30 the right and vice versa. I found that a linear control works best here. */
31
32 balance = *(1-max(0,bal)), *(1-max(0,0-bal));
33
34 /* Generic biquad filter. */
35
36 filter(b0,b1,b2,a0,a1,a2) = f : (+ ~ g)
37 with {
38 f(x) = (b0/a0)*x+(b1/a0)*x'+(b2/a0)*x'';
39 g(y) = 0-(a1/a0)*y-(a2/a0)*y';
40 };
41
42 /* Low and high shelf filters, straight from Robert Bristow-Johnson's "Audio
43 EQ Cookbook", see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt. f0
44 is the shelf midpoint frequency, g the desired gain in dB. S is the shelf
45 slope parameter, we always set that to 1 here. */
46
47 low_shelf(f0,g) = filter(b0,b1,b2,a0,a1,a2)
48 with {
49 S = 1;
50 A = pow(10,g/40);
51 w0 = 2*PI*f0/SR;
52 alpha = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 );
53
54 b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
55 b1 = 2*A*( (A-1) - (A+1)*cos(w0) );
56 b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
57 a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha;
58 a1 = -2*( (A-1) + (A+1)*cos(w0) );
59 a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha;
60 };
61
62 high_shelf(f0,g) = filter(b0,b1,b2,a0,a1,a2)
63 with {
64 S = 1;
65 A = pow(10,g/40);
66 w0 = 2*PI*f0/SR;
67 alpha = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 );
68
69 b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
70 b1 = -2*A*( (A-1) + (A+1)*cos(w0) );
71 b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
72 a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
73 a1 = 2*( (A-1) - (A+1)*cos(w0) );
74 a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
75 };
76
77 /* The tone control. We simply run a low and a high shelf in series here. */
78
79 tone = low_shelf(bass_freq,bass_gain)
80 : high_shelf(treble_freq,treble_gain);
81
82 /* Envelop follower. This is basically a 1 pole LP with configurable attack/
83 release time. The result is converted to dB. You have to set the desired
84 attack/release time in seconds using the t parameter below. */
85
86 t = 0.1; // attack/release time in seconds
87 g = exp(-1/(SR*t)); // corresponding gain factor
88
89 env = abs : *(1-g) : + ~ *(g) : linear2db;
90
91 /* Use this if you want the RMS instead. Note that this doesn't really
92 calculate an RMS value (you'd need an FIR for that), but in practice our
93 simple 1 pole IIR filter works just as well. */
94
95 rms = sqr : *(1-g) : + ~ *(g) : sqrt : linear2db;
96 sqr(x) = x*x;
97
98 /* The dB meters for left and right channel. These are passive controls. */
99
100 left_meter(x) = attach(x, env(x) : hbargraph("left", -96, 10));
101 right_meter(x) = attach(x, env(x) : hbargraph("right", -96, 10));
102
103 /* The main program. */
104
105 process = hgroup("0-amp", hgroup("1-tone", tone, tone) :
106 hgroup("2-gain", (_*gain, _*gain)))
107 : vgroup("3-balance", balance)
108 : vgroup("4-meter", (left_meter, right_meter));