mirror of https://github.com/probonopd/MiniDexed
parent
f0e2593e81
commit
aae85e5f85
@ -0,0 +1,179 @@ |
||||
/*
|
||||
* Phaser Port |
||||
* Ported from https://github.com/ssj71/rkrlv2
|
||||
*
|
||||
* Javier Nonis (https://github.com/jnonis) - 2024
|
||||
*/ |
||||
#ifndef _EFFECT_APHASER_H |
||||
#define _EFFECT_APHASER_H |
||||
|
||||
#include "effect_base.h" |
||||
#include "rkrlv2/APhaser.h" |
||||
|
||||
class AudioEffectAPhaser : public AudioEffect |
||||
{ |
||||
public: |
||||
enum Param |
||||
{ |
||||
BYPASS, |
||||
WETDRY, |
||||
PAN, |
||||
PH_FREQ, |
||||
PH_RND, |
||||
TYPE, |
||||
STDL, |
||||
PH_DEPTH, |
||||
FB, |
||||
STAGES, |
||||
LRCR, |
||||
SUB, |
||||
PHASE, |
||||
UNKNOWN |
||||
}; |
||||
|
||||
AudioEffectAPhaser(float32_t samplerate) : AudioEffect(samplerate) |
||||
{ |
||||
this->phaser = new Analog_Phaser(0, 0, (double) samplerate); |
||||
this->init_params = true; |
||||
|
||||
this->phaser->setpreset(0); |
||||
/*
|
||||
this->setParameter(AudioEffectAPhaser::Param::WETDRY, 64); |
||||
this->setParameter(AudioEffectAPhaser::Param::PAN, 64); |
||||
this->setParameter(AudioEffectAPhaser::Param::PH_FREQ, 11); |
||||
this->setParameter(AudioEffectAPhaser::Param::PH_RND, 0); |
||||
this->setParameter(AudioEffectAPhaser::Param::TYPE, 0); |
||||
this->setParameter(AudioEffectAPhaser::Param::STDL, 64); |
||||
this->setParameter(AudioEffectAPhaser::Param::PH_DEPTH, 110); |
||||
this->setParameter(AudioEffectAPhaser::Param::FB, 64); |
||||
this->setParameter(AudioEffectAPhaser::Param::STAGES, 4); |
||||
this->setParameter(AudioEffectAPhaser::Param::LRCR, 0); |
||||
this->setParameter(AudioEffectAPhaser::Param::SUB, 0); |
||||
this->setParameter(AudioEffectAPhaser::Param::PHASE, 20); |
||||
*/ |
||||
} |
||||
|
||||
virtual ~AudioEffectAPhaser() |
||||
{ |
||||
delete this->phaser; |
||||
} |
||||
|
||||
virtual unsigned getId() |
||||
{ |
||||
return EFFECT_APHASER; |
||||
} |
||||
|
||||
virtual void setParameter(unsigned param, unsigned value) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectAPhaser::Param::BYPASS: |
||||
this->setBypass(value == 1); |
||||
this->phaser->cleanup(); |
||||
break; |
||||
case AudioEffectAPhaser::Param::WETDRY: |
||||
this->phaser->changepar(0, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::PAN: |
||||
this->phaser->changepar(1, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::PH_FREQ: |
||||
this->phaser->changepar(2, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::PH_RND: |
||||
this->phaser->changepar(3, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::TYPE: |
||||
this->phaser->changepar(4, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::STDL: |
||||
this->phaser->changepar(5, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::PH_DEPTH: |
||||
this->phaser->changepar(6, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::FB: |
||||
this->phaser->changepar(7, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::STAGES: |
||||
this->phaser->changepar(8, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::LRCR: |
||||
this->phaser->changepar(9, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::SUB: |
||||
this->phaser->changepar(10, value); |
||||
break; |
||||
case AudioEffectAPhaser::Param::PHASE: |
||||
this->phaser->changepar(11, value); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
virtual unsigned getParameter(unsigned param) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectAPhaser::Param::BYPASS: |
||||
return this->getBypass() ? 1 : 0; |
||||
case AudioEffectAPhaser::Param::WETDRY: |
||||
return this->phaser->getpar(0); |
||||
case AudioEffectAPhaser::Param::PAN: |
||||
return this->phaser->getpar(1); |
||||
case AudioEffectAPhaser::Param::PH_FREQ: |
||||
return this->phaser->getpar(2); |
||||
case AudioEffectAPhaser::Param::PH_RND: |
||||
return this->phaser->getpar(3); |
||||
case AudioEffectAPhaser::Param::TYPE: |
||||
return this->phaser->getpar(4); |
||||
case AudioEffectAPhaser::Param::STDL: |
||||
return this->phaser->getpar(5); |
||||
case AudioEffectAPhaser::Param::PH_DEPTH: |
||||
return this->phaser->getpar(6); |
||||
case AudioEffectAPhaser::Param::FB: |
||||
return this->phaser->getpar(7); |
||||
case AudioEffectAPhaser::Param::STAGES: |
||||
return this->phaser->getpar(8); |
||||
case AudioEffectAPhaser::Param::LRCR: |
||||
return this->phaser->getpar(9); |
||||
case AudioEffectAPhaser::Param::SUB: |
||||
return this->phaser->getpar(10); |
||||
case AudioEffectAPhaser::Param::PHASE: |
||||
return this->phaser->getpar(11); |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
protected: |
||||
virtual size_t getParametersSize() |
||||
{ |
||||
return AudioEffectAPhaser::Param::UNKNOWN; |
||||
} |
||||
|
||||
virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) |
||||
{ |
||||
// LFO effects require period be set before setting other params
|
||||
if(this->init_params) |
||||
{ |
||||
this->phaser->PERIOD = len; |
||||
this->phaser->lfo->updateparams(len); |
||||
this->init_params = false; // so we only do this once
|
||||
} |
||||
|
||||
// now set out ports and global period size
|
||||
this->phaser->efxoutl = outblockL; |
||||
this->phaser->efxoutr = outblockR; |
||||
|
||||
//now run
|
||||
this->phaser->out((float*) inblockL, (float*) inblockR, len); |
||||
} |
||||
|
||||
private: |
||||
Analog_Phaser* phaser; |
||||
bool init_params; |
||||
}; |
||||
|
||||
#endif // _EFFECT_PHASER_H
|
@ -0,0 +1,179 @@ |
||||
/*
|
||||
* Phaser Port |
||||
* Ported from https://github.com/ssj71/rkrlv2
|
||||
*
|
||||
* Javier Nonis (https://github.com/jnonis) - 2024
|
||||
*/ |
||||
#ifndef _EFFECT_PHASER_H |
||||
#define _EFFECT_PHASER_H |
||||
|
||||
#include "effect_base.h" |
||||
#include "rkrlv2/Phaser.h" |
||||
|
||||
class AudioEffectPhaser : public AudioEffect |
||||
{ |
||||
public: |
||||
enum Param |
||||
{ |
||||
BYPASS, |
||||
WETDRY, |
||||
PAN, |
||||
PH_FREQ, |
||||
PH_RND, |
||||
TYPE, |
||||
STDL, |
||||
PH_DEPTH, |
||||
FB, |
||||
STAGES, |
||||
LRCR, |
||||
SUB, |
||||
PHASE, |
||||
UNKNOWN |
||||
}; |
||||
|
||||
AudioEffectPhaser(float32_t samplerate) : AudioEffect(samplerate) |
||||
{ |
||||
this->phaser = new Phaser(0, 0, (double) samplerate); |
||||
this->init_params = true; |
||||
|
||||
this->phaser->setpreset(0); |
||||
/*
|
||||
this->setParameter(AudioEffectPhaser::Param::WETDRY, 64); |
||||
this->setParameter(AudioEffectPhaser::Param::PAN, 64); |
||||
this->setParameter(AudioEffectPhaser::Param::PH_FREQ, 11); |
||||
this->setParameter(AudioEffectPhaser::Param::PH_RND, 0); |
||||
this->setParameter(AudioEffectPhaser::Param::TYPE, 0); |
||||
this->setParameter(AudioEffectPhaser::Param::STDL, 64); |
||||
this->setParameter(AudioEffectPhaser::Param::PH_DEPTH, 110); |
||||
this->setParameter(AudioEffectPhaser::Param::FB, 64); |
||||
this->setParameter(AudioEffectPhaser::Param::STAGES, 4); |
||||
this->setParameter(AudioEffectPhaser::Param::LRCR, 0); |
||||
this->setParameter(AudioEffectPhaser::Param::SUB, 0); |
||||
this->setParameter(AudioEffectPhaser::Param::PHASE, 20); |
||||
*/ |
||||
} |
||||
|
||||
virtual ~AudioEffectPhaser() |
||||
{ |
||||
delete this->phaser; |
||||
} |
||||
|
||||
virtual unsigned getId() |
||||
{ |
||||
return EFFECT_PHASER; |
||||
} |
||||
|
||||
virtual void setParameter(unsigned param, unsigned value) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectPhaser::Param::BYPASS: |
||||
this->setBypass(value == 1); |
||||
this->phaser->cleanup(); |
||||
break; |
||||
case AudioEffectPhaser::Param::WETDRY: |
||||
this->phaser->changepar(0, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::PAN: |
||||
this->phaser->changepar(1, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::PH_FREQ: |
||||
this->phaser->changepar(2, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::PH_RND: |
||||
this->phaser->changepar(3, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::TYPE: |
||||
this->phaser->changepar(4, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::STDL: |
||||
this->phaser->changepar(5, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::PH_DEPTH: |
||||
this->phaser->changepar(6, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::FB: |
||||
this->phaser->changepar(7, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::STAGES: |
||||
this->phaser->changepar(8, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::LRCR: |
||||
this->phaser->changepar(9, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::SUB: |
||||
this->phaser->changepar(10, value); |
||||
break; |
||||
case AudioEffectPhaser::Param::PHASE: |
||||
this->phaser->changepar(11, value); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
virtual unsigned getParameter(unsigned param) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectPhaser::Param::BYPASS: |
||||
return this->getBypass() ? 1 : 0; |
||||
case AudioEffectPhaser::Param::WETDRY: |
||||
return this->phaser->getpar(0); |
||||
case AudioEffectPhaser::Param::PAN: |
||||
return this->phaser->getpar(1); |
||||
case AudioEffectPhaser::Param::PH_FREQ: |
||||
return this->phaser->getpar(2); |
||||
case AudioEffectPhaser::Param::PH_RND: |
||||
return this->phaser->getpar(3); |
||||
case AudioEffectPhaser::Param::TYPE: |
||||
return this->phaser->getpar(4); |
||||
case AudioEffectPhaser::Param::STDL: |
||||
return this->phaser->getpar(5); |
||||
case AudioEffectPhaser::Param::PH_DEPTH: |
||||
return this->phaser->getpar(6); |
||||
case AudioEffectPhaser::Param::FB: |
||||
return this->phaser->getpar(7); |
||||
case AudioEffectPhaser::Param::STAGES: |
||||
return this->phaser->getpar(8); |
||||
case AudioEffectPhaser::Param::LRCR: |
||||
return this->phaser->getpar(9); |
||||
case AudioEffectPhaser::Param::SUB: |
||||
return this->phaser->getpar(10); |
||||
case AudioEffectPhaser::Param::PHASE: |
||||
return this->phaser->getpar(11); |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
protected: |
||||
virtual size_t getParametersSize() |
||||
{ |
||||
return AudioEffectPhaser::Param::UNKNOWN; |
||||
} |
||||
|
||||
virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) |
||||
{ |
||||
// LFO effects require period be set before setting other params
|
||||
if(this->init_params) |
||||
{ |
||||
this->phaser->PERIOD = len; |
||||
this->phaser->lfo->updateparams(len); |
||||
this->init_params = false; // so we only do this once
|
||||
} |
||||
|
||||
// now set out ports and global period size
|
||||
this->phaser->efxoutl = outblockL; |
||||
this->phaser->efxoutr = outblockR; |
||||
|
||||
//now run
|
||||
this->phaser->out((float*) inblockL, (float*) inblockR, len); |
||||
} |
||||
|
||||
private: |
||||
Phaser* phaser; |
||||
bool init_params; |
||||
}; |
||||
|
||||
#endif // _EFFECT_PHASER_H
|
@ -0,0 +1,440 @@ |
||||
/*
|
||||
APhaser.C - 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.C - Phaser effect |
||||
Copyright (C) 2002-2005 Nasca Octavian Paul |
||||
Author: Nasca Octavian Paul |
||||
|
||||
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 |
||||
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. |
||||
|
||||
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 <math.h> |
||||
#include "APhaser.h" |
||||
#include <stdio.h> |
||||
//#include "FPreset.h"
|
||||
#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 (float * efxoutl_, float * efxoutr_, double sample_rate) |
||||
{ |
||||
float fSAMPLE_RATE = sample_rate; |
||||
|
||||
efxoutl = efxoutl_; |
||||
efxoutr = efxoutr_; |
||||
|
||||
lxn1 = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES); |
||||
|
||||
lyn1 = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES); |
||||
|
||||
rxn1 = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES); |
||||
|
||||
ryn1 = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES); |
||||
|
||||
offset = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES); //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 = 2.0f*fSAMPLE_RATE*C; |
||||
|
||||
lfo = new EffectLFO(sample_rate); |
||||
|
||||
Ppreset = 0; |
||||
PERIOD = 255; //make best guess for init;
|
||||
setpreset (Ppreset);//this will get done before out is run
|
||||
cleanup (); |
||||
}; |
||||
|
||||
Analog_Phaser::~Analog_Phaser () |
||||
{ |
||||
free(lxn1); |
||||
free(lyn1); |
||||
free(rxn1); |
||||
free(ryn1); |
||||
free(offset); |
||||
delete lfo; |
||||
}; |
||||
|
||||
|
||||
/*
|
||||
* Effect output |
||||
*/ |
||||
void |
||||
Analog_Phaser::out (float * smpsl, float * smpsr, uint32_t period) |
||||
{ |
||||
unsigned int i; |
||||
int j; |
||||
float lfol, lfor, lgain, rgain, bl, br, gl, gr, rmod, lmod, d, hpfr, hpfl; |
||||
invperiod = 1.0f / (float)PERIOD;//had to move this to run
|
||||
lgain = 0.0; |
||||
rgain = 0.0; |
||||
|
||||
//initialize hpf
|
||||
hpfl = 0.0; |
||||
hpfr = 0.0; |
||||
|
||||
lfo->effectlfoout (&lfol, &lfor); |
||||
lmod = lfol*width + depth; |
||||
rmod = lfor*width + depth; |
||||
|
||||
if (lmod > ONE_) |
||||
lmod = ONE_; |
||||
else if (lmod < ZERO_) |
||||
lmod = ZERO_; |
||||
if (rmod > ONE_) |
||||
rmod = ONE_; |
||||
else if (rmod < ZERO_) |
||||
rmod = ZERO_; |
||||
|
||||
if (Phyper != 0) { |
||||
lmod *= lmod; //Triangle wave squared is approximately sin on bottom, tri on top
|
||||
rmod *= rmod; //Result is exponential sweep more akin to filter in synth with exponential generator circuitry.
|
||||
}; |
||||
|
||||
lmod = sqrtf(1.0f - lmod); //gl,gr is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
|
||||
rmod = sqrtf(1.0f - rmod); |
||||
|
||||
rdiff = (rmod - oldrgain) * invperiod; |
||||
ldiff = (lmod - oldlgain) * invperiod; |
||||
|
||||
gl = oldlgain; |
||||
gr = oldrgain; |
||||
|
||||
oldlgain = lmod; |
||||
oldrgain = rmod; |
||||
|
||||
float v1, v2; |
||||
if (outvolume < 0.5f) |
||||
{ |
||||
v1 = 1.0f; |
||||
v2 = outvolume * 2.0f; |
||||
} |
||||
else |
||||
{ |
||||
v1 = (1.0f - outvolume) * 2.0f; |
||||
v2 = 1.0f; |
||||
} |
||||
|
||||
for (i = 0; i < period; i++) { |
||||
|
||||
gl += ldiff; // Linear interpolation between LFO samples
|
||||
gr += rdiff; |
||||
|
||||
float lxn = smpsl[i]; |
||||
float rxn = smpsr[i]; |
||||
|
||||
|
||||
if (barber) { |
||||
gl = fmodf((gl + 0.25f) , ONE_); |
||||
gr = fmodf((gr + 0.25f) , ONE_); |
||||
}; |
||||
|
||||
|
||||
//Left channel
|
||||
for (j = 0; j < Pstages; j++) { |
||||
//Phasing routine
|
||||
mis = 1.0f + offsetpct*offset[j]; |
||||
d = (1.0f + 2.0f*(0.25f + gl)*hpfl*hpfl*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; |
||||
bl = (Rconst - gl )/ (d*Rmin); // This is 1/R. R is being modulated to control filter fc.
|
||||
lgain = (CFs - bl)/(CFs + bl); |
||||
|
||||
lyn1[j] = lgain * (lxn + lyn1[j]) - lxn1[j]; |
||||
lyn1[j] += DENORMAL_GUARD; |
||||
hpfl = lyn1[j] + (1.0f-lgain)*lxn1[j]; //high pass filter -- Distortion depends on the high-pass part of the AP stage.
|
||||
|
||||
lxn1[j] = lxn; |
||||
lxn = lyn1[j]; |
||||
if (j==1) lxn += fbl; //Insert feedback after first phase stage
|
||||
}; |
||||
|
||||
//Right channel
|
||||
for (j = 0; j < Pstages; j++) { |
||||
//Phasing routine
|
||||
mis = 1.0f + offsetpct*offset[j]; |
||||
d = (1.0f + 2.0f*(0.25f + gr)*hpfr*hpfr*distortion) * mis; // distortion
|
||||
Rconst = 1.0f + mis*Rmx; |
||||
br = (Rconst - gr )/ (d*Rmin); |
||||
rgain = (CFs - br)/(CFs + br); |
||||
|
||||
ryn1[j] = rgain * (rxn + ryn1[j]) - rxn1[j]; |
||||
ryn1[j] += DENORMAL_GUARD; |
||||
hpfr = ryn1[j] + (1.0f-rgain)*rxn1[j]; //high pass filter
|
||||
|
||||
rxn1[j] = rxn; |
||||
rxn = ryn1[j]; |
||||
if (j==1) rxn += fbr; //Insert feedback after first phase stage
|
||||
}; |
||||
|
||||
fbl = lxn * fb; |
||||
fbr = rxn * fb; |
||||
|
||||
if (Poutsub != 0) { |
||||
lxn *= -1.0f; |
||||
rxn *= -1.0f; |
||||
} |
||||
|
||||
efxoutl[i] = smpsl[i] * v1 + lxn * v2; |
||||
efxoutr[i] = smpsr[i] * v1 + rxn * v2; |
||||
}; |
||||
}; |
||||
|
||||
/*
|
||||
* Cleanup the effect |
||||
*/ |
||||
void |
||||
Analog_Phaser::cleanup () |
||||
{ |
||||
fbl = 0.0; |
||||
fbr = 0.0; |
||||
oldlgain = 0.0; |
||||
oldrgain = 0.0; |
||||
for (int i = 0; i < Pstages; i++) { |
||||
lxn1[i] = 0.0; |
||||
|
||||
lyn1[i] = 0.0; |
||||
|
||||
rxn1[i] = 0.0; |
||||
|
||||
ryn1[i] = 0.0; |
||||
|
||||
}; |
||||
}; |
||||
|
||||
/*
|
||||
* Parameter control |
||||
*/ |
||||
void |
||||
Analog_Phaser::setwidth (int Pwidth) |
||||
{ |
||||
this->Pwidth = Pwidth; |
||||
width = ((float)Pwidth / 127.0f); |
||||
}; |
||||
|
||||
|
||||
void |
||||
Analog_Phaser::setfb (int Pfb) |
||||
{ |
||||
this->Pfb = Pfb; |
||||
fb = (float) (Pfb - 64) / 64.2f; |
||||
}; |
||||
|
||||
void |
||||
Analog_Phaser::setvolume (int Pvolume) |
||||
{ |
||||
this->Pvolume = Pvolume; |
||||
// outvolume is needed in calling program
|
||||
outvolume = (float)Pvolume / 127.0f; |
||||
}; |
||||
|
||||
void |
||||
Analog_Phaser::setdistortion (int Pdistortion) |
||||
{ |
||||
this->Pdistortion = Pdistortion; |
||||
distortion = (float)Pdistortion / 127.0f; |
||||
}; |
||||
|
||||
void |
||||
Analog_Phaser::setoffset (int Poffset) |
||||
{ |
||||
this->Poffset = Poffset; |
||||
offsetpct = (float)Poffset / 127.0f; |
||||
}; |
||||
|
||||
void |
||||
Analog_Phaser::setstages (int Pstages) |
||||
{ |
||||
|
||||
if (Pstages >= MAX_PHASER_STAGES) |
||||
Pstages = MAX_PHASER_STAGES ; |
||||
this->Pstages = Pstages; |
||||
|
||||
cleanup (); |
||||
}; |
||||
|
||||
void |
||||
Analog_Phaser::setdepth (int Pdepth) |
||||
{ |
||||
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.
|
||||
}; |
||||
|
||||
|
||||
void |
||||
Analog_Phaser::setpreset (int npreset) |
||||
{ |
||||
const int PRESET_SIZE = 13; |
||||
const int NUM_PRESETS = 6; |
||||
int presets[NUM_PRESETS][PRESET_SIZE] = { |
||||
//Phaser1
|
||||
{64, 20, 14, 0, 1, 64, 110, 40, 4, 10, 0, 64, 1}, |
||||
//Phaser2
|
||||
{64, 20, 14, 5, 1, 64, 110, 40, 6, 10, 0, 70, 1}, |
||||
//Phaser3
|
||||
{64, 20, 9, 0, 0, 64, 40, 40, 8, 10, 0, 60, 0}, |
||||
//Phaser4
|
||||
{64, 20, 14, 10, 0, 64, 110, 80, 7, 10, 1, 45, 1}, |
||||
//Phaser5
|
||||
{25, 20, 240, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0}, |
||||
//Phaser6
|
||||
{64, 20, 1, 10, 1, 64, 110, 40, 12, 10, 0, 70, 1} |
||||
}; |
||||
|
||||
if(npreset>NUM_PRESETS-1) { |
||||
|
||||
} else { |
||||
|
||||
for (int n = 0; n < PRESET_SIZE; n++) |
||||
changepar (n, presets[npreset][n]); |
||||
} |
||||
|
||||
Ppreset = npreset; |
||||
}; |
||||
|
||||
|
||||
void |
||||
Analog_Phaser::changepar (int npar, int value) |
||||
{ |
||||
switch (npar) { |
||||
case 0: |
||||
setvolume (value); |
||||
break; |
||||
case 1: |
||||
setdistortion (value); |
||||
break; |
||||
case 2: |
||||
lfo->Pfreq = value; |
||||
lfo->updateparams (PERIOD); |
||||
break; |
||||
case 3: |
||||
lfo->Prandomness = value; |
||||
lfo->updateparams (PERIOD); |
||||
break; |
||||
case 4: |
||||
lfo->PLFOtype = value; |
||||
lfo->updateparams (PERIOD); |
||||
barber = 0; |
||||
if (value == 2) barber = 1; |
||||
break; |
||||
case 5: |
||||
lfo->Pstereo = value; |
||||
lfo->updateparams (PERIOD); |
||||
break; |
||||
case 6: |
||||
setwidth (value); |
||||
break; |
||||
case 7: |
||||
setfb (value); |
||||
break; |
||||
case 8: |
||||
setstages (value); |
||||
break; |
||||
case 9: |
||||
setoffset (value); |
||||
break; |
||||
case 10: |
||||
if (value > 1) |
||||
value = 1; |
||||
Poutsub = value; |
||||
break; |
||||
case 11: |
||||
setdepth (value); |
||||
break; |
||||
case 12: |
||||
if (value > 1) |
||||
value = 1; |
||||
Phyper = value; |
||||
break; |
||||
}; |
||||
}; |
||||
|
||||
int |
||||
Analog_Phaser::getpar (int npar) |
||||
{ |
||||
switch (npar) { |
||||
case 0: |
||||
return (Pvolume); |
||||
break; |
||||
case 1: |
||||
return (Pdistortion); |
||||
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 (Pwidth); |
||||
break; |
||||
case 7: |
||||
return (Pfb); |
||||
break; |
||||
case 8: |
||||
return (Pstages); |
||||
break; |
||||
case 9: |
||||
return (Poffset); |
||||
break; |
||||
case 10: |
||||
return (Poutsub); |
||||
break; |
||||
case 11: |
||||
return (Pdepth); |
||||
break; |
||||
case 12: |
||||
return (Phyper); |
||||
break; |
||||
|
||||
default: |
||||
return (0); |
||||
}; |
||||
|
||||
}; |
@ -0,0 +1,91 @@ |
||||
/*
|
||||
ZynAddSubFX - a software synthesizer |
||||
|
||||
APhaser.h - Phaser effect |
||||
Copyright (C) 2002-2005 Nasca Octavian Paul |
||||
Author: Nasca Octavian Paul |
||||
|
||||
Modified for rakarrack by Josep Andreu and Ryan Billing |
||||
|
||||
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 |
||||
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. |
||||
|
||||
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 "global.h" |
||||
#include "EffectLFO.h" |
||||
|
||||
|
||||
class Analog_Phaser |
||||
{ |
||||
public: |
||||
Analog_Phaser (float * efxoutl_, float * efxoutr_, double sample_rate); |
||||
~Analog_Phaser (); |
||||
void out (float * smpsl, float * smpsr, uint32_t period); |
||||
void setpreset (int npreset); |
||||
void changepar (int npar, int value); |
||||
int getpar (int npar); |
||||
void cleanup (); |
||||
int Ppreset; |
||||
float *efxoutl; |
||||
float *efxoutr; |
||||
float outvolume; |
||||
|
||||
uint32_t PERIOD; |
||||
EffectLFO *lfo; //Phaser modulator
|
||||
|
||||
private: |
||||
//Phaser parameters
|
||||
int Pvolume; //Used in Process.C to set wet/dry mix
|
||||
int Pdistortion; //Model distortion added by FET element
|
||||
int Pwidth; //Phaser width (LFO amplitude)
|
||||
int Pfb; //feedback
|
||||
int Poffset; //Model mismatch between variable resistors
|
||||
int Pstages; //Number of first-order All-Pass stages
|
||||
int Poutsub; //if I wish to subtract the output instead of the adding it
|
||||
int Phyper; //lfo^2 -- converts tri into hyper-sine
|
||||
int Pdepth; //Depth of phaser sweep
|
||||
int Pbarber; //Enable barber pole phasing
|
||||
|
||||
//Control parameters
|
||||
void setvolume (int Pvolume); |
||||
void setdistortion (int Pdistortion); |
||||
void setwidth (int Pwidth); |
||||
void setfb (int Pfb); |
||||
void setoffset (int Poffset); |
||||
void setstages (int Pstages); |
||||
void setdepth (int Pdepth); |
||||
|
||||
//Internal Variables
|
||||
bool barber; //Barber pole phasing flag
|
||||
float distortion, fb, width, offsetpct, fbl, fbr, depth; |
||||
float *lxn1, *lyn1,*rxn1, *ryn1, *offset; |
||||
float oldlgain, oldrgain, rdiff, ldiff, invperiod; |
||||
|
||||
float mis; |
||||
float Rmin; // 2N5457 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
|
||||
float fPERIOD; |
||||
|
||||
class FPreset *Fpre; |
||||
|
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,256 @@ |
||||
/*
|
||||
ZynAddSubFX - a software synthesizer |
||||
|
||||
EffectLFO.C - Stereo LFO used by some effects |
||||
Copyright (C) 2002-2005 Nasca Octavian Paul |
||||
Author: Nasca Octavian Paul |
||||
|
||||
Modified for rakarrack by Josep Andreu 6 Ryan Billing |
||||
|
||||
|
||||
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) 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 <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <arm_math.h> |
||||
|
||||
#include "global.h" |
||||
#include "EffectLFO.h" |
||||
#include "f_sin.h" |
||||
|
||||
EffectLFO::EffectLFO (double sample_rate) |
||||
{ |
||||
float fPERIOD = 256;//this is our best guess at what it will be, later we'll correct it when we actually know fPERIOD
|
||||
fSAMPLE_RATE = sample_rate; |
||||
xl = 0.0; |
||||
xr = 0.0; |
||||
Pfreq = 40; |
||||
Prandomness = 0; |
||||
PLFOtype = 0; |
||||
Pstereo = 96; |
||||
|
||||
iperiod = fPERIOD/fSAMPLE_RATE; |
||||
h = iperiod; |
||||
a = 10.0f; |
||||
b = 28.0f; |
||||
c = 8.0f / 5.0f; |
||||
scale = 1.0f/36.0f; |
||||
ratediv = 0.1f; |
||||
holdflag = 0; |
||||
tca = iperiod/(iperiod + 0.02); //20ms default
|
||||
tcb = 1.0f - tca; |
||||
rreg = lreg = oldrreg = oldlreg = 0.0f; |
||||
updateparams ((uint32_t)fPERIOD); |
||||
|
||||
ampl1 = (1.0f - lfornd) + lfornd * (float)RND; |
||||
ampl2 = (1.0f - lfornd) + lfornd * (float)RND; |
||||
ampr1 = (1.0f - lfornd) + lfornd * (float)RND; |
||||
ampr2 = (1.0f - lfornd) + lfornd * (float)RND; |
||||
|
||||
|
||||
}; |
||||
|
||||
EffectLFO::~EffectLFO () |
||||
{ |
||||
}; |
||||
|
||||
|
||||
/*
|
||||
* Update the changed parameters |
||||
*/ |
||||
void |
||||
EffectLFO::updateparams (uint32_t period) |
||||
{ |
||||
float fPERIOD = period; |
||||
//must update several parameters once we actually know the period
|
||||
iperiod = fPERIOD/fSAMPLE_RATE; |
||||
h = iperiod; |
||||
tca = iperiod/(iperiod + 0.02); //20ms default
|
||||
tcb = 1.0f - tca; |
||||
|
||||
|
||||
incx = (float)Pfreq * fPERIOD / (fSAMPLE_RATE * 60.0f); |
||||
|
||||
if (incx > 0.49999999) |
||||
incx = 0.499999999f; //Limit the Frequency
|
||||
|
||||
lfornd = (float)Prandomness / 127.0f; |
||||
if (lfornd < 0.0) |
||||
lfornd = 0.0; |
||||
else if (lfornd > 1.0) |
||||
lfornd = 1.0; |
||||
|
||||
if (PLFOtype > 11) //this has to be updated if more lfo's are added
|
||||
PLFOtype = 0;
|
||||
lfotype = PLFOtype; |
||||
|
||||
xr = fmodf (xl + ((float)Pstereo - 64.0f) / 127.0f + 1.0f, 1.0f); |
||||
|
||||
if ((h = incx*ratediv) > 0.02) h = 0.02; //keeps it stable
|
||||
|
||||
a = 10.0f + (((float) RND) - 0.5f)*8.0f; |
||||
b = 28.0f + (((float) RND) - 0.5f)*12.0f; |
||||
c = 1.25f + 3.0f * ((float) RND); |
||||
|
||||
// printf("incx %f x0 %f y0 %f z0 %f out %f c %f b %f a %f\n",incx,x0,y0,z0, (2.0f * radius - 1.0f), c, b, a);
|
||||
x0 = 0.1f + 0.1f * ((float) RND); |
||||
y0 = 0.0f; |
||||
z0 = 0.2f; |
||||
x1 = y1 = z1 = radius = 0.0f; |
||||
|
||||
float tmp = 6.0f/((float) Pfreq); //S/H time attack 0.2*60=12.0
|
||||
tca = iperiod/(iperiod + tmp); //
|
||||
tcb = 1.0f - tca; |
||||
maxrate = 4.0f*iperiod; |
||||
}; |
||||
|
||||
|
||||
/*
|
||||
* Compute the shape of the LFO |
||||
*/ |
||||
float EffectLFO::getlfoshape (float x) |
||||
{ |
||||
float tmpv; |
||||
float out=0.0; |
||||
int iterations = 1; //make fractal go faster
|
||||
switch (lfotype) { |
||||
case 1: //EffectLFO_TRIANGLE
|
||||
if ((x > 0.0) && (x < 0.25)) |
||||
out = 4.0f * x; |
||||
else if ((x > 0.25) && (x < 0.75)) |
||||
out = 2.0f - 4.0f * x; |
||||
else |
||||
out = 4.0f * x - 4.0f; |
||||
break; |
||||
case 2: //EffectLFO_RAMP Ramp+
|
||||
out = 2.0f * x - 1.0f; |
||||
break; |
||||
case 3: //EffectLFO_RAMP Ramp-
|
||||
out = - 2.0f * x + 1.0f; |
||||
break; |
||||
case 4: //ZigZag
|
||||
x = x * 2.0f - 1.0f; |
||||
tmpv = 0.33f * f_sin(x); |
||||
out = f_sin(f_sin(x*D_PI)*x/tmpv); |
||||
break; |
||||
case 5: //Modulated Square ?? ;-)
|
||||
tmpv = x * D_PI; |
||||
out=f_sin(tmpv+f_sin(2.0f*tmpv)); |
||||
break; |
||||
case 6: // Modulated Saw
|
||||
tmpv = x * D_PI; |
||||
out=f_sin(tmpv+f_sin(tmpv)); |
||||
break; |
||||
case 8: //Lorenz Fractal, faster, using X,Y outputs
|
||||
iterations = 4; |
||||
case 7: // Lorenz Fractal
|
||||
for(int j=0; j<iterations; j++) { |
||||
x1 = x0 + h * a * (y0 - x0); |
||||
y1 = y0 + h * (x0 * (b - z0) - y0); |
||||
z1 = z0 + h * (x0 * y0 - c * z0); |
||||
x0 = x1; |
||||
y0 = y1; |
||||
z0 = z1; |
||||
} |
||||
if(lfotype==7) { |
||||
if((radius = (sqrtf(x0*x0 + y0*y0 + z0*z0) * scale) - 0.25f) > 1.0f) radius = 1.0f; |
||||
if(radius < 0.0) radius = 0.0; |
||||
out = 2.0f * radius - 1.0f; |
||||
} |
||||
|
||||
break; |
||||
case 9: //Sample/Hold Random
|
||||
if(fmod(x,0.5f)<=(2.0f*incx)) { //this function is called by left, then right...so must toggle each time called
|
||||
rreg = lreg; |
||||
lreg = RND1; |
||||
|
||||
} |
||||
|
||||
if(xlreg<lreg) xlreg += maxrate; |
||||
else xlreg -= maxrate; |
||||
if(xrreg<rreg) xrreg += maxrate; |
||||
else xrreg -= maxrate; |
||||
oldlreg = xlreg*tca + oldlreg*tcb; |
||||
oldrreg = xrreg*tca + oldrreg*tcb; |
||||
|
||||
if(holdflag) { |
||||
out = 2.0f*oldlreg -1.0f; |
||||
holdflag = (1 + holdflag)%2; |
||||
} else { |
||||
out = 2.0f*oldrreg - 1.0f; |
||||
} |
||||
|
||||
|
||||
break; |
||||
case 10: //Tri-top
|
||||
if(x<=0.5f) out = -f_sin(x*D_PI); |
||||
else if ((x > 0.5f) && (x < 0.75f)) |
||||
out = 6 * (x-0.5); |
||||
else |
||||
out = 1.5 - 6.0f *( x - 0.75f); |
||||
out-=0.25f; |
||||
out*=0.88888889f; |
||||
break; |
||||
case 11: //Tri-Bottom
|
||||
if(x<=0.5f) out = -f_sin(x*D_PI); |
||||
else if ((x > 0.5f) && (x < 0.75f)) |
||||
out = 6 * (x-0.5); |
||||
else |
||||
out = 1.5 - 6.0f *( x - 0.75f); |
||||
out-=0.25f; |
||||
out*=-0.88888889f; |
||||
break;
|
||||
//more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)
|
||||
default: |
||||
out = f_cos (x * D_PI); //EffectLFO_SINE
|
||||
}; |
||||
return (out); |
||||
}; |
||||
|
||||
/*
|
||||
* LFO output |
||||
*/ |
||||
void |
||||
EffectLFO::effectlfoout (float * outl, float * outr) |
||||
{ |
||||
float out; |
||||
|
||||
out = getlfoshape (xl); |
||||
//if ((lfotype == 0) || (lfotype == 1)) //What was that for?
|
||||
out *= (ampl1 + xl * (ampl2 - ampl1)); |
||||
xl += incx; |
||||
if (xl > 1.0) { |
||||
xl -= 1.0f; |
||||
ampl1 = ampl2; |
||||
ampl2 = (1.0f - lfornd) + lfornd * (float)RND; |
||||
}; |
||||
if(lfotype==8) out = scale*x0; //fractal parameter
|
||||
*outl = (out + 1.0f) * 0.5f; |
||||
|
||||
|
||||
if(lfotype==8) out = scale*y0; //fractal parameter
|
||||
else out = getlfoshape (xr); |
||||
|
||||
//if ((lfotype == 0) || (lfotype == 1))
|
||||
out *= (ampr1 + xr * (ampr2 - ampr1)); |
||||
xr += incx; |
||||
if (xr > 1.0) { |
||||
xr -= 1.0f; |
||||
ampr1 = ampr2; |
||||
ampr2 = (1.0f - lfornd) + lfornd * (float)RND; |
||||
}; |
||||
*outr = (out + 1.0f) * 0.5f; |
||||
}; |
@ -0,0 +1,72 @@ |
||||
/*
|
||||
ZynAddSubFX - a software synthesizer |
||||
|
||||
EffectLFO.h - Stereo LFO used by some effects |
||||
Copyright (C) 2002-2005 Nasca Octavian Paul |
||||
Author: Nasca Octavian Paul |
||||
|
||||
Modified for rakarrack by Josep Andreu & Ryan Billing |
||||
|
||||
|
||||
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) 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 EFFECT_LFO_H |
||||
#define EFFECT_LFO_H |
||||
|
||||
#include "global.h" |
||||
#include <arm_math.h> |
||||
|
||||
class EffectLFO |
||||
{ |
||||
public: |
||||
EffectLFO (double sample_rate); |
||||
~EffectLFO (); |
||||
void effectlfoout (float * outl, float * outr); |
||||
void updateparams (uint32_t period); |
||||
int Pfreq; |
||||
int Prandomness; |
||||
int PLFOtype; |
||||
int Pstereo; //"64"=0
|
||||
private: |
||||
float getlfoshape (float x); |
||||
|
||||
float xl, xr; |
||||
float incx; |
||||
float ampl1, ampl2, ampr1, ampr2; //necesar pentru "randomness"
|
||||
float lfointensity; |
||||
float lfornd; |
||||
int lfotype; |
||||
|
||||
//Lorenz Fractal parameters
|
||||
float x0,y0,z0,x1,y1,z1,radius; |
||||
float h; |
||||
float a; |
||||
float b; |
||||
float c; |
||||
float scale; |
||||
float iperiod; |
||||
float ratediv; |
||||
|
||||
//Sample/Hold
|
||||
int holdflag; //toggle left/right channel changes
|
||||
float tca, tcb, maxrate; |
||||
float rreg, lreg, xlreg,xrreg, oldrreg, oldlreg; |
||||
|
||||
float fSAMPLE_RATE; |
||||
}; |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,337 @@ |
||||
/*
|
||||
ZynAddSubFX - a software synthesizer |
||||
|
||||
Phaser.C - Phaser effect |
||||
Copyright (C) 2002-2005 Nasca Octavian Paul |
||||
Author: Nasca Octavian Paul |
||||
|
||||
Modified for rakarrack by Josep Andreu |
||||
|
||||
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) 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 <math.h> |
||||
#include "Phaser.h" |
||||
#include <stdio.h> |
||||
//#include "FPreset.h"
|
||||
#define PHASER_LFO_SHAPE 2 |
||||
|
||||
Phaser::Phaser (float * efxoutl_, float * efxoutr_, double sample_rate) |
||||
{ |
||||
efxoutl = efxoutl_; |
||||
efxoutr = efxoutr_; |
||||
|
||||
oldl = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES * 2); |
||||
oldr = (float *) malloc(sizeof(float)* MAX_PHASER_STAGES * 2); |
||||
|
||||
lfo = new EffectLFO(sample_rate); |
||||
|
||||
Ppreset = 0; |
||||
PERIOD = 256; //best guess until the effect starts running;
|
||||
setpreset (Ppreset); |
||||
cleanup (); |
||||
}; |
||||
|
||||
Phaser::~Phaser () |
||||
{ |
||||
free(oldl); |
||||
free(oldr); |
||||
delete lfo; |
||||
}; |
||||
|
||||
|
||||
/*
|
||||
* Effect output |
||||
*/ |
||||
void |
||||
Phaser::out (float * smpsl, float * smpsr, uint32_t period) |
||||
{ |
||||
unsigned int i; |
||||
int j; |
||||
float lfol, lfor, lgain, rgain, tmp; |
||||
|
||||
lfo->effectlfoout (&lfol, &lfor); |
||||
lgain = lfol; |
||||
rgain = lfor; |
||||
lgain = |
||||
(expf (lgain * PHASER_LFO_SHAPE) - 1.0f) / (expf (PHASER_LFO_SHAPE) - 1.0f); |
||||
rgain = |
||||
(expf (rgain * PHASER_LFO_SHAPE) - 1.0f) / (expf (PHASER_LFO_SHAPE) - 1.0f); |
||||
|
||||
|
||||
lgain = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * lgain * depth; |
||||
rgain = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * rgain * depth; |
||||
|
||||
if (lgain > 1.0) |
||||
lgain = 1.0f; |
||||
else if (lgain < 0.0) |
||||
lgain = 0.0f; |
||||
if (rgain > 1.0) |
||||
rgain = 1.0f; |
||||
else if (rgain < 0.0) |
||||
rgain = 0.0f; |
||||
|
||||
float v1, v2; |
||||
if (outvolume < 0.5f) |
||||
{ |
||||
v1 = 1.0f; |
||||
v2 = outvolume * 2.0f; |
||||
} |
||||
else |
||||
{ |
||||
v1 = (1.0f - outvolume) * 2.0f; |
||||
v2 = 1.0f; |
||||
} |
||||
|
||||
|
||||
for (i = 0; i < period; i++) { |
||||
float x = (float) i / ((float)period); |
||||
float x1 = 1.0f - x; |
||||
float gl = lgain * x + oldlgain * x1; |
||||
float gr = rgain * x + oldrgain * x1; |
||||
float inl = smpsl[i] * panning + fbl; |
||||
float inr = smpsr[i] * (1.0f - panning) + fbr; |
||||
|
||||
//Left channel
|
||||
for (j = 0; j < Pstages * 2; j++) { |
||||
//Phasing routine
|
||||
tmp = oldl[j] + DENORMAL_GUARD; |
||||
oldl[j] = gl * tmp + inl; |
||||
inl = tmp - gl * oldl[j]; |
||||
}; |
||||
//Right channel
|
||||
for (j = 0; j < Pstages * 2; j++) { |
||||
//Phasing routine
|
||||
tmp = oldr[j] + DENORMAL_GUARD; |
||||
oldr[j] = (gr * tmp) + inr; |
||||
inr = tmp - (gr * oldr[j]); |
||||
}; |
||||
//Left/Right crossing
|
||||
float l = inl; |
||||
float r = inr; |
||||
inl = l * (1.0f - lrcross) + r * lrcross; |
||||
inr = r * (1.0f - lrcross) + l * lrcross; |
||||
|
||||
fbl = inl * fb; |
||||
fbr = inr * fb; |
||||
|
||||
if (Poutsub != 0) { |
||||
inl *= -1.0f; |
||||
inr *= -1.0f; |
||||
} |
||||
|
||||
efxoutl[i] = smpsl[i] * v1 + inl * v2; |
||||
efxoutr[i] = smpsr[i] * v1 + inr * v2; |
||||
|
||||
}; |
||||
|
||||
oldlgain = lgain; |
||||
oldrgain = rgain; |
||||
}; |
||||
|
||||
/*
|
||||
* Cleanup the effect |
||||
*/ |
||||
void |
||||
Phaser::cleanup () |
||||
{ |
||||
fbl = 0.0; |
||||
fbr = 0.0; |
||||
oldlgain = 0.0; |
||||
oldrgain = 0.0; |
||||
for (int i = 0; i < Pstages * 2; i++) { |
||||
oldl[i] = 0.0; |
||||
oldr[i] = 0.0; |
||||
}; |
||||
}; |
||||
|
||||
/*
|
||||
* Parameter control |
||||
*/ |
||||
void |
||||
Phaser::setdepth (int Pdepth) |
||||
{ |
||||
this->Pdepth = Pdepth; |
||||
depth = ((float)Pdepth / 127.0f); |
||||
}; |
||||
|
||||
|
||||
void |
||||
Phaser::setfb (int Pfb) |
||||
{ |
||||
this->Pfb = Pfb; |
||||
fb = ((float)Pfb - 64.0f) / 64.1f; |
||||
}; |
||||
|
||||
void |
||||
Phaser::setvolume (int Pvolume) |
||||
{ |
||||
this->Pvolume = Pvolume; |
||||
outvolume = (float)Pvolume / 127.0f; |
||||
}; |
||||
|
||||
void |
||||
Phaser::setpanning (int Ppanning) |
||||
{ |
||||
this->Ppanning = Ppanning; |
||||
panning = ((float)Ppanning + .5f)/ 127.0f; |
||||
}; |
||||
|
||||
void |
||||
Phaser::setlrcross (int Plrcross) |
||||
{ |
||||
this->Plrcross = Plrcross; |
||||
lrcross = (float)Plrcross / 127.0f; |
||||
}; |
||||
|
||||
void |
||||
Phaser::setstages (int Pstages) |
||||
{ |
||||
if (Pstages > MAX_PHASER_STAGES) |
||||
Pstages = MAX_PHASER_STAGES; |
||||
this->Pstages = Pstages; |
||||
cleanup (); |
||||
}; |
||||
|
||||
void |
||||
Phaser::setphase (int Pphase) |
||||
{ |
||||
this->Pphase = Pphase; |
||||
phase = ((float)Pphase / 127.0f); |
||||
}; |
||||
|
||||
|
||||
void |
||||
Phaser::setpreset (int npreset) |
||||
{ |
||||
const int PRESET_SIZE = 12; |
||||
const int NUM_PRESETS = 6; |
||||
int presets[NUM_PRESETS][PRESET_SIZE] = { |
||||
//Phaser1
|
||||
{64, 64, 11, 0, 0, 64, 110, 64, 1, 0, 0, 20}, |
||||
//Phaser2
|
||||
{64, 64, 10, 0, 0, 88, 40, 64, 3, 0, 0, 20}, |
||||
//Phaser3
|
||||
{64, 64, 8, 0, 0, 66, 68, 107, 2, 0, 0, 20}, |
||||
//Phaser4
|
||||
{39, 64, 1, 0, 0, 66, 67, 10, 5, 0, 1, 20}, |
||||
//Phaser5
|
||||
{64, 64, 1, 0, 1, 110, 67, 78, 10, 0, 0, 20}, |
||||
//Phaser6
|
||||
{64, 64, 31, 100, 0, 58, 37, 78, 3, 0, 0, 20} |
||||
}; |
||||
|
||||
if(npreset>NUM_PRESETS-1) { |
||||
|
||||
} else { |
||||
for (int n = 0; n < PRESET_SIZE; n++) |
||||
changepar (n, presets[npreset][n]); |
||||
} |
||||
Ppreset = npreset; |
||||
}; |
||||
|
||||
|
||||
void |
||||
Phaser::changepar (int npar, int value) |
||||
{ |
||||
switch (npar) { |
||||
case 0: |
||||
setvolume (value); |
||||
break; |
||||
case 1: |
||||
setpanning (value); |
||||
break; |
||||
case 2: |
||||
lfo->Pfreq = value; |
||||
lfo->updateparams (PERIOD); |
||||
break; |
||||
case 3: |
||||
lfo->Prandomness = value; |
||||
lfo->updateparams (PERIOD); |
||||
break; |
||||
case 4: |
||||
lfo->PLFOtype = value; |
||||
lfo->updateparams (PERIOD); |
||||
break; |
||||
case 5: |
||||
lfo->Pstereo = value; |
||||
lfo->updateparams (PERIOD); |
||||
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) |
||||
value = 1; |
||||
Poutsub = value; |
||||
break; |
||||
case 11: |
||||
setphase (value); |
||||
break; |
||||
} |
||||
}; |
||||
|
||||
int |
||||
Phaser::getpar (int npar) |
||||
{ |
||||
switch (npar) { |
||||
case 0: |
||||
return (Pvolume); |
||||
break; |
||||
case 1: |
||||
return (Ppanning); |
||||
break; |
||||
case 2: |
||||
return (lfo->Pfreq); // tempo
|
||||
break; |
||||
case 3: |
||||
return (lfo->Prandomness); |
||||
break; |
||||
case 4: |
||||
return (lfo->PLFOtype); |
||||
break; |
||||
case 5: |
||||
return (lfo->Pstereo); // STDL
|
||||
break; |
||||
case 6: |
||||
return (Pdepth); |
||||
break; |
||||
case 7: |
||||
return (Pfb); // pfb feedback
|
||||
break; |
||||
case 8: |
||||
return (Pstages); |
||||
break; |
||||
case 9: |
||||
return (Plrcross); |
||||
break; |
||||
case 10: |
||||
return (Poutsub); |
||||
break; |
||||
case 11: |
||||
return (Pphase); |
||||
break; |
||||
default: |
||||
return (0); |
||||
} |
||||
}; |
@ -0,0 +1,77 @@ |
||||
/*
|
||||
ZynAddSubFX - a software synthesizer |
||||
|
||||
Phaser.h - Phaser effect |
||||
Copyright (C) 2002-2005 Nasca Octavian Paul |
||||
Author: Nasca Octavian Paul |
||||
|
||||
Modified for rakarrack by Josep Andreu |
||||
|
||||
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) 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 PHASER_H |
||||
#define PHASER_H |
||||
#include "global.h" |
||||
#include "EffectLFO.h" |
||||
|
||||
class Phaser |
||||
{ |
||||
public: |
||||
Phaser (float * efxoutl_, float * efxoutr_, double sample_rate); |
||||
~Phaser (); |
||||
void out (float * smpsl, float * smpsr, uint32_t period); |
||||
void setpreset (int npreset); |
||||
void changepar (int npar, int value); |
||||
int getpar (int npar); |
||||
void cleanup (); |
||||
int Ppreset; |
||||
float outvolume; |
||||
|
||||
float *efxoutl; |
||||
float *efxoutr; |
||||
|
||||
uint32_t PERIOD; |
||||
EffectLFO *lfo; //Phaser modulator
|
||||
|
||||
private: |
||||
void setvolume (int Pvolume); |
||||
void setpanning (int Ppanning); |
||||
void setdepth (int Pdepth); |
||||
void setfb (int Pfb); |
||||
void setlrcross (int Plrcross); |
||||
void setstages (int Pstages); |
||||
void setphase (int Pphase); |
||||
|
||||
|
||||
//Parametrii Phaser
|
||||
int Pvolume; |
||||
int Ppanning; |
||||
int Pdepth; //the depth of the Phaser
|
||||
int Pfb; //feedback
|
||||
int Plrcross; //feedback
|
||||
int Pstages; |
||||
int Poutsub; //if I wish to substract the output instead of the adding it
|
||||
int Pphase; |
||||
|
||||
//Control Parametrii
|
||||
|
||||
//Valorile interne
|
||||
float panning, fb, depth, lrcross, fbl, fbr, phase; |
||||
float *oldl, *oldr; |
||||
float oldlgain, oldrgain; |
||||
|
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,50 @@ |
||||
/*
|
||||
Cubic Sine Approximation based upon a modified Taylor Series Expansion |
||||
Author: Ryan Billing (C) 2010 |
||||
|
||||
This is unlicensed. Do whatever you want with but use at your own disgression. |
||||
The author makes no guarantee of its suitability for any purpose. |
||||
*/ |
||||
#ifndef FSIN_H |
||||
#define FSIN_H |
||||
|
||||
#include <arm_math.h> |
||||
#include "global.h" |
||||
|
||||
//globals
|
||||
static const float p2 = PI/2.0f; |
||||
static const float fact3 = 0.148148148148148f; //can multiply by 1/fact3
|
||||
|
||||
static inline float |
||||
f_sin(float x) |
||||
{ |
||||
|
||||
float y; //function output
|
||||
float tmp; |
||||
bool sign; |
||||
if ((x>D_PI) || (x<-D_PI)) x = fmod(x,D_PI); |
||||
if (x < 0.0f) x+=D_PI; |
||||
sign = 0; |
||||
if(x>PI) { |
||||
x = D_PI - x; |
||||
sign = 1; |
||||
} |
||||
|
||||
if (x <= p2) y = x - x*x*x*fact3; |
||||
else { |
||||
tmp = x - PI; |
||||
y = -tmp + tmp*tmp*tmp*fact3; |
||||
} |
||||
|
||||
if (sign) y = -y; |
||||
|
||||
return y; |
||||
} |
||||
|
||||
static inline float |
||||
f_cos(float x_) |
||||
{ |
||||
return f_sin(p2 + x_); |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,181 @@ |
||||
/*
|
||||
rakarrack - a guitar efects software |
||||
|
||||
global.h - Variable Definitions and functions |
||||
Copyright (C) 2008-2010 Josep Andreu |
||||
Author: Josep Andreu & Ryan Billing |
||||
|
||||
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) for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
(version2) along with this program; if not, write to the Free Software Foundation, |
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
|
||||
*/ |
||||
|
||||
|
||||
#ifndef DXEMU_H |
||||
#define DXEMU_H |
||||
|
||||
#include <arm_math.h> |
||||
|
||||
#define D_PI 6.283185f |
||||
//#define PI 3.141598f
|
||||
#define LOG_10 2.302585f |
||||
#define LOG_2 0.693147f |
||||
#define LN2R 1.442695041f |
||||
#define CNST_E 2.71828182845905f |
||||
#define AMPLITUDE_INTERPOLATION_THRESHOLD 0.0001f |
||||
#define FF_MAX_VOWELS 6 |
||||
#define FF_MAX_FORMANTS 12 |
||||
#define FF_MAX_SEQUENCE 8 |
||||
#define MAX_FILTER_STAGES 5 |
||||
#define RND (rand()/(RAND_MAX+1.0)) |
||||
#define RND1 (((float) rand())/(((float) RAND_MAX)+1.0f)) |
||||
#define F2I(f,i) (i)=((f>0) ? ( (int)(f) ) :( (int)(f-1.0f) )) |
||||
#define dB2rap(dB) (float)((expf((dB)*LOG_10/20.0f))) |
||||
#define rap2dB(rap) (float)((20*log(rap)/LOG_10)) |
||||
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) |
||||
#define INTERPOLATE_AMPLITUDE(a,b,x,size) ( (a) + ( (b) - (a) ) * (float)(x) / (float) (size) ) |
||||
#define ABOVE_AMPLITUDE_THRESHOLD(a,b) ( ( 2.0f*fabs( (b) - (a) ) / ( fabs( (b) + (a) + 0.0000000001f) ) ) > AMPLITUDE_INTERPOLATION_THRESHOLD ) |
||||
#define POLY 8 |
||||
#define DENORMAL_GUARD 1e-18f // Make it smaller until CPU problem re-appears
|
||||
#define SwapFourBytes(data) ( (((data) >> 24) & 0x000000ff) | (((data) >> 8) & 0x0000ff00) | (((data) << 8) & 0x00ff0000) | (((data) << 24) & 0xff000000) ) |
||||
#define D_NOTE 1.059463f |
||||
#define LOG_D_NOTE 0.057762f |
||||
#define D_NOTE_SQRT 1.029302f |
||||
#define MAX_PEAKS 8 |
||||
#define MAX_ALIENWAH_DELAY 100 |
||||
#define ATTACK 0.175f //crossover time for reverse delay
|
||||
#define MAX_DELAY 2 // Number of Seconds
|
||||
#define MAXHARMS 8 // max number of harmonics available
|
||||
#define MAX_PHASER_STAGES 12 |
||||
#define MAX_CHORUS_DELAY 250.0f //ms
|
||||
#define LN2 (1.0f) //Uncomment for att/rel to behave more like a capacitor.
|
||||
#define MUG_CORR_FACT 0.4f |
||||
//Crunch waveshaping constants
|
||||
#define Thi 0.67f //High threshold for limiting onset
|
||||
#define Tlo -0.65f //Low threshold for limiting onset
|
||||
#define Tlc -0.6139445f //Tlo + sqrt(Tlo/500)
|
||||
#define Thc 0.6365834f //Thi - sqrt(Thi/600)
|
||||
#define CRUNCH_GAIN 100.0f //Typical voltage gain for most OD stompboxes
|
||||
#define DIV_TLC_CONST 0.002f // 1/300
|
||||
#define DIV_THC_CONST 0.0016666f // 1/600 (approximately)
|
||||
//End waveshaping constants
|
||||
#define D_FLANGE_MAX_DELAY 0.055f // Number of Seconds - 50ms corresponds to fdepth = 20 (Hz). Added some extra for padding
|
||||
#define LFO_CONSTANT 9.765625e-04 // 1/(2^LOG_FMAX - 1)
|
||||
#define LOG_FMAX 10.0f // -- This optimizes LFO sweep for useful range.
|
||||
#define MINDEPTH 20.0f // won't allow filter lower than 20Hz
|
||||
#define MAXDEPTH 15000.0f // Keeps delay greater than 2 samples at 44kHz SR
|
||||
#define MAX_EQ_BANDS 16 |
||||
#define CLOSED 1 |
||||
#define OPENING 2 |
||||
#define OPEN 3 |
||||
#define CLOSING 4 |
||||
#define ENV_TR 0.0001f |
||||
#define HARMONICS 11 |
||||
#define REV_COMBS 8 |
||||
#define REV_APS 4 |
||||
#define MAX_SFILTER_STAGES 12 |
||||
|
||||
#define TEMPBUFSIZE 1024 |
||||
|
||||
typedef union { |
||||
float f; |
||||
long i; |
||||
} ls_pcast32; |
||||
|
||||
/*
|
||||
static inline float f_pow2(float x) |
||||
{ |
||||
ls_pcast32 *px, tx, lx; |
||||
float dx; |
||||
|
||||
px = (ls_pcast32 *)&x; // store address of float as long pointer
|
||||
tx.f = (x-0.5f) + (3<<22); // temporary value for truncation
|
||||
lx.i = tx.i - 0x4b400000; // integer power of 2
|
||||
dx = x - (float)lx.i; // float remainder of power of 2
|
||||
|
||||
x = 1.0f + dx * (0.6960656421638072f + // cubic apporoximation of 2^x
|
||||
dx * (0.224494337302845f + // for x in the range [0, 1]
|
||||
dx * (0.07944023841053369f))); |
||||
(*px).i += (lx.i << 23); // add integer power of 2 to exponent
|
||||
|
||||
return (*px).f; |
||||
} |
||||
*/ |
||||
/*
|
||||
#define P2a0 1.00000534060469 |
||||
#define P2a1 0.693057900547259 |
||||
#define P2a2 0.239411678986933 |
||||
#define P2a3 0.0532229404911678 |
||||
#define P2a4 0.00686649174914722 |
||||
#include <math.h> |
||||
static inline float f_pow2(float x) |
||||
{ |
||||
float y,xx, intpow; |
||||
long xint = (int) fabs(ceil(x)); |
||||
xx = x - ceil(x); |
||||
xint = xint<<xint; |
||||
if(x>0) intpow = (float) xint; |
||||
else intpow = 1.0f; |
||||
|
||||
y = intpow*(xx*(xx*(xx*(xx*P2a4 + P2a3) + P2a2) + P2a1) + P2a0); |
||||
|
||||
return y; |
||||
|
||||
} |
||||
*/ |
||||
|
||||
//The below pow function really works & is good to 16 bits, but is it faster than math lib powf()???
|
||||
//globals
|
||||
#include <math.h> |
||||
static const float a[5] = { 1.00000534060469, 0.693057900547259, 0.239411678986933, 0.0532229404911678, 0.00686649174914722 }; |
||||
//lookup for positive powers of 2
|
||||
static const float pw2[25] = {1.0f, 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f, 512.0f, 1024.0f, 2048.0f, 4096.0f, 8192.0f, 16384.0f, 32768.0f, 65536.0f, 131072.0f, 262144.0f, 524288.0f, 1048576.0f, 2097152.0f, 4194304.0f, 8388608.0f, 16777216.0f}; |
||||
//negative powers of 2, notice ipw2[0] will never be indexed.
|
||||
static const float ipw2[25] = {1.0, 5.0e-01, 2.5e-01, 1.25e-01, 6.25e-02, 3.125e-02, 1.5625e-02, 7.8125e-03, 3.90625e-03, 1.953125e-03, 9.765625e-04, 4.8828125e-04, 2.44140625e-04, 1.220703125e-04, 6.103515625e-05, 3.0517578125e-05, 1.52587890625e-05, 7.62939453125e-06, 3.814697265625e-06, 1.9073486328125e-06, 9.5367431640625e-07, 4.76837158203125e-07, 2.38418579101562e-07, 1.19209289550781e-07, 5.96046447753906e-08}; |
||||
|
||||
static inline float f_pow2(float x) |
||||
{ |
||||
float y = 0.0f; |
||||
|
||||
if(x >=24) return pw2[24]; |
||||
else if (x <= -24.0f) return ipw2[24]; |
||||
else { |
||||
float whole = ceilf(x); |
||||
int xint = (int) whole; |
||||
x = x - whole; |
||||
|
||||
if (xint>=0) { |
||||
y = pw2[xint]*(x*(x*(x*(x*a[4] + a[3]) + a[2]) + a[1]) + a[0]); |
||||
|
||||
} else { |
||||
|
||||
y = ipw2[-xint]*(x*(x*(x*(x*a[4] + a[3]) + a[2]) + a[1]) + a[0]); |
||||
|
||||
} |
||||
|
||||
return y; |
||||
} |
||||
|
||||
} |
||||
|
||||
#define f_exp(x) f_pow2(x * LN2R) |
||||
|
||||
//#include "config.h"
|
||||
#include <sys/time.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
//#include "FPreset.h"
|
||||
|
||||
#endif |
Loading…
Reference in new issue