commit bde41871500a8fa21208e7dd45b9a1e8bd122350
parent 354d630f80b785ce4b412f1af8d431c18804cec2
Author: fundamental <[email protected]>
Date: Sat, 29 May 2010 14:34:15 -0400
Removing APhaser
Diffstat:
9 files changed, 241 insertions(+), 750 deletions(-)
diff --git a/src/Effects/APhaser.cpp b/src/Effects/APhaser.cpp
@@ -1,384 +0,0 @@
-/*
-
- APhaser.cpp - Approximate digital model of an analog JFET phaser.
- Analog modeling implemented by Ryan Billing aka Transmogrifox.
- ZynAddSubFX - a software synthesizer
-
- Phaser.cpp - Phaser effect
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Copyright (C) 2009-2010 Ryan Billing
- Copyright (C) 2010-2010 Mark McCurry
- Author: Nasca Octavian Paul
- Ryan Billing
- Mark McCurry
-
- DSP analog modeling theory & practice largely influenced by various CCRMA publications, particularly works by Julius O. Smith.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include <cmath>
-#include <algorithm>
-#include "APhaser.h"
-
-using namespace std;
-
-#define PHASER_LFO_SHAPE 2
-#define ONE_ 0.99999f // To prevent LFO ever reaching 1.0 for filter stability purposes
-#define ZERO_ 0.00001f // Same idea as above.
-
-Analog_Phaser::Analog_Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
- :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), xn1(NULL), yn1(NULL), diff(0.0), oldgain(0.0),
- fb(0.0)
-{
- //model mismatch between JFET devices
- offset[0] = -0.2509303f;
- offset[1] = 0.9408924f;
- offset[2] = 0.998f;
- offset[3] = -0.3486182f;
- offset[4] = -0.2762545f;
- offset[5] = -0.5215785f;
- offset[6] = 0.2509303f;
- offset[7] = -0.9408924f;
- offset[8] = -0.998f;
- offset[9] = 0.3486182f;
- offset[10] = 0.2762545f;
- offset[11] = 0.5215785f;
-
- barber = 0; //Deactivate barber pole phasing by default
-
- mis = 1.0f;
- Rmin = 625.0f;// 2N5457 typical on resistance at Vgs = 0
- Rmax = 22000.0f;// Resistor parallel to FET
- Rmx = Rmin/Rmax;
- Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
- C = 0.00000005f; // 50 nF
- CFs = (float) 2.0f*(float)SAMPLE_RATE*C;
- invperiod = 1.0f / ((float) SOUND_BUFFER_SIZE);
-
- setpreset(Ppreset);
- cleanup();
-}
-
-Analog_Phaser::~Analog_Phaser()
-{
- if(xn1.l)
- delete[] xn1.l;
- if(yn1.l)
- delete[] yn1.l;
- if(xn1.r)
- delete[] xn1.r;
- if(yn1.r)
- delete[] yn1.r;
-}
-
-/*
- * Effect output
- */
-void Analog_Phaser::out(const Stereo<REALTYPE *> &input)
-{
- Stereo<REALTYPE> gain(0.0), lfoVal(0.0), mod(0.0), g(0.0), b(0.0), hpf(0.0);
-
- lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
- mod.l = lfoVal.l*width + depth;
- mod.r = lfoVal.r*width + depth;
-
- mod.l = limit(mod.l, ZERO_, ONE_);
- mod.r = limit(mod.r, ZERO_, ONE_);
-
- if(Phyper) {
- //Triangle wave squared is approximately sin on bottom, tri on top
- //Result is exponential sweep more akin to filter in synth with
- //exponential generator circuitry.
- mod.l *= mod.l;
- mod.r *= mod.r;
- }
-
- //g.l,g.r is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
- mod.l = sqrtf(1.0f - mod.l);
- mod.r = sqrtf(1.0f - mod.r);
-
- diff.r = (mod.r - oldgain.r) * invperiod;
- diff.l = (mod.l - oldgain.l) * invperiod;
-
- g = oldgain;
- oldgain = mod;
-
- for (int i = 0; i < SOUND_BUFFER_SIZE; i++) {
- g.l += diff.l;// Linear interpolation between LFO samples
- g.r += diff.r;
-
- Stereo<REALTYPE> xn(input.l[i] * panning,
- input.r[i] * (1.0f - panning));
-
- if (barber) {
- g.l = fmodf((g.l + 0.25f), ONE_);
- g.r = fmodf((g.r + 0.25f), ONE_);
- }
-
- xn.l = applyPhase(xn.l, g.l, fb.l, hpf.l, yn1.l, xn1.l);
- xn.r = applyPhase(xn.r, g.r, fb.r, hpf.r, yn1.r, xn1.r);
-
-
- fb.l = xn.l * feedback;
- fb.r = xn.r * feedback;
- efxoutl[i] = xn.l;
- efxoutr[i] = xn.r;
- }
-
- if(Poutsub) {
- invSignal(efxoutl, SOUND_BUFFER_SIZE);
- invSignal(efxoutr, SOUND_BUFFER_SIZE);
- }
-}
-
-REALTYPE Analog_Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb,
- REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1)
-{
- for(int j = 0; j < Pstages; j++) { //Phasing routine
- mis = 1.0f + offsetpct*offset[j];
-
- //This is symmetrical.
- //FET is not, so this deviates slightly, however sym dist. is
- //better sounding than a real FET.
- float d = (1.0f + 2.0f*(0.25f + g)*hpf*hpf*distortion) * mis;
- Rconst = 1.0f + mis*Rmx;
-
- // This is 1/R. R is being modulated to control filter fc.
- float b = (Rconst - g)/ (d*Rmin);
- float gain = (CFs - b)/(CFs + b);
- yn1[j] = gain * (x + yn1[j]) - xn1[j];
-
- //high pass filter:
- //Distortion depends on the high-pass part of the AP stage.
- hpf = yn1[j] + (1.0f-gain)*xn1[j];
-
- xn1[j] = x;
- x = yn1[j];
- if (j==1)
- x += fb; //Insert feedback after first phase stage
- }
- return x;
-}
-
-/*
- * Cleanup the effect
- */
-void Analog_Phaser::cleanup()
-{
- fb = oldgain = Stereo<REALTYPE>(0.0);
- for(int i = 0; i < Pstages; i++) {
- xn1.l[i] = 0.0;
- yn1.l[i] = 0.0;
- xn1.r[i] = 0.0;
- yn1.r[i] = 0.0;
- }
-}
-
-/*
- * Parameter control
- */
-void Analog_Phaser::setwidth(unsigned char Pwidth)
-{
- this->Pwidth = Pwidth;
- width = ((float)Pwidth / 127.0f);
-}
-
-void Analog_Phaser::setpanning(unsigned char Ppanning)
-{
- this->Ppanning = Ppanning;
- panning = (float)Ppanning / 127.0;
-}
-
-
-void Analog_Phaser::setfb(unsigned char Pfb)
-{
- this->Pfb = Pfb;
- feedback = (float) (Pfb - 64) / 64.2f;
-}
-
-void Analog_Phaser::setvolume(unsigned char Pvolume)
-{
- this->Pvolume = Pvolume;
- outvolume = Pvolume / 127.0;
- if(insertion == 0)
- volume = 1.0;
- else
- volume = outvolume;
-}
-
-void Analog_Phaser::setdistortion(unsigned char Pdistortion)
-{
- this->Pdistortion = Pdistortion;
- distortion = (float)Pdistortion / 127.0f;
-}
-
-void Analog_Phaser::setoffset(unsigned char Poffset)
-{
- this->Poffset = Poffset;
- offsetpct = (float)Poffset / 127.0f;
-}
-
-void Analog_Phaser::setstages(unsigned char Pstages)
-{
- if(xn1.l)
- delete[] xn1.l;
- if(yn1.l)
- delete[] yn1.l;
- if(xn1.r)
- delete[] xn1.r;
- if(yn1.r)
- delete[] yn1.r;
-
-
- this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages);
-
- xn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
- new REALTYPE[Pstages]);
-
- yn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
- new REALTYPE[Pstages]);
-
- cleanup();
-}
-
-void Analog_Phaser::setdepth(unsigned char Pdepth)
-{
- //depth shall range 0-0.5 since we don't need to shift the full spectrum.
- this->Pdepth = Pdepth;
- depth = (float)(Pdepth - 64) / 127.0f;
-}
-
-
-void Analog_Phaser::setpreset(unsigned char npreset)
-{
- const int PRESET_SIZE = 15;
- const int NUM_PRESETS = 12;
- unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
- //Phaser
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- {64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20, 0, 0, 0},
- {64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20, 0, 0, 0},
- {64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20, 0, 0, 0},
- {39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20, 0, 0, 0},
- {64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20, 0, 0, 0},
- {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0, 0}
- //APhaser
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- {64, 64, 14, 0, 1, 64, 64, 40, 4, 10, 0, 110, 1, 20, 1},
- {64, 64, 14, 5, 1, 64, 70, 40, 6, 10, 0, 110, 1, 20, 1},
- {64, 64, 9, 0, 0, 64, 60, 40, 8, 10, 0, 40, 0, 20, 1},
- {64, 64, 14, 10, 0, 64, 45, 80, 7, 10, 1, 110, 1, 20, 1},
- {25, 64, 127, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0, 20, 1},
- {64, 64, 1, 10, 1, 64, 70, 40, 12, 10, 0, 110, 1, 20, 1}
- };
- if(npreset >= NUM_PRESETS)
- npreset = NUM_PRESETS - 1;
- for(int n = 0; n < PRESET_SIZE; n++)
- changepar(n, presets[npreset][n]);
- Ppreset = npreset;
-}
-
-
-void Analog_Phaser::changepar(int npar, unsigned char value)
-{
- switch(npar) {
- case 0:
- setvolume(value);
- break;
- case 1:
- setpanning(value);
- break;
- case 2:
- lfo.Pfreq = value;
- lfo.updateparams();
- break;
- case 3:
- lfo.Prandomness = value;
- lfo.updateparams();
- break;
- case 4:
- lfo.PLFOtype = value;
- lfo.updateparams();
- barber = (2 == value);
- break;
- case 5:
- lfo.Pstereo = value;
- lfo.updateparams();
- break;
- case 6:
- setdepth(value);
- break;
- case 7:
- setfb(value);
- break;
- case 8:
- setstages(value);
- break;
- case 9:
- setoffset(value);
- break;
- case 10:
- Poutsub = min((int)value,1);
- break;
- case 11:
- setwidth(value);
- break;
- case 12:
- Phyper = min((int)value, 1);
- break;
- case 13:
- setdistortion(value);
- break;
- }
-}
-
-unsigned char Analog_Phaser::getpar(int npar) const
-{
- switch(npar) {
- case 0:
- return Pvolume;
- case 1:
- return Ppanning;
- case 2:
- return lfo.Pfreq;
- case 3:
- return lfo.Prandomness;
- case 4:
- return lfo.PLFOtype;
- case 5:
- return lfo.Pstereo;
- case 6:
- return Pdepth;
- case 7:
- return Pfb;
- case 8:
- return Pstages;
- case 9:
- return Poffset;
- case 10:
- return Poutsub;
- case 11:
- return Pwidth;
- case 12:
- return Phyper;
- case 13:
- return Pdistortion;
- case 14:
- return 1;
- default:
- return 0;
- }
-}
diff --git a/src/Effects/APhaser.h b/src/Effects/APhaser.h
@@ -1,92 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- Phaser.h - Phaser effect
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Copyright (C) 2009-2010 Ryan Billing
- Copyright (C) 2010-2010 Mark McCurry
- Author: Nasca Octavian Paul
- Ryan Billing
- Mark McCurry
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef APHASER_H
-#define APHASER_H
-#include "../globals.h"
-#include "Effect.h"
-#include "EffectLFO.h"
-
-#define MAX_PHASER_STAGES 12
-
-class Analog_Phaser:public Effect
-{
- public:
- Analog_Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
- ~Analog_Phaser();
- void out(const Stereo<REALTYPE *> &input);
- void setpreset(unsigned char npreset);
- void changepar(int npar, unsigned char value);
- unsigned char getpar(int npar) const;
- void cleanup();
-
- private:
- //Phaser parameters
- EffectLFO lfo; //Phaser modulator
- unsigned char Pvolume; //Used to set wet/dry mix
- unsigned char Ppanning; //Sets the pan of the output
- unsigned char Pdistortion; //Model distortion added by FET element
- unsigned char Pwidth; //Phaser width (LFO amplitude)
- unsigned char Pfb; //feedback
- unsigned char Poffset; //Model mismatch between variable resistors
- unsigned char Pstages; //Number of first-order All-Pass stages
- unsigned char Poutsub; //if I wish to subtract the output instead of adding
- unsigned char Phyper; //lfo^2 -- converts tri into hyper-sine
- unsigned char Pdepth; //Depth of phaser sweep
- unsigned char Pbarber; //Enable parber pole phasing
-
-
- //Control parameters
- void setvolume(unsigned char Pvolume);
- void setpanning(unsigned char Ppanning);
- void setdistortion(unsigned char Pdistortion);
- void setwidth(unsigned char Pwidth);
- void setfb(unsigned char Pfb);
- void setoffset(unsigned char Poffset);
- void setstages(unsigned char Pstages);
- void setdepth(unsigned char Pdepth);
-
- //Internal Variables
- bool barber; //Barber pole phasing flag
- REALTYPE distortion, feedback, width, offsetpct, depth;
- Stereo<REALTYPE *> xn1, yn1;
- Stereo<REALTYPE> diff, oldgain, fb;
- REALTYPE invperiod;
- REALTYPE offset[12];
-
- float mis;
- float Rmin; // 3N5457 typical on resistance at Vgs = 0
- float Rmax; // Resistor parallel to FET
- float Rmx; // Rmin/Rmax to avoid division in loop
- float Rconst; // Handle parallel resistor relationship
- float C; // Capacitor
- float CFs; // A constant derived from capacitor and resistor relationships
-
- REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb,
- REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1);
-};
-
-#endif
diff --git a/src/Effects/CMakeLists.txt b/src/Effects/CMakeLists.txt
@@ -10,7 +10,6 @@ set(zynaddsubfx_effect_SRCS
EQ.cpp
Phaser.cpp
Reverb.cpp
- APhaser.cpp
)
add_library(zynaddsubfx_effect STATIC
diff --git a/src/Effects/EffectMgr.cpp b/src/Effects/EffectMgr.cpp
@@ -103,9 +103,6 @@ void EffectMgr::changeeffect(int nefx_)
case 8:
efx = new DynamicFilter(insertion, efxoutl, efxoutr);
break;
- case 9:
- efx = new Analog_Phaser(insertion, efxoutl, efxoutr);
- break;
//put more effect here
default:
efx = NULL;
diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h
@@ -33,7 +33,6 @@
#include "Distorsion.h"
#include "EQ.h"
#include "DynamicFilter.h"
-#include "APhaser.h"
#include "../Misc/XMLwrapper.h"
#include "../Params/FilterParams.h"
#include "../Params/Presets.h"
diff --git a/src/Effects/Makefile b/src/Effects/Makefile
@@ -2,7 +2,7 @@ include ../Makefile.inc
objects=Alienwah.o Chorus.o Echo.o Effect.o \
EffectLFO.o EffectMgr.o Phaser.o Reverb.o \
- Distorsion.o EQ.o DynamicFilter.o APhaser.o
+ Distorsion.o EQ.o DynamicFilter.o
all: $(objects)
diff --git a/src/Effects/Phaser.cpp b/src/Effects/Phaser.cpp
@@ -40,15 +40,52 @@ using namespace std;
#define ZERO_ 0.00001f // Same idea as above.
Phaser::Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
- :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), oldgain(0.0),
+ :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), xn1(NULL), yn1(NULL), diff(0.0), old(NULL), oldgain(0.0),
fb(0.0)
{
+ analog_setup();
setpreset(Ppreset);
cleanup();
}
+void Phaser::analog_setup()
+{
+ //model mismatch between JFET devices
+ offset[0] = -0.2509303f;
+ offset[1] = 0.9408924f;
+ offset[2] = 0.998f;
+ offset[3] = -0.3486182f;
+ offset[4] = -0.2762545f;
+ offset[5] = -0.5215785f;
+ offset[6] = 0.2509303f;
+ offset[7] = -0.9408924f;
+ offset[8] = -0.998f;
+ offset[9] = 0.3486182f;
+ offset[10] = 0.2762545f;
+ offset[11] = 0.5215785f;
+
+ barber = 0; //Deactivate barber pole phasing by default
+
+ mis = 1.0f;
+ Rmin = 625.0f;// 2N5457 typical on resistance at Vgs = 0
+ Rmax = 22000.0f;// Resistor parallel to FET
+ Rmx = Rmin/Rmax;
+ Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
+ C = 0.00000005f; // 50 nF
+ CFs = (float) 2.0f*(float)SAMPLE_RATE*C;
+ invperiod = 1.0f / ((float) SOUND_BUFFER_SIZE);
+}
+
Phaser::~Phaser()
{
+ if(xn1.l)
+ delete[] xn1.l;
+ if(yn1.l)
+ delete[] yn1.l;
+ if(xn1.r)
+ delete[] xn1.r;
+ if(yn1.r)
+ delete[] yn1.r;
}
/*
@@ -56,6 +93,99 @@ Phaser::~Phaser()
*/
void Phaser::out(const Stereo<REALTYPE *> &input)
{
+ if(Panalog)
+ AnalogPhase(input);
+ else
+ normalPhase(input);
+}
+
+void Phaser::AnalogPhase(const Stereo<REALTYPE *> &input)
+{
+ Stereo<REALTYPE> gain(0.0), lfoVal(0.0), mod(0.0), g(0.0), b(0.0), hpf(0.0);
+
+ lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
+ mod.l = lfoVal.l*width + depth;
+ mod.r = lfoVal.r*width + depth;
+
+ mod.l = limit(mod.l, ZERO_, ONE_);
+ mod.r = limit(mod.r, ZERO_, ONE_);
+
+ if(Phyper) {
+ //Triangle wave squared is approximately sin on bottom, tri on top
+ //Result is exponential sweep more akin to filter in synth with
+ //exponential generator circuitry.
+ mod.l *= mod.l;
+ mod.r *= mod.r;
+ }
+
+ //g.l,g.r is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
+ mod.l = sqrtf(1.0f - mod.l);
+ mod.r = sqrtf(1.0f - mod.r);
+
+ diff.r = (mod.r - oldgain.r) * invperiod;
+ diff.l = (mod.l - oldgain.l) * invperiod;
+
+ g = oldgain;
+ oldgain = mod;
+
+ for (int i = 0; i < SOUND_BUFFER_SIZE; i++) {
+ g.l += diff.l;// Linear interpolation between LFO samples
+ g.r += diff.r;
+
+ Stereo<REALTYPE> xn(input.l[i] * panning,
+ input.r[i] * (1.0f - panning));
+
+ if (barber) {
+ g.l = fmodf((g.l + 0.25f), ONE_);
+ g.r = fmodf((g.r + 0.25f), ONE_);
+ }
+
+ xn.l = applyPhase(xn.l, g.l, fb.l, hpf.l, yn1.l, xn1.l);
+ xn.r = applyPhase(xn.r, g.r, fb.r, hpf.r, yn1.r, xn1.r);
+
+
+ fb.l = xn.l * feedback;
+ fb.r = xn.r * feedback;
+ efxoutl[i] = xn.l;
+ efxoutr[i] = xn.r;
+ }
+
+ if(Poutsub) {
+ invSignal(efxoutl, SOUND_BUFFER_SIZE);
+ invSignal(efxoutr, SOUND_BUFFER_SIZE);
+ }
+}
+
+REALTYPE Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb,
+ REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1)
+{
+ for(int j = 0; j < Pstages; j++) { //Phasing routine
+ mis = 1.0f + offsetpct*offset[j];
+
+ //This is symmetrical.
+ //FET is not, so this deviates slightly, however sym dist. is
+ //better sounding than a real FET.
+ float d = (1.0f + 2.0f*(0.25f + g)*hpf*hpf*distortion) * mis;
+ Rconst = 1.0f + mis*Rmx;
+
+ // This is 1/R. R is being modulated to control filter fc.
+ float b = (Rconst - g)/ (d*Rmin);
+ float gain = (CFs - b)/(CFs + b);
+ yn1[j] = gain * (x + yn1[j]) - xn1[j];
+
+ //high pass filter:
+ //Distortion depends on the high-pass part of the AP stage.
+ hpf = yn1[j] + (1.0f-gain)*xn1[j];
+
+ xn1[j] = x;
+ x = yn1[j];
+ if (j==1)
+ x += fb; //Insert feedback after first phase stage
+ }
+ return x;
+}
+void Phaser::normalPhase(const Stereo<REALTYPE *> &input)
+{
Stereo<REALTYPE> gain(0.0), lfoVal(0.0);
lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
@@ -118,18 +248,23 @@ void Phaser::cleanup()
old.l[i] = 0.0;
old.r[i] = 0.0;
}
+ for(int i = 0; i < Pstages; i++) {
+ xn1.l[i] = 0.0;
+ yn1.l[i] = 0.0;
+ xn1.r[i] = 0.0;
+ yn1.r[i] = 0.0;
+ }
}
/*
* Parameter control
*/
-void Phaser::setdepth(unsigned char Pdepth)
+void Phaser::setwidth(unsigned char Pwidth)
{
- this->Pdepth = Pdepth;
- depth = ((float)Pdepth / 127.0f);
+ this->Pwidth = Pwidth;
+ width = ((float)Pwidth / 127.0f);
}
-
void Phaser::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
@@ -158,12 +293,41 @@ void Phaser::setlrcross(unsigned char Plrcross)
lrcross = Plrcross / 127.0;
}
+void Phaser::setdistortion(unsigned char Pdistortion)
+{
+ this->Pdistortion = Pdistortion;
+ distortion = (float)Pdistortion / 127.0f;
+}
+
+void Phaser::setoffset(unsigned char Poffset)
+{
+ this->Poffset = Poffset;
+ offsetpct = (float)Poffset / 127.0f;
+}
+
void Phaser::setstages(unsigned char Pstages)
{
+ if(xn1.l)
+ delete[] xn1.l;
+ if(yn1.l)
+ delete[] yn1.l;
+ if(xn1.r)
+ delete[] xn1.r;
+ if(yn1.r)
+ delete[] yn1.r;
+
+
this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages);
old = Stereo<REALTYPE *>(new REALTYPE[Pstages * 2],
new REALTYPE[Pstages * 2]);
+
+ xn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
+ new REALTYPE[Pstages]);
+
+ yn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
+ new REALTYPE[Pstages]);
+
cleanup();
}
@@ -173,11 +337,17 @@ void Phaser::setphase(unsigned char Pphase)
phase = (Pphase / 127.0);
}
+void Phaser::setdepth(unsigned char Pdepth)
+{
+ this->Pdepth = Pdepth;
+ depth = (float)(Pdepth) / 127.0f;
+}
+
void Phaser::setpreset(unsigned char npreset)
{
- const int PRESET_SIZE = 15;
- const int NUM_PRESETS = 12;
+ const int PRESET_SIZE = 15;
+ const int NUM_PRESETS = 12;
unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
//Phaser
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
@@ -186,7 +356,7 @@ void Phaser::setpreset(unsigned char npreset)
{64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20, 0, 0, 0},
{39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20, 0, 0, 0},
{64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20, 0, 0, 0},
- {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0, 0}
+ {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0, 0},
//APhaser
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
{64, 64, 14, 0, 1, 64, 64, 40, 4, 10, 0, 110, 1, 20, 1},
@@ -224,6 +394,7 @@ void Phaser::changepar(int npar, unsigned char value)
case 4:
lfo.PLFOtype = value;
lfo.updateparams();
+ barber = (2 == value);
break;
case 5:
lfo.Pstereo = value;
@@ -240,12 +411,20 @@ void Phaser::changepar(int npar, unsigned char value)
break;
case 9:
setlrcross(value);
+ setoffset(value);
break;
case 10:
Poutsub = min((int)value,1);
break;
case 11:
setphase(value);
+ setwidth(value);
+ break;
+ case 12:
+ Phyper = min((int)value, 1);
+ break;
+ case 13:
+ setdistortion(value);
break;
}
}
@@ -273,12 +452,18 @@ unsigned char Phaser::getpar(int npar) const
return Pstages;
case 9:
return Plrcross;
+ return Poffset;
case 10:
return Poutsub;
case 11:
return Pphase;
+ return Pwidth;
+ case 12:
+ return Phyper;
+ case 13:
+ return Pdistortion;
case 14:
- return 0;
+ return Panalog;
default:
return 0;
}
diff --git a/src/Effects/Phaser.h b/src/Effects/Phaser.h
@@ -48,27 +48,55 @@ class Phaser:public Effect
EffectLFO lfo; //Phaser modulator
unsigned char Pvolume; //Used to set wet/dry mix
unsigned char Ppanning;
+ unsigned char Pdistortion; //Model distortion added by FET element
unsigned char Pdepth; //Depth of phaser sweep
+ unsigned char Pwidth; //Phaser width (LFO amplitude)
unsigned char Pfb; //feedback
- unsigned char Plrcross; /**<crossover*/
+ unsigned char Poffset; //Model mismatch between variable resistors
+ unsigned char Plrcross; //crossover
unsigned char Pstages; //Number of first-order All-Pass stages
unsigned char Poutsub; //if I wish to subtract the output instead of adding
unsigned char Pphase;
+ unsigned char Phyper; //lfo^2 -- converts tri into hyper-sine
+ unsigned char Pbarber; //Enable parber pole phasing
+ unsigned char Panalog;
//Control parameters
void setvolume(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdepth(unsigned char Pdepth);
void setfb(unsigned char Pfb);
+ void setdistortion(unsigned char Pdistortion);
+ void setwidth(unsigned char Pwidth);
+ void setoffset(unsigned char Poffset);
void setlrcross(unsigned char Plrcross);
void setstages(unsigned char Pstages);
void setphase(unsigned char Pphase);
//Internal Variables
+ bool barber; //Barber pole phasing flag
+ REALTYPE distortion, width, offsetpct;
REALTYPE panning, feedback, depth, lrcross, phase;
- Stereo<REALTYPE *> old;
- Stereo<REALTYPE> oldgain, fb;
+ Stereo<REALTYPE *> old, xn1, yn1;
+ Stereo<REALTYPE> diff, oldgain, fb;
+ REALTYPE invperiod;
+ REALTYPE offset[12];
+
+ float mis;
+ float Rmin; // 3N5457 typical on resistance at Vgs = 0
+ float Rmax; // Resistor parallel to FET
+ float Rmx; // Rmin/Rmax to avoid division in loop
+ float Rconst; // Handle parallel resistor relationship
+ float C; // Capacitor
+ float CFs; // A constant derived from capacitor and resistor relationships
+ void analog_setup();
+ void AnalogPhase(const Stereo<REALTYPE *> &input);
+ //analog case
+ REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb,
+ REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1);
+
+ void normalPhase(const Stereo<REALTYPE *> &input);
REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old);
};
diff --git a/src/UI/EffUI.fl b/src/UI/EffUI.fl
@@ -155,7 +155,7 @@ return(log(freq/20.0)/log(1000.0));} {}
decl {int maxdB;} {}
}
-class EffUI {open : {public Fl_Group,public PresetsUI_}
+class EffUI {: {public Fl_Group,public PresetsUI_}
} {
Function {EffUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} {
code {eff=NULL;
@@ -167,7 +167,6 @@ effreverbwindow->hide();//delete (effreverbwindow);
effechowindow->hide();//delete (effechowindow);
effchoruswindow->hide();//delete (effchoruswindow);
effphaserwindow->hide();//delete (effphaserwindow);
-effaphaserwindow->hide();//delete (effaphaserwindow);
effalienwahwindow->hide();//delete (effalienwahwindow);
effdistorsionwindow->hide();//delete (effdistorsionwindow);
effeqwindow->hide();//delete (effeqwindow);
@@ -176,7 +175,8 @@ effdynamicfilterwindow->hide();//delete (effdynamicfilterwindow);
if (filterwindow!=NULL){
filterwindow->hide();
delete(filterwindow);
-};} {}
+};} {selected
+ }
}
Function {make_null_window()} {} {
Fl_Window effnullwindow {
@@ -583,11 +583,10 @@ refresh(eff);}
}
}
}
- Function {make_phaser_window()} {open
- } {
- Fl_Window effphaserwindow {open selected
- xywh {75 25 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1
- class Fl_Group visible
+ Function {make_phaser_window()} {} {
+ Fl_Window effphaserwindow {open
+ xywh {75 25 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
+ class Fl_Group
} {
Fl_Choice phaserp {
label Preset
@@ -703,157 +702,20 @@ refresh(eff);}
xywh {155 5 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 maximum 127
class WidgetPDial
}
- Fl_Check_Button {} {
- label Analog
- xywh {305 35 70 15} down_box DOWN_BOX
- }
- Fl_Dial aphaser13 {
- label dist
- callback {eff->seteffectpar(13,(int) o->value());}
- tooltip Distortion xywh {340 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Check_Button aphaser12 {
+ Fl_Check_Button phaserp12 {
label {hyp.}
callback {eff->seteffectpar(12,(int) o->value());}
tooltip hyper xywh {245 35 55 15} down_box DOWN_BOX
}
- }
- }
- Function {make_analog_phaser_window()} {open
- } {
- Fl_Window effaphaserwindow {open
- xywh {465 25 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1
- class Fl_Group visible
- } {
- Fl_Choice aphaserp {
- label Preset
- callback {eff->changepreset((int)o->value());
-refresh(eff);}
- xywh {10 15 105 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7
- } {
- MenuItem {} {
- label {Phaser 1}
- xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 2}
- xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 3}
- xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 4}
- xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 5}
- xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 6}
- xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- }
- Fl_Text_Display {} {
- label APhaser
- xywh {260 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8
- }
- Fl_Dial aphaser0 {
- label Vol
- callback {eff->seteffectpar(0,(int) o->value());}
- tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser1 {
- label Pan
- callback {eff->seteffectpar(1,(int) o->value());}
- xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser2 {
- label Freq
- callback {eff->seteffectpar(2,(int) o->value());}
- tooltip {LFO frequency} xywh {85 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser3 {
- label rnd
- callback {eff->seteffectpar(3,(int) o->value());}
- tooltip Randomness xywh {120 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127
- class WidgetPDial
- }
- Fl_Choice aphaser4 {
- label LFO
- callback {eff->seteffectpar(4,(int) o->value());}
- tooltip {LFO function} xywh {245 55 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 130 textsize 8
- } {
- MenuItem {} {
- label SIN
- xywh {15 15 100 20} labelfont 1 labelsize 10
- }
- MenuItem {} {
- label TRI
- xywh {25 25 100 20} labelfont 1 labelsize 10
- }
- }
- Fl_Dial aphaser5 {
- label {St.df}
- callback {eff->seteffectpar(5,(int) o->value());}
- tooltip {Left/Right Channel Phase Shift} xywh {155 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser6 {
- label Dpth
- callback {eff->seteffectpar(6,(int) o->value());}
- tooltip {LFO Depth} xywh {120 5 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser7 {
- label Fb
- callback {eff->seteffectpar(7,(int) o->value());}
- tooltip Feedback xywh {185 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Counter aphaser8 {
- label Stages
- callback {eff->seteffectpar(8,(int) o->value());}
- xywh {290 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1
- code0 {o->range(1,MAX_PHASER_STAGES);}
- }
- Fl_Dial aphaser9 {
- label offset
- callback {eff->seteffectpar(9,(int) o->value());}
- tooltip offset xywh {215 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Check_Button aphaser10 {
- label Substract
- callback {eff->seteffectpar(10,(int) o->value());}
- tooltip {inverts output} xywh {190 10 74 20} box THIN_UP_BOX down_box DOWN_BOX color 230 labelfont 1 labelsize 10
- }
- Fl_Dial aphaser11 {
- label Width
- callback {eff->seteffectpar(11,(int) o->value());}
- xywh {155 5 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 maximum 127
- class WidgetPDial
- }
- Fl_Check_Button aphaser12 {
- label {hyp.}
- callback {eff->seteffectpar(12,(int) o->value());}
- tooltip hyper xywh {245 35 55 15} down_box DOWN_BOX
- }
- Fl_Dial aphaser13 {
+ Fl_Dial phaserp13 {
label dist
callback {eff->seteffectpar(13,(int) o->value());}
- tooltip Distortion xywh {335 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ tooltip Distortion xywh {340 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
class WidgetPDial
}
- Fl_Check_Button {} {
+ Fl_Check_Button phaserp14 {
label Analog
- xywh {300 35 70 15} down_box DOWN_BOX
+ xywh {305 35 70 15} down_box DOWN_BOX
}
}
}
@@ -1404,7 +1266,6 @@ make_reverb_window();
make_echo_window();
make_chorus_window();
make_phaser_window();
-make_analog_phaser_window();
make_alienwah_window();
make_distorsion_window();
make_eq_window();
@@ -1418,7 +1279,6 @@ effreverbwindow->position(px,py);
effechowindow->position(px,py);
effchoruswindow->position(px,py);
effphaserwindow->position(px,py);
-effaphaserwindow->position(px,py);
effalienwahwindow->position(px,py);
effdistorsionwindow->position(px,py);
effeqwindow->position(px,py);
@@ -1435,7 +1295,6 @@ effreverbwindow->hide();
effechowindow->hide();
effchoruswindow->hide();
effphaserwindow->hide();
-effaphaserwindow->hide();
effalienwahwindow->hide();
effdistorsionwindow->hide();
effeqwindow->hide();
@@ -1508,6 +1367,9 @@ switch(eff->geteffect()){
phaserp9->value(eff->geteffectpar(9));
phaserp10->value(eff->geteffectpar(10));
phaserp11->value(eff->geteffectpar(11));
+ phaserp12->value(eff->geteffectpar(12));
+ phaserp13->value(eff->geteffectpar(13));
+ phaserp14->value(eff->geteffectpar(14));
effphaserwindow->show();
break;
case 5:
@@ -1571,23 +1433,6 @@ switch(eff->geteffect()){
effdynamicfilterwindow->show();
break;
- case 9://make_analog_phaser_window();
- aphaserp->value(eff->getpreset());
- aphaser0->value(eff->geteffectpar(0));if (eff->insertion!=0) aphaser0->label("D/W");
- aphaser1->value(eff->geteffectpar(1));
- aphaser2->value(eff->geteffectpar(2));
- aphaser3->value(eff->geteffectpar(3));
- aphaser4->value(eff->geteffectpar(4));
- aphaser5->value(eff->geteffectpar(5));
- aphaser6->value(eff->geteffectpar(6));
- aphaser7->value(eff->geteffectpar(7));
- aphaser8->value(eff->geteffectpar(8));
- aphaser9->value(eff->geteffectpar(9));
- aphaser10->value(eff->geteffectpar(10));
- aphaser11->value(eff->geteffectpar(11));
- aphaser12->value(eff->geteffectpar(12));
- effaphaserwindow->show();
- break;
default:effnullwindow->show();
break;
};
@@ -1967,78 +1812,6 @@ refresh(eff);}
}
}
}
- Function {make_analog_phaser_window()} {} {
- Fl_Window effaphaserwindow {
- xywh {367 295 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
- class Fl_Group
- } {
- Fl_Choice aphaserp {
- label Preset
- callback {eff->changepreset((int)o->value());
-refresh(eff);}
- xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7
- } {
- MenuItem {} {
- label {Phaser 1}
- xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 2}
- xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 3}
- xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 4}
- xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 5}
- xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- MenuItem {} {
- label {Phaser 6}
- xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7
- }
- }
- Fl_Text_Display {} {
- label APhaser
- xywh {105 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8
- }
- Fl_Dial aphaser0 {
- label Vol
- callback {eff->seteffectpar(0,(int) o->value());}
- tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser2 {
- label Freq
- callback {eff->seteffectpar(2,(int) o->value());}
- tooltip {LFO frequency} xywh {50 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser6 {
- label Dpth
- callback {eff->seteffectpar(6,(int) o->value());}
- tooltip {LFO Depth} xywh {90 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Dial aphaser7 {
- label Fb
- callback {eff->seteffectpar(7,(int) o->value());}
- tooltip Feedback xywh {135 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
- class WidgetPDial
- }
- Fl_Counter aphaser8 {
- label Stages
- callback {eff->seteffectpar(8,(int) o->value());}
- xywh {175 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1
- code0 {o->range(1,MAX_PHASER_STAGES);}
- }
- }
- }
Function {make_alienwah_window()} {} {
Fl_Window effalienwahwindow {
xywh {367 170 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide
@@ -2435,7 +2208,6 @@ make_reverb_window();
make_echo_window();
make_chorus_window();
make_phaser_window();
-make_analog_phaser_window();
make_alienwah_window();
make_distorsion_window();
make_eq_window();
@@ -2449,7 +2221,6 @@ effreverbwindow->position(px,py);
effechowindow->position(px,py);
effchoruswindow->position(px,py);
effphaserwindow->position(px,py);
-effaphaserwindow->position(px,py);
effalienwahwindow->position(px,py);
effdistorsionwindow->position(px,py);
effeqwindow->position(px,py);
@@ -2466,7 +2237,6 @@ effreverbwindow->hide();
effechowindow->hide();
effchoruswindow->hide();
effphaserwindow->hide();
-effaphaserwindow->hide();
effalienwahwindow->hide();
effdistorsionwindow->hide();
effeqwindow->hide();
@@ -2551,17 +2321,6 @@ switch(eff->geteffect()){
effdynamicfilterwindow->show();
break;
- case 9:
- aphaserp->value(eff->getpreset());
- aphaser0->value(eff->geteffectpar(0));if (eff->insertion!=0) dfp0->label("D/W");
- aphaser2->value(eff->geteffectpar(2));
- aphaser6->value(eff->geteffectpar(6));
- aphaser7->value(eff->geteffectpar(7));
- aphaser8->value(eff->geteffectpar(8));
-
-
- effaphaserwindow->show();
- break;
default:effnullwindow->show();
break;
};