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