1 /*
2 Phaser.cpp - Phaser effect
3
4 Original ZynAddSubFX author Nasca Octavian Paul
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Copyright 2009-2011, Alan Calvert
7 Copyright 2018-2021, Will Godfrey
8
9 This file is part of yoshimi, which is free software: you can redistribute
10 it and/or modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either version 2 of
12 the License, or (at your option) any later version.
13
14 yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU General Public License (version 2 or
17 later) for more details.
18
19 You should have received a copy of the GNU General Public License along with
20 yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
21 Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
23 This file is a derivative of a ZynAddSubFX original.
24
25 */
26
27 #include "Misc/SynthEngine.h"
28 #include "Effects/Phaser.h"
29 #include "Misc/NumericFuncs.h"
30
31 #include <algorithm>
32
33
34 using func::limit;
35 using func::invSignal;
36
37
38 #define PHASER_LFO_SHAPE 2
39 #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes
40 #define ZERO_ 0.00001f // Same idea as above.
41
42 namespace {
43 const int PRESET_SIZE = 15;
44 const int NUM_PRESETS = 12;
45 unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
46 // Phaser
47 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
48 {64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20, 0, 0, 0 },
49 {64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20, 0, 0, 0 },
50 {64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20, 0, 0, 0 },
51 {39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20, 0, 0, 0 },
52 {64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20, 0, 0, 0 },
53 {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0, 0 },
54 // APhaser
55 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
56 {64, 64, 14, 0, 1, 64, 64, 40, 4, 10, 0, 110,1, 20, 1 },
57 {64, 64, 14, 5, 1, 64, 70, 40, 6, 10, 0, 110,1, 20, 1 },
58 {64, 64, 9, 0, 0, 64, 60, 40, 8, 10, 0, 40, 0, 20, 1 },
59 {64, 64, 14, 10, 0, 64, 45, 80, 7, 10, 1, 110,1, 20, 1 },
60 {25, 64, 127, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0, 20, 1 },
61 {64, 64, 1, 10, 1, 64, 70, 40, 12, 10, 0, 110,1, 20, 1 }
62 };
63 }
64
65
Phaser(bool insertion_,float * efxoutl_,float * efxoutr_,SynthEngine * _synth)66 Phaser::Phaser(bool insertion_, float *efxoutl_, float *efxoutr_, SynthEngine *_synth) :
67 Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, _synth),
68 lfo(_synth),
69 oldl(NULL),
70 oldr(NULL),
71 xn1l(NULL),
72 xn1r(NULL),
73 yn1l(NULL),
74 yn1r(NULL)
75 {
76 analog_setup();
77 setpreset(Ppreset);
78 Pchanged = false;
79 cleanup();
80 }
81
82
analog_setup()83 void Phaser::analog_setup()
84 {
85 //model mismatch between JFET devices
86 offset[0] = -0.2509303f;
87 offset[1] = 0.9408924f;
88 offset[2] = 0.998f;
89 offset[3] = -0.3486182f;
90 offset[4] = -0.2762545f;
91 offset[5] = -0.5215785f;
92 offset[6] = 0.2509303f;
93 offset[7] = -0.9408924f;
94 offset[8] = -0.998f;
95 offset[9] = 0.3486182f;
96 offset[10] = 0.2762545f;
97 offset[11] = 0.5215785f;
98
99 barber = 0; //Deactivate barber pole phasing by default
100
101 mis = 1.0f;
102 Rmin = 625.0f; // 2N5457 typical on resistance at Vgs = 0
103 Rmax = 22000.0f; // Resistor parallel to FET
104 Rmx = Rmin / Rmax;
105 Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
106 C = 0.00000005f; // 50 nF
107 CFs = 2.0f * synth->samplerate_f * C;
108 invperiod = 1.0f / synth->buffersize_f;
109 }
110
111
~Phaser()112 Phaser::~Phaser()
113 {
114 if (oldl != NULL)
115 delete [] oldl;
116 if (oldr != NULL)
117 delete [] oldr;
118
119 if (xn1l)
120 delete[] xn1l;
121 if (yn1l)
122 delete[] yn1l;
123 if (xn1r)
124 delete[] xn1r;
125 if (yn1r)
126 delete[] yn1r;
127 }
128
129
130 // Effect output
out(float * smpsl,float * smpsr)131 void Phaser::out(float *smpsl, float *smpsr)
132 {
133 outvolume.advanceValue(synth->sent_buffersize);
134
135 if (Panalog)
136 AnalogPhase(smpsl, smpsr);
137 else
138 NormalPhase(smpsl, smpsr);
139 }
140
141
AnalogPhase(float * smpsl,float * smpsr)142 void Phaser::AnalogPhase(float *smpsl, float *smpsr)
143 {
144 float lfoVall;
145 float lfoValr;
146 float modl;
147 float modr;
148 float gl;
149 float gr;
150 float hpfl = 0;
151 float hpfr = 0;
152
153 lfo.effectlfoout(&lfoVall, &lfoValr);
154 modl = lfoVall * width + (depth - 0.5f);
155 modr = lfoValr * width + (depth - 0.5f);
156
157 modl = limit(modl, ZERO_, ONE_);
158 modr = limit(modr, ZERO_, ONE_);
159
160 if (Phyper)
161 {
162 // Triangle wave squared is approximately sine on bottom, triangle on top
163 // Result is exponential sweep more akin to filter in synth with
164 // exponential generator circuitry.
165 modl *= modl;
166 modr *= modr;
167 }
168
169 // g.,g. is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
170 modl = sqrtf(1.0f - modl);
171 modr = sqrtf(1.0f - modr);
172
173 diffr = (modr - oldrgain) * invperiod;
174 diffl = (modl - oldlgain) * invperiod;
175
176 gl = oldlgain;
177 gr = oldrgain;
178 oldlgain = modl;
179 oldrgain = modr;
180
181 for (int i = 0; i < synth->sent_buffersize; ++i)
182 {
183 gl += diffl; // Linear interpolation between LFO samples
184 gr += diffr;
185
186 float xnl(smpsl[i] * pangainL.getAndAdvanceValue());
187 float xnr(smpsr[i] * pangainR.getAndAdvanceValue());
188
189 if (barber)
190 {
191 gl = fmodf((gl + 0.25f), ONE_);
192 gr = fmodf((gr + 0.25f), ONE_);
193 }
194
195 xnl = applyPhase(xnl, gl, fbl, hpfl, yn1l, xn1l);
196 xnr = applyPhase(xnr, gr, fbr, hpfr, yn1r, xn1r);
197
198
199 fbl = xnl * fb;
200 fbr = xnr * fb;
201 efxoutl[i] = xnl;
202 efxoutr[i] = xnr;
203 }
204
205 if (Poutsub)
206 {
207 invSignal(efxoutl, synth->sent_buffersize);
208 invSignal(efxoutr, synth->sent_buffersize);
209 }
210 }
211
212
applyPhase(float x,float g,float fb,float & hpf,float * yn1,float * xn1)213 float Phaser::applyPhase(float x, float g, float fb,
214 float &hpf, float *yn1, float *xn1)
215 {
216 for (int j = 0; j < Pstages; ++j)
217 { //Phasing routine
218 mis = 1.0f + offsetpct * offset[j];
219
220 // This is symmetrical.
221 // FET is not, so this deviates slightly, however sym dist. is
222 // better sounding than a real FET.
223 float d = (1.0f + 2.0f * (0.25f + g) * hpf * hpf * distortion) * mis;
224 Rconst = 1.0f + mis * Rmx;
225
226 // This is 1/R. R is being modulated to control filter fc.
227 float b = (Rconst - g) / (d * Rmin);
228 float gain = (CFs - b) / (CFs + b);
229 yn1[j] = (gain * (x + yn1[j]) - xn1[j]) + 1e-12; // anti-denormal
230
231 // high pass filter:
232 // Distortion depends on the high-pass part of the AP stage.
233 hpf = yn1[j] + (1.0f - gain) * xn1[j];
234
235 xn1[j] = x;
236 x = yn1[j];
237 if (j == 1)
238 x += fb; // Insert feedback after first phase stage
239 }
240 return x;
241 }
242
243
NormalPhase(float * smpsl,float * smpsr)244 void Phaser::NormalPhase(float *smpsl, float *smpsr)
245 {
246 float lfol, lfor, lgain, rgain, tmp;
247
248 lfo.effectlfoout(&lfol, &lfor);
249 lgain = lfol;
250 rgain = lfor;
251 lgain = (expf(lgain * PHASER_LFO_SHAPE) - 1)
252 / (expf(PHASER_LFO_SHAPE) - 1.0f);
253 rgain = (expf(rgain * PHASER_LFO_SHAPE) - 1)
254 / (expf(PHASER_LFO_SHAPE) - 1.0f);
255
256 lgain = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * lgain * depth;
257 lgain = limit(lgain,ZERO_,ONE_);//(lgain > 1.0f) ? 1.0f : lgain;
258 rgain = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * rgain * depth;
259 rgain = limit(rgain,ZERO_,ONE_);//(rgain > 1.0f) ? 1.0f : rgain;
260
261 for (int i = 0; i < synth->sent_buffersize; ++i)
262 {
263 float x = (float)i / synth->sent_buffersize_f;
264 float x1 = 1.0f - x;
265 float gl = lgain * x + oldlgain * x1;
266 float gr = rgain * x + oldrgain * x1;
267 float inl = smpsl[i] * pangainL.getAndAdvanceValue() + fbl;
268 float inr = smpsr[i] * pangainR.getAndAdvanceValue() + fbr;
269
270 // Phasing routine
271 for (int j = 0; j < Pstages * 2; ++j)
272 {
273 // Left channel
274 tmp = oldl[j];
275 oldl[j] = gl * tmp + inl;
276 inl = (tmp - gl * oldl[j]) + 1e-12; // anti-denormal
277 // Right channel
278 tmp = oldr[j];
279 oldr[j] = gr * tmp + inr;
280 inr = (tmp - gr * oldr[j]) + 1e-12; // anti-denormal
281 }
282
283 // Left/Right crossing
284 float l = inl;
285 float r = inr;
286 inl = l * (1.0f - lrcross.getValue()) + r * lrcross.getValue();
287 inr = r * (1.0f - lrcross.getValue()) + l * lrcross.getValue();
288 lrcross.advanceValue();
289 fbl = inl * fb;
290 fbr = inr * fb;
291 efxoutl[i] = inl;
292 efxoutr[i] = inr;
293 }
294 oldlgain = lgain;
295 oldrgain = rgain;
296 if (Poutsub)
297 for (int i = 0; i < synth->sent_buffersize; ++i)
298 {
299 efxoutl[i] *= -1.0f;
300 efxoutr[i] *= -1.0f;
301 }
302 }
303
304
305 // Cleanup the effect
cleanup(void)306 void Phaser::cleanup(void)
307 {
308 fbl = fbr = oldlgain = oldrgain = 0.0f;
309 memset(oldl, 0, sizeof(float)*Pstages * 2);
310 memset(oldr, 0, sizeof(float)*Pstages * 2);
311 memset(xn1l, 0, sizeof(float)*Pstages);
312 memset(xn1r, 0, sizeof(float)*Pstages);
313 memset(yn1l, 0, sizeof(float)*Pstages);
314 memset(yn1r, 0, sizeof(float)*Pstages);
315 lfo.resetState();
316 }
317
318
319 // Parameter control
setdepth(unsigned char Pdepth_)320 void Phaser::setdepth(unsigned char Pdepth_)
321 {
322 Pdepth = Pdepth_;
323 depth = Pdepth / 127.0f;
324 }
325
326
setwidth(unsigned char Pwidth_)327 void Phaser::setwidth(unsigned char Pwidth_)
328 {
329 Pwidth = Pwidth_;
330 width = Pwidth / 127.0f;
331 }
332
333
setfb(unsigned char Pfb_)334 void Phaser::setfb(unsigned char Pfb_)
335 {
336 Pfb = Pfb_;
337 fb = (Pfb - 64.0f) / 64.1f;
338 }
339
340
setvolume(unsigned char Pvolume_)341 void Phaser::setvolume(unsigned char Pvolume_)
342 {
343 Pvolume = Pvolume_;
344 float tmp = Pvolume / 127.0f;
345 outvolume.setTargetValue(tmp);
346 volume.setTargetValue((!insertion) ? 1.0f : tmp);
347 }
348
349
setdistortion(unsigned char Pdistortion_)350 void Phaser::setdistortion(unsigned char Pdistortion_)
351 {
352 Pdistortion = Pdistortion_;
353 distortion = (float)Pdistortion / 127.0f;
354 }
355
356
setoffset(unsigned char Poffset_)357 void Phaser::setoffset(unsigned char Poffset_)
358 {
359 Poffset = Poffset_;
360 offsetpct = (float)Poffset / 127.0f;
361 }
362
363
setstages(unsigned char Pstages_)364 void Phaser::setstages(unsigned char Pstages_)
365 {
366 if (oldl != NULL)
367 delete [] oldl;
368 if (xn1l)
369 delete[] xn1l;
370 if (yn1l)
371 delete[] yn1l;
372 if (oldr != NULL)
373 delete [] oldr;
374 if (xn1r)
375 delete[] xn1r;
376 if (yn1r)
377 delete[] yn1r;
378
379 Pstages = Pstages_;
380 oldl = new float[Pstages * 2];
381 oldr = new float[Pstages * 2];
382 xn1l = new float[Pstages];
383 xn1r = new float[Pstages];
384 yn1l = new float[Pstages];
385 yn1r = new float[Pstages];
386 cleanup();
387 }
388
389
setphase(unsigned char Pphase_)390 void Phaser::setphase(unsigned char Pphase_)
391 {
392 Pphase = Pphase_;
393 phase = Pphase / 127.0;
394 }
395
396
setpreset(unsigned char npreset)397 void Phaser::setpreset(unsigned char npreset)
398 {
399 if (npreset < 0xf)
400 {
401 if (npreset >= NUM_PRESETS)
402 npreset = NUM_PRESETS - 1;
403 for (int n = 0; n < PRESET_SIZE; ++n)
404 changepar(n, presets[npreset][n]);
405 // All presets use no BPM syncing.
406 changepar(EFFECT::control::bpm, 0);
407 Ppreset = npreset;
408 }
409 else
410 {
411 unsigned char preset = npreset & 0xf;
412 unsigned char param = npreset >> 4;
413 if (param == 0xf)
414 param = 0;
415 changepar(param, presets[preset][param]);
416 }
417 Pchanged = false;
418 }
419
420
changepar(int npar,unsigned char value)421 void Phaser::changepar(int npar, unsigned char value)
422 {
423 if (npar == -1)
424 {
425 Pchanged = (value != 0);
426 return;
427 }
428 switch (npar)
429 {
430 case 0:
431 setvolume(value);
432 break;
433
434 case 1:
435 setpanning(value);
436 break;
437
438 case 2:
439 lfo.Pfreq = value;
440 lfo.updateparams();
441 break;
442
443 case 3:
444 lfo.Prandomness = value;
445 lfo.updateparams();
446 break;
447
448 case 4:
449 lfo.PLFOtype = value;
450 lfo.updateparams();
451 barber = (2 == value);
452 break;
453
454 case 5:
455 lfo.Pstereo = value;
456 lfo.updateparams();
457 break;
458
459 case 6:
460 setdepth(value);
461 break;
462
463 case 7:
464 setfb(value);
465 break;
466
467 case 8:
468 setstages(value);
469 break;
470
471 case 9:
472 setlrcross(value);
473 setoffset(value);
474 break;
475
476 case 10:
477 Poutsub = (value > 1) ? 1 : value;
478 break;
479
480 case 11:
481 setphase(value);
482 setwidth(value);
483 break;
484
485 case 12:
486 Phyper = std::min(int(value), 1);
487 break;
488
489 case 13:
490 setdistortion(value);
491 break;
492
493 case 14:
494 Panalog = value;
495 break;
496
497 case EFFECT::control::bpm:
498 lfo.Pbpm = value;
499 break;
500
501 case EFFECT::control::bpmStart:
502 lfo.PbpmStart = value;
503 break;
504 }
505 Pchanged = true;
506 }
507
508
getpar(int npar)509 unsigned char Phaser::getpar(int npar)
510 {
511 switch (npar)
512 {
513 case -1: return Pchanged;
514 case 0: return Pvolume;
515 case 1: return Ppanning;
516 case 2: return lfo.Pfreq;
517 case 3: return lfo.Prandomness;
518 case 4: return lfo.PLFOtype;
519 case 5: return lfo.Pstereo;
520 case 6: return Pdepth;
521 case 7: return Pfb;
522 case 8: return Pstages;
523 case 9: return Plrcross;
524 return Poffset; // same
525 case 10: return Poutsub;
526 case 11: return Pphase;
527 return Pwidth; // same
528 case 12: return Phyper;
529 case 13: return Pdistortion;
530 case 14: return Panalog;
531 case EFFECT::control::bpm: return lfo.Pbpm;
532 case EFFECT::control::bpmStart: return lfo.PbpmStart;
533 default: break;
534 }
535 return 0;
536 }
537
538
getlimits(CommandBlock * getData)539 float Phaserlimit::getlimits(CommandBlock *getData)
540 {
541 int value = getData->data.value;
542 int control = getData->data.control;
543 int request = getData->data.type & TOPLEVEL::type::Default; // clear flags
544 int presetNum = getData->data.engine;
545 int min = 0;
546 int max = 127;
547
548 int def = presets[presetNum][control];
549 unsigned char canLearn = TOPLEVEL::type::Learnable;
550 unsigned char isInteger = TOPLEVEL::type::Integer;
551 switch (control)
552 {
553 case 0:
554 break;
555 case 1:
556 break;
557 case 2:
558 break;
559 case 3:
560 break;
561 case 4:
562 max = 1;
563 canLearn = 0;
564 break;
565 case 5:
566 break;
567 case 6:
568 break;
569 case 7:
570 break;
571 case 8:
572 min = 1;
573 max = 12;
574 canLearn = 0;
575 break;
576 case 9:
577 break;
578 case 10:
579 canLearn = 0;
580 max = 1;
581 break;
582 case 11:
583 break;
584 case 12:
585 canLearn = 0;
586 max = 1;
587 break;
588 case 13:
589 break;
590 case 14:
591 max = 1;
592 canLearn = 0;
593 break;
594 case EFFECT::control::bpm:
595 max = 1;
596 canLearn = 0;
597 break;
598 case EFFECT::control::bpmStart:
599 break;
600 case EFFECT::control::preset:
601 max = 11;
602 canLearn = 0;
603 break;
604 default:
605 getData->data.type |= TOPLEVEL::type::Error;
606 return 1.0f;
607 break;
608 }
609
610 switch (request)
611 {
612 case TOPLEVEL::type::Adjust:
613 if (value < min)
614 value = min;
615 else if (value > max)
616 value = max;
617 break;
618 case TOPLEVEL::type::Minimum:
619 value = min;
620 break;
621 case TOPLEVEL::type::Maximum:
622 value = max;
623 break;
624 case TOPLEVEL::type::Default:
625 value = def;
626 break;
627 }
628 getData->data.type |= (canLearn + isInteger);
629 return float(value);
630 }
631
632