1 /*
2 ZynAddSubFX - a software synthesizer
3
4 DynamicFilter.C - "WahWah" effect and others
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Author: Nasca Octavian Paul
7
8 Modified for rakarrack by Josep Andreu
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of version 2 of the GNU General Public License
12 as published by the Free Software Foundation.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License (version 2) for more details.
18
19 You should have received a copy of the GNU General Public License (version 2)
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24
25 #include <math.h>
26 #include "DynamicFilter.h"
27 #include <stdio.h>
28
DynamicFilter(float * efxoutl_,float * efxoutr_,double sample_rate,uint32_t ibufsz)29 DynamicFilter::DynamicFilter (float * efxoutl_, float * efxoutr_, double sample_rate, uint32_t ibufsz)
30 {
31 efxoutl = efxoutl_;
32 efxoutr = efxoutr_;
33
34 lfo = new EffectLFO(sample_rate);
35
36 Ppreset = 0;
37 filterl = NULL;
38 filterr = NULL;
39 filterpars = new FilterParams (0, 64, 64, sample_rate, ibufsz);
40 PERIOD = 256;//best guess of period size
41 setpreset (Ppreset);
42 cleanup ();
43 };
44
~DynamicFilter()45 DynamicFilter::~DynamicFilter ()
46 {
47 delete lfo;
48 delete filterpars;
49 delete filterl;
50 delete filterr;
51 };
52
53
54 /*
55 * Apply the effect
56 */
57 void
out(float * smpsl,float * smpsr,uint32_t period)58 DynamicFilter::out (float * smpsl, float * smpsr, uint32_t period)
59 {
60 uint32_t i;
61 float lfol, lfor;
62
63 if (filterpars->changed) {
64 filterpars->changed = false;
65 cleanup ();
66 };
67
68 lfo->effectlfoout (&lfol, &lfor);
69 lfol *= depth * 5.0f;
70 lfor *= depth * 5.0f;
71 float freq = filterpars->getfreq ();
72 float q = filterpars->getq ();
73
74 for (i = 0; i < period; i++) {
75 efxoutl[i] = smpsl[i];
76 efxoutr[i] = smpsr[i];
77
78 float x = (fabsf (smpsl[i]) + fabsf (smpsr[i])) * 0.5f;
79 ms1 = ms1 * (1.0f - ampsmooth) + x * ampsmooth + 1e-10f;
80 };
81
82
83 float ampsmooth2 = powf (ampsmooth, 0.2f) * 0.3f;
84 ms2 = ms2 * (1.0f - ampsmooth2) + ms1 * ampsmooth2;
85 ms3 = ms3 * (1.0f - ampsmooth2) + ms2 * ampsmooth2;
86 ms4 = ms4 * (1.0f - ampsmooth2) + ms3 * ampsmooth2;
87 float rms = (sqrtf (ms4)) * ampsns;
88
89 float frl = filterl->getrealfreq (freq + lfol + rms);
90 float frr = filterr->getrealfreq (freq + lfor + rms);
91
92 filterl->setfreq_and_q (frl, q);
93 filterr->setfreq_and_q (frr, q);
94
95
96 filterl->filterout (efxoutl, period);
97 filterr->filterout (efxoutr, period);
98
99 //panning
100 //for (i = 0; i < period; i++) {
101 //efxoutl[i] *= panning;
102 //efxoutr[i] *= (1.0f - panning);
103 //};
104 for (i = 0; i < period; i++) {
105 efxoutl[i] *= (1.0f - panning);
106 efxoutr[i] *= panning;
107 };
108
109 };
110
111 /*
112 * Cleanup the effect
113 */
114 void
cleanup()115 DynamicFilter::cleanup ()
116 {
117 reinitfilter ();
118 ms1 = 0.0;
119 ms2 = 0.0;
120 ms3 = 0.0;
121 ms4 = 0.0;
122 };
123
124
125 /*
126 * Parameter control
127 */
128
129 void
setdepth(int Pdepth)130 DynamicFilter::setdepth (int Pdepth)
131 {
132 this->Pdepth = Pdepth;
133 depth = powf (((float)Pdepth / 127.0f), 2.0f);
134 };
135
136
137 void
setvolume(int Pvolume)138 DynamicFilter::setvolume (int Pvolume)
139 {
140 this->Pvolume = Pvolume;
141 outvolume = (float)Pvolume / 127.0f;
142
143 };
144
145 void
setpanning(int Ppanning)146 DynamicFilter::setpanning (int Ppanning)
147 {
148 this->Ppanning = Ppanning;
149 panning = ((float)Ppanning + .5f) / 127.0f;
150 };
151
152
153 void
setampsns(int Pampsns)154 DynamicFilter::setampsns (int Pampsns)
155 {
156 ampsns = powf ((float)Pampsns / 127.0f, 2.5f) * 10.0f;
157 if (Pampsnsinv != 0)
158 ampsns = -ampsns;
159 ampsmooth = expf ((float)-Pampsmooth / 127.0f * 10.0f) * 0.99f;
160 this->Pampsns = Pampsns;
161 };
162
163 void
reinitfilter()164 DynamicFilter::reinitfilter ()
165 {
166 if (filterl != NULL)
167 delete (filterl);
168 if (filterr != NULL)
169 delete (filterr);
170 filterl = new Filter (filterpars);
171 filterr = new Filter (filterpars);
172 };
173
174 void
setpreset(int npreset)175 DynamicFilter::setpreset (int npreset)
176 {
177 const int PRESET_SIZE = 11;
178 const int NUM_PRESETS = 5;
179 int pdata[PRESET_SIZE];
180 int presets[NUM_PRESETS][PRESET_SIZE] = {
181 //WahWah
182 {64, 64, 80, 0, 0, 64, 70, 90, 0, 60, 0},
183 //AutoWah
184 {64, 64, 70, 0, 0, 80, 70, 0, 0, 60, 1},
185 //Sweep
186 {64, 64, 30, 0, 0, 50, 80, 0, 0, 60, 2},
187 //VocalMorph1
188 {64, 64, 80, 0, 0, 64, 70, 64, 0, 60, 3},
189 //VocalMorph1
190 {64, 64, 50, 0, 0, 96, 64, 0, 0, 60, 4}
191 };
192
193 if(npreset>NUM_PRESETS-1) {
194
195 Fpre->ReadPreset(11,npreset-NUM_PRESETS+1,pdata);
196 for (int n = 0; n < PRESET_SIZE; n++)
197 changepar (n, pdata[n]);
198 } else {
199
200 for (int n = 0; n < PRESET_SIZE; n++)
201 changepar (n, presets[npreset][n]);
202 }
203 // for (int i=0;i<5;i++){
204 // printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q);
205 // };
206
207 Ppreset = npreset;
208
209 };
210
211
212 void
changepar(int npar,int value)213 DynamicFilter::changepar (int npar, int value)
214 {
215 switch (npar) {
216 case 0:
217 setvolume (value);
218 break;
219 case 1:
220 setpanning (value);
221 break;
222 case 2:
223 lfo->Pfreq = value;
224 lfo->updateparams (PERIOD);
225 break;
226 case 3:
227 lfo->Prandomness = value;
228 lfo->updateparams (PERIOD);
229 break;
230 case 4:
231 lfo->PLFOtype = value;
232 lfo->updateparams (PERIOD);
233 break;
234 case 5:
235 lfo->Pstereo = value;
236 lfo->updateparams (PERIOD);
237 break;
238 case 6:
239 setdepth (value);
240 break;
241 case 7:
242 setampsns (value);
243 break;
244 case 8:
245 Pampsnsinv = value;
246 setampsns (Pampsns);
247 break;
248 case 9:
249 Pampsmooth = value;
250 setampsns (Pampsns);
251 break;
252
253 case 10:
254 {
255 Pmode = value;
256 filterpars->defaults ();
257 switch (Pmode) {
258 case 0:
259 filterpars->Pcategory = 0;
260 filterpars->Ptype = 2;
261 filterpars->Pfreq = 45;
262 filterpars->Pq = 64;
263 filterpars->Pstages = 1;
264 filterpars->Pgain = 64;
265 break;
266 case 1:
267 filterpars->Pcategory = 2;
268 filterpars->Ptype = 0;
269 filterpars->Pfreq = 72;
270 filterpars->Pq = 64;
271 filterpars->Pstages = 0;
272 filterpars->Pgain = 64;
273 break;
274 case 2:
275 filterpars->Pcategory = 0;
276 filterpars->Ptype = 4;
277 filterpars->Pfreq = 64;
278 filterpars->Pq = 64;
279 filterpars->Pstages = 2;
280 filterpars->Pgain = 64;
281 break;
282 case 3:
283 filterpars->Pcategory = 1;
284 filterpars->Ptype = 0;
285 filterpars->Pfreq = 50;
286 filterpars->Pq = 70;
287 filterpars->Pstages = 1;
288 filterpars->Pgain = 64;
289
290 filterpars->Psequencesize = 2;
291 // "I"
292 filterpars->Pvowels[0].formants[0].freq = 34;
293 filterpars->Pvowels[0].formants[0].amp = 127;
294 filterpars->Pvowels[0].formants[0].q = 64;
295 filterpars->Pvowels[0].formants[1].freq = 99;
296 filterpars->Pvowels[0].formants[1].amp = 122;
297 filterpars->Pvowels[0].formants[1].q = 64;
298 filterpars->Pvowels[0].formants[2].freq = 108;
299 filterpars->Pvowels[0].formants[2].amp = 112;
300 filterpars->Pvowels[0].formants[2].q = 64;
301 // "A"
302 filterpars->Pvowels[1].formants[0].freq = 61;
303 filterpars->Pvowels[1].formants[0].amp = 127;
304 filterpars->Pvowels[1].formants[0].q = 64;
305 filterpars->Pvowels[1].formants[1].freq = 71;
306 filterpars->Pvowels[1].formants[1].amp = 121;
307 filterpars->Pvowels[1].formants[1].q = 64;
308 filterpars->Pvowels[1].formants[2].freq = 99;
309 filterpars->Pvowels[1].formants[2].amp = 117;
310 filterpars->Pvowels[1].formants[2].q = 64;
311 break;
312 case 4:
313 filterpars->Pcategory = 1;
314 filterpars->Ptype = 0;
315 filterpars->Pfreq = 64;
316 filterpars->Pq = 70;
317 filterpars->Pstages = 1;
318 filterpars->Pgain = 64;
319
320 filterpars->Psequencesize = 2;
321 filterpars->Pnumformants = 2;
322 filterpars->Pvowelclearness = 0;
323
324 filterpars->Pvowels[0].formants[0].freq = 70;
325 filterpars->Pvowels[0].formants[0].amp = 127;
326 filterpars->Pvowels[0].formants[0].q = 64;
327 filterpars->Pvowels[0].formants[1].freq = 80;
328 filterpars->Pvowels[0].formants[1].amp = 122;
329 filterpars->Pvowels[0].formants[1].q = 64;
330
331 filterpars->Pvowels[1].formants[0].freq = 20;
332 filterpars->Pvowels[1].formants[0].amp = 127;
333 filterpars->Pvowels[1].formants[0].q = 64;
334 filterpars->Pvowels[1].formants[1].freq = 100;
335 filterpars->Pvowels[1].formants[1].amp = 121;
336 filterpars->Pvowels[1].formants[1].q = 64;
337 break;
338 };
339 reinitfilter ();
340 }
341 };
342 };
343
344 int
getpar(int npar)345 DynamicFilter::getpar (int npar)
346 {
347 switch (npar) {
348 case 0:
349 return (Pvolume);
350 break;
351 case 1:
352 return (Ppanning);
353 break;
354 case 2:
355 return (lfo->Pfreq);
356 break;
357 case 3:
358 return (lfo->Prandomness);
359 break;
360 case 4:
361 return (lfo->PLFOtype);
362 break;
363 case 5:
364 return (lfo->Pstereo);
365 break;
366 case 6:
367 return (Pdepth);
368 break;
369 case 7:
370 return (Pampsns);
371 break;
372 case 8:
373 return (Pampsnsinv);
374 break;
375 case 9:
376 return (Pampsmooth);
377 break;
378 case 10:
379 return (Pmode);
380 break;
381 default:
382 return (0);
383 };
384
385 };
386