1 /*
2     Copyright (C) 2009 Fons Adriaensen <fons@kokkinizita.net>
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 
20 #include "autowah.h"
21 
22 #include <cmath>
23 
24 
setport(PortIndex port,PortData * data)25 void Ladspa_Autowah::setport (PortIndex port, PortData *data)
26 {
27 	_port [port] = (float*)data;
28 }
29 
30 
31 #define G_RES 4.0f
32 #define F_MIN 300.0f
33 #define F_RAT 10
34 #define B_MIN 0.03f
35 #define B_RAT 4
36 #define T_MIN 0.05f
37 #define T_LOG 2
38 
39 
active(bool act)40 void Ladspa_Autowah::active (bool act)
41 {
42     if (! act) return;
43 
44     _wbase = F_MIN * 6.28f / _fsam;
45     _bbase = B_MIN;
46     _rfact = 64.0f / (_fsam * T_MIN);
47     _z1 = _z2 = 0;
48     _s1 = _s2 = 0;
49     _gx = _gy = 0;
50     _dr = 0;
51 }
52 
53 
runproc(SampleCount len,bool add)54 void Ladspa_Autowah::runproc (SampleCount len, bool add)
55 {
56     int   i, k;
57     float *inp = _port [A_INP];
58     float *out = _port [A_OUT];
59     float z1, z2, s1, s2, gx, gy;
60     float ds1, ds2, dgx, dgy;
61     float gd, rf, md, fr, dr;
62     float b, p, t, w, x, y;
63 
64     gx = _gx;
65     gy = _gy;
66     t = _port [C_OPMIX][0];
67     _gy = G_RES * t;
68     _gx = _gy + 1 - t;
69     dgx = (_gx - gx) / len;
70     dgy = (_gy - gy) / len;
71 
72     gd = 10 * powf (10.0f, 0.05f * _port [C_DRIVE][0]);
73     rf = 1.0f - _rfact / powf (10.0f, T_LOG * _port [C_DECAY][0]);
74     md = _port [C_RANGE][0];
75     fr = _port [C_FREQ][0];
76 
77     z1 = _z1;
78     z2 = _z2;
79     s1 = _s1;
80     s2 = _s2;
81     dr = _dr;
82 
83     while (len)
84     {
85 	k = (len > 80) ? 64 : len;
86 
87 	p = 0;
88 	for (i = 0; i < k; i++)
89 	{
90 	    x = inp [i];
91 	    p += x * x;
92 	}
93 	p = gd * sqrtf (p / k);
94 
95 	if (p > dr) dr += 0.1f *(p - dr);
96 	if (dr > md) dr = md;
97 	t = dr + fr;
98 	dr = dr * rf + 1e-10f;
99 	w = _wbase  * (1 + (F_RAT - 1) * t * t);
100 	b = w * _bbase * (1 + (B_RAT - 1) * t);
101         if (w > 0.7f) w = 0.7f;
102 
103 	_s1 = -cosf (w);
104 	_s2 = (1 - b) / (1 + b);
105 	ds1 = (_s1 - s1) / k;
106 	ds2 = (_s2 - s2) / k;
107 
108 	for (i = 0; i < k; i++)
109 	{
110 	    s1 += ds1;
111 	    s2 += ds2;
112             gx += dgx;
113             gy += dgy;
114             x = inp [i];
115             y = x - s2 * z2;
116             out [i] = gx * x - gy * (z2 + s2 * y);
117             y -= s1 * z1;
118             z2 = z1 + s1 * y;
119             z1 = y + 1e-10f;
120 	}
121 	inp += k;
122 	out += k;
123 	len -= k;
124     }
125 
126     _z1 = z1;
127     _z2 = z2;
128     _dr = dr;
129 }
130 
131