1/*
2    YC-20 percussion circuit emulation in Faust
3    Copyright(C) 2010 Sampo Savolainen <v2@iki.fi>
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18    RMS code by Yann Orlarey from the Faust project
19*/
20
21reduce(op, n, x) = compute ~ (_,_,_) : (!,!,_)
22    with {
23        compute (acc, count, val) =
24            if(count<n, op(acc,x), x),                 // new acc
25            if(count<n, count+1, 1),             // new count
26            if(count<n, val, acc);              // new val
27        if (c, then, else) = select2(c, else, then);
28    };
29
30
31// the sum of the amplitudes of the input signal
32sumn(n) = reduce(+,n);
33
34// the maximum amplitude of the input signal
35maxn(n) = reduce(max,n);
36
37// the minimum amplitude of the input signal
38minn(n) = reduce(min,n);
39
40// the average amplitude of the input signal
41mean(n) = sumn(n)/n;
42
43// RMS
44RMS(n) = float : square : mean(n) : sqrt
45with {
46	square(x) = x*x;
47};
48
49co2db(coeff) = 20.0*log10(coeff);
50
51percussion_envelope = detect : apply_envelope : apply_realism : *(4.5)
52with {
53	rms_approx(n) = square : (sumit ~ _) : sqrt
54	with {
55		square(x) = x * x;
56		sumit(x,prev) = prev *((n-1.0)/n) + x / n;
57	};
58
59	measured_bleed = 0.01357;
60
61	apply_realism = max( select2(realism_control > (3.0/6.0), 0.0, measured_bleed));
62
63	rms_detect_speed = int(max(22050.0,min(192000.0,float(SR))) * 0.001);
64
65	threshold = -25.0;
66	threshold_hyst = threshold - 10.0;
67
68	detect = +(noise*0.000001) : max(-1.0) : min(1.0) : RMS(rms_detect_speed) : co2db : impulse_detector;
69
70	impulse_detector = (hysteresis_detector ~ _) : impulsify;
71	hysteresis_detector(prev, x) = prev + detect_rise(x) - detect_fall(x) : max(0.0) : min(1.0);
72
73	impulsify(sig) =
74		select2( sig  > 0.5, 0.0,
75		select2( sig' < 0.5, 0.0, 1.0));
76
77	detect_rise(sig) =
78		select2( sig  > threshold, 0.0,
79		select2( sig' < threshold, 0.0, 1.0));
80
81	detect_fall(sig) =
82		select2( sig' > threshold_hyst, 0.0,
83		select2( sig  < threshold_hyst, 0.0, 1.0));
84
85
86	envelope_speed = 0.05;
87	envelope_coeff = envelope_speed : exp(1.0) / (1.5 * float(SR) * _) : (1.0 - _);
88
89	apply_envelope = +(_*(1.0-envelope_coeff)) ~ *(envelope_coeff)
90			: *(1.0/(1.0-envelope_coeff)) : min(1.0)
91			: sum_it;
92
93	sum_it(x) = x + x'' + x''' + x'''' : /(4.0);
94};
95
96