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