commit cc2f3cb0bb3869e350efa3282053d60c1e9daf78
parent b1e5f1ad0301b7592d9ee594ad57dee52ede066a
Author: fundamental <[email protected]>
Date: Sun, 23 May 2010 13:43:52 -0400
Phaser: More merge work
Diffstat:
6 files changed, 260 insertions(+), 278 deletions(-)
diff --git a/src/Effects/APhaser.cpp b/src/Effects/APhaser.cpp
@@ -2,30 +2,26 @@
APhaser.cpp - Approximate digital model of an analog JFET phaser.
Analog modeling implemented by Ryan Billing aka Transmogrifox.
- November, 2009
-
- Credit to:
- ///////////////////
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
- Modified for rakarrack by Josep Andreu
-
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
+ 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) for more details.
+ 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,
@@ -34,15 +30,16 @@
*/
#include <cmath>
+#include <algorithm>
#include "APhaser.h"
-#include <cstdio>
-#include <iostream>
+
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_)
+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)
{
@@ -71,8 +68,6 @@ Analog_Phaser::Analog_Phaser(const int & insertion_, REALTYPE *efxoutl_, REALTYP
CFs = (float) 2.0f*(float)SAMPLE_RATE*C;
invperiod = 1.0f / ((float) SOUND_BUFFER_SIZE);
-
- Ppreset = 0;
setpreset(Ppreset);
cleanup();
}
@@ -89,7 +84,6 @@ Analog_Phaser::~Analog_Phaser()
delete[] yn1.r;
}
-
/*
* Effect output
*/
@@ -104,7 +98,7 @@ void Analog_Phaser::out(const Stereo<REALTYPE *> &input)
mod.l = limit(mod.l, ZERO_, ONE_);
mod.r = limit(mod.r, ZERO_, ONE_);
- if(Phyper != 0) {
+ 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.
@@ -113,7 +107,7 @@ void Analog_Phaser::out(const Stereo<REALTYPE *> &input)
}
//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.l = sqrtf(1.0f - mod.l);
mod.r = sqrtf(1.0f - mod.r);
diff.r = (mod.r - oldgain.r) * invperiod;
@@ -122,67 +116,60 @@ void Analog_Phaser::out(const Stereo<REALTYPE *> &input)
g = oldgain;
oldgain = mod;
- for (int i = 0; i < SOUND_BUFFER_SIZE; i++)
- {
-
+ 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], input.r[i]);
if (barber) {
- g.l = fmodf((g.l + 0.25f) , ONE_);
- g.r = fmodf((g.r + 0.25f) , ONE_);
+ g.l = fmodf((g.l + 0.25f), ONE_);
+ g.r = fmodf((g.r + 0.25f), ONE_);
}
- //Left channel
- for (int j = 0; j < Pstages; j++) {//Phasing routine
- mis = 1.0f + offsetpct*offset[j];
- float d = (1.0f + 2.0f*(0.25f + g.l)*hpf.l*hpf.l*distortion) * mis; //This is symmetrical. FET is not, so this deviates slightly, however sym dist. is better sounding than a real FET.
- Rconst = 1.0f + mis*Rmx;
- b.l = (Rconst - g.l )/ (d*Rmin); // This is 1/R. R is being modulated to control filter fc.
- gain.l = (CFs - b.l)/(CFs + b.l);
-
- yn1.l[j] = gain.l * (xn.l + yn1.l[j]) - xn1.l[j];
- hpf.l = yn1.l[j] + (1.0f-gain.l)*xn1.l[j]; //high pass filter -- Distortion depends on the high-pass part of the AP stage.
-
- xn1.l[j] = xn.l;
- xn.l = yn1.l[j];
- if (j==1)
- xn.l += fb.l; //Insert feedback after first phase stage
- }
-
- //Right channel
- for (int j = 0; j < Pstages; j++) {//Phasing routine
- mis = 1.0f + offsetpct*offset[j];
- float d = (1.0f + 2.0f*(0.25f + g.r)*hpf.r*hpf.r*distortion) * mis; // distortion
- Rconst = 1.0f + mis*Rmx;
- b.r = (Rconst - g.r )/ (d*Rmin);
- gain.r = (CFs - b.r)/(CFs + b.r);
-
- yn1.r[j] = gain.r * (xn.r + yn1.r[j]) - xn1.r[j];
- hpf.r = yn1.r[j] + (1.0f-gain.r)*xn1.r[j]; //high pass filter
-
- xn1.r[j] = xn.r;
- xn.r = yn1.r[j];
- if (j==1)
- xn.r += fb.r; //Insert feedback after first phase stage
- }
+ 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);
}
+}
- if(Poutsub != 0)
- for(int i = 0; i < SOUND_BUFFER_SIZE; i++)
- {
- efxoutl[i] *= -1.0f;
- efxoutr[i] *= -1.0f;
- }
+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;
}
/*
@@ -191,13 +178,11 @@ void Analog_Phaser::out(const Stereo<REALTYPE *> &input)
void Analog_Phaser::cleanup()
{
fb = oldgain = Stereo<REALTYPE>(0.0);
- for(int i = 0; i < Pstages; i++)
- {
+ 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;
-
}
}
@@ -220,13 +205,11 @@ void Analog_Phaser::setfb(unsigned char Pfb)
void Analog_Phaser::setvolume(unsigned char Pvolume)
{
this->Pvolume = Pvolume;
- // outvolume is needed in calling program
- if(insertion == 0) {
- outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0;
- volume = 1.0;
- }
+ outvolume = Pvolume / 127.0;
+ if(insertion == 0)
+ volume = 1.0;
else
- volume = outvolume = Pvolume / 127.0;
+ volume = outvolume;
}
void Analog_Phaser::setdistortion(unsigned char Pdistortion)
@@ -237,7 +220,7 @@ void Analog_Phaser::setdistortion(unsigned char Pdistortion)
void Analog_Phaser::setoffset(unsigned char Poffset)
{
- this->Poffset = Poffset;
+ this->Poffset = Poffset;
offsetpct = (float)Poffset / 127.0f;
}
@@ -253,10 +236,7 @@ void Analog_Phaser::setstages(unsigned char Pstages)
delete[] yn1.r;
- if(Pstages >= MAX_PHASER_STAGES)
- Pstages = MAX_PHASER_STAGES;
- this->Pstages = Pstages;
-
+ this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages);
xn1 = Stereo<REALTYPE *>(new REALTYPE[Pstages],
new REALTYPE[Pstages]);
@@ -269,8 +249,9 @@ void Analog_Phaser::setstages(unsigned char Pstages)
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; //Pdepth input should be 0-127. depth shall range 0-0.5 since we don't need to shift the full spectrum.
+ depth = (float)(Pdepth - 64) / 127.0f;
}
@@ -302,8 +283,7 @@ void Analog_Phaser::setpreset(unsigned char npreset)
void Analog_Phaser::changepar(int npar, unsigned char value)
{
- switch(npar)
- {
+ switch(npar) {
case 0:
setvolume(value);
break;
@@ -316,13 +296,12 @@ void Analog_Phaser::changepar(int npar, unsigned char value)
break;
case 3:
lfo.Prandomness = value;
- lfo.updateparams ();
+ lfo.updateparams();
break;
case 4:
lfo.PLFOtype = value;
lfo.updateparams();
- barber = 0;
- if (value == 2) barber = 1;
+ barber = (2 == value);
break;
case 5:
lfo.Pstereo = value;
@@ -341,66 +320,47 @@ void Analog_Phaser::changepar(int npar, unsigned char value)
setoffset(value);
break;
case 10:
- if (value > 1)
- value = 1;
- Poutsub = value;
+ Poutsub = min((int)value,1);
break;
case 11:
setdepth(value);
break;
case 12:
- if (value > 1)
- value = 1;
- Phyper = value;
+ Phyper = min((int)value, 1);
break;
}
}
unsigned char Analog_Phaser::getpar(int npar) const
{
- switch(npar)
- {
+ switch(npar) {
case 0:
- return(Pvolume);
- break;
+ return Pvolume;
case 1:
- return(Pdistortion);
- break;
+ return Pdistortion;
case 2:
- return(lfo.Pfreq);
- break;
+ return lfo.Pfreq;
case 3:
- return(lfo.Prandomness);
- break;
+ return lfo.Prandomness;
case 4:
- return(lfo.PLFOtype);
- break;
+ return lfo.PLFOtype;
case 5:
- return(lfo.Pstereo);
- break;
+ return lfo.Pstereo;
case 6:
- return(Pwidth);
- break;
+ return Pwidth;
case 7:
- return(Pfb);
- break;
+ return Pfb;
case 8:
- return(Pstages);
- break;
+ return Pstages;
case 9:
- return(Poffset);
- break;
+ return Poffset;
case 10:
- return(Poutsub);
- break;
+ return Poutsub;
case 11:
- return(Pdepth);
- break;
+ return Pdepth;
case 12:
- return(Phyper);
- break;
-
+ return Phyper;
default:
- return(0);
+ return 0;
}
}
diff --git a/src/Effects/APhaser.h b/src/Effects/APhaser.h
@@ -1,22 +1,22 @@
/*
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
- Modified for rakarrack by Josep Andreu
-
- Further modified for rakarrack by Ryan Billing (Transmogrifox) to model Analog Phaser behavior 2009
-
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
+ 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) for more details.
+ 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,
@@ -35,25 +35,24 @@
class Analog_Phaser:public Effect
{
public:
- Analog_Phaser(const int & insertion_, REALTYPE * efxoutl_, REALTYPE * efxoutr_);
+ 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();
- //unsigned char Ppreset;
private:
//Phaser parameters
EffectLFO lfo; //Phaser modulator
- unsigned char Pvolume; //Used in Process.cpp to set wet/dry mix
+ unsigned char Pvolume; //Used to set wet/dry mix
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 the adding it
+ 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
@@ -83,6 +82,9 @@ class Analog_Phaser:public Effect
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/Phaser.cpp b/src/Effects/Phaser.cpp
@@ -1,9 +1,18 @@
/*
+
+ Phaser.cpp - Phasing and 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
@@ -21,23 +30,31 @@
*/
#include <cmath>
+#include <algorithm>
#include "Phaser.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.
Phaser::Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_)
- :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(1), oldgain(0.0), fb(0.0)
+ :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), oldgain(0.0),
+ fb(0.0)
{
setpreset(Ppreset);
cleanup();
}
Phaser::~Phaser()
-{}
+{
+}
/*
* Effect output
*/
-void Phaser::out(const Stereo<float *> &smp)
+void Phaser::out(const Stereo<REALTYPE *> &input)
{
Stereo<REALTYPE> gain(0.0), lfoVal(0.0);
@@ -45,51 +62,50 @@ void Phaser::out(const Stereo<float *> &smp)
gain.l = (exp(lfoVal.l * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0);
gain.r = (exp(lfoVal.r * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0);
-
gain.l = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * gain.l * depth;
gain.r = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * gain.r * depth;
- gain.l = limit(gain.l, 0.0f, 1.0f);
- gain.r = limit(gain.r, 0.0f, 1.0f);
+ gain.l = limit(gain.l, ZERO_, ONE_);
+ gain.r = limit(gain.r, ZERO_, ONE_);
for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
REALTYPE x = (REALTYPE) i / SOUND_BUFFER_SIZE;
REALTYPE x1 = 1.0 - x;
+ //TODO think about making panning an external feature
+ Stereo<REALTYPE> xn(input.l[i] * panning + fb.l,
+ input.r[i] * (1.0 - panning) + fb.r);
+
Stereo<REALTYPE> g(gain.l * x + oldgain.l * x1,
gain.l * x + oldgain.r * x1);
- Stereo<REALTYPE> in(smp.l[i] * panning + fb.l,
- smp.r[i] * (1.0 - panning) + fb.r);
-
- //Left channel
- for(int j = 0; j < Pstages * 2; j++) { //Phasing routine
- REALTYPE tmp = old.l[j];
- old.l[j] = g.l * tmp + in.l;
- in.l = tmp - g.l *old.l[j];
- }
- //Right channel
- for(int j = 0; j < Pstages * 2; j++) { //Phasing routine
- REALTYPE tmp = old.r[j];
- old.r[j] = g.r * tmp + in.r;
- in.r = tmp - g.r *old.r[j];
- }
+
+ xn.l = applyPhase(xn.l, g.l, old.l);
+ xn.r = applyPhase(xn.r, g.r, old.r);
+
//Left/Right crossing
- Stereo<REALTYPE> tmp = in;
- in.l = tmp.l * (1.0 - lrcross) + tmp.r * lrcross;
- in.r = tmp.r * (1.0 - lrcross) + tmp.l * lrcross;
-
- fb.l = in.l * feedback;
- fb.r = in.r * feedback;
- efxoutl[i] = in.l;
- efxoutr[i] = in.r;
+ crossover(xn.l, xn.r, lrcross);
+
+ fb.l = xn.l * feedback;
+ fb.r = xn.r * feedback;
+ efxoutl[i] = xn.l;
+ efxoutr[i] = xn.r;
}
oldgain = gain;
- if(Poutsub != 0)
- for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
- efxoutl[i] *= -1.0;
- efxoutr[i] *= -1.0;
- }
+ if(Poutsub) {
+ invSignal(efxoutl, SOUND_BUFFER_SIZE);
+ invSignal(efxoutr, SOUND_BUFFER_SIZE);
+ }
+}
+
+REALTYPE Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old)
+{
+ for(int j = 0; j < Pstages * 2; j++) { //Phasing routine
+ REALTYPE tmp = old[j];
+ old[j] = g * tmp + x;
+ x = tmp - g *old[j];
+ }
+ return x;
}
/*
@@ -97,11 +113,11 @@ void Phaser::out(const Stereo<float *> &smp)
*/
void Phaser::cleanup()
{
- fb.l = 0.0;
- fb.r = 0.0;
- oldgain = Stereo<REALTYPE>(0.0);
- old.l.clear();
- old.r.clear();
+ fb = oldgain = Stereo<REALTYPE>(0.0);
+ for(int i = 0; i < Pstages * 2; i++) {
+ old.l[i] = 0.0;
+ old.r[i] = 0.0;
+ }
}
/*
@@ -110,14 +126,14 @@ void Phaser::cleanup()
void Phaser::setdepth(unsigned char Pdepth)
{
this->Pdepth = Pdepth;
- depth = (Pdepth / 127.0);
+ depth = ((float)Pdepth / 127.0f);
}
void Phaser::setfb(unsigned char Pfb)
{
this->Pfb = Pfb;
- feedback = (Pfb - 64.0) / 64.1;
+ feedback = (float) (Pfb - 64) / 64.2f;
}
void Phaser::setvolume(unsigned char Pvolume)
@@ -133,7 +149,7 @@ void Phaser::setvolume(unsigned char Pvolume)
void Phaser::setpanning(unsigned char Ppanning)
{
this->Ppanning = Ppanning;
- panning = Ppanning / 127.0;
+ panning = (float)Ppanning / 127.0;
}
void Phaser::setlrcross(unsigned char Plrcross)
@@ -144,11 +160,10 @@ void Phaser::setlrcross(unsigned char Plrcross)
void Phaser::setstages(unsigned char Pstages)
{
- if(Pstages >= MAX_PHASER_STAGES)
- this->Pstages = MAX_PHASER_STAGES - 1;
- else
- this->Pstages = Pstages;
- old = Stereo<Sample>(Pstages * 2);
+ this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages);
+
+ old = Stereo<REALTYPE *>(new REALTYPE[Pstages * 2],
+ new REALTYPE[Pstages * 2]);
cleanup();
}
@@ -188,93 +203,77 @@ void Phaser::setpreset(unsigned char npreset)
void 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();
- 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:
- setlrcross(value);
- break;
- case 10:
- if(value > 1)
- Poutsub = 1;
- else
- Poutsub = value;
- break;
- case 11:
- setphase(value);
- break;
+ 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();
+ 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:
+ setlrcross(value);
+ break;
+ case 10:
+ Poutsub = min((int)value,1);
+ break;
+ case 11:
+ setphase(value);
+ break;
}
}
unsigned char Phaser::getpar(int npar) const
{
switch(npar) {
- case 0:
- return Pvolume;
- break;
- case 1:
- return Ppanning;
- break;
- case 2:
- return lfo.Pfreq;
- break;
- case 3:
- return lfo.Prandomness;
- break;
- case 4:
- return lfo.PLFOtype;
- break;
- case 5:
- return lfo.Pstereo;
- break;
- case 6:
- return Pdepth;
- break;
- case 7:
- return Pfb;
- break;
- case 8:
- return Pstages;
- break;
- case 9:
- return Plrcross;
- break;
- case 10:
- return Poutsub;
- break;
- case 11:
- return Pphase;
- break;
- default:
- return 0;
+ 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 Plrcross;
+ case 10:
+ return Poutsub;
+ case 11:
+ return Pphase;
+ default:
+ return 0;
}
}
-
diff --git a/src/Effects/Phaser.h b/src/Effects/Phaser.h
@@ -3,7 +3,11 @@
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
@@ -23,38 +27,35 @@
#ifndef PHASER_H
#define PHASER_H
#include "../globals.h"
-#include "../Misc/Stereo.h"
-#include "../Samples/Sample.h"
#include "Effect.h"
#include "EffectLFO.h"
#define MAX_PHASER_STAGES 12
-/**Phaser Effect*/
+
class Phaser:public Effect
{
public:
- Phaser(const int &insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
+ Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_);
~Phaser();
- void out(const Stereo<float *> &smp);
+ 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();
- void setdryonly();
private:
- //Parametrii Phaser
- EffectLFO lfo; /**<lfo-ul Phaser*/
- unsigned char Pvolume;
+ //Phaser parameters
+ EffectLFO lfo; //Phaser modulator
+ unsigned char Pvolume; //Used to set wet/dry mix
unsigned char Ppanning;
- unsigned char Pdepth; /**<the depth of the Phaser*/
- unsigned char Pfb; /**<feedback*/
+ unsigned char Pdepth; //Depth of phaser sweep
+ unsigned char Pfb; //feedback
unsigned char Plrcross; /**<crossover*/
- unsigned char Pstages;
- unsigned char Poutsub; /**<if I wish to substract the output instead of the adding it*/
+ 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;
- //Control Parameters
+ //Control parameters
void setvolume(unsigned char Pvolume);
void setpanning(unsigned char Ppanning);
void setdepth(unsigned char Pdepth);
@@ -63,11 +64,12 @@ class Phaser:public Effect
void setstages(unsigned char Pstages);
void setphase(unsigned char Pphase);
- //Internal Values
+ //Internal Variables
REALTYPE panning, feedback, depth, lrcross, phase;
- Stereo<Sample> old;
- Stereo<REALTYPE> oldgain;
- Stereo<REALTYPE> fb;
+ Stereo<REALTYPE *> old;
+ Stereo<REALTYPE> oldgain, fb;
+
+ REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old);
};
#endif
diff --git a/src/Misc/Util.cpp b/src/Misc/Util.cpp
@@ -113,3 +113,18 @@ bool fileexists(const char *filename)
return false;
}
+void invSignal(REALTYPE *sig, size_t len)
+{
+ for(int i = 0; i < len; i++)
+ sig[i] *= -1.0f;
+}
+
+void crossover(REALTYPE &a, REALTYPE &b, REALTYPE crossover)
+{
+ REALTYPE tmpa = a;
+ REALTYPE tmpb = b;
+ a = tmpa * (1.0 - crossover) + tmpb * crossover;
+ b = tmpb * (1.0 - crossover) + tmpa * crossover;
+}
+
+
diff --git a/src/Misc/Util.h b/src/Misc/Util.h
@@ -42,6 +42,10 @@ extern REALTYPE *denormalkillbuf; /**<the buffer to add noise in order to avoid
extern Config config;
+void invSignal(REALTYPE *sig, size_t len);
+
+void crossover(REALTYPE &a, REALTYPE &b, REALTYPE crossover);
+
template<class T>
std::string stringFrom(T x)
{