1 /*
2   ZynAddSubFX - a software synthesizer
3 
4   Phaser.C - Phaser effect
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 "Phaser.h"
27 #include <stdio.h>
28 #include "FPreset.h"
29 #define PHASER_LFO_SHAPE 2
30 
Phaser(float * efxoutl_,float * efxoutr_,double sample_rate)31 Phaser::Phaser (float * efxoutl_, float * efxoutr_, double sample_rate)
32 {
33     efxoutl = efxoutl_;
34     efxoutr = efxoutr_;
35 
36     oldl = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES * 2);
37     oldr = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES * 2);
38 
39     lfo = new EffectLFO(sample_rate);
40 
41     Ppreset = 0;
42     PERIOD = 256; //best guess until the effect starts running;
43     setpreset (Ppreset);
44     cleanup ();
45 };
46 
~Phaser()47 Phaser::~Phaser ()
48 {
49 	delete lfo;
50 };
51 
52 
53 /*
54  * Effect output
55  */
56 void
out(float * smpsl,float * smpsr,uint32_t period)57 Phaser::out (float * smpsl, float * smpsr, uint32_t period)
58 {
59     unsigned int i;
60     int j;
61     float lfol, lfor, lgain, rgain, tmp;
62 
63     lfo->effectlfoout (&lfol, &lfor);
64     lgain = lfol;
65     rgain = lfor;
66     lgain =
67         (expf (lgain * PHASER_LFO_SHAPE) - 1.0f) / (expf (PHASER_LFO_SHAPE) - 1.0f);
68     rgain =
69         (expf (rgain * PHASER_LFO_SHAPE) - 1.0f) / (expf (PHASER_LFO_SHAPE) - 1.0f);
70 
71 
72     lgain = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * lgain * depth;
73     rgain = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * rgain * depth;
74 
75     if (lgain > 1.0)
76         lgain = 1.0f;
77     else if (lgain < 0.0)
78         lgain = 0.0f;
79     if (rgain > 1.0)
80         rgain = 1.0f;
81     else if (rgain < 0.0)
82         rgain = 0.0f;
83 
84     for (i = 0; i < period; i++) {
85         float x = (float) i / ((float)period);
86         float x1 = 1.0f - x;
87         float gl = lgain * x + oldlgain * x1;
88         float gr = rgain * x + oldrgain * x1;
89         float inl = smpsl[i] * panning + fbl;
90         float inr = smpsr[i] * (1.0f - panning) + fbr;
91 
92         //Left channel
93         for (j = 0; j < Pstages * 2; j++) {
94             //Phasing routine
95             tmp = oldl[j] + DENORMAL_GUARD;
96             oldl[j] = gl * tmp + inl;
97             inl = tmp - gl * oldl[j];
98         };
99         //Right channel
100         for (j = 0; j < Pstages * 2; j++) {
101             //Phasing routine
102             tmp = oldr[j] + DENORMAL_GUARD;
103             oldr[j] = (gr * tmp) + inr;
104             inr = tmp - (gr * oldr[j]);
105         };
106         //Left/Right crossing
107         float l = inl;
108         float r = inr;
109         inl = l * (1.0f - lrcross) + r * lrcross;
110         inr = r * (1.0f - lrcross) + l * lrcross;
111 
112         fbl = inl * fb;
113         fbr = inr * fb;
114         efxoutl[i] = inl;
115         efxoutr[i] = inr;
116 
117     };
118 
119     oldlgain = lgain;
120     oldrgain = rgain;
121 
122     if (Poutsub != 0)
123         for (i = 0; i < period; i++) {
124             efxoutl[i] *= -1.0f;
125             efxoutr[i] *= -1.0f;
126         };
127 
128 };
129 
130 /*
131  * Cleanup the effect
132  */
133 void
cleanup()134 Phaser::cleanup ()
135 {
136     fbl = 0.0;
137     fbr = 0.0;
138     oldlgain = 0.0;
139     oldrgain = 0.0;
140     for (int i = 0; i < Pstages * 2; i++) {
141         oldl[i] = 0.0;
142         oldr[i] = 0.0;
143     };
144 };
145 
146 /*
147  * Parameter control
148  */
149 void
setdepth(int Pdepth)150 Phaser::setdepth (int Pdepth)
151 {
152     this->Pdepth = Pdepth;
153     depth = ((float)Pdepth / 127.0f);
154 };
155 
156 
157 void
setfb(int Pfb)158 Phaser::setfb (int Pfb)
159 {
160     this->Pfb = Pfb;
161     fb = ((float)Pfb - 64.0f) / 64.1f;
162 };
163 
164 void
setvolume(int Pvolume)165 Phaser::setvolume (int Pvolume)
166 {
167     this->Pvolume = Pvolume;
168     outvolume = (float)Pvolume / 127.0f;
169 };
170 
171 void
setpanning(int Ppanning)172 Phaser::setpanning (int Ppanning)
173 {
174     this->Ppanning = Ppanning;
175     panning = ((float)Ppanning + .5f)/ 127.0f;
176 };
177 
178 void
setlrcross(int Plrcross)179 Phaser::setlrcross (int Plrcross)
180 {
181     this->Plrcross = Plrcross;
182     lrcross = (float)Plrcross / 127.0f;
183 };
184 
185 void
setstages(int Pstages)186 Phaser::setstages (int Pstages)
187 {
188     if (Pstages > MAX_PHASER_STAGES)
189         Pstages = MAX_PHASER_STAGES;
190     this->Pstages = Pstages;
191     cleanup ();
192 };
193 
194 void
setphase(int Pphase)195 Phaser::setphase (int Pphase)
196 {
197     this->Pphase = Pphase;
198     phase = ((float)Pphase / 127.0f);
199 };
200 
201 
202 void
setpreset(int npreset)203 Phaser::setpreset (int npreset)
204 {
205     const int PRESET_SIZE = 12;
206     const int NUM_PRESETS = 6;
207     int pdata[PRESET_SIZE];
208     int presets[NUM_PRESETS][PRESET_SIZE] = {
209         //Phaser1
210         {64, 64, 11, 0, 0, 64, 110, 64, 1, 0, 0, 20},
211         //Phaser2
212         {64, 64, 10, 0, 0, 88, 40, 64, 3, 0, 0, 20},
213         //Phaser3
214         {64, 64, 8, 0, 0, 66, 68, 107, 2, 0, 0, 20},
215         //Phaser4
216         {39, 64, 1, 0, 0, 66, 67, 10, 5, 0, 1, 20},
217         //Phaser5
218         {64, 64, 1, 0, 1, 110, 67, 78, 10, 0, 0, 20},
219         //Phaser6
220         {64, 64, 31, 100, 0, 58, 37, 78, 3, 0, 0, 20}
221     };
222 
223     if(npreset>NUM_PRESETS-1) {
224 
225         Fpre->ReadPreset(6,npreset-NUM_PRESETS+1,pdata);
226         for (int n = 0; n < PRESET_SIZE; n++)
227             changepar (n, pdata[n]);
228     } else {
229         for (int n = 0; n < PRESET_SIZE; n++)
230             changepar (n, presets[npreset][n]);
231     }
232     Ppreset = npreset;
233 };
234 
235 
236 void
changepar(int npar,int value)237 Phaser::changepar (int npar, int value)
238 {
239     switch (npar) {
240     case 0:
241         setvolume (value);
242         break;
243     case 1:
244         setpanning (value);
245         break;
246     case 2:
247         lfo->Pfreq = value;
248         lfo->updateparams (PERIOD);
249         break;
250     case 3:
251         lfo->Prandomness = value;
252         lfo->updateparams (PERIOD);
253         break;
254     case 4:
255         lfo->PLFOtype = value;
256         lfo->updateparams (PERIOD);
257         break;
258     case 5:
259         lfo->Pstereo = value;
260         lfo->updateparams (PERIOD);
261         break;
262     case 6:
263         setdepth (value);
264         break;
265     case 7:
266         setfb (value);
267         break;
268     case 8:
269         setstages (value);
270         break;
271     case 9:
272         setlrcross (value);
273         break;
274     case 10:
275         if (value > 1)
276             value = 1;
277         Poutsub = value;
278         break;
279     case 11:
280         setphase (value);
281         break;
282     }
283 };
284 
285 int
getpar(int npar)286 Phaser::getpar (int npar)
287 {
288     switch (npar) {
289     case 0:
290         return (Pvolume);
291         break;
292     case 1:
293         return (Ppanning);
294         break;
295     case 2:
296         return (lfo->Pfreq);	// tempo
297         break;
298     case 3:
299         return (lfo->Prandomness);
300         break;
301     case 4:
302         return (lfo->PLFOtype);
303         break;
304     case 5:
305         return (lfo->Pstereo);	// STDL
306         break;
307     case 6:
308         return (Pdepth);
309         break;
310     case 7:
311         return (Pfb);			// pfb feedback
312         break;
313     case 8:
314         return (Pstages);
315         break;
316     case 9:
317         return (Plrcross);
318         break;
319     case 10:
320         return (Poutsub);
321         break;
322     case 11:
323         return (Pphase);
324         break;
325     default:
326         return (0);
327     }
328 };
329