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