1 /*
2
3 Synthfilter.C - Approximate digital model of an analog JFET phaser.
4 Analog modeling implemented by Ryan Billing aka Transmogrifox.
5 November, 2009
6
7 Credit to:
8 ///////////////////
9 ZynAddSubFX - a software synthesizer
10
11 Phaser.C - Phaser effect
12 Copyright (C) 2002-2005 Nasca Octavian Paul
13 Author: Nasca Octavian Paul
14
15 Modified for rakarrack by Josep Andreu
16
17 DSP analog modeling theory & practice largely influenced by various CCRMA publications, particularly works by Julius O. Smith.
18 ////////////////////
19
20
21 This program is free software; you can redistribute it and/or modify
22 it under the terms of version 2 of the GNU General Public License
23 as published by the Free Software Foundation.
24
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License (version 2) for more details.
29
30 You should have received a copy of the GNU General Public License (version 2)
31 along with this program; if not, write to the Free Software Foundation,
32 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
34 */
35
36 #include <math.h>
37 #include "Synthfilter.h"
38 #include <stdio.h>
39
40 #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0 for filter stability purposes
41 #define ZERO_ 0.00001f // Same idea as above.
42
Synthfilter(float * efxoutl_,float * efxoutr_,double sample_rate)43 Synthfilter::Synthfilter (float * efxoutl_, float * efxoutr_, double sample_rate)
44 {
45 efxoutl = efxoutl_;
46 efxoutr = efxoutr_;
47
48 lyn1 = new float[MAX_SFILTER_STAGES];
49 ryn1 = new float[MAX_SFILTER_STAGES];
50 lx1hp = new float[MAX_SFILTER_STAGES];
51 rx1hp = new float[MAX_SFILTER_STAGES];
52 ly1hp = new float[MAX_SFILTER_STAGES];
53 ry1hp = new float[MAX_SFILTER_STAGES];
54
55 Plpstages = 4;
56 Phpstages = 2;
57
58 delta = 1.0/sample_rate;
59 Rmin = 185.0f; // 2N5457 typical on resistance at Vgs = 0
60 Rmax = 22000.0f; // Resistor
61 C = 0.00000005f; // 50 nF
62 Chp = 0.00000005f;
63 Clp = 0.00000005f;
64 att = delta * 5.0f; //200ms
65 rls = delta * 5.0f; //200ms
66
67 lfo = new EffectLFO(sample_rate);
68
69
70 Ppreset = 0;
71 setpreset (Ppreset);
72 cleanup ();
73 };
74
~Synthfilter()75 Synthfilter::~Synthfilter ()
76 {
77 delete[] lyn1;
78 delete[] ryn1;
79 delete[] lx1hp;
80 delete[] rx1hp;
81 delete[] ly1hp;
82 delete[] ry1hp;
83 delete lfo;
84 };
85
86
87 /*
88 * Effect output
89 */
90 void
out(float * smpsl,float * smpsr,uint32_t period)91 Synthfilter::out (float * smpsl, float * smpsr, uint32_t period)
92 {
93 unsigned int i;
94 int j;
95 float lfol, lfor, lgain, rgain,rmod, lmod, d;
96 inv_period = 1.f/(float)period;
97 lgain = 0.0;
98 rgain = 0.0;
99
100 lfo->effectlfoout (&lfol, &lfor);
101 lmod = lfol*width + depth + env*sns;
102 rmod = lfor*width + depth + env*sns;
103
104 if (lmod > ONE_)
105 lmod = ONE_;
106 else if (lmod < ZERO_)
107 lmod = ZERO_;
108 if (rmod > ONE_)
109 rmod = ONE_;
110 else if (rmod < ZERO_)
111 rmod = ZERO_;
112
113 lmod = 1.0f - lmod;
114 rmod = 1.0f - rmod;
115 lmod*=lmod;
116 rmod*=rmod;
117
118 float xl = (lmod - oldlgain) * inv_period;
119 float xr = (rmod - oldrgain) * inv_period;
120 float gl = oldlgain; // Linear interpolation between LFO samples
121 float gr = oldrgain;
122
123 for (i = 0; i < period; i++) {
124
125 float lxn = bandgain*smpsl[i];
126 float rxn = bandgain*smpsr[i]; //extra gain
127
128 gl += xl;
129 gr += xr; //linear interpolation of LFO
130
131 //Envelope detection
132 envdelta = (fabsf (efxoutl[i]) + fabsf (efxoutr[i])) - env; //envelope follower from Compressor.C
133 if (delta > 0.0)
134 env += att * envdelta;
135 else
136 env += rls * envdelta;
137
138 //End envelope power detection
139
140 if (Plpstages<1) {
141 lxn += fbl;
142 rxn += fbr;
143 }
144
145
146 //Left channel Low Pass Filter
147 for (j = 0; j < Plpstages; j++) {
148 d = 1.0f + fabs(lxn)*distortion; // gain decreases as signal amplitude increases.
149
150 //low pass filter: alpha*x[n] + (1-alpha)*y[n-1]
151 // alpha = lgain = dt/(RC + dt)
152 lgain = delta/( (Rmax * gl * d + Rmin) * Clp + delta);
153 lyn1[j] = lgain * lxn + (1.0f - lgain) * lyn1[j];
154 lyn1[j] += DENORMAL_GUARD;
155 lxn = lyn1[j];
156 if (j==0) lxn += fbl; //Insert feedback after first filter stage
157 };
158
159
160 //Left channel High Pass Filter
161 for (j = 0; j < Phpstages; j++) {
162
163 //high pass filter: alpha*(y[n-1] + x[n] - x[n-1]) // alpha = lgain = RC/(RC + dt)
164 lgain = (Rmax * gl + Rmin) * Chp/( (Rmax * gl + Rmin) * Chp + delta);
165 ly1hp[j] = lgain * (lxn + ly1hp[j] - lx1hp[j]);
166
167 ly1hp[j] += DENORMAL_GUARD;
168 lx1hp[j] = lxn;
169 lxn = ly1hp[j];
170
171 };
172
173
174 //Right channel Low Pass Filter
175 for (j = 0; j < Plpstages; j++) {
176 d = 1.0f + fabs(rxn)*distortion; //This is symmetrical. FET is not, so this deviates slightly, however sym dist. is better sounding than a real FET.
177
178 rgain = delta/((Rmax*gr*d + Rmin)*Clp + delta);
179 ryn1[j] = rgain * rxn + (1.0f - rgain) * ryn1[j];
180 ryn1[j] += DENORMAL_GUARD;
181 rxn = ryn1[j];
182 if (j==0) rxn += fbr; //Insert feedback after first filter stage
183 };
184
185 //Right channel High Pass Filter
186 for (j = 0; j < Phpstages; j++) {
187 d = 1.0f + fabs(rxn)*distortion; // gain decreases as signal amplitude increases.
188
189 //high pass filter: alpha*(y[n-1] + x[n] - x[n-1]) // alpha = rgain = RC/(RC + dt)
190 rgain = (Rmax * gr + Rmin) * Chp/( (Rmax * gr + Rmin) * Chp + delta);
191 ry1hp[j] = rgain * (rxn + ry1hp[j] - rx1hp[j]);
192
193 ry1hp[j] += DENORMAL_GUARD;
194 rx1hp[j] = rxn;
195 rxn = ry1hp[j];
196 };
197
198 fbl = lxn * fb;
199 fbr = rxn * fb;
200
201 efxoutl[i] = lxn;
202 efxoutr[i] = rxn;
203
204 };
205
206 oldlgain = lmod;
207 oldrgain = rmod;
208
209 if (Poutsub != 0)
210 for (i = 0; i < period; i++) {
211 efxoutl[i] *= -1.0f;
212 efxoutr[i] *= -1.0f;
213 };
214
215 };
216
217 /*
218 * Cleanup the effect
219 */
220 void
cleanup()221 Synthfilter::cleanup ()
222 {
223 fbl = 0.0f;
224 fbr = 0.0f;
225 oldlgain = 0.0f;
226 oldrgain = 0.0f;
227 env = 0.0f;
228 envdelta = 0.0f;
229 for (int i = 0; i <MAX_SFILTER_STAGES; i++) {
230 lyn1[i] = 0.0f;
231 ryn1[i] = 0.0f;
232
233 ly1hp[i] = 0.0f;
234 lx1hp[i] = 0.0f;
235 ry1hp[i] = 0.0f;
236 rx1hp[i] = 0.0f;
237 };
238 };
239
240 /*
241 * Parameter control
242 */
243 void
setwidth(int Pwidth)244 Synthfilter::setwidth (int Pwidth)
245 {
246 this->Pwidth = Pwidth;
247 width = ((float)Pwidth / 127.0f);
248 };
249
250
251 void
setfb(int Pfb)252 Synthfilter::setfb (int Pfb)
253 {
254 this->Pfb = Pfb;
255 fb = (float) Pfb;
256 if (fb<0.0f) fb /= 18.0f;
257 else if (fb>0.0f) fb/=65.0f;
258 if(Plpstages<=2) fb *= 0.3; //keep filter stable when phase shift is small
259
260 };
261
262 void
setvolume(int Pvolume)263 Synthfilter::setvolume (int Pvolume)
264 {
265 this->Pvolume = Pvolume;
266 // outvolume is needed in calling program
267 outvolume = (float)Pvolume / 127.0f;
268 };
269
270 void
setdistortion(int Pdistortion)271 Synthfilter::setdistortion (int Pdistortion)
272 {
273 this->Pdistortion = Pdistortion;
274 distortion = (float)Pdistortion / 127.0f;
275 };
276
277
278 void
setdepth(int Pdepth)279 Synthfilter::setdepth (int Pdepth)
280 {
281 this->Pdepth = Pdepth;
282 depth = (float)(Pdepth - 32) / 95.0f; //Pdepth input should be 0-127. .
283 };
284
285
286 void
setpreset(int npreset)287 Synthfilter::setpreset (int npreset)
288 {
289 const int PRESET_SIZE = 16;
290 const int NUM_PRESETS = 7;
291 int pdata[PRESET_SIZE];
292 int presets[NUM_PRESETS][PRESET_SIZE] = {
293 //Low Pass
294 {0, 20, 14, 0, 1, 64, 110, -40, 6, 0, 0, 32, -32, 500, 100, 0},
295 //High Pass
296 {0, 20, 14, 0, 1, 64, 110, -40, 0, 6, 0, 32, -32, 500, 100, 0},
297 //Band Pass
298 {0, 20, 14, 0, 1, 64, 110, -40, 4, 4, 0, 32, -32, 500, 100, 0},
299 //Lead Synth
300 {0, 89, 31, 0, 1, 95, 38, -16, 1, 2, 1, 114, -32, 92, 215, 29},
301 //Water
302 {20, 69, 88, 0, 6, 0, 76, -50, 6, 2, 1, 0, 19, 114, 221, 127},
303 //Pan Filter
304 {0, 20, 100, 0, 5, 127, 127, -64, 2, 0, 0, 57, 0, 340, 288, 110},
305 //Multi
306 {64, 45, 88, 0, 1, 127, 81, 0, 4, 2, 0, 67, 0, 394, 252, 61}
307
308
309 };
310
311 if(npreset>NUM_PRESETS-1) {
312 Fpre->ReadPreset(27,npreset-NUM_PRESETS+1,pdata);
313 for (int n = 0; n < PRESET_SIZE; n++)
314 changepar (n, pdata[n]);
315 } else {
316
317 for (int n = 0; n < PRESET_SIZE; n++)
318 changepar (n, presets[npreset][n]);
319 }
320 Ppreset = npreset;
321 };
322
323
324 void
changepar(int npar,int value)325 Synthfilter::changepar (int npar, int value)
326 {
327 switch (npar) {
328 case 0:
329 setvolume (value);
330 break;
331 case 1:
332 setdistortion (value);
333 break;
334 case 2:
335 lfo->Pfreq = value;
336 lfo->updateparams (PERIOD);
337 break;
338 case 3:
339 lfo->Prandomness = value;
340 lfo->updateparams (PERIOD);
341 break;
342 case 4:
343 lfo->PLFOtype = value;
344 lfo->updateparams (PERIOD);
345 break;
346 case 5:
347 lfo->Pstereo = value;
348 lfo->updateparams (PERIOD);
349 break;
350 case 6:
351 setwidth (value);
352 break;
353 case 7:
354 setfb (value);
355 break;
356 case 8:
357 Plpstages = value;
358 if (Plpstages >= MAX_SFILTER_STAGES)
359 Plpstages = MAX_SFILTER_STAGES ;
360 if(Plpstages<=2) fb = (float) Pfb * 0.25/65.0f; //keep filter stable when phase shift is small
361 cleanup ();
362 break;
363 case 9:
364 Phpstages = value;
365 if (Phpstages >= MAX_SFILTER_STAGES)
366 Phpstages = MAX_SFILTER_STAGES ;
367 cleanup ();
368 break;
369 case 10:
370 if (value > 1)
371 value = 1;
372 Poutsub = value;
373 break;
374 case 11:
375 setdepth (value);
376 break;
377 case 12:
378 Penvelope = value;
379 sns = (float) Penvelope/8.0f;
380 break;
381 case 13:
382 Pattack = value;
383 if(Pattack < 5) Pattack = 5;
384 att = delta * 1000.0f/((float) Pattack);
385 break;
386 case 14:
387 Prelease = value;
388 if(Prelease < 5) Prelease = 5;
389 rls = delta * 1000.0f/((float) Prelease);
390 break;
391 case 15:
392 Pbandwidth = value;
393 Chp = C * (1.0f + ((float) value)/64.0f); // C*3
394 Clp = C * (1.0f - ((float) value)/190.0f); // C/3
395 break;
396 };
397
398 if(Phpstages && Plpstages)
399 bandgain = powf(((float)(Phpstages*Plpstages + 3)), (1.0f - (float) Pbandwidth/127.0f));
400 else bandgain = 1.0f;
401
402 };
403
404 int
getpar(int npar)405 Synthfilter::getpar (int npar)
406 {
407 switch (npar) {
408 case 0:
409 return (Pvolume);
410 break;
411 case 1:
412 return (Pdistortion);
413 break;
414 case 2:
415 return (lfo->Pfreq);
416 break;
417 case 3:
418 return (lfo->Prandomness);
419 break;
420 case 4:
421 return (lfo->PLFOtype);
422 break;
423 case 5:
424 return (lfo->Pstereo);
425 break;
426 case 6:
427 return (Pwidth);
428 break;
429 case 7:
430 return (Pfb);
431 break;
432 case 8:
433 return (Plpstages);
434 break;
435 case 9:
436 return (Phpstages);
437 break;
438 case 10:
439 return (Poutsub);
440 break;
441 case 11:
442 return (Pdepth);
443 break;
444 case 12:
445 return (Penvelope);
446 break;
447 case 13:
448 return (Pattack);
449 break;
450 case 14:
451 return (Prelease);
452 break;
453 case 15:
454 return (Pbandwidth);
455 break;
456
457 default:
458 return (0);
459 };
460
461 };
462